]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/VEX/priv/guest_arm_toIR.c
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / VEX / priv / guest_arm_toIR.c
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-2010 OpenWorks LLP
11       info@open-works.net
12
13    NEON support is
14    Copyright (C) 2010-2010 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. */
126 static 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). */
131 static Addr32 guest_R15_curr_instr_notENC;
132
133 /* CONST, FOR ASSERTIONS ONLY.  Indicates whether currently processed
134    insn is Thumb (True) or ARM (False). */
135 static Bool __curr_is_Thumb;
136
137 /* MOD: The IRSB* into which we're generating code. */
138 static 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. */
151 static 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. */
157 static 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. */
161 static 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. */
190 static 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. */
202 static 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
210 static 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
218 static 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
228 static 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
274 static IRExpr* mkU64 ( ULong i )
275 {
276    return IRExpr_Const(IRConst_U64(i));
277 }
278
279 static IRExpr* mkU32 ( UInt i )
280 {
281    return IRExpr_Const(IRConst_U32(i));
282 }
283
284 static IRExpr* mkU8 ( UInt i )
285 {
286    vassert(i < 256);
287    return IRExpr_Const(IRConst_U8( (UChar)i ));
288 }
289
290 static IRExpr* mkexpr ( IRTemp tmp )
291 {
292    return IRExpr_RdTmp(tmp);
293 }
294
295 static IRExpr* unop ( IROp op, IRExpr* a )
296 {
297    return IRExpr_Unop(op, a);
298 }
299
300 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
301 {
302    return IRExpr_Binop(op, a1, a2);
303 }
304
305 static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
306 {
307    return IRExpr_Triop(op, a1, a2, a3);
308 }
309
310 static 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". */
316 static void stmt ( IRStmt* st )
317 {
318    addStmtToIRSB( irsb, st );
319 }
320
321 static void assign ( IRTemp dst, IRExpr* e )
322 {
323    stmt( IRStmt_WrTmp(dst, e) );
324 }
325
326 static 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. */
332 static 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. */
340 static 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. */
346 static 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
357 static 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. */
364 static 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
445 static 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. */
472 static 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. */
480 static 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. */
502 static 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. */
519 static 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. */
531 static 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. */
571 static 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. */
594 static 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
604 static 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. */
647 static 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. */
654 static IRExpr* getDReg ( UInt dregNo ) {
655    return llGetDReg( dregNo );
656 }
657
658 /* Plain ("low level") write to a VFP Dreg. */
659 static 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. */
669 static 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. */
691 static 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. */
698 static IRExpr* getDRegI64 ( UInt dregNo ) {
699    return llGetDRegI64( dregNo );
700 }
701
702 /* Plain ("low level") write to a Neon Integer Dreg. */
703 static 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. */
713 static 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
732 static 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. */
758 static 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. */
765 static IRExpr* getQReg ( UInt qregNo ) {
766    return llGetQReg( qregNo );
767 }
768
769 /* Plain ("low level") write to a Neon Qreg. */
770 static 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. */
780 static 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
800 static 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. */
818 static 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. */
825 static IRExpr* getFReg ( UInt fregNo ) {
826    return llGetFReg( fregNo );
827 }
828
829 /* Plain ("low level") write to a VFP Freg. */
830 static 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. */
840 static 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
860 static 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
889 static 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
897 static void put_ITSTATE ( IRTemp t )
898 {
899    ASSERT_IS_THUMB;
900    stmt( IRStmt_Put( OFFB_ITSTATE, mkexpr(t)) );
901 }
902
903 static 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
910 static 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. */
919 static 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. */
937 static 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. */
961 static 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. */
975 static 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. */
991 static 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. */
1013 static 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
1053 static 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 */
1076 static 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 */
1088 static 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 */
1129 static 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. */
1142 static 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. */
1166 static 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. */
1189 static 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
1209 static 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.
1289 static 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. */
1304 static
1305 void 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) */
1350 static 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) */
1362 static 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) */
1374 static 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 */
1391 static 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        ));
1403 }
1404
1405 /* Thumb16 only */
1406 /* ditto, but jump over a 16-bit thumb insn */
1407 static void mk_skip_over_T16_if_cond_is_false ( 
1408                IRTemp guardT /* :: Ity_I32, 0 or 1 */
1409             )
1410 {
1411    ASSERT_IS_THUMB;
1412    vassert(guardT != IRTemp_INVALID);
1413    vassert(0 == (guest_R15_curr_instr_notENC & 1));
1414    stmt( IRStmt_Exit(
1415             unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1416             Ijk_Boring,
1417             IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 2) | 1))
1418        ));
1419 }
1420
1421
1422 /* Thumb32 only */
1423 /* ditto, but jump over a 32-bit thumb insn */
1424 static void mk_skip_over_T32_if_cond_is_false ( 
1425                IRTemp guardT /* :: Ity_I32, 0 or 1 */
1426             )
1427 {
1428    ASSERT_IS_THUMB;
1429    vassert(guardT != IRTemp_INVALID);
1430    vassert(0 == (guest_R15_curr_instr_notENC & 1));
1431    stmt( IRStmt_Exit(
1432             unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
1433             Ijk_Boring,
1434             IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 4) | 1))
1435        ));
1436 }
1437
1438
1439 /* Thumb16 and Thumb32 only
1440    Generate a SIGILL followed by a restart of the current instruction
1441    if the given temp is nonzero. */
1442 static void gen_SIGILL_T_if_nonzero ( IRTemp t /* :: Ity_I32 */ )
1443 {
1444    ASSERT_IS_THUMB;
1445    vassert(t != IRTemp_INVALID);
1446    vassert(0 == (guest_R15_curr_instr_notENC & 1));
1447    stmt(
1448       IRStmt_Exit(
1449          binop(Iop_CmpNE32, mkexpr(t), mkU32(0)),
1450          Ijk_NoDecode,
1451          IRConst_U32(toUInt(guest_R15_curr_instr_notENC | 1))
1452       )
1453    );
1454 }
1455
1456
1457 /* Inspect the old_itstate, and generate a SIGILL if it indicates that
1458    we are currently in an IT block and are not the last in the block.
1459    This also rolls back guest_ITSTATE to its old value before the exit
1460    and restores it to its new value afterwards.  This is so that if
1461    the exit is taken, we have an up to date version of ITSTATE
1462    available.  Without doing that, we have no hope of making precise
1463    exceptions work. */
1464 static void gen_SIGILL_T_if_in_but_NLI_ITBlock (
1465                IRTemp old_itstate /* :: Ity_I32 */,
1466                IRTemp new_itstate /* :: Ity_I32 */
1467             )
1468 {
1469    ASSERT_IS_THUMB;
1470    put_ITSTATE(old_itstate); // backout
1471    IRTemp guards_for_next3 = newTemp(Ity_I32);
1472    assign(guards_for_next3,
1473           binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
1474    gen_SIGILL_T_if_nonzero(guards_for_next3);
1475    put_ITSTATE(new_itstate); //restore
1476 }
1477
1478
1479 /* Simpler version of the above, which generates a SIGILL if
1480    we're anywhere within an IT block. */
1481 static void gen_SIGILL_T_if_in_ITBlock (
1482                IRTemp old_itstate /* :: Ity_I32 */,
1483                IRTemp new_itstate /* :: Ity_I32 */
1484             )
1485 {
1486    put_ITSTATE(old_itstate); // backout
1487    gen_SIGILL_T_if_nonzero(old_itstate);
1488    put_ITSTATE(new_itstate); //restore
1489 }
1490
1491
1492 /* Generate an APSR value, from the NZCV thunk, and
1493    from QFLAG32 and GEFLAG0 .. GEFLAG3. */
1494 static IRTemp synthesise_APSR ( void )
1495 {
1496    IRTemp res1 = newTemp(Ity_I32);
1497    // Get NZCV
1498    assign( res1, mk_armg_calculate_flags_nzcv() );
1499    // OR in the Q value
1500    IRTemp res2 = newTemp(Ity_I32);
1501    assign(
1502       res2,
1503       binop(Iop_Or32,
1504             mkexpr(res1),
1505             binop(Iop_Shl32,
1506                   unop(Iop_1Uto32,
1507                        binop(Iop_CmpNE32,
1508                              mkexpr(get_QFLAG32()),
1509                              mkU32(0))),
1510                   mkU8(ARMG_CC_SHIFT_Q)))
1511    );
1512    // OR in GE0 .. GE3
1513    IRExpr* ge0
1514       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(0), mkU32(0)));
1515    IRExpr* ge1
1516       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(1), mkU32(0)));
1517    IRExpr* ge2
1518       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(2), mkU32(0)));
1519    IRExpr* ge3
1520       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(3), mkU32(0)));
1521    IRTemp res3 = newTemp(Ity_I32);
1522    assign(res3,
1523           binop(Iop_Or32,
1524                 mkexpr(res2),
1525                 binop(Iop_Or32,
1526                       binop(Iop_Or32,
1527                             binop(Iop_Shl32, ge0, mkU8(16)),
1528                             binop(Iop_Shl32, ge1, mkU8(17))),
1529                       binop(Iop_Or32,
1530                             binop(Iop_Shl32, ge2, mkU8(18)),
1531                             binop(Iop_Shl32, ge3, mkU8(19))) )));
1532    return res3;
1533 }
1534
1535
1536 /* and the inverse transformation: given an APSR value,
1537    set the NZCV thunk, the Q flag, and the GE flags. */
1538 static void desynthesise_APSR ( Bool write_nzcvq, Bool write_ge,
1539                                 IRTemp apsrT, IRTemp condT )
1540 {
1541    vassert(write_nzcvq || write_ge);
1542    if (write_nzcvq) {
1543       // Do NZCV
1544       IRTemp immT = newTemp(Ity_I32);
1545       assign(immT, binop(Iop_And32, mkexpr(apsrT), mkU32(0xF0000000)) );
1546       setFlags_D1(ARMG_CC_OP_COPY, immT, condT);
1547       // Do Q
1548       IRTemp qnewT = newTemp(Ity_I32);
1549       assign(qnewT, binop(Iop_And32, mkexpr(apsrT), mkU32(ARMG_CC_MASK_Q)));
1550       put_QFLAG32(qnewT, condT);
1551    }
1552    if (write_ge) {
1553       // Do GE3..0
1554       put_GEFLAG32(0, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<16)),
1555                    condT);
1556       put_GEFLAG32(1, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<17)),
1557                    condT);
1558       put_GEFLAG32(2, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<18)),
1559                    condT);
1560       put_GEFLAG32(3, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<19)),
1561                    condT);
1562    }
1563 }
1564
1565
1566 /*------------------------------------------------------------*/
1567 /*--- Helpers for saturation                               ---*/
1568 /*------------------------------------------------------------*/
1569
1570 /* FIXME: absolutely the only diff. between (a) armUnsignedSatQ and
1571    (b) armSignedSatQ is that in (a) the floor is set to 0, whereas in
1572    (b) the floor is computed from the value of imm5.  these two fnsn
1573    should be commoned up. */
1574
1575 /* UnsignedSatQ(): 'clamp' each value so it lies between 0 <= x <= (2^N)-1
1576    Optionally return flag resQ saying whether saturation occurred.
1577    See definition in manual, section A2.2.1, page 41
1578    (bits(N), boolean) UnsignedSatQ( integer i, integer N )
1579    {
1580      if ( i > (2^N)-1 ) { result = (2^N)-1; saturated = TRUE; }
1581      elsif ( i < 0 )    { result = 0; saturated = TRUE; }
1582      else               { result = i; saturated = FALSE; }
1583      return ( result<N-1:0>, saturated );
1584    }
1585 */
1586 static void armUnsignedSatQ( IRTemp* res,  /* OUT - Ity_I32 */
1587                              IRTemp* resQ, /* OUT - Ity_I32  */
1588                              IRTemp regT,  /* value to clamp - Ity_I32 */
1589                              UInt imm5 )   /* saturation ceiling */
1590 {
1591    UInt ceil  = (1 << imm5) - 1;    // (2^imm5)-1
1592    UInt floor = 0;
1593
1594    IRTemp node0 = newTemp(Ity_I32);
1595    IRTemp node1 = newTemp(Ity_I32);
1596    IRTemp node2 = newTemp(Ity_I1);
1597    IRTemp node3 = newTemp(Ity_I32);
1598    IRTemp node4 = newTemp(Ity_I32);
1599    IRTemp node5 = newTemp(Ity_I1);
1600    IRTemp node6 = newTemp(Ity_I32);
1601
1602    assign( node0, mkexpr(regT) );
1603    assign( node1, mkU32(ceil) );
1604    assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
1605    assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
1606                                 mkexpr(node0),
1607                                 mkexpr(node1) ) );
1608    assign( node4, mkU32(floor) );
1609    assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
1610    assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
1611                                 mkexpr(node3),
1612                                 mkexpr(node4) ) );
1613    assign( *res, mkexpr(node6) );
1614
1615    /* if saturation occurred, then resQ is set to some nonzero value
1616       if sat did not occur, resQ is guaranteed to be zero. */
1617    if (resQ) {
1618       assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
1619    }
1620 }
1621
1622
1623 /* SignedSatQ(): 'clamp' each value so it lies between  -2^N <= x <= (2^N) - 1
1624    Optionally return flag resQ saying whether saturation occurred.
1625    - see definition in manual, section A2.2.1, page 41
1626    (bits(N), boolean ) SignedSatQ( integer i, integer N ) 
1627    {
1628      if ( i > 2^(N-1) - 1 )    { result = 2^(N-1) - 1; saturated = TRUE; }
1629      elsif ( i < -(2^(N-1)) )  { result = -(2^(N-1));  saturated = FALSE; }
1630      else                      { result = i;           saturated = FALSE; }
1631      return ( result[N-1:0], saturated );
1632    }
1633 */
1634 static void armSignedSatQ( IRTemp regT,    /* value to clamp - Ity_I32 */
1635                            UInt imm5,      /* saturation ceiling */
1636                            IRTemp* res,    /* OUT - Ity_I32 */
1637                            IRTemp* resQ )  /* OUT - Ity_I32  */
1638 {
1639    Int ceil  =  (1 << (imm5-1)) - 1;  //  (2^(imm5-1))-1
1640    Int floor = -(1 << (imm5-1));      // -(2^(imm5-1))
1641
1642    IRTemp node0 = newTemp(Ity_I32);
1643    IRTemp node1 = newTemp(Ity_I32);
1644    IRTemp node2 = newTemp(Ity_I1);
1645    IRTemp node3 = newTemp(Ity_I32);
1646    IRTemp node4 = newTemp(Ity_I32);
1647    IRTemp node5 = newTemp(Ity_I1);
1648    IRTemp node6 = newTemp(Ity_I32);
1649
1650    assign( node0, mkexpr(regT) );
1651    assign( node1, mkU32(ceil) );
1652    assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
1653    assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
1654                                 mkexpr(node0),  mkexpr(node1) ) );
1655    assign( node4, mkU32(floor) );
1656    assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
1657    assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
1658                                 mkexpr(node3),  mkexpr(node4) ) );
1659    assign( *res, mkexpr(node6) );
1660
1661    /* if saturation occurred, then resQ is set to some nonzero value
1662       if sat did not occur, resQ is guaranteed to be zero. */
1663    if (resQ) {
1664      assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
1665    }
1666 }
1667
1668
1669 /* Compute a value 0 :: I32 or 1 :: I32, indicating whether signed
1670    overflow occurred for 32-bit addition.  Needs both args and the
1671    result.  HD p27. */
1672 static
1673 IRExpr* signed_overflow_after_Add32 ( IRExpr* resE,
1674                                       IRTemp argL, IRTemp argR )
1675 {
1676    IRTemp res = newTemp(Ity_I32);
1677    assign(res, resE);
1678    return
1679       binop( Iop_Shr32, 
1680              binop( Iop_And32,
1681                     binop( Iop_Xor32, mkexpr(res), mkexpr(argL) ),
1682                     binop( Iop_Xor32, mkexpr(res), mkexpr(argR) )), 
1683              mkU8(31) );
1684 }
1685
1686
1687 /*------------------------------------------------------------*/
1688 /*--- Larger helpers                                       ---*/
1689 /*------------------------------------------------------------*/
1690
1691 /* Compute both the result and new C flag value for a LSL by an imm5
1692    or by a register operand.  May generate reads of the old C value
1693    (hence only safe to use before any writes to guest state happen).
1694    Are factored out so can be used by both ARM and Thumb.
1695
1696    Note that in compute_result_and_C_after_{LSL,LSR,ASR}_by{imm5,reg},
1697    "res" (the result)  is a.k.a. "shop", shifter operand
1698    "newC" (the new C)  is a.k.a. "shco", shifter carry out
1699
1700    The calling convention for res and newC is a bit funny.  They could
1701    be passed by value, but instead are passed by ref.
1702
1703    The C (shco) value computed must be zero in bits 31:1, as the IR
1704    optimisations for flag handling (guest_arm_spechelper) rely on
1705    that, and the slow-path handlers (armg_calculate_flags_nzcv) assert
1706    for it.  Same applies to all these functions that compute shco
1707    after a shift or rotate, not just this one.
1708 */
1709
1710 static void compute_result_and_C_after_LSL_by_imm5 (
1711                /*OUT*/HChar* buf,
1712                IRTemp* res,
1713                IRTemp* newC,
1714                IRTemp rMt, UInt shift_amt, /* operands */
1715                UInt rM      /* only for debug printing */
1716             )
1717 {
1718    if (shift_amt == 0) {
1719       if (newC) {
1720          assign( *newC, mk_armg_calculate_flag_c() );
1721       }
1722       assign( *res, mkexpr(rMt) );
1723       DIS(buf, "r%u", rM);
1724    } else {
1725       vassert(shift_amt >= 1 && shift_amt <= 31);
1726       if (newC) {
1727          assign( *newC,
1728                  binop(Iop_And32,
1729                        binop(Iop_Shr32, mkexpr(rMt), 
1730                                         mkU8(32 - shift_amt)),
1731                        mkU32(1)));
1732       }
1733       assign( *res,
1734               binop(Iop_Shl32, mkexpr(rMt), mkU8(shift_amt)) );
1735       DIS(buf, "r%u, LSL #%u", rM, shift_amt);
1736    }
1737 }
1738
1739
1740 static void compute_result_and_C_after_LSL_by_reg (
1741                /*OUT*/HChar* buf,
1742                IRTemp* res,
1743                IRTemp* newC,
1744                IRTemp rMt, IRTemp rSt,  /* operands */
1745                UInt rM,    UInt rS      /* only for debug printing */
1746             )
1747 {
1748    // shift left in range 0 .. 255
1749    // amt  = rS & 255
1750    // res  = amt < 32 ?  Rm << amt  : 0
1751    // newC = amt == 0     ? oldC  :
1752    //        amt in 1..32 ?  Rm[32-amt]  : 0
1753    IRTemp amtT = newTemp(Ity_I32);
1754    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
1755    if (newC) {
1756       /* mux0X(amt == 0,
1757                mux0X(amt < 32, 
1758                      0,
1759                      Rm[(32-amt) & 31]),
1760                oldC)
1761       */
1762       /* About the best you can do is pray that iropt is able
1763          to nuke most or all of the following junk. */
1764       IRTemp oldC = newTemp(Ity_I32);
1765       assign(oldC, mk_armg_calculate_flag_c() );
1766       assign(
1767          *newC,
1768          IRExpr_Mux0X(
1769             unop(Iop_1Uto8,
1770                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
1771             IRExpr_Mux0X(
1772                unop(Iop_1Uto8,
1773                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
1774                mkU32(0),
1775                binop(Iop_And32,
1776                      binop(Iop_Shr32,
1777                            mkexpr(rMt),
1778                            unop(Iop_32to8,
1779                                 binop(Iop_And32,
1780                                       binop(Iop_Sub32,
1781                                             mkU32(32),
1782                                             mkexpr(amtT)),
1783                                       mkU32(31)
1784                                 )
1785                            )
1786                      ),
1787                      mkU32(1)
1788                )
1789             ),
1790             mkexpr(oldC)
1791          )
1792       );
1793    }
1794    // (Rm << (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
1795    // Lhs of the & limits the shift to 31 bits, so as to
1796    // give known IR semantics.  Rhs of the & is all 1s for
1797    // Rs <= 31 and all 0s for Rs >= 32.
1798    assign(
1799       *res,
1800       binop(
1801          Iop_And32,
1802          binop(Iop_Shl32,
1803                mkexpr(rMt),
1804                unop(Iop_32to8,
1805                     binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
1806          binop(Iop_Sar32,
1807                binop(Iop_Sub32,
1808                      mkexpr(amtT),
1809                      mkU32(32)),
1810                mkU8(31))));
1811     DIS(buf, "r%u, LSL r%u", rM, rS);
1812 }
1813
1814
1815 static void compute_result_and_C_after_LSR_by_imm5 (
1816                /*OUT*/HChar* buf,
1817                IRTemp* res,
1818                IRTemp* newC,
1819                IRTemp rMt, UInt shift_amt, /* operands */
1820                UInt rM      /* only for debug printing */
1821             )
1822 {
1823    if (shift_amt == 0) {
1824       // conceptually a 32-bit shift, however:
1825       // res  = 0
1826       // newC = Rm[31]
1827       if (newC) {
1828          assign( *newC,
1829                  binop(Iop_And32,
1830                        binop(Iop_Shr32, mkexpr(rMt), mkU8(31)), 
1831                        mkU32(1)));
1832       }
1833       assign( *res, mkU32(0) );
1834       DIS(buf, "r%u, LSR #0(a.k.a. 32)", rM);
1835    } else {
1836       // shift in range 1..31
1837       // res  = Rm >>u shift_amt
1838       // newC = Rm[shift_amt - 1]
1839       vassert(shift_amt >= 1 && shift_amt <= 31);
1840       if (newC) {
1841          assign( *newC,
1842                  binop(Iop_And32,
1843                        binop(Iop_Shr32, mkexpr(rMt), 
1844                                         mkU8(shift_amt - 1)),
1845                        mkU32(1)));
1846       }
1847       assign( *res,
1848               binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)) );
1849       DIS(buf, "r%u, LSR #%u", rM, shift_amt);
1850    }
1851 }
1852
1853
1854 static void compute_result_and_C_after_LSR_by_reg (
1855                /*OUT*/HChar* buf,
1856                IRTemp* res,
1857                IRTemp* newC,
1858                IRTemp rMt, IRTemp rSt,  /* operands */
1859                UInt rM,    UInt rS      /* only for debug printing */
1860             )
1861 {
1862    // shift right in range 0 .. 255
1863    // amt = rS & 255
1864    // res  = amt < 32 ?  Rm >>u amt  : 0
1865    // newC = amt == 0     ? oldC  :
1866    //        amt in 1..32 ?  Rm[amt-1]  : 0
1867    IRTemp amtT = newTemp(Ity_I32);
1868    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
1869    if (newC) {
1870       /* mux0X(amt == 0,
1871                mux0X(amt < 32, 
1872                      0,
1873                      Rm[(amt-1) & 31]),
1874                oldC)
1875       */
1876       IRTemp oldC = newTemp(Ity_I32);
1877       assign(oldC, mk_armg_calculate_flag_c() );
1878       assign(
1879          *newC,
1880          IRExpr_Mux0X(
1881             unop(Iop_1Uto8,
1882                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
1883             IRExpr_Mux0X(
1884                unop(Iop_1Uto8,
1885                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
1886                mkU32(0),
1887                binop(Iop_And32,
1888                      binop(Iop_Shr32,
1889                            mkexpr(rMt),
1890                            unop(Iop_32to8,
1891                                 binop(Iop_And32,
1892                                       binop(Iop_Sub32,
1893                                             mkexpr(amtT),
1894                                             mkU32(1)),
1895                                       mkU32(31)
1896                                 )
1897                            )
1898                      ),
1899                      mkU32(1)
1900                )
1901             ),
1902             mkexpr(oldC)
1903          )
1904       );
1905    }
1906    // (Rm >>u (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
1907    // Lhs of the & limits the shift to 31 bits, so as to
1908    // give known IR semantics.  Rhs of the & is all 1s for
1909    // Rs <= 31 and all 0s for Rs >= 32.
1910    assign(
1911       *res,
1912       binop(
1913          Iop_And32,
1914          binop(Iop_Shr32,
1915                mkexpr(rMt),
1916                unop(Iop_32to8,
1917                     binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
1918          binop(Iop_Sar32,
1919                binop(Iop_Sub32,
1920                      mkexpr(amtT),
1921                      mkU32(32)),
1922                mkU8(31))));
1923     DIS(buf, "r%u, LSR r%u", rM, rS);
1924 }
1925
1926
1927 static void compute_result_and_C_after_ASR_by_imm5 (
1928                /*OUT*/HChar* buf,
1929                IRTemp* res,
1930                IRTemp* newC,
1931                IRTemp rMt, UInt shift_amt, /* operands */
1932                UInt rM      /* only for debug printing */
1933             )
1934 {
1935    if (shift_amt == 0) {
1936       // conceptually a 32-bit shift, however:
1937       // res  = Rm >>s 31
1938       // newC = Rm[31]
1939       if (newC) {
1940          assign( *newC,
1941                  binop(Iop_And32,
1942                        binop(Iop_Shr32, mkexpr(rMt), mkU8(31)), 
1943                        mkU32(1)));
1944       }
1945       assign( *res, binop(Iop_Sar32, mkexpr(rMt), mkU8(31)) );
1946       DIS(buf, "r%u, ASR #0(a.k.a. 32)", rM);
1947    } else {
1948       // shift in range 1..31
1949       // res = Rm >>s shift_amt
1950       // newC = Rm[shift_amt - 1]
1951       vassert(shift_amt >= 1 && shift_amt <= 31);
1952       if (newC) {
1953          assign( *newC,
1954                  binop(Iop_And32,
1955                        binop(Iop_Shr32, mkexpr(rMt), 
1956                                         mkU8(shift_amt - 1)),
1957                        mkU32(1)));
1958       }
1959       assign( *res,
1960               binop(Iop_Sar32, mkexpr(rMt), mkU8(shift_amt)) );
1961       DIS(buf, "r%u, ASR #%u", rM, shift_amt);
1962    }
1963 }
1964
1965
1966 static void compute_result_and_C_after_ASR_by_reg (
1967                /*OUT*/HChar* buf,
1968                IRTemp* res,
1969                IRTemp* newC,
1970                IRTemp rMt, IRTemp rSt,  /* operands */
1971                UInt rM,    UInt rS      /* only for debug printing */
1972             )
1973 {
1974    // arithmetic shift right in range 0 .. 255
1975    // amt = rS & 255
1976    // res  = amt < 32 ?  Rm >>s amt  : Rm >>s 31
1977    // newC = amt == 0     ? oldC  :
1978    //        amt in 1..32 ?  Rm[amt-1]  : Rm[31]
1979    IRTemp amtT = newTemp(Ity_I32);
1980    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
1981    if (newC) {
1982       /* mux0X(amt == 0,
1983                mux0X(amt < 32, 
1984                      Rm[31],
1985                      Rm[(amt-1) & 31])
1986                oldC)
1987       */
1988       IRTemp oldC = newTemp(Ity_I32);
1989       assign(oldC, mk_armg_calculate_flag_c() );
1990       assign(
1991          *newC,
1992          IRExpr_Mux0X(
1993             unop(Iop_1Uto8,
1994                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
1995             IRExpr_Mux0X(
1996                unop(Iop_1Uto8,
1997                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
1998                binop(Iop_And32,
1999                      binop(Iop_Shr32,
2000                            mkexpr(rMt),
2001                            mkU8(31)
2002                      ),
2003                      mkU32(1)
2004                ),
2005                binop(Iop_And32,
2006                      binop(Iop_Shr32,
2007                            mkexpr(rMt),
2008                            unop(Iop_32to8,
2009                                 binop(Iop_And32,
2010                                       binop(Iop_Sub32,
2011                                             mkexpr(amtT),
2012                                             mkU32(1)),
2013                                       mkU32(31)
2014                                 )
2015                            )
2016                      ),
2017                      mkU32(1)
2018                )
2019             ),
2020             mkexpr(oldC)
2021          )
2022       );
2023    }
2024    // (Rm >>s (amt <u 32 ? amt : 31))
2025    assign(
2026       *res,
2027       binop(
2028          Iop_Sar32,
2029          mkexpr(rMt),
2030          unop(
2031             Iop_32to8,
2032             IRExpr_Mux0X(
2033                unop(
2034                  Iop_1Uto8,
2035                  binop(Iop_CmpLT32U, mkexpr(amtT), mkU32(32))),
2036                mkU32(31),
2037                mkexpr(amtT)))));
2038     DIS(buf, "r%u, ASR r%u", rM, rS);
2039 }
2040
2041
2042 static void compute_result_and_C_after_ROR_by_reg (
2043                /*OUT*/HChar* buf,
2044                IRTemp* res,
2045                IRTemp* newC,
2046                IRTemp rMt, IRTemp rSt,  /* operands */
2047                UInt rM,    UInt rS      /* only for debug printing */
2048             )
2049 {
2050    // rotate right in range 0 .. 255
2051    // amt = rS & 255
2052    // shop =  Rm `ror` (amt & 31)
2053    // shco =  amt == 0 ? oldC : Rm[(amt-1) & 31]
2054    IRTemp amtT = newTemp(Ity_I32);
2055    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
2056    IRTemp amt5T = newTemp(Ity_I32);
2057    assign( amt5T, binop(Iop_And32, mkexpr(rSt), mkU32(31)) );
2058    IRTemp oldC = newTemp(Ity_I32);
2059    assign(oldC, mk_armg_calculate_flag_c() );
2060    if (newC) {
2061       assign(
2062          *newC,
2063          IRExpr_Mux0X(
2064             unop(Iop_32to8, mkexpr(amtT)),
2065             mkexpr(oldC),
2066             binop(Iop_And32,
2067                   binop(Iop_Shr32,
2068                         mkexpr(rMt), 
2069                         unop(Iop_32to8,
2070                              binop(Iop_And32,
2071                                    binop(Iop_Sub32,
2072                                          mkexpr(amtT), 
2073                                          mkU32(1)
2074                                    ),
2075                                    mkU32(31)
2076                              )
2077                         )
2078                   ),
2079                   mkU32(1)
2080             )
2081          )
2082       );
2083    }
2084    assign(
2085       *res,
2086       IRExpr_Mux0X(
2087          unop(Iop_32to8, mkexpr(amt5T)), mkexpr(rMt),
2088          binop(Iop_Or32,
2089                binop(Iop_Shr32,
2090                      mkexpr(rMt), 
2091                      unop(Iop_32to8, mkexpr(amt5T))
2092                ),
2093                binop(Iop_Shl32,
2094                      mkexpr(rMt),
2095                      unop(Iop_32to8,
2096                           binop(Iop_Sub32, mkU32(32), mkexpr(amt5T))
2097                      )
2098                )
2099          )
2100       )
2101    );
2102    DIS(buf, "r%u, ROR r#%u", rM, rS);
2103 }
2104
2105
2106 /* Generate an expression corresponding to the immediate-shift case of
2107    a shifter operand.  This is used both for ARM and Thumb2.
2108
2109    Bind it to a temporary, and return that via *res.  If newC is
2110    non-NULL, also compute a value for the shifter's carry out (in the
2111    LSB of a word), bind it to a temporary, and return that via *shco.
2112
2113    Generates GETs from the guest state and is therefore not safe to
2114    use once we start doing PUTs to it, for any given instruction.
2115
2116    'how' is encoded thusly:
2117       00b LSL,  01b LSR,  10b ASR,  11b ROR
2118    Most but not all ARM and Thumb integer insns use this encoding.
2119    Be careful to ensure the right value is passed here.
2120 */
2121 static void compute_result_and_C_after_shift_by_imm5 (
2122                /*OUT*/HChar* buf,
2123                /*OUT*/IRTemp* res,
2124                /*OUT*/IRTemp* newC,
2125                IRTemp  rMt,       /* reg to shift */
2126                UInt    how,       /* what kind of shift */
2127                UInt    shift_amt, /* shift amount (0..31) */
2128                UInt    rM         /* only for debug printing */
2129             )
2130 {
2131    vassert(shift_amt < 32);
2132    vassert(how < 4);
2133
2134    switch (how) {
2135
2136       case 0:
2137          compute_result_and_C_after_LSL_by_imm5(
2138             buf, res, newC, rMt, shift_amt, rM
2139          );
2140          break;
2141
2142       case 1:
2143          compute_result_and_C_after_LSR_by_imm5(
2144             buf, res, newC, rMt, shift_amt, rM
2145          );
2146          break;
2147
2148       case 2:
2149          compute_result_and_C_after_ASR_by_imm5(
2150             buf, res, newC, rMt, shift_amt, rM
2151          );
2152          break;
2153
2154       case 3:
2155          if (shift_amt == 0) {
2156             IRTemp oldcT = newTemp(Ity_I32);
2157             // rotate right 1 bit through carry (?)
2158             // RRX -- described at ARM ARM A5-17
2159             // res  = (oldC << 31) | (Rm >>u 1)
2160             // newC = Rm[0]
2161             if (newC) {
2162                assign( *newC,
2163                        binop(Iop_And32, mkexpr(rMt), mkU32(1)));
2164             }
2165             assign( oldcT, mk_armg_calculate_flag_c() );
2166             assign( *res, 
2167                     binop(Iop_Or32,
2168                           binop(Iop_Shl32, mkexpr(oldcT), mkU8(31)),
2169                           binop(Iop_Shr32, mkexpr(rMt), mkU8(1))) );
2170             DIS(buf, "r%u, RRX", rM);
2171          } else {
2172             // rotate right in range 1..31
2173             // res  = Rm `ror` shift_amt
2174             // newC = Rm[shift_amt - 1]
2175             vassert(shift_amt >= 1 && shift_amt <= 31);
2176             if (newC) {
2177                assign( *newC,
2178                        binop(Iop_And32,
2179                              binop(Iop_Shr32, mkexpr(rMt), 
2180                                               mkU8(shift_amt - 1)),
2181                              mkU32(1)));
2182             }
2183             assign( *res,
2184                     binop(Iop_Or32,
2185                           binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)),
2186                           binop(Iop_Shl32, mkexpr(rMt),
2187                                            mkU8(32-shift_amt))));
2188             DIS(buf, "r%u, ROR #%u", rM, shift_amt);
2189          }
2190          break;
2191
2192       default:
2193          /*NOTREACHED*/
2194          vassert(0);
2195    }
2196 }
2197
2198
2199 /* Generate an expression corresponding to the register-shift case of
2200    a shifter operand.  This is used both for ARM and Thumb2.
2201
2202    Bind it to a temporary, and return that via *res.  If newC is
2203    non-NULL, also compute a value for the shifter's carry out (in the
2204    LSB of a word), bind it to a temporary, and return that via *shco.
2205
2206    Generates GETs from the guest state and is therefore not safe to
2207    use once we start doing PUTs to it, for any given instruction.
2208
2209    'how' is encoded thusly:
2210       00b LSL,  01b LSR,  10b ASR,  11b ROR
2211    Most but not all ARM and Thumb integer insns use this encoding.
2212    Be careful to ensure the right value is passed here.
2213 */
2214 static void compute_result_and_C_after_shift_by_reg (
2215                /*OUT*/HChar*  buf,
2216                /*OUT*/IRTemp* res,
2217                /*OUT*/IRTemp* newC,
2218                IRTemp  rMt,       /* reg to shift */
2219                UInt    how,       /* what kind of shift */
2220                IRTemp  rSt,       /* shift amount */
2221                UInt    rM,        /* only for debug printing */
2222                UInt    rS         /* only for debug printing */
2223             )
2224 {
2225    vassert(how < 4);
2226    switch (how) {
2227       case 0: { /* LSL */
2228          compute_result_and_C_after_LSL_by_reg(
2229             buf, res, newC, rMt, rSt, rM, rS
2230          );
2231          break;
2232       }
2233       case 1: { /* LSR */
2234          compute_result_and_C_after_LSR_by_reg(
2235             buf, res, newC, rMt, rSt, rM, rS
2236          );
2237          break;
2238       }
2239       case 2: { /* ASR */
2240          compute_result_and_C_after_ASR_by_reg(
2241             buf, res, newC, rMt, rSt, rM, rS
2242          );
2243          break;
2244       }
2245       case 3: { /* ROR */
2246          compute_result_and_C_after_ROR_by_reg(
2247              buf, res, newC, rMt, rSt, rM, rS
2248          );
2249          break;
2250       }
2251       default:
2252          /*NOTREACHED*/
2253          vassert(0);
2254    }
2255 }
2256
2257
2258 /* Generate an expression corresponding to a shifter_operand, bind it
2259    to a temporary, and return that via *shop.  If shco is non-NULL,
2260    also compute a value for the shifter's carry out (in the LSB of a
2261    word), bind it to a temporary, and return that via *shco.
2262
2263    If for some reason we can't come up with a shifter operand (missing
2264    case?  not really a shifter operand?) return False.
2265
2266    Generates GETs from the guest state and is therefore not safe to
2267    use once we start doing PUTs to it, for any given instruction.
2268
2269    For ARM insns only; not for Thumb.
2270 */
2271 static Bool mk_shifter_operand ( UInt insn_25, UInt insn_11_0,
2272                                  /*OUT*/IRTemp* shop,
2273                                  /*OUT*/IRTemp* shco,
2274                                  /*OUT*/HChar* buf )
2275 {
2276    UInt insn_4 = (insn_11_0 >> 4) & 1;
2277    UInt insn_7 = (insn_11_0 >> 7) & 1;
2278    vassert(insn_25 <= 0x1);
2279    vassert(insn_11_0 <= 0xFFF);
2280
2281    vassert(shop && *shop == IRTemp_INVALID);
2282    *shop = newTemp(Ity_I32);
2283
2284    if (shco) {
2285       vassert(*shco == IRTemp_INVALID);
2286       *shco = newTemp(Ity_I32);
2287    }
2288
2289    /* 32-bit immediate */
2290
2291    if (insn_25 == 1) {
2292       /* immediate: (7:0) rotated right by 2 * (11:8) */
2293       UInt imm = (insn_11_0 >> 0) & 0xFF;
2294       UInt rot = 2 * ((insn_11_0 >> 8) & 0xF);
2295       vassert(rot <= 30);
2296       imm = ROR32(imm, rot);
2297       if (shco) {
2298          if (rot == 0) {
2299             assign( *shco, mk_armg_calculate_flag_c() );
2300          } else {
2301             assign( *shco, mkU32( (imm >> 31) & 1 ) );
2302          }
2303       }
2304       DIS(buf, "#0x%x", imm);
2305       assign( *shop, mkU32(imm) );
2306       return True;
2307    }
2308
2309    /* Shift/rotate by immediate */
2310
2311    if (insn_25 == 0 && insn_4 == 0) {
2312       /* Rm (3:0) shifted (6:5) by immediate (11:7) */
2313       UInt shift_amt = (insn_11_0 >> 7) & 0x1F;
2314       UInt rM        = (insn_11_0 >> 0) & 0xF;
2315       UInt how       = (insn_11_0 >> 5) & 3;
2316       /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
2317       IRTemp rMt = newTemp(Ity_I32);
2318       assign(rMt, getIRegA(rM));
2319
2320       vassert(shift_amt <= 31);
2321
2322           compute_result_and_C_after_shift_by_imm5(
2323                 buf, shop, shco, rMt, how, shift_amt, rM
2324           );
2325           return True;
2326    }
2327
2328    /* Shift/rotate by register */
2329    if (insn_25 == 0 && insn_4 == 1) {
2330       /* Rm (3:0) shifted (6:5) by Rs (11:8) */
2331       UInt rM  = (insn_11_0 >> 0) & 0xF;
2332       UInt rS  = (insn_11_0 >> 8) & 0xF;
2333       UInt how = (insn_11_0 >> 5) & 3;
2334       /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
2335       IRTemp rMt = newTemp(Ity_I32);
2336       IRTemp rSt = newTemp(Ity_I32);
2337
2338       if (insn_7 == 1)
2339          return False; /* not really a shifter operand */
2340
2341       assign(rMt, getIRegA(rM));
2342       assign(rSt, getIRegA(rS));
2343
2344       compute_result_and_C_after_shift_by_reg(
2345          buf, shop, shco, rMt, how, rSt, rM, rS
2346       );
2347       return True;
2348    }
2349
2350    vex_printf("mk_shifter_operand(0x%x,0x%x)\n", insn_25, insn_11_0 );
2351    return False;
2352 }
2353
2354
2355 /* ARM only */
2356 static 
2357 IRExpr* mk_EA_reg_plusminus_imm12 ( UInt rN, UInt bU, UInt imm12,
2358                                     /*OUT*/HChar* buf )
2359 {
2360    vassert(rN < 16);
2361    vassert(bU < 2);
2362    vassert(imm12 < 0x1000);
2363    UChar opChar = bU == 1 ? '+' : '-';
2364    DIS(buf, "[r%u, #%c%u]", rN, opChar, imm12);
2365    return
2366       binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
2367              getIRegA(rN),
2368              mkU32(imm12) );
2369 }
2370
2371
2372 /* ARM only.
2373    NB: This is "DecodeImmShift" in newer versions of the the ARM ARM.
2374 */
2375 static
2376 IRExpr* mk_EA_reg_plusminus_shifted_reg ( UInt rN, UInt bU, UInt rM,
2377                                           UInt sh2, UInt imm5,
2378                                           /*OUT*/HChar* buf )
2379 {
2380    vassert(rN < 16);
2381    vassert(bU < 2);
2382    vassert(rM < 16);
2383    vassert(sh2 < 4);
2384    vassert(imm5 < 32);
2385    UChar   opChar = bU == 1 ? '+' : '-';
2386    IRExpr* index  = NULL;
2387    switch (sh2) {
2388       case 0: /* LSL */
2389          /* imm5 can be in the range 0 .. 31 inclusive. */
2390          index = binop(Iop_Shl32, getIRegA(rM), mkU8(imm5));
2391          DIS(buf, "[r%u, %c r%u LSL #%u]", rN, opChar, rM, imm5); 
2392          break;
2393       case 1: /* LSR */
2394          if (imm5 == 0) {
2395             index = mkU32(0);
2396             vassert(0); // ATC
2397          } else {
2398             index = binop(Iop_Shr32, getIRegA(rM), mkU8(imm5));
2399          }
2400          DIS(buf, "[r%u, %cr%u, LSR #%u]",
2401                   rN, opChar, rM, imm5 == 0 ? 32 : imm5); 
2402          break;
2403       case 2: /* ASR */
2404          /* Doesn't this just mean that the behaviour with imm5 == 0
2405             is the same as if it had been 31 ? */
2406          if (imm5 == 0) {
2407             index = binop(Iop_Sar32, getIRegA(rM), mkU8(31));
2408             vassert(0); // ATC
2409          } else {
2410             index = binop(Iop_Sar32, getIRegA(rM), mkU8(imm5));
2411          }
2412          DIS(buf, "[r%u, %cr%u, ASR #%u]",
2413                   rN, opChar, rM, imm5 == 0 ? 32 : imm5); 
2414          break;
2415       case 3: /* ROR or RRX */
2416          if (imm5 == 0) {
2417             IRTemp rmT    = newTemp(Ity_I32);
2418             IRTemp cflagT = newTemp(Ity_I32);
2419             assign(rmT, getIRegA(rM));
2420             assign(cflagT, mk_armg_calculate_flag_c());
2421             index = binop(Iop_Or32, 
2422                           binop(Iop_Shl32, mkexpr(cflagT), mkU8(31)),
2423                           binop(Iop_Shr32, mkexpr(rmT), mkU8(1)));
2424             DIS(buf, "[r%u, %cr%u, RRX]", rN, opChar, rM);
2425          } else {
2426             IRTemp rmT = newTemp(Ity_I32);
2427             assign(rmT, getIRegA(rM));
2428             vassert(imm5 >= 1 && imm5 <= 31);
2429             index = binop(Iop_Or32, 
2430                           binop(Iop_Shl32, mkexpr(rmT), mkU8(32-imm5)),
2431                           binop(Iop_Shr32, mkexpr(rmT), mkU8(imm5)));
2432             DIS(buf, "[r%u, %cr%u, ROR #%u]", rN, opChar, rM, imm5); 
2433          }
2434          break;
2435       default:
2436          vassert(0);
2437    }
2438    vassert(index);
2439    return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
2440                 getIRegA(rN), index);
2441 }
2442
2443
2444 /* ARM only */
2445 static 
2446 IRExpr* mk_EA_reg_plusminus_imm8 ( UInt rN, UInt bU, UInt imm8,
2447                                    /*OUT*/HChar* buf )
2448 {
2449    vassert(rN < 16);
2450    vassert(bU < 2);
2451    vassert(imm8 < 0x100);
2452    UChar opChar = bU == 1 ? '+' : '-';
2453    DIS(buf, "[r%u, #%c%u]", rN, opChar, imm8);
2454    return
2455       binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
2456              getIRegA(rN),
2457              mkU32(imm8) );
2458 }
2459
2460
2461 /* ARM only */
2462 static
2463 IRExpr* mk_EA_reg_plusminus_reg ( UInt rN, UInt bU, UInt rM,
2464                                   /*OUT*/HChar* buf )
2465 {
2466    vassert(rN < 16);
2467    vassert(bU < 2);
2468    vassert(rM < 16);
2469    UChar   opChar = bU == 1 ? '+' : '-';
2470    IRExpr* index  = getIRegA(rM);
2471    DIS(buf, "[r%u, %c r%u]", rN, opChar, rM); 
2472    return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
2473                 getIRegA(rN), index);
2474 }
2475
2476
2477 /* irRes :: Ity_I32 holds a floating point comparison result encoded
2478    as an IRCmpF64Result.  Generate code to convert it to an
2479    ARM-encoded (N,Z,C,V) group in the lowest 4 bits of an I32 value.
2480    Assign a new temp to hold that value, and return the temp. */
2481 static
2482 IRTemp mk_convert_IRCmpF64Result_to_NZCV ( IRTemp irRes )
2483 {
2484    IRTemp ix       = newTemp(Ity_I32);
2485    IRTemp termL    = newTemp(Ity_I32);
2486    IRTemp termR    = newTemp(Ity_I32);
2487    IRTemp nzcv     = newTemp(Ity_I32);
2488
2489    /* This is where the fun starts.  We have to convert 'irRes' from
2490       an IR-convention return result (IRCmpF64Result) to an
2491       ARM-encoded (N,Z,C,V) group.  The final result is in the bottom
2492       4 bits of 'nzcv'. */
2493    /* Map compare result from IR to ARM(nzcv) */
2494    /*
2495       FP cmp result | IR   | ARM(nzcv)
2496       --------------------------------
2497       UN              0x45   0011
2498       LT              0x01   1000
2499       GT              0x00   0010
2500       EQ              0x40   0110
2501    */
2502    /* Now since you're probably wondering WTF ..
2503
2504       ix fishes the useful bits out of the IR value, bits 6 and 0, and
2505       places them side by side, giving a number which is 0, 1, 2 or 3.
2506
2507       termL is a sequence cooked up by GNU superopt.  It converts ix
2508          into an almost correct value NZCV value (incredibly), except
2509          for the case of UN, where it produces 0100 instead of the
2510          required 0011.
2511
2512       termR is therefore a correction term, also computed from ix.  It
2513          is 1 in the UN case and 0 for LT, GT and UN.  Hence, to get
2514          the final correct value, we subtract termR from termL.
2515
2516       Don't take my word for it.  There's a test program at the bottom
2517       of this file, to try this out with.
2518    */
2519    assign(
2520       ix,
2521       binop(Iop_Or32,
2522             binop(Iop_And32,
2523                   binop(Iop_Shr32, mkexpr(irRes), mkU8(5)),
2524                   mkU32(3)),
2525             binop(Iop_And32, mkexpr(irRes), mkU32(1))));
2526
2527    assign(
2528       termL,
2529       binop(Iop_Add32,
2530             binop(Iop_Shr32,
2531                   binop(Iop_Sub32,
2532                         binop(Iop_Shl32,
2533                               binop(Iop_Xor32, mkexpr(ix), mkU32(1)),
2534                               mkU8(30)),
2535                         mkU32(1)),
2536                   mkU8(29)),
2537             mkU32(1)));
2538
2539    assign(
2540       termR,
2541       binop(Iop_And32,
2542             binop(Iop_And32,
2543                   mkexpr(ix),
2544                   binop(Iop_Shr32, mkexpr(ix), mkU8(1))),
2545             mkU32(1)));
2546
2547    assign(nzcv, binop(Iop_Sub32, mkexpr(termL), mkexpr(termR)));
2548    return nzcv;
2549 }
2550
2551
2552 /* Thumb32 only.  This is "ThumbExpandImm" in the ARM ARM.  If
2553    updatesC is non-NULL, a boolean is written to it indicating whether
2554    or not the C flag is updated, as per ARM ARM "ThumbExpandImm_C".
2555 */
2556 static UInt thumbExpandImm ( Bool* updatesC,
2557                              UInt imm1, UInt imm3, UInt imm8 )
2558 {
2559    vassert(imm1 < (1<<1));
2560    vassert(imm3 < (1<<3));
2561    vassert(imm8 < (1<<8));
2562    UInt i_imm3_a = (imm1 << 4) | (imm3 << 1) | ((imm8 >> 7) & 1);
2563    UInt abcdefgh = imm8;
2564    UInt lbcdefgh = imm8 | 0x80;
2565    if (updatesC) {
2566       *updatesC = i_imm3_a >= 8;
2567    }
2568    switch (i_imm3_a) {
2569       case 0: case 1:
2570          return abcdefgh;
2571       case 2: case 3:
2572          return (abcdefgh << 16) | abcdefgh;
2573       case 4: case 5:
2574          return (abcdefgh << 24) | (abcdefgh << 8);
2575       case 6: case 7:
2576          return (abcdefgh << 24) | (abcdefgh << 16)
2577                 | (abcdefgh << 8) | abcdefgh;
2578       case 8 ... 31:
2579          return lbcdefgh << (32 - i_imm3_a);
2580       default:
2581          break;
2582    }
2583    /*NOTREACHED*/vassert(0);
2584 }
2585
2586
2587 /* Version of thumbExpandImm where we simply feed it the
2588    instruction halfwords (the lowest addressed one is I0). */
2589 static UInt thumbExpandImm_from_I0_I1 ( Bool* updatesC,
2590                                         UShort i0s, UShort i1s )
2591 {
2592    UInt i0    = (UInt)i0s;
2593    UInt i1    = (UInt)i1s;
2594    UInt imm1  = SLICE_UInt(i0,10,10);
2595    UInt imm3  = SLICE_UInt(i1,14,12);
2596    UInt imm8  = SLICE_UInt(i1,7,0);
2597    return thumbExpandImm(updatesC, imm1, imm3, imm8);
2598 }
2599
2600
2601 /* Thumb16 only.  Given the firstcond and mask fields from an IT
2602    instruction, compute the 32-bit ITSTATE value implied, as described
2603    in libvex_guest_arm.h.  This is not the ARM ARM representation.
2604    Also produce the t/e chars for the 2nd, 3rd, 4th insns, for
2605    disassembly printing.  Returns False if firstcond or mask
2606    denote something invalid.
2607
2608    The number and conditions for the instructions to be
2609    conditionalised depend on firstcond and mask:
2610
2611    mask      cond 1    cond 2      cond 3      cond 4
2612
2613    1000      fc[3:0]
2614    x100      fc[3:0]   fc[3:1]:x
2615    xy10      fc[3:0]   fc[3:1]:x   fc[3:1]:y
2616    xyz1      fc[3:0]   fc[3:1]:x   fc[3:1]:y   fc[3:1]:z
2617
2618    The condition fields are assembled in *itstate backwards (cond 4 at
2619    the top, cond 1 at the bottom).  Conditions are << 4'd and then
2620    ^0xE'd, and those fields that correspond to instructions in the IT
2621    block are tagged with a 1 bit.
2622 */
2623 static Bool compute_ITSTATE ( /*OUT*/UInt*  itstate,
2624                               /*OUT*/UChar* ch1,
2625                               /*OUT*/UChar* ch2,
2626                               /*OUT*/UChar* ch3,
2627                               UInt firstcond, UInt mask )
2628 {
2629    vassert(firstcond <= 0xF);
2630    vassert(mask <= 0xF);
2631    *itstate = 0;
2632    *ch1 = *ch2 = *ch3 = '.';
2633    if (mask == 0)
2634       return False; /* the logic below actually ensures this anyway,
2635                        but clearer to make it explicit. */
2636    if (firstcond == 0xF)
2637       return False; /* NV is not allowed */
2638    if (firstcond == 0xE && popcount32(mask) != 1) 
2639       return False; /* if firstcond is AL then all the rest must be too */
2640
2641    UInt m3 = (mask >> 3) & 1;
2642    UInt m2 = (mask >> 2) & 1;
2643    UInt m1 = (mask >> 1) & 1;
2644    UInt m0 = (mask >> 0) & 1;
2645
2646    UInt fc = (firstcond << 4) | 1/*in-IT-block*/;
2647    UInt ni = (0xE/*AL*/ << 4) | 0/*not-in-IT-block*/;
2648
2649    if (m3 == 1 && (m2|m1|m0) == 0) {
2650       *itstate = (ni << 24) | (ni << 16) | (ni << 8) | fc;
2651       *itstate ^= 0xE0E0E0E0;
2652       return True;
2653    }
2654
2655    if (m2 == 1 && (m1|m0) == 0) {
2656       *itstate = (ni << 24) | (ni << 16) | (setbit32(fc, 4, m3) << 8) | fc;
2657       *itstate ^= 0xE0E0E0E0;
2658       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2659       return True;
2660    }
2661
2662    if (m1 == 1 && m0 == 0) {
2663       *itstate = (ni << 24)
2664                  | (setbit32(fc, 4, m2) << 16)
2665                  | (setbit32(fc, 4, m3) << 8) | fc;
2666       *itstate ^= 0xE0E0E0E0;
2667       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2668       *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
2669       return True;
2670    }
2671
2672    if (m0 == 1) {
2673       *itstate = (setbit32(fc, 4, m1) << 24)
2674                  | (setbit32(fc, 4, m2) << 16)
2675                  | (setbit32(fc, 4, m3) << 8) | fc;
2676       *itstate ^= 0xE0E0E0E0;
2677       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
2678       *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
2679       *ch3 = m1 == (firstcond & 1) ? 't' : 'e';
2680       return True;
2681    }
2682
2683    return False;
2684 }
2685
2686
2687 /* Generate IR to do 32-bit bit reversal, a la Hacker's Delight
2688    Chapter 7 Section 1. */
2689 static IRTemp gen_BITREV ( IRTemp x0 )
2690 {
2691    IRTemp x1 = newTemp(Ity_I32);
2692    IRTemp x2 = newTemp(Ity_I32);
2693    IRTemp x3 = newTemp(Ity_I32);
2694    IRTemp x4 = newTemp(Ity_I32);
2695    IRTemp x5 = newTemp(Ity_I32);
2696    UInt   c1 = 0x55555555;
2697    UInt   c2 = 0x33333333;
2698    UInt   c3 = 0x0F0F0F0F;
2699    UInt   c4 = 0x00FF00FF;
2700    UInt   c5 = 0x0000FFFF;
2701    assign(x1,
2702           binop(Iop_Or32,
2703                 binop(Iop_Shl32,
2704                       binop(Iop_And32, mkexpr(x0), mkU32(c1)),
2705                       mkU8(1)),
2706                 binop(Iop_Shr32,
2707                       binop(Iop_And32, mkexpr(x0), mkU32(~c1)),
2708                       mkU8(1))
2709    ));
2710    assign(x2,
2711           binop(Iop_Or32,
2712                 binop(Iop_Shl32,
2713                       binop(Iop_And32, mkexpr(x1), mkU32(c2)),
2714                       mkU8(2)),
2715                 binop(Iop_Shr32,
2716                       binop(Iop_And32, mkexpr(x1), mkU32(~c2)),
2717                       mkU8(2))
2718    ));
2719    assign(x3,
2720           binop(Iop_Or32,
2721                 binop(Iop_Shl32,
2722                       binop(Iop_And32, mkexpr(x2), mkU32(c3)),
2723                       mkU8(4)),
2724                 binop(Iop_Shr32,
2725                       binop(Iop_And32, mkexpr(x2), mkU32(~c3)),
2726                       mkU8(4))
2727    ));
2728    assign(x4,
2729           binop(Iop_Or32,
2730                 binop(Iop_Shl32,
2731                       binop(Iop_And32, mkexpr(x3), mkU32(c4)),
2732                       mkU8(8)),
2733                 binop(Iop_Shr32,
2734                       binop(Iop_And32, mkexpr(x3), mkU32(~c4)),
2735                       mkU8(8))
2736    ));
2737    assign(x5,
2738           binop(Iop_Or32,
2739                 binop(Iop_Shl32,
2740                       binop(Iop_And32, mkexpr(x4), mkU32(c5)),
2741                       mkU8(16)),
2742                 binop(Iop_Shr32,
2743                       binop(Iop_And32, mkexpr(x4), mkU32(~c5)),
2744                       mkU8(16))
2745    ));
2746    return x5;
2747 }
2748
2749
2750 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
2751    0:1:2:3 (aka byte-swap). */
2752 static IRTemp gen_REV ( IRTemp arg )
2753 {
2754    IRTemp res = newTemp(Ity_I32);
2755    assign(res, 
2756           binop(Iop_Or32,
2757                 binop(Iop_Shl32, mkexpr(arg), mkU8(24)),
2758           binop(Iop_Or32,
2759                 binop(Iop_And32, binop(Iop_Shl32, mkexpr(arg), mkU8(8)), 
2760                                  mkU32(0x00FF0000)),
2761           binop(Iop_Or32,
2762                 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
2763                                        mkU32(0x0000FF00)),
2764                 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(24)),
2765                                        mkU32(0x000000FF) )
2766    ))));
2767    return res;
2768 }
2769
2770
2771 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
2772    2:3:0:1 (swap within lo and hi halves). */
2773 static IRTemp gen_REV16 ( IRTemp arg )
2774 {
2775    IRTemp res = newTemp(Ity_I32);
2776    assign(res,
2777           binop(Iop_Or32,
2778                 binop(Iop_And32,
2779                       binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
2780                       mkU32(0xFF00FF00)),
2781                 binop(Iop_And32,
2782                       binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
2783                       mkU32(0x00FF00FF))));
2784    return res;
2785 }
2786
2787
2788 /*------------------------------------------------------------*/
2789 /*--- Advanced SIMD (NEON) instructions                    ---*/
2790 /*------------------------------------------------------------*/
2791
2792 /*------------------------------------------------------------*/
2793 /*--- NEON data processing                                 ---*/
2794 /*------------------------------------------------------------*/
2795
2796 /* For all NEON DP ops, we use the normal scheme to handle conditional
2797    writes to registers -- pass in condT and hand that on to the
2798    put*Reg functions.  In ARM mode condT is always IRTemp_INVALID
2799    since NEON is unconditional for ARM.  In Thumb mode condT is
2800    derived from the ITSTATE shift register in the normal way. */
2801
2802 static
2803 UInt get_neon_d_regno(UInt theInstr)
2804 {
2805    UInt x = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
2806    if (theInstr & 0x40) {
2807       if (x & 1) {
2808          x = x + 0x100;
2809       } else {
2810          x = x >> 1;
2811       }
2812    }
2813    return x;
2814 }
2815
2816 static
2817 UInt get_neon_n_regno(UInt theInstr)
2818 {
2819    UInt x = ((theInstr >> 3) & 0x10) | ((theInstr >> 16) & 0xF);
2820    if (theInstr & 0x40) {
2821       if (x & 1) {
2822          x = x + 0x100;
2823       } else {
2824          x = x >> 1;
2825       }
2826    }
2827    return x;
2828 }
2829
2830 static
2831 UInt get_neon_m_regno(UInt theInstr)
2832 {
2833    UInt x = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
2834    if (theInstr & 0x40) {
2835       if (x & 1) {
2836          x = x + 0x100;
2837       } else {
2838          x = x >> 1;
2839       }
2840    }
2841    return x;
2842 }
2843
2844 static
2845 Bool dis_neon_vext ( UInt theInstr, IRTemp condT )
2846 {
2847    UInt dreg = get_neon_d_regno(theInstr);
2848    UInt mreg = get_neon_m_regno(theInstr);
2849    UInt nreg = get_neon_n_regno(theInstr);
2850    UInt imm4 = (theInstr >> 8) & 0xf;
2851    UInt Q = (theInstr >> 6) & 1;
2852    HChar reg_t = Q ? 'q' : 'd';
2853
2854    if (Q) {
2855       putQReg(dreg, triop(Iop_ExtractV128, getQReg(nreg),
2856                getQReg(mreg), mkU8(imm4)), condT);
2857    } else {
2858       putDRegI64(dreg, triop(Iop_Extract64, getDRegI64(nreg),
2859                  getDRegI64(mreg), mkU8(imm4)), condT);
2860    }
2861    DIP("vext.8 %c%d, %c%d, %c%d, #%d\n", reg_t, dreg, reg_t, nreg,
2862                                          reg_t, mreg, imm4);
2863    return True;
2864 }
2865
2866 /* VTBL, VTBX */
2867 static
2868 Bool dis_neon_vtb ( UInt theInstr, IRTemp condT )
2869 {
2870    UInt op = (theInstr >> 6) & 1;
2871    UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
2872    UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
2873    UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
2874    UInt len = (theInstr >> 8) & 3;
2875    Int i;
2876    IROp cmp;
2877    ULong imm;
2878    IRTemp arg_l;
2879    IRTemp old_mask, new_mask, cur_mask;
2880    IRTemp old_res, new_res;
2881    IRTemp old_arg, new_arg;
2882
2883    if (dreg >= 0x100 || mreg >= 0x100 || nreg >= 0x100)
2884       return False;
2885    if (nreg + len > 31)
2886       return False;
2887
2888    cmp = Iop_CmpGT8Ux8;
2889
2890    old_mask = newTemp(Ity_I64);
2891    old_res = newTemp(Ity_I64);
2892    old_arg = newTemp(Ity_I64);
2893    assign(old_mask, mkU64(0));
2894    assign(old_res, mkU64(0));
2895    assign(old_arg, getDRegI64(mreg));
2896    imm = 8;
2897    imm = (imm <<  8) | imm;
2898    imm = (imm << 16) | imm;
2899    imm = (imm << 32) | imm;
2900
2901    for (i = 0; i <= len; i++) {
2902       arg_l = newTemp(Ity_I64);
2903       new_mask = newTemp(Ity_I64);
2904       cur_mask = newTemp(Ity_I64);
2905       new_res = newTemp(Ity_I64);
2906       new_arg = newTemp(Ity_I64);
2907       assign(arg_l, getDRegI64(nreg+i));
2908       assign(new_arg, binop(Iop_Sub8x8, mkexpr(old_arg), mkU64(imm)));
2909       assign(cur_mask, binop(cmp, mkU64(imm), mkexpr(old_arg)));
2910       assign(new_mask, binop(Iop_Or64, mkexpr(old_mask), mkexpr(cur_mask)));
2911       assign(new_res, binop(Iop_Or64,
2912                             mkexpr(old_res),
2913                             binop(Iop_And64,
2914                                   binop(Iop_Perm8x8,
2915                                         mkexpr(arg_l),
2916                                         binop(Iop_And64,
2917                                               mkexpr(old_arg),
2918                                               mkexpr(cur_mask))),
2919                                   mkexpr(cur_mask))));
2920
2921       old_arg = new_arg;
2922       old_mask = new_mask;
2923       old_res = new_res;
2924    }
2925    if (op) {
2926       new_res = newTemp(Ity_I64);
2927       assign(new_res, binop(Iop_Or64,
2928                             binop(Iop_And64,
2929                                   getDRegI64(dreg),
2930                                   unop(Iop_Not64, mkexpr(old_mask))),
2931                             mkexpr(old_res)));
2932       old_res = new_res;
2933    }
2934
2935    putDRegI64(dreg, mkexpr(old_res), condT);
2936    DIP("vtb%c.8 d%u, {", op ? 'x' : 'l', dreg);
2937    if (len > 0) {
2938       DIP("d%u-d%u", nreg, nreg + len);
2939    } else {
2940       DIP("d%u", nreg);
2941    }
2942    DIP("}, d%u\n", mreg);
2943    return True;
2944 }
2945
2946 /* VDUP (scalar)  */
2947 static
2948 Bool dis_neon_vdup ( UInt theInstr, IRTemp condT )
2949 {
2950    UInt Q = (theInstr >> 6) & 1;
2951    UInt dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
2952    UInt mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
2953    UInt imm4 = (theInstr >> 16) & 0xF;
2954    UInt index;
2955    UInt size;
2956    IRTemp arg_m;
2957    IRTemp res;
2958    IROp op, op2;
2959
2960    if ((imm4 == 0) || (imm4 == 8))
2961       return False;
2962    if ((Q == 1) && ((dreg & 1) == 1))
2963       return False;
2964    if (Q)
2965       dreg >>= 1;
2966    arg_m = newTemp(Ity_I64);
2967    assign(arg_m, getDRegI64(mreg));
2968    if (Q)
2969       res = newTemp(Ity_V128);
2970    else
2971       res = newTemp(Ity_I64);
2972    if ((imm4 & 1) == 1) {
2973       op = Q ? Iop_Dup8x16 : Iop_Dup8x8;
2974       op2 = Iop_GetElem8x8;
2975       index = imm4 >> 1;
2976       size = 8;
2977    } else if ((imm4 & 3) == 2) {
2978       op = Q ? Iop_Dup16x8 : Iop_Dup16x4;
2979       op2 = Iop_GetElem16x4;
2980       index = imm4 >> 2;
2981       size = 16;
2982    } else if ((imm4 & 7) == 4) {
2983       op = Q ? Iop_Dup32x4 : Iop_Dup32x2;
2984       op2 = Iop_GetElem32x2;
2985       index = imm4 >> 3;
2986       size = 32;
2987    } else {
2988       return False; // can this ever happen?
2989    }
2990    assign(res, unop(op, binop(op2, mkexpr(arg_m), mkU8(index))));
2991    if (Q) {
2992       putQReg(dreg, mkexpr(res), condT);
2993    } else {
2994       putDRegI64(dreg, mkexpr(res), condT);
2995    }
2996    DIP("vdup.%d %c%d, d%d[%d]\n", size, Q ? 'q' : 'd', dreg, mreg, index);
2997    return True;
2998 }
2999
3000 /* A7.4.1 Three registers of the same length */
3001 static
3002 Bool dis_neon_data_3same ( UInt theInstr, IRTemp condT )
3003 {
3004    UInt Q = (theInstr >> 6) & 1;
3005    UInt dreg = get_neon_d_regno(theInstr);
3006    UInt nreg = get_neon_n_regno(theInstr);
3007    UInt mreg = get_neon_m_regno(theInstr);
3008    UInt A = (theInstr >> 8) & 0xF;
3009    UInt B = (theInstr >> 4) & 1;
3010    UInt C = (theInstr >> 20) & 0x3;
3011    UInt U = (theInstr >> 24) & 1;
3012    UInt size = C;
3013
3014    IRTemp arg_n;
3015    IRTemp arg_m;
3016    IRTemp res;
3017
3018    if (Q) {
3019       arg_n = newTemp(Ity_V128);
3020       arg_m = newTemp(Ity_V128);
3021       res = newTemp(Ity_V128);
3022       assign(arg_n, getQReg(nreg));
3023       assign(arg_m, getQReg(mreg));
3024    } else {
3025       arg_n = newTemp(Ity_I64);
3026       arg_m = newTemp(Ity_I64);
3027       res = newTemp(Ity_I64);
3028       assign(arg_n, getDRegI64(nreg));
3029       assign(arg_m, getDRegI64(mreg));
3030    }
3031
3032    switch(A) {
3033       case 0:
3034          if (B == 0) {
3035             /* VHADD */
3036             ULong imm = 0;
3037             IRExpr *imm_val;
3038             IROp addOp;
3039             IROp andOp;
3040             IROp shOp;
3041             char regType = Q ? 'q' : 'd';
3042
3043             if (size == 3)
3044                return False;
3045             switch(size) {
3046                case 0: imm = 0x101010101010101LL; break;
3047                case 1: imm = 0x1000100010001LL; break;
3048                case 2: imm = 0x100000001LL; break;
3049                default: vassert(0);
3050             }
3051             if (Q) {
3052                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
3053                andOp = Iop_AndV128;
3054             } else {
3055                imm_val = mkU64(imm);
3056                andOp = Iop_And64;
3057             }
3058             if (U) {
3059                switch(size) {
3060                   case 0:
3061                      addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
3062                      shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3063                      break;
3064                   case 1:
3065                      addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
3066                      shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3067                      break;
3068                   case 2:
3069                      addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
3070                      shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3071                      break;
3072                   default:
3073                      vassert(0);
3074                }
3075             } else {
3076                switch(size) {
3077                   case 0:
3078                      addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
3079                      shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
3080                      break;
3081                   case 1:
3082                      addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
3083                      shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
3084                      break;
3085                   case 2:
3086                      addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
3087                      shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
3088                      break;
3089                   default:
3090                      vassert(0);
3091                }
3092             }
3093             assign(res,
3094                    binop(addOp,
3095                          binop(addOp,
3096                                binop(shOp, mkexpr(arg_m), mkU8(1)),
3097                                binop(shOp, mkexpr(arg_n), mkU8(1))),
3098                          binop(shOp,
3099                                binop(addOp,
3100                                      binop(andOp, mkexpr(arg_m), imm_val),
3101                                      binop(andOp, mkexpr(arg_n), imm_val)),
3102                                mkU8(1))));
3103             DIP("vhadd.%c%d %c%d, %c%d, %c%d\n",
3104                 U ? 'u' : 's', 8 << size, regType,
3105                 dreg, regType, nreg, regType, mreg);
3106          } else {
3107             /* VQADD */
3108             IROp op, op2;
3109             IRTemp tmp;
3110             char reg_t = Q ? 'q' : 'd';
3111             if (Q) {
3112                switch (size) {
3113                   case 0:
3114                      op = U ? Iop_QAdd8Ux16 : Iop_QAdd8Sx16;
3115                      op2 = Iop_Add8x16;
3116                      break;
3117                   case 1:
3118                      op = U ? Iop_QAdd16Ux8 : Iop_QAdd16Sx8;
3119                      op2 = Iop_Add16x8;
3120                      break;
3121                   case 2:
3122                      op = U ? Iop_QAdd32Ux4 : Iop_QAdd32Sx4;
3123                      op2 = Iop_Add32x4;
3124                      break;
3125                   case 3:
3126                      op = U ? Iop_QAdd64Ux2 : Iop_QAdd64Sx2;
3127                      op2 = Iop_Add64x2;
3128                      break;
3129                   default:
3130                      vassert(0);
3131                }
3132             } else {
3133                switch (size) {
3134                   case 0:
3135                      op = U ? Iop_QAdd8Ux8 : Iop_QAdd8Sx8;
3136                      op2 = Iop_Add8x8;
3137                      break;
3138                   case 1:
3139                      op = U ? Iop_QAdd16Ux4 : Iop_QAdd16Sx4;
3140                      op2 = Iop_Add16x4;
3141                      break;
3142                   case 2:
3143                      op = U ? Iop_QAdd32Ux2 : Iop_QAdd32Sx2;
3144                      op2 = Iop_Add32x2;
3145                      break;
3146                   case 3:
3147                      op = U ? Iop_QAdd64Ux1 : Iop_QAdd64Sx1;
3148                      op2 = Iop_Add64;
3149                      break;
3150                   default:
3151                      vassert(0);
3152                }
3153             }
3154             if (Q) {
3155                tmp = newTemp(Ity_V128);
3156             } else {
3157                tmp = newTemp(Ity_I64);
3158             }
3159             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3160 #ifndef DISABLE_QC_FLAG
3161             assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
3162             setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
3163 #endif
3164             DIP("vqadd.%c%d %c%d, %c%d, %c%d\n",
3165                 U ? 'u' : 's',
3166                 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
3167          }
3168          break;
3169       case 1:
3170          if (B == 0) {
3171             /* VRHADD */
3172             /* VRHADD C, A, B ::=
3173                  C = (A >> 1) + (B >> 1) + (((A & 1) + (B & 1) + 1) >> 1) */
3174             IROp shift_op, add_op;
3175             IRTemp cc;
3176             ULong one = 1;
3177             HChar reg_t = Q ? 'q' : 'd';
3178             switch (size) {
3179                case 0: one = (one <<  8) | one; /* fall through */
3180                case 1: one = (one << 16) | one; /* fall through */
3181                case 2: one = (one << 32) | one; break;
3182                case 3: return False;
3183                default: vassert(0);
3184             }
3185             if (Q) {
3186                switch (size) {
3187                   case 0:
3188                      shift_op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
3189                      add_op = Iop_Add8x16;
3190                      break;
3191                   case 1:
3192                      shift_op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
3193                      add_op = Iop_Add16x8;
3194                      break;
3195                   case 2:
3196                      shift_op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
3197                      add_op = Iop_Add32x4;
3198                      break;
3199                   case 3:
3200                      return False;
3201                   default:
3202                      vassert(0);
3203                }
3204             } else {
3205                switch (size) {
3206                   case 0:
3207                      shift_op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
3208                      add_op = Iop_Add8x8;
3209                      break;
3210                   case 1:
3211                      shift_op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
3212                      add_op = Iop_Add16x4;
3213                      break;
3214                   case 2:
3215                      shift_op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
3216                      add_op = Iop_Add32x2;
3217                      break;
3218                   case 3:
3219                      return False;
3220                   default:
3221                      vassert(0);
3222                }
3223             }
3224             if (Q) {
3225                cc = newTemp(Ity_V128);
3226                assign(cc, binop(shift_op,
3227                                 binop(add_op,
3228                                       binop(add_op,
3229                                             binop(Iop_AndV128,
3230                                                   mkexpr(arg_n),
3231                                                   binop(Iop_64HLtoV128,
3232                                                         mkU64(one),
3233                                                         mkU64(one))),
3234                                             binop(Iop_AndV128,
3235                                                   mkexpr(arg_m),
3236                                                   binop(Iop_64HLtoV128,
3237                                                         mkU64(one),
3238                                                         mkU64(one)))),
3239                                       binop(Iop_64HLtoV128,
3240                                             mkU64(one),
3241                                             mkU64(one))),
3242                                 mkU8(1)));
3243                assign(res, binop(add_op,
3244                                  binop(add_op,
3245                                        binop(shift_op,
3246                                              mkexpr(arg_n),
3247                                              mkU8(1)),
3248                                        binop(shift_op,
3249                                              mkexpr(arg_m),
3250                                              mkU8(1))),
3251                                  mkexpr(cc)));
3252             } else {
3253                cc = newTemp(Ity_I64);
3254                assign(cc, binop(shift_op,
3255                                 binop(add_op,
3256                                       binop(add_op,
3257                                             binop(Iop_And64,
3258                                                   mkexpr(arg_n),
3259                                                   mkU64(one)),
3260                                             binop(Iop_And64,
3261                                                   mkexpr(arg_m),
3262                                                   mkU64(one))),
3263                                       mkU64(one)),
3264                                 mkU8(1)));
3265                assign(res, binop(add_op,
3266                                  binop(add_op,
3267                                        binop(shift_op,
3268                                              mkexpr(arg_n),
3269                                              mkU8(1)),
3270                                        binop(shift_op,
3271                                              mkexpr(arg_m),
3272                                              mkU8(1))),
3273                                  mkexpr(cc)));
3274             }
3275             DIP("vrhadd.%c%d %c%d, %c%d, %c%d\n",
3276                 U ? 'u' : 's',
3277                 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
3278          } else {
3279             if (U == 0)  {
3280                switch(C) {
3281                   case 0: {
3282                      /* VAND  */
3283                      HChar reg_t = Q ? 'q' : 'd';
3284                      if (Q) {
3285                         assign(res, binop(Iop_AndV128, mkexpr(arg_n), 
3286                                                        mkexpr(arg_m)));
3287                      } else {
3288                         assign(res, binop(Iop_And64, mkexpr(arg_n),
3289                                                      mkexpr(arg_m)));
3290                      }
3291                      DIP("vand %c%d, %c%d, %c%d\n",
3292                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
3293                      break;
3294                   }
3295                   case 1: {
3296                      /* VBIC  */
3297                      HChar reg_t = Q ? 'q' : 'd';
3298                      if (Q) {
3299                         assign(res, binop(Iop_AndV128,mkexpr(arg_n),
3300                                unop(Iop_NotV128, mkexpr(arg_m))));
3301                      } else {
3302                         assign(res, binop(Iop_And64, mkexpr(arg_n),
3303                                unop(Iop_Not64, mkexpr(arg_m))));
3304                      }
3305                      DIP("vbic %c%d, %c%d, %c%d\n",
3306                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
3307                      break;
3308                   }
3309                   case 2:
3310                      if ( nreg != mreg) {
3311                         /* VORR  */
3312                         HChar reg_t = Q ? 'q' : 'd';
3313                         if (Q) {
3314                            assign(res, binop(Iop_OrV128, mkexpr(arg_n),
3315                                                          mkexpr(arg_m)));
3316                         } else {
3317                            assign(res, binop(Iop_Or64, mkexpr(arg_n),
3318                                                        mkexpr(arg_m)));
3319                         }
3320                         DIP("vorr %c%d, %c%d, %c%d\n",
3321                             reg_t, dreg, reg_t, nreg, reg_t, mreg);
3322                      } else {
3323                         /* VMOV  */
3324                         HChar reg_t = Q ? 'q' : 'd';
3325                         assign(res, mkexpr(arg_m));
3326                         DIP("vmov %c%d, %c%d\n", reg_t, dreg, reg_t, mreg);
3327                      }
3328                      break;
3329                   case 3:{
3330                      /* VORN  */
3331                      HChar reg_t = Q ? 'q' : 'd';
3332                      if (Q) {
3333                         assign(res, binop(Iop_OrV128,mkexpr(arg_n),
3334                                unop(Iop_NotV128, mkexpr(arg_m))));
3335                      } else {
3336                         assign(res, binop(Iop_Or64, mkexpr(arg_n),
3337                                unop(Iop_Not64, mkexpr(arg_m))));
3338                      }
3339                      DIP("vorn %c%d, %c%d, %c%d\n",
3340                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
3341                      break;
3342                   }
3343                }
3344             } else {
3345                switch(C) {
3346                   case 0:
3347                      /* VEOR (XOR)  */
3348                      if (Q) {
3349                         assign(res, binop(Iop_XorV128, mkexpr(arg_n),
3350                                                        mkexpr(arg_m)));
3351                      } else {
3352                         assign(res, binop(Iop_Xor64, mkexpr(arg_n),
3353                                                      mkexpr(arg_m)));
3354                      }
3355                      DIP("veor %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
3356                            Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3357                      break;
3358                   case 1:
3359                      /* VBSL  */
3360                      if (Q) {
3361                         IRTemp reg_d = newTemp(Ity_V128);
3362                         assign(reg_d, getQReg(dreg));
3363                         assign(res,
3364                                binop(Iop_OrV128,
3365                                      binop(Iop_AndV128, mkexpr(arg_n),
3366                                                         mkexpr(reg_d)),
3367                                      binop(Iop_AndV128,
3368                                            mkexpr(arg_m),
3369                                            unop(Iop_NotV128,
3370                                                  mkexpr(reg_d)) ) ) );
3371                      } else {
3372                         IRTemp reg_d = newTemp(Ity_I64);
3373                         assign(reg_d, getDRegI64(dreg));
3374                         assign(res,
3375                                binop(Iop_Or64,
3376                                      binop(Iop_And64, mkexpr(arg_n),
3377                                                       mkexpr(reg_d)),
3378                                      binop(Iop_And64,
3379                                            mkexpr(arg_m),
3380                                            unop(Iop_Not64, mkexpr(reg_d)))));
3381                      }
3382                      DIP("vbsl %c%u, %c%u, %c%u\n",
3383                          Q ? 'q' : 'd', dreg,
3384                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3385                      break;
3386                   case 2:
3387                      /* VBIT  */
3388                      if (Q) {
3389                         IRTemp reg_d = newTemp(Ity_V128);
3390                         assign(reg_d, getQReg(dreg));
3391                         assign(res,
3392                                binop(Iop_OrV128,
3393                                      binop(Iop_AndV128, mkexpr(arg_n), 
3394                                                         mkexpr(arg_m)),
3395                                      binop(Iop_AndV128,
3396                                            mkexpr(reg_d),
3397                                            unop(Iop_NotV128, mkexpr(arg_m)))));
3398                      } else {
3399                         IRTemp reg_d = newTemp(Ity_I64);
3400                         assign(reg_d, getDRegI64(dreg));
3401                         assign(res,
3402                                binop(Iop_Or64,
3403                                      binop(Iop_And64, mkexpr(arg_n),
3404                                                       mkexpr(arg_m)),
3405                                      binop(Iop_And64,
3406                                            mkexpr(reg_d),
3407                                            unop(Iop_Not64, mkexpr(arg_m)))));
3408                      }
3409                      DIP("vbit %c%u, %c%u, %c%u\n",
3410                          Q ? 'q' : 'd', dreg,
3411                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3412                      break;
3413                   case 3:
3414                      /* VBIF  */
3415                      if (Q) {
3416                         IRTemp reg_d = newTemp(Ity_V128);
3417                         assign(reg_d, getQReg(dreg));
3418                         assign(res,
3419                                binop(Iop_OrV128,
3420                                      binop(Iop_AndV128, mkexpr(reg_d),
3421                                                         mkexpr(arg_m)),
3422                                      binop(Iop_AndV128,
3423                                            mkexpr(arg_n),
3424                                            unop(Iop_NotV128, mkexpr(arg_m)))));
3425                      } else {
3426                         IRTemp reg_d = newTemp(Ity_I64);
3427                         assign(reg_d, getDRegI64(dreg));
3428                         assign(res,
3429                                binop(Iop_Or64,
3430                                      binop(Iop_And64, mkexpr(reg_d),
3431                                                       mkexpr(arg_m)),
3432                                      binop(Iop_And64,
3433                                            mkexpr(arg_n),
3434                                            unop(Iop_Not64, mkexpr(arg_m)))));
3435                      }
3436                      DIP("vbif %c%u, %c%u, %c%u\n",
3437                          Q ? 'q' : 'd', dreg,
3438                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
3439                      break;
3440                }
3441             }
3442          }
3443          break;
3444       case 2:
3445          if (B == 0) {
3446             /* VHSUB */
3447             /* (A >> 1) - (B >> 1) - (NOT (A) & B & 1)   */
3448             ULong imm = 0;
3449             IRExpr *imm_val;
3450             IROp subOp;
3451             IROp notOp;
3452             IROp andOp;
3453             IROp shOp;
3454             if (size == 3)
3455                return False;
3456             switch(size) {
3457                case 0: imm = 0x101010101010101LL; break;
3458                case 1: imm = 0x1000100010001LL; break;
3459                case 2: imm = 0x100000001LL; break;
3460                default: vassert(0);
3461             }
3462             if (Q) {
3463                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
3464                andOp = Iop_AndV128;
3465                notOp = Iop_NotV128;
3466             } else {
3467                imm_val = mkU64(imm);
3468                andOp = Iop_And64;
3469                notOp = Iop_Not64;
3470             }
3471             if (U) {
3472                switch(size) {
3473                   case 0:
3474                      subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3475                      shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3476                      break;
3477                   case 1:
3478                      subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3479                      shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3480                      break;
3481                   case 2:
3482                      subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3483                      shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3484                      break;
3485                   default:
3486                      vassert(0);
3487                }
3488             } else {
3489                switch(size) {
3490                   case 0:
3491                      subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3492                      shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
3493                      break;
3494                   case 1:
3495                      subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3496                      shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
3497                      break;
3498                   case 2:
3499                      subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3500                      shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
3501                      break;
3502                   default:
3503                      vassert(0);
3504                }
3505             }
3506             assign(res,
3507                    binop(subOp,
3508                          binop(subOp,
3509                                binop(shOp, mkexpr(arg_n), mkU8(1)),
3510                                binop(shOp, mkexpr(arg_m), mkU8(1))),
3511                          binop(andOp,
3512                                binop(andOp,
3513                                      unop(notOp, mkexpr(arg_n)),
3514                                      mkexpr(arg_m)),
3515                                imm_val)));
3516             DIP("vhsub.%c%u %c%u, %c%u, %c%u\n",
3517                 U ? 'u' : 's', 8 << size,
3518                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3519                 mreg);
3520          } else {
3521             /* VQSUB */
3522             IROp op, op2;
3523             IRTemp tmp;
3524             if (Q) {
3525                switch (size) {
3526                   case 0:
3527                      op = U ? Iop_QSub8Ux16 : Iop_QSub8Sx16;
3528                      op2 = Iop_Sub8x16;
3529                      break;
3530                   case 1:
3531                      op = U ? Iop_QSub16Ux8 : Iop_QSub16Sx8;
3532                      op2 = Iop_Sub16x8;
3533                      break;
3534                   case 2:
3535                      op = U ? Iop_QSub32Ux4 : Iop_QSub32Sx4;
3536                      op2 = Iop_Sub32x4;
3537                      break;
3538                   case 3:
3539                      op = U ? Iop_QSub64Ux2 : Iop_QSub64Sx2;
3540                      op2 = Iop_Sub64x2;
3541                      break;
3542                   default:
3543                      vassert(0);
3544                }
3545             } else {
3546                switch (size) {
3547                   case 0:
3548                      op = U ? Iop_QSub8Ux8 : Iop_QSub8Sx8;
3549                      op2 = Iop_Sub8x8;
3550                      break;
3551                   case 1:
3552                      op = U ? Iop_QSub16Ux4 : Iop_QSub16Sx4;
3553                      op2 = Iop_Sub16x4;
3554                      break;
3555                   case 2:
3556                      op = U ? Iop_QSub32Ux2 : Iop_QSub32Sx2;
3557                      op2 = Iop_Sub32x2;
3558                      break;
3559                   case 3:
3560                      op = U ? Iop_QSub64Ux1 : Iop_QSub64Sx1;
3561                      op2 = Iop_Sub64;
3562                      break;
3563                   default:
3564                      vassert(0);
3565                }
3566             }
3567             if (Q)
3568                tmp = newTemp(Ity_V128);
3569             else
3570                tmp = newTemp(Ity_I64);
3571             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3572 #ifndef DISABLE_QC_FLAG
3573             assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
3574             setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
3575 #endif
3576             DIP("vqsub.%c%u %c%u, %c%u, %c%u\n",
3577                 U ? 'u' : 's', 8 << size,
3578                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3579                 mreg);
3580          }
3581          break;
3582       case 3: {
3583             IROp op;
3584             if (Q) {
3585                switch (size) {
3586                   case 0: op = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; break;
3587                   case 1: op = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; break;
3588                   case 2: op = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; break;
3589                   case 3: return False;
3590                   default: vassert(0);
3591                }
3592             } else {
3593                switch (size) {
3594                   case 0: op = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; break;
3595                   case 1: op = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; break;
3596                   case 2: op = U ? Iop_CmpGT32Ux2: Iop_CmpGT32Sx2; break;
3597                   case 3: return False;
3598                   default: vassert(0);
3599                }
3600             }
3601             if (B == 0) {
3602                /* VCGT  */
3603                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
3604                DIP("vcgt.%c%u %c%u, %c%u, %c%u\n",
3605                    U ? 'u' : 's', 8 << size,
3606                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3607                    mreg);
3608             } else {
3609                /* VCGE  */
3610                /* VCGE res, argn, argm
3611                     is equal to
3612                   VCGT tmp, argm, argn
3613                   VNOT res, tmp */
3614                assign(res,
3615                       unop(Q ? Iop_NotV128 : Iop_Not64,
3616                            binop(op, mkexpr(arg_m), mkexpr(arg_n))));
3617                DIP("vcge.%c%u %c%u, %c%u, %c%u\n",
3618                    U ? 'u' : 's', 8 << size,
3619                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
3620                    mreg);
3621             }
3622          }
3623          break;
3624       case 4:
3625          if (B == 0) {
3626             /* VSHL */
3627             IROp op, sub_op;
3628             IRTemp tmp;
3629             if (U) {
3630                switch (size) {
3631                   case 0: op = Q ? Iop_Shl8x16 : Iop_Shl8x8; break;
3632                   case 1: op = Q ? Iop_Shl16x8 : Iop_Shl16x4; break;
3633                   case 2: op = Q ? Iop_Shl32x4 : Iop_Shl32x2; break;
3634                   case 3: op = Q ? Iop_Shl64x2 : Iop_Shl64; break;
3635                   default: vassert(0);
3636                }
3637             } else {
3638                tmp = newTemp(Q ? Ity_V128 : Ity_I64);
3639                switch (size) {
3640                   case 0:
3641                      op = Q ? Iop_Sar8x16 : Iop_Sar8x8;
3642                      sub_op = Q ? Iop_Sub8x16 : Iop_Sub8x8;
3643                      break;
3644                   case 1:
3645                      op = Q ? Iop_Sar16x8 : Iop_Sar16x4;
3646                      sub_op = Q ? Iop_Sub16x8 : Iop_Sub16x4;
3647                      break;
3648                   case 2:
3649                      op = Q ? Iop_Sar32x4 : Iop_Sar32x2;
3650                      sub_op = Q ? Iop_Sub32x4 : Iop_Sub32x2;
3651                      break;
3652                   case 3:
3653                      op = Q ? Iop_Sar64x2 : Iop_Sar64;
3654                      sub_op = Q ? Iop_Sub64x2 : Iop_Sub64;
3655                      break;
3656                   default:
3657                      vassert(0);
3658                }
3659             }
3660             if (U) {
3661                if (!Q && (size == 3))
3662                   assign(res, binop(op, mkexpr(arg_m),
3663                                         unop(Iop_64to8, mkexpr(arg_n))));
3664                else
3665                   assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
3666             } else {
3667                if (Q)
3668                   assign(tmp, binop(sub_op,
3669                                     binop(Iop_64HLtoV128, mkU64(0), mkU64(0)),
3670                                     mkexpr(arg_n)));
3671                else
3672                   assign(tmp, binop(sub_op, mkU64(0), mkexpr(arg_n)));
3673                if (!Q && (size == 3))
3674                   assign(res, binop(op, mkexpr(arg_m),
3675                                         unop(Iop_64to8, mkexpr(tmp))));
3676                else
3677                   assign(res, binop(op, mkexpr(arg_m), mkexpr(tmp)));
3678             }
3679             DIP("vshl.%c%u %c%u, %c%u, %c%u\n",
3680                 U ? 'u' : 's', 8 << size,
3681                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3682                 nreg);
3683          } else {
3684             /* VQSHL */
3685             IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt;
3686             IRTemp tmp, shval, mask, old_shval;
3687             UInt i;
3688             ULong esize;
3689             cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
3690             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3691             if (U) {
3692                switch (size) {
3693                   case 0:
3694                      op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
3695                      op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
3696                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3697                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3698                      break;
3699                   case 1:
3700                      op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
3701                      op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
3702                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3703                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3704                      break;
3705                   case 2:
3706                      op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
3707                      op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
3708                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3709                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3710                      break;
3711                   case 3:
3712                      op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
3713                      op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
3714                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3715                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3716                      break;
3717                   default:
3718                      vassert(0);
3719                }
3720             } else {
3721                switch (size) {
3722                   case 0:
3723                      op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
3724                      op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
3725                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3726                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3727                      break;
3728                   case 1:
3729                      op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
3730                      op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
3731                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3732                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3733                      break;
3734                   case 2:
3735                      op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
3736                      op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
3737                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3738                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3739                      break;
3740                   case 3:
3741                      op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
3742                      op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
3743                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3744                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3745                      break;
3746                   default:
3747                      vassert(0);
3748                }
3749             }
3750             if (Q) {
3751                tmp = newTemp(Ity_V128);
3752                shval = newTemp(Ity_V128);
3753                mask = newTemp(Ity_V128);
3754             } else {
3755                tmp = newTemp(Ity_I64);
3756                shval = newTemp(Ity_I64);
3757                mask = newTemp(Ity_I64);
3758             }
3759             assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
3760 #ifndef DISABLE_QC_FLAG
3761             /* Only least significant byte from second argument is used.
3762                Copy this byte to the whole vector element. */
3763             assign(shval, binop(op_shrn,
3764                                 binop(op_shln,
3765                                        mkexpr(arg_n),
3766                                        mkU8((8 << size) - 8)),
3767                                 mkU8((8 << size) - 8)));
3768             for(i = 0; i < size; i++) {
3769                old_shval = shval;
3770                shval = newTemp(Q ? Ity_V128 : Ity_I64);
3771                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
3772                                    mkexpr(old_shval),
3773                                    binop(op_shln,
3774                                          mkexpr(old_shval),
3775                                          mkU8(8 << i))));
3776             }
3777             /* If shift is greater or equal to the element size and
3778                element is non-zero, then QC flag should be set. */
3779             esize = (8 << size) - 1;
3780             esize = (esize <<  8) | esize;
3781             esize = (esize << 16) | esize;
3782             esize = (esize << 32) | esize;
3783             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
3784                              binop(cmp_gt, mkexpr(shval),
3785                                            Q ? mkU128(esize) : mkU64(esize)),
3786                              unop(cmp_neq, mkexpr(arg_m))),
3787                        Q ? mkU128(0) : mkU64(0),
3788                        Q, condT);
3789             /* Othervise QC flag should be set if shift value is positive and
3790                result beign rightshifted the same value is not equal to left
3791                argument. */
3792             assign(mask, binop(cmp_gt, mkexpr(shval),
3793                                        Q ? mkU128(0) : mkU64(0)));
3794             if (!Q && size == 3)
3795                assign(tmp, binop(op_rev, mkexpr(res),
3796                                          unop(Iop_64to8, mkexpr(arg_n))));
3797             else
3798                assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
3799             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
3800                              mkexpr(tmp), mkexpr(mask)),
3801                        binop(Q ? Iop_AndV128 : Iop_And64,
3802                              mkexpr(arg_m), mkexpr(mask)),
3803                        Q, condT);
3804 #endif
3805             DIP("vqshl.%c%u %c%u, %c%u, %c%u\n",
3806                 U ? 'u' : 's', 8 << size,
3807                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3808                 nreg);
3809          }
3810          break;
3811       case 5:
3812          if (B == 0) {
3813             /* VRSHL */
3814             IROp op, op_shrn, op_shln, cmp_gt, op_add;
3815             IRTemp shval, old_shval, imm_val, round;
3816             UInt i;
3817             ULong imm;
3818             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3819             imm = 1L;
3820             switch (size) {
3821                case 0: imm = (imm <<  8) | imm; /* fall through */
3822                case 1: imm = (imm << 16) | imm; /* fall through */
3823                case 2: imm = (imm << 32) | imm; /* fall through */
3824                case 3: break;
3825                default: vassert(0);
3826             }
3827             imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
3828             round = newTemp(Q ? Ity_V128 : Ity_I64);
3829             assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
3830             if (U) {
3831                switch (size) {
3832                   case 0:
3833                      op = Q ? Iop_Shl8x16 : Iop_Shl8x8;
3834                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3835                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3836                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3837                      break;
3838                   case 1:
3839                      op = Q ? Iop_Shl16x8 : Iop_Shl16x4;
3840                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3841                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3842                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3843                      break;
3844                   case 2:
3845                      op = Q ? Iop_Shl32x4 : Iop_Shl32x2;
3846                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
3847                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3848                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3849                      break;
3850                   case 3:
3851                      op = Q ? Iop_Shl64x2 : Iop_Shl64;
3852                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
3853                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3854                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3855                      break;
3856                   default:
3857                      vassert(0);
3858                }
3859             } else {
3860                switch (size) {
3861                   case 0:
3862                      op = Q ? Iop_Sal8x16 : Iop_Sal8x8;
3863                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3864                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3865                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3866                      break;
3867                   case 1:
3868                      op = Q ? Iop_Sal16x8 : Iop_Sal16x4;
3869                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3870                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3871                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3872                      break;
3873                   case 2:
3874                      op = Q ? Iop_Sal32x4 : Iop_Sal32x2;
3875                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
3876                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3877                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3878                      break;
3879                   case 3:
3880                      op = Q ? Iop_Sal64x2 : Iop_Sal64x1;
3881                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
3882                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3883                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3884                      break;
3885                   default:
3886                      vassert(0);
3887                }
3888             }
3889             if (Q) {
3890                shval = newTemp(Ity_V128);
3891             } else {
3892                shval = newTemp(Ity_I64);
3893             }
3894             /* Only least significant byte from second argument is used.
3895                Copy this byte to the whole vector element. */
3896             assign(shval, binop(op_shrn,
3897                                 binop(op_shln,
3898                                        mkexpr(arg_n),
3899                                        mkU8((8 << size) - 8)),
3900                                 mkU8((8 << size) - 8)));
3901             for (i = 0; i < size; i++) {
3902                old_shval = shval;
3903                shval = newTemp(Q ? Ity_V128 : Ity_I64);
3904                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
3905                                    mkexpr(old_shval),
3906                                    binop(op_shln,
3907                                          mkexpr(old_shval),
3908                                          mkU8(8 << i))));
3909             }
3910             /* Compute the result */
3911             if (!Q && size == 3 && U) {
3912                assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
3913                                    binop(op,
3914                                          mkexpr(arg_m),
3915                                          unop(Iop_64to8,
3916                                               binop(op_add,
3917                                                     mkexpr(arg_n),
3918                                                     mkexpr(imm_val)))),
3919                                    binop(Q ? Iop_AndV128 : Iop_And64,
3920                                          mkexpr(imm_val),
3921                                          binop(cmp_gt,
3922                                                Q ? mkU128(0) : mkU64(0),
3923                                                mkexpr(arg_n)))));
3924                assign(res, binop(op_add,
3925                                  binop(op,
3926                                        mkexpr(arg_m),
3927                                        unop(Iop_64to8, mkexpr(arg_n))),
3928                                  mkexpr(round)));
3929             } else {
3930                assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
3931                                    binop(op,
3932                                          mkexpr(arg_m),
3933                                          binop(op_add,
3934                                                mkexpr(arg_n),
3935                                                mkexpr(imm_val))),
3936                                    binop(Q ? Iop_AndV128 : Iop_And64,
3937                                          mkexpr(imm_val),
3938                                          binop(cmp_gt,
3939                                                Q ? mkU128(0) : mkU64(0),
3940                                                mkexpr(arg_n)))));
3941                assign(res, binop(op_add,
3942                                  binop(op, mkexpr(arg_m), mkexpr(arg_n)),
3943                                  mkexpr(round)));
3944             }
3945             DIP("vrshl.%c%u %c%u, %c%u, %c%u\n",
3946                 U ? 'u' : 's', 8 << size,
3947                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
3948                 nreg);
3949          } else {
3950             /* VQRSHL */
3951             IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt, op_add;
3952             IRTemp tmp, shval, mask, old_shval, imm_val, round;
3953             UInt i;
3954             ULong esize, imm;
3955             cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
3956             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
3957             imm = 1L;
3958             switch (size) {
3959                case 0: imm = (imm <<  8) | imm; /* fall through */
3960                case 1: imm = (imm << 16) | imm; /* fall through */
3961                case 2: imm = (imm << 32) | imm; /* fall through */
3962                case 3: break;
3963                default: vassert(0);
3964             }
3965             imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
3966             round = newTemp(Q ? Ity_V128 : Ity_I64);
3967             assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
3968             if (U) {
3969                switch (size) {
3970                   case 0:
3971                      op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
3972                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
3973                      op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
3974                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
3975                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
3976                      break;
3977                   case 1:
3978                      op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
3979                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
3980                      op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
3981                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
3982                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
3983                      break;
3984                   case 2:
3985                      op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
3986                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
3987                      op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
3988                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
3989                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
3990                      break;
3991                   case 3:
3992                      op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
3993                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
3994                      op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
3995                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
3996                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
3997                      break;
3998                   default:
3999                      vassert(0);
4000                }
4001             } else {
4002                switch (size) {
4003                   case 0:
4004                      op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
4005                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
4006                      op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
4007                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
4008                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
4009                      break;
4010                   case 1:
4011                      op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
4012                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
4013                      op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
4014                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
4015                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
4016                      break;
4017                   case 2:
4018                      op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
4019                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
4020                      op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
4021                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
4022                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
4023                      break;
4024                   case 3:
4025                      op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
4026                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
4027                      op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
4028                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
4029                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
4030                      break;
4031                   default:
4032                      vassert(0);
4033                }
4034             }
4035             if (Q) {
4036                tmp = newTemp(Ity_V128);
4037                shval = newTemp(Ity_V128);
4038                mask = newTemp(Ity_V128);
4039             } else {
4040                tmp = newTemp(Ity_I64);
4041                shval = newTemp(Ity_I64);
4042                mask = newTemp(Ity_I64);
4043             }
4044             /* Only least significant byte from second argument is used.
4045                Copy this byte to the whole vector element. */
4046             assign(shval, binop(op_shrn,
4047                                 binop(op_shln,
4048                                        mkexpr(arg_n),
4049                                        mkU8((8 << size) - 8)),
4050                                 mkU8((8 << size) - 8)));
4051             for (i = 0; i < size; i++) {
4052                old_shval = shval;
4053                shval = newTemp(Q ? Ity_V128 : Ity_I64);
4054                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
4055                                    mkexpr(old_shval),
4056                                    binop(op_shln,
4057                                          mkexpr(old_shval),
4058                                          mkU8(8 << i))));
4059             }
4060             /* Compute the result */
4061             assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
4062                                 binop(op,
4063                                       mkexpr(arg_m),
4064                                       binop(op_add,
4065                                             mkexpr(arg_n),
4066                                             mkexpr(imm_val))),
4067                                 binop(Q ? Iop_AndV128 : Iop_And64,
4068                                       mkexpr(imm_val),
4069                                       binop(cmp_gt,
4070                                             Q ? mkU128(0) : mkU64(0),
4071                                             mkexpr(arg_n)))));
4072             assign(res, binop(op_add,
4073                               binop(op, mkexpr(arg_m), mkexpr(arg_n)),
4074                               mkexpr(round)));
4075 #ifndef DISABLE_QC_FLAG
4076             /* If shift is greater or equal to the element size and element is
4077                non-zero, then QC flag should be set. */
4078             esize = (8 << size) - 1;
4079             esize = (esize <<  8) | esize;
4080             esize = (esize << 16) | esize;
4081             esize = (esize << 32) | esize;
4082             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4083                              binop(cmp_gt, mkexpr(shval),
4084                                            Q ? mkU128(esize) : mkU64(esize)),
4085                              unop(cmp_neq, mkexpr(arg_m))),
4086                        Q ? mkU128(0) : mkU64(0),
4087                        Q, condT);
4088             /* Othervise QC flag should be set if shift value is positive and
4089                result beign rightshifted the same value is not equal to left
4090                argument. */
4091             assign(mask, binop(cmp_gt, mkexpr(shval),
4092                                Q ? mkU128(0) : mkU64(0)));
4093             if (!Q && size == 3)
4094                assign(tmp, binop(op_rev, mkexpr(res),
4095                                          unop(Iop_64to8, mkexpr(arg_n))));
4096             else
4097                assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
4098             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4099                              mkexpr(tmp), mkexpr(mask)),
4100                        binop(Q ? Iop_AndV128 : Iop_And64,
4101                              mkexpr(arg_m), mkexpr(mask)),
4102                        Q, condT);
4103 #endif
4104             DIP("vqrshl.%c%u %c%u, %c%u, %c%u\n",
4105                 U ? 'u' : 's', 8 << size,
4106                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
4107                 nreg);
4108          }
4109          break;
4110       case 6:
4111          /* VMAX, VMIN  */
4112          if (B == 0) {
4113             /* VMAX */
4114             IROp op;
4115             if (U == 0) {
4116                switch (size) {
4117                   case 0: op = Q ? Iop_Max8Sx16 : Iop_Max8Sx8; break;
4118                   case 1: op = Q ? Iop_Max16Sx8 : Iop_Max16Sx4; break;
4119                   case 2: op = Q ? Iop_Max32Sx4 : Iop_Max32Sx2; break;
4120                   case 3: return False;
4121                   default: vassert(0);
4122                }
4123             } else {
4124                switch (size) {
4125                   case 0: op = Q ? Iop_Max8Ux16 : Iop_Max8Ux8; break;
4126                   case 1: op = Q ? Iop_Max16Ux8 : Iop_Max16Ux4; break;
4127                   case 2: op = Q ? Iop_Max32Ux4 : Iop_Max32Ux2; break;
4128                   case 3: return False;
4129                   default: vassert(0);
4130                }
4131             }
4132             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4133             DIP("vmax.%c%u %c%u, %c%u, %c%u\n",
4134                 U ? 'u' : 's', 8 << size,
4135                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4136                 mreg);
4137          } else {
4138             /* VMIN */
4139             IROp op;
4140             if (U == 0) {
4141                switch (size) {
4142                   case 0: op = Q ? Iop_Min8Sx16 : Iop_Min8Sx8; break;
4143                   case 1: op = Q ? Iop_Min16Sx8 : Iop_Min16Sx4; break;
4144                   case 2: op = Q ? Iop_Min32Sx4 : Iop_Min32Sx2; break;
4145                   case 3: return False;
4146                   default: vassert(0);
4147                }
4148             } else {
4149                switch (size) {
4150                   case 0: op = Q ? Iop_Min8Ux16 : Iop_Min8Ux8; break;
4151                   case 1: op = Q ? Iop_Min16Ux8 : Iop_Min16Ux4; break;
4152                   case 2: op = Q ? Iop_Min32Ux4 : Iop_Min32Ux2; break;
4153                   case 3: return False;
4154                   default: vassert(0);
4155                }
4156             }
4157             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4158             DIP("vmin.%c%u %c%u, %c%u, %c%u\n",
4159                 U ? 'u' : 's', 8 << size,
4160                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4161                 mreg);
4162          }
4163          break;
4164       case 7:
4165          if (B == 0) {
4166             /* VABD */
4167             IROp op_cmp, op_sub;
4168             IRTemp cond;
4169             if ((theInstr >> 23) & 1) {
4170                vpanic("VABDL should not be in dis_neon_data_3same\n");
4171             }
4172             if (Q) {
4173                switch (size) {
4174                   case 0:
4175                      op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
4176                      op_sub = Iop_Sub8x16;
4177                      break;
4178                   case 1:
4179                      op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
4180                      op_sub = Iop_Sub16x8;
4181                      break;
4182                   case 2:
4183                      op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
4184                      op_sub = Iop_Sub32x4;
4185                      break;
4186                   case 3:
4187                      return False;
4188                   default:
4189                      vassert(0);
4190                }
4191             } else {
4192                switch (size) {
4193                   case 0:
4194                      op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4195                      op_sub = Iop_Sub8x8;
4196                      break;
4197                   case 1:
4198                      op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4199                      op_sub = Iop_Sub16x4;
4200                      break;
4201                   case 2:
4202                      op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4203                      op_sub = Iop_Sub32x2;
4204                      break;
4205                   case 3:
4206                      return False;
4207                   default:
4208                      vassert(0);
4209                }
4210             }
4211             if (Q) {
4212                cond = newTemp(Ity_V128);
4213             } else {
4214                cond = newTemp(Ity_I64);
4215             }
4216             assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
4217             assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
4218                               binop(Q ? Iop_AndV128 : Iop_And64,
4219                                     binop(op_sub, mkexpr(arg_n),
4220                                                   mkexpr(arg_m)),
4221                                     mkexpr(cond)),
4222                               binop(Q ? Iop_AndV128 : Iop_And64,
4223                                     binop(op_sub, mkexpr(arg_m),
4224                                                   mkexpr(arg_n)),
4225                                     unop(Q ? Iop_NotV128 : Iop_Not64,
4226                                          mkexpr(cond)))));
4227             DIP("vabd.%c%u %c%u, %c%u, %c%u\n",
4228                 U ? 'u' : 's', 8 << size,
4229                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4230                 mreg);
4231          } else {
4232             /* VABA */
4233             IROp op_cmp, op_sub, op_add;
4234             IRTemp cond, acc, tmp;
4235             if ((theInstr >> 23) & 1) {
4236                vpanic("VABAL should not be in dis_neon_data_3same");
4237             }
4238             if (Q) {
4239                switch (size) {
4240                   case 0:
4241                      op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
4242                      op_sub = Iop_Sub8x16;
4243                      op_add = Iop_Add8x16;
4244                      break;
4245                   case 1:
4246                      op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
4247                      op_sub = Iop_Sub16x8;
4248                      op_add = Iop_Add16x8;
4249                      break;
4250                   case 2:
4251                      op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
4252                      op_sub = Iop_Sub32x4;
4253                      op_add = Iop_Add32x4;
4254                      break;
4255                   case 3:
4256                      return False;
4257                   default:
4258                      vassert(0);
4259                }
4260             } else {
4261                switch (size) {
4262                   case 0:
4263                      op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4264                      op_sub = Iop_Sub8x8;
4265                      op_add = Iop_Add8x8;
4266                      break;
4267                   case 1:
4268                      op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4269                      op_sub = Iop_Sub16x4;
4270                      op_add = Iop_Add16x4;
4271                      break;
4272                   case 2:
4273                      op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4274                      op_sub = Iop_Sub32x2;
4275                      op_add = Iop_Add32x2;
4276                      break;
4277                   case 3:
4278                      return False;
4279                   default:
4280                      vassert(0);
4281                }
4282             }
4283             if (Q) {
4284                cond = newTemp(Ity_V128);
4285                acc = newTemp(Ity_V128);
4286                tmp = newTemp(Ity_V128);
4287                assign(acc, getQReg(dreg));
4288             } else {
4289                cond = newTemp(Ity_I64);
4290                acc = newTemp(Ity_I64);
4291                tmp = newTemp(Ity_I64);
4292                assign(acc, getDRegI64(dreg));
4293             }
4294             assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
4295             assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
4296                               binop(Q ? Iop_AndV128 : Iop_And64,
4297                                     binop(op_sub, mkexpr(arg_n),
4298                                                   mkexpr(arg_m)),
4299                                     mkexpr(cond)),
4300                               binop(Q ? Iop_AndV128 : Iop_And64,
4301                                     binop(op_sub, mkexpr(arg_m),
4302                                                   mkexpr(arg_n)),
4303                                     unop(Q ? Iop_NotV128 : Iop_Not64,
4304                                          mkexpr(cond)))));
4305             assign(res, binop(op_add, mkexpr(acc), mkexpr(tmp)));
4306             DIP("vaba.%c%u %c%u, %c%u, %c%u\n",
4307                 U ? 'u' : 's', 8 << size,
4308                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4309                 mreg);
4310          }
4311          break;
4312       case 8:
4313          if (B == 0) {
4314             IROp op;
4315             if (U == 0) {
4316                /* VADD  */
4317                switch (size) {
4318                   case 0: op = Q ? Iop_Add8x16 : Iop_Add8x8; break;
4319                   case 1: op = Q ? Iop_Add16x8 : Iop_Add16x4; break;
4320                   case 2: op = Q ? Iop_Add32x4 : Iop_Add32x2; break;
4321                   case 3: op = Q ? Iop_Add64x2 : Iop_Add64; break;
4322                   default: vassert(0);
4323                }
4324                DIP("vadd.i%u %c%u, %c%u, %c%u\n",
4325                    8 << size, Q ? 'q' : 'd',
4326                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4327             } else {
4328                /* VSUB  */
4329                switch (size) {
4330                   case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
4331                   case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
4332                   case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
4333                   case 3: op = Q ? Iop_Sub64x2 : Iop_Sub64; break;
4334                   default: vassert(0);
4335                }
4336                DIP("vsub.i%u %c%u, %c%u, %c%u\n",
4337                    8 << size, Q ? 'q' : 'd',
4338                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4339             }
4340             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4341          } else {
4342             IROp op;
4343             switch (size) {
4344                case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
4345                case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
4346                case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
4347                case 3: op = Q ? Iop_CmpNEZ64x2 : Iop_CmpwNEZ64; break;
4348                default: vassert(0);
4349             }
4350             if (U == 0) {
4351                /* VTST  */
4352                assign(res, unop(op, binop(Q ? Iop_AndV128 : Iop_And64,
4353                                           mkexpr(arg_n),
4354                                           mkexpr(arg_m))));
4355                DIP("vtst.%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             } else {
4359                /* VCEQ  */
4360                assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
4361                                 unop(op,
4362                                      binop(Q ? Iop_XorV128 : Iop_Xor64,
4363                                            mkexpr(arg_n),
4364                                            mkexpr(arg_m)))));
4365                DIP("vceq.i%u %c%u, %c%u, %c%u\n",
4366                    8 << size, Q ? 'q' : 'd',
4367                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4368             }
4369          }
4370          break;
4371       case 9:
4372          if (B == 0) {
4373             /* VMLA, VMLS (integer) */
4374             IROp op, op2;
4375             UInt P = (theInstr >> 24) & 1;
4376             if (P) {
4377                switch (size) {
4378                   case 0:
4379                      op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
4380                      op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
4381                      break;
4382                   case 1:
4383                      op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
4384                      op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
4385                      break;
4386                   case 2:
4387                      op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
4388                      op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
4389                      break;
4390                   case 3:
4391                      return False;
4392                   default:
4393                      vassert(0);
4394                }
4395             } else {
4396                switch (size) {
4397                   case 0:
4398                      op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
4399                      op2 = Q ? Iop_Add8x16 : Iop_Add8x8;
4400                      break;
4401                   case 1:
4402                      op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
4403                      op2 = Q ? Iop_Add16x8 : Iop_Add16x4;
4404                      break;
4405                   case 2:
4406                      op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
4407                      op2 = Q ? Iop_Add32x4 : Iop_Add32x2;
4408                      break;
4409                   case 3:
4410                      return False;
4411                   default:
4412                      vassert(0);
4413                }
4414             }
4415             assign(res, binop(op2,
4416                               Q ? getQReg(dreg) : getDRegI64(dreg),
4417                               binop(op, mkexpr(arg_n), mkexpr(arg_m))));
4418             DIP("vml%c.i%u %c%u, %c%u, %c%u\n",
4419                 P ? 's' : 'a', 8 << size,
4420                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4421                 mreg);
4422          } else {
4423             /* VMUL */
4424             IROp op;
4425             UInt P = (theInstr >> 24) & 1;
4426             if (P) {
4427                switch (size) {
4428                   case 0:
4429                      op = Q ? Iop_PolynomialMul8x16 : Iop_PolynomialMul8x8;
4430                      break;
4431                   case 1: case 2: case 3: return False;
4432                   default: vassert(0);
4433                }
4434             } else {
4435                switch (size) {
4436                   case 0: op = Q ? Iop_Mul8x16 : Iop_Mul8x8; break;
4437                   case 1: op = Q ? Iop_Mul16x8 : Iop_Mul16x4; break;
4438                   case 2: op = Q ? Iop_Mul32x4 : Iop_Mul32x2; break;
4439                   case 3: return False;
4440                   default: vassert(0);
4441                }
4442             }
4443             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4444             DIP("vmul.%c%u %c%u, %c%u, %c%u\n",
4445                 P ? 'p' : 'i', 8 << size,
4446                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
4447                 mreg);
4448          }
4449          break;
4450       case 10: {
4451          /* VPMAX, VPMIN  */
4452          UInt P = (theInstr >> 4) & 1;
4453          IROp op;
4454          if (Q)
4455             return False;
4456          if (P) {
4457             switch (size) {
4458                case 0: op = U ? Iop_PwMin8Ux8  : Iop_PwMin8Sx8; break;
4459                case 1: op = U ? Iop_PwMin16Ux4 : Iop_PwMin16Sx4; break;
4460                case 2: op = U ? Iop_PwMin32Ux2 : Iop_PwMin32Sx2; break;
4461                case 3: return False;
4462                default: vassert(0);
4463             }
4464          } else {
4465             switch (size) {
4466                case 0: op = U ? Iop_PwMax8Ux8  : Iop_PwMax8Sx8; break;
4467                case 1: op = U ? Iop_PwMax16Ux4 : Iop_PwMax16Sx4; break;
4468                case 2: op = U ? Iop_PwMax32Ux2 : Iop_PwMax32Sx2; break;
4469                case 3: return False;
4470                default: vassert(0);
4471             }
4472          }
4473          assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4474          DIP("vp%s.%c%u %c%u, %c%u, %c%u\n",
4475              P ? "min" : "max", U ? 'u' : 's',
4476              8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
4477              Q ? 'q' : 'd', mreg);
4478          break;
4479       }
4480       case 11:
4481          if (B == 0) {
4482             if (U == 0) {
4483                /* VQDMULH  */
4484                IROp op ,op2;
4485                ULong imm;
4486                switch (size) {
4487                   case 0: case 3:
4488                      return False;
4489                   case 1:
4490                      op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
4491                      op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
4492                      imm = 1LL << 15;
4493                      imm = (imm << 16) | imm;
4494                      imm = (imm << 32) | imm;
4495                      break;
4496                   case 2:
4497                      op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
4498                      op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
4499                      imm = 1LL << 31;
4500                      imm = (imm << 32) | imm;
4501                      break;
4502                   default:
4503                      vassert(0);
4504                }
4505                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4506 #ifndef DISABLE_QC_FLAG
4507                setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4508                                 binop(op2, mkexpr(arg_n),
4509                                            Q ? mkU128(imm) : mkU64(imm)),
4510                                 binop(op2, mkexpr(arg_m),
4511                                            Q ? mkU128(imm) : mkU64(imm))),
4512                           Q ? mkU128(0) : mkU64(0),
4513                           Q, condT);
4514 #endif
4515                DIP("vqdmulh.s%u %c%u, %c%u, %c%u\n",
4516                    8 << size, Q ? 'q' : 'd',
4517                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4518             } else {
4519                /* VQRDMULH */
4520                IROp op ,op2;
4521                ULong imm;
4522                switch(size) {
4523                   case 0: case 3:
4524                      return False;
4525                   case 1:
4526                      imm = 1LL << 15;
4527                      imm = (imm << 16) | imm;
4528                      imm = (imm << 32) | imm;
4529                      op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
4530                      op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
4531                      break;
4532                   case 2:
4533                      imm = 1LL << 31;
4534                      imm = (imm << 32) | imm;
4535                      op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
4536                      op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
4537                      break;
4538                   default:
4539                      vassert(0);
4540                }
4541                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4542 #ifndef DISABLE_QC_FLAG
4543                setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
4544                                 binop(op2, mkexpr(arg_n),
4545                                            Q ? mkU128(imm) : mkU64(imm)),
4546                                 binop(op2, mkexpr(arg_m),
4547                                            Q ? mkU128(imm) : mkU64(imm))),
4548                           Q ? mkU128(0) : mkU64(0),
4549                           Q, condT);
4550 #endif
4551                DIP("vqrdmulh.s%u %c%u, %c%u, %c%u\n",
4552                    8 << size, Q ? 'q' : 'd',
4553                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4554             }
4555          } else {
4556             if (U == 0) {
4557                /* VPADD */
4558                IROp op;
4559                if (Q)
4560                   return False;
4561                switch (size) {
4562                   case 0: op = Q ? Iop_PwAdd8x16 : Iop_PwAdd8x8;  break;
4563                   case 1: op = Q ? Iop_PwAdd16x8 : Iop_PwAdd16x4; break;
4564                   case 2: op = Q ? Iop_PwAdd32x4 : Iop_PwAdd32x2; break;
4565                   case 3: return False;
4566                   default: vassert(0);
4567                }
4568                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4569                DIP("vpadd.i%d %c%u, %c%u, %c%u\n",
4570                    8 << size, Q ? 'q' : 'd',
4571                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4572             }
4573          }
4574          break;
4575       /* Starting from here these are FP SIMD cases */
4576       case 13:
4577          if (B == 0) {
4578             IROp op;
4579             if (U == 0) {
4580                if ((C >> 1) == 0) {
4581                   /* VADD  */
4582                   op = Q ? Iop_Add32Fx4 : Iop_Add32Fx2 ;
4583                   DIP("vadd.f32 %c%u, %c%u, %c%u\n",
4584                       Q ? 'q' : 'd', dreg,
4585                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4586                } else {
4587                   /* VSUB  */
4588                   op = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2 ;
4589                   DIP("vsub.f32 %c%u, %c%u, %c%u\n",
4590                       Q ? 'q' : 'd', dreg,
4591                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4592                }
4593             } else {
4594                if ((C >> 1) == 0) {
4595                   /* VPADD */
4596                   if (Q)
4597                      return False;
4598                   op = Iop_PwAdd32Fx2;
4599                   DIP("vpadd.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4600                } else {
4601                   /* VABD  */
4602                   if (Q) {
4603                      assign(res, unop(Iop_Abs32Fx4,
4604                                       binop(Iop_Sub32Fx4,
4605                                             mkexpr(arg_n),
4606                                             mkexpr(arg_m))));
4607                   } else {
4608                      assign(res, unop(Iop_Abs32Fx2,
4609                                       binop(Iop_Sub32Fx2,
4610                                             mkexpr(arg_n),
4611                                             mkexpr(arg_m))));
4612                   }
4613                   DIP("vabd.f32 %c%u, %c%u, %c%u\n",
4614                       Q ? 'q' : 'd', dreg,
4615                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4616                   break;
4617                }
4618             }
4619             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4620          } else {
4621             if (U == 0) {
4622                /* VMLA, VMLS  */
4623                IROp op, op2;
4624                UInt P = (theInstr >> 21) & 1;
4625                if (P) {
4626                   switch (size & 1) {
4627                      case 0:
4628                         op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
4629                         op2 = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
4630                         break;
4631                      case 1: return False;
4632                      default: vassert(0);
4633                   }
4634                } else {
4635                   switch (size & 1) {
4636                      case 0:
4637                         op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
4638                         op2 = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
4639                         break;
4640                      case 1: return False;
4641                      default: vassert(0);
4642                   }
4643                }
4644                assign(res, binop(op2,
4645                                  Q ? getQReg(dreg) : getDRegI64(dreg),
4646                                  binop(op, mkexpr(arg_n), mkexpr(arg_m))));
4647
4648                DIP("vml%c.f32 %c%u, %c%u, %c%u\n",
4649                    P ? 's' : 'a', Q ? 'q' : 'd',
4650                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4651             } else {
4652                /* VMUL  */
4653                IROp op;
4654                if ((C >> 1) != 0)
4655                   return False;
4656                op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2 ;
4657                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4658                DIP("vmul.f32 %c%u, %c%u, %c%u\n",
4659                    Q ? 'q' : 'd', dreg,
4660                    Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4661             }
4662          }
4663          break;
4664       case 14:
4665          if (B == 0) {
4666             if (U == 0) {
4667                if ((C >> 1) == 0) {
4668                   /* VCEQ  */
4669                   IROp op;
4670                   if ((theInstr >> 20) & 1)
4671                      return False;
4672                   op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2;
4673                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4674                   DIP("vceq.f32 %c%u, %c%u, %c%u\n",
4675                       Q ? 'q' : 'd', dreg,
4676                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4677                } else {
4678                   return False;
4679                }
4680             } else {
4681                if ((C >> 1) == 0) {
4682                   /* VCGE  */
4683                   IROp op;
4684                   if ((theInstr >> 20) & 1)
4685                      return False;
4686                   op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
4687                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4688                   DIP("vcge.f32 %c%u, %c%u, %c%u\n",
4689                       Q ? 'q' : 'd', dreg,
4690                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4691                } else {
4692                   /* VCGT  */
4693                   IROp op;
4694                   if ((theInstr >> 20) & 1)
4695                      return False;
4696                   op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
4697                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4698                   DIP("vcgt.f32 %c%u, %c%u, %c%u\n",
4699                       Q ? 'q' : 'd', dreg,
4700                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4701                }
4702             }
4703          } else {
4704             if (U == 1) {
4705                /* VACGE, VACGT */
4706                UInt op_bit = (theInstr >> 21) & 1;
4707                IROp op, op2;
4708                op2 = Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2;
4709                if (op_bit) {
4710                   op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
4711                   assign(res, binop(op,
4712                                     unop(op2, mkexpr(arg_n)),
4713                                     unop(op2, mkexpr(arg_m))));
4714                } else {
4715                   op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
4716                   assign(res, binop(op,
4717                                     unop(op2, mkexpr(arg_n)),
4718                                     unop(op2, mkexpr(arg_m))));
4719                }
4720                DIP("vacg%c.f32 %c%u, %c%u, %c%u\n", op_bit ? 't' : 'e',
4721                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
4722                    Q ? 'q' : 'd', mreg);
4723             }
4724          }
4725          break;
4726       case 15:
4727          if (B == 0) {
4728             if (U == 0) {
4729                /* VMAX, VMIN  */
4730                IROp op;
4731                if ((theInstr >> 20) & 1)
4732                   return False;
4733                if ((theInstr >> 21) & 1) {
4734                   op = Q ? Iop_Min32Fx4 : Iop_Min32Fx2;
4735                   DIP("vmin.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4736                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4737                } else {
4738                   op = Q ? Iop_Max32Fx4 : Iop_Max32Fx2;
4739                   DIP("vmax.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4740                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4741                }
4742                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4743             } else {
4744                /* VPMAX, VPMIN   */
4745                IROp op;
4746                if (Q)
4747                   return False;
4748                if ((theInstr >> 20) & 1)
4749                   return False;
4750                if ((theInstr >> 21) & 1) {
4751                   op = Iop_PwMin32Fx2;
4752                   DIP("vpmin.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4753                } else {
4754                   op = Iop_PwMax32Fx2;
4755                   DIP("vpmax.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
4756                }
4757                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
4758             }
4759          } else {
4760             if (U == 0) {
4761                if ((C >> 1) == 0) {
4762                   /* VRECPS */
4763                   if ((theInstr >> 20) & 1)
4764                      return False;
4765                   assign(res, binop(Q ? Iop_Recps32Fx4 : Iop_Recps32Fx2,
4766                                     mkexpr(arg_n),
4767                                     mkexpr(arg_m)));
4768                   DIP("vrecps.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4769                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4770                } else {
4771                   /* VRSQRTS  */
4772                   if ((theInstr >> 20) & 1)
4773                      return False;
4774                   assign(res, binop(Q ? Iop_Rsqrts32Fx4 : Iop_Rsqrts32Fx2,
4775                                     mkexpr(arg_n),
4776                                     mkexpr(arg_m)));
4777                   DIP("vrsqrts.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
4778                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
4779                }
4780             }
4781          }
4782          break;
4783    }
4784
4785    if (Q) {
4786       putQReg(dreg, mkexpr(res), condT);
4787    } else {
4788       putDRegI64(dreg, mkexpr(res), condT);
4789    }
4790
4791    return True;
4792 }
4793
4794 /* A7.4.2 Three registers of different length */
4795 static
4796 Bool dis_neon_data_3diff ( UInt theInstr, IRTemp condT )
4797 {
4798    UInt A = (theInstr >> 8) & 0xf;
4799    UInt B = (theInstr >> 20) & 3;
4800    UInt U = (theInstr >> 24) & 1;
4801    UInt P = (theInstr >> 9) & 1;
4802    UInt mreg = get_neon_m_regno(theInstr);
4803    UInt nreg = get_neon_n_regno(theInstr);
4804    UInt dreg = get_neon_d_regno(theInstr);
4805    UInt size = B;
4806    ULong imm;
4807    IRTemp res, arg_m, arg_n, cond, tmp;
4808    IROp cvt, cvt2, cmp, op, op2, sh, add;
4809    switch (A) {
4810       case 0: case 1: case 2: case 3:
4811          /* VADDL, VADDW, VSUBL, VSUBW */
4812          if (dreg & 1)
4813             return False;
4814          dreg >>= 1;
4815          size = B;
4816          switch (size) {
4817             case 0:
4818                cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
4819                op = (A & 2) ? Iop_Sub16x8 : Iop_Add16x8;
4820                break;
4821             case 1:
4822                cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
4823                op = (A & 2) ? Iop_Sub32x4 : Iop_Add32x4;
4824                break;
4825             case 2:
4826                cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
4827                op = (A & 2) ? Iop_Sub64x2 : Iop_Add64x2;
4828                break;
4829             case 3:
4830                return False;
4831             default:
4832                vassert(0);
4833          }
4834          arg_n = newTemp(Ity_V128);
4835          arg_m = newTemp(Ity_V128);
4836          if (A & 1) {
4837             if (nreg & 1)
4838                return False;
4839             nreg >>= 1;
4840             assign(arg_n, getQReg(nreg));
4841          } else {
4842             assign(arg_n, unop(cvt, getDRegI64(nreg)));
4843          }
4844          assign(arg_m, unop(cvt, getDRegI64(mreg)));
4845          putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
4846                        condT);
4847          DIP("v%s%c.%c%u q%u, %c%u, d%u\n", (A & 2) ? "sub" : "add",
4848              (A & 1) ? 'w' : 'l', U ? 'u' : 's', 8 << size, dreg,
4849              (A & 1) ? 'q' : 'd', nreg, mreg);
4850          return True;
4851       case 4:
4852          /* VADDHN, VRADDHN */
4853          if (mreg & 1)
4854             return False;
4855          mreg >>= 1;
4856          if (nreg & 1)
4857             return False;
4858          nreg >>= 1;
4859          size = B;
4860          switch (size) {
4861             case 0:
4862                op = Iop_Add16x8;
4863                cvt = Iop_Shorten16x8;
4864                sh = Iop_ShrN16x8;
4865                imm = 1U << 7;
4866                imm = (imm << 16) | imm;
4867                imm = (imm << 32) | imm;
4868                break;
4869             case 1:
4870                op = Iop_Add32x4;
4871                cvt = Iop_Shorten32x4;
4872                sh = Iop_ShrN32x4;
4873                imm = 1U << 15;
4874                imm = (imm << 32) | imm;
4875                break;
4876             case 2:
4877                op = Iop_Add64x2;
4878                cvt = Iop_Shorten64x2;
4879                sh = Iop_ShrN64x2;
4880                imm = 1U << 31;
4881                break;
4882             case 3:
4883                return False;
4884             default:
4885                vassert(0);
4886          }
4887          tmp = newTemp(Ity_V128);
4888          res = newTemp(Ity_V128);
4889          assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
4890          if (U) {
4891             /* VRADDHN */
4892             assign(res, binop(op, mkexpr(tmp),
4893                      binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
4894          } else {
4895             assign(res, mkexpr(tmp));
4896          }
4897          putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
4898                     condT);
4899          DIP("v%saddhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
4900              nreg, mreg);
4901          return True;
4902       case 5:
4903          /* VABAL */
4904          if (!((theInstr >> 23) & 1)) {
4905             vpanic("VABA should not be in dis_neon_data_3diff\n");
4906          }
4907          if (dreg & 1)
4908             return False;
4909          dreg >>= 1;
4910          switch (size) {
4911             case 0:
4912                cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
4913                cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
4914                cvt2 = Iop_Longen8Sx8;
4915                op = Iop_Sub16x8;
4916                op2 = Iop_Add16x8;
4917                break;
4918             case 1:
4919                cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
4920                cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
4921                cvt2 = Iop_Longen16Sx4;
4922                op = Iop_Sub32x4;
4923                op2 = Iop_Add32x4;
4924                break;
4925             case 2:
4926                cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
4927                cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
4928                cvt2 = Iop_Longen32Sx2;
4929                op = Iop_Sub64x2;
4930                op2 = Iop_Add64x2;
4931                break;
4932             case 3:
4933                return False;
4934             default:
4935                vassert(0);
4936          }
4937          arg_n = newTemp(Ity_V128);
4938          arg_m = newTemp(Ity_V128);
4939          cond = newTemp(Ity_V128);
4940          res = newTemp(Ity_V128);
4941          assign(arg_n, unop(cvt, getDRegI64(nreg)));
4942          assign(arg_m, unop(cvt, getDRegI64(mreg)));
4943          assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
4944                                             getDRegI64(mreg))));
4945          assign(res, binop(op2,
4946                            binop(Iop_OrV128,
4947                                  binop(Iop_AndV128,
4948                                        binop(op, mkexpr(arg_n), mkexpr(arg_m)),
4949                                        mkexpr(cond)),
4950                                  binop(Iop_AndV128,
4951                                        binop(op, mkexpr(arg_m), mkexpr(arg_n)),
4952                                        unop(Iop_NotV128, mkexpr(cond)))),
4953                            getQReg(dreg)));
4954          putQReg(dreg, mkexpr(res), condT);
4955          DIP("vabal.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
4956              nreg, mreg);
4957          return True;
4958       case 6:
4959          /* VSUBHN, VRSUBHN */
4960          if (mreg & 1)
4961             return False;
4962          mreg >>= 1;
4963          if (nreg & 1)
4964             return False;
4965          nreg >>= 1;
4966          size = B;
4967          switch (size) {
4968             case 0:
4969                op = Iop_Sub16x8;
4970                op2 = Iop_Add16x8;
4971                cvt = Iop_Shorten16x8;
4972                sh = Iop_ShrN16x8;
4973                imm = 1U << 7;
4974                imm = (imm << 16) | imm;
4975                imm = (imm << 32) | imm;
4976                break;
4977             case 1:
4978                op = Iop_Sub32x4;
4979                op2 = Iop_Add32x4;
4980                cvt = Iop_Shorten32x4;
4981                sh = Iop_ShrN32x4;
4982                imm = 1U << 15;
4983                imm = (imm << 32) | imm;
4984                break;
4985             case 2:
4986                op = Iop_Sub64x2;
4987                op2 = Iop_Add64x2;
4988                cvt = Iop_Shorten64x2;
4989                sh = Iop_ShrN64x2;
4990                imm = 1U << 31;
4991                break;
4992             case 3:
4993                return False;
4994             default:
4995                vassert(0);
4996          }
4997          tmp = newTemp(Ity_V128);
4998          res = newTemp(Ity_V128);
4999          assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
5000          if (U) {
5001             /* VRSUBHN */
5002             assign(res, binop(op2, mkexpr(tmp),
5003                      binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
5004          } else {
5005             assign(res, mkexpr(tmp));
5006          }
5007          putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
5008                     condT);
5009          DIP("v%ssubhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
5010              nreg, mreg);
5011          return True;
5012       case 7:
5013          /* VABDL */
5014          if (!((theInstr >> 23) & 1)) {
5015             vpanic("VABL should not be in dis_neon_data_3diff\n");
5016          }
5017          if (dreg & 1)
5018             return False;
5019          dreg >>= 1;
5020          switch (size) {
5021             case 0:
5022                cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
5023                cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
5024                cvt2 = Iop_Longen8Sx8;
5025                op = Iop_Sub16x8;
5026                break;
5027             case 1:
5028                cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
5029                cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
5030                cvt2 = Iop_Longen16Sx4;
5031                op = Iop_Sub32x4;
5032                break;
5033             case 2:
5034                cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
5035                cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
5036                cvt2 = Iop_Longen32Sx2;
5037                op = Iop_Sub64x2;
5038                break;
5039             case 3:
5040                return False;
5041             default:
5042                vassert(0);
5043          }
5044          arg_n = newTemp(Ity_V128);
5045          arg_m = newTemp(Ity_V128);
5046          cond = newTemp(Ity_V128);
5047          res = newTemp(Ity_V128);
5048          assign(arg_n, unop(cvt, getDRegI64(nreg)));
5049          assign(arg_m, unop(cvt, getDRegI64(mreg)));
5050          assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
5051                                             getDRegI64(mreg))));
5052          assign(res, binop(Iop_OrV128,
5053                            binop(Iop_AndV128,
5054                                  binop(op, mkexpr(arg_n), mkexpr(arg_m)),
5055                                  mkexpr(cond)),
5056                            binop(Iop_AndV128,
5057                                  binop(op, mkexpr(arg_m), mkexpr(arg_n)),
5058                                  unop(Iop_NotV128, mkexpr(cond)))));
5059          putQReg(dreg, mkexpr(res), condT);
5060          DIP("vabdl.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
5061              nreg, mreg);
5062          return True;
5063       case 8:
5064       case 10:
5065          /* VMLAL, VMLSL (integer) */
5066          if (dreg & 1)
5067             return False;
5068          dreg >>= 1;
5069          size = B;
5070          switch (size) {
5071             case 0:
5072                op = U ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
5073                op2 = P ? Iop_Sub16x8 : Iop_Add16x8;
5074                break;
5075             case 1:
5076                op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5077                op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5078                break;
5079             case 2:
5080                op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5081                op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5082                break;
5083             case 3:
5084                return False;
5085             default:
5086                vassert(0);
5087          }
5088          res = newTemp(Ity_V128);
5089          assign(res, binop(op, getDRegI64(nreg),getDRegI64(mreg)));
5090          putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
5091          DIP("vml%cl.%c%u q%u, d%u, d%u\n", P ? 's' : 'a', U ? 'u' : 's',
5092              8 << size, dreg, nreg, mreg);
5093          return True;
5094       case 9:
5095       case 11:
5096          /* VQDMLAL, VQDMLSL */
5097          if (U)
5098             return False;
5099          if (dreg & 1)
5100             return False;
5101          dreg >>= 1;
5102          size = B;
5103          switch (size) {
5104             case 0: case 3:
5105                return False;
5106             case 1:
5107                op = Iop_QDMulLong16Sx4;
5108                cmp = Iop_CmpEQ16x4;
5109                add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
5110                op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5111                imm = 1LL << 15;
5112                imm = (imm << 16) | imm;
5113                imm = (imm << 32) | imm;
5114                break;
5115             case 2:
5116                op = Iop_QDMulLong32Sx2;
5117                cmp = Iop_CmpEQ32x2;
5118                add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
5119                op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5120                imm = 1LL << 31;
5121                imm = (imm << 32) | imm;
5122                break;
5123             default:
5124                vassert(0);
5125          }
5126          res = newTemp(Ity_V128);
5127          tmp = newTemp(Ity_V128);
5128          assign(res, binop(op, getDRegI64(nreg), getDRegI64(mreg)));
5129 #ifndef DISABLE_QC_FLAG
5130          assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
5131          setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
5132                     True, condT);
5133          setFlag_QC(binop(Iop_And64,
5134                           binop(cmp, getDRegI64(nreg), mkU64(imm)),
5135                           binop(cmp, getDRegI64(mreg), mkU64(imm))),
5136                     mkU64(0),
5137                     False, condT);
5138 #endif
5139          putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
5140          DIP("vqdml%cl.s%u q%u, d%u, d%u\n", P ? 's' : 'a', 8 << size, dreg,
5141              nreg, mreg);
5142          return True;
5143       case 12:
5144       case 14:
5145          /* VMULL (integer or polynomial) */
5146          if (dreg & 1)
5147             return False;
5148          dreg >>= 1;
5149          size = B;
5150          switch (size) {
5151             case 0:
5152                op = (U) ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
5153                if (P)
5154                   op = Iop_PolynomialMull8x8;
5155                break;
5156             case 1:
5157                op = (U) ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5158                break;
5159             case 2:
5160                op = (U) ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5161                break;
5162             default:
5163                vassert(0);
5164          }
5165          putQReg(dreg, binop(op, getDRegI64(nreg),
5166                                  getDRegI64(mreg)), condT);
5167          DIP("vmull.%c%u q%u, d%u, d%u\n", P ? 'p' : (U ? 'u' : 's'),
5168                8 << size, dreg, nreg, mreg);
5169          return True;
5170       case 13:
5171          /* VQDMULL */
5172          if (U)
5173             return False;
5174          if (dreg & 1)
5175             return False;
5176          dreg >>= 1;
5177          size = B;
5178          switch (size) {
5179             case 0:
5180             case 3:
5181                return False;
5182             case 1:
5183                op = Iop_QDMulLong16Sx4;
5184                op2 = Iop_CmpEQ16x4;
5185                imm = 1LL << 15;
5186                imm = (imm << 16) | imm;
5187                imm = (imm << 32) | imm;
5188                break;
5189             case 2:
5190                op = Iop_QDMulLong32Sx2;
5191                op2 = Iop_CmpEQ32x2;
5192                imm = 1LL << 31;
5193                imm = (imm << 32) | imm;
5194                break;
5195             default:
5196                vassert(0);
5197          }
5198          putQReg(dreg, binop(op, getDRegI64(nreg), getDRegI64(mreg)),
5199                condT);
5200 #ifndef DISABLE_QC_FLAG
5201          setFlag_QC(binop(Iop_And64,
5202                           binop(op2, getDRegI64(nreg), mkU64(imm)),
5203                           binop(op2, getDRegI64(mreg), mkU64(imm))),
5204                     mkU64(0),
5205                     False, condT);
5206 #endif
5207          DIP("vqdmull.s%u q%u, d%u, d%u\n", 8 << size, dreg, nreg, mreg);
5208          return True;
5209       default:
5210          return False;
5211    }
5212    return False;
5213 }
5214
5215 /* A7.4.3 Two registers and a scalar */
5216 static
5217 Bool dis_neon_data_2reg_and_scalar ( UInt theInstr, IRTemp condT )
5218 {
5219 #  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
5220    UInt U = INSN(24,24);
5221    UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
5222    UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
5223    UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
5224    UInt size = INSN(21,20);
5225    UInt index;
5226    UInt Q = INSN(24,24);
5227
5228    if (INSN(27,25) != 1 || INSN(23,23) != 1
5229        || INSN(6,6) != 1 || INSN(4,4) != 0)
5230       return False;
5231
5232    /* VMLA, VMLS (scalar)  */
5233    if ((INSN(11,8) & BITS4(1,0,1,0)) == BITS4(0,0,0,0)) {
5234       IRTemp res, arg_m, arg_n;
5235       IROp dup, get, op, op2, add, sub;
5236       if (Q) {
5237          if ((dreg & 1) || (nreg & 1))
5238             return False;
5239          dreg >>= 1;
5240          nreg >>= 1;
5241          res = newTemp(Ity_V128);
5242          arg_m = newTemp(Ity_V128);
5243          arg_n = newTemp(Ity_V128);
5244          assign(arg_n, getQReg(nreg));
5245          switch(size) {
5246             case 1:
5247                dup = Iop_Dup16x8;
5248                get = Iop_GetElem16x4;
5249                index = mreg >> 3;
5250                mreg &= 7;
5251                break;
5252             case 2:
5253                dup = Iop_Dup32x4;
5254                get = Iop_GetElem32x2;
5255                index = mreg >> 4;
5256                mreg &= 0xf;
5257                break;
5258             case 0:
5259             case 3:
5260                return False;
5261             default:
5262                vassert(0);
5263          }
5264          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5265       } else {
5266          res = newTemp(Ity_I64);
5267          arg_m = newTemp(Ity_I64);
5268          arg_n = newTemp(Ity_I64);
5269          assign(arg_n, getDRegI64(nreg));
5270          switch(size) {
5271             case 1:
5272                dup = Iop_Dup16x4;
5273                get = Iop_GetElem16x4;
5274                index = mreg >> 3;
5275                mreg &= 7;
5276                break;
5277             case 2:
5278                dup = Iop_Dup32x2;
5279                get = Iop_GetElem32x2;
5280                index = mreg >> 4;
5281                mreg &= 0xf;
5282                break;
5283             case 0:
5284             case 3:
5285                return False;
5286             default:
5287                vassert(0);
5288          }
5289          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5290       }
5291       if (INSN(8,8)) {
5292          switch (size) {
5293             case 2:
5294                op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
5295                add = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
5296                sub = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
5297                break;
5298             case 0:
5299             case 1:
5300             case 3:
5301                return False;
5302             default:
5303                vassert(0);
5304          }
5305       } else {
5306          switch (size) {
5307             case 1:
5308                op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
5309                add = Q ? Iop_Add16x8 : Iop_Add16x4;
5310                sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
5311                break;
5312             case 2:
5313                op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
5314                add = Q ? Iop_Add32x4 : Iop_Add32x2;
5315                sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
5316                break;
5317             case 0:
5318             case 3:
5319                return False;
5320             default:
5321                vassert(0);
5322          }
5323       }
5324       op2 = INSN(10,10) ? sub : add;
5325       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5326       if (Q)
5327          putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)),
5328                condT);
5329       else
5330          putDRegI64(dreg, binop(op2, getDRegI64(dreg), mkexpr(res)),
5331                     condT);
5332       DIP("vml%c.%c%u %c%u, %c%u, d%u[%u]\n", INSN(10,10) ? 's' : 'a',
5333             INSN(8,8) ? 'f' : 'i', 8 << size,
5334             Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, mreg, index);
5335       return True;
5336    }
5337
5338    /* VMLAL, VMLSL (scalar)   */
5339    if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,0)) {
5340       IRTemp res, arg_m, arg_n;
5341       IROp dup, get, op, op2, add, sub;
5342       if (dreg & 1)
5343          return False;
5344       dreg >>= 1;
5345       res = newTemp(Ity_V128);
5346       arg_m = newTemp(Ity_I64);
5347       arg_n = newTemp(Ity_I64);
5348       assign(arg_n, getDRegI64(nreg));
5349       switch(size) {
5350          case 1:
5351             dup = Iop_Dup16x4;
5352             get = Iop_GetElem16x4;
5353             index = mreg >> 3;
5354             mreg &= 7;
5355             break;
5356          case 2:
5357             dup = Iop_Dup32x2;
5358             get = Iop_GetElem32x2;
5359             index = mreg >> 4;
5360             mreg &= 0xf;
5361             break;
5362          case 0:
5363          case 3:
5364             return False;
5365          default:
5366             vassert(0);
5367       }
5368       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5369       switch (size) {
5370          case 1:
5371             op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
5372             add = Iop_Add32x4;
5373             sub = Iop_Sub32x4;
5374             break;
5375          case 2:
5376             op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
5377             add = Iop_Add64x2;
5378             sub = Iop_Sub64x2;
5379             break;
5380          case 0:
5381          case 3:
5382             return False;
5383          default:
5384             vassert(0);
5385       }
5386       op2 = INSN(10,10) ? sub : add;
5387       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5388       putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
5389       DIP("vml%cl.%c%u q%u, d%u, d%u[%u]\n",
5390           INSN(10,10) ? 's' : 'a', U ? 'u' : 's',
5391           8 << size, dreg, nreg, mreg, index);
5392       return True;
5393    }
5394
5395    /* VQDMLAL, VQDMLSL (scalar)  */
5396    if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,1) && !U) {
5397       IRTemp res, arg_m, arg_n, tmp;
5398       IROp dup, get, op, op2, add, cmp;
5399       UInt P = INSN(10,10);
5400       ULong imm;
5401       if (dreg & 1)
5402          return False;
5403       dreg >>= 1;
5404       res = newTemp(Ity_V128);
5405       arg_m = newTemp(Ity_I64);
5406       arg_n = newTemp(Ity_I64);
5407       assign(arg_n, getDRegI64(nreg));
5408       switch(size) {
5409          case 1:
5410             dup = Iop_Dup16x4;
5411             get = Iop_GetElem16x4;
5412             index = mreg >> 3;
5413             mreg &= 7;
5414             break;
5415          case 2:
5416             dup = Iop_Dup32x2;
5417             get = Iop_GetElem32x2;
5418             index = mreg >> 4;
5419             mreg &= 0xf;
5420             break;
5421          case 0:
5422          case 3:
5423             return False;
5424          default:
5425             vassert(0);
5426       }
5427       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5428       switch (size) {
5429          case 0:
5430          case 3:
5431             return False;
5432          case 1:
5433             op = Iop_QDMulLong16Sx4;
5434             cmp = Iop_CmpEQ16x4;
5435             add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
5436             op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
5437             imm = 1LL << 15;
5438             imm = (imm << 16) | imm;
5439             imm = (imm << 32) | imm;
5440             break;
5441          case 2:
5442             op = Iop_QDMulLong32Sx2;
5443             cmp = Iop_CmpEQ32x2;
5444             add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
5445             op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
5446             imm = 1LL << 31;
5447             imm = (imm << 32) | imm;
5448             break;
5449          default:
5450             vassert(0);
5451       }
5452       res = newTemp(Ity_V128);
5453       tmp = newTemp(Ity_V128);
5454       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5455 #ifndef DISABLE_QC_FLAG
5456       assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
5457       setFlag_QC(binop(Iop_And64,
5458                        binop(cmp, mkexpr(arg_n), mkU64(imm)),
5459                        binop(cmp, mkexpr(arg_m), mkU64(imm))),
5460                  mkU64(0),
5461                  False, condT);
5462       setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
5463                  True, condT);
5464 #endif
5465       putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
5466       DIP("vqdml%cl.s%u q%u, d%u, d%u[%u]\n", P ? 's' : 'a', 8 << size,
5467           dreg, nreg, mreg, index);
5468       return True;
5469    }
5470
5471    /* VMUL (by scalar)  */
5472    if ((INSN(11,8) & BITS4(1,1,1,0)) == BITS4(1,0,0,0)) {
5473       IRTemp res, arg_m, arg_n;
5474       IROp dup, get, op;
5475       if (Q) {
5476          if ((dreg & 1) || (nreg & 1))
5477             return False;
5478          dreg >>= 1;
5479          nreg >>= 1;
5480          res = newTemp(Ity_V128);
5481          arg_m = newTemp(Ity_V128);
5482          arg_n = newTemp(Ity_V128);
5483          assign(arg_n, getQReg(nreg));
5484          switch(size) {
5485             case 1:
5486                dup = Iop_Dup16x8;
5487                get = Iop_GetElem16x4;
5488                index = mreg >> 3;
5489                mreg &= 7;
5490                break;
5491             case 2:
5492                dup = Iop_Dup32x4;
5493                get = Iop_GetElem32x2;
5494                index = mreg >> 4;
5495                mreg &= 0xf;
5496                break;
5497             case 0:
5498             case 3:
5499                return False;
5500             default:
5501                vassert(0);
5502          }
5503          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5504       } else {
5505          res = newTemp(Ity_I64);
5506          arg_m = newTemp(Ity_I64);
5507          arg_n = newTemp(Ity_I64);
5508          assign(arg_n, getDRegI64(nreg));
5509          switch(size) {
5510             case 1:
5511                dup = Iop_Dup16x4;
5512                get = Iop_GetElem16x4;
5513                index = mreg >> 3;
5514                mreg &= 7;
5515                break;
5516             case 2:
5517                dup = Iop_Dup32x2;
5518                get = Iop_GetElem32x2;
5519                index = mreg >> 4;
5520                mreg &= 0xf;
5521                break;
5522             case 0:
5523             case 3:
5524                return False;
5525             default:
5526                vassert(0);
5527          }
5528          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5529       }
5530       switch (size) {
5531          case 1:
5532             op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
5533             break;
5534          case 2:
5535             op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
5536             break;
5537          case 0:
5538          case 3:
5539             return False;
5540          default:
5541             vassert(0);
5542       }
5543       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5544       if (Q)
5545          putQReg(dreg, mkexpr(res), condT);
5546       else
5547          putDRegI64(dreg, mkexpr(res), condT);
5548       DIP("vmul.i%u %c%u, %c%u, d%u[%u]\n", 8 << size, Q ? 'q' : 'd', dreg,
5549           Q ? 'q' : 'd', nreg, mreg, index);
5550       return True;
5551    }
5552
5553    /* VMULL (scalar) */
5554    if (INSN(11,8) == BITS4(1,0,1,0)) {
5555       IRTemp res, arg_m, arg_n;
5556       IROp dup, get, op;
5557       if (dreg & 1)
5558          return False;
5559       dreg >>= 1;
5560       res = newTemp(Ity_V128);
5561       arg_m = newTemp(Ity_I64);
5562       arg_n = newTemp(Ity_I64);
5563       assign(arg_n, getDRegI64(nreg));
5564       switch(size) {
5565          case 1:
5566             dup = Iop_Dup16x4;
5567             get = Iop_GetElem16x4;
5568             index = mreg >> 3;
5569             mreg &= 7;
5570             break;
5571          case 2:
5572             dup = Iop_Dup32x2;
5573             get = Iop_GetElem32x2;
5574             index = mreg >> 4;
5575             mreg &= 0xf;
5576             break;
5577          case 0:
5578          case 3:
5579             return False;
5580          default:
5581             vassert(0);
5582       }
5583       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5584       switch (size) {
5585          case 1: op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; break;
5586          case 2: op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; break;
5587          case 0: case 3: return False;
5588          default: vassert(0);
5589       }
5590       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5591       putQReg(dreg, mkexpr(res), condT);
5592       DIP("vmull.%c%u q%u, d%u, d%u[%u]\n", U ? 'u' : 's', 8 << size, dreg,
5593           nreg, mreg, index);
5594       return True;
5595    }
5596
5597    /* VQDMULL */
5598    if (INSN(11,8) == BITS4(1,0,1,1) && !U) {
5599       IROp op ,op2, dup, get;
5600       ULong imm;
5601       IRTemp arg_m, arg_n;
5602       if (dreg & 1)
5603          return False;
5604       dreg >>= 1;
5605       arg_m = newTemp(Ity_I64);
5606       arg_n = newTemp(Ity_I64);
5607       assign(arg_n, getDRegI64(nreg));
5608       switch(size) {
5609          case 1:
5610             dup = Iop_Dup16x4;
5611             get = Iop_GetElem16x4;
5612             index = mreg >> 3;
5613             mreg &= 7;
5614             break;
5615          case 2:
5616             dup = Iop_Dup32x2;
5617             get = Iop_GetElem32x2;
5618             index = mreg >> 4;
5619             mreg &= 0xf;
5620             break;
5621          case 0:
5622          case 3:
5623             return False;
5624          default:
5625             vassert(0);
5626       }
5627       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5628       switch (size) {
5629          case 0:
5630          case 3:
5631             return False;
5632          case 1:
5633             op = Iop_QDMulLong16Sx4;
5634             op2 = Iop_CmpEQ16x4;
5635             imm = 1LL << 15;
5636             imm = (imm << 16) | imm;
5637             imm = (imm << 32) | imm;
5638             break;
5639          case 2:
5640             op = Iop_QDMulLong32Sx2;
5641             op2 = Iop_CmpEQ32x2;
5642             imm = 1LL << 31;
5643             imm = (imm << 32) | imm;
5644             break;
5645          default:
5646             vassert(0);
5647       }
5648       putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
5649             condT);
5650 #ifndef DISABLE_QC_FLAG
5651       setFlag_QC(binop(Iop_And64,
5652                        binop(op2, mkexpr(arg_n), mkU64(imm)),
5653                        binop(op2, mkexpr(arg_m), mkU64(imm))),
5654                  mkU64(0),
5655                  False, condT);
5656 #endif
5657       DIP("vqdmull.s%u q%u, d%u, d%u[%u]\n", 8 << size, dreg, nreg, mreg,
5658           index);
5659       return True;
5660    }
5661
5662    /* VQDMULH */
5663    if (INSN(11,8) == BITS4(1,1,0,0)) {
5664       IROp op ,op2, dup, get;
5665       ULong imm;
5666       IRTemp res, arg_m, arg_n;
5667       if (Q) {
5668          if ((dreg & 1) || (nreg & 1))
5669             return False;
5670          dreg >>= 1;
5671          nreg >>= 1;
5672          res = newTemp(Ity_V128);
5673          arg_m = newTemp(Ity_V128);
5674          arg_n = newTemp(Ity_V128);
5675          assign(arg_n, getQReg(nreg));
5676          switch(size) {
5677             case 1:
5678                dup = Iop_Dup16x8;
5679                get = Iop_GetElem16x4;
5680                index = mreg >> 3;
5681                mreg &= 7;
5682                break;
5683             case 2:
5684                dup = Iop_Dup32x4;
5685                get = Iop_GetElem32x2;
5686                index = mreg >> 4;
5687                mreg &= 0xf;
5688                break;
5689             case 0:
5690             case 3:
5691                return False;
5692             default:
5693                vassert(0);
5694          }
5695          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5696       } else {
5697          res = newTemp(Ity_I64);
5698          arg_m = newTemp(Ity_I64);
5699          arg_n = newTemp(Ity_I64);
5700          assign(arg_n, getDRegI64(nreg));
5701          switch(size) {
5702             case 1:
5703                dup = Iop_Dup16x4;
5704                get = Iop_GetElem16x4;
5705                index = mreg >> 3;
5706                mreg &= 7;
5707                break;
5708             case 2:
5709                dup = Iop_Dup32x2;
5710                get = Iop_GetElem32x2;
5711                index = mreg >> 4;
5712                mreg &= 0xf;
5713                break;
5714             case 0:
5715             case 3:
5716                return False;
5717             default:
5718                vassert(0);
5719          }
5720          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5721       }
5722       switch (size) {
5723          case 0:
5724          case 3:
5725             return False;
5726          case 1:
5727             op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
5728             op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
5729             imm = 1LL << 15;
5730             imm = (imm << 16) | imm;
5731             imm = (imm << 32) | imm;
5732             break;
5733          case 2:
5734             op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
5735             op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
5736             imm = 1LL << 31;
5737             imm = (imm << 32) | imm;
5738             break;
5739          default:
5740             vassert(0);
5741       }
5742       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5743 #ifndef DISABLE_QC_FLAG
5744       setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
5745                        binop(op2, mkexpr(arg_n),
5746                                   Q ? mkU128(imm) : mkU64(imm)),
5747                        binop(op2, mkexpr(arg_m),
5748                              Q ? mkU128(imm) : mkU64(imm))),
5749                  Q ? mkU128(0) : mkU64(0),
5750                  Q, condT);
5751 #endif
5752       if (Q)
5753          putQReg(dreg, mkexpr(res), condT);
5754       else
5755          putDRegI64(dreg, mkexpr(res), condT);
5756       DIP("vqdmulh.s%u %c%u, %c%u, d%u[%u]\n",
5757           8 << size, Q ? 'q' : 'd', dreg,
5758           Q ? 'q' : 'd', nreg, mreg, index);
5759       return True;
5760    }
5761
5762    /* VQRDMULH (scalar) */
5763    if (INSN(11,8) == BITS4(1,1,0,1)) {
5764       IROp op ,op2, dup, get;
5765       ULong imm;
5766       IRTemp res, arg_m, arg_n;
5767       if (Q) {
5768          if ((dreg & 1) || (nreg & 1))
5769             return False;
5770          dreg >>= 1;
5771          nreg >>= 1;
5772          res = newTemp(Ity_V128);
5773          arg_m = newTemp(Ity_V128);
5774          arg_n = newTemp(Ity_V128);
5775          assign(arg_n, getQReg(nreg));
5776          switch(size) {
5777             case 1:
5778                dup = Iop_Dup16x8;
5779                get = Iop_GetElem16x4;
5780                index = mreg >> 3;
5781                mreg &= 7;
5782                break;
5783             case 2:
5784                dup = Iop_Dup32x4;
5785                get = Iop_GetElem32x2;
5786                index = mreg >> 4;
5787                mreg &= 0xf;
5788                break;
5789             case 0:
5790             case 3:
5791                return False;
5792             default:
5793                vassert(0);
5794          }
5795          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5796       } else {
5797          res = newTemp(Ity_I64);
5798          arg_m = newTemp(Ity_I64);
5799          arg_n = newTemp(Ity_I64);
5800          assign(arg_n, getDRegI64(nreg));
5801          switch(size) {
5802             case 1:
5803                dup = Iop_Dup16x4;
5804                get = Iop_GetElem16x4;
5805                index = mreg >> 3;
5806                mreg &= 7;
5807                break;
5808             case 2:
5809                dup = Iop_Dup32x2;
5810                get = Iop_GetElem32x2;
5811                index = mreg >> 4;
5812                mreg &= 0xf;
5813                break;
5814             case 0:
5815             case 3:
5816                return False;
5817             default:
5818                vassert(0);
5819          }
5820          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
5821       }
5822       switch (size) {
5823          case 0:
5824          case 3:
5825             return False;
5826          case 1:
5827             op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
5828             op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
5829             imm = 1LL << 15;
5830             imm = (imm << 16) | imm;
5831             imm = (imm << 32) | imm;
5832             break;
5833          case 2:
5834             op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
5835             op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
5836             imm = 1LL << 31;
5837             imm = (imm << 32) | imm;
5838             break;
5839          default:
5840             vassert(0);
5841       }
5842       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
5843 #ifndef DISABLE_QC_FLAG
5844       setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
5845                        binop(op2, mkexpr(arg_n),
5846                                   Q ? mkU128(imm) : mkU64(imm)),
5847                        binop(op2, mkexpr(arg_m),
5848                                   Q ? mkU128(imm) : mkU64(imm))),
5849                  Q ? mkU128(0) : mkU64(0),
5850                  Q, condT);
5851 #endif
5852       if (Q)
5853          putQReg(dreg, mkexpr(res), condT);
5854       else
5855          putDRegI64(dreg, mkexpr(res), condT);
5856       DIP("vqrdmulh.s%u %c%u, %c%u, d%u[%u]\n",
5857           8 << size, Q ? 'q' : 'd', dreg,
5858           Q ? 'q' : 'd', nreg, mreg, index);
5859       return True;
5860    }
5861
5862    return False;
5863 #  undef INSN
5864 }
5865
5866 /* A7.4.4 Two registers and a shift amount */
5867 static
5868 Bool dis_neon_data_2reg_and_shift ( UInt theInstr, IRTemp condT )
5869 {
5870    UInt A = (theInstr >> 8) & 0xf;
5871    UInt B = (theInstr >> 6) & 1;
5872    UInt L = (theInstr >> 7) & 1;
5873    UInt U = (theInstr >> 24) & 1;
5874    UInt Q = B;
5875    UInt imm6 = (theInstr >> 16) & 0x3f;
5876    UInt shift_imm;
5877    UInt size = 4;
5878    UInt tmp;
5879    UInt mreg = get_neon_m_regno(theInstr);
5880    UInt dreg = get_neon_d_regno(theInstr);
5881    ULong imm = 0;
5882    IROp op, cvt, add = Iop_INVALID, cvt2, op_rev;
5883    IRTemp reg_m, res, mask;
5884
5885    if (L == 0 && ((theInstr >> 19) & 7) == 0)
5886       /* It is one reg and immediate */
5887       return False;
5888
5889    tmp = (L << 6) | imm6;
5890    if (tmp & 0x40) {
5891       size = 3;
5892       shift_imm = 64 - imm6;
5893    } else if (tmp & 0x20) {
5894       size = 2;
5895       shift_imm = 64 - imm6;
5896    } else if (tmp & 0x10) {
5897       size = 1;
5898       shift_imm = 32 - imm6;
5899    } else if (tmp & 0x8) {
5900       size = 0;
5901       shift_imm = 16 - imm6;
5902    } else {
5903       return False;
5904    }
5905
5906    switch (A) {
5907       case 3:
5908       case 2:
5909          /* VRSHR, VRSRA */
5910          if (shift_imm > 0) {
5911             IRExpr *imm_val;
5912             imm = 1L;
5913             switch (size) {
5914                case 0:
5915                   imm = (imm << 8) | imm;
5916                   /* fall through */
5917                case 1:
5918                   imm = (imm << 16) | imm;
5919                   /* fall through */
5920                case 2:
5921                   imm = (imm << 32) | imm;
5922                   /* fall through */
5923                case 3:
5924                   break;
5925                default:
5926                   vassert(0);
5927             }
5928             if (Q) {
5929                reg_m = newTemp(Ity_V128);
5930                res = newTemp(Ity_V128);
5931                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
5932                assign(reg_m, getQReg(mreg));
5933                switch (size) {
5934                   case 0:
5935                      add = Iop_Add8x16;
5936                      op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
5937                      break;
5938                   case 1:
5939                      add = Iop_Add16x8;
5940                      op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
5941                      break;
5942                   case 2:
5943                      add = Iop_Add32x4;
5944                      op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
5945                      break;
5946                   case 3:
5947                      add = Iop_Add64x2;
5948                      op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
5949                      break;
5950                   default:
5951                      vassert(0);
5952                }
5953             } else {
5954                reg_m = newTemp(Ity_I64);
5955                res = newTemp(Ity_I64);
5956                imm_val = mkU64(imm);
5957                assign(reg_m, getDRegI64(mreg));
5958                switch (size) {
5959                   case 0:
5960                      add = Iop_Add8x8;
5961                      op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
5962                      break;
5963                   case 1:
5964                      add = Iop_Add16x4;
5965                      op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
5966                      break;
5967                   case 2:
5968                      add = Iop_Add32x2;
5969                      op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
5970                      break;
5971                   case 3:
5972                      add = Iop_Add64;
5973                      op = U ? Iop_Shr64 : Iop_Sar64;
5974                      break;
5975                   default:
5976                      vassert(0);
5977                }
5978             }
5979             assign(res,
5980                    binop(add,
5981                          binop(op,
5982                                mkexpr(reg_m),
5983                                mkU8(shift_imm)),
5984                          binop(Q ? Iop_AndV128 : Iop_And64,
5985                                binop(op,
5986                                      mkexpr(reg_m),
5987                                      mkU8(shift_imm - 1)),
5988                                imm_val)));
5989          } else {
5990             if (Q) {
5991                res = newTemp(Ity_V128);
5992                assign(res, getQReg(mreg));
5993             } else {
5994                res = newTemp(Ity_I64);
5995                assign(res, getDRegI64(mreg));
5996             }
5997          }
5998          if (A == 3) {
5999             if (Q) {
6000                putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
6001                              condT);
6002             } else {
6003                putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
6004                                 condT);
6005             }
6006             DIP("vrsra.%c%u %c%u, %c%u, #%u\n",
6007                 U ? 'u' : 's', 8 << size,
6008                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6009          } else {
6010             if (Q) {
6011                putQReg(dreg, mkexpr(res), condT);
6012             } else {
6013                putDRegI64(dreg, mkexpr(res), condT);
6014             }
6015             DIP("vrshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6016                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6017          }
6018          return True;
6019       case 1:
6020       case 0:
6021          /* VSHR, VSRA */
6022          if (Q) {
6023             reg_m = newTemp(Ity_V128);
6024             assign(reg_m, getQReg(mreg));
6025             res = newTemp(Ity_V128);
6026          } else {
6027             reg_m = newTemp(Ity_I64);
6028             assign(reg_m, getDRegI64(mreg));
6029             res = newTemp(Ity_I64);
6030          }
6031          if (Q) {
6032             switch (size) {
6033                case 0:
6034                   op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
6035                   add = Iop_Add8x16;
6036                   break;
6037                case 1:
6038                   op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
6039                   add = Iop_Add16x8;
6040                   break;
6041                case 2:
6042                   op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
6043                   add = Iop_Add32x4;
6044                   break;
6045                case 3:
6046                   op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
6047                   add = Iop_Add64x2;
6048                   break;
6049                default:
6050                   vassert(0);
6051             }
6052          } else {
6053             switch (size) {
6054                case 0:
6055                   op =  U ? Iop_ShrN8x8 : Iop_SarN8x8;
6056                   add = Iop_Add8x8;
6057                   break;
6058                case 1:
6059                   op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
6060                   add = Iop_Add16x4;
6061                   break;
6062                case 2:
6063                   op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
6064                   add = Iop_Add32x2;
6065                   break;
6066                case 3:
6067                   op = U ? Iop_Shr64 : Iop_Sar64;
6068                   add = Iop_Add64;
6069                   break;
6070                default:
6071                   vassert(0);
6072             }
6073          }
6074          assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6075          if (A == 1) {
6076             if (Q) {
6077                putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
6078                              condT);
6079             } else {
6080                putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
6081                                 condT);
6082             }
6083             DIP("vsra.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6084                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6085          } else {
6086             if (Q) {
6087                putQReg(dreg, mkexpr(res), condT);
6088             } else {
6089                putDRegI64(dreg, mkexpr(res), condT);
6090             }
6091             DIP("vshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
6092                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6093          }
6094          return True;
6095       case 4:
6096          /* VSRI */
6097          if (!U)
6098             return False;
6099          if (Q) {
6100             res = newTemp(Ity_V128);
6101             mask = newTemp(Ity_V128);
6102          } else {
6103             res = newTemp(Ity_I64);
6104             mask = newTemp(Ity_I64);
6105          }
6106          switch (size) {
6107             case 0: op = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; break;
6108             case 1: op = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; break;
6109             case 2: op = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; break;
6110             case 3: op = Q ? Iop_ShrN64x2 : Iop_Shr64; break;
6111             default: vassert(0);
6112          }
6113          if (Q) {
6114             assign(mask, binop(op, binop(Iop_64HLtoV128,
6115                                          mkU64(0xFFFFFFFFFFFFFFFFLL),
6116                                          mkU64(0xFFFFFFFFFFFFFFFFLL)),
6117                                mkU8(shift_imm)));
6118             assign(res, binop(Iop_OrV128,
6119                               binop(Iop_AndV128,
6120                                     getQReg(dreg),
6121                                     unop(Iop_NotV128,
6122                                          mkexpr(mask))),
6123                               binop(op,
6124                                     getQReg(mreg),
6125                                     mkU8(shift_imm))));
6126             putQReg(dreg, mkexpr(res), condT);
6127          } else {
6128             assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
6129                                mkU8(shift_imm)));
6130             assign(res, binop(Iop_Or64,
6131                               binop(Iop_And64,
6132                                     getDRegI64(dreg),
6133                                     unop(Iop_Not64,
6134                                          mkexpr(mask))),
6135                               binop(op,
6136                                     getDRegI64(mreg),
6137                                     mkU8(shift_imm))));
6138             putDRegI64(dreg, mkexpr(res), condT);
6139          }
6140          DIP("vsri.%u %c%u, %c%u, #%u\n",
6141              8 << size, Q ? 'q' : 'd', dreg,
6142              Q ? 'q' : 'd', mreg, shift_imm);
6143          return True;
6144       case 5:
6145          if (U) {
6146             /* VSLI */
6147             shift_imm = 8 * (1 << size) - shift_imm;
6148             if (Q) {
6149                res = newTemp(Ity_V128);
6150                mask = newTemp(Ity_V128);
6151             } else {
6152                res = newTemp(Ity_I64);
6153                mask = newTemp(Ity_I64);
6154             }
6155             switch (size) {
6156                case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
6157                case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
6158                case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
6159                case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
6160                default: vassert(0);
6161             }
6162             if (Q) {
6163                assign(mask, binop(op, binop(Iop_64HLtoV128,
6164                                             mkU64(0xFFFFFFFFFFFFFFFFLL),
6165                                             mkU64(0xFFFFFFFFFFFFFFFFLL)),
6166                                   mkU8(shift_imm)));
6167                assign(res, binop(Iop_OrV128,
6168                                  binop(Iop_AndV128,
6169                                        getQReg(dreg),
6170                                        unop(Iop_NotV128,
6171                                             mkexpr(mask))),
6172                                  binop(op,
6173                                        getQReg(mreg),
6174                                        mkU8(shift_imm))));
6175                putQReg(dreg, mkexpr(res), condT);
6176             } else {
6177                assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
6178                                   mkU8(shift_imm)));
6179                assign(res, binop(Iop_Or64,
6180                                  binop(Iop_And64,
6181                                        getDRegI64(dreg),
6182                                        unop(Iop_Not64,
6183                                             mkexpr(mask))),
6184                                  binop(op,
6185                                        getDRegI64(mreg),
6186                                        mkU8(shift_imm))));
6187                putDRegI64(dreg, mkexpr(res), condT);
6188             }
6189             DIP("vsli.%u %c%u, %c%u, #%u\n",
6190                 8 << size, Q ? 'q' : 'd', dreg,
6191                 Q ? 'q' : 'd', mreg, shift_imm);
6192             return True;
6193          } else {
6194             /* VSHL #imm */
6195             shift_imm = 8 * (1 << size) - shift_imm;
6196             if (Q) {
6197                res = newTemp(Ity_V128);
6198             } else {
6199                res = newTemp(Ity_I64);
6200             }
6201             switch (size) {
6202                case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
6203                case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
6204                case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
6205                case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
6206                default: vassert(0);
6207             }
6208             assign(res, binop(op, Q ? getQReg(mreg) : getDRegI64(mreg),
6209                      mkU8(shift_imm)));
6210             if (Q) {
6211                putQReg(dreg, mkexpr(res), condT);
6212             } else {
6213                putDRegI64(dreg, mkexpr(res), condT);
6214             }
6215             DIP("vshl.i%u %c%u, %c%u, #%u\n",
6216                 8 << size, Q ? 'q' : 'd', dreg,
6217                 Q ? 'q' : 'd', mreg, shift_imm);
6218             return True;
6219          }
6220          break;
6221       case 6:
6222       case 7:
6223          /* VQSHL, VQSHLU */
6224          shift_imm = 8 * (1 << size) - shift_imm;
6225          if (U) {
6226             if (A & 1) {
6227                switch (size) {
6228                   case 0:
6229                      op = Q ? Iop_QShlN8x16 : Iop_QShlN8x8;
6230                      op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
6231                      break;
6232                   case 1:
6233                      op = Q ? Iop_QShlN16x8 : Iop_QShlN16x4;
6234                      op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
6235                      break;
6236                   case 2:
6237                      op = Q ? Iop_QShlN32x4 : Iop_QShlN32x2;
6238                      op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
6239                      break;
6240                   case 3:
6241                      op = Q ? Iop_QShlN64x2 : Iop_QShlN64x1;
6242                      op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
6243                      break;
6244                   default:
6245                      vassert(0);
6246                }
6247                DIP("vqshl.u%u %c%u, %c%u, #%u\n",
6248                    8 << size,
6249                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6250             } else {
6251                switch (size) {
6252                   case 0:
6253                      op = Q ? Iop_QShlN8Sx16 : Iop_QShlN8Sx8;
6254                      op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
6255                      break;
6256                   case 1:
6257                      op = Q ? Iop_QShlN16Sx8 : Iop_QShlN16Sx4;
6258                      op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
6259                      break;
6260                   case 2:
6261                      op = Q ? Iop_QShlN32Sx4 : Iop_QShlN32Sx2;
6262                      op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
6263                      break;
6264                   case 3:
6265                      op = Q ? Iop_QShlN64Sx2 : Iop_QShlN64Sx1;
6266                      op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
6267                      break;
6268                   default:
6269                      vassert(0);
6270                }
6271                DIP("vqshlu.s%u %c%u, %c%u, #%u\n",
6272                    8 << size,
6273                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6274             }
6275          } else {
6276             if (!(A & 1))
6277                return False;
6278             switch (size) {
6279                case 0:
6280                   op = Q ? Iop_QSalN8x16 : Iop_QSalN8x8;
6281                   op_rev = Q ? Iop_SarN8x16 : Iop_SarN8x8;
6282                   break;
6283                case 1:
6284                   op = Q ? Iop_QSalN16x8 : Iop_QSalN16x4;
6285                   op_rev = Q ? Iop_SarN16x8 : Iop_SarN16x4;
6286                   break;
6287                case 2:
6288                   op = Q ? Iop_QSalN32x4 : Iop_QSalN32x2;
6289                   op_rev = Q ? Iop_SarN32x4 : Iop_SarN32x2;
6290                   break;
6291                case 3:
6292                   op = Q ? Iop_QSalN64x2 : Iop_QSalN64x1;
6293                   op_rev = Q ? Iop_SarN64x2 : Iop_Sar64;
6294                   break;
6295                default:
6296                   vassert(0);
6297             }
6298             DIP("vqshl.s%u %c%u, %c%u, #%u\n",
6299                 8 << size,
6300                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
6301          }
6302          if (Q) {
6303             tmp = newTemp(Ity_V128);
6304             res = newTemp(Ity_V128);
6305             reg_m = newTemp(Ity_V128);
6306             assign(reg_m, getQReg(mreg));
6307          } else {
6308             tmp = newTemp(Ity_I64);
6309             res = newTemp(Ity_I64);
6310             reg_m = newTemp(Ity_I64);
6311             assign(reg_m, getDRegI64(mreg));
6312          }
6313          assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6314 #ifndef DISABLE_QC_FLAG
6315          assign(tmp, binop(op_rev, mkexpr(res), mkU8(shift_imm)));
6316          setFlag_QC(mkexpr(tmp), mkexpr(reg_m), Q, condT);
6317 #endif
6318          if (Q)
6319             putQReg(dreg, mkexpr(res), condT);
6320          else
6321             putDRegI64(dreg, mkexpr(res), condT);
6322          return True;
6323       case 8:
6324          if (!U) {
6325             if (L == 1)
6326                return False;
6327             size++;
6328             dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
6329             mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
6330             if (mreg & 1)
6331                return False;
6332             mreg >>= 1;
6333             if (!B) {
6334                /* VSHRN*/
6335                IROp narOp;
6336                reg_m = newTemp(Ity_V128);
6337                assign(reg_m, getQReg(mreg));
6338                res = newTemp(Ity_I64);
6339                switch (size) {
6340                   case 1:
6341                      op = Iop_ShrN16x8;
6342                      narOp = Iop_Shorten16x8;
6343                      break;
6344                   case 2:
6345                      op = Iop_ShrN32x4;
6346                      narOp = Iop_Shorten32x4;
6347                      break;
6348                   case 3:
6349                      op = Iop_ShrN64x2;
6350                      narOp = Iop_Shorten64x2;
6351                      break;
6352                   default:
6353                      vassert(0);
6354                }
6355                assign(res, unop(narOp,
6356                                 binop(op,
6357                                       mkexpr(reg_m),
6358                                       mkU8(shift_imm))));
6359                putDRegI64(dreg, mkexpr(res), condT);
6360                DIP("vshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6361                    shift_imm);
6362                return True;
6363             } else {
6364                /* VRSHRN   */
6365                IROp addOp, shOp, narOp;
6366                IRExpr *imm_val;
6367                reg_m = newTemp(Ity_V128);
6368                assign(reg_m, getQReg(mreg));
6369                res = newTemp(Ity_I64);
6370                imm = 1L;
6371                switch (size) {
6372                   case 0: imm = (imm <<  8) | imm; /* fall through */
6373                   case 1: imm = (imm << 16) | imm; /* fall through */
6374                   case 2: imm = (imm << 32) | imm; /* fall through */
6375                   case 3: break;
6376                   default: vassert(0);
6377                }
6378                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
6379                switch (size) {
6380                   case 1:
6381                      addOp = Iop_Add16x8;
6382                      shOp = Iop_ShrN16x8;
6383                      narOp = Iop_Shorten16x8;
6384                      break;
6385                   case 2:
6386                      addOp = Iop_Add32x4;
6387                      shOp = Iop_ShrN32x4;
6388                      narOp = Iop_Shorten32x4;
6389                      break;
6390                   case 3:
6391                      addOp = Iop_Add64x2;
6392                      shOp = Iop_ShrN64x2;
6393                      narOp = Iop_Shorten64x2;
6394                      break;
6395                   default:
6396                      vassert(0);
6397                }
6398                assign(res, unop(narOp,
6399                                 binop(addOp,
6400                                       binop(shOp,
6401                                             mkexpr(reg_m),
6402                                             mkU8(shift_imm)),
6403                                       binop(Iop_AndV128,
6404                                             binop(shOp,
6405                                                   mkexpr(reg_m),
6406                                                   mkU8(shift_imm - 1)),
6407                                             imm_val))));
6408                putDRegI64(dreg, mkexpr(res), condT);
6409                if (shift_imm == 0) {
6410                   DIP("vmov%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6411                       shift_imm);
6412                } else {
6413                   DIP("vrshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
6414                       shift_imm);
6415                }
6416                return True;
6417             }
6418          } else {
6419             /* fall through */
6420          }
6421       case 9:
6422          dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
6423          mreg = ((theInstr >>  1) & 0x10) | (theInstr & 0xF);
6424          if (mreg & 1)
6425             return False;
6426          mreg >>= 1;
6427          size++;
6428          if ((theInstr >> 8) & 1) {
6429             switch (size) {
6430                case 1:
6431                   op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
6432                   cvt = U ? Iop_QShortenU16Ux8 : Iop_QShortenS16Sx8;
6433                   cvt2 = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
6434                   break;
6435                case 2:
6436                   op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
6437                   cvt = U ? Iop_QShortenU32Ux4 : Iop_QShortenS32Sx4;
6438                   cvt2 = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
6439                   break;
6440                case 3:
6441                   op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
6442                   cvt = U ? Iop_QShortenU64Ux2 : Iop_QShortenS64Sx2;
6443                   cvt2 = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
6444                   break;
6445                default:
6446                   vassert(0);
6447             }
6448             DIP("vq%sshrn.%c%u d%u, q%u, #%u\n", B ? "r" : "",
6449                 U ? 'u' : 's', 8 << size, dreg, mreg, shift_imm);
6450          } else {
6451             vassert(U);
6452             switch (size) {
6453                case 1:
6454                   op = Iop_SarN16x8;
6455                   cvt = Iop_QShortenU16Sx8;
6456                   cvt2 = Iop_Longen8Ux8;
6457                   break;
6458                case 2:
6459                   op = Iop_SarN32x4;
6460                   cvt = Iop_QShortenU32Sx4;
6461                   cvt2 = Iop_Longen16Ux4;
6462                   break;
6463                case 3:
6464                   op = Iop_SarN64x2;
6465                   cvt = Iop_QShortenU64Sx2;
6466                   cvt2 = Iop_Longen32Ux2;
6467                   break;
6468                default:
6469                   vassert(0);
6470             }
6471             DIP("vq%sshrun.s%u d%u, q%u, #%u\n", B ? "r" : "",
6472                 8 << size, dreg, mreg, shift_imm);
6473          }
6474          if (B) {
6475             if (shift_imm > 0) {
6476                imm = 1;
6477                switch (size) {
6478                   case 1: imm = (imm << 16) | imm; /* fall through */
6479                   case 2: imm = (imm << 32) | imm; /* fall through */
6480                   case 3: break;
6481                   case 0: default: vassert(0);
6482                }
6483                switch (size) {
6484                   case 1: add = Iop_Add16x8; break;
6485                   case 2: add = Iop_Add32x4; break;
6486                   case 3: add = Iop_Add64x2; break;
6487                   case 0: default: vassert(0);
6488                }
6489             }
6490          }
6491          reg_m = newTemp(Ity_V128);
6492          res = newTemp(Ity_V128);
6493          assign(reg_m, getQReg(mreg));
6494          if (B) {
6495             /* VQRSHRN, VQRSHRUN */
6496             assign(res, binop(add,
6497                               binop(op, mkexpr(reg_m), mkU8(shift_imm)),
6498                               binop(Iop_AndV128,
6499                                     binop(op,
6500                                           mkexpr(reg_m),
6501                                           mkU8(shift_imm - 1)),
6502                                     mkU128(imm))));
6503          } else {
6504             /* VQSHRN, VQSHRUN */
6505             assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
6506          }
6507 #ifndef DISABLE_QC_FLAG
6508          setFlag_QC(unop(cvt2, unop(cvt, mkexpr(res))), mkexpr(res),
6509                     True, condT);
6510 #endif
6511          putDRegI64(dreg, unop(cvt, mkexpr(res)), condT);
6512          return True;
6513       case 10:
6514          /* VSHLL
6515             VMOVL ::= VSHLL #0 */
6516          if (B)
6517             return False;
6518          if (dreg & 1)
6519             return False;
6520          dreg >>= 1;
6521          shift_imm = (8 << size) - shift_imm;
6522          res = newTemp(Ity_V128);
6523          switch (size) {
6524             case 0:
6525                op = Iop_ShlN16x8;
6526                cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
6527                break;
6528             case 1:
6529                op = Iop_ShlN32x4;
6530                cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
6531                break;
6532             case 2:
6533                op = Iop_ShlN64x2;
6534                cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
6535                break;
6536             case 3:
6537                return False;
6538             default:
6539                vassert(0);
6540          }
6541          assign(res, binop(op, unop(cvt, getDRegI64(mreg)), mkU8(shift_imm)));
6542          putQReg(dreg, mkexpr(res), condT);
6543          if (shift_imm == 0) {
6544             DIP("vmovl.%c%u q%u, d%u\n", U ? 'u' : 's', 8 << size,
6545                 dreg, mreg);
6546          } else {
6547             DIP("vshll.%c%u q%u, d%u, #%u\n", U ? 'u' : 's', 8 << size,
6548                 dreg, mreg, shift_imm);
6549          }
6550          return True;
6551       case 14:
6552       case 15:
6553          /* VCVT floating-point <-> fixed-point */
6554          if ((theInstr >> 8) & 1) {
6555             if (U) {
6556                op = Q ? Iop_F32ToFixed32Ux4_RZ : Iop_F32ToFixed32Ux2_RZ;
6557             } else {
6558                op = Q ? Iop_F32ToFixed32Sx4_RZ : Iop_F32ToFixed32Sx2_RZ;
6559             }
6560             DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
6561                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
6562                 64 - ((theInstr >> 16) & 0x3f));
6563          } else {
6564             if (U) {
6565                op = Q ? Iop_Fixed32UToF32x4_RN : Iop_Fixed32UToF32x2_RN;
6566             } else {
6567                op = Q ? Iop_Fixed32SToF32x4_RN : Iop_Fixed32SToF32x2_RN;
6568             }
6569             DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
6570                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
6571                 64 - ((theInstr >> 16) & 0x3f));
6572          }
6573          if (((theInstr >> 21) & 1) == 0)
6574             return False;
6575          if (Q) {
6576             putQReg(dreg, binop(op, getQReg(mreg),
6577                      mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
6578          } else {
6579             putDRegI64(dreg, binop(op, getDRegI64(mreg),
6580                        mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
6581          }
6582          return True;
6583       default:
6584          return False;
6585
6586    }
6587    return False;
6588 }
6589
6590 /* A7.4.5 Two registers, miscellaneous */
6591 static
6592 Bool dis_neon_data_2reg_misc ( UInt theInstr, IRTemp condT )
6593 {
6594    UInt A = (theInstr >> 16) & 3;
6595    UInt B = (theInstr >> 6) & 0x1f;
6596    UInt Q = (theInstr >> 6) & 1;
6597    UInt U = (theInstr >> 24) & 1;
6598    UInt size = (theInstr >> 18) & 3;
6599    UInt dreg = get_neon_d_regno(theInstr);
6600    UInt mreg = get_neon_m_regno(theInstr);
6601    UInt F = (theInstr >> 10) & 1;
6602    IRTemp arg_d;
6603    IRTemp arg_m;
6604    IRTemp res;
6605    switch (A) {
6606       case 0:
6607          if (Q) {
6608             arg_m = newTemp(Ity_V128);
6609             res = newTemp(Ity_V128);
6610             assign(arg_m, getQReg(mreg));
6611          } else {
6612             arg_m = newTemp(Ity_I64);
6613             res = newTemp(Ity_I64);
6614             assign(arg_m, getDRegI64(mreg));
6615          }
6616          switch (B >> 1) {
6617             case 0: {
6618                /* VREV64 */
6619                IROp op;
6620                switch (size) {
6621                   case 0:
6622                      op = Q ? Iop_Reverse64_8x16 : Iop_Reverse64_8x8;
6623                      break;
6624                   case 1:
6625                      op = Q ? Iop_Reverse64_16x8 : Iop_Reverse64_16x4;
6626                      break;
6627                   case 2:
6628                      op = Q ? Iop_Reverse64_32x4 : Iop_Reverse64_32x2;
6629                      break;
6630                   case 3:
6631                      return False;
6632                   default:
6633                      vassert(0);
6634                }
6635                assign(res, unop(op, mkexpr(arg_m)));
6636                DIP("vrev64.%u %c%u, %c%u\n", 8 << size,
6637                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6638                break;
6639             }
6640             case 1: {
6641                /* VREV32 */
6642                IROp op;
6643                switch (size) {
6644                   case 0:
6645                      op = Q ? Iop_Reverse32_8x16 : Iop_Reverse32_8x8;
6646                      break;
6647                   case 1:
6648                      op = Q ? Iop_Reverse32_16x8 : Iop_Reverse32_16x4;
6649                      break;
6650                   case 2:
6651                   case 3:
6652                      return False;
6653                   default:
6654                      vassert(0);
6655                }
6656                assign(res, unop(op, mkexpr(arg_m)));
6657                DIP("vrev32.%u %c%u, %c%u\n", 8 << size,
6658                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6659                break;
6660             }
6661             case 2: {
6662                /* VREV16 */
6663                IROp op;
6664                switch (size) {
6665                   case 0:
6666                      op = Q ? Iop_Reverse16_8x16 : Iop_Reverse16_8x8;
6667                      break;
6668                   case 1:
6669                   case 2:
6670                   case 3:
6671                      return False;
6672                   default:
6673                      vassert(0);
6674                }
6675                assign(res, unop(op, mkexpr(arg_m)));
6676                DIP("vrev16.%u %c%u, %c%u\n", 8 << size,
6677                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6678                break;
6679             }
6680             case 3:
6681                return False;
6682             case 4:
6683             case 5: {
6684                /* VPADDL */
6685                IROp op;
6686                U = (theInstr >> 7) & 1;
6687                if (Q) {
6688                   switch (size) {
6689                      case 0: op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; break;
6690                      case 1: op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; break;
6691                      case 2: op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; break;
6692                      case 3: return False;
6693                      default: vassert(0);
6694                   }
6695                } else {
6696                   switch (size) {
6697                      case 0: op = U ? Iop_PwAddL8Ux8  : Iop_PwAddL8Sx8;  break;
6698                      case 1: op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; break;
6699                      case 2: op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; break;
6700                      case 3: return False;
6701                      default: vassert(0);
6702                   }
6703                }
6704                assign(res, unop(op, mkexpr(arg_m)));
6705                DIP("vpaddl.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
6706                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6707                break;
6708             }
6709             case 6:
6710             case 7:
6711                return False;
6712             case 8: {
6713                /* VCLS */
6714                IROp op;
6715                switch (size) {
6716                   case 0: op = Q ? Iop_Cls8Sx16 : Iop_Cls8Sx8; break;
6717                   case 1: op = Q ? Iop_Cls16Sx8 : Iop_Cls16Sx4; break;
6718                   case 2: op = Q ? Iop_Cls32Sx4 : Iop_Cls32Sx2; break;
6719                   case 3: return False;
6720                   default: vassert(0);
6721                }
6722                assign(res, unop(op, mkexpr(arg_m)));
6723                DIP("vcls.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6724                    Q ? 'q' : 'd', mreg);
6725                break;
6726             }
6727             case 9: {
6728                /* VCLZ */
6729                IROp op;
6730                switch (size) {
6731                   case 0: op = Q ? Iop_Clz8Sx16 : Iop_Clz8Sx8; break;
6732                   case 1: op = Q ? Iop_Clz16Sx8 : Iop_Clz16Sx4; break;
6733                   case 2: op = Q ? Iop_Clz32Sx4 : Iop_Clz32Sx2; break;
6734                   case 3: return False;
6735                   default: vassert(0);
6736                }
6737                assign(res, unop(op, mkexpr(arg_m)));
6738                DIP("vclz.i%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6739                    Q ? 'q' : 'd', mreg);
6740                break;
6741             }
6742             case 10:
6743                /* VCNT */
6744                assign(res, unop(Q ? Iop_Cnt8x16 : Iop_Cnt8x8, mkexpr(arg_m)));
6745                DIP("vcnt.8 %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
6746                    mreg);
6747                break;
6748             case 11:
6749                /* VMVN */
6750                if (Q)
6751                   assign(res, unop(Iop_NotV128, mkexpr(arg_m)));
6752                else
6753                   assign(res, unop(Iop_Not64, mkexpr(arg_m)));
6754                DIP("vmvn %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
6755                    mreg);
6756                break;
6757             case 12:
6758             case 13: {
6759                /* VPADAL */
6760                IROp op, add_op;
6761                U = (theInstr >> 7) & 1;
6762                if (Q) {
6763                   switch (size) {
6764                      case 0:
6765                         op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16;
6766                         add_op = Iop_Add16x8;
6767                         break;
6768                      case 1:
6769                         op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8;
6770                         add_op = Iop_Add32x4;
6771                         break;
6772                      case 2:
6773                         op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4;
6774                         add_op = Iop_Add64x2;
6775                         break;
6776                      case 3:
6777                         return False;
6778                      default:
6779                         vassert(0);
6780                   }
6781                } else {
6782                   switch (size) {
6783                      case 0:
6784                         op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8;
6785                         add_op = Iop_Add16x4;
6786                         break;
6787                      case 1:
6788                         op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4;
6789                         add_op = Iop_Add32x2;
6790                         break;
6791                      case 2:
6792                         op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2;
6793                         add_op = Iop_Add64;
6794                         break;
6795                      case 3:
6796                         return False;
6797                      default:
6798                         vassert(0);
6799                   }
6800                }
6801                if (Q) {
6802                   arg_d = newTemp(Ity_V128);
6803                   assign(arg_d, getQReg(dreg));
6804                } else {
6805                   arg_d = newTemp(Ity_I64);
6806                   assign(arg_d, getDRegI64(dreg));
6807                }
6808                assign(res, binop(add_op, unop(op, mkexpr(arg_m)),
6809                                          mkexpr(arg_d)));
6810                DIP("vpadal.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
6811                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6812                break;
6813             }
6814             case 14: {
6815                /* VQABS */
6816                IROp op_sub, op_qsub, op_cmp;
6817                IRTemp mask, tmp;
6818                IRExpr *zero1, *zero2;
6819                IRExpr *neg, *neg2;
6820                if (Q) {
6821                   zero1 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6822                   zero2 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6823                   mask = newTemp(Ity_V128);
6824                   tmp = newTemp(Ity_V128);
6825                } else {
6826                   zero1 = mkU64(0);
6827                   zero2 = mkU64(0);
6828                   mask = newTemp(Ity_I64);
6829                   tmp = newTemp(Ity_I64);
6830                }
6831                switch (size) {
6832                   case 0:
6833                      op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
6834                      op_qsub = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
6835                      op_cmp = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
6836                      break;
6837                   case 1:
6838                      op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
6839                      op_qsub = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
6840                      op_cmp = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4;
6841                      break;
6842                   case 2:
6843                      op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
6844                      op_qsub = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
6845                      op_cmp = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2;
6846                      break;
6847                   case 3:
6848                      return False;
6849                   default:
6850                      vassert(0);
6851                }
6852                assign(mask, binop(op_cmp, mkexpr(arg_m), zero1));
6853                neg = binop(op_qsub, zero2, mkexpr(arg_m));
6854                neg2 = binop(op_sub, zero2, mkexpr(arg_m));
6855                assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
6856                                  binop(Q ? Iop_AndV128 : Iop_And64,
6857                                        mkexpr(mask),
6858                                        mkexpr(arg_m)),
6859                                  binop(Q ? Iop_AndV128 : Iop_And64,
6860                                        unop(Q ? Iop_NotV128 : Iop_Not64,
6861                                             mkexpr(mask)),
6862                                        neg)));
6863 #ifndef DISABLE_QC_FLAG
6864                assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
6865                                  binop(Q ? Iop_AndV128 : Iop_And64,
6866                                        mkexpr(mask),
6867                                        mkexpr(arg_m)),
6868                                  binop(Q ? Iop_AndV128 : Iop_And64,
6869                                        unop(Q ? Iop_NotV128 : Iop_Not64,
6870                                             mkexpr(mask)),
6871                                        neg2)));
6872                setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
6873 #endif
6874                DIP("vqabs.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6875                    Q ? 'q' : 'd', mreg);
6876                break;
6877             }
6878             case 15: {
6879                /* VQNEG */
6880                IROp op, op2;
6881                IRExpr *zero;
6882                if (Q) {
6883                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6884                } else {
6885                   zero = mkU64(0);
6886                }
6887                switch (size) {
6888                   case 0:
6889                      op = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
6890                      op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
6891                      break;
6892                   case 1:
6893                      op = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
6894                      op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
6895                      break;
6896                   case 2:
6897                      op = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
6898                      op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
6899                      break;
6900                   case 3:
6901                      return False;
6902                   default:
6903                      vassert(0);
6904                }
6905                assign(res, binop(op, zero, mkexpr(arg_m)));
6906 #ifndef DISABLE_QC_FLAG
6907                setFlag_QC(mkexpr(res), binop(op2, zero, mkexpr(arg_m)),
6908                           Q, condT);
6909 #endif
6910                DIP("vqneg.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
6911                    Q ? 'q' : 'd', mreg);
6912                break;
6913             }
6914             default:
6915                vassert(0);
6916          }
6917          if (Q) {
6918             putQReg(dreg, mkexpr(res), condT);
6919          } else {
6920             putDRegI64(dreg, mkexpr(res), condT);
6921          }
6922          return True;
6923       case 1:
6924          if (Q) {
6925             arg_m = newTemp(Ity_V128);
6926             res = newTemp(Ity_V128);
6927             assign(arg_m, getQReg(mreg));
6928          } else {
6929             arg_m = newTemp(Ity_I64);
6930             res = newTemp(Ity_I64);
6931             assign(arg_m, getDRegI64(mreg));
6932          }
6933          switch ((B >> 1) & 0x7) {
6934             case 0: {
6935                /* VCGT #0 */
6936                IRExpr *zero;
6937                IROp op;
6938                if (Q) {
6939                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6940                } else {
6941                   zero = mkU64(0);
6942                }
6943                if (F) {
6944                   switch (size) {
6945                      case 0: case 1: case 3: return False;
6946                      case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
6947                      default: vassert(0);
6948                   }
6949                } else {
6950                   switch (size) {
6951                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
6952                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
6953                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
6954                      case 3: return False;
6955                      default: vassert(0);
6956                   }
6957                }
6958                assign(res, binop(op, mkexpr(arg_m), zero));
6959                DIP("vcgt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
6960                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6961                break;
6962             }
6963             case 1: {
6964                /* VCGE #0 */
6965                IROp op;
6966                IRExpr *zero;
6967                if (Q) {
6968                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
6969                } else {
6970                   zero = mkU64(0);
6971                }
6972                if (F) {
6973                   switch (size) {
6974                      case 0: case 1: case 3: return False;
6975                      case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
6976                      default: vassert(0);
6977                   }
6978                   assign(res, binop(op, mkexpr(arg_m), zero));
6979                } else {
6980                   switch (size) {
6981                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
6982                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
6983                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
6984                      case 3: return False;
6985                      default: vassert(0);
6986                   }
6987                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
6988                                    binop(op, zero, mkexpr(arg_m))));
6989                }
6990                DIP("vcge.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
6991                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
6992                break;
6993             }
6994             case 2: {
6995                /* VCEQ #0 */
6996                IROp op;
6997                IRExpr *zero;
6998                if (F) {
6999                   if (Q) {
7000                      zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7001                   } else {
7002                      zero = mkU64(0);
7003                   }
7004                   switch (size) {
7005                      case 0: case 1: case 3: return False;
7006                      case 2: op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; break;
7007                      default: vassert(0);
7008                   }
7009                   assign(res, binop(op, zero, mkexpr(arg_m)));
7010                } else {
7011                   switch (size) {
7012                      case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
7013                      case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
7014                      case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
7015                      case 3: return False;
7016                      default: vassert(0);
7017                   }
7018                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
7019                                    unop(op, mkexpr(arg_m))));
7020                }
7021                DIP("vceq.%c%u %c%u, %c%u, #0\n", F ? 'f' : 'i', 8 << size,
7022                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7023                break;
7024             }
7025             case 3: {
7026                /* VCLE #0 */
7027                IRExpr *zero;
7028                IROp op;
7029                if (Q) {
7030                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7031                } else {
7032                   zero = mkU64(0);
7033                }
7034                if (F) {
7035                   switch (size) {
7036                      case 0: case 1: case 3: return False;
7037                      case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
7038                      default: vassert(0);
7039                   }
7040                   assign(res, binop(op, zero, mkexpr(arg_m)));
7041                } else {
7042                   switch (size) {
7043                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
7044                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
7045                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
7046                      case 3: return False;
7047                      default: vassert(0);
7048                   }
7049                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
7050                                    binop(op, mkexpr(arg_m), zero)));
7051                }
7052                DIP("vcle.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
7053                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7054                break;
7055             }
7056             case 4: {
7057                /* VCLT #0 */
7058                IROp op;
7059                IRExpr *zero;
7060                if (Q) {
7061                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7062                } else {
7063                   zero = mkU64(0);
7064                }
7065                if (F) {
7066                   switch (size) {
7067                      case 0: case 1: case 3: return False;
7068                      case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
7069                      default: vassert(0);
7070                   }
7071                   assign(res, binop(op, zero, mkexpr(arg_m)));
7072                } else {
7073                   switch (size) {
7074                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
7075                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
7076                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
7077                      case 3: return False;
7078                      default: vassert(0);
7079                   }
7080                   assign(res, binop(op, zero, mkexpr(arg_m)));
7081                }
7082                DIP("vclt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
7083                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7084                break;
7085             }
7086             case 5:
7087                return False;
7088             case 6: {
7089                /* VABS */
7090                if (!F) {
7091                   IROp op;
7092                   switch(size) {
7093                      case 0: op = Q ? Iop_Abs8x16 : Iop_Abs8x8; break;
7094                      case 1: op = Q ? Iop_Abs16x8 : Iop_Abs16x4; break;
7095                      case 2: op = Q ? Iop_Abs32x4 : Iop_Abs32x2; break;
7096                      case 3: return False;
7097                      default: vassert(0);
7098                   }
7099                   assign(res, unop(op, mkexpr(arg_m)));
7100                } else {
7101                   assign(res, unop(Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2,
7102                                    mkexpr(arg_m)));
7103                }
7104                DIP("vabs.%c%u %c%u, %c%u\n",
7105                    F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
7106                    Q ? 'q' : 'd', mreg);
7107                break;
7108             }
7109             case 7: {
7110                /* VNEG */
7111                IROp op;
7112                IRExpr *zero;
7113                if (F) {
7114                   switch (size) {
7115                      case 0: case 1: case 3: return False;
7116                      case 2: op = Q ? Iop_Neg32Fx4 : Iop_Neg32Fx2; break;
7117                      default: vassert(0);
7118                   }
7119                   assign(res, unop(op, mkexpr(arg_m)));
7120                } else {
7121                   if (Q) {
7122                      zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
7123                   } else {
7124                      zero = mkU64(0);
7125                   }
7126                   switch (size) {
7127                      case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
7128                      case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
7129                      case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
7130                      case 3: return False;
7131                      default: vassert(0);
7132                   }
7133                   assign(res, binop(op, zero, mkexpr(arg_m)));
7134                }
7135                DIP("vneg.%c%u %c%u, %c%u\n",
7136                    F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
7137                    Q ? 'q' : 'd', mreg);
7138                break;
7139             }
7140             default:
7141                vassert(0);
7142          }
7143          if (Q) {
7144             putQReg(dreg, mkexpr(res), condT);
7145          } else {
7146             putDRegI64(dreg, mkexpr(res), condT);
7147          }
7148          return True;
7149       case 2:
7150          if ((B >> 1) == 0) {
7151             /* VSWP */
7152             if (Q) {
7153                arg_m = newTemp(Ity_V128);
7154                assign(arg_m, getQReg(mreg));
7155                putQReg(mreg, getQReg(dreg), condT);
7156                putQReg(dreg, mkexpr(arg_m), condT);
7157             } else {
7158                arg_m = newTemp(Ity_I64);
7159                assign(arg_m, getDRegI64(mreg));
7160                putDRegI64(mreg, getDRegI64(dreg), condT);
7161                putDRegI64(dreg, mkexpr(arg_m), condT);
7162             }
7163             DIP("vswp %c%u, %c%u\n",
7164                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7165             return True;
7166          } else if ((B >> 1) == 1) {
7167             /* VTRN */
7168             IROp op_lo, op_hi;
7169             IRTemp res1, res2;
7170             if (Q) {
7171                arg_m = newTemp(Ity_V128);
7172                arg_d = newTemp(Ity_V128);
7173                res1 = newTemp(Ity_V128);
7174                res2 = newTemp(Ity_V128);
7175                assign(arg_m, getQReg(mreg));
7176                assign(arg_d, getQReg(dreg));
7177             } else {
7178                res1 = newTemp(Ity_I64);
7179                res2 = newTemp(Ity_I64);
7180                arg_m = newTemp(Ity_I64);
7181                arg_d = newTemp(Ity_I64);
7182                assign(arg_m, getDRegI64(mreg));
7183                assign(arg_d, getDRegI64(dreg));
7184             }
7185             if (Q) {
7186                switch (size) {
7187                   case 0:
7188                      op_lo = Iop_InterleaveOddLanes8x16;
7189                      op_hi = Iop_InterleaveEvenLanes8x16;
7190                      break;
7191                   case 1:
7192                      op_lo = Iop_InterleaveOddLanes16x8;
7193                      op_hi = Iop_InterleaveEvenLanes16x8;
7194                      break;
7195                   case 2:
7196                      op_lo = Iop_InterleaveOddLanes32x4;
7197                      op_hi = Iop_InterleaveEvenLanes32x4;
7198                      break;
7199                   case 3:
7200                      return False;
7201                   default:
7202                      vassert(0);
7203                }
7204             } else {
7205                switch (size) {
7206                   case 0:
7207                      op_lo = Iop_InterleaveOddLanes8x8;
7208                      op_hi = Iop_InterleaveEvenLanes8x8;
7209                      break;
7210                   case 1:
7211                      op_lo = Iop_InterleaveOddLanes16x4;
7212                      op_hi = Iop_InterleaveEvenLanes16x4;
7213                      break;
7214                   case 2:
7215                      op_lo = Iop_InterleaveLO32x2;
7216                      op_hi = Iop_InterleaveHI32x2;
7217                      break;
7218                   case 3:
7219                      return False;
7220                   default:
7221                      vassert(0);
7222                }
7223             }
7224             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7225             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7226             if (Q) {
7227                putQReg(dreg, mkexpr(res1), condT);
7228                putQReg(mreg, mkexpr(res2), condT);
7229             } else {
7230                putDRegI64(dreg, mkexpr(res1), condT);
7231                putDRegI64(mreg, mkexpr(res2), condT);
7232             }
7233             DIP("vtrn.%u %c%u, %c%u\n",
7234                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7235             return True;
7236          } else if ((B >> 1) == 2) {
7237             /* VUZP */
7238             IROp op_lo, op_hi;
7239             IRTemp res1, res2;
7240             if (!Q && size == 2)
7241                return False;
7242             if (Q) {
7243                arg_m = newTemp(Ity_V128);
7244                arg_d = newTemp(Ity_V128);
7245                res1 = newTemp(Ity_V128);
7246                res2 = newTemp(Ity_V128);
7247                assign(arg_m, getQReg(mreg));
7248                assign(arg_d, getQReg(dreg));
7249             } else {
7250                res1 = newTemp(Ity_I64);
7251                res2 = newTemp(Ity_I64);
7252                arg_m = newTemp(Ity_I64);
7253                arg_d = newTemp(Ity_I64);
7254                assign(arg_m, getDRegI64(mreg));
7255                assign(arg_d, getDRegI64(dreg));
7256             }
7257             switch (size) {
7258                case 0:
7259                   op_lo = Q ? Iop_CatOddLanes8x16 : Iop_CatOddLanes8x8;
7260                   op_hi = Q ? Iop_CatEvenLanes8x16 : Iop_CatEvenLanes8x8;
7261                   break;
7262                case 1:
7263                   op_lo = Q ? Iop_CatOddLanes16x8 : Iop_CatOddLanes16x4;
7264                   op_hi = Q ? Iop_CatEvenLanes16x8 : Iop_CatEvenLanes16x4;
7265                   break;
7266                case 2:
7267                   op_lo = Iop_CatOddLanes32x4;
7268                   op_hi = Iop_CatEvenLanes32x4;
7269                   break;
7270                case 3:
7271                   return False;
7272                default:
7273                   vassert(0);
7274             }
7275             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7276             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7277             if (Q) {
7278                putQReg(dreg, mkexpr(res1), condT);
7279                putQReg(mreg, mkexpr(res2), condT);
7280             } else {
7281                putDRegI64(dreg, mkexpr(res1), condT);
7282                putDRegI64(mreg, mkexpr(res2), condT);
7283             }
7284             DIP("vuzp.%u %c%u, %c%u\n",
7285                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7286             return True;
7287          } else if ((B >> 1) == 3) {
7288             /* VZIP */
7289             IROp op_lo, op_hi;
7290             IRTemp res1, res2;
7291             if (!Q && size == 2)
7292                return False;
7293             if (Q) {
7294                arg_m = newTemp(Ity_V128);
7295                arg_d = newTemp(Ity_V128);
7296                res1 = newTemp(Ity_V128);
7297                res2 = newTemp(Ity_V128);
7298                assign(arg_m, getQReg(mreg));
7299                assign(arg_d, getQReg(dreg));
7300             } else {
7301                res1 = newTemp(Ity_I64);
7302                res2 = newTemp(Ity_I64);
7303                arg_m = newTemp(Ity_I64);
7304                arg_d = newTemp(Ity_I64);
7305                assign(arg_m, getDRegI64(mreg));
7306                assign(arg_d, getDRegI64(dreg));
7307             }
7308             switch (size) {
7309                case 0:
7310                   op_lo = Q ? Iop_InterleaveHI8x16 : Iop_InterleaveHI8x8;
7311                   op_hi = Q ? Iop_InterleaveLO8x16 : Iop_InterleaveLO8x8;
7312                   break;
7313                case 1:
7314                   op_lo = Q ? Iop_InterleaveHI16x8 : Iop_InterleaveHI16x4;
7315                   op_hi = Q ? Iop_InterleaveLO16x8 : Iop_InterleaveLO16x4;
7316                   break;
7317                case 2:
7318                   op_lo = Iop_InterleaveHI32x4;
7319                   op_hi = Iop_InterleaveLO32x4;
7320                   break;
7321                case 3:
7322                   return False;
7323                default:
7324                   vassert(0);
7325             }
7326             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
7327             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
7328             if (Q) {
7329                putQReg(dreg, mkexpr(res1), condT);
7330                putQReg(mreg, mkexpr(res2), condT);
7331             } else {
7332                putDRegI64(dreg, mkexpr(res1), condT);
7333                putDRegI64(mreg, mkexpr(res2), condT);
7334             }
7335             DIP("vzip.%u %c%u, %c%u\n",
7336                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7337             return True;
7338          } else if (B == 8) {
7339             /* VMOVN */
7340             IROp op;
7341             mreg >>= 1;
7342             switch (size) {
7343                case 0: op = Iop_Shorten16x8; break;
7344                case 1: op = Iop_Shorten32x4; break;
7345                case 2: op = Iop_Shorten64x2; break;
7346                case 3: return False;
7347                default: vassert(0);
7348             }
7349             putDRegI64(dreg, unop(op, getQReg(mreg)), condT);
7350             DIP("vmovn.i%u d%u, q%u\n", 16 << size, dreg, mreg);
7351             return True;
7352          } else if (B == 9 || (B >> 1) == 5) {
7353             /* VQMOVN, VQMOVUN */
7354             IROp op, op2;
7355             IRTemp tmp;
7356             dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
7357             mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
7358             if (mreg & 1)
7359                return False;
7360             mreg >>= 1;
7361             switch (size) {
7362                case 0: op2 = Iop_Shorten16x8; break;
7363                case 1: op2 = Iop_Shorten32x4; break;
7364                case 2: op2 = Iop_Shorten64x2; break;
7365                case 3: return False;
7366                default: vassert(0);
7367             }
7368             switch (B & 3) {
7369                case 0:
7370                   vassert(0);
7371                case 1:
7372                   switch (size) {
7373                      case 0: op = Iop_QShortenU16Sx8; break;
7374                      case 1: op = Iop_QShortenU32Sx4; break;
7375                      case 2: op = Iop_QShortenU64Sx2; break;
7376                      case 3: return False;
7377                      default: vassert(0);
7378                   }
7379                   DIP("vqmovun.s%u d%u, q%u\n", 16 << size, dreg, mreg);
7380                   break;
7381                case 2:
7382                   switch (size) {
7383                      case 0: op = Iop_QShortenS16Sx8; break;
7384                      case 1: op = Iop_QShortenS32Sx4; break;
7385                      case 2: op = Iop_QShortenS64Sx2; break;
7386                      case 3: return False;
7387                      default: vassert(0);
7388                   }
7389                   DIP("vqmovn.s%u d%u, q%u\n", 16 << size, dreg, mreg);
7390                   break;
7391                case 3:
7392                   switch (size) {
7393                      case 0: op = Iop_QShortenU16Ux8; break;
7394                      case 1: op = Iop_QShortenU32Ux4; break;
7395                      case 2: op = Iop_QShortenU64Ux2; break;
7396                      case 3: return False;
7397                      default: vassert(0);
7398                   }
7399                   DIP("vqmovn.u%u d%u, q%u\n", 16 << size, dreg, mreg);
7400                   break;
7401                default:
7402                   vassert(0);
7403             }
7404             res = newTemp(Ity_I64);
7405             tmp = newTemp(Ity_I64);
7406             assign(res, unop(op, getQReg(mreg)));
7407 #ifndef DISABLE_QC_FLAG
7408             assign(tmp, unop(op2, getQReg(mreg)));
7409             setFlag_QC(mkexpr(res), mkexpr(tmp), False, condT);
7410 #endif
7411             putDRegI64(dreg, mkexpr(res), condT);
7412             return True;
7413          } else if (B == 12) {
7414             /* VSHLL (maximum shift) */
7415             IROp op, cvt;
7416             UInt shift_imm;
7417             if (Q)
7418                return False;
7419             if (dreg & 1)
7420                return False;
7421             dreg >>= 1;
7422             shift_imm = 8 << size;
7423             res = newTemp(Ity_V128);
7424             switch (size) {
7425                case 0: op = Iop_ShlN16x8; cvt = Iop_Longen8Ux8; break;
7426                case 1: op = Iop_ShlN32x4; cvt = Iop_Longen16Ux4; break;
7427                case 2: op = Iop_ShlN64x2; cvt = Iop_Longen32Ux2; break;
7428                case 3: return False;
7429                default: vassert(0);
7430             }
7431             assign(res, binop(op, unop(cvt, getDRegI64(mreg)),
7432                                   mkU8(shift_imm)));
7433             putQReg(dreg, mkexpr(res), condT);
7434             DIP("vshll.i%u q%u, d%u, #%u\n", 8 << size, dreg, mreg, 8 << size);
7435             return True;
7436          } else if ((B >> 3) == 3 && (B & 3) == 0) {
7437             /* VCVT (half<->single) */
7438             /* Half-precision extensions are needed to run this */
7439             vassert(0); // ATC
7440             if (((theInstr >> 18) & 3) != 1)
7441                return False;
7442             if ((theInstr >> 8) & 1) {
7443                if (dreg & 1)
7444                   return False;
7445                dreg >>= 1;
7446                putQReg(dreg, unop(Iop_F16toF32x4, getDRegI64(mreg)),
7447                      condT);
7448                DIP("vcvt.f32.f16 q%u, d%u\n", dreg, mreg);
7449             } else {
7450                if (mreg & 1)
7451                   return False;
7452                mreg >>= 1;
7453                putDRegI64(dreg, unop(Iop_F32toF16x4, getQReg(mreg)),
7454                                 condT);
7455                DIP("vcvt.f16.f32 d%u, q%u\n", dreg, mreg);
7456             }
7457             return True;
7458          } else {
7459             return False;
7460          }
7461          vassert(0);
7462          return True;
7463       case 3:
7464          if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) {
7465             /* VRECPE */
7466             IROp op;
7467             F = (theInstr >> 8) & 1;
7468             if (size != 2)
7469                return False;
7470             if (Q) {
7471                op = F ? Iop_Recip32Fx4 : Iop_Recip32x4;
7472                putQReg(dreg, unop(op, getQReg(mreg)), condT);
7473                DIP("vrecpe.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
7474             } else {
7475                op = F ? Iop_Recip32Fx2 : Iop_Recip32x2;
7476                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7477                DIP("vrecpe.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
7478             }
7479             return True;
7480          } else if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) {
7481             /* VRSQRTE */
7482             IROp op;
7483             F = (B >> 2) & 1;
7484             if (size != 2)
7485                return False;
7486             if (F) {
7487                /* fp */
7488                op = Q ? Iop_Rsqrte32Fx4 : Iop_Rsqrte32Fx2;
7489             } else {
7490                /* unsigned int */
7491                op = Q ? Iop_Rsqrte32x4 : Iop_Rsqrte32x2;
7492             }
7493             if (Q) {
7494                putQReg(dreg, unop(op, getQReg(mreg)), condT);
7495                DIP("vrsqrte.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
7496             } else {
7497                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7498                DIP("vrsqrte.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
7499             }
7500             return True;
7501          } else if ((B >> 3) == 3) {
7502             /* VCVT (fp<->integer) */
7503             IROp op;
7504             if (size != 2)
7505                return False;
7506             switch ((B >> 1) & 3) {
7507                case 0:
7508                   op = Q ? Iop_I32StoFx4 : Iop_I32StoFx2;
7509                   DIP("vcvt.f32.s32 %c%u, %c%u\n",
7510                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7511                   break;
7512                case 1:
7513                   op = Q ? Iop_I32UtoFx4 : Iop_I32UtoFx2;
7514                   DIP("vcvt.f32.u32 %c%u, %c%u\n",
7515                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7516                   break;
7517                case 2:
7518                   op = Q ? Iop_FtoI32Sx4_RZ : Iop_FtoI32Sx2_RZ;
7519                   DIP("vcvt.s32.f32 %c%u, %c%u\n",
7520                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7521                   break;
7522                case 3:
7523                   op = Q ? Iop_FtoI32Ux4_RZ : Iop_FtoI32Ux2_RZ;
7524                   DIP("vcvt.u32.f32 %c%u, %c%u\n",
7525                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
7526                   break;
7527                default:
7528                   vassert(0);
7529             }
7530             if (Q) {
7531                putQReg(dreg, unop(op, getQReg(mreg)), condT);
7532             } else {
7533                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
7534             }
7535             return True;
7536          } else {
7537             return False;
7538          }
7539          vassert(0);
7540          return True;
7541       default:
7542          vassert(0);
7543    }
7544    return False;
7545 }
7546
7547 /* A7.4.6 One register and a modified immediate value */
7548 static
7549 void ppNeonImm(UInt imm, UInt cmode, UInt op)
7550 {
7551    int i;
7552    switch (cmode) {
7553       case 0: case 1: case 8: case 9:
7554          vex_printf("0x%x", imm);
7555          break;
7556       case 2: case 3: case 10: case 11:
7557          vex_printf("0x%x00", imm);
7558          break;
7559       case 4: case 5:
7560          vex_printf("0x%x0000", imm);
7561          break;
7562       case 6: case 7:
7563          vex_printf("0x%x000000", imm);
7564          break;
7565       case 12:
7566          vex_printf("0x%xff", imm);
7567          break;
7568       case 13:
7569          vex_printf("0x%xffff", imm);
7570          break;
7571       case 14:
7572          if (op) {
7573             vex_printf("0x");
7574             for (i = 7; i >= 0; i--)
7575                vex_printf("%s", (imm & (1 << i)) ? "ff" : "00");
7576          } else {
7577             vex_printf("0x%x", imm);
7578          }
7579          break;
7580       case 15:
7581          vex_printf("0x%x", imm);
7582          break;
7583    }
7584 }
7585
7586 static
7587 const char *ppNeonImmType(UInt cmode, UInt op)
7588 {
7589    switch (cmode) {
7590       case 0 ... 7:
7591       case 12: case 13:
7592          return "i32";
7593       case 8 ... 11:
7594          return "i16";
7595       case 14:
7596          if (op)
7597             return "i64";
7598          else
7599             return "i8";
7600       case 15:
7601          if (op)
7602             vassert(0);
7603          else
7604             return "f32";
7605       default:
7606          vassert(0);
7607    }
7608 }
7609
7610 static
7611 void DIPimm(UInt imm, UInt cmode, UInt op,
7612             const char *instr, UInt Q, UInt dreg)
7613 {
7614    if (vex_traceflags & VEX_TRACE_FE) {
7615       vex_printf("%s.%s %c%u, #", instr,
7616                  ppNeonImmType(cmode, op), Q ? 'q' : 'd', dreg);
7617       ppNeonImm(imm, cmode, op);
7618       vex_printf("\n");
7619    }
7620 }
7621
7622 static
7623 Bool dis_neon_data_1reg_and_imm ( UInt theInstr, IRTemp condT )
7624 {
7625    UInt dreg = get_neon_d_regno(theInstr);
7626    ULong imm_raw = ((theInstr >> 17) & 0x80) | ((theInstr >> 12) & 0x70) |
7627                   (theInstr & 0xf);
7628    ULong imm_raw_pp = imm_raw;
7629    UInt cmode = (theInstr >> 8) & 0xf;
7630    UInt op_bit = (theInstr >> 5) & 1;
7631    ULong imm = 0;
7632    UInt Q = (theInstr >> 6) & 1;
7633    int i, j;
7634    UInt tmp;
7635    IRExpr *imm_val;
7636    IRExpr *expr;
7637    IRTemp tmp_var;
7638    switch(cmode) {
7639       case 7: case 6:
7640          imm_raw = imm_raw << 8;
7641          /* fallthrough */
7642       case 5: case 4:
7643          imm_raw = imm_raw << 8;
7644          /* fallthrough */
7645       case 3: case 2:
7646          imm_raw = imm_raw << 8;
7647          /* fallthrough */
7648       case 0: case 1:
7649          imm = (imm_raw << 32) | imm_raw;
7650          break;
7651       case 11: case 10:
7652          imm_raw = imm_raw << 8;
7653          /* fallthrough */
7654       case 9: case 8:
7655          imm_raw = (imm_raw << 16) | imm_raw;
7656          imm = (imm_raw << 32) | imm_raw;
7657          break;
7658       case 13:
7659          imm_raw = (imm_raw << 8) | 0xff;
7660          /* fallthrough */
7661       case 12:
7662          imm_raw = (imm_raw << 8) | 0xff;
7663          imm = (imm_raw << 32) | imm_raw;
7664          break;
7665       case 14:
7666          if (! op_bit) {
7667             for(i = 0; i < 8; i++) {
7668                imm = (imm << 8) | imm_raw;
7669             }
7670          } else {
7671             for(i = 7; i >= 0; i--) {
7672                tmp = 0;
7673                for(j = 0; j < 8; j++) {
7674                   tmp = (tmp << 1) | ((imm_raw >> i) & 1);
7675                }
7676                imm = (imm << 8) | tmp;
7677             }
7678          }
7679          break;
7680       case 15:
7681          imm = (imm_raw & 0x80) << 5;
7682          imm |= ~((imm_raw & 0x40) << 5);
7683          for(i = 1; i <= 4; i++)
7684             imm |= (imm_raw & 0x40) << i;
7685          imm |= (imm_raw & 0x7f);
7686          imm = imm << 19;
7687          imm = (imm << 32) | imm;
7688          break;
7689       default:
7690          return False;
7691    }
7692    if (Q) {
7693       imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
7694    } else {
7695       imm_val = mkU64(imm);
7696    }
7697    if (((op_bit == 0) &&
7698       (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 12) == 12))) ||
7699       ((op_bit == 1) && (cmode == 14))) {
7700       /* VMOV (immediate) */
7701       if (Q) {
7702          putQReg(dreg, imm_val, condT);
7703       } else {
7704          putDRegI64(dreg, imm_val, condT);
7705       }
7706       DIPimm(imm_raw_pp, cmode, op_bit, "vmov", Q, dreg);
7707       return True;
7708    }
7709    if ((op_bit == 1) &&
7710       (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 14) == 12))) {
7711       /* VMVN (immediate) */
7712       if (Q) {
7713          putQReg(dreg, unop(Iop_NotV128, imm_val), condT);
7714       } else {
7715          putDRegI64(dreg, unop(Iop_Not64, imm_val), condT);
7716       }
7717       DIPimm(imm_raw_pp, cmode, op_bit, "vmvn", Q, dreg);
7718       return True;
7719    }
7720    if (Q) {
7721       tmp_var = newTemp(Ity_V128);
7722       assign(tmp_var, getQReg(dreg));
7723    } else {
7724       tmp_var = newTemp(Ity_I64);
7725       assign(tmp_var, getDRegI64(dreg));
7726    }
7727    if ((op_bit == 0) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
7728       /* VORR (immediate) */
7729       if (Q)
7730          expr = binop(Iop_OrV128, mkexpr(tmp_var), imm_val);
7731       else
7732          expr = binop(Iop_Or64, mkexpr(tmp_var), imm_val);
7733       DIPimm(imm_raw_pp, cmode, op_bit, "vorr", Q, dreg);
7734    } else if ((op_bit == 1) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
7735       /* VBIC (immediate) */
7736       if (Q)
7737          expr = binop(Iop_AndV128, mkexpr(tmp_var),
7738                                    unop(Iop_NotV128, imm_val));
7739       else
7740          expr = binop(Iop_And64, mkexpr(tmp_var), unop(Iop_Not64, imm_val));
7741       DIPimm(imm_raw_pp, cmode, op_bit, "vbic", Q, dreg);
7742    } else {
7743       return False;
7744    }
7745    if (Q)
7746       putQReg(dreg, expr, condT);
7747    else
7748       putDRegI64(dreg, expr, condT);
7749    return True;
7750 }
7751
7752 /* A7.4 Advanced SIMD data-processing instructions */
7753 static
7754 Bool dis_neon_data_processing ( UInt theInstr, IRTemp condT )
7755 {
7756    UInt A = (theInstr >> 19) & 0x1F;
7757    UInt B = (theInstr >>  8) & 0xF;
7758    UInt C = (theInstr >>  4) & 0xF;
7759    UInt U = (theInstr >> 24) & 0x1;
7760
7761    if (! (A & 0x10)) {
7762       return dis_neon_data_3same(theInstr, condT);
7763    }
7764    if (((A & 0x17) == 0x10) && ((C & 0x9) == 0x1)) {
7765       return dis_neon_data_1reg_and_imm(theInstr, condT);
7766    }
7767    if ((C & 1) == 1) {
7768       return dis_neon_data_2reg_and_shift(theInstr, condT);
7769    }
7770    if (((C & 5) == 0) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
7771       return dis_neon_data_3diff(theInstr, condT);
7772    }
7773    if (((C & 5) == 4) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
7774       return dis_neon_data_2reg_and_scalar(theInstr, condT);
7775    }
7776    if ((A & 0x16) == 0x16) {
7777       if ((U == 0) && ((C & 1) == 0)) {
7778          return dis_neon_vext(theInstr, condT);
7779       }
7780       if ((U != 1) || ((C & 1) == 1))
7781          return False;
7782       if ((B & 8) == 0) {
7783          return dis_neon_data_2reg_misc(theInstr, condT);
7784       }
7785       if ((B & 12) == 8) {
7786          return dis_neon_vtb(theInstr, condT);
7787       }
7788       if ((B == 12) && ((C & 9) == 0)) {
7789          return dis_neon_vdup(theInstr, condT);
7790       }
7791    }
7792    return False;
7793 }
7794
7795
7796 /*------------------------------------------------------------*/
7797 /*--- NEON loads and stores                                ---*/
7798 /*------------------------------------------------------------*/
7799
7800 /* For NEON memory operations, we use the standard scheme to handle
7801    conditionalisation: generate a jump around the instruction if the
7802    condition is false.  That's only necessary in Thumb mode, however,
7803    since in ARM mode NEON instructions are unconditional. */
7804
7805 /* A helper function for what follows.  It assumes we already went
7806    uncond as per comments at the top of this section. */
7807 static
7808 void mk_neon_elem_load_to_one_lane( UInt rD, UInt inc, UInt index,
7809                                     UInt N, UInt size, IRTemp addr )
7810 {
7811    UInt i;
7812    switch (size) {
7813       case 0:
7814          putDRegI64(rD, triop(Iop_SetElem8x8, getDRegI64(rD), mkU8(index),
7815                     loadLE(Ity_I8, mkexpr(addr))), IRTemp_INVALID);
7816          break;
7817       case 1:
7818          putDRegI64(rD, triop(Iop_SetElem16x4, getDRegI64(rD), mkU8(index),
7819                     loadLE(Ity_I16, mkexpr(addr))), IRTemp_INVALID);
7820          break;
7821       case 2:
7822          putDRegI64(rD, triop(Iop_SetElem32x2, getDRegI64(rD), mkU8(index),
7823                     loadLE(Ity_I32, mkexpr(addr))), IRTemp_INVALID);
7824          break;
7825       default:
7826          vassert(0);
7827    }
7828    for (i = 1; i <= N; i++) {
7829       switch (size) {
7830          case 0:
7831             putDRegI64(rD + i * inc,
7832                        triop(Iop_SetElem8x8,
7833                              getDRegI64(rD + i * inc),
7834                              mkU8(index),
7835                              loadLE(Ity_I8, binop(Iop_Add32,
7836                                                   mkexpr(addr),
7837                                                   mkU32(i * 1)))),
7838                        IRTemp_INVALID);
7839             break;
7840          case 1:
7841             putDRegI64(rD + i * inc,
7842                        triop(Iop_SetElem16x4,
7843                              getDRegI64(rD + i * inc),
7844                              mkU8(index),
7845                              loadLE(Ity_I16, binop(Iop_Add32,
7846                                                    mkexpr(addr),
7847                                                    mkU32(i * 2)))),
7848                        IRTemp_INVALID);
7849             break;
7850          case 2:
7851             putDRegI64(rD + i * inc,
7852                        triop(Iop_SetElem32x2,
7853                              getDRegI64(rD + i * inc),
7854                              mkU8(index),
7855                              loadLE(Ity_I32, binop(Iop_Add32,
7856                                                    mkexpr(addr),
7857                                                    mkU32(i * 4)))),
7858                        IRTemp_INVALID);
7859             break;
7860          default:
7861             vassert(0);
7862       }
7863    }
7864 }
7865
7866 /* A(nother) helper function for what follows.  It assumes we already
7867    went uncond as per comments at the top of this section. */
7868 static
7869 void mk_neon_elem_store_from_one_lane( UInt rD, UInt inc, UInt index,
7870                                        UInt N, UInt size, IRTemp addr )
7871 {
7872    UInt i;
7873    switch (size) {
7874       case 0:
7875          storeLE(mkexpr(addr),
7876                  binop(Iop_GetElem8x8, getDRegI64(rD), mkU8(index)));
7877          break;
7878       case 1:
7879          storeLE(mkexpr(addr),
7880                  binop(Iop_GetElem16x4, getDRegI64(rD), mkU8(index)));
7881          break;
7882       case 2:
7883          storeLE(mkexpr(addr),
7884                  binop(Iop_GetElem32x2, getDRegI64(rD), mkU8(index)));
7885          break;
7886       default:
7887          vassert(0);
7888    }
7889    for (i = 1; i <= N; i++) {
7890       switch (size) {
7891          case 0:
7892             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 1)),
7893                     binop(Iop_GetElem8x8, getDRegI64(rD + i * inc),
7894                                           mkU8(index)));
7895             break;
7896          case 1:
7897             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 2)),
7898                     binop(Iop_GetElem16x4, getDRegI64(rD + i * inc),
7899                                            mkU8(index)));
7900             break;
7901          case 2:
7902             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 4)),
7903                     binop(Iop_GetElem32x2, getDRegI64(rD + i * inc),
7904                                            mkU8(index)));
7905             break;
7906          default:
7907             vassert(0);
7908       }
7909    }
7910 }
7911
7912 /* A7.7 Advanced SIMD element or structure load/store instructions */
7913 static
7914 Bool dis_neon_elem_or_struct_load ( UInt theInstr,
7915                                     Bool isT, IRTemp condT )
7916 {
7917 #  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
7918    UInt A = INSN(23,23);
7919    UInt B = INSN(11,8);
7920    UInt L = INSN(21,21);
7921    UInt rD = (INSN(22,22) << 4) | INSN(15,12);
7922    UInt rN = INSN(19,16);
7923    UInt rM = INSN(3,0);
7924    UInt N, size, i, j;
7925    UInt inc;
7926    UInt regs = 1;
7927
7928    if (isT) {
7929       vassert(condT != IRTemp_INVALID);
7930    } else {
7931       vassert(condT == IRTemp_INVALID);
7932    }
7933    /* So now, if condT is not IRTemp_INVALID, we know we're
7934       dealing with Thumb code. */
7935
7936    if (INSN(20,20) != 0)
7937       return False;
7938
7939    IRTemp initialRn = newTemp(Ity_I32);
7940    assign(initialRn, isT ? getIRegT(rN) : getIRegA(rN));
7941
7942    IRTemp initialRm = newTemp(Ity_I32);
7943    assign(initialRm, isT ? getIRegT(rM) : getIRegA(rM));
7944
7945    if (A) {
7946       N = B & 3;
7947       if ((B >> 2) < 3) {
7948          /* VSTn / VLDn (n-element structure from/to one lane) */
7949
7950          size = B >> 2;
7951
7952          switch (size) {
7953             case 0: i = INSN(7,5); inc = 1; break;
7954             case 1: i = INSN(7,6); inc = INSN(5,5) ? 2 : 1; break;
7955             case 2: i = INSN(7,7); inc = INSN(6,6) ? 2 : 1; break;
7956             case 3: return False;
7957             default: vassert(0);
7958          }
7959
7960          IRTemp addr = newTemp(Ity_I32);
7961          assign(addr, mkexpr(initialRn));
7962
7963          // go uncond
7964          if (condT != IRTemp_INVALID)
7965             mk_skip_over_T32_if_cond_is_false(condT);
7966          // now uncond
7967
7968          if (L)
7969             mk_neon_elem_load_to_one_lane(rD, inc, i, N, size, addr);
7970          else
7971             mk_neon_elem_store_from_one_lane(rD, inc, i, N, size, addr);
7972          DIP("v%s%u.%u {", L ? "ld" : "st", N + 1, 8 << size);
7973          for (j = 0; j <= N; j++) {
7974             if (j)
7975                DIP(", ");
7976             DIP("d%u[%u]", rD + j * inc, i);
7977          }
7978          DIP("}, [r%u]", rN);
7979          if (rM != 13 && rM != 15) {
7980             DIP(", r%u\n", rM);
7981          } else {
7982             DIP("%s\n", (rM != 15) ? "!" : "");
7983          }
7984       } else {
7985          /* VLDn (single element to all lanes) */
7986          UInt r;
7987          if (L == 0)
7988             return False;
7989
7990          inc = INSN(5,5) + 1;
7991          size = INSN(7,6);
7992
7993          /* size == 3 and size == 2 cases differ in alignment constraints */
7994          if (size == 3 && N == 3 && INSN(4,4) == 1)
7995             size = 2;
7996
7997          if (size == 0 && N == 0 && INSN(4,4) == 1)
7998             return False;
7999          if (N == 2 && INSN(4,4) == 1)
8000             return False;
8001          if (size == 3)
8002             return False;
8003
8004          // go uncond
8005          if (condT != IRTemp_INVALID)
8006             mk_skip_over_T32_if_cond_is_false(condT);
8007          // now uncond
8008
8009          IRTemp addr = newTemp(Ity_I32);
8010          assign(addr, mkexpr(initialRn));
8011
8012          if (N == 0 && INSN(5,5))
8013             regs = 2;
8014
8015          for (r = 0; r < regs; r++) {
8016             switch (size) {
8017                case 0:
8018                   putDRegI64(rD + r, unop(Iop_Dup8x8,
8019                                           loadLE(Ity_I8, mkexpr(addr))),
8020                              IRTemp_INVALID);
8021                   break;
8022                case 1:
8023                   putDRegI64(rD + r, unop(Iop_Dup16x4,
8024                                           loadLE(Ity_I16, mkexpr(addr))),
8025                              IRTemp_INVALID);
8026                   break;
8027                case 2:
8028                   putDRegI64(rD + r, unop(Iop_Dup32x2,
8029                                           loadLE(Ity_I32, mkexpr(addr))),
8030                              IRTemp_INVALID);
8031                   break;
8032                default:
8033                   vassert(0);
8034             }
8035             for (i = 1; i <= N; i++) {
8036                switch (size) {
8037                   case 0:
8038                      putDRegI64(rD + r + i * inc,
8039                                 unop(Iop_Dup8x8,
8040                                      loadLE(Ity_I8, binop(Iop_Add32,
8041                                                           mkexpr(addr),
8042                                                           mkU32(i * 1)))),
8043                                 IRTemp_INVALID);
8044                      break;
8045                   case 1:
8046                      putDRegI64(rD + r + i * inc,
8047                                 unop(Iop_Dup16x4,
8048                                      loadLE(Ity_I16, binop(Iop_Add32,
8049                                                            mkexpr(addr),
8050                                                            mkU32(i * 2)))),
8051                                 IRTemp_INVALID);
8052                      break;
8053                   case 2:
8054                      putDRegI64(rD + r + i * inc,
8055                                 unop(Iop_Dup32x2,
8056                                      loadLE(Ity_I32, binop(Iop_Add32,
8057                                                            mkexpr(addr),
8058                                                            mkU32(i * 4)))),
8059                                 IRTemp_INVALID);
8060                      break;
8061                   default:
8062                      vassert(0);
8063                }
8064             }
8065          }
8066          DIP("vld%u.%u {", N + 1, 8 << size);
8067          for (r = 0; r < regs; r++) {
8068             for (i = 0; i <= N; i++) {
8069                if (i || r)
8070                   DIP(", ");
8071                DIP("d%u[]", rD + r + i * inc);
8072             }
8073          }
8074          DIP("}, [r%u]", rN);
8075          if (rM != 13 && rM != 15) {
8076             DIP(", r%u\n", rM);
8077          } else {
8078             DIP("%s\n", (rM != 15) ? "!" : "");
8079          }
8080       }
8081       /* Writeback.  We're uncond here, so no condT-ing. */
8082       if (rM != 15) {
8083          if (rM == 13) {
8084             IRExpr* e = binop(Iop_Add32,
8085                               mkexpr(initialRn),
8086                               mkU32((1 << size) * (N + 1)));
8087             if (isT)
8088                putIRegT(rN, e, IRTemp_INVALID);
8089             else
8090                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8091          } else {
8092             IRExpr* e = binop(Iop_Add32,
8093                               mkexpr(initialRn),
8094                               mkexpr(initialRm));
8095             if (isT)
8096                putIRegT(rN, e, IRTemp_INVALID);
8097             else
8098                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8099          }
8100       }
8101       return True;
8102    } else {
8103       IRTemp tmp;
8104       UInt r, elems;
8105       /* VSTn / VLDn (multiple n-element structures) */
8106       if (B == BITS4(0,0,1,0) || B == BITS4(0,1,1,0)
8107           || B == BITS4(0,1,1,1) || B == BITS4(1,0,1,0)) {
8108          N = 0;
8109       } else if (B == BITS4(0,0,1,1) || B == BITS4(1,0,0,0)
8110                  || B == BITS4(1,0,0,1)) {
8111          N = 1;
8112       } else if (B == BITS4(0,1,0,0) || B == BITS4(0,1,0,1)) {
8113          N = 2;
8114       } else if (B == BITS4(0,0,0,0) || B == BITS4(0,0,0,1)) {
8115          N = 3;
8116       } else {
8117          return False;
8118       }
8119       inc = (B & 1) + 1;
8120       if (N == 1 && B == BITS4(0,0,1,1)) {
8121          regs = 2;
8122       } else if (N == 0) {
8123          if (B == BITS4(1,0,1,0)) {
8124             regs = 2;
8125          } else if (B == BITS4(0,1,1,0)) {
8126             regs = 3;
8127          } else if (B == BITS4(0,0,1,0)) {
8128             regs = 4;
8129          }
8130       }
8131
8132       size = INSN(7,6);
8133       if (N == 0 && size == 3)
8134          size = 2;
8135       if (size == 3)
8136          return False;
8137
8138       elems = 8 / (1 << size);
8139
8140       // go uncond
8141       if (condT != IRTemp_INVALID)
8142          mk_skip_over_T32_if_cond_is_false(condT);
8143       // now uncond
8144
8145       IRTemp addr = newTemp(Ity_I32);
8146       assign(addr, mkexpr(initialRn));
8147
8148       for (r = 0; r < regs; r++) {
8149          for (i = 0; i < elems; i++) {
8150             if (L)
8151                mk_neon_elem_load_to_one_lane(rD + r, inc, i, N, size, addr);
8152             else
8153                mk_neon_elem_store_from_one_lane(rD + r, inc, i, N, size, addr);
8154             tmp = newTemp(Ity_I32);
8155             assign(tmp, binop(Iop_Add32, mkexpr(addr),
8156                                          mkU32((1 << size) * (N + 1))));
8157             addr = tmp;
8158          }
8159       }
8160       /* Writeback */
8161       if (rM != 15) {
8162          if (rM == 13) {
8163             IRExpr* e = binop(Iop_Add32,
8164                               mkexpr(initialRn),
8165                               mkU32(8 * (N + 1) * regs));
8166             if (isT)
8167                putIRegT(rN, e, IRTemp_INVALID);
8168             else
8169                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8170          } else {
8171             IRExpr* e = binop(Iop_Add32,
8172                               mkexpr(initialRn),
8173                               mkexpr(initialRm));
8174             if (isT)
8175                putIRegT(rN, e, IRTemp_INVALID);
8176             else
8177                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
8178          }
8179       }
8180       DIP("v%s%u.%u {", L ? "ld" : "st", N + 1, 8 << INSN(7,6));
8181       if ((inc == 1 && regs * (N + 1) > 1)
8182           || (inc == 2 && regs > 1 && N > 0)) {
8183          DIP("d%u-d%u", rD, rD + regs * (N + 1) - 1);
8184       } else {
8185          for (r = 0; r < regs; r++) {
8186             for (i = 0; i <= N; i++) {
8187                if (i || r)
8188                   DIP(", ");
8189                DIP("d%u", rD + r + i * inc);
8190             }
8191          }
8192       }
8193       DIP("}, [r%u]", rN);
8194       if (rM != 13 && rM != 15) {
8195          DIP(", r%u\n", rM);
8196       } else {
8197          DIP("%s\n", (rM != 15) ? "!" : "");
8198       }
8199       return True;
8200    }
8201 #  undef INSN
8202 }
8203
8204
8205 /*------------------------------------------------------------*/
8206 /*--- NEON, top level control                              ---*/
8207 /*------------------------------------------------------------*/
8208
8209 /* Both ARM and Thumb */
8210
8211 /* Translate a NEON instruction.    If successful, returns
8212    True and *dres may or may not be updated.  If failure, returns
8213    False and doesn't change *dres nor create any IR.
8214
8215    The Thumb and ARM encodings are similar for the 24 bottom bits, but
8216    the top 8 bits are slightly different.  In both cases, the caller
8217    must pass the entire 32 bits.  Callers may pass any instruction;
8218    this ignores non-NEON ones.
8219
8220    Caller must supply an IRTemp 'condT' holding the gating condition,
8221    or IRTemp_INVALID indicating the insn is always executed.  In ARM
8222    code, this must always be IRTemp_INVALID because NEON insns are
8223    unconditional for ARM.
8224
8225    Finally, the caller must indicate whether this occurs in ARM or in
8226    Thumb code.
8227 */
8228 static Bool decode_NEON_instruction (
8229                /*MOD*/DisResult* dres,
8230                UInt              insn32,
8231                IRTemp            condT,
8232                Bool              isT
8233             )
8234 {
8235 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn32, (_bMax), (_bMin))
8236
8237    /* There are two kinds of instruction to deal with: load/store and
8238       data processing.  In each case, in ARM mode we merely identify
8239       the kind, and pass it on to the relevant sub-handler.  In Thumb
8240       mode we identify the kind, swizzle the bits around to make it
8241       have the same encoding as in ARM, and hand it on to the
8242       sub-handler.
8243    */
8244
8245    /* In ARM mode, NEON instructions can't be conditional. */
8246    if (!isT)
8247       vassert(condT == IRTemp_INVALID);
8248
8249    /* Data processing:
8250       Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx
8251       ARM:   1111 001U AAAA Axxx xxxx BBBB CCCC xxxx
8252    */
8253    if (!isT && INSN(31,25) == BITS7(1,1,1,1,0,0,1)) {
8254       // ARM, DP
8255       return dis_neon_data_processing(INSN(31,0), condT);
8256    }
8257    if (isT && INSN(31,29) == BITS3(1,1,1)
8258        && INSN(27,24) == BITS4(1,1,1,1)) {
8259       // Thumb, DP
8260       UInt reformatted = INSN(23,0);
8261       reformatted |= (INSN(28,28) << 24); // U bit
8262       reformatted |= (BITS7(1,1,1,1,0,0,1) << 25);
8263       return dis_neon_data_processing(reformatted, condT);
8264    }
8265
8266    /* Load/store:
8267       Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx
8268       ARM:   1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx
8269    */
8270    if (!isT && INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) {
8271       // ARM, memory
8272       return dis_neon_elem_or_struct_load(INSN(31,0), isT, condT);
8273    }
8274    if (isT && INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) {
8275       UInt reformatted = INSN(23,0);
8276       reformatted |= (BITS8(1,1,1,1,0,1,0,0) << 24);
8277       return dis_neon_elem_or_struct_load(reformatted, isT, condT);
8278    }
8279
8280    /* Doesn't match. */
8281    return False;
8282
8283 #  undef INSN
8284 }
8285
8286
8287 /*------------------------------------------------------------*/
8288 /*--- V6 MEDIA instructions                                ---*/
8289 /*------------------------------------------------------------*/
8290
8291 /* Both ARM and Thumb */
8292
8293 /* Translate a V6 media instruction.    If successful, returns
8294    True and *dres may or may not be updated.  If failure, returns
8295    False and doesn't change *dres nor create any IR.
8296
8297    The Thumb and ARM encodings are completely different.  In Thumb
8298    mode, the caller must pass the entire 32 bits.  In ARM mode it must
8299    pass the lower 28 bits.  Apart from that, callers may pass any
8300    instruction; this function ignores anything it doesn't recognise.
8301
8302    Caller must supply an IRTemp 'condT' holding the gating condition,
8303    or IRTemp_INVALID indicating the insn is always executed.
8304
8305    Caller must also supply an ARMCondcode 'cond'.  This is only used
8306    for debug printing, no other purpose.  For ARM, this is simply the
8307    top 4 bits of the original instruction.  For Thumb, the condition
8308    is not (really) known until run time, and so ARMCondAL should be
8309    passed, only so that printing of these instructions does not show
8310    any condition.
8311
8312    Finally, the caller must indicate whether this occurs in ARM or in
8313    Thumb code.
8314 */
8315 static Bool decode_V6MEDIA_instruction (
8316                /*MOD*/DisResult* dres,
8317                UInt              insnv6m,
8318                IRTemp            condT,
8319                ARMCondcode       conq,
8320                Bool              isT
8321             )
8322 {
8323 #  define INSNA(_bMax,_bMin)   SLICE_UInt(insnv6m, (_bMax), (_bMin))
8324 #  define INSNT0(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \
8325                                            (_bMax), (_bMin) )
8326 #  define INSNT1(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 0)  & 0xFFFF), \
8327                                            (_bMax), (_bMin) )
8328    HChar dis_buf[128];
8329    dis_buf[0] = 0;
8330
8331    if (isT) {
8332       vassert(conq == ARMCondAL);
8333    } else {
8334       vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation
8335       vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
8336    }
8337
8338    /* ----------- smulbb, smulbt, smultb, smultt ----------- */
8339    {
8340      UInt regD = 99, regM = 99, regN = 99, bitM = 0, bitN = 0;
8341      Bool gate = False;
8342
8343      if (isT) {
8344         if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1)
8345             && INSNT1(7,6) == BITS2(0,0)) {
8346            regD = INSNT1(11,8);
8347            regM = INSNT1(3,0);
8348            regN = INSNT0(3,0);
8349            bitM = INSNT1(4,4);
8350            bitN = INSNT1(5,5);
8351            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8352               gate = True;
8353         }
8354      } else {
8355         if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) &&
8356             BITS4(0,0,0,0)         == INSNA(15,12) &&
8357             BITS4(1,0,0,0)         == (INSNA(7,4) & BITS4(1,0,0,1)) ) {
8358            regD = INSNA(19,16);
8359            regM = INSNA(11,8);
8360            regN = INSNA(3,0);
8361            bitM = INSNA(6,6);
8362            bitN = INSNA(5,5);
8363            if (regD != 15 && regN != 15 && regM != 15)
8364               gate = True;
8365         }
8366      }
8367
8368      if (gate) {
8369         IRTemp srcN = newTemp(Ity_I32);
8370         IRTemp srcM = newTemp(Ity_I32);
8371         IRTemp res  = newTemp(Ity_I32);
8372
8373         assign( srcN, binop(Iop_Sar32,
8374                             binop(Iop_Shl32,
8375                                   isT ? getIRegT(regN) : getIRegA(regN),
8376                                   mkU8(bitN ? 0 : 16)), mkU8(16)) );
8377         assign( srcM, binop(Iop_Sar32,
8378                             binop(Iop_Shl32,
8379                                   isT ? getIRegT(regM) : getIRegA(regM),
8380                                   mkU8(bitM ? 0 : 16)), mkU8(16)) );
8381         assign( res, binop(Iop_Mul32, mkexpr(srcN), mkexpr(srcM)) );
8382
8383         if (isT)
8384            putIRegT( regD, mkexpr(res), condT );
8385         else
8386            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8387
8388         DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN ? 't' : 'b', bitM ? 't' : 'b',
8389              nCC(conq), regD, regN, regM );
8390         return True;
8391      }
8392      /* fall through */
8393    }
8394
8395    /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */
8396    /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */
8397    {
8398      UInt regD = 99, regN = 99, regM = 99, bitM = 0;
8399      Bool gate = False;
8400
8401      if (isT) {
8402         if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1)
8403             && INSNT1(7,5) == BITS3(0,0,0)) {
8404           regN = INSNT0(3,0);
8405           regD = INSNT1(11,8);
8406           regM = INSNT1(3,0);
8407           bitM = INSNT1(4,4);
8408           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8409              gate = True;
8410         }
8411      } else {
8412         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) && 
8413             INSNA(15,12) == BITS4(0,0,0,0)         &&
8414             (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) {
8415            regD = INSNA(19,16);
8416            regN = INSNA(3,0);
8417            regM = INSNA(11,8);
8418            bitM = INSNA(6,6);
8419            if (regD != 15 && regN != 15 && regM != 15)
8420               gate = True;
8421         }
8422      }
8423
8424      if (gate) {
8425         IRTemp irt_prod = newTemp(Ity_I64);
8426
8427         assign( irt_prod, 
8428                 binop(Iop_MullS32,
8429                       isT ? getIRegT(regN) : getIRegA(regN),
8430                       binop(Iop_Sar32, 
8431                             binop(Iop_Shl32,
8432                                   isT ? getIRegT(regM) : getIRegA(regM),
8433                                   mkU8(bitM ? 0 : 16)), 
8434                             mkU8(16))) );
8435
8436         IRExpr* ire_result = binop(Iop_Or32, 
8437                                    binop( Iop_Shl32, 
8438                                           unop(Iop_64HIto32, mkexpr(irt_prod)), 
8439                                           mkU8(16) ), 
8440                                    binop( Iop_Shr32, 
8441                                           unop(Iop_64to32, mkexpr(irt_prod)), 
8442                                           mkU8(16) ) );
8443
8444         if (isT)
8445            putIRegT( regD, ire_result, condT );
8446         else
8447            putIRegA( regD, ire_result, condT, Ijk_Boring );
8448
8449         DIP("smulw%c%s r%u, r%u, r%u\n",
8450             bitM ? 't' : 'b', nCC(conq),regD,regN,regM);
8451         return True;
8452      }
8453      /* fall through */
8454    }
8455
8456    /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */
8457    /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */
8458    {
8459      UInt regD = 99, regN = 99, regM = 99, imm5 = 99, shift_type = 99;
8460      Bool tbform = False;
8461      Bool gate = False;
8462
8463      if (isT) {
8464         if (INSNT0(15,4) == 0xEAC 
8465             && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) {
8466            regN = INSNT0(3,0);
8467            regD = INSNT1(11,8);
8468            regM = INSNT1(3,0);
8469            imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6);
8470            shift_type = (INSNT1(5,5) << 1) | 0;
8471            tbform = (INSNT1(5,5) == 0) ? False : True;
8472            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8473               gate = True;
8474         }
8475      } else {
8476         if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
8477             INSNA(5,4)   == BITS2(0,1)             &&
8478             (INSNA(6,6)  == 0 || INSNA(6,6) == 1) ) {
8479            regD = INSNA(15,12);
8480            regN = INSNA(19,16);
8481            regM = INSNA(3,0);
8482            imm5 = INSNA(11,7);
8483            shift_type = (INSNA(6,6) << 1) | 0;
8484            tbform = (INSNA(6,6) == 0) ? False : True;
8485            if (regD != 15 && regN != 15 && regM != 15)
8486               gate = True;
8487         }
8488      }
8489
8490      if (gate) {
8491         IRTemp irt_regM       = newTemp(Ity_I32);
8492         IRTemp irt_regM_shift = newTemp(Ity_I32);
8493         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
8494         compute_result_and_C_after_shift_by_imm5(
8495            dis_buf, &irt_regM_shift, NULL, irt_regM, shift_type, imm5, regM );
8496
8497         UInt mask = (tbform == True) ? 0x0000FFFF : 0xFFFF0000;
8498         IRExpr* ire_result 
8499           = binop( Iop_Or32, 
8500                    binop(Iop_And32, mkexpr(irt_regM_shift), mkU32(mask)), 
8501                    binop(Iop_And32, isT ? getIRegT(regN) : getIRegA(regN),
8502                                     unop(Iop_Not32, mkU32(mask))) );
8503
8504         if (isT)
8505            putIRegT( regD, ire_result, condT );
8506         else
8507            putIRegA( regD, ire_result, condT, Ijk_Boring );
8508
8509         DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform ? "tb" : "bt", 
8510              nCC(conq), regD, regN, regM, dis_buf );
8511
8512         return True;
8513      }
8514      /* fall through */
8515    }
8516
8517    /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
8518    {
8519      UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
8520      Bool gate = False;
8521
8522      if (isT) {
8523         if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0)
8524             && INSNT0(4,4) == 0
8525             && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
8526            regD       = INSNT1(11,8);
8527            regN       = INSNT0(3,0);
8528            shift_type = (INSNT0(5,5) << 1) | 0;
8529            imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
8530            sat_imm    = INSNT1(4,0);
8531            if (!isBadRegT(regD) && !isBadRegT(regN))
8532               gate = True;
8533            if (shift_type == BITS2(1,0) && imm5 == 0)
8534               gate = False;
8535         }
8536      } else {
8537         if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) &&
8538             INSNA(5,4)   == BITS2(0,1)) {
8539            regD       = INSNA(15,12);
8540            regN       = INSNA(3,0);
8541            shift_type = (INSNA(6,6) << 1) | 0;
8542            imm5       = INSNA(11,7);
8543            sat_imm    = INSNA(20,16);
8544            if (regD != 15 && regN != 15)
8545               gate = True;
8546         }
8547      }
8548
8549      if (gate) {
8550         IRTemp irt_regN       = newTemp(Ity_I32);
8551         IRTemp irt_regN_shift = newTemp(Ity_I32);
8552         IRTemp irt_sat_Q      = newTemp(Ity_I32);
8553         IRTemp irt_result     = newTemp(Ity_I32);
8554
8555         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8556         compute_result_and_C_after_shift_by_imm5(
8557                 dis_buf, &irt_regN_shift, NULL,
8558                 irt_regN, shift_type, imm5, regN );
8559
8560         armUnsignedSatQ( &irt_result, &irt_sat_Q, irt_regN_shift, sat_imm );
8561         or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
8562
8563         if (isT)
8564            putIRegT( regD, mkexpr(irt_result), condT );
8565         else
8566            putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
8567
8568         DIP("usat%s r%u, #0x%04x, %s\n",
8569             nCC(conq), regD, imm5, dis_buf);
8570         return True;
8571      }
8572      /* fall through */
8573    }
8574
8575   /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
8576    {
8577      UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
8578      Bool gate = False;
8579
8580      if (isT) {
8581         if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
8582             && INSNT0(4,4) == 0
8583             && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
8584            regD       = INSNT1(11,8);
8585            regN       = INSNT0(3,0);
8586            shift_type = (INSNT0(5,5) << 1) | 0;
8587            imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
8588            sat_imm    = INSNT1(4,0) + 1;
8589            if (!isBadRegT(regD) && !isBadRegT(regN))
8590               gate = True;
8591            if (shift_type == BITS2(1,0) && imm5 == 0)
8592               gate = False;
8593         }
8594      } else {
8595         if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) &&
8596             INSNA(5,4)   == BITS2(0,1)) {
8597            regD       = INSNA(15,12);
8598            regN       = INSNA(3,0);
8599            shift_type = (INSNA(6,6) << 1) | 0;
8600            imm5       = INSNA(11,7);
8601            sat_imm    = INSNA(20,16) + 1;
8602            if (regD != 15 && regN != 15)
8603               gate = True;
8604         }
8605      }
8606
8607      if (gate) {
8608         IRTemp irt_regN       = newTemp(Ity_I32);
8609         IRTemp irt_regN_shift = newTemp(Ity_I32);
8610         IRTemp irt_sat_Q      = newTemp(Ity_I32);
8611         IRTemp irt_result     = newTemp(Ity_I32);
8612
8613         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8614         compute_result_and_C_after_shift_by_imm5(
8615                 dis_buf, &irt_regN_shift, NULL,
8616                 irt_regN, shift_type, imm5, regN );
8617
8618         armSignedSatQ( irt_regN_shift, sat_imm, &irt_result, &irt_sat_Q );
8619         or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
8620
8621         if (isT)
8622            putIRegT( regD, mkexpr(irt_result), condT );
8623         else
8624            putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
8625
8626         DIP( "ssat%s r%u, #0x%04x, %s\n",
8627              nCC(conq), regD, imm5, dis_buf);
8628         return True;
8629     }
8630     /* fall through */
8631   }
8632
8633    /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */
8634    {
8635      UInt regD = 99, regN = 99, sat_imm = 99;
8636      Bool gate = False;
8637
8638      if (isT) {
8639         if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) {
8640            regN = INSNT0(3,0);
8641            regD = INSNT1(11,8);
8642            sat_imm = INSNT1(3,0);
8643            if (!isBadRegT(regD) && !isBadRegT(regN))
8644               gate = True;
8645        }
8646      } else {
8647         if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) &&
8648             INSNA(11,8)  == BITS4(1,1,1,1)         &&
8649             INSNA(7,4)   == BITS4(0,0,1,1)) {
8650            regD    = INSNA(15,12);
8651            regN    = INSNA(3,0);
8652            sat_imm = INSNA(19,16);
8653            if (regD != 15 && regN != 15)
8654               gate = True;
8655         }
8656      }
8657
8658      if (gate) {
8659         IRTemp irt_regN    = newTemp(Ity_I32);
8660         IRTemp irt_regN_lo = newTemp(Ity_I32);
8661         IRTemp irt_regN_hi = newTemp(Ity_I32);
8662         IRTemp irt_Q_lo    = newTemp(Ity_I32);
8663         IRTemp irt_Q_hi    = newTemp(Ity_I32);
8664         IRTemp irt_res_lo  = newTemp(Ity_I32);
8665         IRTemp irt_res_hi  = newTemp(Ity_I32);
8666
8667         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
8668         assign( irt_regN_lo, binop( Iop_Sar32, 
8669                                     binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
8670                                     mkU8(16)) );
8671         assign( irt_regN_hi, binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)) );
8672
8673         armUnsignedSatQ( &irt_res_lo, &irt_Q_lo, irt_regN_lo, sat_imm );
8674         or_into_QFLAG32( mkexpr(irt_Q_lo), condT );
8675
8676         armUnsignedSatQ( &irt_res_hi, &irt_Q_hi, irt_regN_hi, sat_imm );
8677         or_into_QFLAG32( mkexpr(irt_Q_hi), condT );
8678
8679         IRExpr* ire_result = binop( Iop_Or32, 
8680                                     binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)),
8681                                     mkexpr(irt_res_lo) );
8682
8683         if (isT)
8684            putIRegT( regD, ire_result, condT );
8685         else
8686            putIRegA( regD, ire_result, condT, Ijk_Boring );
8687
8688         DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq), regD, sat_imm, regN );
8689         return True;
8690      }
8691      /* fall through */
8692    }
8693
8694    /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */
8695    {
8696      UInt regD = 99, regN = 99, regM = 99;
8697      Bool gate = False;
8698
8699      if (isT) {
8700         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8701            regN = INSNT0(3,0);
8702            regD = INSNT1(11,8);
8703            regM = INSNT1(3,0);
8704            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8705               gate = True;
8706         }
8707      } else {
8708         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) && 
8709             INSNA(11,8)  == BITS4(1,1,1,1)         &&
8710             INSNA(7,4)   == BITS4(0,0,0,1)) {
8711            regD = INSNA(15,12);
8712            regN = INSNA(19,16);
8713            regM = INSNA(3,0);
8714            if (regD != 15 && regN != 15 && regM != 15)
8715               gate = True;
8716         }
8717      }
8718
8719      if (gate) {
8720         IRTemp rNt  = newTemp(Ity_I32);
8721         IRTemp rMt  = newTemp(Ity_I32);
8722         IRTemp res  = newTemp(Ity_I32);
8723         IRTemp reso = newTemp(Ity_I32);
8724
8725         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8726         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8727
8728         assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
8729         if (isT)
8730            putIRegT( regD, mkexpr(res), condT );
8731         else
8732            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8733
8734         assign(reso, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
8735         set_GE_32_10_from_bits_31_15(reso, condT);
8736
8737         DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8738         return True;
8739      }
8740      /* fall through */
8741    }
8742
8743    /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */
8744    {
8745      UInt regD = 99, regN = 99, regM = 99;
8746      Bool gate = False;
8747
8748      if (isT) {
8749         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8750            regN = INSNT0(3,0);
8751            regD = INSNT1(11,8);
8752            regM = INSNT1(3,0);
8753            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8754               gate = True;
8755         }
8756      } else {
8757         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 
8758             INSNA(11,8)  == BITS4(1,1,1,1)         &&
8759             INSNA(7,4)   == BITS4(0,0,0,1)) {
8760            regD = INSNA(15,12);
8761            regN = INSNA(19,16);
8762            regM = INSNA(3,0);
8763            if (regD != 15 && regN != 15 && regM != 15)
8764               gate = True;
8765         }
8766      }
8767
8768      if (gate) {
8769         IRTemp rNt  = newTemp(Ity_I32);
8770         IRTemp rMt  = newTemp(Ity_I32);
8771         IRTemp res  = newTemp(Ity_I32);
8772         IRTemp reso = newTemp(Ity_I32);
8773
8774         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8775         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8776
8777         assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
8778         if (isT)
8779            putIRegT( regD, mkexpr(res), condT );
8780         else
8781            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8782
8783         assign(reso, unop(Iop_Not32,
8784                           binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt))));
8785         set_GE_32_10_from_bits_31_15(reso, condT);
8786
8787         DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8788         return True;
8789      }
8790      /* fall through */
8791    }
8792
8793    /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */
8794    {
8795      UInt regD = 99, regN = 99, regM = 99;
8796      Bool gate = False;
8797
8798      if (isT) {
8799         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8800            regN = INSNT0(3,0);
8801            regD = INSNT1(11,8);
8802            regM = INSNT1(3,0);
8803            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8804               gate = True;
8805         }
8806      } else {
8807         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) && 
8808             INSNA(11,8)  == BITS4(1,1,1,1)         &&
8809             INSNA(7,4)   == BITS4(0,1,1,1)) {
8810            regD = INSNA(15,12);
8811            regN = INSNA(19,16);
8812            regM = INSNA(3,0);
8813            if (regD != 15 && regN != 15 && regM != 15)
8814              gate = True;
8815         }
8816      }
8817
8818      if (gate) {
8819         IRTemp rNt  = newTemp(Ity_I32);
8820         IRTemp rMt  = newTemp(Ity_I32);
8821         IRTemp res  = newTemp(Ity_I32);
8822         IRTemp reso = newTemp(Ity_I32);
8823
8824         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8825         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8826
8827         assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
8828         if (isT)
8829            putIRegT( regD, mkexpr(res), condT );
8830         else
8831            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8832
8833         assign(reso, unop(Iop_Not32,
8834                           binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt))));
8835         set_GE_32_10_from_bits_31_15(reso, condT);
8836
8837         DIP("usub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8838         return True;
8839      }
8840      /* fall through */
8841    }
8842
8843    /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */
8844    {
8845      UInt regD = 99, regN = 99, regM = 99;
8846      Bool gate = False;
8847
8848      if (isT) {
8849         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8850            regN = INSNT0(3,0);
8851            regD = INSNT1(11,8);
8852            regM = INSNT1(3,0);
8853            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8854               gate = True;
8855         }
8856      } else {
8857         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) && 
8858             INSNA(11,8)  == BITS4(1,1,1,1)         &&
8859             INSNA(7,4)   == BITS4(0,1,1,1)) {
8860            regD = INSNA(15,12);
8861            regN = INSNA(19,16);
8862            regM = INSNA(3,0);
8863            if (regD != 15 && regN != 15 && regM != 15)
8864               gate = True;
8865         }
8866      }
8867
8868      if (gate) {
8869         IRTemp rNt  = newTemp(Ity_I32);
8870         IRTemp rMt  = newTemp(Ity_I32);
8871         IRTemp res  = newTemp(Ity_I32);
8872         IRTemp reso = newTemp(Ity_I32);
8873
8874         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8875         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8876
8877         assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
8878         if (isT)
8879            putIRegT( regD, mkexpr(res), condT );
8880         else
8881            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8882
8883         assign(reso, unop(Iop_Not32,
8884                           binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt))));
8885         set_GE_32_10_from_bits_31_15(reso, condT);
8886
8887         DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8888         return True;
8889      }
8890      /* fall through */
8891    }
8892
8893    /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */
8894    {
8895      UInt regD = 99, regN = 99, regM = 99;
8896      Bool gate = False;
8897
8898      if (isT) {
8899         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8900            regN = INSNT0(3,0);
8901            regD = INSNT1(11,8);
8902            regM = INSNT1(3,0);
8903            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8904               gate = True;
8905         }
8906      } else {
8907         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
8908             INSNA(11,8)  == BITS4(1,1,1,1)         &&
8909             (INSNA(7,4)  == BITS4(1,0,0,1))) {
8910            regD = INSNA(15,12);
8911            regN = INSNA(19,16);
8912            regM = INSNA(3,0);
8913            if (regD != 15 && regN != 15 && regM != 15)
8914               gate = True;
8915         }
8916      }
8917
8918      if (gate) {
8919         IRTemp rNt  = newTemp(Ity_I32);
8920         IRTemp rMt  = newTemp(Ity_I32);
8921         IRTemp res  = newTemp(Ity_I32);
8922         IRTemp reso = newTemp(Ity_I32);
8923
8924         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8925         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8926
8927         assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
8928         if (isT)
8929            putIRegT( regD, mkexpr(res), condT );
8930         else
8931            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8932
8933         assign(reso, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
8934         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
8935
8936         DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8937         return True;
8938      }
8939      /* fall through */
8940    }
8941
8942    /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
8943    {
8944      UInt regD = 99, regN = 99, regM = 99;
8945      Bool gate = False;
8946
8947      if (isT) {
8948         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
8949            regN = INSNT0(3,0);
8950            regD = INSNT1(11,8);
8951            regM = INSNT1(3,0);
8952            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
8953               gate = True;
8954         }
8955      } else {
8956         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
8957             INSNA(11,8)  == BITS4(1,1,1,1)         &&
8958             (INSNA(7,4)  == BITS4(1,0,0,1))) {
8959            regD = INSNA(15,12);
8960            regN = INSNA(19,16);
8961            regM = INSNA(3,0);
8962            if (regD != 15 && regN != 15 && regM != 15)
8963               gate = True;
8964         }
8965      }
8966
8967      if (gate) {
8968         IRTemp rNt  = newTemp(Ity_I32);
8969         IRTemp rMt  = newTemp(Ity_I32);
8970         IRTemp res  = newTemp(Ity_I32);
8971         IRTemp reso = newTemp(Ity_I32);
8972
8973         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
8974         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
8975
8976         assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
8977         if (isT)
8978            putIRegT( regD, mkexpr(res), condT );
8979         else
8980            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
8981
8982         assign(reso, unop(Iop_Not32,
8983                           binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt))));
8984         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
8985
8986         DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
8987         return True;
8988      }
8989      /* fall through */
8990    }
8991
8992    /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
8993    {
8994      UInt regD = 99, regN = 99, regM = 99;
8995      Bool gate = False;
8996
8997      if (isT) {
8998         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
8999            regN = INSNT0(3,0);
9000            regD = INSNT1(11,8);
9001            regM = INSNT1(3,0);
9002            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9003               gate = True;
9004         }
9005      } else {
9006         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
9007             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9008             (INSNA(7,4)  == BITS4(1,1,1,1))) {
9009            regD = INSNA(15,12);
9010            regN = INSNA(19,16);
9011            regM = INSNA(3,0);
9012            if (regD != 15 && regN != 15 && regM != 15)
9013              gate = True;
9014         }
9015      }
9016
9017      if (gate) {
9018         IRTemp rNt  = newTemp(Ity_I32);
9019         IRTemp rMt  = newTemp(Ity_I32);
9020         IRTemp res  = newTemp(Ity_I32);
9021         IRTemp reso = newTemp(Ity_I32);
9022
9023         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9024         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9025
9026         assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
9027         if (isT)
9028            putIRegT( regD, mkexpr(res), condT );
9029         else
9030            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
9031
9032         assign(reso, unop(Iop_Not32,
9033                           binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt))));
9034         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
9035
9036         DIP("usub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9037         return True;
9038      }
9039      /* fall through */
9040    }
9041
9042    /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9043    {
9044      UInt regD = 99, regN = 99, regM = 99;
9045      Bool gate = False;
9046
9047      if (isT) {
9048         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9049            regN = INSNT0(3,0);
9050            regD = INSNT1(11,8);
9051            regM = INSNT1(3,0);
9052            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9053               gate = True;
9054         }
9055      } else {
9056         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9057             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9058             INSNA(7,4)   == BITS4(1,1,1,1)) {
9059            regD = INSNA(15,12);
9060            regN = INSNA(19,16);
9061            regM = INSNA(3,0);
9062            if (regD != 15 && regN != 15 && regM != 15)
9063               gate = True;
9064         }
9065      }
9066
9067      if (gate) {
9068         IRTemp rNt  = newTemp(Ity_I32);
9069         IRTemp rMt  = newTemp(Ity_I32);
9070         IRTemp res  = newTemp(Ity_I32);
9071         IRTemp reso = newTemp(Ity_I32);
9072
9073         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9074         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9075
9076         assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
9077         if (isT)
9078            putIRegT( regD, mkexpr(res), condT );
9079         else
9080            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
9081
9082         assign(reso, unop(Iop_Not32,
9083                           binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt))));
9084         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
9085
9086         DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9087         return True;
9088      }
9089      /* fall through */
9090    }
9091
9092    /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9093    {
9094      UInt regD = 99, regN = 99, regM = 99;
9095      Bool gate = False;
9096
9097      if (isT) {
9098         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9099            regN = INSNT0(3,0);
9100            regD = INSNT1(11,8);
9101            regM = INSNT1(3,0);
9102            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9103               gate = True;
9104         }
9105      } else {
9106         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9107             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9108             INSNA(7,4)   == BITS4(1,0,0,1)) {
9109            regD = INSNA(15,12);
9110            regN = INSNA(19,16);
9111            regM = INSNA(3,0);
9112            if (regD != 15 && regN != 15 && regM != 15)
9113               gate = True;
9114         }
9115      }
9116
9117      if (gate) {
9118         IRTemp rNt   = newTemp(Ity_I32);
9119         IRTemp rMt   = newTemp(Ity_I32);
9120         IRTemp res_q = newTemp(Ity_I32);
9121
9122         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9123         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9124
9125         assign(res_q, binop(Iop_QAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
9126         if (isT)
9127            putIRegT( regD, mkexpr(res_q), condT );
9128         else
9129            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9130
9131         DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9132         return True;
9133      }
9134      /* fall through */
9135    }
9136
9137    /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
9138    {
9139      UInt regD = 99, regN = 99, regM = 99;
9140      Bool gate = False;
9141
9142      if (isT) {
9143         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9144            regN = INSNT0(3,0);
9145            regD = INSNT1(11,8);
9146            regM = INSNT1(3,0);
9147            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9148               gate = True;
9149         }
9150      } else {
9151         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9152             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9153             INSNA(7,4)   == BITS4(1,1,1,1)) {
9154            regD = INSNA(15,12);
9155            regN = INSNA(19,16);
9156            regM = INSNA(3,0);
9157            if (regD != 15 && regN != 15 && regM != 15)
9158               gate = True;
9159         }
9160      }
9161
9162      if (gate) {
9163         IRTemp rNt   = newTemp(Ity_I32);
9164         IRTemp rMt   = newTemp(Ity_I32);
9165         IRTemp res_q = newTemp(Ity_I32);
9166
9167         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9168         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9169
9170         assign(res_q, binop(Iop_QSub8Sx4, mkexpr(rNt), mkexpr(rMt)));
9171         if (isT)
9172            putIRegT( regD, mkexpr(res_q), condT );
9173         else
9174            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9175
9176         DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9177         return True;
9178      }
9179      /* fall through */
9180    }
9181
9182    /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
9183    {
9184      UInt regD = 99, regN = 99, regM = 99;
9185      Bool gate = False;
9186
9187      if (isT) {
9188         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9189            regN = INSNT0(3,0);
9190            regD = INSNT1(11,8);
9191            regM = INSNT1(3,0);
9192            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9193               gate = True;
9194         }
9195      } else {
9196         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9197             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9198             (INSNA(7,4)  == BITS4(1,0,0,1))) {
9199            regD = INSNA(15,12);
9200            regN = INSNA(19,16);
9201            regM = INSNA(3,0);
9202            if (regD != 15 && regN != 15 && regM != 15)
9203               gate = True;
9204         }
9205      }
9206
9207      if (gate) {
9208         IRTemp rNt   = newTemp(Ity_I32);
9209         IRTemp rMt   = newTemp(Ity_I32);
9210         IRTemp res_q = newTemp(Ity_I32);
9211
9212         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9213         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9214
9215         assign(res_q, binop(Iop_QAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
9216         if (isT)
9217            putIRegT( regD, mkexpr(res_q), condT );
9218         else
9219            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9220
9221         DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9222         return True;
9223      }
9224      /* fall through */
9225    }
9226
9227    /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
9228    {
9229      UInt regD = 99, regN = 99, regM = 99;
9230      Bool gate = False;
9231
9232      if (isT) {
9233         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
9234            regN = INSNT0(3,0);
9235            regD = INSNT1(11,8);
9236            regM = INSNT1(3,0);
9237            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9238               gate = True;
9239         }
9240      } else {
9241         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
9242             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9243             (INSNA(7,4)  == BITS4(1,1,1,1))) {
9244            regD = INSNA(15,12);
9245            regN = INSNA(19,16);
9246            regM = INSNA(3,0);
9247            if (regD != 15 && regN != 15 && regM != 15)
9248              gate = True;
9249         }
9250      }
9251
9252      if (gate) {
9253         IRTemp rNt   = newTemp(Ity_I32);
9254         IRTemp rMt   = newTemp(Ity_I32);
9255         IRTemp res_q = newTemp(Ity_I32);
9256
9257         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9258         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9259
9260         assign(res_q, binop(Iop_QSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
9261         if (isT)
9262            putIRegT( regD, mkexpr(res_q), condT );
9263         else
9264            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9265
9266         DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9267         return True;
9268      }
9269      /* fall through */
9270    }
9271
9272    /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9273    {
9274      UInt regD = 99, regN = 99, regM = 99;
9275      Bool gate = False;
9276
9277      if (isT) {
9278         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
9279            regN = INSNT0(3,0);
9280            regD = INSNT1(11,8);
9281            regM = INSNT1(3,0);
9282            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9283               gate = True;
9284         }
9285      } else {
9286         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
9287             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9288             INSNA(7,4)   == BITS4(1,0,0,1)) {
9289            regD = INSNA(15,12);
9290            regN = INSNA(19,16);
9291            regM = INSNA(3,0);
9292            if (regD != 15 && regN != 15 && regM != 15)
9293               gate = True;
9294         }
9295      }
9296
9297      if (gate) {
9298         IRTemp rNt   = newTemp(Ity_I32);
9299         IRTemp rMt   = newTemp(Ity_I32);
9300         IRTemp res_q = newTemp(Ity_I32);
9301
9302         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9303         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9304
9305         assign(res_q, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
9306         if (isT)
9307            putIRegT( regD, mkexpr(res_q), condT );
9308         else
9309            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9310
9311         DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9312         return True;
9313      }
9314      /* fall through */
9315    }
9316
9317    /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
9318    {
9319      UInt regD = 99, regN = 99, regM = 99;
9320      Bool gate = False;
9321
9322      if (isT) {
9323         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
9324            regN = INSNT0(3,0);
9325            regD = INSNT1(11,8);
9326            regM = INSNT1(3,0);
9327            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9328               gate = True;
9329         }
9330      } else {
9331         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
9332             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9333             INSNA(7,4)   == BITS4(1,0,0,1)) {
9334            regD = INSNA(15,12);
9335            regN = INSNA(19,16);
9336            regM = INSNA(3,0);
9337            if (regD != 15 && regN != 15 && regM != 15)
9338               gate = True;
9339         }
9340      }
9341
9342      if (gate) {
9343         IRTemp rNt   = newTemp(Ity_I32);
9344         IRTemp rMt   = newTemp(Ity_I32);
9345         IRTemp res_q = newTemp(Ity_I32);
9346
9347         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9348         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9349
9350         assign(res_q, binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
9351         if (isT)
9352            putIRegT( regD, mkexpr(res_q), condT );
9353         else
9354            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9355
9356         DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9357         return True;
9358      }
9359      /* fall through */
9360    }
9361
9362    /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
9363    {
9364      UInt regD = 99, regN = 99, regM = 99;
9365      Bool gate = False;
9366
9367      if (isT) {
9368         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9369            regN = INSNT0(3,0);
9370            regD = INSNT1(11,8);
9371            regM = INSNT1(3,0);
9372            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9373               gate = True;
9374         }
9375      } else {
9376         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9377             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9378             INSNA(7,4)   == BITS4(0,0,0,1)) {
9379            regD = INSNA(15,12);
9380            regN = INSNA(19,16);
9381            regM = INSNA(3,0);
9382            if (regD != 15 && regN != 15 && regM != 15)
9383               gate = True;
9384         }
9385      }
9386
9387      if (gate) {
9388         IRTemp rNt   = newTemp(Ity_I32);
9389         IRTemp rMt   = newTemp(Ity_I32);
9390         IRTemp res_q = newTemp(Ity_I32);
9391
9392         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9393         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9394
9395         assign(res_q, binop(Iop_QAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
9396         if (isT)
9397            putIRegT( regD, mkexpr(res_q), condT );
9398         else
9399            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9400
9401         DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9402         return True;
9403      }
9404      /* fall through */
9405    }
9406
9407    /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
9408    {
9409      UInt regD = 99, regN = 99, regM = 99;
9410      Bool gate = False;
9411
9412       if (isT) {
9413         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9414            regN = INSNT0(3,0);
9415            regD = INSNT1(11,8);
9416            regM = INSNT1(3,0);
9417            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9418               gate = True;
9419         }
9420      } else {
9421         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9422             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9423             INSNA(7,4)   == BITS4(0,1,1,1)) {
9424            regD = INSNA(15,12);
9425            regN = INSNA(19,16);
9426            regM = INSNA(3,0);
9427            if (regD != 15 && regN != 15 && regM != 15)
9428              gate = True;
9429         }
9430      }
9431
9432      if (gate) {
9433         IRTemp rNt   = newTemp(Ity_I32);
9434         IRTemp rMt   = newTemp(Ity_I32);
9435         IRTemp res_q = newTemp(Ity_I32);
9436
9437         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
9438         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
9439
9440         assign(res_q, binop(Iop_QSub16Sx2, mkexpr(rNt), mkexpr(rMt)));
9441         if (isT)
9442            putIRegT( regD, mkexpr(res_q), condT );
9443         else
9444            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
9445
9446         DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
9447         return True;
9448      }
9449      /* fall through */
9450    }
9451
9452    /////////////////////////////////////////////////////////////////
9453    /////////////////////////////////////////////////////////////////
9454    /////////////////////////////////////////////////////////////////
9455    /////////////////////////////////////////////////////////////////
9456    /////////////////////////////////////////////////////////////////
9457
9458    /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
9459    /* note: the hardware seems to construct the result differently
9460       from wot the manual says. */
9461    {
9462      UInt regD = 99, regN = 99, regM = 99;
9463      Bool gate = False;
9464
9465      if (isT) {
9466         if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9467            regN = INSNT0(3,0);
9468            regD = INSNT1(11,8);
9469            regM = INSNT1(3,0);
9470            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9471               gate = True;
9472         }
9473      } else {
9474         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9475             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9476             INSNA(7,4)   == BITS4(0,1,0,1)) {
9477            regD = INSNA(15,12);
9478            regN = INSNA(19,16);
9479            regM = INSNA(3,0);
9480            if (regD != 15 && regN != 15 && regM != 15)
9481               gate = True;
9482         }
9483      }
9484
9485      if (gate) {
9486         IRTemp irt_regN     = newTemp(Ity_I32);
9487         IRTemp irt_regM     = newTemp(Ity_I32);
9488         IRTemp irt_sum      = newTemp(Ity_I32);
9489         IRTemp irt_diff     = newTemp(Ity_I32);
9490         IRTemp irt_sum_res  = newTemp(Ity_I32);
9491         IRTemp irt_diff_res = newTemp(Ity_I32);
9492
9493         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9494         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9495
9496         assign( irt_diff, 
9497                 binop( Iop_Sub32, 
9498                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
9499                        binop( Iop_Sar32, 
9500                               binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
9501                               mkU8(16) ) ) );
9502         armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL);
9503
9504         assign( irt_sum, 
9505                 binop( Iop_Add32, 
9506                        binop( Iop_Sar32, 
9507                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
9508                               mkU8(16) ), 
9509                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) );
9510         armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL );
9511
9512         IRExpr* ire_result = binop( Iop_Or32, 
9513                                     binop( Iop_Shl32, mkexpr(irt_diff_res), 
9514                                            mkU8(16) ), 
9515                                     binop( Iop_And32, mkexpr(irt_sum_res), 
9516                                            mkU32(0xFFFF)) );
9517
9518         if (isT) 
9519            putIRegT( regD, ire_result, condT );
9520         else
9521            putIRegA( regD, ire_result, condT, Ijk_Boring );
9522
9523         DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9524         return True;
9525      }
9526      /* fall through */
9527    }
9528
9529    /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
9530    {
9531      UInt regD = 99, regN = 99, regM = 99;
9532      Bool gate = False;
9533
9534      if (isT) {
9535         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
9536            regN = INSNT0(3,0);
9537            regD = INSNT1(11,8);
9538            regM = INSNT1(3,0);
9539            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9540               gate = True;
9541         }
9542      } else {
9543         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
9544             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9545             INSNA(7,4)   == BITS4(0,0,1,1)) {
9546            regD = INSNA(15,12);
9547            regN = INSNA(19,16);
9548            regM = INSNA(3,0);
9549            if (regD != 15 && regN != 15 && regM != 15)
9550               gate = True;
9551         }
9552      }
9553
9554      if (gate) {
9555         IRTemp irt_regN     = newTemp(Ity_I32);
9556         IRTemp irt_regM     = newTemp(Ity_I32);
9557         IRTemp irt_sum      = newTemp(Ity_I32);
9558         IRTemp irt_diff     = newTemp(Ity_I32);
9559         IRTemp irt_res_sum  = newTemp(Ity_I32);
9560         IRTemp irt_res_diff = newTemp(Ity_I32);
9561
9562         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9563         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9564
9565         assign( irt_diff,  
9566                 binop( Iop_Sub32, 
9567                        binop( Iop_Sar32, 
9568                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
9569                               mkU8(16) ), 
9570                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9571         armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL );
9572
9573         assign( irt_sum, 
9574                 binop( Iop_Add32, 
9575                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 
9576                        binop( Iop_Sar32, 
9577                               binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 
9578                               mkU8(16) ) ) );
9579         armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL );
9580        
9581         IRExpr* ire_result 
9582           = binop( Iop_Or32, 
9583                    binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ), 
9584                    binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) );
9585
9586         if (isT)
9587            putIRegT( regD, ire_result, condT );
9588         else
9589            putIRegA( regD, ire_result, condT, Ijk_Boring );
9590
9591         DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9592         return True;
9593      }
9594      /* fall through */
9595    }
9596
9597    /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
9598    {
9599      UInt regD = 99, regN = 99, regM = 99;
9600      Bool gate = False;
9601
9602      if (isT) {
9603         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
9604            regN = INSNT0(3,0);
9605            regD = INSNT1(11,8);
9606            regM = INSNT1(3,0);
9607            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9608               gate = True;
9609         }
9610      } else {
9611         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
9612             INSNA(11,8)  == BITS4(1,1,1,1)         &&
9613             INSNA(7,4)   == BITS4(0,0,1,1)) {
9614            regD = INSNA(15,12);
9615            regN = INSNA(19,16);
9616            regM = INSNA(3,0);
9617            if (regD != 15 && regN != 15 && regM != 15)
9618               gate = True;
9619         }
9620      }
9621
9622      if (gate) {
9623         IRTemp irt_regN = newTemp(Ity_I32);
9624         IRTemp irt_regM = newTemp(Ity_I32);
9625         IRTemp irt_sum  = newTemp(Ity_I32);
9626         IRTemp irt_diff = newTemp(Ity_I32);
9627
9628         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9629         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
9630
9631         assign( irt_diff,  
9632                 binop( Iop_Sub32, 
9633                        binop( Iop_Sar32, 
9634                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
9635                               mkU8(16) ), 
9636                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9637
9638         assign( irt_sum, 
9639                 binop( Iop_Add32, 
9640                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 
9641                        binop( Iop_Sar32, 
9642                               binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 
9643                               mkU8(16) ) ) );
9644        
9645         IRExpr* ire_result 
9646           = binop( Iop_Or32, 
9647                    binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ), 
9648                    binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) );
9649
9650         IRTemp ge10 = newTemp(Ity_I32);
9651         assign(ge10, unop(Iop_Not32, mkexpr(irt_diff)));
9652         put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
9653         put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
9654
9655         IRTemp ge32 = newTemp(Ity_I32);
9656         assign(ge32, unop(Iop_Not32, mkexpr(irt_sum)));
9657         put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
9658         put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
9659
9660         if (isT)
9661            putIRegT( regD, ire_result, condT );
9662         else
9663            putIRegA( regD, ire_result, condT, Ijk_Boring );
9664
9665         DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
9666         return True;
9667      }
9668      /* fall through */
9669    }
9670
9671    /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
9672    /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */
9673    {
9674      UInt regD = 99, regN = 99, regM = 99, bitM = 99;
9675      Bool gate = False, isAD = False;
9676
9677      if (isT) {
9678         if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
9679             && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
9680            regN = INSNT0(3,0);
9681            regD = INSNT1(11,8);
9682            regM = INSNT1(3,0);
9683            bitM = INSNT1(4,4);
9684            isAD = INSNT0(15,4) == 0xFB2;
9685            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9686               gate = True;
9687         }
9688      } else {
9689         if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
9690             INSNA(15,12) == BITS4(1,1,1,1)         &&
9691             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) {
9692            regD = INSNA(19,16);
9693            regN = INSNA(3,0);
9694            regM = INSNA(11,8);
9695            bitM = INSNA(5,5);
9696            isAD = INSNA(6,6) == 0;
9697            if (regD != 15 && regN != 15 && regM != 15)
9698               gate = True;
9699         }
9700      }
9701
9702      if (gate) {
9703         IRTemp irt_regN    = newTemp(Ity_I32);
9704         IRTemp irt_regM    = newTemp(Ity_I32);
9705         IRTemp irt_prod_lo = newTemp(Ity_I32);
9706         IRTemp irt_prod_hi = newTemp(Ity_I32);
9707         IRTemp tmpM        = newTemp(Ity_I32);
9708
9709         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9710
9711         assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
9712         assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
9713
9714         assign( irt_prod_lo, 
9715                 binop( Iop_Mul32, 
9716                        binop( Iop_Sar32, 
9717                               binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)), 
9718                               mkU8(16) ), 
9719                        binop( Iop_Sar32, 
9720                               binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)), 
9721                               mkU8(16) ) ) );
9722         assign( irt_prod_hi, binop(Iop_Mul32, 
9723                                    binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)), 
9724                                    binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
9725         IRExpr* ire_result 
9726            = binop( isAD ? Iop_Add32 : Iop_Sub32,
9727                     mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) );
9728
9729         if (isT)
9730            putIRegT( regD, ire_result, condT );
9731         else
9732            putIRegA( regD, ire_result, condT, Ijk_Boring );
9733
9734         if (isAD) {
9735            or_into_QFLAG32(
9736               signed_overflow_after_Add32( ire_result,
9737                                            irt_prod_lo, irt_prod_hi ),
9738               condT
9739            );
9740         }
9741
9742         DIP("smu%cd%s%s r%u, r%u, r%u\n",
9743             isAD ? 'a' : 's',
9744             bitM ? "x" : "", nCC(conq), regD, regN, regM);
9745         return True;
9746      }
9747      /* fall through */
9748    }
9749
9750    /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
9751    /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
9752    {
9753      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
9754      Bool gate = False, isAD = False;
9755
9756      if (isT) {
9757        if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
9758            && INSNT1(7,5) == BITS3(0,0,0)) {
9759            regN = INSNT0(3,0);
9760            regD = INSNT1(11,8);
9761            regM = INSNT1(3,0);
9762            regA = INSNT1(15,12);
9763            bitM = INSNT1(4,4);
9764            isAD = INSNT0(15,4) == 0xFB2;
9765            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
9766                && !isBadRegT(regA))
9767               gate = True;
9768         }
9769      } else {
9770         if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
9771             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
9772            regD = INSNA(19,16);
9773            regA = INSNA(15,12);
9774            regN = INSNA(3,0);
9775            regM = INSNA(11,8);
9776            bitM = INSNA(5,5);
9777            isAD = INSNA(6,6) == 0;
9778            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
9779               gate = True;
9780         }
9781      }
9782
9783      if (gate) {
9784         IRTemp irt_regN    = newTemp(Ity_I32);
9785         IRTemp irt_regM    = newTemp(Ity_I32);
9786         IRTemp irt_regA    = newTemp(Ity_I32);
9787         IRTemp irt_prod_lo = newTemp(Ity_I32);
9788         IRTemp irt_prod_hi = newTemp(Ity_I32);
9789         IRTemp irt_sum     = newTemp(Ity_I32);
9790         IRTemp tmpM        = newTemp(Ity_I32);
9791
9792         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
9793         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
9794
9795         assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
9796         assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
9797
9798         assign( irt_prod_lo, 
9799                 binop(Iop_Mul32, 
9800                       binop(Iop_Sar32, 
9801                             binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ), 
9802                             mkU8(16)), 
9803                       binop(Iop_Sar32, 
9804                             binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ), 
9805                             mkU8(16))) );
9806         assign( irt_prod_hi, 
9807                 binop( Iop_Mul32, 
9808                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ), 
9809                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
9810         assign( irt_sum, binop( isAD ? Iop_Add32 : Iop_Sub32, 
9811                                 mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) );
9812
9813         IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA));
9814
9815         if (isT)
9816            putIRegT( regD, ire_result, condT );
9817         else
9818            putIRegA( regD, ire_result, condT, Ijk_Boring );
9819
9820         if (isAD) {
9821            or_into_QFLAG32(
9822               signed_overflow_after_Add32( mkexpr(irt_sum),
9823                                            irt_prod_lo, irt_prod_hi ),
9824               condT
9825            );
9826         }
9827
9828         or_into_QFLAG32(
9829            signed_overflow_after_Add32( ire_result, irt_sum, irt_regA ),
9830            condT
9831         );
9832
9833         DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n",
9834             isAD ? 'a' : 's',
9835             bitM ? "x" : "", nCC(conq), regD, regN, regM, regA);
9836         return True;
9837      }
9838      /* fall through */
9839    }
9840
9841    /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
9842    {
9843      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99;
9844      Bool gate = False;
9845
9846      if (isT) {
9847         if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
9848            regN = INSNT0(3,0);
9849            regD = INSNT1(11,8);
9850            regM = INSNT1(3,0);
9851            regA = INSNT1(15,12);
9852            bitM = INSNT1(4,4);
9853            bitN = INSNT1(5,5);
9854            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
9855                && !isBadRegT(regA))
9856               gate = True;
9857         }
9858      } else {
9859         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
9860             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
9861            regD = INSNA(19,16);
9862            regN = INSNA(3,0);
9863            regM = INSNA(11,8);
9864            regA = INSNA(15,12);
9865            bitM = INSNA(6,6);
9866            bitN = INSNA(5,5);
9867            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
9868               gate = True;
9869         }
9870      }
9871
9872      if (gate) {
9873         IRTemp irt_regA = newTemp(Ity_I32);
9874         IRTemp irt_prod = newTemp(Ity_I32);
9875
9876         assign( irt_prod, 
9877                 binop(Iop_Mul32, 
9878                       binop(Iop_Sar32, 
9879                             binop(Iop_Shl32,
9880                                   isT ? getIRegT(regN) : getIRegA(regN),
9881                                   mkU8(bitN ? 0 : 16)),
9882                             mkU8(16)), 
9883                       binop(Iop_Sar32, 
9884                             binop(Iop_Shl32,
9885                                   isT ? getIRegT(regM) : getIRegA(regM),
9886                                   mkU8(bitM ? 0 : 16)), 
9887                             mkU8(16))) );
9888
9889         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
9890
9891         IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA));
9892
9893         if (isT)
9894            putIRegT( regD, ire_result, condT );
9895         else
9896            putIRegA( regD, ire_result, condT, Ijk_Boring );
9897
9898         or_into_QFLAG32(
9899            signed_overflow_after_Add32( ire_result, irt_prod, irt_regA ),
9900            condT
9901         );
9902
9903         DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n", 
9904              bitN ? 't' : 'b', bitM ? 't' : 'b', 
9905              nCC(conq), regD, regN, regM, regA );
9906         return True;
9907      }
9908      /* fall through */
9909    }
9910
9911    /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
9912    {
9913      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
9914      Bool gate = False;
9915
9916      if (isT) {
9917         if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
9918            regN = INSNT0(3,0);
9919            regD = INSNT1(11,8);
9920            regM = INSNT1(3,0);
9921            regA = INSNT1(15,12);
9922            bitM = INSNT1(4,4);
9923            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
9924                && !isBadRegT(regA))
9925               gate = True;
9926         }
9927      } else {
9928         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
9929             (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
9930            regD = INSNA(19,16);
9931            regN = INSNA(3,0);
9932            regM = INSNA(11,8);
9933            regA = INSNA(15,12);
9934            bitM = INSNA(6,6);
9935            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
9936               gate = True;
9937         }
9938      }
9939
9940      if (gate) {
9941         IRTemp irt_regA = newTemp(Ity_I32);
9942         IRTemp irt_prod = newTemp(Ity_I64);
9943
9944         assign( irt_prod, 
9945                 binop(Iop_MullS32, 
9946                       isT ? getIRegT(regN) : getIRegA(regN),
9947                       binop(Iop_Sar32, 
9948                             binop(Iop_Shl32,
9949                                   isT ? getIRegT(regM) : getIRegA(regM),
9950                                   mkU8(bitM ? 0 : 16)), 
9951                             mkU8(16))) );
9952
9953         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
9954
9955         IRTemp prod32 = newTemp(Ity_I32);
9956         assign(prod32,
9957                binop(Iop_Or32,
9958                      binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)),
9959                      binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16))
9960         ));
9961
9962         IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA));
9963
9964         if (isT)
9965            putIRegT( regD, ire_result, condT );
9966         else
9967            putIRegA( regD, ire_result, condT, Ijk_Boring );
9968
9969         or_into_QFLAG32(
9970            signed_overflow_after_Add32( ire_result, prod32, irt_regA ),
9971            condT
9972         );
9973
9974         DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n", 
9975              bitM ? 't' : 'b', 
9976              nCC(conq), regD, regN, regM, regA );
9977         return True;
9978      }
9979      /* fall through */
9980    }
9981
9982    /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
9983    /* fixme: fix up the test in v6media.c so that we can pass the ge
9984       flags as part of the test. */
9985    {
9986      UInt regD = 99, regN = 99, regM = 99;
9987      Bool gate = False;
9988
9989      if (isT) {
9990         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
9991            regN = INSNT0(3,0);
9992            regD = INSNT1(11,8);
9993            regM = INSNT1(3,0);
9994            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
9995               gate = True;
9996         }
9997      } else {
9998         if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
9999             INSNA(11,8)  == BITS4(1,1,1,1)         &&
10000             INSNA(7,4)   == BITS4(1,0,1,1)) {
10001            regD = INSNA(15,12);
10002            regN = INSNA(19,16);
10003            regM = INSNA(3,0);
10004            if (regD != 15 && regN != 15 && regM != 15)
10005               gate = True;
10006         }
10007      }
10008
10009      if (gate) {
10010         IRTemp irt_ge_flag0 = newTemp(Ity_I32);
10011         IRTemp irt_ge_flag1 = newTemp(Ity_I32);
10012         IRTemp irt_ge_flag2 = newTemp(Ity_I32);
10013         IRTemp irt_ge_flag3 = newTemp(Ity_I32);
10014
10015         assign( irt_ge_flag0, get_GEFLAG32(0) );
10016         assign( irt_ge_flag1, get_GEFLAG32(1) );
10017         assign( irt_ge_flag2, get_GEFLAG32(2) );
10018         assign( irt_ge_flag3, get_GEFLAG32(3) );
10019
10020         IRExpr* ire_ge_flag0_or 
10021           = binop(Iop_Or32, mkexpr(irt_ge_flag0), 
10022                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0)));
10023         IRExpr* ire_ge_flag1_or 
10024           = binop(Iop_Or32, mkexpr(irt_ge_flag1), 
10025                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1)));
10026         IRExpr* ire_ge_flag2_or 
10027           = binop(Iop_Or32, mkexpr(irt_ge_flag2), 
10028                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2)));
10029         IRExpr* ire_ge_flag3_or 
10030           = binop(Iop_Or32, mkexpr(irt_ge_flag3), 
10031                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3)));
10032
10033         IRExpr* ire_ge_flags 
10034           = binop( Iop_Or32, 
10035                    binop(Iop_Or32, 
10036                          binop(Iop_And32, 
10037                                binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)), 
10038                                mkU32(0x000000ff)), 
10039                          binop(Iop_And32, 
10040                                binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)), 
10041                                mkU32(0x0000ff00))), 
10042                    binop(Iop_Or32, 
10043                          binop(Iop_And32, 
10044                                binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)), 
10045                                mkU32(0x00ff0000)), 
10046                          binop(Iop_And32, 
10047                                binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)), 
10048                                mkU32(0xff000000))) );
10049
10050         IRExpr* ire_result 
10051           = binop(Iop_Or32, 
10052                   binop(Iop_And32,
10053                         isT ? getIRegT(regN) : getIRegA(regN),
10054                         ire_ge_flags ), 
10055                   binop(Iop_And32,
10056                         isT ? getIRegT(regM) : getIRegA(regM),
10057                         unop(Iop_Not32, ire_ge_flags)));
10058
10059         if (isT)
10060            putIRegT( regD, ire_result, condT );
10061         else
10062            putIRegA( regD, ire_result, condT, Ijk_Boring );
10063
10064         DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
10065         return True;
10066      }
10067      /* fall through */
10068    }
10069
10070    /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
10071    {
10072      UInt regD = 99, regN = 99, regM = 99, rotate = 99;
10073      Bool gate = False;
10074
10075      if (isT) {
10076         if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
10077            regN   = INSNT0(3,0);
10078            regD   = INSNT1(11,8);
10079            regM   = INSNT1(3,0);
10080            rotate = INSNT1(5,4);
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,1,0,0) &&
10086             INSNA(9,4)   == BITS6(0,0,0,1,1,1) ) {
10087            regD   = INSNA(15,12);
10088            regN   = INSNA(19,16);
10089            regM   = INSNA(3,0);
10090            rotate = INSNA(11,10);
10091            if (regD != 15 && regN != 15 && regM != 15)
10092              gate = True;
10093         }
10094      }
10095
10096      if (gate) {
10097         IRTemp irt_regN = newTemp(Ity_I32);
10098         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
10099
10100         IRTemp irt_regM = newTemp(Ity_I32);
10101         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
10102
10103         IRTemp irt_rot = newTemp(Ity_I32);
10104         assign( irt_rot, binop(Iop_And32,
10105                                genROR32(irt_regM, 8 * rotate),
10106                                mkU32(0x00FF00FF)) );
10107
10108         IRExpr* resLo
10109            = binop(Iop_And32,
10110                    binop(Iop_Add32, mkexpr(irt_regN), mkexpr(irt_rot)),
10111                    mkU32(0x0000FFFF));
10112
10113         IRExpr* resHi
10114            = binop(Iop_Add32, 
10115                    binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF0000)),
10116                    binop(Iop_And32, mkexpr(irt_rot),  mkU32(0xFFFF0000)));
10117
10118         IRExpr* ire_result 
10119            = binop( Iop_Or32, resHi, resLo );
10120
10121         if (isT)
10122            putIRegT( regD, ire_result, condT );
10123         else
10124            putIRegA( regD, ire_result, condT, Ijk_Boring );
10125
10126         DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n", 
10127              nCC(conq), regD, regN, regM, 8 * rotate );
10128         return True;
10129      }
10130      /* fall through */
10131    }
10132
10133    /* --------------- usad8  Rd,Rn,Rm    ---------------- */
10134    /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */
10135    {
10136      UInt rD = 99, rN = 99, rM = 99, rA = 99;
10137      Bool gate = False;
10138
10139      if (isT) {
10140        if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) {
10141            rN = INSNT0(3,0);
10142            rA = INSNT1(15,12);
10143            rD = INSNT1(11,8);
10144            rM = INSNT1(3,0);
10145            if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && rA != 13)
10146               gate = True;
10147         }
10148      } else {
10149         if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) &&
10150             INSNA(7,4)   == BITS4(0,0,0,1) ) {
10151            rD = INSNA(19,16);
10152            rA = INSNA(15,12);
10153            rM = INSNA(11,8);
10154            rN = INSNA(3,0);
10155            if (rD != 15 && rN != 15 && rM != 15 /* but rA can be 15 */)
10156               gate = True;
10157         }
10158      }
10159      /* We allow rA == 15, to denote the usad8 (no accumulator) case. */
10160
10161      if (gate) {
10162         IRExpr* rNe = isT ? getIRegT(rN) : getIRegA(rN);
10163         IRExpr* rMe = isT ? getIRegT(rM) : getIRegA(rM);
10164         IRExpr* rAe = rA == 15 ? mkU32(0)
10165                                : (isT ? getIRegT(rA) : getIRegA(rA)); 
10166         IRExpr* res = binop(Iop_Add32,
10167                             binop(Iop_Sad8Ux4, rNe, rMe),
10168                             rAe);
10169         if (isT)
10170            putIRegT( rD, res, condT );
10171         else
10172            putIRegA( rD, res, condT, Ijk_Boring );
10173
10174         if (rA == 15) {
10175            DIP( "usad8%s r%u, r%u, r%u\n", 
10176                 nCC(conq), rD, rN, rM );
10177         } else {
10178            DIP( "usada8%s r%u, r%u, r%u, r%u\n", 
10179                 nCC(conq), rD, rN, rM, rA );
10180         }
10181         return True;
10182      }
10183      /* fall through */
10184    }
10185
10186    /* ---------- Doesn't match anything. ---------- */
10187    return False;
10188
10189 #  undef INSNA
10190 #  undef INSNT0
10191 #  undef INSNT1
10192 }
10193
10194
10195 /*------------------------------------------------------------*/
10196 /*--- LDMxx/STMxx helper (both ARM and Thumb32)            ---*/
10197 /*------------------------------------------------------------*/
10198
10199 /* Generate IR for LDMxx and STMxx.  This is complex.  Assumes it's
10200    unconditional, so the caller must produce a jump-around before
10201    calling this, if the insn is to be conditional.  Caller is
10202    responsible for all validation of parameters.  For LDMxx, if PC is
10203    amongst the values loaded, caller is also responsible for
10204    generating the jump. */
10205 static void mk_ldm_stm ( Bool arm,     /* True: ARM, False: Thumb */
10206                          UInt rN,      /* base reg */
10207                          UInt bINC,    /* 1: inc,  0: dec */
10208                          UInt bBEFORE, /* 1: inc/dec before, 0: after */
10209                          UInt bW,      /* 1: writeback to Rn */
10210                          UInt bL,      /* 1: load, 0: store */
10211                          UInt regList )
10212 {
10213    Int i, r, m, nRegs;
10214
10215    /* Get hold of the old Rn value.  We might need to write its value
10216       to memory during a store, and if it's also the writeback
10217       register then we need to get its value now.  We can't treat it
10218       exactly like the other registers we're going to transfer,
10219       because for xxMDA and xxMDB writeback forms, the generated IR
10220       updates Rn in the guest state before any transfers take place.
10221       We have to do this as per comments below, in order that if Rn is
10222       the stack pointer then it always has a value is below or equal
10223       to any of the transfer addresses.  Ick. */
10224    IRTemp oldRnT = newTemp(Ity_I32);
10225    assign(oldRnT, arm ? getIRegA(rN) : getIRegT(rN));
10226
10227    IRTemp anchorT = newTemp(Ity_I32);
10228    /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx
10229       ignore the bottom two bits of the address.  However, Cortex-A8
10230       doesn't seem to care.  Hence: */
10231    /* No .. don't force alignment .. */
10232    /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */
10233    /* Instead, use the potentially misaligned address directly. */
10234    assign(anchorT, mkexpr(oldRnT));
10235
10236    IROp opADDorSUB = bINC ? Iop_Add32 : Iop_Sub32;
10237    // bINC == 1:  xxMIA, xxMIB
10238    // bINC == 0:  xxMDA, xxMDB
10239
10240    // For xxMDA and xxMDB, update Rn first if necessary.  We have
10241    // to do this first so that, for the common idiom of the transfers
10242    // faulting because we're pushing stuff onto a stack and the stack
10243    // is growing down onto allocate-on-fault pages (as Valgrind simulates),
10244    // we need to have the SP up-to-date "covering" (pointing below) the
10245    // transfer area.  For the same reason, if we are doing xxMIA or xxMIB,
10246    // do the transfer first, and then update rN afterwards.
10247    nRegs = 0;
10248    for (i = 0; i < 16; i++) {
10249      if ((regList & (1 << i)) != 0)
10250          nRegs++;
10251    }
10252    if (bW == 1 && !bINC) {
10253       IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
10254       if (arm)
10255          putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
10256       else
10257          putIRegT( rN, e, IRTemp_INVALID );
10258    }
10259
10260    // Make up a list of the registers to transfer, and their offsets
10261    // in memory relative to the anchor.  If the base reg (Rn) is part
10262    // of the transfer, then do it last for a load and first for a store.
10263    UInt xReg[16], xOff[16];
10264    Int  nX = 0;
10265    m = 0;
10266    for (i = 0; i < 16; i++) {
10267       r = bINC ? i : (15-i);
10268       if (0 == (regList & (1<<r)))
10269          continue;
10270       if (bBEFORE)
10271          m++;
10272       /* paranoia: check we aren't transferring the writeback
10273          register during a load. Should be assured by decode-point
10274          check above. */
10275       if (bW == 1 && bL == 1)
10276          vassert(r != rN);
10277
10278       xOff[nX] = 4 * m;
10279       xReg[nX] = r;
10280       nX++;
10281
10282       if (!bBEFORE)
10283          m++;
10284    }
10285    vassert(m == nRegs);
10286    vassert(nX == nRegs);
10287    vassert(nX <= 16);
10288
10289    if (bW == 0 && (regList & (1<<rN)) != 0) {
10290       /* Non-writeback, and basereg is to be transferred.  Do its
10291          transfer last for a load and first for a store.  Requires
10292          reordering xOff/xReg. */
10293       if (0) {
10294          vex_printf("\nREG_LIST_PRE: (rN=%d)\n", rN);
10295          for (i = 0; i < nX; i++)
10296             vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
10297          vex_printf("\n");
10298       }
10299
10300       vassert(nX > 0);
10301       for (i = 0; i < nX; i++) {
10302          if (xReg[i] == rN)
10303              break;
10304       }
10305       vassert(i < nX); /* else we didn't find it! */
10306       UInt tReg = xReg[i];
10307       UInt tOff = xOff[i];
10308       if (bL == 1) {
10309          /* load; make this transfer happen last */
10310          if (i < nX-1) {
10311             for (m = i+1; m < nX; m++) {
10312                xReg[m-1] = xReg[m];
10313                xOff[m-1] = xOff[m];
10314             }
10315             vassert(m == nX);
10316             xReg[m-1] = tReg;
10317             xOff[m-1] = tOff;
10318          }
10319       } else {
10320          /* store; make this transfer happen first */
10321          if (i > 0) {
10322             for (m = i-1; m >= 0; m--) {
10323                xReg[m+1] = xReg[m];
10324                xOff[m+1] = xOff[m];
10325             }
10326             vassert(m == -1);
10327             xReg[0] = tReg;
10328             xOff[0] = tOff;
10329          }
10330       }
10331
10332       if (0) {
10333          vex_printf("REG_LIST_POST:\n");
10334          for (i = 0; i < nX; i++)
10335             vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
10336          vex_printf("\n");
10337       }
10338    }
10339
10340    /* Actually generate the transfers */
10341    for (i = 0; i < nX; i++) {
10342       r = xReg[i];
10343       if (bL == 1) {
10344          IRExpr* e = loadLE(Ity_I32,
10345                             binop(opADDorSUB, mkexpr(anchorT),
10346                                   mkU32(xOff[i])));
10347          if (arm) {
10348             putIRegA( r, e, IRTemp_INVALID, Ijk_Ret );
10349          } else {
10350             // no: putIRegT( r, e, IRTemp_INVALID );
10351             // putIRegT refuses to write to R15.  But that might happen.
10352             // Since this is uncond, and we need to be able to
10353             // write the PC, just use the low level put:
10354             llPutIReg( r, e );
10355          }
10356       } else {
10357          /* if we're storing Rn, make sure we use the correct
10358             value, as per extensive comments above */
10359          storeLE( binop(opADDorSUB, mkexpr(anchorT), mkU32(xOff[i])),
10360                   r == rN ? mkexpr(oldRnT) 
10361                           : (arm ? getIRegA(r) : getIRegT(r) ) );
10362       }
10363    }
10364
10365    // If we are doing xxMIA or xxMIB,
10366    // do the transfer first, and then update rN afterwards.
10367    if (bW == 1 && bINC) {
10368       IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
10369       if (arm)
10370          putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
10371       else
10372          putIRegT( rN, e, IRTemp_INVALID );
10373    }
10374 }
10375
10376
10377 /*------------------------------------------------------------*/
10378 /*--- VFP (CP 10 and 11) instructions                      ---*/
10379 /*------------------------------------------------------------*/
10380
10381 /* Both ARM and Thumb */
10382
10383 /* Translate a CP10 or CP11 instruction.  If successful, returns
10384    True and *dres may or may not be updated.  If failure, returns
10385    False and doesn't change *dres nor create any IR.
10386
10387    The ARM and Thumb encodings are identical for the low 28 bits of
10388    the insn (yay!) and that's what the caller must supply, iow, imm28
10389    has the top 4 bits masked out.  Caller is responsible for
10390    determining whether the masked-out bits are valid for a CP10/11
10391    insn.  The rules for the top 4 bits are:
10392
10393      ARM: 0000 to 1110 allowed, and this is the gating condition.
10394      1111 (NV) is not allowed.
10395
10396      Thumb: must be 1110.  The gating condition is taken from
10397      ITSTATE in the normal way.
10398
10399    Conditionalisation:
10400
10401    Caller must supply an IRTemp 'condT' holding the gating condition,
10402    or IRTemp_INVALID indicating the insn is always executed.
10403
10404    Caller must also supply an ARMCondcode 'cond'.  This is only used
10405    for debug printing, no other purpose.  For ARM, this is simply the
10406    top 4 bits of the original instruction.  For Thumb, the condition
10407    is not (really) known until run time, and so ARMCondAL should be
10408    passed, only so that printing of these instructions does not show
10409    any condition.
10410
10411    Finally, the caller must indicate whether this occurs in ARM or
10412    Thumb code.
10413 */
10414 static Bool decode_CP10_CP11_instruction (
10415                /*MOD*/DisResult* dres,
10416                UInt              insn28,
10417                IRTemp            condT,
10418                ARMCondcode       conq,
10419                Bool              isT
10420             )
10421 {
10422 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn28, (_bMax), (_bMin))
10423
10424    vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation
10425
10426    if (isT) {
10427       vassert(conq == ARMCondAL);
10428    } else {
10429       vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
10430    }
10431
10432    /* ----------------------------------------------------------- */
10433    /* -- VFP instructions -- double precision (mostly)         -- */
10434    /* ----------------------------------------------------------- */
10435
10436    /* --------------------- fldmx, fstmx --------------------- */
10437    /*
10438                                  31   27   23   19 15 11   7   0
10439                                          P U WL
10440       C4-100, C5-26  1  FSTMX    cond 1100 1000 Rn Dd 1011 offset
10441       C4-100, C5-28  2  FSTMIAX  cond 1100 1010 Rn Dd 1011 offset
10442       C4-100, C5-30  3  FSTMDBX  cond 1101 0010 Rn Dd 1011 offset
10443
10444       C4-42, C5-26   1  FLDMX    cond 1100 1001 Rn Dd 1011 offset
10445       C4-42, C5-28   2  FLDMIAX  cond 1100 1011 Rn Dd 1011 offset
10446       C4-42, C5-30   3  FLDMDBX  cond 1101 0011 Rn Dd 1011 offset
10447
10448       Regs transferred: Dd .. D(d + (offset-3)/2)
10449       offset must be odd, must not imply a reg > 15
10450       IA/DB: Rn is changed by (4 + 8 x # regs transferred)
10451
10452       case coding:
10453          1  at-Rn   (access at Rn)
10454          2  ia-Rn   (access at Rn, then Rn += 4+8n)
10455          3  db-Rn   (Rn -= 4+8n,   then access at Rn)
10456    */
10457    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
10458        && INSN(11,8) == BITS4(1,0,1,1)) {
10459       UInt bP      = (insn28 >> 24) & 1;
10460       UInt bU      = (insn28 >> 23) & 1;
10461       UInt bW      = (insn28 >> 21) & 1;
10462       UInt bL      = (insn28 >> 20) & 1;
10463       UInt offset  = (insn28 >> 0) & 0xFF;
10464       UInt rN      = INSN(19,16);
10465       UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
10466       UInt nRegs   = (offset - 1) / 2;
10467       UInt summary = 0;
10468       Int  i;
10469
10470       /**/ if (bP == 0 && bU == 1 && bW == 0) {
10471          summary = 1;
10472       }
10473       else if (bP == 0 && bU == 1 && bW == 1) {
10474          summary = 2;
10475       }
10476       else if (bP == 1 && bU == 0 && bW == 1) {
10477          summary = 3;
10478       }
10479       else goto after_vfp_fldmx_fstmx;
10480
10481       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
10482       if (rN == 15 && (summary == 2 || summary == 3 || isT))
10483          goto after_vfp_fldmx_fstmx;
10484
10485       /* offset must be odd, and specify at least one register */
10486       if (0 == (offset & 1) || offset < 3)
10487          goto after_vfp_fldmx_fstmx;
10488
10489       /* can't transfer regs after D15 */
10490       if (dD + nRegs - 1 >= 32)
10491          goto after_vfp_fldmx_fstmx;
10492
10493       /* Now, we can't do a conditional load or store, since that very
10494          likely will generate an exception.  So we have to take a side
10495          exit at this point if the condition is false. */
10496       if (condT != IRTemp_INVALID) {
10497          if (isT)
10498             mk_skip_over_T32_if_cond_is_false( condT );
10499          else
10500             mk_skip_over_A32_if_cond_is_false( condT );
10501          condT = IRTemp_INVALID;
10502       }
10503       /* Ok, now we're unconditional.  Do the load or store. */
10504
10505       /* get the old Rn value */
10506       IRTemp rnT = newTemp(Ity_I32);
10507       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
10508                            rN == 15));
10509
10510       /* make a new value for Rn, post-insn */
10511       IRTemp rnTnew = IRTemp_INVALID;
10512       if (summary == 2 || summary == 3) {
10513          rnTnew = newTemp(Ity_I32);
10514          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
10515                               mkexpr(rnT),
10516                               mkU32(4 + 8 * nRegs)));
10517       }
10518
10519       /* decide on the base transfer address */
10520       IRTemp taT = newTemp(Ity_I32);
10521       assign(taT,  summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
10522
10523       /* update Rn if necessary -- in case 3, we're moving it down, so
10524          update before any memory reference, in order to keep Memcheck
10525          and V's stack-extending logic (on linux) happy */
10526       if (summary == 3) {
10527          if (isT)
10528             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
10529          else
10530             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
10531       }
10532
10533       /* generate the transfers */
10534       for (i = 0; i < nRegs; i++) {
10535          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
10536          if (bL) {
10537             putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
10538          } else {
10539             storeLE(addr, getDReg(dD + i));
10540          }
10541       }
10542
10543       /* update Rn if necessary -- in case 2, we're moving it up, so
10544          update after any memory reference, in order to keep Memcheck
10545          and V's stack-extending logic (on linux) happy */
10546       if (summary == 2) {
10547          if (isT)
10548             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
10549          else
10550             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
10551       }
10552
10553       HChar* nm = bL==1 ? "ld" : "st";
10554       switch (summary) {
10555          case 1:  DIP("f%smx%s r%u, {d%u-d%u}\n", 
10556                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
10557                   break;
10558          case 2:  DIP("f%smiax%s r%u!, {d%u-d%u}\n", 
10559                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
10560                   break;
10561          case 3:  DIP("f%smdbx%s r%u!, {d%u-d%u}\n", 
10562                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
10563                   break;
10564          default: vassert(0);
10565       }
10566
10567       goto decode_success_vfp;
10568       /* FIXME alignment constraints? */
10569    }
10570
10571   after_vfp_fldmx_fstmx:
10572
10573    /* --------------------- fldmd, fstmd --------------------- */
10574    /*
10575                                  31   27   23   19 15 11   7   0
10576                                          P U WL
10577       C4-96, C5-26   1  FSTMD    cond 1100 1000 Rn Dd 1011 offset
10578       C4-96, C5-28   2  FSTMDIA  cond 1100 1010 Rn Dd 1011 offset
10579       C4-96, C5-30   3  FSTMDDB  cond 1101 0010 Rn Dd 1011 offset
10580
10581       C4-38, C5-26   1  FLDMD    cond 1100 1001 Rn Dd 1011 offset
10582       C4-38, C5-28   2  FLDMIAD  cond 1100 1011 Rn Dd 1011 offset
10583       C4-38, C5-30   3  FLDMDBD  cond 1101 0011 Rn Dd 1011 offset
10584
10585       Regs transferred: Dd .. D(d + (offset-2)/2)
10586       offset must be even, must not imply a reg > 15
10587       IA/DB: Rn is changed by (8 x # regs transferred)
10588
10589       case coding:
10590          1  at-Rn   (access at Rn)
10591          2  ia-Rn   (access at Rn, then Rn += 8n)
10592          3  db-Rn   (Rn -= 8n,     then access at Rn)
10593    */
10594    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
10595        && INSN(11,8) == BITS4(1,0,1,1)) {
10596       UInt bP      = (insn28 >> 24) & 1;
10597       UInt bU      = (insn28 >> 23) & 1;
10598       UInt bW      = (insn28 >> 21) & 1;
10599       UInt bL      = (insn28 >> 20) & 1;
10600       UInt offset  = (insn28 >> 0) & 0xFF;
10601       UInt rN      = INSN(19,16);
10602       UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
10603       UInt nRegs   = offset / 2;
10604       UInt summary = 0;
10605       Int  i;
10606
10607       /**/ if (bP == 0 && bU == 1 && bW == 0) {
10608          summary = 1;
10609       }
10610       else if (bP == 0 && bU == 1 && bW == 1) {
10611          summary = 2;
10612       }
10613       else if (bP == 1 && bU == 0 && bW == 1) {
10614          summary = 3;
10615       }
10616       else goto after_vfp_fldmd_fstmd;
10617
10618       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
10619       if (rN == 15 && (summary == 2 || summary == 3 || isT))
10620          goto after_vfp_fldmd_fstmd;
10621
10622       /* offset must be even, and specify at least one register */
10623       if (1 == (offset & 1) || offset < 2)
10624          goto after_vfp_fldmd_fstmd;
10625
10626       /* can't transfer regs after D15 */
10627       if (dD + nRegs - 1 >= 32)
10628          goto after_vfp_fldmd_fstmd;
10629
10630       /* Now, we can't do a conditional load or store, since that very
10631          likely will generate an exception.  So we have to take a side
10632          exit at this point if the condition is false. */
10633       if (condT != IRTemp_INVALID) {
10634          if (isT)
10635             mk_skip_over_T32_if_cond_is_false( condT );
10636          else
10637             mk_skip_over_A32_if_cond_is_false( condT );
10638          condT = IRTemp_INVALID;
10639       }
10640       /* Ok, now we're unconditional.  Do the load or store. */
10641
10642       /* get the old Rn value */
10643       IRTemp rnT = newTemp(Ity_I32);
10644       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
10645                            rN == 15));
10646
10647       /* make a new value for Rn, post-insn */
10648       IRTemp rnTnew = IRTemp_INVALID;
10649       if (summary == 2 || summary == 3) {
10650          rnTnew = newTemp(Ity_I32);
10651          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
10652                               mkexpr(rnT),
10653                               mkU32(8 * nRegs)));
10654       }
10655
10656       /* decide on the base transfer address */
10657       IRTemp taT = newTemp(Ity_I32);
10658       assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
10659
10660       /* update Rn if necessary -- in case 3, we're moving it down, so
10661          update before any memory reference, in order to keep Memcheck
10662          and V's stack-extending logic (on linux) happy */
10663       if (summary == 3) {
10664          if (isT)
10665             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
10666          else
10667             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
10668       }
10669
10670       /* generate the transfers */
10671       for (i = 0; i < nRegs; i++) {
10672          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
10673          if (bL) {
10674             putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
10675          } else {
10676             storeLE(addr, getDReg(dD + i));
10677          }
10678       }
10679
10680       /* update Rn if necessary -- in case 2, we're moving it up, so
10681          update after any memory reference, in order to keep Memcheck
10682          and V's stack-extending logic (on linux) happy */
10683       if (summary == 2) {
10684          if (isT)
10685             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
10686          else
10687             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
10688       }
10689
10690       HChar* nm = bL==1 ? "ld" : "st";
10691       switch (summary) {
10692          case 1:  DIP("f%smd%s r%u, {d%u-d%u}\n", 
10693                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
10694                   break;
10695          case 2:  DIP("f%smiad%s r%u!, {d%u-d%u}\n", 
10696                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
10697                   break;
10698          case 3:  DIP("f%smdbd%s r%u!, {d%u-d%u}\n", 
10699                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
10700                   break;
10701          default: vassert(0);
10702       }
10703
10704       goto decode_success_vfp;
10705       /* FIXME alignment constraints? */
10706    }
10707
10708   after_vfp_fldmd_fstmd:
10709
10710    /* ------------------- fmrx, fmxr ------------------- */
10711    if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20)
10712        && BITS4(1,0,1,0) == INSN(11,8)
10713        && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
10714       UInt rD  = INSN(15,12);
10715       UInt reg = INSN(19,16);
10716       if (reg == BITS4(0,0,0,1)) {
10717          if (rD == 15) {
10718             IRTemp nzcvT = newTemp(Ity_I32);
10719             /* When rD is 15, we are copying the top 4 bits of FPSCR
10720                into CPSR.  That is, set the flags thunk to COPY and
10721                install FPSCR[31:28] as the value to copy. */
10722             assign(nzcvT, binop(Iop_And32,
10723                                 IRExpr_Get(OFFB_FPSCR, Ity_I32),
10724                                 mkU32(0xF0000000)));
10725             setFlags_D1(ARMG_CC_OP_COPY, nzcvT, condT);
10726             DIP("fmstat%s\n", nCC(conq));
10727          } else {
10728             /* Otherwise, merely transfer FPSCR to r0 .. r14. */
10729             IRExpr* e = IRExpr_Get(OFFB_FPSCR, Ity_I32);
10730             if (isT)
10731                putIRegT(rD, e, condT);
10732             else
10733                putIRegA(rD, e, condT, Ijk_Boring);
10734             DIP("fmrx%s r%u, fpscr\n", nCC(conq), rD);
10735          }
10736          goto decode_success_vfp;
10737       }
10738       /* fall through */
10739    }
10740
10741    if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20)
10742        && BITS4(1,0,1,0) == INSN(11,8)
10743        && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
10744       UInt rD  = INSN(15,12);
10745       UInt reg = INSN(19,16);
10746       if (reg == BITS4(0,0,0,1)) {
10747          putMiscReg32(OFFB_FPSCR,
10748                       isT ? getIRegT(rD) : getIRegA(rD), condT);
10749          DIP("fmxr%s fpscr, r%u\n", nCC(conq), rD);
10750          goto decode_success_vfp;
10751       }
10752       /* fall through */
10753    }
10754
10755    /* --------------------- vmov --------------------- */
10756    // VMOV dM, rD, rN
10757    if (0x0C400B10 == (insn28 & 0x0FF00FD0)) {
10758       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
10759       UInt rD = INSN(15,12); /* lo32 */
10760       UInt rN = INSN(19,16); /* hi32 */
10761       if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))) {
10762          /* fall through */
10763       } else {
10764          putDReg(dM,
10765                  unop(Iop_ReinterpI64asF64,
10766                       binop(Iop_32HLto64,
10767                             isT ? getIRegT(rN) : getIRegA(rN),
10768                             isT ? getIRegT(rD) : getIRegA(rD))),
10769                  condT);
10770          DIP("vmov%s d%u, r%u, r%u\n", nCC(conq), dM, rD, rN);
10771          goto decode_success_vfp;
10772       }
10773       /* fall through */
10774    }
10775
10776    // VMOV rD, rN, dM
10777    if (0x0C500B10 == (insn28 & 0x0FF00FD0)) {
10778       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
10779       UInt rD = INSN(15,12); /* lo32 */
10780       UInt rN = INSN(19,16); /* hi32 */
10781       if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))
10782           || rD == rN) {
10783          /* fall through */
10784       } else {
10785          IRTemp i64 = newTemp(Ity_I64);
10786          assign(i64, unop(Iop_ReinterpF64asI64, getDReg(dM)));
10787          IRExpr* hi32 = unop(Iop_64HIto32, mkexpr(i64));
10788          IRExpr* lo32 = unop(Iop_64to32,   mkexpr(i64));
10789          if (isT) {
10790             putIRegT(rN, hi32, condT);
10791             putIRegT(rD, lo32, condT);
10792          } else {
10793             putIRegA(rN, hi32, condT, Ijk_Boring);
10794             putIRegA(rD, lo32, condT, Ijk_Boring);
10795          }
10796          DIP("vmov%s r%u, r%u, d%u\n", nCC(conq), rD, rN, dM);
10797          goto decode_success_vfp;
10798       }
10799       /* fall through */
10800    }
10801
10802    // VMOV sD, sD+1, rN, rM
10803    if (0x0C400A10 == (insn28 & 0x0FF00FD0)) {
10804       UInt sD = (INSN(3,0) << 1) | INSN(5,5);
10805       UInt rN = INSN(15,12);
10806       UInt rM = INSN(19,16);
10807       if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
10808           || sD == 31) {
10809          /* fall through */
10810       } else {
10811          putFReg(sD,
10812                  unop(Iop_ReinterpI32asF32, isT ? getIRegT(rN) : getIRegA(rN)),
10813                  condT);
10814          putFReg(sD+1,
10815                  unop(Iop_ReinterpI32asF32, isT ? getIRegT(rM) : getIRegA(rM)),
10816                  condT);
10817          DIP("vmov%s, s%u, s%u, r%u, r%u\n",
10818               nCC(conq), sD, sD + 1, rN, rM);
10819          goto decode_success_vfp;
10820       }
10821    }
10822
10823    // VMOV rN, rM, sD, sD+1
10824    if (0x0C500A10 == (insn28 & 0x0FF00FD0)) {
10825       UInt sD = (INSN(3,0) << 1) | INSN(5,5);
10826       UInt rN = INSN(15,12);
10827       UInt rM = INSN(19,16);
10828       if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
10829           || sD == 31 || rN == rM) {
10830          /* fall through */
10831       } else {
10832          IRExpr* res0 = unop(Iop_ReinterpF32asI32, getFReg(sD));
10833          IRExpr* res1 = unop(Iop_ReinterpF32asI32, getFReg(sD+1));
10834          if (isT) {
10835             putIRegT(rN, res0, condT);
10836             putIRegT(rM, res1, condT);
10837          } else {
10838             putIRegA(rN, res0, condT, Ijk_Boring);
10839             putIRegA(rM, res1, condT, Ijk_Boring);
10840          }
10841          DIP("vmov%s, r%u, r%u, s%u, s%u\n",
10842              nCC(conq), rN, rM, sD, sD + 1);
10843          goto decode_success_vfp;
10844       }
10845    }
10846
10847    // VMOV rD[x], rT  (ARM core register to scalar)
10848    if (0x0E000B10 == (insn28 & 0x0F900F1F)) {
10849       UInt rD  = (INSN(7,7) << 4) | INSN(19,16);
10850       UInt rT  = INSN(15,12);
10851       UInt opc = (INSN(22,21) << 2) | INSN(6,5);
10852       UInt index;
10853       if (rT == 15 || (isT && rT == 13)) {
10854          /* fall through */
10855       } else {
10856          if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
10857             index = opc & 7;
10858             putDRegI64(rD, triop(Iop_SetElem8x8,
10859                                  getDRegI64(rD),
10860                                  mkU8(index),
10861                                  unop(Iop_32to8,
10862                                       isT ? getIRegT(rT) : getIRegA(rT))),
10863                            condT);
10864             DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
10865             goto decode_success_vfp;
10866          }
10867          else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
10868             index = (opc >> 1) & 3;
10869             putDRegI64(rD, triop(Iop_SetElem16x4,
10870                                  getDRegI64(rD),
10871                                  mkU8(index),
10872                                  unop(Iop_32to16,
10873                                       isT ? getIRegT(rT) : getIRegA(rT))),
10874                            condT);
10875             DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
10876             goto decode_success_vfp;
10877          }
10878          else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0)) {
10879             index = (opc >> 2) & 1;
10880             putDRegI64(rD, triop(Iop_SetElem32x2,
10881                                  getDRegI64(rD),
10882                                  mkU8(index),
10883                                  isT ? getIRegT(rT) : getIRegA(rT)),
10884                            condT);
10885             DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
10886             goto decode_success_vfp;
10887          } else {
10888             /* fall through */
10889          }
10890       }
10891    }
10892
10893    // VMOV (scalar to ARM core register)
10894    // VMOV rT, rD[x]
10895    if (0x0E100B10 == (insn28 & 0x0F100F1F)) {
10896       UInt rN  = (INSN(7,7) << 4) | INSN(19,16);
10897       UInt rT  = INSN(15,12);
10898       UInt U   = INSN(23,23);
10899       UInt opc = (INSN(22,21) << 2) | INSN(6,5);
10900       UInt index;
10901       if (rT == 15 || (isT && rT == 13)) {
10902          /* fall through */
10903       } else {
10904          if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
10905             index = opc & 7;
10906             IRExpr* e = unop(U ? Iop_8Uto32 : Iop_8Sto32,
10907                              binop(Iop_GetElem8x8,
10908                                    getDRegI64(rN),
10909                                    mkU8(index)));
10910             if (isT)
10911                putIRegT(rT, e, condT);
10912             else
10913                putIRegA(rT, e, condT, Ijk_Boring);
10914             DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
10915                   rT, rN, index);
10916             goto decode_success_vfp;
10917          }
10918          else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
10919             index = (opc >> 1) & 3;
10920             IRExpr* e = unop(U ? Iop_16Uto32 : Iop_16Sto32,
10921                              binop(Iop_GetElem16x4,
10922                                    getDRegI64(rN),
10923                                    mkU8(index)));
10924             if (isT)
10925                putIRegT(rT, e, condT);
10926             else
10927                putIRegA(rT, e, condT, Ijk_Boring);
10928             DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
10929                   rT, rN, index);
10930             goto decode_success_vfp;
10931          }
10932          else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U == 0) {
10933             index = (opc >> 2) & 1;
10934             IRExpr* e = binop(Iop_GetElem32x2, getDRegI64(rN), mkU8(index));
10935             if (isT)
10936                putIRegT(rT, e, condT);
10937             else
10938                putIRegA(rT, e, condT, Ijk_Boring);
10939             DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq), rT, rN, index);
10940             goto decode_success_vfp;
10941          } else {
10942             /* fall through */
10943          }
10944       }
10945    }
10946
10947    // VMOV.F32 sD, #imm
10948    // FCONSTS sD, #imm
10949    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
10950        && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) {
10951       UInt rD   = (INSN(15,12) << 1) | INSN(22,22);
10952       UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
10953       UInt b    = (imm8 >> 6) & 1;
10954       UInt imm;
10955       imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,(imm8 >> 5) & 1) << 8)
10956              | ((imm8 & 0x1f) << 3);
10957       imm <<= 16;
10958       putFReg(rD, unop(Iop_ReinterpI32asF32, mkU32(imm)), condT);
10959       DIP("fconsts%s s%u #%u", nCC(conq), rD, imm8);
10960       goto decode_success_vfp;
10961    }
10962
10963    // VMOV.F64 dD, #imm
10964    // FCONSTD dD, #imm
10965    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
10966        && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) {
10967       UInt rD   = INSN(15,12) | (INSN(22,22) << 4);
10968       UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
10969       UInt b    = (imm8 >> 6) & 1;
10970       ULong imm;
10971       imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,b) << 8)
10972              | BITS8(b,b,0,0,0,0,0,0) | (imm8 & 0x3f);
10973       imm <<= 48;
10974       putDReg(rD, unop(Iop_ReinterpI64asF64, mkU64(imm)), condT);
10975       DIP("fconstd%s d%u #%u", nCC(conq), rD, imm8);
10976       goto decode_success_vfp;
10977    }
10978
10979    /* ---------------------- vdup ------------------------- */
10980    // VDUP dD, rT
10981    // VDUP qD, rT
10982    if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1))
10983        && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) {
10984       UInt rD   = (INSN(7,7) << 4) | INSN(19,16);
10985       UInt rT   = INSN(15,12);
10986       UInt Q    = INSN(21,21);
10987       UInt size = (INSN(22,22) << 1) | INSN(5,5);
10988       if (rT == 15 || (isT && rT == 13) || size == 3 || (Q && (rD & 1))) {
10989          /* fall through */
10990       } else {
10991          IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT);
10992          if (Q) {
10993             rD >>= 1;
10994             switch (size) {
10995                case 0:
10996                   putQReg(rD, unop(Iop_Dup32x4, e), condT);
10997                   break;
10998                case 1:
10999                   putQReg(rD, unop(Iop_Dup16x8, unop(Iop_32to16, e)),
11000                               condT);
11001                   break;
11002                case 2:
11003                   putQReg(rD, unop(Iop_Dup8x16, unop(Iop_32to8, e)),
11004                               condT);
11005                   break;
11006                default:
11007                   vassert(0);
11008             }
11009             DIP("vdup.%u q%u, r%u\n", 32 / (1<<size), rD, rT);
11010          } else {
11011             switch (size) {
11012                case 0:
11013                   putDRegI64(rD, unop(Iop_Dup32x2, e), condT);
11014                   break;
11015                case 1:
11016                   putDRegI64(rD, unop(Iop_Dup16x4, unop(Iop_32to16, e)),
11017                                condT);
11018                   break;
11019                case 2:
11020                   putDRegI64(rD, unop(Iop_Dup8x8, unop(Iop_32to8, e)),
11021                                condT);
11022                   break;
11023                default:
11024                   vassert(0);
11025             }
11026             DIP("vdup.%u d%u, r%u\n", 32 / (1<<size), rD, rT);
11027          }
11028          goto decode_success_vfp;
11029       }
11030    }
11031
11032    /* --------------------- f{ld,st}d --------------------- */
11033    // FLDD, FSTD
11034    if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
11035        && BITS4(1,0,1,1) == INSN(11,8)) {
11036       UInt dD     = INSN(15,12) | (INSN(22,22) << 4);
11037       UInt rN     = INSN(19,16);
11038       UInt offset = (insn28 & 0xFF) << 2;
11039       UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
11040       UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
11041       /* make unconditional */
11042       if (condT != IRTemp_INVALID) {
11043          if (isT)
11044             mk_skip_over_T32_if_cond_is_false( condT );
11045          else
11046             mk_skip_over_A32_if_cond_is_false( condT );
11047          condT = IRTemp_INVALID;
11048       }
11049       IRTemp ea = newTemp(Ity_I32);
11050       assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
11051                        align4if(isT ? getIRegT(rN) : getIRegA(rN),
11052                                 rN == 15),
11053                        mkU32(offset)));
11054       if (bL) {
11055          putDReg(dD, loadLE(Ity_F64,mkexpr(ea)), IRTemp_INVALID);
11056       } else {
11057          storeLE(mkexpr(ea), getDReg(dD));
11058       }
11059       DIP("f%sd%s d%u, [r%u, %c#%u]\n",
11060           bL ? "ld" : "st", nCC(conq), dD, rN,
11061           bU ? '+' : '-', offset);
11062       goto decode_success_vfp;
11063    }
11064
11065    /* --------------------- dp insns (D) --------------------- */
11066    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
11067        && BITS4(1,0,1,1) == INSN(11,8)
11068        && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
11069       UInt    dM  = INSN(3,0)   | (INSN(5,5) << 4);       /* argR */
11070       UInt    dD  = INSN(15,12) | (INSN(22,22) << 4);   /* dst/acc */
11071       UInt    dN  = INSN(19,16) | (INSN(7,7) << 4);     /* argL */
11072       UInt    bP  = (insn28 >> 23) & 1;
11073       UInt    bQ  = (insn28 >> 21) & 1;
11074       UInt    bR  = (insn28 >> 20) & 1;
11075       UInt    bS  = (insn28 >> 6) & 1;
11076       UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
11077       IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11078       switch (opc) {
11079          case BITS4(0,0,0,0): /* MAC: d + n * m */
11080             putDReg(dD, triop(Iop_AddF64, rm,
11081                               getDReg(dD),
11082                               triop(Iop_MulF64, rm, getDReg(dN),
11083                                                     getDReg(dM))),
11084                         condT);
11085             DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11086             goto decode_success_vfp;
11087          case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
11088             putDReg(dD, triop(Iop_AddF64, rm,
11089                               getDReg(dD),
11090                               unop(Iop_NegF64,
11091                                    triop(Iop_MulF64, rm, getDReg(dN),
11092                                                          getDReg(dM)))),
11093                         condT);
11094             DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11095             goto decode_success_vfp;
11096          case BITS4(0,0,1,0): /* MSC: - d + n * m */
11097             putDReg(dD, triop(Iop_AddF64, rm,
11098                               unop(Iop_NegF64, getDReg(dD)),
11099                               triop(Iop_MulF64, rm, getDReg(dN),
11100                                                     getDReg(dM))),
11101                         condT);
11102             DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11103             goto decode_success_vfp;
11104          case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
11105             putDReg(dD, triop(Iop_AddF64, rm,
11106                               unop(Iop_NegF64, getDReg(dD)),
11107                               unop(Iop_NegF64,
11108                                    triop(Iop_MulF64, rm, getDReg(dN),
11109                                                          getDReg(dM)))),
11110                         condT);
11111             DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11112             goto decode_success_vfp;
11113          case BITS4(0,1,0,0): /* MUL: n * m */
11114             putDReg(dD, triop(Iop_MulF64, rm, getDReg(dN), getDReg(dM)),
11115                         condT);
11116             DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11117             goto decode_success_vfp;
11118          case BITS4(0,1,0,1): /* NMUL: - n * m */
11119             putDReg(dD, unop(Iop_NegF64,
11120                              triop(Iop_MulF64, rm, getDReg(dN),
11121                                                    getDReg(dM))),
11122                     condT);
11123             DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11124             goto decode_success_vfp;
11125          case BITS4(0,1,1,0): /* ADD: n + m */
11126             putDReg(dD, triop(Iop_AddF64, rm, getDReg(dN), getDReg(dM)),
11127                         condT);
11128             DIP("faddd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11129             goto decode_success_vfp;
11130          case BITS4(0,1,1,1): /* SUB: n - m */
11131             putDReg(dD, triop(Iop_SubF64, rm, getDReg(dN), getDReg(dM)),
11132                         condT);
11133             DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11134             goto decode_success_vfp;
11135          case BITS4(1,0,0,0): /* DIV: n / m */
11136             putDReg(dD, triop(Iop_DivF64, rm, getDReg(dN), getDReg(dM)),
11137                         condT);
11138             DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
11139             goto decode_success_vfp;
11140          default:
11141             break;
11142       }
11143    }
11144
11145    /* --------------------- compares (D) --------------------- */
11146    /*          31   27   23   19   15 11   7    3
11147                  28   24   20   16 12    8    4    0 
11148       FCMPD    cond 1110 1D11 0100 Dd 1011 0100 Dm
11149       FCMPED   cond 1110 1D11 0100 Dd 1011 1100 Dm
11150       FCMPZD   cond 1110 1D11 0101 Dd 1011 0100 0000
11151       FCMPZED  cond 1110 1D11 0101 Dd 1011 1100 0000
11152                                  Z         N
11153
11154       Z=0 Compare Dd vs Dm     and set FPSCR 31:28 accordingly
11155       Z=1 Compare Dd vs zero
11156
11157       N=1 generates Invalid Operation exn if either arg is any kind of NaN
11158       N=0 generates Invalid Operation exn if either arg is a signalling NaN
11159       (Not that we pay any attention to N here)
11160    */
11161    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11162        && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11163        && BITS4(1,0,1,1) == INSN(11,8)
11164        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11165       UInt bZ = (insn28 >> 16) & 1;
11166       UInt bN = (insn28 >> 7) & 1;
11167       UInt dD = INSN(15,12) | (INSN(22,22) << 4);
11168       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
11169       if (bZ && INSN(3,0) != 0) {
11170          /* does not decode; fall through */
11171       } else {
11172          IRTemp argL = newTemp(Ity_F64);
11173          IRTemp argR = newTemp(Ity_F64);
11174          IRTemp irRes = newTemp(Ity_I32);
11175          assign(argL, getDReg(dD));
11176          assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM));
11177          assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
11178
11179          IRTemp nzcv     = IRTemp_INVALID;
11180          IRTemp oldFPSCR = newTemp(Ity_I32);
11181          IRTemp newFPSCR = newTemp(Ity_I32);
11182
11183          /* This is where the fun starts.  We have to convert 'irRes'
11184             from an IR-convention return result (IRCmpF64Result) to an
11185             ARM-encoded (N,Z,C,V) group.  The final result is in the
11186             bottom 4 bits of 'nzcv'. */
11187          /* Map compare result from IR to ARM(nzcv) */
11188          /*
11189             FP cmp result | IR   | ARM(nzcv)
11190             --------------------------------
11191             UN              0x45   0011
11192             LT              0x01   1000
11193             GT              0x00   0010
11194             EQ              0x40   0110
11195          */
11196          nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
11197
11198          /* And update FPSCR accordingly */
11199          assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
11200          assign(newFPSCR, 
11201                 binop(Iop_Or32, 
11202                       binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
11203                       binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
11204
11205          putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
11206
11207          if (bZ) {
11208             DIP("fcmpz%sd%s d%u\n", bN ? "e" : "", nCC(conq), dD);
11209          } else {
11210             DIP("fcmp%sd%s d%u, d%u\n", bN ? "e" : "", nCC(conq), dD, dM);
11211          }
11212          goto decode_success_vfp;
11213       }
11214       /* fall through */
11215    }  
11216
11217    /* --------------------- unary (D) --------------------- */
11218    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11219        && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11220        && BITS4(1,0,1,1) == INSN(11,8)
11221        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11222       UInt dD  = INSN(15,12) | (INSN(22,22) << 4);
11223       UInt dM  = INSN(3,0) | (INSN(5,5) << 4);
11224       UInt b16 = (insn28 >> 16) & 1;
11225       UInt b7  = (insn28 >> 7) & 1;
11226       /**/ if (b16 == 0 && b7 == 0) {
11227          // FCPYD
11228          putDReg(dD, getDReg(dM), condT);
11229          DIP("fcpyd%s d%u, d%u\n", nCC(conq), dD, dM);
11230          goto decode_success_vfp;
11231       }
11232       else if (b16 == 0 && b7 == 1) {
11233          // FABSD
11234          putDReg(dD, unop(Iop_AbsF64, getDReg(dM)), condT);
11235          DIP("fabsd%s d%u, d%u\n", nCC(conq), dD, dM);
11236          goto decode_success_vfp;
11237       }
11238       else if (b16 == 1 && b7 == 0) {
11239          // FNEGD
11240          putDReg(dD, unop(Iop_NegF64, getDReg(dM)), condT);
11241          DIP("fnegd%s d%u, d%u\n", nCC(conq), dD, dM);
11242          goto decode_success_vfp;
11243       }
11244       else if (b16 == 1 && b7 == 1) {
11245          // FSQRTD
11246          IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11247          putDReg(dD, binop(Iop_SqrtF64, rm, getDReg(dM)), condT);
11248          DIP("fsqrtd%s d%u, d%u\n", nCC(conq), dD, dM);
11249          goto decode_success_vfp;
11250       }
11251       else
11252          vassert(0);
11253
11254       /* fall through */
11255    }
11256
11257    /* ----------------- I <-> D conversions ----------------- */
11258
11259    // F{S,U}ITOD dD, fM
11260    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11261        && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
11262        && BITS4(1,0,1,1) == INSN(11,8)
11263        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11264       UInt bM    = (insn28 >> 5) & 1;
11265       UInt fM    = (INSN(3,0) << 1) | bM;
11266       UInt dD    = INSN(15,12) | (INSN(22,22) << 4);
11267       UInt syned = (insn28 >> 7) & 1;
11268       if (syned) {
11269          // FSITOD
11270          putDReg(dD, unop(Iop_I32StoF64,
11271                           unop(Iop_ReinterpF32asI32, getFReg(fM))),
11272                  condT);
11273          DIP("fsitod%s d%u, s%u\n", nCC(conq), dD, fM);
11274       } else {
11275          // FUITOD
11276          putDReg(dD, unop(Iop_I32UtoF64,
11277                           unop(Iop_ReinterpF32asI32, getFReg(fM))),
11278                  condT);
11279          DIP("fuitod%s d%u, s%u\n", nCC(conq), dD, fM);
11280       }
11281       goto decode_success_vfp;
11282    }
11283
11284    // FTO{S,U}ID fD, dM
11285    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11286        && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11287        && BITS4(1,0,1,1) == INSN(11,8)
11288        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11289       UInt   bD    = (insn28 >> 22) & 1;
11290       UInt   fD    = (INSN(15,12) << 1) | bD;
11291       UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
11292       UInt   bZ    = (insn28 >> 7) & 1;
11293       UInt   syned = (insn28 >> 16) & 1;
11294       IRTemp rmode = newTemp(Ity_I32);
11295       assign(rmode, bZ ? mkU32(Irrm_ZERO)
11296                        : mkexpr(mk_get_IR_rounding_mode()));
11297       if (syned) {
11298          // FTOSID
11299          putFReg(fD, unop(Iop_ReinterpI32asF32,
11300                           binop(Iop_F64toI32S, mkexpr(rmode),
11301                                 getDReg(dM))),
11302                  condT);
11303          DIP("ftosi%sd%s s%u, d%u\n", bZ ? "z" : "",
11304              nCC(conq), fD, dM);
11305       } else {
11306          // FTOUID
11307          putFReg(fD, unop(Iop_ReinterpI32asF32,
11308                           binop(Iop_F64toI32U, mkexpr(rmode),
11309                                 getDReg(dM))),
11310                  condT);
11311          DIP("ftoui%sd%s s%u, d%u\n", bZ ? "z" : "",
11312              nCC(conq), fD, dM);
11313       }
11314       goto decode_success_vfp;
11315    }
11316
11317    /* ----------------------------------------------------------- */
11318    /* -- VFP instructions -- single precision                  -- */
11319    /* ----------------------------------------------------------- */
11320
11321    /* --------------------- fldms, fstms --------------------- */
11322    /*
11323                                  31   27   23   19 15 11   7   0
11324                                          P UDWL
11325       C4-98, C5-26   1  FSTMD    cond 1100 1x00 Rn Fd 1010 offset
11326       C4-98, C5-28   2  FSTMDIA  cond 1100 1x10 Rn Fd 1010 offset
11327       C4-98, C5-30   3  FSTMDDB  cond 1101 0x10 Rn Fd 1010 offset
11328
11329       C4-40, C5-26   1  FLDMD    cond 1100 1x01 Rn Fd 1010 offset
11330       C4-40, C5-26   2  FLDMIAD  cond 1100 1x11 Rn Fd 1010 offset
11331       C4-40, C5-26   3  FLDMDBD  cond 1101 0x11 Rn Fd 1010 offset
11332
11333       Regs transferred: F(Fd:D) .. F(Fd:d + offset)
11334       offset must not imply a reg > 15
11335       IA/DB: Rn is changed by (4 x # regs transferred)
11336
11337       case coding:
11338          1  at-Rn   (access at Rn)
11339          2  ia-Rn   (access at Rn, then Rn += 4n)
11340          3  db-Rn   (Rn -= 4n,     then access at Rn)
11341    */
11342    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
11343        && INSN(11,8) == BITS4(1,0,1,0)) {
11344       UInt bP      = (insn28 >> 24) & 1;
11345       UInt bU      = (insn28 >> 23) & 1;
11346       UInt bW      = (insn28 >> 21) & 1;
11347       UInt bL      = (insn28 >> 20) & 1;
11348       UInt bD      = (insn28 >> 22) & 1;
11349       UInt offset  = (insn28 >> 0) & 0xFF;
11350       UInt rN      = INSN(19,16);
11351       UInt fD      = (INSN(15,12) << 1) | bD;
11352       UInt nRegs   = offset;
11353       UInt summary = 0;
11354       Int  i;
11355
11356       /**/ if (bP == 0 && bU == 1 && bW == 0) {
11357          summary = 1;
11358       }
11359       else if (bP == 0 && bU == 1 && bW == 1) {
11360          summary = 2;
11361       }
11362       else if (bP == 1 && bU == 0 && bW == 1) {
11363          summary = 3;
11364       }
11365       else goto after_vfp_fldms_fstms;
11366
11367       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
11368       if (rN == 15 && (summary == 2 || summary == 3 || isT))
11369          goto after_vfp_fldms_fstms;
11370
11371       /* offset must specify at least one register */
11372       if (offset < 1)
11373          goto after_vfp_fldms_fstms;
11374
11375       /* can't transfer regs after S31 */
11376       if (fD + nRegs - 1 >= 32)
11377          goto after_vfp_fldms_fstms;
11378
11379       /* Now, we can't do a conditional load or store, since that very
11380          likely will generate an exception.  So we have to take a side
11381          exit at this point if the condition is false. */
11382       if (condT != IRTemp_INVALID) {
11383          if (isT)
11384             mk_skip_over_T32_if_cond_is_false( condT );
11385          else
11386             mk_skip_over_A32_if_cond_is_false( condT );
11387          condT = IRTemp_INVALID;
11388       }
11389       /* Ok, now we're unconditional.  Do the load or store. */
11390
11391       /* get the old Rn value */
11392       IRTemp rnT = newTemp(Ity_I32);
11393       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
11394                            rN == 15));
11395
11396       /* make a new value for Rn, post-insn */
11397       IRTemp rnTnew = IRTemp_INVALID;
11398       if (summary == 2 || summary == 3) {
11399          rnTnew = newTemp(Ity_I32);
11400          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
11401                               mkexpr(rnT),
11402                               mkU32(4 * nRegs)));
11403       }
11404
11405       /* decide on the base transfer address */
11406       IRTemp taT = newTemp(Ity_I32);
11407       assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
11408
11409       /* update Rn if necessary -- in case 3, we're moving it down, so
11410          update before any memory reference, in order to keep Memcheck
11411          and V's stack-extending logic (on linux) happy */
11412       if (summary == 3) {
11413          if (isT)
11414             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11415          else
11416             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11417       }
11418
11419       /* generate the transfers */
11420       for (i = 0; i < nRegs; i++) {
11421          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(4*i));
11422          if (bL) {
11423             putFReg(fD + i, loadLE(Ity_F32, addr), IRTemp_INVALID);
11424          } else {
11425             storeLE(addr, getFReg(fD + i));
11426          }
11427       }
11428
11429       /* update Rn if necessary -- in case 2, we're moving it up, so
11430          update after any memory reference, in order to keep Memcheck
11431          and V's stack-extending logic (on linux) happy */
11432       if (summary == 2) {
11433          if (isT)
11434             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
11435          else
11436             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
11437       }
11438
11439       HChar* nm = bL==1 ? "ld" : "st";
11440       switch (summary) {
11441          case 1:  DIP("f%sms%s r%u, {s%u-s%u}\n", 
11442                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
11443                   break;
11444          case 2:  DIP("f%smias%s r%u!, {s%u-s%u}\n", 
11445                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
11446                   break;
11447          case 3:  DIP("f%smdbs%s r%u!, {s%u-s%u}\n", 
11448                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
11449                   break;
11450          default: vassert(0);
11451       }
11452
11453       goto decode_success_vfp;
11454       /* FIXME alignment constraints? */
11455    }
11456
11457   after_vfp_fldms_fstms:
11458
11459    /* --------------------- fmsr, fmrs --------------------- */
11460    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
11461        && BITS4(1,0,1,0) == INSN(11,8)
11462        && BITS4(0,0,0,0) == INSN(3,0)
11463        && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
11464       UInt rD  = INSN(15,12);
11465       UInt b7  = (insn28 >> 7) & 1;
11466       UInt fN  = (INSN(19,16) << 1) | b7;
11467       UInt b20 = (insn28 >> 20) & 1;
11468       if (rD == 15) {
11469          /* fall through */
11470          /* Let's assume that no sane person would want to do
11471             floating-point transfers to or from the program counter,
11472             and simply decline to decode the instruction.  The ARM ARM
11473             doesn't seem to explicitly disallow this case, though. */
11474       } else {
11475          if (b20) {
11476             IRExpr* res = unop(Iop_ReinterpF32asI32, getFReg(fN));
11477             if (isT)
11478                putIRegT(rD, res, condT);
11479             else
11480                putIRegA(rD, res, condT, Ijk_Boring);
11481             DIP("fmrs%s r%u, s%u\n", nCC(conq), rD, fN);
11482          } else {
11483             putFReg(fN, unop(Iop_ReinterpI32asF32,
11484                              isT ? getIRegT(rD) : getIRegA(rD)),
11485                         condT);
11486             DIP("fmsr%s s%u, r%u\n", nCC(conq), fN, rD);
11487          }
11488          goto decode_success_vfp;
11489       }
11490       /* fall through */
11491    }
11492
11493    /* --------------------- f{ld,st}s --------------------- */
11494    // FLDS, FSTS
11495    if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
11496        && BITS4(1,0,1,0) == INSN(11,8)) {
11497       UInt bD     = (insn28 >> 22) & 1;
11498       UInt fD     = (INSN(15,12) << 1) | bD;
11499       UInt rN     = INSN(19,16);
11500       UInt offset = (insn28 & 0xFF) << 2;
11501       UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
11502       UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
11503       /* make unconditional */
11504       if (condT != IRTemp_INVALID) {
11505          if (isT)
11506             mk_skip_over_T32_if_cond_is_false( condT );
11507          else
11508             mk_skip_over_A32_if_cond_is_false( condT );
11509          condT = IRTemp_INVALID;
11510       }
11511       IRTemp ea = newTemp(Ity_I32);
11512       assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
11513                        align4if(isT ? getIRegT(rN) : getIRegA(rN),
11514                                 rN == 15),
11515                        mkU32(offset)));
11516       if (bL) {
11517          putFReg(fD, loadLE(Ity_F32,mkexpr(ea)), IRTemp_INVALID);
11518       } else {
11519          storeLE(mkexpr(ea), getFReg(fD));
11520       }
11521       DIP("f%ss%s s%u, [r%u, %c#%u]\n",
11522           bL ? "ld" : "st", nCC(conq), fD, rN,
11523           bU ? '+' : '-', offset);
11524       goto decode_success_vfp;
11525    }
11526
11527    /* --------------------- dp insns (F) --------------------- */
11528    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
11529        && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
11530        && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
11531       UInt    bM  = (insn28 >> 5) & 1;
11532       UInt    bD  = (insn28 >> 22) & 1;
11533       UInt    bN  = (insn28 >> 7) & 1;
11534       UInt    fM  = (INSN(3,0) << 1) | bM;   /* argR */
11535       UInt    fD  = (INSN(15,12) << 1) | bD; /* dst/acc */
11536       UInt    fN  = (INSN(19,16) << 1) | bN; /* argL */
11537       UInt    bP  = (insn28 >> 23) & 1;
11538       UInt    bQ  = (insn28 >> 21) & 1;
11539       UInt    bR  = (insn28 >> 20) & 1;
11540       UInt    bS  = (insn28 >> 6) & 1;
11541       UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
11542       IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11543       switch (opc) {
11544          case BITS4(0,0,0,0): /* MAC: d + n * m */
11545             putFReg(fD, triop(Iop_AddF32, rm,
11546                               getFReg(fD),
11547                               triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
11548                         condT);
11549             DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11550             goto decode_success_vfp;
11551          case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
11552             putFReg(fD, triop(Iop_AddF32, rm,
11553                               getFReg(fD),
11554                               unop(Iop_NegF32,
11555                                    triop(Iop_MulF32, rm, getFReg(fN),
11556                                                          getFReg(fM)))),
11557                         condT);
11558             DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11559             goto decode_success_vfp;
11560          case BITS4(0,0,1,0): /* MSC: - d + n * m */
11561             putFReg(fD, triop(Iop_AddF32, rm,
11562                               unop(Iop_NegF32, getFReg(fD)),
11563                               triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
11564                         condT);
11565             DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11566             goto decode_success_vfp;
11567          case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
11568             putFReg(fD, triop(Iop_AddF32, rm,
11569                               unop(Iop_NegF32, getFReg(fD)),
11570                               unop(Iop_NegF32,
11571                                    triop(Iop_MulF32, rm,
11572                                                      getFReg(fN),
11573                                                     getFReg(fM)))),
11574                         condT);
11575             DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11576             goto decode_success_vfp;
11577          case BITS4(0,1,0,0): /* MUL: n * m */
11578             putFReg(fD, triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM)),
11579                         condT);
11580             DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11581             goto decode_success_vfp;
11582          case BITS4(0,1,0,1): /* NMUL: - n * m */
11583             putFReg(fD, unop(Iop_NegF32,
11584                              triop(Iop_MulF32, rm, getFReg(fN),
11585                                                    getFReg(fM))),
11586                     condT);
11587             DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11588             goto decode_success_vfp;
11589          case BITS4(0,1,1,0): /* ADD: n + m */
11590             putFReg(fD, triop(Iop_AddF32, rm, getFReg(fN), getFReg(fM)),
11591                         condT);
11592             DIP("fadds%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11593             goto decode_success_vfp;
11594          case BITS4(0,1,1,1): /* SUB: n - m */
11595             putFReg(fD, triop(Iop_SubF32, rm, getFReg(fN), getFReg(fM)),
11596                         condT);
11597             DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11598             goto decode_success_vfp;
11599          case BITS4(1,0,0,0): /* DIV: n / m */
11600             putFReg(fD, triop(Iop_DivF32, rm, getFReg(fN), getFReg(fM)),
11601                         condT);
11602             DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
11603             goto decode_success_vfp;
11604          default:
11605             break;
11606       }
11607    }
11608
11609    /* --------------------- compares (S) --------------------- */
11610    /*          31   27   23   19   15 11   7    3
11611                  28   24   20   16 12    8    4    0 
11612       FCMPS    cond 1110 1D11 0100 Fd 1010 01M0 Fm
11613       FCMPES   cond 1110 1D11 0100 Fd 1010 11M0 Fm
11614       FCMPZS   cond 1110 1D11 0101 Fd 1010 0100 0000
11615       FCMPZED  cond 1110 1D11 0101 Fd 1010 1100 0000
11616                                  Z         N
11617
11618       Z=0 Compare Fd:D vs Fm:M     and set FPSCR 31:28 accordingly
11619       Z=1 Compare Fd:D vs zero
11620
11621       N=1 generates Invalid Operation exn if either arg is any kind of NaN
11622       N=0 generates Invalid Operation exn if either arg is a signalling NaN
11623       (Not that we pay any attention to N here)
11624    */
11625    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11626        && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11627        && BITS4(1,0,1,0) == INSN(11,8)
11628        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11629       UInt bZ = (insn28 >> 16) & 1;
11630       UInt bN = (insn28 >> 7) & 1;
11631       UInt bD = (insn28 >> 22) & 1;
11632       UInt bM = (insn28 >> 5) & 1;
11633       UInt fD = (INSN(15,12) << 1) | bD;
11634       UInt fM = (INSN(3,0) << 1) | bM;
11635       if (bZ && (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) {
11636          /* does not decode; fall through */
11637       } else {
11638          IRTemp argL = newTemp(Ity_F64);
11639          IRTemp argR = newTemp(Ity_F64);
11640          IRTemp irRes = newTemp(Ity_I32);
11641
11642          assign(argL, unop(Iop_F32toF64, getFReg(fD)));
11643          assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0))
11644                          : unop(Iop_F32toF64, getFReg(fM)));
11645          assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
11646
11647          IRTemp nzcv     = IRTemp_INVALID;
11648          IRTemp oldFPSCR = newTemp(Ity_I32);
11649          IRTemp newFPSCR = newTemp(Ity_I32);
11650
11651          /* This is where the fun starts.  We have to convert 'irRes'
11652             from an IR-convention return result (IRCmpF64Result) to an
11653             ARM-encoded (N,Z,C,V) group.  The final result is in the
11654             bottom 4 bits of 'nzcv'. */
11655          /* Map compare result from IR to ARM(nzcv) */
11656          /*
11657             FP cmp result | IR   | ARM(nzcv)
11658             --------------------------------
11659             UN              0x45   0011
11660             LT              0x01   1000
11661             GT              0x00   0010
11662             EQ              0x40   0110
11663          */
11664          nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
11665
11666          /* And update FPSCR accordingly */
11667          assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
11668          assign(newFPSCR, 
11669                 binop(Iop_Or32, 
11670                       binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
11671                       binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
11672
11673          putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
11674
11675          if (bZ) {
11676             DIP("fcmpz%ss%s s%u\n", bN ? "e" : "", nCC(conq), fD);
11677          } else {
11678             DIP("fcmp%ss%s s%u, s%u\n", bN ? "e" : "",
11679                 nCC(conq), fD, fM);
11680          }
11681          goto decode_success_vfp;
11682       }
11683       /* fall through */
11684    }  
11685
11686    /* --------------------- unary (S) --------------------- */
11687    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11688        && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11689        && BITS4(1,0,1,0) == INSN(11,8)
11690        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11691       UInt bD = (insn28 >> 22) & 1;
11692       UInt bM = (insn28 >> 5) & 1;
11693       UInt fD  = (INSN(15,12) << 1) | bD;
11694       UInt fM  = (INSN(3,0) << 1) | bM;
11695       UInt b16 = (insn28 >> 16) & 1;
11696       UInt b7  = (insn28 >> 7) & 1;
11697       /**/ if (b16 == 0 && b7 == 0) {
11698          // FCPYS
11699          putFReg(fD, getFReg(fM), condT);
11700          DIP("fcpys%s s%u, s%u\n", nCC(conq), fD, fM);
11701          goto decode_success_vfp;
11702       }
11703       else if (b16 == 0 && b7 == 1) {
11704          // FABSS
11705          putFReg(fD, unop(Iop_AbsF32, getFReg(fM)), condT);
11706          DIP("fabss%s s%u, s%u\n", nCC(conq), fD, fM);
11707          goto decode_success_vfp;
11708       }
11709       else if (b16 == 1 && b7 == 0) {
11710          // FNEGS
11711          putFReg(fD, unop(Iop_NegF32, getFReg(fM)), condT);
11712          DIP("fnegs%s s%u, s%u\n", nCC(conq), fD, fM);
11713          goto decode_success_vfp;
11714       }
11715       else if (b16 == 1 && b7 == 1) {
11716          // FSQRTS
11717          IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
11718          putFReg(fD, binop(Iop_SqrtF32, rm, getFReg(fM)), condT);
11719          DIP("fsqrts%s s%u, s%u\n", nCC(conq), fD, fM);
11720          goto decode_success_vfp;
11721       }
11722       else
11723          vassert(0);
11724
11725       /* fall through */
11726    }
11727
11728    /* ----------------- I <-> S conversions ----------------- */
11729
11730    // F{S,U}ITOS fD, fM
11731    /* These are more complex than FSITOD/FUITOD.  In the D cases, a 32
11732       bit int will always fit within the 53 bit mantissa, so there's
11733       no possibility of a loss of precision, but that's obviously not
11734       the case here.  Hence this case possibly requires rounding, and
11735       so it drags in the current rounding mode. */
11736    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11737        && BITS4(1,0,0,0) == INSN(19,16)
11738        && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
11739        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11740       UInt bM    = (insn28 >> 5) & 1;
11741       UInt bD    = (insn28 >> 22) & 1;
11742       UInt fM    = (INSN(3,0) << 1) | bM;
11743       UInt fD    = (INSN(15,12) << 1) | bD;
11744       UInt syned = (insn28 >> 7) & 1;
11745       IRTemp rmode = newTemp(Ity_I32);
11746       assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
11747       if (syned) {
11748          // FSITOS
11749          putFReg(fD, binop(Iop_F64toF32,
11750                            mkexpr(rmode),
11751                            unop(Iop_I32StoF64,
11752                                 unop(Iop_ReinterpF32asI32, getFReg(fM)))),
11753                  condT);
11754          DIP("fsitos%s s%u, s%u\n", nCC(conq), fD, fM);
11755       } else {
11756          // FUITOS
11757          putFReg(fD, binop(Iop_F64toF32,
11758                            mkexpr(rmode),
11759                            unop(Iop_I32UtoF64,
11760                                 unop(Iop_ReinterpF32asI32, getFReg(fM)))),
11761                  condT);
11762          DIP("fuitos%s s%u, s%u\n", nCC(conq), fD, fM);
11763       }
11764       goto decode_success_vfp;
11765    }
11766
11767    // FTO{S,U}IS fD, fM
11768    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11769        && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
11770        && BITS4(1,0,1,0) == INSN(11,8)
11771        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
11772       UInt   bM    = (insn28 >> 5) & 1;
11773       UInt   bD    = (insn28 >> 22) & 1;
11774       UInt   fD    = (INSN(15,12) << 1) | bD;
11775       UInt   fM    = (INSN(3,0) << 1) | bM;
11776       UInt   bZ    = (insn28 >> 7) & 1;
11777       UInt   syned = (insn28 >> 16) & 1;
11778       IRTemp rmode = newTemp(Ity_I32);
11779       assign(rmode, bZ ? mkU32(Irrm_ZERO)
11780                        : mkexpr(mk_get_IR_rounding_mode()));
11781       if (syned) {
11782          // FTOSIS
11783          putFReg(fD, unop(Iop_ReinterpI32asF32,
11784                           binop(Iop_F64toI32S, mkexpr(rmode),
11785                                 unop(Iop_F32toF64, getFReg(fM)))),
11786                  condT);
11787          DIP("ftosi%ss%s s%u, d%u\n", bZ ? "z" : "",
11788              nCC(conq), fD, fM);
11789          goto decode_success_vfp;
11790       } else {
11791          // FTOUIS
11792          putFReg(fD, unop(Iop_ReinterpI32asF32,
11793                           binop(Iop_F64toI32U, mkexpr(rmode),
11794                                 unop(Iop_F32toF64, getFReg(fM)))),
11795                  condT);
11796          DIP("ftoui%ss%s s%u, d%u\n", bZ ? "z" : "",
11797              nCC(conq), fD, fM);
11798          goto decode_success_vfp;
11799       }
11800    }
11801
11802    /* ----------------- S <-> D conversions ----------------- */
11803
11804    // FCVTDS
11805    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11806        && BITS4(0,1,1,1) == INSN(19,16)
11807        && BITS4(1,0,1,0) == INSN(11,8)
11808        && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
11809       UInt dD = INSN(15,12) | (INSN(22,22) << 4);
11810       UInt bM = (insn28 >> 5) & 1;
11811       UInt fM = (INSN(3,0) << 1) | bM;
11812       putDReg(dD, unop(Iop_F32toF64, getFReg(fM)), condT);
11813       DIP("fcvtds%s d%u, s%u\n", nCC(conq), dD, fM);
11814       goto decode_success_vfp;
11815    }
11816
11817    // FCVTSD
11818    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
11819        && BITS4(0,1,1,1) == INSN(19,16)
11820        && BITS4(1,0,1,1) == INSN(11,8)
11821        && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
11822       UInt   bD    = (insn28 >> 22) & 1;
11823       UInt   fD    = (INSN(15,12) << 1) | bD;
11824       UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
11825       IRTemp rmode = newTemp(Ity_I32);
11826       assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
11827       putFReg(fD, binop(Iop_F64toF32, mkexpr(rmode), getDReg(dM)),
11828                   condT);
11829       DIP("fcvtsd%s s%u, d%u\n", nCC(conq), fD, dM);
11830       goto decode_success_vfp;
11831    }
11832
11833    /* FAILURE */
11834    return False;
11835
11836   decode_success_vfp:
11837    /* Check that any accepted insn really is a CP10 or CP11 insn, iow,
11838       assert that we aren't accepting, in this fn, insns that actually
11839       should be handled somewhere else. */
11840    vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011
11841    return True;  
11842
11843 #  undef INSN
11844 }
11845
11846
11847 /*------------------------------------------------------------*/
11848 /*--- Instructions in NV (never) space                     ---*/
11849 /*------------------------------------------------------------*/
11850
11851 /* ARM only */
11852 /* Translate a NV space instruction.  If successful, returns True and
11853    *dres may or may not be updated.  If failure, returns False and
11854    doesn't change *dres nor create any IR.
11855
11856    Note that all NEON instructions (in ARM mode) are handled through
11857    here, since they are all in NV space.
11858 */
11859 static Bool decode_NV_instruction ( /*MOD*/DisResult* dres,
11860                                     VexArchInfo* archinfo,
11861                                     UInt insn )
11862 {
11863 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
11864 #  define INSN_COND          SLICE_UInt(insn, 31, 28)
11865
11866    HChar dis_buf[128];
11867
11868    // Should only be called for NV instructions
11869    vassert(BITS4(1,1,1,1) == INSN_COND);
11870
11871    /* ------------------------ pld ------------------------ */
11872    if (BITS8(0,1,0,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
11873        && BITS4(1,1,1,1) == INSN(15,12)) {
11874       UInt rN    = INSN(19,16);
11875       UInt imm12 = INSN(11,0);
11876       UInt bU    = INSN(23,23);
11877       DIP("pld [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
11878       return True;
11879    }
11880
11881    if (BITS8(0,1,1,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
11882        && BITS4(1,1,1,1) == INSN(15,12)
11883        && 0 == INSN(4,4)) {
11884       UInt rN   = INSN(19,16);
11885       UInt rM   = INSN(3,0);
11886       UInt imm5 = INSN(11,7);
11887       UInt sh2  = INSN(6,5);
11888       UInt bU   = INSN(23,23);
11889       if (rM != 15) {
11890          IRExpr* eaE = mk_EA_reg_plusminus_shifted_reg(rN, bU, rM,
11891                                                        sh2, imm5, dis_buf);
11892          IRTemp eaT = newTemp(Ity_I32);
11893          /* Bind eaE to a temp merely for debugging-vex purposes, so we
11894             can check it's a plausible decoding.  It will get removed
11895             by iropt a little later on. */
11896          vassert(eaE);
11897          assign(eaT, eaE);
11898          DIP("pld %s\n", dis_buf);
11899          return True;
11900       }
11901       /* fall through */
11902    }
11903
11904    /* ------------------------ pli ------------------------ */
11905    if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
11906        && BITS4(1,1,1,1) == INSN(15,12)) {
11907       UInt rN    = INSN(19,16);
11908       UInt imm12 = INSN(11,0);
11909       UInt bU    = INSN(23,23);
11910       DIP("pli [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
11911       return True;
11912    }
11913
11914    /* --------------------- Interworking branches --------------------- */
11915
11916    // BLX (1), viz, unconditional branch and link to R15+simm24
11917    // and set CPSR.T = 1, that is, switch to Thumb mode
11918    if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) {
11919       UInt bitH   = INSN(24,24);
11920       Int  uimm24 = INSN(23,0);
11921       Int  simm24 = (((uimm24 << 8) >> 8) << 2) + (bitH << 1);
11922       /* Now this is a bit tricky.  Since we're decoding an ARM insn,
11923          it is implies that CPSR.T == 0.  Hence the current insn's
11924          address is guaranteed to be of the form X--(30)--X00.  So, no
11925          need to mask any bits off it.  But need to set the lowest bit
11926          to 1 to denote we're in Thumb mode after this, since
11927          guest_R15T has CPSR.T as the lowest bit.  And we can't chase
11928          into the call, so end the block at this point. */
11929       UInt dst = guest_R15_curr_instr_notENC + 8 + (simm24 | 1);
11930       putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
11931                     IRTemp_INVALID/*because AL*/, Ijk_Boring );
11932       irsb->next     = mkU32(dst);
11933       irsb->jumpkind = Ijk_Call;
11934       dres->whatNext = Dis_StopHere;
11935       DIP("blx 0x%x (and switch to Thumb mode)\n", dst - 1);
11936       return True;
11937    }
11938
11939    /* ------------------- v7 barrier insns ------------------- */
11940    switch (insn) {
11941       case 0xF57FF06F: /* ISB */
11942          stmt( IRStmt_MBE(Imbe_Fence) );
11943          DIP("ISB\n");
11944          return True;
11945       case 0xF57FF04F: /* DSB sy */
11946       case 0xF57FF04E: /* DSB st */
11947       case 0xF57FF04B: /* DSB ish */
11948       case 0xF57FF04A: /* DSB ishst */
11949       case 0xF57FF047: /* DSB nsh */
11950       case 0xF57FF046: /* DSB nshst */
11951       case 0xF57FF043: /* DSB osh */
11952       case 0xF57FF042: /* DSB oshst */
11953          stmt( IRStmt_MBE(Imbe_Fence) );
11954          DIP("DSB\n");
11955          return True;
11956       case 0xF57FF05F: /* DMB sy */
11957       case 0xF57FF05E: /* DMB st */
11958       case 0xF57FF05B: /* DMB ish */
11959       case 0xF57FF05A: /* DMB ishst */
11960       case 0xF57FF057: /* DMB nsh */
11961       case 0xF57FF056: /* DMB nshst */
11962       case 0xF57FF053: /* DMB osh */
11963       case 0xF57FF052: /* DMB oshst */
11964          stmt( IRStmt_MBE(Imbe_Fence) );
11965          DIP("DMB\n");
11966          return True;
11967       default:
11968          break;
11969    }
11970
11971    /* ------------------- NEON ------------------- */
11972    if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
11973       Bool ok_neon = decode_NEON_instruction(
11974                         dres, insn, IRTemp_INVALID/*unconditional*/, 
11975                         False/*!isT*/
11976                      );
11977       if (ok_neon)
11978          return True;
11979    }
11980
11981    // unrecognised
11982    return False;
11983
11984 #  undef INSN_COND
11985 #  undef INSN
11986 }
11987
11988
11989 /*------------------------------------------------------------*/
11990 /*--- Disassemble a single ARM instruction                 ---*/
11991 /*------------------------------------------------------------*/
11992
11993 /* Disassemble a single ARM instruction into IR.  The instruction is
11994    located in host memory at guest_instr, and has (decoded) guest IP
11995    of guest_R15_curr_instr_notENC, which will have been set before the
11996    call here. */
11997
11998 static
11999 DisResult disInstr_ARM_WRK (
12000              Bool         put_IP,
12001              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
12002              Bool         resteerCisOk,
12003              void*        callback_opaque,
12004              UChar*       guest_instr,
12005              VexArchInfo* archinfo,
12006              VexAbiInfo*  abiinfo
12007           )
12008 {
12009    // A macro to fish bits out of 'insn'.
12010 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
12011 #  define INSN_COND          SLICE_UInt(insn, 31, 28)
12012
12013    DisResult dres;
12014    UInt      insn;
12015    //Bool      allow_VFP = False;
12016    //UInt      hwcaps = archinfo->hwcaps;
12017    IRTemp    condT; /* :: Ity_I32 */
12018    UInt      summary;
12019    HChar     dis_buf[128];  // big enough to hold LDMIA etc text
12020
12021    /* What insn variants are we supporting today? */
12022    //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
12023    // etc etc
12024
12025    /* Set result defaults. */
12026    dres.whatNext   = Dis_Continue;
12027    dres.len        = 4;
12028    dres.continueAt = 0;
12029
12030    /* Set default actions for post-insn handling of writes to r15, if
12031       required. */
12032    r15written = False;
12033    r15guard   = IRTemp_INVALID; /* unconditional */
12034    r15kind    = Ijk_Boring;
12035
12036    /* At least this is simple on ARM: insns are all 4 bytes long, and
12037       4-aligned.  So just fish the whole thing out of memory right now
12038       and have done. */
12039    insn = getUIntLittleEndianly( guest_instr );
12040
12041    if (0) vex_printf("insn: 0x%x\n", insn);
12042
12043    DIP("\t(arm) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
12044
12045    /* We may be asked to update the guest R15 before going further. */
12046    vassert(0 == (guest_R15_curr_instr_notENC & 3));
12047    if (put_IP) {
12048       llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
12049    }
12050
12051    /* ----------------------------------------------------------- */
12052
12053    /* Spot "Special" instructions (see comment at top of file). */
12054    {
12055       UChar* code = (UChar*)guest_instr;
12056       /* Spot the 16-byte preamble: 
12057
12058          e1a0c1ec  mov r12, r12, ROR #3
12059          e1a0c6ec  mov r12, r12, ROR #13
12060          e1a0ceec  mov r12, r12, ROR #29
12061          e1a0c9ec  mov r12, r12, ROR #19
12062       */
12063       UInt word1 = 0xE1A0C1EC;
12064       UInt word2 = 0xE1A0C6EC;
12065       UInt word3 = 0xE1A0CEEC;
12066       UInt word4 = 0xE1A0C9EC;
12067       if (getUIntLittleEndianly(code+ 0) == word1 &&
12068           getUIntLittleEndianly(code+ 4) == word2 &&
12069           getUIntLittleEndianly(code+ 8) == word3 &&
12070           getUIntLittleEndianly(code+12) == word4) {
12071          /* Got a "Special" instruction preamble.  Which one is it? */
12072          if (getUIntLittleEndianly(code+16) == 0xE18AA00A
12073                                                /* orr r10,r10,r10 */) {
12074             /* R3 = client_request ( R4 ) */
12075             DIP("r3 = client_request ( %%r4 )\n");
12076             irsb->next     = mkU32( guest_R15_curr_instr_notENC + 20 );
12077             irsb->jumpkind = Ijk_ClientReq;
12078             dres.whatNext  = Dis_StopHere;
12079             goto decode_success;
12080          }
12081          else
12082          if (getUIntLittleEndianly(code+16) == 0xE18BB00B
12083                                                /* orr r11,r11,r11 */) {
12084             /* R3 = guest_NRADDR */
12085             DIP("r3 = guest_NRADDR\n");
12086             dres.len = 20;
12087             llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
12088             goto decode_success;
12089          }
12090          else
12091          if (getUIntLittleEndianly(code+16) == 0xE18CC00C
12092                                                /* orr r12,r12,r12 */) {
12093             /*  branch-and-link-to-noredir R4 */
12094             DIP("branch-and-link-to-noredir r4\n");
12095             llPutIReg(14, mkU32( guest_R15_curr_instr_notENC + 20) );
12096             irsb->next     = llGetIReg(4);
12097             irsb->jumpkind = Ijk_NoRedir;
12098             dres.whatNext  = Dis_StopHere;
12099             goto decode_success;
12100          }
12101          /* We don't know what it is.  Set opc1/opc2 so decode_failure
12102             can print the insn following the Special-insn preamble. */
12103          insn = getUIntLittleEndianly(code+16);
12104          goto decode_failure;
12105          /*NOTREACHED*/
12106       }
12107
12108    }
12109
12110    /* ----------------------------------------------------------- */
12111
12112    /* Main ARM instruction decoder starts here. */
12113
12114    /* Deal with the condition.  Strategy is to merely generate a
12115       condition temporary at this point (or IRTemp_INVALID, meaning
12116       unconditional).  We leave it to lower-level instruction decoders
12117       to decide whether they can generate straight-line code, or
12118       whether they must generate a side exit before the instruction.
12119       condT :: Ity_I32 and is always either zero or one. */
12120    condT = IRTemp_INVALID;
12121    switch ( (ARMCondcode)INSN_COND ) {
12122       case ARMCondNV: {
12123          // Illegal instruction prior to v5 (see ARM ARM A3-5), but
12124          // some cases are acceptable
12125          Bool ok = decode_NV_instruction(&dres, archinfo, insn);
12126          if (ok)
12127             goto decode_success;
12128          else
12129          goto decode_failure;
12130       }
12131       case ARMCondAL: // Always executed
12132          break;
12133       case ARMCondEQ: case ARMCondNE: case ARMCondHS: case ARMCondLO:
12134       case ARMCondMI: case ARMCondPL: case ARMCondVS: case ARMCondVC:
12135       case ARMCondHI: case ARMCondLS: case ARMCondGE: case ARMCondLT:
12136       case ARMCondGT: case ARMCondLE:
12137          condT = newTemp(Ity_I32);
12138          assign( condT, mk_armg_calculate_condition( INSN_COND ));
12139          break;
12140    }
12141
12142    /* ----------------------------------------------------------- */
12143    /* -- ARMv5 integer instructions                            -- */
12144    /* ----------------------------------------------------------- */
12145
12146    /* ---------------- Data processing ops ------------------- */
12147
12148    if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0))
12149        && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) {
12150       IRTemp  shop = IRTemp_INVALID; /* shifter operand */
12151       IRTemp  shco = IRTemp_INVALID; /* shifter carry out */
12152       UInt    rD   = (insn >> 12) & 0xF; /* 15:12 */
12153       UInt    rN   = (insn >> 16) & 0xF; /* 19:16 */
12154       UInt    bitS = (insn >> 20) & 1; /* 20:20 */
12155       IRTemp  rNt  = IRTemp_INVALID;
12156       IRTemp  res  = IRTemp_INVALID;
12157       IRTemp  oldV = IRTemp_INVALID;
12158       IRTemp  oldC = IRTemp_INVALID;
12159       HChar*  name = NULL;
12160       IROp    op   = Iop_INVALID;
12161       Bool    ok;
12162
12163       switch (INSN(24,21)) {
12164
12165          /* --------- ADD, SUB, AND, OR --------- */
12166          case BITS4(0,1,0,0): /* ADD:  Rd = Rn + shifter_operand */
12167             name = "add"; op = Iop_Add32; goto rd_eq_rn_op_SO;
12168          case BITS4(0,0,1,0): /* SUB:  Rd = Rn - shifter_operand */
12169             name = "sub"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
12170          case BITS4(0,0,1,1): /* RSB:  Rd = shifter_operand - Rn */
12171             name = "rsb"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
12172          case BITS4(0,0,0,0): /* AND:  Rd = Rn & shifter_operand */
12173             name = "and"; op = Iop_And32; goto rd_eq_rn_op_SO;
12174          case BITS4(1,1,0,0): /* OR:   Rd = Rn | shifter_operand */
12175             name = "orr"; op = Iop_Or32; goto rd_eq_rn_op_SO;
12176          case BITS4(0,0,0,1): /* EOR:  Rd = Rn ^ shifter_operand */
12177             name = "eor"; op = Iop_Xor32; goto rd_eq_rn_op_SO;
12178          case BITS4(1,1,1,0): /* BIC:  Rd = Rn & ~shifter_operand */
12179             name = "bic"; op = Iop_And32; goto rd_eq_rn_op_SO;
12180          rd_eq_rn_op_SO: {
12181             Bool isRSB = False;
12182             Bool isBIC = False;
12183             switch (INSN(24,21)) {
12184                case BITS4(0,0,1,1):
12185                   vassert(op == Iop_Sub32); isRSB = True; break;
12186                case BITS4(1,1,1,0):
12187                   vassert(op == Iop_And32); isBIC = True; break;
12188                default:
12189                   break;
12190             }
12191             rNt = newTemp(Ity_I32);
12192             assign(rNt, getIRegA(rN));
12193             ok = mk_shifter_operand(
12194                     INSN(25,25), INSN(11,0), 
12195                     &shop, bitS ? &shco : NULL, dis_buf
12196                  );
12197             if (!ok)
12198                break;
12199             res = newTemp(Ity_I32);
12200             // compute the main result
12201             if (isRSB) {
12202                // reverse-subtract: shifter_operand - Rn
12203                vassert(op == Iop_Sub32);
12204                assign(res, binop(op, mkexpr(shop), mkexpr(rNt)) );
12205             } else if (isBIC) {
12206                // andn: shifter_operand & ~Rn
12207                vassert(op == Iop_And32);
12208                assign(res, binop(op, mkexpr(rNt),
12209                                      unop(Iop_Not32, mkexpr(shop))) );
12210             } else {
12211                // normal: Rn op shifter_operand
12212                assign(res, binop(op, mkexpr(rNt), mkexpr(shop)) );
12213             }
12214             // but don't commit it until after we've finished
12215             // all necessary reads from the guest state
12216             if (bitS
12217                 && (op == Iop_And32 || op == Iop_Or32 || op == Iop_Xor32)) {
12218                oldV = newTemp(Ity_I32);
12219                assign( oldV, mk_armg_calculate_flag_v() );
12220             }
12221             // can't safely read guest state after here
12222             // now safe to put the main result
12223             putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
12224             // XXXX!! not safe to read any guest state after
12225             // this point (I think the code below doesn't do that).
12226             if (!bitS)
12227                vassert(shco == IRTemp_INVALID);
12228             /* Update the flags thunk if necessary */
12229             if (bitS) {
12230                vassert(shco != IRTemp_INVALID);
12231                switch (op) {
12232                   case Iop_Add32:
12233                      setFlags_D1_D2( ARMG_CC_OP_ADD, rNt, shop, condT );
12234                      break;
12235                   case Iop_Sub32:
12236                      if (isRSB) {
12237                         setFlags_D1_D2( ARMG_CC_OP_SUB, shop, rNt, condT );
12238                      } else {
12239                         setFlags_D1_D2( ARMG_CC_OP_SUB, rNt, shop, condT );
12240                      }
12241                      break;
12242                   case Iop_And32: /* BIC and AND set the flags the same */
12243                   case Iop_Or32:
12244                   case Iop_Xor32:
12245                      // oldV has been read just above
12246                      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12247                                         res, shco, oldV, condT );
12248                      break;
12249                   default:
12250                      vassert(0);
12251                }
12252             }
12253             DIP("%s%s%s r%u, r%u, %s\n",
12254                 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
12255             goto decode_success;
12256          }
12257
12258          /* --------- MOV, MVN --------- */
12259          case BITS4(1,1,0,1):   /* MOV: Rd = shifter_operand */
12260          case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */
12261             Bool isMVN = INSN(24,21) == BITS4(1,1,1,1);
12262             if (rN != 0)
12263                break; /* rN must be zero */
12264             ok = mk_shifter_operand(
12265                     INSN(25,25), INSN(11,0), 
12266                     &shop, bitS ? &shco : NULL, dis_buf
12267                  );
12268             if (!ok)
12269                break;
12270             res = newTemp(Ity_I32);
12271             assign( res, isMVN ? unop(Iop_Not32, mkexpr(shop))
12272                                : mkexpr(shop) );
12273             if (bitS) {
12274                vassert(shco != IRTemp_INVALID);
12275                oldV = newTemp(Ity_I32);
12276                assign( oldV, mk_armg_calculate_flag_v() );
12277             } else {
12278                vassert(shco == IRTemp_INVALID);
12279             }
12280             // can't safely read guest state after here
12281             putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
12282             /* Update the flags thunk if necessary */
12283             if (bitS) {
12284                setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, 
12285                                   res, shco, oldV, condT );
12286             }
12287             DIP("%s%s%s r%u, %s\n",
12288                 isMVN ? "mvn" : "mov",
12289                 nCC(INSN_COND), bitS ? "s" : "", rD, dis_buf );
12290             goto decode_success;
12291          }
12292
12293          /* --------- CMP --------- */
12294          case BITS4(1,0,1,0):   /* CMP:  (void) Rn - shifter_operand */
12295          case BITS4(1,0,1,1): { /* CMN:  (void) Rn + shifter_operand */
12296             Bool isCMN = INSN(24,21) == BITS4(1,0,1,1);
12297             if (rD != 0)
12298                break; /* rD must be zero */
12299             if (bitS == 0)
12300                break; /* if S (bit 20) is not set, it's not CMP/CMN */
12301             rNt = newTemp(Ity_I32);
12302             assign(rNt, getIRegA(rN));
12303             ok = mk_shifter_operand(
12304                     INSN(25,25), INSN(11,0), 
12305                     &shop, NULL, dis_buf
12306                  );
12307             if (!ok)
12308                break;
12309             // can't safely read guest state after here
12310             /* Update the flags thunk. */
12311             setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
12312                             rNt, shop, condT );
12313             DIP("%s%s r%u, %s\n",
12314                 isCMN ? "cmn" : "cmp",
12315                 nCC(INSN_COND), rN, dis_buf );
12316             goto decode_success;
12317          }
12318
12319          /* --------- TST --------- */
12320          case BITS4(1,0,0,0):   /* TST:  (void) Rn & shifter_operand */
12321          case BITS4(1,0,0,1): { /* TEQ:  (void) Rn ^ shifter_operand */
12322             Bool isTEQ = INSN(24,21) == BITS4(1,0,0,1);
12323             if (rD != 0)
12324                break; /* rD must be zero */
12325             if (bitS == 0)
12326                break; /* if S (bit 20) is not set, it's not TST/TEQ */
12327             rNt = newTemp(Ity_I32);
12328             assign(rNt, getIRegA(rN));
12329             ok = mk_shifter_operand(
12330                     INSN(25,25), INSN(11,0), 
12331                     &shop, &shco, dis_buf
12332                  );
12333             if (!ok)
12334                break;
12335             /* Update the flags thunk. */
12336             res = newTemp(Ity_I32);
12337             assign( res, binop(isTEQ ? Iop_Xor32 : Iop_And32, 
12338                                mkexpr(rNt), mkexpr(shop)) );
12339             oldV = newTemp(Ity_I32);
12340             assign( oldV, mk_armg_calculate_flag_v() );
12341             // can't safely read guest state after here
12342             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
12343                                res, shco, oldV, condT );
12344             DIP("%s%s r%u, %s\n",
12345                 isTEQ ? "teq" : "tst",
12346                 nCC(INSN_COND), rN, dis_buf );
12347             goto decode_success;
12348          }
12349
12350          /* --------- ADC, SBC, RSC --------- */
12351          case BITS4(0,1,0,1): /* ADC:  Rd = Rn + shifter_operand + oldC */
12352             name = "adc"; goto rd_eq_rn_op_SO_op_oldC;
12353          case BITS4(0,1,1,0): /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
12354             name = "sbc"; goto rd_eq_rn_op_SO_op_oldC;
12355          case BITS4(0,1,1,1): /* RSC:  Rd = shifter_operand - Rn - (oldC ^ 1) */
12356             name = "rsc"; goto rd_eq_rn_op_SO_op_oldC;
12357          rd_eq_rn_op_SO_op_oldC: {
12358             // FIXME: shco isn't used for anything.  Get rid of it.
12359             rNt = newTemp(Ity_I32);
12360             assign(rNt, getIRegA(rN));
12361             ok = mk_shifter_operand(
12362                     INSN(25,25), INSN(11,0), 
12363                     &shop, bitS ? &shco : NULL, dis_buf
12364                  );
12365             if (!ok)
12366                break;
12367             oldC = newTemp(Ity_I32);
12368             assign( oldC, mk_armg_calculate_flag_c() );
12369             res = newTemp(Ity_I32);
12370             // compute the main result
12371             switch (INSN(24,21)) {
12372                case BITS4(0,1,0,1): /* ADC */
12373                   assign(res,
12374                          binop(Iop_Add32,
12375                                binop(Iop_Add32, mkexpr(rNt), mkexpr(shop)),
12376                                mkexpr(oldC) ));
12377                   break;
12378                case BITS4(0,1,1,0): /* SBC */
12379                   assign(res,
12380                          binop(Iop_Sub32,
12381                                binop(Iop_Sub32, mkexpr(rNt), mkexpr(shop)),
12382                                binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
12383                   break;
12384                case BITS4(0,1,1,1): /* RSC */
12385                   assign(res,
12386                          binop(Iop_Sub32,
12387                                binop(Iop_Sub32, mkexpr(shop), mkexpr(rNt)),
12388                                binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
12389                   break;
12390                default:
12391                   vassert(0);
12392             }
12393             // but don't commit it until after we've finished
12394             // all necessary reads from the guest state
12395             // now safe to put the main result
12396             putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
12397             // XXXX!! not safe to read any guest state after
12398             // this point (I think the code below doesn't do that).
12399             if (!bitS)
12400                vassert(shco == IRTemp_INVALID);
12401             /* Update the flags thunk if necessary */
12402             if (bitS) {
12403                vassert(shco != IRTemp_INVALID);
12404                switch (INSN(24,21)) {
12405                   case BITS4(0,1,0,1): /* ADC */
12406                      setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
12407                                         rNt, shop, oldC, condT );
12408                      break;
12409                   case BITS4(0,1,1,0): /* SBC */
12410                      setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
12411                                         rNt, shop, oldC, condT );
12412                      break;
12413                   case BITS4(0,1,1,1): /* RSC */
12414                      setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
12415                                         shop, rNt, oldC, condT );
12416                      break;
12417                   default:
12418                      vassert(0);
12419                }
12420             }
12421             DIP("%s%s%s r%u, r%u, %s\n",
12422                 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
12423             goto decode_success;
12424          }
12425
12426          /* --------- ??? --------- */
12427          default:
12428             break;
12429       }
12430    } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */
12431
12432    /* --------------------- Load/store (ubyte & word) -------- */
12433    // LDR STR LDRB STRB
12434    /*                 31   27   23   19 15 11    6   4 3  # highest bit
12435                         28   24   20 16 12
12436       A5-20   1 | 16  cond 0101 UB0L Rn Rd imm12
12437       A5-22   1 | 32  cond 0111 UBOL Rn Rd imm5  sh2 0 Rm
12438       A5-24   2 | 16  cond 0101 UB1L Rn Rd imm12
12439       A5-26   2 | 32  cond 0111 UB1L Rn Rd imm5  sh2 0 Rm
12440       A5-28   3 | 16  cond 0100 UB0L Rn Rd imm12
12441       A5-32   3 | 32  cond 0110 UB0L Rn Rd imm5  sh2 0 Rm
12442    */
12443    /* case coding:
12444              1   at-ea               (access at ea)
12445              2   at-ea-then-upd      (access at ea, then Rn = ea)
12446              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
12447       ea coding
12448              16  Rn +/- imm12
12449              32  Rn +/- Rm sh2 imm5
12450    */
12451    /* Quickly skip over all of this for hopefully most instructions */
12452    if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0))
12453       goto after_load_store_ubyte_or_word;
12454
12455    summary = 0;
12456    
12457    /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) {
12458       summary = 1 | 16;
12459    }
12460    else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0
12461                                           && INSN(4,4) == 0) {
12462       summary = 1 | 32;
12463    }
12464    else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) {
12465       summary = 2 | 16;
12466    }
12467    else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1
12468                                           && INSN(4,4) == 0) {
12469       summary = 2 | 32;
12470    }
12471    else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) {
12472       summary = 3 | 16;
12473    }
12474    else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0
12475                                           && INSN(4,4) == 0) {
12476       summary = 3 | 32;
12477    }
12478    else goto after_load_store_ubyte_or_word;
12479
12480    { UInt rN = (insn >> 16) & 0xF; /* 19:16 */
12481      UInt rD = (insn >> 12) & 0xF; /* 15:12 */
12482      UInt rM = (insn >> 0)  & 0xF; /*  3:0  */
12483      UInt bU = (insn >> 23) & 1;      /* 23 */
12484      UInt bB = (insn >> 22) & 1;      /* 22 */
12485      UInt bL = (insn >> 20) & 1;      /* 20 */
12486      UInt imm12 = (insn >> 0) & 0xFFF; /* 11:0 */
12487      UInt imm5  = (insn >> 7) & 0x1F;  /* 11:7 */
12488      UInt sh2   = (insn >> 5) & 3;     /* 6:5 */
12489
12490      /* Skip some invalid cases, which would lead to two competing
12491         updates to the same register, or which are otherwise
12492         disallowed by the spec. */
12493      switch (summary) {
12494         case 1 | 16:
12495            break;
12496         case 1 | 32: 
12497            if (rM == 15) goto after_load_store_ubyte_or_word;
12498            break;
12499         case 2 | 16: case 3 | 16:
12500            if (rN == 15) goto after_load_store_ubyte_or_word;
12501            if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
12502            break;
12503         case 2 | 32: case 3 | 32:
12504            if (rM == 15) goto after_load_store_ubyte_or_word;
12505            if (rN == 15) goto after_load_store_ubyte_or_word;
12506            if (rN == rM) goto after_load_store_ubyte_or_word;
12507            if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
12508            break;
12509         default:
12510            vassert(0);
12511      }
12512
12513      /* Now, we can't do a conditional load or store, since that very
12514         likely will generate an exception.  So we have to take a side
12515         exit at this point if the condition is false. */
12516      if (condT != IRTemp_INVALID) {
12517         mk_skip_over_A32_if_cond_is_false( condT );
12518         condT = IRTemp_INVALID;
12519      }
12520      /* Ok, now we're unconditional.  Do the load or store. */
12521
12522      /* compute the effective address.  Bind it to a tmp since we
12523         may need to use it twice. */
12524      IRExpr* eaE = NULL;
12525      switch (summary & 0xF0) {
12526         case 16:
12527            eaE = mk_EA_reg_plusminus_imm12( rN, bU, imm12, dis_buf );
12528            break;
12529         case 32:
12530            eaE = mk_EA_reg_plusminus_shifted_reg( rN, bU, rM, sh2, imm5,
12531                                                   dis_buf );
12532            break;
12533      }
12534      vassert(eaE);
12535      IRTemp eaT = newTemp(Ity_I32);
12536      assign(eaT, eaE);
12537
12538      /* get the old Rn value */
12539      IRTemp rnT = newTemp(Ity_I32);
12540      assign(rnT, getIRegA(rN));
12541
12542      /* decide on the transfer address */
12543      IRTemp taT = IRTemp_INVALID;
12544      switch (summary & 0x0F) {
12545         case 1: case 2: taT = eaT; break;
12546         case 3:         taT = rnT; break;
12547      }
12548      vassert(taT != IRTemp_INVALID);
12549
12550      if (bL == 0) {
12551        /* Store.  If necessary, update the base register before the
12552           store itself, so that the common idiom of "str rX, [sp,
12553           #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push
12554           rX") doesn't cause Memcheck to complain that the access is
12555           below the stack pointer.  Also, not updating sp before the
12556           store confuses Valgrind's dynamic stack-extending logic.  So
12557           do it before the store.  Hence we need to snarf the store
12558           data before doing the basereg update. */
12559
12560         /* get hold of the data to be stored */
12561         IRTemp rDt = newTemp(Ity_I32);
12562         assign(rDt, getIRegA(rD));
12563
12564         /* Update Rn if necessary. */
12565         switch (summary & 0x0F) {
12566            case 2: case 3:
12567               putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
12568               break;
12569         }
12570
12571         /* generate the transfer */
12572         if (bB == 0) { // word store
12573            storeLE( mkexpr(taT), mkexpr(rDt) );
12574         } else { // byte store
12575            vassert(bB == 1);
12576            storeLE( mkexpr(taT), unop(Iop_32to8, mkexpr(rDt)) );
12577         }
12578
12579      } else {
12580         /* Load */
12581         vassert(bL == 1);
12582
12583         /* generate the transfer */
12584         if (bB == 0) { // word load
12585            putIRegA( rD, loadLE(Ity_I32, mkexpr(taT)),
12586                      IRTemp_INVALID, Ijk_Boring );
12587         } else { // byte load
12588            vassert(bB == 1);
12589            putIRegA( rD, unop(Iop_8Uto32, loadLE(Ity_I8, mkexpr(taT))),
12590                      IRTemp_INVALID, Ijk_Boring );
12591         }
12592
12593         /* Update Rn if necessary. */
12594         switch (summary & 0x0F) {
12595            case 2: case 3:
12596               // should be assured by logic above:
12597               if (bL == 1)
12598                  vassert(rD != rN); /* since we just wrote rD */
12599               putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
12600               break;
12601         }
12602      }
12603  
12604      switch (summary & 0x0F) {
12605         case 1:  DIP("%sr%s%s r%u, %s\n",
12606                      bL == 0 ? "st" : "ld",
12607                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
12608                  break;
12609         case 2:  DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
12610                      bL == 0 ? "st" : "ld",
12611                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
12612                  break;
12613         case 3:  DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
12614                      bL == 0 ? "st" : "ld",
12615                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
12616                  break;
12617         default: vassert(0);
12618      }
12619
12620      /* XXX deal with alignment constraints */
12621
12622      goto decode_success;
12623
12624      /* Complications:
12625
12626         For all loads: if the Amode specifies base register
12627         writeback, and the same register is specified for Rd and Rn,
12628         the results are UNPREDICTABLE.
12629
12630         For all loads and stores: if R15 is written, branch to
12631         that address afterwards.
12632
12633         STRB: straightforward
12634         LDRB: loaded data is zero extended
12635         STR:  lowest 2 bits of address are ignored
12636         LDR:  if the lowest 2 bits of the address are nonzero
12637               then the loaded value is rotated right by 8 * the lowest 2 bits
12638      */
12639    }
12640
12641   after_load_store_ubyte_or_word:
12642
12643    /* --------------------- Load/store (sbyte & hword) -------- */
12644    // LDRH LDRSH STRH LDRSB
12645    /*                 31   27   23   19 15 11   7    3     # highest bit
12646                         28   24   20 16 12    8    4    0
12647       A5-36   1 | 16  cond 0001 U10L Rn Rd im4h 1SH1 im4l
12648       A5-38   1 | 32  cond 0001 U00L Rn Rd 0000 1SH1 Rm
12649       A5-40   2 | 16  cond 0001 U11L Rn Rd im4h 1SH1 im4l
12650       A5-42   2 | 32  cond 0001 U01L Rn Rd 0000 1SH1 Rm
12651       A5-44   3 | 16  cond 0000 U10L Rn Rd im4h 1SH1 im4l
12652       A5-46   3 | 32  cond 0000 U00L Rn Rd 0000 1SH1 Rm
12653    */
12654    /* case coding:
12655              1   at-ea               (access at ea)
12656              2   at-ea-then-upd      (access at ea, then Rn = ea)
12657              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
12658       ea coding
12659              16  Rn +/- imm8
12660              32  Rn +/- Rm
12661    */
12662    /* Quickly skip over all of this for hopefully most instructions */
12663    if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
12664       goto after_load_store_sbyte_or_hword;
12665
12666    /* Check the "1SH1" thing. */
12667    if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1))
12668       goto after_load_store_sbyte_or_hword;
12669
12670    summary = 0;
12671
12672    /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) {
12673       summary = 1 | 16;
12674    }
12675    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) {
12676       summary = 1 | 32;
12677    }
12678    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) {
12679       summary = 2 | 16;
12680    }
12681    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) {
12682       summary = 2 | 32;
12683    }
12684    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) {
12685       summary = 3 | 16;
12686    }
12687    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) {
12688       summary = 3 | 32;
12689    }
12690    else goto after_load_store_sbyte_or_hword;
12691
12692    { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
12693      UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
12694      UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
12695      UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
12696      UInt bL   = (insn >> 20) & 1;   /* 20 L=1 load, L=0 store */
12697      UInt bH   = (insn >> 5) & 1;    /* H=1 halfword, H=0 byte */
12698      UInt bS   = (insn >> 6) & 1;    /* S=1 signed, S=0 unsigned */
12699      UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
12700
12701      /* Skip combinations that are either meaningless or already
12702         handled by main word-or-unsigned-byte load-store
12703         instructions. */
12704      if (bS == 0 && bH == 0) /* "unsigned byte" */
12705         goto after_load_store_sbyte_or_hword;
12706      if (bS == 1 && bL == 0) /* "signed store" */
12707         goto after_load_store_sbyte_or_hword;
12708
12709      /* Require 11:8 == 0 for Rn +/- Rm cases */
12710      if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
12711         goto after_load_store_sbyte_or_hword;
12712
12713      /* Skip some invalid cases, which would lead to two competing
12714         updates to the same register, or which are otherwise
12715         disallowed by the spec. */
12716      switch (summary) {
12717         case 1 | 16:
12718            break;
12719         case 1 | 32: 
12720            if (rM == 15) goto after_load_store_sbyte_or_hword;
12721            break;
12722         case 2 | 16: case 3 | 16:
12723            if (rN == 15) goto after_load_store_sbyte_or_hword;
12724            if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
12725            break;
12726         case 2 | 32: case 3 | 32:
12727            if (rM == 15) goto after_load_store_sbyte_or_hword;
12728            if (rN == 15) goto after_load_store_sbyte_or_hword;
12729            if (rN == rM) goto after_load_store_sbyte_or_hword;
12730            if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
12731            break;
12732         default:
12733            vassert(0);
12734      }
12735
12736      /* Now, we can't do a conditional load or store, since that very
12737         likely will generate an exception.  So we have to take a side
12738         exit at this point if the condition is false. */
12739      if (condT != IRTemp_INVALID) {
12740         mk_skip_over_A32_if_cond_is_false( condT );
12741         condT = IRTemp_INVALID;
12742      }
12743      /* Ok, now we're unconditional.  Do the load or store. */
12744
12745      /* compute the effective address.  Bind it to a tmp since we
12746         may need to use it twice. */
12747      IRExpr* eaE = NULL;
12748      switch (summary & 0xF0) {
12749         case 16:
12750            eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
12751            break;
12752         case 32:
12753            eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
12754            break;
12755      }
12756      vassert(eaE);
12757      IRTemp eaT = newTemp(Ity_I32);
12758      assign(eaT, eaE);
12759
12760      /* get the old Rn value */
12761      IRTemp rnT = newTemp(Ity_I32);
12762      assign(rnT, getIRegA(rN));
12763
12764      /* decide on the transfer address */
12765      IRTemp taT = IRTemp_INVALID;
12766      switch (summary & 0x0F) {
12767         case 1: case 2: taT = eaT; break;
12768         case 3:         taT = rnT; break;
12769      }
12770      vassert(taT != IRTemp_INVALID);
12771
12772      /* halfword store  H 1  L 0  S 0
12773         uhalf load      H 1  L 1  S 0
12774         shalf load      H 1  L 1  S 1
12775         sbyte load      H 0  L 1  S 1
12776      */
12777      HChar* name = NULL;
12778      /* generate the transfer */
12779      /**/ if (bH == 1 && bL == 0 && bS == 0) { // halfword store
12780         storeLE( mkexpr(taT), unop(Iop_32to16, getIRegA(rD)) );
12781         name = "strh";
12782      }
12783      else if (bH == 1 && bL == 1 && bS == 0) { // uhalf load
12784         putIRegA( rD, unop(Iop_16Uto32, loadLE(Ity_I16, mkexpr(taT))),
12785                   IRTemp_INVALID, Ijk_Boring );
12786         name = "ldrh";
12787      }
12788      else if (bH == 1 && bL == 1 && bS == 1) { // shalf load
12789         putIRegA( rD, unop(Iop_16Sto32, loadLE(Ity_I16, mkexpr(taT))),
12790                   IRTemp_INVALID, Ijk_Boring );
12791         name = "ldrsh";
12792      }
12793      else if (bH == 0 && bL == 1 && bS == 1) { // sbyte load
12794         putIRegA( rD, unop(Iop_8Sto32, loadLE(Ity_I8, mkexpr(taT))),
12795                   IRTemp_INVALID, Ijk_Boring );
12796         name = "ldrsb";
12797      }
12798      else
12799         vassert(0); // should be assured by logic above
12800
12801      /* Update Rn if necessary. */
12802      switch (summary & 0x0F) {
12803         case 2: case 3:
12804            // should be assured by logic above:
12805            if (bL == 1)
12806               vassert(rD != rN); /* since we just wrote rD */
12807            putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
12808            break;
12809      }
12810
12811      switch (summary & 0x0F) {
12812         case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
12813                  break;
12814         case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
12815                      name, nCC(INSN_COND), rD, dis_buf);
12816                  break;
12817         case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
12818                      name, nCC(INSN_COND), rD, dis_buf);
12819                  break;
12820         default: vassert(0);
12821      }
12822
12823      /* XXX deal with alignment constraints */
12824
12825      goto decode_success;
12826
12827      /* Complications:
12828
12829         For all loads: if the Amode specifies base register
12830         writeback, and the same register is specified for Rd and Rn,
12831         the results are UNPREDICTABLE.
12832
12833         For all loads and stores: if R15 is written, branch to
12834         that address afterwards.
12835
12836         Misaligned halfword stores => Unpredictable
12837         Misaligned halfword loads  => Unpredictable
12838      */
12839    }
12840
12841   after_load_store_sbyte_or_hword:
12842
12843    /* --------------------- Load/store multiple -------------- */
12844    // LD/STMIA LD/STMIB LD/STMDA LD/STMDB
12845    // Remarkably complex and difficult to get right
12846    // match 27:20 as 100XX0WL
12847    if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) {
12848       // A5-50 LD/STMIA  cond 1000 10WL Rn RegList
12849       // A5-51 LD/STMIB  cond 1001 10WL Rn RegList
12850       // A5-53 LD/STMDA  cond 1000 00WL Rn RegList
12851       // A5-53 LD/STMDB  cond 1001 00WL Rn RegList
12852       //                   28   24   20 16       0
12853
12854       UInt bINC    = (insn >> 23) & 1;
12855       UInt bBEFORE = (insn >> 24) & 1;
12856
12857       UInt bL      = (insn >> 20) & 1;  /* load=1, store=0 */
12858       UInt bW      = (insn >> 21) & 1;  /* Rn wback=1, no wback=0 */
12859       UInt rN      = (insn >> 16) & 0xF;
12860       UInt regList = insn & 0xFFFF;
12861       /* Skip some invalid cases, which would lead to two competing
12862          updates to the same register, or which are otherwise
12863          disallowed by the spec.  Note the test above has required
12864          that S == 0, since that looks like a kernel-mode only thing.
12865          Done by forcing the real pattern, viz 100XXSWL to actually be
12866          100XX0WL. */
12867       if (rN == 15) goto after_load_store_multiple;
12868       // reglist can't be empty
12869       if (regList == 0) goto after_load_store_multiple;
12870       // if requested to writeback Rn, and this is a load instruction,
12871       // then Rn can't appear in RegList, since we'd have two competing
12872       // new values for Rn.  We do however accept this case for store
12873       // instructions.
12874       if (bW == 1 && bL == 1 && ((1 << rN) & regList) > 0)
12875          goto after_load_store_multiple;
12876
12877       /* Now, we can't do a conditional load or store, since that very
12878          likely will generate an exception.  So we have to take a side
12879          exit at this point if the condition is false. */
12880       if (condT != IRTemp_INVALID) {
12881          mk_skip_over_A32_if_cond_is_false( condT );
12882          condT = IRTemp_INVALID;
12883       }
12884
12885       /* Ok, now we're unconditional.  Generate the IR. */
12886       mk_ldm_stm( True/*arm*/, rN, bINC, bBEFORE, bW, bL, regList );
12887
12888       DIP("%sm%c%c%s r%u%s, {0x%04x}\n",
12889           bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
12890           nCC(INSN_COND),
12891           rN, bW ? "!" : "", regList);
12892
12893       goto decode_success;
12894    }
12895
12896   after_load_store_multiple:
12897
12898    /* --------------------- Control flow --------------------- */
12899    // B, BL (Branch, or Branch-and-Link, to immediate offset)
12900    //
12901    if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) {
12902       UInt link   = (insn >> 24) & 1;
12903       UInt uimm24 = insn & ((1<<24)-1);
12904       Int  simm24 = (Int)uimm24;
12905       UInt dst    = guest_R15_curr_instr_notENC + 8
12906                     + (((simm24 << 8) >> 8) << 2);
12907       IRJumpKind jk = link ? Ijk_Call : Ijk_Boring;
12908       if (link) {
12909          putIRegA(14, mkU32(guest_R15_curr_instr_notENC + 4),
12910                       condT, Ijk_Boring);
12911       }
12912       if (condT == IRTemp_INVALID) {
12913          /* unconditional transfer to 'dst'.  See if we can simply
12914             continue tracing at the destination. */
12915          if (resteerOkFn( callback_opaque, (Addr64)dst )) {
12916             /* yes */
12917             dres.whatNext   = Dis_ResteerU;
12918             dres.continueAt = (Addr64)dst;
12919          } else {
12920             /* no; terminate the SB at this point. */
12921             irsb->next     = mkU32(dst);
12922             irsb->jumpkind = jk;
12923             dres.whatNext  = Dis_StopHere;
12924          }
12925          DIP("b%s 0x%x\n", link ? "l" : "", dst);
12926       } else {
12927          /* conditional transfer to 'dst' */
12928          HChar* comment = "";
12929
12930          /* First see if we can do some speculative chasing into one
12931             arm or the other.  Be conservative and only chase if
12932             !link, that is, this is a normal conditional branch to a
12933             known destination. */
12934          if (!link
12935              && resteerCisOk
12936              && vex_control.guest_chase_cond
12937              && dst < guest_R15_curr_instr_notENC
12938              && resteerOkFn( callback_opaque, (Addr64)(Addr32)dst) ) {
12939             /* Speculation: assume this backward branch is taken.  So
12940                we need to emit a side-exit to the insn following this
12941                one, on the negation of the condition, and continue at
12942                the branch target address (dst). */
12943             stmt( IRStmt_Exit( unop(Iop_Not1,
12944                                     unop(Iop_32to1, mkexpr(condT))),
12945                                Ijk_Boring,
12946                                IRConst_U32(guest_R15_curr_instr_notENC+4) ));
12947             dres.whatNext   = Dis_ResteerC;
12948             dres.continueAt = (Addr64)(Addr32)dst;
12949             comment = "(assumed taken)";
12950          }
12951          else
12952          if (!link
12953              && resteerCisOk
12954              && vex_control.guest_chase_cond
12955              && dst >= guest_R15_curr_instr_notENC
12956              && resteerOkFn( callback_opaque, 
12957                              (Addr64)(Addr32)
12958                                      (guest_R15_curr_instr_notENC+4)) ) {
12959             /* Speculation: assume this forward branch is not taken.
12960                So we need to emit a side-exit to dst (the dest) and
12961                continue disassembling at the insn immediately
12962                following this one. */
12963             stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
12964                                Ijk_Boring,
12965                                IRConst_U32(dst) ));
12966             dres.whatNext   = Dis_ResteerC;
12967             dres.continueAt = (Addr64)(Addr32)
12968                                       (guest_R15_curr_instr_notENC+4);
12969             comment = "(assumed not taken)";
12970          }
12971          else {
12972             /* Conservative default translation - end the block at
12973                this point. */
12974          stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
12975                             jk, IRConst_U32(dst) ));
12976          irsb->next     = mkU32(guest_R15_curr_instr_notENC + 4);
12977          irsb->jumpkind = jk;
12978          dres.whatNext  = Dis_StopHere;
12979          }
12980          DIP("b%s%s 0x%x %s\n", link ? "l" : "", nCC(INSN_COND),
12981              dst, comment);
12982       }
12983       goto decode_success;
12984    }
12985
12986    // B, BL (Branch, or Branch-and-Link, to a register)
12987    // NB: interworking branch
12988    if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
12989        && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1)
12990        && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1)
12991            || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) {
12992       IRExpr* dst;
12993       UInt    link = (INSN(11,4) >> 1) & 1;
12994       UInt    rM   = INSN(3,0);
12995       // we don't decode the case (link && rM == 15), as that's
12996       // Unpredictable.
12997       if (!(link && rM == 15)) {
12998          if (condT != IRTemp_INVALID) {
12999             mk_skip_over_A32_if_cond_is_false( condT );
13000          }
13001          // rM contains an interworking address exactly as we require
13002          // (with continuation CPSR.T in bit 0), so we can use it
13003          // as-is, with no masking.
13004          dst = getIRegA(rM);
13005          if (link) {
13006             putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
13007                       IRTemp_INVALID/*because AL*/, Ijk_Boring );
13008          }
13009          irsb->next     = dst;
13010          irsb->jumpkind = link ? Ijk_Call
13011                                : (rM == 14 ? Ijk_Ret : Ijk_Boring);
13012          dres.whatNext  = Dis_StopHere;
13013          if (condT == IRTemp_INVALID) {
13014             DIP("b%sx r%u\n", link ? "l" : "", rM);
13015          } else {
13016             DIP("b%sx%s r%u\n", link ? "l" : "", nCC(INSN_COND), rM);
13017          }
13018          goto decode_success;
13019       }
13020       /* else: (link && rM == 15): just fall through */
13021    }
13022
13023    /* --- NB: ARM interworking branches are in NV space, hence
13024       are handled elsewhere by decode_NV_instruction.
13025       ---
13026    */
13027
13028    /* --------------------- Clz --------------------- */
13029    // CLZ
13030    if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0)
13031        && INSN(19,16) == BITS4(1,1,1,1)
13032        && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) {
13033       UInt rD = INSN(15,12);
13034       UInt rM = INSN(3,0);
13035       IRTemp arg = newTemp(Ity_I32);
13036       IRTemp res = newTemp(Ity_I32);
13037       assign(arg, getIRegA(rM));
13038       assign(res, IRExpr_Mux0X(
13039                      unop(Iop_1Uto8,binop(Iop_CmpEQ32, mkexpr(arg),
13040                                                        mkU32(0))),
13041                      unop(Iop_Clz32, mkexpr(arg)),
13042                      mkU32(32)
13043             ));
13044       putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13045       DIP("clz%s r%u, r%u\n", nCC(INSN_COND), rD, rM);
13046       goto decode_success;
13047    }
13048
13049    /* --------------------- Mul etc --------------------- */
13050    // MUL
13051    if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
13052        && INSN(15,12) == BITS4(0,0,0,0)
13053        && INSN(7,4) == BITS4(1,0,0,1)) {
13054       UInt bitS = (insn >> 20) & 1; /* 20:20 */
13055       UInt rD = INSN(19,16);
13056       UInt rS = INSN(11,8);
13057       UInt rM = INSN(3,0);
13058       if (rD == 15 || rM == 15 || rS == 15) {
13059          /* Unpredictable; don't decode; fall through */
13060       } else {
13061          IRTemp argL = newTemp(Ity_I32);
13062          IRTemp argR = newTemp(Ity_I32);
13063          IRTemp res  = newTemp(Ity_I32);
13064          IRTemp oldC = IRTemp_INVALID;
13065          IRTemp oldV = IRTemp_INVALID;
13066          assign( argL, getIRegA(rM));
13067          assign( argR, getIRegA(rS));
13068          assign( res, binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) );
13069          if (bitS) {
13070             oldC = newTemp(Ity_I32);
13071             assign(oldC, mk_armg_calculate_flag_c());
13072             oldV = newTemp(Ity_I32);
13073             assign(oldV, mk_armg_calculate_flag_v());
13074          }
13075          // now update guest state
13076          putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
13077          if (bitS) {
13078             IRTemp pair = newTemp(Ity_I32);
13079             assign( pair, binop(Iop_Or32,
13080                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13081                                 mkexpr(oldV)) );
13082             setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
13083          }
13084          DIP("mul%c%s r%u, r%u, r%u\n",
13085              bitS ? 's' : ' ', nCC(INSN_COND), rD, rM, rS);
13086          goto decode_success;
13087       }
13088       /* fall through */
13089    }
13090
13091    // MLA, MLS
13092    if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13093        && INSN(7,4) == BITS4(1,0,0,1)) {
13094       UInt bitS  = (insn >> 20) & 1; /* 20:20 */
13095       UInt isMLS = (insn >> 22) & 1; /* 22:22 */
13096       UInt rD = INSN(19,16);
13097       UInt rN = INSN(15,12);
13098       UInt rS = INSN(11,8);
13099       UInt rM = INSN(3,0);
13100       if (bitS == 1 && isMLS == 1) {
13101          /* This isn't allowed (MLS that sets flags).  don't decode;
13102             fall through */
13103       }
13104       else
13105       if (rD == 15 || rM == 15 || rS == 15 || rN == 15) {
13106          /* Unpredictable; don't decode; fall through */
13107       } else {
13108          IRTemp argL = newTemp(Ity_I32);
13109          IRTemp argR = newTemp(Ity_I32);
13110          IRTemp argP = newTemp(Ity_I32);
13111          IRTemp res  = newTemp(Ity_I32);
13112          IRTemp oldC = IRTemp_INVALID;
13113          IRTemp oldV = IRTemp_INVALID;
13114          assign( argL, getIRegA(rM));
13115          assign( argR, getIRegA(rS));
13116          assign( argP, getIRegA(rN));
13117          assign( res, binop(isMLS ? Iop_Sub32 : Iop_Add32,
13118                             mkexpr(argP),
13119                             binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) ));
13120          if (bitS) {
13121             vassert(!isMLS); // guaranteed above
13122             oldC = newTemp(Ity_I32);
13123             assign(oldC, mk_armg_calculate_flag_c());
13124             oldV = newTemp(Ity_I32);
13125             assign(oldV, mk_armg_calculate_flag_v());
13126          }
13127          // now update guest state
13128          putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
13129          if (bitS) {
13130             IRTemp pair = newTemp(Ity_I32);
13131             assign( pair, binop(Iop_Or32,
13132                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13133                                 mkexpr(oldV)) );
13134             setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
13135          }
13136          DIP("ml%c%c%s r%u, r%u, r%u, r%u\n",
13137              isMLS ? 's' : 'a', bitS ? 's' : ' ',
13138              nCC(INSN_COND), rD, rM, rS, rN);
13139          goto decode_success;
13140       }
13141       /* fall through */
13142    }
13143
13144    // SMULL, UMULL
13145    if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13146        && INSN(7,4) == BITS4(1,0,0,1)) {
13147       UInt bitS = (insn >> 20) & 1; /* 20:20 */
13148       UInt rDhi = INSN(19,16);
13149       UInt rDlo = INSN(15,12);
13150       UInt rS   = INSN(11,8);
13151       UInt rM   = INSN(3,0);
13152       UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
13153       if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
13154          /* Unpredictable; don't decode; fall through */
13155       } else {
13156          IRTemp argL  = newTemp(Ity_I32);
13157          IRTemp argR  = newTemp(Ity_I32);
13158          IRTemp res   = newTemp(Ity_I64);
13159          IRTemp resHi = newTemp(Ity_I32);
13160          IRTemp resLo = newTemp(Ity_I32);
13161          IRTemp oldC  = IRTemp_INVALID;
13162          IRTemp oldV  = IRTemp_INVALID;
13163          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
13164          assign( argL, getIRegA(rM));
13165          assign( argR, getIRegA(rS));
13166          assign( res, binop(mulOp, mkexpr(argL), mkexpr(argR)) );
13167          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
13168          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
13169          if (bitS) {
13170             oldC = newTemp(Ity_I32);
13171             assign(oldC, mk_armg_calculate_flag_c());
13172             oldV = newTemp(Ity_I32);
13173             assign(oldV, mk_armg_calculate_flag_v());
13174          }
13175          // now update guest state
13176          putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
13177          putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
13178          if (bitS) {
13179             IRTemp pair = newTemp(Ity_I32);
13180             assign( pair, binop(Iop_Or32,
13181                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13182                                 mkexpr(oldV)) );
13183             setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
13184          }
13185          DIP("%cmull%c%s r%u, r%u, r%u, r%u\n",
13186              isS ? 's' : 'u', bitS ? 's' : ' ',
13187              nCC(INSN_COND), rDlo, rDhi, rM, rS);
13188          goto decode_success;
13189       }
13190       /* fall through */
13191    }
13192
13193    // SMLAL, UMLAL
13194    if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13195        && INSN(7,4) == BITS4(1,0,0,1)) {
13196       UInt bitS = (insn >> 20) & 1; /* 20:20 */
13197       UInt rDhi = INSN(19,16);
13198       UInt rDlo = INSN(15,12);
13199       UInt rS   = INSN(11,8);
13200       UInt rM   = INSN(3,0);
13201       UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
13202       if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
13203          /* Unpredictable; don't decode; fall through */
13204       } else {
13205          IRTemp argL  = newTemp(Ity_I32);
13206          IRTemp argR  = newTemp(Ity_I32);
13207          IRTemp old   = newTemp(Ity_I64);
13208          IRTemp res   = newTemp(Ity_I64);
13209          IRTemp resHi = newTemp(Ity_I32);
13210          IRTemp resLo = newTemp(Ity_I32);
13211          IRTemp oldC  = IRTemp_INVALID;
13212          IRTemp oldV  = IRTemp_INVALID;
13213          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
13214          assign( argL, getIRegA(rM));
13215          assign( argR, getIRegA(rS));
13216          assign( old, binop(Iop_32HLto64, getIRegA(rDhi), getIRegA(rDlo)) );
13217          assign( res, binop(Iop_Add64,
13218                             mkexpr(old),
13219                             binop(mulOp, mkexpr(argL), mkexpr(argR))) );
13220          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
13221          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
13222          if (bitS) {
13223             oldC = newTemp(Ity_I32);
13224             assign(oldC, mk_armg_calculate_flag_c());
13225             oldV = newTemp(Ity_I32);
13226             assign(oldV, mk_armg_calculate_flag_v());
13227          }
13228          // now update guest state
13229          putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
13230          putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
13231          if (bitS) {
13232             IRTemp pair = newTemp(Ity_I32);
13233             assign( pair, binop(Iop_Or32,
13234                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
13235                                 mkexpr(oldV)) );
13236             setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
13237          }
13238          DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n",
13239              isS ? 's' : 'u', bitS ? 's' : ' ', nCC(INSN_COND),
13240              rDlo, rDhi, rM, rS);
13241          goto decode_success;
13242       }
13243       /* fall through */
13244    }
13245
13246    /* --------------------- Msr etc --------------------- */
13247
13248    // MSR apsr, #imm
13249    if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0)
13250        && INSN(17,12) == BITS6(0,0,1,1,1,1)) {
13251       UInt write_ge    = INSN(18,18);
13252       UInt write_nzcvq = INSN(19,19);
13253       if (write_nzcvq || write_ge) {
13254          UInt   imm = (INSN(11,0) >> 0) & 0xFF;
13255          UInt   rot = 2 * ((INSN(11,0) >> 8) & 0xF);
13256          IRTemp immT = newTemp(Ity_I32);
13257          vassert(rot <= 30);
13258          imm = ROR32(imm, rot);
13259          assign(immT, mkU32(imm));
13260          desynthesise_APSR( write_nzcvq, write_ge, immT, condT );
13261          DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND),
13262              write_nzcvq ? "f" : "", write_ge ? "g" : "", imm);
13263          goto decode_success;
13264       }
13265       /* fall through */
13266    }
13267
13268    // MSR apsr, reg
13269    if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0) 
13270        && INSN(17,12) == BITS6(0,0,1,1,1,1)
13271        && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) {
13272       UInt rN          = INSN(3,0);
13273       UInt write_ge    = INSN(18,18);
13274       UInt write_nzcvq = INSN(19,19);
13275       if (rN != 15 && (write_nzcvq || write_ge)) {
13276          IRTemp rNt = newTemp(Ity_I32);
13277          assign(rNt, getIRegA(rN));
13278          desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
13279          DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND),
13280              write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
13281          goto decode_success;
13282       }
13283       /* fall through */
13284    }
13285
13286    // MRS rD, cpsr
13287    if ((insn & 0x0FFF0FFF) == 0x010F0000) {
13288       UInt rD   = INSN(15,12);
13289       if (rD != 15) {
13290          IRTemp apsr = synthesise_APSR();
13291          putIRegA( rD, mkexpr(apsr), condT, Ijk_Boring );
13292          DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND), rD);
13293          goto decode_success;
13294       }
13295       /* fall through */
13296    }
13297
13298    /* --------------------- Svc --------------------- */
13299    if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) {
13300       UInt imm24 = (insn >> 0) & 0xFFFFFF;
13301       if (imm24 == 0) {
13302          /* A syscall.  We can't do this conditionally, hence: */
13303          if (condT != IRTemp_INVALID) {
13304             mk_skip_over_A32_if_cond_is_false( condT );
13305          }
13306          // AL after here
13307          irsb->next     = mkU32( guest_R15_curr_instr_notENC + 4 );
13308          irsb->jumpkind = Ijk_Sys_syscall;
13309          dres.whatNext  = Dis_StopHere;
13310          DIP("svc%s #0x%08x\n", nCC(INSN_COND), imm24);
13311          goto decode_success;
13312       }
13313       /* fall through */
13314    }
13315
13316    /* ------------------------ swp ------------------------ */
13317
13318    // SWP, SWPB
13319    if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
13320        && BITS4(0,0,0,0) == INSN(11,8)
13321        && BITS4(1,0,0,1) == INSN(7,4)) {
13322       UInt   rN   = INSN(19,16);
13323       UInt   rD   = INSN(15,12);
13324       UInt   rM   = INSN(3,0);
13325       IRTemp tRn  = newTemp(Ity_I32);
13326       IRTemp tNew = newTemp(Ity_I32);
13327       IRTemp tOld = IRTemp_INVALID;
13328       IRTemp tSC1 = newTemp(Ity_I1);
13329       UInt   isB  = (insn >> 22) & 1;
13330
13331       if (rD == 15 || rN == 15 || rM == 15 || rN == rM || rN == rD) {
13332          /* undecodable; fall through */
13333       } else {
13334          /* make unconditional */
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.  Generate a LL-SC loop. */
13340          assign(tRn, getIRegA(rN));
13341          assign(tNew, getIRegA(rM));
13342          if (isB) {
13343             /* swpb */
13344             tOld = newTemp(Ity_I8);
13345             stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
13346                               NULL/*=>isLL*/) );
13347             stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
13348                               unop(Iop_32to8, mkexpr(tNew))) );
13349          } else {
13350             /* swp */
13351             tOld = newTemp(Ity_I32);
13352             stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
13353                               NULL/*=>isLL*/) );
13354             stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
13355                               mkexpr(tNew)) );
13356          }
13357          stmt( IRStmt_Exit(unop(Iop_Not1, mkexpr(tSC1)),
13358                            /*Ijk_NoRedir*/Ijk_Boring,
13359                            IRConst_U32(guest_R15_curr_instr_notENC)) );
13360          putIRegA(rD, isB ? unop(Iop_8Uto32, mkexpr(tOld)) : mkexpr(tOld),
13361                       IRTemp_INVALID, Ijk_Boring);
13362          DIP("swp%s%s r%u, r%u, [r%u]\n",
13363              isB ? "b" : "", nCC(INSN_COND), rD, rM, rN);
13364          goto decode_success;
13365       }
13366       /* fall through */
13367    }
13368
13369    /* ----------------------------------------------------------- */
13370    /* -- ARMv6 instructions                                    -- */
13371    /* ----------------------------------------------------------- */
13372
13373    /* --------------------- ldrex, strex --------------------- */
13374
13375    // LDREX
13376    if (0x01900F9F == (insn & 0x0FF00FFF)) {
13377       UInt rT = INSN(15,12);
13378       UInt rN = INSN(19,16);
13379       if (rT == 15 || rN == 15) {
13380          /* undecodable; fall through */
13381       } else {
13382          IRTemp res;
13383          /* make unconditional */
13384          if (condT != IRTemp_INVALID) {
13385             mk_skip_over_A32_if_cond_is_false( condT );
13386             condT = IRTemp_INVALID;
13387          }
13388          /* Ok, now we're unconditional.  Do the load. */
13389          res = newTemp(Ity_I32);
13390          stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN),
13391                            NULL/*this is a load*/) );
13392          putIRegA(rT, mkexpr(res), IRTemp_INVALID, Ijk_Boring);
13393          DIP("ldrex%s r%u, [r%u]\n", nCC(INSN_COND), rT, rN);
13394          goto decode_success;
13395       }
13396       /* fall through */
13397    }
13398
13399    // STREX
13400    if (0x01800F90 == (insn & 0x0FF00FF0)) {
13401       UInt rT = INSN(3,0);
13402       UInt rN = INSN(19,16);
13403       UInt rD = INSN(15,12);
13404       if (rT == 15 || rN == 15 || rD == 15
13405           || rD == rT || rD == rN) {
13406          /* undecodable; fall through */
13407       } else {
13408          IRTemp resSC1, resSC32;
13409
13410          /* make unconditional */
13411          if (condT != IRTemp_INVALID) {
13412             mk_skip_over_A32_if_cond_is_false( condT );
13413             condT = IRTemp_INVALID;
13414          }
13415
13416          /* Ok, now we're unconditional.  Do the store. */
13417          resSC1 = newTemp(Ity_I1);
13418          stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), getIRegA(rT)) );
13419
13420          /* Set rD to 1 on failure, 0 on success.  Currently we have
13421             resSC1 == 0 on failure, 1 on success. */
13422          resSC32 = newTemp(Ity_I32);
13423          assign(resSC32,
13424                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
13425
13426          putIRegA(rD, mkexpr(resSC32),
13427                       IRTemp_INVALID, Ijk_Boring);
13428          DIP("strex%s r%u, r%u, [r%u]\n", nCC(INSN_COND), rD, rT, rN);
13429          goto decode_success;
13430       }
13431       /* fall through */
13432    }
13433
13434    /* --------------------- movw, movt --------------------- */
13435    if (0x03000000 == (insn & 0x0FF00000)
13436        || 0x03400000 == (insn & 0x0FF00000)) /* pray for CSE */ {
13437       UInt rD    = INSN(15,12);
13438       UInt imm16 = (insn & 0xFFF) | ((insn >> 4) & 0x0000F000);
13439       UInt isT   = (insn >> 22) & 1;
13440       if (rD == 15) {
13441          /* forget it */
13442       } else {
13443          if (isT) {
13444             putIRegA(rD,
13445                      binop(Iop_Or32,
13446                            binop(Iop_And32, getIRegA(rD), mkU32(0xFFFF)),
13447                            mkU32(imm16 << 16)),
13448                      condT, Ijk_Boring);
13449             DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
13450             goto decode_success;
13451          } else {
13452             putIRegA(rD, mkU32(imm16), condT, Ijk_Boring);
13453             DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
13454             goto decode_success;
13455          }
13456       }
13457       /* fall through */
13458    }
13459
13460    /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */
13461    /* FIXME: this is an exact duplicate of the Thumb version.  They
13462       should be commoned up. */
13463    if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0))
13464        && BITS4(1,1,1,1) == INSN(19,16)
13465        && BITS4(0,1,1,1) == INSN(7,4)
13466        && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) {
13467       UInt subopc = INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1);
13468       if (subopc != BITS4(0,0,0,1) && subopc != BITS4(0,1,0,1)) {
13469          Int    rot  = (INSN(11,8) >> 2) & 3;
13470          UInt   rM   = INSN(3,0);
13471          UInt   rD   = INSN(15,12);
13472          IRTemp srcT = newTemp(Ity_I32);
13473          IRTemp rotT = newTemp(Ity_I32);
13474          IRTemp dstT = newTemp(Ity_I32);
13475          HChar* nm   = "???";
13476          assign(srcT, getIRegA(rM));
13477          assign(rotT, genROR32(srcT, 8 * rot)); /* 0, 8, 16 or 24 only */
13478          switch (subopc) {
13479             case BITS4(0,1,1,0): // UXTB
13480                assign(dstT, unop(Iop_8Uto32, unop(Iop_32to8, mkexpr(rotT))));
13481                nm = "uxtb";
13482                break;
13483             case BITS4(0,0,1,0): // SXTB
13484                assign(dstT, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rotT))));
13485                nm = "sxtb";
13486                break;
13487             case BITS4(0,1,1,1): // UXTH
13488                assign(dstT, unop(Iop_16Uto32, unop(Iop_32to16, mkexpr(rotT))));
13489                nm = "uxth";
13490                break;
13491             case BITS4(0,0,1,1): // SXTH
13492                assign(dstT, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rotT))));
13493                nm = "sxth";
13494                break;
13495             case BITS4(0,1,0,0): // UXTB16
13496                assign(dstT, binop(Iop_And32, mkexpr(rotT), mkU32(0x00FF00FF)));
13497                nm = "uxtb16";
13498                break;
13499             case BITS4(0,0,0,0): { // SXTB16
13500                IRTemp lo32 = newTemp(Ity_I32);
13501                IRTemp hi32 = newTemp(Ity_I32);
13502                assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
13503                assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
13504                assign(
13505                   dstT,
13506                   binop(Iop_Or32,
13507                         binop(Iop_And32,
13508                               unop(Iop_8Sto32,
13509                                    unop(Iop_32to8, mkexpr(lo32))),
13510                               mkU32(0xFFFF)),
13511                         binop(Iop_Shl32,
13512                               unop(Iop_8Sto32,
13513                                    unop(Iop_32to8, mkexpr(hi32))),
13514                               mkU8(16))
13515                ));
13516                nm = "sxtb16";
13517                break;
13518             }
13519             default:
13520                vassert(0); // guarded by "if" above
13521          }
13522          putIRegA(rD, mkexpr(dstT), condT, Ijk_Boring);
13523          DIP("%s%s r%u, r%u, ROR #%u\n", nm, nCC(INSN_COND), rD, rM, rot);
13524          goto decode_success;
13525       }
13526       /* fall through */
13527    }
13528
13529    /* ------------------- bfi, bfc ------------------- */
13530    if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
13531        && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
13532       UInt rD  = INSN(15,12);
13533       UInt rN  = INSN(3,0);
13534       UInt msb = (insn >> 16) & 0x1F; /* 20:16 */
13535       UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
13536       if (rD == 15 || msb < lsb) {
13537          /* undecodable; fall through */
13538       } else {
13539          IRTemp src    = newTemp(Ity_I32);
13540          IRTemp olddst = newTemp(Ity_I32);
13541          IRTemp newdst = newTemp(Ity_I32);
13542          UInt   mask = 1 << (msb - lsb);
13543          mask = (mask - 1) + mask;
13544          vassert(mask != 0); // guaranteed by "msb < lsb" check above
13545          mask <<= lsb;
13546
13547          assign(src, rN == 15 ? mkU32(0) : getIRegA(rN));
13548          assign(olddst, getIRegA(rD));
13549          assign(newdst,
13550                 binop(Iop_Or32,
13551                    binop(Iop_And32,
13552                          binop(Iop_Shl32, mkexpr(src), mkU8(lsb)), 
13553                          mkU32(mask)),
13554                    binop(Iop_And32,
13555                          mkexpr(olddst),
13556                          mkU32(~mask)))
13557                );
13558
13559          putIRegA(rD, mkexpr(newdst), condT, Ijk_Boring);
13560
13561          if (rN == 15) {
13562             DIP("bfc%s r%u, #%u, #%u\n",
13563                 nCC(INSN_COND), rD, lsb, msb-lsb+1);
13564          } else {
13565             DIP("bfi%s r%u, r%u, #%u, #%u\n",
13566                 nCC(INSN_COND), rD, rN, lsb, msb-lsb+1);
13567          }
13568          goto decode_success;
13569       }
13570       /* fall through */
13571    }
13572
13573    /* ------------------- {u,s}bfx ------------------- */
13574    if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
13575        && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
13576       UInt rD  = INSN(15,12);
13577       UInt rN  = INSN(3,0);
13578       UInt wm1 = (insn >> 16) & 0x1F; /* 20:16 */
13579       UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
13580       UInt msb = lsb + wm1;
13581       UInt isU = (insn >> 22) & 1;    /* 22:22 */
13582       if (rD == 15 || rN == 15 || msb >= 32) {
13583          /* undecodable; fall through */
13584       } else {
13585          IRTemp src  = newTemp(Ity_I32);
13586          IRTemp tmp  = newTemp(Ity_I32);
13587          IRTemp res  = newTemp(Ity_I32);
13588          UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
13589          vassert(msb >= 0 && msb <= 31);
13590          vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
13591
13592          assign(src, getIRegA(rN));
13593          assign(tmp, binop(Iop_And32,
13594                            binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
13595                            mkU32(mask)));
13596          assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
13597                            binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
13598                            mkU8(31-wm1)));
13599
13600          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13601
13602          DIP("%s%s r%u, r%u, #%u, #%u\n",
13603              isU ? "ubfx" : "sbfx",
13604              nCC(INSN_COND), rD, rN, lsb, wm1 + 1);
13605          goto decode_success;
13606       }
13607       /* fall through */
13608    }
13609
13610    /* --------------------- Load/store doubleword ------------- */
13611    // LDRD STRD
13612    /*                 31   27   23   19 15 11   7    3     # highest bit
13613                         28   24   20 16 12    8    4    0
13614       A5-36   1 | 16  cond 0001 U100 Rn Rd im4h 11S1 im4l
13615       A5-38   1 | 32  cond 0001 U000 Rn Rd 0000 11S1 Rm
13616       A5-40   2 | 16  cond 0001 U110 Rn Rd im4h 11S1 im4l
13617       A5-42   2 | 32  cond 0001 U010 Rn Rd 0000 11S1 Rm
13618       A5-44   3 | 16  cond 0000 U100 Rn Rd im4h 11S1 im4l
13619       A5-46   3 | 32  cond 0000 U000 Rn Rd 0000 11S1 Rm
13620    */
13621    /* case coding:
13622              1   at-ea               (access at ea)
13623              2   at-ea-then-upd      (access at ea, then Rn = ea)
13624              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
13625       ea coding
13626              16  Rn +/- imm8
13627              32  Rn +/- Rm
13628    */
13629    /* Quickly skip over all of this for hopefully most instructions */
13630    if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
13631       goto after_load_store_doubleword;
13632
13633    /* Check the "11S1" thing. */
13634    if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1))
13635       goto after_load_store_doubleword;
13636
13637    summary = 0;
13638
13639    /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) {
13640       summary = 1 | 16;
13641    }
13642    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) {
13643       summary = 1 | 32;
13644    }
13645    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) {
13646       summary = 2 | 16;
13647    }
13648    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) {
13649       summary = 2 | 32;
13650    }
13651    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) {
13652       summary = 3 | 16;
13653    }
13654    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) {
13655       summary = 3 | 32;
13656    }
13657    else goto after_load_store_doubleword;
13658
13659    { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
13660      UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
13661      UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
13662      UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
13663      UInt bS   = (insn >> 5) & 1;    /* S=1 store, S=0 load */
13664      UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
13665
13666      /* Require rD to be an even numbered register */
13667      if ((rD & 1) != 0)
13668         goto after_load_store_doubleword;
13669
13670      /* Require 11:8 == 0 for Rn +/- Rm cases */
13671      if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
13672         goto after_load_store_doubleword;
13673
13674      /* Skip some invalid cases, which would lead to two competing
13675         updates to the same register, or which are otherwise
13676         disallowed by the spec. */
13677      switch (summary) {
13678         case 1 | 16:
13679            break;
13680         case 1 | 32: 
13681            if (rM == 15) goto after_load_store_doubleword;
13682            break;
13683         case 2 | 16: case 3 | 16:
13684            if (rN == 15) goto after_load_store_doubleword;
13685            if (bS == 0 && (rN == rD || rN == rD+1))
13686               goto after_load_store_doubleword;
13687            break;
13688         case 2 | 32: case 3 | 32:
13689            if (rM == 15) goto after_load_store_doubleword;
13690            if (rN == 15) goto after_load_store_doubleword;
13691            if (rN == rM) goto after_load_store_doubleword;
13692            if (bS == 0 && (rN == rD || rN == rD+1))
13693               goto after_load_store_doubleword;
13694            break;
13695         default:
13696            vassert(0);
13697      }
13698
13699      /* Now, we can't do a conditional load or store, since that very
13700         likely will generate an exception.  So we have to take a side
13701         exit at this point if the condition is false. */
13702      if (condT != IRTemp_INVALID) {
13703         mk_skip_over_A32_if_cond_is_false( condT );
13704         condT = IRTemp_INVALID;
13705      }
13706      /* Ok, now we're unconditional.  Do the load or store. */
13707
13708      /* compute the effective address.  Bind it to a tmp since we
13709         may need to use it twice. */
13710      IRExpr* eaE = NULL;
13711      switch (summary & 0xF0) {
13712         case 16:
13713            eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
13714            break;
13715         case 32:
13716            eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
13717            break;
13718      }
13719      vassert(eaE);
13720      IRTemp eaT = newTemp(Ity_I32);
13721      assign(eaT, eaE);
13722
13723      /* get the old Rn value */
13724      IRTemp rnT = newTemp(Ity_I32);
13725      assign(rnT, getIRegA(rN));
13726
13727      /* decide on the transfer address */
13728      IRTemp taT = IRTemp_INVALID;
13729      switch (summary & 0x0F) {
13730         case 1: case 2: taT = eaT; break;
13731         case 3:         taT = rnT; break;
13732      }
13733      vassert(taT != IRTemp_INVALID);
13734
13735      /* XXX deal with alignment constraints */
13736      /* XXX: but the A8 doesn't seem to trap for misaligned loads, so,
13737         ignore alignment issues for the time being. */
13738
13739      /* doubleword store  S 1
13740         doubleword load   S 0
13741      */
13742      HChar* name = NULL;
13743      /* generate the transfers */
13744      if (bS == 1) { // doubleword store
13745         storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(0)), getIRegA(rD+0) );
13746         storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(4)), getIRegA(rD+1) );
13747         name = "strd";
13748      } else { // doubleword load
13749         putIRegA( rD+0,
13750                   loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(0))),
13751                   IRTemp_INVALID, Ijk_Boring );
13752         putIRegA( rD+1,
13753                   loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(4))),
13754                   IRTemp_INVALID, Ijk_Boring );
13755         name = "ldrd";
13756      }
13757
13758      /* Update Rn if necessary. */
13759      switch (summary & 0x0F) {
13760         case 2: case 3:
13761            // should be assured by logic above:
13762            if (bS == 0) {
13763               vassert(rD+0 != rN); /* since we just wrote rD+0 */
13764               vassert(rD+1 != rN); /* since we just wrote rD+1 */
13765            }
13766            putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
13767            break;
13768      }
13769
13770      switch (summary & 0x0F) {
13771         case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
13772                  break;
13773         case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
13774                      name, nCC(INSN_COND), rD, dis_buf);
13775                  break;
13776         case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
13777                      name, nCC(INSN_COND), rD, dis_buf);
13778                  break;
13779         default: vassert(0);
13780      }
13781
13782      goto decode_success;
13783    }
13784
13785   after_load_store_doubleword:
13786
13787    /* ------------------- {s,u}xtab ------------- */
13788    if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
13789        && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
13790        && BITS4(0,1,1,1) == INSN(7,4)) {
13791       UInt rN  = INSN(19,16);
13792       UInt rD  = INSN(15,12);
13793       UInt rM  = INSN(3,0);
13794       UInt rot = (insn >> 10) & 3;
13795       UInt isU = INSN(22,22);
13796       if (rN == 15/*it's {S,U}XTB*/ || rD == 15 || rM == 15) {
13797          /* undecodable; fall through */
13798       } else {
13799          IRTemp srcL = newTemp(Ity_I32);
13800          IRTemp srcR = newTemp(Ity_I32);
13801          IRTemp res  = newTemp(Ity_I32);
13802          assign(srcR, getIRegA(rM));
13803          assign(srcL, getIRegA(rN));
13804          assign(res,  binop(Iop_Add32,
13805                             mkexpr(srcL),
13806                             unop(isU ? Iop_8Uto32 : Iop_8Sto32,
13807                                  unop(Iop_32to8, 
13808                                       genROR32(srcR, 8 * rot)))));
13809          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13810          DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n",
13811              isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
13812          goto decode_success;
13813       }
13814       /* fall through */
13815    }
13816
13817    /* ------------------- {s,u}xtah ------------- */
13818    if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
13819        && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
13820        && BITS4(0,1,1,1) == INSN(7,4)) {
13821       UInt rN  = INSN(19,16);
13822       UInt rD  = INSN(15,12);
13823       UInt rM  = INSN(3,0);
13824       UInt rot = (insn >> 10) & 3;
13825       UInt isU = INSN(22,22);
13826       if (rN == 15/*it's {S,U}XTH*/ || rD == 15 || rM == 15) {
13827          /* undecodable; fall through */
13828       } else {
13829          IRTemp srcL = newTemp(Ity_I32);
13830          IRTemp srcR = newTemp(Ity_I32);
13831          IRTemp res  = newTemp(Ity_I32);
13832          assign(srcR, getIRegA(rM));
13833          assign(srcL, getIRegA(rN));
13834          assign(res,  binop(Iop_Add32,
13835                             mkexpr(srcL),
13836                             unop(isU ? Iop_16Uto32 : Iop_16Sto32,
13837                                  unop(Iop_32to16, 
13838                                       genROR32(srcR, 8 * rot)))));
13839          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13840
13841          DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n",
13842              isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
13843          goto decode_success;
13844       }
13845       /* fall through */
13846    }
13847
13848    /* ------------------- rev16, rev ------------------ */
13849    if (INSN(27,16) == 0x6BF
13850        && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) {
13851       Bool isREV = INSN(11,4) == 0xF3;
13852       UInt rM    = INSN(3,0);
13853       UInt rD    = INSN(15,12);
13854       if (rM != 15 && rD != 15) {
13855          IRTemp rMt = newTemp(Ity_I32);
13856          assign(rMt, getIRegA(rM));
13857          IRTemp res = isREV ? gen_REV(rMt) : gen_REV16(rMt);
13858          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13859          DIP("rev%s%s r%u, r%u\n", isREV ? "" : "16",
13860              nCC(INSN_COND), rD, rM);
13861          goto decode_success;
13862       }
13863    }
13864
13865    /* ------------------- rbit ------------------ */
13866    if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) {
13867       UInt rD = INSN(15,12);
13868       UInt rM = INSN(3,0);
13869       if (rD != 15 && rM != 15) {
13870          IRTemp arg = newTemp(Ity_I32);
13871          assign(arg, getIRegA(rM));
13872          IRTemp res = gen_BITREV(arg);
13873          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
13874          DIP("rbit r%u, r%u\n", rD, rM);
13875          goto decode_success;
13876       }
13877    }
13878
13879    /* ------------------- smmul ------------------ */
13880    if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
13881        && INSN(15,12) == BITS4(1,1,1,1)
13882        && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
13883       UInt bitR = INSN(5,5);
13884       UInt rD = INSN(19,16);
13885       UInt rM = INSN(11,8);
13886       UInt rN = INSN(3,0);
13887       if (rD != 15 && rM != 15 && rN != 15) {
13888          IRExpr* res
13889          = unop(Iop_64HIto32,
13890                 binop(Iop_Add64,
13891                       binop(Iop_MullS32, getIRegA(rN), getIRegA(rM)),
13892                       mkU64(bitR ? 0x80000000ULL : 0ULL)));
13893          putIRegA(rD, res, condT, Ijk_Boring);
13894          DIP("smmul%s%s r%u, r%u, r%u\n",
13895              nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM);
13896          goto decode_success;
13897       }
13898    }
13899
13900    /* ------------------- NOP ------------------ */
13901    if (0x0320F000 == (insn & 0x0FFFFFFF)) {
13902       DIP("nop%s\n", nCC(INSN_COND));
13903       goto decode_success;
13904    }
13905
13906    /* ----------------------------------------------------------- */
13907    /* -- ARMv7 instructions                                    -- */
13908    /* ----------------------------------------------------------- */
13909
13910    /* -------------- read CP15 TPIDRURO register ------------- */
13911    /* mrc     p15, 0, r0, c13, c0, 3  up to
13912       mrc     p15, 0, r14, c13, c0, 3
13913    */
13914    /* I don't know whether this is really v7-only.  But anyway, we
13915       have to support it since arm-linux uses TPIDRURO as a thread
13916       state register. */
13917    if (0x0E1D0F70 == (insn & 0x0FFF0FFF)) {
13918       UInt rD = INSN(15,12);
13919       if (rD <= 14) {
13920          /* skip r15, that's too stupid to handle */
13921          putIRegA(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32),
13922                       condT, Ijk_Boring);
13923          DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND), rD);
13924          goto decode_success;
13925       }
13926       /* fall through */
13927    }
13928
13929    /* Handle various kinds of barriers.  This is rather indiscriminate
13930       in the sense that they are all turned into an IR Fence, which
13931       means we don't know which they are, so the back end has to
13932       re-emit them all when it comes acrosss an IR Fence.
13933    */
13934    switch (insn) {
13935       case 0xEE070F9A: /* v6 */
13936          /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7).  Data
13937             Synch Barrier -- ensures completion of memory accesses. */
13938          stmt( IRStmt_MBE(Imbe_Fence) );
13939          DIP("mcr 15, 0, r0, c7, c10, 4 (data synch barrier)\n");
13940          goto decode_success;
13941       case 0xEE070FBA: /* v6 */
13942          /* mcr 15, 0, r0, c7, c10, 5 (v6) equiv to DMB (v7).  Data
13943             Memory Barrier -- ensures ordering of memory accesses. */
13944          stmt( IRStmt_MBE(Imbe_Fence) );
13945          DIP("mcr 15, 0, r0, c7, c10, 5 (data memory barrier)\n");
13946          goto decode_success;
13947       case 0xEE070F95: /* v6 */
13948          /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7).
13949             Instruction Synchronisation Barrier (or Flush Prefetch
13950             Buffer) -- a pipe flush, I think.  I suspect we could
13951             ignore those, but to be on the safe side emit a fence
13952             anyway. */
13953          stmt( IRStmt_MBE(Imbe_Fence) );
13954          DIP("mcr 15, 0, r0, c7, c5, 4 (insn synch barrier)\n");
13955          goto decode_success;
13956       default:
13957          break;
13958    }
13959
13960    /* ----------------------------------------------------------- */
13961    /* -- VFP (CP 10, CP 11) instructions (in ARM mode)         -- */
13962    /* ----------------------------------------------------------- */
13963
13964    if (INSN_COND != ARMCondNV) {
13965       Bool ok_vfp = decode_CP10_CP11_instruction (
13966                        &dres, INSN(27,0), condT, INSN_COND,
13967                        False/*!isT*/
13968                     );
13969       if (ok_vfp)
13970          goto decode_success;
13971    }
13972
13973    /* ----------------------------------------------------------- */
13974    /* -- NEON instructions (in ARM mode)                       -- */
13975    /* ----------------------------------------------------------- */
13976
13977    /* These are all in NV space, and so are taken care of (far) above,
13978       by a call from this function to decode_NV_instruction(). */
13979
13980    /* ----------------------------------------------------------- */
13981    /* -- v6 media instructions (in ARM mode)                   -- */
13982    /* ----------------------------------------------------------- */
13983
13984    { Bool ok_v6m = decode_V6MEDIA_instruction(
13985                        &dres, INSN(27,0), condT, INSN_COND,
13986                        False/*!isT*/
13987                    );
13988      if (ok_v6m)
13989         goto decode_success;
13990    }
13991
13992    /* ----------------------------------------------------------- */
13993    /* -- Undecodable                                           -- */
13994    /* ----------------------------------------------------------- */
13995
13996    goto decode_failure;
13997    /*NOTREACHED*/
13998
13999   decode_failure:
14000    /* All decode failures end up here. */
14001    vex_printf("disInstr(arm): unhandled instruction: "
14002               "0x%x\n", insn);
14003    vex_printf("                 cond=%d(0x%x) 27:20=%u(0x%02x) "
14004                                 "4:4=%d "
14005                                 "3:0=%u(0x%x)\n",
14006               (Int)INSN_COND, (UInt)INSN_COND,
14007               (Int)INSN(27,20), (UInt)INSN(27,20),
14008               (Int)INSN(4,4),
14009               (Int)INSN(3,0), (UInt)INSN(3,0) );
14010
14011    /* Tell the dispatcher that this insn cannot be decoded, and so has
14012       not been executed, and (is currently) the next to be executed.
14013       R15 should be up-to-date since it made so at the start of each
14014       insn, but nevertheless be paranoid and update it again right
14015       now. */
14016    vassert(0 == (guest_R15_curr_instr_notENC & 3));
14017    llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
14018    irsb->next     = mkU32(guest_R15_curr_instr_notENC);
14019    irsb->jumpkind = Ijk_NoDecode;
14020    dres.whatNext  = Dis_StopHere;
14021    dres.len       = 0;
14022    return dres;
14023
14024   decode_success:
14025    /* All decode successes end up here. */
14026    DIP("\n");
14027
14028    vassert(dres.len == 4 || dres.len == 20);
14029
14030    /* Now then.  Do we have an implicit jump to r15 to deal with? */
14031    if (r15written) {
14032       /* If we get jump to deal with, we assume that there's been no
14033          other competing branch stuff previously generated for this
14034          insn.  That's reasonable, in the sense that the ARM insn set
14035          appears to declare as "Unpredictable" any instruction which
14036          generates more than one possible new value for r15.  Hence
14037          just assert.  The decoders themselves should check against
14038          all such instructions which are thusly Unpredictable, and
14039          decline to decode them.  Hence we should never get here if we
14040          have competing new values for r15, and hence it is safe to
14041          assert here. */
14042       vassert(dres.whatNext == Dis_Continue);
14043       vassert(irsb->next == NULL);
14044       vassert(irsb->jumpkind == Ijk_Boring);
14045       /* If r15 is unconditionally written, terminate the block by
14046          jumping to it.  If it's conditionally written, still
14047          terminate the block (a shame, but we can't do side exits to
14048          arbitrary destinations), but first jump to the next
14049          instruction if the condition doesn't hold. */
14050       /* We can't use getIReg(15) to get the destination, since that
14051          will produce r15+8, which isn't what we want.  Must use
14052          llGetIReg(15) instead. */
14053       if (r15guard == IRTemp_INVALID) {
14054          /* unconditional */
14055       } else {
14056          /* conditional */
14057          stmt( IRStmt_Exit(
14058                   unop(Iop_32to1,
14059                        binop(Iop_Xor32,
14060                              mkexpr(r15guard), mkU32(1))),
14061                   r15kind,
14062                   IRConst_U32(guest_R15_curr_instr_notENC + 4)
14063          ));
14064       }
14065       irsb->next     = llGetIReg(15);
14066       irsb->jumpkind = r15kind;
14067       dres.whatNext  = Dis_StopHere;
14068    }
14069
14070    return dres;
14071
14072 #  undef INSN_COND
14073 #  undef INSN
14074 }
14075
14076
14077 /*------------------------------------------------------------*/
14078 /*--- Disassemble a single Thumb2 instruction              ---*/
14079 /*------------------------------------------------------------*/
14080
14081 /* NB: in Thumb mode we do fetches of regs with getIRegT, which
14082    automagically adds 4 to fetches of r15.  However, writes to regs
14083    are done with putIRegT, which disallows writes to r15.  Hence any
14084    r15 writes and associated jumps have to be done "by hand". */
14085
14086 /* Disassemble a single Thumb instruction into IR.  The instruction is
14087    located in host memory at guest_instr, and has (decoded) guest IP
14088    of guest_R15_curr_instr_notENC, which will have been set before the
14089    call here. */
14090
14091 static   
14092 DisResult disInstr_THUMB_WRK (
14093              Bool         put_IP,
14094              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
14095              Bool         resteerCisOk,
14096              void*        callback_opaque,
14097              UChar*       guest_instr,
14098              VexArchInfo* archinfo,
14099              VexAbiInfo*  abiinfo
14100           )
14101 {
14102    /* A macro to fish bits out of insn0.  There's also INSN1, to fish
14103       bits out of insn1, but that's defined only after the end of the
14104       16-bit insn decoder, so as to stop it mistakenly being used
14105       therein. */
14106 #  define INSN0(_bMax,_bMin)  SLICE_UInt(((UInt)insn0), (_bMax), (_bMin))
14107
14108    DisResult dres;
14109    UShort    insn0; /* first 16 bits of the insn */
14110    //Bool      allow_VFP = False;
14111    //UInt      hwcaps = archinfo->hwcaps;
14112    HChar     dis_buf[128];  // big enough to hold LDMIA etc text
14113
14114    /* Summary result of the ITxxx backwards analysis: False == safe
14115       but suboptimal. */
14116    Bool guaranteedUnconditional = False;
14117
14118    /* What insn variants are we supporting today? */
14119    //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
14120    // etc etc
14121
14122    /* Set result defaults. */
14123    dres.whatNext   = Dis_Continue;
14124    dres.len        = 2;
14125    dres.continueAt = 0;
14126
14127    /* Set default actions for post-insn handling of writes to r15, if
14128       required. */
14129    r15written = False;
14130    r15guard   = IRTemp_INVALID; /* unconditional */
14131    r15kind    = Ijk_Boring;
14132
14133    /* Insns could be 2 or 4 bytes long.  Just get the first 16 bits at
14134       this point.  If we need the second 16, get them later.  We can't
14135       get them both out immediately because it risks a fault (very
14136       unlikely, but ..) if the second 16 bits aren't actually
14137       necessary. */
14138    insn0 = getUShortLittleEndianly( guest_instr );
14139
14140    if (0) vex_printf("insn: 0x%x\n", insn0);
14141
14142    DIP("\t(thumb) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
14143
14144    /* We may be asked to update the guest R15 before going further. */
14145    vassert(0 == (guest_R15_curr_instr_notENC & 1));
14146    if (put_IP) {
14147       llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
14148    }
14149
14150    /* ----------------------------------------------------------- */
14151    /* Spot "Special" instructions (see comment at top of file). */
14152    {
14153       UChar* code = (UChar*)guest_instr;
14154       /* Spot the 16-byte preamble: 
14155
14156          ea4f 0cfc  mov.w   ip, ip, ror #3
14157          ea4f 3c7c  mov.w   ip, ip, ror #13
14158          ea4f 7c7c  mov.w   ip, ip, ror #29
14159          ea4f 4cfc  mov.w   ip, ip, ror #19
14160       */
14161       UInt word1 = 0x0CFCEA4F;
14162       UInt word2 = 0x3C7CEA4F;
14163       UInt word3 = 0x7C7CEA4F;
14164       UInt word4 = 0x4CFCEA4F;
14165       if (getUIntLittleEndianly(code+ 0) == word1 &&
14166           getUIntLittleEndianly(code+ 4) == word2 &&
14167           getUIntLittleEndianly(code+ 8) == word3 &&
14168           getUIntLittleEndianly(code+12) == word4) {
14169          /* Got a "Special" instruction preamble.  Which one is it? */
14170          // 0x 0A 0A EA 4A
14171          if (getUIntLittleEndianly(code+16) == 0x0A0AEA4A
14172                                                /* orr.w r10,r10,r10 */) {
14173             /* R3 = client_request ( R4 ) */
14174             DIP("r3 = client_request ( %%r4 )\n");
14175             irsb->next     = mkU32( (guest_R15_curr_instr_notENC + 20) | 1 );
14176             irsb->jumpkind = Ijk_ClientReq;
14177             dres.whatNext  = Dis_StopHere;
14178             goto decode_success;
14179          }
14180          else
14181          // 0x 0B 0B EA 4B
14182          if (getUIntLittleEndianly(code+16) == 0x0B0BEA4B
14183                                                /* orr r11,r11,r11 */) {
14184             /* R3 = guest_NRADDR */
14185             DIP("r3 = guest_NRADDR\n");
14186             dres.len = 20;
14187             llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
14188             goto decode_success;
14189          }
14190          else
14191          // 0x 0C 0C EA 4C
14192          if (getUIntLittleEndianly(code+16) == 0x0C0CEA4C
14193                                                /* orr r12,r12,r12 */) {
14194             /*  branch-and-link-to-noredir R4 */
14195             DIP("branch-and-link-to-noredir r4\n");
14196             llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ));
14197             irsb->next     = getIRegT(4);
14198             irsb->jumpkind = Ijk_NoRedir;
14199             dres.whatNext  = Dis_StopHere;
14200             goto decode_success;
14201          }
14202          /* We don't know what it is.  Set insn0 so decode_failure
14203             can print the insn following the Special-insn preamble. */
14204          insn0 = getUShortLittleEndianly(code+16);
14205          goto decode_failure;
14206          /*NOTREACHED*/
14207       }
14208
14209    }
14210
14211    /* ----------------------------------------------------------- */
14212
14213    /* Main Thumb instruction decoder starts here.  It's a series of
14214       switches which examine ever longer bit sequences at the MSB of
14215       the instruction word, first for 16-bit insns, then for 32-bit
14216       insns. */
14217
14218    /* --- BEGIN ITxxx optimisation analysis --- */
14219    /* This is a crucial optimisation for the ITState boilerplate that
14220       follows.  Examine the 9 halfwords preceding this instruction,
14221       and if we are absolutely sure that none of them constitute an
14222       'it' instruction, then we can be sure that this instruction is
14223       not under the control of any 'it' instruction, and so
14224       guest_ITSTATE must be zero.  So write zero into ITSTATE right
14225       now, so that iropt can fold out almost all of the resulting
14226       junk.
14227
14228       If we aren't sure, we can always safely skip this step.  So be a
14229       bit conservative about it: only poke around in the same page as
14230       this instruction, lest we get a fault from the previous page
14231       that would not otherwise have happened.  The saving grace is
14232       that such skipping is pretty rare -- it only happens,
14233       statistically, 18/4096ths of the time, so is judged unlikely to
14234       be a performance problems.
14235
14236       FIXME: do better.  Take into account the number of insns covered
14237       by any IT insns we find, to rule out cases where an IT clearly
14238       cannot cover this instruction.  This would improve behaviour for
14239       branch targets immediately following an IT-guarded group that is
14240       not of full length.  Eg, (and completely ignoring issues of 16-
14241       vs 32-bit insn length):
14242
14243              ite cond
14244              insn1
14245              insn2
14246       label: insn3
14247              insn4
14248
14249       The 'it' only conditionalises insn1 and insn2.  However, the
14250       current analysis is conservative and considers insn3 and insn4
14251       also possibly guarded.  Hence if 'label:' is the start of a hot
14252       loop we will get a big performance hit.
14253    */
14254    {
14255       /* Summary result of this analysis: False == safe but
14256          suboptimal. */
14257       vassert(guaranteedUnconditional == False);
14258
14259       UInt pc = guest_R15_curr_instr_notENC;
14260       vassert(0 == (pc & 1));
14261
14262       UInt pageoff = pc & 0xFFF;
14263       if (pageoff >= 18) {
14264          /* It's safe to poke about in the 9 halfwords preceding this
14265             insn.  So, have a look at them. */
14266          guaranteedUnconditional = True; /* assume no 'it' insn found, till we do */
14267
14268          UShort* hwp = (UShort*)(HWord)pc;
14269          Int i;
14270          for (i = -1; i >= -9; i--) {
14271             /* We're in the same page.  (True, but commented out due
14272                to expense.) */
14273             /*
14274             vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 )
14275                       == ( pc & 0xFFFFF000 ) );
14276             */
14277             /* All valid IT instructions must have the form 0xBFxy,
14278                where x can be anything, but y must be nonzero. */
14279             if ((hwp[i] & 0xFF00) == 0xBF00 && (hwp[i] & 0xF) != 0) {
14280                /* might be an 'it' insn.  Play safe. */
14281                guaranteedUnconditional = False;
14282                break;
14283             }
14284          }
14285       }
14286    }
14287    /* --- END ITxxx optimisation analysis --- */
14288
14289    /* Generate the guarding condition for this insn, by examining
14290       ITSTATE.  Assign it to condT.  Also, generate new
14291       values for ITSTATE ready for stuffing back into the
14292       guest state, but don't actually do the Put yet, since it will
14293       need to stuffed back in only after the instruction gets to a
14294       point where it is sure to complete.  Mostly we let the code at
14295       decode_success handle this, but in cases where the insn contains
14296       a side exit, we have to update them before the exit. */
14297
14298    /* If the ITxxx optimisation analysis above could not prove that
14299       this instruction is guaranteed unconditional, we insert a
14300       lengthy IR preamble to compute the guarding condition at
14301       runtime.  If it can prove it (which obviously we hope is the
14302       normal case) then we insert a minimal preamble, which is
14303       equivalent to setting guest_ITSTATE to zero and then folding
14304       that through the full preamble (which completely disappears). */
14305
14306    IRTemp condT              = IRTemp_INVALID;
14307    IRTemp old_itstate        = IRTemp_INVALID;
14308    IRTemp new_itstate        = IRTemp_INVALID;
14309    IRTemp cond_AND_notInIT_T = IRTemp_INVALID;
14310
14311    if (guaranteedUnconditional) {
14312       /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
14313
14314       // ITSTATE = 0 :: I32
14315       IRTemp z32 = newTemp(Ity_I32);
14316       assign(z32, mkU32(0));
14317       put_ITSTATE(z32);
14318
14319       // old_itstate = 0 :: I32
14320       //
14321       // old_itstate = get_ITSTATE();
14322       old_itstate = z32; /* 0 :: I32 */
14323
14324       // new_itstate = old_itstate >> 8
14325       //             = 0 >> 8
14326       //             = 0 :: I32
14327       //
14328       // new_itstate = newTemp(Ity_I32);
14329       // assign(new_itstate,
14330       //        binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
14331       new_itstate = z32;
14332
14333       // ITSTATE = 0 :: I32(again)
14334       //
14335       // put_ITSTATE(new_itstate);
14336
14337       // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) )
14338       //        = calc_cond_dyn( xor(0,0xE0) )
14339       //        = calc_cond_dyn ( 0xE0 )
14340       //        = 1 :: I32
14341       // Not that this matters, since the computed value is not used:
14342       // see condT folding below
14343       //
14344       // IRTemp condT1 = newTemp(Ity_I32);
14345       // assign(condT1,
14346       //        mk_armg_calculate_condition_dyn(
14347       //           binop(Iop_Xor32,
14348       //                 binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
14349       //                 mkU32(0xE0))
14350       //       )
14351       // );
14352
14353       // condT = 32to8(and32(old_itstate,0xF0)) == 0  ? 1  : condT1
14354       //       = 32to8(and32(0,0xF0)) == 0  ? 1  : condT1
14355       //       = 32to8(0) == 0  ? 1  : condT1
14356       //       = 0 == 0  ? 1  : condT1
14357       //       = 1
14358       //
14359       // condT = newTemp(Ity_I32);
14360       // assign(condT, IRExpr_Mux0X(
14361       //                  unop(Iop_32to8, binop(Iop_And32,
14362       //                                        mkexpr(old_itstate),
14363       //                                        mkU32(0xF0))),
14364       //                  mkU32(1),
14365       //                  mkexpr(condT1)
14366       //       ));
14367       condT = newTemp(Ity_I32);
14368       assign(condT, mkU32(1));
14369
14370       // notInITt = xor32(and32(old_itstate, 1), 1)
14371       //          = xor32(and32(0, 1), 1)
14372       //          = xor32(0, 1)
14373       //          = 1 :: I32
14374       //
14375       // IRTemp notInITt = newTemp(Ity_I32);
14376       // assign(notInITt,
14377       //        binop(Iop_Xor32,
14378       //              binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
14379       //              mkU32(1)));
14380
14381       // cond_AND_notInIT_T = and32(notInITt, condT)
14382       //                    = and32(1, 1)
14383       //                    = 1
14384       //
14385       // cond_AND_notInIT_T = newTemp(Ity_I32);
14386       // assign(cond_AND_notInIT_T,
14387       //        binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
14388       cond_AND_notInIT_T = condT; /* 1 :: I32 */
14389
14390       /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
14391    } else {
14392       /* BEGIN { STANDARD PREAMBLE; } */
14393
14394       old_itstate = get_ITSTATE();
14395
14396       new_itstate = newTemp(Ity_I32);
14397       assign(new_itstate,
14398              binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
14399
14400       put_ITSTATE(new_itstate);
14401
14402       /* Same strategy as for ARM insns: generate a condition
14403          temporary at this point (or IRTemp_INVALID, meaning
14404          unconditional).  We leave it to lower-level instruction
14405          decoders to decide whether they can generate straight-line
14406          code, or whether they must generate a side exit before the
14407          instruction.  condT :: Ity_I32 and is always either zero or
14408          one. */
14409       IRTemp condT1 = newTemp(Ity_I32);
14410       assign(condT1,
14411              mk_armg_calculate_condition_dyn(
14412                 binop(Iop_Xor32,
14413                       binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
14414                       mkU32(0xE0))
14415             )
14416       );
14417
14418       /* This is a bit complex, but needed to make Memcheck understand
14419          that, if the condition in old_itstate[7:4] denotes AL (that
14420          is, if this instruction is to be executed unconditionally),
14421          then condT does not depend on the results of calling the
14422          helper.
14423
14424          We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in
14425          that case set condT directly to 1.  Else we use the results
14426          of the helper.  Since old_itstate is always defined and
14427          because Memcheck does lazy V-bit propagation through Mux0X,
14428          this will cause condT to always be a defined 1 if the
14429          condition is 'AL'.  From an execution semantics point of view
14430          this is irrelevant since we're merely duplicating part of the
14431          behaviour of the helper.  But it makes it clear to Memcheck,
14432          in this case, that condT does not in fact depend on the
14433          contents of the condition code thunk.  Without it, we get
14434          quite a lot of false errors.
14435
14436          So, just to clarify: from a straight semantics point of view,
14437          we can simply do "assign(condT, mkexpr(condT1))", and the
14438          simulator still runs fine.  It's just that we get loads of
14439          false errors from Memcheck. */
14440       condT = newTemp(Ity_I32);
14441       assign(condT, IRExpr_Mux0X(
14442                        unop(Iop_32to8, binop(Iop_And32,
14443                                              mkexpr(old_itstate),
14444                                              mkU32(0xF0))),
14445                        mkU32(1),
14446                        mkexpr(condT1)
14447             ));
14448
14449       /* Something we don't have in ARM: generate a 0 or 1 value
14450          indicating whether or not we are in an IT block (NB: 0 = in
14451          IT block, 1 = not in IT block).  This is used to gate
14452          condition code updates in 16-bit Thumb instructions. */
14453       IRTemp notInITt = newTemp(Ity_I32);
14454       assign(notInITt,
14455              binop(Iop_Xor32,
14456                    binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
14457                    mkU32(1)));
14458
14459       /* Compute 'condT && notInITt' -- that is, the instruction is
14460          going to execute, and we're not in an IT block.  This is the
14461          gating condition for updating condition codes in 16-bit Thumb
14462          instructions, except for CMP, CMN and TST. */
14463       cond_AND_notInIT_T = newTemp(Ity_I32);
14464       assign(cond_AND_notInIT_T,
14465              binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
14466       /* END { STANDARD PREAMBLE; } */
14467    }
14468
14469
14470    /* At this point:
14471       * ITSTATE has been updated
14472       * condT holds the guarding condition for this instruction (0 or 1),
14473       * notInITt is 1 if we're in "normal" code, 0 if in an IT block
14474       * cond_AND_notInIT_T is the AND of the above two.
14475
14476       If the instruction proper can't trap, then there's nothing else
14477       to do w.r.t. ITSTATE -- just go and and generate IR for the
14478       insn, taking into account the guarding condition.
14479
14480       If, however, the instruction might trap, then we must back up
14481       ITSTATE to the old value, and re-update it after the potentially
14482       trapping IR section.  A trap can happen either via a memory
14483       reference or because we need to throw SIGILL.
14484
14485       If an instruction has a side exit, we need to be sure that any
14486       ITSTATE backup is re-updated before the side exit.
14487    */
14488
14489    /* ----------------------------------------------------------- */
14490    /* --                                                       -- */
14491    /* -- Thumb 16-bit integer instructions                     -- */
14492    /* --                                                       -- */
14493    /* -- IMPORTANT: references to insn1 or INSN1 are           -- */
14494    /* --            not allowed in this section                -- */
14495    /* --                                                       -- */
14496    /* ----------------------------------------------------------- */
14497
14498    /* 16-bit instructions inside an IT block, apart from CMP, CMN and
14499       TST, do not set the condition codes.  Hence we must dynamically
14500       test for this case for every condition code update. */
14501
14502    IROp   anOp   = Iop_INVALID;
14503    HChar* anOpNm = NULL;
14504
14505    /* ================ 16-bit 15:6 cases ================ */
14506
14507    switch (INSN0(15,6)) {
14508
14509    case 0x10a:   // CMP
14510    case 0x10b: { // CMN
14511       /* ---------------- CMP Rn, Rm ---------------- */
14512       Bool   isCMN = INSN0(15,6) == 0x10b;
14513       UInt   rN    = INSN0(2,0);
14514       UInt   rM    = INSN0(5,3);
14515       IRTemp argL  = newTemp(Ity_I32);
14516       IRTemp argR  = newTemp(Ity_I32);
14517       assign( argL, getIRegT(rN) );
14518       assign( argR, getIRegT(rM) );
14519       /* Update flags regardless of whether in an IT block or not. */
14520       setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
14521                       argL, argR, condT );
14522       DIP("%s r%u, r%u\n", isCMN ? "cmn" : "cmp", rN, rM);
14523       goto decode_success;
14524    }
14525
14526    case 0x108: {
14527       /* ---------------- TST Rn, Rm ---------------- */
14528       UInt   rN   = INSN0(2,0);
14529       UInt   rM   = INSN0(5,3);
14530       IRTemp oldC = newTemp(Ity_I32);
14531       IRTemp oldV = newTemp(Ity_I32);
14532       IRTemp res  = newTemp(Ity_I32);
14533       assign( oldC, mk_armg_calculate_flag_c() );
14534       assign( oldV, mk_armg_calculate_flag_v() );
14535       assign( res,  binop(Iop_And32, getIRegT(rN), getIRegT(rM)) );
14536       /* Update flags regardless of whether in an IT block or not. */
14537       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
14538       DIP("tst r%u, r%u\n", rN, rM);
14539       goto decode_success;
14540    }
14541
14542    case 0x109: {
14543       /* ---------------- NEGS Rd, Rm ---------------- */
14544       /* Rd = -Rm */
14545       UInt   rM   = INSN0(5,3);
14546       UInt   rD   = INSN0(2,0);
14547       IRTemp arg  = newTemp(Ity_I32);
14548       IRTemp zero = newTemp(Ity_I32);
14549       assign(arg, getIRegT(rM));
14550       assign(zero, mkU32(0));
14551       // rD can never be r15
14552       putIRegT(rD, binop(Iop_Sub32, mkexpr(zero), mkexpr(arg)), condT);
14553       setFlags_D1_D2( ARMG_CC_OP_SUB, zero, arg, cond_AND_notInIT_T);
14554       DIP("negs r%u, r%u\n", rD, rM);
14555       goto decode_success;
14556    }
14557
14558    case 0x10F: {
14559       /* ---------------- MVNS Rd, Rm ---------------- */
14560       /* Rd = ~Rm */
14561       UInt   rM   = INSN0(5,3);
14562       UInt   rD   = INSN0(2,0);
14563       IRTemp oldV = newTemp(Ity_I32);
14564       IRTemp oldC = newTemp(Ity_I32);
14565       IRTemp res  = newTemp(Ity_I32);
14566       assign( oldV, mk_armg_calculate_flag_v() );
14567       assign( oldC, mk_armg_calculate_flag_c() );
14568       assign(res, unop(Iop_Not32, getIRegT(rM)));
14569       // rD can never be r15
14570       putIRegT(rD, mkexpr(res), condT);
14571       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
14572                          cond_AND_notInIT_T );
14573       DIP("mvns r%u, r%u\n", rD, rM);
14574       goto decode_success;
14575    }
14576
14577    case 0x10C:
14578       /* ---------------- ORRS Rd, Rm ---------------- */
14579       anOp = Iop_Or32; anOpNm = "orr"; goto and_orr_eor_mul;
14580    case 0x100:
14581       /* ---------------- ANDS Rd, Rm ---------------- */
14582       anOp = Iop_And32; anOpNm = "and"; goto and_orr_eor_mul;
14583    case 0x101:
14584       /* ---------------- EORS Rd, Rm ---------------- */
14585       anOp = Iop_Xor32; anOpNm = "eor"; goto and_orr_eor_mul;
14586    case 0x10d:
14587       /* ---------------- MULS Rd, Rm ---------------- */
14588       anOp = Iop_Mul32; anOpNm = "mul"; goto and_orr_eor_mul;
14589    and_orr_eor_mul: {
14590       /* Rd = Rd `op` Rm */
14591       UInt   rM   = INSN0(5,3);
14592       UInt   rD   = INSN0(2,0);
14593       IRTemp res  = newTemp(Ity_I32);
14594       IRTemp oldV = newTemp(Ity_I32);
14595       IRTemp oldC = newTemp(Ity_I32);
14596       assign( oldV, mk_armg_calculate_flag_v() );
14597       assign( oldC, mk_armg_calculate_flag_c() );
14598       assign( res, binop(anOp, getIRegT(rD), getIRegT(rM) ));
14599       // not safe to read guest state after here
14600       // rD can never be r15
14601       putIRegT(rD, mkexpr(res), condT);
14602       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
14603                          cond_AND_notInIT_T );
14604       DIP("%s r%u, r%u\n", anOpNm, rD, rM);
14605       goto decode_success;
14606    }
14607
14608    case 0x10E: {
14609       /* ---------------- BICS Rd, Rm ---------------- */
14610       /* Rd = Rd & ~Rm */
14611       UInt   rM   = INSN0(5,3);
14612       UInt   rD   = INSN0(2,0);
14613       IRTemp res  = newTemp(Ity_I32);
14614       IRTemp oldV = newTemp(Ity_I32);
14615       IRTemp oldC = newTemp(Ity_I32);
14616       assign( oldV, mk_armg_calculate_flag_v() );
14617       assign( oldC, mk_armg_calculate_flag_c() );
14618       assign( res, binop(Iop_And32, getIRegT(rD),
14619                                     unop(Iop_Not32, getIRegT(rM) )));
14620       // not safe to read guest state after here
14621       // rD can never be r15
14622       putIRegT(rD, mkexpr(res), condT);
14623       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
14624                          cond_AND_notInIT_T );
14625       DIP("bics r%u, r%u\n", rD, rM);
14626       goto decode_success;
14627    }
14628
14629    case 0x105: {
14630       /* ---------------- ADCS Rd, Rm ---------------- */
14631       /* Rd = Rd + Rm + oldC */
14632       UInt   rM   = INSN0(5,3);
14633       UInt   rD   = INSN0(2,0);
14634       IRTemp argL = newTemp(Ity_I32);
14635       IRTemp argR = newTemp(Ity_I32);
14636       IRTemp oldC = newTemp(Ity_I32);
14637       IRTemp res  = newTemp(Ity_I32);
14638       assign(argL, getIRegT(rD));
14639       assign(argR, getIRegT(rM));
14640       assign(oldC, mk_armg_calculate_flag_c());
14641       assign(res, binop(Iop_Add32,
14642                         binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
14643                         mkexpr(oldC)));
14644       // rD can never be r15
14645       putIRegT(rD, mkexpr(res), condT);
14646       setFlags_D1_D2_ND( ARMG_CC_OP_ADC, argL, argR, oldC,
14647                          cond_AND_notInIT_T );
14648       DIP("adcs r%u, r%u\n", rD, rM);
14649       goto decode_success;
14650    }
14651
14652    case 0x106: {
14653       /* ---------------- SBCS Rd, Rm ---------------- */
14654       /* Rd = Rd - Rm - (oldC ^ 1) */
14655       UInt   rM   = INSN0(5,3);
14656       UInt   rD   = INSN0(2,0);
14657       IRTemp argL = newTemp(Ity_I32);
14658       IRTemp argR = newTemp(Ity_I32);
14659       IRTemp oldC = newTemp(Ity_I32);
14660       IRTemp res  = newTemp(Ity_I32);
14661       assign(argL, getIRegT(rD));
14662       assign(argR, getIRegT(rM));
14663       assign(oldC, mk_armg_calculate_flag_c());
14664       assign(res, binop(Iop_Sub32,
14665                         binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
14666                         binop(Iop_Xor32, mkexpr(oldC), mkU32(1))));
14667       // rD can never be r15
14668       putIRegT(rD, mkexpr(res), condT);
14669       setFlags_D1_D2_ND( ARMG_CC_OP_SBB, argL, argR, oldC,
14670                          cond_AND_notInIT_T );
14671       DIP("sbcs r%u, r%u\n", rD, rM);
14672       goto decode_success;
14673    }
14674
14675    case 0x2CB: {
14676       /* ---------------- UXTB Rd, Rm ---------------- */
14677       /* Rd = 8Uto32(Rm) */
14678       UInt rM = INSN0(5,3);
14679       UInt rD = INSN0(2,0);
14680       putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFF)),
14681                    condT);
14682       DIP("uxtb r%u, r%u\n", rD, rM);
14683       goto decode_success;
14684    }
14685
14686    case 0x2C9: {
14687       /* ---------------- SXTB Rd, Rm ---------------- */
14688       /* Rd = 8Sto32(Rm) */
14689       UInt rM = INSN0(5,3);
14690       UInt rD = INSN0(2,0);
14691       putIRegT(rD, binop(Iop_Sar32,
14692                          binop(Iop_Shl32, getIRegT(rM), mkU8(24)),
14693                          mkU8(24)),
14694                    condT);
14695       DIP("sxtb r%u, r%u\n", rD, rM);
14696       goto decode_success;
14697    }
14698
14699    case 0x2CA: {
14700       /* ---------------- UXTH Rd, Rm ---------------- */
14701       /* Rd = 16Uto32(Rm) */
14702       UInt rM = INSN0(5,3);
14703       UInt rD = INSN0(2,0);
14704       putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFFFF)),
14705                    condT);
14706       DIP("uxth r%u, r%u\n", rD, rM);
14707       goto decode_success;
14708    }
14709
14710    case 0x2C8: {
14711       /* ---------------- SXTH Rd, Rm ---------------- */
14712       /* Rd = 16Sto32(Rm) */
14713       UInt rM = INSN0(5,3);
14714       UInt rD = INSN0(2,0);
14715       putIRegT(rD, binop(Iop_Sar32,
14716                          binop(Iop_Shl32, getIRegT(rM), mkU8(16)),
14717                          mkU8(16)),
14718                    condT);
14719       DIP("sxth r%u, r%u\n", rD, rM);
14720       goto decode_success;
14721    }
14722
14723    case 0x102:   // LSLS
14724    case 0x103:   // LSRS
14725    case 0x104:   // ASRS
14726    case 0x107: { // RORS
14727       /* ---------------- LSLS Rs, Rd ---------------- */
14728       /* ---------------- LSRS Rs, Rd ---------------- */
14729       /* ---------------- ASRS Rs, Rd ---------------- */
14730       /* ---------------- RORS Rs, Rd ---------------- */
14731       /* Rd = Rd `op` Rs, and set flags */
14732       UInt   rS   = INSN0(5,3);
14733       UInt   rD   = INSN0(2,0);
14734       IRTemp oldV = newTemp(Ity_I32);
14735       IRTemp rDt  = newTemp(Ity_I32);
14736       IRTemp rSt  = newTemp(Ity_I32);
14737       IRTemp res  = newTemp(Ity_I32);
14738       IRTemp resC = newTemp(Ity_I32);
14739       HChar* wot  = "???";
14740       assign(rSt, getIRegT(rS));
14741       assign(rDt, getIRegT(rD));
14742       assign(oldV, mk_armg_calculate_flag_v());
14743       /* Does not appear to be the standard 'how' encoding. */
14744       switch (INSN0(15,6)) {
14745          case 0x102:
14746             compute_result_and_C_after_LSL_by_reg(
14747                dis_buf, &res, &resC, rDt, rSt, rD, rS
14748             );
14749             wot = "lsl";
14750             break;
14751          case 0x103:
14752             compute_result_and_C_after_LSR_by_reg(
14753                dis_buf, &res, &resC, rDt, rSt, rD, rS
14754             );
14755             wot = "lsr";
14756             break;
14757          case 0x104:
14758             compute_result_and_C_after_ASR_by_reg(
14759                dis_buf, &res, &resC, rDt, rSt, rD, rS
14760             );
14761             wot = "asr";
14762             break;
14763          case 0x107:
14764             compute_result_and_C_after_ROR_by_reg(
14765                dis_buf, &res, &resC, rDt, rSt, rD, rS
14766             );
14767             wot = "ror";
14768             break;
14769          default:
14770             /*NOTREACHED*/vassert(0);
14771       }
14772       // not safe to read guest state after this point
14773       putIRegT(rD, mkexpr(res), condT);
14774       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
14775                          cond_AND_notInIT_T );
14776       DIP("%ss r%u, r%u\n", wot, rS, rD);
14777       goto decode_success;
14778    }
14779
14780    case 0x2E8:   // REV
14781    case 0x2E9: { // REV16
14782       /* ---------------- REV   Rd, Rm ---------------- */
14783       /* ---------------- REV16 Rd, Rm ---------------- */
14784       UInt rM = INSN0(5,3);
14785       UInt rD = INSN0(2,0);
14786       Bool isREV = INSN0(15,6) == 0x2E8;
14787       IRTemp arg = newTemp(Ity_I32);
14788       assign(arg, getIRegT(rM));
14789       IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
14790       putIRegT(rD, mkexpr(res), condT);
14791       DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM);
14792       goto decode_success;
14793    }
14794
14795    default:
14796       break; /* examine the next shortest prefix */
14797
14798    }
14799
14800
14801    /* ================ 16-bit 15:7 cases ================ */
14802
14803    switch (INSN0(15,7)) {
14804
14805    case BITS9(1,0,1,1,0,0,0,0,0): {
14806       /* ------------ ADD SP, #imm7 * 4 ------------ */
14807       UInt uimm7 = INSN0(6,0);
14808       putIRegT(13, binop(Iop_Add32, getIRegT(13), mkU32(uimm7 * 4)),
14809                    condT);
14810       DIP("add sp, #%u\n", uimm7 * 4);
14811       goto decode_success;
14812    }
14813
14814    case BITS9(1,0,1,1,0,0,0,0,1): {
14815       /* ------------ SUB SP, #imm7 * 4 ------------ */
14816       UInt uimm7 = INSN0(6,0);
14817       putIRegT(13, binop(Iop_Sub32, getIRegT(13), mkU32(uimm7 * 4)),
14818                    condT);
14819       DIP("sub sp, #%u\n", uimm7 * 4);
14820       goto decode_success;
14821    }
14822
14823    case BITS9(0,1,0,0,0,1,1,1,0): {
14824       /* ---------------- BX rM ---------------- */
14825       /* Branch to reg, and optionally switch modes.  Reg contains a
14826          suitably encoded address therefore (w CPSR.T at the bottom).
14827          Have to special-case r15, as usual. */
14828       UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
14829       if (BITS3(0,0,0) == INSN0(2,0)) {
14830          IRTemp dst = newTemp(Ity_I32);
14831          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
14832          mk_skip_over_T16_if_cond_is_false(condT);
14833          condT = IRTemp_INVALID;
14834          // now uncond
14835          if (rM <= 14) {
14836             assign( dst, getIRegT(rM) );
14837          } else {
14838             vassert(rM == 15);
14839             assign( dst, mkU32(guest_R15_curr_instr_notENC + 4) );
14840          }
14841          irsb->next     = mkexpr(dst);
14842          irsb->jumpkind = Ijk_Boring;
14843          dres.whatNext  = Dis_StopHere;
14844          DIP("bx r%u (possibly switch to ARM mode)\n", rM);
14845          goto decode_success;
14846       }
14847       break;
14848    }
14849
14850    /* ---------------- BLX rM ---------------- */
14851    /* Branch and link to interworking address in rM. */
14852    case BITS9(0,1,0,0,0,1,1,1,1): {
14853       if (BITS3(0,0,0) == INSN0(2,0)) {
14854          UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
14855          IRTemp dst = newTemp(Ity_I32);
14856          if (rM <= 14) {
14857             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
14858             mk_skip_over_T16_if_cond_is_false(condT);
14859             condT = IRTemp_INVALID;
14860             // now uncond
14861             /* We're returning to Thumb code, hence "| 1" */
14862             assign( dst, getIRegT(rM) );
14863             putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ),
14864                           IRTemp_INVALID );
14865             irsb->next     = mkexpr(dst);
14866             irsb->jumpkind = Ijk_Call;
14867             dres.whatNext  = Dis_StopHere;
14868             DIP("blx r%u (possibly switch to ARM mode)\n", rM);
14869             goto decode_success;
14870          }
14871          /* else unpredictable, fall through */
14872       }
14873       break;
14874    }
14875
14876    default:
14877       break; /* examine the next shortest prefix */
14878
14879    }
14880
14881
14882    /* ================ 16-bit 15:8 cases ================ */
14883
14884    switch (INSN0(15,8)) {
14885
14886    case BITS8(1,1,0,1,1,1,1,1): {
14887       /* ---------------- SVC ---------------- */
14888       UInt imm8 = INSN0(7,0);
14889       if (imm8 == 0) {
14890          /* A syscall.  We can't do this conditionally, hence: */
14891          mk_skip_over_T16_if_cond_is_false( condT );
14892          // FIXME: what if we have to back up and restart this insn?
14893          // then ITSTATE will be wrong (we'll have it as "used")
14894          // when it isn't.  Correct is to save ITSTATE in a 
14895          // stash pseudo-reg, and back up from that if we have to
14896          // restart.
14897          // uncond after here
14898          irsb->next     = mkU32( (guest_R15_curr_instr_notENC + 2) | 1 );
14899          irsb->jumpkind = Ijk_Sys_syscall;
14900          dres.whatNext  = Dis_StopHere;
14901          DIP("svc #0x%08x\n", imm8);
14902          goto decode_success;
14903       }
14904       /* else fall through */
14905       break;
14906    }
14907
14908    case BITS8(0,1,0,0,0,1,0,0): {
14909       /* ---------------- ADD(HI) Rd, Rm ---------------- */
14910       UInt h1 = INSN0(7,7);
14911       UInt h2 = INSN0(6,6);
14912       UInt rM = (h2 << 3) | INSN0(5,3);
14913       UInt rD = (h1 << 3) | INSN0(2,0);
14914       //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive
14915       if (rD == 15 && rM == 15) {
14916          // then it's invalid
14917       } else {
14918          IRTemp res = newTemp(Ity_I32);
14919          assign( res, binop(Iop_Add32, getIRegT(rD), getIRegT(rM) ));
14920          if (rD != 15) {
14921             putIRegT( rD, mkexpr(res), condT );
14922          } else {
14923             /* Only allowed outside or last-in IT block; SIGILL if not so. */
14924             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
14925             /* jump over insn if not selected */
14926             mk_skip_over_T16_if_cond_is_false(condT);
14927             condT = IRTemp_INVALID;
14928             // now uncond
14929             /* non-interworking branch */
14930             irsb->next = binop(Iop_Or32, mkexpr(res), mkU32(1));
14931             irsb->jumpkind = Ijk_Boring;
14932             dres.whatNext = Dis_StopHere;
14933          }
14934          DIP("add(hi) r%u, r%u\n", rD, rM);
14935          goto decode_success;
14936       }
14937       break;
14938    }
14939
14940    case BITS8(0,1,0,0,0,1,0,1): {
14941       /* ---------------- CMP(HI) Rd, Rm ---------------- */
14942       UInt h1 = INSN0(7,7);
14943       UInt h2 = INSN0(6,6);
14944       UInt rM = (h2 << 3) | INSN0(5,3);
14945       UInt rN = (h1 << 3) | INSN0(2,0);
14946       if (h1 != 0 || h2 != 0) {
14947          IRTemp argL  = newTemp(Ity_I32);
14948          IRTemp argR  = newTemp(Ity_I32);
14949          assign( argL, getIRegT(rN) );
14950          assign( argR, getIRegT(rM) );
14951          /* Update flags regardless of whether in an IT block or not. */
14952          setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
14953          DIP("cmphi r%u, r%u\n", rN, rM);
14954          goto decode_success;
14955       }
14956       break;
14957    }
14958
14959    case BITS8(0,1,0,0,0,1,1,0): {
14960       /* ---------------- MOV(HI) Rd, Rm ---------------- */
14961       UInt h1 = INSN0(7,7);
14962       UInt h2 = INSN0(6,6);
14963       UInt rM = (h2 << 3) | INSN0(5,3);
14964       UInt rD = (h1 << 3) | INSN0(2,0);
14965       /* The old ARM ARM seems to disallow the case where both Rd and
14966          Rm are "low" registers, but newer versions allow it. */
14967       if (1 /*h1 != 0 || h2 != 0*/) {
14968          IRTemp val = newTemp(Ity_I32);
14969          assign( val, getIRegT(rM) );
14970          if (rD != 15) {
14971             putIRegT( rD, mkexpr(val), condT );
14972          } else {
14973             /* Only allowed outside or last-in IT block; SIGILL if not so. */
14974             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
14975             /* jump over insn if not selected */
14976             mk_skip_over_T16_if_cond_is_false(condT);
14977             condT = IRTemp_INVALID;
14978             // now uncond
14979             /* non-interworking branch */
14980             irsb->next = binop(Iop_Or32, mkexpr(val), mkU32(1));
14981             irsb->jumpkind = Ijk_Boring;
14982             dres.whatNext = Dis_StopHere;
14983          }
14984          DIP("mov r%u, r%u\n", rD, rM);
14985          goto decode_success;
14986       }
14987       break;
14988    }
14989
14990    case BITS8(1,0,1,1,1,1,1,1): {
14991       /* ---------------- IT (if-then) ---------------- */
14992       UInt firstcond = INSN0(7,4);
14993       UInt mask = INSN0(3,0);
14994       UInt newITSTATE = 0;
14995       /* This is the ITSTATE represented as described in
14996          libvex_guest_arm.h.  It is not the ARM ARM representation. */
14997       UChar c1 = '.';
14998       UChar c2 = '.';
14999       UChar c3 = '.';
15000       Bool valid = compute_ITSTATE( &newITSTATE, &c1, &c2, &c3,
15001                                     firstcond, mask );
15002       if (valid && firstcond != 0xF/*NV*/) {
15003          /* Not allowed in an IT block; SIGILL if so. */
15004          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
15005
15006          IRTemp t = newTemp(Ity_I32);
15007          assign(t, mkU32(newITSTATE));
15008          put_ITSTATE(t);
15009
15010          DIP("it%c%c%c %s\n", c1, c2, c3, nCC(firstcond));
15011          goto decode_success;
15012       }
15013       break;
15014    }
15015
15016    case BITS8(1,0,1,1,0,0,0,1):
15017    case BITS8(1,0,1,1,0,0,1,1):
15018    case BITS8(1,0,1,1,1,0,0,1):
15019    case BITS8(1,0,1,1,1,0,1,1): {
15020       /* ---------------- CB{N}Z ---------------- */
15021       UInt rN    = INSN0(2,0);
15022       UInt bOP   = INSN0(11,11);
15023       UInt imm32 = (INSN0(9,9) << 6) | (INSN0(7,3) << 1);
15024       gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
15025       /* It's a conditional branch forward. */
15026       IRTemp kond = newTemp(Ity_I1);
15027       assign( kond, binop(bOP ? Iop_CmpNE32 : Iop_CmpEQ32,
15028                           getIRegT(rN), mkU32(0)) );
15029
15030       vassert(0 == (guest_R15_curr_instr_notENC & 1));
15031       /* Looks like the nearest insn we can branch to is the one after
15032          next.  That makes sense, as there's no point in being able to
15033          encode a conditional branch to the next instruction. */
15034       UInt dst = (guest_R15_curr_instr_notENC + 4 + imm32) | 1;
15035       stmt(IRStmt_Exit( mkexpr(kond),
15036                         Ijk_Boring,
15037                         IRConst_U32(toUInt(dst)) ));
15038       DIP("cb%s r%u, 0x%x\n", bOP ? "nz" : "z", rN, dst - 1);
15039       goto decode_success;
15040    }
15041
15042    default:
15043       break; /* examine the next shortest prefix */
15044
15045    }
15046
15047
15048    /* ================ 16-bit 15:9 cases ================ */
15049
15050    switch (INSN0(15,9)) {
15051
15052    case BITS7(1,0,1,1,0,1,0): {
15053       /* ---------------- PUSH ---------------- */
15054       /* This is a bit like STMxx, but way simpler. Complications we
15055          don't have to deal with:
15056          * SP being one of the transferred registers
15057          * direction (increment vs decrement)
15058          * before-vs-after-ness
15059       */
15060       Int  i, nRegs;
15061       UInt bitR    = INSN0(8,8);
15062       UInt regList = INSN0(7,0);
15063       if (bitR) regList |= (1 << 14);
15064    
15065       if (regList != 0) {
15066          /* Since we can't generate a guaranteed non-trapping IR
15067             sequence, (1) jump over the insn if it is gated false, and
15068             (2) back out the ITSTATE update. */
15069          mk_skip_over_T16_if_cond_is_false(condT);
15070          condT = IRTemp_INVALID;
15071          put_ITSTATE(old_itstate);
15072          // now uncond
15073
15074          nRegs = 0;
15075          for (i = 0; i < 16; i++) {
15076             if ((regList & (1 << i)) != 0)
15077                nRegs++;
15078          }
15079          vassert(nRegs >= 1 && nRegs <= 8);
15080
15081          /* Move SP down first of all, so we're "covered".  And don't
15082             mess with its alignment. */
15083          IRTemp newSP = newTemp(Ity_I32);
15084          assign(newSP, binop(Iop_Sub32, getIRegT(13), mkU32(4 * nRegs)));
15085          putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
15086
15087          /* Generate a transfer base address as a forced-aligned
15088             version of the final SP value. */
15089          IRTemp base = newTemp(Ity_I32);
15090          assign(base, binop(Iop_And32, mkexpr(newSP), mkU32(~3)));
15091
15092          /* Now the transfers */
15093          nRegs = 0;
15094          for (i = 0; i < 16; i++) {
15095             if ((regList & (1 << i)) != 0) {
15096                storeLE( binop(Iop_Add32, mkexpr(base), mkU32(4 * nRegs)),
15097                         getIRegT(i) );
15098                nRegs++;
15099             }
15100          }
15101
15102          /* Reinstate the ITSTATE update. */
15103          put_ITSTATE(new_itstate);
15104
15105          DIP("push {%s0x%04x}\n", bitR ? "lr," : "", regList & 0xFF);
15106          goto decode_success;
15107       }
15108       break;
15109    }
15110
15111    case BITS7(1,0,1,1,1,1,0): {
15112       /* ---------------- POP ---------------- */
15113       Int  i, nRegs;
15114       UInt bitR    = INSN0(8,8);
15115       UInt regList = INSN0(7,0);
15116    
15117       if (regList != 0 || bitR) {
15118          /* Since we can't generate a guaranteed non-trapping IR
15119             sequence, (1) jump over the insn if it is gated false, and
15120             (2) back out the ITSTATE update. */
15121          mk_skip_over_T16_if_cond_is_false(condT);
15122          condT = IRTemp_INVALID;
15123          put_ITSTATE(old_itstate);
15124          // now uncond
15125
15126          nRegs = 0;
15127          for (i = 0; i < 8; i++) {
15128             if ((regList & (1 << i)) != 0)
15129                nRegs++;
15130          }
15131          vassert(nRegs >= 0 && nRegs <= 7);
15132          vassert(bitR == 0 || bitR == 1);
15133
15134          IRTemp oldSP = newTemp(Ity_I32);
15135          assign(oldSP, getIRegT(13));
15136
15137          /* Generate a transfer base address as a forced-aligned
15138             version of the original SP value. */
15139          IRTemp base = newTemp(Ity_I32);
15140          assign(base, binop(Iop_And32, mkexpr(oldSP), mkU32(~3)));
15141
15142          /* Compute a new value for SP, but don't install it yet, so
15143             that we're "covered" until all the transfers are done.
15144             And don't mess with its alignment. */
15145          IRTemp newSP = newTemp(Ity_I32);
15146          assign(newSP, binop(Iop_Add32, mkexpr(oldSP),
15147                                         mkU32(4 * (nRegs + bitR))));
15148
15149          /* Now the transfers, not including PC */
15150          nRegs = 0;
15151          for (i = 0; i < 8; i++) {
15152             if ((regList & (1 << i)) != 0) {
15153                putIRegT(i, loadLE( Ity_I32,
15154                                    binop(Iop_Add32, mkexpr(base),
15155                                                     mkU32(4 * nRegs))),
15156                            IRTemp_INVALID );
15157                nRegs++;
15158             }
15159          }
15160
15161          IRTemp newPC = IRTemp_INVALID;
15162          if (bitR) {
15163             newPC = newTemp(Ity_I32);
15164             assign( newPC, loadLE( Ity_I32,
15165                                    binop(Iop_Add32, mkexpr(base),
15166                                                     mkU32(4 * nRegs))));
15167          }
15168
15169          /* Now we can safely install the new SP value */
15170          putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
15171
15172          /* Reinstate the ITSTATE update. */
15173          put_ITSTATE(new_itstate);
15174
15175          /* now, do we also have to do a branch?  If so, it turns out
15176             that the new PC value is encoded exactly as we need it to
15177             be -- with CPSR.T in the bottom bit.  So we can simply use
15178             it as is, no need to mess with it.  Note, therefore, this
15179             is an interworking return. */
15180          if (bitR) {
15181             irsb->next     = mkexpr(newPC);
15182             irsb->jumpkind = Ijk_Ret;
15183             dres.whatNext  = Dis_StopHere;
15184          }
15185
15186          DIP("pop {%s0x%04x}\n", bitR ? "pc," : "", regList & 0xFF);
15187          goto decode_success;
15188       }
15189       break;
15190    }
15191
15192    case BITS7(0,0,0,1,1,1,0):   /* ADDS */
15193    case BITS7(0,0,0,1,1,1,1): { /* SUBS */
15194       /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */
15195       /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */
15196       UInt   uimm3 = INSN0(8,6);
15197       UInt   rN    = INSN0(5,3);
15198       UInt   rD    = INSN0(2,0);
15199       UInt   isSub = INSN0(9,9);
15200       IRTemp argL  = newTemp(Ity_I32);
15201       IRTemp argR  = newTemp(Ity_I32);
15202       assign( argL, getIRegT(rN) );
15203       assign( argR, mkU32(uimm3) );
15204       putIRegT(rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
15205                          mkexpr(argL), mkexpr(argR)),
15206                    condT);
15207       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
15208                       argL, argR, cond_AND_notInIT_T );
15209       DIP("%s r%u, r%u, #%u\n", isSub ? "subs" : "adds", rD, rN, uimm3);
15210       goto decode_success;
15211    }
15212
15213    case BITS7(0,0,0,1,1,0,0):   /* ADDS */
15214    case BITS7(0,0,0,1,1,0,1): { /* SUBS */
15215       /* ---------------- ADDS Rd, Rn, Rm ---------------- */
15216       /* ---------------- SUBS Rd, Rn, Rm ---------------- */
15217       UInt   rM    = INSN0(8,6);
15218       UInt   rN    = INSN0(5,3);
15219       UInt   rD    = INSN0(2,0);
15220       UInt   isSub = INSN0(9,9);
15221       IRTemp argL  = newTemp(Ity_I32);
15222       IRTemp argR  = newTemp(Ity_I32);
15223       assign( argL, getIRegT(rN) );
15224       assign( argR, getIRegT(rM) );
15225       putIRegT( rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
15226                           mkexpr(argL), mkexpr(argR)),
15227                     condT );
15228       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
15229                       argL, argR, cond_AND_notInIT_T );
15230       DIP("%s r%u, r%u, r%u\n", isSub ? "subs" : "adds", rD, rN, rM);
15231       goto decode_success;
15232    }
15233
15234    case BITS7(0,1,0,1,0,0,0):   /* STR */
15235    case BITS7(0,1,0,1,1,0,0): { /* LDR */
15236       /* ------------- LDR Rd, [Rn, Rm] ------------- */
15237       /* ------------- STR Rd, [Rn, Rm] ------------- */
15238       /* LDR/STR Rd, [Rn + Rm] */
15239       UInt    rD   = INSN0(2,0);
15240       UInt    rN   = INSN0(5,3);
15241       UInt    rM   = INSN0(8,6);
15242       UInt    isLD = INSN0(11,11);
15243
15244       mk_skip_over_T16_if_cond_is_false(condT);
15245       condT = IRTemp_INVALID;
15246       // now uncond
15247
15248       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
15249       put_ITSTATE(old_itstate); // backout
15250       if (isLD) {
15251          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
15252       } else {
15253          storeLE(ea, getIRegT(rD));
15254       }
15255       put_ITSTATE(new_itstate); // restore
15256
15257       DIP("%s r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
15258       goto decode_success;
15259    }
15260
15261    case BITS7(0,1,0,1,0,0,1):
15262    case BITS7(0,1,0,1,1,0,1): {
15263       /* ------------- LDRH Rd, [Rn, Rm] ------------- */
15264       /* ------------- STRH Rd, [Rn, Rm] ------------- */
15265       /* LDRH/STRH Rd, [Rn + Rm] */
15266       UInt    rD   = INSN0(2,0);
15267       UInt    rN   = INSN0(5,3);
15268       UInt    rM   = INSN0(8,6);
15269       UInt    isLD = INSN0(11,11);
15270
15271       mk_skip_over_T16_if_cond_is_false(condT);
15272       condT = IRTemp_INVALID;
15273       // now uncond
15274
15275       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
15276       put_ITSTATE(old_itstate); // backout
15277       if (isLD) {
15278          putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
15279                       IRTemp_INVALID);
15280       } else {
15281          storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
15282       }
15283       put_ITSTATE(new_itstate); // restore
15284
15285       DIP("%sh r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
15286       goto decode_success;
15287    }
15288
15289    case BITS7(0,1,0,1,1,1,1): {
15290       /* ------------- LDRSH Rd, [Rn, Rm] ------------- */
15291       /* LDRSH Rd, [Rn + Rm] */
15292       UInt    rD = INSN0(2,0);
15293       UInt    rN = INSN0(5,3);
15294       UInt    rM = INSN0(8,6);
15295
15296       mk_skip_over_T16_if_cond_is_false(condT);
15297       condT = IRTemp_INVALID;
15298       // now uncond
15299
15300       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
15301       put_ITSTATE(old_itstate); // backout
15302       putIRegT(rD, unop(Iop_16Sto32, loadLE(Ity_I16, ea)),
15303                    IRTemp_INVALID);
15304       put_ITSTATE(new_itstate); // restore
15305
15306       DIP("ldrsh r%u, [r%u, r%u]\n", rD, rN, rM);
15307       goto decode_success;
15308    }
15309
15310    case BITS7(0,1,0,1,0,1,1): {
15311       /* ------------- LDRSB Rd, [Rn, Rm] ------------- */
15312       /* LDRSB Rd, [Rn + Rm] */
15313       UInt    rD = INSN0(2,0);
15314       UInt    rN = INSN0(5,3);
15315       UInt    rM = INSN0(8,6);
15316
15317       mk_skip_over_T16_if_cond_is_false(condT);
15318       condT = IRTemp_INVALID;
15319       // now uncond
15320
15321       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
15322       put_ITSTATE(old_itstate); // backout
15323       putIRegT(rD, unop(Iop_8Sto32, loadLE(Ity_I8, ea)),
15324                    IRTemp_INVALID);
15325       put_ITSTATE(new_itstate); // restore
15326
15327       DIP("ldrsb r%u, [r%u, r%u]\n", rD, rN, rM);
15328       goto decode_success;
15329    }
15330
15331    case BITS7(0,1,0,1,0,1,0):
15332    case BITS7(0,1,0,1,1,1,0): {
15333       /* ------------- LDRB Rd, [Rn, Rm] ------------- */
15334       /* ------------- STRB Rd, [Rn, Rm] ------------- */
15335       /* LDRB/STRB Rd, [Rn + Rm] */
15336       UInt    rD   = INSN0(2,0);
15337       UInt    rN   = INSN0(5,3);
15338       UInt    rM   = INSN0(8,6);
15339       UInt    isLD = INSN0(11,11);
15340
15341       mk_skip_over_T16_if_cond_is_false(condT);
15342       condT = IRTemp_INVALID;
15343       // now uncond
15344
15345       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
15346       put_ITSTATE(old_itstate); // backout
15347       if (isLD) {
15348          putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
15349                   IRTemp_INVALID);
15350       } else {
15351          storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
15352       }
15353       put_ITSTATE(new_itstate); // restore
15354
15355       DIP("%sb r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
15356       goto decode_success;
15357    }
15358
15359    default:
15360       break; /* examine the next shortest prefix */
15361
15362    }
15363
15364
15365    /* ================ 16-bit 15:11 cases ================ */
15366
15367    switch (INSN0(15,11)) {
15368
15369    case BITS5(0,0,1,1,0):
15370    case BITS5(0,0,1,1,1): {
15371       /* ---------------- ADDS Rn, #uimm8 ---------------- */
15372       /* ---------------- SUBS Rn, #uimm8 ---------------- */
15373       UInt   isSub = INSN0(11,11);
15374       UInt   rN    = INSN0(10,8);
15375       UInt   uimm8 = INSN0(7,0);
15376       IRTemp argL  = newTemp(Ity_I32);
15377       IRTemp argR  = newTemp(Ity_I32);
15378       assign( argL, getIRegT(rN) );
15379       assign( argR, mkU32(uimm8) );
15380       putIRegT( rN, binop(isSub ? Iop_Sub32 : Iop_Add32,
15381                           mkexpr(argL), mkexpr(argR)), condT );
15382       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
15383                       argL, argR, cond_AND_notInIT_T );
15384       DIP("%s r%u, #%u\n", isSub ? "subs" : "adds", rN, uimm8);
15385       goto decode_success;
15386    }
15387
15388    case BITS5(1,0,1,0,0): {
15389       /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */
15390       /* a.k.a. ADR */
15391       /* rD = align4(PC) + imm8 * 4 */
15392       UInt rD   = INSN0(10,8);
15393       UInt imm8 = INSN0(7,0);
15394       putIRegT(rD, binop(Iop_Add32, 
15395                          binop(Iop_And32, getIRegT(15), mkU32(~3U)),
15396                          mkU32(imm8 * 4)),
15397                    condT);
15398       DIP("add r%u, pc, #%u\n", rD, imm8 * 4);
15399       goto decode_success;
15400    }
15401
15402    case BITS5(1,0,1,0,1): {
15403       /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */
15404       UInt rD   = INSN0(10,8);
15405       UInt imm8 = INSN0(7,0);
15406       putIRegT(rD, binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)),
15407                    condT);
15408       DIP("add r%u, r13, #%u\n", rD, imm8 * 4);
15409       goto decode_success;
15410    }
15411
15412    case BITS5(0,0,1,0,1): {
15413       /* ---------------- CMP Rn, #uimm8 ---------------- */
15414       UInt   rN    = INSN0(10,8);
15415       UInt   uimm8 = INSN0(7,0);
15416       IRTemp argL  = newTemp(Ity_I32);
15417       IRTemp argR  = newTemp(Ity_I32);
15418       assign( argL, getIRegT(rN) );
15419       assign( argR, mkU32(uimm8) );
15420       /* Update flags regardless of whether in an IT block or not. */
15421       setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
15422       DIP("cmp r%u, #%u\n", rN, uimm8);
15423       goto decode_success;
15424    }
15425
15426    case BITS5(0,0,1,0,0): {
15427       /* -------------- (T1) MOVS Rn, #uimm8 -------------- */
15428       UInt   rD    = INSN0(10,8);
15429       UInt   uimm8 = INSN0(7,0);
15430       IRTemp oldV  = newTemp(Ity_I32);
15431       IRTemp oldC  = newTemp(Ity_I32);
15432       IRTemp res   = newTemp(Ity_I32);
15433       assign( oldV, mk_armg_calculate_flag_v() );
15434       assign( oldC, mk_armg_calculate_flag_c() );
15435       assign( res, mkU32(uimm8) );
15436       putIRegT(rD, mkexpr(res), condT);
15437       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
15438                          cond_AND_notInIT_T );
15439       DIP("movs r%u, #%u\n", rD, uimm8);
15440       goto decode_success;
15441    }
15442
15443    case BITS5(0,1,0,0,1): {
15444       /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */
15445       /* LDR Rd, [align4(PC) + imm8 * 4] */
15446       UInt   rD   = INSN0(10,8);
15447       UInt   imm8 = INSN0(7,0);
15448       IRTemp ea   = newTemp(Ity_I32);
15449
15450       mk_skip_over_T16_if_cond_is_false(condT);
15451       condT = IRTemp_INVALID;
15452       // now uncond
15453
15454       assign(ea, binop(Iop_Add32, 
15455                        binop(Iop_And32, getIRegT(15), mkU32(~3U)),
15456                        mkU32(imm8 * 4)));
15457       put_ITSTATE(old_itstate); // backout
15458       putIRegT(rD, loadLE(Ity_I32, mkexpr(ea)),
15459                    IRTemp_INVALID);
15460       put_ITSTATE(new_itstate); // restore
15461
15462       DIP("ldr r%u, [pc, #%u]\n", rD, imm8 * 4);
15463       goto decode_success;
15464    }
15465
15466    case BITS5(0,1,1,0,0):   /* STR */
15467    case BITS5(0,1,1,0,1): { /* LDR */
15468       /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */
15469       /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */
15470       /* LDR/STR Rd, [Rn + imm5 * 4] */
15471       UInt    rD   = INSN0(2,0);
15472       UInt    rN   = INSN0(5,3);
15473       UInt    imm5 = INSN0(10,6);
15474       UInt    isLD = INSN0(11,11);
15475
15476       mk_skip_over_T16_if_cond_is_false(condT);
15477       condT = IRTemp_INVALID;
15478       // now uncond
15479
15480       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 4));
15481       put_ITSTATE(old_itstate); // backout
15482       if (isLD) {
15483          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
15484       } else {
15485          storeLE( ea, getIRegT(rD) );
15486       }
15487       put_ITSTATE(new_itstate); // restore
15488
15489       DIP("%s r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 4);
15490       goto decode_success;
15491    }
15492
15493    case BITS5(1,0,0,0,0):   /* STRH */
15494    case BITS5(1,0,0,0,1): { /* LDRH */
15495       /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */
15496       /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */
15497       /* LDRH/STRH Rd, [Rn + imm5 * 2] */
15498       UInt    rD   = INSN0(2,0);
15499       UInt    rN   = INSN0(5,3);
15500       UInt    imm5 = INSN0(10,6);
15501       UInt    isLD = INSN0(11,11);
15502
15503       mk_skip_over_T16_if_cond_is_false(condT);
15504       condT = IRTemp_INVALID;
15505       // now uncond
15506
15507       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 2));
15508       put_ITSTATE(old_itstate); // backout
15509       if (isLD) {
15510          putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
15511                   IRTemp_INVALID);
15512       } else {
15513          storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
15514       }
15515       put_ITSTATE(new_itstate); // restore
15516
15517       DIP("%sh r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 2);
15518       goto decode_success;
15519    }
15520
15521    case BITS5(0,1,1,1,0):   /* STRB */
15522    case BITS5(0,1,1,1,1): { /* LDRB */
15523       /* ------------- LDRB Rd, [Rn, #imm5] ------------- */
15524       /* ------------- STRB Rd, [Rn, #imm5] ------------- */
15525       /* LDRB/STRB Rd, [Rn + imm5] */
15526       UInt    rD   = INSN0(2,0);
15527       UInt    rN   = INSN0(5,3);
15528       UInt    imm5 = INSN0(10,6);
15529       UInt    isLD = INSN0(11,11);
15530
15531       mk_skip_over_T16_if_cond_is_false(condT);
15532       condT = IRTemp_INVALID;
15533       // now uncond
15534
15535       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5));
15536       put_ITSTATE(old_itstate); // backout
15537       if (isLD) {
15538          putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
15539                   IRTemp_INVALID);
15540       } else {
15541          storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
15542       }
15543       put_ITSTATE(new_itstate); // restore
15544
15545       DIP("%sb r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5);
15546       goto decode_success;
15547    }
15548
15549    case BITS5(1,0,0,1,0):   /* STR */
15550    case BITS5(1,0,0,1,1): { /* LDR */
15551       /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */
15552       /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */
15553       /* LDR/STR Rd, [SP + imm8 * 4] */
15554       UInt rD    = INSN0(10,8);
15555       UInt imm8  = INSN0(7,0);
15556       UInt isLD  = INSN0(11,11);
15557
15558       mk_skip_over_T16_if_cond_is_false(condT);
15559       condT = IRTemp_INVALID;
15560       // now uncond
15561
15562       IRExpr* ea = binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4));
15563       put_ITSTATE(old_itstate); // backout
15564       if (isLD) {
15565          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
15566       } else {
15567          storeLE(ea, getIRegT(rD));
15568       }
15569       put_ITSTATE(new_itstate); // restore
15570
15571       DIP("%s r%u, [sp, #%u]\n", isLD ? "ldr" : "str", rD, imm8 * 4);
15572       goto decode_success;
15573    }
15574
15575    case BITS5(1,1,0,0,1): {
15576       /* ------------- LDMIA Rn!, {reglist} ------------- */
15577       Int i, nRegs = 0;
15578       UInt rN   = INSN0(10,8);
15579       UInt list = INSN0(7,0);
15580       /* Empty lists aren't allowed. */
15581       if (list != 0) {
15582          mk_skip_over_T16_if_cond_is_false(condT);
15583          condT = IRTemp_INVALID;
15584          put_ITSTATE(old_itstate);
15585          // now uncond
15586
15587          IRTemp oldRn = newTemp(Ity_I32);
15588          IRTemp base  = newTemp(Ity_I32);
15589          assign(oldRn, getIRegT(rN));
15590          assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
15591          for (i = 0; i < 8; i++) {
15592             if (0 == (list & (1 << i)))
15593                continue;
15594             nRegs++;
15595             putIRegT(
15596                i, loadLE(Ity_I32,
15597                          binop(Iop_Add32, mkexpr(base),
15598                                           mkU32(nRegs * 4 - 4))),
15599                IRTemp_INVALID
15600             );
15601          }
15602          /* Only do the writeback for rN if it isn't in the list of
15603             registers to be transferred. */
15604          if (0 == (list & (1 << rN))) {
15605             putIRegT(rN,
15606                      binop(Iop_Add32, mkexpr(oldRn),
15607                                       mkU32(nRegs * 4)),
15608                      IRTemp_INVALID
15609             );
15610          }
15611
15612          /* Reinstate the ITSTATE update. */
15613          put_ITSTATE(new_itstate);
15614
15615          DIP("ldmia r%u!, {0x%04x}\n", rN, list);
15616          goto decode_success;
15617       }
15618       break;
15619    }
15620
15621    case BITS5(1,1,0,0,0): {
15622       /* ------------- STMIA Rn!, {reglist} ------------- */
15623       Int i, nRegs = 0;
15624       UInt rN   = INSN0(10,8);
15625       UInt list = INSN0(7,0);
15626       /* Empty lists aren't allowed.  Also, if rN is in the list then
15627          it must be the lowest numbered register in the list. */
15628       Bool valid = list != 0;
15629       if (valid && 0 != (list & (1 << rN))) {
15630          for (i = 0; i < rN; i++) {
15631             if (0 != (list & (1 << i)))
15632                valid = False;
15633          }
15634       }
15635       if (valid) {
15636          mk_skip_over_T16_if_cond_is_false(condT);
15637          condT = IRTemp_INVALID;
15638          put_ITSTATE(old_itstate);
15639          // now uncond
15640
15641          IRTemp oldRn = newTemp(Ity_I32);
15642          IRTemp base = newTemp(Ity_I32);
15643          assign(oldRn, getIRegT(rN));
15644          assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
15645          for (i = 0; i < 8; i++) {
15646             if (0 == (list & (1 << i)))
15647                continue;
15648             nRegs++;
15649             storeLE( binop(Iop_Add32, mkexpr(base), mkU32(nRegs * 4 - 4)),
15650                      getIRegT(i) );
15651          }
15652          /* Always do the writeback. */
15653          putIRegT(rN,
15654                   binop(Iop_Add32, mkexpr(oldRn),
15655                                    mkU32(nRegs * 4)),
15656                   IRTemp_INVALID);
15657
15658          /* Reinstate the ITSTATE update. */
15659          put_ITSTATE(new_itstate);
15660
15661          DIP("stmia r%u!, {0x%04x}\n", rN, list);
15662          goto decode_success;
15663       }
15664       break;
15665    }
15666
15667    case BITS5(0,0,0,0,0):   /* LSLS */
15668    case BITS5(0,0,0,0,1):   /* LSRS */
15669    case BITS5(0,0,0,1,0): { /* ASRS */
15670       /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */
15671       /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */
15672       /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */
15673       UInt   rD   = INSN0(2,0);
15674       UInt   rM   = INSN0(5,3);
15675       UInt   imm5 = INSN0(10,6);
15676       IRTemp res  = newTemp(Ity_I32);
15677       IRTemp resC = newTemp(Ity_I32);
15678       IRTemp rMt  = newTemp(Ity_I32);
15679       IRTemp oldV = newTemp(Ity_I32);
15680       HChar* wot  = "???";
15681       assign(rMt, getIRegT(rM));
15682       assign(oldV, mk_armg_calculate_flag_v());
15683       /* Looks like INSN0(12,11) are the standard 'how' encoding.
15684          Could compactify if the ROR case later appears. */
15685       switch (INSN0(15,11)) {
15686          case BITS5(0,0,0,0,0):
15687             compute_result_and_C_after_LSL_by_imm5(
15688                dis_buf, &res, &resC, rMt, imm5, rM
15689             );
15690             wot = "lsl";
15691             break;
15692          case BITS5(0,0,0,0,1):
15693             compute_result_and_C_after_LSR_by_imm5(
15694                dis_buf, &res, &resC, rMt, imm5, rM
15695             );
15696             wot = "lsr";
15697             break;
15698          case BITS5(0,0,0,1,0):
15699             compute_result_and_C_after_ASR_by_imm5(
15700                dis_buf, &res, &resC, rMt, imm5, rM
15701             );
15702             wot = "asr";
15703             break;
15704          default:
15705             /*NOTREACHED*/vassert(0);
15706       }
15707       // not safe to read guest state after this point
15708       putIRegT(rD, mkexpr(res), condT);
15709       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
15710                          cond_AND_notInIT_T );
15711       /* ignore buf and roll our own output */
15712       DIP("%ss r%u, r%u, #%u\n", wot, rD, rM, imm5);
15713       goto decode_success;
15714    }
15715
15716    case BITS5(1,1,1,0,0): {
15717       /* ---------------- B #simm11 ---------------- */
15718       Int  simm11 = INSN0(10,0);
15719            simm11 = (simm11 << 21) >> 20;
15720       UInt dst    = simm11 + guest_R15_curr_instr_notENC + 4;
15721       /* Only allowed outside or last-in IT block; SIGILL if not so. */
15722       gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15723       // and skip this insn if not selected; being cleverer is too
15724       // difficult
15725       mk_skip_over_T16_if_cond_is_false(condT);
15726       condT = IRTemp_INVALID;
15727       // now uncond
15728       irsb->next     = mkU32( dst | 1 /*CPSR.T*/ );
15729       irsb->jumpkind = Ijk_Boring;
15730       dres.whatNext  = Dis_StopHere;
15731       DIP("b 0x%x\n", dst);
15732       goto decode_success;
15733    }
15734
15735    default:
15736       break; /* examine the next shortest prefix */
15737
15738    }
15739
15740
15741    /* ================ 16-bit 15:12 cases ================ */
15742
15743    switch (INSN0(15,12)) {
15744
15745    case BITS4(1,1,0,1): {
15746       /* ---------------- Bcond #simm8 ---------------- */
15747       UInt cond  = INSN0(11,8);
15748       Int  simm8 = INSN0(7,0);
15749            simm8 = (simm8 << 24) >> 23;
15750       UInt dst   = simm8 + guest_R15_curr_instr_notENC + 4;
15751       if (cond != ARMCondAL && cond != ARMCondNV) {
15752          /* Not allowed in an IT block; SIGILL if so. */
15753          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
15754
15755          IRTemp kondT = newTemp(Ity_I32);
15756          assign( kondT, mk_armg_calculate_condition(cond) );
15757          stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
15758                             Ijk_Boring,
15759                             IRConst_U32(dst | 1/*CPSR.T*/) ));
15760          irsb->next = mkU32( (guest_R15_curr_instr_notENC + 2) 
15761                              | 1 /*CPSR.T*/ );
15762          irsb->jumpkind = Ijk_Boring;
15763          dres.whatNext  = Dis_StopHere;
15764          DIP("b%s 0x%x\n", nCC(cond), dst);
15765          goto decode_success;
15766       }
15767       break;
15768    }
15769
15770    default:
15771       break; /* hmm, nothing matched */
15772
15773    }
15774
15775    /* ================ 16-bit misc cases ================ */
15776
15777    /* ------ NOP ------ */
15778    if (INSN0(15,0) == 0xBF00) {
15779       DIP("nop");
15780       goto decode_success;
15781    }
15782
15783    /* ----------------------------------------------------------- */
15784    /* --                                                       -- */
15785    /* -- Thumb 32-bit integer instructions                     -- */
15786    /* --                                                       -- */
15787    /* ----------------------------------------------------------- */
15788
15789 #  define INSN1(_bMax,_bMin)  SLICE_UInt(((UInt)insn1), (_bMax), (_bMin))
15790
15791    /* second 16 bits of the instruction, if any */
15792    UShort insn1 = getUShortLittleEndianly( guest_instr+2 );
15793
15794    anOp   = Iop_INVALID; /* paranoia */
15795    anOpNm = NULL;        /* paranoia */
15796
15797    /* Change result defaults to suit 32-bit insns. */
15798    vassert(dres.whatNext   == Dis_Continue);
15799    vassert(dres.len        == 2);
15800    vassert(dres.continueAt == 0);
15801    dres.len = 4;
15802
15803    /* ---------------- BL/BLX simm26 ---------------- */
15804    if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) {
15805       UInt isBL = INSN1(12,12);
15806       UInt bS   = INSN0(10,10);
15807       UInt bJ1  = INSN1(13,13);
15808       UInt bJ2  = INSN1(11,11);
15809       UInt bI1  = 1 ^ (bJ1 ^ bS);
15810       UInt bI2  = 1 ^ (bJ2 ^ bS);
15811       Int simm25
15812          =   (bS          << (1 + 1 + 10 + 11 + 1))
15813            | (bI1         << (1 + 10 + 11 + 1))
15814            | (bI2         << (10 + 11 + 1))
15815            | (INSN0(9,0)  << (11 + 1))
15816            | (INSN1(10,0) << 1);
15817       simm25 = (simm25 << 7) >> 7;
15818
15819       vassert(0 == (guest_R15_curr_instr_notENC & 1));
15820       UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
15821
15822       /* One further validity case to check: in the case of BLX
15823          (not-BL), that insn1[0] must be zero. */
15824       Bool valid = True;
15825       if (isBL == 0 && INSN1(0,0) == 1) valid = False;
15826       if (valid) {
15827          /* Only allowed outside or last-in IT block; SIGILL if not so. */
15828          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15829          // and skip this insn if not selected; being cleverer is too
15830          // difficult
15831          mk_skip_over_T32_if_cond_is_false(condT);
15832          condT = IRTemp_INVALID;
15833          // now uncond
15834
15835          /* We're returning to Thumb code, hence "| 1" */
15836          putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 4) | 1 ),
15837                    IRTemp_INVALID);
15838          if (isBL) {
15839             /* BL: unconditional T -> T call */
15840             /* we're calling Thumb code, hence "| 1" */
15841             irsb->next = mkU32( dst | 1 );
15842             DIP("bl 0x%x (stay in Thumb mode)\n", dst);
15843          } else {
15844             /* BLX: unconditional T -> A call */
15845             /* we're calling ARM code, hence "& 3" to align to a
15846                valid ARM insn address */
15847             irsb->next = mkU32( dst & ~3 );
15848             DIP("blx 0x%x (switch to ARM mode)\n", dst & ~3);
15849          }
15850          irsb->jumpkind = Ijk_Call;
15851          dres.whatNext = Dis_StopHere;
15852          goto decode_success;
15853       }
15854    }
15855
15856    /* ---------------- {LD,ST}M{IA,DB} ---------------- */
15857    if (0x3a2 == INSN0(15,6) // {LD,ST}MIA
15858        || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB
15859       UInt bW      = INSN0(5,5); /* writeback Rn ? */
15860       UInt bL      = INSN0(4,4);
15861       UInt rN      = INSN0(3,0);
15862       UInt bP      = INSN1(15,15); /* reglist entry for r15 */
15863       UInt bM      = INSN1(14,14); /* reglist entry for r14 */
15864       UInt rLmost  = INSN1(12,0);  /* reglist entry for r0 .. 12 */
15865       UInt rL13    = INSN1(13,13); /* must be zero */
15866       UInt regList = 0;
15867       Bool valid   = True;
15868
15869       UInt bINC    = 1;
15870       UInt bBEFORE = 0;
15871       if (INSN0(15,6) == 0x3a4) {
15872          bINC    = 0;
15873          bBEFORE = 1;
15874       }
15875
15876       /* detect statically invalid cases, and construct the final
15877          reglist */
15878       if (rL13 == 1)
15879          valid = False;
15880
15881       if (bL == 1) {
15882          regList = (bP << 15) | (bM << 14) | rLmost;
15883          if (rN == 15)                       valid = False;
15884          if (popcount32(regList) < 2)        valid = False;
15885          if (bP == 1 && bM == 1)             valid = False;
15886          if (bW == 1 && (regList & (1<<rN))) valid = False;
15887       } else {
15888          regList = (bM << 14) | rLmost;
15889          if (bP == 1)                        valid = False;
15890          if (rN == 15)                       valid = False;
15891          if (popcount32(regList) < 2)        valid = False;
15892          if (bW == 1 && (regList & (1<<rN))) valid = False;
15893          if (regList & (1<<rN)) {
15894             UInt i;
15895             /* if Rn is in the list, then it must be the
15896                lowest numbered entry */
15897             for (i = 0; i < rN; i++) {
15898                if (regList & (1<<i))
15899                   valid = False;
15900             }
15901          }
15902       }
15903
15904       if (valid) {
15905          if (bL == 1 && bP == 1) {
15906             // We'll be writing the PC.  Hence:
15907             /* Only allowed outside or last-in IT block; SIGILL if not so. */
15908             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
15909          }
15910
15911          /* Go uncond: */
15912          mk_skip_over_T32_if_cond_is_false(condT);
15913          condT = IRTemp_INVALID;
15914          // now uncond
15915
15916          /* Generate the IR.  This might generate a write to R15, */
15917          mk_ldm_stm(False/*!arm*/, rN, bINC, bBEFORE, bW, bL, regList);
15918
15919          if (bL == 1 && (regList & (1<<15))) {
15920             // If we wrote to R15, we have an interworking return to
15921             // deal with.
15922             irsb->next     = llGetIReg(15);
15923             irsb->jumpkind = Ijk_Ret;
15924             dres.whatNext  = Dis_StopHere;
15925          }
15926
15927          DIP("%sm%c%c r%u%s, {0x%04x}\n",
15928               bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
15929               rN, bW ? "!" : "", regList);
15930
15931          goto decode_success;
15932       }
15933    }
15934
15935    /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */
15936    if (INSN0(15,11) == BITS5(1,1,1,1,0)
15937        && INSN0(9,5) == BITS5(0,1,0,0,0)
15938        && INSN1(15,15) == 0) {
15939       UInt bS = INSN0(4,4);
15940       UInt rN = INSN0(3,0);
15941       UInt rD = INSN1(11,8);
15942       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
15943       /* but allow "add.w reg, sp, #constT" */ 
15944       if (!valid && rN == 13)
15945          valid = True;
15946       if (valid) {
15947          IRTemp argL  = newTemp(Ity_I32);
15948          IRTemp argR  = newTemp(Ity_I32);
15949          IRTemp res   = newTemp(Ity_I32);
15950          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
15951          assign(argL, getIRegT(rN));
15952          assign(argR, mkU32(imm32));
15953          assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
15954          putIRegT(rD, mkexpr(res), condT);
15955          if (bS == 1)
15956             setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
15957          DIP("add%s.w r%u, r%u, #%u\n",
15958              bS == 1 ? "s" : "", rD, rN, imm32);
15959          goto decode_success;
15960       }
15961    }
15962
15963    /* ---------------- (T2) CMP.W Rn, #constT ---------------- */
15964    /* ---------------- (T2) CMN.W Rn, #constT ---------------- */
15965    if (INSN0(15,11) == BITS5(1,1,1,1,0)
15966        && (   INSN0(9,4) == BITS6(0,1,1,0,1,1)  // CMP
15967            || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN
15968        && INSN1(15,15) == 0
15969        && INSN1(11,8) == BITS4(1,1,1,1)) {
15970       UInt rN = INSN0(3,0);
15971       if (rN != 15) {
15972          IRTemp argL  = newTemp(Ity_I32);
15973          IRTemp argR  = newTemp(Ity_I32);
15974          Bool   isCMN = INSN0(9,4) == BITS6(0,1,0,0,0,1);
15975          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
15976          assign(argL, getIRegT(rN));
15977          assign(argR, mkU32(imm32));
15978          setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
15979                          argL, argR, condT );
15980          DIP("%s.w r%u, #%u\n", isCMN ? "cmn" : "cmp", rN, imm32);
15981          goto decode_success;
15982       }
15983    }
15984
15985    /* -------------- (T1) TST.W Rn, #constT -------------- */
15986    /* -------------- (T1) TEQ.W Rn, #constT -------------- */
15987    if (INSN0(15,11) == BITS5(1,1,1,1,0)
15988        && (   INSN0(9,4) == BITS6(0,0,0,0,0,1)  // TST
15989            || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ
15990        && INSN1(15,15) == 0
15991        && INSN1(11,8) == BITS4(1,1,1,1)) {
15992       UInt rN = INSN0(3,0);
15993       if (!isBadRegT(rN)) { // yes, really, it's inconsistent with CMP.W
15994          Bool  isTST  = INSN0(9,4) == BITS6(0,0,0,0,0,1);
15995          IRTemp argL  = newTemp(Ity_I32);
15996          IRTemp argR  = newTemp(Ity_I32);
15997          IRTemp res   = newTemp(Ity_I32);
15998          IRTemp oldV  = newTemp(Ity_I32);
15999          IRTemp oldC  = newTemp(Ity_I32);
16000          Bool   updC  = False;
16001          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
16002          assign(argL, getIRegT(rN));
16003          assign(argR, mkU32(imm32));
16004          assign(res,  binop(isTST ? Iop_And32 : Iop_Xor32,
16005                             mkexpr(argL), mkexpr(argR)));
16006          assign( oldV, mk_armg_calculate_flag_v() );
16007          assign( oldC, updC 
16008                        ? mkU32((imm32 >> 31) & 1)
16009                        : mk_armg_calculate_flag_c() );
16010          setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
16011          DIP("%s.w r%u, #%u\n", isTST ? "tst" : "teq", rN, imm32);
16012          goto decode_success;
16013       }
16014    }
16015
16016    /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */
16017    /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */
16018    if (INSN0(15,11) == BITS5(1,1,1,1,0)
16019        && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB
16020            || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB
16021        && INSN1(15,15) == 0) {
16022       Bool isRSB = INSN0(9,5) == BITS5(0,1,1,1,0);
16023       UInt bS    = INSN0(4,4);
16024       UInt rN    = INSN0(3,0);
16025       UInt rD    = INSN1(11,8);
16026       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
16027       /* but allow "sub{s}.w reg, sp, #constT 
16028          this is (T2) of "SUB (SP minus immediate)" */
16029       if (!valid && !isRSB && rN == 13 && rD != 15)
16030          valid = True;
16031       if (valid) {
16032          IRTemp argL  = newTemp(Ity_I32);
16033          IRTemp argR  = newTemp(Ity_I32);
16034          IRTemp res   = newTemp(Ity_I32);
16035          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16036          assign(argL, getIRegT(rN));
16037          assign(argR, mkU32(imm32));
16038          assign(res,  isRSB
16039                       ? binop(Iop_Sub32, mkexpr(argR), mkexpr(argL))
16040                       : binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
16041          putIRegT(rD, mkexpr(res), condT);
16042          if (bS == 1) {
16043             if (isRSB)
16044                setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
16045             else
16046                setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
16047          }
16048          DIP("%s%s.w r%u, r%u, #%u\n",
16049              isRSB ? "rsb" : "sub", bS == 1 ? "s" : "", rD, rN, imm32);
16050          goto decode_success;
16051       }
16052    }
16053
16054    /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */
16055    /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */
16056    if (INSN0(15,11) == BITS5(1,1,1,1,0)
16057        && (   INSN0(9,5) == BITS5(0,1,0,1,0)  // ADC
16058            || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC
16059        && INSN1(15,15) == 0) {
16060       /* ADC:  Rd = Rn + constT + oldC */
16061       /* SBC:  Rd = Rn - constT - (oldC ^ 1) */
16062       UInt bS    = INSN0(4,4);
16063       UInt rN    = INSN0(3,0);
16064       UInt rD    = INSN1(11,8);
16065       if (!isBadRegT(rN) && !isBadRegT(rD)) {
16066          IRTemp argL  = newTemp(Ity_I32);
16067          IRTemp argR  = newTemp(Ity_I32);
16068          IRTemp res   = newTemp(Ity_I32);
16069          IRTemp oldC  = newTemp(Ity_I32);
16070          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
16071          assign(argL, getIRegT(rN));
16072          assign(argR, mkU32(imm32));
16073          assign(oldC, mk_armg_calculate_flag_c() );
16074          HChar* nm  = "???";
16075          switch (INSN0(9,5)) {
16076             case BITS5(0,1,0,1,0): // ADC
16077                nm = "adc";
16078                assign(res,
16079                       binop(Iop_Add32,
16080                             binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
16081                             mkexpr(oldC) ));
16082                putIRegT(rD, mkexpr(res), condT);
16083                if (bS)
16084                   setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
16085                                      argL, argR, oldC, condT );
16086                break;
16087             case BITS5(0,1,0,1,1): // SBC
16088                nm = "sbc";
16089                assign(res,
16090                       binop(Iop_Sub32,
16091                             binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
16092                             binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
16093                putIRegT(rD, mkexpr(res), condT);
16094                if (bS)
16095                   setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
16096                                      argL, argR, oldC, condT );
16097                break;
16098             default:
16099               vassert(0);
16100          }
16101          DIP("%s%s.w r%u, r%u, #%u\n",
16102              nm, bS == 1 ? "s" : "", rD, rN, imm32);
16103          goto decode_success;
16104       }
16105    }
16106
16107    /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */
16108    /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */
16109    /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */
16110    /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */
16111    if (INSN0(15,11) == BITS5(1,1,1,1,0)
16112        && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // ORR
16113            || INSN0(9,5) == BITS5(0,0,0,0,0)  // AND
16114            || INSN0(9,5) == BITS5(0,0,0,0,1)  // BIC
16115            || INSN0(9,5) == BITS5(0,0,1,0,0)  // EOR
16116            || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN
16117        && INSN1(15,15) == 0) {
16118       UInt bS = INSN0(4,4);
16119       UInt rN = INSN0(3,0);
16120       UInt rD = INSN1(11,8);
16121       if (!isBadRegT(rN) && !isBadRegT(rD)) {
16122          Bool   notArgR = False;
16123          IROp   op      = Iop_INVALID;
16124          HChar* nm      = "???";
16125          switch (INSN0(9,5)) {
16126             case BITS5(0,0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
16127             case BITS5(0,0,0,0,0): op = Iop_And32; nm = "and"; break;
16128             case BITS5(0,0,0,0,1): op = Iop_And32; nm = "bic";
16129                                    notArgR = True; break;
16130             case BITS5(0,0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
16131             case BITS5(0,0,0,1,1): op = Iop_Or32;  nm = "orn";
16132                                    notArgR = True; break;
16133             default: vassert(0);
16134          }
16135          IRTemp argL  = newTemp(Ity_I32);
16136          IRTemp argR  = newTemp(Ity_I32);
16137          IRTemp res   = newTemp(Ity_I32);
16138          Bool   updC  = False;
16139          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
16140          assign(argL, getIRegT(rN));
16141          assign(argR, mkU32(notArgR ? ~imm32 : imm32));
16142          assign(res,  binop(op, mkexpr(argL), mkexpr(argR)));
16143          putIRegT(rD, mkexpr(res), condT);
16144          if (bS) {
16145             IRTemp oldV = newTemp(Ity_I32);
16146             IRTemp oldC = newTemp(Ity_I32);
16147             assign( oldV, mk_armg_calculate_flag_v() );
16148             assign( oldC, updC 
16149                           ? mkU32((imm32 >> 31) & 1)
16150                           : mk_armg_calculate_flag_c() );
16151             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16152                                condT );
16153          }
16154          DIP("%s%s.w r%u, r%u, #%u\n",
16155              nm, bS == 1 ? "s" : "", rD, rN, imm32);
16156          goto decode_success;
16157       }
16158    }
16159
16160    /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */
16161    /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */
16162    /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */
16163    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16164        && (   INSN0(8,5) == BITS4(1,0,0,0)  // add subopc
16165            || INSN0(8,5) == BITS4(1,1,0,1)  // sub subopc
16166            || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc
16167        && INSN1(15,15) == 0) {
16168       UInt rN   = INSN0(3,0);
16169       UInt rD   = INSN1(11,8);
16170       UInt rM   = INSN1(3,0);
16171       UInt bS   = INSN0(4,4);
16172       UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16173       UInt how  = INSN1(5,4);
16174
16175       Bool valid = !isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM);
16176       /* but allow "add.w reg, sp, reg   w/ no shift
16177          (T3) "ADD (SP plus register) */
16178       if (!valid && INSN0(8,5) == BITS4(1,0,0,0) // add
16179           && rD != 15 && rN == 13 && imm5 == 0 && how == 0) {
16180          valid = True;
16181       }
16182       /* also allow "sub.w reg, sp, reg   w/ no shift
16183          (T1) "SUB (SP minus register) */
16184       if (!valid && INSN0(8,5) == BITS4(1,1,0,1) // sub
16185           && rD != 15 && rN == 13 && imm5 == 0 && how == 0) {
16186          valid = True;
16187       }
16188       if (valid) {
16189          Bool   swap = False;
16190          IROp   op   = Iop_INVALID;
16191          HChar* nm   = "???";
16192          switch (INSN0(8,5)) {
16193             case BITS4(1,0,0,0): op = Iop_Add32; nm = "add"; break;
16194             case BITS4(1,1,0,1): op = Iop_Sub32; nm = "sub"; break;
16195             case BITS4(1,1,1,0): op = Iop_Sub32; nm = "rsb"; 
16196                                  swap = True; break;
16197             default: vassert(0);
16198          }
16199
16200          IRTemp argL = newTemp(Ity_I32);
16201          assign(argL, getIRegT(rN));
16202
16203          IRTemp rMt = newTemp(Ity_I32);
16204          assign(rMt, getIRegT(rM));
16205
16206          IRTemp argR = newTemp(Ity_I32);
16207          compute_result_and_C_after_shift_by_imm5(
16208             dis_buf, &argR, NULL, rMt, how, imm5, rM
16209          );
16210
16211          IRTemp res = newTemp(Ity_I32);
16212          assign(res, swap 
16213                      ? binop(op, mkexpr(argR), mkexpr(argL))
16214                      : binop(op, mkexpr(argL), mkexpr(argR)));
16215
16216          putIRegT(rD, mkexpr(res), condT);
16217          if (bS) {
16218             switch (op) {
16219                case Iop_Add32:
16220                   setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
16221                   break;
16222                case Iop_Sub32:
16223                   if (swap)
16224                      setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
16225                   else
16226                      setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
16227                   break;
16228                default:
16229                   vassert(0);
16230             }
16231          }
16232
16233          DIP("%s%s.w r%u, r%u, %s\n",
16234              nm, bS ? "s" : "", rD, rN, dis_buf);
16235          goto decode_success;
16236       }
16237    }
16238
16239    /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */
16240    /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */
16241    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16242        && (   INSN0(8,5) == BITS4(1,0,1,0)   // adc subopc
16243            || INSN0(8,5) == BITS4(1,0,1,1))  // sbc subopc
16244        && INSN1(15,15) == 0) {
16245       /* ADC:  Rd = Rn + shifter_operand + oldC */
16246       /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
16247       UInt rN = INSN0(3,0);
16248       UInt rD = INSN1(11,8);
16249       UInt rM = INSN1(3,0);
16250       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
16251          UInt bS   = INSN0(4,4);
16252          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16253          UInt how  = INSN1(5,4);
16254
16255          IRTemp argL = newTemp(Ity_I32);
16256          assign(argL, getIRegT(rN));
16257
16258          IRTemp rMt = newTemp(Ity_I32);
16259          assign(rMt, getIRegT(rM));
16260
16261          IRTemp oldC = newTemp(Ity_I32);
16262          assign(oldC, mk_armg_calculate_flag_c());
16263
16264          IRTemp argR = newTemp(Ity_I32);
16265          compute_result_and_C_after_shift_by_imm5(
16266             dis_buf, &argR, NULL, rMt, how, imm5, rM
16267          );
16268
16269          HChar* nm  = "???";
16270          IRTemp res = newTemp(Ity_I32);
16271          switch (INSN0(8,5)) {
16272             case BITS4(1,0,1,0): // ADC
16273                nm = "adc";
16274                assign(res,
16275                       binop(Iop_Add32,
16276                             binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
16277                             mkexpr(oldC) ));
16278                putIRegT(rD, mkexpr(res), condT);
16279                if (bS)
16280                   setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
16281                                      argL, argR, oldC, condT );
16282                break;
16283             case BITS4(1,0,1,1): // SBC
16284                nm = "sbc";
16285                assign(res,
16286                       binop(Iop_Sub32,
16287                             binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
16288                             binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
16289                putIRegT(rD, mkexpr(res), condT);
16290                if (bS)
16291                   setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
16292                                      argL, argR, oldC, condT );
16293                break;
16294             default:
16295                vassert(0);
16296          }
16297
16298          DIP("%s%s.w r%u, r%u, %s\n",
16299              nm, bS ? "s" : "", rD, rN, dis_buf);
16300          goto decode_success;
16301       }
16302    }
16303
16304    /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */
16305    /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */
16306    /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */
16307    /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */
16308    /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */
16309    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16310        && (   INSN0(8,5) == BITS4(0,0,0,0)  // and subopc
16311            || INSN0(8,5) == BITS4(0,0,1,0)  // orr subopc
16312            || INSN0(8,5) == BITS4(0,1,0,0)  // eor subopc
16313            || INSN0(8,5) == BITS4(0,0,0,1)  // bic subopc
16314            || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc
16315        && INSN1(15,15) == 0) {
16316       UInt rN = INSN0(3,0);
16317       UInt rD = INSN1(11,8);
16318       UInt rM = INSN1(3,0);
16319       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
16320          Bool notArgR = False;
16321          IROp op      = Iop_INVALID;
16322          HChar* nm  = "???";
16323          switch (INSN0(8,5)) {
16324             case BITS4(0,0,0,0): op = Iop_And32; nm = "and"; break;
16325             case BITS4(0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
16326             case BITS4(0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
16327             case BITS4(0,0,0,1): op = Iop_And32; nm = "bic";
16328                                  notArgR = True; break;
16329             case BITS4(0,0,1,1): op = Iop_Or32; nm = "orn";
16330                                  notArgR = True; break;
16331             default: vassert(0);
16332          }
16333          UInt bS   = INSN0(4,4);
16334          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16335          UInt how  = INSN1(5,4);
16336
16337          IRTemp rNt = newTemp(Ity_I32);
16338          assign(rNt, getIRegT(rN));
16339
16340          IRTemp rMt = newTemp(Ity_I32);
16341          assign(rMt, getIRegT(rM));
16342
16343          IRTemp argR = newTemp(Ity_I32);
16344          IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
16345
16346          compute_result_and_C_after_shift_by_imm5(
16347             dis_buf, &argR, bS ? &oldC : NULL, rMt, how, imm5, rM
16348          );
16349
16350          IRTemp res = newTemp(Ity_I32);
16351          if (notArgR) {
16352             vassert(op == Iop_And32 || op == Iop_Or32);
16353             assign(res, binop(op, mkexpr(rNt),
16354                                   unop(Iop_Not32, mkexpr(argR))));
16355          } else {
16356             assign(res, binop(op, mkexpr(rNt), mkexpr(argR)));
16357          }
16358
16359          putIRegT(rD, mkexpr(res), condT);
16360          if (bS) {
16361             IRTemp oldV = newTemp(Ity_I32);
16362             assign( oldV, mk_armg_calculate_flag_v() );
16363             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16364                                condT );
16365          }
16366
16367          DIP("%s%s.w r%u, r%u, %s\n",
16368              nm, bS ? "s" : "", rD, rN, dis_buf);
16369          goto decode_success;
16370       }
16371    }
16372
16373    /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */
16374    /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */
16375    /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */
16376    /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */
16377    if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0)
16378        && INSN1(15,12) == BITS4(1,1,1,1)
16379        && INSN1(7,4) == BITS4(0,0,0,0)) {
16380       UInt how = INSN0(6,5); // standard encoding
16381       UInt rN  = INSN0(3,0);
16382       UInt rD  = INSN1(11,8);
16383       UInt rM  = INSN1(3,0);
16384       UInt bS  = INSN0(4,4);
16385       Bool valid = !isBadRegT(rN) && !isBadRegT(rM) && !isBadRegT(rD);
16386       if (how == 3) valid = False; //ATC
16387       if (valid) {
16388          IRTemp rNt    = newTemp(Ity_I32);
16389          IRTemp rMt    = newTemp(Ity_I32);
16390          IRTemp res    = newTemp(Ity_I32);
16391          IRTemp oldC   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
16392          IRTemp oldV   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
16393          HChar* nms[4] = { "lsl", "lsr", "asr", "ror" };
16394          HChar* nm     = nms[how];
16395          assign(rNt, getIRegT(rN));
16396          assign(rMt, getIRegT(rM));
16397          compute_result_and_C_after_shift_by_reg(
16398             dis_buf, &res, bS ? &oldC : NULL,
16399             rNt, how, rMt, rN, rM
16400          );
16401          if (bS)
16402             assign(oldV, mk_armg_calculate_flag_v());
16403          putIRegT(rD, mkexpr(res), condT);
16404          if (bS) {
16405             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16406                                condT );
16407          }
16408          DIP("%s%s.w r%u, r%u, r%u\n",
16409              nm, bS ? "s" : "", rD, rN, rM);
16410          goto decode_success;
16411       }
16412    }
16413
16414    /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */
16415    /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */
16416    if ((INSN0(15,0) & 0xFFCF) == 0xEA4F
16417        && INSN1(15,15) == 0) {
16418       UInt rD = INSN1(11,8);
16419       UInt rN = INSN1(3,0);
16420       if (!isBadRegT(rD) && !isBadRegT(rN)) {
16421          UInt bS    = INSN0(4,4);
16422          UInt isMVN = INSN0(5,5);
16423          UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
16424          UInt how   = INSN1(5,4);
16425
16426          IRTemp rNt = newTemp(Ity_I32);
16427          assign(rNt, getIRegT(rN));
16428
16429          IRTemp oldRn = newTemp(Ity_I32);
16430          IRTemp oldC  = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
16431          compute_result_and_C_after_shift_by_imm5(
16432             dis_buf, &oldRn, bS ? &oldC : NULL, rNt, how, imm5, rN
16433          );
16434
16435          IRTemp res = newTemp(Ity_I32);
16436          assign(res, isMVN ? unop(Iop_Not32, mkexpr(oldRn))
16437                            : mkexpr(oldRn));
16438
16439          putIRegT(rD, mkexpr(res), condT);
16440          if (bS) {
16441             IRTemp oldV = newTemp(Ity_I32);
16442             assign( oldV, mk_armg_calculate_flag_v() );
16443             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT);
16444          }
16445          DIP("%s%s.w r%u, %s\n",
16446              isMVN ? "mvn" : "mov", bS ? "s" : "", rD, dis_buf);
16447          goto decode_success;
16448       }
16449    }
16450
16451    /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */
16452    /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */
16453    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16454        && (   INSN0(8,4) == BITS5(0,0,0,0,1)  // TST
16455            || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ
16456        && INSN1(15,15) == 0
16457        && INSN1(11,8) == BITS4(1,1,1,1)) {
16458       UInt rN = INSN0(3,0);
16459       UInt rM = INSN1(3,0);
16460       if (!isBadRegT(rN) && !isBadRegT(rM)) {
16461          Bool isTST = INSN0(8,4) == BITS5(0,0,0,0,1);
16462
16463          UInt how  = INSN1(5,4);
16464          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
16465
16466          IRTemp argL = newTemp(Ity_I32);
16467          assign(argL, getIRegT(rN));
16468
16469          IRTemp rMt = newTemp(Ity_I32);
16470          assign(rMt, getIRegT(rM));
16471
16472          IRTemp argR = newTemp(Ity_I32);
16473          IRTemp oldC = newTemp(Ity_I32);
16474          compute_result_and_C_after_shift_by_imm5(
16475             dis_buf, &argR, &oldC, rMt, how, imm5, rM
16476          );
16477
16478          IRTemp oldV = newTemp(Ity_I32);
16479          assign( oldV, mk_armg_calculate_flag_v() );
16480
16481          IRTemp res = newTemp(Ity_I32);
16482          assign(res, binop(isTST ? Iop_And32 : Iop_Xor32,
16483                            mkexpr(argL), mkexpr(argR)));
16484
16485          setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16486                             condT );
16487          DIP("%s.w r%u, %s\n", isTST ? "tst" : "teq", rN, dis_buf);
16488          goto decode_success;
16489       }
16490    }
16491
16492    /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */
16493    /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */
16494    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
16495        && (   INSN0(8,4) == BITS5(1,1,0,1,1)  // CMP
16496            || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN
16497        && INSN1(15,15) == 0
16498        && INSN1(11,8) == BITS4(1,1,1,1)) {
16499       UInt rN = INSN0(3,0);
16500       UInt rM = INSN1(3,0);
16501       if (!isBadRegT(rN) && !isBadRegT(rM)) {
16502          Bool isCMN = INSN0(8,4) == BITS5(1,0,0,0,1);
16503          UInt how   = INSN1(5,4);
16504          UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
16505
16506          IRTemp argL = newTemp(Ity_I32);
16507          assign(argL, getIRegT(rN));
16508
16509          IRTemp rMt = newTemp(Ity_I32);
16510          assign(rMt, getIRegT(rM));
16511
16512          IRTemp argR = newTemp(Ity_I32);
16513          compute_result_and_C_after_shift_by_imm5(
16514             dis_buf, &argR, NULL, rMt, how, imm5, rM
16515          );
16516
16517          setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
16518                          argL, argR, condT );
16519
16520          DIP("%s.w r%u, %s\n", isCMN ? "cmn" : "cmp", rN, dis_buf);
16521          goto decode_success;
16522       }
16523    }
16524
16525    /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */
16526    /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */
16527    if (INSN0(15,11) == BITS5(1,1,1,1,0)
16528        && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // MOV
16529            || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN
16530        && INSN0(3,0) == BITS4(1,1,1,1)
16531        && INSN1(15,15) == 0) {
16532       UInt rD = INSN1(11,8);
16533       if (!isBadRegT(rD)) {
16534          Bool   updC  = False;
16535          UInt   bS    = INSN0(4,4);
16536          Bool   isMVN = INSN0(5,5) == 1;
16537          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
16538          IRTemp res   = newTemp(Ity_I32);
16539          assign(res, mkU32(isMVN ? ~imm32 : imm32));
16540          putIRegT(rD, mkexpr(res), condT);
16541          if (bS) {
16542             IRTemp oldV = newTemp(Ity_I32);
16543             IRTemp oldC = newTemp(Ity_I32);
16544             assign( oldV, mk_armg_calculate_flag_v() );
16545             assign( oldC, updC 
16546                           ? mkU32((imm32 >> 31) & 1)
16547                           : mk_armg_calculate_flag_c() );
16548             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
16549                                condT );
16550          }
16551          DIP("%s%s.w r%u, #%u\n",
16552              isMVN ? "mvn" : "mov", bS ? "s" : "", rD, imm32);
16553          goto decode_success;
16554       }
16555    }
16556
16557    /* -------------- (T3) MOVW Rd, #imm16 -------------- */
16558    if (INSN0(15,11) == BITS5(1,1,1,1,0)
16559        && INSN0(9,4) == BITS6(1,0,0,1,0,0)
16560        && INSN1(15,15) == 0) {
16561       UInt rD = INSN1(11,8);
16562       if (!isBadRegT(rD)) {
16563          UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
16564                       | (INSN1(14,12) << 8) | INSN1(7,0);
16565          putIRegT(rD, mkU32(imm16), condT);
16566          DIP("movw r%u, #%u\n", rD, imm16);
16567          goto decode_success;
16568       }
16569    }
16570
16571    /* ---------------- MOVT Rd, #imm16 ---------------- */
16572    if (INSN0(15,11) == BITS5(1,1,1,1,0)
16573        && INSN0(9,4) == BITS6(1,0,1,1,0,0)
16574        && INSN1(15,15) == 0) {
16575       UInt rD = INSN1(11,8);
16576       if (!isBadRegT(rD)) {
16577          UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
16578                       | (INSN1(14,12) << 8) | INSN1(7,0);
16579          IRTemp res = newTemp(Ity_I32);
16580          assign(res,
16581                 binop(Iop_Or32,
16582                       binop(Iop_And32, getIRegT(rD), mkU32(0xFFFF)),
16583                       mkU32(imm16 << 16)));
16584          putIRegT(rD, mkexpr(res), condT);
16585          DIP("movt r%u, #%u\n", rD, imm16);
16586          goto decode_success;
16587       }
16588    }
16589
16590    /* ---------------- LD/ST reg+/-#imm8 ---------------- */
16591    /* Loads and stores of the form:
16592          op  Rt, [Rn, #-imm8]      or
16593          op  Rt, [Rn], #+/-imm8    or
16594          op  Rt, [Rn, #+/-imm8]!  
16595       where op is one of
16596          ldrb ldrh ldr  ldrsb ldrsh
16597          strb strh str
16598    */
16599    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) {
16600       Bool   valid  = True;
16601       Bool   syned  = False;
16602       Bool   isST   = False;
16603       IRType ty     = Ity_I8;
16604       HChar* nm     = "???";
16605
16606       switch (INSN0(8,4)) {
16607          case BITS5(0,0,0,0,0):   // strb
16608             nm = "strb"; isST = True; break;
16609          case BITS5(0,0,0,0,1):   // ldrb
16610             nm = "ldrb"; break;
16611          case BITS5(1,0,0,0,1):   // ldrsb
16612             nm = "ldrsb"; syned = True; break;
16613          case BITS5(0,0,0,1,0):   // strh
16614             nm = "strh"; ty = Ity_I16; isST = True; break;
16615          case BITS5(0,0,0,1,1):   // ldrh
16616             nm = "ldrh"; ty = Ity_I16; break;
16617          case BITS5(1,0,0,1,1):   // ldrsh
16618             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
16619          case BITS5(0,0,1,0,0):   // str
16620             nm = "str"; ty = Ity_I32; isST = True; break;
16621          case BITS5(0,0,1,0,1):
16622             nm = "ldr"; ty = Ity_I32; break;  // ldr
16623          default:
16624             valid = False; break;
16625       }
16626
16627       UInt rN      = INSN0(3,0);
16628       UInt rT      = INSN1(15,12);
16629       UInt bP      = INSN1(10,10);
16630       UInt bU      = INSN1(9,9);
16631       UInt bW      = INSN1(8,8);
16632       UInt imm8    = INSN1(7,0);
16633       Bool loadsPC = False;
16634
16635       if (valid) {
16636          if (bP == 1 && bU == 1 && bW == 0)
16637             valid = False;
16638          if (bP == 0 && bW == 0)
16639             valid = False;
16640          if (rN == 15)
16641             valid = False;
16642          if (bW == 1 && rN == rT)
16643             valid = False;
16644          if (ty == Ity_I8 || ty == Ity_I16) {
16645             if (isBadRegT(rT))
16646                valid = False;
16647          } else {
16648             /* ty == Ity_I32 */
16649             if (isST && rT == 15)
16650                valid = False;
16651             if (!isST && rT == 15)
16652                loadsPC = True;
16653          }
16654       }
16655
16656       if (valid) {
16657          // if it's a branch, it can't happen in the middle of an IT block
16658          if (loadsPC)
16659             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16660          // go uncond
16661          mk_skip_over_T32_if_cond_is_false(condT);
16662          condT = IRTemp_INVALID;
16663          // now uncond
16664
16665          IRTemp preAddr = newTemp(Ity_I32);
16666          assign(preAddr, getIRegT(rN));
16667
16668          IRTemp postAddr = newTemp(Ity_I32);
16669          assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
16670                                 mkexpr(preAddr), mkU32(imm8)));
16671
16672          IRTemp transAddr = bP == 1 ? postAddr : preAddr;
16673
16674          if (isST) {
16675
16676              /* Store.  If necessary, update the base register before
16677                 the store itself, so that the common idiom of "str rX,
16678                 [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4,
16679                 a.k.a "push rX") doesn't cause Memcheck to complain
16680                 that the access is below the stack pointer.  Also, not
16681                 updating sp before the store confuses Valgrind's
16682                 dynamic stack-extending logic.  So do it before the
16683                 store.  Hence we need to snarf the store data before
16684                 doing the basereg update. */
16685
16686             /* get hold of the data to be stored */
16687             IRTemp oldRt = newTemp(Ity_I32);
16688             assign(oldRt, getIRegT(rT));
16689
16690             /* Update Rn if necessary. */
16691             if (bW == 1) {
16692                vassert(rN != rT); // assured by validity check above
16693                putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
16694             }
16695
16696             /* generate the transfer */
16697             switch (ty) {
16698                case Ity_I8:
16699                   storeLE(mkexpr(transAddr),
16700                                  unop(Iop_32to8, mkexpr(oldRt)));
16701                   break;
16702                case Ity_I16:
16703                   storeLE(mkexpr(transAddr),
16704                           unop(Iop_32to16, mkexpr(oldRt)));
16705                   break;
16706               case Ity_I32:
16707                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
16708                   break;
16709               default:
16710                  vassert(0);
16711             }
16712
16713          } else {
16714
16715             /* Load. */
16716
16717             /* generate the transfer */
16718             IRTemp newRt = newTemp(Ity_I32);
16719             IROp   widen = Iop_INVALID;
16720             switch (ty) {
16721                case Ity_I8:
16722                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
16723                case Ity_I16:
16724                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
16725                case Ity_I32:
16726                   break;
16727                default:
16728                   vassert(0);
16729             }
16730             if (widen == Iop_INVALID) {
16731                assign(newRt, loadLE(ty, mkexpr(transAddr)));
16732             } else {
16733                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
16734             }
16735             if (loadsPC) {
16736                vassert(rT == 15);
16737                llPutIReg(rT, mkexpr(newRt));
16738             } else {
16739                putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
16740             }
16741
16742             if (loadsPC) {
16743                /* Presumably this is an interworking branch. */
16744                irsb->next = mkexpr(newRt);
16745                irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
16746                dres.whatNext  = Dis_StopHere;
16747             }
16748
16749             /* Update Rn if necessary. */
16750             if (bW == 1) {
16751                vassert(rN != rT); // assured by validity check above
16752                putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
16753             }
16754          }
16755
16756          if (bP == 1 && bW == 0) {
16757             DIP("%s.w r%u, [r%u, #%c%u]\n",
16758                 nm, rT, rN, bU ? '+' : '-', imm8);
16759          }
16760          else if (bP == 1 && bW == 1) {
16761             DIP("%s.w r%u, [r%u, #%c%u]!\n",
16762                 nm, rT, rN, bU ? '+' : '-', imm8);
16763          }
16764          else {
16765             vassert(bP == 0 && bW == 1);
16766             DIP("%s.w r%u, [r%u], #%c%u\n",
16767                 nm, rT, rN, bU ? '+' : '-', imm8);
16768          }
16769
16770          goto decode_success;
16771       }
16772    }
16773
16774    /* ------------- LD/ST reg+(reg<<imm2) ------------- */
16775    /* Loads and stores of the form:
16776          op  Rt, [Rn, Rm, LSL #imm8]
16777       where op is one of
16778          ldrb ldrh ldr  ldrsb ldrsh
16779          strb strh str
16780    */
16781    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)
16782        && INSN1(11,6) == BITS6(0,0,0,0,0,0)) {
16783       Bool   valid  = True;
16784       Bool   syned  = False;
16785       Bool   isST   = False;
16786       IRType ty     = Ity_I8;
16787       HChar* nm     = "???";
16788
16789       switch (INSN0(8,4)) {
16790          case BITS5(0,0,0,0,0):   // strb
16791             nm = "strb"; isST = True; break;
16792          case BITS5(0,0,0,0,1):   // ldrb
16793             nm = "ldrb"; break;
16794          case BITS5(1,0,0,0,1):   // ldrsb
16795             nm = "ldrsb"; syned = True; break;
16796          case BITS5(0,0,0,1,0):   // strh
16797             nm = "strh"; ty = Ity_I16; isST = True; break;
16798          case BITS5(0,0,0,1,1):   // ldrh
16799             nm = "ldrh"; ty = Ity_I16; break;
16800          case BITS5(1,0,0,1,1):   // ldrsh
16801             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
16802          case BITS5(0,0,1,0,0):   // str
16803             nm = "str"; ty = Ity_I32; isST = True; break;
16804          case BITS5(0,0,1,0,1):
16805             nm = "ldr"; ty = Ity_I32; break;  // ldr
16806          default:
16807             valid = False; break;
16808       }
16809
16810       UInt rN      = INSN0(3,0);
16811       UInt rM      = INSN1(3,0);
16812       UInt rT      = INSN1(15,12);
16813       UInt imm2    = INSN1(5,4);
16814       Bool loadsPC = False;
16815
16816       if (ty == Ity_I8 || ty == Ity_I16) {
16817          /* all 8- and 16-bit load and store cases have the
16818             same exclusion set. */
16819          if (rN == 15 || isBadRegT(rT) || isBadRegT(rM))
16820             valid = False;
16821       } else {
16822          vassert(ty == Ity_I32);
16823          if (rN == 15 || isBadRegT(rM))
16824             valid = False;
16825          if (isST && rT == 15)
16826             valid = False;
16827          /* If it is a load and rT is 15, that's only allowable if we
16828             not in an IT block, or are the last in it.  Need to insert
16829             a dynamic check for that. */
16830          if (!isST && rT == 15)
16831             loadsPC = True;
16832       }
16833
16834       if (valid) {
16835          // if it's a branch, it can't happen in the middle of an IT block
16836          if (loadsPC)
16837             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16838          // go uncond
16839          mk_skip_over_T32_if_cond_is_false(condT);
16840          condT = IRTemp_INVALID;
16841          // now uncond
16842
16843          IRTemp transAddr = newTemp(Ity_I32);
16844          assign(transAddr,
16845                 binop( Iop_Add32,
16846                        getIRegT(rN),
16847                        binop(Iop_Shl32, getIRegT(rM), mkU8(imm2)) ));
16848
16849          if (isST) {
16850             IRTemp oldRt = newTemp(Ity_I32);
16851             assign(oldRt, getIRegT(rT));
16852             switch (ty) {
16853                case Ity_I8:
16854                   storeLE(mkexpr(transAddr),
16855                                  unop(Iop_32to8, mkexpr(oldRt)));
16856                   break;
16857                case Ity_I16:
16858                   storeLE(mkexpr(transAddr),
16859                           unop(Iop_32to16, mkexpr(oldRt)));
16860                   break;
16861               case Ity_I32:
16862                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
16863                   break;
16864               default:
16865                  vassert(0);
16866             }
16867          } else {
16868             IRTemp newRt = newTemp(Ity_I32);
16869             IROp   widen = Iop_INVALID;
16870             switch (ty) {
16871                case Ity_I8:
16872                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
16873                case Ity_I16:
16874                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
16875                case Ity_I32:
16876                   break;
16877                default:
16878                   vassert(0);
16879             }
16880             if (widen == Iop_INVALID) {
16881                assign(newRt, loadLE(ty, mkexpr(transAddr)));
16882             } else {
16883                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
16884             }
16885
16886             /* If we're loading the PC, putIRegT will assert.  So go
16887                direct via llPutIReg.  In all other cases use putIRegT
16888                as it is safer (although could simply use llPutIReg for
16889                _all_ cases here.) */
16890             if (loadsPC) {
16891                vassert(rT == 15);
16892                llPutIReg(rT, mkexpr(newRt));
16893             } else {
16894                putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
16895             }
16896
16897             if (loadsPC) {
16898                /* Presumably this is an interworking branch. */
16899                irsb->next = mkexpr(newRt);
16900                irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
16901                dres.whatNext  = Dis_StopHere;
16902             }
16903          }
16904
16905          DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n",
16906              nm, rT, rN, rM, imm2);
16907
16908          goto decode_success;
16909       }
16910    }
16911
16912    /* --------------- LD/ST reg+imm12 --------------- */
16913    /* Loads and stores of the form:
16914          op  Rt, [Rn, +#imm12]
16915       where op is one of
16916          ldrb ldrh ldr  ldrsb ldrsh
16917          strb strh str
16918    */
16919    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) {
16920       Bool   valid  = True;
16921       Bool   syned  = False;
16922       Bool   isST   = False;
16923       IRType ty     = Ity_I8;
16924       HChar* nm     = "???";
16925
16926       switch (INSN0(8,4)) {
16927          case BITS5(0,1,0,0,0):   // strb
16928             nm = "strb"; isST = True; break;
16929          case BITS5(0,1,0,0,1):   // ldrb
16930             nm = "ldrb"; break;
16931          case BITS5(1,1,0,0,1):   // ldrsb
16932             nm = "ldrsb"; syned = True; break;
16933          case BITS5(0,1,0,1,0):   // strh
16934             nm = "strh"; ty = Ity_I16; isST = True; break;
16935          case BITS5(0,1,0,1,1):   // ldrh
16936             nm = "ldrh"; ty = Ity_I16; break;
16937          case BITS5(1,1,0,1,1):   // ldrsh
16938             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
16939          case BITS5(0,1,1,0,0):   // str
16940             nm = "str"; ty = Ity_I32; isST = True; break;
16941          case BITS5(0,1,1,0,1):
16942             nm = "ldr"; ty = Ity_I32; break;  // ldr
16943          default:
16944             valid = False; break;
16945       }
16946
16947       UInt rN      = INSN0(3,0);
16948       UInt rT      = INSN1(15,12);
16949       UInt imm12   = INSN1(11,0);
16950       Bool loadsPC = False;
16951
16952       if (ty == Ity_I8 || ty == Ity_I16) {
16953          /* all 8- and 16-bit load and store cases have the
16954             same exclusion set. */
16955          if (rN == 15 || isBadRegT(rT))
16956             valid = False;
16957       } else {
16958          vassert(ty == Ity_I32);
16959          if (isST) {
16960             if (rN == 15 || rT == 15)
16961                valid = False;
16962          } else {
16963             /* For a 32-bit load, rT == 15 is only allowable if we not
16964                in an IT block, or are the last in it.  Need to insert
16965                a dynamic check for that.  Also, in this particular
16966                case, rN == 15 is allowable.  In this case however, the
16967                value obtained for rN is (apparently)
16968                "word-align(address of current insn + 4)". */
16969             if (rT == 15)
16970                loadsPC = True;
16971          }
16972       }
16973
16974       if (valid) {
16975          // if it's a branch, it can't happen in the middle of an IT block
16976          if (loadsPC)
16977             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
16978          // go uncond
16979          mk_skip_over_T32_if_cond_is_false(condT);
16980          condT = IRTemp_INVALID;
16981          // now uncond
16982
16983          IRTemp rNt = newTemp(Ity_I32);
16984          if (rN == 15) {
16985             vassert(ty == Ity_I32 && !isST);
16986             assign(rNt, binop(Iop_And32, getIRegT(rN), mkU32(~3)));
16987          } else {
16988             assign(rNt, getIRegT(rN));
16989          }
16990
16991          IRTemp transAddr = newTemp(Ity_I32);
16992          assign(transAddr,
16993                 binop( Iop_Add32, mkexpr(rNt), mkU32(imm12) ));
16994
16995          if (isST) {
16996             IRTemp oldRt = newTemp(Ity_I32);
16997             assign(oldRt, getIRegT(rT));
16998             switch (ty) {
16999                case Ity_I8:
17000                   storeLE(mkexpr(transAddr),
17001                                  unop(Iop_32to8, mkexpr(oldRt)));
17002                   break;
17003                case Ity_I16:
17004                   storeLE(mkexpr(transAddr),
17005                           unop(Iop_32to16, mkexpr(oldRt)));
17006                   break;
17007               case Ity_I32:
17008                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
17009                   break;
17010               default:
17011                  vassert(0);
17012             }
17013          } else {
17014             IRTemp newRt = newTemp(Ity_I32);
17015             IROp   widen = Iop_INVALID;
17016             switch (ty) {
17017                case Ity_I8:
17018                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
17019                case Ity_I16:
17020                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
17021                case Ity_I32:
17022                   break;
17023                default:
17024                   vassert(0);
17025             }
17026             if (widen == Iop_INVALID) {
17027                assign(newRt, loadLE(ty, mkexpr(transAddr)));
17028             } else {
17029                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
17030             }
17031             putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
17032
17033             if (loadsPC) {
17034                /* Presumably this is an interworking branch. */
17035                irsb->next = mkexpr(newRt);
17036                irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
17037                dres.whatNext  = Dis_StopHere;
17038             }
17039          }
17040
17041          DIP("%s.w r%u, [r%u, +#%u]\n", nm, rT, rN, imm12);
17042
17043          goto decode_success;
17044       }
17045    }
17046
17047    /* -------------- LDRD/STRD reg+/-#imm8 -------------- */
17048    /* Doubleword loads and stores of the form:
17049          ldrd/strd  Rt, Rt2, [Rn, #-imm8]      or
17050          ldrd/strd  Rt, Rt2, [Rn], #+/-imm8    or
17051          ldrd/strd  Rt, Rt2, [Rn, #+/-imm8]!  
17052    */
17053    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) {
17054       UInt bP   = INSN0(8,8);
17055       UInt bU   = INSN0(7,7);
17056       UInt bW   = INSN0(5,5);
17057       UInt bL   = INSN0(4,4);  // 1: load  0: store
17058       UInt rN   = INSN0(3,0);
17059       UInt rT   = INSN1(15,12);
17060       UInt rT2  = INSN1(11,8);
17061       UInt imm8 = INSN1(7,0);
17062
17063       Bool valid = True;
17064       if (bP == 0 && bW == 0)                 valid = False;
17065       if (bW == 1 && (rN == rT || rN == rT2)) valid = False;
17066       if (isBadRegT(rT) || isBadRegT(rT2))    valid = False;
17067       if (rN == 15)                           valid = False;
17068       if (bL == 1 && rT == rT2)               valid = False;
17069
17070       if (valid) {
17071          // go uncond
17072          mk_skip_over_T32_if_cond_is_false(condT);
17073          condT = IRTemp_INVALID;
17074          // now uncond
17075
17076          IRTemp preAddr = newTemp(Ity_I32);
17077          assign(preAddr, getIRegT(rN));
17078
17079          IRTemp postAddr = newTemp(Ity_I32);
17080          assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
17081                                 mkexpr(preAddr), mkU32(imm8 << 2)));
17082
17083          IRTemp transAddr = bP == 1 ? postAddr : preAddr;
17084
17085          if (bL == 0) {
17086             IRTemp oldRt  = newTemp(Ity_I32);
17087             IRTemp oldRt2 = newTemp(Ity_I32);
17088             assign(oldRt,  getIRegT(rT));
17089             assign(oldRt2, getIRegT(rT2));
17090             storeLE(mkexpr(transAddr),
17091                     mkexpr(oldRt));
17092             storeLE(binop(Iop_Add32, mkexpr(transAddr), mkU32(4)),
17093                     mkexpr(oldRt2));
17094          } else {
17095             IRTemp newRt  = newTemp(Ity_I32);
17096             IRTemp newRt2 = newTemp(Ity_I32);
17097             assign(newRt,
17098                    loadLE(Ity_I32,
17099                           mkexpr(transAddr)));
17100             assign(newRt2,
17101                    loadLE(Ity_I32,
17102                           binop(Iop_Add32, mkexpr(transAddr), mkU32(4))));
17103             putIRegT(rT,  mkexpr(newRt), IRTemp_INVALID);
17104             putIRegT(rT2, mkexpr(newRt2), IRTemp_INVALID);
17105          }
17106
17107          if (bW == 1) {
17108             putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
17109          }
17110
17111          HChar* nm = bL ? "ldrd" : "strd";
17112
17113          if (bP == 1 && bW == 0) {
17114             DIP("%s.w r%u, r%u, [r%u, #%c%u]\n",
17115                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17116          }
17117          else if (bP == 1 && bW == 1) {
17118             DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n",
17119                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17120          }
17121          else {
17122             vassert(bP == 0 && bW == 1);
17123             DIP("%s.w r%u, r%u, [r%u], #%c%u\n",
17124                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
17125          }
17126
17127          goto decode_success;
17128       }
17129    }
17130
17131    /* -------------- (T3) Bcond.W label -------------- */
17132    /* This variant carries its own condition, so can't be part of an
17133       IT block ... */
17134    if (INSN0(15,11) == BITS5(1,1,1,1,0)
17135        && INSN1(15,14) == BITS2(1,0)
17136        && INSN1(12,12) == 0) {
17137       UInt cond = INSN0(9,6);
17138       if (cond != ARMCondAL && cond != ARMCondNV) {
17139          Int simm21
17140             =   (INSN0(10,10) << (1 + 1 + 6 + 11 + 1))
17141               | (INSN1(11,11) << (1 + 6 + 11 + 1))
17142               | (INSN1(13,13) << (6 + 11 + 1))
17143               | (INSN0(5,0)   << (11 + 1))
17144               | (INSN1(10,0)  << 1);
17145          simm21 = (simm21 << 11) >> 11;
17146
17147          vassert(0 == (guest_R15_curr_instr_notENC & 1));
17148          UInt dst = simm21 + guest_R15_curr_instr_notENC + 4;
17149
17150          /* Not allowed in an IT block; SIGILL if so. */
17151          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
17152
17153          IRTemp kondT = newTemp(Ity_I32);
17154          assign( kondT, mk_armg_calculate_condition(cond) );
17155          stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
17156                             Ijk_Boring,
17157                             IRConst_U32(dst | 1/*CPSR.T*/) ));
17158          irsb->next = mkU32( (guest_R15_curr_instr_notENC + 4) 
17159                              | 1 /*CPSR.T*/ );
17160          irsb->jumpkind = Ijk_Boring;
17161          dres.whatNext  = Dis_StopHere;
17162          DIP("b%s.w 0x%x\n", nCC(cond), dst);
17163          goto decode_success;
17164       }
17165    }
17166
17167    /* ---------------- (T4) B.W label ---------------- */
17168    /* ... whereas this variant doesn't carry its own condition, so it
17169       has to be either unconditional or the conditional by virtue of
17170       being the last in an IT block.  The upside is that there's 4
17171       more bits available for the jump offset, so it has a 16-times
17172       greater branch range than the T3 variant. */
17173    if (INSN0(15,11) == BITS5(1,1,1,1,0)
17174        && INSN1(15,14) == BITS2(1,0)
17175        && INSN1(12,12) == 1) {
17176       if (1) {
17177          UInt bS  = INSN0(10,10);
17178          UInt bJ1 = INSN1(13,13);
17179          UInt bJ2 = INSN1(11,11);
17180          UInt bI1 = 1 ^ (bJ1 ^ bS);
17181          UInt bI2 = 1 ^ (bJ2 ^ bS);
17182          Int simm25
17183             =   (bS          << (1 + 1 + 10 + 11 + 1))
17184               | (bI1         << (1 + 10 + 11 + 1))
17185               | (bI2         << (10 + 11 + 1))
17186               | (INSN0(9,0)  << (11 + 1))
17187               | (INSN1(10,0) << 1);
17188          simm25 = (simm25 << 7) >> 7;
17189
17190          vassert(0 == (guest_R15_curr_instr_notENC & 1));
17191          UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
17192
17193          /* If in an IT block, must be the last insn. */
17194          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
17195
17196          // go uncond
17197          mk_skip_over_T32_if_cond_is_false(condT);
17198          condT = IRTemp_INVALID;
17199          // now uncond
17200
17201          // branch to dst
17202          irsb->next = mkU32( dst | 1 /*CPSR.T*/ );
17203          irsb->jumpkind = Ijk_Boring;
17204          dres.whatNext  = Dis_StopHere;
17205          DIP("b.w 0x%x\n", dst);
17206          goto decode_success;
17207       }
17208    }
17209
17210    /* ------------------ TBB, TBH ------------------ */
17211    if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) {
17212       UInt rN = INSN0(3,0);
17213       UInt rM = INSN1(3,0);
17214       UInt bH = INSN1(4,4);
17215       if (bH/*ATC*/ || (rN != 13 && !isBadRegT(rM))) {
17216          /* Must be last or not-in IT block */
17217          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
17218          /* Go uncond */
17219          mk_skip_over_T32_if_cond_is_false(condT);
17220          condT = IRTemp_INVALID;
17221
17222          IRExpr* ea
17223              = binop(Iop_Add32,
17224                      getIRegT(rN),
17225                      bH ? binop(Iop_Shl32, getIRegT(rM), mkU8(1))
17226                         : getIRegT(rM));
17227
17228          IRTemp delta = newTemp(Ity_I32);
17229          if (bH) {
17230             assign(delta, unop(Iop_16Uto32, loadLE(Ity_I16, ea)));
17231          } else {
17232             assign(delta, unop(Iop_8Uto32, loadLE(Ity_I8, ea)));
17233          }
17234
17235          irsb->next
17236             = binop(Iop_Or32,
17237                     binop(Iop_Add32,
17238                           getIRegT(15),
17239                           binop(Iop_Shl32, mkexpr(delta), mkU8(1))
17240                     ),
17241                     mkU32(1)
17242               );
17243          irsb->jumpkind = Ijk_Boring;
17244          dres.whatNext = Dis_StopHere;
17245          DIP("tb%c [r%u, r%u%s]\n",
17246              bH ? 'h' : 'b', rN, rM, bH ? ", LSL #1" : "");
17247          goto decode_success;
17248       }
17249    }
17250
17251    /* ------------------ UBFX ------------------ */
17252    /* ------------------ SBFX ------------------ */
17253    /* There's also ARM versions of same, but it doesn't seem worth the
17254       hassle to common up the handling (it's only a couple of C
17255       statements). */
17256    if ((INSN0(15,4) == 0xF3C // UBFX
17257         || INSN0(15,4) == 0xF34) // SBFX
17258        && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
17259       UInt rN  = INSN0(3,0);
17260       UInt rD  = INSN1(11,8);
17261       UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
17262       UInt wm1 = INSN1(4,0);
17263       UInt msb =  lsb + wm1;
17264       if (!isBadRegT(rD) && !isBadRegT(rN) && msb <= 31) {
17265          Bool   isU  = INSN0(15,4) == 0xF3C;
17266          IRTemp src  = newTemp(Ity_I32);
17267          IRTemp tmp  = newTemp(Ity_I32);
17268          IRTemp res  = newTemp(Ity_I32);
17269          UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
17270          vassert(msb >= 0 && msb <= 31);
17271          vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
17272
17273          assign(src, getIRegT(rN));
17274          assign(tmp, binop(Iop_And32,
17275                            binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
17276                            mkU32(mask)));
17277          assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
17278                            binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
17279                            mkU8(31-wm1)));
17280
17281          putIRegT(rD, mkexpr(res), condT);
17282
17283          DIP("%s r%u, r%u, #%u, #%u\n",
17284              isU ? "ubfx" : "sbfx", rD, rN, lsb, wm1 + 1);
17285          goto decode_success;
17286       }
17287    }
17288
17289    /* ------------------ UXTB ------------------ */
17290    /* ------------------ UXTH ------------------ */
17291    /* ------------------ SXTB ------------------ */
17292    /* ------------------ SXTH ------------------ */
17293    /* ----------------- UXTB16 ----------------- */
17294    /* ----------------- SXTB16 ----------------- */
17295    /* FIXME: this is an exact duplicate of the ARM version.  They
17296       should be commoned up. */
17297    if ((INSN0(15,0) == 0xFA5F     // UXTB
17298         || INSN0(15,0) == 0xFA1F  // UXTH
17299         || INSN0(15,0) == 0xFA4F  // SXTB
17300         || INSN0(15,0) == 0xFA0F  // SXTH
17301         || INSN0(15,0) == 0xFA3F  // UXTB16
17302         || INSN0(15,0) == 0xFA2F) // SXTB16
17303        && INSN1(15,12) == BITS4(1,1,1,1)
17304        && INSN1(7,6) == BITS2(1,0)) {
17305       UInt rD = INSN1(11,8);
17306       UInt rM = INSN1(3,0);
17307       UInt rot = INSN1(5,4);
17308       if (!isBadRegT(rD) && !isBadRegT(rM)) {
17309          HChar* nm = "???";
17310          IRTemp srcT = newTemp(Ity_I32);
17311          IRTemp rotT = newTemp(Ity_I32);
17312          IRTemp dstT = newTemp(Ity_I32);
17313          assign(srcT, getIRegT(rM));
17314          assign(rotT, genROR32(srcT, 8 * rot));
17315          switch (INSN0(15,0)) {
17316             case 0xFA5F: // UXTB
17317                nm = "uxtb";
17318                assign(dstT, unop(Iop_8Uto32,
17319                                  unop(Iop_32to8, mkexpr(rotT))));
17320                break;
17321             case 0xFA1F: // UXTH
17322                nm = "uxth";
17323                assign(dstT, unop(Iop_16Uto32,
17324                                  unop(Iop_32to16, mkexpr(rotT))));
17325                break;
17326             case 0xFA4F: // SXTB
17327                nm = "sxtb";
17328                assign(dstT, unop(Iop_8Sto32,
17329                                  unop(Iop_32to8, mkexpr(rotT))));
17330                break;
17331             case 0xFA0F: // SXTH
17332                nm = "sxth";
17333                assign(dstT, unop(Iop_16Sto32,
17334                                  unop(Iop_32to16, mkexpr(rotT))));
17335                break;
17336             case 0xFA3F: // UXTB16
17337                nm = "uxtb16";
17338                assign(dstT, binop(Iop_And32, mkexpr(rotT),
17339                                              mkU32(0x00FF00FF)));
17340                break;
17341             case 0xFA2F: { // SXTB16
17342                nm = "sxtb16";
17343                IRTemp lo32 = newTemp(Ity_I32);
17344                IRTemp hi32 = newTemp(Ity_I32);
17345                assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
17346                assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
17347                assign(
17348                   dstT,
17349                   binop(Iop_Or32,
17350                         binop(Iop_And32,
17351                               unop(Iop_8Sto32,
17352                                    unop(Iop_32to8, mkexpr(lo32))),
17353                               mkU32(0xFFFF)),
17354                         binop(Iop_Shl32,
17355                               unop(Iop_8Sto32,
17356                                    unop(Iop_32to8, mkexpr(hi32))),
17357                               mkU8(16))
17358                ));
17359                break;
17360             }
17361             default:
17362                vassert(0);
17363          }
17364          putIRegT(rD, mkexpr(dstT), condT);
17365          DIP("%s r%u, r%u, ror #%u\n", nm, rD, rM, 8 * rot);
17366          goto decode_success;
17367       }
17368    }
17369
17370    /* -------------- MUL.W Rd, Rn, Rm -------------- */
17371    if (INSN0(15,4) == 0xFB0
17372        && (INSN1(15,0) & 0xF0F0) == 0xF000) {
17373       UInt rN = INSN0(3,0);
17374       UInt rD = INSN1(11,8);
17375       UInt rM = INSN1(3,0);
17376       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
17377          IRTemp res = newTemp(Ity_I32);
17378          assign(res, binop(Iop_Mul32, getIRegT(rN), getIRegT(rM)));
17379          putIRegT(rD, mkexpr(res), condT);
17380          DIP("mul.w r%u, r%u, r%u\n", rD, rN, rM);
17381          goto decode_success;
17382       }
17383    }
17384
17385    /* ------------------ {U,S}MULL ------------------ */
17386    if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA)
17387        && INSN1(7,4) == BITS4(0,0,0,0)) {
17388       UInt isU  = INSN0(5,5);
17389       UInt rN   = INSN0(3,0);
17390       UInt rDlo = INSN1(15,12);
17391       UInt rDhi = INSN1(11,8);
17392       UInt rM   = INSN1(3,0);
17393       if (!isBadRegT(rDhi) && !isBadRegT(rDlo)
17394           && !isBadRegT(rN) && !isBadRegT(rM) && rDlo != rDhi) {
17395          IRTemp res   = newTemp(Ity_I64);
17396          assign(res, binop(isU ? Iop_MullU32 : Iop_MullS32,
17397                            getIRegT(rN), getIRegT(rM)));
17398          putIRegT( rDhi, unop(Iop_64HIto32, mkexpr(res)), condT );
17399          putIRegT( rDlo, unop(Iop_64to32, mkexpr(res)), condT );
17400          DIP("%cmull r%u, r%u, r%u, r%u\n",
17401              isU ? 'u' : 's', rDlo, rDhi, rN, rM);
17402          goto decode_success;
17403       }
17404    }
17405
17406    /* ------------------ ML{A,S} ------------------ */
17407    if (INSN0(15,4) == 0xFB0
17408        && (   INSN1(7,4) == BITS4(0,0,0,0)    // MLA
17409            || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS
17410       UInt rN = INSN0(3,0);
17411       UInt rA = INSN1(15,12);
17412       UInt rD = INSN1(11,8);
17413       UInt rM = INSN1(3,0);
17414       if (!isBadRegT(rD) && !isBadRegT(rN)
17415           && !isBadRegT(rM) && !isBadRegT(rA)) {
17416          Bool   isMLA = INSN1(7,4) == BITS4(0,0,0,0);
17417          IRTemp res   = newTemp(Ity_I32);
17418          assign(res,
17419                 binop(isMLA ? Iop_Add32 : Iop_Sub32,
17420                       getIRegT(rA),
17421                       binop(Iop_Mul32, getIRegT(rN), getIRegT(rM))));
17422          putIRegT(rD, mkexpr(res), condT);
17423          DIP("%s r%u, r%u, r%u, r%u\n",
17424              isMLA ? "mla" : "mls", rD, rN, rM, rA);
17425          goto decode_success;
17426       }
17427    }
17428
17429    /* ------------------ (T3) ADR ------------------ */
17430    if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F)
17431        && INSN1(15,15) == 0) {
17432       /* rD = align4(PC) + imm32 */
17433       UInt rD = INSN1(11,8);
17434       if (!isBadRegT(rD)) {
17435          UInt imm32 = (INSN0(10,10) << 11)
17436                       | (INSN1(14,12) << 8) | INSN1(7,0);
17437          putIRegT(rD, binop(Iop_Add32, 
17438                             binop(Iop_And32, getIRegT(15), mkU32(~3U)),
17439                             mkU32(imm32)),
17440                       condT);
17441          DIP("add r%u, pc, #%u\n", rD, imm32);
17442          goto decode_success;
17443       }
17444    }
17445
17446    /* ----------------- (T1) UMLAL ----------------- */
17447    /* ----------------- (T1) SMLAL ----------------- */
17448    if ((INSN0(15,4) == 0xFBE // UMLAL
17449         || INSN0(15,4) == 0xFBC) // SMLAL
17450        && INSN1(7,4) == BITS4(0,0,0,0)) {
17451       UInt rN   = INSN0(3,0);
17452       UInt rDlo = INSN1(15,12);
17453       UInt rDhi = INSN1(11,8);
17454       UInt rM   = INSN1(3,0);
17455       if (!isBadRegT(rDlo) && !isBadRegT(rDhi) && !isBadRegT(rN)
17456           && !isBadRegT(rM) && rDhi != rDlo) {
17457          Bool   isS   = INSN0(15,4) == 0xFBC;
17458          IRTemp argL  = newTemp(Ity_I32);
17459          IRTemp argR  = newTemp(Ity_I32);
17460          IRTemp old   = newTemp(Ity_I64);
17461          IRTemp res   = newTemp(Ity_I64);
17462          IRTemp resHi = newTemp(Ity_I32);
17463          IRTemp resLo = newTemp(Ity_I32);
17464          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
17465          assign( argL, getIRegT(rM));
17466          assign( argR, getIRegT(rN));
17467          assign( old, binop(Iop_32HLto64, getIRegT(rDhi), getIRegT(rDlo)) );
17468          assign( res, binop(Iop_Add64,
17469                             mkexpr(old),
17470                             binop(mulOp, mkexpr(argL), mkexpr(argR))) );
17471          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
17472          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
17473          putIRegT( rDhi, mkexpr(resHi), condT );
17474          putIRegT( rDlo, mkexpr(resLo), condT );
17475          DIP("%cmlal r%u, r%u, r%u, r%u\n",
17476              isS ? 's' : 'u', rDlo, rDhi, rN, rM);
17477          goto decode_success;
17478       }
17479    }
17480
17481    /* ------------------ (T2) ADR ------------------ */
17482    if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF)
17483        && INSN1(15,15) == 0) {
17484       /* rD = align4(PC) - imm32 */
17485       UInt rD = INSN1(11,8);
17486       if (!isBadRegT(rD)) {
17487          UInt imm32 = (INSN0(10,10) << 11)
17488                       | (INSN1(14,12) << 8) | INSN1(7,0);
17489          putIRegT(rD, binop(Iop_Sub32, 
17490                             binop(Iop_And32, getIRegT(15), mkU32(~3U)),
17491                             mkU32(imm32)),
17492                       condT);
17493          DIP("sub r%u, pc, #%u\n", rD, imm32);
17494          goto decode_success;
17495       }
17496    }
17497
17498    /* ------------------- (T1) BFI ------------------- */
17499    /* ------------------- (T1) BFC ------------------- */
17500    if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
17501       UInt rD  = INSN1(11,8);
17502       UInt rN  = INSN0(3,0);
17503       UInt msb = INSN1(4,0);
17504       UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
17505       if (isBadRegT(rD) || rN == 13 || msb < lsb) {
17506          /* undecodable; fall through */
17507       } else {
17508          IRTemp src    = newTemp(Ity_I32);
17509          IRTemp olddst = newTemp(Ity_I32);
17510          IRTemp newdst = newTemp(Ity_I32);
17511          UInt   mask = 1 << (msb - lsb);
17512          mask = (mask - 1) + mask;
17513          vassert(mask != 0); // guaranteed by "msb < lsb" check above
17514          mask <<= lsb;
17515
17516          assign(src, rN == 15 ? mkU32(0) : getIRegT(rN));
17517          assign(olddst, getIRegT(rD));
17518          assign(newdst,
17519                 binop(Iop_Or32,
17520                    binop(Iop_And32,
17521                          binop(Iop_Shl32, mkexpr(src), mkU8(lsb)), 
17522                          mkU32(mask)),
17523                    binop(Iop_And32,
17524                          mkexpr(olddst),
17525                          mkU32(~mask)))
17526                );
17527
17528          putIRegT(rD, mkexpr(newdst), condT);
17529
17530          if (rN == 15) {
17531             DIP("bfc r%u, #%u, #%u\n",
17532                 rD, lsb, msb-lsb+1);
17533          } else {
17534             DIP("bfi r%u, r%u, #%u, #%u\n",
17535                 rD, rN, lsb, msb-lsb+1);
17536          }
17537          goto decode_success;
17538       }
17539    }
17540
17541    /* ------------------- (T1) SXTAH ------------------- */
17542    /* ------------------- (T1) UXTAH ------------------- */
17543    if ((INSN0(15,4) == 0xFA1      // UXTAH
17544         || INSN0(15,4) == 0xFA0)  // SXTAH
17545        && INSN1(15,12) == BITS4(1,1,1,1)
17546        && INSN1(7,6) == BITS2(1,0)) {
17547       Bool isU = INSN0(15,4) == 0xFA1;
17548       UInt rN  = INSN0(3,0);
17549       UInt rD  = INSN1(11,8);
17550       UInt rM  = INSN1(3,0);
17551       UInt rot = INSN1(5,4);
17552       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
17553          IRTemp srcL = newTemp(Ity_I32);
17554          IRTemp srcR = newTemp(Ity_I32);
17555          IRTemp res  = newTemp(Ity_I32);
17556          assign(srcR, getIRegT(rM));
17557          assign(srcL, getIRegT(rN));
17558          assign(res,  binop(Iop_Add32,
17559                             mkexpr(srcL),
17560                             unop(isU ? Iop_16Uto32 : Iop_16Sto32,
17561                                  unop(Iop_32to16, 
17562                                       genROR32(srcR, 8 * rot)))));
17563          putIRegT(rD, mkexpr(res), condT);
17564          DIP("%cxtah r%u, r%u, r%u, ror #%u\n",
17565              isU ? 'u' : 's', rD, rN, rM, rot);
17566          goto decode_success;
17567       }
17568    }
17569
17570    /* ------------------- (T1) SXTAB ------------------- */
17571    /* ------------------- (T1) UXTAB ------------------- */
17572    if ((INSN0(15,4) == 0xFA5      // UXTAB
17573         || INSN0(15,4) == 0xFA4)  // SXTAB
17574        && INSN1(15,12) == BITS4(1,1,1,1)
17575        && INSN1(7,6) == BITS2(1,0)) {
17576       Bool isU = INSN0(15,4) == 0xFA5;
17577       UInt rN  = INSN0(3,0);
17578       UInt rD  = INSN1(11,8);
17579       UInt rM  = INSN1(3,0);
17580       UInt rot = INSN1(5,4);
17581       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
17582          IRTemp srcL = newTemp(Ity_I32);
17583          IRTemp srcR = newTemp(Ity_I32);
17584          IRTemp res  = newTemp(Ity_I32);
17585          assign(srcR, getIRegT(rM));
17586          assign(srcL, getIRegT(rN));
17587          assign(res,  binop(Iop_Add32,
17588                             mkexpr(srcL),
17589                             unop(isU ? Iop_8Uto32 : Iop_8Sto32,
17590                                  unop(Iop_32to8, 
17591                                       genROR32(srcR, 8 * rot)))));
17592          putIRegT(rD, mkexpr(res), condT);
17593          DIP("%cxtab r%u, r%u, r%u, ror #%u\n",
17594              isU ? 'u' : 's', rD, rN, rM, rot);
17595          goto decode_success;
17596       }
17597    }
17598
17599    /* ------------------- (T1) CLZ ------------------- */
17600    if (INSN0(15,4) == 0xFAB
17601        && INSN1(15,12) == BITS4(1,1,1,1)
17602        && INSN1(7,4) == BITS4(1,0,0,0)) {
17603       UInt rM1 = INSN0(3,0);
17604       UInt rD  = INSN1(11,8);
17605       UInt rM2 = INSN1(3,0);
17606       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
17607          IRTemp arg = newTemp(Ity_I32);
17608          IRTemp res = newTemp(Ity_I32);
17609          assign(arg, getIRegT(rM1));
17610          assign(res, IRExpr_Mux0X(
17611                         unop(Iop_1Uto8,binop(Iop_CmpEQ32,
17612                                              mkexpr(arg),
17613                                              mkU32(0))),
17614                         unop(Iop_Clz32, mkexpr(arg)),
17615                         mkU32(32)
17616          ));
17617          putIRegT(rD, mkexpr(res), condT);
17618          DIP("clz r%u, r%u\n", rD, rM1);
17619          goto decode_success;
17620       }
17621    }
17622
17623    /* ------------------- (T1) RBIT ------------------- */
17624    if (INSN0(15,4) == 0xFA9
17625        && INSN1(15,12) == BITS4(1,1,1,1)
17626        && INSN1(7,4) == BITS4(1,0,1,0)) {
17627       UInt rM1 = INSN0(3,0);
17628       UInt rD  = INSN1(11,8);
17629       UInt rM2 = INSN1(3,0);
17630       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
17631          IRTemp arg = newTemp(Ity_I32);
17632          assign(arg, getIRegT(rM1));
17633          IRTemp res = gen_BITREV(arg);
17634          putIRegT(rD, mkexpr(res), condT);
17635          DIP("rbit r%u, r%u\n", rD, rM1);
17636          goto decode_success;
17637       }
17638    }
17639
17640    /* ------------------- (T2) REV   ------------------- */
17641    /* ------------------- (T2) REV16 ------------------- */
17642    if (INSN0(15,4) == 0xFA9
17643        && INSN1(15,12) == BITS4(1,1,1,1)
17644        && (   INSN1(7,4) == BITS4(1,0,0,0)     // REV
17645            || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16
17646       UInt rM1   = INSN0(3,0);
17647       UInt rD    = INSN1(11,8);
17648       UInt rM2   = INSN1(3,0);
17649       Bool isREV = INSN1(7,4) == BITS4(1,0,0,0);
17650       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
17651          IRTemp arg = newTemp(Ity_I32);
17652          assign(arg, getIRegT(rM1));
17653          IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
17654          putIRegT(rD, mkexpr(res), condT);
17655          DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM1);
17656          goto decode_success;
17657       }
17658    }
17659
17660    /* -------------- (T1) MSR apsr, reg -------------- */
17661    if (INSN0(15,4) == 0xF38 
17662        && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) {
17663       UInt rN          = INSN0(3,0);
17664       UInt write_ge    = INSN1(10,10);
17665       UInt write_nzcvq = INSN1(11,11);
17666       if (!isBadRegT(rN) && (write_nzcvq || write_ge)) {
17667          IRTemp rNt = newTemp(Ity_I32);
17668          assign(rNt, getIRegT(rN));
17669          desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
17670          DIP("msr cpsr_%s%s, r%u\n",
17671              write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
17672          goto decode_success;
17673       }
17674    }
17675
17676    /* -------------- (T1) MRS reg, apsr -------------- */
17677    if (INSN0(15,0) == 0xF3EF
17678        && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) {
17679       UInt rD = INSN1(11,8);
17680       if (!isBadRegT(rD)) {
17681          IRTemp apsr = synthesise_APSR();
17682          putIRegT( rD, mkexpr(apsr), condT );
17683          DIP("mrs r%u, cpsr\n", rD);
17684          goto decode_success;
17685       }
17686    }
17687
17688    /* ----------------- (T1) LDREX ----------------- */
17689    if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) {
17690       UInt rN   = INSN0(3,0);
17691       UInt rT   = INSN1(15,12);
17692       UInt imm8 = INSN1(7,0);
17693       if (!isBadRegT(rT) && rN != 15) {
17694          IRTemp res;
17695          // go uncond
17696          mk_skip_over_T32_if_cond_is_false( condT );
17697          // now uncond
17698          res = newTemp(Ity_I32);
17699          stmt( IRStmt_LLSC(Iend_LE,
17700                            res,
17701                            binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
17702                            NULL/*this is a load*/ ));
17703          putIRegT(rT, mkexpr(res), IRTemp_INVALID);
17704          DIP("ldrex r%u, [r%u, #+%u]\n", rT, rN, imm8 * 4);
17705          goto decode_success;
17706       }
17707    }
17708
17709    /* ----------------- (T1) STREX ----------------- */
17710    if (INSN0(15,4) == 0xE84) {
17711       UInt rN   = INSN0(3,0);
17712       UInt rT   = INSN1(15,12);
17713       UInt rD   = INSN1(11,8);
17714       UInt imm8 = INSN1(7,0);
17715       if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15 
17716           && rD != rN && rD != rT) {
17717          IRTemp resSC1, resSC32;
17718
17719          // go uncond
17720          mk_skip_over_T32_if_cond_is_false( condT );
17721          // now uncond
17722
17723          /* Ok, now we're unconditional.  Do the store. */
17724          resSC1 = newTemp(Ity_I1);
17725          stmt( IRStmt_LLSC(Iend_LE,
17726                            resSC1,
17727                            binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
17728                            getIRegT(rT)) );
17729
17730          /* Set rD to 1 on failure, 0 on success.  Currently we have
17731             resSC1 == 0 on failure, 1 on success. */
17732          resSC32 = newTemp(Ity_I32);
17733          assign(resSC32,
17734                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
17735
17736          putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
17737          DIP("strex r%u, r%u, [r%u, #+%u]\n", rD, rT, rN, imm8 * 4);
17738          goto decode_success;
17739       }
17740    }
17741
17742    /* -------------- v7 barrier insns -------------- */
17743    if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) {
17744       /* XXX this isn't really right, is it?  The generated IR does
17745          them unconditionally.  I guess it doesn't matter since it
17746          doesn't do any harm to do them even when the guarding
17747          condition is false -- it's just a performance loss. */
17748       switch (INSN1(7,0)) {
17749          case 0x4F: /* DSB sy */
17750          case 0x4E: /* DSB st */
17751          case 0x4B: /* DSB ish */
17752          case 0x4A: /* DSB ishst */
17753          case 0x47: /* DSB nsh */
17754          case 0x46: /* DSB nshst */
17755          case 0x43: /* DSB osh */
17756          case 0x42: /* DSB oshst */
17757             stmt( IRStmt_MBE(Imbe_Fence) );
17758             DIP("DSB\n");
17759             goto decode_success;
17760          case 0x5F: /* DMB sy */
17761          case 0x5E: /* DMB st */
17762          case 0x5B: /* DMB ish */
17763          case 0x5A: /* DMB ishst */
17764          case 0x57: /* DMB nsh */
17765          case 0x56: /* DMB nshst */
17766          case 0x53: /* DMB osh */
17767          case 0x52: /* DMB oshst */
17768             stmt( IRStmt_MBE(Imbe_Fence) );
17769             DIP("DMB\n");
17770             goto decode_success;
17771          case 0x6F: /* ISB */
17772             stmt( IRStmt_MBE(Imbe_Fence) );
17773             DIP("ISB\n");
17774             goto decode_success;
17775          default:
17776             break;
17777       }
17778    }
17779
17780    /* -------------- read CP15 TPIDRURO register ------------- */
17781    /* mrc     p15, 0,  r0, c13, c0, 3  up to
17782       mrc     p15, 0, r14, c13, c0, 3
17783    */
17784    /* I don't know whether this is really v7-only.  But anyway, we
17785       have to support it since arm-linux uses TPIDRURO as a thread
17786       state register. */
17787    
17788    if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
17789       UInt rD = INSN1(15,12);
17790       if (!isBadRegT(rD)) {
17791          putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID);
17792          DIP("mrc p15,0, r%u, c13, c0, 3\n", rD);
17793          goto decode_success;
17794       }
17795       /* fall through */
17796    }
17797
17798    /* ------------------- NOP ------------------ */
17799    if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
17800       DIP("nop\n");
17801       goto decode_success;
17802    }
17803
17804    /* ----------------------------------------------------------- */
17805    /* -- VFP (CP 10, CP 11) instructions (in Thumb mode)       -- */
17806    /* ----------------------------------------------------------- */
17807
17808    if (INSN0(15,12) == BITS4(1,1,1,0)) {
17809       UInt insn28 = (INSN0(11,0) << 16) | INSN1(15,0);
17810       Bool ok_vfp = decode_CP10_CP11_instruction (
17811                        &dres, insn28, condT, ARMCondAL/*bogus*/,
17812                        True/*isT*/
17813                     );
17814       if (ok_vfp)
17815          goto decode_success;
17816    }
17817
17818    /* ----------------------------------------------------------- */
17819    /* -- NEON instructions (in Thumb mode)                     -- */
17820    /* ----------------------------------------------------------- */
17821
17822    if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
17823       UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
17824       Bool ok_neon = decode_NEON_instruction(
17825                         &dres, insn32, condT, True/*isT*/
17826                      );
17827       if (ok_neon)
17828          goto decode_success;
17829    }
17830
17831    /* ----------------------------------------------------------- */
17832    /* -- v6 media instructions (in Thumb mode)                 -- */
17833    /* ----------------------------------------------------------- */
17834
17835    { UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
17836      Bool ok_v6m = decode_V6MEDIA_instruction(
17837                       &dres, insn32, condT, ARMCondAL/*bogus*/,
17838                       True/*isT*/
17839                    );
17840      if (ok_v6m)
17841         goto decode_success;
17842    }
17843
17844    /* ----------------------------------------------------------- */
17845    /* -- Undecodable                                           -- */
17846    /* ----------------------------------------------------------- */
17847
17848    goto decode_failure;
17849    /*NOTREACHED*/
17850
17851   decode_failure:
17852    /* All decode failures end up here. */
17853    vex_printf("disInstr(thumb): unhandled instruction: "
17854               "0x%04x 0x%04x\n", (UInt)insn0, (UInt)insn1);
17855
17856    /* Back up ITSTATE to the initial value for this instruction.
17857       If we don't do that, any subsequent restart of the instruction
17858       will restart with the wrong value. */
17859    put_ITSTATE(old_itstate);
17860    /* Tell the dispatcher that this insn cannot be decoded, and so has
17861       not been executed, and (is currently) the next to be executed.
17862       R15 should be up-to-date since it made so at the start of each
17863       insn, but nevertheless be paranoid and update it again right
17864       now. */
17865    vassert(0 == (guest_R15_curr_instr_notENC & 1));
17866    llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
17867    irsb->next     = mkU32(guest_R15_curr_instr_notENC | 1 /* CPSR.T */);
17868    irsb->jumpkind = Ijk_NoDecode;
17869    dres.whatNext  = Dis_StopHere;
17870    dres.len       = 0;
17871    return dres;
17872
17873   decode_success:
17874    /* All decode successes end up here. */
17875    DIP("\n");
17876
17877    vassert(dres.len == 2 || dres.len == 4 || dres.len == 20);
17878
17879 #if 0
17880    // XXX is this necessary on Thumb?
17881    /* Now then.  Do we have an implicit jump to r15 to deal with? */
17882    if (r15written) {
17883       /* If we get jump to deal with, we assume that there's been no
17884          other competing branch stuff previously generated for this
17885          insn.  That's reasonable, in the sense that the ARM insn set
17886          appears to declare as "Unpredictable" any instruction which
17887          generates more than one possible new value for r15.  Hence
17888          just assert.  The decoders themselves should check against
17889          all such instructions which are thusly Unpredictable, and
17890          decline to decode them.  Hence we should never get here if we
17891          have competing new values for r15, and hence it is safe to
17892          assert here. */
17893       vassert(dres.whatNext == Dis_Continue);
17894       vassert(irsb->next == NULL);
17895       vassert(irsb->jumpkind == Ijk_Boring);
17896       /* If r15 is unconditionally written, terminate the block by
17897          jumping to it.  If it's conditionally written, still
17898          terminate the block (a shame, but we can't do side exits to
17899          arbitrary destinations), but first jump to the next
17900          instruction if the condition doesn't hold. */
17901       /* We can't use getIRegT(15) to get the destination, since that
17902          will produce r15+4, which isn't what we want.  Must use
17903          llGetIReg(15) instead. */
17904       if (r15guard == IRTemp_INVALID) {
17905          /* unconditional */
17906       } else {
17907          /* conditional */
17908          stmt( IRStmt_Exit(
17909                   unop(Iop_32to1,
17910                        binop(Iop_Xor32,
17911                              mkexpr(r15guard), mkU32(1))),
17912                   r15kind,
17913                   IRConst_U32(guest_R15_curr_instr_notENC + 4)
17914          ));
17915       }
17916       irsb->next     = llGetIReg(15);
17917       irsb->jumpkind = r15kind;
17918       dres.whatNext  = Dis_StopHere;
17919    }
17920 #endif
17921
17922    return dres;
17923
17924 #  undef INSN0
17925 #  undef INSN1
17926 }
17927
17928 #undef DIP
17929 #undef DIS
17930
17931
17932 /*------------------------------------------------------------*/
17933 /*--- Top-level fn                                         ---*/
17934 /*------------------------------------------------------------*/
17935
17936 /* Disassemble a single instruction into IR.  The instruction
17937    is located in host memory at &guest_code[delta]. */
17938
17939 DisResult disInstr_ARM ( IRSB*        irsb_IN,
17940                          Bool         put_IP,
17941                          Bool         (*resteerOkFn) ( void*, Addr64 ),
17942                          Bool         resteerCisOk,
17943                          void*        callback_opaque,
17944                          UChar*       guest_code_IN,
17945                          Long         delta_ENCODED,
17946                          Addr64       guest_IP_ENCODED,
17947                          VexArch      guest_arch,
17948                          VexArchInfo* archinfo,
17949                          VexAbiInfo*  abiinfo,
17950                          Bool         host_bigendian_IN )
17951 {
17952    DisResult dres;
17953    Bool isThumb = (Bool)(guest_IP_ENCODED & 1);
17954
17955    /* Set globals (see top of this file) */
17956    vassert(guest_arch == VexArchARM);
17957
17958    irsb              = irsb_IN;
17959    host_is_bigendian = host_bigendian_IN;
17960    __curr_is_Thumb   = isThumb;
17961
17962    if (isThumb) {
17963       guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED - 1;
17964    } else {
17965       guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED;
17966    }
17967
17968    if (isThumb) {
17969       dres = disInstr_THUMB_WRK ( put_IP, resteerOkFn,
17970                                   resteerCisOk, callback_opaque,
17971                                   &guest_code_IN[delta_ENCODED - 1],
17972                                   archinfo, abiinfo );
17973    } else {
17974       dres = disInstr_ARM_WRK ( put_IP, resteerOkFn,
17975                                 resteerCisOk, callback_opaque,
17976                                 &guest_code_IN[delta_ENCODED],
17977                                 archinfo, abiinfo );
17978    }
17979
17980    return dres;
17981 }
17982
17983 /* Test program for the conversion of IRCmpF64Result values to VFP
17984    nzcv values.  See handling of FCMPD et al above. */
17985 /*
17986 UInt foo ( UInt x )
17987 {
17988    UInt ix    = ((x >> 5) & 3) | (x & 1);
17989    UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1);
17990    UInt termR = (ix & (ix >> 1) & 1);
17991    return termL  -  termR;
17992 }
17993
17994 void try ( char* s, UInt ir, UInt req )
17995 {
17996    UInt act = foo(ir);
17997    printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n",
17998           s, ir, (req >> 3) & 1, (req >> 2) & 1, 
17999                  (req >> 1) & 1, (req >> 0) & 1, 
18000                  (act >> 3) & 1, (act >> 2) & 1, 
18001                  (act >> 1) & 1, (act >> 0) & 1, act);
18002
18003 }
18004
18005 int main ( void )
18006 {
18007    printf("\n");
18008    try("UN", 0x45, 0b0011);
18009    try("LT", 0x01, 0b1000);
18010    try("GT", 0x00, 0b0010);
18011    try("EQ", 0x40, 0b0110);
18012    printf("\n");
18013    return 0;
18014 }
18015 */
18016
18017 /*--------------------------------------------------------------------*/
18018 /*--- end                                         guest_arm_toIR.c ---*/
18019 /*--------------------------------------------------------------------*/