Home | History | Annotate | Download | only in priv
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- begin                                       guest_arm_toIR.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2004-2012 OpenWorks LLP
     11       info (at) open-works.net
     12 
     13    NEON support is
     14    Copyright (C) 2010-2012 Samsung Electronics
     15    contributed by Dmitry Zhurikhin <zhur (at) ispras.ru>
     16               and Kirill Batuzov <batuzovk (at) 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             OFFB_R15T
   1403        ));
   1404 }
   1405 
   1406 /* Thumb16 only */
   1407 /* ditto, but jump over a 16-bit thumb insn */
   1408 static void mk_skip_over_T16_if_cond_is_false (
   1409                IRTemp guardT /* :: Ity_I32, 0 or 1 */
   1410             )
   1411 {
   1412    ASSERT_IS_THUMB;
   1413    vassert(guardT != IRTemp_INVALID);
   1414    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   1415    stmt( IRStmt_Exit(
   1416             unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
   1417             Ijk_Boring,
   1418             IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 2) | 1)),
   1419             OFFB_R15T
   1420        ));
   1421 }
   1422 
   1423 
   1424 /* Thumb32 only */
   1425 /* ditto, but jump over a 32-bit thumb insn */
   1426 static void mk_skip_over_T32_if_cond_is_false (
   1427                IRTemp guardT /* :: Ity_I32, 0 or 1 */
   1428             )
   1429 {
   1430    ASSERT_IS_THUMB;
   1431    vassert(guardT != IRTemp_INVALID);
   1432    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   1433    stmt( IRStmt_Exit(
   1434             unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
   1435             Ijk_Boring,
   1436             IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 4) | 1)),
   1437             OFFB_R15T
   1438        ));
   1439 }
   1440 
   1441 
   1442 /* Thumb16 and Thumb32 only
   1443    Generate a SIGILL followed by a restart of the current instruction
   1444    if the given temp is nonzero. */
   1445 static void gen_SIGILL_T_if_nonzero ( IRTemp t /* :: Ity_I32 */ )
   1446 {
   1447    ASSERT_IS_THUMB;
   1448    vassert(t != IRTemp_INVALID);
   1449    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   1450    stmt(
   1451       IRStmt_Exit(
   1452          binop(Iop_CmpNE32, mkexpr(t), mkU32(0)),
   1453          Ijk_NoDecode,
   1454          IRConst_U32(toUInt(guest_R15_curr_instr_notENC | 1)),
   1455          OFFB_R15T
   1456       )
   1457    );
   1458 }
   1459 
   1460 
   1461 /* Inspect the old_itstate, and generate a SIGILL if it indicates that
   1462    we are currently in an IT block and are not the last in the block.
   1463    This also rolls back guest_ITSTATE to its old value before the exit
   1464    and restores it to its new value afterwards.  This is so that if
   1465    the exit is taken, we have an up to date version of ITSTATE
   1466    available.  Without doing that, we have no hope of making precise
   1467    exceptions work. */
   1468 static void gen_SIGILL_T_if_in_but_NLI_ITBlock (
   1469                IRTemp old_itstate /* :: Ity_I32 */,
   1470                IRTemp new_itstate /* :: Ity_I32 */
   1471             )
   1472 {
   1473    ASSERT_IS_THUMB;
   1474    put_ITSTATE(old_itstate); // backout
   1475    IRTemp guards_for_next3 = newTemp(Ity_I32);
   1476    assign(guards_for_next3,
   1477           binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
   1478    gen_SIGILL_T_if_nonzero(guards_for_next3);
   1479    put_ITSTATE(new_itstate); //restore
   1480 }
   1481 
   1482 
   1483 /* Simpler version of the above, which generates a SIGILL if
   1484    we're anywhere within an IT block. */
   1485 static void gen_SIGILL_T_if_in_ITBlock (
   1486                IRTemp old_itstate /* :: Ity_I32 */,
   1487                IRTemp new_itstate /* :: Ity_I32 */
   1488             )
   1489 {
   1490    put_ITSTATE(old_itstate); // backout
   1491    gen_SIGILL_T_if_nonzero(old_itstate);
   1492    put_ITSTATE(new_itstate); //restore
   1493 }
   1494 
   1495 
   1496 /* Generate an APSR value, from the NZCV thunk, and
   1497    from QFLAG32 and GEFLAG0 .. GEFLAG3. */
   1498 static IRTemp synthesise_APSR ( void )
   1499 {
   1500    IRTemp res1 = newTemp(Ity_I32);
   1501    // Get NZCV
   1502    assign( res1, mk_armg_calculate_flags_nzcv() );
   1503    // OR in the Q value
   1504    IRTemp res2 = newTemp(Ity_I32);
   1505    assign(
   1506       res2,
   1507       binop(Iop_Or32,
   1508             mkexpr(res1),
   1509             binop(Iop_Shl32,
   1510                   unop(Iop_1Uto32,
   1511                        binop(Iop_CmpNE32,
   1512                              mkexpr(get_QFLAG32()),
   1513                              mkU32(0))),
   1514                   mkU8(ARMG_CC_SHIFT_Q)))
   1515    );
   1516    // OR in GE0 .. GE3
   1517    IRExpr* ge0
   1518       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(0), mkU32(0)));
   1519    IRExpr* ge1
   1520       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(1), mkU32(0)));
   1521    IRExpr* ge2
   1522       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(2), mkU32(0)));
   1523    IRExpr* ge3
   1524       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(3), mkU32(0)));
   1525    IRTemp res3 = newTemp(Ity_I32);
   1526    assign(res3,
   1527           binop(Iop_Or32,
   1528                 mkexpr(res2),
   1529                 binop(Iop_Or32,
   1530                       binop(Iop_Or32,
   1531                             binop(Iop_Shl32, ge0, mkU8(16)),
   1532                             binop(Iop_Shl32, ge1, mkU8(17))),
   1533                       binop(Iop_Or32,
   1534                             binop(Iop_Shl32, ge2, mkU8(18)),
   1535                             binop(Iop_Shl32, ge3, mkU8(19))) )));
   1536    return res3;
   1537 }
   1538 
   1539 
   1540 /* and the inverse transformation: given an APSR value,
   1541    set the NZCV thunk, the Q flag, and the GE flags. */
   1542 static void desynthesise_APSR ( Bool write_nzcvq, Bool write_ge,
   1543                                 IRTemp apsrT, IRTemp condT )
   1544 {
   1545    vassert(write_nzcvq || write_ge);
   1546    if (write_nzcvq) {
   1547       // Do NZCV
   1548       IRTemp immT = newTemp(Ity_I32);
   1549       assign(immT, binop(Iop_And32, mkexpr(apsrT), mkU32(0xF0000000)) );
   1550       setFlags_D1(ARMG_CC_OP_COPY, immT, condT);
   1551       // Do Q
   1552       IRTemp qnewT = newTemp(Ity_I32);
   1553       assign(qnewT, binop(Iop_And32, mkexpr(apsrT), mkU32(ARMG_CC_MASK_Q)));
   1554       put_QFLAG32(qnewT, condT);
   1555    }
   1556    if (write_ge) {
   1557       // Do GE3..0
   1558       put_GEFLAG32(0, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<16)),
   1559                    condT);
   1560       put_GEFLAG32(1, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<17)),
   1561                    condT);
   1562       put_GEFLAG32(2, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<18)),
   1563                    condT);
   1564       put_GEFLAG32(3, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<19)),
   1565                    condT);
   1566    }
   1567 }
   1568 
   1569 
   1570 /*------------------------------------------------------------*/
   1571 /*--- Helpers for saturation                               ---*/
   1572 /*------------------------------------------------------------*/
   1573 
   1574 /* FIXME: absolutely the only diff. between (a) armUnsignedSatQ and
   1575    (b) armSignedSatQ is that in (a) the floor is set to 0, whereas in
   1576    (b) the floor is computed from the value of imm5.  these two fnsn
   1577    should be commoned up. */
   1578 
   1579 /* UnsignedSatQ(): 'clamp' each value so it lies between 0 <= x <= (2^N)-1
   1580    Optionally return flag resQ saying whether saturation occurred.
   1581    See definition in manual, section A2.2.1, page 41
   1582    (bits(N), boolean) UnsignedSatQ( integer i, integer N )
   1583    {
   1584      if ( i > (2^N)-1 ) { result = (2^N)-1; saturated = TRUE; }
   1585      elsif ( i < 0 )    { result = 0; saturated = TRUE; }
   1586      else               { result = i; saturated = FALSE; }
   1587      return ( result<N-1:0>, saturated );
   1588    }
   1589 */
   1590 static void armUnsignedSatQ( IRTemp* res,  /* OUT - Ity_I32 */
   1591                              IRTemp* resQ, /* OUT - Ity_I32  */
   1592                              IRTemp regT,  /* value to clamp - Ity_I32 */
   1593                              UInt imm5 )   /* saturation ceiling */
   1594 {
   1595    UInt ceil  = (1 << imm5) - 1;    // (2^imm5)-1
   1596    UInt floor = 0;
   1597 
   1598    IRTemp node0 = newTemp(Ity_I32);
   1599    IRTemp node1 = newTemp(Ity_I32);
   1600    IRTemp node2 = newTemp(Ity_I1);
   1601    IRTemp node3 = newTemp(Ity_I32);
   1602    IRTemp node4 = newTemp(Ity_I32);
   1603    IRTemp node5 = newTemp(Ity_I1);
   1604    IRTemp node6 = newTemp(Ity_I32);
   1605 
   1606    assign( node0, mkexpr(regT) );
   1607    assign( node1, mkU32(ceil) );
   1608    assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
   1609    assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
   1610                                 mkexpr(node0),
   1611                                 mkexpr(node1) ) );
   1612    assign( node4, mkU32(floor) );
   1613    assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
   1614    assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
   1615                                 mkexpr(node3),
   1616                                 mkexpr(node4) ) );
   1617    assign( *res, mkexpr(node6) );
   1618 
   1619    /* if saturation occurred, then resQ is set to some nonzero value
   1620       if sat did not occur, resQ is guaranteed to be zero. */
   1621    if (resQ) {
   1622       assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
   1623    }
   1624 }
   1625 
   1626 
   1627 /* SignedSatQ(): 'clamp' each value so it lies between  -2^N <= x <= (2^N) - 1
   1628    Optionally return flag resQ saying whether saturation occurred.
   1629    - see definition in manual, section A2.2.1, page 41
   1630    (bits(N), boolean ) SignedSatQ( integer i, integer N )
   1631    {
   1632      if ( i > 2^(N-1) - 1 )    { result = 2^(N-1) - 1; saturated = TRUE; }
   1633      elsif ( i < -(2^(N-1)) )  { result = -(2^(N-1));  saturated = FALSE; }
   1634      else                      { result = i;           saturated = FALSE; }
   1635      return ( result[N-1:0], saturated );
   1636    }
   1637 */
   1638 static void armSignedSatQ( IRTemp regT,    /* value to clamp - Ity_I32 */
   1639                            UInt imm5,      /* saturation ceiling */
   1640                            IRTemp* res,    /* OUT - Ity_I32 */
   1641                            IRTemp* resQ )  /* OUT - Ity_I32  */
   1642 {
   1643    Int ceil  =  (1 << (imm5-1)) - 1;  //  (2^(imm5-1))-1
   1644    Int floor = -(1 << (imm5-1));      // -(2^(imm5-1))
   1645 
   1646    IRTemp node0 = newTemp(Ity_I32);
   1647    IRTemp node1 = newTemp(Ity_I32);
   1648    IRTemp node2 = newTemp(Ity_I1);
   1649    IRTemp node3 = newTemp(Ity_I32);
   1650    IRTemp node4 = newTemp(Ity_I32);
   1651    IRTemp node5 = newTemp(Ity_I1);
   1652    IRTemp node6 = newTemp(Ity_I32);
   1653 
   1654    assign( node0, mkexpr(regT) );
   1655    assign( node1, mkU32(ceil) );
   1656    assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
   1657    assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
   1658                                 mkexpr(node0),  mkexpr(node1) ) );
   1659    assign( node4, mkU32(floor) );
   1660    assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
   1661    assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
   1662                                 mkexpr(node3),  mkexpr(node4) ) );
   1663    assign( *res, mkexpr(node6) );
   1664 
   1665    /* if saturation occurred, then resQ is set to some nonzero value
   1666       if sat did not occur, resQ is guaranteed to be zero. */
   1667    if (resQ) {
   1668      assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
   1669    }
   1670 }
   1671 
   1672 
   1673 /* Compute a value 0 :: I32 or 1 :: I32, indicating whether signed
   1674    overflow occurred for 32-bit addition.  Needs both args and the
   1675    result.  HD p27. */
   1676 static
   1677 IRExpr* signed_overflow_after_Add32 ( IRExpr* resE,
   1678                                       IRTemp argL, IRTemp argR )
   1679 {
   1680    IRTemp res = newTemp(Ity_I32);
   1681    assign(res, resE);
   1682    return
   1683       binop( Iop_Shr32,
   1684              binop( Iop_And32,
   1685                     binop( Iop_Xor32, mkexpr(res), mkexpr(argL) ),
   1686                     binop( Iop_Xor32, mkexpr(res), mkexpr(argR) )),
   1687              mkU8(31) );
   1688 }
   1689 
   1690 /* Similarly .. also from HD p27 .. */
   1691 static
   1692 IRExpr* signed_overflow_after_Sub32 ( IRExpr* resE,
   1693                                       IRTemp argL, IRTemp argR )
   1694 {
   1695    IRTemp res = newTemp(Ity_I32);
   1696    assign(res, resE);
   1697    return
   1698       binop( Iop_Shr32,
   1699              binop( Iop_And32,
   1700                     binop( Iop_Xor32, mkexpr(argL), mkexpr(argR) ),
   1701                     binop( Iop_Xor32, mkexpr(res),  mkexpr(argL) )),
   1702              mkU8(31) );
   1703 }
   1704 
   1705 
   1706 /*------------------------------------------------------------*/
   1707 /*--- Larger helpers                                       ---*/
   1708 /*------------------------------------------------------------*/
   1709 
   1710 /* Compute both the result and new C flag value for a LSL by an imm5
   1711    or by a register operand.  May generate reads of the old C value
   1712    (hence only safe to use before any writes to guest state happen).
   1713    Are factored out so can be used by both ARM and Thumb.
   1714 
   1715    Note that in compute_result_and_C_after_{LSL,LSR,ASR}_by{imm5,reg},
   1716    "res" (the result)  is a.k.a. "shop", shifter operand
   1717    "newC" (the new C)  is a.k.a. "shco", shifter carry out
   1718 
   1719    The calling convention for res and newC is a bit funny.  They could
   1720    be passed by value, but instead are passed by ref.
   1721 
   1722    The C (shco) value computed must be zero in bits 31:1, as the IR
   1723    optimisations for flag handling (guest_arm_spechelper) rely on
   1724    that, and the slow-path handlers (armg_calculate_flags_nzcv) assert
   1725    for it.  Same applies to all these functions that compute shco
   1726    after a shift or rotate, not just this one.
   1727 */
   1728 
   1729 static void compute_result_and_C_after_LSL_by_imm5 (
   1730                /*OUT*/HChar* buf,
   1731                IRTemp* res,
   1732                IRTemp* newC,
   1733                IRTemp rMt, UInt shift_amt, /* operands */
   1734                UInt rM      /* only for debug printing */
   1735             )
   1736 {
   1737    if (shift_amt == 0) {
   1738       if (newC) {
   1739          assign( *newC, mk_armg_calculate_flag_c() );
   1740       }
   1741       assign( *res, mkexpr(rMt) );
   1742       DIS(buf, "r%u", rM);
   1743    } else {
   1744       vassert(shift_amt >= 1 && shift_amt <= 31);
   1745       if (newC) {
   1746          assign( *newC,
   1747                  binop(Iop_And32,
   1748                        binop(Iop_Shr32, mkexpr(rMt),
   1749                                         mkU8(32 - shift_amt)),
   1750                        mkU32(1)));
   1751       }
   1752       assign( *res,
   1753               binop(Iop_Shl32, mkexpr(rMt), mkU8(shift_amt)) );
   1754       DIS(buf, "r%u, LSL #%u", rM, shift_amt);
   1755    }
   1756 }
   1757 
   1758 
   1759 static void compute_result_and_C_after_LSL_by_reg (
   1760                /*OUT*/HChar* buf,
   1761                IRTemp* res,
   1762                IRTemp* newC,
   1763                IRTemp rMt, IRTemp rSt,  /* operands */
   1764                UInt rM,    UInt rS      /* only for debug printing */
   1765             )
   1766 {
   1767    // shift left in range 0 .. 255
   1768    // amt  = rS & 255
   1769    // res  = amt < 32 ?  Rm << amt  : 0
   1770    // newC = amt == 0     ? oldC  :
   1771    //        amt in 1..32 ?  Rm[32-amt]  : 0
   1772    IRTemp amtT = newTemp(Ity_I32);
   1773    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   1774    if (newC) {
   1775       /* mux0X(amt == 0,
   1776                mux0X(amt < 32,
   1777                      0,
   1778                      Rm[(32-amt) & 31]),
   1779                oldC)
   1780       */
   1781       /* About the best you can do is pray that iropt is able
   1782          to nuke most or all of the following junk. */
   1783       IRTemp oldC = newTemp(Ity_I32);
   1784       assign(oldC, mk_armg_calculate_flag_c() );
   1785       assign(
   1786          *newC,
   1787          IRExpr_Mux0X(
   1788             unop(Iop_1Uto8,
   1789                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
   1790             IRExpr_Mux0X(
   1791                unop(Iop_1Uto8,
   1792                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
   1793                mkU32(0),
   1794                binop(Iop_And32,
   1795                      binop(Iop_Shr32,
   1796                            mkexpr(rMt),
   1797                            unop(Iop_32to8,
   1798                                 binop(Iop_And32,
   1799                                       binop(Iop_Sub32,
   1800                                             mkU32(32),
   1801                                             mkexpr(amtT)),
   1802                                       mkU32(31)
   1803                                 )
   1804                            )
   1805                      ),
   1806                      mkU32(1)
   1807                )
   1808             ),
   1809             mkexpr(oldC)
   1810          )
   1811       );
   1812    }
   1813    // (Rm << (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
   1814    // Lhs of the & limits the shift to 31 bits, so as to
   1815    // give known IR semantics.  Rhs of the & is all 1s for
   1816    // Rs <= 31 and all 0s for Rs >= 32.
   1817    assign(
   1818       *res,
   1819       binop(
   1820          Iop_And32,
   1821          binop(Iop_Shl32,
   1822                mkexpr(rMt),
   1823                unop(Iop_32to8,
   1824                     binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
   1825          binop(Iop_Sar32,
   1826                binop(Iop_Sub32,
   1827                      mkexpr(amtT),
   1828                      mkU32(32)),
   1829                mkU8(31))));
   1830     DIS(buf, "r%u, LSL r%u", rM, rS);
   1831 }
   1832 
   1833 
   1834 static void compute_result_and_C_after_LSR_by_imm5 (
   1835                /*OUT*/HChar* buf,
   1836                IRTemp* res,
   1837                IRTemp* newC,
   1838                IRTemp rMt, UInt shift_amt, /* operands */
   1839                UInt rM      /* only for debug printing */
   1840             )
   1841 {
   1842    if (shift_amt == 0) {
   1843       // conceptually a 32-bit shift, however:
   1844       // res  = 0
   1845       // newC = Rm[31]
   1846       if (newC) {
   1847          assign( *newC,
   1848                  binop(Iop_And32,
   1849                        binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
   1850                        mkU32(1)));
   1851       }
   1852       assign( *res, mkU32(0) );
   1853       DIS(buf, "r%u, LSR #0(a.k.a. 32)", rM);
   1854    } else {
   1855       // shift in range 1..31
   1856       // res  = Rm >>u shift_amt
   1857       // newC = Rm[shift_amt - 1]
   1858       vassert(shift_amt >= 1 && shift_amt <= 31);
   1859       if (newC) {
   1860          assign( *newC,
   1861                  binop(Iop_And32,
   1862                        binop(Iop_Shr32, mkexpr(rMt),
   1863                                         mkU8(shift_amt - 1)),
   1864                        mkU32(1)));
   1865       }
   1866       assign( *res,
   1867               binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)) );
   1868       DIS(buf, "r%u, LSR #%u", rM, shift_amt);
   1869    }
   1870 }
   1871 
   1872 
   1873 static void compute_result_and_C_after_LSR_by_reg (
   1874                /*OUT*/HChar* buf,
   1875                IRTemp* res,
   1876                IRTemp* newC,
   1877                IRTemp rMt, IRTemp rSt,  /* operands */
   1878                UInt rM,    UInt rS      /* only for debug printing */
   1879             )
   1880 {
   1881    // shift right in range 0 .. 255
   1882    // amt = rS & 255
   1883    // res  = amt < 32 ?  Rm >>u amt  : 0
   1884    // newC = amt == 0     ? oldC  :
   1885    //        amt in 1..32 ?  Rm[amt-1]  : 0
   1886    IRTemp amtT = newTemp(Ity_I32);
   1887    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   1888    if (newC) {
   1889       /* mux0X(amt == 0,
   1890                mux0X(amt < 32,
   1891                      0,
   1892                      Rm[(amt-1) & 31]),
   1893                oldC)
   1894       */
   1895       IRTemp oldC = newTemp(Ity_I32);
   1896       assign(oldC, mk_armg_calculate_flag_c() );
   1897       assign(
   1898          *newC,
   1899          IRExpr_Mux0X(
   1900             unop(Iop_1Uto8,
   1901                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
   1902             IRExpr_Mux0X(
   1903                unop(Iop_1Uto8,
   1904                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
   1905                mkU32(0),
   1906                binop(Iop_And32,
   1907                      binop(Iop_Shr32,
   1908                            mkexpr(rMt),
   1909                            unop(Iop_32to8,
   1910                                 binop(Iop_And32,
   1911                                       binop(Iop_Sub32,
   1912                                             mkexpr(amtT),
   1913                                             mkU32(1)),
   1914                                       mkU32(31)
   1915                                 )
   1916                            )
   1917                      ),
   1918                      mkU32(1)
   1919                )
   1920             ),
   1921             mkexpr(oldC)
   1922          )
   1923       );
   1924    }
   1925    // (Rm >>u (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
   1926    // Lhs of the & limits the shift to 31 bits, so as to
   1927    // give known IR semantics.  Rhs of the & is all 1s for
   1928    // Rs <= 31 and all 0s for Rs >= 32.
   1929    assign(
   1930       *res,
   1931       binop(
   1932          Iop_And32,
   1933          binop(Iop_Shr32,
   1934                mkexpr(rMt),
   1935                unop(Iop_32to8,
   1936                     binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
   1937          binop(Iop_Sar32,
   1938                binop(Iop_Sub32,
   1939                      mkexpr(amtT),
   1940                      mkU32(32)),
   1941                mkU8(31))));
   1942     DIS(buf, "r%u, LSR r%u", rM, rS);
   1943 }
   1944 
   1945 
   1946 static void compute_result_and_C_after_ASR_by_imm5 (
   1947                /*OUT*/HChar* buf,
   1948                IRTemp* res,
   1949                IRTemp* newC,
   1950                IRTemp rMt, UInt shift_amt, /* operands */
   1951                UInt rM      /* only for debug printing */
   1952             )
   1953 {
   1954    if (shift_amt == 0) {
   1955       // conceptually a 32-bit shift, however:
   1956       // res  = Rm >>s 31
   1957       // newC = Rm[31]
   1958       if (newC) {
   1959          assign( *newC,
   1960                  binop(Iop_And32,
   1961                        binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
   1962                        mkU32(1)));
   1963       }
   1964       assign( *res, binop(Iop_Sar32, mkexpr(rMt), mkU8(31)) );
   1965       DIS(buf, "r%u, ASR #0(a.k.a. 32)", rM);
   1966    } else {
   1967       // shift in range 1..31
   1968       // res = Rm >>s shift_amt
   1969       // newC = Rm[shift_amt - 1]
   1970       vassert(shift_amt >= 1 && shift_amt <= 31);
   1971       if (newC) {
   1972          assign( *newC,
   1973                  binop(Iop_And32,
   1974                        binop(Iop_Shr32, mkexpr(rMt),
   1975                                         mkU8(shift_amt - 1)),
   1976                        mkU32(1)));
   1977       }
   1978       assign( *res,
   1979               binop(Iop_Sar32, mkexpr(rMt), mkU8(shift_amt)) );
   1980       DIS(buf, "r%u, ASR #%u", rM, shift_amt);
   1981    }
   1982 }
   1983 
   1984 
   1985 static void compute_result_and_C_after_ASR_by_reg (
   1986                /*OUT*/HChar* buf,
   1987                IRTemp* res,
   1988                IRTemp* newC,
   1989                IRTemp rMt, IRTemp rSt,  /* operands */
   1990                UInt rM,    UInt rS      /* only for debug printing */
   1991             )
   1992 {
   1993    // arithmetic shift right in range 0 .. 255
   1994    // amt = rS & 255
   1995    // res  = amt < 32 ?  Rm >>s amt  : Rm >>s 31
   1996    // newC = amt == 0     ? oldC  :
   1997    //        amt in 1..32 ?  Rm[amt-1]  : Rm[31]
   1998    IRTemp amtT = newTemp(Ity_I32);
   1999    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   2000    if (newC) {
   2001       /* mux0X(amt == 0,
   2002                mux0X(amt < 32,
   2003                      Rm[31],
   2004                      Rm[(amt-1) & 31])
   2005                oldC)
   2006       */
   2007       IRTemp oldC = newTemp(Ity_I32);
   2008       assign(oldC, mk_armg_calculate_flag_c() );
   2009       assign(
   2010          *newC,
   2011          IRExpr_Mux0X(
   2012             unop(Iop_1Uto8,
   2013                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
   2014             IRExpr_Mux0X(
   2015                unop(Iop_1Uto8,
   2016                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
   2017                binop(Iop_And32,
   2018                      binop(Iop_Shr32,
   2019                            mkexpr(rMt),
   2020                            mkU8(31)
   2021                      ),
   2022                      mkU32(1)
   2023                ),
   2024                binop(Iop_And32,
   2025                      binop(Iop_Shr32,
   2026                            mkexpr(rMt),
   2027                            unop(Iop_32to8,
   2028                                 binop(Iop_And32,
   2029                                       binop(Iop_Sub32,
   2030                                             mkexpr(amtT),
   2031                                             mkU32(1)),
   2032                                       mkU32(31)
   2033                                 )
   2034                            )
   2035                      ),
   2036                      mkU32(1)
   2037                )
   2038             ),
   2039             mkexpr(oldC)
   2040          )
   2041       );
   2042    }
   2043    // (Rm >>s (amt <u 32 ? amt : 31))
   2044    assign(
   2045       *res,
   2046       binop(
   2047          Iop_Sar32,
   2048          mkexpr(rMt),
   2049          unop(
   2050             Iop_32to8,
   2051             IRExpr_Mux0X(
   2052                unop(
   2053                  Iop_1Uto8,
   2054                  binop(Iop_CmpLT32U, mkexpr(amtT), mkU32(32))),
   2055                mkU32(31),
   2056                mkexpr(amtT)))));
   2057     DIS(buf, "r%u, ASR r%u", rM, rS);
   2058 }
   2059 
   2060 
   2061 static void compute_result_and_C_after_ROR_by_reg (
   2062                /*OUT*/HChar* buf,
   2063                IRTemp* res,
   2064                IRTemp* newC,
   2065                IRTemp rMt, IRTemp rSt,  /* operands */
   2066                UInt rM,    UInt rS      /* only for debug printing */
   2067             )
   2068 {
   2069    // rotate right in range 0 .. 255
   2070    // amt = rS & 255
   2071    // shop =  Rm `ror` (amt & 31)
   2072    // shco =  amt == 0 ? oldC : Rm[(amt-1) & 31]
   2073    IRTemp amtT = newTemp(Ity_I32);
   2074    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   2075    IRTemp amt5T = newTemp(Ity_I32);
   2076    assign( amt5T, binop(Iop_And32, mkexpr(rSt), mkU32(31)) );
   2077    IRTemp oldC = newTemp(Ity_I32);
   2078    assign(oldC, mk_armg_calculate_flag_c() );
   2079    if (newC) {
   2080       assign(
   2081          *newC,
   2082          IRExpr_Mux0X(
   2083             unop(Iop_32to8, mkexpr(amtT)),
   2084             mkexpr(oldC),
   2085             binop(Iop_And32,
   2086                   binop(Iop_Shr32,
   2087                         mkexpr(rMt),
   2088                         unop(Iop_32to8,
   2089                              binop(Iop_And32,
   2090                                    binop(Iop_Sub32,
   2091                                          mkexpr(amtT),
   2092                                          mkU32(1)
   2093                                    ),
   2094                                    mkU32(31)
   2095                              )
   2096                         )
   2097                   ),
   2098                   mkU32(1)
   2099             )
   2100          )
   2101       );
   2102    }
   2103    assign(
   2104       *res,
   2105       IRExpr_Mux0X(
   2106          unop(Iop_32to8, mkexpr(amt5T)), mkexpr(rMt),
   2107          binop(Iop_Or32,
   2108                binop(Iop_Shr32,
   2109                      mkexpr(rMt),
   2110                      unop(Iop_32to8, mkexpr(amt5T))
   2111                ),
   2112                binop(Iop_Shl32,
   2113                      mkexpr(rMt),
   2114                      unop(Iop_32to8,
   2115                           binop(Iop_Sub32, mkU32(32), mkexpr(amt5T))
   2116                      )
   2117                )
   2118          )
   2119       )
   2120    );
   2121    DIS(buf, "r%u, ROR r#%u", rM, rS);
   2122 }
   2123 
   2124 
   2125 /* Generate an expression corresponding to the immediate-shift case of
   2126    a shifter operand.  This is used both for ARM and Thumb2.
   2127 
   2128    Bind it to a temporary, and return that via *res.  If newC is
   2129    non-NULL, also compute a value for the shifter's carry out (in the
   2130    LSB of a word), bind it to a temporary, and return that via *shco.
   2131 
   2132    Generates GETs from the guest state and is therefore not safe to
   2133    use once we start doing PUTs to it, for any given instruction.
   2134 
   2135    'how' is encoded thusly:
   2136       00b LSL,  01b LSR,  10b ASR,  11b ROR
   2137    Most but not all ARM and Thumb integer insns use this encoding.
   2138    Be careful to ensure the right value is passed here.
   2139 */
   2140 static void compute_result_and_C_after_shift_by_imm5 (
   2141                /*OUT*/HChar* buf,
   2142                /*OUT*/IRTemp* res,
   2143                /*OUT*/IRTemp* newC,
   2144                IRTemp  rMt,       /* reg to shift */
   2145                UInt    how,       /* what kind of shift */
   2146                UInt    shift_amt, /* shift amount (0..31) */
   2147                UInt    rM         /* only for debug printing */
   2148             )
   2149 {
   2150    vassert(shift_amt < 32);
   2151    vassert(how < 4);
   2152 
   2153    switch (how) {
   2154 
   2155       case 0:
   2156          compute_result_and_C_after_LSL_by_imm5(
   2157             buf, res, newC, rMt, shift_amt, rM
   2158          );
   2159          break;
   2160 
   2161       case 1:
   2162          compute_result_and_C_after_LSR_by_imm5(
   2163             buf, res, newC, rMt, shift_amt, rM
   2164          );
   2165          break;
   2166 
   2167       case 2:
   2168          compute_result_and_C_after_ASR_by_imm5(
   2169             buf, res, newC, rMt, shift_amt, rM
   2170          );
   2171          break;
   2172 
   2173       case 3:
   2174          if (shift_amt == 0) {
   2175             IRTemp oldcT = newTemp(Ity_I32);
   2176             // rotate right 1 bit through carry (?)
   2177             // RRX -- described at ARM ARM A5-17
   2178             // res  = (oldC << 31) | (Rm >>u 1)
   2179             // newC = Rm[0]
   2180             if (newC) {
   2181                assign( *newC,
   2182                        binop(Iop_And32, mkexpr(rMt), mkU32(1)));
   2183             }
   2184             assign( oldcT, mk_armg_calculate_flag_c() );
   2185             assign( *res,
   2186                     binop(Iop_Or32,
   2187                           binop(Iop_Shl32, mkexpr(oldcT), mkU8(31)),
   2188                           binop(Iop_Shr32, mkexpr(rMt), mkU8(1))) );
   2189             DIS(buf, "r%u, RRX", rM);
   2190          } else {
   2191             // rotate right in range 1..31
   2192             // res  = Rm `ror` shift_amt
   2193             // newC = Rm[shift_amt - 1]
   2194             vassert(shift_amt >= 1 && shift_amt <= 31);
   2195             if (newC) {
   2196                assign( *newC,
   2197                        binop(Iop_And32,
   2198                              binop(Iop_Shr32, mkexpr(rMt),
   2199                                               mkU8(shift_amt - 1)),
   2200                              mkU32(1)));
   2201             }
   2202             assign( *res,
   2203                     binop(Iop_Or32,
   2204                           binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)),
   2205                           binop(Iop_Shl32, mkexpr(rMt),
   2206                                            mkU8(32-shift_amt))));
   2207             DIS(buf, "r%u, ROR #%u", rM, shift_amt);
   2208          }
   2209          break;
   2210 
   2211       default:
   2212          /*NOTREACHED*/
   2213          vassert(0);
   2214    }
   2215 }
   2216 
   2217 
   2218 /* Generate an expression corresponding to the register-shift case of
   2219    a shifter operand.  This is used both for ARM and Thumb2.
   2220 
   2221    Bind it to a temporary, and return that via *res.  If newC is
   2222    non-NULL, also compute a value for the shifter's carry out (in the
   2223    LSB of a word), bind it to a temporary, and return that via *shco.
   2224 
   2225    Generates GETs from the guest state and is therefore not safe to
   2226    use once we start doing PUTs to it, for any given instruction.
   2227 
   2228    'how' is encoded thusly:
   2229       00b LSL,  01b LSR,  10b ASR,  11b ROR
   2230    Most but not all ARM and Thumb integer insns use this encoding.
   2231    Be careful to ensure the right value is passed here.
   2232 */
   2233 static void compute_result_and_C_after_shift_by_reg (
   2234                /*OUT*/HChar*  buf,
   2235                /*OUT*/IRTemp* res,
   2236                /*OUT*/IRTemp* newC,
   2237                IRTemp  rMt,       /* reg to shift */
   2238                UInt    how,       /* what kind of shift */
   2239                IRTemp  rSt,       /* shift amount */
   2240                UInt    rM,        /* only for debug printing */
   2241                UInt    rS         /* only for debug printing */
   2242             )
   2243 {
   2244    vassert(how < 4);
   2245    switch (how) {
   2246       case 0: { /* LSL */
   2247          compute_result_and_C_after_LSL_by_reg(
   2248             buf, res, newC, rMt, rSt, rM, rS
   2249          );
   2250          break;
   2251       }
   2252       case 1: { /* LSR */
   2253          compute_result_and_C_after_LSR_by_reg(
   2254             buf, res, newC, rMt, rSt, rM, rS
   2255          );
   2256          break;
   2257       }
   2258       case 2: { /* ASR */
   2259          compute_result_and_C_after_ASR_by_reg(
   2260             buf, res, newC, rMt, rSt, rM, rS
   2261          );
   2262          break;
   2263       }
   2264       case 3: { /* ROR */
   2265          compute_result_and_C_after_ROR_by_reg(
   2266              buf, res, newC, rMt, rSt, rM, rS
   2267          );
   2268          break;
   2269       }
   2270       default:
   2271          /*NOTREACHED*/
   2272          vassert(0);
   2273    }
   2274 }
   2275 
   2276 
   2277 /* Generate an expression corresponding to a shifter_operand, bind it
   2278    to a temporary, and return that via *shop.  If shco is non-NULL,
   2279    also compute a value for the shifter's carry out (in the LSB of a
   2280    word), bind it to a temporary, and return that via *shco.
   2281 
   2282    If for some reason we can't come up with a shifter operand (missing
   2283    case?  not really a shifter operand?) return False.
   2284 
   2285    Generates GETs from the guest state and is therefore not safe to
   2286    use once we start doing PUTs to it, for any given instruction.
   2287 
   2288    For ARM insns only; not for Thumb.
   2289 */
   2290 static Bool mk_shifter_operand ( UInt insn_25, UInt insn_11_0,
   2291                                  /*OUT*/IRTemp* shop,
   2292                                  /*OUT*/IRTemp* shco,
   2293                                  /*OUT*/HChar* buf )
   2294 {
   2295    UInt insn_4 = (insn_11_0 >> 4) & 1;
   2296    UInt insn_7 = (insn_11_0 >> 7) & 1;
   2297    vassert(insn_25 <= 0x1);
   2298    vassert(insn_11_0 <= 0xFFF);
   2299 
   2300    vassert(shop && *shop == IRTemp_INVALID);
   2301    *shop = newTemp(Ity_I32);
   2302 
   2303    if (shco) {
   2304       vassert(*shco == IRTemp_INVALID);
   2305       *shco = newTemp(Ity_I32);
   2306    }
   2307 
   2308    /* 32-bit immediate */
   2309 
   2310    if (insn_25 == 1) {
   2311       /* immediate: (7:0) rotated right by 2 * (11:8) */
   2312       UInt imm = (insn_11_0 >> 0) & 0xFF;
   2313       UInt rot = 2 * ((insn_11_0 >> 8) & 0xF);
   2314       vassert(rot <= 30);
   2315       imm = ROR32(imm, rot);
   2316       if (shco) {
   2317          if (rot == 0) {
   2318             assign( *shco, mk_armg_calculate_flag_c() );
   2319          } else {
   2320             assign( *shco, mkU32( (imm >> 31) & 1 ) );
   2321          }
   2322       }
   2323       DIS(buf, "#0x%x", imm);
   2324       assign( *shop, mkU32(imm) );
   2325       return True;
   2326    }
   2327 
   2328    /* Shift/rotate by immediate */
   2329 
   2330    if (insn_25 == 0 && insn_4 == 0) {
   2331       /* Rm (3:0) shifted (6:5) by immediate (11:7) */
   2332       UInt shift_amt = (insn_11_0 >> 7) & 0x1F;
   2333       UInt rM        = (insn_11_0 >> 0) & 0xF;
   2334       UInt how       = (insn_11_0 >> 5) & 3;
   2335       /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
   2336       IRTemp rMt = newTemp(Ity_I32);
   2337       assign(rMt, getIRegA(rM));
   2338 
   2339       vassert(shift_amt <= 31);
   2340 
   2341       compute_result_and_C_after_shift_by_imm5(
   2342          buf, shop, shco, rMt, how, shift_amt, rM
   2343       );
   2344       return True;
   2345    }
   2346 
   2347    /* Shift/rotate by register */
   2348    if (insn_25 == 0 && insn_4 == 1) {
   2349       /* Rm (3:0) shifted (6:5) by Rs (11:8) */
   2350       UInt rM  = (insn_11_0 >> 0) & 0xF;
   2351       UInt rS  = (insn_11_0 >> 8) & 0xF;
   2352       UInt how = (insn_11_0 >> 5) & 3;
   2353       /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
   2354       IRTemp rMt = newTemp(Ity_I32);
   2355       IRTemp rSt = newTemp(Ity_I32);
   2356 
   2357       if (insn_7 == 1)
   2358          return False; /* not really a shifter operand */
   2359 
   2360       assign(rMt, getIRegA(rM));
   2361       assign(rSt, getIRegA(rS));
   2362 
   2363       compute_result_and_C_after_shift_by_reg(
   2364          buf, shop, shco, rMt, how, rSt, rM, rS
   2365       );
   2366       return True;
   2367    }
   2368 
   2369    vex_printf("mk_shifter_operand(0x%x,0x%x)\n", insn_25, insn_11_0 );
   2370    return False;
   2371 }
   2372 
   2373 
   2374 /* ARM only */
   2375 static
   2376 IRExpr* mk_EA_reg_plusminus_imm12 ( UInt rN, UInt bU, UInt imm12,
   2377                                     /*OUT*/HChar* buf )
   2378 {
   2379    vassert(rN < 16);
   2380    vassert(bU < 2);
   2381    vassert(imm12 < 0x1000);
   2382    UChar opChar = bU == 1 ? '+' : '-';
   2383    DIS(buf, "[r%u, #%c%u]", rN, opChar, imm12);
   2384    return
   2385       binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
   2386              getIRegA(rN),
   2387              mkU32(imm12) );
   2388 }
   2389 
   2390 
   2391 /* ARM only.
   2392    NB: This is "DecodeImmShift" in newer versions of the the ARM ARM.
   2393 */
   2394 static
   2395 IRExpr* mk_EA_reg_plusminus_shifted_reg ( UInt rN, UInt bU, UInt rM,
   2396                                           UInt sh2, UInt imm5,
   2397                                           /*OUT*/HChar* buf )
   2398 {
   2399    vassert(rN < 16);
   2400    vassert(bU < 2);
   2401    vassert(rM < 16);
   2402    vassert(sh2 < 4);
   2403    vassert(imm5 < 32);
   2404    UChar   opChar = bU == 1 ? '+' : '-';
   2405    IRExpr* index  = NULL;
   2406    switch (sh2) {
   2407       case 0: /* LSL */
   2408          /* imm5 can be in the range 0 .. 31 inclusive. */
   2409          index = binop(Iop_Shl32, getIRegA(rM), mkU8(imm5));
   2410          DIS(buf, "[r%u, %c r%u LSL #%u]", rN, opChar, rM, imm5);
   2411          break;
   2412       case 1: /* LSR */
   2413          if (imm5 == 0) {
   2414             index = mkU32(0);
   2415             vassert(0); // ATC
   2416          } else {
   2417             index = binop(Iop_Shr32, getIRegA(rM), mkU8(imm5));
   2418          }
   2419          DIS(buf, "[r%u, %cr%u, LSR #%u]",
   2420                   rN, opChar, rM, imm5 == 0 ? 32 : imm5);
   2421          break;
   2422       case 2: /* ASR */
   2423          /* Doesn't this just mean that the behaviour with imm5 == 0
   2424             is the same as if it had been 31 ? */
   2425          if (imm5 == 0) {
   2426             index = binop(Iop_Sar32, getIRegA(rM), mkU8(31));
   2427             vassert(0); // ATC
   2428          } else {
   2429             index = binop(Iop_Sar32, getIRegA(rM), mkU8(imm5));
   2430          }
   2431          DIS(buf, "[r%u, %cr%u, ASR #%u]",
   2432                   rN, opChar, rM, imm5 == 0 ? 32 : imm5);
   2433          break;
   2434       case 3: /* ROR or RRX */
   2435          if (imm5 == 0) {
   2436             IRTemp rmT    = newTemp(Ity_I32);
   2437             IRTemp cflagT = newTemp(Ity_I32);
   2438             assign(rmT, getIRegA(rM));
   2439             assign(cflagT, mk_armg_calculate_flag_c());
   2440             index = binop(Iop_Or32,
   2441                           binop(Iop_Shl32, mkexpr(cflagT), mkU8(31)),
   2442                           binop(Iop_Shr32, mkexpr(rmT), mkU8(1)));
   2443             DIS(buf, "[r%u, %cr%u, RRX]", rN, opChar, rM);
   2444          } else {
   2445             IRTemp rmT = newTemp(Ity_I32);
   2446             assign(rmT, getIRegA(rM));
   2447             vassert(imm5 >= 1 && imm5 <= 31);
   2448             index = binop(Iop_Or32,
   2449                           binop(Iop_Shl32, mkexpr(rmT), mkU8(32-imm5)),
   2450                           binop(Iop_Shr32, mkexpr(rmT), mkU8(imm5)));
   2451             DIS(buf, "[r%u, %cr%u, ROR #%u]", rN, opChar, rM, imm5);
   2452          }
   2453          break;
   2454       default:
   2455          vassert(0);
   2456    }
   2457    vassert(index);
   2458    return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   2459                 getIRegA(rN), index);
   2460 }
   2461 
   2462 
   2463 /* ARM only */
   2464 static
   2465 IRExpr* mk_EA_reg_plusminus_imm8 ( UInt rN, UInt bU, UInt imm8,
   2466                                    /*OUT*/HChar* buf )
   2467 {
   2468    vassert(rN < 16);
   2469    vassert(bU < 2);
   2470    vassert(imm8 < 0x100);
   2471    UChar opChar = bU == 1 ? '+' : '-';
   2472    DIS(buf, "[r%u, #%c%u]", rN, opChar, imm8);
   2473    return
   2474       binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
   2475              getIRegA(rN),
   2476              mkU32(imm8) );
   2477 }
   2478 
   2479 
   2480 /* ARM only */
   2481 static
   2482 IRExpr* mk_EA_reg_plusminus_reg ( UInt rN, UInt bU, UInt rM,
   2483                                   /*OUT*/HChar* buf )
   2484 {
   2485    vassert(rN < 16);
   2486    vassert(bU < 2);
   2487    vassert(rM < 16);
   2488    UChar   opChar = bU == 1 ? '+' : '-';
   2489    IRExpr* index  = getIRegA(rM);
   2490    DIS(buf, "[r%u, %c r%u]", rN, opChar, rM);
   2491    return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   2492                 getIRegA(rN), index);
   2493 }
   2494 
   2495 
   2496 /* irRes :: Ity_I32 holds a floating point comparison result encoded
   2497    as an IRCmpF64Result.  Generate code to convert it to an
   2498    ARM-encoded (N,Z,C,V) group in the lowest 4 bits of an I32 value.
   2499    Assign a new temp to hold that value, and return the temp. */
   2500 static
   2501 IRTemp mk_convert_IRCmpF64Result_to_NZCV ( IRTemp irRes )
   2502 {
   2503    IRTemp ix       = newTemp(Ity_I32);
   2504    IRTemp termL    = newTemp(Ity_I32);
   2505    IRTemp termR    = newTemp(Ity_I32);
   2506    IRTemp nzcv     = newTemp(Ity_I32);
   2507 
   2508    /* This is where the fun starts.  We have to convert 'irRes' from
   2509       an IR-convention return result (IRCmpF64Result) to an
   2510       ARM-encoded (N,Z,C,V) group.  The final result is in the bottom
   2511       4 bits of 'nzcv'. */
   2512    /* Map compare result from IR to ARM(nzcv) */
   2513    /*
   2514       FP cmp result | IR   | ARM(nzcv)
   2515       --------------------------------
   2516       UN              0x45   0011
   2517       LT              0x01   1000
   2518       GT              0x00   0010
   2519       EQ              0x40   0110
   2520    */
   2521    /* Now since you're probably wondering WTF ..
   2522 
   2523       ix fishes the useful bits out of the IR value, bits 6 and 0, and
   2524       places them side by side, giving a number which is 0, 1, 2 or 3.
   2525 
   2526       termL is a sequence cooked up by GNU superopt.  It converts ix
   2527          into an almost correct value NZCV value (incredibly), except
   2528          for the case of UN, where it produces 0100 instead of the
   2529          required 0011.
   2530 
   2531       termR is therefore a correction term, also computed from ix.  It
   2532          is 1 in the UN case and 0 for LT, GT and UN.  Hence, to get
   2533          the final correct value, we subtract termR from termL.
   2534 
   2535       Don't take my word for it.  There's a test program at the bottom
   2536       of this file, to try this out with.
   2537    */
   2538    assign(
   2539       ix,
   2540       binop(Iop_Or32,
   2541             binop(Iop_And32,
   2542                   binop(Iop_Shr32, mkexpr(irRes), mkU8(5)),
   2543                   mkU32(3)),
   2544             binop(Iop_And32, mkexpr(irRes), mkU32(1))));
   2545 
   2546    assign(
   2547       termL,
   2548       binop(Iop_Add32,
   2549             binop(Iop_Shr32,
   2550                   binop(Iop_Sub32,
   2551                         binop(Iop_Shl32,
   2552                               binop(Iop_Xor32, mkexpr(ix), mkU32(1)),
   2553                               mkU8(30)),
   2554                         mkU32(1)),
   2555                   mkU8(29)),
   2556             mkU32(1)));
   2557 
   2558    assign(
   2559       termR,
   2560       binop(Iop_And32,
   2561             binop(Iop_And32,
   2562                   mkexpr(ix),
   2563                   binop(Iop_Shr32, mkexpr(ix), mkU8(1))),
   2564             mkU32(1)));
   2565 
   2566    assign(nzcv, binop(Iop_Sub32, mkexpr(termL), mkexpr(termR)));
   2567    return nzcv;
   2568 }
   2569 
   2570 
   2571 /* Thumb32 only.  This is "ThumbExpandImm" in the ARM ARM.  If
   2572    updatesC is non-NULL, a boolean is written to it indicating whether
   2573    or not the C flag is updated, as per ARM ARM "ThumbExpandImm_C".
   2574 */
   2575 static UInt thumbExpandImm ( Bool* updatesC,
   2576                              UInt imm1, UInt imm3, UInt imm8 )
   2577 {
   2578    vassert(imm1 < (1<<1));
   2579    vassert(imm3 < (1<<3));
   2580    vassert(imm8 < (1<<8));
   2581    UInt i_imm3_a = (imm1 << 4) | (imm3 << 1) | ((imm8 >> 7) & 1);
   2582    UInt abcdefgh = imm8;
   2583    UInt lbcdefgh = imm8 | 0x80;
   2584    if (updatesC) {
   2585       *updatesC = i_imm3_a >= 8;
   2586    }
   2587    switch (i_imm3_a) {
   2588       case 0: case 1:
   2589          return abcdefgh;
   2590       case 2: case 3:
   2591          return (abcdefgh << 16) | abcdefgh;
   2592       case 4: case 5:
   2593          return (abcdefgh << 24) | (abcdefgh << 8);
   2594       case 6: case 7:
   2595          return (abcdefgh << 24) | (abcdefgh << 16)
   2596                 | (abcdefgh << 8) | abcdefgh;
   2597       case 8 ... 31:
   2598          return lbcdefgh << (32 - i_imm3_a);
   2599       default:
   2600          break;
   2601    }
   2602    /*NOTREACHED*/vassert(0);
   2603 }
   2604 
   2605 
   2606 /* Version of thumbExpandImm where we simply feed it the
   2607    instruction halfwords (the lowest addressed one is I0). */
   2608 static UInt thumbExpandImm_from_I0_I1 ( Bool* updatesC,
   2609                                         UShort i0s, UShort i1s )
   2610 {
   2611    UInt i0    = (UInt)i0s;
   2612    UInt i1    = (UInt)i1s;
   2613    UInt imm1  = SLICE_UInt(i0,10,10);
   2614    UInt imm3  = SLICE_UInt(i1,14,12);
   2615    UInt imm8  = SLICE_UInt(i1,7,0);
   2616    return thumbExpandImm(updatesC, imm1, imm3, imm8);
   2617 }
   2618 
   2619 
   2620 /* Thumb16 only.  Given the firstcond and mask fields from an IT
   2621    instruction, compute the 32-bit ITSTATE value implied, as described
   2622    in libvex_guest_arm.h.  This is not the ARM ARM representation.
   2623    Also produce the t/e chars for the 2nd, 3rd, 4th insns, for
   2624    disassembly printing.  Returns False if firstcond or mask
   2625    denote something invalid.
   2626 
   2627    The number and conditions for the instructions to be
   2628    conditionalised depend on firstcond and mask:
   2629 
   2630    mask      cond 1    cond 2      cond 3      cond 4
   2631 
   2632    1000      fc[3:0]
   2633    x100      fc[3:0]   fc[3:1]:x
   2634    xy10      fc[3:0]   fc[3:1]:x   fc[3:1]:y
   2635    xyz1      fc[3:0]   fc[3:1]:x   fc[3:1]:y   fc[3:1]:z
   2636 
   2637    The condition fields are assembled in *itstate backwards (cond 4 at
   2638    the top, cond 1 at the bottom).  Conditions are << 4'd and then
   2639    ^0xE'd, and those fields that correspond to instructions in the IT
   2640    block are tagged with a 1 bit.
   2641 */
   2642 static Bool compute_ITSTATE ( /*OUT*/UInt*  itstate,
   2643                               /*OUT*/UChar* ch1,
   2644                               /*OUT*/UChar* ch2,
   2645                               /*OUT*/UChar* ch3,
   2646                               UInt firstcond, UInt mask )
   2647 {
   2648    vassert(firstcond <= 0xF);
   2649    vassert(mask <= 0xF);
   2650    *itstate = 0;
   2651    *ch1 = *ch2 = *ch3 = '.';
   2652    if (mask == 0)
   2653       return False; /* the logic below actually ensures this anyway,
   2654                        but clearer to make it explicit. */
   2655    if (firstcond == 0xF)
   2656       return False; /* NV is not allowed */
   2657    if (firstcond == 0xE && popcount32(mask) != 1)
   2658       return False; /* if firstcond is AL then all the rest must be too */
   2659 
   2660    UInt m3 = (mask >> 3) & 1;
   2661    UInt m2 = (mask >> 2) & 1;
   2662    UInt m1 = (mask >> 1) & 1;
   2663    UInt m0 = (mask >> 0) & 1;
   2664 
   2665    UInt fc = (firstcond << 4) | 1/*in-IT-block*/;
   2666    UInt ni = (0xE/*AL*/ << 4) | 0/*not-in-IT-block*/;
   2667 
   2668    if (m3 == 1 && (m2|m1|m0) == 0) {
   2669       *itstate = (ni << 24) | (ni << 16) | (ni << 8) | fc;
   2670       *itstate ^= 0xE0E0E0E0;
   2671       return True;
   2672    }
   2673 
   2674    if (m2 == 1 && (m1|m0) == 0) {
   2675       *itstate = (ni << 24) | (ni << 16) | (setbit32(fc, 4, m3) << 8) | fc;
   2676       *itstate ^= 0xE0E0E0E0;
   2677       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
   2678       return True;
   2679    }
   2680 
   2681    if (m1 == 1 && m0 == 0) {
   2682       *itstate = (ni << 24)
   2683                  | (setbit32(fc, 4, m2) << 16)
   2684                  | (setbit32(fc, 4, m3) << 8) | fc;
   2685       *itstate ^= 0xE0E0E0E0;
   2686       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
   2687       *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
   2688       return True;
   2689    }
   2690 
   2691    if (m0 == 1) {
   2692       *itstate = (setbit32(fc, 4, m1) << 24)
   2693                  | (setbit32(fc, 4, m2) << 16)
   2694                  | (setbit32(fc, 4, m3) << 8) | fc;
   2695       *itstate ^= 0xE0E0E0E0;
   2696       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
   2697       *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
   2698       *ch3 = m1 == (firstcond & 1) ? 't' : 'e';
   2699       return True;
   2700    }
   2701 
   2702    return False;
   2703 }
   2704 
   2705 
   2706 /* Generate IR to do 32-bit bit reversal, a la Hacker's Delight
   2707    Chapter 7 Section 1. */
   2708 static IRTemp gen_BITREV ( IRTemp x0 )
   2709 {
   2710    IRTemp x1 = newTemp(Ity_I32);
   2711    IRTemp x2 = newTemp(Ity_I32);
   2712    IRTemp x3 = newTemp(Ity_I32);
   2713    IRTemp x4 = newTemp(Ity_I32);
   2714    IRTemp x5 = newTemp(Ity_I32);
   2715    UInt   c1 = 0x55555555;
   2716    UInt   c2 = 0x33333333;
   2717    UInt   c3 = 0x0F0F0F0F;
   2718    UInt   c4 = 0x00FF00FF;
   2719    UInt   c5 = 0x0000FFFF;
   2720    assign(x1,
   2721           binop(Iop_Or32,
   2722                 binop(Iop_Shl32,
   2723                       binop(Iop_And32, mkexpr(x0), mkU32(c1)),
   2724                       mkU8(1)),
   2725                 binop(Iop_Shr32,
   2726                       binop(Iop_And32, mkexpr(x0), mkU32(~c1)),
   2727                       mkU8(1))
   2728    ));
   2729    assign(x2,
   2730           binop(Iop_Or32,
   2731                 binop(Iop_Shl32,
   2732                       binop(Iop_And32, mkexpr(x1), mkU32(c2)),
   2733                       mkU8(2)),
   2734                 binop(Iop_Shr32,
   2735                       binop(Iop_And32, mkexpr(x1), mkU32(~c2)),
   2736                       mkU8(2))
   2737    ));
   2738    assign(x3,
   2739           binop(Iop_Or32,
   2740                 binop(Iop_Shl32,
   2741                       binop(Iop_And32, mkexpr(x2), mkU32(c3)),
   2742                       mkU8(4)),
   2743                 binop(Iop_Shr32,
   2744                       binop(Iop_And32, mkexpr(x2), mkU32(~c3)),
   2745                       mkU8(4))
   2746    ));
   2747    assign(x4,
   2748           binop(Iop_Or32,
   2749                 binop(Iop_Shl32,
   2750                       binop(Iop_And32, mkexpr(x3), mkU32(c4)),
   2751                       mkU8(8)),
   2752                 binop(Iop_Shr32,
   2753                       binop(Iop_And32, mkexpr(x3), mkU32(~c4)),
   2754                       mkU8(8))
   2755    ));
   2756    assign(x5,
   2757           binop(Iop_Or32,
   2758                 binop(Iop_Shl32,
   2759                       binop(Iop_And32, mkexpr(x4), mkU32(c5)),
   2760                       mkU8(16)),
   2761                 binop(Iop_Shr32,
   2762                       binop(Iop_And32, mkexpr(x4), mkU32(~c5)),
   2763                       mkU8(16))
   2764    ));
   2765    return x5;
   2766 }
   2767 
   2768 
   2769 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
   2770    0:1:2:3 (aka byte-swap). */
   2771 static IRTemp gen_REV ( IRTemp arg )
   2772 {
   2773    IRTemp res = newTemp(Ity_I32);
   2774    assign(res,
   2775           binop(Iop_Or32,
   2776                 binop(Iop_Shl32, mkexpr(arg), mkU8(24)),
   2777           binop(Iop_Or32,
   2778                 binop(Iop_And32, binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
   2779                                  mkU32(0x00FF0000)),
   2780           binop(Iop_Or32,
   2781                 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
   2782                                        mkU32(0x0000FF00)),
   2783                 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(24)),
   2784                                        mkU32(0x000000FF) )
   2785    ))));
   2786    return res;
   2787 }
   2788 
   2789 
   2790 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
   2791    2:3:0:1 (swap within lo and hi halves). */
   2792 static IRTemp gen_REV16 ( IRTemp arg )
   2793 {
   2794    IRTemp res = newTemp(Ity_I32);
   2795    assign(res,
   2796           binop(Iop_Or32,
   2797                 binop(Iop_And32,
   2798                       binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
   2799                       mkU32(0xFF00FF00)),
   2800                 binop(Iop_And32,
   2801                       binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
   2802                       mkU32(0x00FF00FF))));
   2803    return res;
   2804 }
   2805 
   2806 
   2807 /*------------------------------------------------------------*/
   2808 /*--- Advanced SIMD (NEON) instructions                    ---*/
   2809 /*------------------------------------------------------------*/
   2810 
   2811 /*------------------------------------------------------------*/
   2812 /*--- NEON data processing                                 ---*/
   2813 /*------------------------------------------------------------*/
   2814 
   2815 /* For all NEON DP ops, we use the normal scheme to handle conditional
   2816    writes to registers -- pass in condT and hand that on to the
   2817    put*Reg functions.  In ARM mode condT is always IRTemp_INVALID
   2818    since NEON is unconditional for ARM.  In Thumb mode condT is
   2819    derived from the ITSTATE shift register in the normal way. */
   2820 
   2821 static
   2822 UInt get_neon_d_regno(UInt theInstr)
   2823 {
   2824    UInt x = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   2825    if (theInstr & 0x40) {
   2826       if (x & 1) {
   2827          x = x + 0x100;
   2828       } else {
   2829          x = x >> 1;
   2830       }
   2831    }
   2832    return x;
   2833 }
   2834 
   2835 static
   2836 UInt get_neon_n_regno(UInt theInstr)
   2837 {
   2838    UInt x = ((theInstr >> 3) & 0x10) | ((theInstr >> 16) & 0xF);
   2839    if (theInstr & 0x40) {
   2840       if (x & 1) {
   2841          x = x + 0x100;
   2842       } else {
   2843          x = x >> 1;
   2844       }
   2845    }
   2846    return x;
   2847 }
   2848 
   2849 static
   2850 UInt get_neon_m_regno(UInt theInstr)
   2851 {
   2852    UInt x = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   2853    if (theInstr & 0x40) {
   2854       if (x & 1) {
   2855          x = x + 0x100;
   2856       } else {
   2857          x = x >> 1;
   2858       }
   2859    }
   2860    return x;
   2861 }
   2862 
   2863 static
   2864 Bool dis_neon_vext ( UInt theInstr, IRTemp condT )
   2865 {
   2866    UInt dreg = get_neon_d_regno(theInstr);
   2867    UInt mreg = get_neon_m_regno(theInstr);
   2868    UInt nreg = get_neon_n_regno(theInstr);
   2869    UInt imm4 = (theInstr >> 8) & 0xf;
   2870    UInt Q = (theInstr >> 6) & 1;
   2871    HChar reg_t = Q ? 'q' : 'd';
   2872 
   2873    if (Q) {
   2874       putQReg(dreg, triop(Iop_ExtractV128, getQReg(nreg),
   2875                getQReg(mreg), mkU8(imm4)), condT);
   2876    } else {
   2877       putDRegI64(dreg, triop(Iop_Extract64, getDRegI64(nreg),
   2878                  getDRegI64(mreg), mkU8(imm4)), condT);
   2879    }
   2880    DIP("vext.8 %c%d, %c%d, %c%d, #%d\n", reg_t, dreg, reg_t, nreg,
   2881                                          reg_t, mreg, imm4);
   2882    return True;
   2883 }
   2884 
   2885 /* VTBL, VTBX */
   2886 static
   2887 Bool dis_neon_vtb ( UInt theInstr, IRTemp condT )
   2888 {
   2889    UInt op = (theInstr >> 6) & 1;
   2890    UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
   2891    UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
   2892    UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
   2893    UInt len = (theInstr >> 8) & 3;
   2894    Int i;
   2895    IROp cmp;
   2896    ULong imm;
   2897    IRTemp arg_l;
   2898    IRTemp old_mask, new_mask, cur_mask;
   2899    IRTemp old_res, new_res;
   2900    IRTemp old_arg, new_arg;
   2901 
   2902    if (dreg >= 0x100 || mreg >= 0x100 || nreg >= 0x100)
   2903       return False;
   2904    if (nreg + len > 31)
   2905       return False;
   2906 
   2907    cmp = Iop_CmpGT8Ux8;
   2908 
   2909    old_mask = newTemp(Ity_I64);
   2910    old_res = newTemp(Ity_I64);
   2911    old_arg = newTemp(Ity_I64);
   2912    assign(old_mask, mkU64(0));
   2913    assign(old_res, mkU64(0));
   2914    assign(old_arg, getDRegI64(mreg));
   2915    imm = 8;
   2916    imm = (imm <<  8) | imm;
   2917    imm = (imm << 16) | imm;
   2918    imm = (imm << 32) | imm;
   2919 
   2920    for (i = 0; i <= len; i++) {
   2921       arg_l = newTemp(Ity_I64);
   2922       new_mask = newTemp(Ity_I64);
   2923       cur_mask = newTemp(Ity_I64);
   2924       new_res = newTemp(Ity_I64);
   2925       new_arg = newTemp(Ity_I64);
   2926       assign(arg_l, getDRegI64(nreg+i));
   2927       assign(new_arg, binop(Iop_Sub8x8, mkexpr(old_arg), mkU64(imm)));
   2928       assign(cur_mask, binop(cmp, mkU64(imm), mkexpr(old_arg)));
   2929       assign(new_mask, binop(Iop_Or64, mkexpr(old_mask), mkexpr(cur_mask)));
   2930       assign(new_res, binop(Iop_Or64,
   2931                             mkexpr(old_res),
   2932                             binop(Iop_And64,
   2933                                   binop(Iop_Perm8x8,
   2934                                         mkexpr(arg_l),
   2935                                         binop(Iop_And64,
   2936                                               mkexpr(old_arg),
   2937                                               mkexpr(cur_mask))),
   2938                                   mkexpr(cur_mask))));
   2939 
   2940       old_arg = new_arg;
   2941       old_mask = new_mask;
   2942       old_res = new_res;
   2943    }
   2944    if (op) {
   2945       new_res = newTemp(Ity_I64);
   2946       assign(new_res, binop(Iop_Or64,
   2947                             binop(Iop_And64,
   2948                                   getDRegI64(dreg),
   2949                                   unop(Iop_Not64, mkexpr(old_mask))),
   2950                             mkexpr(old_res)));
   2951       old_res = new_res;
   2952    }
   2953 
   2954    putDRegI64(dreg, mkexpr(old_res), condT);
   2955    DIP("vtb%c.8 d%u, {", op ? 'x' : 'l', dreg);
   2956    if (len > 0) {
   2957       DIP("d%u-d%u", nreg, nreg + len);
   2958    } else {
   2959       DIP("d%u", nreg);
   2960    }
   2961    DIP("}, d%u\n", mreg);
   2962    return True;
   2963 }
   2964 
   2965 /* VDUP (scalar)  */
   2966 static
   2967 Bool dis_neon_vdup ( UInt theInstr, IRTemp condT )
   2968 {
   2969    UInt Q = (theInstr >> 6) & 1;
   2970    UInt dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   2971    UInt mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   2972    UInt imm4 = (theInstr >> 16) & 0xF;
   2973    UInt index;
   2974    UInt size;
   2975    IRTemp arg_m;
   2976    IRTemp res;
   2977    IROp op, op2;
   2978 
   2979    if ((imm4 == 0) || (imm4 == 8))
   2980       return False;
   2981    if ((Q == 1) && ((dreg & 1) == 1))
   2982       return False;
   2983    if (Q)
   2984       dreg >>= 1;
   2985    arg_m = newTemp(Ity_I64);
   2986    assign(arg_m, getDRegI64(mreg));
   2987    if (Q)
   2988       res = newTemp(Ity_V128);
   2989    else
   2990       res = newTemp(Ity_I64);
   2991    if ((imm4 & 1) == 1) {
   2992       op = Q ? Iop_Dup8x16 : Iop_Dup8x8;
   2993       op2 = Iop_GetElem8x8;
   2994       index = imm4 >> 1;
   2995       size = 8;
   2996    } else if ((imm4 & 3) == 2) {
   2997       op = Q ? Iop_Dup16x8 : Iop_Dup16x4;
   2998       op2 = Iop_GetElem16x4;
   2999       index = imm4 >> 2;
   3000       size = 16;
   3001    } else if ((imm4 & 7) == 4) {
   3002       op = Q ? Iop_Dup32x4 : Iop_Dup32x2;
   3003       op2 = Iop_GetElem32x2;
   3004       index = imm4 >> 3;
   3005       size = 32;
   3006    } else {
   3007       return False; // can this ever happen?
   3008    }
   3009    assign(res, unop(op, binop(op2, mkexpr(arg_m), mkU8(index))));
   3010    if (Q) {
   3011       putQReg(dreg, mkexpr(res), condT);
   3012    } else {
   3013       putDRegI64(dreg, mkexpr(res), condT);
   3014    }
   3015    DIP("vdup.%d %c%d, d%d[%d]\n", size, Q ? 'q' : 'd', dreg, mreg, index);
   3016    return True;
   3017 }
   3018 
   3019 /* A7.4.1 Three registers of the same length */
   3020 static
   3021 Bool dis_neon_data_3same ( UInt theInstr, IRTemp condT )
   3022 {
   3023    UInt Q = (theInstr >> 6) & 1;
   3024    UInt dreg = get_neon_d_regno(theInstr);
   3025    UInt nreg = get_neon_n_regno(theInstr);
   3026    UInt mreg = get_neon_m_regno(theInstr);
   3027    UInt A = (theInstr >> 8) & 0xF;
   3028    UInt B = (theInstr >> 4) & 1;
   3029    UInt C = (theInstr >> 20) & 0x3;
   3030    UInt U = (theInstr >> 24) & 1;
   3031    UInt size = C;
   3032 
   3033    IRTemp arg_n;
   3034    IRTemp arg_m;
   3035    IRTemp res;
   3036 
   3037    if (Q) {
   3038       arg_n = newTemp(Ity_V128);
   3039       arg_m = newTemp(Ity_V128);
   3040       res = newTemp(Ity_V128);
   3041       assign(arg_n, getQReg(nreg));
   3042       assign(arg_m, getQReg(mreg));
   3043    } else {
   3044       arg_n = newTemp(Ity_I64);
   3045       arg_m = newTemp(Ity_I64);
   3046       res = newTemp(Ity_I64);
   3047       assign(arg_n, getDRegI64(nreg));
   3048       assign(arg_m, getDRegI64(mreg));
   3049    }
   3050 
   3051    switch(A) {
   3052       case 0:
   3053          if (B == 0) {
   3054             /* VHADD */
   3055             ULong imm = 0;
   3056             IRExpr *imm_val;
   3057             IROp addOp;
   3058             IROp andOp;
   3059             IROp shOp;
   3060             char regType = Q ? 'q' : 'd';
   3061 
   3062             if (size == 3)
   3063                return False;
   3064             switch(size) {
   3065                case 0: imm = 0x101010101010101LL; break;
   3066                case 1: imm = 0x1000100010001LL; break;
   3067                case 2: imm = 0x100000001LL; break;
   3068                default: vassert(0);
   3069             }
   3070             if (Q) {
   3071                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   3072                andOp = Iop_AndV128;
   3073             } else {
   3074                imm_val = mkU64(imm);
   3075                andOp = Iop_And64;
   3076             }
   3077             if (U) {
   3078                switch(size) {
   3079                   case 0:
   3080                      addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
   3081                      shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3082                      break;
   3083                   case 1:
   3084                      addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
   3085                      shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3086                      break;
   3087                   case 2:
   3088                      addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
   3089                      shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3090                      break;
   3091                   default:
   3092                      vassert(0);
   3093                }
   3094             } else {
   3095                switch(size) {
   3096                   case 0:
   3097                      addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
   3098                      shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
   3099                      break;
   3100                   case 1:
   3101                      addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
   3102                      shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
   3103                      break;
   3104                   case 2:
   3105                      addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
   3106                      shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
   3107                      break;
   3108                   default:
   3109                      vassert(0);
   3110                }
   3111             }
   3112             assign(res,
   3113                    binop(addOp,
   3114                          binop(addOp,
   3115                                binop(shOp, mkexpr(arg_m), mkU8(1)),
   3116                                binop(shOp, mkexpr(arg_n), mkU8(1))),
   3117                          binop(shOp,
   3118                                binop(addOp,
   3119                                      binop(andOp, mkexpr(arg_m), imm_val),
   3120                                      binop(andOp, mkexpr(arg_n), imm_val)),
   3121                                mkU8(1))));
   3122             DIP("vhadd.%c%d %c%d, %c%d, %c%d\n",
   3123                 U ? 'u' : 's', 8 << size, regType,
   3124                 dreg, regType, nreg, regType, mreg);
   3125          } else {
   3126             /* VQADD */
   3127             IROp op, op2;
   3128             IRTemp tmp;
   3129             char reg_t = Q ? 'q' : 'd';
   3130             if (Q) {
   3131                switch (size) {
   3132                   case 0:
   3133                      op = U ? Iop_QAdd8Ux16 : Iop_QAdd8Sx16;
   3134                      op2 = Iop_Add8x16;
   3135                      break;
   3136                   case 1:
   3137                      op = U ? Iop_QAdd16Ux8 : Iop_QAdd16Sx8;
   3138                      op2 = Iop_Add16x8;
   3139                      break;
   3140                   case 2:
   3141                      op = U ? Iop_QAdd32Ux4 : Iop_QAdd32Sx4;
   3142                      op2 = Iop_Add32x4;
   3143                      break;
   3144                   case 3:
   3145                      op = U ? Iop_QAdd64Ux2 : Iop_QAdd64Sx2;
   3146                      op2 = Iop_Add64x2;
   3147                      break;
   3148                   default:
   3149                      vassert(0);
   3150                }
   3151             } else {
   3152                switch (size) {
   3153                   case 0:
   3154                      op = U ? Iop_QAdd8Ux8 : Iop_QAdd8Sx8;
   3155                      op2 = Iop_Add8x8;
   3156                      break;
   3157                   case 1:
   3158                      op = U ? Iop_QAdd16Ux4 : Iop_QAdd16Sx4;
   3159                      op2 = Iop_Add16x4;
   3160                      break;
   3161                   case 2:
   3162                      op = U ? Iop_QAdd32Ux2 : Iop_QAdd32Sx2;
   3163                      op2 = Iop_Add32x2;
   3164                      break;
   3165                   case 3:
   3166                      op = U ? Iop_QAdd64Ux1 : Iop_QAdd64Sx1;
   3167                      op2 = Iop_Add64;
   3168                      break;
   3169                   default:
   3170                      vassert(0);
   3171                }
   3172             }
   3173             if (Q) {
   3174                tmp = newTemp(Ity_V128);
   3175             } else {
   3176                tmp = newTemp(Ity_I64);
   3177             }
   3178             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   3179 #ifndef DISABLE_QC_FLAG
   3180             assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
   3181             setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
   3182 #endif
   3183             DIP("vqadd.%c%d %c%d, %c%d, %c%d\n",
   3184                 U ? 'u' : 's',
   3185                 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3186          }
   3187          break;
   3188       case 1:
   3189          if (B == 0) {
   3190             /* VRHADD */
   3191             /* VRHADD C, A, B ::=
   3192                  C = (A >> 1) + (B >> 1) + (((A & 1) + (B & 1) + 1) >> 1) */
   3193             IROp shift_op, add_op;
   3194             IRTemp cc;
   3195             ULong one = 1;
   3196             HChar reg_t = Q ? 'q' : 'd';
   3197             switch (size) {
   3198                case 0: one = (one <<  8) | one; /* fall through */
   3199                case 1: one = (one << 16) | one; /* fall through */
   3200                case 2: one = (one << 32) | one; break;
   3201                case 3: return False;
   3202                default: vassert(0);
   3203             }
   3204             if (Q) {
   3205                switch (size) {
   3206                   case 0:
   3207                      shift_op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
   3208                      add_op = Iop_Add8x16;
   3209                      break;
   3210                   case 1:
   3211                      shift_op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   3212                      add_op = Iop_Add16x8;
   3213                      break;
   3214                   case 2:
   3215                      shift_op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   3216                      add_op = Iop_Add32x4;
   3217                      break;
   3218                   case 3:
   3219                      return False;
   3220                   default:
   3221                      vassert(0);
   3222                }
   3223             } else {
   3224                switch (size) {
   3225                   case 0:
   3226                      shift_op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
   3227                      add_op = Iop_Add8x8;
   3228                      break;
   3229                   case 1:
   3230                      shift_op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
   3231                      add_op = Iop_Add16x4;
   3232                      break;
   3233                   case 2:
   3234                      shift_op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
   3235                      add_op = Iop_Add32x2;
   3236                      break;
   3237                   case 3:
   3238                      return False;
   3239                   default:
   3240                      vassert(0);
   3241                }
   3242             }
   3243             if (Q) {
   3244                cc = newTemp(Ity_V128);
   3245                assign(cc, binop(shift_op,
   3246                                 binop(add_op,
   3247                                       binop(add_op,
   3248                                             binop(Iop_AndV128,
   3249                                                   mkexpr(arg_n),
   3250                                                   binop(Iop_64HLtoV128,
   3251                                                         mkU64(one),
   3252                                                         mkU64(one))),
   3253                                             binop(Iop_AndV128,
   3254                                                   mkexpr(arg_m),
   3255                                                   binop(Iop_64HLtoV128,
   3256                                                         mkU64(one),
   3257                                                         mkU64(one)))),
   3258                                       binop(Iop_64HLtoV128,
   3259                                             mkU64(one),
   3260                                             mkU64(one))),
   3261                                 mkU8(1)));
   3262                assign(res, binop(add_op,
   3263                                  binop(add_op,
   3264                                        binop(shift_op,
   3265                                              mkexpr(arg_n),
   3266                                              mkU8(1)),
   3267                                        binop(shift_op,
   3268                                              mkexpr(arg_m),
   3269                                              mkU8(1))),
   3270                                  mkexpr(cc)));
   3271             } else {
   3272                cc = newTemp(Ity_I64);
   3273                assign(cc, binop(shift_op,
   3274                                 binop(add_op,
   3275                                       binop(add_op,
   3276                                             binop(Iop_And64,
   3277                                                   mkexpr(arg_n),
   3278                                                   mkU64(one)),
   3279                                             binop(Iop_And64,
   3280                                                   mkexpr(arg_m),
   3281                                                   mkU64(one))),
   3282                                       mkU64(one)),
   3283                                 mkU8(1)));
   3284                assign(res, binop(add_op,
   3285                                  binop(add_op,
   3286                                        binop(shift_op,
   3287                                              mkexpr(arg_n),
   3288                                              mkU8(1)),
   3289                                        binop(shift_op,
   3290                                              mkexpr(arg_m),
   3291                                              mkU8(1))),
   3292                                  mkexpr(cc)));
   3293             }
   3294             DIP("vrhadd.%c%d %c%d, %c%d, %c%d\n",
   3295                 U ? 'u' : 's',
   3296                 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3297          } else {
   3298             if (U == 0)  {
   3299                switch(C) {
   3300                   case 0: {
   3301                      /* VAND  */
   3302                      HChar reg_t = Q ? 'q' : 'd';
   3303                      if (Q) {
   3304                         assign(res, binop(Iop_AndV128, mkexpr(arg_n),
   3305                                                        mkexpr(arg_m)));
   3306                      } else {
   3307                         assign(res, binop(Iop_And64, mkexpr(arg_n),
   3308                                                      mkexpr(arg_m)));
   3309                      }
   3310                      DIP("vand %c%d, %c%d, %c%d\n",
   3311                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3312                      break;
   3313                   }
   3314                   case 1: {
   3315                      /* VBIC  */
   3316                      HChar reg_t = Q ? 'q' : 'd';
   3317                      if (Q) {
   3318                         assign(res, binop(Iop_AndV128,mkexpr(arg_n),
   3319                                unop(Iop_NotV128, mkexpr(arg_m))));
   3320                      } else {
   3321                         assign(res, binop(Iop_And64, mkexpr(arg_n),
   3322                                unop(Iop_Not64, mkexpr(arg_m))));
   3323                      }
   3324                      DIP("vbic %c%d, %c%d, %c%d\n",
   3325                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3326                      break;
   3327                   }
   3328                   case 2:
   3329                      if ( nreg != mreg) {
   3330                         /* VORR  */
   3331                         HChar reg_t = Q ? 'q' : 'd';
   3332                         if (Q) {
   3333                            assign(res, binop(Iop_OrV128, mkexpr(arg_n),
   3334                                                          mkexpr(arg_m)));
   3335                         } else {
   3336                            assign(res, binop(Iop_Or64, mkexpr(arg_n),
   3337                                                        mkexpr(arg_m)));
   3338                         }
   3339                         DIP("vorr %c%d, %c%d, %c%d\n",
   3340                             reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3341                      } else {
   3342                         /* VMOV  */
   3343                         HChar reg_t = Q ? 'q' : 'd';
   3344                         assign(res, mkexpr(arg_m));
   3345                         DIP("vmov %c%d, %c%d\n", reg_t, dreg, reg_t, mreg);
   3346                      }
   3347                      break;
   3348                   case 3:{
   3349                      /* VORN  */
   3350                      HChar reg_t = Q ? 'q' : 'd';
   3351                      if (Q) {
   3352                         assign(res, binop(Iop_OrV128,mkexpr(arg_n),
   3353                                unop(Iop_NotV128, mkexpr(arg_m))));
   3354                      } else {
   3355                         assign(res, binop(Iop_Or64, mkexpr(arg_n),
   3356                                unop(Iop_Not64, mkexpr(arg_m))));
   3357                      }
   3358                      DIP("vorn %c%d, %c%d, %c%d\n",
   3359                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3360                      break;
   3361                   }
   3362                }
   3363             } else {
   3364                switch(C) {
   3365                   case 0:
   3366                      /* VEOR (XOR)  */
   3367                      if (Q) {
   3368                         assign(res, binop(Iop_XorV128, mkexpr(arg_n),
   3369                                                        mkexpr(arg_m)));
   3370                      } else {
   3371                         assign(res, binop(Iop_Xor64, mkexpr(arg_n),
   3372                                                      mkexpr(arg_m)));
   3373                      }
   3374                      DIP("veor %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   3375                            Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3376                      break;
   3377                   case 1:
   3378                      /* VBSL  */
   3379                      if (Q) {
   3380                         IRTemp reg_d = newTemp(Ity_V128);
   3381                         assign(reg_d, getQReg(dreg));
   3382                         assign(res,
   3383                                binop(Iop_OrV128,
   3384                                      binop(Iop_AndV128, mkexpr(arg_n),
   3385                                                         mkexpr(reg_d)),
   3386                                      binop(Iop_AndV128,
   3387                                            mkexpr(arg_m),
   3388                                            unop(Iop_NotV128,
   3389                                                  mkexpr(reg_d)) ) ) );
   3390                      } else {
   3391                         IRTemp reg_d = newTemp(Ity_I64);
   3392                         assign(reg_d, getDRegI64(dreg));
   3393                         assign(res,
   3394                                binop(Iop_Or64,
   3395                                      binop(Iop_And64, mkexpr(arg_n),
   3396                                                       mkexpr(reg_d)),
   3397                                      binop(Iop_And64,
   3398                                            mkexpr(arg_m),
   3399                                            unop(Iop_Not64, mkexpr(reg_d)))));
   3400                      }
   3401                      DIP("vbsl %c%u, %c%u, %c%u\n",
   3402                          Q ? 'q' : 'd', dreg,
   3403                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3404                      break;
   3405                   case 2:
   3406                      /* VBIT  */
   3407                      if (Q) {
   3408                         IRTemp reg_d = newTemp(Ity_V128);
   3409                         assign(reg_d, getQReg(dreg));
   3410                         assign(res,
   3411                                binop(Iop_OrV128,
   3412                                      binop(Iop_AndV128, mkexpr(arg_n),
   3413                                                         mkexpr(arg_m)),
   3414                                      binop(Iop_AndV128,
   3415                                            mkexpr(reg_d),
   3416                                            unop(Iop_NotV128, mkexpr(arg_m)))));
   3417                      } else {
   3418                         IRTemp reg_d = newTemp(Ity_I64);
   3419                         assign(reg_d, getDRegI64(dreg));
   3420                         assign(res,
   3421                                binop(Iop_Or64,
   3422                                      binop(Iop_And64, mkexpr(arg_n),
   3423                                                       mkexpr(arg_m)),
   3424                                      binop(Iop_And64,
   3425                                            mkexpr(reg_d),
   3426                                            unop(Iop_Not64, mkexpr(arg_m)))));
   3427                      }
   3428                      DIP("vbit %c%u, %c%u, %c%u\n",
   3429                          Q ? 'q' : 'd', dreg,
   3430                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3431                      break;
   3432                   case 3:
   3433                      /* VBIF  */
   3434                      if (Q) {
   3435                         IRTemp reg_d = newTemp(Ity_V128);
   3436                         assign(reg_d, getQReg(dreg));
   3437                         assign(res,
   3438                                binop(Iop_OrV128,
   3439                                      binop(Iop_AndV128, mkexpr(reg_d),
   3440                                                         mkexpr(arg_m)),
   3441                                      binop(Iop_AndV128,
   3442                                            mkexpr(arg_n),
   3443                                            unop(Iop_NotV128, mkexpr(arg_m)))));
   3444                      } else {
   3445                         IRTemp reg_d = newTemp(Ity_I64);
   3446                         assign(reg_d, getDRegI64(dreg));
   3447                         assign(res,
   3448                                binop(Iop_Or64,
   3449                                      binop(Iop_And64, mkexpr(reg_d),
   3450                                                       mkexpr(arg_m)),
   3451                                      binop(Iop_And64,
   3452                                            mkexpr(arg_n),
   3453                                            unop(Iop_Not64, mkexpr(arg_m)))));
   3454                      }
   3455                      DIP("vbif %c%u, %c%u, %c%u\n",
   3456                          Q ? 'q' : 'd', dreg,
   3457                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3458                      break;
   3459                }
   3460             }
   3461          }
   3462          break;
   3463       case 2:
   3464          if (B == 0) {
   3465             /* VHSUB */
   3466             /* (A >> 1) - (B >> 1) - (NOT (A) & B & 1)   */
   3467             ULong imm = 0;
   3468             IRExpr *imm_val;
   3469             IROp subOp;
   3470             IROp notOp;
   3471             IROp andOp;
   3472             IROp shOp;
   3473             if (size == 3)
   3474                return False;
   3475             switch(size) {
   3476                case 0: imm = 0x101010101010101LL; break;
   3477                case 1: imm = 0x1000100010001LL; break;
   3478                case 2: imm = 0x100000001LL; break;
   3479                default: vassert(0);
   3480             }
   3481             if (Q) {
   3482                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   3483                andOp = Iop_AndV128;
   3484                notOp = Iop_NotV128;
   3485             } else {
   3486                imm_val = mkU64(imm);
   3487                andOp = Iop_And64;
   3488                notOp = Iop_Not64;
   3489             }
   3490             if (U) {
   3491                switch(size) {
   3492                   case 0:
   3493                      subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3494                      shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3495                      break;
   3496                   case 1:
   3497                      subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3498                      shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3499                      break;
   3500                   case 2:
   3501                      subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3502                      shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3503                      break;
   3504                   default:
   3505                      vassert(0);
   3506                }
   3507             } else {
   3508                switch(size) {
   3509                   case 0:
   3510                      subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3511                      shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
   3512                      break;
   3513                   case 1:
   3514                      subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3515                      shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
   3516                      break;
   3517                   case 2:
   3518                      subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3519                      shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
   3520                      break;
   3521                   default:
   3522                      vassert(0);
   3523                }
   3524             }
   3525             assign(res,
   3526                    binop(subOp,
   3527                          binop(subOp,
   3528                                binop(shOp, mkexpr(arg_n), mkU8(1)),
   3529                                binop(shOp, mkexpr(arg_m), mkU8(1))),
   3530                          binop(andOp,
   3531                                binop(andOp,
   3532                                      unop(notOp, mkexpr(arg_n)),
   3533                                      mkexpr(arg_m)),
   3534                                imm_val)));
   3535             DIP("vhsub.%c%u %c%u, %c%u, %c%u\n",
   3536                 U ? 'u' : 's', 8 << size,
   3537                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3538                 mreg);
   3539          } else {
   3540             /* VQSUB */
   3541             IROp op, op2;
   3542             IRTemp tmp;
   3543             if (Q) {
   3544                switch (size) {
   3545                   case 0:
   3546                      op = U ? Iop_QSub8Ux16 : Iop_QSub8Sx16;
   3547                      op2 = Iop_Sub8x16;
   3548                      break;
   3549                   case 1:
   3550                      op = U ? Iop_QSub16Ux8 : Iop_QSub16Sx8;
   3551                      op2 = Iop_Sub16x8;
   3552                      break;
   3553                   case 2:
   3554                      op = U ? Iop_QSub32Ux4 : Iop_QSub32Sx4;
   3555                      op2 = Iop_Sub32x4;
   3556                      break;
   3557                   case 3:
   3558                      op = U ? Iop_QSub64Ux2 : Iop_QSub64Sx2;
   3559                      op2 = Iop_Sub64x2;
   3560                      break;
   3561                   default:
   3562                      vassert(0);
   3563                }
   3564             } else {
   3565                switch (size) {
   3566                   case 0:
   3567                      op = U ? Iop_QSub8Ux8 : Iop_QSub8Sx8;
   3568                      op2 = Iop_Sub8x8;
   3569                      break;
   3570                   case 1:
   3571                      op = U ? Iop_QSub16Ux4 : Iop_QSub16Sx4;
   3572                      op2 = Iop_Sub16x4;
   3573                      break;
   3574                   case 2:
   3575                      op = U ? Iop_QSub32Ux2 : Iop_QSub32Sx2;
   3576                      op2 = Iop_Sub32x2;
   3577                      break;
   3578                   case 3:
   3579                      op = U ? Iop_QSub64Ux1 : Iop_QSub64Sx1;
   3580                      op2 = Iop_Sub64;
   3581                      break;
   3582                   default:
   3583                      vassert(0);
   3584                }
   3585             }
   3586             if (Q)
   3587                tmp = newTemp(Ity_V128);
   3588             else
   3589                tmp = newTemp(Ity_I64);
   3590             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   3591 #ifndef DISABLE_QC_FLAG
   3592             assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
   3593             setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
   3594 #endif
   3595             DIP("vqsub.%c%u %c%u, %c%u, %c%u\n",
   3596                 U ? 'u' : 's', 8 << size,
   3597                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3598                 mreg);
   3599          }
   3600          break;
   3601       case 3: {
   3602             IROp op;
   3603             if (Q) {
   3604                switch (size) {
   3605                   case 0: op = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; break;
   3606                   case 1: op = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; break;
   3607                   case 2: op = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; break;
   3608                   case 3: return False;
   3609                   default: vassert(0);
   3610                }
   3611             } else {
   3612                switch (size) {
   3613                   case 0: op = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; break;
   3614                   case 1: op = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; break;
   3615                   case 2: op = U ? Iop_CmpGT32Ux2: Iop_CmpGT32Sx2; break;
   3616                   case 3: return False;
   3617                   default: vassert(0);
   3618                }
   3619             }
   3620             if (B == 0) {
   3621                /* VCGT  */
   3622                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   3623                DIP("vcgt.%c%u %c%u, %c%u, %c%u\n",
   3624                    U ? 'u' : 's', 8 << size,
   3625                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3626                    mreg);
   3627             } else {
   3628                /* VCGE  */
   3629                /* VCGE res, argn, argm
   3630                     is equal to
   3631                   VCGT tmp, argm, argn
   3632                   VNOT res, tmp */
   3633                assign(res,
   3634                       unop(Q ? Iop_NotV128 : Iop_Not64,
   3635                            binop(op, mkexpr(arg_m), mkexpr(arg_n))));
   3636                DIP("vcge.%c%u %c%u, %c%u, %c%u\n",
   3637                    U ? 'u' : 's', 8 << size,
   3638                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3639                    mreg);
   3640             }
   3641          }
   3642          break;
   3643       case 4:
   3644          if (B == 0) {
   3645             /* VSHL */
   3646             IROp op, sub_op;
   3647             IRTemp tmp;
   3648             if (U) {
   3649                switch (size) {
   3650                   case 0: op = Q ? Iop_Shl8x16 : Iop_Shl8x8; break;
   3651                   case 1: op = Q ? Iop_Shl16x8 : Iop_Shl16x4; break;
   3652                   case 2: op = Q ? Iop_Shl32x4 : Iop_Shl32x2; break;
   3653                   case 3: op = Q ? Iop_Shl64x2 : Iop_Shl64; break;
   3654                   default: vassert(0);
   3655                }
   3656             } else {
   3657                tmp = newTemp(Q ? Ity_V128 : Ity_I64);
   3658                switch (size) {
   3659                   case 0:
   3660                      op = Q ? Iop_Sar8x16 : Iop_Sar8x8;
   3661                      sub_op = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3662                      break;
   3663                   case 1:
   3664                      op = Q ? Iop_Sar16x8 : Iop_Sar16x4;
   3665                      sub_op = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3666                      break;
   3667                   case 2:
   3668                      op = Q ? Iop_Sar32x4 : Iop_Sar32x2;
   3669                      sub_op = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3670                      break;
   3671                   case 3:
   3672                      op = Q ? Iop_Sar64x2 : Iop_Sar64;
   3673                      sub_op = Q ? Iop_Sub64x2 : Iop_Sub64;
   3674                      break;
   3675                   default:
   3676                      vassert(0);
   3677                }
   3678             }
   3679             if (U) {
   3680                if (!Q && (size == 3))
   3681                   assign(res, binop(op, mkexpr(arg_m),
   3682                                         unop(Iop_64to8, mkexpr(arg_n))));
   3683                else
   3684                   assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
   3685             } else {
   3686                if (Q)
   3687                   assign(tmp, binop(sub_op,
   3688                                     binop(Iop_64HLtoV128, mkU64(0), mkU64(0)),
   3689                                     mkexpr(arg_n)));
   3690                else
   3691                   assign(tmp, binop(sub_op, mkU64(0), mkexpr(arg_n)));
   3692                if (!Q && (size == 3))
   3693                   assign(res, binop(op, mkexpr(arg_m),
   3694                                         unop(Iop_64to8, mkexpr(tmp))));
   3695                else
   3696                   assign(res, binop(op, mkexpr(arg_m), mkexpr(tmp)));
   3697             }
   3698             DIP("vshl.%c%u %c%u, %c%u, %c%u\n",
   3699                 U ? 'u' : 's', 8 << size,
   3700                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   3701                 nreg);
   3702          } else {
   3703             /* VQSHL */
   3704             IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt;
   3705             IRTemp tmp, shval, mask, old_shval;
   3706             UInt i;
   3707             ULong esize;
   3708             cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
   3709             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   3710             if (U) {
   3711                switch (size) {
   3712                   case 0:
   3713                      op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
   3714                      op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
   3715                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3716                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3717                      break;
   3718                   case 1:
   3719                      op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
   3720                      op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
   3721                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3722                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3723                      break;
   3724                   case 2:
   3725                      op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
   3726                      op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
   3727                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3728                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3729                      break;
   3730                   case 3:
   3731                      op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
   3732                      op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
   3733                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3734                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3735                      break;
   3736                   default:
   3737                      vassert(0);
   3738                }
   3739             } else {
   3740                switch (size) {
   3741                   case 0:
   3742                      op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
   3743                      op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
   3744                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3745                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3746                      break;
   3747                   case 1:
   3748                      op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
   3749                      op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
   3750                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3751                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3752                      break;
   3753                   case 2:
   3754                      op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
   3755                      op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
   3756                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3757                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3758                      break;
   3759                   case 3:
   3760                      op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
   3761                      op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
   3762                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3763                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3764                      break;
   3765                   default:
   3766                      vassert(0);
   3767                }
   3768             }
   3769             if (Q) {
   3770                tmp = newTemp(Ity_V128);
   3771                shval = newTemp(Ity_V128);
   3772                mask = newTemp(Ity_V128);
   3773             } else {
   3774                tmp = newTemp(Ity_I64);
   3775                shval = newTemp(Ity_I64);
   3776                mask = newTemp(Ity_I64);
   3777             }
   3778             assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
   3779 #ifndef DISABLE_QC_FLAG
   3780             /* Only least significant byte from second argument is used.
   3781                Copy this byte to the whole vector element. */
   3782             assign(shval, binop(op_shrn,
   3783                                 binop(op_shln,
   3784                                        mkexpr(arg_n),
   3785                                        mkU8((8 << size) - 8)),
   3786                                 mkU8((8 << size) - 8)));
   3787             for(i = 0; i < size; i++) {
   3788                old_shval = shval;
   3789                shval = newTemp(Q ? Ity_V128 : Ity_I64);
   3790                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
   3791                                    mkexpr(old_shval),
   3792                                    binop(op_shln,
   3793                                          mkexpr(old_shval),
   3794                                          mkU8(8 << i))));
   3795             }
   3796             /* If shift is greater or equal to the element size and
   3797                element is non-zero, then QC flag should be set. */
   3798             esize = (8 << size) - 1;
   3799             esize = (esize <<  8) | esize;
   3800             esize = (esize << 16) | esize;
   3801             esize = (esize << 32) | esize;
   3802             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   3803                              binop(cmp_gt, mkexpr(shval),
   3804                                            Q ? mkU128(esize) : mkU64(esize)),
   3805                              unop(cmp_neq, mkexpr(arg_m))),
   3806                        Q ? mkU128(0) : mkU64(0),
   3807                        Q, condT);
   3808             /* Othervise QC flag should be set if shift value is positive and
   3809                result beign rightshifted the same value is not equal to left
   3810                argument. */
   3811             assign(mask, binop(cmp_gt, mkexpr(shval),
   3812                                        Q ? mkU128(0) : mkU64(0)));
   3813             if (!Q && size == 3)
   3814                assign(tmp, binop(op_rev, mkexpr(res),
   3815                                          unop(Iop_64to8, mkexpr(arg_n))));
   3816             else
   3817                assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
   3818             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   3819                              mkexpr(tmp), mkexpr(mask)),
   3820                        binop(Q ? Iop_AndV128 : Iop_And64,
   3821                              mkexpr(arg_m), mkexpr(mask)),
   3822                        Q, condT);
   3823 #endif
   3824             DIP("vqshl.%c%u %c%u, %c%u, %c%u\n",
   3825                 U ? 'u' : 's', 8 << size,
   3826                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   3827                 nreg);
   3828          }
   3829          break;
   3830       case 5:
   3831          if (B == 0) {
   3832             /* VRSHL */
   3833             IROp op, op_shrn, op_shln, cmp_gt, op_add;
   3834             IRTemp shval, old_shval, imm_val, round;
   3835             UInt i;
   3836             ULong imm;
   3837             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   3838             imm = 1L;
   3839             switch (size) {
   3840                case 0: imm = (imm <<  8) | imm; /* fall through */
   3841                case 1: imm = (imm << 16) | imm; /* fall through */
   3842                case 2: imm = (imm << 32) | imm; /* fall through */
   3843                case 3: break;
   3844                default: vassert(0);
   3845             }
   3846             imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
   3847             round = newTemp(Q ? Ity_V128 : Ity_I64);
   3848             assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
   3849             if (U) {
   3850                switch (size) {
   3851                   case 0:
   3852                      op = Q ? Iop_Shl8x16 : Iop_Shl8x8;
   3853                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   3854                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3855                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3856                      break;
   3857                   case 1:
   3858                      op = Q ? Iop_Shl16x8 : Iop_Shl16x4;
   3859                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   3860                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3861                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3862                      break;
   3863                   case 2:
   3864                      op = Q ? Iop_Shl32x4 : Iop_Shl32x2;
   3865                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   3866                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3867                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3868                      break;
   3869                   case 3:
   3870                      op = Q ? Iop_Shl64x2 : Iop_Shl64;
   3871                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   3872                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3873                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3874                      break;
   3875                   default:
   3876                      vassert(0);
   3877                }
   3878             } else {
   3879                switch (size) {
   3880                   case 0:
   3881                      op = Q ? Iop_Sal8x16 : Iop_Sal8x8;
   3882                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   3883                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3884                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3885                      break;
   3886                   case 1:
   3887                      op = Q ? Iop_Sal16x8 : Iop_Sal16x4;
   3888                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   3889                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3890                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3891                      break;
   3892                   case 2:
   3893                      op = Q ? Iop_Sal32x4 : Iop_Sal32x2;
   3894                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   3895                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3896                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3897                      break;
   3898                   case 3:
   3899                      op = Q ? Iop_Sal64x2 : Iop_Sal64x1;
   3900                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   3901                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3902                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3903                      break;
   3904                   default:
   3905                      vassert(0);
   3906                }
   3907             }
   3908             if (Q) {
   3909                shval = newTemp(Ity_V128);
   3910             } else {
   3911                shval = newTemp(Ity_I64);
   3912             }
   3913             /* Only least significant byte from second argument is used.
   3914                Copy this byte to the whole vector element. */
   3915             assign(shval, binop(op_shrn,
   3916                                 binop(op_shln,
   3917                                        mkexpr(arg_n),
   3918                                        mkU8((8 << size) - 8)),
   3919                                 mkU8((8 << size) - 8)));
   3920             for (i = 0; i < size; i++) {
   3921                old_shval = shval;
   3922                shval = newTemp(Q ? Ity_V128 : Ity_I64);
   3923                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
   3924                                    mkexpr(old_shval),
   3925                                    binop(op_shln,
   3926                                          mkexpr(old_shval),
   3927                                          mkU8(8 << i))));
   3928             }
   3929             /* Compute the result */
   3930             if (!Q && size == 3 && U) {
   3931                assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
   3932                                    binop(op,
   3933                                          mkexpr(arg_m),
   3934                                          unop(Iop_64to8,
   3935                                               binop(op_add,
   3936                                                     mkexpr(arg_n),
   3937                                                     mkexpr(imm_val)))),
   3938                                    binop(Q ? Iop_AndV128 : Iop_And64,
   3939                                          mkexpr(imm_val),
   3940                                          binop(cmp_gt,
   3941                                                Q ? mkU128(0) : mkU64(0),
   3942                                                mkexpr(arg_n)))));
   3943                assign(res, binop(op_add,
   3944                                  binop(op,
   3945                                        mkexpr(arg_m),
   3946                                        unop(Iop_64to8, mkexpr(arg_n))),
   3947                                  mkexpr(round)));
   3948             } else {
   3949                assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
   3950                                    binop(op,
   3951                                          mkexpr(arg_m),
   3952                                          binop(op_add,
   3953                                                mkexpr(arg_n),
   3954                                                mkexpr(imm_val))),
   3955                                    binop(Q ? Iop_AndV128 : Iop_And64,
   3956                                          mkexpr(imm_val),
   3957                                          binop(cmp_gt,
   3958                                                Q ? mkU128(0) : mkU64(0),
   3959                                                mkexpr(arg_n)))));
   3960                assign(res, binop(op_add,
   3961                                  binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   3962                                  mkexpr(round)));
   3963             }
   3964             DIP("vrshl.%c%u %c%u, %c%u, %c%u\n",
   3965                 U ? 'u' : 's', 8 << size,
   3966                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   3967                 nreg);
   3968          } else {
   3969             /* VQRSHL */
   3970             IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt, op_add;
   3971             IRTemp tmp, shval, mask, old_shval, imm_val, round;
   3972             UInt i;
   3973             ULong esize, imm;
   3974             cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
   3975             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   3976             imm = 1L;
   3977             switch (size) {
   3978                case 0: imm = (imm <<  8) | imm; /* fall through */
   3979                case 1: imm = (imm << 16) | imm; /* fall through */
   3980                case 2: imm = (imm << 32) | imm; /* fall through */
   3981                case 3: break;
   3982                default: vassert(0);
   3983             }
   3984             imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
   3985             round = newTemp(Q ? Ity_V128 : Ity_I64);
   3986             assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
   3987             if (U) {
   3988                switch (size) {
   3989                   case 0:
   3990                      op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
   3991                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   3992                      op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
   3993                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3994                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3995                      break;
   3996                   case 1:
   3997                      op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
   3998                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   3999                      op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
   4000                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   4001                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   4002                      break;
   4003                   case 2:
   4004                      op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
   4005                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   4006                      op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
   4007                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   4008                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   4009                      break;
   4010                   case 3:
   4011                      op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
   4012                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   4013                      op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
   4014                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   4015                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   4016                      break;
   4017                   default:
   4018                      vassert(0);
   4019                }
   4020             } else {
   4021                switch (size) {
   4022                   case 0:
   4023                      op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
   4024                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   4025                      op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
   4026                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   4027                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   4028                      break;
   4029                   case 1:
   4030                      op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
   4031                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   4032                      op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
   4033                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   4034                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   4035                      break;
   4036                   case 2:
   4037                      op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
   4038                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   4039                      op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
   4040                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   4041                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   4042                      break;
   4043                   case 3:
   4044                      op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
   4045                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   4046                      op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
   4047                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   4048                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   4049                      break;
   4050                   default:
   4051                      vassert(0);
   4052                }
   4053             }
   4054             if (Q) {
   4055                tmp = newTemp(Ity_V128);
   4056                shval = newTemp(Ity_V128);
   4057                mask = newTemp(Ity_V128);
   4058             } else {
   4059                tmp = newTemp(Ity_I64);
   4060                shval = newTemp(Ity_I64);
   4061                mask = newTemp(Ity_I64);
   4062             }
   4063             /* Only least significant byte from second argument is used.
   4064                Copy this byte to the whole vector element. */
   4065             assign(shval, binop(op_shrn,
   4066                                 binop(op_shln,
   4067                                        mkexpr(arg_n),
   4068                                        mkU8((8 << size) - 8)),
   4069                                 mkU8((8 << size) - 8)));
   4070             for (i = 0; i < size; i++) {
   4071                old_shval = shval;
   4072                shval = newTemp(Q ? Ity_V128 : Ity_I64);
   4073                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
   4074                                    mkexpr(old_shval),
   4075                                    binop(op_shln,
   4076                                          mkexpr(old_shval),
   4077                                          mkU8(8 << i))));
   4078             }
   4079             /* Compute the result */
   4080             assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
   4081                                 binop(op,
   4082                                       mkexpr(arg_m),
   4083                                       binop(op_add,
   4084                                             mkexpr(arg_n),
   4085                                             mkexpr(imm_val))),
   4086                                 binop(Q ? Iop_AndV128 : Iop_And64,
   4087                                       mkexpr(imm_val),
   4088                                       binop(cmp_gt,
   4089                                             Q ? mkU128(0) : mkU64(0),
   4090                                             mkexpr(arg_n)))));
   4091             assign(res, binop(op_add,
   4092                               binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   4093                               mkexpr(round)));
   4094 #ifndef DISABLE_QC_FLAG
   4095             /* If shift is greater or equal to the element size and element is
   4096                non-zero, then QC flag should be set. */
   4097             esize = (8 << size) - 1;
   4098             esize = (esize <<  8) | esize;
   4099             esize = (esize << 16) | esize;
   4100             esize = (esize << 32) | esize;
   4101             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4102                              binop(cmp_gt, mkexpr(shval),
   4103                                            Q ? mkU128(esize) : mkU64(esize)),
   4104                              unop(cmp_neq, mkexpr(arg_m))),
   4105                        Q ? mkU128(0) : mkU64(0),
   4106                        Q, condT);
   4107             /* Othervise QC flag should be set if shift value is positive and
   4108                result beign rightshifted the same value is not equal to left
   4109                argument. */
   4110             assign(mask, binop(cmp_gt, mkexpr(shval),
   4111                                Q ? mkU128(0) : mkU64(0)));
   4112             if (!Q && size == 3)
   4113                assign(tmp, binop(op_rev, mkexpr(res),
   4114                                          unop(Iop_64to8, mkexpr(arg_n))));
   4115             else
   4116                assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
   4117             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4118                              mkexpr(tmp), mkexpr(mask)),
   4119                        binop(Q ? Iop_AndV128 : Iop_And64,
   4120                              mkexpr(arg_m), mkexpr(mask)),
   4121                        Q, condT);
   4122 #endif
   4123             DIP("vqrshl.%c%u %c%u, %c%u, %c%u\n",
   4124                 U ? 'u' : 's', 8 << size,
   4125                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   4126                 nreg);
   4127          }
   4128          break;
   4129       case 6:
   4130          /* VMAX, VMIN  */
   4131          if (B == 0) {
   4132             /* VMAX */
   4133             IROp op;
   4134             if (U == 0) {
   4135                switch (size) {
   4136                   case 0: op = Q ? Iop_Max8Sx16 : Iop_Max8Sx8; break;
   4137                   case 1: op = Q ? Iop_Max16Sx8 : Iop_Max16Sx4; break;
   4138                   case 2: op = Q ? Iop_Max32Sx4 : Iop_Max32Sx2; break;
   4139                   case 3: return False;
   4140                   default: vassert(0);
   4141                }
   4142             } else {
   4143                switch (size) {
   4144                   case 0: op = Q ? Iop_Max8Ux16 : Iop_Max8Ux8; break;
   4145                   case 1: op = Q ? Iop_Max16Ux8 : Iop_Max16Ux4; break;
   4146                   case 2: op = Q ? Iop_Max32Ux4 : Iop_Max32Ux2; break;
   4147                   case 3: return False;
   4148                   default: vassert(0);
   4149                }
   4150             }
   4151             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4152             DIP("vmax.%c%u %c%u, %c%u, %c%u\n",
   4153                 U ? 'u' : 's', 8 << size,
   4154                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4155                 mreg);
   4156          } else {
   4157             /* VMIN */
   4158             IROp op;
   4159             if (U == 0) {
   4160                switch (size) {
   4161                   case 0: op = Q ? Iop_Min8Sx16 : Iop_Min8Sx8; break;
   4162                   case 1: op = Q ? Iop_Min16Sx8 : Iop_Min16Sx4; break;
   4163                   case 2: op = Q ? Iop_Min32Sx4 : Iop_Min32Sx2; break;
   4164                   case 3: return False;
   4165                   default: vassert(0);
   4166                }
   4167             } else {
   4168                switch (size) {
   4169                   case 0: op = Q ? Iop_Min8Ux16 : Iop_Min8Ux8; break;
   4170                   case 1: op = Q ? Iop_Min16Ux8 : Iop_Min16Ux4; break;
   4171                   case 2: op = Q ? Iop_Min32Ux4 : Iop_Min32Ux2; break;
   4172                   case 3: return False;
   4173                   default: vassert(0);
   4174                }
   4175             }
   4176             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4177             DIP("vmin.%c%u %c%u, %c%u, %c%u\n",
   4178                 U ? 'u' : 's', 8 << size,
   4179                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4180                 mreg);
   4181          }
   4182          break;
   4183       case 7:
   4184          if (B == 0) {
   4185             /* VABD */
   4186             IROp op_cmp, op_sub;
   4187             IRTemp cond;
   4188             if ((theInstr >> 23) & 1) {
   4189                vpanic("VABDL should not be in dis_neon_data_3same\n");
   4190             }
   4191             if (Q) {
   4192                switch (size) {
   4193                   case 0:
   4194                      op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
   4195                      op_sub = Iop_Sub8x16;
   4196                      break;
   4197                   case 1:
   4198                      op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
   4199                      op_sub = Iop_Sub16x8;
   4200                      break;
   4201                   case 2:
   4202                      op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
   4203                      op_sub = Iop_Sub32x4;
   4204                      break;
   4205                   case 3:
   4206                      return False;
   4207                   default:
   4208                      vassert(0);
   4209                }
   4210             } else {
   4211                switch (size) {
   4212                   case 0:
   4213                      op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   4214                      op_sub = Iop_Sub8x8;
   4215                      break;
   4216                   case 1:
   4217                      op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   4218                      op_sub = Iop_Sub16x4;
   4219                      break;
   4220                   case 2:
   4221                      op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   4222                      op_sub = Iop_Sub32x2;
   4223                      break;
   4224                   case 3:
   4225                      return False;
   4226                   default:
   4227                      vassert(0);
   4228                }
   4229             }
   4230             if (Q) {
   4231                cond = newTemp(Ity_V128);
   4232             } else {
   4233                cond = newTemp(Ity_I64);
   4234             }
   4235             assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
   4236             assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
   4237                               binop(Q ? Iop_AndV128 : Iop_And64,
   4238                                     binop(op_sub, mkexpr(arg_n),
   4239                                                   mkexpr(arg_m)),
   4240                                     mkexpr(cond)),
   4241                               binop(Q ? Iop_AndV128 : Iop_And64,
   4242                                     binop(op_sub, mkexpr(arg_m),
   4243                                                   mkexpr(arg_n)),
   4244                                     unop(Q ? Iop_NotV128 : Iop_Not64,
   4245                                          mkexpr(cond)))));
   4246             DIP("vabd.%c%u %c%u, %c%u, %c%u\n",
   4247                 U ? 'u' : 's', 8 << size,
   4248                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4249                 mreg);
   4250          } else {
   4251             /* VABA */
   4252             IROp op_cmp, op_sub, op_add;
   4253             IRTemp cond, acc, tmp;
   4254             if ((theInstr >> 23) & 1) {
   4255                vpanic("VABAL should not be in dis_neon_data_3same");
   4256             }
   4257             if (Q) {
   4258                switch (size) {
   4259                   case 0:
   4260                      op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
   4261                      op_sub = Iop_Sub8x16;
   4262                      op_add = Iop_Add8x16;
   4263                      break;
   4264                   case 1:
   4265                      op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
   4266                      op_sub = Iop_Sub16x8;
   4267                      op_add = Iop_Add16x8;
   4268                      break;
   4269                   case 2:
   4270                      op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
   4271                      op_sub = Iop_Sub32x4;
   4272                      op_add = Iop_Add32x4;
   4273                      break;
   4274                   case 3:
   4275                      return False;
   4276                   default:
   4277                      vassert(0);
   4278                }
   4279             } else {
   4280                switch (size) {
   4281                   case 0:
   4282                      op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   4283                      op_sub = Iop_Sub8x8;
   4284                      op_add = Iop_Add8x8;
   4285                      break;
   4286                   case 1:
   4287                      op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   4288                      op_sub = Iop_Sub16x4;
   4289                      op_add = Iop_Add16x4;
   4290                      break;
   4291                   case 2:
   4292                      op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   4293                      op_sub = Iop_Sub32x2;
   4294                      op_add = Iop_Add32x2;
   4295                      break;
   4296                   case 3:
   4297                      return False;
   4298                   default:
   4299                      vassert(0);
   4300                }
   4301             }
   4302             if (Q) {
   4303                cond = newTemp(Ity_V128);
   4304                acc = newTemp(Ity_V128);
   4305                tmp = newTemp(Ity_V128);
   4306                assign(acc, getQReg(dreg));
   4307             } else {
   4308                cond = newTemp(Ity_I64);
   4309                acc = newTemp(Ity_I64);
   4310                tmp = newTemp(Ity_I64);
   4311                assign(acc, getDRegI64(dreg));
   4312             }
   4313             assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
   4314             assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
   4315                               binop(Q ? Iop_AndV128 : Iop_And64,
   4316                                     binop(op_sub, mkexpr(arg_n),
   4317                                                   mkexpr(arg_m)),
   4318                                     mkexpr(cond)),
   4319                               binop(Q ? Iop_AndV128 : Iop_And64,
   4320                                     binop(op_sub, mkexpr(arg_m),
   4321                                                   mkexpr(arg_n)),
   4322                                     unop(Q ? Iop_NotV128 : Iop_Not64,
   4323                                          mkexpr(cond)))));
   4324             assign(res, binop(op_add, mkexpr(acc), mkexpr(tmp)));
   4325             DIP("vaba.%c%u %c%u, %c%u, %c%u\n",
   4326                 U ? 'u' : 's', 8 << size,
   4327                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4328                 mreg);
   4329          }
   4330          break;
   4331       case 8:
   4332          if (B == 0) {
   4333             IROp op;
   4334             if (U == 0) {
   4335                /* VADD  */
   4336                switch (size) {
   4337                   case 0: op = Q ? Iop_Add8x16 : Iop_Add8x8; break;
   4338                   case 1: op = Q ? Iop_Add16x8 : Iop_Add16x4; break;
   4339                   case 2: op = Q ? Iop_Add32x4 : Iop_Add32x2; break;
   4340                   case 3: op = Q ? Iop_Add64x2 : Iop_Add64; break;
   4341                   default: vassert(0);
   4342                }
   4343                DIP("vadd.i%u %c%u, %c%u, %c%u\n",
   4344                    8 << size, Q ? 'q' : 'd',
   4345                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4346             } else {
   4347                /* VSUB  */
   4348                switch (size) {
   4349                   case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
   4350                   case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
   4351                   case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
   4352                   case 3: op = Q ? Iop_Sub64x2 : Iop_Sub64; break;
   4353                   default: vassert(0);
   4354                }
   4355                DIP("vsub.i%u %c%u, %c%u, %c%u\n",
   4356                    8 << size, Q ? 'q' : 'd',
   4357                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4358             }
   4359             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4360          } else {
   4361             IROp op;
   4362             switch (size) {
   4363                case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
   4364                case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
   4365                case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
   4366                case 3: op = Q ? Iop_CmpNEZ64x2 : Iop_CmpwNEZ64; break;
   4367                default: vassert(0);
   4368             }
   4369             if (U == 0) {
   4370                /* VTST  */
   4371                assign(res, unop(op, binop(Q ? Iop_AndV128 : Iop_And64,
   4372                                           mkexpr(arg_n),
   4373                                           mkexpr(arg_m))));
   4374                DIP("vtst.%u %c%u, %c%u, %c%u\n",
   4375                    8 << size, Q ? 'q' : 'd',
   4376                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4377             } else {
   4378                /* VCEQ  */
   4379                assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   4380                                 unop(op,
   4381                                      binop(Q ? Iop_XorV128 : Iop_Xor64,
   4382                                            mkexpr(arg_n),
   4383                                            mkexpr(arg_m)))));
   4384                DIP("vceq.i%u %c%u, %c%u, %c%u\n",
   4385                    8 << size, Q ? 'q' : 'd',
   4386                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4387             }
   4388          }
   4389          break;
   4390       case 9:
   4391          if (B == 0) {
   4392             /* VMLA, VMLS (integer) */
   4393             IROp op, op2;
   4394             UInt P = (theInstr >> 24) & 1;
   4395             if (P) {
   4396                switch (size) {
   4397                   case 0:
   4398                      op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
   4399                      op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   4400                      break;
   4401                   case 1:
   4402                      op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   4403                      op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   4404                      break;
   4405                   case 2:
   4406                      op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   4407                      op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   4408                      break;
   4409                   case 3:
   4410                      return False;
   4411                   default:
   4412                      vassert(0);
   4413                }
   4414             } else {
   4415                switch (size) {
   4416                   case 0:
   4417                      op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
   4418                      op2 = Q ? Iop_Add8x16 : Iop_Add8x8;
   4419                      break;
   4420                   case 1:
   4421                      op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   4422                      op2 = Q ? Iop_Add16x8 : Iop_Add16x4;
   4423                      break;
   4424                   case 2:
   4425                      op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   4426                      op2 = Q ? Iop_Add32x4 : Iop_Add32x2;
   4427                      break;
   4428                   case 3:
   4429                      return False;
   4430                   default:
   4431                      vassert(0);
   4432                }
   4433             }
   4434             assign(res, binop(op2,
   4435                               Q ? getQReg(dreg) : getDRegI64(dreg),
   4436                               binop(op, mkexpr(arg_n), mkexpr(arg_m))));
   4437             DIP("vml%c.i%u %c%u, %c%u, %c%u\n",
   4438                 P ? 's' : 'a', 8 << size,
   4439                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4440                 mreg);
   4441          } else {
   4442             /* VMUL */
   4443             IROp op;
   4444             UInt P = (theInstr >> 24) & 1;
   4445             if (P) {
   4446                switch (size) {
   4447                   case 0:
   4448                      op = Q ? Iop_PolynomialMul8x16 : Iop_PolynomialMul8x8;
   4449                      break;
   4450                   case 1: case 2: case 3: return False;
   4451                   default: vassert(0);
   4452                }
   4453             } else {
   4454                switch (size) {
   4455                   case 0: op = Q ? Iop_Mul8x16 : Iop_Mul8x8; break;
   4456                   case 1: op = Q ? Iop_Mul16x8 : Iop_Mul16x4; break;
   4457                   case 2: op = Q ? Iop_Mul32x4 : Iop_Mul32x2; break;
   4458                   case 3: return False;
   4459                   default: vassert(0);
   4460                }
   4461             }
   4462             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4463             DIP("vmul.%c%u %c%u, %c%u, %c%u\n",
   4464                 P ? 'p' : 'i', 8 << size,
   4465                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4466                 mreg);
   4467          }
   4468          break;
   4469       case 10: {
   4470          /* VPMAX, VPMIN  */
   4471          UInt P = (theInstr >> 4) & 1;
   4472          IROp op;
   4473          if (Q)
   4474             return False;
   4475          if (P) {
   4476             switch (size) {
   4477                case 0: op = U ? Iop_PwMin8Ux8  : Iop_PwMin8Sx8; break;
   4478                case 1: op = U ? Iop_PwMin16Ux4 : Iop_PwMin16Sx4; break;
   4479                case 2: op = U ? Iop_PwMin32Ux2 : Iop_PwMin32Sx2; break;
   4480                case 3: return False;
   4481                default: vassert(0);
   4482             }
   4483          } else {
   4484             switch (size) {
   4485                case 0: op = U ? Iop_PwMax8Ux8  : Iop_PwMax8Sx8; break;
   4486                case 1: op = U ? Iop_PwMax16Ux4 : Iop_PwMax16Sx4; break;
   4487                case 2: op = U ? Iop_PwMax32Ux2 : Iop_PwMax32Sx2; break;
   4488                case 3: return False;
   4489                default: vassert(0);
   4490             }
   4491          }
   4492          assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4493          DIP("vp%s.%c%u %c%u, %c%u, %c%u\n",
   4494              P ? "min" : "max", U ? 'u' : 's',
   4495              8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
   4496              Q ? 'q' : 'd', mreg);
   4497          break;
   4498       }
   4499       case 11:
   4500          if (B == 0) {
   4501             if (U == 0) {
   4502                /* VQDMULH  */
   4503                IROp op ,op2;
   4504                ULong imm;
   4505                switch (size) {
   4506                   case 0: case 3:
   4507                      return False;
   4508                   case 1:
   4509                      op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
   4510                      op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   4511                      imm = 1LL << 15;
   4512                      imm = (imm << 16) | imm;
   4513                      imm = (imm << 32) | imm;
   4514                      break;
   4515                   case 2:
   4516                      op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
   4517                      op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   4518                      imm = 1LL << 31;
   4519                      imm = (imm << 32) | imm;
   4520                      break;
   4521                   default:
   4522                      vassert(0);
   4523                }
   4524                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4525 #ifndef DISABLE_QC_FLAG
   4526                setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4527                                 binop(op2, mkexpr(arg_n),
   4528                                            Q ? mkU128(imm) : mkU64(imm)),
   4529                                 binop(op2, mkexpr(arg_m),
   4530                                            Q ? mkU128(imm) : mkU64(imm))),
   4531                           Q ? mkU128(0) : mkU64(0),
   4532                           Q, condT);
   4533 #endif
   4534                DIP("vqdmulh.s%u %c%u, %c%u, %c%u\n",
   4535                    8 << size, Q ? 'q' : 'd',
   4536                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4537             } else {
   4538                /* VQRDMULH */
   4539                IROp op ,op2;
   4540                ULong imm;
   4541                switch(size) {
   4542                   case 0: case 3:
   4543                      return False;
   4544                   case 1:
   4545                      imm = 1LL << 15;
   4546                      imm = (imm << 16) | imm;
   4547                      imm = (imm << 32) | imm;
   4548                      op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
   4549                      op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   4550                      break;
   4551                   case 2:
   4552                      imm = 1LL << 31;
   4553                      imm = (imm << 32) | imm;
   4554                      op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
   4555                      op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   4556                      break;
   4557                   default:
   4558                      vassert(0);
   4559                }
   4560                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4561 #ifndef DISABLE_QC_FLAG
   4562                setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4563                                 binop(op2, mkexpr(arg_n),
   4564                                            Q ? mkU128(imm) : mkU64(imm)),
   4565                                 binop(op2, mkexpr(arg_m),
   4566                                            Q ? mkU128(imm) : mkU64(imm))),
   4567                           Q ? mkU128(0) : mkU64(0),
   4568                           Q, condT);
   4569 #endif
   4570                DIP("vqrdmulh.s%u %c%u, %c%u, %c%u\n",
   4571                    8 << size, Q ? 'q' : 'd',
   4572                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4573             }
   4574          } else {
   4575             if (U == 0) {
   4576                /* VPADD */
   4577                IROp op;
   4578                if (Q)
   4579                   return False;
   4580                switch (size) {
   4581                   case 0: op = Q ? Iop_PwAdd8x16 : Iop_PwAdd8x8;  break;
   4582                   case 1: op = Q ? Iop_PwAdd16x8 : Iop_PwAdd16x4; break;
   4583                   case 2: op = Q ? Iop_PwAdd32x4 : Iop_PwAdd32x2; break;
   4584                   case 3: return False;
   4585                   default: vassert(0);
   4586                }
   4587                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4588                DIP("vpadd.i%d %c%u, %c%u, %c%u\n",
   4589                    8 << size, Q ? 'q' : 'd',
   4590                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4591             }
   4592          }
   4593          break;
   4594       /* Starting from here these are FP SIMD cases */
   4595       case 13:
   4596          if (B == 0) {
   4597             IROp op;
   4598             if (U == 0) {
   4599                if ((C >> 1) == 0) {
   4600                   /* VADD  */
   4601                   op = Q ? Iop_Add32Fx4 : Iop_Add32Fx2 ;
   4602                   DIP("vadd.f32 %c%u, %c%u, %c%u\n",
   4603                       Q ? 'q' : 'd', dreg,
   4604                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4605                } else {
   4606                   /* VSUB  */
   4607                   op = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2 ;
   4608                   DIP("vsub.f32 %c%u, %c%u, %c%u\n",
   4609                       Q ? 'q' : 'd', dreg,
   4610                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4611                }
   4612             } else {
   4613                if ((C >> 1) == 0) {
   4614                   /* VPADD */
   4615                   if (Q)
   4616                      return False;
   4617                   op = Iop_PwAdd32Fx2;
   4618                   DIP("vpadd.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
   4619                } else {
   4620                   /* VABD  */
   4621                   if (Q) {
   4622                      assign(res, unop(Iop_Abs32Fx4,
   4623                                       binop(Iop_Sub32Fx4,
   4624                                             mkexpr(arg_n),
   4625                                             mkexpr(arg_m))));
   4626                   } else {
   4627                      assign(res, unop(Iop_Abs32Fx2,
   4628                                       binop(Iop_Sub32Fx2,
   4629                                             mkexpr(arg_n),
   4630                                             mkexpr(arg_m))));
   4631                   }
   4632                   DIP("vabd.f32 %c%u, %c%u, %c%u\n",
   4633                       Q ? 'q' : 'd', dreg,
   4634                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4635                   break;
   4636                }
   4637             }
   4638             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4639          } else {
   4640             if (U == 0) {
   4641                /* VMLA, VMLS  */
   4642                IROp op, op2;
   4643                UInt P = (theInstr >> 21) & 1;
   4644                if (P) {
   4645                   switch (size & 1) {
   4646                      case 0:
   4647                         op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   4648                         op2 = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
   4649                         break;
   4650                      case 1: return False;
   4651                      default: vassert(0);
   4652                   }
   4653                } else {
   4654                   switch (size & 1) {
   4655                      case 0:
   4656                         op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   4657                         op2 = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
   4658                         break;
   4659                      case 1: return False;
   4660                      default: vassert(0);
   4661                   }
   4662                }
   4663                assign(res, binop(op2,
   4664                                  Q ? getQReg(dreg) : getDRegI64(dreg),
   4665                                  binop(op, mkexpr(arg_n), mkexpr(arg_m))));
   4666 
   4667                DIP("vml%c.f32 %c%u, %c%u, %c%u\n",
   4668                    P ? 's' : 'a', Q ? 'q' : 'd',
   4669                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4670             } else {
   4671                /* VMUL  */
   4672                IROp op;
   4673                if ((C >> 1) != 0)
   4674                   return False;
   4675                op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2 ;
   4676                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4677                DIP("vmul.f32 %c%u, %c%u, %c%u\n",
   4678                    Q ? 'q' : 'd', dreg,
   4679                    Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4680             }
   4681          }
   4682          break;
   4683       case 14:
   4684          if (B == 0) {
   4685             if (U == 0) {
   4686                if ((C >> 1) == 0) {
   4687                   /* VCEQ  */
   4688                   IROp op;
   4689                   if ((theInstr >> 20) & 1)
   4690                      return False;
   4691                   op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2;
   4692                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4693                   DIP("vceq.f32 %c%u, %c%u, %c%u\n",
   4694                       Q ? 'q' : 'd', dreg,
   4695                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4696                } else {
   4697                   return False;
   4698                }
   4699             } else {
   4700                if ((C >> 1) == 0) {
   4701                   /* VCGE  */
   4702                   IROp op;
   4703                   if ((theInstr >> 20) & 1)
   4704                      return False;
   4705                   op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
   4706                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4707                   DIP("vcge.f32 %c%u, %c%u, %c%u\n",
   4708                       Q ? 'q' : 'd', dreg,
   4709                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4710                } else {
   4711                   /* VCGT  */
   4712                   IROp op;
   4713                   if ((theInstr >> 20) & 1)
   4714                      return False;
   4715                   op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
   4716                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4717                   DIP("vcgt.f32 %c%u, %c%u, %c%u\n",
   4718                       Q ? 'q' : 'd', dreg,
   4719                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4720                }
   4721             }
   4722          } else {
   4723             if (U == 1) {
   4724                /* VACGE, VACGT */
   4725                UInt op_bit = (theInstr >> 21) & 1;
   4726                IROp op, op2;
   4727                op2 = Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2;
   4728                if (op_bit) {
   4729                   op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
   4730                   assign(res, binop(op,
   4731                                     unop(op2, mkexpr(arg_n)),
   4732                                     unop(op2, mkexpr(arg_m))));
   4733                } else {
   4734                   op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
   4735                   assign(res, binop(op,
   4736                                     unop(op2, mkexpr(arg_n)),
   4737                                     unop(op2, mkexpr(arg_m))));
   4738                }
   4739                DIP("vacg%c.f32 %c%u, %c%u, %c%u\n", op_bit ? 't' : 'e',
   4740                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
   4741                    Q ? 'q' : 'd', mreg);
   4742             }
   4743          }
   4744          break;
   4745       case 15:
   4746          if (B == 0) {
   4747             if (U == 0) {
   4748                /* VMAX, VMIN  */
   4749                IROp op;
   4750                if ((theInstr >> 20) & 1)
   4751                   return False;
   4752                if ((theInstr >> 21) & 1) {
   4753                   op = Q ? Iop_Min32Fx4 : Iop_Min32Fx2;
   4754                   DIP("vmin.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4755                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4756                } else {
   4757                   op = Q ? Iop_Max32Fx4 : Iop_Max32Fx2;
   4758                   DIP("vmax.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4759                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4760                }
   4761                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4762             } else {
   4763                /* VPMAX, VPMIN   */
   4764                IROp op;
   4765                if (Q)
   4766                   return False;
   4767                if ((theInstr >> 20) & 1)
   4768                   return False;
   4769                if ((theInstr >> 21) & 1) {
   4770                   op = Iop_PwMin32Fx2;
   4771                   DIP("vpmin.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
   4772                } else {
   4773                   op = Iop_PwMax32Fx2;
   4774                   DIP("vpmax.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
   4775                }
   4776                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4777             }
   4778          } else {
   4779             if (U == 0) {
   4780                if ((C >> 1) == 0) {
   4781                   /* VRECPS */
   4782                   if ((theInstr >> 20) & 1)
   4783                      return False;
   4784                   assign(res, binop(Q ? Iop_Recps32Fx4 : Iop_Recps32Fx2,
   4785                                     mkexpr(arg_n),
   4786                                     mkexpr(arg_m)));
   4787                   DIP("vrecps.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4788                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4789                } else {
   4790                   /* VRSQRTS  */
   4791                   if ((theInstr >> 20) & 1)
   4792                      return False;
   4793                   assign(res, binop(Q ? Iop_Rsqrts32Fx4 : Iop_Rsqrts32Fx2,
   4794                                     mkexpr(arg_n),
   4795                                     mkexpr(arg_m)));
   4796                   DIP("vrsqrts.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4797                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4798                }
   4799             }
   4800          }
   4801          break;
   4802    }
   4803 
   4804    if (Q) {
   4805       putQReg(dreg, mkexpr(res), condT);
   4806    } else {
   4807       putDRegI64(dreg, mkexpr(res), condT);
   4808    }
   4809 
   4810    return True;
   4811 }
   4812 
   4813 /* A7.4.2 Three registers of different length */
   4814 static
   4815 Bool dis_neon_data_3diff ( UInt theInstr, IRTemp condT )
   4816 {
   4817    UInt A = (theInstr >> 8) & 0xf;
   4818    UInt B = (theInstr >> 20) & 3;
   4819    UInt U = (theInstr >> 24) & 1;
   4820    UInt P = (theInstr >> 9) & 1;
   4821    UInt mreg = get_neon_m_regno(theInstr);
   4822    UInt nreg = get_neon_n_regno(theInstr);
   4823    UInt dreg = get_neon_d_regno(theInstr);
   4824    UInt size = B;
   4825    ULong imm;
   4826    IRTemp res, arg_m, arg_n, cond, tmp;
   4827    IROp cvt, cvt2, cmp, op, op2, sh, add;
   4828    switch (A) {
   4829       case 0: case 1: case 2: case 3:
   4830          /* VADDL, VADDW, VSUBL, VSUBW */
   4831          if (dreg & 1)
   4832             return False;
   4833          dreg >>= 1;
   4834          size = B;
   4835          switch (size) {
   4836             case 0:
   4837                cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
   4838                op = (A & 2) ? Iop_Sub16x8 : Iop_Add16x8;
   4839                break;
   4840             case 1:
   4841                cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
   4842                op = (A & 2) ? Iop_Sub32x4 : Iop_Add32x4;
   4843                break;
   4844             case 2:
   4845                cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
   4846                op = (A & 2) ? Iop_Sub64x2 : Iop_Add64x2;
   4847                break;
   4848             case 3:
   4849                return False;
   4850             default:
   4851                vassert(0);
   4852          }
   4853          arg_n = newTemp(Ity_V128);
   4854          arg_m = newTemp(Ity_V128);
   4855          if (A & 1) {
   4856             if (nreg & 1)
   4857                return False;
   4858             nreg >>= 1;
   4859             assign(arg_n, getQReg(nreg));
   4860          } else {
   4861             assign(arg_n, unop(cvt, getDRegI64(nreg)));
   4862          }
   4863          assign(arg_m, unop(cvt, getDRegI64(mreg)));
   4864          putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   4865                        condT);
   4866          DIP("v%s%c.%c%u q%u, %c%u, d%u\n", (A & 2) ? "sub" : "add",
   4867              (A & 1) ? 'w' : 'l', U ? 'u' : 's', 8 << size, dreg,
   4868              (A & 1) ? 'q' : 'd', nreg, mreg);
   4869          return True;
   4870       case 4:
   4871          /* VADDHN, VRADDHN */
   4872          if (mreg & 1)
   4873             return False;
   4874          mreg >>= 1;
   4875          if (nreg & 1)
   4876             return False;
   4877          nreg >>= 1;
   4878          size = B;
   4879          switch (size) {
   4880             case 0:
   4881                op = Iop_Add16x8;
   4882                cvt = Iop_NarrowUn16to8x8;
   4883                sh = Iop_ShrN16x8;
   4884                imm = 1U << 7;
   4885                imm = (imm << 16) | imm;
   4886                imm = (imm << 32) | imm;
   4887                break;
   4888             case 1:
   4889                op = Iop_Add32x4;
   4890                cvt = Iop_NarrowUn32to16x4;
   4891                sh = Iop_ShrN32x4;
   4892                imm = 1U << 15;
   4893                imm = (imm << 32) | imm;
   4894                break;
   4895             case 2:
   4896                op = Iop_Add64x2;
   4897                cvt = Iop_NarrowUn64to32x2;
   4898                sh = Iop_ShrN64x2;
   4899                imm = 1U << 31;
   4900                break;
   4901             case 3:
   4902                return False;
   4903             default:
   4904                vassert(0);
   4905          }
   4906          tmp = newTemp(Ity_V128);
   4907          res = newTemp(Ity_V128);
   4908          assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
   4909          if (U) {
   4910             /* VRADDHN */
   4911             assign(res, binop(op, mkexpr(tmp),
   4912                      binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
   4913          } else {
   4914             assign(res, mkexpr(tmp));
   4915          }
   4916          putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
   4917                     condT);
   4918          DIP("v%saddhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
   4919              nreg, mreg);
   4920          return True;
   4921       case 5:
   4922          /* VABAL */
   4923          if (!((theInstr >> 23) & 1)) {
   4924             vpanic("VABA should not be in dis_neon_data_3diff\n");
   4925          }
   4926          if (dreg & 1)
   4927             return False;
   4928          dreg >>= 1;
   4929          switch (size) {
   4930             case 0:
   4931                cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   4932                cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
   4933                cvt2 = Iop_Widen8Sto16x8;
   4934                op = Iop_Sub16x8;
   4935                op2 = Iop_Add16x8;
   4936                break;
   4937             case 1:
   4938                cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   4939                cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
   4940                cvt2 = Iop_Widen16Sto32x4;
   4941                op = Iop_Sub32x4;
   4942                op2 = Iop_Add32x4;
   4943                break;
   4944             case 2:
   4945                cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   4946                cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
   4947                cvt2 = Iop_Widen32Sto64x2;
   4948                op = Iop_Sub64x2;
   4949                op2 = Iop_Add64x2;
   4950                break;
   4951             case 3:
   4952                return False;
   4953             default:
   4954                vassert(0);
   4955          }
   4956          arg_n = newTemp(Ity_V128);
   4957          arg_m = newTemp(Ity_V128);
   4958          cond = newTemp(Ity_V128);
   4959          res = newTemp(Ity_V128);
   4960          assign(arg_n, unop(cvt, getDRegI64(nreg)));
   4961          assign(arg_m, unop(cvt, getDRegI64(mreg)));
   4962          assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
   4963                                             getDRegI64(mreg))));
   4964          assign(res, binop(op2,
   4965                            binop(Iop_OrV128,
   4966                                  binop(Iop_AndV128,
   4967                                        binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   4968                                        mkexpr(cond)),
   4969                                  binop(Iop_AndV128,
   4970                                        binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   4971                                        unop(Iop_NotV128, mkexpr(cond)))),
   4972                            getQReg(dreg)));
   4973          putQReg(dreg, mkexpr(res), condT);
   4974          DIP("vabal.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
   4975              nreg, mreg);
   4976          return True;
   4977       case 6:
   4978          /* VSUBHN, VRSUBHN */
   4979          if (mreg & 1)
   4980             return False;
   4981          mreg >>= 1;
   4982          if (nreg & 1)
   4983             return False;
   4984          nreg >>= 1;
   4985          size = B;
   4986          switch (size) {
   4987             case 0:
   4988                op = Iop_Sub16x8;
   4989                op2 = Iop_Add16x8;
   4990                cvt = Iop_NarrowUn16to8x8;
   4991                sh = Iop_ShrN16x8;
   4992                imm = 1U << 7;
   4993                imm = (imm << 16) | imm;
   4994                imm = (imm << 32) | imm;
   4995                break;
   4996             case 1:
   4997                op = Iop_Sub32x4;
   4998                op2 = Iop_Add32x4;
   4999                cvt = Iop_NarrowUn32to16x4;
   5000                sh = Iop_ShrN32x4;
   5001                imm = 1U << 15;
   5002                imm = (imm << 32) | imm;
   5003                break;
   5004             case 2:
   5005                op = Iop_Sub64x2;
   5006                op2 = Iop_Add64x2;
   5007                cvt = Iop_NarrowUn64to32x2;
   5008                sh = Iop_ShrN64x2;
   5009                imm = 1U << 31;
   5010                break;
   5011             case 3:
   5012                return False;
   5013             default:
   5014                vassert(0);
   5015          }
   5016          tmp = newTemp(Ity_V128);
   5017          res = newTemp(Ity_V128);
   5018          assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
   5019          if (U) {
   5020             /* VRSUBHN */
   5021             assign(res, binop(op2, mkexpr(tmp),
   5022                      binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
   5023          } else {
   5024             assign(res, mkexpr(tmp));
   5025          }
   5026          putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
   5027                     condT);
   5028          DIP("v%ssubhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
   5029              nreg, mreg);
   5030          return True;
   5031       case 7:
   5032          /* VABDL */
   5033          if (!((theInstr >> 23) & 1)) {
   5034             vpanic("VABL should not be in dis_neon_data_3diff\n");
   5035          }
   5036          if (dreg & 1)
   5037             return False;
   5038          dreg >>= 1;
   5039          switch (size) {
   5040             case 0:
   5041                cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   5042                cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
   5043                cvt2 = Iop_Widen8Sto16x8;
   5044                op = Iop_Sub16x8;
   5045                break;
   5046             case 1:
   5047                cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   5048                cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
   5049                cvt2 = Iop_Widen16Sto32x4;
   5050                op = Iop_Sub32x4;
   5051                break;
   5052             case 2:
   5053                cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   5054                cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
   5055                cvt2 = Iop_Widen32Sto64x2;
   5056                op = Iop_Sub64x2;
   5057                break;
   5058             case 3:
   5059                return False;
   5060             default:
   5061                vassert(0);
   5062          }
   5063          arg_n = newTemp(Ity_V128);
   5064          arg_m = newTemp(Ity_V128);
   5065          cond = newTemp(Ity_V128);
   5066          res = newTemp(Ity_V128);
   5067          assign(arg_n, unop(cvt, getDRegI64(nreg)));
   5068          assign(arg_m, unop(cvt, getDRegI64(mreg)));
   5069          assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
   5070                                             getDRegI64(mreg))));
   5071          assign(res, binop(Iop_OrV128,
   5072                            binop(Iop_AndV128,
   5073                                  binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   5074                                  mkexpr(cond)),
   5075                            binop(Iop_AndV128,
   5076                                  binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   5077                                  unop(Iop_NotV128, mkexpr(cond)))));
   5078          putQReg(dreg, mkexpr(res), condT);
   5079          DIP("vabdl.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
   5080              nreg, mreg);
   5081          return True;
   5082       case 8:
   5083       case 10:
   5084          /* VMLAL, VMLSL (integer) */
   5085          if (dreg & 1)
   5086             return False;
   5087          dreg >>= 1;
   5088          size = B;
   5089          switch (size) {
   5090             case 0:
   5091                op = U ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
   5092                op2 = P ? Iop_Sub16x8 : Iop_Add16x8;
   5093                break;
   5094             case 1:
   5095                op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
   5096                op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
   5097                break;
   5098             case 2:
   5099                op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
   5100                op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
   5101                break;
   5102             case 3:
   5103                return False;
   5104             default:
   5105                vassert(0);
   5106          }
   5107          res = newTemp(Ity_V128);
   5108          assign(res, binop(op, getDRegI64(nreg),getDRegI64(mreg)));
   5109          putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
   5110          DIP("vml%cl.%c%u q%u, d%u, d%u\n", P ? 's' : 'a', U ? 'u' : 's',
   5111              8 << size, dreg, nreg, mreg);
   5112          return True;
   5113       case 9:
   5114       case 11:
   5115          /* VQDMLAL, VQDMLSL */
   5116          if (U)
   5117             return False;
   5118          if (dreg & 1)
   5119             return False;
   5120          dreg >>= 1;
   5121          size = B;
   5122          switch (size) {
   5123             case 0: case 3:
   5124                return False;
   5125             case 1:
   5126                op = Iop_QDMulLong16Sx4;
   5127                cmp = Iop_CmpEQ16x4;
   5128                add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
   5129                op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
   5130                imm = 1LL << 15;
   5131                imm = (imm << 16) | imm;
   5132                imm = (imm << 32) | imm;
   5133                break;
   5134             case 2:
   5135                op = Iop_QDMulLong32Sx2;
   5136                cmp = Iop_CmpEQ32x2;
   5137                add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
   5138                op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
   5139                imm = 1LL << 31;
   5140                imm = (imm << 32) | imm;
   5141                break;
   5142             default:
   5143                vassert(0);
   5144          }
   5145          res = newTemp(Ity_V128);
   5146          tmp = newTemp(Ity_V128);
   5147          assign(res, binop(op, getDRegI64(nreg), getDRegI64(mreg)));
   5148 #ifndef DISABLE_QC_FLAG
   5149          assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
   5150          setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
   5151                     True, condT);
   5152          setFlag_QC(binop(Iop_And64,
   5153                           binop(cmp, getDRegI64(nreg), mkU64(imm)),
   5154                           binop(cmp, getDRegI64(mreg), mkU64(imm))),
   5155                     mkU64(0),
   5156                     False, condT);
   5157 #endif
   5158          putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
   5159          DIP("vqdml%cl.s%u q%u, d%u, d%u\n", P ? 's' : 'a', 8 << size, dreg,
   5160              nreg, mreg);
   5161          return True;
   5162       case 12:
   5163       case 14:
   5164          /* VMULL (integer or polynomial) */
   5165          if (dreg & 1)
   5166             return False;
   5167          dreg >>= 1;
   5168          size = B;
   5169          switch (size) {
   5170             case 0:
   5171                op = (U) ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
   5172                if (P)
   5173                   op = Iop_PolynomialMull8x8;
   5174                break;
   5175             case 1:
   5176                op = (U) ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
   5177                break;
   5178             case 2:
   5179                op = (U) ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
   5180                break;
   5181             default:
   5182                vassert(0);
   5183          }
   5184          putQReg(dreg, binop(op, getDRegI64(nreg),
   5185                                  getDRegI64(mreg)), condT);
   5186          DIP("vmull.%c%u q%u, d%u, d%u\n", P ? 'p' : (U ? 'u' : 's'),
   5187                8 << size, dreg, nreg, mreg);
   5188          return True;
   5189       case 13:
   5190          /* VQDMULL */
   5191          if (U)
   5192             return False;
   5193          if (dreg & 1)
   5194             return False;
   5195          dreg >>= 1;
   5196          size = B;
   5197          switch (size) {
   5198             case 0:
   5199             case 3:
   5200                return False;
   5201             case 1:
   5202                op = Iop_QDMulLong16Sx4;
   5203                op2 = Iop_CmpEQ16x4;
   5204                imm = 1LL << 15;
   5205                imm = (imm << 16) | imm;
   5206                imm = (imm << 32) | imm;
   5207                break;
   5208             case 2:
   5209                op = Iop_QDMulLong32Sx2;
   5210                op2 = Iop_CmpEQ32x2;
   5211                imm = 1LL << 31;
   5212                imm = (imm << 32) | imm;
   5213                break;
   5214             default:
   5215                vassert(0);
   5216          }
   5217          putQReg(dreg, binop(op, getDRegI64(nreg), getDRegI64(mreg)),
   5218                condT);
   5219 #ifndef DISABLE_QC_FLAG
   5220          setFlag_QC(binop(Iop_And64,
   5221                           binop(op2, getDRegI64(nreg), mkU64(imm)),
   5222                           binop(op2, getDRegI64(mreg), mkU64(imm))),
   5223                     mkU64(0),
   5224                     False, condT);
   5225 #endif
   5226          DIP("vqdmull.s%u q%u, d%u, d%u\n", 8 << size, dreg, nreg, mreg);
   5227          return True;
   5228       default:
   5229          return False;
   5230    }
   5231    return False;
   5232 }
   5233 
   5234 /* A7.4.3 Two registers and a scalar */
   5235 static
   5236 Bool dis_neon_data_2reg_and_scalar ( UInt theInstr, IRTemp condT )
   5237 {
   5238 #  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
   5239    UInt U = INSN(24,24);
   5240    UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
   5241    UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
   5242    UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
   5243    UInt size = INSN(21,20);
   5244    UInt index;
   5245    UInt Q = INSN(24,24);
   5246 
   5247    if (INSN(27,25) != 1 || INSN(23,23) != 1
   5248        || INSN(6,6) != 1 || INSN(4,4) != 0)
   5249       return False;
   5250 
   5251    /* VMLA, VMLS (scalar)  */
   5252    if ((INSN(11,8) & BITS4(1,0,1,0)) == BITS4(0,0,0,0)) {
   5253       IRTemp res, arg_m, arg_n;
   5254       IROp dup, get, op, op2, add, sub;
   5255       if (Q) {
   5256          if ((dreg & 1) || (nreg & 1))
   5257             return False;
   5258          dreg >>= 1;
   5259          nreg >>= 1;
   5260          res = newTemp(Ity_V128);
   5261          arg_m = newTemp(Ity_V128);
   5262          arg_n = newTemp(Ity_V128);
   5263          assign(arg_n, getQReg(nreg));
   5264          switch(size) {
   5265             case 1:
   5266                dup = Iop_Dup16x8;
   5267                get = Iop_GetElem16x4;
   5268                index = mreg >> 3;
   5269                mreg &= 7;
   5270                break;
   5271             case 2:
   5272                dup = Iop_Dup32x4;
   5273                get = Iop_GetElem32x2;
   5274                index = mreg >> 4;
   5275                mreg &= 0xf;
   5276                break;
   5277             case 0:
   5278             case 3:
   5279                return False;
   5280             default:
   5281                vassert(0);
   5282          }
   5283          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5284       } else {
   5285          res = newTemp(Ity_I64);
   5286          arg_m = newTemp(Ity_I64);
   5287          arg_n = newTemp(Ity_I64);
   5288          assign(arg_n, getDRegI64(nreg));
   5289          switch(size) {
   5290             case 1:
   5291                dup = Iop_Dup16x4;
   5292                get = Iop_GetElem16x4;
   5293                index = mreg >> 3;
   5294                mreg &= 7;
   5295                break;
   5296             case 2:
   5297                dup = Iop_Dup32x2;
   5298                get = Iop_GetElem32x2;
   5299                index = mreg >> 4;
   5300                mreg &= 0xf;
   5301                break;
   5302             case 0:
   5303             case 3:
   5304                return False;
   5305             default:
   5306                vassert(0);
   5307          }
   5308          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5309       }
   5310       if (INSN(8,8)) {
   5311          switch (size) {
   5312             case 2:
   5313                op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   5314                add = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
   5315                sub = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
   5316                break;
   5317             case 0:
   5318             case 1:
   5319             case 3:
   5320                return False;
   5321             default:
   5322                vassert(0);
   5323          }
   5324       } else {
   5325          switch (size) {
   5326             case 1:
   5327                op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   5328                add = Q ? Iop_Add16x8 : Iop_Add16x4;
   5329                sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   5330                break;
   5331             case 2:
   5332                op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   5333                add = Q ? Iop_Add32x4 : Iop_Add32x2;
   5334                sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   5335                break;
   5336             case 0:
   5337             case 3:
   5338                return False;
   5339             default:
   5340                vassert(0);
   5341          }
   5342       }
   5343       op2 = INSN(10,10) ? sub : add;
   5344       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5345       if (Q)
   5346          putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)),
   5347                condT);
   5348       else
   5349          putDRegI64(dreg, binop(op2, getDRegI64(dreg), mkexpr(res)),
   5350                     condT);
   5351       DIP("vml%c.%c%u %c%u, %c%u, d%u[%u]\n", INSN(10,10) ? 's' : 'a',
   5352             INSN(8,8) ? 'f' : 'i', 8 << size,
   5353             Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, mreg, index);
   5354       return True;
   5355    }
   5356 
   5357    /* VMLAL, VMLSL (scalar)   */
   5358    if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,0)) {
   5359       IRTemp res, arg_m, arg_n;
   5360       IROp dup, get, op, op2, add, sub;
   5361       if (dreg & 1)
   5362          return False;
   5363       dreg >>= 1;
   5364       res = newTemp(Ity_V128);
   5365       arg_m = newTemp(Ity_I64);
   5366       arg_n = newTemp(Ity_I64);
   5367       assign(arg_n, getDRegI64(nreg));
   5368       switch(size) {
   5369          case 1:
   5370             dup = Iop_Dup16x4;
   5371             get = Iop_GetElem16x4;
   5372             index = mreg >> 3;
   5373             mreg &= 7;
   5374             break;
   5375          case 2:
   5376             dup = Iop_Dup32x2;
   5377             get = Iop_GetElem32x2;
   5378             index = mreg >> 4;
   5379             mreg &= 0xf;
   5380             break;
   5381          case 0:
   5382          case 3:
   5383             return False;
   5384          default:
   5385             vassert(0);
   5386       }
   5387       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5388       switch (size) {
   5389          case 1:
   5390             op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
   5391             add = Iop_Add32x4;
   5392             sub = Iop_Sub32x4;
   5393             break;
   5394          case 2:
   5395             op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
   5396             add = Iop_Add64x2;
   5397             sub = Iop_Sub64x2;
   5398             break;
   5399          case 0:
   5400          case 3:
   5401             return False;
   5402          default:
   5403             vassert(0);
   5404       }
   5405       op2 = INSN(10,10) ? sub : add;
   5406       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5407       putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
   5408       DIP("vml%cl.%c%u q%u, d%u, d%u[%u]\n",
   5409           INSN(10,10) ? 's' : 'a', U ? 'u' : 's',
   5410           8 << size, dreg, nreg, mreg, index);
   5411       return True;
   5412    }
   5413 
   5414    /* VQDMLAL, VQDMLSL (scalar)  */
   5415    if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,1) && !U) {
   5416       IRTemp res, arg_m, arg_n, tmp;
   5417       IROp dup, get, op, op2, add, cmp;
   5418       UInt P = INSN(10,10);
   5419       ULong imm;
   5420       if (dreg & 1)
   5421          return False;
   5422       dreg >>= 1;
   5423       res = newTemp(Ity_V128);
   5424       arg_m = newTemp(Ity_I64);
   5425       arg_n = newTemp(Ity_I64);
   5426       assign(arg_n, getDRegI64(nreg));
   5427       switch(size) {
   5428          case 1:
   5429             dup = Iop_Dup16x4;
   5430             get = Iop_GetElem16x4;
   5431             index = mreg >> 3;
   5432             mreg &= 7;
   5433             break;
   5434          case 2:
   5435             dup = Iop_Dup32x2;
   5436             get = Iop_GetElem32x2;
   5437             index = mreg >> 4;
   5438             mreg &= 0xf;
   5439             break;
   5440          case 0:
   5441          case 3:
   5442             return False;
   5443          default:
   5444             vassert(0);
   5445       }
   5446       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5447       switch (size) {
   5448          case 0:
   5449          case 3:
   5450             return False;
   5451          case 1:
   5452             op = Iop_QDMulLong16Sx4;
   5453             cmp = Iop_CmpEQ16x4;
   5454             add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
   5455             op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
   5456             imm = 1LL << 15;
   5457             imm = (imm << 16) | imm;
   5458             imm = (imm << 32) | imm;
   5459             break;
   5460          case 2:
   5461             op = Iop_QDMulLong32Sx2;
   5462             cmp = Iop_CmpEQ32x2;
   5463             add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
   5464             op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
   5465             imm = 1LL << 31;
   5466             imm = (imm << 32) | imm;
   5467             break;
   5468          default:
   5469             vassert(0);
   5470       }
   5471       res = newTemp(Ity_V128);
   5472       tmp = newTemp(Ity_V128);
   5473       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5474 #ifndef DISABLE_QC_FLAG
   5475       assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
   5476       setFlag_QC(binop(Iop_And64,
   5477                        binop(cmp, mkexpr(arg_n), mkU64(imm)),
   5478                        binop(cmp, mkexpr(arg_m), mkU64(imm))),
   5479                  mkU64(0),
   5480                  False, condT);
   5481       setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
   5482                  True, condT);
   5483 #endif
   5484       putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
   5485       DIP("vqdml%cl.s%u q%u, d%u, d%u[%u]\n", P ? 's' : 'a', 8 << size,
   5486           dreg, nreg, mreg, index);
   5487       return True;
   5488    }
   5489 
   5490    /* VMUL (by scalar)  */
   5491    if ((INSN(11,8) & BITS4(1,1,1,0)) == BITS4(1,0,0,0)) {
   5492       IRTemp res, arg_m, arg_n;
   5493       IROp dup, get, op;
   5494       if (Q) {
   5495          if ((dreg & 1) || (nreg & 1))
   5496             return False;
   5497          dreg >>= 1;
   5498          nreg >>= 1;
   5499          res = newTemp(Ity_V128);
   5500          arg_m = newTemp(Ity_V128);
   5501          arg_n = newTemp(Ity_V128);
   5502          assign(arg_n, getQReg(nreg));
   5503          switch(size) {
   5504             case 1:
   5505                dup = Iop_Dup16x8;
   5506                get = Iop_GetElem16x4;
   5507                index = mreg >> 3;
   5508                mreg &= 7;
   5509                break;
   5510             case 2:
   5511                dup = Iop_Dup32x4;
   5512                get = Iop_GetElem32x2;
   5513                index = mreg >> 4;
   5514                mreg &= 0xf;
   5515                break;
   5516             case 0:
   5517             case 3:
   5518                return False;
   5519             default:
   5520                vassert(0);
   5521          }
   5522          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5523       } else {
   5524          res = newTemp(Ity_I64);
   5525          arg_m = newTemp(Ity_I64);
   5526          arg_n = newTemp(Ity_I64);
   5527          assign(arg_n, getDRegI64(nreg));
   5528          switch(size) {
   5529             case 1:
   5530                dup = Iop_Dup16x4;
   5531                get = Iop_GetElem16x4;
   5532                index = mreg >> 3;
   5533                mreg &= 7;
   5534                break;
   5535             case 2:
   5536                dup = Iop_Dup32x2;
   5537                get = Iop_GetElem32x2;
   5538                index = mreg >> 4;
   5539                mreg &= 0xf;
   5540                break;
   5541             case 0:
   5542             case 3:
   5543                return False;
   5544             default:
   5545                vassert(0);
   5546          }
   5547          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5548       }
   5549       if (INSN(8,8)) {
   5550          switch (size) {
   5551             case 2:
   5552                op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   5553                break;
   5554             case 0:
   5555             case 1:
   5556             case 3:
   5557                return False;
   5558             default:
   5559                vassert(0);
   5560          }
   5561       } else {
   5562          switch (size) {
   5563             case 1:
   5564                op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   5565                break;
   5566             case 2:
   5567                op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   5568                break;
   5569             case 0:
   5570             case 3:
   5571                return False;
   5572             default:
   5573                vassert(0);
   5574          }
   5575       }
   5576       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5577       if (Q)
   5578          putQReg(dreg, mkexpr(res), condT);
   5579       else
   5580          putDRegI64(dreg, mkexpr(res), condT);
   5581       DIP("vmul.%c%u %c%u, %c%u, d%u[%u]\n", INSN(8,8) ? 'f' : 'i',
   5582           8 << size, Q ? 'q' : 'd', dreg,
   5583           Q ? 'q' : 'd', nreg, mreg, index);
   5584       return True;
   5585    }
   5586 
   5587    /* VMULL (scalar) */
   5588    if (INSN(11,8) == BITS4(1,0,1,0)) {
   5589       IRTemp res, arg_m, arg_n;
   5590       IROp dup, get, op;
   5591       if (dreg & 1)
   5592          return False;
   5593       dreg >>= 1;
   5594       res = newTemp(Ity_V128);
   5595       arg_m = newTemp(Ity_I64);
   5596       arg_n = newTemp(Ity_I64);
   5597       assign(arg_n, getDRegI64(nreg));
   5598       switch(size) {
   5599          case 1:
   5600             dup = Iop_Dup16x4;
   5601             get = Iop_GetElem16x4;
   5602             index = mreg >> 3;
   5603             mreg &= 7;
   5604             break;
   5605          case 2:
   5606             dup = Iop_Dup32x2;
   5607             get = Iop_GetElem32x2;
   5608             index = mreg >> 4;
   5609             mreg &= 0xf;
   5610             break;
   5611          case 0:
   5612          case 3:
   5613             return False;
   5614          default:
   5615             vassert(0);
   5616       }
   5617       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5618       switch (size) {
   5619          case 1: op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; break;
   5620          case 2: op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; break;
   5621          case 0: case 3: return False;
   5622          default: vassert(0);
   5623       }
   5624       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5625       putQReg(dreg, mkexpr(res), condT);
   5626       DIP("vmull.%c%u q%u, d%u, d%u[%u]\n", U ? 'u' : 's', 8 << size, dreg,
   5627           nreg, mreg, index);
   5628       return True;
   5629    }
   5630 
   5631    /* VQDMULL */
   5632    if (INSN(11,8) == BITS4(1,0,1,1) && !U) {
   5633       IROp op ,op2, dup, get;
   5634       ULong imm;
   5635       IRTemp arg_m, arg_n;
   5636       if (dreg & 1)
   5637          return False;
   5638       dreg >>= 1;
   5639       arg_m = newTemp(Ity_I64);
   5640       arg_n = newTemp(Ity_I64);
   5641       assign(arg_n, getDRegI64(nreg));
   5642       switch(size) {
   5643          case 1:
   5644             dup = Iop_Dup16x4;
   5645             get = Iop_GetElem16x4;
   5646             index = mreg >> 3;
   5647             mreg &= 7;
   5648             break;
   5649          case 2:
   5650             dup = Iop_Dup32x2;
   5651             get = Iop_GetElem32x2;
   5652             index = mreg >> 4;
   5653             mreg &= 0xf;
   5654             break;
   5655          case 0:
   5656          case 3:
   5657             return False;
   5658          default:
   5659             vassert(0);
   5660       }
   5661       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5662       switch (size) {
   5663          case 0:
   5664          case 3:
   5665             return False;
   5666          case 1:
   5667             op = Iop_QDMulLong16Sx4;
   5668             op2 = Iop_CmpEQ16x4;
   5669             imm = 1LL << 15;
   5670             imm = (imm << 16) | imm;
   5671             imm = (imm << 32) | imm;
   5672             break;
   5673          case 2:
   5674             op = Iop_QDMulLong32Sx2;
   5675             op2 = Iop_CmpEQ32x2;
   5676             imm = 1LL << 31;
   5677             imm = (imm << 32) | imm;
   5678             break;
   5679          default:
   5680             vassert(0);
   5681       }
   5682       putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   5683             condT);
   5684 #ifndef DISABLE_QC_FLAG
   5685       setFlag_QC(binop(Iop_And64,
   5686                        binop(op2, mkexpr(arg_n), mkU64(imm)),
   5687                        binop(op2, mkexpr(arg_m), mkU64(imm))),
   5688                  mkU64(0),
   5689                  False, condT);
   5690 #endif
   5691       DIP("vqdmull.s%u q%u, d%u, d%u[%u]\n", 8 << size, dreg, nreg, mreg,
   5692           index);
   5693       return True;
   5694    }
   5695 
   5696    /* VQDMULH */
   5697    if (INSN(11,8) == BITS4(1,1,0,0)) {
   5698       IROp op ,op2, dup, get;
   5699       ULong imm;
   5700       IRTemp res, arg_m, arg_n;
   5701       if (Q) {
   5702          if ((dreg & 1) || (nreg & 1))
   5703             return False;
   5704          dreg >>= 1;
   5705          nreg >>= 1;
   5706          res = newTemp(Ity_V128);
   5707          arg_m = newTemp(Ity_V128);
   5708          arg_n = newTemp(Ity_V128);
   5709          assign(arg_n, getQReg(nreg));
   5710          switch(size) {
   5711             case 1:
   5712                dup = Iop_Dup16x8;
   5713                get = Iop_GetElem16x4;
   5714                index = mreg >> 3;
   5715                mreg &= 7;
   5716                break;
   5717             case 2:
   5718                dup = Iop_Dup32x4;
   5719                get = Iop_GetElem32x2;
   5720                index = mreg >> 4;
   5721                mreg &= 0xf;
   5722                break;
   5723             case 0:
   5724             case 3:
   5725                return False;
   5726             default:
   5727                vassert(0);
   5728          }
   5729          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5730       } else {
   5731          res = newTemp(Ity_I64);
   5732          arg_m = newTemp(Ity_I64);
   5733          arg_n = newTemp(Ity_I64);
   5734          assign(arg_n, getDRegI64(nreg));
   5735          switch(size) {
   5736             case 1:
   5737                dup = Iop_Dup16x4;
   5738                get = Iop_GetElem16x4;
   5739                index = mreg >> 3;
   5740                mreg &= 7;
   5741                break;
   5742             case 2:
   5743                dup = Iop_Dup32x2;
   5744                get = Iop_GetElem32x2;
   5745                index = mreg >> 4;
   5746                mreg &= 0xf;
   5747                break;
   5748             case 0:
   5749             case 3:
   5750                return False;
   5751             default:
   5752                vassert(0);
   5753          }
   5754          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5755       }
   5756       switch (size) {
   5757          case 0:
   5758          case 3:
   5759             return False;
   5760          case 1:
   5761             op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
   5762             op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   5763             imm = 1LL << 15;
   5764             imm = (imm << 16) | imm;
   5765             imm = (imm << 32) | imm;
   5766             break;
   5767          case 2:
   5768             op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
   5769             op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   5770             imm = 1LL << 31;
   5771             imm = (imm << 32) | imm;
   5772             break;
   5773          default:
   5774             vassert(0);
   5775       }
   5776       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5777 #ifndef DISABLE_QC_FLAG
   5778       setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   5779                        binop(op2, mkexpr(arg_n),
   5780                                   Q ? mkU128(imm) : mkU64(imm)),
   5781                        binop(op2, mkexpr(arg_m),
   5782                              Q ? mkU128(imm) : mkU64(imm))),
   5783                  Q ? mkU128(0) : mkU64(0),
   5784                  Q, condT);
   5785 #endif
   5786       if (Q)
   5787          putQReg(dreg, mkexpr(res), condT);
   5788       else
   5789          putDRegI64(dreg, mkexpr(res), condT);
   5790       DIP("vqdmulh.s%u %c%u, %c%u, d%u[%u]\n",
   5791           8 << size, Q ? 'q' : 'd', dreg,
   5792           Q ? 'q' : 'd', nreg, mreg, index);
   5793       return True;
   5794    }
   5795 
   5796    /* VQRDMULH (scalar) */
   5797    if (INSN(11,8) == BITS4(1,1,0,1)) {
   5798       IROp op ,op2, dup, get;
   5799       ULong imm;
   5800       IRTemp res, arg_m, arg_n;
   5801       if (Q) {
   5802          if ((dreg & 1) || (nreg & 1))
   5803             return False;
   5804          dreg >>= 1;
   5805          nreg >>= 1;
   5806          res = newTemp(Ity_V128);
   5807          arg_m = newTemp(Ity_V128);
   5808          arg_n = newTemp(Ity_V128);
   5809          assign(arg_n, getQReg(nreg));
   5810          switch(size) {
   5811             case 1:
   5812                dup = Iop_Dup16x8;
   5813                get = Iop_GetElem16x4;
   5814                index = mreg >> 3;
   5815                mreg &= 7;
   5816                break;
   5817             case 2:
   5818                dup = Iop_Dup32x4;
   5819                get = Iop_GetElem32x2;
   5820                index = mreg >> 4;
   5821                mreg &= 0xf;
   5822                break;
   5823             case 0:
   5824             case 3:
   5825                return False;
   5826             default:
   5827                vassert(0);
   5828          }
   5829          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5830       } else {
   5831          res = newTemp(Ity_I64);
   5832          arg_m = newTemp(Ity_I64);
   5833          arg_n = newTemp(Ity_I64);
   5834          assign(arg_n, getDRegI64(nreg));
   5835          switch(size) {
   5836             case 1:
   5837                dup = Iop_Dup16x4;
   5838                get = Iop_GetElem16x4;
   5839                index = mreg >> 3;
   5840                mreg &= 7;
   5841                break;
   5842             case 2:
   5843                dup = Iop_Dup32x2;
   5844                get = Iop_GetElem32x2;
   5845                index = mreg >> 4;
   5846                mreg &= 0xf;
   5847                break;
   5848             case 0:
   5849             case 3:
   5850                return False;
   5851             default:
   5852                vassert(0);
   5853          }
   5854          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5855       }
   5856       switch (size) {
   5857          case 0:
   5858          case 3:
   5859             return False;
   5860          case 1:
   5861             op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
   5862             op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   5863             imm = 1LL << 15;
   5864             imm = (imm << 16) | imm;
   5865             imm = (imm << 32) | imm;
   5866             break;
   5867          case 2:
   5868             op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
   5869             op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   5870             imm = 1LL << 31;
   5871             imm = (imm << 32) | imm;
   5872             break;
   5873          default:
   5874             vassert(0);
   5875       }
   5876       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5877 #ifndef DISABLE_QC_FLAG
   5878       setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   5879                        binop(op2, mkexpr(arg_n),
   5880                                   Q ? mkU128(imm) : mkU64(imm)),
   5881                        binop(op2, mkexpr(arg_m),
   5882                                   Q ? mkU128(imm) : mkU64(imm))),
   5883                  Q ? mkU128(0) : mkU64(0),
   5884                  Q, condT);
   5885 #endif
   5886       if (Q)
   5887          putQReg(dreg, mkexpr(res), condT);
   5888       else
   5889          putDRegI64(dreg, mkexpr(res), condT);
   5890       DIP("vqrdmulh.s%u %c%u, %c%u, d%u[%u]\n",
   5891           8 << size, Q ? 'q' : 'd', dreg,
   5892           Q ? 'q' : 'd', nreg, mreg, index);
   5893       return True;
   5894    }
   5895 
   5896    return False;
   5897 #  undef INSN
   5898 }
   5899 
   5900 /* A7.4.4 Two registers and a shift amount */
   5901 static
   5902 Bool dis_neon_data_2reg_and_shift ( UInt theInstr, IRTemp condT )
   5903 {
   5904    UInt A = (theInstr >> 8) & 0xf;
   5905    UInt B = (theInstr >> 6) & 1;
   5906    UInt L = (theInstr >> 7) & 1;
   5907    UInt U = (theInstr >> 24) & 1;
   5908    UInt Q = B;
   5909    UInt imm6 = (theInstr >> 16) & 0x3f;
   5910    UInt shift_imm;
   5911    UInt size = 4;
   5912    UInt tmp;
   5913    UInt mreg = get_neon_m_regno(theInstr);
   5914    UInt dreg = get_neon_d_regno(theInstr);
   5915    ULong imm = 0;
   5916    IROp op, cvt, add = Iop_INVALID, cvt2, op_rev;
   5917    IRTemp reg_m, res, mask;
   5918 
   5919    if (L == 0 && ((theInstr >> 19) & 7) == 0)
   5920       /* It is one reg and immediate */
   5921       return False;
   5922 
   5923    tmp = (L << 6) | imm6;
   5924    if (tmp & 0x40) {
   5925       size = 3;
   5926       shift_imm = 64 - imm6;
   5927    } else if (tmp & 0x20) {
   5928       size = 2;
   5929       shift_imm = 64 - imm6;
   5930    } else if (tmp & 0x10) {
   5931       size = 1;
   5932       shift_imm = 32 - imm6;
   5933    } else if (tmp & 0x8) {
   5934       size = 0;
   5935       shift_imm = 16 - imm6;
   5936    } else {
   5937       return False;
   5938    }
   5939 
   5940    switch (A) {
   5941       case 3:
   5942       case 2:
   5943          /* VRSHR, VRSRA */
   5944          if (shift_imm > 0) {
   5945             IRExpr *imm_val;
   5946             imm = 1L;
   5947             switch (size) {
   5948                case 0:
   5949                   imm = (imm << 8) | imm;
   5950                   /* fall through */
   5951                case 1:
   5952                   imm = (imm << 16) | imm;
   5953                   /* fall through */
   5954                case 2:
   5955                   imm = (imm << 32) | imm;
   5956                   /* fall through */
   5957                case 3:
   5958                   break;
   5959                default:
   5960                   vassert(0);
   5961             }
   5962             if (Q) {
   5963                reg_m = newTemp(Ity_V128);
   5964                res = newTemp(Ity_V128);
   5965                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   5966                assign(reg_m, getQReg(mreg));
   5967                switch (size) {
   5968                   case 0:
   5969                      add = Iop_Add8x16;
   5970                      op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
   5971                      break;
   5972                   case 1:
   5973                      add = Iop_Add16x8;
   5974                      op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   5975                      break;
   5976                   case 2:
   5977                      add = Iop_Add32x4;
   5978                      op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   5979                      break;
   5980                   case 3:
   5981                      add = Iop_Add64x2;
   5982                      op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
   5983                      break;
   5984                   default:
   5985                      vassert(0);
   5986                }
   5987             } else {
   5988                reg_m = newTemp(Ity_I64);
   5989                res = newTemp(Ity_I64);
   5990                imm_val = mkU64(imm);
   5991                assign(reg_m, getDRegI64(mreg));
   5992                switch (size) {
   5993                   case 0:
   5994                      add = Iop_Add8x8;
   5995                      op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
   5996                      break;
   5997                   case 1:
   5998                      add = Iop_Add16x4;
   5999                      op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
   6000                      break;
   6001                   case 2:
   6002                      add = Iop_Add32x2;
   6003                      op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
   6004                      break;
   6005                   case 3:
   6006                      add = Iop_Add64;
   6007                      op = U ? Iop_Shr64 : Iop_Sar64;
   6008                      break;
   6009                   default:
   6010                      vassert(0);
   6011                }
   6012             }
   6013             assign(res,
   6014                    binop(add,
   6015                          binop(op,
   6016                                mkexpr(reg_m),
   6017                                mkU8(shift_imm)),
   6018                          binop(Q ? Iop_AndV128 : Iop_And64,
   6019                                binop(op,
   6020                                      mkexpr(reg_m),
   6021                                      mkU8(shift_imm - 1)),
   6022                                imm_val)));
   6023          } else {
   6024             if (Q) {
   6025                res = newTemp(Ity_V128);
   6026                assign(res, getQReg(mreg));
   6027             } else {
   6028                res = newTemp(Ity_I64);
   6029                assign(res, getDRegI64(mreg));
   6030             }
   6031          }
   6032          if (A == 3) {
   6033             if (Q) {
   6034                putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
   6035                              condT);
   6036             } else {
   6037                putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
   6038                                 condT);
   6039             }
   6040             DIP("vrsra.%c%u %c%u, %c%u, #%u\n",
   6041                 U ? 'u' : 's', 8 << size,
   6042                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6043          } else {
   6044             if (Q) {
   6045                putQReg(dreg, mkexpr(res), condT);
   6046             } else {
   6047                putDRegI64(dreg, mkexpr(res), condT);
   6048             }
   6049             DIP("vrshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
   6050                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6051          }
   6052          return True;
   6053       case 1:
   6054       case 0:
   6055          /* VSHR, VSRA */
   6056          if (Q) {
   6057             reg_m = newTemp(Ity_V128);
   6058             assign(reg_m, getQReg(mreg));
   6059             res = newTemp(Ity_V128);
   6060          } else {
   6061             reg_m = newTemp(Ity_I64);
   6062             assign(reg_m, getDRegI64(mreg));
   6063             res = newTemp(Ity_I64);
   6064          }
   6065          if (Q) {
   6066             switch (size) {
   6067                case 0:
   6068                   op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
   6069                   add = Iop_Add8x16;
   6070                   break;
   6071                case 1:
   6072                   op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   6073                   add = Iop_Add16x8;
   6074                   break;
   6075                case 2:
   6076                   op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   6077                   add = Iop_Add32x4;
   6078                   break;
   6079                case 3:
   6080                   op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
   6081                   add = Iop_Add64x2;
   6082                   break;
   6083                default:
   6084                   vassert(0);
   6085             }
   6086          } else {
   6087             switch (size) {
   6088                case 0:
   6089                   op =  U ? Iop_ShrN8x8 : Iop_SarN8x8;
   6090                   add = Iop_Add8x8;
   6091                   break;
   6092                case 1:
   6093                   op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
   6094                   add = Iop_Add16x4;
   6095                   break;
   6096                case 2:
   6097                   op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
   6098                   add = Iop_Add32x2;
   6099                   break;
   6100                case 3:
   6101                   op = U ? Iop_Shr64 : Iop_Sar64;
   6102                   add = Iop_Add64;
   6103                   break;
   6104                default:
   6105                   vassert(0);
   6106             }
   6107          }
   6108          assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
   6109          if (A == 1) {
   6110             if (Q) {
   6111                putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
   6112                              condT);
   6113             } else {
   6114                putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
   6115                                 condT);
   6116             }
   6117             DIP("vsra.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
   6118                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6119          } else {
   6120             if (Q) {
   6121                putQReg(dreg, mkexpr(res), condT);
   6122             } else {
   6123                putDRegI64(dreg, mkexpr(res), condT);
   6124             }
   6125             DIP("vshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
   6126                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6127          }
   6128          return True;
   6129       case 4:
   6130          /* VSRI */
   6131          if (!U)
   6132             return False;
   6133          if (Q) {
   6134             res = newTemp(Ity_V128);
   6135             mask = newTemp(Ity_V128);
   6136          } else {
   6137             res = newTemp(Ity_I64);
   6138             mask = newTemp(Ity_I64);
   6139          }
   6140          switch (size) {
   6141             case 0: op = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; break;
   6142             case 1: op = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; break;
   6143             case 2: op = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; break;
   6144             case 3: op = Q ? Iop_ShrN64x2 : Iop_Shr64; break;
   6145             default: vassert(0);
   6146          }
   6147          if (Q) {
   6148             assign(mask, binop(op, binop(Iop_64HLtoV128,
   6149                                          mkU64(0xFFFFFFFFFFFFFFFFLL),
   6150                                          mkU64(0xFFFFFFFFFFFFFFFFLL)),
   6151                                mkU8(shift_imm)));
   6152             assign(res, binop(Iop_OrV128,
   6153                               binop(Iop_AndV128,
   6154                                     getQReg(dreg),
   6155                                     unop(Iop_NotV128,
   6156                                          mkexpr(mask))),
   6157                               binop(op,
   6158                                     getQReg(mreg),
   6159                                     mkU8(shift_imm))));
   6160             putQReg(dreg, mkexpr(res), condT);
   6161          } else {
   6162             assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
   6163                                mkU8(shift_imm)));
   6164             assign(res, binop(Iop_Or64,
   6165                               binop(Iop_And64,
   6166                                     getDRegI64(dreg),
   6167                                     unop(Iop_Not64,
   6168                                          mkexpr(mask))),
   6169                               binop(op,
   6170                                     getDRegI64(mreg),
   6171                                     mkU8(shift_imm))));
   6172             putDRegI64(dreg, mkexpr(res), condT);
   6173          }
   6174          DIP("vsri.%u %c%u, %c%u, #%u\n",
   6175              8 << size, Q ? 'q' : 'd', dreg,
   6176              Q ? 'q' : 'd', mreg, shift_imm);
   6177          return True;
   6178       case 5:
   6179          if (U) {
   6180             /* VSLI */
   6181             shift_imm = 8 * (1 << size) - shift_imm;
   6182             if (Q) {
   6183                res = newTemp(Ity_V128);
   6184                mask = newTemp(Ity_V128);
   6185             } else {
   6186                res = newTemp(Ity_I64);
   6187                mask = newTemp(Ity_I64);
   6188             }
   6189             switch (size) {
   6190                case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
   6191                case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
   6192                case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
   6193                case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
   6194                default: vassert(0);
   6195             }
   6196             if (Q) {
   6197                assign(mask, binop(op, binop(Iop_64HLtoV128,
   6198                                             mkU64(0xFFFFFFFFFFFFFFFFLL),
   6199                                             mkU64(0xFFFFFFFFFFFFFFFFLL)),
   6200                                   mkU8(shift_imm)));
   6201                assign(res, binop(Iop_OrV128,
   6202                                  binop(Iop_AndV128,
   6203                                        getQReg(dreg),
   6204                                        unop(Iop_NotV128,
   6205                                             mkexpr(mask))),
   6206                                  binop(op,
   6207                                        getQReg(mreg),
   6208                                        mkU8(shift_imm))));
   6209                putQReg(dreg, mkexpr(res), condT);
   6210             } else {
   6211                assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
   6212                                   mkU8(shift_imm)));
   6213                assign(res, binop(Iop_Or64,
   6214                                  binop(Iop_And64,
   6215                                        getDRegI64(dreg),
   6216                                        unop(Iop_Not64,
   6217                                             mkexpr(mask))),
   6218                                  binop(op,
   6219                                        getDRegI64(mreg),
   6220                                        mkU8(shift_imm))));
   6221                putDRegI64(dreg, mkexpr(res), condT);
   6222             }
   6223             DIP("vsli.%u %c%u, %c%u, #%u\n",
   6224                 8 << size, Q ? 'q' : 'd', dreg,
   6225                 Q ? 'q' : 'd', mreg, shift_imm);
   6226             return True;
   6227          } else {
   6228             /* VSHL #imm */
   6229             shift_imm = 8 * (1 << size) - shift_imm;
   6230             if (Q) {
   6231                res = newTemp(Ity_V128);
   6232             } else {
   6233                res = newTemp(Ity_I64);
   6234             }
   6235             switch (size) {
   6236                case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
   6237                case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
   6238                case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
   6239                case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
   6240                default: vassert(0);
   6241             }
   6242             assign(res, binop(op, Q ? getQReg(mreg) : getDRegI64(mreg),
   6243                      mkU8(shift_imm)));
   6244             if (Q) {
   6245                putQReg(dreg, mkexpr(res), condT);
   6246             } else {
   6247                putDRegI64(dreg, mkexpr(res), condT);
   6248             }
   6249             DIP("vshl.i%u %c%u, %c%u, #%u\n",
   6250                 8 << size, Q ? 'q' : 'd', dreg,
   6251                 Q ? 'q' : 'd', mreg, shift_imm);
   6252             return True;
   6253          }
   6254          break;
   6255       case 6:
   6256       case 7:
   6257          /* VQSHL, VQSHLU */
   6258          shift_imm = 8 * (1 << size) - shift_imm;
   6259          if (U) {
   6260             if (A & 1) {
   6261                switch (size) {
   6262                   case 0:
   6263                      op = Q ? Iop_QShlN8x16 : Iop_QShlN8x8;
   6264                      op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   6265                      break;
   6266                   case 1:
   6267                      op = Q ? Iop_QShlN16x8 : Iop_QShlN16x4;
   6268                      op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   6269                      break;
   6270                   case 2:
   6271                      op = Q ? Iop_QShlN32x4 : Iop_QShlN32x2;
   6272                      op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   6273                      break;
   6274                   case 3:
   6275                      op = Q ? Iop_QShlN64x2 : Iop_QShlN64x1;
   6276                      op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
   6277                      break;
   6278                   default:
   6279                      vassert(0);
   6280                }
   6281                DIP("vqshl.u%u %c%u, %c%u, #%u\n",
   6282                    8 << size,
   6283                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6284             } else {
   6285                switch (size) {
   6286                   case 0:
   6287                      op = Q ? Iop_QShlN8Sx16 : Iop_QShlN8Sx8;
   6288                      op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   6289                      break;
   6290                   case 1:
   6291                      op = Q ? Iop_QShlN16Sx8 : Iop_QShlN16Sx4;
   6292                      op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   6293                      break;
   6294                   case 2:
   6295                      op = Q ? Iop_QShlN32Sx4 : Iop_QShlN32Sx2;
   6296                      op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   6297                      break;
   6298                   case 3:
   6299                      op = Q ? Iop_QShlN64Sx2 : Iop_QShlN64Sx1;
   6300                      op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
   6301                      break;
   6302                   default:
   6303                      vassert(0);
   6304                }
   6305                DIP("vqshlu.s%u %c%u, %c%u, #%u\n",
   6306                    8 << size,
   6307                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6308             }
   6309          } else {
   6310             if (!(A & 1))
   6311                return False;
   6312             switch (size) {
   6313                case 0:
   6314                   op = Q ? Iop_QSalN8x16 : Iop_QSalN8x8;
   6315                   op_rev = Q ? Iop_SarN8x16 : Iop_SarN8x8;
   6316                   break;
   6317                case 1:
   6318                   op = Q ? Iop_QSalN16x8 : Iop_QSalN16x4;
   6319                   op_rev = Q ? Iop_SarN16x8 : Iop_SarN16x4;
   6320                   break;
   6321                case 2:
   6322                   op = Q ? Iop_QSalN32x4 : Iop_QSalN32x2;
   6323                   op_rev = Q ? Iop_SarN32x4 : Iop_SarN32x2;
   6324                   break;
   6325                case 3:
   6326                   op = Q ? Iop_QSalN64x2 : Iop_QSalN64x1;
   6327                   op_rev = Q ? Iop_SarN64x2 : Iop_Sar64;
   6328                   break;
   6329                default:
   6330                   vassert(0);
   6331             }
   6332             DIP("vqshl.s%u %c%u, %c%u, #%u\n",
   6333                 8 << size,
   6334                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6335          }
   6336          if (Q) {
   6337             tmp = newTemp(Ity_V128);
   6338             res = newTemp(Ity_V128);
   6339             reg_m = newTemp(Ity_V128);
   6340             assign(reg_m, getQReg(mreg));
   6341          } else {
   6342             tmp = newTemp(Ity_I64);
   6343             res = newTemp(Ity_I64);
   6344             reg_m = newTemp(Ity_I64);
   6345             assign(reg_m, getDRegI64(mreg));
   6346          }
   6347          assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
   6348 #ifndef DISABLE_QC_FLAG
   6349          assign(tmp, binop(op_rev, mkexpr(res), mkU8(shift_imm)));
   6350          setFlag_QC(mkexpr(tmp), mkexpr(reg_m), Q, condT);
   6351 #endif
   6352          if (Q)
   6353             putQReg(dreg, mkexpr(res), condT);
   6354          else
   6355             putDRegI64(dreg, mkexpr(res), condT);
   6356          return True;
   6357       case 8:
   6358          if (!U) {
   6359             if (L == 1)
   6360                return False;
   6361             size++;
   6362             dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   6363             mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   6364             if (mreg & 1)
   6365                return False;
   6366             mreg >>= 1;
   6367             if (!B) {
   6368                /* VSHRN*/
   6369                IROp narOp;
   6370                reg_m = newTemp(Ity_V128);
   6371                assign(reg_m, getQReg(mreg));
   6372                res = newTemp(Ity_I64);
   6373                switch (size) {
   6374                   case 1:
   6375                      op = Iop_ShrN16x8;
   6376                      narOp = Iop_NarrowUn16to8x8;
   6377                      break;
   6378                   case 2:
   6379                      op = Iop_ShrN32x4;
   6380                      narOp = Iop_NarrowUn32to16x4;
   6381                      break;
   6382                   case 3:
   6383                      op = Iop_ShrN64x2;
   6384                      narOp = Iop_NarrowUn64to32x2;
   6385                      break;
   6386                   default:
   6387                      vassert(0);
   6388                }
   6389                assign(res, unop(narOp,
   6390                                 binop(op,
   6391                                       mkexpr(reg_m),
   6392                                       mkU8(shift_imm))));
   6393                putDRegI64(dreg, mkexpr(res), condT);
   6394                DIP("vshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
   6395                    shift_imm);
   6396                return True;
   6397             } else {
   6398                /* VRSHRN   */
   6399                IROp addOp, shOp, narOp;
   6400                IRExpr *imm_val;
   6401                reg_m = newTemp(Ity_V128);
   6402                assign(reg_m, getQReg(mreg));
   6403                res = newTemp(Ity_I64);
   6404                imm = 1L;
   6405                switch (size) {
   6406                   case 0: imm = (imm <<  8) | imm; /* fall through */
   6407                   case 1: imm = (imm << 16) | imm; /* fall through */
   6408                   case 2: imm = (imm << 32) | imm; /* fall through */
   6409                   case 3: break;
   6410                   default: vassert(0);
   6411                }
   6412                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   6413                switch (size) {
   6414                   case 1:
   6415                      addOp = Iop_Add16x8;
   6416                      shOp = Iop_ShrN16x8;
   6417                      narOp = Iop_NarrowUn16to8x8;
   6418                      break;
   6419                   case 2:
   6420                      addOp = Iop_Add32x4;
   6421                      shOp = Iop_ShrN32x4;
   6422                      narOp = Iop_NarrowUn32to16x4;
   6423                      break;
   6424                   case 3:
   6425                      addOp = Iop_Add64x2;
   6426                      shOp = Iop_ShrN64x2;
   6427                      narOp = Iop_NarrowUn64to32x2;
   6428                      break;
   6429                   default:
   6430                      vassert(0);
   6431                }
   6432                assign(res, unop(narOp,
   6433                                 binop(addOp,
   6434                                       binop(shOp,
   6435                                             mkexpr(reg_m),
   6436                                             mkU8(shift_imm)),
   6437                                       binop(Iop_AndV128,
   6438                                             binop(shOp,
   6439                                                   mkexpr(reg_m),
   6440                                                   mkU8(shift_imm - 1)),
   6441                                             imm_val))));
   6442                putDRegI64(dreg, mkexpr(res), condT);
   6443                if (shift_imm == 0) {
   6444                   DIP("vmov%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
   6445                       shift_imm);
   6446                } else {
   6447                   DIP("vrshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
   6448                       shift_imm);
   6449                }
   6450                return True;
   6451             }
   6452          } else {
   6453             /* fall through */
   6454          }
   6455       case 9:
   6456          dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   6457          mreg = ((theInstr >>  1) & 0x10) | (theInstr & 0xF);
   6458          if (mreg & 1)
   6459             return False;
   6460          mreg >>= 1;
   6461          size++;
   6462          if ((theInstr >> 8) & 1) {
   6463             switch (size) {
   6464                case 1:
   6465                   op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   6466                   cvt = U ? Iop_QNarrowUn16Uto8Ux8 : Iop_QNarrowUn16Sto8Sx8;
   6467                   cvt2 = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
   6468                   break;
   6469                case 2:
   6470                   op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   6471                   cvt = U ? Iop_QNarrowUn32Uto16Ux4 : Iop_QNarrowUn32Sto16Sx4;
   6472                   cvt2 = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
   6473                   break;
   6474                case 3:
   6475                   op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
   6476                   cvt = U ? Iop_QNarrowUn64Uto32Ux2 : Iop_QNarrowUn64Sto32Sx2;
   6477                   cvt2 = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
   6478                   break;
   6479                default:
   6480                   vassert(0);
   6481             }
   6482             DIP("vq%sshrn.%c%u d%u, q%u, #%u\n", B ? "r" : "",
   6483                 U ? 'u' : 's', 8 << size, dreg, mreg, shift_imm);
   6484          } else {
   6485             vassert(U);
   6486             switch (size) {
   6487                case 1:
   6488                   op = Iop_SarN16x8;
   6489                   cvt = Iop_QNarrowUn16Sto8Ux8;
   6490                   cvt2 = Iop_Widen8Uto16x8;
   6491                   break;
   6492                case 2:
   6493                   op = Iop_SarN32x4;
   6494                   cvt = Iop_QNarrowUn32Sto16Ux4;
   6495                   cvt2 = Iop_Widen16Uto32x4;
   6496                   break;
   6497                case 3:
   6498                   op = Iop_SarN64x2;
   6499                   cvt = Iop_QNarrowUn64Sto32Ux2;
   6500                   cvt2 = Iop_Widen32Uto64x2;
   6501                   break;
   6502                default:
   6503                   vassert(0);
   6504             }
   6505             DIP("vq%sshrun.s%u d%u, q%u, #%u\n", B ? "r" : "",
   6506                 8 << size, dreg, mreg, shift_imm);
   6507          }
   6508          if (B) {
   6509             if (shift_imm > 0) {
   6510                imm = 1;
   6511                switch (size) {
   6512                   case 1: imm = (imm << 16) | imm; /* fall through */
   6513                   case 2: imm = (imm << 32) | imm; /* fall through */
   6514                   case 3: break;
   6515                   case 0: default: vassert(0);
   6516                }
   6517                switch (size) {
   6518                   case 1: add = Iop_Add16x8; break;
   6519                   case 2: add = Iop_Add32x4; break;
   6520                   case 3: add = Iop_Add64x2; break;
   6521                   case 0: default: vassert(0);
   6522                }
   6523             }
   6524          }
   6525          reg_m = newTemp(Ity_V128);
   6526          res = newTemp(Ity_V128);
   6527          assign(reg_m, getQReg(mreg));
   6528          if (B) {
   6529             /* VQRSHRN, VQRSHRUN */
   6530             assign(res, binop(add,
   6531                               binop(op, mkexpr(reg_m), mkU8(shift_imm)),
   6532                               binop(Iop_AndV128,
   6533                                     binop(op,
   6534                                           mkexpr(reg_m),
   6535                                           mkU8(shift_imm - 1)),
   6536                                     mkU128(imm))));
   6537          } else {
   6538             /* VQSHRN, VQSHRUN */
   6539             assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
   6540          }
   6541 #ifndef DISABLE_QC_FLAG
   6542          setFlag_QC(unop(cvt2, unop(cvt, mkexpr(res))), mkexpr(res),
   6543                     True, condT);
   6544 #endif
   6545          putDRegI64(dreg, unop(cvt, mkexpr(res)), condT);
   6546          return True;
   6547       case 10:
   6548          /* VSHLL
   6549             VMOVL ::= VSHLL #0 */
   6550          if (B)
   6551             return False;
   6552          if (dreg & 1)
   6553             return False;
   6554          dreg >>= 1;
   6555          shift_imm = (8 << size) - shift_imm;
   6556          res = newTemp(Ity_V128);
   6557          switch (size) {
   6558             case 0:
   6559                op = Iop_ShlN16x8;
   6560                cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
   6561                break;
   6562             case 1:
   6563                op = Iop_ShlN32x4;
   6564                cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
   6565                break;
   6566             case 2:
   6567                op = Iop_ShlN64x2;
   6568                cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
   6569                break;
   6570             case 3:
   6571                return False;
   6572             default:
   6573                vassert(0);
   6574          }
   6575          assign(res, binop(op, unop(cvt, getDRegI64(mreg)), mkU8(shift_imm)));
   6576          putQReg(dreg, mkexpr(res), condT);
   6577          if (shift_imm == 0) {
   6578             DIP("vmovl.%c%u q%u, d%u\n", U ? 'u' : 's', 8 << size,
   6579                 dreg, mreg);
   6580          } else {
   6581             DIP("vshll.%c%u q%u, d%u, #%u\n", U ? 'u' : 's', 8 << size,
   6582                 dreg, mreg, shift_imm);
   6583          }
   6584          return True;
   6585       case 14:
   6586       case 15:
   6587          /* VCVT floating-point <-> fixed-point */
   6588          if ((theInstr >> 8) & 1) {
   6589             if (U) {
   6590                op = Q ? Iop_F32ToFixed32Ux4_RZ : Iop_F32ToFixed32Ux2_RZ;
   6591             } else {
   6592                op = Q ? Iop_F32ToFixed32Sx4_RZ : Iop_F32ToFixed32Sx2_RZ;
   6593             }
   6594             DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
   6595                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
   6596                 64 - ((theInstr >> 16) & 0x3f));
   6597          } else {
   6598             if (U) {
   6599                op = Q ? Iop_Fixed32UToF32x4_RN : Iop_Fixed32UToF32x2_RN;
   6600             } else {
   6601                op = Q ? Iop_Fixed32SToF32x4_RN : Iop_Fixed32SToF32x2_RN;
   6602             }
   6603             DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
   6604                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
   6605                 64 - ((theInstr >> 16) & 0x3f));
   6606          }
   6607          if (((theInstr >> 21) & 1) == 0)
   6608             return False;
   6609          if (Q) {
   6610             putQReg(dreg, binop(op, getQReg(mreg),
   6611                      mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
   6612          } else {
   6613             putDRegI64(dreg, binop(op, getDRegI64(mreg),
   6614                        mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
   6615          }
   6616          return True;
   6617       default:
   6618          return False;
   6619 
   6620    }
   6621    return False;
   6622 }
   6623 
   6624 /* A7.4.5 Two registers, miscellaneous */
   6625 static
   6626 Bool dis_neon_data_2reg_misc ( UInt theInstr, IRTemp condT )
   6627 {
   6628    UInt A = (theInstr >> 16) & 3;
   6629    UInt B = (theInstr >> 6) & 0x1f;
   6630    UInt Q = (theInstr >> 6) & 1;
   6631    UInt U = (theInstr >> 24) & 1;
   6632    UInt size = (theInstr >> 18) & 3;
   6633    UInt dreg = get_neon_d_regno(theInstr);
   6634    UInt mreg = get_neon_m_regno(theInstr);
   6635    UInt F = (theInstr >> 10) & 1;
   6636    IRTemp arg_d;
   6637    IRTemp arg_m;
   6638    IRTemp res;
   6639    switch (A) {
   6640       case 0:
   6641          if (Q) {
   6642             arg_m = newTemp(Ity_V128);
   6643             res = newTemp(Ity_V128);
   6644             assign(arg_m, getQReg(mreg));
   6645          } else {
   6646             arg_m = newTemp(Ity_I64);
   6647             res = newTemp(Ity_I64);
   6648             assign(arg_m, getDRegI64(mreg));
   6649          }
   6650          switch (B >> 1) {
   6651             case 0: {
   6652                /* VREV64 */
   6653                IROp op;
   6654                switch (size) {
   6655                   case 0:
   6656                      op = Q ? Iop_Reverse64_8x16 : Iop_Reverse64_8x8;
   6657                      break;
   6658                   case 1:
   6659                      op = Q ? Iop_Reverse64_16x8 : Iop_Reverse64_16x4;
   6660                      break;
   6661                   case 2:
   6662                      op = Q ? Iop_Reverse64_32x4 : Iop_Reverse64_32x2;
   6663                      break;
   6664                   case 3:
   6665                      return False;
   6666                   default:
   6667                      vassert(0);
   6668                }
   6669                assign(res, unop(op, mkexpr(arg_m)));
   6670                DIP("vrev64.%u %c%u, %c%u\n", 8 << size,
   6671                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6672                break;
   6673             }
   6674             case 1: {
   6675                /* VREV32 */
   6676                IROp op;
   6677                switch (size) {
   6678                   case 0:
   6679                      op = Q ? Iop_Reverse32_8x16 : Iop_Reverse32_8x8;
   6680                      break;
   6681                   case 1:
   6682                      op = Q ? Iop_Reverse32_16x8 : Iop_Reverse32_16x4;
   6683                      break;
   6684                   case 2:
   6685                   case 3:
   6686                      return False;
   6687                   default:
   6688                      vassert(0);
   6689                }
   6690                assign(res, unop(op, mkexpr(arg_m)));
   6691                DIP("vrev32.%u %c%u, %c%u\n", 8 << size,
   6692                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6693                break;
   6694             }
   6695             case 2: {
   6696                /* VREV16 */
   6697                IROp op;
   6698                switch (size) {
   6699                   case 0:
   6700                      op = Q ? Iop_Reverse16_8x16 : Iop_Reverse16_8x8;
   6701                      break;
   6702                   case 1:
   6703                   case 2:
   6704                   case 3:
   6705                      return False;
   6706                   default:
   6707                      vassert(0);
   6708                }
   6709                assign(res, unop(op, mkexpr(arg_m)));
   6710                DIP("vrev16.%u %c%u, %c%u\n", 8 << size,
   6711                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6712                break;
   6713             }
   6714             case 3:
   6715                return False;
   6716             case 4:
   6717             case 5: {
   6718                /* VPADDL */
   6719                IROp op;
   6720                U = (theInstr >> 7) & 1;
   6721                if (Q) {
   6722                   switch (size) {
   6723                      case 0: op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; break;
   6724                      case 1: op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; break;
   6725                      case 2: op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; break;
   6726                      case 3: return False;
   6727                      default: vassert(0);
   6728                   }
   6729                } else {
   6730                   switch (size) {
   6731                      case 0: op = U ? Iop_PwAddL8Ux8  : Iop_PwAddL8Sx8;  break;
   6732                      case 1: op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; break;
   6733                      case 2: op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; break;
   6734                      case 3: return False;
   6735                      default: vassert(0);
   6736                   }
   6737                }
   6738                assign(res, unop(op, mkexpr(arg_m)));
   6739                DIP("vpaddl.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
   6740                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6741                break;
   6742             }
   6743             case 6:
   6744             case 7:
   6745                return False;
   6746             case 8: {
   6747                /* VCLS */
   6748                IROp op;
   6749                switch (size) {
   6750                   case 0: op = Q ? Iop_Cls8Sx16 : Iop_Cls8Sx8; break;
   6751                   case 1: op = Q ? Iop_Cls16Sx8 : Iop_Cls16Sx4; break;
   6752                   case 2: op = Q ? Iop_Cls32Sx4 : Iop_Cls32Sx2; break;
   6753                   case 3: return False;
   6754                   default: vassert(0);
   6755                }
   6756                assign(res, unop(op, mkexpr(arg_m)));
   6757                DIP("vcls.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6758                    Q ? 'q' : 'd', mreg);
   6759                break;
   6760             }
   6761             case 9: {
   6762                /* VCLZ */
   6763                IROp op;
   6764                switch (size) {
   6765                   case 0: op = Q ? Iop_Clz8Sx16 : Iop_Clz8Sx8; break;
   6766                   case 1: op = Q ? Iop_Clz16Sx8 : Iop_Clz16Sx4; break;
   6767                   case 2: op = Q ? Iop_Clz32Sx4 : Iop_Clz32Sx2; break;
   6768                   case 3: return False;
   6769                   default: vassert(0);
   6770                }
   6771                assign(res, unop(op, mkexpr(arg_m)));
   6772                DIP("vclz.i%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6773                    Q ? 'q' : 'd', mreg);
   6774                break;
   6775             }
   6776             case 10:
   6777                /* VCNT */
   6778                assign(res, unop(Q ? Iop_Cnt8x16 : Iop_Cnt8x8, mkexpr(arg_m)));
   6779                DIP("vcnt.8 %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
   6780                    mreg);
   6781                break;
   6782             case 11:
   6783                /* VMVN */
   6784                if (Q)
   6785                   assign(res, unop(Iop_NotV128, mkexpr(arg_m)));
   6786                else
   6787                   assign(res, unop(Iop_Not64, mkexpr(arg_m)));
   6788                DIP("vmvn %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
   6789                    mreg);
   6790                break;
   6791             case 12:
   6792             case 13: {
   6793                /* VPADAL */
   6794                IROp op, add_op;
   6795                U = (theInstr >> 7) & 1;
   6796                if (Q) {
   6797                   switch (size) {
   6798                      case 0:
   6799                         op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16;
   6800                         add_op = Iop_Add16x8;
   6801                         break;
   6802                      case 1:
   6803                         op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8;
   6804                         add_op = Iop_Add32x4;
   6805                         break;
   6806                      case 2:
   6807                         op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4;
   6808                         add_op = Iop_Add64x2;
   6809                         break;
   6810                      case 3:
   6811                         return False;
   6812                      default:
   6813                         vassert(0);
   6814                   }
   6815                } else {
   6816                   switch (size) {
   6817                      case 0:
   6818                         op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8;
   6819                         add_op = Iop_Add16x4;
   6820                         break;
   6821                      case 1:
   6822                         op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4;
   6823                         add_op = Iop_Add32x2;
   6824                         break;
   6825                      case 2:
   6826                         op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2;
   6827                         add_op = Iop_Add64;
   6828                         break;
   6829                      case 3:
   6830                         return False;
   6831                      default:
   6832                         vassert(0);
   6833                   }
   6834                }
   6835                if (Q) {
   6836                   arg_d = newTemp(Ity_V128);
   6837                   assign(arg_d, getQReg(dreg));
   6838                } else {
   6839                   arg_d = newTemp(Ity_I64);
   6840                   assign(arg_d, getDRegI64(dreg));
   6841                }
   6842                assign(res, binop(add_op, unop(op, mkexpr(arg_m)),
   6843                                          mkexpr(arg_d)));
   6844                DIP("vpadal.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
   6845                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6846                break;
   6847             }
   6848             case 14: {
   6849                /* VQABS */
   6850                IROp op_sub, op_qsub, op_cmp;
   6851                IRTemp mask, tmp;
   6852                IRExpr *zero1, *zero2;
   6853                IRExpr *neg, *neg2;
   6854                if (Q) {
   6855                   zero1 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6856                   zero2 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6857                   mask = newTemp(Ity_V128);
   6858                   tmp = newTemp(Ity_V128);
   6859                } else {
   6860                   zero1 = mkU64(0);
   6861                   zero2 = mkU64(0);
   6862                   mask = newTemp(Ity_I64);
   6863                   tmp = newTemp(Ity_I64);
   6864                }
   6865                switch (size) {
   6866                   case 0:
   6867                      op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   6868                      op_qsub = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
   6869                      op_cmp = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   6870                      break;
   6871                   case 1:
   6872                      op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   6873                      op_qsub = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
   6874                      op_cmp = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4;
   6875                      break;
   6876                   case 2:
   6877                      op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   6878                      op_qsub = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
   6879                      op_cmp = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2;
   6880                      break;
   6881                   case 3:
   6882                      return False;
   6883                   default:
   6884                      vassert(0);
   6885                }
   6886                assign(mask, binop(op_cmp, mkexpr(arg_m), zero1));
   6887                neg = binop(op_qsub, zero2, mkexpr(arg_m));
   6888                neg2 = binop(op_sub, zero2, mkexpr(arg_m));
   6889                assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
   6890                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6891                                        mkexpr(mask),
   6892                                        mkexpr(arg_m)),
   6893                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6894                                        unop(Q ? Iop_NotV128 : Iop_Not64,
   6895                                             mkexpr(mask)),
   6896                                        neg)));
   6897 #ifndef DISABLE_QC_FLAG
   6898                assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
   6899                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6900                                        mkexpr(mask),
   6901                                        mkexpr(arg_m)),
   6902                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6903                                        unop(Q ? Iop_NotV128 : Iop_Not64,
   6904                                             mkexpr(mask)),
   6905                                        neg2)));
   6906                setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
   6907 #endif
   6908                DIP("vqabs.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6909                    Q ? 'q' : 'd', mreg);
   6910                break;
   6911             }
   6912             case 15: {
   6913                /* VQNEG */
   6914                IROp op, op2;
   6915                IRExpr *zero;
   6916                if (Q) {
   6917                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6918                } else {
   6919                   zero = mkU64(0);
   6920                }
   6921                switch (size) {
   6922                   case 0:
   6923                      op = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
   6924                      op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   6925                      break;
   6926                   case 1:
   6927                      op = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
   6928                      op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   6929                      break;
   6930                   case 2:
   6931                      op = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
   6932                      op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   6933                      break;
   6934                   case 3:
   6935                      return False;
   6936                   default:
   6937                      vassert(0);
   6938                }
   6939                assign(res, binop(op, zero, mkexpr(arg_m)));
   6940 #ifndef DISABLE_QC_FLAG
   6941                setFlag_QC(mkexpr(res), binop(op2, zero, mkexpr(arg_m)),
   6942                           Q, condT);
   6943 #endif
   6944                DIP("vqneg.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6945                    Q ? 'q' : 'd', mreg);
   6946                break;
   6947             }
   6948             default:
   6949                vassert(0);
   6950          }
   6951          if (Q) {
   6952             putQReg(dreg, mkexpr(res), condT);
   6953          } else {
   6954             putDRegI64(dreg, mkexpr(res), condT);
   6955          }
   6956          return True;
   6957       case 1:
   6958          if (Q) {
   6959             arg_m = newTemp(Ity_V128);
   6960             res = newTemp(Ity_V128);
   6961             assign(arg_m, getQReg(mreg));
   6962          } else {
   6963             arg_m = newTemp(Ity_I64);
   6964             res = newTemp(Ity_I64);
   6965             assign(arg_m, getDRegI64(mreg));
   6966          }
   6967          switch ((B >> 1) & 0x7) {
   6968             case 0: {
   6969                /* VCGT #0 */
   6970                IRExpr *zero;
   6971                IROp op;
   6972                if (Q) {
   6973                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6974                } else {
   6975                   zero = mkU64(0);
   6976                }
   6977                if (F) {
   6978                   switch (size) {
   6979                      case 0: case 1: case 3: return False;
   6980                      case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
   6981                      default: vassert(0);
   6982                   }
   6983                } else {
   6984                   switch (size) {
   6985                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   6986                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   6987                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   6988                      case 3: return False;
   6989                      default: vassert(0);
   6990                   }
   6991                }
   6992                assign(res, binop(op, mkexpr(arg_m), zero));
   6993                DIP("vcgt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   6994                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6995                break;
   6996             }
   6997             case 1: {
   6998                /* VCGE #0 */
   6999                IROp op;
   7000                IRExpr *zero;
   7001                if (Q) {
   7002                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7003                } else {
   7004                   zero = mkU64(0);
   7005                }
   7006                if (F) {
   7007                   switch (size) {
   7008                      case 0: case 1: case 3: return False;
   7009                      case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
   7010                      default: vassert(0);
   7011                   }
   7012                   assign(res, binop(op, mkexpr(arg_m), zero));
   7013                } else {
   7014                   switch (size) {
   7015                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   7016                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   7017                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   7018                      case 3: return False;
   7019                      default: vassert(0);
   7020                   }
   7021                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   7022                                    binop(op, zero, mkexpr(arg_m))));
   7023                }
   7024                DIP("vcge.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   7025                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7026                break;
   7027             }
   7028             case 2: {
   7029                /* VCEQ #0 */
   7030                IROp op;
   7031                IRExpr *zero;
   7032                if (F) {
   7033                   if (Q) {
   7034                      zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7035                   } else {
   7036                      zero = mkU64(0);
   7037                   }
   7038                   switch (size) {
   7039                      case 0: case 1: case 3: return False;
   7040                      case 2: op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; break;
   7041                      default: vassert(0);
   7042                   }
   7043                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7044                } else {
   7045                   switch (size) {
   7046                      case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
   7047                      case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
   7048                      case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
   7049                      case 3: return False;
   7050                      default: vassert(0);
   7051                   }
   7052                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   7053                                    unop(op, mkexpr(arg_m))));
   7054                }
   7055                DIP("vceq.%c%u %c%u, %c%u, #0\n", F ? 'f' : 'i', 8 << size,
   7056                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7057                break;
   7058             }
   7059             case 3: {
   7060                /* VCLE #0 */
   7061                IRExpr *zero;
   7062                IROp op;
   7063                if (Q) {
   7064                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7065                } else {
   7066                   zero = mkU64(0);
   7067                }
   7068                if (F) {
   7069                   switch (size) {
   7070                      case 0: case 1: case 3: return False;
   7071                      case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
   7072                      default: vassert(0);
   7073                   }
   7074                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7075                } else {
   7076                   switch (size) {
   7077                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   7078                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   7079                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   7080                      case 3: return False;
   7081                      default: vassert(0);
   7082                   }
   7083                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   7084                                    binop(op, mkexpr(arg_m), zero)));
   7085                }
   7086                DIP("vcle.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   7087                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7088                break;
   7089             }
   7090             case 4: {
   7091                /* VCLT #0 */
   7092                IROp op;
   7093                IRExpr *zero;
   7094                if (Q) {
   7095                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7096                } else {
   7097                   zero = mkU64(0);
   7098                }
   7099                if (F) {
   7100                   switch (size) {
   7101                      case 0: case 1: case 3: return False;
   7102                      case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
   7103                      default: vassert(0);
   7104                   }
   7105                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7106                } else {
   7107                   switch (size) {
   7108                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   7109                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   7110                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   7111                      case 3: return False;
   7112                      default: vassert(0);
   7113                   }
   7114                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7115                }
   7116                DIP("vclt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   7117                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7118                break;
   7119             }
   7120             case 5:
   7121                return False;
   7122             case 6: {
   7123                /* VABS */
   7124                if (!F) {
   7125                   IROp op;
   7126                   switch(size) {
   7127                      case 0: op = Q ? Iop_Abs8x16 : Iop_Abs8x8; break;
   7128                      case 1: op = Q ? Iop_Abs16x8 : Iop_Abs16x4; break;
   7129                      case 2: op = Q ? Iop_Abs32x4 : Iop_Abs32x2; break;
   7130                      case 3: return False;
   7131                      default: vassert(0);
   7132                   }
   7133                   assign(res, unop(op, mkexpr(arg_m)));
   7134                } else {
   7135                   assign(res, unop(Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2,
   7136                                    mkexpr(arg_m)));
   7137                }
   7138                DIP("vabs.%c%u %c%u, %c%u\n",
   7139                    F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
   7140                    Q ? 'q' : 'd', mreg);
   7141                break;
   7142             }
   7143             case 7: {
   7144                /* VNEG */
   7145                IROp op;
   7146                IRExpr *zero;
   7147                if (F) {
   7148                   switch (size) {
   7149                      case 0: case 1: case 3: return False;
   7150                      case 2: op = Q ? Iop_Neg32Fx4 : Iop_Neg32Fx2; break;
   7151                      default: vassert(0);
   7152                   }
   7153                   assign(res, unop(op, mkexpr(arg_m)));
   7154                } else {
   7155                   if (Q) {
   7156                      zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7157                   } else {
   7158                      zero = mkU64(0);
   7159                   }
   7160                   switch (size) {
   7161                      case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
   7162                      case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
   7163                      case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
   7164                      case 3: return False;
   7165                      default: vassert(0);
   7166                   }
   7167                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7168                }
   7169                DIP("vneg.%c%u %c%u, %c%u\n",
   7170                    F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
   7171                    Q ? 'q' : 'd', mreg);
   7172                break;
   7173             }
   7174             default:
   7175                vassert(0);
   7176          }
   7177          if (Q) {
   7178             putQReg(dreg, mkexpr(res), condT);
   7179          } else {
   7180             putDRegI64(dreg, mkexpr(res), condT);
   7181          }
   7182          return True;
   7183       case 2:
   7184          if ((B >> 1) == 0) {
   7185             /* VSWP */
   7186             if (Q) {
   7187                arg_m = newTemp(Ity_V128);
   7188                assign(arg_m, getQReg(mreg));
   7189                putQReg(mreg, getQReg(dreg), condT);
   7190                putQReg(dreg, mkexpr(arg_m), condT);
   7191             } else {
   7192                arg_m = newTemp(Ity_I64);
   7193                assign(arg_m, getDRegI64(mreg));
   7194                putDRegI64(mreg, getDRegI64(dreg), condT);
   7195                putDRegI64(dreg, mkexpr(arg_m), condT);
   7196             }
   7197             DIP("vswp %c%u, %c%u\n",
   7198                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7199             return True;
   7200          } else if ((B >> 1) == 1) {
   7201             /* VTRN */
   7202             IROp op_lo, op_hi;
   7203             IRTemp res1, res2;
   7204             if (Q) {
   7205                arg_m = newTemp(Ity_V128);
   7206                arg_d = newTemp(Ity_V128);
   7207                res1 = newTemp(Ity_V128);
   7208                res2 = newTemp(Ity_V128);
   7209                assign(arg_m, getQReg(mreg));
   7210                assign(arg_d, getQReg(dreg));
   7211             } else {
   7212                res1 = newTemp(Ity_I64);
   7213                res2 = newTemp(Ity_I64);
   7214                arg_m = newTemp(Ity_I64);
   7215                arg_d = newTemp(Ity_I64);
   7216                assign(arg_m, getDRegI64(mreg));
   7217                assign(arg_d, getDRegI64(dreg));
   7218             }
   7219             if (Q) {
   7220                switch (size) {
   7221                   case 0:
   7222                      op_lo = Iop_InterleaveOddLanes8x16;
   7223                      op_hi = Iop_InterleaveEvenLanes8x16;
   7224                      break;
   7225                   case 1:
   7226                      op_lo = Iop_InterleaveOddLanes16x8;
   7227                      op_hi = Iop_InterleaveEvenLanes16x8;
   7228                      break;
   7229                   case 2:
   7230                      op_lo = Iop_InterleaveOddLanes32x4;
   7231                      op_hi = Iop_InterleaveEvenLanes32x4;
   7232                      break;
   7233                   case 3:
   7234                      return False;
   7235                   default:
   7236                      vassert(0);
   7237                }
   7238             } else {
   7239                switch (size) {
   7240                   case 0:
   7241                      op_lo = Iop_InterleaveOddLanes8x8;
   7242                      op_hi = Iop_InterleaveEvenLanes8x8;
   7243                      break;
   7244                   case 1:
   7245                      op_lo = Iop_InterleaveOddLanes16x4;
   7246                      op_hi = Iop_InterleaveEvenLanes16x4;
   7247                      break;
   7248                   case 2:
   7249                      op_lo = Iop_InterleaveLO32x2;
   7250                      op_hi = Iop_InterleaveHI32x2;
   7251                      break;
   7252                   case 3:
   7253                      return False;
   7254                   default:
   7255                      vassert(0);
   7256                }
   7257             }
   7258             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
   7259             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
   7260             if (Q) {
   7261                putQReg(dreg, mkexpr(res1), condT);
   7262                putQReg(mreg, mkexpr(res2), condT);
   7263             } else {
   7264                putDRegI64(dreg, mkexpr(res1), condT);
   7265                putDRegI64(mreg, mkexpr(res2), condT);
   7266             }
   7267             DIP("vtrn.%u %c%u, %c%u\n",
   7268                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7269             return True;
   7270          } else if ((B >> 1) == 2) {
   7271             /* VUZP */
   7272             IROp op_lo, op_hi;
   7273             IRTemp res1, res2;
   7274             if (!Q && size == 2)
   7275                return False;
   7276             if (Q) {
   7277                arg_m = newTemp(Ity_V128);
   7278                arg_d = newTemp(Ity_V128);
   7279                res1 = newTemp(Ity_V128);
   7280                res2 = newTemp(Ity_V128);
   7281                assign(arg_m, getQReg(mreg));
   7282                assign(arg_d, getQReg(dreg));
   7283             } else {
   7284                res1 = newTemp(Ity_I64);
   7285                res2 = newTemp(Ity_I64);
   7286                arg_m = newTemp(Ity_I64);
   7287                arg_d = newTemp(Ity_I64);
   7288                assign(arg_m, getDRegI64(mreg));
   7289                assign(arg_d, getDRegI64(dreg));
   7290             }
   7291             switch (size) {
   7292                case 0:
   7293                   op_lo = Q ? Iop_CatOddLanes8x16 : Iop_CatOddLanes8x8;
   7294                   op_hi = Q ? Iop_CatEvenLanes8x16 : Iop_CatEvenLanes8x8;
   7295                   break;
   7296                case 1:
   7297                   op_lo = Q ? Iop_CatOddLanes16x8 : Iop_CatOddLanes16x4;
   7298                   op_hi = Q ? Iop_CatEvenLanes16x8 : Iop_CatEvenLanes16x4;
   7299                   break;
   7300                case 2:
   7301                   op_lo = Iop_CatOddLanes32x4;
   7302                   op_hi = Iop_CatEvenLanes32x4;
   7303                   break;
   7304                case 3:
   7305                   return False;
   7306                default:
   7307                   vassert(0);
   7308             }
   7309             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
   7310             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
   7311             if (Q) {
   7312                putQReg(dreg, mkexpr(res1), condT);
   7313                putQReg(mreg, mkexpr(res2), condT);
   7314             } else {
   7315                putDRegI64(dreg, mkexpr(res1), condT);
   7316                putDRegI64(mreg, mkexpr(res2), condT);
   7317             }
   7318             DIP("vuzp.%u %c%u, %c%u\n",
   7319                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7320             return True;
   7321          } else if ((B >> 1) == 3) {
   7322             /* VZIP */
   7323             IROp op_lo, op_hi;
   7324             IRTemp res1, res2;
   7325             if (!Q && size == 2)
   7326                return False;
   7327             if (Q) {
   7328                arg_m = newTemp(Ity_V128);
   7329                arg_d = newTemp(Ity_V128);
   7330                res1 = newTemp(Ity_V128);
   7331                res2 = newTemp(Ity_V128);
   7332                assign(arg_m, getQReg(mreg));
   7333                assign(arg_d, getQReg(dreg));
   7334             } else {
   7335                res1 = newTemp(Ity_I64);
   7336                res2 = newTemp(Ity_I64);
   7337                arg_m = newTemp(Ity_I64);
   7338                arg_d = newTemp(Ity_I64);
   7339                assign(arg_m, getDRegI64(mreg));
   7340                assign(arg_d, getDRegI64(dreg));
   7341             }
   7342             switch (size) {
   7343                case 0:
   7344                   op_lo = Q ? Iop_InterleaveHI8x16 : Iop_InterleaveHI8x8;
   7345                   op_hi = Q ? Iop_InterleaveLO8x16 : Iop_InterleaveLO8x8;
   7346                   break;
   7347                case 1:
   7348                   op_lo = Q ? Iop_InterleaveHI16x8 : Iop_InterleaveHI16x4;
   7349                   op_hi = Q ? Iop_InterleaveLO16x8 : Iop_InterleaveLO16x4;
   7350                   break;
   7351                case 2:
   7352                   op_lo = Iop_InterleaveHI32x4;
   7353                   op_hi = Iop_InterleaveLO32x4;
   7354                   break;
   7355                case 3:
   7356                   return False;
   7357                default:
   7358                   vassert(0);
   7359             }
   7360             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
   7361             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
   7362             if (Q) {
   7363                putQReg(dreg, mkexpr(res1), condT);
   7364                putQReg(mreg, mkexpr(res2), condT);
   7365             } else {
   7366                putDRegI64(dreg, mkexpr(res1), condT);
   7367                putDRegI64(mreg, mkexpr(res2), condT);
   7368             }
   7369             DIP("vzip.%u %c%u, %c%u\n",
   7370                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7371             return True;
   7372          } else if (B == 8) {
   7373             /* VMOVN */
   7374             IROp op;
   7375             mreg >>= 1;
   7376             switch (size) {
   7377                case 0: op = Iop_NarrowUn16to8x8;  break;
   7378                case 1: op = Iop_NarrowUn32to16x4; break;
   7379                case 2: op = Iop_NarrowUn64to32x2; break;
   7380                case 3: return False;
   7381                default: vassert(0);
   7382             }
   7383             putDRegI64(dreg, unop(op, getQReg(mreg)), condT);
   7384             DIP("vmovn.i%u d%u, q%u\n", 16 << size, dreg, mreg);
   7385             return True;
   7386          } else if (B == 9 || (B >> 1) == 5) {
   7387             /* VQMOVN, VQMOVUN */
   7388             IROp op, op2;
   7389             IRTemp tmp;
   7390             dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   7391             mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   7392             if (mreg & 1)
   7393                return False;
   7394             mreg >>= 1;
   7395             switch (size) {
   7396                case 0: op2 = Iop_NarrowUn16to8x8;  break;
   7397                case 1: op2 = Iop_NarrowUn32to16x4; break;
   7398                case 2: op2 = Iop_NarrowUn64to32x2; break;
   7399                case 3: return False;
   7400                default: vassert(0);
   7401             }
   7402             switch (B & 3) {
   7403                case 0:
   7404                   vassert(0);
   7405                case 1:
   7406                   switch (size) {
   7407                      case 0: op = Iop_QNarrowUn16Sto8Ux8;  break;
   7408                      case 1: op = Iop_QNarrowUn32Sto16Ux4; break;
   7409                      case 2: op = Iop_QNarrowUn64Sto32Ux2; break;
   7410                      case 3: return False;
   7411                      default: vassert(0);
   7412                   }
   7413                   DIP("vqmovun.s%u d%u, q%u\n", 16 << size, dreg, mreg);
   7414                   break;
   7415                case 2:
   7416                   switch (size) {
   7417                      case 0: op = Iop_QNarrowUn16Sto8Sx8;  break;
   7418                      case 1: op = Iop_QNarrowUn32Sto16Sx4; break;
   7419                      case 2: op = Iop_QNarrowUn64Sto32Sx2; break;
   7420                      case 3: return False;
   7421                      default: vassert(0);
   7422                   }
   7423                   DIP("vqmovn.s%u d%u, q%u\n", 16 << size, dreg, mreg);
   7424                   break;
   7425                case 3:
   7426                   switch (size) {
   7427                      case 0: op = Iop_QNarrowUn16Uto8Ux8;  break;
   7428                      case 1: op = Iop_QNarrowUn32Uto16Ux4; break;
   7429                      case 2: op = Iop_QNarrowUn64Uto32Ux2; break;
   7430                      case 3: return False;
   7431                      default: vassert(0);
   7432                   }
   7433                   DIP("vqmovn.u%u d%u, q%u\n", 16 << size, dreg, mreg);
   7434                   break;
   7435                default:
   7436                   vassert(0);
   7437             }
   7438             res = newTemp(Ity_I64);
   7439             tmp = newTemp(Ity_I64);
   7440             assign(res, unop(op, getQReg(mreg)));
   7441 #ifndef DISABLE_QC_FLAG
   7442             assign(tmp, unop(op2, getQReg(mreg)));
   7443             setFlag_QC(mkexpr(res), mkexpr(tmp), False, condT);
   7444 #endif
   7445             putDRegI64(dreg, mkexpr(res), condT);
   7446             return True;
   7447          } else if (B == 12) {
   7448             /* VSHLL (maximum shift) */
   7449             IROp op, cvt;
   7450             UInt shift_imm;
   7451             if (Q)
   7452                return False;
   7453             if (dreg & 1)
   7454                return False;
   7455             dreg >>= 1;
   7456             shift_imm = 8 << size;
   7457             res = newTemp(Ity_V128);
   7458             switch (size) {
   7459                case 0: op = Iop_ShlN16x8; cvt = Iop_Widen8Uto16x8;  break;
   7460                case 1: op = Iop_ShlN32x4; cvt = Iop_Widen16Uto32x4; break;
   7461                case 2: op = Iop_ShlN64x2; cvt = Iop_Widen32Uto64x2; break;
   7462                case 3: return False;
   7463                default: vassert(0);
   7464             }
   7465             assign(res, binop(op, unop(cvt, getDRegI64(mreg)),
   7466                                   mkU8(shift_imm)));
   7467             putQReg(dreg, mkexpr(res), condT);
   7468             DIP("vshll.i%u q%u, d%u, #%u\n", 8 << size, dreg, mreg, 8 << size);
   7469             return True;
   7470          } else if ((B >> 3) == 3 && (B & 3) == 0) {
   7471             /* VCVT (half<->single) */
   7472             /* Half-precision extensions are needed to run this */
   7473             vassert(0); // ATC
   7474             if (((theInstr >> 18) & 3) != 1)
   7475                return False;
   7476             if ((theInstr >> 8) & 1) {
   7477                if (dreg & 1)
   7478                   return False;
   7479                dreg >>= 1;
   7480                putQReg(dreg, unop(Iop_F16toF32x4, getDRegI64(mreg)),
   7481                      condT);
   7482                DIP("vcvt.f32.f16 q%u, d%u\n", dreg, mreg);
   7483             } else {
   7484                if (mreg & 1)
   7485                   return False;
   7486                mreg >>= 1;
   7487                putDRegI64(dreg, unop(Iop_F32toF16x4, getQReg(mreg)),
   7488                                 condT);
   7489                DIP("vcvt.f16.f32 d%u, q%u\n", dreg, mreg);
   7490             }
   7491             return True;
   7492          } else {
   7493             return False;
   7494          }
   7495          vassert(0);
   7496          return True;
   7497       case 3:
   7498          if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) {
   7499             /* VRECPE */
   7500             IROp op;
   7501             F = (theInstr >> 8) & 1;
   7502             if (size != 2)
   7503                return False;
   7504             if (Q) {
   7505                op = F ? Iop_Recip32Fx4 : Iop_Recip32x4;
   7506                putQReg(dreg, unop(op, getQReg(mreg)), condT);
   7507                DIP("vrecpe.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
   7508             } else {
   7509                op = F ? Iop_Recip32Fx2 : Iop_Recip32x2;
   7510                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
   7511                DIP("vrecpe.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
   7512             }
   7513             return True;
   7514          } else if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) {
   7515             /* VRSQRTE */
   7516             IROp op;
   7517             F = (B >> 2) & 1;
   7518             if (size != 2)
   7519                return False;
   7520             if (F) {
   7521                /* fp */
   7522                op = Q ? Iop_Rsqrte32Fx4 : Iop_Rsqrte32Fx2;
   7523             } else {
   7524                /* unsigned int */
   7525                op = Q ? Iop_Rsqrte32x4 : Iop_Rsqrte32x2;
   7526             }
   7527             if (Q) {
   7528                putQReg(dreg, unop(op, getQReg(mreg)), condT);
   7529                DIP("vrsqrte.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
   7530             } else {
   7531                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
   7532                DIP("vrsqrte.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
   7533             }
   7534             return True;
   7535          } else if ((B >> 3) == 3) {
   7536             /* VCVT (fp<->integer) */
   7537             IROp op;
   7538             if (size != 2)
   7539                return False;
   7540             switch ((B >> 1) & 3) {
   7541                case 0:
   7542                   op = Q ? Iop_I32StoFx4 : Iop_I32StoFx2;
   7543                   DIP("vcvt.f32.s32 %c%u, %c%u\n",
   7544                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7545                   break;
   7546                case 1:
   7547                   op = Q ? Iop_I32UtoFx4 : Iop_I32UtoFx2;
   7548                   DIP("vcvt.f32.u32 %c%u, %c%u\n",
   7549                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7550                   break;
   7551                case 2:
   7552                   op = Q ? Iop_FtoI32Sx4_RZ : Iop_FtoI32Sx2_RZ;
   7553                   DIP("vcvt.s32.f32 %c%u, %c%u\n",
   7554                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7555                   break;
   7556                case 3:
   7557                   op = Q ? Iop_FtoI32Ux4_RZ : Iop_FtoI32Ux2_RZ;
   7558                   DIP("vcvt.u32.f32 %c%u, %c%u\n",
   7559                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7560                   break;
   7561                default:
   7562                   vassert(0);
   7563             }
   7564             if (Q) {
   7565                putQReg(dreg, unop(op, getQReg(mreg)), condT);
   7566             } else {
   7567                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
   7568             }
   7569             return True;
   7570          } else {
   7571             return False;
   7572          }
   7573          vassert(0);
   7574          return True;
   7575       default:
   7576          vassert(0);
   7577    }
   7578    return False;
   7579 }
   7580 
   7581 /* A7.4.6 One register and a modified immediate value */
   7582 static
   7583 void ppNeonImm(UInt imm, UInt cmode, UInt op)
   7584 {
   7585    int i;
   7586    switch (cmode) {
   7587       case 0: case 1: case 8: case 9:
   7588          vex_printf("0x%x", imm);
   7589          break;
   7590       case 2: case 3: case 10: case 11:
   7591          vex_printf("0x%x00", imm);
   7592          break;
   7593       case 4: case 5:
   7594          vex_printf("0x%x0000", imm);
   7595          break;
   7596       case 6: case 7:
   7597          vex_printf("0x%x000000", imm);
   7598          break;
   7599       case 12:
   7600          vex_printf("0x%xff", imm);
   7601          break;
   7602       case 13:
   7603          vex_printf("0x%xffff", imm);
   7604          break;
   7605       case 14:
   7606          if (op) {
   7607             vex_printf("0x");
   7608             for (i = 7; i >= 0; i--)
   7609                vex_printf("%s", (imm & (1 << i)) ? "ff" : "00");
   7610          } else {
   7611             vex_printf("0x%x", imm);
   7612          }
   7613          break;
   7614       case 15:
   7615          vex_printf("0x%x", imm);
   7616          break;
   7617    }
   7618 }
   7619 
   7620 static
   7621 const char *ppNeonImmType(UInt cmode, UInt op)
   7622 {
   7623    switch (cmode) {
   7624       case 0 ... 7:
   7625       case 12: case 13:
   7626          return "i32";
   7627       case 8 ... 11:
   7628          return "i16";
   7629       case 14:
   7630          if (op)
   7631             return "i64";
   7632          else
   7633             return "i8";
   7634       case 15:
   7635          if (op)
   7636             vassert(0);
   7637          else
   7638             return "f32";
   7639       default:
   7640          vassert(0);
   7641    }
   7642 }
   7643 
   7644 static
   7645 void DIPimm(UInt imm, UInt cmode, UInt op,
   7646             const char *instr, UInt Q, UInt dreg)
   7647 {
   7648    if (vex_traceflags & VEX_TRACE_FE) {
   7649       vex_printf("%s.%s %c%u, #", instr,
   7650                  ppNeonImmType(cmode, op), Q ? 'q' : 'd', dreg);
   7651       ppNeonImm(imm, cmode, op);
   7652       vex_printf("\n");
   7653    }
   7654 }
   7655 
   7656 static
   7657 Bool dis_neon_data_1reg_and_imm ( UInt theInstr, IRTemp condT )
   7658 {
   7659    UInt dreg = get_neon_d_regno(theInstr);
   7660    ULong imm_raw = ((theInstr >> 17) & 0x80) | ((theInstr >> 12) & 0x70) |
   7661                   (theInstr & 0xf);
   7662    ULong imm_raw_pp = imm_raw;
   7663    UInt cmode = (theInstr >> 8) & 0xf;
   7664    UInt op_bit = (theInstr >> 5) & 1;
   7665    ULong imm = 0;
   7666    UInt Q = (theInstr >> 6) & 1;
   7667    int i, j;
   7668    UInt tmp;
   7669    IRExpr *imm_val;
   7670    IRExpr *expr;
   7671    IRTemp tmp_var;
   7672    switch(cmode) {
   7673       case 7: case 6:
   7674          imm_raw = imm_raw << 8;
   7675          /* fallthrough */
   7676       case 5: case 4:
   7677          imm_raw = imm_raw << 8;
   7678          /* fallthrough */
   7679       case 3: case 2:
   7680          imm_raw = imm_raw << 8;
   7681          /* fallthrough */
   7682       case 0: case 1:
   7683          imm = (imm_raw << 32) | imm_raw;
   7684          break;
   7685       case 11: case 10:
   7686          imm_raw = imm_raw << 8;
   7687          /* fallthrough */
   7688       case 9: case 8:
   7689          imm_raw = (imm_raw << 16) | imm_raw;
   7690          imm = (imm_raw << 32) | imm_raw;
   7691          break;
   7692       case 13:
   7693          imm_raw = (imm_raw << 8) | 0xff;
   7694          /* fallthrough */
   7695       case 12:
   7696          imm_raw = (imm_raw << 8) | 0xff;
   7697          imm = (imm_raw << 32) | imm_raw;
   7698          break;
   7699       case 14:
   7700          if (! op_bit) {
   7701             for(i = 0; i < 8; i++) {
   7702                imm = (imm << 8) | imm_raw;
   7703             }
   7704          } else {
   7705             for(i = 7; i >= 0; i--) {
   7706                tmp = 0;
   7707                for(j = 0; j < 8; j++) {
   7708                   tmp = (tmp << 1) | ((imm_raw >> i) & 1);
   7709                }
   7710                imm = (imm << 8) | tmp;
   7711             }
   7712          }
   7713          break;
   7714       case 15:
   7715          imm = (imm_raw & 0x80) << 5;
   7716          imm |= ((~imm_raw & 0x40) << 5);
   7717          for(i = 1; i <= 4; i++)
   7718             imm |= (imm_raw & 0x40) << i;
   7719          imm |= (imm_raw & 0x7f);
   7720          imm = imm << 19;
   7721          imm = (imm << 32) | imm;
   7722          break;
   7723       default:
   7724          return False;
   7725    }
   7726    if (Q) {
   7727       imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   7728    } else {
   7729       imm_val = mkU64(imm);
   7730    }
   7731    if (((op_bit == 0) &&
   7732       (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 12) == 12))) ||
   7733       ((op_bit == 1) && (cmode == 14))) {
   7734       /* VMOV (immediate) */
   7735       if (Q) {
   7736          putQReg(dreg, imm_val, condT);
   7737       } else {
   7738          putDRegI64(dreg, imm_val, condT);
   7739       }
   7740       DIPimm(imm_raw_pp, cmode, op_bit, "vmov", Q, dreg);
   7741       return True;
   7742    }
   7743    if ((op_bit == 1) &&
   7744       (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 14) == 12))) {
   7745       /* VMVN (immediate) */
   7746       if (Q) {
   7747          putQReg(dreg, unop(Iop_NotV128, imm_val), condT);
   7748       } else {
   7749          putDRegI64(dreg, unop(Iop_Not64, imm_val), condT);
   7750       }
   7751       DIPimm(imm_raw_pp, cmode, op_bit, "vmvn", Q, dreg);
   7752       return True;
   7753    }
   7754    if (Q) {
   7755       tmp_var = newTemp(Ity_V128);
   7756       assign(tmp_var, getQReg(dreg));
   7757    } else {
   7758       tmp_var = newTemp(Ity_I64);
   7759       assign(tmp_var, getDRegI64(dreg));
   7760    }
   7761    if ((op_bit == 0) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
   7762       /* VORR (immediate) */
   7763       if (Q)
   7764          expr = binop(Iop_OrV128, mkexpr(tmp_var), imm_val);
   7765       else
   7766          expr = binop(Iop_Or64, mkexpr(tmp_var), imm_val);
   7767       DIPimm(imm_raw_pp, cmode, op_bit, "vorr", Q, dreg);
   7768    } else if ((op_bit == 1) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
   7769       /* VBIC (immediate) */
   7770       if (Q)
   7771          expr = binop(Iop_AndV128, mkexpr(tmp_var),
   7772                                    unop(Iop_NotV128, imm_val));
   7773       else
   7774          expr = binop(Iop_And64, mkexpr(tmp_var), unop(Iop_Not64, imm_val));
   7775       DIPimm(imm_raw_pp, cmode, op_bit, "vbic", Q, dreg);
   7776    } else {
   7777       return False;
   7778    }
   7779    if (Q)
   7780       putQReg(dreg, expr, condT);
   7781    else
   7782       putDRegI64(dreg, expr, condT);
   7783    return True;
   7784 }
   7785 
   7786 /* A7.4 Advanced SIMD data-processing instructions */
   7787 static
   7788 Bool dis_neon_data_processing ( UInt theInstr, IRTemp condT )
   7789 {
   7790    UInt A = (theInstr >> 19) & 0x1F;
   7791    UInt B = (theInstr >>  8) & 0xF;
   7792    UInt C = (theInstr >>  4) & 0xF;
   7793    UInt U = (theInstr >> 24) & 0x1;
   7794 
   7795    if (! (A & 0x10)) {
   7796       return dis_neon_data_3same(theInstr, condT);
   7797    }
   7798    if (((A & 0x17) == 0x10) && ((C & 0x9) == 0x1)) {
   7799       return dis_neon_data_1reg_and_imm(theInstr, condT);
   7800    }
   7801    if ((C & 1) == 1) {
   7802       return dis_neon_data_2reg_and_shift(theInstr, condT);
   7803    }
   7804    if (((C & 5) == 0) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
   7805       return dis_neon_data_3diff(theInstr, condT);
   7806    }
   7807    if (((C & 5) == 4) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
   7808       return dis_neon_data_2reg_and_scalar(theInstr, condT);
   7809    }
   7810    if ((A & 0x16) == 0x16) {
   7811       if ((U == 0) && ((C & 1) == 0)) {
   7812          return dis_neon_vext(theInstr, condT);
   7813       }
   7814       if ((U != 1) || ((C & 1) == 1))
   7815          return False;
   7816       if ((B & 8) == 0) {
   7817          return dis_neon_data_2reg_misc(theInstr, condT);
   7818       }
   7819       if ((B & 12) == 8) {
   7820          return dis_neon_vtb(theInstr, condT);
   7821       }
   7822       if ((B == 12) && ((C & 9) == 0)) {
   7823          return dis_neon_vdup(theInstr, condT);
   7824       }
   7825    }
   7826    return False;
   7827 }
   7828 
   7829 
   7830 /*------------------------------------------------------------*/
   7831 /*--- NEON loads and stores                                ---*/
   7832 /*------------------------------------------------------------*/
   7833 
   7834 /* For NEON memory operations, we use the standard scheme to handle
   7835    conditionalisation: generate a jump around the instruction if the
   7836    condition is false.  That's only necessary in Thumb mode, however,
   7837    since in ARM mode NEON instructions are unconditional. */
   7838 
   7839 /* A helper function for what follows.  It assumes we already went
   7840    uncond as per comments at the top of this section. */
   7841 static
   7842 void mk_neon_elem_load_to_one_lane( UInt rD, UInt inc, UInt index,
   7843                                     UInt N, UInt size, IRTemp addr )
   7844 {
   7845    UInt i;
   7846    switch (size) {
   7847       case 0:
   7848          putDRegI64(rD, triop(Iop_SetElem8x8, getDRegI64(rD), mkU8(index),
   7849                     loadLE(Ity_I8, mkexpr(addr))), IRTemp_INVALID);
   7850          break;
   7851       case 1:
   7852          putDRegI64(rD, triop(Iop_SetElem16x4, getDRegI64(rD), mkU8(index),
   7853                     loadLE(Ity_I16, mkexpr(addr))), IRTemp_INVALID);
   7854          break;
   7855       case 2:
   7856          putDRegI64(rD, triop(Iop_SetElem32x2, getDRegI64(rD), mkU8(index),
   7857                     loadLE(Ity_I32, mkexpr(addr))), IRTemp_INVALID);
   7858          break;
   7859       default:
   7860          vassert(0);
   7861    }
   7862    for (i = 1; i <= N; i++) {
   7863       switch (size) {
   7864          case 0:
   7865             putDRegI64(rD + i * inc,
   7866                        triop(Iop_SetElem8x8,
   7867                              getDRegI64(rD + i * inc),
   7868                              mkU8(index),
   7869                              loadLE(Ity_I8, binop(Iop_Add32,
   7870                                                   mkexpr(addr),
   7871                                                   mkU32(i * 1)))),
   7872                        IRTemp_INVALID);
   7873             break;
   7874          case 1:
   7875             putDRegI64(rD + i * inc,
   7876                        triop(Iop_SetElem16x4,
   7877                              getDRegI64(rD + i * inc),
   7878                              mkU8(index),
   7879                              loadLE(Ity_I16, binop(Iop_Add32,
   7880                                                    mkexpr(addr),
   7881                                                    mkU32(i * 2)))),
   7882                        IRTemp_INVALID);
   7883             break;
   7884          case 2:
   7885             putDRegI64(rD + i * inc,
   7886                        triop(Iop_SetElem32x2,
   7887                              getDRegI64(rD + i * inc),
   7888                              mkU8(index),
   7889                              loadLE(Ity_I32, binop(Iop_Add32,
   7890                                                    mkexpr(addr),
   7891                                                    mkU32(i * 4)))),
   7892                        IRTemp_INVALID);
   7893             break;
   7894          default:
   7895             vassert(0);
   7896       }
   7897    }
   7898 }
   7899 
   7900 /* A(nother) helper function for what follows.  It assumes we already
   7901    went uncond as per comments at the top of this section. */
   7902 static
   7903 void mk_neon_elem_store_from_one_lane( UInt rD, UInt inc, UInt index,
   7904                                        UInt N, UInt size, IRTemp addr )
   7905 {
   7906    UInt i;
   7907    switch (size) {
   7908       case 0:
   7909          storeLE(mkexpr(addr),
   7910                  binop(Iop_GetElem8x8, getDRegI64(rD), mkU8(index)));
   7911          break;
   7912       case 1:
   7913          storeLE(mkexpr(addr),
   7914                  binop(Iop_GetElem16x4, getDRegI64(rD), mkU8(index)));
   7915          break;
   7916       case 2:
   7917          storeLE(mkexpr(addr),
   7918                  binop(Iop_GetElem32x2, getDRegI64(rD), mkU8(index)));
   7919          break;
   7920       default:
   7921          vassert(0);
   7922    }
   7923    for (i = 1; i <= N; i++) {
   7924       switch (size) {
   7925          case 0:
   7926             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 1)),
   7927                     binop(Iop_GetElem8x8, getDRegI64(rD + i * inc),
   7928                                           mkU8(index)));
   7929             break;
   7930          case 1:
   7931             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 2)),
   7932                     binop(Iop_GetElem16x4, getDRegI64(rD + i * inc),
   7933                                            mkU8(index)));
   7934             break;
   7935          case 2:
   7936             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 4)),
   7937                     binop(Iop_GetElem32x2, getDRegI64(rD + i * inc),
   7938                                            mkU8(index)));
   7939             break;
   7940          default:
   7941             vassert(0);
   7942       }
   7943    }
   7944 }
   7945 
   7946 /* A7.7 Advanced SIMD element or structure load/store instructions */
   7947 static
   7948 Bool dis_neon_load_or_store ( UInt theInstr,
   7949                               Bool isT, IRTemp condT )
   7950 {
   7951 #  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
   7952    UInt bA = INSN(23,23);
   7953    UInt fB = INSN(11,8);
   7954    UInt bL = INSN(21,21);
   7955    UInt rD = (INSN(22,22) << 4) | INSN(15,12);
   7956    UInt rN = INSN(19,16);
   7957    UInt rM = INSN(3,0);
   7958    UInt N, size, i, j;
   7959    UInt inc;
   7960    UInt regs = 1;
   7961 
   7962    if (isT) {
   7963       vassert(condT != IRTemp_INVALID);
   7964    } else {
   7965       vassert(condT == IRTemp_INVALID);
   7966    }
   7967    /* So now, if condT is not IRTemp_INVALID, we know we're
   7968       dealing with Thumb code. */
   7969 
   7970    if (INSN(20,20) != 0)
   7971       return False;
   7972 
   7973    IRTemp initialRn = newTemp(Ity_I32);
   7974    assign(initialRn, isT ? getIRegT(rN) : getIRegA(rN));
   7975 
   7976    IRTemp initialRm = newTemp(Ity_I32);
   7977    assign(initialRm, isT ? getIRegT(rM) : getIRegA(rM));
   7978 
   7979    /* There are 3 cases:
   7980       (1) VSTn / VLDn (n-element structure from/to one lane)
   7981       (2) VLDn (single element to all lanes)
   7982       (3) VSTn / VLDn (multiple n-element structures)
   7983    */
   7984    if (bA) {
   7985       N = fB & 3;
   7986       if ((fB >> 2) < 3) {
   7987          /* ------------ Case (1) ------------
   7988             VSTn / VLDn (n-element structure from/to one lane) */
   7989 
   7990          size = fB >> 2;
   7991 
   7992          switch (size) {
   7993             case 0: i = INSN(7,5); inc = 1; break;
   7994             case 1: i = INSN(7,6); inc = INSN(5,5) ? 2 : 1; break;
   7995             case 2: i = INSN(7,7); inc = INSN(6,6) ? 2 : 1; break;
   7996             case 3: return False;
   7997             default: vassert(0);
   7998          }
   7999 
   8000          IRTemp addr = newTemp(Ity_I32);
   8001          assign(addr, mkexpr(initialRn));
   8002 
   8003          // go uncond
   8004          if (condT != IRTemp_INVALID)
   8005             mk_skip_over_T32_if_cond_is_false(condT);
   8006          // now uncond
   8007 
   8008          if (bL)
   8009             mk_neon_elem_load_to_one_lane(rD, inc, i, N, size, addr);
   8010          else
   8011             mk_neon_elem_store_from_one_lane(rD, inc, i, N, size, addr);
   8012          DIP("v%s%u.%u {", bL ? "ld" : "st", N + 1, 8 << size);
   8013          for (j = 0; j <= N; j++) {
   8014             if (j)
   8015                DIP(", ");
   8016             DIP("d%u[%u]", rD + j * inc, i);
   8017          }
   8018          DIP("}, [r%u]", rN);
   8019          if (rM != 13 && rM != 15) {
   8020             DIP(", r%u\n", rM);
   8021          } else {
   8022             DIP("%s\n", (rM != 15) ? "!" : "");
   8023          }
   8024       } else {
   8025          /* ------------ Case (2) ------------
   8026             VLDn (single element to all lanes) */
   8027          UInt r;
   8028          if (bL == 0)
   8029             return False;
   8030 
   8031          inc = INSN(5,5) + 1;
   8032          size = INSN(7,6);
   8033 
   8034          /* size == 3 and size == 2 cases differ in alignment constraints */
   8035          if (size == 3 && N == 3 && INSN(4,4) == 1)
   8036             size = 2;
   8037 
   8038          if (size == 0 && N == 0 && INSN(4,4) == 1)
   8039             return False;
   8040          if (N == 2 && INSN(4,4) == 1)
   8041             return False;
   8042          if (size == 3)
   8043             return False;
   8044 
   8045          // go uncond
   8046          if (condT != IRTemp_INVALID)
   8047             mk_skip_over_T32_if_cond_is_false(condT);
   8048          // now uncond
   8049 
   8050          IRTemp addr = newTemp(Ity_I32);
   8051          assign(addr, mkexpr(initialRn));
   8052 
   8053          if (N == 0 && INSN(5,5))
   8054             regs = 2;
   8055 
   8056          for (r = 0; r < regs; r++) {
   8057             switch (size) {
   8058                case 0:
   8059                   putDRegI64(rD + r, unop(Iop_Dup8x8,
   8060                                           loadLE(Ity_I8, mkexpr(addr))),
   8061                              IRTemp_INVALID);
   8062                   break;
   8063                case 1:
   8064                   putDRegI64(rD + r, unop(Iop_Dup16x4,
   8065                                           loadLE(Ity_I16, mkexpr(addr))),
   8066                              IRTemp_INVALID);
   8067                   break;
   8068                case 2:
   8069                   putDRegI64(rD + r, unop(Iop_Dup32x2,
   8070                                           loadLE(Ity_I32, mkexpr(addr))),
   8071                              IRTemp_INVALID);
   8072                   break;
   8073                default:
   8074                   vassert(0);
   8075             }
   8076             for (i = 1; i <= N; i++) {
   8077                switch (size) {
   8078                   case 0:
   8079                      putDRegI64(rD + r + i * inc,
   8080                                 unop(Iop_Dup8x8,
   8081                                      loadLE(Ity_I8, binop(Iop_Add32,
   8082                                                           mkexpr(addr),
   8083                                                           mkU32(i * 1)))),
   8084                                 IRTemp_INVALID);
   8085                      break;
   8086                   case 1:
   8087                      putDRegI64(rD + r + i * inc,
   8088                                 unop(Iop_Dup16x4,
   8089                                      loadLE(Ity_I16, binop(Iop_Add32,
   8090                                                            mkexpr(addr),
   8091                                                            mkU32(i * 2)))),
   8092                                 IRTemp_INVALID);
   8093                      break;
   8094                   case 2:
   8095                      putDRegI64(rD + r + i * inc,
   8096                                 unop(Iop_Dup32x2,
   8097                                      loadLE(Ity_I32, binop(Iop_Add32,
   8098                                                            mkexpr(addr),
   8099                                                            mkU32(i * 4)))),
   8100                                 IRTemp_INVALID);
   8101                      break;
   8102                   default:
   8103                      vassert(0);
   8104                }
   8105             }
   8106          }
   8107          DIP("vld%u.%u {", N + 1, 8 << size);
   8108          for (r = 0; r < regs; r++) {
   8109             for (i = 0; i <= N; i++) {
   8110                if (i || r)
   8111                   DIP(", ");
   8112                DIP("d%u[]", rD + r + i * inc);
   8113             }
   8114          }
   8115          DIP("}, [r%u]", rN);
   8116          if (rM != 13 && rM != 15) {
   8117             DIP(", r%u\n", rM);
   8118          } else {
   8119             DIP("%s\n", (rM != 15) ? "!" : "");
   8120          }
   8121       }
   8122       /* Writeback.  We're uncond here, so no condT-ing. */
   8123       if (rM != 15) {
   8124          if (rM == 13) {
   8125             IRExpr* e = binop(Iop_Add32,
   8126                               mkexpr(initialRn),
   8127                               mkU32((1 << size) * (N + 1)));
   8128             if (isT)
   8129                putIRegT(rN, e, IRTemp_INVALID);
   8130             else
   8131                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8132          } else {
   8133             IRExpr* e = binop(Iop_Add32,
   8134                               mkexpr(initialRn),
   8135                               mkexpr(initialRm));
   8136             if (isT)
   8137                putIRegT(rN, e, IRTemp_INVALID);
   8138             else
   8139                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8140          }
   8141       }
   8142       return True;
   8143    } else {
   8144       /* ------------ Case (3) ------------
   8145          VSTn / VLDn (multiple n-element structures) */
   8146       IRTemp tmp;
   8147       UInt r, elems;
   8148       if (fB == BITS4(0,0,1,0) || fB == BITS4(0,1,1,0)
   8149           || fB == BITS4(0,1,1,1) || fB == BITS4(1,0,1,0)) {
   8150          N = 0;
   8151       } else if (fB == BITS4(0,0,1,1) || fB == BITS4(1,0,0,0)
   8152                  || fB == BITS4(1,0,0,1)) {
   8153          N = 1;
   8154       } else if (fB == BITS4(0,1,0,0) || fB == BITS4(0,1,0,1)) {
   8155          N = 2;
   8156       } else if (fB == BITS4(0,0,0,0) || fB == BITS4(0,0,0,1)) {
   8157          N = 3;
   8158       } else {
   8159          return False;
   8160       }
   8161       inc = (fB & 1) + 1;
   8162       if (N == 1 && fB == BITS4(0,0,1,1)) {
   8163          regs = 2;
   8164       } else if (N == 0) {
   8165          if (fB == BITS4(1,0,1,0)) {
   8166             regs = 2;
   8167          } else if (fB == BITS4(0,1,1,0)) {
   8168             regs = 3;
   8169          } else if (fB == BITS4(0,0,1,0)) {
   8170             regs = 4;
   8171          }
   8172       }
   8173 
   8174       size = INSN(7,6);
   8175       if (N == 0 && size == 3)
   8176          size = 2;
   8177       if (size == 3)
   8178          return False;
   8179 
   8180       elems = 8 / (1 << size);
   8181 
   8182       // go uncond
   8183       if (condT != IRTemp_INVALID)
   8184          mk_skip_over_T32_if_cond_is_false(condT);
   8185       // now uncond
   8186 
   8187       IRTemp addr = newTemp(Ity_I32);
   8188       assign(addr, mkexpr(initialRn));
   8189 
   8190       for (r = 0; r < regs; r++) {
   8191          for (i = 0; i < elems; i++) {
   8192             if (bL)
   8193                mk_neon_elem_load_to_one_lane(rD + r, inc, i, N, size, addr);
   8194             else
   8195                mk_neon_elem_store_from_one_lane(rD + r, inc, i, N, size, addr);
   8196             tmp = newTemp(Ity_I32);
   8197             assign(tmp, binop(Iop_Add32, mkexpr(addr),
   8198                                          mkU32((1 << size) * (N + 1))));
   8199             addr = tmp;
   8200          }
   8201       }
   8202       /* Writeback */
   8203       if (rM != 15) {
   8204          if (rM == 13) {
   8205             IRExpr* e = binop(Iop_Add32,
   8206                               mkexpr(initialRn),
   8207                               mkU32(8 * (N + 1) * regs));
   8208             if (isT)
   8209                putIRegT(rN, e, IRTemp_INVALID);
   8210             else
   8211                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8212          } else {
   8213             IRExpr* e = binop(Iop_Add32,
   8214                               mkexpr(initialRn),
   8215                               mkexpr(initialRm));
   8216             if (isT)
   8217                putIRegT(rN, e, IRTemp_INVALID);
   8218             else
   8219                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8220          }
   8221       }
   8222       DIP("v%s%u.%u {", bL ? "ld" : "st", N + 1, 8 << INSN(7,6));
   8223       if ((inc == 1 && regs * (N + 1) > 1)
   8224           || (inc == 2 && regs > 1 && N > 0)) {
   8225          DIP("d%u-d%u", rD, rD + regs * (N + 1) - 1);
   8226       } else {
   8227          for (r = 0; r < regs; r++) {
   8228             for (i = 0; i <= N; i++) {
   8229                if (i || r)
   8230                   DIP(", ");
   8231                DIP("d%u", rD + r + i * inc);
   8232             }
   8233          }
   8234       }
   8235       DIP("}, [r%u]", rN);
   8236       if (rM != 13 && rM != 15) {
   8237          DIP(", r%u\n", rM);
   8238       } else {
   8239          DIP("%s\n", (rM != 15) ? "!" : "");
   8240       }
   8241       return True;
   8242    }
   8243 #  undef INSN
   8244 }
   8245 
   8246 
   8247 /*------------------------------------------------------------*/
   8248 /*--- NEON, top level control                              ---*/
   8249 /*------------------------------------------------------------*/
   8250 
   8251 /* Both ARM and Thumb */
   8252 
   8253 /* Translate a NEON instruction.    If successful, returns
   8254    True and *dres may or may not be updated.  If failure, returns
   8255    False and doesn't change *dres nor create any IR.
   8256 
   8257    The Thumb and ARM encodings are similar for the 24 bottom bits, but
   8258    the top 8 bits are slightly different.  In both cases, the caller
   8259    must pass the entire 32 bits.  Callers may pass any instruction;
   8260    this ignores non-NEON ones.
   8261 
   8262    Caller must supply an IRTemp 'condT' holding the gating condition,
   8263    or IRTemp_INVALID indicating the insn is always executed.  In ARM
   8264    code, this must always be IRTemp_INVALID because NEON insns are
   8265    unconditional for ARM.
   8266 
   8267    Finally, the caller must indicate whether this occurs in ARM or in
   8268    Thumb code.
   8269 */
   8270 static Bool decode_NEON_instruction (
   8271                /*MOD*/DisResult* dres,
   8272                UInt              insn32,
   8273                IRTemp            condT,
   8274                Bool              isT
   8275             )
   8276 {
   8277 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn32, (_bMax), (_bMin))
   8278 
   8279    /* There are two kinds of instruction to deal with: load/store and
   8280       data processing.  In each case, in ARM mode we merely identify
   8281       the kind, and pass it on to the relevant sub-handler.  In Thumb
   8282       mode we identify the kind, swizzle the bits around to make it
   8283       have the same encoding as in ARM, and hand it on to the
   8284       sub-handler.
   8285    */
   8286 
   8287    /* In ARM mode, NEON instructions can't be conditional. */
   8288    if (!isT)
   8289       vassert(condT == IRTemp_INVALID);
   8290 
   8291    /* Data processing:
   8292       Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx
   8293       ARM:   1111 001U AAAA Axxx xxxx BBBB CCCC xxxx
   8294    */
   8295    if (!isT && INSN(31,25) == BITS7(1,1,1,1,0,0,1)) {
   8296       // ARM, DP
   8297       return dis_neon_data_processing(INSN(31,0), condT);
   8298    }
   8299    if (isT && INSN(31,29) == BITS3(1,1,1)
   8300        && INSN(27,24) == BITS4(1,1,1,1)) {
   8301       // Thumb, DP
   8302       UInt reformatted = INSN(23,0);
   8303       reformatted |= (INSN(28,28) << 24); // U bit
   8304       reformatted |= (BITS7(1,1,1,1,0,0,1) << 25);
   8305       return dis_neon_data_processing(reformatted, condT);
   8306    }
   8307 
   8308    /* Load/store:
   8309       Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx
   8310       ARM:   1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx
   8311    */
   8312    if (!isT && INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) {
   8313       // ARM, memory
   8314       return dis_neon_load_or_store(INSN(31,0), isT, condT);
   8315    }
   8316    if (isT && INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) {
   8317       UInt reformatted = INSN(23,0);
   8318       reformatted |= (BITS8(1,1,1,1,0,1,0,0) << 24);
   8319       return dis_neon_load_or_store(reformatted, isT, condT);
   8320    }
   8321 
   8322    /* Doesn't match. */
   8323    return False;
   8324 
   8325 #  undef INSN
   8326 }
   8327 
   8328 
   8329 /*------------------------------------------------------------*/
   8330 /*--- V6 MEDIA instructions                                ---*/
   8331 /*------------------------------------------------------------*/
   8332 
   8333 /* Both ARM and Thumb */
   8334 
   8335 /* Translate a V6 media instruction.    If successful, returns
   8336    True and *dres may or may not be updated.  If failure, returns
   8337    False and doesn't change *dres nor create any IR.
   8338 
   8339    The Thumb and ARM encodings are completely different.  In Thumb
   8340    mode, the caller must pass the entire 32 bits.  In ARM mode it must
   8341    pass the lower 28 bits.  Apart from that, callers may pass any
   8342    instruction; this function ignores anything it doesn't recognise.
   8343 
   8344    Caller must supply an IRTemp 'condT' holding the gating condition,
   8345    or IRTemp_INVALID indicating the insn is always executed.
   8346 
   8347    Caller must also supply an ARMCondcode 'cond'.  This is only used
   8348    for debug printing, no other purpose.  For ARM, this is simply the
   8349    top 4 bits of the original instruction.  For Thumb, the condition
   8350    is not (really) known until run time, and so ARMCondAL should be
   8351    passed, only so that printing of these instructions does not show
   8352    any condition.
   8353 
   8354    Finally, the caller must indicate whether this occurs in ARM or in
   8355    Thumb code.
   8356 */
   8357 static Bool decode_V6MEDIA_instruction (
   8358                /*MOD*/DisResult* dres,
   8359                UInt              insnv6m,
   8360                IRTemp            condT,
   8361                ARMCondcode       conq,
   8362                Bool              isT
   8363             )
   8364 {
   8365 #  define INSNA(_bMax,_bMin)   SLICE_UInt(insnv6m, (_bMax), (_bMin))
   8366 #  define INSNT0(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \
   8367                                            (_bMax), (_bMin) )
   8368 #  define INSNT1(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 0)  & 0xFFFF), \
   8369                                            (_bMax), (_bMin) )
   8370    HChar dis_buf[128];
   8371    dis_buf[0] = 0;
   8372 
   8373    if (isT) {
   8374       vassert(conq == ARMCondAL);
   8375    } else {
   8376       vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation
   8377       vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
   8378    }
   8379 
   8380    /* ----------- smulbb, smulbt, smultb, smultt ----------- */
   8381    {
   8382      UInt regD = 99, regM = 99, regN = 99, bitM = 0, bitN = 0;
   8383      Bool gate = False;
   8384 
   8385      if (isT) {
   8386         if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1)
   8387             && INSNT1(7,6) == BITS2(0,0)) {
   8388            regD = INSNT1(11,8);
   8389            regM = INSNT1(3,0);
   8390            regN = INSNT0(3,0);
   8391            bitM = INSNT1(4,4);
   8392            bitN = INSNT1(5,5);
   8393            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8394               gate = True;
   8395         }
   8396      } else {
   8397         if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) &&
   8398             BITS4(0,0,0,0)         == INSNA(15,12) &&
   8399             BITS4(1,0,0,0)         == (INSNA(7,4) & BITS4(1,0,0,1)) ) {
   8400            regD = INSNA(19,16);
   8401            regM = INSNA(11,8);
   8402            regN = INSNA(3,0);
   8403            bitM = INSNA(6,6);
   8404            bitN = INSNA(5,5);
   8405            if (regD != 15 && regN != 15 && regM != 15)
   8406               gate = True;
   8407         }
   8408      }
   8409 
   8410      if (gate) {
   8411         IRTemp srcN = newTemp(Ity_I32);
   8412         IRTemp srcM = newTemp(Ity_I32);
   8413         IRTemp res  = newTemp(Ity_I32);
   8414 
   8415         assign( srcN, binop(Iop_Sar32,
   8416                             binop(Iop_Shl32,
   8417                                   isT ? getIRegT(regN) : getIRegA(regN),
   8418                                   mkU8(bitN ? 0 : 16)), mkU8(16)) );
   8419         assign( srcM, binop(Iop_Sar32,
   8420                             binop(Iop_Shl32,
   8421                                   isT ? getIRegT(regM) : getIRegA(regM),
   8422                                   mkU8(bitM ? 0 : 16)), mkU8(16)) );
   8423         assign( res, binop(Iop_Mul32, mkexpr(srcN), mkexpr(srcM)) );
   8424 
   8425         if (isT)
   8426            putIRegT( regD, mkexpr(res), condT );
   8427         else
   8428            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8429 
   8430         DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN ? 't' : 'b', bitM ? 't' : 'b',
   8431              nCC(conq), regD, regN, regM );
   8432         return True;
   8433      }
   8434      /* fall through */
   8435    }
   8436 
   8437    /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */
   8438    /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */
   8439    {
   8440      UInt regD = 99, regN = 99, regM = 99, bitM = 0;
   8441      Bool gate = False;
   8442 
   8443      if (isT) {
   8444         if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1)
   8445             && INSNT1(7,5) == BITS3(0,0,0)) {
   8446           regN = INSNT0(3,0);
   8447           regD = INSNT1(11,8);
   8448           regM = INSNT1(3,0);
   8449           bitM = INSNT1(4,4);
   8450           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8451              gate = True;
   8452         }
   8453      } else {
   8454         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
   8455             INSNA(15,12) == BITS4(0,0,0,0)         &&
   8456             (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) {
   8457            regD = INSNA(19,16);
   8458            regN = INSNA(3,0);
   8459            regM = INSNA(11,8);
   8460            bitM = INSNA(6,6);
   8461            if (regD != 15 && regN != 15 && regM != 15)
   8462               gate = True;
   8463         }
   8464      }
   8465 
   8466      if (gate) {
   8467         IRTemp irt_prod = newTemp(Ity_I64);
   8468 
   8469         assign( irt_prod,
   8470                 binop(Iop_MullS32,
   8471                       isT ? getIRegT(regN) : getIRegA(regN),
   8472                       binop(Iop_Sar32,
   8473                             binop(Iop_Shl32,
   8474                                   isT ? getIRegT(regM) : getIRegA(regM),
   8475                                   mkU8(bitM ? 0 : 16)),
   8476                             mkU8(16))) );
   8477 
   8478         IRExpr* ire_result = binop(Iop_Or32,
   8479                                    binop( Iop_Shl32,
   8480                                           unop(Iop_64HIto32, mkexpr(irt_prod)),
   8481                                           mkU8(16) ),
   8482                                    binop( Iop_Shr32,
   8483                                           unop(Iop_64to32, mkexpr(irt_prod)),
   8484                                           mkU8(16) ) );
   8485 
   8486         if (isT)
   8487            putIRegT( regD, ire_result, condT );
   8488         else
   8489            putIRegA( regD, ire_result, condT, Ijk_Boring );
   8490 
   8491         DIP("smulw%c%s r%u, r%u, r%u\n",
   8492             bitM ? 't' : 'b', nCC(conq),regD,regN,regM);
   8493         return True;
   8494      }
   8495      /* fall through */
   8496    }
   8497 
   8498    /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */
   8499    /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */
   8500    {
   8501      UInt regD = 99, regN = 99, regM = 99, imm5 = 99, shift_type = 99;
   8502      Bool tbform = False;
   8503      Bool gate = False;
   8504 
   8505      if (isT) {
   8506         if (INSNT0(15,4) == 0xEAC
   8507             && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) {
   8508            regN = INSNT0(3,0);
   8509            regD = INSNT1(11,8);
   8510            regM = INSNT1(3,0);
   8511            imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6);
   8512            shift_type = (INSNT1(5,5) << 1) | 0;
   8513            tbform = (INSNT1(5,5) == 0) ? False : True;
   8514            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8515               gate = True;
   8516         }
   8517      } else {
   8518         if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
   8519             INSNA(5,4)   == BITS2(0,1)             &&
   8520             (INSNA(6,6)  == 0 || INSNA(6,6) == 1) ) {
   8521            regD = INSNA(15,12);
   8522            regN = INSNA(19,16);
   8523            regM = INSNA(3,0);
   8524            imm5 = INSNA(11,7);
   8525            shift_type = (INSNA(6,6) << 1) | 0;
   8526            tbform = (INSNA(6,6) == 0) ? False : True;
   8527            if (regD != 15 && regN != 15 && regM != 15)
   8528               gate = True;
   8529         }
   8530      }
   8531 
   8532      if (gate) {
   8533         IRTemp irt_regM       = newTemp(Ity_I32);
   8534         IRTemp irt_regM_shift = newTemp(Ity_I32);
   8535         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   8536         compute_result_and_C_after_shift_by_imm5(
   8537            dis_buf, &irt_regM_shift, NULL, irt_regM, shift_type, imm5, regM );
   8538 
   8539         UInt mask = (tbform == True) ? 0x0000FFFF : 0xFFFF0000;
   8540         IRExpr* ire_result
   8541           = binop( Iop_Or32,
   8542                    binop(Iop_And32, mkexpr(irt_regM_shift), mkU32(mask)),
   8543                    binop(Iop_And32, isT ? getIRegT(regN) : getIRegA(regN),
   8544                                     unop(Iop_Not32, mkU32(mask))) );
   8545 
   8546         if (isT)
   8547            putIRegT( regD, ire_result, condT );
   8548         else
   8549            putIRegA( regD, ire_result, condT, Ijk_Boring );
   8550 
   8551         DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform ? "tb" : "bt",
   8552              nCC(conq), regD, regN, regM, dis_buf );
   8553 
   8554         return True;
   8555      }
   8556      /* fall through */
   8557    }
   8558 
   8559    /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
   8560    {
   8561      UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
   8562      Bool gate = False;
   8563 
   8564      if (isT) {
   8565         if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0)
   8566             && INSNT0(4,4) == 0
   8567             && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
   8568            regD       = INSNT1(11,8);
   8569            regN       = INSNT0(3,0);
   8570            shift_type = (INSNT0(5,5) << 1) | 0;
   8571            imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
   8572            sat_imm    = INSNT1(4,0);
   8573            if (!isBadRegT(regD) && !isBadRegT(regN))
   8574               gate = True;
   8575            if (shift_type == BITS2(1,0) && imm5 == 0)
   8576               gate = False;
   8577         }
   8578      } else {
   8579         if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) &&
   8580             INSNA(5,4)   == BITS2(0,1)) {
   8581            regD       = INSNA(15,12);
   8582            regN       = INSNA(3,0);
   8583            shift_type = (INSNA(6,6) << 1) | 0;
   8584            imm5       = INSNA(11,7);
   8585            sat_imm    = INSNA(20,16);
   8586            if (regD != 15 && regN != 15)
   8587               gate = True;
   8588         }
   8589      }
   8590 
   8591      if (gate) {
   8592         IRTemp irt_regN       = newTemp(Ity_I32);
   8593         IRTemp irt_regN_shift = newTemp(Ity_I32);
   8594         IRTemp irt_sat_Q      = newTemp(Ity_I32);
   8595         IRTemp irt_result     = newTemp(Ity_I32);
   8596 
   8597         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   8598         compute_result_and_C_after_shift_by_imm5(
   8599                 dis_buf, &irt_regN_shift, NULL,
   8600                 irt_regN, shift_type, imm5, regN );
   8601 
   8602         armUnsignedSatQ( &irt_result, &irt_sat_Q, irt_regN_shift, sat_imm );
   8603         or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
   8604 
   8605         if (isT)
   8606            putIRegT( regD, mkexpr(irt_result), condT );
   8607         else
   8608            putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
   8609 
   8610         DIP("usat%s r%u, #0x%04x, %s\n",
   8611             nCC(conq), regD, imm5, dis_buf);
   8612         return True;
   8613      }
   8614      /* fall through */
   8615    }
   8616 
   8617   /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
   8618    {
   8619      UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
   8620      Bool gate = False;
   8621 
   8622      if (isT) {
   8623         if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
   8624             && INSNT0(4,4) == 0
   8625             && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
   8626            regD       = INSNT1(11,8);
   8627            regN       = INSNT0(3,0);
   8628            shift_type = (INSNT0(5,5) << 1) | 0;
   8629            imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
   8630            sat_imm    = INSNT1(4,0) + 1;
   8631            if (!isBadRegT(regD) && !isBadRegT(regN))
   8632               gate = True;
   8633            if (shift_type == BITS2(1,0) && imm5 == 0)
   8634               gate = False;
   8635         }
   8636      } else {
   8637         if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) &&
   8638             INSNA(5,4)   == BITS2(0,1)) {
   8639            regD       = INSNA(15,12);
   8640            regN       = INSNA(3,0);
   8641            shift_type = (INSNA(6,6) << 1) | 0;
   8642            imm5       = INSNA(11,7);
   8643            sat_imm    = INSNA(20,16) + 1;
   8644            if (regD != 15 && regN != 15)
   8645               gate = True;
   8646         }
   8647      }
   8648 
   8649      if (gate) {
   8650         IRTemp irt_regN       = newTemp(Ity_I32);
   8651         IRTemp irt_regN_shift = newTemp(Ity_I32);
   8652         IRTemp irt_sat_Q      = newTemp(Ity_I32);
   8653         IRTemp irt_result     = newTemp(Ity_I32);
   8654 
   8655         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   8656         compute_result_and_C_after_shift_by_imm5(
   8657                 dis_buf, &irt_regN_shift, NULL,
   8658                 irt_regN, shift_type, imm5, regN );
   8659 
   8660         armSignedSatQ( irt_regN_shift, sat_imm, &irt_result, &irt_sat_Q );
   8661         or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
   8662 
   8663         if (isT)
   8664            putIRegT( regD, mkexpr(irt_result), condT );
   8665         else
   8666            putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
   8667 
   8668         DIP( "ssat%s r%u, #0x%04x, %s\n",
   8669              nCC(conq), regD, imm5, dis_buf);
   8670         return True;
   8671     }
   8672     /* fall through */
   8673   }
   8674 
   8675    /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */
   8676    {
   8677      UInt regD = 99, regN = 99, sat_imm = 99;
   8678      Bool gate = False;
   8679 
   8680      if (isT) {
   8681         if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) {
   8682            regN = INSNT0(3,0);
   8683            regD = INSNT1(11,8);
   8684            sat_imm = INSNT1(3,0);
   8685            if (!isBadRegT(regD) && !isBadRegT(regN))
   8686               gate = True;
   8687        }
   8688      } else {
   8689         if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) &&
   8690             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8691             INSNA(7,4)   == BITS4(0,0,1,1)) {
   8692            regD    = INSNA(15,12);
   8693            regN    = INSNA(3,0);
   8694            sat_imm = INSNA(19,16);
   8695            if (regD != 15 && regN != 15)
   8696               gate = True;
   8697         }
   8698      }
   8699 
   8700      if (gate) {
   8701         IRTemp irt_regN    = newTemp(Ity_I32);
   8702         IRTemp irt_regN_lo = newTemp(Ity_I32);
   8703         IRTemp irt_regN_hi = newTemp(Ity_I32);
   8704         IRTemp irt_Q_lo    = newTemp(Ity_I32);
   8705         IRTemp irt_Q_hi    = newTemp(Ity_I32);
   8706         IRTemp irt_res_lo  = newTemp(Ity_I32);
   8707         IRTemp irt_res_hi  = newTemp(Ity_I32);
   8708 
   8709         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   8710         assign( irt_regN_lo, binop( Iop_Sar32,
   8711                                     binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
   8712                                     mkU8(16)) );
   8713         assign( irt_regN_hi, binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)) );
   8714 
   8715         armUnsignedSatQ( &irt_res_lo, &irt_Q_lo, irt_regN_lo, sat_imm );
   8716         or_into_QFLAG32( mkexpr(irt_Q_lo), condT );
   8717 
   8718         armUnsignedSatQ( &irt_res_hi, &irt_Q_hi, irt_regN_hi, sat_imm );
   8719         or_into_QFLAG32( mkexpr(irt_Q_hi), condT );
   8720 
   8721         IRExpr* ire_result = binop( Iop_Or32,
   8722                                     binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)),
   8723                                     mkexpr(irt_res_lo) );
   8724 
   8725         if (isT)
   8726            putIRegT( regD, ire_result, condT );
   8727         else
   8728            putIRegA( regD, ire_result, condT, Ijk_Boring );
   8729 
   8730         DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq), regD, sat_imm, regN );
   8731         return True;
   8732      }
   8733      /* fall through */
   8734    }
   8735 
   8736    /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */
   8737    {
   8738      UInt regD = 99, regN = 99, regM = 99;
   8739      Bool gate = False;
   8740 
   8741      if (isT) {
   8742         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   8743            regN = INSNT0(3,0);
   8744            regD = INSNT1(11,8);
   8745            regM = INSNT1(3,0);
   8746            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8747               gate = True;
   8748         }
   8749      } else {
   8750         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   8751             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8752             INSNA(7,4)   == BITS4(0,0,0,1)) {
   8753            regD = INSNA(15,12);
   8754            regN = INSNA(19,16);
   8755            regM = INSNA(3,0);
   8756            if (regD != 15 && regN != 15 && regM != 15)
   8757               gate = True;
   8758         }
   8759      }
   8760 
   8761      if (gate) {
   8762         IRTemp rNt  = newTemp(Ity_I32);
   8763         IRTemp rMt  = newTemp(Ity_I32);
   8764         IRTemp res  = newTemp(Ity_I32);
   8765         IRTemp reso = newTemp(Ity_I32);
   8766 
   8767         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8768         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8769 
   8770         assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
   8771         if (isT)
   8772            putIRegT( regD, mkexpr(res), condT );
   8773         else
   8774            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8775 
   8776         assign(reso, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
   8777         set_GE_32_10_from_bits_31_15(reso, condT);
   8778 
   8779         DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8780         return True;
   8781      }
   8782      /* fall through */
   8783    }
   8784 
   8785    /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */
   8786    {
   8787      UInt regD = 99, regN = 99, regM = 99;
   8788      Bool gate = False;
   8789 
   8790      if (isT) {
   8791         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   8792            regN = INSNT0(3,0);
   8793            regD = INSNT1(11,8);
   8794            regM = INSNT1(3,0);
   8795            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8796               gate = True;
   8797         }
   8798      } else {
   8799         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   8800             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8801             INSNA(7,4)   == BITS4(0,0,0,1)) {
   8802            regD = INSNA(15,12);
   8803            regN = INSNA(19,16);
   8804            regM = INSNA(3,0);
   8805            if (regD != 15 && regN != 15 && regM != 15)
   8806               gate = True;
   8807         }
   8808      }
   8809 
   8810      if (gate) {
   8811         IRTemp rNt  = newTemp(Ity_I32);
   8812         IRTemp rMt  = newTemp(Ity_I32);
   8813         IRTemp res  = newTemp(Ity_I32);
   8814         IRTemp reso = newTemp(Ity_I32);
   8815 
   8816         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8817         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8818 
   8819         assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
   8820         if (isT)
   8821            putIRegT( regD, mkexpr(res), condT );
   8822         else
   8823            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8824 
   8825         assign(reso, unop(Iop_Not32,
   8826                           binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt))));
   8827         set_GE_32_10_from_bits_31_15(reso, condT);
   8828 
   8829         DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8830         return True;
   8831      }
   8832      /* fall through */
   8833    }
   8834 
   8835    /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */
   8836    {
   8837      UInt regD = 99, regN = 99, regM = 99;
   8838      Bool gate = False;
   8839 
   8840      if (isT) {
   8841         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   8842            regN = INSNT0(3,0);
   8843            regD = INSNT1(11,8);
   8844            regM = INSNT1(3,0);
   8845            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8846               gate = True;
   8847         }
   8848      } else {
   8849         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   8850             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8851             INSNA(7,4)   == BITS4(0,1,1,1)) {
   8852            regD = INSNA(15,12);
   8853            regN = INSNA(19,16);
   8854            regM = INSNA(3,0);
   8855            if (regD != 15 && regN != 15 && regM != 15)
   8856              gate = True;
   8857         }
   8858      }
   8859 
   8860      if (gate) {
   8861         IRTemp rNt  = newTemp(Ity_I32);
   8862         IRTemp rMt  = newTemp(Ity_I32);
   8863         IRTemp res  = newTemp(Ity_I32);
   8864         IRTemp reso = newTemp(Ity_I32);
   8865 
   8866         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8867         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8868 
   8869         assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
   8870         if (isT)
   8871            putIRegT( regD, mkexpr(res), condT );
   8872         else
   8873            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8874 
   8875         assign(reso, unop(Iop_Not32,
   8876                           binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt))));
   8877         set_GE_32_10_from_bits_31_15(reso, condT);
   8878 
   8879         DIP("usub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8880         return True;
   8881      }
   8882      /* fall through */
   8883    }
   8884 
   8885    /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */
   8886    {
   8887      UInt regD = 99, regN = 99, regM = 99;
   8888      Bool gate = False;
   8889 
   8890      if (isT) {
   8891         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   8892            regN = INSNT0(3,0);
   8893            regD = INSNT1(11,8);
   8894            regM = INSNT1(3,0);
   8895            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8896               gate = True;
   8897         }
   8898      } else {
   8899         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   8900             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8901             INSNA(7,4)   == BITS4(0,1,1,1)) {
   8902            regD = INSNA(15,12);
   8903            regN = INSNA(19,16);
   8904            regM = INSNA(3,0);
   8905            if (regD != 15 && regN != 15 && regM != 15)
   8906               gate = True;
   8907         }
   8908      }
   8909 
   8910      if (gate) {
   8911         IRTemp rNt  = newTemp(Ity_I32);
   8912         IRTemp rMt  = newTemp(Ity_I32);
   8913         IRTemp res  = newTemp(Ity_I32);
   8914         IRTemp reso = newTemp(Ity_I32);
   8915 
   8916         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8917         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8918 
   8919         assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
   8920         if (isT)
   8921            putIRegT( regD, mkexpr(res), condT );
   8922         else
   8923            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8924 
   8925         assign(reso, unop(Iop_Not32,
   8926                           binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt))));
   8927         set_GE_32_10_from_bits_31_15(reso, condT);
   8928 
   8929         DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8930         return True;
   8931      }
   8932      /* fall through */
   8933    }
   8934 
   8935    /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */
   8936    {
   8937      UInt regD = 99, regN = 99, regM = 99;
   8938      Bool gate = False;
   8939 
   8940      if (isT) {
   8941         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   8942            regN = INSNT0(3,0);
   8943            regD = INSNT1(11,8);
   8944            regM = INSNT1(3,0);
   8945            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8946               gate = True;
   8947         }
   8948      } else {
   8949         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   8950             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8951             (INSNA(7,4)  == BITS4(1,0,0,1))) {
   8952            regD = INSNA(15,12);
   8953            regN = INSNA(19,16);
   8954            regM = INSNA(3,0);
   8955            if (regD != 15 && regN != 15 && regM != 15)
   8956               gate = True;
   8957         }
   8958      }
   8959 
   8960      if (gate) {
   8961         IRTemp rNt  = newTemp(Ity_I32);
   8962         IRTemp rMt  = newTemp(Ity_I32);
   8963         IRTemp res  = newTemp(Ity_I32);
   8964         IRTemp reso = newTemp(Ity_I32);
   8965 
   8966         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8967         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8968 
   8969         assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
   8970         if (isT)
   8971            putIRegT( regD, mkexpr(res), condT );
   8972         else
   8973            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8974 
   8975         assign(reso, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
   8976         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   8977 
   8978         DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8979         return True;
   8980      }
   8981      /* fall through */
   8982    }
   8983 
   8984    /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
   8985    {
   8986      UInt regD = 99, regN = 99, regM = 99;
   8987      Bool gate = False;
   8988 
   8989      if (isT) {
   8990         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   8991            regN = INSNT0(3,0);
   8992            regD = INSNT1(11,8);
   8993            regM = INSNT1(3,0);
   8994            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8995               gate = True;
   8996         }
   8997      } else {
   8998         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   8999             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9000             (INSNA(7,4)  == BITS4(1,0,0,1))) {
   9001            regD = INSNA(15,12);
   9002            regN = INSNA(19,16);
   9003            regM = INSNA(3,0);
   9004            if (regD != 15 && regN != 15 && regM != 15)
   9005               gate = True;
   9006         }
   9007      }
   9008 
   9009      if (gate) {
   9010         IRTemp rNt  = newTemp(Ity_I32);
   9011         IRTemp rMt  = newTemp(Ity_I32);
   9012         IRTemp res  = newTemp(Ity_I32);
   9013         IRTemp reso = newTemp(Ity_I32);
   9014 
   9015         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9016         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9017 
   9018         assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
   9019         if (isT)
   9020            putIRegT( regD, mkexpr(res), condT );
   9021         else
   9022            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   9023 
   9024         assign(reso, unop(Iop_Not32,
   9025                           binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt))));
   9026         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   9027 
   9028         DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9029         return True;
   9030      }
   9031      /* fall through */
   9032    }
   9033 
   9034    /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9035    {
   9036      UInt regD = 99, regN = 99, regM = 99;
   9037      Bool gate = False;
   9038 
   9039      if (isT) {
   9040         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   9041            regN = INSNT0(3,0);
   9042            regD = INSNT1(11,8);
   9043            regM = INSNT1(3,0);
   9044            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9045               gate = True;
   9046         }
   9047      } else {
   9048         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   9049             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9050             (INSNA(7,4)  == BITS4(1,1,1,1))) {
   9051            regD = INSNA(15,12);
   9052            regN = INSNA(19,16);
   9053            regM = INSNA(3,0);
   9054            if (regD != 15 && regN != 15 && regM != 15)
   9055              gate = True;
   9056         }
   9057      }
   9058 
   9059      if (gate) {
   9060         IRTemp rNt  = newTemp(Ity_I32);
   9061         IRTemp rMt  = newTemp(Ity_I32);
   9062         IRTemp res  = newTemp(Ity_I32);
   9063         IRTemp reso = newTemp(Ity_I32);
   9064 
   9065         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9066         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9067 
   9068         assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
   9069         if (isT)
   9070            putIRegT( regD, mkexpr(res), condT );
   9071         else
   9072            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   9073 
   9074         assign(reso, unop(Iop_Not32,
   9075                           binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt))));
   9076         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   9077 
   9078         DIP("usub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9079         return True;
   9080      }
   9081      /* fall through */
   9082    }
   9083 
   9084    /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9085    {
   9086      UInt regD = 99, regN = 99, regM = 99;
   9087      Bool gate = False;
   9088 
   9089      if (isT) {
   9090         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   9091            regN = INSNT0(3,0);
   9092            regD = INSNT1(11,8);
   9093            regM = INSNT1(3,0);
   9094            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9095               gate = True;
   9096         }
   9097      } else {
   9098         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   9099             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9100             INSNA(7,4)   == BITS4(1,1,1,1)) {
   9101            regD = INSNA(15,12);
   9102            regN = INSNA(19,16);
   9103            regM = INSNA(3,0);
   9104            if (regD != 15 && regN != 15 && regM != 15)
   9105               gate = True;
   9106         }
   9107      }
   9108 
   9109      if (gate) {
   9110         IRTemp rNt  = newTemp(Ity_I32);
   9111         IRTemp rMt  = newTemp(Ity_I32);
   9112         IRTemp res  = newTemp(Ity_I32);
   9113         IRTemp reso = newTemp(Ity_I32);
   9114 
   9115         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9116         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9117 
   9118         assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
   9119         if (isT)
   9120            putIRegT( regD, mkexpr(res), condT );
   9121         else
   9122            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   9123 
   9124         assign(reso, unop(Iop_Not32,
   9125                           binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt))));
   9126         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   9127 
   9128         DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9129         return True;
   9130      }
   9131      /* fall through */
   9132    }
   9133 
   9134    /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9135    {
   9136      UInt regD = 99, regN = 99, regM = 99;
   9137      Bool gate = False;
   9138 
   9139      if (isT) {
   9140         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9141            regN = INSNT0(3,0);
   9142            regD = INSNT1(11,8);
   9143            regM = INSNT1(3,0);
   9144            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9145               gate = True;
   9146         }
   9147      } else {
   9148         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9149             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9150             INSNA(7,4)   == BITS4(1,0,0,1)) {
   9151            regD = INSNA(15,12);
   9152            regN = INSNA(19,16);
   9153            regM = INSNA(3,0);
   9154            if (regD != 15 && regN != 15 && regM != 15)
   9155               gate = True;
   9156         }
   9157      }
   9158 
   9159      if (gate) {
   9160         IRTemp rNt   = newTemp(Ity_I32);
   9161         IRTemp rMt   = newTemp(Ity_I32);
   9162         IRTemp res_q = newTemp(Ity_I32);
   9163 
   9164         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9165         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9166 
   9167         assign(res_q, binop(Iop_QAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
   9168         if (isT)
   9169            putIRegT( regD, mkexpr(res_q), condT );
   9170         else
   9171            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9172 
   9173         DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9174         return True;
   9175      }
   9176      /* fall through */
   9177    }
   9178 
   9179    /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9180    {
   9181      UInt regD = 99, regN = 99, regM = 99;
   9182      Bool gate = False;
   9183 
   9184      if (isT) {
   9185         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9186            regN = INSNT0(3,0);
   9187            regD = INSNT1(11,8);
   9188            regM = INSNT1(3,0);
   9189            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9190               gate = True;
   9191         }
   9192      } else {
   9193         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9194             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9195             INSNA(7,4)   == BITS4(1,1,1,1)) {
   9196            regD = INSNA(15,12);
   9197            regN = INSNA(19,16);
   9198            regM = INSNA(3,0);
   9199            if (regD != 15 && regN != 15 && regM != 15)
   9200               gate = True;
   9201         }
   9202      }
   9203 
   9204      if (gate) {
   9205         IRTemp rNt   = newTemp(Ity_I32);
   9206         IRTemp rMt   = newTemp(Ity_I32);
   9207         IRTemp res_q = newTemp(Ity_I32);
   9208 
   9209         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9210         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9211 
   9212         assign(res_q, binop(Iop_QSub8Sx4, mkexpr(rNt), mkexpr(rMt)));
   9213         if (isT)
   9214            putIRegT( regD, mkexpr(res_q), condT );
   9215         else
   9216            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9217 
   9218         DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9219         return True;
   9220      }
   9221      /* fall through */
   9222    }
   9223 
   9224    /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9225    {
   9226      UInt regD = 99, regN = 99, regM = 99;
   9227      Bool gate = False;
   9228 
   9229      if (isT) {
   9230         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
   9231            regN = INSNT0(3,0);
   9232            regD = INSNT1(11,8);
   9233            regM = INSNT1(3,0);
   9234            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9235               gate = True;
   9236         }
   9237      } else {
   9238         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
   9239             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9240             (INSNA(7,4)  == BITS4(1,0,0,1))) {
   9241            regD = INSNA(15,12);
   9242            regN = INSNA(19,16);
   9243            regM = INSNA(3,0);
   9244            if (regD != 15 && regN != 15 && regM != 15)
   9245               gate = True;
   9246         }
   9247      }
   9248 
   9249      if (gate) {
   9250         IRTemp rNt   = newTemp(Ity_I32);
   9251         IRTemp rMt   = newTemp(Ity_I32);
   9252         IRTemp res_q = newTemp(Ity_I32);
   9253 
   9254         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9255         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9256 
   9257         assign(res_q, binop(Iop_QAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
   9258         if (isT)
   9259            putIRegT( regD, mkexpr(res_q), condT );
   9260         else
   9261            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9262 
   9263         DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9264         return True;
   9265      }
   9266      /* fall through */
   9267    }
   9268 
   9269    /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9270    {
   9271      UInt regD = 99, regN = 99, regM = 99;
   9272      Bool gate = False;
   9273 
   9274      if (isT) {
   9275         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
   9276            regN = INSNT0(3,0);
   9277            regD = INSNT1(11,8);
   9278            regM = INSNT1(3,0);
   9279            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9280               gate = True;
   9281         }
   9282      } else {
   9283         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
   9284             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9285             (INSNA(7,4)  == BITS4(1,1,1,1))) {
   9286            regD = INSNA(15,12);
   9287            regN = INSNA(19,16);
   9288            regM = INSNA(3,0);
   9289            if (regD != 15 && regN != 15 && regM != 15)
   9290              gate = True;
   9291         }
   9292      }
   9293 
   9294      if (gate) {
   9295         IRTemp rNt   = newTemp(Ity_I32);
   9296         IRTemp rMt   = newTemp(Ity_I32);
   9297         IRTemp res_q = newTemp(Ity_I32);
   9298 
   9299         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9300         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9301 
   9302         assign(res_q, binop(Iop_QSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
   9303         if (isT)
   9304            putIRegT( regD, mkexpr(res_q), condT );
   9305         else
   9306            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9307 
   9308         DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9309         return True;
   9310      }
   9311      /* fall through */
   9312    }
   9313 
   9314    /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9315    {
   9316      UInt regD = 99, regN = 99, regM = 99;
   9317      Bool gate = False;
   9318 
   9319      if (isT) {
   9320         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
   9321            regN = INSNT0(3,0);
   9322            regD = INSNT1(11,8);
   9323            regM = INSNT1(3,0);
   9324            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9325               gate = True;
   9326         }
   9327      } else {
   9328         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
   9329             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9330             INSNA(7,4)   == BITS4(1,0,0,1)) {
   9331            regD = INSNA(15,12);
   9332            regN = INSNA(19,16);
   9333            regM = INSNA(3,0);
   9334            if (regD != 15 && regN != 15 && regM != 15)
   9335               gate = True;
   9336         }
   9337      }
   9338 
   9339      if (gate) {
   9340         IRTemp rNt   = newTemp(Ity_I32);
   9341         IRTemp rMt   = newTemp(Ity_I32);
   9342         IRTemp res_q = newTemp(Ity_I32);
   9343 
   9344         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9345         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9346 
   9347         assign(res_q, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
   9348         if (isT)
   9349            putIRegT( regD, mkexpr(res_q), condT );
   9350         else
   9351            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9352 
   9353         DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9354         return True;
   9355      }
   9356      /* fall through */
   9357    }
   9358 
   9359    /* ----------------- uhadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
   9360    {
   9361      UInt regD = 99, regN = 99, regM = 99;
   9362      Bool gate = False;
   9363 
   9364      if (isT) {
   9365         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
   9366            regN = INSNT0(3,0);
   9367            regD = INSNT1(11,8);
   9368            regM = INSNT1(3,0);
   9369            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9370               gate = True;
   9371         }
   9372      } else {
   9373         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
   9374             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9375             INSNA(7,4)   == BITS4(0,0,0,1)) {
   9376            regD = INSNA(15,12);
   9377            regN = INSNA(19,16);
   9378            regM = INSNA(3,0);
   9379            if (regD != 15 && regN != 15 && regM != 15)
   9380               gate = True;
   9381         }
   9382      }
   9383 
   9384      if (gate) {
   9385         IRTemp rNt   = newTemp(Ity_I32);
   9386         IRTemp rMt   = newTemp(Ity_I32);
   9387         IRTemp res_q = newTemp(Ity_I32);
   9388 
   9389         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9390         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9391 
   9392         assign(res_q, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
   9393         if (isT)
   9394            putIRegT( regD, mkexpr(res_q), condT );
   9395         else
   9396            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9397 
   9398         DIP("uhadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9399         return True;
   9400      }
   9401      /* fall through */
   9402    }
   9403 
   9404    /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9405    {
   9406      UInt regD = 99, regN = 99, regM = 99;
   9407      Bool gate = False;
   9408 
   9409      if (isT) {
   9410         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
   9411            regN = INSNT0(3,0);
   9412            regD = INSNT1(11,8);
   9413            regM = INSNT1(3,0);
   9414            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9415               gate = True;
   9416         }
   9417      } else {
   9418         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
   9419             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9420             INSNA(7,4)   == BITS4(1,0,0,1)) {
   9421            regD = INSNA(15,12);
   9422            regN = INSNA(19,16);
   9423            regM = INSNA(3,0);
   9424            if (regD != 15 && regN != 15 && regM != 15)
   9425               gate = True;
   9426         }
   9427      }
   9428 
   9429      if (gate) {
   9430         IRTemp rNt   = newTemp(Ity_I32);
   9431         IRTemp rMt   = newTemp(Ity_I32);
   9432         IRTemp res_q = newTemp(Ity_I32);
   9433 
   9434         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9435         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9436 
   9437         assign(res_q, binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
   9438         if (isT)
   9439            putIRegT( regD, mkexpr(res_q), condT );
   9440         else
   9441            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9442 
   9443         DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9444         return True;
   9445      }
   9446      /* fall through */
   9447    }
   9448 
   9449    /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
   9450    {
   9451      UInt regD = 99, regN = 99, regM = 99;
   9452      Bool gate = False;
   9453 
   9454      if (isT) {
   9455         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9456            regN = INSNT0(3,0);
   9457            regD = INSNT1(11,8);
   9458            regM = INSNT1(3,0);
   9459            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9460               gate = True;
   9461         }
   9462      } else {
   9463         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9464             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9465             INSNA(7,4)   == BITS4(0,0,0,1)) {
   9466            regD = INSNA(15,12);
   9467            regN = INSNA(19,16);
   9468            regM = INSNA(3,0);
   9469            if (regD != 15 && regN != 15 && regM != 15)
   9470               gate = True;
   9471         }
   9472      }
   9473 
   9474      if (gate) {
   9475         IRTemp rNt   = newTemp(Ity_I32);
   9476         IRTemp rMt   = newTemp(Ity_I32);
   9477         IRTemp res_q = newTemp(Ity_I32);
   9478 
   9479         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9480         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9481 
   9482         assign(res_q, binop(Iop_QAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
   9483         if (isT)
   9484            putIRegT( regD, mkexpr(res_q), condT );
   9485         else
   9486            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9487 
   9488         DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9489         return True;
   9490      }
   9491      /* fall through */
   9492    }
   9493 
   9494    /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
   9495    {
   9496      UInt regD = 99, regN = 99, regM = 99;
   9497      Bool gate = False;
   9498 
   9499       if (isT) {
   9500         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9501            regN = INSNT0(3,0);
   9502            regD = INSNT1(11,8);
   9503            regM = INSNT1(3,0);
   9504            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9505               gate = True;
   9506         }
   9507      } else {
   9508         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9509             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9510             INSNA(7,4)   == BITS4(0,1,1,1)) {
   9511            regD = INSNA(15,12);
   9512            regN = INSNA(19,16);
   9513            regM = INSNA(3,0);
   9514            if (regD != 15 && regN != 15 && regM != 15)
   9515              gate = True;
   9516         }
   9517      }
   9518 
   9519      if (gate) {
   9520         IRTemp rNt   = newTemp(Ity_I32);
   9521         IRTemp rMt   = newTemp(Ity_I32);
   9522         IRTemp res_q = newTemp(Ity_I32);
   9523 
   9524         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9525         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9526 
   9527         assign(res_q, binop(Iop_QSub16Sx2, mkexpr(rNt), mkexpr(rMt)));
   9528         if (isT)
   9529            putIRegT( regD, mkexpr(res_q), condT );
   9530         else
   9531            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9532 
   9533         DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9534         return True;
   9535      }
   9536      /* fall through */
   9537    }
   9538 
   9539    /////////////////////////////////////////////////////////////////
   9540    /////////////////////////////////////////////////////////////////
   9541    /////////////////////////////////////////////////////////////////
   9542    /////////////////////////////////////////////////////////////////
   9543    /////////////////////////////////////////////////////////////////
   9544 
   9545    /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
   9546    /* note: the hardware seems to construct the result differently
   9547       from wot the manual says. */
   9548    {
   9549      UInt regD = 99, regN = 99, regM = 99;
   9550      Bool gate = False;
   9551 
   9552      if (isT) {
   9553         if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9554            regN = INSNT0(3,0);
   9555            regD = INSNT1(11,8);
   9556            regM = INSNT1(3,0);
   9557            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9558               gate = True;
   9559         }
   9560      } else {
   9561         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9562             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9563             INSNA(7,4)   == BITS4(0,1,0,1)) {
   9564            regD = INSNA(15,12);
   9565            regN = INSNA(19,16);
   9566            regM = INSNA(3,0);
   9567            if (regD != 15 && regN != 15 && regM != 15)
   9568               gate = True;
   9569         }
   9570      }
   9571 
   9572      if (gate) {
   9573         IRTemp irt_regN     = newTemp(Ity_I32);
   9574         IRTemp irt_regM     = newTemp(Ity_I32);
   9575         IRTemp irt_sum      = newTemp(Ity_I32);
   9576         IRTemp irt_diff     = newTemp(Ity_I32);
   9577         IRTemp irt_sum_res  = newTemp(Ity_I32);
   9578         IRTemp irt_diff_res = newTemp(Ity_I32);
   9579 
   9580         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9581         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   9582 
   9583         assign( irt_diff,
   9584                 binop( Iop_Sub32,
   9585                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9586                        binop( Iop_Sar32,
   9587                               binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
   9588                               mkU8(16) ) ) );
   9589         armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL);
   9590 
   9591         assign( irt_sum,
   9592                 binop( Iop_Add32,
   9593                        binop( Iop_Sar32,
   9594                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9595                               mkU8(16) ),
   9596                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) );
   9597         armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL );
   9598 
   9599         IRExpr* ire_result = binop( Iop_Or32,
   9600                                     binop( Iop_Shl32, mkexpr(irt_diff_res),
   9601                                            mkU8(16) ),
   9602                                     binop( Iop_And32, mkexpr(irt_sum_res),
   9603                                            mkU32(0xFFFF)) );
   9604 
   9605         if (isT)
   9606            putIRegT( regD, ire_result, condT );
   9607         else
   9608            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9609 
   9610         DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   9611         return True;
   9612      }
   9613      /* fall through */
   9614    }
   9615 
   9616    /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
   9617    {
   9618      UInt regD = 99, regN = 99, regM = 99;
   9619      Bool gate = False;
   9620 
   9621      if (isT) {
   9622         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9623            regN = INSNT0(3,0);
   9624            regD = INSNT1(11,8);
   9625            regM = INSNT1(3,0);
   9626            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9627               gate = True;
   9628         }
   9629      } else {
   9630         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9631             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9632             INSNA(7,4)   == BITS4(0,0,1,1)) {
   9633            regD = INSNA(15,12);
   9634            regN = INSNA(19,16);
   9635            regM = INSNA(3,0);
   9636            if (regD != 15 && regN != 15 && regM != 15)
   9637               gate = True;
   9638         }
   9639      }
   9640 
   9641      if (gate) {
   9642         IRTemp irt_regN     = newTemp(Ity_I32);
   9643         IRTemp irt_regM     = newTemp(Ity_I32);
   9644         IRTemp irt_sum      = newTemp(Ity_I32);
   9645         IRTemp irt_diff     = newTemp(Ity_I32);
   9646         IRTemp irt_res_sum  = newTemp(Ity_I32);
   9647         IRTemp irt_res_diff = newTemp(Ity_I32);
   9648 
   9649         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9650         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   9651 
   9652         assign( irt_diff,
   9653                 binop( Iop_Sub32,
   9654                        binop( Iop_Sar32,
   9655                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9656                               mkU8(16) ),
   9657                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
   9658         armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL );
   9659 
   9660         assign( irt_sum,
   9661                 binop( Iop_Add32,
   9662                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9663                        binop( Iop_Sar32,
   9664                               binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
   9665                               mkU8(16) ) ) );
   9666         armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL );
   9667 
   9668         IRExpr* ire_result
   9669           = binop( Iop_Or32,
   9670                    binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ),
   9671                    binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) );
   9672 
   9673         if (isT)
   9674            putIRegT( regD, ire_result, condT );
   9675         else
   9676            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9677 
   9678         DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   9679         return True;
   9680      }
   9681      /* fall through */
   9682    }
   9683 
   9684    /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
   9685    {
   9686      UInt regD = 99, regN = 99, regM = 99;
   9687      Bool gate = False;
   9688 
   9689      if (isT) {
   9690         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   9691            regN = INSNT0(3,0);
   9692            regD = INSNT1(11,8);
   9693            regM = INSNT1(3,0);
   9694            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9695               gate = True;
   9696         }
   9697      } else {
   9698         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   9699             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9700             INSNA(7,4)   == BITS4(0,0,1,1)) {
   9701            regD = INSNA(15,12);
   9702            regN = INSNA(19,16);
   9703            regM = INSNA(3,0);
   9704            if (regD != 15 && regN != 15 && regM != 15)
   9705               gate = True;
   9706         }
   9707      }
   9708 
   9709      if (gate) {
   9710         IRTemp irt_regN = newTemp(Ity_I32);
   9711         IRTemp irt_regM = newTemp(Ity_I32);
   9712         IRTemp irt_sum  = newTemp(Ity_I32);
   9713         IRTemp irt_diff = newTemp(Ity_I32);
   9714 
   9715         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9716         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   9717 
   9718         assign( irt_diff,
   9719                 binop( Iop_Sub32,
   9720                        binop( Iop_Sar32,
   9721                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9722                               mkU8(16) ),
   9723                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
   9724 
   9725         assign( irt_sum,
   9726                 binop( Iop_Add32,
   9727                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9728                        binop( Iop_Sar32,
   9729                               binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
   9730                               mkU8(16) ) ) );
   9731 
   9732         IRExpr* ire_result
   9733           = binop( Iop_Or32,
   9734                    binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ),
   9735                    binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) );
   9736 
   9737         IRTemp ge10 = newTemp(Ity_I32);
   9738         assign(ge10, unop(Iop_Not32, mkexpr(irt_diff)));
   9739         put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
   9740         put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
   9741 
   9742         IRTemp ge32 = newTemp(Ity_I32);
   9743         assign(ge32, unop(Iop_Not32, mkexpr(irt_sum)));
   9744         put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
   9745         put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
   9746 
   9747         if (isT)
   9748            putIRegT( regD, ire_result, condT );
   9749         else
   9750            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9751 
   9752         DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   9753         return True;
   9754      }
   9755      /* fall through */
   9756    }
   9757 
   9758    /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
   9759    /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */
   9760    {
   9761      UInt regD = 99, regN = 99, regM = 99, bitM = 99;
   9762      Bool gate = False, isAD = False;
   9763 
   9764      if (isT) {
   9765         if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
   9766             && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
   9767            regN = INSNT0(3,0);
   9768            regD = INSNT1(11,8);
   9769            regM = INSNT1(3,0);
   9770            bitM = INSNT1(4,4);
   9771            isAD = INSNT0(15,4) == 0xFB2;
   9772            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9773               gate = True;
   9774         }
   9775      } else {
   9776         if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
   9777             INSNA(15,12) == BITS4(1,1,1,1)         &&
   9778             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) {
   9779            regD = INSNA(19,16);
   9780            regN = INSNA(3,0);
   9781            regM = INSNA(11,8);
   9782            bitM = INSNA(5,5);
   9783            isAD = INSNA(6,6) == 0;
   9784            if (regD != 15 && regN != 15 && regM != 15)
   9785               gate = True;
   9786         }
   9787      }
   9788 
   9789      if (gate) {
   9790         IRTemp irt_regN    = newTemp(Ity_I32);
   9791         IRTemp irt_regM    = newTemp(Ity_I32);
   9792         IRTemp irt_prod_lo = newTemp(Ity_I32);
   9793         IRTemp irt_prod_hi = newTemp(Ity_I32);
   9794         IRTemp tmpM        = newTemp(Ity_I32);
   9795 
   9796         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9797 
   9798         assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
   9799         assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
   9800 
   9801         assign( irt_prod_lo,
   9802                 binop( Iop_Mul32,
   9803                        binop( Iop_Sar32,
   9804                               binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
   9805                               mkU8(16) ),
   9806                        binop( Iop_Sar32,
   9807                               binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
   9808                               mkU8(16) ) ) );
   9809         assign( irt_prod_hi, binop(Iop_Mul32,
   9810                                    binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)),
   9811                                    binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
   9812         IRExpr* ire_result
   9813            = binop( isAD ? Iop_Add32 : Iop_Sub32,
   9814                     mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) );
   9815 
   9816         if (isT)
   9817            putIRegT( regD, ire_result, condT );
   9818         else
   9819            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9820 
   9821         if (isAD) {
   9822            or_into_QFLAG32(
   9823               signed_overflow_after_Add32( ire_result,
   9824                                            irt_prod_lo, irt_prod_hi ),
   9825               condT
   9826            );
   9827         }
   9828 
   9829         DIP("smu%cd%s%s r%u, r%u, r%u\n",
   9830             isAD ? 'a' : 's',
   9831             bitM ? "x" : "", nCC(conq), regD, regN, regM);
   9832         return True;
   9833      }
   9834      /* fall through */
   9835    }
   9836 
   9837    /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
   9838    /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
   9839    {
   9840      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
   9841      Bool gate = False, isAD = False;
   9842 
   9843      if (isT) {
   9844        if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
   9845            && INSNT1(7,5) == BITS3(0,0,0)) {
   9846            regN = INSNT0(3,0);
   9847            regD = INSNT1(11,8);
   9848            regM = INSNT1(3,0);
   9849            regA = INSNT1(15,12);
   9850            bitM = INSNT1(4,4);
   9851            isAD = INSNT0(15,4) == 0xFB2;
   9852            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
   9853                && !isBadRegT(regA))
   9854               gate = True;
   9855         }
   9856      } else {
   9857         if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
   9858             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
   9859            regD = INSNA(19,16);
   9860            regA = INSNA(15,12);
   9861            regN = INSNA(3,0);
   9862            regM = INSNA(11,8);
   9863            bitM = INSNA(5,5);
   9864            isAD = INSNA(6,6) == 0;
   9865            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
   9866               gate = True;
   9867         }
   9868      }
   9869 
   9870      if (gate) {
   9871         IRTemp irt_regN    = newTemp(Ity_I32);
   9872         IRTemp irt_regM    = newTemp(Ity_I32);
   9873         IRTemp irt_regA    = newTemp(Ity_I32);
   9874         IRTemp irt_prod_lo = newTemp(Ity_I32);
   9875         IRTemp irt_prod_hi = newTemp(Ity_I32);
   9876         IRTemp irt_sum     = newTemp(Ity_I32);
   9877         IRTemp tmpM        = newTemp(Ity_I32);
   9878 
   9879         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9880         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
   9881 
   9882         assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
   9883         assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
   9884 
   9885         assign( irt_prod_lo,
   9886                 binop(Iop_Mul32,
   9887                       binop(Iop_Sar32,
   9888                             binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9889                             mkU8(16)),
   9890                       binop(Iop_Sar32,
   9891                             binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
   9892                             mkU8(16))) );
   9893         assign( irt_prod_hi,
   9894                 binop( Iop_Mul32,
   9895                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9896                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
   9897         assign( irt_sum, binop( isAD ? Iop_Add32 : Iop_Sub32,
   9898                                 mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) );
   9899 
   9900         IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA));
   9901 
   9902         if (isT)
   9903            putIRegT( regD, ire_result, condT );
   9904         else
   9905            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9906 
   9907         if (isAD) {
   9908            or_into_QFLAG32(
   9909               signed_overflow_after_Add32( mkexpr(irt_sum),
   9910                                            irt_prod_lo, irt_prod_hi ),
   9911               condT
   9912            );
   9913         }
   9914 
   9915         or_into_QFLAG32(
   9916            signed_overflow_after_Add32( ire_result, irt_sum, irt_regA ),
   9917            condT
   9918         );
   9919 
   9920         DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n",
   9921             isAD ? 'a' : 's',
   9922             bitM ? "x" : "", nCC(conq), regD, regN, regM, regA);
   9923         return True;
   9924      }
   9925      /* fall through */
   9926    }
   9927 
   9928    /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
   9929    {
   9930      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99;
   9931      Bool gate = False;
   9932 
   9933      if (isT) {
   9934         if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
   9935            regN = INSNT0(3,0);
   9936            regD = INSNT1(11,8);
   9937            regM = INSNT1(3,0);
   9938            regA = INSNT1(15,12);
   9939            bitM = INSNT1(4,4);
   9940            bitN = INSNT1(5,5);
   9941            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
   9942                && !isBadRegT(regA))
   9943               gate = True;
   9944         }
   9945      } else {
   9946         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
   9947             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
   9948            regD = INSNA(19,16);
   9949            regN = INSNA(3,0);
   9950            regM = INSNA(11,8);
   9951            regA = INSNA(15,12);
   9952            bitM = INSNA(6,6);
   9953            bitN = INSNA(5,5);
   9954            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
   9955               gate = True;
   9956         }
   9957      }
   9958 
   9959      if (gate) {
   9960         IRTemp irt_regA = newTemp(Ity_I32);
   9961         IRTemp irt_prod = newTemp(Ity_I32);
   9962 
   9963         assign( irt_prod,
   9964                 binop(Iop_Mul32,
   9965                       binop(Iop_Sar32,
   9966                             binop(Iop_Shl32,
   9967                                   isT ? getIRegT(regN) : getIRegA(regN),
   9968                                   mkU8(bitN ? 0 : 16)),
   9969                             mkU8(16)),
   9970                       binop(Iop_Sar32,
   9971                             binop(Iop_Shl32,
   9972                                   isT ? getIRegT(regM) : getIRegA(regM),
   9973                                   mkU8(bitM ? 0 : 16)),
   9974                             mkU8(16))) );
   9975 
   9976         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
   9977 
   9978         IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA));
   9979 
   9980         if (isT)
   9981            putIRegT( regD, ire_result, condT );
   9982         else
   9983            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9984 
   9985         or_into_QFLAG32(
   9986            signed_overflow_after_Add32( ire_result, irt_prod, irt_regA ),
   9987            condT
   9988         );
   9989 
   9990         DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n",
   9991              bitN ? 't' : 'b', bitM ? 't' : 'b',
   9992              nCC(conq), regD, regN, regM, regA );
   9993         return True;
   9994      }
   9995      /* fall through */
   9996    }
   9997 
   9998    /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
   9999    {
   10000      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
   10001      Bool gate = False;
   10002 
   10003      if (isT) {
   10004         if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
   10005            regN = INSNT0(3,0);
   10006            regD = INSNT1(11,8);
   10007            regM = INSNT1(3,0);
   10008            regA = INSNT1(15,12);
   10009            bitM = INSNT1(4,4);
   10010            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
   10011                && !isBadRegT(regA))
   10012               gate = True;
   10013         }
   10014      } else {
   10015         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
   10016             (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
   10017            regD = INSNA(19,16);
   10018            regN = INSNA(3,0);
   10019            regM = INSNA(11,8);
   10020            regA = INSNA(15,12);
   10021            bitM = INSNA(6,6);
   10022            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
   10023               gate = True;
   10024         }
   10025      }
   10026 
   10027      if (gate) {
   10028         IRTemp irt_regA = newTemp(Ity_I32);
   10029         IRTemp irt_prod = newTemp(Ity_I64);
   10030 
   10031         assign( irt_prod,
   10032                 binop(Iop_MullS32,
   10033                       isT ? getIRegT(regN) : getIRegA(regN),
   10034                       binop(Iop_Sar32,
   10035                             binop(Iop_Shl32,
   10036                                   isT ? getIRegT(regM) : getIRegA(regM),
   10037                                   mkU8(bitM ? 0 : 16)),
   10038                             mkU8(16))) );
   10039 
   10040         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
   10041 
   10042         IRTemp prod32 = newTemp(Ity_I32);
   10043         assign(prod32,
   10044                binop(Iop_Or32,
   10045                      binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)),
   10046                      binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16))
   10047         ));
   10048 
   10049         IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA));
   10050 
   10051         if (isT)
   10052            putIRegT( regD, ire_result, condT );
   10053         else
   10054            putIRegA( regD, ire_result, condT, Ijk_Boring );
   10055 
   10056         or_into_QFLAG32(
   10057            signed_overflow_after_Add32( ire_result, prod32, irt_regA ),
   10058            condT
   10059         );
   10060 
   10061         DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n",
   10062              bitM ? 't' : 'b',
   10063              nCC(conq), regD, regN, regM, regA );
   10064         return True;
   10065      }
   10066      /* fall through */
   10067    }
   10068 
   10069    /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
   10070    /* fixme: fix up the test in v6media.c so that we can pass the ge
   10071       flags as part of the test. */
   10072    {
   10073      UInt regD = 99, regN = 99, regM = 99;
   10074      Bool gate = False;
   10075 
   10076      if (isT) {
   10077         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
   10078            regN = INSNT0(3,0);
   10079            regD = INSNT1(11,8);
   10080            regM = INSNT1(3,0);
   10081            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10082               gate = True;
   10083         }
   10084      } else {
   10085         if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
   10086             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   10087             INSNA(7,4)   == BITS4(1,0,1,1)) {
   10088            regD = INSNA(15,12);
   10089            regN = INSNA(19,16);
   10090            regM = INSNA(3,0);
   10091            if (regD != 15 && regN != 15 && regM != 15)
   10092               gate = True;
   10093         }
   10094      }
   10095 
   10096      if (gate) {
   10097         IRTemp irt_ge_flag0 = newTemp(Ity_I32);
   10098         IRTemp irt_ge_flag1 = newTemp(Ity_I32);
   10099         IRTemp irt_ge_flag2 = newTemp(Ity_I32);
   10100         IRTemp irt_ge_flag3 = newTemp(Ity_I32);
   10101 
   10102         assign( irt_ge_flag0, get_GEFLAG32(0) );
   10103         assign( irt_ge_flag1, get_GEFLAG32(1) );
   10104         assign( irt_ge_flag2, get_GEFLAG32(2) );
   10105         assign( irt_ge_flag3, get_GEFLAG32(3) );
   10106 
   10107         IRExpr* ire_ge_flag0_or
   10108           = binop(Iop_Or32, mkexpr(irt_ge_flag0),
   10109                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0)));
   10110         IRExpr* ire_ge_flag1_or
   10111           = binop(Iop_Or32, mkexpr(irt_ge_flag1),
   10112                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1)));
   10113         IRExpr* ire_ge_flag2_or
   10114           = binop(Iop_Or32, mkexpr(irt_ge_flag2),
   10115                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2)));
   10116         IRExpr* ire_ge_flag3_or
   10117           = binop(Iop_Or32, mkexpr(irt_ge_flag3),
   10118                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3)));
   10119 
   10120         IRExpr* ire_ge_flags
   10121           = binop( Iop_Or32,
   10122                    binop(Iop_Or32,
   10123                          binop(Iop_And32,
   10124                                binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)),
   10125                                mkU32(0x000000ff)),
   10126                          binop(Iop_And32,
   10127                                binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)),
   10128                                mkU32(0x0000ff00))),
   10129                    binop(Iop_Or32,
   10130                          binop(Iop_And32,
   10131                                binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)),
   10132                                mkU32(0x00ff0000)),
   10133                          binop(Iop_And32,
   10134                                binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)),
   10135                                mkU32(0xff000000))) );
   10136 
   10137         IRExpr* ire_result
   10138           = binop(Iop_Or32,
   10139                   binop(Iop_And32,
   10140                         isT ? getIRegT(regN) : getIRegA(regN),
   10141                         ire_ge_flags ),
   10142                   binop(Iop_And32,
   10143                         isT ? getIRegT(regM) : getIRegA(regM),
   10144                         unop(Iop_Not32, ire_ge_flags)));
   10145 
   10146         if (isT)
   10147            putIRegT( regD, ire_result, condT );
   10148         else
   10149            putIRegA( regD, ire_result, condT, Ijk_Boring );
   10150 
   10151         DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   10152         return True;
   10153      }
   10154      /* fall through */
   10155    }
   10156 
   10157    /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
   10158    {
   10159      UInt regD = 99, regN = 99, regM = 99, rotate = 99;
   10160      Bool gate = False;
   10161 
   10162      if (isT) {
   10163         if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
   10164            regN   = INSNT0(3,0);
   10165            regD   = INSNT1(11,8);
   10166            regM   = INSNT1(3,0);
   10167            rotate = INSNT1(5,4);
   10168            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10169               gate = True;
   10170         }
   10171      } else {
   10172         if (INSNA(27,20) == BITS8(0,1,1,0,1,1,0,0) &&
   10173             INSNA(9,4)   == BITS6(0,0,0,1,1,1) ) {
   10174            regD   = INSNA(15,12);
   10175            regN   = INSNA(19,16);
   10176            regM   = INSNA(3,0);
   10177            rotate = INSNA(11,10);
   10178            if (regD != 15 && regN != 15 && regM != 15)
   10179              gate = True;
   10180         }
   10181      }
   10182 
   10183      if (gate) {
   10184         IRTemp irt_regN = newTemp(Ity_I32);
   10185         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   10186 
   10187         IRTemp irt_regM = newTemp(Ity_I32);
   10188         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   10189 
   10190         IRTemp irt_rot = newTemp(Ity_I32);
   10191         assign( irt_rot, binop(Iop_And32,
   10192                                genROR32(irt_regM, 8 * rotate),
   10193                                mkU32(0x00FF00FF)) );
   10194 
   10195         IRExpr* resLo
   10196            = binop(Iop_And32,
   10197                    binop(Iop_Add32, mkexpr(irt_regN), mkexpr(irt_rot)),
   10198                    mkU32(0x0000FFFF));
   10199 
   10200         IRExpr* resHi
   10201            = binop(Iop_Add32,
   10202                    binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF0000)),
   10203                    binop(Iop_And32, mkexpr(irt_rot),  mkU32(0xFFFF0000)));
   10204 
   10205         IRExpr* ire_result
   10206            = binop( Iop_Or32, resHi, resLo );
   10207 
   10208         if (isT)
   10209            putIRegT( regD, ire_result, condT );
   10210         else
   10211            putIRegA( regD, ire_result, condT, Ijk_Boring );
   10212 
   10213         DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n",
   10214              nCC(conq), regD, regN, regM, 8 * rotate );
   10215         return True;
   10216      }
   10217      /* fall through */
   10218    }
   10219 
   10220    /* --------------- usad8  Rd,Rn,Rm    ---------------- */
   10221    /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */
   10222    {
   10223      UInt rD = 99, rN = 99, rM = 99, rA = 99;
   10224      Bool gate = False;
   10225 
   10226      if (isT) {
   10227        if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) {
   10228            rN = INSNT0(3,0);
   10229            rA = INSNT1(15,12);
   10230            rD = INSNT1(11,8);
   10231            rM = INSNT1(3,0);
   10232            if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && rA != 13)
   10233               gate = True;
   10234         }
   10235      } else {
   10236         if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) &&
   10237             INSNA(7,4)   == BITS4(0,0,0,1) ) {
   10238            rD = INSNA(19,16);
   10239            rA = INSNA(15,12);
   10240            rM = INSNA(11,8);
   10241            rN = INSNA(3,0);
   10242            if (rD != 15 && rN != 15 && rM != 15 /* but rA can be 15 */)
   10243               gate = True;
   10244         }
   10245      }
   10246      /* We allow rA == 15, to denote the usad8 (no accumulator) case. */
   10247 
   10248      if (gate) {
   10249         IRExpr* rNe = isT ? getIRegT(rN) : getIRegA(rN);
   10250         IRExpr* rMe = isT ? getIRegT(rM) : getIRegA(rM);
   10251         IRExpr* rAe = rA == 15 ? mkU32(0)
   10252                                : (isT ? getIRegT(rA) : getIRegA(rA));
   10253         IRExpr* res = binop(Iop_Add32,
   10254                             binop(Iop_Sad8Ux4, rNe, rMe),
   10255                             rAe);
   10256         if (isT)
   10257            putIRegT( rD, res, condT );
   10258         else
   10259            putIRegA( rD, res, condT, Ijk_Boring );
   10260 
   10261         if (rA == 15) {
   10262            DIP( "usad8%s r%u, r%u, r%u\n",
   10263                 nCC(conq), rD, rN, rM );
   10264         } else {
   10265            DIP( "usada8%s r%u, r%u, r%u, r%u\n",
   10266                 nCC(conq), rD, rN, rM, rA );
   10267         }
   10268         return True;
   10269      }
   10270      /* fall through */
   10271    }
   10272 
   10273    /* ------------------ qadd<c> <Rd>,<Rn>,<Rm> ------------------- */
   10274    {
   10275      UInt regD = 99, regN = 99, regM = 99;
   10276      Bool gate = False;
   10277 
   10278      if (isT) {
   10279         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
   10280            regN = INSNT0(3,0);
   10281            regD = INSNT1(11,8);
   10282            regM = INSNT1(3,0);
   10283            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10284               gate = True;
   10285         }
   10286      } else {
   10287         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
   10288             INSNA(11,8)  == BITS4(0,0,0,0)         &&
   10289             INSNA(7,4)   == BITS4(0,1,0,1)) {
   10290            regD = INSNA(15,12);
   10291            regN = INSNA(19,16);
   10292            regM = INSNA(3,0);
   10293            if (regD != 15 && regN != 15 && regM != 15)
   10294               gate = True;
   10295         }
   10296      }
   10297 
   10298      if (gate) {
   10299         IRTemp rNt   = newTemp(Ity_I32);
   10300         IRTemp rMt   = newTemp(Ity_I32);
   10301         IRTemp res_q = newTemp(Ity_I32);
   10302 
   10303         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   10304         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   10305 
   10306         assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rNt)));
   10307         if (isT)
   10308            putIRegT( regD, mkexpr(res_q), condT );
   10309         else
   10310            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   10311 
   10312         or_into_QFLAG32(
   10313            signed_overflow_after_Add32(
   10314               binop(Iop_Add32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt),
   10315            condT
   10316         );
   10317 
   10318         DIP("qadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
   10319         return True;
   10320      }
   10321      /* fall through */
   10322    }
   10323 
   10324    /* ------------------ qdadd<c> <Rd>,<Rm>,<Rn> ------------------- */
   10325    {
   10326      UInt regD = 99, regN = 99, regM = 99;
   10327      Bool gate = False;
   10328 
   10329      if (isT) {
   10330         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF090) {
   10331            regN = INSNT0(3,0);
   10332            regD = INSNT1(11,8);
   10333            regM = INSNT1(3,0);
   10334            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10335               gate = True;
   10336         }
   10337      } else {
   10338         if (INSNA(27,20) == BITS8(0,0,0,1,0,1,0,0) &&
   10339             INSNA(11,8)  == BITS4(0,0,0,0)         &&
   10340             INSNA(7,4)   == BITS4(0,1,0,1)) {
   10341            regD = INSNA(15,12);
   10342            regN = INSNA(19,16);
   10343            regM = INSNA(3,0);
   10344            if (regD != 15 && regN != 15 && regM != 15)
   10345               gate = True;
   10346         }
   10347      }
   10348 
   10349      if (gate) {
   10350         IRTemp rNt   = newTemp(Ity_I32);
   10351         IRTemp rMt   = newTemp(Ity_I32);
   10352         IRTemp rN_d  = newTemp(Ity_I32);
   10353         IRTemp res_q = newTemp(Ity_I32);
   10354 
   10355         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   10356         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   10357 
   10358         or_into_QFLAG32(
   10359            signed_overflow_after_Add32(
   10360               binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt),
   10361            condT
   10362         );
   10363 
   10364         assign(rN_d,  binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt)));
   10365         assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rN_d)));
   10366         if (isT)
   10367            putIRegT( regD, mkexpr(res_q), condT );
   10368         else
   10369            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   10370 
   10371         or_into_QFLAG32(
   10372            signed_overflow_after_Add32(
   10373               binop(Iop_Add32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d),
   10374            condT
   10375         );
   10376 
   10377         DIP("qdadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
   10378         return True;
   10379      }
   10380      /* fall through */
   10381    }
   10382 
   10383    /* ------------------ qsub<c> <Rd>,<Rn>,<Rm> ------------------- */
   10384    {
   10385      UInt regD = 99, regN = 99, regM = 99;
   10386      Bool gate = False;
   10387 
   10388      if (isT) {
   10389         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0A0) {
   10390            regN = INSNT0(3,0);
   10391            regD = INSNT1(11,8);
   10392            regM = INSNT1(3,0);
   10393            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10394               gate = True;
   10395         }
   10396      } else {
   10397         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
   10398             INSNA(11,8)  == BITS4(0,0,0,0)         &&
   10399             INSNA(7,4)   == BITS4(0,1,0,1)) {
   10400            regD = INSNA(15,12);
   10401            regN = INSNA(19,16);
   10402            regM = INSNA(3,0);
   10403            if (regD != 15 && regN != 15 && regM != 15)
   10404               gate = True;
   10405         }
   10406      }
   10407 
   10408      if (gate) {
   10409         IRTemp rNt   = newTemp(Ity_I32);
   10410         IRTemp rMt   = newTemp(Ity_I32);
   10411         IRTemp res_q = newTemp(Ity_I32);
   10412 
   10413         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   10414         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   10415 
   10416         assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rNt)));
   10417         if (isT)
   10418            putIRegT( regD, mkexpr(res_q), condT );
   10419         else
   10420            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   10421 
   10422         or_into_QFLAG32(
   10423            signed_overflow_after_Sub32(
   10424               binop(Iop_Sub32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt),
   10425            condT
   10426         );
   10427 
   10428         DIP("qsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
   10429         return True;
   10430      }
   10431      /* fall through */
   10432    }
   10433 
   10434    /* ------------------ qdsub<c> <Rd>,<Rm>,<Rn> ------------------- */
   10435    {
   10436      UInt regD = 99, regN = 99, regM = 99;
   10437      Bool gate = False;
   10438 
   10439      if (isT) {
   10440         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0B0) {
   10441            regN = INSNT0(3,0);
   10442            regD = INSNT1(11,8);
   10443            regM = INSNT1(3,0);
   10444            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10445               gate = True;
   10446         }
   10447      } else {
   10448         if (INSNA(27,20) == BITS8(0,0,0,1,0,1,1,0) &&
   10449             INSNA(11,8)  == BITS4(0,0,0,0)         &&
   10450             INSNA(7,4)   == BITS4(0,1,0,1)) {
   10451            regD = INSNA(15,12);
   10452            regN = INSNA(19,16);
   10453            regM = INSNA(3,0);
   10454            if (regD != 15 && regN != 15 && regM != 15)
   10455               gate = True;
   10456         }
   10457      }
   10458 
   10459      if (gate) {
   10460         IRTemp rNt   = newTemp(Ity_I32);
   10461         IRTemp rMt   = newTemp(Ity_I32);
   10462         IRTemp rN_d  = newTemp(Ity_I32);
   10463         IRTemp res_q = newTemp(Ity_I32);
   10464 
   10465         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   10466         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   10467 
   10468         or_into_QFLAG32(
   10469            signed_overflow_after_Add32(
   10470               binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt),
   10471            condT
   10472         );
   10473 
   10474         assign(rN_d,  binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt)));
   10475         assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rN_d)));
   10476         if (isT)
   10477            putIRegT( regD, mkexpr(res_q), condT );
   10478         else
   10479            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   10480 
   10481         or_into_QFLAG32(
   10482            signed_overflow_after_Sub32(
   10483               binop(Iop_Sub32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d),
   10484            condT
   10485         );
   10486 
   10487         DIP("qdsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
   10488         return True;
   10489      }
   10490      /* fall through */
   10491    }
   10492 
   10493    /* ------------------ uqsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
   10494    {
   10495      UInt regD = 99, regN = 99, regM = 99;
   10496      Bool gate = False;
   10497 
   10498      if (isT) {
   10499         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
   10500            regN = INSNT0(3,0);
   10501            regD = INSNT1(11,8);
   10502            regM = INSNT1(3,0);
   10503            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10504               gate = True;
   10505         }
   10506      } else {
   10507         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
   10508             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   10509             INSNA(7,4)   == BITS4(0,1,1,1)) {
   10510            regD = INSNA(15,12);
   10511            regN = INSNA(19,16);
   10512            regM = INSNA(3,0);
   10513            if (regD != 15 && regN != 15 && regM != 15)
   10514              gate = True;
   10515         }
   10516      }
   10517 
   10518      if (gate) {
   10519         IRTemp rNt   = newTemp(Ity_I32);
   10520         IRTemp rMt   = newTemp(Ity_I32);
   10521         IRTemp res_q = newTemp(Ity_I32);
   10522 
   10523         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   10524         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   10525 
   10526         assign(res_q, binop(Iop_QSub16Ux2, mkexpr(rNt), mkexpr(rMt)));
   10527         if (isT)
   10528            putIRegT( regD, mkexpr(res_q), condT );
   10529         else
   10530            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   10531 
   10532         DIP("uqsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   10533         return True;
   10534      }
   10535      /* fall through */
   10536    }
   10537 
   10538    /* ----------------- shadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
   10539    {
   10540      UInt regD = 99, regN = 99, regM = 99;
   10541      Bool gate = False;
   10542 
   10543      if (isT) {
   10544         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
   10545            regN = INSNT0(3,0);
   10546            regD = INSNT1(11,8);
   10547            regM = INSNT1(3,0);
   10548            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10549               gate = True;
   10550         }
   10551      } else {
   10552         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
   10553             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   10554             INSNA(7,4)   == BITS4(0,0,0,1)) {
   10555            regD = INSNA(15,12);
   10556            regN = INSNA(19,16);
   10557            regM = INSNA(3,0);
   10558            if (regD != 15 && regN != 15 && regM != 15)
   10559               gate = True;
   10560         }
   10561      }
   10562 
   10563      if (gate) {
   10564         IRTemp rNt   = newTemp(Ity_I32);
   10565         IRTemp rMt   = newTemp(Ity_I32);
   10566         IRTemp res_q = newTemp(Ity_I32);
   10567 
   10568         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   10569         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   10570 
   10571         assign(res_q, binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
   10572         if (isT)
   10573            putIRegT( regD, mkexpr(res_q), condT );
   10574         else
   10575            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   10576 
   10577         DIP("shadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   10578         return True;
   10579      }
   10580      /* fall through */
   10581    }
   10582 
   10583    /* ----------------- uhsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
   10584    {
   10585      UInt regD = 99, regN = 99, regM = 99;
   10586      Bool gate = False;
   10587 
   10588      if (isT) {
   10589         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
   10590            regN = INSNT0(3,0);
   10591            regD = INSNT1(11,8);
   10592            regM = INSNT1(3,0);
   10593            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10594               gate = True;
   10595         }
   10596      } else {
   10597         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
   10598             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   10599             INSNA(7,4)   == BITS4(1,1,1,1)) {
   10600            regD = INSNA(15,12);
   10601            regN = INSNA(19,16);
   10602            regM = INSNA(3,0);
   10603            if (regD != 15 && regN != 15 && regM != 15)
   10604               gate = True;
   10605         }
   10606      }
   10607 
   10608      if (gate) {
   10609         IRTemp rNt   = newTemp(Ity_I32);
   10610         IRTemp rMt   = newTemp(Ity_I32);
   10611         IRTemp res_q = newTemp(Ity_I32);
   10612 
   10613         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   10614         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   10615 
   10616         assign(res_q, binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
   10617         if (isT)
   10618            putIRegT( regD, mkexpr(res_q), condT );
   10619         else
   10620            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   10621 
   10622         DIP("uhsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   10623         return True;
   10624      }
   10625      /* fall through */
   10626    }
   10627 
   10628    /* ----------------- uhsub16<c> <Rd>,<Rn>,<Rm> ------------------- */
   10629    {
   10630      UInt regD = 99, regN = 99, regM = 99;
   10631      Bool gate = False;
   10632 
   10633      if (isT) {
   10634         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
   10635            regN = INSNT0(3,0);
   10636            regD = INSNT1(11,8);
   10637            regM = INSNT1(3,0);
   10638            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10639               gate = True;
   10640         }
   10641      } else {
   10642         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
   10643             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   10644             INSNA(7,4)   == BITS4(0,1,1,1)) {
   10645            regD = INSNA(15,12);
   10646            regN = INSNA(19,16);
   10647            regM = INSNA(3,0);
   10648            if (regD != 15 && regN != 15 && regM != 15)
   10649               gate = True;
   10650         }
   10651      }
   10652 
   10653      if (gate) {
   10654         IRTemp rNt   = newTemp(Ity_I32);
   10655         IRTemp rMt   = newTemp(Ity_I32);
   10656         IRTemp res_q = newTemp(Ity_I32);
   10657 
   10658         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   10659         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   10660 
   10661         assign(res_q, binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt)));
   10662         if (isT)
   10663            putIRegT( regD, mkexpr(res_q), condT );
   10664         else
   10665            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   10666 
   10667         DIP("uhsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   10668         return True;
   10669      }
   10670      /* fall through */
   10671    }
   10672 
   10673    /* ---------- Doesn't match anything. ---------- */
   10674    return False;
   10675 
   10676 #  undef INSNA
   10677 #  undef INSNT0
   10678 #  undef INSNT1
   10679 }
   10680 
   10681 
   10682 /*------------------------------------------------------------*/
   10683 /*--- LDMxx/STMxx helper (both ARM and Thumb32)            ---*/
   10684 /*------------------------------------------------------------*/
   10685 
   10686 /* Generate IR for LDMxx and STMxx.  This is complex.  Assumes it's
   10687    unconditional, so the caller must produce a jump-around before
   10688    calling this, if the insn is to be conditional.  Caller is
   10689    responsible for all validation of parameters.  For LDMxx, if PC is
   10690    amongst the values loaded, caller is also responsible for
   10691    generating the jump. */
   10692 static void mk_ldm_stm ( Bool arm,     /* True: ARM, False: Thumb */
   10693                          UInt rN,      /* base reg */
   10694                          UInt bINC,    /* 1: inc,  0: dec */
   10695                          UInt bBEFORE, /* 1: inc/dec before, 0: after */
   10696                          UInt bW,      /* 1: writeback to Rn */
   10697                          UInt bL,      /* 1: load, 0: store */
   10698                          UInt regList )
   10699 {
   10700    Int i, r, m, nRegs;
   10701    IRTemp jk = Ijk_Boring;
   10702 
   10703    /* Get hold of the old Rn value.  We might need to write its value
   10704       to memory during a store, and if it's also the writeback
   10705       register then we need to get its value now.  We can't treat it
   10706       exactly like the other registers we're going to transfer,
   10707       because for xxMDA and xxMDB writeback forms, the generated IR
   10708       updates Rn in the guest state before any transfers take place.
   10709       We have to do this as per comments below, in order that if Rn is
   10710       the stack pointer then it always has a value is below or equal
   10711       to any of the transfer addresses.  Ick. */
   10712    IRTemp oldRnT = newTemp(Ity_I32);
   10713    assign(oldRnT, arm ? getIRegA(rN) : getIRegT(rN));
   10714 
   10715    IRTemp anchorT = newTemp(Ity_I32);
   10716    /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx
   10717       ignore the bottom two bits of the address.  However, Cortex-A8
   10718       doesn't seem to care.  Hence: */
   10719    /* No .. don't force alignment .. */
   10720    /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */
   10721    /* Instead, use the potentially misaligned address directly. */
   10722    assign(anchorT, mkexpr(oldRnT));
   10723 
   10724    IROp opADDorSUB = bINC ? Iop_Add32 : Iop_Sub32;
   10725    // bINC == 1:  xxMIA, xxMIB
   10726    // bINC == 0:  xxMDA, xxMDB
   10727 
   10728    // For xxMDA and xxMDB, update Rn first if necessary.  We have
   10729    // to do this first so that, for the common idiom of the transfers
   10730    // faulting because we're pushing stuff onto a stack and the stack
   10731    // is growing down onto allocate-on-fault pages (as Valgrind simulates),
   10732    // we need to have the SP up-to-date "covering" (pointing below) the
   10733    // transfer area.  For the same reason, if we are doing xxMIA or xxMIB,
   10734    // do the transfer first, and then update rN afterwards.
   10735    nRegs = 0;
   10736    for (i = 0; i < 16; i++) {
   10737      if ((regList & (1 << i)) != 0)
   10738          nRegs++;
   10739    }
   10740    if (bW == 1 && !bINC) {
   10741       IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
   10742       if (arm)
   10743          putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
   10744       else
   10745          putIRegT( rN, e, IRTemp_INVALID );
   10746    }
   10747 
   10748    // Make up a list of the registers to transfer, and their offsets
   10749    // in memory relative to the anchor.  If the base reg (Rn) is part
   10750    // of the transfer, then do it last for a load and first for a store.
   10751    UInt xReg[16], xOff[16];
   10752    Int  nX = 0;
   10753    m = 0;
   10754    for (i = 0; i < 16; i++) {
   10755       r = bINC ? i : (15-i);
   10756       if (0 == (regList & (1<<r)))
   10757          continue;
   10758       if (bBEFORE)
   10759          m++;
   10760       /* paranoia: check we aren't transferring the writeback
   10761          register during a load. Should be assured by decode-point
   10762          check above. */
   10763       if (bW == 1 && bL == 1)
   10764          vassert(r != rN);
   10765 
   10766       xOff[nX] = 4 * m;
   10767       xReg[nX] = r;
   10768       nX++;
   10769 
   10770       if (!bBEFORE)
   10771          m++;
   10772    }
   10773    vassert(m == nRegs);
   10774    vassert(nX == nRegs);
   10775    vassert(nX <= 16);
   10776 
   10777    if (bW == 0 && (regList & (1<<rN)) != 0) {
   10778       /* Non-writeback, and basereg is to be transferred.  Do its
   10779          transfer last for a load and first for a store.  Requires
   10780          reordering xOff/xReg. */
   10781       if (0) {
   10782          vex_printf("\nREG_LIST_PRE: (rN=%d)\n", rN);
   10783          for (i = 0; i < nX; i++)
   10784             vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
   10785          vex_printf("\n");
   10786       }
   10787 
   10788       vassert(nX > 0);
   10789       for (i = 0; i < nX; i++) {
   10790          if (xReg[i] == rN)
   10791              break;
   10792       }
   10793       vassert(i < nX); /* else we didn't find it! */
   10794       UInt tReg = xReg[i];
   10795       UInt tOff = xOff[i];
   10796       if (bL == 1) {
   10797          /* load; make this transfer happen last */
   10798          if (i < nX-1) {
   10799             for (m = i+1; m < nX; m++) {
   10800                xReg[m-1] = xReg[m];
   10801                xOff[m-1] = xOff[m];
   10802             }
   10803             vassert(m == nX);
   10804             xReg[m-1] = tReg;
   10805             xOff[m-1] = tOff;
   10806          }
   10807       } else {
   10808          /* store; make this transfer happen first */
   10809          if (i > 0) {
   10810             for (m = i-1; m >= 0; m--) {
   10811                xReg[m+1] = xReg[m];
   10812                xOff[m+1] = xOff[m];
   10813             }
   10814             vassert(m == -1);
   10815             xReg[0] = tReg;
   10816             xOff[0] = tOff;
   10817          }
   10818       }
   10819 
   10820       if (0) {
   10821          vex_printf("REG_LIST_POST:\n");
   10822          for (i = 0; i < nX; i++)
   10823             vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
   10824          vex_printf("\n");
   10825       }
   10826    }
   10827 
   10828    /* According to the Cortex A8 TRM Sec. 5.2.1, LDM(1) with r13 as the base
   10829        register and PC in the register list is a return for purposes of branch
   10830        prediction.
   10831       The ARM ARM Sec. C9.10.1 further specifies that writeback must be enabled
   10832        to be counted in event 0x0E (Procedure return).*/
   10833    if (rN == 13 && bL == 1 && bINC && !bBEFORE && bW == 1) {
   10834       jk = Ijk_Ret;
   10835    }
   10836 
   10837    /* Actually generate the transfers */
   10838    for (i = 0; i < nX; i++) {
   10839       r = xReg[i];
   10840       if (bL == 1) {
   10841          IRExpr* e = loadLE(Ity_I32,
   10842                             binop(opADDorSUB, mkexpr(anchorT),
   10843                                   mkU32(xOff[i])));
   10844          if (arm) {
   10845             putIRegA( r, e, IRTemp_INVALID, jk );
   10846          } else {
   10847             // no: putIRegT( r, e, IRTemp_INVALID );
   10848             // putIRegT refuses to write to R15.  But that might happen.
   10849             // Since this is uncond, and we need to be able to
   10850             // write the PC, just use the low level put:
   10851             llPutIReg( r, e );
   10852          }
   10853       } else {
   10854          /* if we're storing Rn, make sure we use the correct
   10855             value, as per extensive comments above */
   10856          storeLE( binop(opADDorSUB, mkexpr(anchorT), mkU32(xOff[i])),
   10857                   r == rN ? mkexpr(oldRnT)
   10858                           : (arm ? getIRegA(r) : getIRegT(r) ) );
   10859       }
   10860    }
   10861 
   10862    // If we are doing xxMIA or xxMIB,
   10863    // do the transfer first, and then update rN afterwards.
   10864    if (bW == 1 && bINC) {
   10865       IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
   10866       if (arm)
   10867          putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
   10868       else
   10869          putIRegT( rN, e, IRTemp_INVALID );
   10870    }
   10871 }
   10872 
   10873 
   10874 /*------------------------------------------------------------*/
   10875 /*--- VFP (CP 10 and 11) instructions                      ---*/
   10876 /*------------------------------------------------------------*/
   10877 
   10878 /* Both ARM and Thumb */
   10879 
   10880 /* Translate a CP10 or CP11 instruction.  If successful, returns
   10881    True and *dres may or may not be updated.  If failure, returns
   10882    False and doesn't change *dres nor create any IR.
   10883 
   10884    The ARM and Thumb encodings are identical for the low 28 bits of
   10885    the insn (yay!) and that's what the caller must supply, iow, imm28
   10886    has the top 4 bits masked out.  Caller is responsible for
   10887    determining whether the masked-out bits are valid for a CP10/11
   10888    insn.  The rules for the top 4 bits are:
   10889 
   10890      ARM: 0000 to 1110 allowed, and this is the gating condition.
   10891      1111 (NV) is not allowed.
   10892 
   10893      Thumb: must be 1110.  The gating condition is taken from
   10894      ITSTATE in the normal way.
   10895 
   10896    Conditionalisation:
   10897 
   10898    Caller must supply an IRTemp 'condT' holding the gating condition,
   10899    or IRTemp_INVALID indicating the insn is always executed.
   10900 
   10901    Caller must also supply an ARMCondcode 'cond'.  This is only used
   10902    for debug printing, no other purpose.  For ARM, this is simply the
   10903    top 4 bits of the original instruction.  For Thumb, the condition
   10904    is not (really) known until run time, and so ARMCondAL should be
   10905    passed, only so that printing of these instructions does not show
   10906    any condition.
   10907 
   10908    Finally, the caller must indicate whether this occurs in ARM or
   10909    Thumb code.
   10910 */
   10911 static Bool decode_CP10_CP11_instruction (
   10912                /*MOD*/DisResult* dres,
   10913                UInt              insn28,
   10914                IRTemp            condT,
   10915                ARMCondcode       conq,
   10916                Bool              isT
   10917             )
   10918 {
   10919 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn28, (_bMax), (_bMin))
   10920 
   10921    vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation
   10922 
   10923    if (isT) {
   10924       vassert(conq == ARMCondAL);
   10925    } else {
   10926       vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
   10927    }
   10928 
   10929    /* ----------------------------------------------------------- */
   10930    /* -- VFP instructions -- double precision (mostly)         -- */
   10931    /* ----------------------------------------------------------- */
   10932 
   10933    /* --------------------- fldmx, fstmx --------------------- */
   10934    /*
   10935                                  31   27   23   19 15 11   7   0
   10936                                          P U WL
   10937       C4-100, C5-26  1  FSTMX    cond 1100 1000 Rn Dd 1011 offset
   10938       C4-100, C5-28  2  FSTMIAX  cond 1100 1010 Rn Dd 1011 offset
   10939       C4-100, C5-30  3  FSTMDBX  cond 1101 0010 Rn Dd 1011 offset
   10940 
   10941       C4-42, C5-26   1  FLDMX    cond 1100 1001 Rn Dd 1011 offset
   10942       C4-42, C5-28   2  FLDMIAX  cond 1100 1011 Rn Dd 1011 offset
   10943       C4-42, C5-30   3  FLDMDBX  cond 1101 0011 Rn Dd 1011 offset
   10944 
   10945       Regs transferred: Dd .. D(d + (offset-3)/2)
   10946       offset must be odd, must not imply a reg > 15
   10947       IA/DB: Rn is changed by (4 + 8 x # regs transferred)
   10948 
   10949       case coding:
   10950          1  at-Rn   (access at Rn)
   10951          2  ia-Rn   (access at Rn, then Rn += 4+8n)
   10952          3  db-Rn   (Rn -= 4+8n,   then access at Rn)
   10953    */
   10954    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
   10955        && INSN(11,8) == BITS4(1,0,1,1)) {
   10956       UInt bP      = (insn28 >> 24) & 1;
   10957       UInt bU      = (insn28 >> 23) & 1;
   10958       UInt bW      = (insn28 >> 21) & 1;
   10959       UInt bL      = (insn28 >> 20) & 1;
   10960       UInt offset  = (insn28 >> 0) & 0xFF;
   10961       UInt rN      = INSN(19,16);
   10962       UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
   10963       UInt nRegs   = (offset - 1) / 2;
   10964       UInt summary = 0;
   10965       Int  i;
   10966 
   10967       /**/ if (bP == 0 && bU == 1 && bW == 0) {
   10968          summary = 1;
   10969       }
   10970       else if (bP == 0 && bU == 1 && bW == 1) {
   10971          summary = 2;
   10972       }
   10973       else if (bP == 1 && bU == 0 && bW == 1) {
   10974          summary = 3;
   10975       }
   10976       else goto after_vfp_fldmx_fstmx;
   10977 
   10978       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
   10979       if (rN == 15 && (summary == 2 || summary == 3 || isT))
   10980          goto after_vfp_fldmx_fstmx;
   10981 
   10982       /* offset must be odd, and specify at least one register */
   10983       if (0 == (offset & 1) || offset < 3)
   10984          goto after_vfp_fldmx_fstmx;
   10985 
   10986       /* can't transfer regs after D15 */
   10987       if (dD + nRegs - 1 >= 32)
   10988          goto after_vfp_fldmx_fstmx;
   10989 
   10990       /* Now, we can't do a conditional load or store, since that very
   10991          likely will generate an exception.  So we have to take a side
   10992          exit at this point if the condition is false. */
   10993       if (condT != IRTemp_INVALID) {
   10994          if (isT)
   10995             mk_skip_over_T32_if_cond_is_false( condT );
   10996          else
   10997             mk_skip_over_A32_if_cond_is_false( condT );
   10998          condT = IRTemp_INVALID;
   10999       }
   11000       /* Ok, now we're unconditional.  Do the load or store. */
   11001 
   11002       /* get the old Rn value */
   11003       IRTemp rnT = newTemp(Ity_I32);
   11004       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
   11005                            rN == 15));
   11006 
   11007       /* make a new value for Rn, post-insn */
   11008       IRTemp rnTnew = IRTemp_INVALID;
   11009       if (summary == 2 || summary == 3) {
   11010          rnTnew = newTemp(Ity_I32);
   11011          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
   11012                               mkexpr(rnT),
   11013                               mkU32(4 + 8 * nRegs)));
   11014       }
   11015 
   11016       /* decide on the base transfer address */
   11017       IRTemp taT = newTemp(Ity_I32);
   11018       assign(taT,  summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
   11019 
   11020       /* update Rn if necessary -- in case 3, we're moving it down, so
   11021          update before any memory reference, in order to keep Memcheck
   11022          and V's stack-extending logic (on linux) happy */
   11023       if (summary == 3) {
   11024          if (isT)
   11025             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   11026          else
   11027             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   11028       }
   11029 
   11030       /* generate the transfers */
   11031       for (i = 0; i < nRegs; i++) {
   11032          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
   11033          if (bL) {
   11034             putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
   11035          } else {
   11036             storeLE(addr, getDReg(dD + i));
   11037          }
   11038       }
   11039 
   11040       /* update Rn if necessary -- in case 2, we're moving it up, so
   11041          update after any memory reference, in order to keep Memcheck
   11042          and V's stack-extending logic (on linux) happy */
   11043       if (summary == 2) {
   11044          if (isT)
   11045             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   11046          else
   11047             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   11048       }
   11049 
   11050       HChar* nm = bL==1 ? "ld" : "st";
   11051       switch (summary) {
   11052          case 1:  DIP("f%smx%s r%u, {d%u-d%u}\n",
   11053                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   11054                   break;
   11055          case 2:  DIP("f%smiax%s r%u!, {d%u-d%u}\n",
   11056                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   11057                   break;
   11058          case 3:  DIP("f%smdbx%s r%u!, {d%u-d%u}\n",
   11059                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   11060                   break;
   11061          default: vassert(0);
   11062       }
   11063 
   11064       goto decode_success_vfp;
   11065       /* FIXME alignment constraints? */
   11066    }
   11067 
   11068   after_vfp_fldmx_fstmx:
   11069 
   11070    /* --------------------- fldmd, fstmd --------------------- */
   11071    /*
   11072                                  31   27   23   19 15 11   7   0
   11073                                          P U WL
   11074       C4-96, C5-26   1  FSTMD    cond 1100 1000 Rn Dd 1011 offset
   11075       C4-96, C5-28   2  FSTMDIA  cond 1100 1010 Rn Dd 1011 offset
   11076       C4-96, C5-30   3  FSTMDDB  cond 1101 0010 Rn Dd 1011 offset
   11077 
   11078       C4-38, C5-26   1  FLDMD    cond 1100 1001 Rn Dd 1011 offset
   11079       C4-38, C5-28   2  FLDMIAD  cond 1100 1011 Rn Dd 1011 offset
   11080       C4-38, C5-30   3  FLDMDBD  cond 1101 0011 Rn Dd 1011 offset
   11081 
   11082       Regs transferred: Dd .. D(d + (offset-2)/2)
   11083       offset must be even, must not imply a reg > 15
   11084       IA/DB: Rn is changed by (8 x # regs transferred)
   11085 
   11086       case coding:
   11087          1  at-Rn   (access at Rn)
   11088          2  ia-Rn   (access at Rn, then Rn += 8n)
   11089          3  db-Rn   (Rn -= 8n,     then access at Rn)
   11090    */
   11091    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
   11092        && INSN(11,8) == BITS4(1,0,1,1)) {
   11093       UInt bP      = (insn28 >> 24) & 1;
   11094       UInt bU      = (insn28 >> 23) & 1;
   11095       UInt bW      = (insn28 >> 21) & 1;
   11096       UInt bL      = (insn28 >> 20) & 1;
   11097       UInt offset  = (insn28 >> 0) & 0xFF;
   11098       UInt rN      = INSN(19,16);
   11099       UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
   11100       UInt nRegs   = offset / 2;
   11101       UInt summary = 0;
   11102       Int  i;
   11103 
   11104       /**/ if (bP == 0 && bU == 1 && bW == 0) {
   11105          summary = 1;
   11106       }
   11107       else if (bP == 0 && bU == 1 && bW == 1) {
   11108          summary = 2;
   11109       }
   11110       else if (bP == 1 && bU == 0 && bW == 1) {
   11111          summary = 3;
   11112       }
   11113       else goto after_vfp_fldmd_fstmd;
   11114 
   11115       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
   11116       if (rN == 15 && (summary == 2 || summary == 3 || isT))
   11117          goto after_vfp_fldmd_fstmd;
   11118 
   11119       /* offset must be even, and specify at least one register */
   11120       if (1 == (offset & 1) || offset < 2)
   11121          goto after_vfp_fldmd_fstmd;
   11122 
   11123       /* can't transfer regs after D15 */
   11124       if (dD + nRegs - 1 >= 32)
   11125          goto after_vfp_fldmd_fstmd;
   11126 
   11127       /* Now, we can't do a conditional load or store, since that very
   11128          likely will generate an exception.  So we have to take a side
   11129          exit at this point if the condition is false. */
   11130       if (condT != IRTemp_INVALID) {
   11131          if (isT)
   11132             mk_skip_over_T32_if_cond_is_false( condT );
   11133          else
   11134             mk_skip_over_A32_if_cond_is_false( condT );
   11135          condT = IRTemp_INVALID;
   11136       }
   11137       /* Ok, now we're unconditional.  Do the load or store. */
   11138 
   11139       /* get the old Rn value */
   11140       IRTemp rnT = newTemp(Ity_I32);
   11141       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
   11142                            rN == 15));
   11143 
   11144       /* make a new value for Rn, post-insn */
   11145       IRTemp rnTnew = IRTemp_INVALID;
   11146       if (summary == 2 || summary == 3) {
   11147          rnTnew = newTemp(Ity_I32);
   11148          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
   11149                               mkexpr(rnT),
   11150                               mkU32(8 * nRegs)));
   11151       }
   11152 
   11153       /* decide on the base transfer address */
   11154       IRTemp taT = newTemp(Ity_I32);
   11155       assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
   11156 
   11157       /* update Rn if necessary -- in case 3, we're moving it down, so
   11158          update before any memory reference, in order to keep Memcheck
   11159          and V's stack-extending logic (on linux) happy */
   11160       if (summary == 3) {
   11161          if (isT)
   11162             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   11163          else
   11164             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   11165       }
   11166 
   11167       /* generate the transfers */
   11168       for (i = 0; i < nRegs; i++) {
   11169          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
   11170          if (bL) {
   11171             putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
   11172          } else {
   11173             storeLE(addr, getDReg(dD + i));
   11174          }
   11175       }
   11176 
   11177       /* update Rn if necessary -- in case 2, we're moving it up, so
   11178          update after any memory reference, in order to keep Memcheck
   11179          and V's stack-extending logic (on linux) happy */
   11180       if (summary == 2) {
   11181          if (isT)
   11182             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   11183          else
   11184             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   11185       }
   11186 
   11187       HChar* nm = bL==1 ? "ld" : "st";
   11188       switch (summary) {
   11189          case 1:  DIP("f%smd%s r%u, {d%u-d%u}\n",
   11190                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   11191                   break;
   11192          case 2:  DIP("f%smiad%s r%u!, {d%u-d%u}\n",
   11193                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   11194                   break;
   11195          case 3:  DIP("f%smdbd%s r%u!, {d%u-d%u}\n",
   11196                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   11197                   break;
   11198          default: vassert(0);
   11199       }
   11200 
   11201       goto decode_success_vfp;
   11202       /* FIXME alignment constraints? */
   11203    }
   11204 
   11205   after_vfp_fldmd_fstmd:
   11206 
   11207    /* ------------------- fmrx, fmxr ------------------- */
   11208    if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20)
   11209        && BITS4(1,0,1,0) == INSN(11,8)
   11210        && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
   11211       UInt rD  = INSN(15,12);
   11212       UInt reg = INSN(19,16);
   11213       if (reg == BITS4(0,0,0,1)) {
   11214          if (rD == 15) {
   11215             IRTemp nzcvT = newTemp(Ity_I32);
   11216             /* When rD is 15, we are copying the top 4 bits of FPSCR
   11217                into CPSR.  That is, set the flags thunk to COPY and
   11218                install FPSCR[31:28] as the value to copy. */
   11219             assign(nzcvT, binop(Iop_And32,
   11220                                 IRExpr_Get(OFFB_FPSCR, Ity_I32),
   11221                                 mkU32(0xF0000000)));
   11222             setFlags_D1(ARMG_CC_OP_COPY, nzcvT, condT);
   11223             DIP("fmstat%s\n", nCC(conq));
   11224          } else {
   11225             /* Otherwise, merely transfer FPSCR to r0 .. r14. */
   11226             IRExpr* e = IRExpr_Get(OFFB_FPSCR, Ity_I32);
   11227             if (isT)
   11228                putIRegT(rD, e, condT);
   11229             else
   11230                putIRegA(rD, e, condT, Ijk_Boring);
   11231             DIP("fmrx%s r%u, fpscr\n", nCC(conq), rD);
   11232          }
   11233          goto decode_success_vfp;
   11234       }
   11235       /* fall through */
   11236    }
   11237 
   11238    if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20)
   11239        && BITS4(1,0,1,0) == INSN(11,8)
   11240        && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
   11241       UInt rD  = INSN(15,12);
   11242       UInt reg = INSN(19,16);
   11243       if (reg == BITS4(0,0,0,1)) {
   11244          putMiscReg32(OFFB_FPSCR,
   11245                       isT ? getIRegT(rD) : getIRegA(rD), condT);
   11246          DIP("fmxr%s fpscr, r%u\n", nCC(conq), rD);
   11247          goto decode_success_vfp;
   11248       }
   11249       /* fall through */
   11250    }
   11251 
   11252    /* --------------------- vmov --------------------- */
   11253    // VMOV dM, rD, rN
   11254    if (0x0C400B10 == (insn28 & 0x0FF00FD0)) {
   11255       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
   11256       UInt rD = INSN(15,12); /* lo32 */
   11257       UInt rN = INSN(19,16); /* hi32 */
   11258       if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))) {
   11259          /* fall through */
   11260       } else {
   11261          putDReg(dM,
   11262                  unop(Iop_ReinterpI64asF64,
   11263                       binop(Iop_32HLto64,
   11264                             isT ? getIRegT(rN) : getIRegA(rN),
   11265                             isT ? getIRegT(rD) : getIRegA(rD))),
   11266                  condT);
   11267          DIP("vmov%s d%u, r%u, r%u\n", nCC(conq), dM, rD, rN);
   11268          goto decode_success_vfp;
   11269       }
   11270       /* fall through */
   11271    }
   11272 
   11273    // VMOV rD, rN, dM
   11274    if (0x0C500B10 == (insn28 & 0x0FF00FD0)) {
   11275       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
   11276       UInt rD = INSN(15,12); /* lo32 */
   11277       UInt rN = INSN(19,16); /* hi32 */
   11278       if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))
   11279           || rD == rN) {
   11280          /* fall through */
   11281       } else {
   11282          IRTemp i64 = newTemp(Ity_I64);
   11283          assign(i64, unop(Iop_ReinterpF64asI64, getDReg(dM)));
   11284          IRExpr* hi32 = unop(Iop_64HIto32, mkexpr(i64));
   11285          IRExpr* lo32 = unop(Iop_64to32,   mkexpr(i64));
   11286          if (isT) {
   11287             putIRegT(rN, hi32, condT);
   11288             putIRegT(rD, lo32, condT);
   11289          } else {
   11290             putIRegA(rN, hi32, condT, Ijk_Boring);
   11291             putIRegA(rD, lo32, condT, Ijk_Boring);
   11292          }
   11293          DIP("vmov%s r%u, r%u, d%u\n", nCC(conq), rD, rN, dM);
   11294          goto decode_success_vfp;
   11295       }
   11296       /* fall through */
   11297    }
   11298 
   11299    // VMOV sD, sD+1, rN, rM
   11300    if (0x0C400A10 == (insn28 & 0x0FF00FD0)) {
   11301       UInt sD = (INSN(3,0) << 1) | INSN(5,5);
   11302       UInt rN = INSN(15,12);
   11303       UInt rM = INSN(19,16);
   11304       if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
   11305           || sD == 31) {
   11306          /* fall through */
   11307       } else {
   11308          putFReg(sD,
   11309                  unop(Iop_ReinterpI32asF32, isT ? getIRegT(rN) : getIRegA(rN)),
   11310                  condT);
   11311          putFReg(sD+1,
   11312                  unop(Iop_ReinterpI32asF32, isT ? getIRegT(rM) : getIRegA(rM)),
   11313                  condT);
   11314          DIP("vmov%s, s%u, s%u, r%u, r%u\n",
   11315               nCC(conq), sD, sD + 1, rN, rM);
   11316          goto decode_success_vfp;
   11317       }
   11318    }
   11319 
   11320    // VMOV rN, rM, sD, sD+1
   11321    if (0x0C500A10 == (insn28 & 0x0FF00FD0)) {
   11322       UInt sD = (INSN(3,0) << 1) | INSN(5,5);
   11323       UInt rN = INSN(15,12);
   11324       UInt rM = INSN(19,16);
   11325       if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
   11326           || sD == 31 || rN == rM) {
   11327          /* fall through */
   11328       } else {
   11329          IRExpr* res0 = unop(Iop_ReinterpF32asI32, getFReg(sD));
   11330          IRExpr* res1 = unop(Iop_ReinterpF32asI32, getFReg(sD+1));
   11331          if (isT) {
   11332             putIRegT(rN, res0, condT);
   11333             putIRegT(rM, res1, condT);
   11334          } else {
   11335             putIRegA(rN, res0, condT, Ijk_Boring);
   11336             putIRegA(rM, res1, condT, Ijk_Boring);
   11337          }
   11338          DIP("vmov%s, r%u, r%u, s%u, s%u\n",
   11339              nCC(conq), rN, rM, sD, sD + 1);
   11340          goto decode_success_vfp;
   11341       }
   11342    }
   11343 
   11344    // VMOV rD[x], rT  (ARM core register to scalar)
   11345    if (0x0E000B10 == (insn28 & 0x0F900F1F)) {
   11346       UInt rD  = (INSN(7,7) << 4) | INSN(19,16);
   11347       UInt rT  = INSN(15,12);
   11348       UInt opc = (INSN(22,21) << 2) | INSN(6,5);
   11349       UInt index;
   11350       if (rT == 15 || (isT && rT == 13)) {
   11351          /* fall through */
   11352       } else {
   11353          if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
   11354             index = opc & 7;
   11355             putDRegI64(rD, triop(Iop_SetElem8x8,
   11356                                  getDRegI64(rD),
   11357                                  mkU8(index),
   11358                                  unop(Iop_32to8,
   11359                                       isT ? getIRegT(rT) : getIRegA(rT))),
   11360                            condT);
   11361             DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
   11362             goto decode_success_vfp;
   11363          }
   11364          else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
   11365             index = (opc >> 1) & 3;
   11366             putDRegI64(rD, triop(Iop_SetElem16x4,
   11367                                  getDRegI64(rD),
   11368                                  mkU8(index),
   11369                                  unop(Iop_32to16,
   11370                                       isT ? getIRegT(rT) : getIRegA(rT))),
   11371                            condT);
   11372             DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
   11373             goto decode_success_vfp;
   11374          }
   11375          else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0)) {
   11376             index = (opc >> 2) & 1;
   11377             putDRegI64(rD, triop(Iop_SetElem32x2,
   11378                                  getDRegI64(rD),
   11379                                  mkU8(index),
   11380                                  isT ? getIRegT(rT) : getIRegA(rT)),
   11381                            condT);
   11382             DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
   11383             goto decode_success_vfp;
   11384          } else {
   11385             /* fall through */
   11386          }
   11387       }
   11388    }
   11389 
   11390    // VMOV (scalar to ARM core register)
   11391    // VMOV rT, rD[x]
   11392    if (0x0E100B10 == (insn28 & 0x0F100F1F)) {
   11393       UInt rN  = (INSN(7,7) << 4) | INSN(19,16);
   11394       UInt rT  = INSN(15,12);
   11395       UInt U   = INSN(23,23);
   11396       UInt opc = (INSN(22,21) << 2) | INSN(6,5);
   11397       UInt index;
   11398       if (rT == 15 || (isT && rT == 13)) {
   11399          /* fall through */
   11400       } else {
   11401          if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
   11402             index = opc & 7;
   11403             IRExpr* e = unop(U ? Iop_8Uto32 : Iop_8Sto32,
   11404                              binop(Iop_GetElem8x8,
   11405                                    getDRegI64(rN),
   11406                                    mkU8(index)));
   11407             if (isT)
   11408                putIRegT(rT, e, condT);
   11409             else
   11410                putIRegA(rT, e, condT, Ijk_Boring);
   11411             DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
   11412                   rT, rN, index);
   11413             goto decode_success_vfp;
   11414          }
   11415          else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
   11416             index = (opc >> 1) & 3;
   11417             IRExpr* e = unop(U ? Iop_16Uto32 : Iop_16Sto32,
   11418                              binop(Iop_GetElem16x4,
   11419                                    getDRegI64(rN),
   11420                                    mkU8(index)));
   11421             if (isT)
   11422                putIRegT(rT, e, condT);
   11423             else
   11424                putIRegA(rT, e, condT, Ijk_Boring);
   11425             DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
   11426                   rT, rN, index);
   11427             goto decode_success_vfp;
   11428          }
   11429          else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U == 0) {
   11430             index = (opc >> 2) & 1;
   11431             IRExpr* e = binop(Iop_GetElem32x2, getDRegI64(rN), mkU8(index));
   11432             if (isT)
   11433                putIRegT(rT, e, condT);
   11434             else
   11435                putIRegA(rT, e, condT, Ijk_Boring);
   11436             DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq), rT, rN, index);
   11437             goto decode_success_vfp;
   11438          } else {
   11439             /* fall through */
   11440          }
   11441       }
   11442    }
   11443 
   11444    // VMOV.F32 sD, #imm
   11445    // FCONSTS sD, #imm
   11446    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11447        && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) {
   11448       UInt rD   = (INSN(15,12) << 1) | INSN(22,22);
   11449       UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
   11450       UInt b    = (imm8 >> 6) & 1;
   11451       UInt imm;
   11452       imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,(imm8 >> 5) & 1) << 8)
   11453              | ((imm8 & 0x1f) << 3);
   11454       imm <<= 16;
   11455       putFReg(rD, unop(Iop_ReinterpI32asF32, mkU32(imm)), condT);
   11456       DIP("fconsts%s s%u #%u", nCC(conq), rD, imm8);
   11457       goto decode_success_vfp;
   11458    }
   11459 
   11460    // VMOV.F64 dD, #imm
   11461    // FCONSTD dD, #imm
   11462    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11463        && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) {
   11464       UInt rD   = INSN(15,12) | (INSN(22,22) << 4);
   11465       UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
   11466       UInt b    = (imm8 >> 6) & 1;
   11467       ULong imm;
   11468       imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,b) << 8)
   11469              | BITS8(b,b,0,0,0,0,0,0) | (imm8 & 0x3f);
   11470       imm <<= 48;
   11471       putDReg(rD, unop(Iop_ReinterpI64asF64, mkU64(imm)), condT);
   11472       DIP("fconstd%s d%u #%u", nCC(conq), rD, imm8);
   11473       goto decode_success_vfp;
   11474    }
   11475 
   11476    /* ---------------------- vdup ------------------------- */
   11477    // VDUP dD, rT
   11478    // VDUP qD, rT
   11479    if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1))
   11480        && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) {
   11481       UInt rD   = (INSN(7,7) << 4) | INSN(19,16);
   11482       UInt rT   = INSN(15,12);
   11483       UInt Q    = INSN(21,21);
   11484       UInt size = (INSN(22,22) << 1) | INSN(5,5);
   11485       if (rT == 15 || (isT && rT == 13) || size == 3 || (Q && (rD & 1))) {
   11486          /* fall through */
   11487       } else {
   11488          IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT);
   11489          if (Q) {
   11490             rD >>= 1;
   11491             switch (size) {
   11492                case 0:
   11493                   putQReg(rD, unop(Iop_Dup32x4, e), condT);
   11494                   break;
   11495                case 1:
   11496                   putQReg(rD, unop(Iop_Dup16x8, unop(Iop_32to16, e)),
   11497                               condT);
   11498                   break;
   11499                case 2:
   11500                   putQReg(rD, unop(Iop_Dup8x16, unop(Iop_32to8, e)),
   11501                               condT);
   11502                   break;
   11503                default:
   11504                   vassert(0);
   11505             }
   11506             DIP("vdup.%u q%u, r%u\n", 32 / (1<<size), rD, rT);
   11507          } else {
   11508             switch (size) {
   11509                case 0:
   11510                   putDRegI64(rD, unop(Iop_Dup32x2, e), condT);
   11511                   break;
   11512                case 1:
   11513                   putDRegI64(rD, unop(Iop_Dup16x4, unop(Iop_32to16, e)),
   11514                                condT);
   11515                   break;
   11516                case 2:
   11517                   putDRegI64(rD, unop(Iop_Dup8x8, unop(Iop_32to8, e)),
   11518                                condT);
   11519                   break;
   11520                default:
   11521                   vassert(0);
   11522             }
   11523             DIP("vdup.%u d%u, r%u\n", 32 / (1<<size), rD, rT);
   11524          }
   11525          goto decode_success_vfp;
   11526       }
   11527    }
   11528 
   11529    /* --------------------- f{ld,st}d --------------------- */
   11530    // FLDD, FSTD
   11531    if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
   11532        && BITS4(1,0,1,1) == INSN(11,8)) {
   11533       UInt dD     = INSN(15,12) | (INSN(22,22) << 4);
   11534       UInt rN     = INSN(19,16);
   11535       UInt offset = (insn28 & 0xFF) << 2;
   11536       UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
   11537       UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
   11538       /* make unconditional */
   11539       if (condT != IRTemp_INVALID) {
   11540          if (isT)
   11541             mk_skip_over_T32_if_cond_is_false( condT );
   11542          else
   11543             mk_skip_over_A32_if_cond_is_false( condT );
   11544          condT = IRTemp_INVALID;
   11545       }
   11546       IRTemp ea = newTemp(Ity_I32);
   11547       assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
   11548                        align4if(isT ? getIRegT(rN) : getIRegA(rN),
   11549                                 rN == 15),
   11550                        mkU32(offset)));
   11551       if (bL) {
   11552          putDReg(dD, loadLE(Ity_F64,mkexpr(ea)), IRTemp_INVALID);
   11553       } else {
   11554          storeLE(mkexpr(ea), getDReg(dD));
   11555       }
   11556       DIP("f%sd%s d%u, [r%u, %c#%u]\n",
   11557           bL ? "ld" : "st", nCC(conq), dD, rN,
   11558           bU ? '+' : '-', offset);
   11559       goto decode_success_vfp;
   11560    }
   11561 
   11562    /* --------------------- dp insns (D) --------------------- */
   11563    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
   11564        && BITS4(1,0,1,1) == INSN(11,8)
   11565        && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
   11566       UInt    dM  = INSN(3,0)   | (INSN(5,5) << 4);       /* argR */
   11567       UInt    dD  = INSN(15,12) | (INSN(22,22) << 4);   /* dst/acc */
   11568       UInt    dN  = INSN(19,16) | (INSN(7,7) << 4);     /* argL */
   11569       UInt    bP  = (insn28 >> 23) & 1;
   11570       UInt    bQ  = (insn28 >> 21) & 1;
   11571       UInt    bR  = (insn28 >> 20) & 1;
   11572       UInt    bS  = (insn28 >> 6) & 1;
   11573       UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
   11574       IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   11575       switch (opc) {
   11576          case BITS4(0,0,0,0): /* MAC: d + n * m */
   11577             putDReg(dD, triop(Iop_AddF64, rm,
   11578                               getDReg(dD),
   11579                               triop(Iop_MulF64, rm, getDReg(dN),
   11580                                                     getDReg(dM))),
   11581                         condT);
   11582             DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11583             goto decode_success_vfp;
   11584          case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
   11585             putDReg(dD, triop(Iop_AddF64, rm,
   11586                               getDReg(dD),
   11587                               unop(Iop_NegF64,
   11588                                    triop(Iop_MulF64, rm, getDReg(dN),
   11589                                                          getDReg(dM)))),
   11590                         condT);
   11591             DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11592             goto decode_success_vfp;
   11593          case BITS4(0,0,1,0): /* MSC: - d + n * m */
   11594             putDReg(dD, triop(Iop_AddF64, rm,
   11595                               unop(Iop_NegF64, getDReg(dD)),
   11596                               triop(Iop_MulF64, rm, getDReg(dN),
   11597                                                     getDReg(dM))),
   11598                         condT);
   11599             DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11600             goto decode_success_vfp;
   11601          case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
   11602             putDReg(dD, triop(Iop_AddF64, rm,
   11603                               unop(Iop_NegF64, getDReg(dD)),
   11604                               unop(Iop_NegF64,
   11605                                    triop(Iop_MulF64, rm, getDReg(dN),
   11606                                                          getDReg(dM)))),
   11607                         condT);
   11608             DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11609             goto decode_success_vfp;
   11610          case BITS4(0,1,0,0): /* MUL: n * m */
   11611             putDReg(dD, triop(Iop_MulF64, rm, getDReg(dN), getDReg(dM)),
   11612                         condT);
   11613             DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11614             goto decode_success_vfp;
   11615          case BITS4(0,1,0,1): /* NMUL: - n * m */
   11616             putDReg(dD, unop(Iop_NegF64,
   11617                              triop(Iop_MulF64, rm, getDReg(dN),
   11618                                                    getDReg(dM))),
   11619                     condT);
   11620             DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11621             goto decode_success_vfp;
   11622          case BITS4(0,1,1,0): /* ADD: n + m */
   11623             putDReg(dD, triop(Iop_AddF64, rm, getDReg(dN), getDReg(dM)),
   11624                         condT);
   11625             DIP("faddd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11626             goto decode_success_vfp;
   11627          case BITS4(0,1,1,1): /* SUB: n - m */
   11628             putDReg(dD, triop(Iop_SubF64, rm, getDReg(dN), getDReg(dM)),
   11629                         condT);
   11630             DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11631             goto decode_success_vfp;
   11632          case BITS4(1,0,0,0): /* DIV: n / m */
   11633             putDReg(dD, triop(Iop_DivF64, rm, getDReg(dN), getDReg(dM)),
   11634                         condT);
   11635             DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11636             goto decode_success_vfp;
   11637          default:
   11638             break;
   11639       }
   11640    }
   11641 
   11642    /* --------------------- compares (D) --------------------- */
   11643    /*          31   27   23   19   15 11   7    3
   11644                  28   24   20   16 12    8    4    0
   11645       FCMPD    cond 1110 1D11 0100 Dd 1011 0100 Dm
   11646       FCMPED   cond 1110 1D11 0100 Dd 1011 1100 Dm
   11647       FCMPZD   cond 1110 1D11 0101 Dd 1011 0100 0000
   11648       FCMPZED  cond 1110 1D11 0101 Dd 1011 1100 0000
   11649                                  Z         N
   11650 
   11651       Z=0 Compare Dd vs Dm     and set FPSCR 31:28 accordingly
   11652       Z=1 Compare Dd vs zero
   11653 
   11654       N=1 generates Invalid Operation exn if either arg is any kind of NaN
   11655       N=0 generates Invalid Operation exn if either arg is a signalling NaN
   11656       (Not that we pay any attention to N here)
   11657    */
   11658    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11659        && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11660        && BITS4(1,0,1,1) == INSN(11,8)
   11661        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11662       UInt bZ = (insn28 >> 16) & 1;
   11663       UInt bN = (insn28 >> 7) & 1;
   11664       UInt dD = INSN(15,12) | (INSN(22,22) << 4);
   11665       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
   11666       if (bZ && INSN(3,0) != 0) {
   11667          /* does not decode; fall through */
   11668       } else {
   11669          IRTemp argL = newTemp(Ity_F64);
   11670          IRTemp argR = newTemp(Ity_F64);
   11671          IRTemp irRes = newTemp(Ity_I32);
   11672          assign(argL, getDReg(dD));
   11673          assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM));
   11674          assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
   11675 
   11676          IRTemp nzcv     = IRTemp_INVALID;
   11677          IRTemp oldFPSCR = newTemp(Ity_I32);
   11678          IRTemp newFPSCR = newTemp(Ity_I32);
   11679 
   11680          /* This is where the fun starts.  We have to convert 'irRes'
   11681             from an IR-convention return result (IRCmpF64Result) to an
   11682             ARM-encoded (N,Z,C,V) group.  The final result is in the
   11683             bottom 4 bits of 'nzcv'. */
   11684          /* Map compare result from IR to ARM(nzcv) */
   11685          /*
   11686             FP cmp result | IR   | ARM(nzcv)
   11687             --------------------------------
   11688             UN              0x45   0011
   11689             LT              0x01   1000
   11690             GT              0x00   0010
   11691             EQ              0x40   0110
   11692          */
   11693          nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
   11694 
   11695          /* And update FPSCR accordingly */
   11696          assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
   11697          assign(newFPSCR,
   11698                 binop(Iop_Or32,
   11699                       binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
   11700                       binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
   11701 
   11702          putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
   11703 
   11704          if (bZ) {
   11705             DIP("fcmpz%sd%s d%u\n", bN ? "e" : "", nCC(conq), dD);
   11706          } else {
   11707             DIP("fcmp%sd%s d%u, d%u\n", bN ? "e" : "", nCC(conq), dD, dM);
   11708          }
   11709          goto decode_success_vfp;
   11710       }
   11711       /* fall through */
   11712    }
   11713 
   11714    /* --------------------- unary (D) --------------------- */
   11715    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11716        && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11717        && BITS4(1,0,1,1) == INSN(11,8)
   11718        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11719       UInt dD  = INSN(15,12) | (INSN(22,22) << 4);
   11720       UInt dM  = INSN(3,0) | (INSN(5,5) << 4);
   11721       UInt b16 = (insn28 >> 16) & 1;
   11722       UInt b7  = (insn28 >> 7) & 1;
   11723       /**/ if (b16 == 0 && b7 == 0) {
   11724          // FCPYD
   11725          putDReg(dD, getDReg(dM), condT);
   11726          DIP("fcpyd%s d%u, d%u\n", nCC(conq), dD, dM);
   11727          goto decode_success_vfp;
   11728       }
   11729       else if (b16 == 0 && b7 == 1) {
   11730          // FABSD
   11731          putDReg(dD, unop(Iop_AbsF64, getDReg(dM)), condT);
   11732          DIP("fabsd%s d%u, d%u\n", nCC(conq), dD, dM);
   11733          goto decode_success_vfp;
   11734       }
   11735       else if (b16 == 1 && b7 == 0) {
   11736          // FNEGD
   11737          putDReg(dD, unop(Iop_NegF64, getDReg(dM)), condT);
   11738          DIP("fnegd%s d%u, d%u\n", nCC(conq), dD, dM);
   11739          goto decode_success_vfp;
   11740       }
   11741       else if (b16 == 1 && b7 == 1) {
   11742          // FSQRTD
   11743          IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   11744          putDReg(dD, binop(Iop_SqrtF64, rm, getDReg(dM)), condT);
   11745          DIP("fsqrtd%s d%u, d%u\n", nCC(conq), dD, dM);
   11746          goto decode_success_vfp;
   11747       }
   11748       else
   11749          vassert(0);
   11750 
   11751       /* fall through */
   11752    }
   11753 
   11754    /* ----------------- I <-> D conversions ----------------- */
   11755 
   11756    // F{S,U}ITOD dD, fM
   11757    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11758        && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
   11759        && BITS4(1,0,1,1) == INSN(11,8)
   11760        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11761       UInt bM    = (insn28 >> 5) & 1;
   11762       UInt fM    = (INSN(3,0) << 1) | bM;
   11763       UInt dD    = INSN(15,12) | (INSN(22,22) << 4);
   11764       UInt syned = (insn28 >> 7) & 1;
   11765       if (syned) {
   11766          // FSITOD
   11767          putDReg(dD, unop(Iop_I32StoF64,
   11768                           unop(Iop_ReinterpF32asI32, getFReg(fM))),
   11769                  condT);
   11770          DIP("fsitod%s d%u, s%u\n", nCC(conq), dD, fM);
   11771       } else {
   11772          // FUITOD
   11773          putDReg(dD, unop(Iop_I32UtoF64,
   11774                           unop(Iop_ReinterpF32asI32, getFReg(fM))),
   11775                  condT);
   11776          DIP("fuitod%s d%u, s%u\n", nCC(conq), dD, fM);
   11777       }
   11778       goto decode_success_vfp;
   11779    }
   11780 
   11781    // FTO{S,U}ID fD, dM
   11782    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11783        && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11784        && BITS4(1,0,1,1) == INSN(11,8)
   11785        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11786       UInt   bD    = (insn28 >> 22) & 1;
   11787       UInt   fD    = (INSN(15,12) << 1) | bD;
   11788       UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
   11789       UInt   bZ    = (insn28 >> 7) & 1;
   11790       UInt   syned = (insn28 >> 16) & 1;
   11791       IRTemp rmode = newTemp(Ity_I32);
   11792       assign(rmode, bZ ? mkU32(Irrm_ZERO)
   11793                        : mkexpr(mk_get_IR_rounding_mode()));
   11794       if (syned) {
   11795          // FTOSID
   11796          putFReg(fD, unop(Iop_ReinterpI32asF32,
   11797                           binop(Iop_F64toI32S, mkexpr(rmode),
   11798                                 getDReg(dM))),
   11799                  condT);
   11800          DIP("ftosi%sd%s s%u, d%u\n", bZ ? "z" : "",
   11801              nCC(conq), fD, dM);
   11802       } else {
   11803          // FTOUID
   11804          putFReg(fD, unop(Iop_ReinterpI32asF32,
   11805                           binop(Iop_F64toI32U, mkexpr(rmode),
   11806                                 getDReg(dM))),
   11807                  condT);
   11808          DIP("ftoui%sd%s s%u, d%u\n", bZ ? "z" : "",
   11809              nCC(conq), fD, dM);
   11810       }
   11811       goto decode_success_vfp;
   11812    }
   11813 
   11814    /* ----------------------------------------------------------- */
   11815    /* -- VFP instructions -- single precision                  -- */
   11816    /* ----------------------------------------------------------- */
   11817 
   11818    /* --------------------- fldms, fstms --------------------- */
   11819    /*
   11820                                  31   27   23   19 15 11   7   0
   11821                                          P UDWL
   11822       C4-98, C5-26   1  FSTMD    cond 1100 1x00 Rn Fd 1010 offset
   11823       C4-98, C5-28   2  FSTMDIA  cond 1100 1x10 Rn Fd 1010 offset
   11824       C4-98, C5-30   3  FSTMDDB  cond 1101 0x10 Rn Fd 1010 offset
   11825 
   11826       C4-40, C5-26   1  FLDMD    cond 1100 1x01 Rn Fd 1010 offset
   11827       C4-40, C5-26   2  FLDMIAD  cond 1100 1x11 Rn Fd 1010 offset
   11828       C4-40, C5-26   3  FLDMDBD  cond 1101 0x11 Rn Fd 1010 offset
   11829 
   11830       Regs transferred: F(Fd:D) .. F(Fd:d + offset)
   11831       offset must not imply a reg > 15
   11832       IA/DB: Rn is changed by (4 x # regs transferred)
   11833 
   11834       case coding:
   11835          1  at-Rn   (access at Rn)
   11836          2  ia-Rn   (access at Rn, then Rn += 4n)
   11837          3  db-Rn   (Rn -= 4n,     then access at Rn)
   11838    */
   11839    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
   11840        && INSN(11,8) == BITS4(1,0,1,0)) {
   11841       UInt bP      = (insn28 >> 24) & 1;
   11842       UInt bU      = (insn28 >> 23) & 1;
   11843       UInt bW      = (insn28 >> 21) & 1;
   11844       UInt bL      = (insn28 >> 20) & 1;
   11845       UInt bD      = (insn28 >> 22) & 1;
   11846       UInt offset  = (insn28 >> 0) & 0xFF;
   11847       UInt rN      = INSN(19,16);
   11848       UInt fD      = (INSN(15,12) << 1) | bD;
   11849       UInt nRegs   = offset;
   11850       UInt summary = 0;
   11851       Int  i;
   11852 
   11853       /**/ if (bP == 0 && bU == 1 && bW == 0) {
   11854          summary = 1;
   11855       }
   11856       else if (bP == 0 && bU == 1 && bW == 1) {
   11857          summary = 2;
   11858       }
   11859       else if (bP == 1 && bU == 0 && bW == 1) {
   11860          summary = 3;
   11861       }
   11862       else goto after_vfp_fldms_fstms;
   11863 
   11864       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
   11865       if (rN == 15 && (summary == 2 || summary == 3 || isT))
   11866          goto after_vfp_fldms_fstms;
   11867 
   11868       /* offset must specify at least one register */
   11869       if (offset < 1)
   11870          goto after_vfp_fldms_fstms;
   11871 
   11872       /* can't transfer regs after S31 */
   11873       if (fD + nRegs - 1 >= 32)
   11874          goto after_vfp_fldms_fstms;
   11875 
   11876       /* Now, we can't do a conditional load or store, since that very
   11877          likely will generate an exception.  So we have to take a side
   11878          exit at this point if the condition is false. */
   11879       if (condT != IRTemp_INVALID) {
   11880          if (isT)
   11881             mk_skip_over_T32_if_cond_is_false( condT );
   11882          else
   11883             mk_skip_over_A32_if_cond_is_false( condT );
   11884          condT = IRTemp_INVALID;
   11885       }
   11886       /* Ok, now we're unconditional.  Do the load or store. */
   11887 
   11888       /* get the old Rn value */
   11889       IRTemp rnT = newTemp(Ity_I32);
   11890       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
   11891                            rN == 15));
   11892 
   11893       /* make a new value for Rn, post-insn */
   11894       IRTemp rnTnew = IRTemp_INVALID;
   11895       if (summary == 2 || summary == 3) {
   11896          rnTnew = newTemp(Ity_I32);
   11897          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
   11898                               mkexpr(rnT),
   11899                               mkU32(4 * nRegs)));
   11900       }
   11901 
   11902       /* decide on the base transfer address */
   11903       IRTemp taT = newTemp(Ity_I32);
   11904       assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
   11905 
   11906       /* update Rn if necessary -- in case 3, we're moving it down, so
   11907          update before any memory reference, in order to keep Memcheck
   11908          and V's stack-extending logic (on linux) happy */
   11909       if (summary == 3) {
   11910          if (isT)
   11911             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   11912          else
   11913             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   11914       }
   11915 
   11916       /* generate the transfers */
   11917       for (i = 0; i < nRegs; i++) {
   11918          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(4*i));
   11919          if (bL) {
   11920             putFReg(fD + i, loadLE(Ity_F32, addr), IRTemp_INVALID);
   11921          } else {
   11922             storeLE(addr, getFReg(fD + i));
   11923          }
   11924       }
   11925 
   11926       /* update Rn if necessary -- in case 2, we're moving it up, so
   11927          update after any memory reference, in order to keep Memcheck
   11928          and V's stack-extending logic (on linux) happy */
   11929       if (summary == 2) {
   11930          if (isT)
   11931             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   11932          else
   11933             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   11934       }
   11935 
   11936       HChar* nm = bL==1 ? "ld" : "st";
   11937       switch (summary) {
   11938          case 1:  DIP("f%sms%s r%u, {s%u-s%u}\n",
   11939                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
   11940                   break;
   11941          case 2:  DIP("f%smias%s r%u!, {s%u-s%u}\n",
   11942                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
   11943                   break;
   11944          case 3:  DIP("f%smdbs%s r%u!, {s%u-s%u}\n",
   11945                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
   11946                   break;
   11947          default: vassert(0);
   11948       }
   11949 
   11950       goto decode_success_vfp;
   11951       /* FIXME alignment constraints? */
   11952    }
   11953 
   11954   after_vfp_fldms_fstms:
   11955 
   11956    /* --------------------- fmsr, fmrs --------------------- */
   11957    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
   11958        && BITS4(1,0,1,0) == INSN(11,8)
   11959        && BITS4(0,0,0,0) == INSN(3,0)
   11960        && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
   11961       UInt rD  = INSN(15,12);
   11962       UInt b7  = (insn28 >> 7) & 1;
   11963       UInt fN  = (INSN(19,16) << 1) | b7;
   11964       UInt b20 = (insn28 >> 20) & 1;
   11965       if (rD == 15) {
   11966          /* fall through */
   11967          /* Let's assume that no sane person would want to do
   11968             floating-point transfers to or from the program counter,
   11969             and simply decline to decode the instruction.  The ARM ARM
   11970             doesn't seem to explicitly disallow this case, though. */
   11971       } else {
   11972          if (b20) {
   11973             IRExpr* res = unop(Iop_ReinterpF32asI32, getFReg(fN));
   11974             if (isT)
   11975                putIRegT(rD, res, condT);
   11976             else
   11977                putIRegA(rD, res, condT, Ijk_Boring);
   11978             DIP("fmrs%s r%u, s%u\n", nCC(conq), rD, fN);
   11979          } else {
   11980             putFReg(fN, unop(Iop_ReinterpI32asF32,
   11981                              isT ? getIRegT(rD) : getIRegA(rD)),
   11982                         condT);
   11983             DIP("fmsr%s s%u, r%u\n", nCC(conq), fN, rD);
   11984          }
   11985          goto decode_success_vfp;
   11986       }
   11987       /* fall through */
   11988    }
   11989 
   11990    /* --------------------- f{ld,st}s --------------------- */
   11991    // FLDS, FSTS
   11992    if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
   11993        && BITS4(1,0,1,0) == INSN(11,8)) {
   11994       UInt bD     = (insn28 >> 22) & 1;
   11995       UInt fD     = (INSN(15,12) << 1) | bD;
   11996       UInt rN     = INSN(19,16);
   11997       UInt offset = (insn28 & 0xFF) << 2;
   11998       UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
   11999       UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
   12000       /* make unconditional */
   12001       if (condT != IRTemp_INVALID) {
   12002          if (isT)
   12003             mk_skip_over_T32_if_cond_is_false( condT );
   12004          else
   12005             mk_skip_over_A32_if_cond_is_false( condT );
   12006          condT = IRTemp_INVALID;
   12007       }
   12008       IRTemp ea = newTemp(Ity_I32);
   12009       assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
   12010                        align4if(isT ? getIRegT(rN) : getIRegA(rN),
   12011                                 rN == 15),
   12012                        mkU32(offset)));
   12013       if (bL) {
   12014          putFReg(fD, loadLE(Ity_F32,mkexpr(ea)), IRTemp_INVALID);
   12015       } else {
   12016          storeLE(mkexpr(ea), getFReg(fD));
   12017       }
   12018       DIP("f%ss%s s%u, [r%u, %c#%u]\n",
   12019           bL ? "ld" : "st", nCC(conq), fD, rN,
   12020           bU ? '+' : '-', offset);
   12021       goto decode_success_vfp;
   12022    }
   12023 
   12024    /* --------------------- dp insns (F) --------------------- */
   12025    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
   12026        && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
   12027        && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
   12028       UInt    bM  = (insn28 >> 5) & 1;
   12029       UInt    bD  = (insn28 >> 22) & 1;
   12030       UInt    bN  = (insn28 >> 7) & 1;
   12031       UInt    fM  = (INSN(3,0) << 1) | bM;   /* argR */
   12032       UInt    fD  = (INSN(15,12) << 1) | bD; /* dst/acc */
   12033       UInt    fN  = (INSN(19,16) << 1) | bN; /* argL */
   12034       UInt    bP  = (insn28 >> 23) & 1;
   12035       UInt    bQ  = (insn28 >> 21) & 1;
   12036       UInt    bR  = (insn28 >> 20) & 1;
   12037       UInt    bS  = (insn28 >> 6) & 1;
   12038       UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
   12039       IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   12040       switch (opc) {
   12041          case BITS4(0,0,0,0): /* MAC: d + n * m */
   12042             putFReg(fD, triop(Iop_AddF32, rm,
   12043                               getFReg(fD),
   12044                               triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
   12045                         condT);
   12046             DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   12047             goto decode_success_vfp;
   12048          case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
   12049             putFReg(fD, triop(Iop_AddF32, rm,
   12050                               getFReg(fD),
   12051                               unop(Iop_NegF32,
   12052                                    triop(Iop_MulF32, rm, getFReg(fN),
   12053                                                          getFReg(fM)))),
   12054                         condT);
   12055             DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   12056             goto decode_success_vfp;
   12057          case BITS4(0,0,1,0): /* MSC: - d + n * m */
   12058             putFReg(fD, triop(Iop_AddF32, rm,
   12059                               unop(Iop_NegF32, getFReg(fD)),
   12060                               triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
   12061                         condT);
   12062             DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   12063             goto decode_success_vfp;
   12064          case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
   12065             putFReg(fD, triop(Iop_AddF32, rm,
   12066                               unop(Iop_NegF32, getFReg(fD)),
   12067                               unop(Iop_NegF32,
   12068                                    triop(Iop_MulF32, rm,
   12069                                                      getFReg(fN),
   12070                                                     getFReg(fM)))),
   12071                         condT);
   12072             DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   12073             goto decode_success_vfp;
   12074          case BITS4(0,1,0,0): /* MUL: n * m */
   12075             putFReg(fD, triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM)),
   12076                         condT);
   12077             DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   12078             goto decode_success_vfp;
   12079          case BITS4(0,1,0,1): /* NMUL: - n * m */
   12080             putFReg(fD, unop(Iop_NegF32,
   12081                              triop(Iop_MulF32, rm, getFReg(fN),
   12082                                                    getFReg(fM))),
   12083                     condT);
   12084             DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   12085             goto decode_success_vfp;
   12086          case BITS4(0,1,1,0): /* ADD: n + m */
   12087             putFReg(fD, triop(Iop_AddF32, rm, getFReg(fN), getFReg(fM)),
   12088                         condT);
   12089             DIP("fadds%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   12090             goto decode_success_vfp;
   12091          case BITS4(0,1,1,1): /* SUB: n - m */
   12092             putFReg(fD, triop(Iop_SubF32, rm, getFReg(fN), getFReg(fM)),
   12093                         condT);
   12094             DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   12095             goto decode_success_vfp;
   12096          case BITS4(1,0,0,0): /* DIV: n / m */
   12097             putFReg(fD, triop(Iop_DivF32, rm, getFReg(fN), getFReg(fM)),
   12098                         condT);
   12099             DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   12100             goto decode_success_vfp;
   12101          default:
   12102             break;
   12103       }
   12104    }
   12105 
   12106    /* --------------------- compares (S) --------------------- */
   12107    /*          31   27   23   19   15 11   7    3
   12108                  28   24   20   16 12    8    4    0
   12109       FCMPS    cond 1110 1D11 0100 Fd 1010 01M0 Fm
   12110       FCMPES   cond 1110 1D11 0100 Fd 1010 11M0 Fm
   12111       FCMPZS   cond 1110 1D11 0101 Fd 1010 0100 0000
   12112       FCMPZED  cond 1110 1D11 0101 Fd 1010 1100 0000
   12113                                  Z         N
   12114 
   12115       Z=0 Compare Fd:D vs Fm:M     and set FPSCR 31:28 accordingly
   12116       Z=1 Compare Fd:D vs zero
   12117 
   12118       N=1 generates Invalid Operation exn if either arg is any kind of NaN
   12119       N=0 generates Invalid Operation exn if either arg is a signalling NaN
   12120       (Not that we pay any attention to N here)
   12121    */
   12122    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   12123        && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   12124        && BITS4(1,0,1,0) == INSN(11,8)
   12125        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   12126       UInt bZ = (insn28 >> 16) & 1;
   12127       UInt bN = (insn28 >> 7) & 1;
   12128       UInt bD = (insn28 >> 22) & 1;
   12129       UInt bM = (insn28 >> 5) & 1;
   12130       UInt fD = (INSN(15,12) << 1) | bD;
   12131       UInt fM = (INSN(3,0) << 1) | bM;
   12132       if (bZ && (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) {
   12133          /* does not decode; fall through */
   12134       } else {
   12135          IRTemp argL = newTemp(Ity_F64);
   12136          IRTemp argR = newTemp(Ity_F64);
   12137          IRTemp irRes = newTemp(Ity_I32);
   12138 
   12139          assign(argL, unop(Iop_F32toF64, getFReg(fD)));
   12140          assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0))
   12141                          : unop(Iop_F32toF64, getFReg(fM)));
   12142          assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
   12143 
   12144          IRTemp nzcv     = IRTemp_INVALID;
   12145          IRTemp oldFPSCR = newTemp(Ity_I32);
   12146          IRTemp newFPSCR = newTemp(Ity_I32);
   12147 
   12148          /* This is where the fun starts.  We have to convert 'irRes'
   12149             from an IR-convention return result (IRCmpF64Result) to an
   12150             ARM-encoded (N,Z,C,V) group.  The final result is in the
   12151             bottom 4 bits of 'nzcv'. */
   12152          /* Map compare result from IR to ARM(nzcv) */
   12153          /*
   12154             FP cmp result | IR   | ARM(nzcv)
   12155             --------------------------------
   12156             UN              0x45   0011
   12157             LT              0x01   1000
   12158             GT              0x00   0010
   12159             EQ              0x40   0110
   12160          */
   12161          nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
   12162 
   12163          /* And update FPSCR accordingly */
   12164          assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
   12165          assign(newFPSCR,
   12166                 binop(Iop_Or32,
   12167                       binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
   12168                       binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
   12169 
   12170          putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
   12171 
   12172          if (bZ) {
   12173             DIP("fcmpz%ss%s s%u\n", bN ? "e" : "", nCC(conq), fD);
   12174          } else {
   12175             DIP("fcmp%ss%s s%u, s%u\n", bN ? "e" : "",
   12176                 nCC(conq), fD, fM);
   12177          }
   12178          goto decode_success_vfp;
   12179       }
   12180       /* fall through */
   12181    }
   12182 
   12183    /* --------------------- unary (S) --------------------- */
   12184    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   12185        && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   12186        && BITS4(1,0,1,0) == INSN(11,8)
   12187        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   12188       UInt bD = (insn28 >> 22) & 1;
   12189       UInt bM = (insn28 >> 5) & 1;
   12190       UInt fD  = (INSN(15,12) << 1) | bD;
   12191       UInt fM  = (INSN(3,0) << 1) | bM;
   12192       UInt b16 = (insn28 >> 16) & 1;
   12193       UInt b7  = (insn28 >> 7) & 1;
   12194       /**/ if (b16 == 0 && b7 == 0) {
   12195          // FCPYS
   12196          putFReg(fD, getFReg(fM), condT);
   12197          DIP("fcpys%s s%u, s%u\n", nCC(conq), fD, fM);
   12198          goto decode_success_vfp;
   12199       }
   12200       else if (b16 == 0 && b7 == 1) {
   12201          // FABSS
   12202          putFReg(fD, unop(Iop_AbsF32, getFReg(fM)), condT);
   12203          DIP("fabss%s s%u, s%u\n", nCC(conq), fD, fM);
   12204          goto decode_success_vfp;
   12205       }
   12206       else if (b16 == 1 && b7 == 0) {
   12207          // FNEGS
   12208          putFReg(fD, unop(Iop_NegF32, getFReg(fM)), condT);
   12209          DIP("fnegs%s s%u, s%u\n", nCC(conq), fD, fM);
   12210          goto decode_success_vfp;
   12211       }
   12212       else if (b16 == 1 && b7 == 1) {
   12213          // FSQRTS
   12214          IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   12215          putFReg(fD, binop(Iop_SqrtF32, rm, getFReg(fM)), condT);
   12216          DIP("fsqrts%s s%u, s%u\n", nCC(conq), fD, fM);
   12217          goto decode_success_vfp;
   12218       }
   12219       else
   12220          vassert(0);
   12221 
   12222       /* fall through */
   12223    }
   12224 
   12225    /* ----------------- I <-> S conversions ----------------- */
   12226 
   12227    // F{S,U}ITOS fD, fM
   12228    /* These are more complex than FSITOD/FUITOD.  In the D cases, a 32
   12229       bit int will always fit within the 53 bit mantissa, so there's
   12230       no possibility of a loss of precision, but that's obviously not
   12231       the case here.  Hence this case possibly requires rounding, and
   12232       so it drags in the current rounding mode. */
   12233    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   12234        && BITS4(1,0,0,0) == INSN(19,16)
   12235        && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
   12236        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   12237       UInt bM    = (insn28 >> 5) & 1;
   12238       UInt bD    = (insn28 >> 22) & 1;
   12239       UInt fM    = (INSN(3,0) << 1) | bM;
   12240       UInt fD    = (INSN(15,12) << 1) | bD;
   12241       UInt syned = (insn28 >> 7) & 1;
   12242       IRTemp rmode = newTemp(Ity_I32);
   12243       assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
   12244       if (syned) {
   12245          // FSITOS
   12246          putFReg(fD, binop(Iop_F64toF32,
   12247                            mkexpr(rmode),
   12248                            unop(Iop_I32StoF64,
   12249                                 unop(Iop_ReinterpF32asI32, getFReg(fM)))),
   12250                  condT);
   12251          DIP("fsitos%s s%u, s%u\n", nCC(conq), fD, fM);
   12252       } else {
   12253          // FUITOS
   12254          putFReg(fD, binop(Iop_F64toF32,
   12255                            mkexpr(rmode),
   12256                            unop(Iop_I32UtoF64,
   12257                                 unop(Iop_ReinterpF32asI32, getFReg(fM)))),
   12258                  condT);
   12259          DIP("fuitos%s s%u, s%u\n", nCC(conq), fD, fM);
   12260       }
   12261       goto decode_success_vfp;
   12262    }
   12263 
   12264    // FTO{S,U}IS fD, fM
   12265    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   12266        && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   12267        && BITS4(1,0,1,0) == INSN(11,8)
   12268        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   12269       UInt   bM    = (insn28 >> 5) & 1;
   12270       UInt   bD    = (insn28 >> 22) & 1;
   12271       UInt   fD    = (INSN(15,12) << 1) | bD;
   12272       UInt   fM    = (INSN(3,0) << 1) | bM;
   12273       UInt   bZ    = (insn28 >> 7) & 1;
   12274       UInt   syned = (insn28 >> 16) & 1;
   12275       IRTemp rmode = newTemp(Ity_I32);
   12276       assign(rmode, bZ ? mkU32(Irrm_ZERO)
   12277                        : mkexpr(mk_get_IR_rounding_mode()));
   12278       if (syned) {
   12279          // FTOSIS
   12280          putFReg(fD, unop(Iop_ReinterpI32asF32,
   12281                           binop(Iop_F64toI32S, mkexpr(rmode),
   12282                                 unop(Iop_F32toF64, getFReg(fM)))),
   12283                  condT);
   12284          DIP("ftosi%ss%s s%u, d%u\n", bZ ? "z" : "",
   12285              nCC(conq), fD, fM);
   12286          goto decode_success_vfp;
   12287       } else {
   12288          // FTOUIS
   12289          putFReg(fD, unop(Iop_ReinterpI32asF32,
   12290                           binop(Iop_F64toI32U, mkexpr(rmode),
   12291                                 unop(Iop_F32toF64, getFReg(fM)))),
   12292                  condT);
   12293          DIP("ftoui%ss%s s%u, d%u\n", bZ ? "z" : "",
   12294              nCC(conq), fD, fM);
   12295          goto decode_success_vfp;
   12296       }
   12297    }
   12298 
   12299    /* ----------------- S <-> D conversions ----------------- */
   12300 
   12301    // FCVTDS
   12302    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   12303        && BITS4(0,1,1,1) == INSN(19,16)
   12304        && BITS4(1,0,1,0) == INSN(11,8)
   12305        && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
   12306       UInt dD = INSN(15,12) | (INSN(22,22) << 4);
   12307       UInt bM = (insn28 >> 5) & 1;
   12308       UInt fM = (INSN(3,0) << 1) | bM;
   12309       putDReg(dD, unop(Iop_F32toF64, getFReg(fM)), condT);
   12310       DIP("fcvtds%s d%u, s%u\n", nCC(conq), dD, fM);
   12311       goto decode_success_vfp;
   12312    }
   12313 
   12314    // FCVTSD
   12315    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   12316        && BITS4(0,1,1,1) == INSN(19,16)
   12317        && BITS4(1,0,1,1) == INSN(11,8)
   12318        && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
   12319       UInt   bD    = (insn28 >> 22) & 1;
   12320       UInt   fD    = (INSN(15,12) << 1) | bD;
   12321       UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
   12322       IRTemp rmode = newTemp(Ity_I32);
   12323       assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
   12324       putFReg(fD, binop(Iop_F64toF32, mkexpr(rmode), getDReg(dM)),
   12325                   condT);
   12326       DIP("fcvtsd%s s%u, d%u\n", nCC(conq), fD, dM);
   12327       goto decode_success_vfp;
   12328    }
   12329 
   12330    /* --------------- VCVT fixed<->floating, VFP --------------- */
   12331    /*          31   27   23   19   15 11   7    3
   12332                  28   24   20   16 12    8    4    0
   12333 
   12334                cond 1110 1D11 1p1U Vd 101f x1i0 imm4
   12335 
   12336       VCVT<c>.<Td>.F64 <Dd>, <Dd>, #fbits
   12337       VCVT<c>.<Td>.F32 <Dd>, <Dd>, #fbits
   12338       VCVT<c>.F64.<Td> <Dd>, <Dd>, #fbits
   12339       VCVT<c>.F32.<Td> <Dd>, <Dd>, #fbits
   12340       are of this form.  We only handle a subset of the cases though.
   12341    */
   12342    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   12343        && BITS4(1,0,1,0) == (INSN(19,16) & BITS4(1,0,1,0))
   12344        && BITS3(1,0,1) == INSN(11,9)
   12345        && BITS3(1,0,0) == (INSN(6,4) & BITS3(1,0,1))) {
   12346       UInt bD   = INSN(22,22);
   12347       UInt bOP  = INSN(18,18);
   12348       UInt bU   = INSN(16,16);
   12349       UInt Vd   = INSN(15,12);
   12350       UInt bSF  = INSN(8,8);
   12351       UInt bSX  = INSN(7,7);
   12352       UInt bI   = INSN(5,5);
   12353       UInt imm4 = INSN(3,0);
   12354       Bool to_fixed = bOP == 1;
   12355       Bool dp_op    = bSF == 1;
   12356       Bool unsyned = bU == 1;
   12357       UInt size = bSX == 0 ? 16 : 32;
   12358       Int frac_bits = size - ((imm4 << 1) | bI);
   12359       UInt d = dp_op  ? ((bD << 4) | Vd)  : ((Vd << 1) | bD);
   12360       if (frac_bits >= 1 && frac_bits <= 32 && !to_fixed && size == 32) {
   12361          /* dp_op == 0 : VCVT.F32.{S,U}32 S[d], S[d], #frac_bits */
   12362          /* dp_op == 1 : VCVT.F64.{S,U}32 D[d], D[d], #frac_bits */
   12363          /* This generates really horrible code.  We could potentially
   12364             do much better. */
   12365          IRTemp rmode = newTemp(Ity_I32);
   12366          assign(rmode, mkU32(Irrm_NEAREST)); // rmode that this insn is defd to use
   12367          IRTemp src32 = newTemp(Ity_I32);
   12368          if (dp_op == 0) {
   12369             assign(src32,  unop(Iop_ReinterpF32asI32, getFReg(d)));
   12370          } else {
   12371             /* Example code sequence of using vcvt.f64.s32. The s32 value is
   12372                initialized in s14 but loaded via d7 (s14 is the low half of
   12373                d7), so we need to decode the register using getDReg instead of
   12374                getFReg. Since the conversion size is from s32 to f64, we also
   12375                need to explicitly extract the low half of i64 here.
   12376 
   12377                81a0:       ee07 2a10       vmov            s14, r2
   12378                81a4:       eeba 7bef       vcvt.f64.s32    d7, d7, #1
   12379              */
   12380             IRTemp src64 = newTemp(Ity_I64);
   12381             assign(src64,  unop(Iop_ReinterpF64asI64, getDReg(d)));
   12382             assign(src32, unop(Iop_64to32, mkexpr(src64)));
   12383          }
   12384          IRExpr* as_F64 = unop( unsyned ? Iop_I32UtoF64 : Iop_I32StoF64,
   12385                                 mkexpr(src32 ) );
   12386          IRTemp scale = newTemp(Ity_F64);
   12387          assign(scale, unop(Iop_I32UtoF64, mkU32( 1 << (frac_bits-1) )));
   12388          IRExpr* rm     = mkU32(Irrm_NEAREST);
   12389          IRExpr* resF64 = triop(Iop_DivF64,
   12390                                 rm, as_F64,
   12391                                 triop(Iop_AddF64, rm, mkexpr(scale), mkexpr(scale)));
   12392          if (dp_op == 0) {
   12393             IRExpr* resF32 = binop(Iop_F64toF32, mkexpr(rmode), resF64);
   12394             putFReg(d, resF32, condT);
   12395             DIP("vcvt.f32.%c32, s%u, s%u, #%d\n",
   12396                 unsyned ? 'u' : 's', d, d, frac_bits);
   12397          } else {
   12398             putDReg(d, resF64, condT);
   12399             DIP("vcvt.f64.%c32, d%u, d%u, #%d\n",
   12400                 unsyned ? 'u' : 's', d, d, frac_bits);
   12401          }
   12402          goto decode_success_vfp;
   12403       }
   12404       /* fall through */
   12405    }
   12406 
   12407    /* FAILURE */
   12408    return False;
   12409 
   12410   decode_success_vfp:
   12411    /* Check that any accepted insn really is a CP10 or CP11 insn, iow,
   12412       assert that we aren't accepting, in this fn, insns that actually
   12413       should be handled somewhere else. */
   12414    vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011
   12415    return True;
   12416 
   12417 #  undef INSN
   12418 }
   12419 
   12420 
   12421 /*------------------------------------------------------------*/
   12422 /*--- Instructions in NV (never) space                     ---*/
   12423 /*------------------------------------------------------------*/
   12424 
   12425 /* ARM only */
   12426 /* Translate a NV space instruction.  If successful, returns True and
   12427    *dres may or may not be updated.  If failure, returns False and
   12428    doesn't change *dres nor create any IR.
   12429 
   12430    Note that all NEON instructions (in ARM mode) are handled through
   12431    here, since they are all in NV space.
   12432 */
   12433 static Bool decode_NV_instruction ( /*MOD*/DisResult* dres,
   12434                                     VexArchInfo* archinfo,
   12435                                     UInt insn )
   12436 {
   12437 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
   12438 #  define INSN_COND          SLICE_UInt(insn, 31, 28)
   12439 
   12440    HChar dis_buf[128];
   12441 
   12442    // Should only be called for NV instructions
   12443    vassert(BITS4(1,1,1,1) == INSN_COND);
   12444 
   12445    /* ------------------------ pld ------------------------ */
   12446    if (BITS8(0,1,0,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
   12447        && BITS4(1,1,1,1) == INSN(15,12)) {
   12448       UInt rN    = INSN(19,16);
   12449       UInt imm12 = INSN(11,0);
   12450       UInt bU    = INSN(23,23);
   12451       DIP("pld [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
   12452       return True;
   12453    }
   12454 
   12455    if (BITS8(0,1,1,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
   12456        && BITS4(1,1,1,1) == INSN(15,12)
   12457        && 0 == INSN(4,4)) {
   12458       UInt rN   = INSN(19,16);
   12459       UInt rM   = INSN(3,0);
   12460       UInt imm5 = INSN(11,7);
   12461       UInt sh2  = INSN(6,5);
   12462       UInt bU   = INSN(23,23);
   12463       if (rM != 15) {
   12464          IRExpr* eaE = mk_EA_reg_plusminus_shifted_reg(rN, bU, rM,
   12465                                                        sh2, imm5, dis_buf);
   12466          IRTemp eaT = newTemp(Ity_I32);
   12467          /* Bind eaE to a temp merely for debugging-vex purposes, so we
   12468             can check it's a plausible decoding.  It will get removed
   12469             by iropt a little later on. */
   12470          vassert(eaE);
   12471          assign(eaT, eaE);
   12472          DIP("pld %s\n", dis_buf);
   12473          return True;
   12474       }
   12475       /* fall through */
   12476    }
   12477 
   12478    /* ------------------------ pli ------------------------ */
   12479    if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
   12480        && BITS4(1,1,1,1) == INSN(15,12)) {
   12481       UInt rN    = INSN(19,16);
   12482       UInt imm12 = INSN(11,0);
   12483       UInt bU    = INSN(23,23);
   12484       DIP("pli [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
   12485       return True;
   12486    }
   12487 
   12488    /* --------------------- Interworking branches --------------------- */
   12489 
   12490    // BLX (1), viz, unconditional branch and link to R15+simm24
   12491    // and set CPSR.T = 1, that is, switch to Thumb mode
   12492    if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) {
   12493       UInt bitH   = INSN(24,24);
   12494       Int  uimm24 = INSN(23,0);
   12495       Int  simm24 = (((uimm24 << 8) >> 8) << 2) + (bitH << 1);
   12496       /* Now this is a bit tricky.  Since we're decoding an ARM insn,
   12497          it is implies that CPSR.T == 0.  Hence the current insn's
   12498          address is guaranteed to be of the form X--(30)--X00.  So, no
   12499          need to mask any bits off it.  But need to set the lowest bit
   12500          to 1 to denote we're in Thumb mode after this, since
   12501          guest_R15T has CPSR.T as the lowest bit.  And we can't chase
   12502          into the call, so end the block at this point. */
   12503       UInt dst = guest_R15_curr_instr_notENC + 8 + (simm24 | 1);
   12504       putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
   12505                     IRTemp_INVALID/*because AL*/, Ijk_Boring );
   12506       llPutIReg(15, mkU32(dst));
   12507       dres->jk_StopHere = Ijk_Call;
   12508       dres->whatNext    = Dis_StopHere;
   12509       DIP("blx 0x%x (and switch to Thumb mode)\n", dst - 1);
   12510       return True;
   12511    }
   12512 
   12513    /* ------------------- v7 barrier insns ------------------- */
   12514    switch (insn) {
   12515       case 0xF57FF06F: /* ISB */
   12516          stmt( IRStmt_MBE(Imbe_Fence) );
   12517          DIP("ISB\n");
   12518          return True;
   12519       case 0xF57FF04F: /* DSB sy */
   12520       case 0xF57FF04E: /* DSB st */
   12521       case 0xF57FF04B: /* DSB ish */
   12522       case 0xF57FF04A: /* DSB ishst */
   12523       case 0xF57FF047: /* DSB nsh */
   12524       case 0xF57FF046: /* DSB nshst */
   12525       case 0xF57FF043: /* DSB osh */
   12526       case 0xF57FF042: /* DSB oshst */
   12527          stmt( IRStmt_MBE(Imbe_Fence) );
   12528          DIP("DSB\n");
   12529          return True;
   12530       case 0xF57FF05F: /* DMB sy */
   12531       case 0xF57FF05E: /* DMB st */
   12532       case 0xF57FF05B: /* DMB ish */
   12533       case 0xF57FF05A: /* DMB ishst */
   12534       case 0xF57FF057: /* DMB nsh */
   12535       case 0xF57FF056: /* DMB nshst */
   12536       case 0xF57FF053: /* DMB osh */
   12537       case 0xF57FF052: /* DMB oshst */
   12538          stmt( IRStmt_MBE(Imbe_Fence) );
   12539          DIP("DMB\n");
   12540          return True;
   12541       default:
   12542          break;
   12543    }
   12544 
   12545    /* ------------------- CLREX ------------------ */
   12546    if (insn == 0xF57FF01F) {
   12547       /* AFAICS, this simply cancels a (all?) reservations made by a
   12548          (any?) preceding LDREX(es).  Arrange to hand it through to
   12549          the back end. */
   12550       stmt( IRStmt_MBE(Imbe_CancelReservation) );
   12551       DIP("clrex\n");
   12552       return True;
   12553    }
   12554 
   12555    /* ------------------- NEON ------------------- */
   12556    if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
   12557       Bool ok_neon = decode_NEON_instruction(
   12558                         dres, insn, IRTemp_INVALID/*unconditional*/,
   12559                         False/*!isT*/
   12560                      );
   12561       if (ok_neon)
   12562          return True;
   12563    }
   12564 
   12565    // unrecognised
   12566    return False;
   12567 
   12568 #  undef INSN_COND
   12569 #  undef INSN
   12570 }
   12571 
   12572 
   12573 /*------------------------------------------------------------*/
   12574 /*--- Disassemble a single ARM instruction                 ---*/
   12575 /*------------------------------------------------------------*/
   12576 
   12577 /* Disassemble a single ARM instruction into IR.  The instruction is
   12578    located in host memory at guest_instr, and has (decoded) guest IP
   12579    of guest_R15_curr_instr_notENC, which will have been set before the
   12580    call here. */
   12581 
   12582 static
   12583 DisResult disInstr_ARM_WRK (
   12584              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
   12585              Bool         resteerCisOk,
   12586              void*        callback_opaque,
   12587              UChar*       guest_instr,
   12588              VexArchInfo* archinfo,
   12589              VexAbiInfo*  abiinfo
   12590           )
   12591 {
   12592    // A macro to fish bits out of 'insn'.
   12593 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
   12594 #  define INSN_COND          SLICE_UInt(insn, 31, 28)
   12595 
   12596    DisResult dres;
   12597    UInt      insn;
   12598    //Bool      allow_VFP = False;
   12599    //UInt      hwcaps = archinfo->hwcaps;
   12600    IRTemp    condT; /* :: Ity_I32 */
   12601    UInt      summary;
   12602    HChar     dis_buf[128];  // big enough to hold LDMIA etc text
   12603 
   12604    /* What insn variants are we supporting today? */
   12605    //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
   12606    // etc etc
   12607 
   12608    /* Set result defaults. */
   12609    dres.whatNext    = Dis_Continue;
   12610    dres.len         = 4;
   12611    dres.continueAt  = 0;
   12612    dres.jk_StopHere = Ijk_INVALID;
   12613 
   12614    /* Set default actions for post-insn handling of writes to r15, if
   12615       required. */
   12616    r15written = False;
   12617    r15guard   = IRTemp_INVALID; /* unconditional */
   12618    r15kind    = Ijk_Boring;
   12619 
   12620    /* At least this is simple on ARM: insns are all 4 bytes long, and
   12621       4-aligned.  So just fish the whole thing out of memory right now
   12622       and have done. */
   12623    insn = getUIntLittleEndianly( guest_instr );
   12624 
   12625    if (0) vex_printf("insn: 0x%x\n", insn);
   12626 
   12627    DIP("\t(arm) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
   12628 
   12629    vassert(0 == (guest_R15_curr_instr_notENC & 3));
   12630 
   12631    /* ----------------------------------------------------------- */
   12632 
   12633    /* Spot "Special" instructions (see comment at top of file). */
   12634    {
   12635       UChar* code = (UChar*)guest_instr;
   12636       /* Spot the 16-byte preamble:
   12637 
   12638          e1a0c1ec  mov r12, r12, ROR #3
   12639          e1a0c6ec  mov r12, r12, ROR #13
   12640          e1a0ceec  mov r12, r12, ROR #29
   12641          e1a0c9ec  mov r12, r12, ROR #19
   12642       */
   12643       UInt word1 = 0xE1A0C1EC;
   12644       UInt word2 = 0xE1A0C6EC;
   12645       UInt word3 = 0xE1A0CEEC;
   12646       UInt word4 = 0xE1A0C9EC;
   12647       if (getUIntLittleEndianly(code+ 0) == word1 &&
   12648           getUIntLittleEndianly(code+ 4) == word2 &&
   12649           getUIntLittleEndianly(code+ 8) == word3 &&
   12650           getUIntLittleEndianly(code+12) == word4) {
   12651          /* Got a "Special" instruction preamble.  Which one is it? */
   12652          if (getUIntLittleEndianly(code+16) == 0xE18AA00A
   12653                                                /* orr r10,r10,r10 */) {
   12654             /* R3 = client_request ( R4 ) */
   12655             DIP("r3 = client_request ( %%r4 )\n");
   12656             llPutIReg(15, mkU32( guest_R15_curr_instr_notENC + 20 ));
   12657             dres.jk_StopHere = Ijk_ClientReq;
   12658             dres.whatNext    = Dis_StopHere;
   12659             goto decode_success;
   12660          }
   12661          else
   12662          if (getUIntLittleEndianly(code+16) == 0xE18BB00B
   12663                                                /* orr r11,r11,r11 */) {
   12664             /* R3 = guest_NRADDR */
   12665             DIP("r3 = guest_NRADDR\n");
   12666             dres.len = 20;
   12667             llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
   12668             goto decode_success;
   12669          }
   12670          else
   12671          if (getUIntLittleEndianly(code+16) == 0xE18CC00C
   12672                                                /* orr r12,r12,r12 */) {
   12673             /*  branch-and-link-to-noredir R4 */
   12674             DIP("branch-and-link-to-noredir r4\n");
   12675             llPutIReg(14, mkU32( guest_R15_curr_instr_notENC + 20) );
   12676             llPutIReg(15, llGetIReg(4));
   12677             dres.jk_StopHere = Ijk_NoRedir;
   12678             dres.whatNext    = Dis_StopHere;
   12679             goto decode_success;
   12680          }
   12681          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   12682             can print the insn following the Special-insn preamble. */
   12683          insn = getUIntLittleEndianly(code+16);
   12684          goto decode_failure;
   12685          /*NOTREACHED*/
   12686       }
   12687 
   12688    }
   12689 
   12690    /* ----------------------------------------------------------- */
   12691 
   12692    /* Main ARM instruction decoder starts here. */
   12693 
   12694    /* Deal with the condition.  Strategy is to merely generate a
   12695       condition temporary at this point (or IRTemp_INVALID, meaning
   12696       unconditional).  We leave it to lower-level instruction decoders
   12697       to decide whether they can generate straight-line code, or
   12698       whether they must generate a side exit before the instruction.
   12699       condT :: Ity_I32 and is always either zero or one. */
   12700    condT = IRTemp_INVALID;
   12701    switch ( (ARMCondcode)INSN_COND ) {
   12702       case ARMCondNV: {
   12703          // Illegal instruction prior to v5 (see ARM ARM A3-5), but
   12704          // some cases are acceptable
   12705          Bool ok = decode_NV_instruction(&dres, archinfo, insn);
   12706          if (ok)
   12707             goto decode_success;
   12708          else
   12709             goto decode_failure;
   12710       }
   12711       case ARMCondAL: // Always executed
   12712          break;
   12713       case ARMCondEQ: case ARMCondNE: case ARMCondHS: case ARMCondLO:
   12714       case ARMCondMI: case ARMCondPL: case ARMCondVS: case ARMCondVC:
   12715       case ARMCondHI: case ARMCondLS: case ARMCondGE: case ARMCondLT:
   12716       case ARMCondGT: case ARMCondLE:
   12717          condT = newTemp(Ity_I32);
   12718          assign( condT, mk_armg_calculate_condition( INSN_COND ));
   12719          break;
   12720    }
   12721 
   12722    /* ----------------------------------------------------------- */
   12723    /* -- ARMv5 integer instructions                            -- */
   12724    /* ----------------------------------------------------------- */
   12725 
   12726    /* ---------------- Data processing ops ------------------- */
   12727 
   12728    if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0))
   12729        && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) {
   12730       IRTemp  shop = IRTemp_INVALID; /* shifter operand */
   12731       IRTemp  shco = IRTemp_INVALID; /* shifter carry out */
   12732       UInt    rD   = (insn >> 12) & 0xF; /* 15:12 */
   12733       UInt    rN   = (insn >> 16) & 0xF; /* 19:16 */
   12734       UInt    bitS = (insn >> 20) & 1; /* 20:20 */
   12735       IRTemp  rNt  = IRTemp_INVALID;
   12736       IRTemp  res  = IRTemp_INVALID;
   12737       IRTemp  oldV = IRTemp_INVALID;
   12738       IRTemp  oldC = IRTemp_INVALID;
   12739       HChar*  name = NULL;
   12740       IROp    op   = Iop_INVALID;
   12741       Bool    ok;
   12742 
   12743       switch (INSN(24,21)) {
   12744 
   12745          /* --------- ADD, SUB, AND, OR --------- */
   12746          case BITS4(0,1,0,0): /* ADD:  Rd = Rn + shifter_operand */
   12747             name = "add"; op = Iop_Add32; goto rd_eq_rn_op_SO;
   12748          case BITS4(0,0,1,0): /* SUB:  Rd = Rn - shifter_operand */
   12749             name = "sub"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
   12750          case BITS4(0,0,1,1): /* RSB:  Rd = shifter_operand - Rn */
   12751             name = "rsb"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
   12752          case BITS4(0,0,0,0): /* AND:  Rd = Rn & shifter_operand */
   12753             name = "and"; op = Iop_And32; goto rd_eq_rn_op_SO;
   12754          case BITS4(1,1,0,0): /* OR:   Rd = Rn | shifter_operand */
   12755             name = "orr"; op = Iop_Or32; goto rd_eq_rn_op_SO;
   12756          case BITS4(0,0,0,1): /* EOR:  Rd = Rn ^ shifter_operand */
   12757             name = "eor"; op = Iop_Xor32; goto rd_eq_rn_op_SO;
   12758          case BITS4(1,1,1,0): /* BIC:  Rd = Rn & ~shifter_operand */
   12759             name = "bic"; op = Iop_And32; goto rd_eq_rn_op_SO;
   12760          rd_eq_rn_op_SO: {
   12761             Bool isRSB = False;
   12762             Bool isBIC = False;
   12763             switch (INSN(24,21)) {
   12764                case BITS4(0,0,1,1):
   12765                   vassert(op == Iop_Sub32); isRSB = True; break;
   12766                case BITS4(1,1,1,0):
   12767                   vassert(op == Iop_And32); isBIC = True; break;
   12768                default:
   12769                   break;
   12770             }
   12771             rNt = newTemp(Ity_I32);
   12772             assign(rNt, getIRegA(rN));
   12773             ok = mk_shifter_operand(
   12774                     INSN(25,25), INSN(11,0),
   12775                     &shop, bitS ? &shco : NULL, dis_buf
   12776                  );
   12777             if (!ok)
   12778                break;
   12779             res = newTemp(Ity_I32);
   12780             // compute the main result
   12781             if (isRSB) {
   12782                // reverse-subtract: shifter_operand - Rn
   12783                vassert(op == Iop_Sub32);
   12784                assign(res, binop(op, mkexpr(shop), mkexpr(rNt)) );
   12785             } else if (isBIC) {
   12786                // andn: shifter_operand & ~Rn
   12787                vassert(op == Iop_And32);
   12788                assign(res, binop(op, mkexpr(rNt),
   12789                                      unop(Iop_Not32, mkexpr(shop))) );
   12790             } else {
   12791                // normal: Rn op shifter_operand
   12792                assign(res, binop(op, mkexpr(rNt), mkexpr(shop)) );
   12793             }
   12794             // but don't commit it until after we've finished
   12795             // all necessary reads from the guest state
   12796             if (bitS
   12797                 && (op == Iop_And32 || op == Iop_Or32 || op == Iop_Xor32)) {
   12798                oldV = newTemp(Ity_I32);
   12799                assign( oldV, mk_armg_calculate_flag_v() );
   12800             }
   12801             // can't safely read guest state after here
   12802             // now safe to put the main result
   12803             putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   12804             // XXXX!! not safe to read any guest state after
   12805             // this point (I think the code below doesn't do that).
   12806             if (!bitS)
   12807                vassert(shco == IRTemp_INVALID);
   12808             /* Update the flags thunk if necessary */
   12809             if (bitS) {
   12810                vassert(shco != IRTemp_INVALID);
   12811                switch (op) {
   12812                   case Iop_Add32:
   12813                      setFlags_D1_D2( ARMG_CC_OP_ADD, rNt, shop, condT );
   12814                      break;
   12815                   case Iop_Sub32:
   12816                      if (isRSB) {
   12817                         setFlags_D1_D2( ARMG_CC_OP_SUB, shop, rNt, condT );
   12818                      } else {
   12819                         setFlags_D1_D2( ARMG_CC_OP_SUB, rNt, shop, condT );
   12820                      }
   12821                      break;
   12822                   case Iop_And32: /* BIC and AND set the flags the same */
   12823                   case Iop_Or32:
   12824                   case Iop_Xor32:
   12825                      // oldV has been read just above
   12826                      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
   12827                                         res, shco, oldV, condT );
   12828                      break;
   12829                   default:
   12830                      vassert(0);
   12831                }
   12832             }
   12833             DIP("%s%s%s r%u, r%u, %s\n",
   12834                 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
   12835             goto decode_success;
   12836          }
   12837 
   12838          /* --------- MOV, MVN --------- */
   12839          case BITS4(1,1,0,1):   /* MOV: Rd = shifter_operand */
   12840          case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */
   12841             Bool isMVN = INSN(24,21) == BITS4(1,1,1,1);
   12842             IRTemp jk = Ijk_Boring;
   12843             if (rN != 0)
   12844                break; /* rN must be zero */
   12845             ok = mk_shifter_operand(
   12846                     INSN(25,25), INSN(11,0),
   12847                     &shop, bitS ? &shco : NULL, dis_buf
   12848                  );
   12849             if (!ok)
   12850                break;
   12851             res = newTemp(Ity_I32);
   12852             assign( res, isMVN ? unop(Iop_Not32, mkexpr(shop))
   12853                                : mkexpr(shop) );
   12854             if (bitS) {
   12855                vassert(shco != IRTemp_INVALID);
   12856                oldV = newTemp(Ity_I32);
   12857                assign( oldV, mk_armg_calculate_flag_v() );
   12858             } else {
   12859                vassert(shco == IRTemp_INVALID);
   12860             }
   12861             /* According to the Cortex A8 TRM Sec. 5.2.1, MOV PC, r14 is a
   12862                 return for purposes of branch prediction. */
   12863             if (!isMVN && INSN(11,0) == 14) {
   12864               jk = Ijk_Ret;
   12865             }
   12866             // can't safely read guest state after here
   12867             putIRegA( rD, mkexpr(res), condT, jk );
   12868             /* Update the flags thunk if necessary */
   12869             if (bitS) {
   12870                setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
   12871                                   res, shco, oldV, condT );
   12872             }
   12873             DIP("%s%s%s r%u, %s\n",
   12874                 isMVN ? "mvn" : "mov",
   12875                 nCC(INSN_COND), bitS ? "s" : "", rD, dis_buf );
   12876             goto decode_success;
   12877          }
   12878 
   12879          /* --------- CMP --------- */
   12880          case BITS4(1,0,1,0):   /* CMP:  (void) Rn - shifter_operand */
   12881          case BITS4(1,0,1,1): { /* CMN:  (void) Rn + shifter_operand */
   12882             Bool isCMN = INSN(24,21) == BITS4(1,0,1,1);
   12883             if (rD != 0)
   12884                break; /* rD must be zero */
   12885             if (bitS == 0)
   12886                break; /* if S (bit 20) is not set, it's not CMP/CMN */
   12887             rNt = newTemp(Ity_I32);
   12888             assign(rNt, getIRegA(rN));
   12889             ok = mk_shifter_operand(
   12890                     INSN(25,25), INSN(11,0),
   12891                     &shop, NULL, dis_buf
   12892                  );
   12893             if (!ok)
   12894                break;
   12895             // can't safely read guest state after here
   12896             /* Update the flags thunk. */
   12897             setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   12898                             rNt, shop, condT );
   12899             DIP("%s%s r%u, %s\n",
   12900                 isCMN ? "cmn" : "cmp",
   12901                 nCC(INSN_COND), rN, dis_buf );
   12902             goto decode_success;
   12903          }
   12904 
   12905          /* --------- TST --------- */
   12906          case BITS4(1,0,0,0):   /* TST:  (void) Rn & shifter_operand */
   12907          case BITS4(1,0,0,1): { /* TEQ:  (void) Rn ^ shifter_operand */
   12908             Bool isTEQ = INSN(24,21) == BITS4(1,0,0,1);
   12909             if (rD != 0)
   12910                break; /* rD must be zero */
   12911             if (bitS == 0)
   12912                break; /* if S (bit 20) is not set, it's not TST/TEQ */
   12913             rNt = newTemp(Ity_I32);
   12914             assign(rNt, getIRegA(rN));
   12915             ok = mk_shifter_operand(
   12916                     INSN(25,25), INSN(11,0),
   12917                     &shop, &shco, dis_buf
   12918                  );
   12919             if (!ok)
   12920                break;
   12921             /* Update the flags thunk. */
   12922             res = newTemp(Ity_I32);
   12923             assign( res, binop(isTEQ ? Iop_Xor32 : Iop_And32,
   12924                                mkexpr(rNt), mkexpr(shop)) );
   12925             oldV = newTemp(Ity_I32);
   12926             assign( oldV, mk_armg_calculate_flag_v() );
   12927             // can't safely read guest state after here
   12928             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
   12929                                res, shco, oldV, condT );
   12930             DIP("%s%s r%u, %s\n",
   12931                 isTEQ ? "teq" : "tst",
   12932                 nCC(INSN_COND), rN, dis_buf );
   12933             goto decode_success;
   12934          }
   12935 
   12936          /* --------- ADC, SBC, RSC --------- */
   12937          case BITS4(0,1,0,1): /* ADC:  Rd = Rn + shifter_operand + oldC */
   12938             name = "adc"; goto rd_eq_rn_op_SO_op_oldC;
   12939          case BITS4(0,1,1,0): /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
   12940             name = "sbc"; goto rd_eq_rn_op_SO_op_oldC;
   12941          case BITS4(0,1,1,1): /* RSC:  Rd = shifter_operand - Rn - (oldC ^ 1) */
   12942             name = "rsc"; goto rd_eq_rn_op_SO_op_oldC;
   12943          rd_eq_rn_op_SO_op_oldC: {
   12944             // FIXME: shco isn't used for anything.  Get rid of it.
   12945             rNt = newTemp(Ity_I32);
   12946             assign(rNt, getIRegA(rN));
   12947             ok = mk_shifter_operand(
   12948                     INSN(25,25), INSN(11,0),
   12949                     &shop, bitS ? &shco : NULL, dis_buf
   12950                  );
   12951             if (!ok)
   12952                break;
   12953             oldC = newTemp(Ity_I32);
   12954             assign( oldC, mk_armg_calculate_flag_c() );
   12955             res = newTemp(Ity_I32);
   12956             // compute the main result
   12957             switch (INSN(24,21)) {
   12958                case BITS4(0,1,0,1): /* ADC */
   12959                   assign(res,
   12960                          binop(Iop_Add32,
   12961                                binop(Iop_Add32, mkexpr(rNt), mkexpr(shop)),
   12962                                mkexpr(oldC) ));
   12963                   break;
   12964                case BITS4(0,1,1,0): /* SBC */
   12965                   assign(res,
   12966                          binop(Iop_Sub32,
   12967                                binop(Iop_Sub32, mkexpr(rNt), mkexpr(shop)),
   12968                                binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   12969                   break;
   12970                case BITS4(0,1,1,1): /* RSC */
   12971                   assign(res,
   12972                          binop(Iop_Sub32,
   12973                                binop(Iop_Sub32, mkexpr(shop), mkexpr(rNt)),
   12974                                binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   12975                   break;
   12976                default:
   12977                   vassert(0);
   12978             }
   12979             // but don't commit it until after we've finished
   12980             // all necessary reads from the guest state
   12981             // now safe to put the main result
   12982             putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   12983             // XXXX!! not safe to read any guest state after
   12984             // this point (I think the code below doesn't do that).
   12985             if (!bitS)
   12986                vassert(shco == IRTemp_INVALID);
   12987             /* Update the flags thunk if necessary */
   12988             if (bitS) {
   12989                vassert(shco != IRTemp_INVALID);
   12990                switch (INSN(24,21)) {
   12991                   case BITS4(0,1,0,1): /* ADC */
   12992                      setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
   12993                                         rNt, shop, oldC, condT );
   12994                      break;
   12995                   case BITS4(0,1,1,0): /* SBC */
   12996                      setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   12997                                         rNt, shop, oldC, condT );
   12998                      break;
   12999                   case BITS4(0,1,1,1): /* RSC */
   13000                      setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   13001                                         shop, rNt, oldC, condT );
   13002                      break;
   13003                   default:
   13004                      vassert(0);
   13005                }
   13006             }
   13007             DIP("%s%s%s r%u, r%u, %s\n",
   13008                 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
   13009             goto decode_success;
   13010          }
   13011 
   13012          /* --------- ??? --------- */
   13013          default:
   13014             break;
   13015       }
   13016    } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */
   13017 
   13018    /* --------------------- Load/store (ubyte & word) -------- */
   13019    // LDR STR LDRB STRB
   13020    /*                 31   27   23   19 15 11    6   4 3  # highest bit
   13021                         28   24   20 16 12
   13022       A5-20   1 | 16  cond 0101 UB0L Rn Rd imm12
   13023       A5-22   1 | 32  cond 0111 UBOL Rn Rd imm5  sh2 0 Rm
   13024       A5-24   2 | 16  cond 0101 UB1L Rn Rd imm12
   13025       A5-26   2 | 32  cond 0111 UB1L Rn Rd imm5  sh2 0 Rm
   13026       A5-28   3 | 16  cond 0100 UB0L Rn Rd imm12
   13027       A5-32   3 | 32  cond 0110 UB0L Rn Rd imm5  sh2 0 Rm
   13028    */
   13029    /* case coding:
   13030              1   at-ea               (access at ea)
   13031              2   at-ea-then-upd      (access at ea, then Rn = ea)
   13032              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
   13033       ea coding
   13034              16  Rn +/- imm12
   13035              32  Rn +/- Rm sh2 imm5
   13036    */
   13037    /* Quickly skip over all of this for hopefully most instructions */
   13038    if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0))
   13039       goto after_load_store_ubyte_or_word;
   13040 
   13041    summary = 0;
   13042 
   13043    /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) {
   13044       summary = 1 | 16;
   13045    }
   13046    else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0
   13047                                           && INSN(4,4) == 0) {
   13048       summary = 1 | 32;
   13049    }
   13050    else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) {
   13051       summary = 2 | 16;
   13052    }
   13053    else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1
   13054                                           && INSN(4,4) == 0) {
   13055       summary = 2 | 32;
   13056    }
   13057    else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) {
   13058       summary = 3 | 16;
   13059    }
   13060    else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0
   13061                                           && INSN(4,4) == 0) {
   13062       summary = 3 | 32;
   13063    }
   13064    else goto after_load_store_ubyte_or_word;
   13065 
   13066    { UInt rN = (insn >> 16) & 0xF; /* 19:16 */
   13067      UInt rD = (insn >> 12) & 0xF; /* 15:12 */
   13068      UInt rM = (insn >> 0)  & 0xF; /*  3:0  */
   13069      UInt bU = (insn >> 23) & 1;      /* 23 */
   13070      UInt bB = (insn >> 22) & 1;      /* 22 */
   13071      UInt bL = (insn >> 20) & 1;      /* 20 */
   13072      UInt imm12 = (insn >> 0) & 0xFFF; /* 11:0 */
   13073      UInt imm5  = (insn >> 7) & 0x1F;  /* 11:7 */
   13074      UInt sh2   = (insn >> 5) & 3;     /* 6:5 */
   13075 
   13076      /* Skip some invalid cases, which would lead to two competing
   13077         updates to the same register, or which are otherwise
   13078         disallowed by the spec. */
   13079      switch (summary) {
   13080         case 1 | 16:
   13081            break;
   13082         case 1 | 32:
   13083            if (rM == 15) goto after_load_store_ubyte_or_word;
   13084            break;
   13085         case 2 | 16: case 3 | 16:
   13086            if (rN == 15) goto after_load_store_ubyte_or_word;
   13087            if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
   13088            break;
   13089         case 2 | 32: case 3 | 32:
   13090            if (rM == 15) goto after_load_store_ubyte_or_word;
   13091            if (rN == 15) goto after_load_store_ubyte_or_word;
   13092            if (rN == rM) goto after_load_store_ubyte_or_word;
   13093            if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
   13094            break;
   13095         default:
   13096            vassert(0);
   13097      }
   13098 
   13099      /* Now, we can't do a conditional load or store, since that very
   13100         likely will generate an exception.  So we have to take a side
   13101         exit at this point if the condition is false. */
   13102      if (condT != IRTemp_INVALID) {
   13103         mk_skip_over_A32_if_cond_is_false( condT );
   13104         condT = IRTemp_INVALID;
   13105      }
   13106      /* Ok, now we're unconditional.  Do the load or store. */
   13107 
   13108      /* compute the effective address.  Bind it to a tmp since we
   13109         may need to use it twice. */
   13110      IRExpr* eaE = NULL;
   13111      switch (summary & 0xF0) {
   13112         case 16:
   13113            eaE = mk_EA_reg_plusminus_imm12( rN, bU, imm12, dis_buf );
   13114            break;
   13115         case 32:
   13116            eaE = mk_EA_reg_plusminus_shifted_reg( rN, bU, rM, sh2, imm5,
   13117                                                   dis_buf );
   13118            break;
   13119      }
   13120      vassert(eaE);
   13121      IRTemp eaT = newTemp(Ity_I32);
   13122      assign(eaT, eaE);
   13123 
   13124      /* get the old Rn value */
   13125      IRTemp rnT = newTemp(Ity_I32);
   13126      assign(rnT, getIRegA(rN));
   13127 
   13128      /* decide on the transfer address */
   13129      IRTemp taT = IRTemp_INVALID;
   13130      switch (summary & 0x0F) {
   13131         case 1: case 2: taT = eaT; break;
   13132         case 3:         taT = rnT; break;
   13133      }
   13134      vassert(taT != IRTemp_INVALID);
   13135 
   13136      if (bL == 0) {
   13137        /* Store.  If necessary, update the base register before the
   13138           store itself, so that the common idiom of "str rX, [sp,
   13139           #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push
   13140           rX") doesn't cause Memcheck to complain that the access is
   13141           below the stack pointer.  Also, not updating sp before the
   13142           store confuses Valgrind's dynamic stack-extending logic.  So
   13143           do it before the store.  Hence we need to snarf the store
   13144           data before doing the basereg update. */
   13145 
   13146         /* get hold of the data to be stored */
   13147         IRTemp rDt = newTemp(Ity_I32);
   13148         assign(rDt, getIRegA(rD));
   13149 
   13150         /* Update Rn if necessary. */
   13151         switch (summary & 0x0F) {
   13152            case 2: case 3:
   13153               putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   13154               break;
   13155         }
   13156 
   13157         /* generate the transfer */
   13158         if (bB == 0) { // word store
   13159            storeLE( mkexpr(taT), mkexpr(rDt) );
   13160         } else { // byte store
   13161            vassert(bB == 1);
   13162            storeLE( mkexpr(taT), unop(Iop_32to8, mkexpr(rDt)) );
   13163         }
   13164 
   13165      } else {
   13166         /* Load */
   13167         vassert(bL == 1);
   13168 
   13169         /* generate the transfer */
   13170         if (bB == 0) { // word load
   13171            IRTemp jk = Ijk_Boring;
   13172            /* According to the Cortex A8 TRM Sec. 5.2.1, LDR(1) with r13 as the
   13173                base register and PC as the destination register is a return for
   13174                purposes of branch prediction.
   13175               The ARM ARM Sec. C9.10.1 further specifies that it must use a
   13176                post-increment by immediate addressing mode to be counted in
   13177                event 0x0E (Procedure return).*/
   13178            if (rN == 13 && summary == (3 | 16) && bB == 0) {
   13179               jk = Ijk_Ret;
   13180            }
   13181            putIRegA( rD, loadLE(Ity_I32, mkexpr(taT)),
   13182                      IRTemp_INVALID, jk );
   13183         } else { // byte load
   13184            vassert(bB == 1);
   13185            putIRegA( rD, unop(Iop_8Uto32, loadLE(Ity_I8, mkexpr(taT))),
   13186                      IRTemp_INVALID, Ijk_Boring );
   13187         }
   13188 
   13189         /* Update Rn if necessary. */
   13190         switch (summary & 0x0F) {
   13191            case 2: case 3:
   13192               // should be assured by logic above:
   13193               if (bL == 1)
   13194                  vassert(rD != rN); /* since we just wrote rD */
   13195               putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   13196               break;
   13197         }
   13198      }
   13199 
   13200      switch (summary & 0x0F) {
   13201         case 1:  DIP("%sr%s%s r%u, %s\n",
   13202                      bL == 0 ? "st" : "ld",
   13203                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
   13204                  break;
   13205         case 2:  DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
   13206                      bL == 0 ? "st" : "ld",
   13207                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
   13208                  break;
   13209         case 3:  DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
   13210                      bL == 0 ? "st" : "ld",
   13211                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
   13212                  break;
   13213         default: vassert(0);
   13214      }
   13215 
   13216      /* XXX deal with alignment constraints */
   13217 
   13218      goto decode_success;
   13219 
   13220      /* Complications:
   13221 
   13222         For all loads: if the Amode specifies base register
   13223         writeback, and the same register is specified for Rd and Rn,
   13224         the results are UNPREDICTABLE.
   13225 
   13226         For all loads and stores: if R15 is written, branch to
   13227         that address afterwards.
   13228 
   13229         STRB: straightforward
   13230         LDRB: loaded data is zero extended
   13231         STR:  lowest 2 bits of address are ignored
   13232         LDR:  if the lowest 2 bits of the address are nonzero
   13233               then the loaded value is rotated right by 8 * the lowest 2 bits
   13234      */
   13235    }
   13236 
   13237   after_load_store_ubyte_or_word:
   13238 
   13239    /* --------------------- Load/store (sbyte & hword) -------- */
   13240    // LDRH LDRSH STRH LDRSB
   13241    /*                 31   27   23   19 15 11   7    3     # highest bit
   13242                         28   24   20 16 12    8    4    0
   13243       A5-36   1 | 16  cond 0001 U10L Rn Rd im4h 1SH1 im4l
   13244       A5-38   1 | 32  cond 0001 U00L Rn Rd 0000 1SH1 Rm
   13245       A5-40   2 | 16  cond 0001 U11L Rn Rd im4h 1SH1 im4l
   13246       A5-42   2 | 32  cond 0001 U01L Rn Rd 0000 1SH1 Rm
   13247       A5-44   3 | 16  cond 0000 U10L Rn Rd im4h 1SH1 im4l
   13248       A5-46   3 | 32  cond 0000 U00L Rn Rd 0000 1SH1 Rm
   13249    */
   13250    /* case coding:
   13251              1   at-ea               (access at ea)
   13252              2   at-ea-then-upd      (access at ea, then Rn = ea)
   13253              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
   13254       ea coding
   13255              16  Rn +/- imm8
   13256              32  Rn +/- Rm
   13257    */
   13258    /* Quickly skip over all of this for hopefully most instructions */
   13259    if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
   13260       goto after_load_store_sbyte_or_hword;
   13261 
   13262    /* Check the "1SH1" thing. */
   13263    if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1))
   13264       goto after_load_store_sbyte_or_hword;
   13265 
   13266    summary = 0;
   13267 
   13268    /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) {
   13269       summary = 1 | 16;
   13270    }
   13271    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) {
   13272       summary = 1 | 32;
   13273    }
   13274    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) {
   13275       summary = 2 | 16;
   13276    }
   13277    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) {
   13278       summary = 2 | 32;
   13279    }
   13280    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) {
   13281       summary = 3 | 16;
   13282    }
   13283    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) {
   13284       summary = 3 | 32;
   13285    }
   13286    else goto after_load_store_sbyte_or_hword;
   13287 
   13288    { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
   13289      UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
   13290      UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
   13291      UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
   13292      UInt bL   = (insn >> 20) & 1;   /* 20 L=1 load, L=0 store */
   13293      UInt bH   = (insn >> 5) & 1;    /* H=1 halfword, H=0 byte */
   13294      UInt bS   = (insn >> 6) & 1;    /* S=1 signed, S=0 unsigned */
   13295      UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
   13296 
   13297      /* Skip combinations that are either meaningless or already
   13298         handled by main word-or-unsigned-byte load-store
   13299         instructions. */
   13300      if (bS == 0 && bH == 0) /* "unsigned byte" */
   13301         goto after_load_store_sbyte_or_hword;
   13302      if (bS == 1 && bL == 0) /* "signed store" */
   13303         goto after_load_store_sbyte_or_hword;
   13304 
   13305      /* Require 11:8 == 0 for Rn +/- Rm cases */
   13306      if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
   13307         goto after_load_store_sbyte_or_hword;
   13308 
   13309      /* Skip some invalid cases, which would lead to two competing
   13310         updates to the same register, or which are otherwise
   13311         disallowed by the spec. */
   13312      switch (summary) {
   13313         case 1 | 16:
   13314            break;
   13315         case 1 | 32:
   13316            if (rM == 15) goto after_load_store_sbyte_or_hword;
   13317            break;
   13318         case 2 | 16: case 3 | 16:
   13319            if (rN == 15) goto after_load_store_sbyte_or_hword;
   13320            if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
   13321            break;
   13322         case 2 | 32: case 3 | 32:
   13323            if (rM == 15) goto after_load_store_sbyte_or_hword;
   13324            if (rN == 15) goto after_load_store_sbyte_or_hword;
   13325            if (rN == rM) goto after_load_store_sbyte_or_hword;
   13326            if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
   13327            break;
   13328         default:
   13329            vassert(0);
   13330      }
   13331 
   13332      /* Now, we can't do a conditional load or store, since that very
   13333         likely will generate an exception.  So we have to take a side
   13334         exit at this point if the condition is false. */
   13335      if (condT != IRTemp_INVALID) {
   13336         mk_skip_over_A32_if_cond_is_false( condT );
   13337         condT = IRTemp_INVALID;
   13338      }
   13339      /* Ok, now we're unconditional.  Do the load or store. */
   13340 
   13341      /* compute the effective address.  Bind it to a tmp since we
   13342         may need to use it twice. */
   13343      IRExpr* eaE = NULL;
   13344      switch (summary & 0xF0) {
   13345         case 16:
   13346            eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
   13347            break;
   13348         case 32:
   13349            eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
   13350            break;
   13351      }
   13352      vassert(eaE);
   13353      IRTemp eaT = newTemp(Ity_I32);
   13354      assign(eaT, eaE);
   13355 
   13356      /* get the old Rn value */
   13357      IRTemp rnT = newTemp(Ity_I32);
   13358      assign(rnT, getIRegA(rN));
   13359 
   13360      /* decide on the transfer address */
   13361      IRTemp taT = IRTemp_INVALID;
   13362      switch (summary & 0x0F) {
   13363         case 1: case 2: taT = eaT; break;
   13364         case 3:         taT = rnT; break;
   13365      }
   13366      vassert(taT != IRTemp_INVALID);
   13367 
   13368      /* halfword store  H 1  L 0  S 0
   13369         uhalf load      H 1  L 1  S 0
   13370         shalf load      H 1  L 1  S 1
   13371         sbyte load      H 0  L 1  S 1
   13372      */
   13373      HChar* name = NULL;
   13374      /* generate the transfer */
   13375      /**/ if (bH == 1 && bL == 0 && bS == 0) { // halfword store
   13376         storeLE( mkexpr(taT), unop(Iop_32to16, getIRegA(rD)) );
   13377         name = "strh";
   13378      }
   13379      else if (bH == 1 && bL == 1 && bS == 0) { // uhalf load
   13380         putIRegA( rD, unop(Iop_16Uto32, loadLE(Ity_I16, mkexpr(taT))),
   13381                   IRTemp_INVALID, Ijk_Boring );
   13382         name = "ldrh";
   13383      }
   13384      else if (bH == 1 && bL == 1 && bS == 1) { // shalf load
   13385         putIRegA( rD, unop(Iop_16Sto32, loadLE(Ity_I16, mkexpr(taT))),
   13386                   IRTemp_INVALID, Ijk_Boring );
   13387         name = "ldrsh";
   13388      }
   13389      else if (bH == 0 && bL == 1 && bS == 1) { // sbyte load
   13390         putIRegA( rD, unop(Iop_8Sto32, loadLE(Ity_I8, mkexpr(taT))),
   13391                   IRTemp_INVALID, Ijk_Boring );
   13392         name = "ldrsb";
   13393      }
   13394      else
   13395         vassert(0); // should be assured by logic above
   13396 
   13397      /* Update Rn if necessary. */
   13398      switch (summary & 0x0F) {
   13399         case 2: case 3:
   13400            // should be assured by logic above:
   13401            if (bL == 1)
   13402               vassert(rD != rN); /* since we just wrote rD */
   13403            putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   13404            break;
   13405      }
   13406 
   13407      switch (summary & 0x0F) {
   13408         case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
   13409                  break;
   13410         case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
   13411                      name, nCC(INSN_COND), rD, dis_buf);
   13412                  break;
   13413         case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
   13414                      name, nCC(INSN_COND), rD, dis_buf);
   13415                  break;
   13416         default: vassert(0);
   13417      }
   13418 
   13419      /* XXX deal with alignment constraints */
   13420 
   13421      goto decode_success;
   13422 
   13423      /* Complications:
   13424 
   13425         For all loads: if the Amode specifies base register
   13426         writeback, and the same register is specified for Rd and Rn,
   13427         the results are UNPREDICTABLE.
   13428 
   13429         For all loads and stores: if R15 is written, branch to
   13430         that address afterwards.
   13431 
   13432         Misaligned halfword stores => Unpredictable
   13433         Misaligned halfword loads  => Unpredictable
   13434      */
   13435    }
   13436 
   13437   after_load_store_sbyte_or_hword:
   13438 
   13439    /* --------------------- Load/store multiple -------------- */
   13440    // LD/STMIA LD/STMIB LD/STMDA LD/STMDB
   13441    // Remarkably complex and difficult to get right
   13442    // match 27:20 as 100XX0WL
   13443    if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) {
   13444       // A5-50 LD/STMIA  cond 1000 10WL Rn RegList
   13445       // A5-51 LD/STMIB  cond 1001 10WL Rn RegList
   13446       // A5-53 LD/STMDA  cond 1000 00WL Rn RegList
   13447       // A5-53 LD/STMDB  cond 1001 00WL Rn RegList
   13448       //                   28   24   20 16       0
   13449 
   13450       UInt bINC    = (insn >> 23) & 1;
   13451       UInt bBEFORE = (insn >> 24) & 1;
   13452 
   13453       UInt bL      = (insn >> 20) & 1;  /* load=1, store=0 */
   13454       UInt bW      = (insn >> 21) & 1;  /* Rn wback=1, no wback=0 */
   13455       UInt rN      = (insn >> 16) & 0xF;
   13456       UInt regList = insn & 0xFFFF;
   13457       /* Skip some invalid cases, which would lead to two competing
   13458          updates to the same register, or which are otherwise
   13459          disallowed by the spec.  Note the test above has required
   13460          that S == 0, since that looks like a kernel-mode only thing.
   13461          Done by forcing the real pattern, viz 100XXSWL to actually be
   13462          100XX0WL. */
   13463       if (rN == 15) goto after_load_store_multiple;
   13464       // reglist can't be empty
   13465       if (regList == 0) goto after_load_store_multiple;
   13466       // if requested to writeback Rn, and this is a load instruction,
   13467       // then Rn can't appear in RegList, since we'd have two competing
   13468       // new values for Rn.  We do however accept this case for store
   13469       // instructions.
   13470       if (bW == 1 && bL == 1 && ((1 << rN) & regList) > 0)
   13471          goto after_load_store_multiple;
   13472 
   13473       /* Now, we can't do a conditional load or store, since that very
   13474          likely will generate an exception.  So we have to take a side
   13475          exit at this point if the condition is false. */
   13476       if (condT != IRTemp_INVALID) {
   13477          mk_skip_over_A32_if_cond_is_false( condT );
   13478          condT = IRTemp_INVALID;
   13479       }
   13480 
   13481       /* Ok, now we're unconditional.  Generate the IR. */
   13482       mk_ldm_stm( True/*arm*/, rN, bINC, bBEFORE, bW, bL, regList );
   13483 
   13484       DIP("%sm%c%c%s r%u%s, {0x%04x}\n",
   13485           bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
   13486           nCC(INSN_COND),
   13487           rN, bW ? "!" : "", regList);
   13488 
   13489       goto decode_success;
   13490    }
   13491 
   13492   after_load_store_multiple:
   13493 
   13494    /* --------------------- Control flow --------------------- */
   13495    // B, BL (Branch, or Branch-and-Link, to immediate offset)
   13496    //
   13497    if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) {
   13498       UInt link   = (insn >> 24) & 1;
   13499       UInt uimm24 = insn & ((1<<24)-1);
   13500       Int  simm24 = (Int)uimm24;
   13501       UInt dst    = guest_R15_curr_instr_notENC + 8
   13502                     + (((simm24 << 8) >> 8) << 2);
   13503       IRJumpKind jk = link ? Ijk_Call : Ijk_Boring;
   13504       if (link) {
   13505          putIRegA(14, mkU32(guest_R15_curr_instr_notENC + 4),
   13506                       condT, Ijk_Boring);
   13507       }
   13508       if (condT == IRTemp_INVALID) {
   13509          /* unconditional transfer to 'dst'.  See if we can simply
   13510             continue tracing at the destination. */
   13511          if (resteerOkFn( callback_opaque, (Addr64)dst )) {
   13512             /* yes */
   13513             dres.whatNext   = Dis_ResteerU;
   13514             dres.continueAt = (Addr64)dst;
   13515          } else {
   13516             /* no; terminate the SB at this point. */
   13517             llPutIReg(15, mkU32(dst));
   13518             dres.jk_StopHere = jk;
   13519             dres.whatNext    = Dis_StopHere;
   13520          }
   13521          DIP("b%s 0x%x\n", link ? "l" : "", dst);
   13522       } else {
   13523          /* conditional transfer to 'dst' */
   13524          HChar* comment = "";
   13525 
   13526          /* First see if we can do some speculative chasing into one
   13527             arm or the other.  Be conservative and only chase if
   13528             !link, that is, this is a normal conditional branch to a
   13529             known destination. */
   13530          if (!link
   13531              && resteerCisOk
   13532              && vex_control.guest_chase_cond
   13533              && dst < guest_R15_curr_instr_notENC
   13534              && resteerOkFn( callback_opaque, (Addr64)(Addr32)dst) ) {
   13535             /* Speculation: assume this backward branch is taken.  So
   13536                we need to emit a side-exit to the insn following this
   13537                one, on the negation of the condition, and continue at
   13538                the branch target address (dst). */
   13539             stmt( IRStmt_Exit( unop(Iop_Not1,
   13540                                     unop(Iop_32to1, mkexpr(condT))),
   13541                                Ijk_Boring,
   13542                                IRConst_U32(guest_R15_curr_instr_notENC+4),
   13543                                OFFB_R15T ));
   13544             dres.whatNext   = Dis_ResteerC;
   13545             dres.continueAt = (Addr64)(Addr32)dst;
   13546             comment = "(assumed taken)";
   13547          }
   13548          else
   13549          if (!link
   13550              && resteerCisOk
   13551              && vex_control.guest_chase_cond
   13552              && dst >= guest_R15_curr_instr_notENC
   13553              && resteerOkFn( callback_opaque,
   13554                              (Addr64)(Addr32)
   13555                                      (guest_R15_curr_instr_notENC+4)) ) {
   13556             /* Speculation: assume this forward branch is not taken.
   13557                So we need to emit a side-exit to dst (the dest) and
   13558                continue disassembling at the insn immediately
   13559                following this one. */
   13560             stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
   13561                                Ijk_Boring,
   13562                                IRConst_U32(dst),
   13563                                OFFB_R15T ));
   13564             dres.whatNext   = Dis_ResteerC;
   13565             dres.continueAt = (Addr64)(Addr32)
   13566                                       (guest_R15_curr_instr_notENC+4);
   13567             comment = "(assumed not taken)";
   13568          }
   13569          else {
   13570             /* Conservative default translation - end the block at
   13571                this point. */
   13572             stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
   13573                                jk, IRConst_U32(dst), OFFB_R15T ));
   13574             llPutIReg(15, mkU32(guest_R15_curr_instr_notENC + 4));
   13575             dres.jk_StopHere = Ijk_Boring;
   13576             dres.whatNext    = Dis_StopHere;
   13577          }
   13578          DIP("b%s%s 0x%x %s\n", link ? "l" : "", nCC(INSN_COND),
   13579              dst, comment);
   13580       }
   13581       goto decode_success;
   13582    }
   13583 
   13584    // B, BL (Branch, or Branch-and-Link, to a register)
   13585    // NB: interworking branch
   13586    if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
   13587        && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1)
   13588        && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1)
   13589            || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) {
   13590       IRTemp  dst = newTemp(Ity_I32);
   13591       UInt    link = (INSN(11,4) >> 1) & 1;
   13592       UInt    rM   = INSN(3,0);
   13593       // we don't decode the case (link && rM == 15), as that's
   13594       // Unpredictable.
   13595       if (!(link && rM == 15)) {
   13596          if (condT != IRTemp_INVALID) {
   13597             mk_skip_over_A32_if_cond_is_false( condT );
   13598          }
   13599          // rM contains an interworking address exactly as we require
   13600          // (with continuation CPSR.T in bit 0), so we can use it
   13601          // as-is, with no masking.
   13602          assign( dst, getIRegA(rM) );
   13603          if (link) {
   13604             putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
   13605                       IRTemp_INVALID/*because AL*/, Ijk_Boring );
   13606          }
   13607          llPutIReg(15, mkexpr(dst));
   13608          dres.jk_StopHere = link ? Ijk_Call
   13609                                  : (rM == 14 ? Ijk_Ret : Ijk_Boring);
   13610          dres.whatNext    = Dis_StopHere;
   13611          if (condT == IRTemp_INVALID) {
   13612             DIP("b%sx r%u\n", link ? "l" : "", rM);
   13613          } else {
   13614             DIP("b%sx%s r%u\n", link ? "l" : "", nCC(INSN_COND), rM);
   13615          }
   13616          goto decode_success;
   13617       }
   13618       /* else: (link && rM == 15): just fall through */
   13619    }
   13620 
   13621    /* --- NB: ARM interworking branches are in NV space, hence
   13622       are handled elsewhere by decode_NV_instruction.
   13623       ---
   13624    */
   13625 
   13626    /* --------------------- Clz --------------------- */
   13627    // CLZ
   13628    if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0)
   13629        && INSN(19,16) == BITS4(1,1,1,1)
   13630        && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) {
   13631       UInt rD = INSN(15,12);
   13632       UInt rM = INSN(3,0);
   13633       IRTemp arg = newTemp(Ity_I32);
   13634       IRTemp res = newTemp(Ity_I32);
   13635       assign(arg, getIRegA(rM));
   13636       assign(res, IRExpr_Mux0X(
   13637                      unop(Iop_1Uto8,binop(Iop_CmpEQ32, mkexpr(arg),
   13638                                                        mkU32(0))),
   13639                      unop(Iop_Clz32, mkexpr(arg)),
   13640                      mkU32(32)
   13641             ));
   13642       putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13643       DIP("clz%s r%u, r%u\n", nCC(INSN_COND), rD, rM);
   13644       goto decode_success;
   13645    }
   13646 
   13647    /* --------------------- Mul etc --------------------- */
   13648    // MUL
   13649    if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
   13650        && INSN(15,12) == BITS4(0,0,0,0)
   13651        && INSN(7,4) == BITS4(1,0,0,1)) {
   13652       UInt bitS = (insn >> 20) & 1; /* 20:20 */
   13653       UInt rD = INSN(19,16);
   13654       UInt rS = INSN(11,8);
   13655       UInt rM = INSN(3,0);
   13656       if (rD == 15 || rM == 15 || rS == 15) {
   13657          /* Unpredictable; don't decode; fall through */
   13658       } else {
   13659          IRTemp argL = newTemp(Ity_I32);
   13660          IRTemp argR = newTemp(Ity_I32);
   13661          IRTemp res  = newTemp(Ity_I32);
   13662          IRTemp oldC = IRTemp_INVALID;
   13663          IRTemp oldV = IRTemp_INVALID;
   13664          assign( argL, getIRegA(rM));
   13665          assign( argR, getIRegA(rS));
   13666          assign( res, binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) );
   13667          if (bitS) {
   13668             oldC = newTemp(Ity_I32);
   13669             assign(oldC, mk_armg_calculate_flag_c());
   13670             oldV = newTemp(Ity_I32);
   13671             assign(oldV, mk_armg_calculate_flag_v());
   13672          }
   13673          // now update guest state
   13674          putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   13675          if (bitS) {
   13676             IRTemp pair = newTemp(Ity_I32);
   13677             assign( pair, binop(Iop_Or32,
   13678                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13679                                 mkexpr(oldV)) );
   13680             setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
   13681          }
   13682          DIP("mul%c%s r%u, r%u, r%u\n",
   13683              bitS ? 's' : ' ', nCC(INSN_COND), rD, rM, rS);
   13684          goto decode_success;
   13685       }
   13686       /* fall through */
   13687    }
   13688 
   13689    /* --------------------- Integer Divides --------------------- */
   13690    // SDIV
   13691    if (BITS8(0,1,1,1,0,0,0,1) == INSN(27,20)
   13692        && INSN(15,12) == BITS4(1,1,1,1)
   13693        && INSN(7,4) == BITS4(0,0,0,1)) {
   13694       UInt rD = INSN(19,16);
   13695       UInt rM = INSN(11,8);
   13696       UInt rN = INSN(3,0);
   13697       if (rD == 15 || rM == 15 || rN == 15) {
   13698          /* Unpredictable; don't decode; fall through */
   13699       } else {
   13700          IRTemp res = newTemp(Ity_I32);
   13701          IRTemp argL  = newTemp(Ity_I32);
   13702          IRTemp argR  = newTemp(Ity_I32);
   13703          assign(argL, getIRegA(rN));
   13704          assign(argR, getIRegA(rM));
   13705          assign(res, binop(Iop_DivS32, mkexpr(argL), mkexpr(argR)));
   13706          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13707          DIP("sdiv r%u, r%u, r%u\n", rD, rN, rM);
   13708          goto decode_success;
   13709       }
   13710     }
   13711 
   13712    // UDIV
   13713    if (BITS8(0,1,1,1,0,0,1,1) == INSN(27,20)
   13714        && INSN(15,12) == BITS4(1,1,1,1)
   13715        && INSN(7,4) == BITS4(0,0,0,1)) {
   13716       UInt rD = INSN(19,16);
   13717       UInt rM = INSN(11,8);
   13718       UInt rN = INSN(3,0);
   13719       if (rD == 15 || rM == 15 || rN == 15) {
   13720          /* Unpredictable; don't decode; fall through */
   13721       } else {
   13722          IRTemp res = newTemp(Ity_I32);
   13723          IRTemp argL  = newTemp(Ity_I32);
   13724          IRTemp argR  = newTemp(Ity_I32);
   13725          assign(argL, getIRegA(rN));
   13726          assign(argR, getIRegA(rM));
   13727          assign(res, binop(Iop_DivU32, mkexpr(argL), mkexpr(argR)));
   13728          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13729          DIP("udiv r%u, r%u, r%u\n", rD, rN, rM);
   13730          goto decode_success;
   13731       }
   13732     }
   13733 
   13734    // MLA, MLS
   13735    if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13736        && INSN(7,4) == BITS4(1,0,0,1)) {
   13737       UInt bitS  = (insn >> 20) & 1; /* 20:20 */
   13738       UInt isMLS = (insn >> 22) & 1; /* 22:22 */
   13739       UInt rD = INSN(19,16);
   13740       UInt rN = INSN(15,12);
   13741       UInt rS = INSN(11,8);
   13742       UInt rM = INSN(3,0);
   13743       if (bitS == 1 && isMLS == 1) {
   13744          /* This isn't allowed (MLS that sets flags).  don't decode;
   13745             fall through */
   13746       }
   13747       else
   13748       if (rD == 15 || rM == 15 || rS == 15 || rN == 15) {
   13749          /* Unpredictable; don't decode; fall through */
   13750       } else {
   13751          IRTemp argL = newTemp(Ity_I32);
   13752          IRTemp argR = newTemp(Ity_I32);
   13753          IRTemp argP = newTemp(Ity_I32);
   13754          IRTemp res  = newTemp(Ity_I32);
   13755          IRTemp oldC = IRTemp_INVALID;
   13756          IRTemp oldV = IRTemp_INVALID;
   13757          assign( argL, getIRegA(rM));
   13758          assign( argR, getIRegA(rS));
   13759          assign( argP, getIRegA(rN));
   13760          assign( res, binop(isMLS ? Iop_Sub32 : Iop_Add32,
   13761                             mkexpr(argP),
   13762                             binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) ));
   13763          if (bitS) {
   13764             vassert(!isMLS); // guaranteed above
   13765             oldC = newTemp(Ity_I32);
   13766             assign(oldC, mk_armg_calculate_flag_c());
   13767             oldV = newTemp(Ity_I32);
   13768             assign(oldV, mk_armg_calculate_flag_v());
   13769          }
   13770          // now update guest state
   13771          putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   13772          if (bitS) {
   13773             IRTemp pair = newTemp(Ity_I32);
   13774             assign( pair, binop(Iop_Or32,
   13775                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13776                                 mkexpr(oldV)) );
   13777             setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
   13778          }
   13779          DIP("ml%c%c%s r%u, r%u, r%u, r%u\n",
   13780              isMLS ? 's' : 'a', bitS ? 's' : ' ',
   13781              nCC(INSN_COND), rD, rM, rS, rN);
   13782          goto decode_success;
   13783       }
   13784       /* fall through */
   13785    }
   13786 
   13787    // SMULL, UMULL
   13788    if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13789        && INSN(7,4) == BITS4(1,0,0,1)) {
   13790       UInt bitS = (insn >> 20) & 1; /* 20:20 */
   13791       UInt rDhi = INSN(19,16);
   13792       UInt rDlo = INSN(15,12);
   13793       UInt rS   = INSN(11,8);
   13794       UInt rM   = INSN(3,0);
   13795       UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
   13796       if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
   13797          /* Unpredictable; don't decode; fall through */
   13798       } else {
   13799          IRTemp argL  = newTemp(Ity_I32);
   13800          IRTemp argR  = newTemp(Ity_I32);
   13801          IRTemp res   = newTemp(Ity_I64);
   13802          IRTemp resHi = newTemp(Ity_I32);
   13803          IRTemp resLo = newTemp(Ity_I32);
   13804          IRTemp oldC  = IRTemp_INVALID;
   13805          IRTemp oldV  = IRTemp_INVALID;
   13806          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
   13807          assign( argL, getIRegA(rM));
   13808          assign( argR, getIRegA(rS));
   13809          assign( res, binop(mulOp, mkexpr(argL), mkexpr(argR)) );
   13810          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
   13811          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
   13812          if (bitS) {
   13813             oldC = newTemp(Ity_I32);
   13814             assign(oldC, mk_armg_calculate_flag_c());
   13815             oldV = newTemp(Ity_I32);
   13816             assign(oldV, mk_armg_calculate_flag_v());
   13817          }
   13818          // now update guest state
   13819          putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
   13820          putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
   13821          if (bitS) {
   13822             IRTemp pair = newTemp(Ity_I32);
   13823             assign( pair, binop(Iop_Or32,
   13824                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13825                                 mkexpr(oldV)) );
   13826             setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
   13827          }
   13828          DIP("%cmull%c%s r%u, r%u, r%u, r%u\n",
   13829              isS ? 's' : 'u', bitS ? 's' : ' ',
   13830              nCC(INSN_COND), rDlo, rDhi, rM, rS);
   13831          goto decode_success;
   13832       }
   13833       /* fall through */
   13834    }
   13835 
   13836    // SMLAL, UMLAL
   13837    if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13838        && INSN(7,4) == BITS4(1,0,0,1)) {
   13839       UInt bitS = (insn >> 20) & 1; /* 20:20 */
   13840       UInt rDhi = INSN(19,16);
   13841       UInt rDlo = INSN(15,12);
   13842       UInt rS   = INSN(11,8);
   13843       UInt rM   = INSN(3,0);
   13844       UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
   13845       if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
   13846          /* Unpredictable; don't decode; fall through */
   13847       } else {
   13848          IRTemp argL  = newTemp(Ity_I32);
   13849          IRTemp argR  = newTemp(Ity_I32);
   13850          IRTemp old   = newTemp(Ity_I64);
   13851          IRTemp res   = newTemp(Ity_I64);
   13852          IRTemp resHi = newTemp(Ity_I32);
   13853          IRTemp resLo = newTemp(Ity_I32);
   13854          IRTemp oldC  = IRTemp_INVALID;
   13855          IRTemp oldV  = IRTemp_INVALID;
   13856          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
   13857          assign( argL, getIRegA(rM));
   13858          assign( argR, getIRegA(rS));
   13859          assign( old, binop(Iop_32HLto64, getIRegA(rDhi), getIRegA(rDlo)) );
   13860          assign( res, binop(Iop_Add64,
   13861                             mkexpr(old),
   13862                             binop(mulOp, mkexpr(argL), mkexpr(argR))) );
   13863          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
   13864          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
   13865          if (bitS) {
   13866             oldC = newTemp(Ity_I32);
   13867             assign(oldC, mk_armg_calculate_flag_c());
   13868             oldV = newTemp(Ity_I32);
   13869             assign(oldV, mk_armg_calculate_flag_v());
   13870          }
   13871          // now update guest state
   13872          putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
   13873          putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
   13874          if (bitS) {
   13875             IRTemp pair = newTemp(Ity_I32);
   13876             assign( pair, binop(Iop_Or32,
   13877                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13878                                 mkexpr(oldV)) );
   13879             setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
   13880          }
   13881          DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n",
   13882              isS ? 's' : 'u', bitS ? 's' : ' ', nCC(INSN_COND),
   13883              rDlo, rDhi, rM, rS);
   13884          goto decode_success;
   13885       }
   13886       /* fall through */
   13887    }
   13888 
   13889    /* --------------------- Msr etc --------------------- */
   13890 
   13891    // MSR apsr, #imm
   13892    if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0)
   13893        && INSN(17,12) == BITS6(0,0,1,1,1,1)) {
   13894       UInt write_ge    = INSN(18,18);
   13895       UInt write_nzcvq = INSN(19,19);
   13896       if (write_nzcvq || write_ge) {
   13897          UInt   imm = (INSN(11,0) >> 0) & 0xFF;
   13898          UInt   rot = 2 * ((INSN(11,0) >> 8) & 0xF);
   13899          IRTemp immT = newTemp(Ity_I32);
   13900          vassert(rot <= 30);
   13901          imm = ROR32(imm, rot);
   13902          assign(immT, mkU32(imm));
   13903          desynthesise_APSR( write_nzcvq, write_ge, immT, condT );
   13904          DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND),
   13905              write_nzcvq ? "f" : "", write_ge ? "g" : "", imm);
   13906          goto decode_success;
   13907       }
   13908       /* fall through */
   13909    }
   13910 
   13911    // MSR apsr, reg
   13912    if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
   13913        && INSN(17,12) == BITS6(0,0,1,1,1,1)
   13914        && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) {
   13915       UInt rN          = INSN(3,0);
   13916       UInt write_ge    = INSN(18,18);
   13917       UInt write_nzcvq = INSN(19,19);
   13918       if (rN != 15 && (write_nzcvq || write_ge)) {
   13919          IRTemp rNt = newTemp(Ity_I32);
   13920          assign(rNt, getIRegA(rN));
   13921          desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
   13922          DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND),
   13923              write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
   13924          goto decode_success;
   13925       }
   13926       /* fall through */
   13927    }
   13928 
   13929    // MRS rD, cpsr
   13930    if ((insn & 0x0FFF0FFF) == 0x010F0000) {
   13931       UInt rD   = INSN(15,12);
   13932       if (rD != 15) {
   13933          IRTemp apsr = synthesise_APSR();
   13934          putIRegA( rD, mkexpr(apsr), condT, Ijk_Boring );
   13935          DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND), rD);
   13936          goto decode_success;
   13937       }
   13938       /* fall through */
   13939    }
   13940 
   13941    /* --------------------- Svc --------------------- */
   13942    if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) {
   13943       UInt imm24 = (insn >> 0) & 0xFFFFFF;
   13944       if (imm24 == 0) {
   13945          /* A syscall.  We can't do this conditionally, hence: */
   13946          if (condT != IRTemp_INVALID) {
   13947             mk_skip_over_A32_if_cond_is_false( condT );
   13948          }
   13949          // AL after here
   13950          llPutIReg(15, mkU32( guest_R15_curr_instr_notENC + 4 ));
   13951          dres.jk_StopHere = Ijk_Sys_syscall;
   13952          dres.whatNext    = Dis_StopHere;
   13953          DIP("svc%s #0x%08x\n", nCC(INSN_COND), imm24);
   13954          goto decode_success;
   13955       }
   13956       /* fall through */
   13957    }
   13958 
   13959    /* ------------------------ swp ------------------------ */
   13960 
   13961    // SWP, SWPB
   13962    if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   13963        && BITS4(0,0,0,0) == INSN(11,8)
   13964        && BITS4(1,0,0,1) == INSN(7,4)) {
   13965       UInt   rN   = INSN(19,16);
   13966       UInt   rD   = INSN(15,12);
   13967       UInt   rM   = INSN(3,0);
   13968       IRTemp tRn  = newTemp(Ity_I32);
   13969       IRTemp tNew = newTemp(Ity_I32);
   13970       IRTemp tOld = IRTemp_INVALID;
   13971       IRTemp tSC1 = newTemp(Ity_I1);
   13972       UInt   isB  = (insn >> 22) & 1;
   13973 
   13974       if (rD == 15 || rN == 15 || rM == 15 || rN == rM || rN == rD) {
   13975          /* undecodable; fall through */
   13976       } else {
   13977          /* make unconditional */
   13978          if (condT != IRTemp_INVALID) {
   13979             mk_skip_over_A32_if_cond_is_false( condT );
   13980             condT = IRTemp_INVALID;
   13981          }
   13982          /* Ok, now we're unconditional.  Generate a LL-SC loop. */
   13983          assign(tRn, getIRegA(rN));
   13984          assign(tNew, getIRegA(rM));
   13985          if (isB) {
   13986             /* swpb */
   13987             tOld = newTemp(Ity_I8);
   13988             stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
   13989                               NULL/*=>isLL*/) );
   13990             stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
   13991                               unop(Iop_32to8, mkexpr(tNew))) );
   13992          } else {
   13993             /* swp */
   13994             tOld = newTemp(Ity_I32);
   13995             stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
   13996                               NULL/*=>isLL*/) );
   13997             stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
   13998                               mkexpr(tNew)) );
   13999          }
   14000          stmt( IRStmt_Exit(unop(Iop_Not1, mkexpr(tSC1)),
   14001                            /*Ijk_NoRedir*/Ijk_Boring,
   14002                            IRConst_U32(guest_R15_curr_instr_notENC),
   14003                            OFFB_R15T ));
   14004          putIRegA(rD, isB ? unop(Iop_8Uto32, mkexpr(tOld)) : mkexpr(tOld),
   14005                       IRTemp_INVALID, Ijk_Boring);
   14006          DIP("swp%s%s r%u, r%u, [r%u]\n",
   14007              isB ? "b" : "", nCC(INSN_COND), rD, rM, rN);
   14008          goto decode_success;
   14009       }
   14010       /* fall through */
   14011    }
   14012 
   14013    /* ----------------------------------------------------------- */
   14014    /* -- ARMv6 instructions                                    -- */
   14015    /* ----------------------------------------------------------- */
   14016 
   14017    /* ------------------- {ldr,str}ex{,b,h,d} ------------------- */
   14018 
   14019    // LDREXD, LDREX, LDREXH, LDREXB
   14020    if (0x01900F9F == (insn & 0x0F900FFF)) {
   14021       UInt   rT    = INSN(15,12);
   14022       UInt   rN    = INSN(19,16);
   14023       IRType ty    = Ity_INVALID;
   14024       IROp   widen = Iop_INVALID;
   14025       HChar* nm    = NULL;
   14026       Bool   valid = True;
   14027       switch (INSN(22,21)) {
   14028          case 0: nm = "";  ty = Ity_I32; break;
   14029          case 1: nm = "d"; ty = Ity_I64; break;
   14030          case 2: nm = "b"; ty = Ity_I8;  widen = Iop_8Uto32; break;
   14031          case 3: nm = "h"; ty = Ity_I16; widen = Iop_16Uto32; break;
   14032          default: vassert(0);
   14033       }
   14034       if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
   14035          if (rT == 15 || rN == 15)
   14036             valid = False;
   14037       } else {
   14038          vassert(ty == Ity_I64);
   14039          if ((rT & 1) == 1 || rT == 14 || rN == 15)
   14040             valid = False;
   14041       }
   14042       if (valid) {
   14043          IRTemp res;
   14044          /* make unconditional */
   14045          if (condT != IRTemp_INVALID) {
   14046            mk_skip_over_A32_if_cond_is_false( condT );
   14047            condT = IRTemp_INVALID;
   14048          }
   14049          /* Ok, now we're unconditional.  Do the load. */
   14050          res = newTemp(ty);
   14051          // FIXME: assumes little-endian guest
   14052          stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN),
   14053                            NULL/*this is a load*/) );
   14054          if (ty == Ity_I64) {
   14055             // FIXME: assumes little-endian guest
   14056             putIRegA(rT+0, unop(Iop_64to32, mkexpr(res)),
   14057                            IRTemp_INVALID, Ijk_Boring);
   14058             putIRegA(rT+1, unop(Iop_64HIto32, mkexpr(res)),
   14059                            IRTemp_INVALID, Ijk_Boring);
   14060             DIP("ldrex%s%s r%u, r%u, [r%u]\n",
   14061                 nm, nCC(INSN_COND), rT+0, rT+1, rN);
   14062          } else {
   14063             putIRegA(rT, widen == Iop_INVALID
   14064                             ? mkexpr(res) : unop(widen, mkexpr(res)),
   14065                      IRTemp_INVALID, Ijk_Boring);
   14066             DIP("ldrex%s%s r%u, [r%u]\n", nm, nCC(INSN_COND), rT, rN);
   14067          }
   14068          goto decode_success;
   14069       }
   14070       /* undecodable; fall through */
   14071    }
   14072 
   14073    // STREXD, STREX, STREXH, STREXB
   14074    if (0x01800F90 == (insn & 0x0F900FF0)) {
   14075       UInt   rT     = INSN(3,0);
   14076       UInt   rN     = INSN(19,16);
   14077       UInt   rD     = INSN(15,12);
   14078       IRType ty     = Ity_INVALID;
   14079       IROp   narrow = Iop_INVALID;
   14080       HChar* nm     = NULL;
   14081       Bool   valid  = True;
   14082       switch (INSN(22,21)) {
   14083          case 0: nm = "";  ty = Ity_I32; break;
   14084          case 1: nm = "d"; ty = Ity_I64; break;
   14085          case 2: nm = "b"; ty = Ity_I8;  narrow = Iop_32to8; break;
   14086          case 3: nm = "h"; ty = Ity_I16; narrow = Iop_32to16; break;
   14087          default: vassert(0);
   14088       }
   14089       if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
   14090          if (rD == 15 || rN == 15 || rT == 15
   14091              || rD == rN || rD == rT)
   14092             valid = False;
   14093       } else {
   14094          vassert(ty == Ity_I64);
   14095          if (rD == 15 || (rT & 1) == 1 || rT == 14 || rN == 15
   14096              || rD == rN || rD == rT || rD == rT+1)
   14097             valid = False;
   14098       }
   14099       if (valid) {
   14100          IRTemp resSC1, resSC32, data;
   14101          /* make unconditional */
   14102          if (condT != IRTemp_INVALID) {
   14103             mk_skip_over_A32_if_cond_is_false( condT );
   14104             condT = IRTemp_INVALID;
   14105          }
   14106          /* Ok, now we're unconditional.  Do the store. */
   14107          data = newTemp(ty);
   14108          assign(data,
   14109                 ty == Ity_I64
   14110                    // FIXME: assumes little-endian guest
   14111                    ? binop(Iop_32HLto64, getIRegA(rT+1), getIRegA(rT+0))
   14112                    : narrow == Iop_INVALID
   14113                       ? getIRegA(rT)
   14114                       : unop(narrow, getIRegA(rT)));
   14115          resSC1 = newTemp(Ity_I1);
   14116          // FIXME: assumes little-endian guest
   14117          stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), mkexpr(data)) );
   14118 
   14119          /* Set rD to 1 on failure, 0 on success.  Currently we have
   14120             resSC1 == 0 on failure, 1 on success. */
   14121          resSC32 = newTemp(Ity_I32);
   14122          assign(resSC32,
   14123                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   14124 
   14125          putIRegA(rD, mkexpr(resSC32),
   14126                       IRTemp_INVALID, Ijk_Boring);
   14127          if (ty == Ity_I64) {
   14128             DIP("strex%s%s r%u, r%u, r%u, [r%u]\n",
   14129                 nm, nCC(INSN_COND), rD, rT, rT+1, rN);
   14130          } else {
   14131             DIP("strex%s%s r%u, r%u, [r%u]\n",
   14132                 nm, nCC(INSN_COND), rD, rT, rN);
   14133          }
   14134          goto decode_success;
   14135       }
   14136       /* fall through */
   14137    }
   14138 
   14139    /* --------------------- movw, movt --------------------- */
   14140    if (0x03000000 == (insn & 0x0FF00000)
   14141        || 0x03400000 == (insn & 0x0FF00000)) /* pray for CSE */ {
   14142       UInt rD    = INSN(15,12);
   14143       UInt imm16 = (insn & 0xFFF) | ((insn >> 4) & 0x0000F000);
   14144       UInt isT   = (insn >> 22) & 1;
   14145       if (rD == 15) {
   14146          /* forget it */
   14147       } else {
   14148          if (isT) {
   14149             putIRegA(rD,
   14150                      binop(Iop_Or32,
   14151                            binop(Iop_And32, getIRegA(rD), mkU32(0xFFFF)),
   14152                            mkU32(imm16 << 16)),
   14153                      condT, Ijk_Boring);
   14154             DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
   14155             goto decode_success;
   14156          } else {
   14157             putIRegA(rD, mkU32(imm16), condT, Ijk_Boring);
   14158             DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
   14159             goto decode_success;
   14160          }
   14161       }
   14162       /* fall through */
   14163    }
   14164 
   14165    /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */
   14166    /* FIXME: this is an exact duplicate of the Thumb version.  They
   14167       should be commoned up. */
   14168    if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0))
   14169        && BITS4(1,1,1,1) == INSN(19,16)
   14170        && BITS4(0,1,1,1) == INSN(7,4)
   14171        && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) {
   14172       UInt subopc = INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1);
   14173       if (subopc != BITS4(0,0,0,1) && subopc != BITS4(0,1,0,1)) {
   14174          Int    rot  = (INSN(11,8) >> 2) & 3;
   14175          UInt   rM   = INSN(3,0);
   14176          UInt   rD   = INSN(15,12);
   14177          IRTemp srcT = newTemp(Ity_I32);
   14178          IRTemp rotT = newTemp(Ity_I32);
   14179          IRTemp dstT = newTemp(Ity_I32);
   14180          HChar* nm   = "???";
   14181          assign(srcT, getIRegA(rM));
   14182          assign(rotT, genROR32(srcT, 8 * rot)); /* 0, 8, 16 or 24 only */
   14183          switch (subopc) {
   14184             case BITS4(0,1,1,0): // UXTB
   14185                assign(dstT, unop(Iop_8Uto32, unop(Iop_32to8, mkexpr(rotT))));
   14186                nm = "uxtb";
   14187                break;
   14188             case BITS4(0,0,1,0): // SXTB
   14189                assign(dstT, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rotT))));
   14190                nm = "sxtb";
   14191                break;
   14192             case BITS4(0,1,1,1): // UXTH
   14193                assign(dstT, unop(Iop_16Uto32, unop(Iop_32to16, mkexpr(rotT))));
   14194                nm = "uxth";
   14195                break;
   14196             case BITS4(0,0,1,1): // SXTH
   14197                assign(dstT, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rotT))));
   14198                nm = "sxth";
   14199                break;
   14200             case BITS4(0,1,0,0): // UXTB16
   14201                assign(dstT, binop(Iop_And32, mkexpr(rotT), mkU32(0x00FF00FF)));
   14202                nm = "uxtb16";
   14203                break;
   14204             case BITS4(0,0,0,0): { // SXTB16
   14205                IRTemp lo32 = newTemp(Ity_I32);
   14206                IRTemp hi32 = newTemp(Ity_I32);
   14207                assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
   14208                assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
   14209                assign(
   14210                   dstT,
   14211                   binop(Iop_Or32,
   14212                         binop(Iop_And32,
   14213                               unop(Iop_8Sto32,
   14214                                    unop(Iop_32to8, mkexpr(lo32))),
   14215                               mkU32(0xFFFF)),
   14216                         binop(Iop_Shl32,
   14217                               unop(Iop_8Sto32,
   14218                                    unop(Iop_32to8, mkexpr(hi32))),
   14219                               mkU8(16))
   14220                ));
   14221                nm = "sxtb16";
   14222                break;
   14223             }
   14224             default:
   14225                vassert(0); // guarded by "if" above
   14226          }
   14227          putIRegA(rD, mkexpr(dstT), condT, Ijk_Boring);
   14228          DIP("%s%s r%u, r%u, ROR #%u\n", nm, nCC(INSN_COND), rD, rM, rot);
   14229          goto decode_success;
   14230       }
   14231       /* fall through */
   14232    }
   14233 
   14234    /* ------------------- bfi, bfc ------------------- */
   14235    if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
   14236        && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
   14237       UInt rD  = INSN(15,12);
   14238       UInt rN  = INSN(3,0);
   14239       UInt msb = (insn >> 16) & 0x1F; /* 20:16 */
   14240       UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
   14241       if (rD == 15 || msb < lsb) {
   14242          /* undecodable; fall through */
   14243       } else {
   14244          IRTemp src    = newTemp(Ity_I32);
   14245          IRTemp olddst = newTemp(Ity_I32);
   14246          IRTemp newdst = newTemp(Ity_I32);
   14247          UInt   mask = 1 << (msb - lsb);
   14248          mask = (mask - 1) + mask;
   14249          vassert(mask != 0); // guaranteed by "msb < lsb" check above
   14250          mask <<= lsb;
   14251 
   14252          assign(src, rN == 15 ? mkU32(0) : getIRegA(rN));
   14253          assign(olddst, getIRegA(rD));
   14254          assign(newdst,
   14255                 binop(Iop_Or32,
   14256                    binop(Iop_And32,
   14257                          binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
   14258                          mkU32(mask)),
   14259                    binop(Iop_And32,
   14260                          mkexpr(olddst),
   14261                          mkU32(~mask)))
   14262                );
   14263 
   14264          putIRegA(rD, mkexpr(newdst), condT, Ijk_Boring);
   14265 
   14266          if (rN == 15) {
   14267             DIP("bfc%s r%u, #%u, #%u\n",
   14268                 nCC(INSN_COND), rD, lsb, msb-lsb+1);
   14269          } else {
   14270             DIP("bfi%s r%u, r%u, #%u, #%u\n",
   14271                 nCC(INSN_COND), rD, rN, lsb, msb-lsb+1);
   14272          }
   14273          goto decode_success;
   14274       }
   14275       /* fall through */
   14276    }
   14277 
   14278    /* ------------------- {u,s}bfx ------------------- */
   14279    if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   14280        && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
   14281       UInt rD  = INSN(15,12);
   14282       UInt rN  = INSN(3,0);
   14283       UInt wm1 = (insn >> 16) & 0x1F; /* 20:16 */
   14284       UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
   14285       UInt msb = lsb + wm1;
   14286       UInt isU = (insn >> 22) & 1;    /* 22:22 */
   14287       if (rD == 15 || rN == 15 || msb >= 32) {
   14288          /* undecodable; fall through */
   14289       } else {
   14290          IRTemp src  = newTemp(Ity_I32);
   14291          IRTemp tmp  = newTemp(Ity_I32);
   14292          IRTemp res  = newTemp(Ity_I32);
   14293          UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
   14294          vassert(msb >= 0 && msb <= 31);
   14295          vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
   14296 
   14297          assign(src, getIRegA(rN));
   14298          assign(tmp, binop(Iop_And32,
   14299                            binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
   14300                            mkU32(mask)));
   14301          assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
   14302                            binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
   14303                            mkU8(31-wm1)));
   14304 
   14305          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   14306 
   14307          DIP("%s%s r%u, r%u, #%u, #%u\n",
   14308              isU ? "ubfx" : "sbfx",
   14309              nCC(INSN_COND), rD, rN, lsb, wm1 + 1);
   14310          goto decode_success;
   14311       }
   14312       /* fall through */
   14313    }
   14314 
   14315    /* --------------------- Load/store doubleword ------------- */
   14316    // LDRD STRD
   14317    /*                 31   27   23   19 15 11   7    3     # highest bit
   14318                         28   24   20 16 12    8    4    0
   14319       A5-36   1 | 16  cond 0001 U100 Rn Rd im4h 11S1 im4l
   14320       A5-38   1 | 32  cond 0001 U000 Rn Rd 0000 11S1 Rm
   14321       A5-40   2 | 16  cond 0001 U110 Rn Rd im4h 11S1 im4l
   14322       A5-42   2 | 32  cond 0001 U010 Rn Rd 0000 11S1 Rm
   14323       A5-44   3 | 16  cond 0000 U100 Rn Rd im4h 11S1 im4l
   14324       A5-46   3 | 32  cond 0000 U000 Rn Rd 0000 11S1 Rm
   14325    */
   14326    /* case coding:
   14327              1   at-ea               (access at ea)
   14328              2   at-ea-then-upd      (access at ea, then Rn = ea)
   14329              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
   14330       ea coding
   14331              16  Rn +/- imm8
   14332              32  Rn +/- Rm
   14333    */
   14334    /* Quickly skip over all of this for hopefully most instructions */
   14335    if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
   14336       goto after_load_store_doubleword;
   14337 
   14338    /* Check the "11S1" thing. */
   14339    if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1))
   14340       goto after_load_store_doubleword;
   14341 
   14342    summary = 0;
   14343 
   14344    /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) {
   14345       summary = 1 | 16;
   14346    }
   14347    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) {
   14348       summary = 1 | 32;
   14349    }
   14350    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) {
   14351       summary = 2 | 16;
   14352    }
   14353    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) {
   14354       summary = 2 | 32;
   14355    }
   14356    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) {
   14357       summary = 3 | 16;
   14358    }
   14359    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) {
   14360       summary = 3 | 32;
   14361    }
   14362    else goto after_load_store_doubleword;
   14363 
   14364    { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
   14365      UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
   14366      UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
   14367      UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
   14368      UInt bS   = (insn >> 5) & 1;    /* S=1 store, S=0 load */
   14369      UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
   14370 
   14371      /* Require rD to be an even numbered register */
   14372      if ((rD & 1) != 0)
   14373         goto after_load_store_doubleword;
   14374 
   14375      /* Require 11:8 == 0 for Rn +/- Rm cases */
   14376      if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
   14377         goto after_load_store_doubleword;
   14378 
   14379      /* Skip some invalid cases, which would lead to two competing
   14380         updates to the same register, or which are otherwise
   14381         disallowed by the spec. */
   14382      switch (summary) {
   14383         case 1 | 16:
   14384            break;
   14385         case 1 | 32:
   14386            if (rM == 15) goto after_load_store_doubleword;
   14387            break;
   14388         case 2 | 16: case 3 | 16:
   14389            if (rN == 15) goto after_load_store_doubleword;
   14390            if (bS == 0 && (rN == rD || rN == rD+1))
   14391               goto after_load_store_doubleword;
   14392            break;
   14393         case 2 | 32: case 3 | 32:
   14394            if (rM == 15) goto after_load_store_doubleword;
   14395            if (rN == 15) goto after_load_store_doubleword;
   14396            if (rN == rM) goto after_load_store_doubleword;
   14397            if (bS == 0 && (rN == rD || rN == rD+1))
   14398               goto after_load_store_doubleword;
   14399            break;
   14400         default:
   14401            vassert(0);
   14402      }
   14403 
   14404      /* Now, we can't do a conditional load or store, since that very
   14405         likely will generate an exception.  So we have to take a side
   14406         exit at this point if the condition is false. */
   14407      if (condT != IRTemp_INVALID) {
   14408         mk_skip_over_A32_if_cond_is_false( condT );
   14409         condT = IRTemp_INVALID;
   14410      }
   14411      /* Ok, now we're unconditional.  Do the load or store. */
   14412 
   14413      /* compute the effective address.  Bind it to a tmp since we
   14414         may need to use it twice. */
   14415      IRExpr* eaE = NULL;
   14416      switch (summary & 0xF0) {
   14417         case 16:
   14418            eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
   14419            break;
   14420         case 32:
   14421            eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
   14422            break;
   14423      }
   14424      vassert(eaE);
   14425      IRTemp eaT = newTemp(Ity_I32);
   14426      assign(eaT, eaE);
   14427 
   14428      /* get the old Rn value */
   14429      IRTemp rnT = newTemp(Ity_I32);
   14430      assign(rnT, getIRegA(rN));
   14431 
   14432      /* decide on the transfer address */
   14433      IRTemp taT = IRTemp_INVALID;
   14434      switch (summary & 0x0F) {
   14435         case 1: case 2: taT = eaT; break;
   14436         case 3:         taT = rnT; break;
   14437      }
   14438      vassert(taT != IRTemp_INVALID);
   14439 
   14440      /* XXX deal with alignment constraints */
   14441      /* XXX: but the A8 doesn't seem to trap for misaligned loads, so,
   14442         ignore alignment issues for the time being. */
   14443 
   14444      /* doubleword store  S 1
   14445         doubleword load   S 0
   14446      */
   14447      HChar* name = NULL;
   14448      /* generate the transfers */
   14449      if (bS == 1) { // doubleword store
   14450         storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(0)), getIRegA(rD+0) );
   14451         storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(4)), getIRegA(rD+1) );
   14452         name = "strd";
   14453      } else { // doubleword load
   14454         putIRegA( rD+0,
   14455                   loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(0))),
   14456                   IRTemp_INVALID, Ijk_Boring );
   14457         putIRegA( rD+1,
   14458                   loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(4))),
   14459                   IRTemp_INVALID, Ijk_Boring );
   14460         name = "ldrd";
   14461      }
   14462 
   14463      /* Update Rn if necessary. */
   14464      switch (summary & 0x0F) {
   14465         case 2: case 3:
   14466            // should be assured by logic above:
   14467            if (bS == 0) {
   14468               vassert(rD+0 != rN); /* since we just wrote rD+0 */
   14469               vassert(rD+1 != rN); /* since we just wrote rD+1 */
   14470            }
   14471            putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   14472            break;
   14473      }
   14474 
   14475      switch (summary & 0x0F) {
   14476         case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
   14477                  break;
   14478         case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
   14479                      name, nCC(INSN_COND), rD, dis_buf);
   14480                  break;
   14481         case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
   14482                      name, nCC(INSN_COND), rD, dis_buf);
   14483                  break;
   14484         default: vassert(0);
   14485      }
   14486 
   14487      goto decode_success;
   14488    }
   14489 
   14490   after_load_store_doubleword:
   14491 
   14492    /* ------------------- {s,u}xtab ------------- */
   14493    if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   14494        && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
   14495        && BITS4(0,1,1,1) == INSN(7,4)) {
   14496       UInt rN  = INSN(19,16);
   14497       UInt rD  = INSN(15,12);
   14498       UInt rM  = INSN(3,0);
   14499       UInt rot = (insn >> 10) & 3;
   14500       UInt isU = INSN(22,22);
   14501       if (rN == 15/*it's {S,U}XTB*/ || rD == 15 || rM == 15) {
   14502          /* undecodable; fall through */
   14503       } else {
   14504          IRTemp srcL = newTemp(Ity_I32);
   14505          IRTemp srcR = newTemp(Ity_I32);
   14506          IRTemp res  = newTemp(Ity_I32);
   14507          assign(srcR, getIRegA(rM));
   14508          assign(srcL, getIRegA(rN));
   14509          assign(res,  binop(Iop_Add32,
   14510                             mkexpr(srcL),
   14511                             unop(isU ? Iop_8Uto32 : Iop_8Sto32,
   14512                                  unop(Iop_32to8,
   14513                                       genROR32(srcR, 8 * rot)))));
   14514          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   14515          DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n",
   14516              isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
   14517          goto decode_success;
   14518       }
   14519       /* fall through */
   14520    }
   14521 
   14522    /* ------------------- {s,u}xtah ------------- */
   14523    if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   14524        && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
   14525        && BITS4(0,1,1,1) == INSN(7,4)) {
   14526       UInt rN  = INSN(19,16);
   14527       UInt rD  = INSN(15,12);
   14528       UInt rM  = INSN(3,0);
   14529       UInt rot = (insn >> 10) & 3;
   14530       UInt isU = INSN(22,22);
   14531       if (rN == 15/*it's {S,U}XTH*/ || rD == 15 || rM == 15) {
   14532          /* undecodable; fall through */
   14533       } else {
   14534          IRTemp srcL = newTemp(Ity_I32);
   14535          IRTemp srcR = newTemp(Ity_I32);
   14536          IRTemp res  = newTemp(Ity_I32);
   14537          assign(srcR, getIRegA(rM));
   14538          assign(srcL, getIRegA(rN));
   14539          assign(res,  binop(Iop_Add32,
   14540                             mkexpr(srcL),
   14541                             unop(isU ? Iop_16Uto32 : Iop_16Sto32,
   14542                                  unop(Iop_32to16,
   14543                                       genROR32(srcR, 8 * rot)))));
   14544          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   14545 
   14546          DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n",
   14547              isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
   14548          goto decode_success;
   14549       }
   14550       /* fall through */
   14551    }
   14552 
   14553    /* ------------------- rev16, rev ------------------ */
   14554    if (INSN(27,16) == 0x6BF
   14555        && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) {
   14556       Bool isREV = INSN(11,4) == 0xF3;
   14557       UInt rM    = INSN(3,0);
   14558       UInt rD    = INSN(15,12);
   14559       if (rM != 15 && rD != 15) {
   14560          IRTemp rMt = newTemp(Ity_I32);
   14561          assign(rMt, getIRegA(rM));
   14562          IRTemp res = isREV ? gen_REV(rMt) : gen_REV16(rMt);
   14563          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   14564          DIP("rev%s%s r%u, r%u\n", isREV ? "" : "16",
   14565              nCC(INSN_COND), rD, rM);
   14566          goto decode_success;
   14567       }
   14568    }
   14569 
   14570    /* ------------------- rbit ------------------ */
   14571    if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) {
   14572       UInt rD = INSN(15,12);
   14573       UInt rM = INSN(3,0);
   14574       if (rD != 15 && rM != 15) {
   14575          IRTemp arg = newTemp(Ity_I32);
   14576          assign(arg, getIRegA(rM));
   14577          IRTemp res = gen_BITREV(arg);
   14578          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   14579          DIP("rbit r%u, r%u\n", rD, rM);
   14580          goto decode_success;
   14581       }
   14582    }
   14583 
   14584    /* ------------------- smmul ------------------ */
   14585    if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
   14586        && INSN(15,12) == BITS4(1,1,1,1)
   14587        && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
   14588       UInt bitR = INSN(5,5);
   14589       UInt rD = INSN(19,16);
   14590       UInt rM = INSN(11,8);
   14591       UInt rN = INSN(3,0);
   14592       if (rD != 15 && rM != 15 && rN != 15) {
   14593          IRExpr* res
   14594          = unop(Iop_64HIto32,
   14595                 binop(Iop_Add64,
   14596                       binop(Iop_MullS32, getIRegA(rN), getIRegA(rM)),
   14597                       mkU64(bitR ? 0x80000000ULL : 0ULL)));
   14598          putIRegA(rD, res, condT, Ijk_Boring);
   14599          DIP("smmul%s%s r%u, r%u, r%u\n",
   14600              nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM);
   14601          goto decode_success;
   14602       }
   14603    }
   14604 
   14605    /* ------------------- smmla ------------------ */
   14606    if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
   14607        && INSN(15,12) != BITS4(1,1,1,1)
   14608        && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
   14609       UInt bitR = INSN(5,5);
   14610       UInt rD = INSN(19,16);
   14611       UInt rA = INSN(15,12);
   14612       UInt rM = INSN(11,8);
   14613       UInt rN = INSN(3,0);
   14614       if (rD != 15 && rM != 15 && rN != 15) {
   14615          IRExpr* res
   14616          = unop(Iop_64HIto32,
   14617                 binop(Iop_Add64,
   14618                       binop(Iop_Add64,
   14619                             binop(Iop_32HLto64, getIRegA(rA), mkU32(0)),
   14620                             binop(Iop_MullS32, getIRegA(rN), getIRegA(rM))),
   14621                       mkU64(bitR ? 0x80000000ULL : 0ULL)));
   14622          putIRegA(rD, res, condT, Ijk_Boring);
   14623          DIP("smmla%s%s r%u, r%u, r%u, r%u\n",
   14624              nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM, rA);
   14625          goto decode_success;
   14626       }
   14627    }
   14628 
   14629    /* ------------------- NOP ------------------ */
   14630    if (0x0320F000 == (insn & 0x0FFFFFFF)) {
   14631       DIP("nop%s\n", nCC(INSN_COND));
   14632       goto decode_success;
   14633    }
   14634 
   14635    /* ----------------------------------------------------------- */
   14636    /* -- ARMv7 instructions                                    -- */
   14637    /* ----------------------------------------------------------- */
   14638 
   14639    /* -------------- read CP15 TPIDRURO register ------------- */
   14640    /* mrc     p15, 0, r0, c13, c0, 3  up to
   14641       mrc     p15, 0, r14, c13, c0, 3
   14642    */
   14643    /* I don't know whether this is really v7-only.  But anyway, we
   14644       have to support it since arm-linux uses TPIDRURO as a thread
   14645       state register. */
   14646    if (0x0E1D0F70 == (insn & 0x0FFF0FFF)) {
   14647       UInt rD = INSN(15,12);
   14648       if (rD <= 14) {
   14649          /* skip r15, that's too stupid to handle */
   14650          putIRegA(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32),
   14651                       condT, Ijk_Boring);
   14652          DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND), rD);
   14653          goto decode_success;
   14654       }
   14655       /* fall through */
   14656    }
   14657 
   14658    /* Handle various kinds of barriers.  This is rather indiscriminate
   14659       in the sense that they are all turned into an IR Fence, which
   14660       means we don't know which they are, so the back end has to
   14661       re-emit them all when it comes acrosss an IR Fence.
   14662    */
   14663    /* v6 */ /* mcr 15, 0, rT, c7, c10, 5 */
   14664    if (0xEE070FBA == (insn & 0xFFFF0FFF)) {
   14665       UInt rT = INSN(15,12);
   14666       if (rT <= 14) {
   14667          /* mcr 15, 0, rT, c7, c10, 5 (v6) equiv to DMB (v7).  Data
   14668             Memory Barrier -- ensures ordering of memory accesses. */
   14669          stmt( IRStmt_MBE(Imbe_Fence) );
   14670          DIP("mcr 15, 0, r%u, c7, c10, 5 (data memory barrier)\n", rT);
   14671          goto decode_success;
   14672       }
   14673       /* fall through */
   14674    }
   14675    /* other flavours of barrier */
   14676    switch (insn) {
   14677       case 0xEE070F9A: /* v6 */
   14678          /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7).  Data
   14679             Synch Barrier -- ensures completion of memory accesses. */
   14680          stmt( IRStmt_MBE(Imbe_Fence) );
   14681          DIP("mcr 15, 0, r0, c7, c10, 4 (data synch barrier)\n");
   14682          goto decode_success;
   14683       case 0xEE070F95: /* v6 */
   14684          /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7).
   14685             Instruction Synchronisation Barrier (or Flush Prefetch
   14686             Buffer) -- a pipe flush, I think.  I suspect we could
   14687             ignore those, but to be on the safe side emit a fence
   14688             anyway. */
   14689          stmt( IRStmt_MBE(Imbe_Fence) );
   14690          DIP("mcr 15, 0, r0, c7, c5, 4 (insn synch barrier)\n");
   14691          goto decode_success;
   14692       default:
   14693          break;
   14694    }
   14695 
   14696    /* ----------------------------------------------------------- */
   14697    /* -- VFP (CP 10, CP 11) instructions (in ARM mode)         -- */
   14698    /* ----------------------------------------------------------- */
   14699 
   14700    if (INSN_COND != ARMCondNV) {
   14701       Bool ok_vfp = decode_CP10_CP11_instruction (
   14702                        &dres, INSN(27,0), condT, INSN_COND,
   14703                        False/*!isT*/
   14704                     );
   14705       if (ok_vfp)
   14706          goto decode_success;
   14707    }
   14708 
   14709    /* ----------------------------------------------------------- */
   14710    /* -- NEON instructions (in ARM mode)                       -- */
   14711    /* ----------------------------------------------------------- */
   14712 
   14713    /* These are all in NV space, and so are taken care of (far) above,
   14714       by a call from this function to decode_NV_instruction(). */
   14715 
   14716    /* ----------------------------------------------------------- */
   14717    /* -- v6 media instructions (in ARM mode)                   -- */
   14718    /* ----------------------------------------------------------- */
   14719 
   14720    { Bool ok_v6m = decode_V6MEDIA_instruction(
   14721                        &dres, INSN(27,0), condT, INSN_COND,
   14722                        False/*!isT*/
   14723                    );
   14724      if (ok_v6m)
   14725         goto decode_success;
   14726    }
   14727 
   14728    /* ----------------------------------------------------------- */
   14729    /* -- Undecodable                                           -- */
   14730    /* ----------------------------------------------------------- */
   14731 
   14732    goto decode_failure;
   14733    /*NOTREACHED*/
   14734 
   14735   decode_failure:
   14736    /* All decode failures end up here. */
   14737    vex_printf("disInstr(arm): unhandled instruction: "
   14738               "0x%x\n", insn);
   14739    vex_printf("                 cond=%d(0x%x) 27:20=%u(0x%02x) "
   14740                                 "4:4=%d "
   14741                                 "3:0=%u(0x%x)\n",
   14742               (Int)INSN_COND, (UInt)INSN_COND,
   14743               (Int)INSN(27,20), (UInt)INSN(27,20),
   14744               (Int)INSN(4,4),
   14745               (Int)INSN(3,0), (UInt)INSN(3,0) );
   14746 
   14747    /* Tell the dispatcher that this insn cannot be decoded, and so has
   14748       not been executed, and (is currently) the next to be executed.
   14749       R15 should be up-to-date since it made so at the start of each
   14750       insn, but nevertheless be paranoid and update it again right
   14751       now. */
   14752    vassert(0 == (guest_R15_curr_instr_notENC & 3));
   14753    llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
   14754    dres.whatNext    = Dis_StopHere;
   14755    dres.jk_StopHere = Ijk_NoDecode;
   14756    dres.len         = 0;
   14757    return dres;
   14758 
   14759   decode_success:
   14760    /* All decode successes end up here. */
   14761    DIP("\n");
   14762 
   14763    vassert(dres.len == 4 || dres.len == 20);
   14764 
   14765    /* Now then.  Do we have an implicit jump to r15 to deal with? */
   14766    if (r15written) {
   14767       /* If we get jump to deal with, we assume that there's been no
   14768          other competing branch stuff previously generated for this
   14769          insn.  That's reasonable, in the sense that the ARM insn set
   14770          appears to declare as "Unpredictable" any instruction which
   14771          generates more than one possible new value for r15.  Hence
   14772          just assert.  The decoders themselves should check against
   14773          all such instructions which are thusly Unpredictable, and
   14774          decline to decode them.  Hence we should never get here if we
   14775          have competing new values for r15, and hence it is safe to
   14776          assert here. */
   14777       vassert(dres.whatNext == Dis_Continue);
   14778       vassert(irsb->next == NULL);
   14779       vassert(irsb->jumpkind == Ijk_Boring);
   14780       /* If r15 is unconditionally written, terminate the block by
   14781          jumping to it.  If it's conditionally written, still
   14782          terminate the block (a shame, but we can't do side exits to
   14783          arbitrary destinations), but first jump to the next
   14784          instruction if the condition doesn't hold. */
   14785       /* We can't use getIReg(15) to get the destination, since that
   14786          will produce r15+8, which isn't what we want.  Must use
   14787          llGetIReg(15) instead. */
   14788       if (r15guard == IRTemp_INVALID) {
   14789          /* unconditional */
   14790       } else {
   14791          /* conditional */
   14792          stmt( IRStmt_Exit(
   14793                   unop(Iop_32to1,
   14794                        binop(Iop_Xor32,
   14795                              mkexpr(r15guard), mkU32(1))),
   14796                   r15kind,
   14797                   IRConst_U32(guest_R15_curr_instr_notENC + 4),
   14798                   OFFB_R15T
   14799          ));
   14800       }
   14801       /* This seems crazy, but we're required to finish the insn with
   14802          a write to the guest PC.  As usual we rely on ir_opt to tidy
   14803          up later. */
   14804       llPutIReg(15, llGetIReg(15));
   14805       dres.whatNext    = Dis_StopHere;
   14806       dres.jk_StopHere = r15kind;
   14807    } else {
   14808       /* Set up the end-state in the normal way. */
   14809       switch (dres.whatNext) {
   14810          case Dis_Continue:
   14811             llPutIReg(15, mkU32(dres.len + guest_R15_curr_instr_notENC));
   14812             break;
   14813          case Dis_ResteerU:
   14814          case Dis_ResteerC:
   14815             llPutIReg(15, mkU32(dres.continueAt));
   14816             break;
   14817          case Dis_StopHere:
   14818             break;
   14819          default:
   14820             vassert(0);
   14821       }
   14822    }
   14823 
   14824    return dres;
   14825 
   14826 #  undef INSN_COND
   14827 #  undef INSN
   14828 }
   14829 
   14830 
   14831 /*------------------------------------------------------------*/
   14832 /*--- Disassemble a single Thumb2 instruction              ---*/
   14833 /*------------------------------------------------------------*/
   14834 
   14835 static const UChar it_length_table[256]; /* fwds */
   14836 
   14837 /* NB: in Thumb mode we do fetches of regs with getIRegT, which
   14838    automagically adds 4 to fetches of r15.  However, writes to regs
   14839    are done with putIRegT, which disallows writes to r15.  Hence any
   14840    r15 writes and associated jumps have to be done "by hand". */
   14841 
   14842 /* Disassemble a single Thumb instruction into IR.  The instruction is
   14843    located in host memory at guest_instr, and has (decoded) guest IP
   14844    of guest_R15_curr_instr_notENC, which will have been set before the
   14845    call here. */
   14846 
   14847 static
   14848 DisResult disInstr_THUMB_WRK (
   14849              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
   14850              Bool         resteerCisOk,
   14851              void*        callback_opaque,
   14852              UChar*       guest_instr,
   14853              VexArchInfo* archinfo,
   14854              VexAbiInfo*  abiinfo
   14855           )
   14856 {
   14857    /* A macro to fish bits out of insn0.  There's also INSN1, to fish
   14858       bits out of insn1, but that's defined only after the end of the
   14859       16-bit insn decoder, so as to stop it mistakenly being used
   14860       therein. */
   14861 #  define INSN0(_bMax,_bMin)  SLICE_UInt(((UInt)insn0), (_bMax), (_bMin))
   14862 
   14863    DisResult dres;
   14864    UShort    insn0; /*  first 16 bits of the insn */
   14865    UShort    insn1; /* second 16 bits of the insn */
   14866    //Bool      allow_VFP = False;
   14867    //UInt      hwcaps = archinfo->hwcaps;
   14868    HChar     dis_buf[128];  // big enough to hold LDMIA etc text
   14869 
   14870    /* Summary result of the ITxxx backwards analysis: False == safe
   14871       but suboptimal. */
   14872    Bool guaranteedUnconditional = False;
   14873 
   14874    /* What insn variants are we supporting today? */
   14875    //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
   14876    // etc etc
   14877 
   14878    /* Set result defaults. */
   14879    dres.whatNext    = Dis_Continue;
   14880    dres.len         = 2;
   14881    dres.continueAt  = 0;
   14882    dres.jk_StopHere = Ijk_INVALID;
   14883 
   14884    /* Set default actions for post-insn handling of writes to r15, if
   14885       required. */
   14886    r15written = False;
   14887    r15guard   = IRTemp_INVALID; /* unconditional */
   14888    r15kind    = Ijk_Boring;
   14889 
   14890    /* Insns could be 2 or 4 bytes long.  Just get the first 16 bits at
   14891       this point.  If we need the second 16, get them later.  We can't
   14892       get them both out immediately because it risks a fault (very
   14893       unlikely, but ..) if the second 16 bits aren't actually
   14894       necessary. */
   14895    insn0 = getUShortLittleEndianly( guest_instr );
   14896    insn1 = 0; /* We'll get it later, once we know we need it. */
   14897 
   14898    /* Similarly, will set this later. */
   14899    IRTemp old_itstate = IRTemp_INVALID;
   14900 
   14901    if (0) vex_printf("insn: 0x%x\n", insn0);
   14902 
   14903    DIP("\t(thumb) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
   14904 
   14905    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   14906 
   14907    /* ----------------------------------------------------------- */
   14908    /* Spot "Special" instructions (see comment at top of file). */
   14909    {
   14910       UChar* code = (UChar*)guest_instr;
   14911       /* Spot the 16-byte preamble:
   14912 
   14913          ea4f 0cfc  mov.w   ip, ip, ror #3
   14914          ea4f 3c7c  mov.w   ip, ip, ror #13
   14915          ea4f 7c7c  mov.w   ip, ip, ror #29
   14916          ea4f 4cfc  mov.w   ip, ip, ror #19
   14917       */
   14918       UInt word1 = 0x0CFCEA4F;
   14919       UInt word2 = 0x3C7CEA4F;
   14920       UInt word3 = 0x7C7CEA4F;
   14921       UInt word4 = 0x4CFCEA4F;
   14922       if (getUIntLittleEndianly(code+ 0) == word1 &&
   14923           getUIntLittleEndianly(code+ 4) == word2 &&
   14924           getUIntLittleEndianly(code+ 8) == word3 &&
   14925           getUIntLittleEndianly(code+12) == word4) {
   14926          /* Got a "Special" instruction preamble.  Which one is it? */
   14927          // 0x 0A 0A EA 4A
   14928          if (getUIntLittleEndianly(code+16) == 0x0A0AEA4A
   14929                                                /* orr.w r10,r10,r10 */) {
   14930             /* R3 = client_request ( R4 ) */
   14931             DIP("r3 = client_request ( %%r4 )\n");
   14932             llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ));
   14933             dres.jk_StopHere = Ijk_ClientReq;
   14934             dres.whatNext    = Dis_StopHere;
   14935             goto decode_success;
   14936          }
   14937          else
   14938          // 0x 0B 0B EA 4B
   14939          if (getUIntLittleEndianly(code+16) == 0x0B0BEA4B
   14940                                                /* orr r11,r11,r11 */) {
   14941             /* R3 = guest_NRADDR */
   14942             DIP("r3 = guest_NRADDR\n");
   14943             dres.len = 20;
   14944             llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
   14945             goto decode_success;
   14946          }
   14947          else
   14948          // 0x 0C 0C EA 4C
   14949          if (getUIntLittleEndianly(code+16) == 0x0C0CEA4C
   14950                                                /* orr r12,r12,r12 */) {
   14951             /*  branch-and-link-to-noredir R4 */
   14952             DIP("branch-and-link-to-noredir r4\n");
   14953             llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ));
   14954             llPutIReg(15, getIRegT(4));
   14955             dres.jk_StopHere = Ijk_NoRedir;
   14956             dres.whatNext    = Dis_StopHere;
   14957             goto decode_success;
   14958          }
   14959          /* We don't know what it is.  Set insn0 so decode_failure
   14960             can print the insn following the Special-insn preamble. */
   14961          insn0 = getUShortLittleEndianly(code+16);
   14962          goto decode_failure;
   14963          /*NOTREACHED*/
   14964       }
   14965 
   14966    }
   14967 
   14968    /* ----------------------------------------------------------- */
   14969 
   14970    /* Main Thumb instruction decoder starts here.  It's a series of
   14971       switches which examine ever longer bit sequences at the MSB of
   14972       the instruction word, first for 16-bit insns, then for 32-bit
   14973       insns. */
   14974 
   14975    /* --- BEGIN ITxxx optimisation analysis --- */
   14976    /* This is a crucial optimisation for the ITState boilerplate that
   14977       follows.  Examine the 9 halfwords preceding this instruction,
   14978       and if we are absolutely sure that none of them constitute an
   14979       'it' instruction, then we can be sure that this instruction is
   14980       not under the control of any 'it' instruction, and so
   14981       guest_ITSTATE must be zero.  So write zero into ITSTATE right
   14982       now, so that iropt can fold out almost all of the resulting
   14983       junk.
   14984 
   14985       If we aren't sure, we can always safely skip this step.  So be a
   14986       bit conservative about it: only poke around in the same page as
   14987       this instruction, lest we get a fault from the previous page
   14988       that would not otherwise have happened.  The saving grace is
   14989       that such skipping is pretty rare -- it only happens,
   14990       statistically, 18/4096ths of the time, so is judged unlikely to
   14991       be a performance problems.
   14992 
   14993       FIXME: do better.  Take into account the number of insns covered
   14994       by any IT insns we find, to rule out cases where an IT clearly
   14995       cannot cover this instruction.  This would improve behaviour for
   14996       branch targets immediately following an IT-guarded group that is
   14997       not of full length.  Eg, (and completely ignoring issues of 16-
   14998       vs 32-bit insn length):
   14999 
   15000              ite cond
   15001              insn1
   15002              insn2
   15003       label: insn3
   15004              insn4
   15005 
   15006       The 'it' only conditionalises insn1 and insn2.  However, the
   15007       current analysis is conservative and considers insn3 and insn4
   15008       also possibly guarded.  Hence if 'label:' is the start of a hot
   15009       loop we will get a big performance hit.
   15010    */
   15011    {
   15012       /* Summary result of this analysis: False == safe but
   15013          suboptimal. */
   15014       vassert(guaranteedUnconditional == False);
   15015 
   15016       UInt pc = guest_R15_curr_instr_notENC;
   15017       vassert(0 == (pc & 1));
   15018 
   15019       UInt pageoff = pc & 0xFFF;
   15020       if (pageoff >= 18) {
   15021          /* It's safe to poke about in the 9 halfwords preceding this
   15022             insn.  So, have a look at them. */
   15023          guaranteedUnconditional = True; /* assume no 'it' insn found,
   15024                                             till we do */
   15025          UShort* hwp = (UShort*)(HWord)pc;
   15026          Int i;
   15027          for (i = -1; i >= -9; i--) {
   15028             /* We're in the same page.  (True, but commented out due
   15029                to expense.) */
   15030             /*
   15031             vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 )
   15032                       == ( pc & 0xFFFFF000 ) );
   15033             */
   15034             /* All valid IT instructions must have the form 0xBFxy,
   15035                where x can be anything, but y must be nonzero.  Find
   15036                the number of insns covered by it (1 .. 4) and check to
   15037                see if it can possibly reach up to the instruction in
   15038                question.  Some (x,y) combinations mean UNPREDICTABLE,
   15039                and the table is constructed to be conservative by
   15040                returning 4 for those cases, so the analysis is safe
   15041                even if the code uses unpredictable IT instructions (in
   15042                which case its authors are nuts, but hey.)  */
   15043             UShort hwp_i = hwp[i];
   15044             if (UNLIKELY((hwp_i & 0xFF00) == 0xBF00 && (hwp_i & 0xF) != 0)) {
   15045                /* might be an 'it' insn. */
   15046                /* # guarded insns */
   15047                Int n_guarded = (Int)it_length_table[hwp_i & 0xFF];
   15048                vassert(n_guarded >= 1 && n_guarded <= 4);
   15049                if (n_guarded * 2 /* # guarded HWs, worst case */
   15050                    > (-(i+1)))   /* -(i+1): # remaining HWs after the IT */
   15051                    /* -(i+0) also seems to work, even though I think
   15052                       it's wrong.  I don't understand that. */
   15053                   guaranteedUnconditional = False;
   15054                break;
   15055             }
   15056          }
   15057       }
   15058    }
   15059    /* --- END ITxxx optimisation analysis --- */
   15060 
   15061    /* Generate the guarding condition for this insn, by examining
   15062       ITSTATE.  Assign it to condT.  Also, generate new
   15063       values for ITSTATE ready for stuffing back into the
   15064       guest state, but don't actually do the Put yet, since it will
   15065       need to stuffed back in only after the instruction gets to a
   15066       point where it is sure to complete.  Mostly we let the code at
   15067       decode_success handle this, but in cases where the insn contains
   15068       a side exit, we have to update them before the exit. */
   15069 
   15070    /* If the ITxxx optimisation analysis above could not prove that
   15071       this instruction is guaranteed unconditional, we insert a
   15072       lengthy IR preamble to compute the guarding condition at
   15073       runtime.  If it can prove it (which obviously we hope is the
   15074       normal case) then we insert a minimal preamble, which is
   15075       equivalent to setting guest_ITSTATE to zero and then folding
   15076       that through the full preamble (which completely disappears). */
   15077 
   15078    IRTemp condT              = IRTemp_INVALID;
   15079    IRTemp cond_AND_notInIT_T = IRTemp_INVALID;
   15080 
   15081    IRTemp new_itstate        = IRTemp_INVALID;
   15082    vassert(old_itstate == IRTemp_INVALID);
   15083 
   15084    if (guaranteedUnconditional) {
   15085       /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
   15086 
   15087       // ITSTATE = 0 :: I32
   15088       IRTemp z32 = newTemp(Ity_I32);
   15089       assign(z32, mkU32(0));
   15090       put_ITSTATE(z32);
   15091 
   15092       // old_itstate = 0 :: I32
   15093       //
   15094       // old_itstate = get_ITSTATE();
   15095       old_itstate = z32; /* 0 :: I32 */
   15096 
   15097       // new_itstate = old_itstate >> 8
   15098       //             = 0 >> 8
   15099       //             = 0 :: I32
   15100       //
   15101       // new_itstate = newTemp(Ity_I32);
   15102       // assign(new_itstate,
   15103       //        binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
   15104       new_itstate = z32;
   15105 
   15106       // ITSTATE = 0 :: I32(again)
   15107       //
   15108       // put_ITSTATE(new_itstate);
   15109 
   15110       // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) )
   15111       //        = calc_cond_dyn( xor(0,0xE0) )
   15112       //        = calc_cond_dyn ( 0xE0 )
   15113       //        = 1 :: I32
   15114       // Not that this matters, since the computed value is not used:
   15115       // see condT folding below
   15116       //
   15117       // IRTemp condT1 = newTemp(Ity_I32);
   15118       // assign(condT1,
   15119       //        mk_armg_calculate_condition_dyn(
   15120       //           binop(Iop_Xor32,
   15121       //                 binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
   15122       //                 mkU32(0xE0))
   15123       //       )
   15124       // );
   15125 
   15126       // condT = 32to8(and32(old_itstate,0xF0)) == 0  ? 1  : condT1
   15127       //       = 32to8(and32(0,0xF0)) == 0  ? 1  : condT1
   15128       //       = 32to8(0) == 0  ? 1  : condT1
   15129       //       = 0 == 0  ? 1  : condT1
   15130       //       = 1
   15131       //
   15132       // condT = newTemp(Ity_I32);
   15133       // assign(condT, IRExpr_Mux0X(
   15134       //                  unop(Iop_32to8, binop(Iop_And32,
   15135       //                                        mkexpr(old_itstate),
   15136       //                                        mkU32(0xF0))),
   15137       //                  mkU32(1),
   15138       //                  mkexpr(condT1)
   15139       //       ));
   15140       condT = newTemp(Ity_I32);
   15141       assign(condT, mkU32(1));
   15142 
   15143       // notInITt = xor32(and32(old_itstate, 1), 1)
   15144       //          = xor32(and32(0, 1), 1)
   15145       //          = xor32(0, 1)
   15146       //          = 1 :: I32
   15147       //
   15148       // IRTemp notInITt = newTemp(Ity_I32);
   15149       // assign(notInITt,
   15150       //        binop(Iop_Xor32,
   15151       //              binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
   15152       //              mkU32(1)));
   15153 
   15154       // cond_AND_notInIT_T = and32(notInITt, condT)
   15155       //                    = and32(1, 1)
   15156       //                    = 1
   15157       //
   15158       // cond_AND_notInIT_T = newTemp(Ity_I32);
   15159       // assign(cond_AND_notInIT_T,
   15160       //        binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
   15161       cond_AND_notInIT_T = condT; /* 1 :: I32 */
   15162 
   15163       /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
   15164    } else {
   15165       /* BEGIN { STANDARD PREAMBLE; } */
   15166 
   15167       old_itstate = get_ITSTATE();
   15168 
   15169       new_itstate = newTemp(Ity_I32);
   15170       assign(new_itstate,
   15171              binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
   15172 
   15173       put_ITSTATE(new_itstate);
   15174 
   15175       /* Same strategy as for ARM insns: generate a condition
   15176          temporary at this point (or IRTemp_INVALID, meaning
   15177          unconditional).  We leave it to lower-level instruction
   15178          decoders to decide whether they can generate straight-line
   15179          code, or whether they must generate a side exit before the
   15180          instruction.  condT :: Ity_I32 and is always either zero or
   15181          one. */
   15182       IRTemp condT1 = newTemp(Ity_I32);
   15183       assign(condT1,
   15184              mk_armg_calculate_condition_dyn(
   15185                 binop(Iop_Xor32,
   15186                       binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
   15187                       mkU32(0xE0))
   15188             )
   15189       );
   15190 
   15191       /* This is a bit complex, but needed to make Memcheck understand
   15192          that, if the condition in old_itstate[7:4] denotes AL (that
   15193          is, if this instruction is to be executed unconditionally),
   15194          then condT does not depend on the results of calling the
   15195          helper.
   15196 
   15197          We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in
   15198          that case set condT directly to 1.  Else we use the results
   15199          of the helper.  Since old_itstate is always defined and
   15200          because Memcheck does lazy V-bit propagation through Mux0X,
   15201          this will cause condT to always be a defined 1 if the
   15202          condition is 'AL'.  From an execution semantics point of view
   15203          this is irrelevant since we're merely duplicating part of the
   15204          behaviour of the helper.  But it makes it clear to Memcheck,
   15205          in this case, that condT does not in fact depend on the
   15206          contents of the condition code thunk.  Without it, we get
   15207          quite a lot of false errors.
   15208 
   15209          So, just to clarify: from a straight semantics point of view,
   15210          we can simply do "assign(condT, mkexpr(condT1))", and the
   15211          simulator still runs fine.  It's just that we get loads of
   15212          false errors from Memcheck. */
   15213       condT = newTemp(Ity_I32);
   15214       assign(condT, IRExpr_Mux0X(
   15215                        unop(Iop_32to8, binop(Iop_And32,
   15216                                              mkexpr(old_itstate),
   15217                                              mkU32(0xF0))),
   15218                        mkU32(1),
   15219                        mkexpr(condT1)
   15220             ));
   15221 
   15222       /* Something we don't have in ARM: generate a 0 or 1 value
   15223          indicating whether or not we are in an IT block (NB: 0 = in
   15224          IT block, 1 = not in IT block).  This is used to gate
   15225          condition code updates in 16-bit Thumb instructions. */
   15226       IRTemp notInITt = newTemp(Ity_I32);
   15227       assign(notInITt,
   15228              binop(Iop_Xor32,
   15229                    binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
   15230                    mkU32(1)));
   15231 
   15232       /* Compute 'condT && notInITt' -- that is, the instruction is
   15233          going to execute, and we're not in an IT block.  This is the
   15234          gating condition for updating condition codes in 16-bit Thumb
   15235          instructions, except for CMP, CMN and TST. */
   15236       cond_AND_notInIT_T = newTemp(Ity_I32);
   15237       assign(cond_AND_notInIT_T,
   15238              binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
   15239       /* END { STANDARD PREAMBLE; } */
   15240    }
   15241 
   15242 
   15243    /* At this point:
   15244       * ITSTATE has been updated
   15245       * condT holds the guarding condition for this instruction (0 or 1),
   15246       * notInITt is 1 if we're in "normal" code, 0 if in an IT block
   15247       * cond_AND_notInIT_T is the AND of the above two.
   15248 
   15249       If the instruction proper can't trap, then there's nothing else
   15250       to do w.r.t. ITSTATE -- just go and and generate IR for the
   15251       insn, taking into account the guarding condition.
   15252 
   15253       If, however, the instruction might trap, then we must back up
   15254       ITSTATE to the old value, and re-update it after the potentially
   15255       trapping IR section.  A trap can happen either via a memory
   15256       reference or because we need to throw SIGILL.
   15257 
   15258       If an instruction has a side exit, we need to be sure that any
   15259       ITSTATE backup is re-updated before the side exit.
   15260    */
   15261 
   15262    /* ----------------------------------------------------------- */
   15263    /* --                                                       -- */
   15264    /* -- Thumb 16-bit integer instructions                     -- */
   15265    /* --                                                       -- */
   15266    /* -- IMPORTANT: references to insn1 or INSN1 are           -- */
   15267    /* --            not allowed in this section                -- */
   15268    /* --                                                       -- */
   15269    /* ----------------------------------------------------------- */
   15270 
   15271    /* 16-bit instructions inside an IT block, apart from CMP, CMN and
   15272       TST, do not set the condition codes.  Hence we must dynamically
   15273       test for this case for every condition code update. */
   15274 
   15275    IROp   anOp   = Iop_INVALID;
   15276    HChar* anOpNm = NULL;
   15277 
   15278    /* ================ 16-bit 15:6 cases ================ */
   15279 
   15280    switch (INSN0(15,6)) {
   15281 
   15282    case 0x10a:   // CMP
   15283    case 0x10b: { // CMN
   15284       /* ---------------- CMP Rn, Rm ---------------- */
   15285       Bool   isCMN = INSN0(15,6) == 0x10b;
   15286       UInt   rN    = INSN0(2,0);
   15287       UInt   rM    = INSN0(5,3);
   15288       IRTemp argL  = newTemp(Ity_I32);
   15289       IRTemp argR  = newTemp(Ity_I32);
   15290       assign( argL, getIRegT(rN) );
   15291       assign( argR, getIRegT(rM) );
   15292       /* Update flags regardless of whether in an IT block or not. */
   15293       setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   15294                       argL, argR, condT );
   15295       DIP("%s r%u, r%u\n", isCMN ? "cmn" : "cmp", rN, rM);
   15296       goto decode_success;
   15297    }
   15298 
   15299    case 0x108: {
   15300       /* ---------------- TST Rn, Rm ---------------- */
   15301       UInt   rN   = INSN0(2,0);
   15302       UInt   rM   = INSN0(5,3);
   15303       IRTemp oldC = newTemp(Ity_I32);
   15304       IRTemp oldV = newTemp(Ity_I32);
   15305       IRTemp res  = newTemp(Ity_I32);
   15306       assign( oldC, mk_armg_calculate_flag_c() );
   15307       assign( oldV, mk_armg_calculate_flag_v() );
   15308       assign( res,  binop(Iop_And32, getIRegT(rN), getIRegT(rM)) );
   15309       /* Update flags regardless of whether in an IT block or not. */
   15310       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
   15311       DIP("tst r%u, r%u\n", rN, rM);
   15312       goto decode_success;
   15313    }
   15314 
   15315    case 0x109: {
   15316       /* ---------------- NEGS Rd, Rm ---------------- */
   15317       /* Rd = -Rm */
   15318       UInt   rM   = INSN0(5,3);
   15319       UInt   rD   = INSN0(2,0);
   15320       IRTemp arg  = newTemp(Ity_I32);
   15321       IRTemp zero = newTemp(Ity_I32);
   15322       assign(arg, getIRegT(rM));
   15323       assign(zero, mkU32(0));
   15324       // rD can never be r15
   15325       putIRegT(rD, binop(Iop_Sub32, mkexpr(zero), mkexpr(arg)), condT);
   15326       setFlags_D1_D2( ARMG_CC_OP_SUB, zero, arg, cond_AND_notInIT_T);
   15327       DIP("negs r%u, r%u\n", rD, rM);
   15328       goto decode_success;
   15329    }
   15330 
   15331    case 0x10F: {
   15332       /* ---------------- MVNS Rd, Rm ---------------- */
   15333       /* Rd = ~Rm */
   15334       UInt   rM   = INSN0(5,3);
   15335       UInt   rD   = INSN0(2,0);
   15336       IRTemp oldV = newTemp(Ity_I32);
   15337       IRTemp oldC = newTemp(Ity_I32);
   15338       IRTemp res  = newTemp(Ity_I32);
   15339       assign( oldV, mk_armg_calculate_flag_v() );
   15340       assign( oldC, mk_armg_calculate_flag_c() );
   15341       assign(res, unop(Iop_Not32, getIRegT(rM)));
   15342       // rD can never be r15
   15343       putIRegT(rD, mkexpr(res), condT);
   15344       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   15345                          cond_AND_notInIT_T );
   15346       DIP("mvns r%u, r%u\n", rD, rM);
   15347       goto decode_success;
   15348    }
   15349 
   15350    case 0x10C:
   15351       /* ---------------- ORRS Rd, Rm ---------------- */
   15352       anOp = Iop_Or32; anOpNm = "orr"; goto and_orr_eor_mul;
   15353    case 0x100:
   15354       /* ---------------- ANDS Rd, Rm ---------------- */
   15355       anOp = Iop_And32; anOpNm = "and"; goto and_orr_eor_mul;
   15356    case 0x101:
   15357       /* ---------------- EORS Rd, Rm ---------------- */
   15358       anOp = Iop_Xor32; anOpNm = "eor"; goto and_orr_eor_mul;
   15359    case 0x10d:
   15360       /* ---------------- MULS Rd, Rm ---------------- */
   15361       anOp = Iop_Mul32; anOpNm = "mul"; goto and_orr_eor_mul;
   15362    and_orr_eor_mul: {
   15363       /* Rd = Rd `op` Rm */
   15364       UInt   rM   = INSN0(5,3);
   15365       UInt   rD   = INSN0(2,0);
   15366       IRTemp res  = newTemp(Ity_I32);
   15367       IRTemp oldV = newTemp(Ity_I32);
   15368       IRTemp oldC = newTemp(Ity_I32);
   15369       assign( oldV, mk_armg_calculate_flag_v() );
   15370       assign( oldC, mk_armg_calculate_flag_c() );
   15371       assign( res, binop(anOp, getIRegT(rD), getIRegT(rM) ));
   15372       // not safe to read guest state after here
   15373       // rD can never be r15
   15374       putIRegT(rD, mkexpr(res), condT);
   15375       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   15376                          cond_AND_notInIT_T );
   15377       DIP("%s r%u, r%u\n", anOpNm, rD, rM);
   15378       goto decode_success;
   15379    }
   15380 
   15381    case 0x10E: {
   15382       /* ---------------- BICS Rd, Rm ---------------- */
   15383       /* Rd = Rd & ~Rm */
   15384       UInt   rM   = INSN0(5,3);
   15385       UInt   rD   = INSN0(2,0);
   15386       IRTemp res  = newTemp(Ity_I32);
   15387       IRTemp oldV = newTemp(Ity_I32);
   15388       IRTemp oldC = newTemp(Ity_I32);
   15389       assign( oldV, mk_armg_calculate_flag_v() );
   15390       assign( oldC, mk_armg_calculate_flag_c() );
   15391       assign( res, binop(Iop_And32, getIRegT(rD),
   15392                                     unop(Iop_Not32, getIRegT(rM) )));
   15393       // not safe to read guest state after here
   15394       // rD can never be r15
   15395       putIRegT(rD, mkexpr(res), condT);
   15396       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   15397                          cond_AND_notInIT_T );
   15398       DIP("bics r%u, r%u\n", rD, rM);
   15399       goto decode_success;
   15400    }
   15401 
   15402    case 0x105: {
   15403       /* ---------------- ADCS Rd, Rm ---------------- */
   15404       /* Rd = Rd + Rm + oldC */
   15405       UInt   rM   = INSN0(5,3);
   15406       UInt   rD   = INSN0(2,0);
   15407       IRTemp argL = newTemp(Ity_I32);
   15408       IRTemp argR = newTemp(Ity_I32);
   15409       IRTemp oldC = newTemp(Ity_I32);
   15410       IRTemp res  = newTemp(Ity_I32);
   15411       assign(argL, getIRegT(rD));
   15412       assign(argR, getIRegT(rM));
   15413       assign(oldC, mk_armg_calculate_flag_c());
   15414       assign(res, binop(Iop_Add32,
   15415                         binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
   15416                         mkexpr(oldC)));
   15417       // rD can never be r15
   15418       putIRegT(rD, mkexpr(res), condT);
   15419       setFlags_D1_D2_ND( ARMG_CC_OP_ADC, argL, argR, oldC,
   15420                          cond_AND_notInIT_T );
   15421       DIP("adcs r%u, r%u\n", rD, rM);
   15422       goto decode_success;
   15423    }
   15424 
   15425    case 0x106: {
   15426       /* ---------------- SBCS Rd, Rm ---------------- */
   15427       /* Rd = Rd - Rm - (oldC ^ 1) */
   15428       UInt   rM   = INSN0(5,3);
   15429       UInt   rD   = INSN0(2,0);
   15430       IRTemp argL = newTemp(Ity_I32);
   15431       IRTemp argR = newTemp(Ity_I32);
   15432       IRTemp oldC = newTemp(Ity_I32);
   15433       IRTemp res  = newTemp(Ity_I32);
   15434       assign(argL, getIRegT(rD));
   15435       assign(argR, getIRegT(rM));
   15436       assign(oldC, mk_armg_calculate_flag_c());
   15437       assign(res, binop(Iop_Sub32,
   15438                         binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
   15439                         binop(Iop_Xor32, mkexpr(oldC), mkU32(1))));
   15440       // rD can never be r15
   15441       putIRegT(rD, mkexpr(res), condT);
   15442       setFlags_D1_D2_ND( ARMG_CC_OP_SBB, argL, argR, oldC,
   15443                          cond_AND_notInIT_T );
   15444       DIP("sbcs r%u, r%u\n", rD, rM);
   15445       goto decode_success;
   15446    }
   15447 
   15448    case 0x2CB: {
   15449       /* ---------------- UXTB Rd, Rm ---------------- */
   15450       /* Rd = 8Uto32(Rm) */
   15451       UInt rM = INSN0(5,3);
   15452       UInt rD = INSN0(2,0);
   15453       putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFF)),
   15454                    condT);
   15455       DIP("uxtb r%u, r%u\n", rD, rM);
   15456       goto decode_success;
   15457    }
   15458 
   15459    case 0x2C9: {
   15460       /* ---------------- SXTB Rd, Rm ---------------- */
   15461       /* Rd = 8Sto32(Rm) */
   15462       UInt rM = INSN0(5,3);
   15463       UInt rD = INSN0(2,0);
   15464       putIRegT(rD, binop(Iop_Sar32,
   15465                          binop(Iop_Shl32, getIRegT(rM), mkU8(24)),
   15466                          mkU8(24)),
   15467                    condT);
   15468       DIP("sxtb r%u, r%u\n", rD, rM);
   15469       goto decode_success;
   15470    }
   15471 
   15472    case 0x2CA: {
   15473       /* ---------------- UXTH Rd, Rm ---------------- */
   15474       /* Rd = 16Uto32(Rm) */
   15475       UInt rM = INSN0(5,3);
   15476       UInt rD = INSN0(2,0);
   15477       putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFFFF)),
   15478                    condT);
   15479       DIP("uxth r%u, r%u\n", rD, rM);
   15480       goto decode_success;
   15481    }
   15482 
   15483    case 0x2C8: {
   15484       /* ---------------- SXTH Rd, Rm ---------------- */
   15485       /* Rd = 16Sto32(Rm) */
   15486       UInt rM = INSN0(5,3);
   15487       UInt rD = INSN0(2,0);
   15488       putIRegT(rD, binop(Iop_Sar32,
   15489                          binop(Iop_Shl32, getIRegT(rM), mkU8(16)),
   15490                          mkU8(16)),
   15491                    condT);
   15492       DIP("sxth r%u, r%u\n", rD, rM);
   15493       goto decode_success;
   15494    }
   15495 
   15496    case 0x102:   // LSLS
   15497    case 0x103:   // LSRS
   15498    case 0x104:   // ASRS
   15499    case 0x107: { // RORS
   15500       /* ---------------- LSLS Rs, Rd ---------------- */
   15501       /* ---------------- LSRS Rs, Rd ---------------- */
   15502       /* ---------------- ASRS Rs, Rd ---------------- */
   15503       /* ---------------- RORS Rs, Rd ---------------- */
   15504       /* Rd = Rd `op` Rs, and set flags */
   15505       UInt   rS   = INSN0(5,3);
   15506       UInt   rD   = INSN0(2,0);
   15507       IRTemp oldV = newTemp(Ity_I32);
   15508       IRTemp rDt  = newTemp(Ity_I32);
   15509       IRTemp rSt  = newTemp(Ity_I32);
   15510       IRTemp res  = newTemp(Ity_I32);
   15511       IRTemp resC = newTemp(Ity_I32);
   15512       HChar* wot  = "???";
   15513       assign(rSt, getIRegT(rS));
   15514       assign(rDt, getIRegT(rD));
   15515       assign(oldV, mk_armg_calculate_flag_v());
   15516       /* Does not appear to be the standard 'how' encoding. */
   15517       switch (INSN0(15,6)) {
   15518          case 0x102:
   15519             compute_result_and_C_after_LSL_by_reg(
   15520                dis_buf, &res, &resC, rDt, rSt, rD, rS
   15521             );
   15522             wot = "lsl";
   15523             break;
   15524          case 0x103:
   15525             compute_result_and_C_after_LSR_by_reg(
   15526                dis_buf, &res, &resC, rDt, rSt, rD, rS
   15527             );
   15528             wot = "lsr";
   15529             break;
   15530          case 0x104:
   15531             compute_result_and_C_after_ASR_by_reg(
   15532                dis_buf, &res, &resC, rDt, rSt, rD, rS
   15533             );
   15534             wot = "asr";
   15535             break;
   15536          case 0x107:
   15537             compute_result_and_C_after_ROR_by_reg(
   15538                dis_buf, &res, &resC, rDt, rSt, rD, rS
   15539             );
   15540             wot = "ror";
   15541             break;
   15542          default:
   15543             /*NOTREACHED*/vassert(0);
   15544       }
   15545       // not safe to read guest state after this point
   15546       putIRegT(rD, mkexpr(res), condT);
   15547       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
   15548                          cond_AND_notInIT_T );
   15549       DIP("%ss r%u, r%u\n", wot, rS, rD);
   15550       goto decode_success;
   15551    }
   15552 
   15553    case 0x2E8:   // REV
   15554    case 0x2E9: { // REV16
   15555       /* ---------------- REV   Rd, Rm ---------------- */
   15556       /* ---------------- REV16 Rd, Rm ---------------- */
   15557       UInt rM = INSN0(5,3);
   15558       UInt rD = INSN0(2,0);
   15559       Bool isREV = INSN0(15,6) == 0x2E8;
   15560       IRTemp arg = newTemp(Ity_I32);
   15561       assign(arg, getIRegT(rM));
   15562       IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
   15563       putIRegT(rD, mkexpr(res), condT);
   15564       DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM);
   15565       goto decode_success;
   15566    }
   15567 
   15568    default:
   15569       break; /* examine the next shortest prefix */
   15570 
   15571    }
   15572 
   15573 
   15574    /* ================ 16-bit 15:7 cases ================ */
   15575 
   15576    switch (INSN0(15,7)) {
   15577 
   15578    case BITS9(1,0,1,1,0,0,0,0,0): {
   15579       /* ------------ ADD SP, #imm7 * 4 ------------ */
   15580       UInt uimm7 = INSN0(6,0);
   15581       putIRegT(13, binop(Iop_Add32, getIRegT(13), mkU32(uimm7 * 4)),
   15582                    condT);
   15583       DIP("add sp, #%u\n", uimm7 * 4);
   15584       goto decode_success;
   15585    }
   15586 
   15587    case BITS9(1,0,1,1,0,0,0,0,1): {
   15588       /* ------------ SUB SP, #imm7 * 4 ------------ */
   15589       UInt uimm7 = INSN0(6,0);
   15590       putIRegT(13, binop(Iop_Sub32, getIRegT(13), mkU32(uimm7 * 4)),
   15591                    condT);
   15592       DIP("sub sp, #%u\n", uimm7 * 4);
   15593       goto decode_success;
   15594    }
   15595 
   15596    case BITS9(0,1,0,0,0,1,1,1,0): {
   15597       /* ---------------- BX rM ---------------- */
   15598       /* Branch to reg, and optionally switch modes.  Reg contains a
   15599          suitably encoded address therefore (w CPSR.T at the bottom).
   15600          Have to special-case r15, as usual. */
   15601       UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
   15602       if (BITS3(0,0,0) == INSN0(2,0)) {
   15603          IRTemp dst = newTemp(Ity_I32);
   15604          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15605          mk_skip_over_T16_if_cond_is_false(condT);
   15606          condT = IRTemp_INVALID;
   15607          // now uncond
   15608          if (rM <= 14) {
   15609             assign( dst, getIRegT(rM) );
   15610          } else {
   15611             vassert(rM == 15);
   15612             assign( dst, mkU32(guest_R15_curr_instr_notENC + 4) );
   15613          }
   15614          llPutIReg(15, mkexpr(dst));
   15615          dres.jk_StopHere = rM == 14 ? Ijk_Ret : Ijk_Boring;
   15616          dres.whatNext    = Dis_StopHere;
   15617          DIP("bx r%u (possibly switch to ARM mode)\n", rM);
   15618          goto decode_success;
   15619       }
   15620       break;
   15621    }
   15622 
   15623    /* ---------------- BLX rM ---------------- */
   15624    /* Branch and link to interworking address in rM. */
   15625    case BITS9(0,1,0,0,0,1,1,1,1): {
   15626       if (BITS3(0,0,0) == INSN0(2,0)) {
   15627          UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
   15628          IRTemp dst = newTemp(Ity_I32);
   15629          if (rM <= 14) {
   15630             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15631             mk_skip_over_T16_if_cond_is_false(condT);
   15632             condT = IRTemp_INVALID;
   15633             // now uncond
   15634             /* We're returning to Thumb code, hence "| 1" */
   15635             assign( dst, getIRegT(rM) );
   15636             putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ),
   15637                           IRTemp_INVALID );
   15638             llPutIReg(15, mkexpr(dst));
   15639             dres.jk_StopHere = Ijk_Call;
   15640             dres.whatNext    = Dis_StopHere;
   15641             DIP("blx r%u (possibly switch to ARM mode)\n", rM);
   15642             goto decode_success;
   15643          }
   15644          /* else unpredictable, fall through */
   15645       }
   15646       break;
   15647    }
   15648 
   15649    default:
   15650       break; /* examine the next shortest prefix */
   15651 
   15652    }
   15653 
   15654 
   15655    /* ================ 16-bit 15:8 cases ================ */
   15656 
   15657    switch (INSN0(15,8)) {
   15658 
   15659    case BITS8(1,1,0,1,1,1,1,1): {
   15660       /* ---------------- SVC ---------------- */
   15661       UInt imm8 = INSN0(7,0);
   15662       if (imm8 == 0) {
   15663          /* A syscall.  We can't do this conditionally, hence: */
   15664          mk_skip_over_T16_if_cond_is_false( condT );
   15665          // FIXME: what if we have to back up and restart this insn?
   15666          // then ITSTATE will be wrong (we'll have it as "used")
   15667          // when it isn't.  Correct is to save ITSTATE in a
   15668          // stash pseudo-reg, and back up from that if we have to
   15669          // restart.
   15670          // uncond after here
   15671          llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ));
   15672          dres.jk_StopHere = Ijk_Sys_syscall;
   15673          dres.whatNext    = Dis_StopHere;
   15674          DIP("svc #0x%08x\n", imm8);
   15675          goto decode_success;
   15676       }
   15677       /* else fall through */
   15678       break;
   15679    }
   15680 
   15681    case BITS8(0,1,0,0,0,1,0,0): {
   15682       /* ---------------- ADD(HI) Rd, Rm ---------------- */
   15683       UInt h1 = INSN0(7,7);
   15684       UInt h2 = INSN0(6,6);
   15685       UInt rM = (h2 << 3) | INSN0(5,3);
   15686       UInt rD = (h1 << 3) | INSN0(2,0);
   15687       //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive
   15688       if (rD == 15 && rM == 15) {
   15689          // then it's invalid
   15690       } else {
   15691          IRTemp res = newTemp(Ity_I32);
   15692          assign( res, binop(Iop_Add32, getIRegT(rD), getIRegT(rM) ));
   15693          if (rD != 15) {
   15694             putIRegT( rD, mkexpr(res), condT );
   15695          } else {
   15696             /* Only allowed outside or last-in IT block; SIGILL if not so. */
   15697             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15698             /* jump over insn if not selected */
   15699             mk_skip_over_T16_if_cond_is_false(condT);
   15700             condT = IRTemp_INVALID;
   15701             // now uncond
   15702             /* non-interworking branch */
   15703             irsb->next = binop(Iop_Or32, mkexpr(res), mkU32(1));
   15704             irsb->jumpkind = Ijk_Boring;
   15705             dres.whatNext = Dis_StopHere;
   15706          }
   15707          DIP("add(hi) r%u, r%u\n", rD, rM);
   15708          goto decode_success;
   15709       }
   15710       break;
   15711    }
   15712 
   15713    case BITS8(0,1,0,0,0,1,0,1): {
   15714       /* ---------------- CMP(HI) Rd, Rm ---------------- */
   15715       UInt h1 = INSN0(7,7);
   15716       UInt h2 = INSN0(6,6);
   15717       UInt rM = (h2 << 3) | INSN0(5,3);
   15718       UInt rN = (h1 << 3) | INSN0(2,0);
   15719       if (h1 != 0 || h2 != 0) {
   15720          IRTemp argL  = newTemp(Ity_I32);
   15721          IRTemp argR  = newTemp(Ity_I32);
   15722          assign( argL, getIRegT(rN) );
   15723          assign( argR, getIRegT(rM) );
   15724          /* Update flags regardless of whether in an IT block or not. */
   15725          setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   15726          DIP("cmphi r%u, r%u\n", rN, rM);
   15727          goto decode_success;
   15728       }
   15729       break;
   15730    }
   15731 
   15732    case BITS8(0,1,0,0,0,1,1,0): {
   15733       /* ---------------- MOV(HI) Rd, Rm ---------------- */
   15734       UInt h1 = INSN0(7,7);
   15735       UInt h2 = INSN0(6,6);
   15736       UInt rM = (h2 << 3) | INSN0(5,3);
   15737       UInt rD = (h1 << 3) | INSN0(2,0);
   15738       /* The old ARM ARM seems to disallow the case where both Rd and
   15739          Rm are "low" registers, but newer versions allow it. */
   15740       if (1 /*h1 != 0 || h2 != 0*/) {
   15741          IRTemp val = newTemp(Ity_I32);
   15742          assign( val, getIRegT(rM) );
   15743          if (rD != 15) {
   15744             putIRegT( rD, mkexpr(val), condT );
   15745          } else {
   15746             /* Only allowed outside or last-in IT block; SIGILL if not so. */
   15747             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15748             /* jump over insn if not selected */
   15749             mk_skip_over_T16_if_cond_is_false(condT);
   15750             condT = IRTemp_INVALID;
   15751             // now uncond
   15752             /* non-interworking branch */
   15753             llPutIReg(15, binop(Iop_Or32, mkexpr(val), mkU32(1)));
   15754             dres.jk_StopHere = rM == 14 ? Ijk_Ret : Ijk_Boring;
   15755             dres.whatNext    = Dis_StopHere;
   15756          }
   15757          DIP("mov r%u, r%u\n", rD, rM);
   15758          goto decode_success;
   15759       }
   15760       break;
   15761    }
   15762 
   15763    case BITS8(1,0,1,1,1,1,1,1): {
   15764       /* ---------------- IT (if-then) ---------------- */
   15765       UInt firstcond = INSN0(7,4);
   15766       UInt mask = INSN0(3,0);
   15767       UInt newITSTATE = 0;
   15768       /* This is the ITSTATE represented as described in
   15769          libvex_guest_arm.h.  It is not the ARM ARM representation. */
   15770       UChar c1 = '.';
   15771       UChar c2 = '.';
   15772       UChar c3 = '.';
   15773       Bool valid = compute_ITSTATE( &newITSTATE, &c1, &c2, &c3,
   15774                                     firstcond, mask );
   15775       if (valid && firstcond != 0xF/*NV*/) {
   15776          /* Not allowed in an IT block; SIGILL if so. */
   15777          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   15778 
   15779          IRTemp t = newTemp(Ity_I32);
   15780          assign(t, mkU32(newITSTATE));
   15781          put_ITSTATE(t);
   15782 
   15783          DIP("it%c%c%c %s\n", c1, c2, c3, nCC(firstcond));
   15784          goto decode_success;
   15785       }
   15786       break;
   15787    }
   15788 
   15789    case BITS8(1,0,1,1,0,0,0,1):
   15790    case BITS8(1,0,1,1,0,0,1,1):
   15791    case BITS8(1,0,1,1,1,0,0,1):
   15792    case BITS8(1,0,1,1,1,0,1,1): {
   15793       /* ---------------- CB{N}Z ---------------- */
   15794       UInt rN    = INSN0(2,0);
   15795       UInt bOP   = INSN0(11,11);
   15796       UInt imm32 = (INSN0(9,9) << 6) | (INSN0(7,3) << 1);
   15797       gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   15798       /* It's a conditional branch forward. */
   15799       IRTemp kond = newTemp(Ity_I1);
   15800       assign( kond, binop(bOP ? Iop_CmpNE32 : Iop_CmpEQ32,
   15801                           getIRegT(rN), mkU32(0)) );
   15802 
   15803       vassert(0 == (guest_R15_curr_instr_notENC & 1));
   15804       /* Looks like the nearest insn we can branch to is the one after
   15805          next.  That makes sense, as there's no point in being able to
   15806          encode a conditional branch to the next instruction. */
   15807       UInt dst = (guest_R15_curr_instr_notENC + 4 + imm32) | 1;
   15808       stmt(IRStmt_Exit( mkexpr(kond),
   15809                         Ijk_Boring,
   15810                         IRConst_U32(toUInt(dst)),
   15811                         OFFB_R15T ));
   15812       DIP("cb%s r%u, 0x%x\n", bOP ? "nz" : "z", rN, dst - 1);
   15813       goto decode_success;
   15814    }
   15815 
   15816    default:
   15817       break; /* examine the next shortest prefix */
   15818 
   15819    }
   15820 
   15821 
   15822    /* ================ 16-bit 15:9 cases ================ */
   15823 
   15824    switch (INSN0(15,9)) {
   15825 
   15826    case BITS7(1,0,1,1,0,1,0): {
   15827       /* ---------------- PUSH ---------------- */
   15828       /* This is a bit like STMxx, but way simpler. Complications we
   15829          don't have to deal with:
   15830          * SP being one of the transferred registers
   15831          * direction (increment vs decrement)
   15832          * before-vs-after-ness
   15833       */
   15834       Int  i, nRegs;
   15835       UInt bitR    = INSN0(8,8);
   15836       UInt regList = INSN0(7,0);
   15837       if (bitR) regList |= (1 << 14);
   15838 
   15839       /* At least one register must be transferred, else result is
   15840          UNPREDICTABLE. */
   15841       if (regList != 0) {
   15842          /* Since we can't generate a guaranteed non-trapping IR
   15843             sequence, (1) jump over the insn if it is gated false, and
   15844             (2) back out the ITSTATE update. */
   15845          mk_skip_over_T16_if_cond_is_false(condT);
   15846          condT = IRTemp_INVALID;
   15847          put_ITSTATE(old_itstate);
   15848          // now uncond
   15849 
   15850          nRegs = 0;
   15851          for (i = 0; i < 16; i++) {
   15852             if ((regList & (1 << i)) != 0)
   15853                nRegs++;
   15854          }
   15855          vassert(nRegs >= 1 && nRegs <= 9);
   15856 
   15857          /* Move SP down first of all, so we're "covered".  And don't
   15858             mess with its alignment. */
   15859          IRTemp newSP = newTemp(Ity_I32);
   15860          assign(newSP, binop(Iop_Sub32, getIRegT(13), mkU32(4 * nRegs)));
   15861          putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
   15862 
   15863          /* Generate a transfer base address as a forced-aligned
   15864             version of the final SP value. */
   15865          IRTemp base = newTemp(Ity_I32);
   15866          assign(base, binop(Iop_And32, mkexpr(newSP), mkU32(~3)));
   15867 
   15868          /* Now the transfers */
   15869          nRegs = 0;
   15870          for (i = 0; i < 16; i++) {
   15871             if ((regList & (1 << i)) != 0) {
   15872                storeLE( binop(Iop_Add32, mkexpr(base), mkU32(4 * nRegs)),
   15873                         getIRegT(i) );
   15874                nRegs++;
   15875             }
   15876          }
   15877 
   15878          /* Reinstate the ITSTATE update. */
   15879          put_ITSTATE(new_itstate);
   15880 
   15881          DIP("push {%s0x%04x}\n", bitR ? "lr," : "", regList & 0xFF);
   15882          goto decode_success;
   15883       }
   15884       break;
   15885    }
   15886 
   15887    case BITS7(1,0,1,1,1,1,0): {
   15888       /* ---------------- POP ---------------- */
   15889       Int  i, nRegs;
   15890       UInt bitR    = INSN0(8,8);
   15891       UInt regList = INSN0(7,0);
   15892 
   15893       /* At least one register must be transferred, else result is
   15894          UNPREDICTABLE. */
   15895       if (regList != 0 || bitR) {
   15896          /* Since we can't generate a guaranteed non-trapping IR
   15897             sequence, (1) jump over the insn if it is gated false, and
   15898             (2) back out the ITSTATE update. */
   15899          mk_skip_over_T16_if_cond_is_false(condT);
   15900          condT = IRTemp_INVALID;
   15901          put_ITSTATE(old_itstate);
   15902          // now uncond
   15903 
   15904          nRegs = 0;
   15905          for (i = 0; i < 8; i++) {
   15906             if ((regList & (1 << i)) != 0)
   15907                nRegs++;
   15908          }
   15909          vassert(nRegs >= 0 && nRegs <= 8);
   15910          vassert(bitR == 0 || bitR == 1);
   15911 
   15912          IRTemp oldSP = newTemp(Ity_I32);
   15913          assign(oldSP, getIRegT(13));
   15914 
   15915          /* Generate a transfer base address as a forced-aligned
   15916             version of the original SP value. */
   15917          IRTemp base = newTemp(Ity_I32);
   15918          assign(base, binop(Iop_And32, mkexpr(oldSP), mkU32(~3)));
   15919 
   15920          /* Compute a new value for SP, but don't install it yet, so
   15921             that we're "covered" until all the transfers are done.
   15922             And don't mess with its alignment. */
   15923          IRTemp newSP = newTemp(Ity_I32);
   15924          assign(newSP, binop(Iop_Add32, mkexpr(oldSP),
   15925                                         mkU32(4 * (nRegs + bitR))));
   15926 
   15927          /* Now the transfers, not including PC */
   15928          nRegs = 0;
   15929          for (i = 0; i < 8; i++) {
   15930             if ((regList & (1 << i)) != 0) {
   15931                putIRegT(i, loadLE( Ity_I32,
   15932                                    binop(Iop_Add32, mkexpr(base),
   15933                                                     mkU32(4 * nRegs))),
   15934                            IRTemp_INVALID );
   15935                nRegs++;
   15936             }
   15937          }
   15938 
   15939          IRTemp newPC = IRTemp_INVALID;
   15940          if (bitR) {
   15941             newPC = newTemp(Ity_I32);
   15942             assign( newPC, loadLE( Ity_I32,
   15943                                    binop(Iop_Add32, mkexpr(base),
   15944                                                     mkU32(4 * nRegs))));
   15945          }
   15946 
   15947          /* Now we can safely install the new SP value */
   15948          putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
   15949 
   15950          /* Reinstate the ITSTATE update. */
   15951          put_ITSTATE(new_itstate);
   15952 
   15953          /* now, do we also have to do a branch?  If so, it turns out
   15954             that the new PC value is encoded exactly as we need it to
   15955             be -- with CPSR.T in the bottom bit.  So we can simply use
   15956             it as is, no need to mess with it.  Note, therefore, this
   15957             is an interworking return. */
   15958          if (bitR) {
   15959             llPutIReg(15, mkexpr(newPC));
   15960             dres.jk_StopHere = Ijk_Ret;
   15961             dres.whatNext    = Dis_StopHere;
   15962          }
   15963 
   15964          DIP("pop {%s0x%04x}\n", bitR ? "pc," : "", regList & 0xFF);
   15965          goto decode_success;
   15966       }
   15967       break;
   15968    }
   15969 
   15970    case BITS7(0,0,0,1,1,1,0):   /* ADDS */
   15971    case BITS7(0,0,0,1,1,1,1): { /* SUBS */
   15972       /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */
   15973       /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */
   15974       UInt   uimm3 = INSN0(8,6);
   15975       UInt   rN    = INSN0(5,3);
   15976       UInt   rD    = INSN0(2,0);
   15977       UInt   isSub = INSN0(9,9);
   15978       IRTemp argL  = newTemp(Ity_I32);
   15979       IRTemp argR  = newTemp(Ity_I32);
   15980       assign( argL, getIRegT(rN) );
   15981       assign( argR, mkU32(uimm3) );
   15982       putIRegT(rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
   15983                          mkexpr(argL), mkexpr(argR)),
   15984                    condT);
   15985       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
   15986                       argL, argR, cond_AND_notInIT_T );
   15987       DIP("%s r%u, r%u, #%u\n", isSub ? "subs" : "adds", rD, rN, uimm3);
   15988       goto decode_success;
   15989    }
   15990 
   15991    case BITS7(0,0,0,1,1,0,0):   /* ADDS */
   15992    case BITS7(0,0,0,1,1,0,1): { /* SUBS */
   15993       /* ---------------- ADDS Rd, Rn, Rm ---------------- */
   15994       /* ---------------- SUBS Rd, Rn, Rm ---------------- */
   15995       UInt   rM    = INSN0(8,6);
   15996       UInt   rN    = INSN0(5,3);
   15997       UInt   rD    = INSN0(2,0);
   15998       UInt   isSub = INSN0(9,9);
   15999       IRTemp argL  = newTemp(Ity_I32);
   16000       IRTemp argR  = newTemp(Ity_I32);
   16001       assign( argL, getIRegT(rN) );
   16002       assign( argR, getIRegT(rM) );
   16003       putIRegT( rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
   16004                           mkexpr(argL), mkexpr(argR)),
   16005                     condT );
   16006       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
   16007                       argL, argR, cond_AND_notInIT_T );
   16008       DIP("%s r%u, r%u, r%u\n", isSub ? "subs" : "adds", rD, rN, rM);
   16009       goto decode_success;
   16010    }
   16011 
   16012    case BITS7(0,1,0,1,0,0,0):   /* STR */
   16013    case BITS7(0,1,0,1,1,0,0): { /* LDR */
   16014       /* ------------- LDR Rd, [Rn, Rm] ------------- */
   16015       /* ------------- STR Rd, [Rn, Rm] ------------- */
   16016       /* LDR/STR Rd, [Rn + Rm] */
   16017       UInt    rD   = INSN0(2,0);
   16018       UInt    rN   = INSN0(5,3);
   16019       UInt    rM   = INSN0(8,6);
   16020       UInt    isLD = INSN0(11,11);
   16021 
   16022       mk_skip_over_T16_if_cond_is_false(condT);
   16023       condT = IRTemp_INVALID;
   16024       // now uncond
   16025 
   16026       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   16027       put_ITSTATE(old_itstate); // backout
   16028       if (isLD) {
   16029          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
   16030       } else {
   16031          storeLE(ea, getIRegT(rD));
   16032       }
   16033       put_ITSTATE(new_itstate); // restore
   16034 
   16035       DIP("%s r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
   16036       goto decode_success;
   16037    }
   16038 
   16039    case BITS7(0,1,0,1,0,0,1):
   16040    case BITS7(0,1,0,1,1,0,1): {
   16041       /* ------------- LDRH Rd, [Rn, Rm] ------------- */
   16042       /* ------------- STRH Rd, [Rn, Rm] ------------- */
   16043       /* LDRH/STRH Rd, [Rn + Rm] */
   16044       UInt    rD   = INSN0(2,0);
   16045       UInt    rN   = INSN0(5,3);
   16046       UInt    rM   = INSN0(8,6);
   16047       UInt    isLD = INSN0(11,11);
   16048 
   16049       mk_skip_over_T16_if_cond_is_false(condT);
   16050       condT = IRTemp_INVALID;
   16051       // now uncond
   16052 
   16053       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   16054       put_ITSTATE(old_itstate); // backout
   16055       if (isLD) {
   16056          putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
   16057                       IRTemp_INVALID);
   16058       } else {
   16059          storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
   16060       }
   16061       put_ITSTATE(new_itstate); // restore
   16062 
   16063       DIP("%sh r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
   16064       goto decode_success;
   16065    }
   16066 
   16067    case BITS7(0,1,0,1,1,1,1): {
   16068       /* ------------- LDRSH Rd, [Rn, Rm] ------------- */
   16069       /* LDRSH Rd, [Rn + Rm] */
   16070       UInt    rD = INSN0(2,0);
   16071       UInt    rN = INSN0(5,3);
   16072       UInt    rM = INSN0(8,6);
   16073 
   16074       mk_skip_over_T16_if_cond_is_false(condT);
   16075       condT = IRTemp_INVALID;
   16076       // now uncond
   16077 
   16078       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   16079       put_ITSTATE(old_itstate); // backout
   16080       putIRegT(rD, unop(Iop_16Sto32, loadLE(Ity_I16, ea)),
   16081                    IRTemp_INVALID);
   16082       put_ITSTATE(new_itstate); // restore
   16083 
   16084       DIP("ldrsh r%u, [r%u, r%u]\n", rD, rN, rM);
   16085       goto decode_success;
   16086    }
   16087 
   16088    case BITS7(0,1,0,1,0,1,1): {
   16089       /* ------------- LDRSB Rd, [Rn, Rm] ------------- */
   16090       /* LDRSB Rd, [Rn + Rm] */
   16091       UInt    rD = INSN0(2,0);
   16092       UInt    rN = INSN0(5,3);
   16093       UInt    rM = INSN0(8,6);
   16094 
   16095       mk_skip_over_T16_if_cond_is_false(condT);
   16096       condT = IRTemp_INVALID;
   16097       // now uncond
   16098 
   16099       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   16100       put_ITSTATE(old_itstate); // backout
   16101       putIRegT(rD, unop(Iop_8Sto32, loadLE(Ity_I8, ea)),
   16102                    IRTemp_INVALID);
   16103       put_ITSTATE(new_itstate); // restore
   16104 
   16105       DIP("ldrsb r%u, [r%u, r%u]\n", rD, rN, rM);
   16106       goto decode_success;
   16107    }
   16108 
   16109    case BITS7(0,1,0,1,0,1,0):
   16110    case BITS7(0,1,0,1,1,1,0): {
   16111       /* ------------- LDRB Rd, [Rn, Rm] ------------- */
   16112       /* ------------- STRB Rd, [Rn, Rm] ------------- */
   16113       /* LDRB/STRB Rd, [Rn + Rm] */
   16114       UInt    rD   = INSN0(2,0);
   16115       UInt    rN   = INSN0(5,3);
   16116       UInt    rM   = INSN0(8,6);
   16117       UInt    isLD = INSN0(11,11);
   16118 
   16119       mk_skip_over_T16_if_cond_is_false(condT);
   16120       condT = IRTemp_INVALID;
   16121       // now uncond
   16122 
   16123       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   16124       put_ITSTATE(old_itstate); // backout
   16125       if (isLD) {
   16126          putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
   16127                   IRTemp_INVALID);
   16128       } else {
   16129          storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
   16130       }
   16131       put_ITSTATE(new_itstate); // restore
   16132 
   16133       DIP("%sb r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
   16134       goto decode_success;
   16135    }
   16136 
   16137    default:
   16138       break; /* examine the next shortest prefix */
   16139 
   16140    }
   16141 
   16142 
   16143    /* ================ 16-bit 15:11 cases ================ */
   16144 
   16145    switch (INSN0(15,11)) {
   16146 
   16147    case BITS5(0,0,1,1,0):
   16148    case BITS5(0,0,1,1,1): {
   16149       /* ---------------- ADDS Rn, #uimm8 ---------------- */
   16150       /* ---------------- SUBS Rn, #uimm8 ---------------- */
   16151       UInt   isSub = INSN0(11,11);
   16152       UInt   rN    = INSN0(10,8);
   16153       UInt   uimm8 = INSN0(7,0);
   16154       IRTemp argL  = newTemp(Ity_I32);
   16155       IRTemp argR  = newTemp(Ity_I32);
   16156       assign( argL, getIRegT(rN) );
   16157       assign( argR, mkU32(uimm8) );
   16158       putIRegT( rN, binop(isSub ? Iop_Sub32 : Iop_Add32,
   16159                           mkexpr(argL), mkexpr(argR)), condT );
   16160       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
   16161                       argL, argR, cond_AND_notInIT_T );
   16162       DIP("%s r%u, #%u\n", isSub ? "subs" : "adds", rN, uimm8);
   16163       goto decode_success;
   16164    }
   16165 
   16166    case BITS5(1,0,1,0,0): {
   16167       /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */
   16168       /* a.k.a. ADR */
   16169       /* rD = align4(PC) + imm8 * 4 */
   16170       UInt rD   = INSN0(10,8);
   16171       UInt imm8 = INSN0(7,0);
   16172       putIRegT(rD, binop(Iop_Add32,
   16173                          binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   16174                          mkU32(imm8 * 4)),
   16175                    condT);
   16176       DIP("add r%u, pc, #%u\n", rD, imm8 * 4);
   16177       goto decode_success;
   16178    }
   16179 
   16180    case BITS5(1,0,1,0,1): {
   16181       /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */
   16182       UInt rD   = INSN0(10,8);
   16183       UInt imm8 = INSN0(7,0);
   16184       putIRegT(rD, binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)),
   16185                    condT);
   16186       DIP("add r%u, r13, #%u\n", rD, imm8 * 4);
   16187       goto decode_success;
   16188    }
   16189 
   16190    case BITS5(0,0,1,0,1): {
   16191       /* ---------------- CMP Rn, #uimm8 ---------------- */
   16192       UInt   rN    = INSN0(10,8);
   16193       UInt   uimm8 = INSN0(7,0);
   16194       IRTemp argL  = newTemp(Ity_I32);
   16195       IRTemp argR  = newTemp(Ity_I32);
   16196       assign( argL, getIRegT(rN) );
   16197       assign( argR, mkU32(uimm8) );
   16198       /* Update flags regardless of whether in an IT block or not. */
   16199       setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   16200       DIP("cmp r%u, #%u\n", rN, uimm8);
   16201       goto decode_success;
   16202    }
   16203 
   16204    case BITS5(0,0,1,0,0): {
   16205       /* -------------- (T1) MOVS Rn, #uimm8 -------------- */
   16206       UInt   rD    = INSN0(10,8);
   16207       UInt   uimm8 = INSN0(7,0);
   16208       IRTemp oldV  = newTemp(Ity_I32);
   16209       IRTemp oldC  = newTemp(Ity_I32);
   16210       IRTemp res   = newTemp(Ity_I32);
   16211       assign( oldV, mk_armg_calculate_flag_v() );
   16212       assign( oldC, mk_armg_calculate_flag_c() );
   16213       assign( res, mkU32(uimm8) );
   16214       putIRegT(rD, mkexpr(res), condT);
   16215       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16216                          cond_AND_notInIT_T );
   16217       DIP("movs r%u, #%u\n", rD, uimm8);
   16218       goto decode_success;
   16219    }
   16220 
   16221    case BITS5(0,1,0,0,1): {
   16222       /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */
   16223       /* LDR Rd, [align4(PC) + imm8 * 4] */
   16224       UInt   rD   = INSN0(10,8);
   16225       UInt   imm8 = INSN0(7,0);
   16226       IRTemp ea   = newTemp(Ity_I32);
   16227 
   16228       mk_skip_over_T16_if_cond_is_false(condT);
   16229       condT = IRTemp_INVALID;
   16230       // now uncond
   16231 
   16232       assign(ea, binop(Iop_Add32,
   16233                        binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   16234                        mkU32(imm8 * 4)));
   16235       put_ITSTATE(old_itstate); // backout
   16236       putIRegT(rD, loadLE(Ity_I32, mkexpr(ea)),
   16237                    IRTemp_INVALID);
   16238       put_ITSTATE(new_itstate); // restore
   16239 
   16240       DIP("ldr r%u, [pc, #%u]\n", rD, imm8 * 4);
   16241       goto decode_success;
   16242    }
   16243 
   16244    case BITS5(0,1,1,0,0):   /* STR */
   16245    case BITS5(0,1,1,0,1): { /* LDR */
   16246       /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */
   16247       /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */
   16248       /* LDR/STR Rd, [Rn + imm5 * 4] */
   16249       UInt    rD   = INSN0(2,0);
   16250       UInt    rN   = INSN0(5,3);
   16251       UInt    imm5 = INSN0(10,6);
   16252       UInt    isLD = INSN0(11,11);
   16253 
   16254       mk_skip_over_T16_if_cond_is_false(condT);
   16255       condT = IRTemp_INVALID;
   16256       // now uncond
   16257 
   16258       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 4));
   16259       put_ITSTATE(old_itstate); // backout
   16260       if (isLD) {
   16261          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
   16262       } else {
   16263          storeLE( ea, getIRegT(rD) );
   16264       }
   16265       put_ITSTATE(new_itstate); // restore
   16266 
   16267       DIP("%s r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 4);
   16268       goto decode_success;
   16269    }
   16270 
   16271    case BITS5(1,0,0,0,0):   /* STRH */
   16272    case BITS5(1,0,0,0,1): { /* LDRH */
   16273       /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */
   16274       /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */
   16275       /* LDRH/STRH Rd, [Rn + imm5 * 2] */
   16276       UInt    rD   = INSN0(2,0);
   16277       UInt    rN   = INSN0(5,3);
   16278       UInt    imm5 = INSN0(10,6);
   16279       UInt    isLD = INSN0(11,11);
   16280 
   16281       mk_skip_over_T16_if_cond_is_false(condT);
   16282       condT = IRTemp_INVALID;
   16283       // now uncond
   16284 
   16285       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 2));
   16286       put_ITSTATE(old_itstate); // backout
   16287       if (isLD) {
   16288          putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
   16289                   IRTemp_INVALID);
   16290       } else {
   16291          storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
   16292       }
   16293       put_ITSTATE(new_itstate); // restore
   16294 
   16295       DIP("%sh r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 2);
   16296       goto decode_success;
   16297    }
   16298 
   16299    case BITS5(0,1,1,1,0):   /* STRB */
   16300    case BITS5(0,1,1,1,1): { /* LDRB */
   16301       /* ------------- LDRB Rd, [Rn, #imm5] ------------- */
   16302       /* ------------- STRB Rd, [Rn, #imm5] ------------- */
   16303       /* LDRB/STRB Rd, [Rn + imm5] */
   16304       UInt    rD   = INSN0(2,0);
   16305       UInt    rN   = INSN0(5,3);
   16306       UInt    imm5 = INSN0(10,6);
   16307       UInt    isLD = INSN0(11,11);
   16308 
   16309       mk_skip_over_T16_if_cond_is_false(condT);
   16310       condT = IRTemp_INVALID;
   16311       // now uncond
   16312 
   16313       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5));
   16314       put_ITSTATE(old_itstate); // backout
   16315       if (isLD) {
   16316          putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
   16317                   IRTemp_INVALID);
   16318       } else {
   16319          storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
   16320       }
   16321       put_ITSTATE(new_itstate); // restore
   16322 
   16323       DIP("%sb r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5);
   16324       goto decode_success;
   16325    }
   16326 
   16327    case BITS5(1,0,0,1,0):   /* STR */
   16328    case BITS5(1,0,0,1,1): { /* LDR */
   16329       /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */
   16330       /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */
   16331       /* LDR/STR Rd, [SP + imm8 * 4] */
   16332       UInt rD    = INSN0(10,8);
   16333       UInt imm8  = INSN0(7,0);
   16334       UInt isLD  = INSN0(11,11);
   16335 
   16336       mk_skip_over_T16_if_cond_is_false(condT);
   16337       condT = IRTemp_INVALID;
   16338       // now uncond
   16339 
   16340       IRExpr* ea = binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4));
   16341       put_ITSTATE(old_itstate); // backout
   16342       if (isLD) {
   16343          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
   16344       } else {
   16345          storeLE(ea, getIRegT(rD));
   16346       }
   16347       put_ITSTATE(new_itstate); // restore
   16348 
   16349       DIP("%s r%u, [sp, #%u]\n", isLD ? "ldr" : "str", rD, imm8 * 4);
   16350       goto decode_success;
   16351    }
   16352 
   16353    case BITS5(1,1,0,0,1): {
   16354       /* ------------- LDMIA Rn!, {reglist} ------------- */
   16355       Int i, nRegs = 0;
   16356       UInt rN   = INSN0(10,8);
   16357       UInt list = INSN0(7,0);
   16358       /* Empty lists aren't allowed. */
   16359       if (list != 0) {
   16360          mk_skip_over_T16_if_cond_is_false(condT);
   16361          condT = IRTemp_INVALID;
   16362          put_ITSTATE(old_itstate);
   16363          // now uncond
   16364 
   16365          IRTemp oldRn = newTemp(Ity_I32);
   16366          IRTemp base  = newTemp(Ity_I32);
   16367          assign(oldRn, getIRegT(rN));
   16368          assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
   16369          for (i = 0; i < 8; i++) {
   16370             if (0 == (list & (1 << i)))
   16371                continue;
   16372             nRegs++;
   16373             putIRegT(
   16374                i, loadLE(Ity_I32,
   16375                          binop(Iop_Add32, mkexpr(base),
   16376                                           mkU32(nRegs * 4 - 4))),
   16377                IRTemp_INVALID
   16378             );
   16379          }
   16380          /* Only do the writeback for rN if it isn't in the list of
   16381             registers to be transferred. */
   16382          if (0 == (list & (1 << rN))) {
   16383             putIRegT(rN,
   16384                      binop(Iop_Add32, mkexpr(oldRn),
   16385                                       mkU32(nRegs * 4)),
   16386                      IRTemp_INVALID
   16387             );
   16388          }
   16389 
   16390          /* Reinstate the ITSTATE update. */
   16391          put_ITSTATE(new_itstate);
   16392 
   16393          DIP("ldmia r%u!, {0x%04x}\n", rN, list);
   16394          goto decode_success;
   16395       }
   16396       break;
   16397    }
   16398 
   16399    case BITS5(1,1,0,0,0): {
   16400       /* ------------- STMIA Rn!, {reglist} ------------- */
   16401       Int i, nRegs = 0;
   16402       UInt rN   = INSN0(10,8);
   16403       UInt list = INSN0(7,0);
   16404       /* Empty lists aren't allowed.  Also, if rN is in the list then
   16405          it must be the lowest numbered register in the list. */
   16406       Bool valid = list != 0;
   16407       if (valid && 0 != (list & (1 << rN))) {
   16408          for (i = 0; i < rN; i++) {
   16409             if (0 != (list & (1 << i)))
   16410                valid = False;
   16411          }
   16412       }
   16413       if (valid) {
   16414          mk_skip_over_T16_if_cond_is_false(condT);
   16415          condT = IRTemp_INVALID;
   16416          put_ITSTATE(old_itstate);
   16417          // now uncond
   16418 
   16419          IRTemp oldRn = newTemp(Ity_I32);
   16420          IRTemp base = newTemp(Ity_I32);
   16421          assign(oldRn, getIRegT(rN));
   16422          assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
   16423          for (i = 0; i < 8; i++) {
   16424             if (0 == (list & (1 << i)))
   16425                continue;
   16426             nRegs++;
   16427             storeLE( binop(Iop_Add32, mkexpr(base), mkU32(nRegs * 4 - 4)),
   16428                      getIRegT(i) );
   16429          }
   16430          /* Always do the writeback. */
   16431          putIRegT(rN,
   16432                   binop(Iop_Add32, mkexpr(oldRn),
   16433                                    mkU32(nRegs * 4)),
   16434                   IRTemp_INVALID);
   16435 
   16436          /* Reinstate the ITSTATE update. */
   16437          put_ITSTATE(new_itstate);
   16438 
   16439          DIP("stmia r%u!, {0x%04x}\n", rN, list);
   16440          goto decode_success;
   16441       }
   16442       break;
   16443    }
   16444 
   16445    case BITS5(0,0,0,0,0):   /* LSLS */
   16446    case BITS5(0,0,0,0,1):   /* LSRS */
   16447    case BITS5(0,0,0,1,0): { /* ASRS */
   16448       /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */
   16449       /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */
   16450       /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */
   16451       UInt   rD   = INSN0(2,0);
   16452       UInt   rM   = INSN0(5,3);
   16453       UInt   imm5 = INSN0(10,6);
   16454       IRTemp res  = newTemp(Ity_I32);
   16455       IRTemp resC = newTemp(Ity_I32);
   16456       IRTemp rMt  = newTemp(Ity_I32);
   16457       IRTemp oldV = newTemp(Ity_I32);
   16458       HChar* wot  = "???";
   16459       assign(rMt, getIRegT(rM));
   16460       assign(oldV, mk_armg_calculate_flag_v());
   16461       /* Looks like INSN0(12,11) are the standard 'how' encoding.
   16462          Could compactify if the ROR case later appears. */
   16463       switch (INSN0(15,11)) {
   16464          case BITS5(0,0,0,0,0):
   16465             compute_result_and_C_after_LSL_by_imm5(
   16466                dis_buf, &res, &resC, rMt, imm5, rM
   16467             );
   16468             wot = "lsl";
   16469             break;
   16470          case BITS5(0,0,0,0,1):
   16471             compute_result_and_C_after_LSR_by_imm5(
   16472                dis_buf, &res, &resC, rMt, imm5, rM
   16473             );
   16474             wot = "lsr";
   16475             break;
   16476          case BITS5(0,0,0,1,0):
   16477             compute_result_and_C_after_ASR_by_imm5(
   16478                dis_buf, &res, &resC, rMt, imm5, rM
   16479             );
   16480             wot = "asr";
   16481             break;
   16482          default:
   16483             /*NOTREACHED*/vassert(0);
   16484       }
   16485       // not safe to read guest state after this point
   16486       putIRegT(rD, mkexpr(res), condT);
   16487       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
   16488                          cond_AND_notInIT_T );
   16489       /* ignore buf and roll our own output */
   16490       DIP("%ss r%u, r%u, #%u\n", wot, rD, rM, imm5);
   16491       goto decode_success;
   16492    }
   16493 
   16494    case BITS5(1,1,1,0,0): {
   16495       /* ---------------- B #simm11 ---------------- */
   16496       Int  simm11 = INSN0(10,0);
   16497            simm11 = (simm11 << 21) >> 20;
   16498       UInt dst    = simm11 + guest_R15_curr_instr_notENC + 4;
   16499       /* Only allowed outside or last-in IT block; SIGILL if not so. */
   16500       gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   16501       // and skip this insn if not selected; being cleverer is too
   16502       // difficult
   16503       mk_skip_over_T16_if_cond_is_false(condT);
   16504       condT = IRTemp_INVALID;
   16505       // now uncond
   16506       llPutIReg(15, mkU32( dst | 1 /*CPSR.T*/ ));
   16507       dres.jk_StopHere = Ijk_Boring;
   16508       dres.whatNext    = Dis_StopHere;
   16509       DIP("b 0x%x\n", dst);
   16510       goto decode_success;
   16511    }
   16512 
   16513    default:
   16514       break; /* examine the next shortest prefix */
   16515 
   16516    }
   16517 
   16518 
   16519    /* ================ 16-bit 15:12 cases ================ */
   16520 
   16521    switch (INSN0(15,12)) {
   16522 
   16523    case BITS4(1,1,0,1): {
   16524       /* ---------------- Bcond #simm8 ---------------- */
   16525       UInt cond  = INSN0(11,8);
   16526       Int  simm8 = INSN0(7,0);
   16527            simm8 = (simm8 << 24) >> 23;
   16528       UInt dst   = simm8 + guest_R15_curr_instr_notENC + 4;
   16529       if (cond != ARMCondAL && cond != ARMCondNV) {
   16530          /* Not allowed in an IT block; SIGILL if so. */
   16531          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   16532 
   16533          IRTemp kondT = newTemp(Ity_I32);
   16534          assign( kondT, mk_armg_calculate_condition(cond) );
   16535          stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
   16536                             Ijk_Boring,
   16537                             IRConst_U32(dst | 1/*CPSR.T*/),
   16538                             OFFB_R15T ));
   16539          llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 2)
   16540                               | 1 /*CPSR.T*/ ));
   16541          dres.jk_StopHere = Ijk_Boring;
   16542          dres.whatNext    = Dis_StopHere;
   16543          DIP("b%s 0x%x\n", nCC(cond), dst);
   16544          goto decode_success;
   16545       }
   16546       break;
   16547    }
   16548 
   16549    default:
   16550       break; /* hmm, nothing matched */
   16551 
   16552    }
   16553 
   16554    /* ================ 16-bit misc cases ================ */
   16555 
   16556    /* ------ NOP ------ */
   16557    if (INSN0(15,0) == 0xBF00) {
   16558       DIP("nop");
   16559       goto decode_success;
   16560    }
   16561 
   16562    /* ----------------------------------------------------------- */
   16563    /* --                                                       -- */
   16564    /* -- Thumb 32-bit integer instructions                     -- */
   16565    /* --                                                       -- */
   16566    /* ----------------------------------------------------------- */
   16567 
   16568 #  define INSN1(_bMax,_bMin)  SLICE_UInt(((UInt)insn1), (_bMax), (_bMin))
   16569 
   16570    /* second 16 bits of the instruction, if any */
   16571    vassert(insn1 == 0);
   16572    insn1 = getUShortLittleEndianly( guest_instr+2 );
   16573 
   16574    anOp   = Iop_INVALID; /* paranoia */
   16575    anOpNm = NULL;        /* paranoia */
   16576 
   16577    /* Change result defaults to suit 32-bit insns. */
   16578    vassert(dres.whatNext   == Dis_Continue);
   16579    vassert(dres.len        == 2);
   16580    vassert(dres.continueAt == 0);
   16581    dres.len = 4;
   16582 
   16583    /* ---------------- BL/BLX simm26 ---------------- */
   16584    if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) {
   16585       UInt isBL = INSN1(12,12);
   16586       UInt bS   = INSN0(10,10);
   16587       UInt bJ1  = INSN1(13,13);
   16588       UInt bJ2  = INSN1(11,11);
   16589       UInt bI1  = 1 ^ (bJ1 ^ bS);
   16590       UInt bI2  = 1 ^ (bJ2 ^ bS);
   16591       Int simm25
   16592          =   (bS          << (1 + 1 + 10 + 11 + 1))
   16593            | (bI1         << (1 + 10 + 11 + 1))
   16594            | (bI2         << (10 + 11 + 1))
   16595            | (INSN0(9,0)  << (11 + 1))
   16596            | (INSN1(10,0) << 1);
   16597       simm25 = (simm25 << 7) >> 7;
   16598 
   16599       vassert(0 == (guest_R15_curr_instr_notENC & 1));
   16600       UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
   16601 
   16602       /* One further validity case to check: in the case of BLX
   16603          (not-BL), that insn1[0] must be zero. */
   16604       Bool valid = True;
   16605       if (isBL == 0 && INSN1(0,0) == 1) valid = False;
   16606       if (valid) {
   16607          /* Only allowed outside or last-in IT block; SIGILL if not so. */
   16608          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   16609          // and skip this insn if not selected; being cleverer is too
   16610          // difficult
   16611          mk_skip_over_T32_if_cond_is_false(condT);
   16612          condT = IRTemp_INVALID;
   16613          // now uncond
   16614 
   16615          /* We're returning to Thumb code, hence "| 1" */
   16616          putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 4) | 1 ),
   16617                    IRTemp_INVALID);
   16618          if (isBL) {
   16619             /* BL: unconditional T -> T call */
   16620             /* we're calling Thumb code, hence "| 1" */
   16621             llPutIReg(15, mkU32( dst | 1 ));
   16622             DIP("bl 0x%x (stay in Thumb mode)\n", dst);
   16623          } else {
   16624             /* BLX: unconditional T -> A call */
   16625             /* we're calling ARM code, hence "& 3" to align to a
   16626                valid ARM insn address */
   16627             llPutIReg(15, mkU32( dst & ~3 ));
   16628             DIP("blx 0x%x (switch to ARM mode)\n", dst & ~3);
   16629          }
   16630          dres.whatNext    = Dis_StopHere;
   16631          dres.jk_StopHere = Ijk_Call;
   16632          goto decode_success;
   16633       }
   16634    }
   16635 
   16636    /* ---------------- {LD,ST}M{IA,DB} ---------------- */
   16637    if (0x3a2 == INSN0(15,6) // {LD,ST}MIA
   16638        || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB
   16639       UInt bW      = INSN0(5,5); /* writeback Rn ? */
   16640       UInt bL      = INSN0(4,4);
   16641       UInt rN      = INSN0(3,0);
   16642       UInt bP      = INSN1(15,15); /* reglist entry for r15 */
   16643       UInt bM      = INSN1(14,14); /* reglist entry for r14 */
   16644       UInt rLmost  = INSN1(12,0);  /* reglist entry for r0 .. 12 */
   16645       UInt rL13    = INSN1(13,13); /* must be zero */
   16646       UInt regList = 0;
   16647       Bool valid   = True;
   16648 
   16649       UInt bINC    = 1;
   16650       UInt bBEFORE = 0;
   16651       if (INSN0(15,6) == 0x3a4) {
   16652          bINC    = 0;
   16653          bBEFORE = 1;
   16654       }
   16655 
   16656       /* detect statically invalid cases, and construct the final
   16657          reglist */
   16658       if (rL13 == 1)
   16659          valid = False;
   16660 
   16661       if (bL == 1) {
   16662          regList = (bP << 15) | (bM << 14) | rLmost;
   16663          if (rN == 15)                       valid = False;
   16664          if (popcount32(regList) < 2)        valid = False;
   16665          if (bP == 1 && bM == 1)             valid = False;
   16666          if (bW == 1 && (regList & (1<<rN))) valid = False;
   16667       } else {
   16668          regList = (bM << 14) | rLmost;
   16669          if (bP == 1)                        valid = False;
   16670          if (rN == 15)                       valid = False;
   16671          if (popcount32(regList) < 2)        valid = False;
   16672          if (bW == 1 && (regList & (1<<rN))) valid = False;
   16673       }
   16674 
   16675       if (valid) {
   16676          if (bL == 1 && bP == 1) {
   16677             // We'll be writing the PC.  Hence:
   16678             /* Only allowed outside or last-in IT block; SIGILL if not so. */
   16679             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   16680          }
   16681 
   16682          /* Go uncond: */
   16683          mk_skip_over_T32_if_cond_is_false(condT);
   16684          condT = IRTemp_INVALID;
   16685          // now uncond
   16686 
   16687          /* Generate the IR.  This might generate a write to R15. */
   16688          mk_ldm_stm(False/*!arm*/, rN, bINC, bBEFORE, bW, bL, regList);
   16689 
   16690          if (bL == 1 && (regList & (1<<15))) {
   16691             // If we wrote to R15, we have an interworking return to
   16692             // deal with.
   16693             llPutIReg(15, llGetIReg(15));
   16694             dres.jk_StopHere = Ijk_Ret;
   16695             dres.whatNext    = Dis_StopHere;
   16696          }
   16697 
   16698          DIP("%sm%c%c r%u%s, {0x%04x}\n",
   16699               bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
   16700               rN, bW ? "!" : "", regList);
   16701 
   16702          goto decode_success;
   16703       }
   16704    }
   16705 
   16706    /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */
   16707    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16708        && INSN0(9,5) == BITS5(0,1,0,0,0)
   16709        && INSN1(15,15) == 0) {
   16710       UInt bS = INSN0(4,4);
   16711       UInt rN = INSN0(3,0);
   16712       UInt rD = INSN1(11,8);
   16713       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16714       /* but allow "add.w reg, sp, #constT" for reg != PC */
   16715       if (!valid && rD <= 14 && rN == 13)
   16716          valid = True;
   16717       if (valid) {
   16718          IRTemp argL  = newTemp(Ity_I32);
   16719          IRTemp argR  = newTemp(Ity_I32);
   16720          IRTemp res   = newTemp(Ity_I32);
   16721          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16722          assign(argL, getIRegT(rN));
   16723          assign(argR, mkU32(imm32));
   16724          assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
   16725          putIRegT(rD, mkexpr(res), condT);
   16726          if (bS == 1)
   16727             setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
   16728          DIP("add%s.w r%u, r%u, #%u\n",
   16729              bS == 1 ? "s" : "", rD, rN, imm32);
   16730          goto decode_success;
   16731       }
   16732    }
   16733 
   16734    /* ---------------- (T4) ADDW Rd, Rn, #uimm12 -------------- */
   16735    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16736        && INSN0(9,4) == BITS6(1,0,0,0,0,0)
   16737        && INSN1(15,15) == 0) {
   16738       UInt rN = INSN0(3,0);
   16739       UInt rD = INSN1(11,8);
   16740       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16741       /* but allow "addw reg, sp, #uimm12" for reg != PC */
   16742       if (!valid && rD <= 14 && rN == 13)
   16743          valid = True;
   16744       if (valid) {
   16745          IRTemp argL = newTemp(Ity_I32);
   16746          IRTemp argR = newTemp(Ity_I32);
   16747          IRTemp res  = newTemp(Ity_I32);
   16748          UInt imm12  = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
   16749          assign(argL, getIRegT(rN));
   16750          assign(argR, mkU32(imm12));
   16751          assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
   16752          putIRegT(rD, mkexpr(res), condT);
   16753          DIP("addw r%u, r%u, #%u\n", rD, rN, imm12);
   16754          goto decode_success;
   16755       }
   16756    }
   16757 
   16758    /* ---------------- (T2) CMP.W Rn, #constT ---------------- */
   16759    /* ---------------- (T2) CMN.W Rn, #constT ---------------- */
   16760    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16761        && (   INSN0(9,4) == BITS6(0,1,1,0,1,1)  // CMP
   16762            || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN
   16763        && INSN1(15,15) == 0
   16764        && INSN1(11,8) == BITS4(1,1,1,1)) {
   16765       UInt rN = INSN0(3,0);
   16766       if (rN != 15) {
   16767          IRTemp argL  = newTemp(Ity_I32);
   16768          IRTemp argR  = newTemp(Ity_I32);
   16769          Bool   isCMN = INSN0(9,4) == BITS6(0,1,0,0,0,1);
   16770          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16771          assign(argL, getIRegT(rN));
   16772          assign(argR, mkU32(imm32));
   16773          setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   16774                          argL, argR, condT );
   16775          DIP("%s.w r%u, #%u\n", isCMN ? "cmn" : "cmp", rN, imm32);
   16776          goto decode_success;
   16777       }
   16778    }
   16779 
   16780    /* -------------- (T1) TST.W Rn, #constT -------------- */
   16781    /* -------------- (T1) TEQ.W Rn, #constT -------------- */
   16782    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16783        && (   INSN0(9,4) == BITS6(0,0,0,0,0,1)  // TST
   16784            || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ
   16785        && INSN1(15,15) == 0
   16786        && INSN1(11,8) == BITS4(1,1,1,1)) {
   16787       UInt rN = INSN0(3,0);
   16788       if (!isBadRegT(rN)) { // yes, really, it's inconsistent with CMP.W
   16789          Bool  isTST  = INSN0(9,4) == BITS6(0,0,0,0,0,1);
   16790          IRTemp argL  = newTemp(Ity_I32);
   16791          IRTemp argR  = newTemp(Ity_I32);
   16792          IRTemp res   = newTemp(Ity_I32);
   16793          IRTemp oldV  = newTemp(Ity_I32);
   16794          IRTemp oldC  = newTemp(Ity_I32);
   16795          Bool   updC  = False;
   16796          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
   16797          assign(argL, getIRegT(rN));
   16798          assign(argR, mkU32(imm32));
   16799          assign(res,  binop(isTST ? Iop_And32 : Iop_Xor32,
   16800                             mkexpr(argL), mkexpr(argR)));
   16801          assign( oldV, mk_armg_calculate_flag_v() );
   16802          assign( oldC, updC
   16803                        ? mkU32((imm32 >> 31) & 1)
   16804                        : mk_armg_calculate_flag_c() );
   16805          setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
   16806          DIP("%s.w r%u, #%u\n", isTST ? "tst" : "teq", rN, imm32);
   16807          goto decode_success;
   16808       }
   16809    }
   16810 
   16811    /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */
   16812    /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */
   16813    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16814        && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB
   16815            || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB
   16816        && INSN1(15,15) == 0) {
   16817       Bool isRSB = INSN0(9,5) == BITS5(0,1,1,1,0);
   16818       UInt bS    = INSN0(4,4);
   16819       UInt rN    = INSN0(3,0);
   16820       UInt rD    = INSN1(11,8);
   16821       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16822       /* but allow "sub{s}.w reg, sp, #constT
   16823          this is (T2) of "SUB (SP minus immediate)" */
   16824       if (!valid && !isRSB && rN == 13 && rD != 15)
   16825          valid = True;
   16826       if (valid) {
   16827          IRTemp argL  = newTemp(Ity_I32);
   16828          IRTemp argR  = newTemp(Ity_I32);
   16829          IRTemp res   = newTemp(Ity_I32);
   16830          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16831          assign(argL, getIRegT(rN));
   16832          assign(argR, mkU32(imm32));
   16833          assign(res,  isRSB
   16834                       ? binop(Iop_Sub32, mkexpr(argR), mkexpr(argL))
   16835                       : binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
   16836          putIRegT(rD, mkexpr(res), condT);
   16837          if (bS == 1) {
   16838             if (isRSB)
   16839                setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
   16840             else
   16841                setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   16842          }
   16843          DIP("%s%s.w r%u, r%u, #%u\n",
   16844              isRSB ? "rsb" : "sub", bS == 1 ? "s" : "", rD, rN, imm32);
   16845          goto decode_success;
   16846       }
   16847    }
   16848 
   16849    /* -------------- (T4) SUBW Rd, Rn, #uimm12 ------------------- */
   16850    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16851        && INSN0(9,4) == BITS6(1,0,1,0,1,0)
   16852        && INSN1(15,15) == 0) {
   16853       UInt rN = INSN0(3,0);
   16854       UInt rD = INSN1(11,8);
   16855       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16856       /* but allow "subw sp, sp, #uimm12" */
   16857       if (!valid && rD == 13 && rN == 13)
   16858          valid = True;
   16859       if (valid) {
   16860          IRTemp argL  = newTemp(Ity_I32);
   16861          IRTemp argR  = newTemp(Ity_I32);
   16862          IRTemp res   = newTemp(Ity_I32);
   16863          UInt imm12   = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
   16864          assign(argL, getIRegT(rN));
   16865          assign(argR, mkU32(imm12));
   16866          assign(res,  binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
   16867          putIRegT(rD, mkexpr(res), condT);
   16868          DIP("subw r%u, r%u, #%u\n", rD, rN, imm12);
   16869          goto decode_success;
   16870       }
   16871    }
   16872 
   16873    /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */
   16874    /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */
   16875    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16876        && (   INSN0(9,5) == BITS5(0,1,0,1,0)  // ADC
   16877            || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC
   16878        && INSN1(15,15) == 0) {
   16879       /* ADC:  Rd = Rn + constT + oldC */
   16880       /* SBC:  Rd = Rn - constT - (oldC ^ 1) */
   16881       UInt bS    = INSN0(4,4);
   16882       UInt rN    = INSN0(3,0);
   16883       UInt rD    = INSN1(11,8);
   16884       if (!isBadRegT(rN) && !isBadRegT(rD)) {
   16885          IRTemp argL  = newTemp(Ity_I32);
   16886          IRTemp argR  = newTemp(Ity_I32);
   16887          IRTemp res   = newTemp(Ity_I32);
   16888          IRTemp oldC  = newTemp(Ity_I32);
   16889          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16890          assign(argL, getIRegT(rN));
   16891          assign(argR, mkU32(imm32));
   16892          assign(oldC, mk_armg_calculate_flag_c() );
   16893          HChar* nm  = "???";
   16894          switch (INSN0(9,5)) {
   16895             case BITS5(0,1,0,1,0): // ADC
   16896                nm = "adc";
   16897                assign(res,
   16898                       binop(Iop_Add32,
   16899                             binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
   16900                             mkexpr(oldC) ));
   16901                putIRegT(rD, mkexpr(res), condT);
   16902                if (bS)
   16903                   setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
   16904                                      argL, argR, oldC, condT );
   16905                break;
   16906             case BITS5(0,1,0,1,1): // SBC
   16907                nm = "sbc";
   16908                assign(res,
   16909                       binop(Iop_Sub32,
   16910                             binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
   16911                             binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   16912                putIRegT(rD, mkexpr(res), condT);
   16913                if (bS)
   16914                   setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   16915                                      argL, argR, oldC, condT );
   16916                break;
   16917             default:
   16918               vassert(0);
   16919          }
   16920          DIP("%s%s.w r%u, r%u, #%u\n",
   16921              nm, bS == 1 ? "s" : "", rD, rN, imm32);
   16922          goto decode_success;
   16923       }
   16924    }
   16925 
   16926    /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */
   16927    /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */
   16928    /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */
   16929    /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */
   16930    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16931        && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // ORR
   16932            || INSN0(9,5) == BITS5(0,0,0,0,0)  // AND
   16933            || INSN0(9,5) == BITS5(0,0,0,0,1)  // BIC
   16934            || INSN0(9,5) == BITS5(0,0,1,0,0)  // EOR
   16935            || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN
   16936        && INSN1(15,15) == 0) {
   16937       UInt bS = INSN0(4,4);
   16938       UInt rN = INSN0(3,0);
   16939       UInt rD = INSN1(11,8);
   16940       if (!isBadRegT(rN) && !isBadRegT(rD)) {
   16941          Bool   notArgR = False;
   16942          IROp   op      = Iop_INVALID;
   16943          HChar* nm      = "???";
   16944          switch (INSN0(9,5)) {
   16945             case BITS5(0,0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
   16946             case BITS5(0,0,0,0,0): op = Iop_And32; nm = "and"; break;
   16947             case BITS5(0,0,0,0,1): op = Iop_And32; nm = "bic";
   16948                                    notArgR = True; break;
   16949             case BITS5(0,0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
   16950             case BITS5(0,0,0,1,1): op = Iop_Or32;  nm = "orn";
   16951                                    notArgR = True; break;
   16952             default: vassert(0);
   16953          }
   16954          IRTemp argL  = newTemp(Ity_I32);
   16955          IRTemp argR  = newTemp(Ity_I32);
   16956          IRTemp res   = newTemp(Ity_I32);
   16957          Bool   updC  = False;
   16958          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
   16959          assign(argL, getIRegT(rN));
   16960          assign(argR, mkU32(notArgR ? ~imm32 : imm32));
   16961          assign(res,  binop(op, mkexpr(argL), mkexpr(argR)));
   16962          putIRegT(rD, mkexpr(res), condT);
   16963          if (bS) {
   16964             IRTemp oldV = newTemp(Ity_I32);
   16965             IRTemp oldC = newTemp(Ity_I32);
   16966             assign( oldV, mk_armg_calculate_flag_v() );
   16967             assign( oldC, updC
   16968                           ? mkU32((imm32 >> 31) & 1)
   16969                           : mk_armg_calculate_flag_c() );
   16970             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16971                                condT );
   16972          }
   16973          DIP("%s%s.w r%u, r%u, #%u\n",
   16974              nm, bS == 1 ? "s" : "", rD, rN, imm32);
   16975          goto decode_success;
   16976       }
   16977    }
   16978 
   16979    /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */
   16980    /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */
   16981    /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */
   16982    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16983        && (   INSN0(8,5) == BITS4(1,0,0,0)  // add subopc
   16984            || INSN0(8,5) == BITS4(1,1,0,1)  // sub subopc
   16985            || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc
   16986        && INSN1(15,15) == 0) {
   16987       UInt rN   = INSN0(3,0);
   16988       UInt rD   = INSN1(11,8);
   16989       UInt rM   = INSN1(3,0);
   16990       UInt bS   = INSN0(4,4);
   16991       UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   16992       UInt how  = INSN1(5,4);
   16993 
   16994       Bool valid = !isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM);
   16995       /* but allow "add.w reg, sp, reg, lsl #N for N=0,1,2 or 3
   16996          (T3) "ADD (SP plus register) */
   16997       if (!valid && INSN0(8,5) == BITS4(1,0,0,0) // add
   16998           && rD != 15 && rN == 13 && imm5 <= 3 && how == 0) {
   16999          valid = True;
   17000       }
   17001       /* also allow "sub.w reg, sp, reg   w/ no shift
   17002          (T1) "SUB (SP minus register) */
   17003       if (!valid && INSN0(8,5) == BITS4(1,1,0,1) // sub
   17004           && rD != 15 && rN == 13 && imm5 == 0 && how == 0) {
   17005          valid = True;
   17006       }
   17007       if (valid) {
   17008          Bool   swap = False;
   17009          IROp   op   = Iop_INVALID;
   17010          HChar* nm   = "???";
   17011          switch (INSN0(8,5)) {
   17012             case BITS4(1,0,0,0): op = Iop_Add32; nm = "add"; break;
   17013             case BITS4(1,1,0,1): op = Iop_Sub32; nm = "sub"; break;
   17014             case BITS4(1,1,1,0): op = Iop_Sub32; nm = "rsb";
   17015                                  swap = True; break;
   17016             default: vassert(0);
   17017          }
   17018 
   17019          IRTemp argL = newTemp(Ity_I32);
   17020          assign(argL, getIRegT(rN));
   17021 
   17022          IRTemp rMt = newTemp(Ity_I32);
   17023          assign(rMt, getIRegT(rM));
   17024 
   17025          IRTemp argR = newTemp(Ity_I32);
   17026          compute_result_and_C_after_shift_by_imm5(
   17027             dis_buf, &argR, NULL, rMt, how, imm5, rM
   17028          );
   17029 
   17030          IRTemp res = newTemp(Ity_I32);
   17031          assign(res, swap
   17032                      ? binop(op, mkexpr(argR), mkexpr(argL))
   17033                      : binop(op, mkexpr(argL), mkexpr(argR)));
   17034 
   17035          putIRegT(rD, mkexpr(res), condT);
   17036          if (bS) {
   17037             switch (op) {
   17038                case Iop_Add32:
   17039                   setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
   17040                   break;
   17041                case Iop_Sub32:
   17042                   if (swap)
   17043                      setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
   17044                   else
   17045                      setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   17046                   break;
   17047                default:
   17048                   vassert(0);
   17049             }
   17050          }
   17051 
   17052          DIP("%s%s.w r%u, r%u, %s\n",
   17053              nm, bS ? "s" : "", rD, rN, dis_buf);
   17054          goto decode_success;
   17055       }
   17056    }
   17057 
   17058    /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */
   17059    /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */
   17060    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   17061        && (   INSN0(8,5) == BITS4(1,0,1,0)   // adc subopc
   17062            || INSN0(8,5) == BITS4(1,0,1,1))  // sbc subopc
   17063        && INSN1(15,15) == 0) {
   17064       /* ADC:  Rd = Rn + shifter_operand + oldC */
   17065       /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
   17066       UInt rN = INSN0(3,0);
   17067       UInt rD = INSN1(11,8);
   17068       UInt rM = INSN1(3,0);
   17069       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   17070          UInt bS   = INSN0(4,4);
   17071          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   17072          UInt how  = INSN1(5,4);
   17073 
   17074          IRTemp argL = newTemp(Ity_I32);
   17075          assign(argL, getIRegT(rN));
   17076 
   17077          IRTemp rMt = newTemp(Ity_I32);
   17078          assign(rMt, getIRegT(rM));
   17079 
   17080          IRTemp oldC = newTemp(Ity_I32);
   17081          assign(oldC, mk_armg_calculate_flag_c());
   17082 
   17083          IRTemp argR = newTemp(Ity_I32);
   17084          compute_result_and_C_after_shift_by_imm5(
   17085             dis_buf, &argR, NULL, rMt, how, imm5, rM
   17086          );
   17087 
   17088          HChar* nm  = "???";
   17089          IRTemp res = newTemp(Ity_I32);
   17090          switch (INSN0(8,5)) {
   17091             case BITS4(1,0,1,0): // ADC
   17092                nm = "adc";
   17093                assign(res,
   17094                       binop(Iop_Add32,
   17095                             binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
   17096                             mkexpr(oldC) ));
   17097                putIRegT(rD, mkexpr(res), condT);
   17098                if (bS)
   17099                   setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
   17100                                      argL, argR, oldC, condT );
   17101                break;
   17102             case BITS4(1,0,1,1): // SBC
   17103                nm = "sbc";
   17104                assign(res,
   17105                       binop(Iop_Sub32,
   17106                             binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
   17107                             binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   17108                putIRegT(rD, mkexpr(res), condT);
   17109                if (bS)
   17110                   setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   17111                                      argL, argR, oldC, condT );
   17112                break;
   17113             default:
   17114                vassert(0);
   17115          }
   17116 
   17117          DIP("%s%s.w r%u, r%u, %s\n",
   17118              nm, bS ? "s" : "", rD, rN, dis_buf);
   17119          goto decode_success;
   17120       }
   17121    }
   17122 
   17123    /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */
   17124    /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */
   17125    /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */
   17126    /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */
   17127    /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */
   17128    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   17129        && (   INSN0(8,5) == BITS4(0,0,0,0)  // and subopc
   17130            || INSN0(8,5) == BITS4(0,0,1,0)  // orr subopc
   17131            || INSN0(8,5) == BITS4(0,1,0,0)  // eor subopc
   17132            || INSN0(8,5) == BITS4(0,0,0,1)  // bic subopc
   17133            || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc
   17134        && INSN1(15,15) == 0) {
   17135       UInt rN = INSN0(3,0);
   17136       UInt rD = INSN1(11,8);
   17137       UInt rM = INSN1(3,0);
   17138       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   17139          Bool notArgR = False;
   17140          IROp op      = Iop_INVALID;
   17141          HChar* nm  = "???";
   17142          switch (INSN0(8,5)) {
   17143             case BITS4(0,0,0,0): op = Iop_And32; nm = "and"; break;
   17144             case BITS4(0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
   17145             case BITS4(0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
   17146             case BITS4(0,0,0,1): op = Iop_And32; nm = "bic";
   17147                                  notArgR = True; break;
   17148             case BITS4(0,0,1,1): op = Iop_Or32; nm = "orn";
   17149                                  notArgR = True; break;
   17150             default: vassert(0);
   17151          }
   17152          UInt bS   = INSN0(4,4);
   17153          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   17154          UInt how  = INSN1(5,4);
   17155 
   17156          IRTemp rNt = newTemp(Ity_I32);
   17157          assign(rNt, getIRegT(rN));
   17158 
   17159          IRTemp rMt = newTemp(Ity_I32);
   17160          assign(rMt, getIRegT(rM));
   17161 
   17162          IRTemp argR = newTemp(Ity_I32);
   17163          IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   17164 
   17165          compute_result_and_C_after_shift_by_imm5(
   17166             dis_buf, &argR, bS ? &oldC : NULL, rMt, how, imm5, rM
   17167          );
   17168 
   17169          IRTemp res = newTemp(Ity_I32);
   17170          if (notArgR) {
   17171             vassert(op == Iop_And32 || op == Iop_Or32);
   17172             assign(res, binop(op, mkexpr(rNt),
   17173                                   unop(Iop_Not32, mkexpr(argR))));
   17174          } else {
   17175             assign(res, binop(op, mkexpr(rNt), mkexpr(argR)));
   17176          }
   17177 
   17178          putIRegT(rD, mkexpr(res), condT);
   17179          if (bS) {
   17180             IRTemp oldV = newTemp(Ity_I32);
   17181             assign( oldV, mk_armg_calculate_flag_v() );
   17182             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   17183                                condT );
   17184          }
   17185 
   17186          DIP("%s%s.w r%u, r%u, %s\n",
   17187              nm, bS ? "s" : "", rD, rN, dis_buf);
   17188          goto decode_success;
   17189       }
   17190    }
   17191 
   17192    /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */
   17193    /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */
   17194    /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */
   17195    /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */
   17196    if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0)
   17197        && INSN1(15,12) == BITS4(1,1,1,1)
   17198        && INSN1(7,4) == BITS4(0,0,0,0)) {
   17199       UInt how = INSN0(6,5); // standard encoding
   17200       UInt rN  = INSN0(3,0);
   17201       UInt rD  = INSN1(11,8);
   17202       UInt rM  = INSN1(3,0);
   17203       UInt bS  = INSN0(4,4);
   17204       Bool valid = !isBadRegT(rN) && !isBadRegT(rM) && !isBadRegT(rD);
   17205       if (valid) {
   17206          IRTemp rNt    = newTemp(Ity_I32);
   17207          IRTemp rMt    = newTemp(Ity_I32);
   17208          IRTemp res    = newTemp(Ity_I32);
   17209          IRTemp oldC   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   17210          IRTemp oldV   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   17211          HChar* nms[4] = { "lsl", "lsr", "asr", "ror" };
   17212          HChar* nm     = nms[how];
   17213          assign(rNt, getIRegT(rN));
   17214          assign(rMt, getIRegT(rM));
   17215          compute_result_and_C_after_shift_by_reg(
   17216             dis_buf, &res, bS ? &oldC : NULL,
   17217             rNt, how, rMt, rN, rM
   17218          );
   17219          if (bS)
   17220             assign(oldV, mk_armg_calculate_flag_v());
   17221          putIRegT(rD, mkexpr(res), condT);
   17222          if (bS) {
   17223             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   17224                                condT );
   17225          }
   17226          DIP("%s%s.w r%u, r%u, r%u\n",
   17227              nm, bS ? "s" : "", rD, rN, rM);
   17228          goto decode_success;
   17229       }
   17230    }
   17231 
   17232    /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */
   17233    /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */
   17234    if ((INSN0(15,0) & 0xFFCF) == 0xEA4F
   17235        && INSN1(15,15) == 0) {
   17236       UInt rD = INSN1(11,8);
   17237       UInt rN = INSN1(3,0);
   17238       if (!isBadRegT(rD) && !isBadRegT(rN)) {
   17239          UInt bS    = INSN0(4,4);
   17240          UInt isMVN = INSN0(5,5);
   17241          UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
   17242          UInt how   = INSN1(5,4);
   17243 
   17244          IRTemp rNt = newTemp(Ity_I32);
   17245          assign(rNt, getIRegT(rN));
   17246 
   17247          IRTemp oldRn = newTemp(Ity_I32);
   17248          IRTemp oldC  = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   17249          compute_result_and_C_after_shift_by_imm5(
   17250             dis_buf, &oldRn, bS ? &oldC : NULL, rNt, how, imm5, rN
   17251          );
   17252 
   17253          IRTemp res = newTemp(Ity_I32);
   17254          assign(res, isMVN ? unop(Iop_Not32, mkexpr(oldRn))
   17255                            : mkexpr(oldRn));
   17256 
   17257          putIRegT(rD, mkexpr(res), condT);
   17258          if (bS) {
   17259             IRTemp oldV = newTemp(Ity_I32);
   17260             assign( oldV, mk_armg_calculate_flag_v() );
   17261             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT);
   17262          }
   17263          DIP("%s%s.w r%u, %s\n",
   17264              isMVN ? "mvn" : "mov", bS ? "s" : "", rD, dis_buf);
   17265          goto decode_success;
   17266       }
   17267    }
   17268 
   17269    /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */
   17270    /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */
   17271    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   17272        && (   INSN0(8,4) == BITS5(0,0,0,0,1)  // TST
   17273            || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ
   17274        && INSN1(15,15) == 0
   17275        && INSN1(11,8) == BITS4(1,1,1,1)) {
   17276       UInt rN = INSN0(3,0);
   17277       UInt rM = INSN1(3,0);
   17278       if (!isBadRegT(rN) && !isBadRegT(rM)) {
   17279          Bool isTST = INSN0(8,4) == BITS5(0,0,0,0,1);
   17280 
   17281          UInt how  = INSN1(5,4);
   17282          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   17283 
   17284          IRTemp argL = newTemp(Ity_I32);
   17285          assign(argL, getIRegT(rN));
   17286 
   17287          IRTemp rMt = newTemp(Ity_I32);
   17288          assign(rMt, getIRegT(rM));
   17289 
   17290          IRTemp argR = newTemp(Ity_I32);
   17291          IRTemp oldC = newTemp(Ity_I32);
   17292          compute_result_and_C_after_shift_by_imm5(
   17293             dis_buf, &argR, &oldC, rMt, how, imm5, rM
   17294          );
   17295 
   17296          IRTemp oldV = newTemp(Ity_I32);
   17297          assign( oldV, mk_armg_calculate_flag_v() );
   17298 
   17299          IRTemp res = newTemp(Ity_I32);
   17300          assign(res, binop(isTST ? Iop_And32 : Iop_Xor32,
   17301                            mkexpr(argL), mkexpr(argR)));
   17302 
   17303          setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   17304                             condT );
   17305          DIP("%s.w r%u, %s\n", isTST ? "tst" : "teq", rN, dis_buf);
   17306          goto decode_success;
   17307       }
   17308    }
   17309 
   17310    /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */
   17311    /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */
   17312    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   17313        && (   INSN0(8,4) == BITS5(1,1,0,1,1)  // CMP
   17314            || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN
   17315        && INSN1(15,15) == 0
   17316        && INSN1(11,8) == BITS4(1,1,1,1)) {
   17317       UInt rN = INSN0(3,0);
   17318       UInt rM = INSN1(3,0);
   17319       if (!isBadRegT(rN) && !isBadRegT(rM)) {
   17320          Bool isCMN = INSN0(8,4) == BITS5(1,0,0,0,1);
   17321          UInt how   = INSN1(5,4);
   17322          UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
   17323 
   17324          IRTemp argL = newTemp(Ity_I32);
   17325          assign(argL, getIRegT(rN));
   17326 
   17327          IRTemp rMt = newTemp(Ity_I32);
   17328          assign(rMt, getIRegT(rM));
   17329 
   17330          IRTemp argR = newTemp(Ity_I32);
   17331          compute_result_and_C_after_shift_by_imm5(
   17332             dis_buf, &argR, NULL, rMt, how, imm5, rM
   17333          );
   17334 
   17335          setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   17336                          argL, argR, condT );
   17337 
   17338          DIP("%s.w r%u, %s\n", isCMN ? "cmn" : "cmp", rN, dis_buf);
   17339          goto decode_success;
   17340       }
   17341    }
   17342 
   17343    /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */
   17344    /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */
   17345    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   17346        && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // MOV
   17347            || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN
   17348        && INSN0(3,0) == BITS4(1,1,1,1)
   17349        && INSN1(15,15) == 0) {
   17350       UInt rD = INSN1(11,8);
   17351       if (!isBadRegT(rD)) {
   17352          Bool   updC  = False;
   17353          UInt   bS    = INSN0(4,4);
   17354          Bool   isMVN = INSN0(5,5) == 1;
   17355          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
   17356          IRTemp res   = newTemp(Ity_I32);
   17357          assign(res, mkU32(isMVN ? ~imm32 : imm32));
   17358          putIRegT(rD, mkexpr(res), condT);
   17359          if (bS) {
   17360             IRTemp oldV = newTemp(Ity_I32);
   17361             IRTemp oldC = newTemp(Ity_I32);
   17362             assign( oldV, mk_armg_calculate_flag_v() );
   17363             assign( oldC, updC
   17364                           ? mkU32((imm32 >> 31) & 1)
   17365                           : mk_armg_calculate_flag_c() );
   17366             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   17367                                condT );
   17368          }
   17369          DIP("%s%s.w r%u, #%u\n",
   17370              isMVN ? "mvn" : "mov", bS ? "s" : "", rD, imm32);
   17371          goto decode_success;
   17372       }
   17373    }
   17374 
   17375    /* -------------- (T3) MOVW Rd, #imm16 -------------- */
   17376    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   17377        && INSN0(9,4) == BITS6(1,0,0,1,0,0)
   17378        && INSN1(15,15) == 0) {
   17379       UInt rD = INSN1(11,8);
   17380       if (!isBadRegT(rD)) {
   17381          UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
   17382                       | (INSN1(14,12) << 8) | INSN1(7,0);
   17383          putIRegT(rD, mkU32(imm16), condT);
   17384          DIP("movw r%u, #%u\n", rD, imm16);
   17385          goto decode_success;
   17386       }
   17387    }
   17388 
   17389    /* ---------------- MOVT Rd, #imm16 ---------------- */
   17390    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   17391        && INSN0(9,4) == BITS6(1,0,1,1,0,0)
   17392        && INSN1(15,15) == 0) {
   17393       UInt rD = INSN1(11,8);
   17394       if (!isBadRegT(rD)) {
   17395          UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
   17396                       | (INSN1(14,12) << 8) | INSN1(7,0);
   17397          IRTemp res = newTemp(Ity_I32);
   17398          assign(res,
   17399                 binop(Iop_Or32,
   17400                       binop(Iop_And32, getIRegT(rD), mkU32(0xFFFF)),
   17401                       mkU32(imm16 << 16)));
   17402          putIRegT(rD, mkexpr(res), condT);
   17403          DIP("movt r%u, #%u\n", rD, imm16);
   17404          goto decode_success;
   17405       }
   17406    }
   17407 
   17408    /* ---------------- LD/ST reg+/-#imm8 ---------------- */
   17409    /* Loads and stores of the form:
   17410          op  Rt, [Rn, #-imm8]      or
   17411          op  Rt, [Rn], #+/-imm8    or
   17412          op  Rt, [Rn, #+/-imm8]!
   17413       where op is one of
   17414          ldrb ldrh ldr  ldrsb ldrsh
   17415          strb strh str
   17416    */
   17417    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) {
   17418       Bool   valid  = True;
   17419       Bool   syned  = False;
   17420       Bool   isST   = False;
   17421       IRType ty     = Ity_I8;
   17422       HChar* nm     = "???";
   17423 
   17424       switch (INSN0(8,4)) {
   17425          case BITS5(0,0,0,0,0):   // strb
   17426             nm = "strb"; isST = True; break;
   17427          case BITS5(0,0,0,0,1):   // ldrb
   17428             nm = "ldrb"; break;
   17429          case BITS5(1,0,0,0,1):   // ldrsb
   17430             nm = "ldrsb"; syned = True; break;
   17431          case BITS5(0,0,0,1,0):   // strh
   17432             nm = "strh"; ty = Ity_I16; isST = True; break;
   17433          case BITS5(0,0,0,1,1):   // ldrh
   17434             nm = "ldrh"; ty = Ity_I16; break;
   17435          case BITS5(1,0,0,1,1):   // ldrsh
   17436             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
   17437          case BITS5(0,0,1,0,0):   // str
   17438             nm = "str"; ty = Ity_I32; isST = True; break;
   17439          case BITS5(0,0,1,0,1):
   17440             nm = "ldr"; ty = Ity_I32; break;  // ldr
   17441          default:
   17442             valid = False; break;
   17443       }
   17444 
   17445       UInt rN      = INSN0(3,0);
   17446       UInt rT      = INSN1(15,12);
   17447       UInt bP      = INSN1(10,10);
   17448       UInt bU      = INSN1(9,9);
   17449       UInt bW      = INSN1(8,8);
   17450       UInt imm8    = INSN1(7,0);
   17451       Bool loadsPC = False;
   17452 
   17453       if (valid) {
   17454          if (bP == 1 && bU == 1 && bW == 0)
   17455             valid = False;
   17456          if (bP == 0 && bW == 0)
   17457             valid = False;
   17458          if (rN == 15)
   17459             valid = False;
   17460          if (bW == 1 && rN == rT)
   17461             valid = False;
   17462          if (ty == Ity_I8 || ty == Ity_I16) {
   17463             if (isBadRegT(rT))
   17464                valid = False;
   17465          } else {
   17466             /* ty == Ity_I32 */
   17467             if (isST && rT == 15)
   17468                valid = False;
   17469             if (!isST && rT == 15)
   17470                loadsPC = True;
   17471          }
   17472       }
   17473 
   17474       if (valid) {
   17475          // if it's a branch, it can't happen in the middle of an IT block
   17476          if (loadsPC)
   17477             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   17478          // go uncond
   17479          mk_skip_over_T32_if_cond_is_false(condT);
   17480          condT = IRTemp_INVALID;
   17481          // now uncond
   17482 
   17483          IRTemp preAddr = newTemp(Ity_I32);
   17484          assign(preAddr, getIRegT(rN));
   17485 
   17486          IRTemp postAddr = newTemp(Ity_I32);
   17487          assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   17488                                 mkexpr(preAddr), mkU32(imm8)));
   17489 
   17490          IRTemp transAddr = bP == 1 ? postAddr : preAddr;
   17491 
   17492          if (isST) {
   17493 
   17494              /* Store.  If necessary, update the base register before
   17495                 the store itself, so that the common idiom of "str rX,
   17496                 [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4,
   17497                 a.k.a "push rX") doesn't cause Memcheck to complain
   17498                 that the access is below the stack pointer.  Also, not
   17499                 updating sp before the store confuses Valgrind's
   17500                 dynamic stack-extending logic.  So do it before the
   17501                 store.  Hence we need to snarf the store data before
   17502                 doing the basereg update. */
   17503 
   17504             /* get hold of the data to be stored */
   17505             IRTemp oldRt = newTemp(Ity_I32);
   17506             assign(oldRt, getIRegT(rT));
   17507 
   17508             /* Update Rn if necessary. */
   17509             if (bW == 1) {
   17510                vassert(rN != rT); // assured by validity check above
   17511                putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
   17512             }
   17513 
   17514             /* generate the transfer */
   17515             switch (ty) {
   17516                case Ity_I8:
   17517                   storeLE(mkexpr(transAddr),
   17518                                  unop(Iop_32to8, mkexpr(oldRt)));
   17519                   break;
   17520                case Ity_I16:
   17521                   storeLE(mkexpr(transAddr),
   17522                           unop(Iop_32to16, mkexpr(oldRt)));
   17523                   break;
   17524               case Ity_I32:
   17525                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
   17526                   break;
   17527               default:
   17528                  vassert(0);
   17529             }
   17530 
   17531          } else {
   17532 
   17533             /* Load. */
   17534 
   17535             /* generate the transfer */
   17536             IRTemp newRt = newTemp(Ity_I32);
   17537             IROp   widen = Iop_INVALID;
   17538             switch (ty) {
   17539                case Ity_I8:
   17540                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
   17541                case Ity_I16:
   17542                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
   17543                case Ity_I32:
   17544                   break;
   17545                default:
   17546                   vassert(0);
   17547             }
   17548             if (widen == Iop_INVALID) {
   17549                assign(newRt, loadLE(ty, mkexpr(transAddr)));
   17550             } else {
   17551                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
   17552             }
   17553             if (loadsPC) {
   17554                vassert(rT == 15);
   17555                llPutIReg(rT, mkexpr(newRt));
   17556             } else {
   17557                putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
   17558             }
   17559 
   17560             /* Update Rn if necessary. */
   17561             if (bW == 1) {
   17562                vassert(rN != rT); // assured by validity check above
   17563                putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
   17564             }
   17565 
   17566             if (loadsPC) {
   17567                /* Presumably this is an interworking branch. */
   17568                vassert(rN != 15); // assured by validity check above
   17569                llPutIReg(15, mkexpr(newRt));
   17570                dres.jk_StopHere = Ijk_Boring;  /* or _Ret ? */
   17571                dres.whatNext    = Dis_StopHere;
   17572             }
   17573          }
   17574 
   17575          if (bP == 1 && bW == 0) {
   17576             DIP("%s.w r%u, [r%u, #%c%u]\n",
   17577                 nm, rT, rN, bU ? '+' : '-', imm8);
   17578          }
   17579          else if (bP == 1 && bW == 1) {
   17580             DIP("%s.w r%u, [r%u, #%c%u]!\n",
   17581                 nm, rT, rN, bU ? '+' : '-', imm8);
   17582          }
   17583          else {
   17584             vassert(bP == 0 && bW == 1);
   17585             DIP("%s.w r%u, [r%u], #%c%u\n",
   17586                 nm, rT, rN, bU ? '+' : '-', imm8);
   17587          }
   17588 
   17589          goto decode_success;
   17590       }
   17591    }
   17592 
   17593    /* ------------- LD/ST reg+(reg<<imm2) ------------- */
   17594    /* Loads and stores of the form:
   17595          op  Rt, [Rn, Rm, LSL #imm8]
   17596       where op is one of
   17597          ldrb ldrh ldr  ldrsb ldrsh
   17598          strb strh str
   17599    */
   17600    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)
   17601        && INSN1(11,6) == BITS6(0,0,0,0,0,0)) {
   17602       Bool   valid  = True;
   17603       Bool   syned  = False;
   17604       Bool   isST   = False;
   17605       IRType ty     = Ity_I8;
   17606       HChar* nm     = "???";
   17607 
   17608       switch (INSN0(8,4)) {
   17609          case BITS5(0,0,0,0,0):   // strb
   17610             nm = "strb"; isST = True; break;
   17611          case BITS5(0,0,0,0,1):   // ldrb
   17612             nm = "ldrb"; break;
   17613          case BITS5(1,0,0,0,1):   // ldrsb
   17614             nm = "ldrsb"; syned = True; break;
   17615          case BITS5(0,0,0,1,0):   // strh
   17616             nm = "strh"; ty = Ity_I16; isST = True; break;
   17617          case BITS5(0,0,0,1,1):   // ldrh
   17618             nm = "ldrh"; ty = Ity_I16; break;
   17619          case BITS5(1,0,0,1,1):   // ldrsh
   17620             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
   17621          case BITS5(0,0,1,0,0):   // str
   17622             nm = "str"; ty = Ity_I32; isST = True; break;
   17623          case BITS5(0,0,1,0,1):
   17624             nm = "ldr"; ty = Ity_I32; break;  // ldr
   17625          default:
   17626             valid = False; break;
   17627       }
   17628 
   17629       UInt rN      = INSN0(3,0);
   17630       UInt rM      = INSN1(3,0);
   17631       UInt rT      = INSN1(15,12);
   17632       UInt imm2    = INSN1(5,4);
   17633       Bool loadsPC = False;
   17634 
   17635       if (ty == Ity_I8 || ty == Ity_I16) {
   17636          /* all 8- and 16-bit load and store cases have the
   17637             same exclusion set. */
   17638          if (rN == 15 || isBadRegT(rT) || isBadRegT(rM))
   17639             valid = False;
   17640       } else {
   17641          vassert(ty == Ity_I32);
   17642          if (rN == 15 || isBadRegT(rM))
   17643             valid = False;
   17644          if (isST && rT == 15)
   17645             valid = False;
   17646          /* If it is a load and rT is 15, that's only allowable if we
   17647             not in an IT block, or are the last in it.  Need to insert
   17648             a dynamic check for that. */
   17649          if (!isST && rT == 15)
   17650             loadsPC = True;
   17651       }
   17652 
   17653       if (valid) {
   17654          // if it's a branch, it can't happen in the middle of an IT block
   17655          if (loadsPC)
   17656             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   17657          // go uncond
   17658          mk_skip_over_T32_if_cond_is_false(condT);
   17659          condT = IRTemp_INVALID;
   17660          // now uncond
   17661 
   17662          IRTemp transAddr = newTemp(Ity_I32);
   17663          assign(transAddr,
   17664                 binop( Iop_Add32,
   17665                        getIRegT(rN),
   17666                        binop(Iop_Shl32, getIRegT(rM), mkU8(imm2)) ));
   17667 
   17668          if (isST) {
   17669             IRTemp oldRt = newTemp(Ity_I32);
   17670             assign(oldRt, getIRegT(rT));
   17671             switch (ty) {
   17672                case Ity_I8:
   17673                   storeLE(mkexpr(transAddr),
   17674                                  unop(Iop_32to8, mkexpr(oldRt)));
   17675                   break;
   17676                case Ity_I16:
   17677                   storeLE(mkexpr(transAddr),
   17678                           unop(Iop_32to16, mkexpr(oldRt)));
   17679                   break;
   17680               case Ity_I32:
   17681                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
   17682                   break;
   17683               default:
   17684                  vassert(0);
   17685             }
   17686          } else {
   17687             IRTemp newRt = newTemp(Ity_I32);
   17688             IROp   widen = Iop_INVALID;
   17689             switch (ty) {
   17690                case Ity_I8:
   17691                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
   17692                case Ity_I16:
   17693                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
   17694                case Ity_I32:
   17695                   break;
   17696                default:
   17697                   vassert(0);
   17698             }
   17699             if (widen == Iop_INVALID) {
   17700                assign(newRt, loadLE(ty, mkexpr(transAddr)));
   17701             } else {
   17702                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
   17703             }
   17704 
   17705             /* If we're loading the PC, putIRegT will assert.  So go
   17706                direct via llPutIReg.  In all other cases use putIRegT
   17707                as it is safer (although could simply use llPutIReg for
   17708                _all_ cases here.) */
   17709             if (loadsPC) {
   17710                vassert(rT == 15);
   17711                llPutIReg(rT, mkexpr(newRt));
   17712             } else {
   17713                putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
   17714             }
   17715 
   17716             if (loadsPC) {
   17717                /* Presumably this is an interworking branch. */
   17718                llPutIReg(15, mkexpr(newRt));
   17719                dres.jk_StopHere = Ijk_Boring;  /* or _Ret ? */
   17720                dres.whatNext    = Dis_StopHere;
   17721             }
   17722          }
   17723 
   17724          DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n",
   17725              nm, rT, rN, rM, imm2);
   17726 
   17727          goto decode_success;
   17728       }
   17729    }
   17730 
   17731    /* --------------- LD/ST reg+imm12 --------------- */
   17732    /* Loads and stores of the form:
   17733          op  Rt, [Rn, +#imm12]
   17734       where op is one of
   17735          ldrb ldrh ldr  ldrsb ldrsh
   17736          strb strh str
   17737    */
   17738    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) {
   17739       Bool   valid  = True;
   17740       Bool   syned  = False;
   17741       Bool   isST   = False;
   17742       IRType ty     = Ity_I8;
   17743       HChar* nm     = "???";
   17744 
   17745       switch (INSN0(8,4)) {
   17746          case BITS5(0,1,0,0,0):   // strb
   17747             nm = "strb"; isST = True; break;
   17748          case BITS5(0,1,0,0,1):   // ldrb
   17749             nm = "ldrb"; break;
   17750          case BITS5(1,1,0,0,1):   // ldrsb
   17751             nm = "ldrsb"; syned = True; break;
   17752          case BITS5(0,1,0,1,0):   // strh
   17753             nm = "strh"; ty = Ity_I16; isST = True; break;
   17754          case BITS5(0,1,0,1,1):   // ldrh
   17755             nm = "ldrh"; ty = Ity_I16; break;
   17756          case BITS5(1,1,0,1,1):   // ldrsh
   17757             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
   17758          case BITS5(0,1,1,0,0):   // str
   17759             nm = "str"; ty = Ity_I32; isST = True; break;
   17760          case BITS5(0,1,1,0,1):
   17761             nm = "ldr"; ty = Ity_I32; break;  // ldr
   17762          default:
   17763             valid = False; break;
   17764       }
   17765 
   17766       UInt rN      = INSN0(3,0);
   17767       UInt rT      = INSN1(15,12);
   17768       UInt imm12   = INSN1(11,0);
   17769       Bool loadsPC = False;
   17770 
   17771       if (ty == Ity_I8 || ty == Ity_I16) {
   17772          /* all 8- and 16-bit load and store cases have the
   17773             same exclusion set. */
   17774          if (rN == 15 || isBadRegT(rT))
   17775             valid = False;
   17776       } else {
   17777          vassert(ty == Ity_I32);
   17778          if (isST) {
   17779             if (rN == 15 || rT == 15)
   17780                valid = False;
   17781          } else {
   17782             /* For a 32-bit load, rT == 15 is only allowable if we not
   17783                in an IT block, or are the last in it.  Need to insert
   17784                a dynamic check for that.  Also, in this particular
   17785                case, rN == 15 is allowable.  In this case however, the
   17786                value obtained for rN is (apparently)
   17787                "word-align(address of current insn + 4)". */
   17788             if (rT == 15)
   17789                loadsPC = True;
   17790          }
   17791       }
   17792 
   17793       if (valid) {
   17794          // if it's a branch, it can't happen in the middle of an IT block
   17795          if (loadsPC)
   17796             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   17797          // go uncond
   17798          mk_skip_over_T32_if_cond_is_false(condT);
   17799          condT = IRTemp_INVALID;
   17800          // now uncond
   17801 
   17802          IRTemp rNt = newTemp(Ity_I32);
   17803          if (rN == 15) {
   17804             vassert(ty == Ity_I32 && !isST);
   17805             assign(rNt, binop(Iop_And32, getIRegT(rN), mkU32(~3)));
   17806          } else {
   17807             assign(rNt, getIRegT(rN));
   17808          }
   17809 
   17810          IRTemp transAddr = newTemp(Ity_I32);
   17811          assign(transAddr,
   17812                 binop( Iop_Add32, mkexpr(rNt), mkU32(imm12) ));
   17813 
   17814          if (isST) {
   17815             IRTemp oldRt = newTemp(Ity_I32);
   17816             assign(oldRt, getIRegT(rT));
   17817             switch (ty) {
   17818                case Ity_I8:
   17819                   storeLE(mkexpr(transAddr),
   17820                                  unop(Iop_32to8, mkexpr(oldRt)));
   17821                   break;
   17822                case Ity_I16:
   17823                   storeLE(mkexpr(transAddr),
   17824                           unop(Iop_32to16, mkexpr(oldRt)));
   17825                   break;
   17826               case Ity_I32:
   17827                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
   17828                   break;
   17829               default:
   17830                  vassert(0);
   17831             }
   17832          } else {
   17833             IRTemp newRt = newTemp(Ity_I32);
   17834             IROp   widen = Iop_INVALID;
   17835             switch (ty) {
   17836                case Ity_I8:
   17837                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
   17838                case Ity_I16:
   17839                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
   17840                case Ity_I32:
   17841                   break;
   17842                default:
   17843                   vassert(0);
   17844             }
   17845             if (widen == Iop_INVALID) {
   17846                assign(newRt, loadLE(ty, mkexpr(transAddr)));
   17847             } else {
   17848                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
   17849             }
   17850             putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
   17851 
   17852             if (loadsPC) {
   17853                /* Presumably this is an interworking branch. */
   17854                irsb->next = mkexpr(newRt);
   17855                irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
   17856                dres.whatNext  = Dis_StopHere;
   17857             }
   17858          }
   17859 
   17860          DIP("%s.w r%u, [r%u, +#%u]\n", nm, rT, rN, imm12);
   17861 
   17862          goto decode_success;
   17863       }
   17864    }
   17865 
   17866    /* -------------- LDRD/STRD reg+/-#imm8 -------------- */
   17867    /* Doubleword loads and stores of the form:
   17868          ldrd/strd  Rt, Rt2, [Rn, #-imm8]      or
   17869          ldrd/strd  Rt, Rt2, [Rn], #+/-imm8    or
   17870          ldrd/strd  Rt, Rt2, [Rn, #+/-imm8]!
   17871    */
   17872    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) {
   17873       UInt bP   = INSN0(8,8);
   17874       UInt bU   = INSN0(7,7);
   17875       UInt bW   = INSN0(5,5);
   17876       UInt bL   = INSN0(4,4);  // 1: load  0: store
   17877       UInt rN   = INSN0(3,0);
   17878       UInt rT   = INSN1(15,12);
   17879       UInt rT2  = INSN1(11,8);
   17880       UInt imm8 = INSN1(7,0);
   17881 
   17882       Bool valid = True;
   17883       if (bP == 0 && bW == 0)                 valid = False;
   17884       if (bW == 1 && (rN == rT || rN == rT2)) valid = False;
   17885       if (isBadRegT(rT) || isBadRegT(rT2))    valid = False;
   17886       if (rN == 15)                           valid = False;
   17887       if (bL == 1 && rT == rT2)               valid = False;
   17888 
   17889       if (valid) {
   17890          // go uncond
   17891          mk_skip_over_T32_if_cond_is_false(condT);
   17892          condT = IRTemp_INVALID;
   17893          // now uncond
   17894 
   17895          IRTemp preAddr = newTemp(Ity_I32);
   17896          assign(preAddr, getIRegT(rN));
   17897 
   17898          IRTemp postAddr = newTemp(Ity_I32);
   17899          assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   17900                                 mkexpr(preAddr), mkU32(imm8 << 2)));
   17901 
   17902          IRTemp transAddr = bP == 1 ? postAddr : preAddr;
   17903 
   17904          if (bL == 0) {
   17905             IRTemp oldRt  = newTemp(Ity_I32);
   17906             IRTemp oldRt2 = newTemp(Ity_I32);
   17907             assign(oldRt,  getIRegT(rT));
   17908             assign(oldRt2, getIRegT(rT2));
   17909             storeLE(mkexpr(transAddr),
   17910                     mkexpr(oldRt));
   17911             storeLE(binop(Iop_Add32, mkexpr(transAddr), mkU32(4)),
   17912                     mkexpr(oldRt2));
   17913          } else {
   17914             IRTemp newRt  = newTemp(Ity_I32);
   17915             IRTemp newRt2 = newTemp(Ity_I32);
   17916             assign(newRt,
   17917                    loadLE(Ity_I32,
   17918                           mkexpr(transAddr)));
   17919             assign(newRt2,
   17920                    loadLE(Ity_I32,
   17921                           binop(Iop_Add32, mkexpr(transAddr), mkU32(4))));
   17922             putIRegT(rT,  mkexpr(newRt), IRTemp_INVALID);
   17923             putIRegT(rT2, mkexpr(newRt2), IRTemp_INVALID);
   17924          }
   17925 
   17926          if (bW == 1) {
   17927             putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
   17928          }
   17929 
   17930          HChar* nm = bL ? "ldrd" : "strd";
   17931 
   17932          if (bP == 1 && bW == 0) {
   17933             DIP("%s.w r%u, r%u, [r%u, #%c%u]\n",
   17934                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
   17935          }
   17936          else if (bP == 1 && bW == 1) {
   17937             DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n",
   17938                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
   17939          }
   17940          else {
   17941             vassert(bP == 0 && bW == 1);
   17942             DIP("%s.w r%u, r%u, [r%u], #%c%u\n",
   17943                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
   17944          }
   17945 
   17946          goto decode_success;
   17947       }
   17948    }
   17949 
   17950    /* -------------- (T3) Bcond.W label -------------- */
   17951    /* This variant carries its own condition, so can't be part of an
   17952       IT block ... */
   17953    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   17954        && INSN1(15,14) == BITS2(1,0)
   17955        && INSN1(12,12) == 0) {
   17956       UInt cond = INSN0(9,6);
   17957       if (cond != ARMCondAL && cond != ARMCondNV) {
   17958          Int simm21
   17959             =   (INSN0(10,10) << (1 + 1 + 6 + 11 + 1))
   17960               | (INSN1(11,11) << (1 + 6 + 11 + 1))
   17961               | (INSN1(13,13) << (6 + 11 + 1))
   17962               | (INSN0(5,0)   << (11 + 1))
   17963               | (INSN1(10,0)  << 1);
   17964          simm21 = (simm21 << 11) >> 11;
   17965 
   17966          vassert(0 == (guest_R15_curr_instr_notENC & 1));
   17967          UInt dst = simm21 + guest_R15_curr_instr_notENC + 4;
   17968 
   17969          /* Not allowed in an IT block; SIGILL if so. */
   17970          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   17971 
   17972          IRTemp kondT = newTemp(Ity_I32);
   17973          assign( kondT, mk_armg_calculate_condition(cond) );
   17974          stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
   17975                             Ijk_Boring,
   17976                             IRConst_U32(dst | 1/*CPSR.T*/),
   17977                             OFFB_R15T ));
   17978          llPutIReg(15, mkU32( (guest_R15_curr_instr_notENC + 4)
   17979                               | 1 /*CPSR.T*/ ));
   17980          dres.jk_StopHere = Ijk_Boring;
   17981          dres.whatNext    = Dis_StopHere;
   17982          DIP("b%s.w 0x%x\n", nCC(cond), dst);
   17983          goto decode_success;
   17984       }
   17985    }
   17986 
   17987    /* ---------------- (T4) B.W label ---------------- */
   17988    /* ... whereas this variant doesn't carry its own condition, so it
   17989       has to be either unconditional or the conditional by virtue of
   17990       being the last in an IT block.  The upside is that there's 4
   17991       more bits available for the jump offset, so it has a 16-times
   17992       greater branch range than the T3 variant. */
   17993    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   17994        && INSN1(15,14) == BITS2(1,0)
   17995        && INSN1(12,12) == 1) {
   17996       if (1) {
   17997          UInt bS  = INSN0(10,10);
   17998          UInt bJ1 = INSN1(13,13);
   17999          UInt bJ2 = INSN1(11,11);
   18000          UInt bI1 = 1 ^ (bJ1 ^ bS);
   18001          UInt bI2 = 1 ^ (bJ2 ^ bS);
   18002          Int simm25
   18003             =   (bS          << (1 + 1 + 10 + 11 + 1))
   18004               | (bI1         << (1 + 10 + 11 + 1))
   18005               | (bI2         << (10 + 11 + 1))
   18006               | (INSN0(9,0)  << (11 + 1))
   18007               | (INSN1(10,0) << 1);
   18008          simm25 = (simm25 << 7) >> 7;
   18009 
   18010          vassert(0 == (guest_R15_curr_instr_notENC & 1));
   18011          UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
   18012 
   18013          /* If in an IT block, must be the last insn. */
   18014          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   18015 
   18016          // go uncond
   18017          mk_skip_over_T32_if_cond_is_false(condT);
   18018          condT = IRTemp_INVALID;
   18019          // now uncond
   18020 
   18021          // branch to dst
   18022          llPutIReg(15, mkU32( dst | 1 /*CPSR.T*/ ));
   18023          dres.jk_StopHere = Ijk_Boring;
   18024          dres.whatNext    = Dis_StopHere;
   18025          DIP("b.w 0x%x\n", dst);
   18026          goto decode_success;
   18027       }
   18028    }
   18029 
   18030    /* ------------------ TBB, TBH ------------------ */
   18031    if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) {
   18032       UInt rN = INSN0(3,0);
   18033       UInt rM = INSN1(3,0);
   18034       UInt bH = INSN1(4,4);
   18035       if (bH/*ATC*/ || (rN != 13 && !isBadRegT(rM))) {
   18036          /* Must be last or not-in IT block */
   18037          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   18038          /* Go uncond */
   18039          mk_skip_over_T32_if_cond_is_false(condT);
   18040          condT = IRTemp_INVALID;
   18041 
   18042          IRExpr* ea
   18043              = binop(Iop_Add32,
   18044                      getIRegT(rN),
   18045                      bH ? binop(Iop_Shl32, getIRegT(rM), mkU8(1))
   18046                         : getIRegT(rM));
   18047 
   18048          IRTemp delta = newTemp(Ity_I32);
   18049          if (bH) {
   18050             assign(delta, unop(Iop_16Uto32, loadLE(Ity_I16, ea)));
   18051          } else {
   18052             assign(delta, unop(Iop_8Uto32, loadLE(Ity_I8, ea)));
   18053          }
   18054 
   18055          llPutIReg(
   18056             15,
   18057             binop(Iop_Or32,
   18058                   binop(Iop_Add32,
   18059                         getIRegT(15),
   18060                         binop(Iop_Shl32, mkexpr(delta), mkU8(1))
   18061                   ),
   18062                   mkU32(1)
   18063          ));
   18064          dres.jk_StopHere = Ijk_Boring;
   18065          dres.whatNext    = Dis_StopHere;
   18066          DIP("tb%c [r%u, r%u%s]\n",
   18067              bH ? 'h' : 'b', rN, rM, bH ? ", LSL #1" : "");
   18068          goto decode_success;
   18069       }
   18070    }
   18071 
   18072    /* ------------------ UBFX ------------------ */
   18073    /* ------------------ SBFX ------------------ */
   18074    /* There's also ARM versions of same, but it doesn't seem worth the
   18075       hassle to common up the handling (it's only a couple of C
   18076       statements). */
   18077    if ((INSN0(15,4) == 0xF3C // UBFX
   18078         || INSN0(15,4) == 0xF34) // SBFX
   18079        && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
   18080       UInt rN  = INSN0(3,0);
   18081       UInt rD  = INSN1(11,8);
   18082       UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
   18083       UInt wm1 = INSN1(4,0);
   18084       UInt msb =  lsb + wm1;
   18085       if (!isBadRegT(rD) && !isBadRegT(rN) && msb <= 31) {
   18086          Bool   isU  = INSN0(15,4) == 0xF3C;
   18087          IRTemp src  = newTemp(Ity_I32);
   18088          IRTemp tmp  = newTemp(Ity_I32);
   18089          IRTemp res  = newTemp(Ity_I32);
   18090          UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
   18091          vassert(msb >= 0 && msb <= 31);
   18092          vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
   18093 
   18094          assign(src, getIRegT(rN));
   18095          assign(tmp, binop(Iop_And32,
   18096                            binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
   18097                            mkU32(mask)));
   18098          assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
   18099                            binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
   18100                            mkU8(31-wm1)));
   18101 
   18102          putIRegT(rD, mkexpr(res), condT);
   18103 
   18104          DIP("%s r%u, r%u, #%u, #%u\n",
   18105              isU ? "ubfx" : "sbfx", rD, rN, lsb, wm1 + 1);
   18106          goto decode_success;
   18107       }
   18108    }
   18109 
   18110    /* ------------------ UXTB ------------------ */
   18111    /* ------------------ UXTH ------------------ */
   18112    /* ------------------ SXTB ------------------ */
   18113    /* ------------------ SXTH ------------------ */
   18114    /* ----------------- UXTB16 ----------------- */
   18115    /* ----------------- SXTB16 ----------------- */
   18116    /* FIXME: this is an exact duplicate of the ARM version.  They
   18117       should be commoned up. */
   18118    if ((INSN0(15,0) == 0xFA5F     // UXTB
   18119         || INSN0(15,0) == 0xFA1F  // UXTH
   18120         || INSN0(15,0) == 0xFA4F  // SXTB
   18121         || INSN0(15,0) == 0xFA0F  // SXTH
   18122         || INSN0(15,0) == 0xFA3F  // UXTB16
   18123         || INSN0(15,0) == 0xFA2F) // SXTB16
   18124        && INSN1(15,12) == BITS4(1,1,1,1)
   18125        && INSN1(7,6) == BITS2(1,0)) {
   18126       UInt rD = INSN1(11,8);
   18127       UInt rM = INSN1(3,0);
   18128       UInt rot = INSN1(5,4);
   18129       if (!isBadRegT(rD) && !isBadRegT(rM)) {
   18130          HChar* nm = "???";
   18131          IRTemp srcT = newTemp(Ity_I32);
   18132          IRTemp rotT = newTemp(Ity_I32);
   18133          IRTemp dstT = newTemp(Ity_I32);
   18134          assign(srcT, getIRegT(rM));
   18135          assign(rotT, genROR32(srcT, 8 * rot));
   18136          switch (INSN0(15,0)) {
   18137             case 0xFA5F: // UXTB
   18138                nm = "uxtb";
   18139                assign(dstT, unop(Iop_8Uto32,
   18140                                  unop(Iop_32to8, mkexpr(rotT))));
   18141                break;
   18142             case 0xFA1F: // UXTH
   18143                nm = "uxth";
   18144                assign(dstT, unop(Iop_16Uto32,
   18145                                  unop(Iop_32to16, mkexpr(rotT))));
   18146                break;
   18147             case 0xFA4F: // SXTB
   18148                nm = "sxtb";
   18149                assign(dstT, unop(Iop_8Sto32,
   18150                                  unop(Iop_32to8, mkexpr(rotT))));
   18151                break;
   18152             case 0xFA0F: // SXTH
   18153                nm = "sxth";
   18154                assign(dstT, unop(Iop_16Sto32,
   18155                                  unop(Iop_32to16, mkexpr(rotT))));
   18156                break;
   18157             case 0xFA3F: // UXTB16
   18158                nm = "uxtb16";
   18159                assign(dstT, binop(Iop_And32, mkexpr(rotT),
   18160                                              mkU32(0x00FF00FF)));
   18161                break;
   18162             case 0xFA2F: { // SXTB16
   18163                nm = "sxtb16";
   18164                IRTemp lo32 = newTemp(Ity_I32);
   18165                IRTemp hi32 = newTemp(Ity_I32);
   18166                assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
   18167                assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
   18168                assign(
   18169                   dstT,
   18170                   binop(Iop_Or32,
   18171                         binop(Iop_And32,
   18172                               unop(Iop_8Sto32,
   18173                                    unop(Iop_32to8, mkexpr(lo32))),
   18174                               mkU32(0xFFFF)),
   18175                         binop(Iop_Shl32,
   18176                               unop(Iop_8Sto32,
   18177                                    unop(Iop_32to8, mkexpr(hi32))),
   18178                               mkU8(16))
   18179                ));
   18180                break;
   18181             }
   18182             default:
   18183                vassert(0);
   18184          }
   18185          putIRegT(rD, mkexpr(dstT), condT);
   18186          DIP("%s r%u, r%u, ror #%u\n", nm, rD, rM, 8 * rot);
   18187          goto decode_success;
   18188       }
   18189    }
   18190 
   18191    /* -------------- MUL.W Rd, Rn, Rm -------------- */
   18192    if (INSN0(15,4) == 0xFB0
   18193        && (INSN1(15,0) & 0xF0F0) == 0xF000) {
   18194       UInt rN = INSN0(3,0);
   18195       UInt rD = INSN1(11,8);
   18196       UInt rM = INSN1(3,0);
   18197       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   18198          IRTemp res = newTemp(Ity_I32);
   18199          assign(res, binop(Iop_Mul32, getIRegT(rN), getIRegT(rM)));
   18200          putIRegT(rD, mkexpr(res), condT);
   18201          DIP("mul.w r%u, r%u, r%u\n", rD, rN, rM);
   18202          goto decode_success;
   18203       }
   18204    }
   18205 
   18206    /* -------------- SDIV.W Rd, Rn, Rm -------------- */
   18207    if (INSN0(15,4) == 0xFB9
   18208        && (INSN1(15,0) & 0xF0F0) == 0xF0F0) {
   18209       UInt rN = INSN0(3,0);
   18210       UInt rD = INSN1(11,8);
   18211       UInt rM = INSN1(3,0);
   18212       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   18213          IRTemp res = newTemp(Ity_I32);
   18214          IRTemp argL  = newTemp(Ity_I32);
   18215          IRTemp argR  = newTemp(Ity_I32);
   18216          assign(argL, getIRegT(rN));
   18217          assign(argR, getIRegT(rM));
   18218          assign(res, binop(Iop_DivS32, mkexpr(argL), mkexpr(argR)));
   18219          putIRegT(rD, mkexpr(res), condT);
   18220          DIP("sdiv.w r%u, r%u, r%u\n", rD, rN, rM);
   18221          goto decode_success;
   18222       }
   18223    }
   18224 
   18225    /* -------------- UDIV.W Rd, Rn, Rm -------------- */
   18226    if (INSN0(15,4) == 0xFBB
   18227        && (INSN1(15,0) & 0xF0F0) == 0xF0F0) {
   18228       UInt rN = INSN0(3,0);
   18229       UInt rD = INSN1(11,8);
   18230       UInt rM = INSN1(3,0);
   18231       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   18232          IRTemp res = newTemp(Ity_I32);
   18233          IRTemp argL  = newTemp(Ity_I32);
   18234          IRTemp argR  = newTemp(Ity_I32);
   18235          assign(argL, getIRegT(rN));
   18236          assign(argR, getIRegT(rM));
   18237          assign(res, binop(Iop_DivU32, mkexpr(argL), mkexpr(argR)));
   18238          putIRegT(rD, mkexpr(res), condT);
   18239          DIP("udiv.w r%u, r%u, r%u\n", rD, rN, rM);
   18240          goto decode_success;
   18241       }
   18242    }
   18243 
   18244    /* ------------------ {U,S}MULL ------------------ */
   18245    if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA)
   18246        && INSN1(7,4) == BITS4(0,0,0,0)) {
   18247       UInt isU  = INSN0(5,5);
   18248       UInt rN   = INSN0(3,0);
   18249       UInt rDlo = INSN1(15,12);
   18250       UInt rDhi = INSN1(11,8);
   18251       UInt rM   = INSN1(3,0);
   18252       if (!isBadRegT(rDhi) && !isBadRegT(rDlo)
   18253           && !isBadRegT(rN) && !isBadRegT(rM) && rDlo != rDhi) {
   18254          IRTemp res   = newTemp(Ity_I64);
   18255          assign(res, binop(isU ? Iop_MullU32 : Iop_MullS32,
   18256                            getIRegT(rN), getIRegT(rM)));
   18257          putIRegT( rDhi, unop(Iop_64HIto32, mkexpr(res)), condT );
   18258          putIRegT( rDlo, unop(Iop_64to32, mkexpr(res)), condT );
   18259          DIP("%cmull r%u, r%u, r%u, r%u\n",
   18260              isU ? 'u' : 's', rDlo, rDhi, rN, rM);
   18261          goto decode_success;
   18262       }
   18263    }
   18264 
   18265    /* ------------------ ML{A,S} ------------------ */
   18266    if (INSN0(15,4) == 0xFB0
   18267        && (   INSN1(7,4) == BITS4(0,0,0,0)    // MLA
   18268            || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS
   18269       UInt rN = INSN0(3,0);
   18270       UInt rA = INSN1(15,12);
   18271       UInt rD = INSN1(11,8);
   18272       UInt rM = INSN1(3,0);
   18273       if (!isBadRegT(rD) && !isBadRegT(rN)
   18274           && !isBadRegT(rM) && !isBadRegT(rA)) {
   18275          Bool   isMLA = INSN1(7,4) == BITS4(0,0,0,0);
   18276          IRTemp res   = newTemp(Ity_I32);
   18277          assign(res,
   18278                 binop(isMLA ? Iop_Add32 : Iop_Sub32,
   18279                       getIRegT(rA),
   18280                       binop(Iop_Mul32, getIRegT(rN), getIRegT(rM))));
   18281          putIRegT(rD, mkexpr(res), condT);
   18282          DIP("%s r%u, r%u, r%u, r%u\n",
   18283              isMLA ? "mla" : "mls", rD, rN, rM, rA);
   18284          goto decode_success;
   18285       }
   18286    }
   18287 
   18288    /* ------------------ (T3) ADR ------------------ */
   18289    if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F)
   18290        && INSN1(15,15) == 0) {
   18291       /* rD = align4(PC) + imm32 */
   18292       UInt rD = INSN1(11,8);
   18293       if (!isBadRegT(rD)) {
   18294          UInt imm32 = (INSN0(10,10) << 11)
   18295                       | (INSN1(14,12) << 8) | INSN1(7,0);
   18296          putIRegT(rD, binop(Iop_Add32,
   18297                             binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   18298                             mkU32(imm32)),
   18299                       condT);
   18300          DIP("add r%u, pc, #%u\n", rD, imm32);
   18301          goto decode_success;
   18302       }
   18303    }
   18304 
   18305    /* ----------------- (T1) UMLAL ----------------- */
   18306    /* ----------------- (T1) SMLAL ----------------- */
   18307    if ((INSN0(15,4) == 0xFBE // UMLAL
   18308         || INSN0(15,4) == 0xFBC) // SMLAL
   18309        && INSN1(7,4) == BITS4(0,0,0,0)) {
   18310       UInt rN   = INSN0(3,0);
   18311       UInt rDlo = INSN1(15,12);
   18312       UInt rDhi = INSN1(11,8);
   18313       UInt rM   = INSN1(3,0);
   18314       if (!isBadRegT(rDlo) && !isBadRegT(rDhi) && !isBadRegT(rN)
   18315           && !isBadRegT(rM) && rDhi != rDlo) {
   18316          Bool   isS   = INSN0(15,4) == 0xFBC;
   18317          IRTemp argL  = newTemp(Ity_I32);
   18318          IRTemp argR  = newTemp(Ity_I32);
   18319          IRTemp old   = newTemp(Ity_I64);
   18320          IRTemp res   = newTemp(Ity_I64);
   18321          IRTemp resHi = newTemp(Ity_I32);
   18322          IRTemp resLo = newTemp(Ity_I32);
   18323          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
   18324          assign( argL, getIRegT(rM));
   18325          assign( argR, getIRegT(rN));
   18326          assign( old, binop(Iop_32HLto64, getIRegT(rDhi), getIRegT(rDlo)) );
   18327          assign( res, binop(Iop_Add64,
   18328                             mkexpr(old),
   18329                             binop(mulOp, mkexpr(argL), mkexpr(argR))) );
   18330          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
   18331          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
   18332          putIRegT( rDhi, mkexpr(resHi), condT );
   18333          putIRegT( rDlo, mkexpr(resLo), condT );
   18334          DIP("%cmlal r%u, r%u, r%u, r%u\n",
   18335              isS ? 's' : 'u', rDlo, rDhi, rN, rM);
   18336          goto decode_success;
   18337       }
   18338    }
   18339 
   18340    /* ------------------ (T2) ADR ------------------ */
   18341    if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF)
   18342        && INSN1(15,15) == 0) {
   18343       /* rD = align4(PC) - imm32 */
   18344       UInt rD = INSN1(11,8);
   18345       if (!isBadRegT(rD)) {
   18346          UInt imm32 = (INSN0(10,10) << 11)
   18347                       | (INSN1(14,12) << 8) | INSN1(7,0);
   18348          putIRegT(rD, binop(Iop_Sub32,
   18349                             binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   18350                             mkU32(imm32)),
   18351                       condT);
   18352          DIP("sub r%u, pc, #%u\n", rD, imm32);
   18353          goto decode_success;
   18354       }
   18355    }
   18356 
   18357    /* ------------------- (T1) BFI ------------------- */
   18358    /* ------------------- (T1) BFC ------------------- */
   18359    if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
   18360       UInt rD  = INSN1(11,8);
   18361       UInt rN  = INSN0(3,0);
   18362       UInt msb = INSN1(4,0);
   18363       UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
   18364       if (isBadRegT(rD) || rN == 13 || msb < lsb) {
   18365          /* undecodable; fall through */
   18366       } else {
   18367          IRTemp src    = newTemp(Ity_I32);
   18368          IRTemp olddst = newTemp(Ity_I32);
   18369          IRTemp newdst = newTemp(Ity_I32);
   18370          UInt   mask = 1 << (msb - lsb);
   18371          mask = (mask - 1) + mask;
   18372          vassert(mask != 0); // guaranteed by "msb < lsb" check above
   18373          mask <<= lsb;
   18374 
   18375          assign(src, rN == 15 ? mkU32(0) : getIRegT(rN));
   18376          assign(olddst, getIRegT(rD));
   18377          assign(newdst,
   18378                 binop(Iop_Or32,
   18379                    binop(Iop_And32,
   18380                          binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
   18381                          mkU32(mask)),
   18382                    binop(Iop_And32,
   18383                          mkexpr(olddst),
   18384                          mkU32(~mask)))
   18385                );
   18386 
   18387          putIRegT(rD, mkexpr(newdst), condT);
   18388 
   18389          if (rN == 15) {
   18390             DIP("bfc r%u, #%u, #%u\n",
   18391                 rD, lsb, msb-lsb+1);
   18392          } else {
   18393             DIP("bfi r%u, r%u, #%u, #%u\n",
   18394                 rD, rN, lsb, msb-lsb+1);
   18395          }
   18396          goto decode_success;
   18397       }
   18398    }
   18399 
   18400    /* ------------------- (T1) SXTAH ------------------- */
   18401    /* ------------------- (T1) UXTAH ------------------- */
   18402    if ((INSN0(15,4) == 0xFA1      // UXTAH
   18403         || INSN0(15,4) == 0xFA0)  // SXTAH
   18404        && INSN1(15,12) == BITS4(1,1,1,1)
   18405        && INSN1(7,6) == BITS2(1,0)) {
   18406       Bool isU = INSN0(15,4) == 0xFA1;
   18407       UInt rN  = INSN0(3,0);
   18408       UInt rD  = INSN1(11,8);
   18409       UInt rM  = INSN1(3,0);
   18410       UInt rot = INSN1(5,4);
   18411       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   18412          IRTemp srcL = newTemp(Ity_I32);
   18413          IRTemp srcR = newTemp(Ity_I32);
   18414          IRTemp res  = newTemp(Ity_I32);
   18415          assign(srcR, getIRegT(rM));
   18416          assign(srcL, getIRegT(rN));
   18417          assign(res,  binop(Iop_Add32,
   18418                             mkexpr(srcL),
   18419                             unop(isU ? Iop_16Uto32 : Iop_16Sto32,
   18420                                  unop(Iop_32to16,
   18421                                       genROR32(srcR, 8 * rot)))));
   18422          putIRegT(rD, mkexpr(res), condT);
   18423          DIP("%cxtah r%u, r%u, r%u, ror #%u\n",
   18424              isU ? 'u' : 's', rD, rN, rM, rot);
   18425          goto decode_success;
   18426       }
   18427    }
   18428 
   18429    /* ------------------- (T1) SXTAB ------------------- */
   18430    /* ------------------- (T1) UXTAB ------------------- */
   18431    if ((INSN0(15,4) == 0xFA5      // UXTAB
   18432         || INSN0(15,4) == 0xFA4)  // SXTAB
   18433        && INSN1(15,12) == BITS4(1,1,1,1)
   18434        && INSN1(7,6) == BITS2(1,0)) {
   18435       Bool isU = INSN0(15,4) == 0xFA5;
   18436       UInt rN  = INSN0(3,0);
   18437       UInt rD  = INSN1(11,8);
   18438       UInt rM  = INSN1(3,0);
   18439       UInt rot = INSN1(5,4);
   18440       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   18441          IRTemp srcL = newTemp(Ity_I32);
   18442          IRTemp srcR = newTemp(Ity_I32);
   18443          IRTemp res  = newTemp(Ity_I32);
   18444          assign(srcR, getIRegT(rM));
   18445          assign(srcL, getIRegT(rN));
   18446          assign(res,  binop(Iop_Add32,
   18447                             mkexpr(srcL),
   18448                             unop(isU ? Iop_8Uto32 : Iop_8Sto32,
   18449                                  unop(Iop_32to8,
   18450                                       genROR32(srcR, 8 * rot)))));
   18451          putIRegT(rD, mkexpr(res), condT);
   18452          DIP("%cxtab r%u, r%u, r%u, ror #%u\n",
   18453              isU ? 'u' : 's', rD, rN, rM, rot);
   18454          goto decode_success;
   18455       }
   18456    }
   18457 
   18458    /* ------------------- (T1) CLZ ------------------- */
   18459    if (INSN0(15,4) == 0xFAB
   18460        && INSN1(15,12) == BITS4(1,1,1,1)
   18461        && INSN1(7,4) == BITS4(1,0,0,0)) {
   18462       UInt rM1 = INSN0(3,0);
   18463       UInt rD  = INSN1(11,8);
   18464       UInt rM2 = INSN1(3,0);
   18465       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
   18466          IRTemp arg = newTemp(Ity_I32);
   18467          IRTemp res = newTemp(Ity_I32);
   18468          assign(arg, getIRegT(rM1));
   18469          assign(res, IRExpr_Mux0X(
   18470                         unop(Iop_1Uto8,binop(Iop_CmpEQ32,
   18471                                              mkexpr(arg),
   18472                                              mkU32(0))),
   18473                         unop(Iop_Clz32, mkexpr(arg)),
   18474                         mkU32(32)
   18475          ));
   18476          putIRegT(rD, mkexpr(res), condT);
   18477          DIP("clz r%u, r%u\n", rD, rM1);
   18478          goto decode_success;
   18479       }
   18480    }
   18481 
   18482    /* ------------------- (T1) RBIT ------------------- */
   18483    if (INSN0(15,4) == 0xFA9
   18484        && INSN1(15,12) == BITS4(1,1,1,1)
   18485        && INSN1(7,4) == BITS4(1,0,1,0)) {
   18486       UInt rM1 = INSN0(3,0);
   18487       UInt rD  = INSN1(11,8);
   18488       UInt rM2 = INSN1(3,0);
   18489       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
   18490          IRTemp arg = newTemp(Ity_I32);
   18491          assign(arg, getIRegT(rM1));
   18492          IRTemp res = gen_BITREV(arg);
   18493          putIRegT(rD, mkexpr(res), condT);
   18494          DIP("rbit r%u, r%u\n", rD, rM1);
   18495          goto decode_success;
   18496       }
   18497    }
   18498 
   18499    /* ------------------- (T2) REV   ------------------- */
   18500    /* ------------------- (T2) REV16 ------------------- */
   18501    if (INSN0(15,4) == 0xFA9
   18502        && INSN1(15,12) == BITS4(1,1,1,1)
   18503        && (   INSN1(7,4) == BITS4(1,0,0,0)     // REV
   18504            || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16
   18505       UInt rM1   = INSN0(3,0);
   18506       UInt rD    = INSN1(11,8);
   18507       UInt rM2   = INSN1(3,0);
   18508       Bool isREV = INSN1(7,4) == BITS4(1,0,0,0);
   18509       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
   18510          IRTemp arg = newTemp(Ity_I32);
   18511          assign(arg, getIRegT(rM1));
   18512          IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
   18513          putIRegT(rD, mkexpr(res), condT);
   18514          DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM1);
   18515          goto decode_success;
   18516       }
   18517    }
   18518 
   18519    /* -------------- (T1) MSR apsr, reg -------------- */
   18520    if (INSN0(15,4) == 0xF38
   18521        && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) {
   18522       UInt rN          = INSN0(3,0);
   18523       UInt write_ge    = INSN1(10,10);
   18524       UInt write_nzcvq = INSN1(11,11);
   18525       if (!isBadRegT(rN) && (write_nzcvq || write_ge)) {
   18526          IRTemp rNt = newTemp(Ity_I32);
   18527          assign(rNt, getIRegT(rN));
   18528          desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
   18529          DIP("msr cpsr_%s%s, r%u\n",
   18530              write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
   18531          goto decode_success;
   18532       }
   18533    }
   18534 
   18535    /* -------------- (T1) MRS reg, apsr -------------- */
   18536    if (INSN0(15,0) == 0xF3EF
   18537        && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) {
   18538       UInt rD = INSN1(11,8);
   18539       if (!isBadRegT(rD)) {
   18540          IRTemp apsr = synthesise_APSR();
   18541          putIRegT( rD, mkexpr(apsr), condT );
   18542          DIP("mrs r%u, cpsr\n", rD);
   18543          goto decode_success;
   18544       }
   18545    }
   18546 
   18547    /* ----------------- (T1) LDREX ----------------- */
   18548    if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) {
   18549       UInt rN   = INSN0(3,0);
   18550       UInt rT   = INSN1(15,12);
   18551       UInt imm8 = INSN1(7,0);
   18552       if (!isBadRegT(rT) && rN != 15) {
   18553          IRTemp res;
   18554          // go uncond
   18555          mk_skip_over_T32_if_cond_is_false( condT );
   18556          // now uncond
   18557          res = newTemp(Ity_I32);
   18558          stmt( IRStmt_LLSC(Iend_LE,
   18559                            res,
   18560                            binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
   18561                            NULL/*this is a load*/ ));
   18562          putIRegT(rT, mkexpr(res), IRTemp_INVALID);
   18563          DIP("ldrex r%u, [r%u, #+%u]\n", rT, rN, imm8 * 4);
   18564          goto decode_success;
   18565       }
   18566    }
   18567 
   18568    /* --------------- (T1) LDREX{B,H} --------------- */
   18569    if (INSN0(15,4) == 0xE8D
   18570        && (INSN1(11,0) == 0xF4F || INSN1(11,0) == 0xF5F)) {
   18571       UInt rN  = INSN0(3,0);
   18572       UInt rT  = INSN1(15,12);
   18573       Bool isH = INSN1(11,0) == 0xF5F;
   18574       if (!isBadRegT(rT) && rN != 15) {
   18575          IRTemp res;
   18576          // go uncond
   18577          mk_skip_over_T32_if_cond_is_false( condT );
   18578          // now uncond
   18579          res = newTemp(isH ? Ity_I16 : Ity_I8);
   18580          stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN),
   18581                            NULL/*this is a load*/ ));
   18582          putIRegT(rT, unop(isH ? Iop_16Uto32 : Iop_8Uto32, mkexpr(res)),
   18583                       IRTemp_INVALID);
   18584          DIP("ldrex%c r%u, [r%u]\n", isH ? 'h' : 'b', rT, rN);
   18585          goto decode_success;
   18586       }
   18587    }
   18588 
   18589    /* --------------- (T1) LDREXD --------------- */
   18590    if (INSN0(15,4) == 0xE8D && INSN1(7,0) == 0x7F) {
   18591       UInt rN  = INSN0(3,0);
   18592       UInt rT  = INSN1(15,12);
   18593       UInt rT2 = INSN1(11,8);
   18594       if (!isBadRegT(rT) && !isBadRegT(rT2) && rT != rT2 && rN != 15) {
   18595          IRTemp res;
   18596          // go uncond
   18597          mk_skip_over_T32_if_cond_is_false( condT );
   18598          // now uncond
   18599          res = newTemp(Ity_I64);
   18600          // FIXME: assumes little-endian guest
   18601          stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN),
   18602                            NULL/*this is a load*/ ));
   18603          // FIXME: assumes little-endian guest
   18604          putIRegT(rT,  unop(Iop_64to32,   mkexpr(res)), IRTemp_INVALID);
   18605          putIRegT(rT2, unop(Iop_64HIto32, mkexpr(res)), IRTemp_INVALID);
   18606          DIP("ldrexd r%u, r%u, [r%u]\n", rT, rT2, rN);
   18607          goto decode_success;
   18608       }
   18609    }
   18610 
   18611    /* ----------------- (T1) STREX ----------------- */
   18612    if (INSN0(15,4) == 0xE84) {
   18613       UInt rN   = INSN0(3,0);
   18614       UInt rT   = INSN1(15,12);
   18615       UInt rD   = INSN1(11,8);
   18616       UInt imm8 = INSN1(7,0);
   18617       if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15
   18618           && rD != rN && rD != rT) {
   18619          IRTemp resSC1, resSC32;
   18620          // go uncond
   18621          mk_skip_over_T32_if_cond_is_false( condT );
   18622          // now uncond
   18623          /* Ok, now we're unconditional.  Do the store. */
   18624          resSC1 = newTemp(Ity_I1);
   18625          stmt( IRStmt_LLSC(Iend_LE,
   18626                            resSC1,
   18627                            binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
   18628                            getIRegT(rT)) );
   18629          /* Set rD to 1 on failure, 0 on success.  Currently we have
   18630             resSC1 == 0 on failure, 1 on success. */
   18631          resSC32 = newTemp(Ity_I32);
   18632          assign(resSC32,
   18633                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   18634          putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
   18635          DIP("strex r%u, r%u, [r%u, #+%u]\n", rD, rT, rN, imm8 * 4);
   18636          goto decode_success;
   18637       }
   18638    }
   18639 
   18640    /* --------------- (T1) STREX{B,H} --------------- */
   18641    if (INSN0(15,4) == 0xE8C
   18642        && (INSN1(11,4) == 0xF4 || INSN1(11,4) == 0xF5)) {
   18643       UInt rN  = INSN0(3,0);
   18644       UInt rT  = INSN1(15,12);
   18645       UInt rD  = INSN1(3,0);
   18646       Bool isH = INSN1(11,4) == 0xF5;
   18647       if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15
   18648           && rD != rN && rD != rT) {
   18649          IRTemp resSC1, resSC32;
   18650          // go uncond
   18651          mk_skip_over_T32_if_cond_is_false( condT );
   18652          // now uncond
   18653          /* Ok, now we're unconditional.  Do the store. */
   18654          resSC1 = newTemp(Ity_I1);
   18655          stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN),
   18656                            unop(isH ? Iop_32to16 : Iop_32to8,
   18657                                 getIRegT(rT))) );
   18658          /* Set rD to 1 on failure, 0 on success.  Currently we have
   18659             resSC1 == 0 on failure, 1 on success. */
   18660          resSC32 = newTemp(Ity_I32);
   18661          assign(resSC32,
   18662                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   18663          putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
   18664          DIP("strex%c r%u, r%u, [r%u]\n", isH ? 'h' : 'b', rD, rT, rN);
   18665          goto decode_success;
   18666       }
   18667    }
   18668 
   18669    /* ---------------- (T1) STREXD ---------------- */
   18670    if (INSN0(15,4) == 0xE8C && INSN1(7,4) == BITS4(0,1,1,1)) {
   18671       UInt rN  = INSN0(3,0);
   18672       UInt rT  = INSN1(15,12);
   18673       UInt rT2 = INSN1(11,8);
   18674       UInt rD  = INSN1(3,0);
   18675       if (!isBadRegT(rD) && !isBadRegT(rT) && !isBadRegT(rT2)
   18676           && rN != 15 && rD != rN && rD != rT && rD != rT) {
   18677          IRTemp resSC1, resSC32, data;
   18678          // go uncond
   18679          mk_skip_over_T32_if_cond_is_false( condT );
   18680          // now uncond
   18681          /* Ok, now we're unconditional.  Do the store. */
   18682          resSC1 = newTemp(Ity_I1);
   18683          data = newTemp(Ity_I64);
   18684          // FIXME: assumes little-endian guest
   18685          assign(data, binop(Iop_32HLto64, getIRegT(rT2), getIRegT(rT)));
   18686          // FIXME: assumes little-endian guest
   18687          stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN), mkexpr(data)));
   18688          /* Set rD to 1 on failure, 0 on success.  Currently we have
   18689             resSC1 == 0 on failure, 1 on success. */
   18690          resSC32 = newTemp(Ity_I32);
   18691          assign(resSC32,
   18692                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   18693          putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
   18694          DIP("strexd r%u, r%u, r%u, [r%u]\n", rD, rT, rT2, rN);
   18695          goto decode_success;
   18696       }
   18697    }
   18698    /* -------------- v7 barrier insns -------------- */
   18699    if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) {
   18700       /* FIXME: should this be unconditional? */
   18701       /* XXX this isn't really right, is it?  The generated IR does
   18702          them unconditionally.  I guess it doesn't matter since it
   18703          doesn't do any harm to do them even when the guarding
   18704          condition is false -- it's just a performance loss. */
   18705       switch (INSN1(7,0)) {
   18706          case 0x4F: /* DSB sy */
   18707          case 0x4E: /* DSB st */
   18708          case 0x4B: /* DSB ish */
   18709          case 0x4A: /* DSB ishst */
   18710          case 0x47: /* DSB nsh */
   18711          case 0x46: /* DSB nshst */
   18712          case 0x43: /* DSB osh */
   18713          case 0x42: /* DSB oshst */
   18714             stmt( IRStmt_MBE(Imbe_Fence) );
   18715             DIP("DSB\n");
   18716             goto decode_success;
   18717          case 0x5F: /* DMB sy */
   18718          case 0x5E: /* DMB st */
   18719          case 0x5B: /* DMB ish */
   18720          case 0x5A: /* DMB ishst */
   18721          case 0x57: /* DMB nsh */
   18722          case 0x56: /* DMB nshst */
   18723          case 0x53: /* DMB osh */
   18724          case 0x52: /* DMB oshst */
   18725             stmt( IRStmt_MBE(Imbe_Fence) );
   18726             DIP("DMB\n");
   18727             goto decode_success;
   18728          case 0x6F: /* ISB */
   18729             stmt( IRStmt_MBE(Imbe_Fence) );
   18730             DIP("ISB\n");
   18731             goto decode_success;
   18732          default:
   18733             break;
   18734       }
   18735    }
   18736 
   18737    /* ---------------------- PLD{,W} ---------------------- */
   18738    if ((INSN0(15,4) & 0xFFD) == 0xF89 && INSN1(15,12) == 0xF) {
   18739       /* FIXME: should this be unconditional? */
   18740       /* PLD/PLDW immediate, encoding T1 */
   18741       UInt rN    = INSN0(3,0);
   18742       UInt bW    = INSN0(5,5);
   18743       UInt imm12 = INSN1(11,0);
   18744       DIP("pld%s [r%u, #%u]\n", bW ? "w" : "",  rN, imm12);
   18745       goto decode_success;
   18746    }
   18747 
   18748    if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,8) == 0xFC) {
   18749       /* FIXME: should this be unconditional? */
   18750       /* PLD/PLDW immediate, encoding T2 */
   18751       UInt rN    = INSN0(3,0);
   18752       UInt bW    = INSN0(5,5);
   18753       UInt imm8  = INSN1(7,0);
   18754       DIP("pld%s [r%u, #-%u]\n", bW ? "w" : "",  rN, imm8);
   18755       goto decode_success;
   18756    }
   18757 
   18758    if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,6) == 0x3C0) {
   18759       /* FIXME: should this be unconditional? */
   18760       /* PLD/PLDW register, encoding T1 */
   18761       UInt rN   = INSN0(3,0);
   18762       UInt rM   = INSN1(3,0);
   18763       UInt bW   = INSN0(5,5);
   18764       UInt imm2 = INSN1(5,4);
   18765       if (!isBadRegT(rM)) {
   18766          DIP("pld%s [r%u, r%u, lsl %d]\n", bW ? "w" : "", rN, rM, imm2);
   18767          goto decode_success;
   18768       }
   18769       /* fall through */
   18770    }
   18771 
   18772    /* -------------- read CP15 TPIDRURO register ------------- */
   18773    /* mrc     p15, 0,  r0, c13, c0, 3  up to
   18774       mrc     p15, 0, r14, c13, c0, 3
   18775    */
   18776    /* I don't know whether this is really v7-only.  But anyway, we
   18777       have to support it since arm-linux uses TPIDRURO as a thread
   18778       state register. */
   18779    if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
   18780       /* FIXME: should this be unconditional? */
   18781       UInt rD = INSN1(15,12);
   18782       if (!isBadRegT(rD)) {
   18783          putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID);
   18784          DIP("mrc p15,0, r%u, c13, c0, 3\n", rD);
   18785          goto decode_success;
   18786       }
   18787       /* fall through */
   18788    }
   18789 
   18790    /* ------------------- CLREX ------------------ */
   18791    if (INSN0(15,0) == 0xF3BF && INSN1(15,0) == 0x8F2F) {
   18792       /* AFAICS, this simply cancels a (all?) reservations made by a
   18793          (any?) preceding LDREX(es).  Arrange to hand it through to
   18794          the back end. */
   18795       mk_skip_over_T32_if_cond_is_false( condT );
   18796       stmt( IRStmt_MBE(Imbe_CancelReservation) );
   18797       DIP("clrex\n");
   18798       goto decode_success;
   18799    }
   18800 
   18801    /* ------------------- NOP ------------------ */
   18802    if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
   18803       DIP("nop\n");
   18804       goto decode_success;
   18805    }
   18806 
   18807    /* ------------------- (T1) SMMUL{R} ------------------ */
   18808    if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
   18809        && INSN0(6,4) == BITS3(1,0,1)
   18810        && INSN1(15,12) == BITS4(1,1,1,1)
   18811        && INSN1(7,5) == BITS3(0,0,0)) {
   18812       UInt bitR = INSN1(4,4);
   18813       UInt rD = INSN1(11,8);
   18814       UInt rM = INSN1(3,0);
   18815       UInt rN = INSN0(3,0);
   18816       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   18817          IRExpr* res
   18818          = unop(Iop_64HIto32,
   18819                 binop(Iop_Add64,
   18820                       binop(Iop_MullS32, getIRegT(rN), getIRegT(rM)),
   18821                       mkU64(bitR ? 0x80000000ULL : 0ULL)));
   18822          putIRegT(rD, res, condT);
   18823          DIP("smmul%s r%u, r%u, r%u\n",
   18824              bitR ? "r" : "", rD, rN, rM);
   18825          goto decode_success;
   18826       }
   18827    }
   18828 
   18829    /* ------------------- (T1) SMMLA{R} ------------------ */
   18830    if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
   18831        && INSN0(6,4) == BITS3(1,0,1)
   18832        && INSN1(7,5) == BITS3(0,0,0)) {
   18833       UInt bitR = INSN1(4,4);
   18834       UInt rA = INSN1(15,12);
   18835       UInt rD = INSN1(11,8);
   18836       UInt rM = INSN1(3,0);
   18837       UInt rN = INSN0(3,0);
   18838       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && (rA != 13)) {
   18839          IRExpr* res
   18840          = unop(Iop_64HIto32,
   18841                 binop(Iop_Add64,
   18842                       binop(Iop_Add64,
   18843                             binop(Iop_32HLto64, getIRegT(rA), mkU32(0)),
   18844                             binop(Iop_MullS32, getIRegT(rN), getIRegT(rM))),
   18845                       mkU64(bitR ? 0x80000000ULL : 0ULL)));
   18846          putIRegT(rD, res, condT);
   18847          DIP("smmla%s r%u, r%u, r%u, r%u\n",
   18848              bitR ? "r" : "", rD, rN, rM, rA);
   18849          goto decode_success;
   18850       }
   18851    }
   18852 
   18853    /* ----------------------------------------------------------- */
   18854    /* -- VFP (CP 10, CP 11) instructions (in Thumb mode)       -- */
   18855    /* ----------------------------------------------------------- */
   18856 
   18857    if (INSN0(15,12) == BITS4(1,1,1,0)) {
   18858       UInt insn28 = (INSN0(11,0) << 16) | INSN1(15,0);
   18859       Bool ok_vfp = decode_CP10_CP11_instruction (
   18860                        &dres, insn28, condT, ARMCondAL/*bogus*/,
   18861                        True/*isT*/
   18862                     );
   18863       if (ok_vfp)
   18864          goto decode_success;
   18865    }
   18866 
   18867    /* ----------------------------------------------------------- */
   18868    /* -- NEON instructions (in Thumb mode)                     -- */
   18869    /* ----------------------------------------------------------- */
   18870 
   18871    if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
   18872       UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
   18873       Bool ok_neon = decode_NEON_instruction(
   18874                         &dres, insn32, condT, True/*isT*/
   18875                      );
   18876       if (ok_neon)
   18877          goto decode_success;
   18878    }
   18879 
   18880    /* ----------------------------------------------------------- */
   18881    /* -- v6 media instructions (in Thumb mode)                 -- */
   18882    /* ----------------------------------------------------------- */
   18883 
   18884    { UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
   18885      Bool ok_v6m = decode_V6MEDIA_instruction(
   18886                       &dres, insn32, condT, ARMCondAL/*bogus*/,
   18887                       True/*isT*/
   18888                    );
   18889      if (ok_v6m)
   18890         goto decode_success;
   18891    }
   18892 
   18893    /* ----------------------------------------------------------- */
   18894    /* -- Undecodable                                           -- */
   18895    /* ----------------------------------------------------------- */
   18896 
   18897    goto decode_failure;
   18898    /*NOTREACHED*/
   18899 
   18900   decode_failure:
   18901    /* All decode failures end up here. */
   18902    vex_printf("disInstr(thumb): unhandled instruction: "
   18903               "0x%04x 0x%04x\n", (UInt)insn0, (UInt)insn1);
   18904 
   18905    /* Back up ITSTATE to the initial value for this instruction.
   18906       If we don't do that, any subsequent restart of the instruction
   18907       will restart with the wrong value. */
   18908    if (old_itstate != IRTemp_INVALID)
   18909       put_ITSTATE(old_itstate);
   18910 
   18911    /* Tell the dispatcher that this insn cannot be decoded, and so has
   18912       not been executed, and (is currently) the next to be executed.
   18913       R15 should be up-to-date since it made so at the start of each
   18914       insn, but nevertheless be paranoid and update it again right
   18915       now. */
   18916    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   18917    llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
   18918    dres.whatNext    = Dis_StopHere;
   18919    dres.jk_StopHere = Ijk_NoDecode;
   18920    dres.len         = 0;
   18921    return dres;
   18922 
   18923   decode_success:
   18924    /* All decode successes end up here. */
   18925    vassert(dres.len == 4 || dres.len == 2 || dres.len == 20);
   18926    switch (dres.whatNext) {
   18927       case Dis_Continue:
   18928          llPutIReg(15, mkU32(dres.len + (guest_R15_curr_instr_notENC | 1)));
   18929          break;
   18930       case Dis_ResteerU:
   18931       case Dis_ResteerC:
   18932          llPutIReg(15, mkU32(dres.continueAt));
   18933          break;
   18934       case Dis_StopHere:
   18935          break;
   18936       default:
   18937          vassert(0);
   18938    }
   18939 
   18940    DIP("\n");
   18941 
   18942    return dres;
   18943 
   18944 #  undef INSN0
   18945 #  undef INSN1
   18946 }
   18947 
   18948 #undef DIP
   18949 #undef DIS
   18950 
   18951 
   18952 /* Helper table for figuring out how many insns an IT insn
   18953    conditionalises.
   18954 
   18955    An ITxyz instruction of the format "1011 1111 firstcond mask"
   18956    conditionalises some number of instructions, as indicated by the
   18957    following table.  A value of zero indicates the instruction is
   18958    invalid in some way.
   18959 
   18960    mask = 0 means this isn't an IT instruction
   18961    fc = 15 (NV) means unpredictable
   18962 
   18963    The line fc = 14 (AL) is different from the others; there are
   18964    additional constraints in this case.
   18965 
   18966           mask(0 ..                   15)
   18967         +--------------------------------
   18968    fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18969    ..   | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18970         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18971         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18972         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18973         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18974         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18975         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18976         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18977         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18978         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18979         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18980         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18981         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18982         | 0 4 3 0 2 0 0 0 1 0 0 0 0 0 0 0
   18983    15)  | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
   18984 
   18985    To be conservative with the analysis, let's rule out the mask = 0
   18986    case, since that isn't an IT insn at all.  But for all the other
   18987    cases where the table contains zero, that means unpredictable, so
   18988    let's say 4 to be conservative.  Hence we have a safe value for any
   18989    IT (mask,fc) pair that the CPU would actually identify as an IT
   18990    instruction.  The final table is
   18991 
   18992           mask(0 ..                   15)
   18993         +--------------------------------
   18994    fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18995    ..   | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18996         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18997         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18998         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18999         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   19000         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   19001         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   19002         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   19003         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   19004         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   19005         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   19006         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   19007         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   19008         | 0 4 3 4 2 4 4 4 1 4 4 4 4 4 4 4
   19009    15)  | 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
   19010 */
   19011 static const UChar it_length_table[256]
   19012    = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19013        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19014        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19015        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19016        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19017        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19018        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19019        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19020        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19021        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19022        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19023        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19024        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19025        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   19026        0, 4, 3, 4, 2, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4,
   19027        0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
   19028      };
   19029 
   19030 
   19031 /*------------------------------------------------------------*/
   19032 /*--- Top-level fn                                         ---*/
   19033 /*------------------------------------------------------------*/
   19034 
   19035 /* Disassemble a single instruction into IR.  The instruction
   19036    is located in host memory at &guest_code[delta]. */
   19037 
   19038 DisResult disInstr_ARM ( IRSB*        irsb_IN,
   19039                          Bool         (*resteerOkFn) ( void*, Addr64 ),
   19040                          Bool         resteerCisOk,
   19041                          void*        callback_opaque,
   19042                          UChar*       guest_code_IN,
   19043                          Long         delta_ENCODED,
   19044                          Addr64       guest_IP_ENCODED,
   19045                          VexArch      guest_arch,
   19046                          VexArchInfo* archinfo,
   19047                          VexAbiInfo*  abiinfo,
   19048                          Bool         host_bigendian_IN )
   19049 {
   19050    DisResult dres;
   19051    Bool isThumb = (Bool)(guest_IP_ENCODED & 1);
   19052 
   19053    /* Set globals (see top of this file) */
   19054    vassert(guest_arch == VexArchARM);
   19055 
   19056    irsb              = irsb_IN;
   19057    host_is_bigendian = host_bigendian_IN;
   19058    __curr_is_Thumb   = isThumb;
   19059 
   19060    if (isThumb) {
   19061       guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED - 1;
   19062    } else {
   19063       guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED;
   19064    }
   19065 
   19066    if (isThumb) {
   19067       dres = disInstr_THUMB_WRK ( resteerOkFn,
   19068                                   resteerCisOk, callback_opaque,
   19069                                   &guest_code_IN[delta_ENCODED - 1],
   19070                                   archinfo, abiinfo );
   19071    } else {
   19072       dres = disInstr_ARM_WRK ( resteerOkFn,
   19073                                 resteerCisOk, callback_opaque,
   19074                                 &guest_code_IN[delta_ENCODED],
   19075                                 archinfo, abiinfo );
   19076    }
   19077 
   19078    return dres;
   19079 }
   19080 
   19081 /* Test program for the conversion of IRCmpF64Result values to VFP
   19082    nzcv values.  See handling of FCMPD et al above. */
   19083 /*
   19084 UInt foo ( UInt x )
   19085 {
   19086    UInt ix    = ((x >> 5) & 3) | (x & 1);
   19087    UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1);
   19088    UInt termR = (ix & (ix >> 1) & 1);
   19089    return termL  -  termR;
   19090 }
   19091 
   19092 void try ( char* s, UInt ir, UInt req )
   19093 {
   19094    UInt act = foo(ir);
   19095    printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n",
   19096           s, ir, (req >> 3) & 1, (req >> 2) & 1,
   19097                  (req >> 1) & 1, (req >> 0) & 1,
   19098                  (act >> 3) & 1, (act >> 2) & 1,
   19099                  (act >> 1) & 1, (act >> 0) & 1, act);
   19100 
   19101 }
   19102 
   19103 int main ( void )
   19104 {
   19105    printf("\n");
   19106    try("UN", 0x45, 0b0011);
   19107    try("LT", 0x01, 0b1000);
   19108    try("GT", 0x00, 0b0010);
   19109    try("EQ", 0x40, 0b0110);
   19110    printf("\n");
   19111    return 0;
   19112 }
   19113 */
   19114 
   19115 /*--------------------------------------------------------------------*/
   19116 /*--- end                                         guest_arm_toIR.c ---*/
   19117 /*--------------------------------------------------------------------*/
   19118