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-2011 OpenWorks LLP
     11       info (at) open-works.net
     12 
     13    NEON support is
     14    Copyright (C) 2010-2011 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        ));
   1403 }
   1404 
   1405 /* Thumb16 only */
   1406 /* ditto, but jump over a 16-bit thumb insn */
   1407 static void mk_skip_over_T16_if_cond_is_false (
   1408                IRTemp guardT /* :: Ity_I32, 0 or 1 */
   1409             )
   1410 {
   1411    ASSERT_IS_THUMB;
   1412    vassert(guardT != IRTemp_INVALID);
   1413    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   1414    stmt( IRStmt_Exit(
   1415             unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
   1416             Ijk_Boring,
   1417             IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 2) | 1))
   1418        ));
   1419 }
   1420 
   1421 
   1422 /* Thumb32 only */
   1423 /* ditto, but jump over a 32-bit thumb insn */
   1424 static void mk_skip_over_T32_if_cond_is_false (
   1425                IRTemp guardT /* :: Ity_I32, 0 or 1 */
   1426             )
   1427 {
   1428    ASSERT_IS_THUMB;
   1429    vassert(guardT != IRTemp_INVALID);
   1430    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   1431    stmt( IRStmt_Exit(
   1432             unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
   1433             Ijk_Boring,
   1434             IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 4) | 1))
   1435        ));
   1436 }
   1437 
   1438 
   1439 /* Thumb16 and Thumb32 only
   1440    Generate a SIGILL followed by a restart of the current instruction
   1441    if the given temp is nonzero. */
   1442 static void gen_SIGILL_T_if_nonzero ( IRTemp t /* :: Ity_I32 */ )
   1443 {
   1444    ASSERT_IS_THUMB;
   1445    vassert(t != IRTemp_INVALID);
   1446    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   1447    stmt(
   1448       IRStmt_Exit(
   1449          binop(Iop_CmpNE32, mkexpr(t), mkU32(0)),
   1450          Ijk_NoDecode,
   1451          IRConst_U32(toUInt(guest_R15_curr_instr_notENC | 1))
   1452       )
   1453    );
   1454 }
   1455 
   1456 
   1457 /* Inspect the old_itstate, and generate a SIGILL if it indicates that
   1458    we are currently in an IT block and are not the last in the block.
   1459    This also rolls back guest_ITSTATE to its old value before the exit
   1460    and restores it to its new value afterwards.  This is so that if
   1461    the exit is taken, we have an up to date version of ITSTATE
   1462    available.  Without doing that, we have no hope of making precise
   1463    exceptions work. */
   1464 static void gen_SIGILL_T_if_in_but_NLI_ITBlock (
   1465                IRTemp old_itstate /* :: Ity_I32 */,
   1466                IRTemp new_itstate /* :: Ity_I32 */
   1467             )
   1468 {
   1469    ASSERT_IS_THUMB;
   1470    put_ITSTATE(old_itstate); // backout
   1471    IRTemp guards_for_next3 = newTemp(Ity_I32);
   1472    assign(guards_for_next3,
   1473           binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
   1474    gen_SIGILL_T_if_nonzero(guards_for_next3);
   1475    put_ITSTATE(new_itstate); //restore
   1476 }
   1477 
   1478 
   1479 /* Simpler version of the above, which generates a SIGILL if
   1480    we're anywhere within an IT block. */
   1481 static void gen_SIGILL_T_if_in_ITBlock (
   1482                IRTemp old_itstate /* :: Ity_I32 */,
   1483                IRTemp new_itstate /* :: Ity_I32 */
   1484             )
   1485 {
   1486    put_ITSTATE(old_itstate); // backout
   1487    gen_SIGILL_T_if_nonzero(old_itstate);
   1488    put_ITSTATE(new_itstate); //restore
   1489 }
   1490 
   1491 
   1492 /* Generate an APSR value, from the NZCV thunk, and
   1493    from QFLAG32 and GEFLAG0 .. GEFLAG3. */
   1494 static IRTemp synthesise_APSR ( void )
   1495 {
   1496    IRTemp res1 = newTemp(Ity_I32);
   1497    // Get NZCV
   1498    assign( res1, mk_armg_calculate_flags_nzcv() );
   1499    // OR in the Q value
   1500    IRTemp res2 = newTemp(Ity_I32);
   1501    assign(
   1502       res2,
   1503       binop(Iop_Or32,
   1504             mkexpr(res1),
   1505             binop(Iop_Shl32,
   1506                   unop(Iop_1Uto32,
   1507                        binop(Iop_CmpNE32,
   1508                              mkexpr(get_QFLAG32()),
   1509                              mkU32(0))),
   1510                   mkU8(ARMG_CC_SHIFT_Q)))
   1511    );
   1512    // OR in GE0 .. GE3
   1513    IRExpr* ge0
   1514       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(0), mkU32(0)));
   1515    IRExpr* ge1
   1516       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(1), mkU32(0)));
   1517    IRExpr* ge2
   1518       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(2), mkU32(0)));
   1519    IRExpr* ge3
   1520       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(3), mkU32(0)));
   1521    IRTemp res3 = newTemp(Ity_I32);
   1522    assign(res3,
   1523           binop(Iop_Or32,
   1524                 mkexpr(res2),
   1525                 binop(Iop_Or32,
   1526                       binop(Iop_Or32,
   1527                             binop(Iop_Shl32, ge0, mkU8(16)),
   1528                             binop(Iop_Shl32, ge1, mkU8(17))),
   1529                       binop(Iop_Or32,
   1530                             binop(Iop_Shl32, ge2, mkU8(18)),
   1531                             binop(Iop_Shl32, ge3, mkU8(19))) )));
   1532    return res3;
   1533 }
   1534 
   1535 
   1536 /* and the inverse transformation: given an APSR value,
   1537    set the NZCV thunk, the Q flag, and the GE flags. */
   1538 static void desynthesise_APSR ( Bool write_nzcvq, Bool write_ge,
   1539                                 IRTemp apsrT, IRTemp condT )
   1540 {
   1541    vassert(write_nzcvq || write_ge);
   1542    if (write_nzcvq) {
   1543       // Do NZCV
   1544       IRTemp immT = newTemp(Ity_I32);
   1545       assign(immT, binop(Iop_And32, mkexpr(apsrT), mkU32(0xF0000000)) );
   1546       setFlags_D1(ARMG_CC_OP_COPY, immT, condT);
   1547       // Do Q
   1548       IRTemp qnewT = newTemp(Ity_I32);
   1549       assign(qnewT, binop(Iop_And32, mkexpr(apsrT), mkU32(ARMG_CC_MASK_Q)));
   1550       put_QFLAG32(qnewT, condT);
   1551    }
   1552    if (write_ge) {
   1553       // Do GE3..0
   1554       put_GEFLAG32(0, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<16)),
   1555                    condT);
   1556       put_GEFLAG32(1, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<17)),
   1557                    condT);
   1558       put_GEFLAG32(2, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<18)),
   1559                    condT);
   1560       put_GEFLAG32(3, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<19)),
   1561                    condT);
   1562    }
   1563 }
   1564 
   1565 
   1566 /*------------------------------------------------------------*/
   1567 /*--- Helpers for saturation                               ---*/
   1568 /*------------------------------------------------------------*/
   1569 
   1570 /* FIXME: absolutely the only diff. between (a) armUnsignedSatQ and
   1571    (b) armSignedSatQ is that in (a) the floor is set to 0, whereas in
   1572    (b) the floor is computed from the value of imm5.  these two fnsn
   1573    should be commoned up. */
   1574 
   1575 /* UnsignedSatQ(): 'clamp' each value so it lies between 0 <= x <= (2^N)-1
   1576    Optionally return flag resQ saying whether saturation occurred.
   1577    See definition in manual, section A2.2.1, page 41
   1578    (bits(N), boolean) UnsignedSatQ( integer i, integer N )
   1579    {
   1580      if ( i > (2^N)-1 ) { result = (2^N)-1; saturated = TRUE; }
   1581      elsif ( i < 0 )    { result = 0; saturated = TRUE; }
   1582      else               { result = i; saturated = FALSE; }
   1583      return ( result<N-1:0>, saturated );
   1584    }
   1585 */
   1586 static void armUnsignedSatQ( IRTemp* res,  /* OUT - Ity_I32 */
   1587                              IRTemp* resQ, /* OUT - Ity_I32  */
   1588                              IRTemp regT,  /* value to clamp - Ity_I32 */
   1589                              UInt imm5 )   /* saturation ceiling */
   1590 {
   1591    UInt ceil  = (1 << imm5) - 1;    // (2^imm5)-1
   1592    UInt floor = 0;
   1593 
   1594    IRTemp node0 = newTemp(Ity_I32);
   1595    IRTemp node1 = newTemp(Ity_I32);
   1596    IRTemp node2 = newTemp(Ity_I1);
   1597    IRTemp node3 = newTemp(Ity_I32);
   1598    IRTemp node4 = newTemp(Ity_I32);
   1599    IRTemp node5 = newTemp(Ity_I1);
   1600    IRTemp node6 = newTemp(Ity_I32);
   1601 
   1602    assign( node0, mkexpr(regT) );
   1603    assign( node1, mkU32(ceil) );
   1604    assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
   1605    assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
   1606                                 mkexpr(node0),
   1607                                 mkexpr(node1) ) );
   1608    assign( node4, mkU32(floor) );
   1609    assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
   1610    assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
   1611                                 mkexpr(node3),
   1612                                 mkexpr(node4) ) );
   1613    assign( *res, mkexpr(node6) );
   1614 
   1615    /* if saturation occurred, then resQ is set to some nonzero value
   1616       if sat did not occur, resQ is guaranteed to be zero. */
   1617    if (resQ) {
   1618       assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
   1619    }
   1620 }
   1621 
   1622 
   1623 /* SignedSatQ(): 'clamp' each value so it lies between  -2^N <= x <= (2^N) - 1
   1624    Optionally return flag resQ saying whether saturation occurred.
   1625    - see definition in manual, section A2.2.1, page 41
   1626    (bits(N), boolean ) SignedSatQ( integer i, integer N )
   1627    {
   1628      if ( i > 2^(N-1) - 1 )    { result = 2^(N-1) - 1; saturated = TRUE; }
   1629      elsif ( i < -(2^(N-1)) )  { result = -(2^(N-1));  saturated = FALSE; }
   1630      else                      { result = i;           saturated = FALSE; }
   1631      return ( result[N-1:0], saturated );
   1632    }
   1633 */
   1634 static void armSignedSatQ( IRTemp regT,    /* value to clamp - Ity_I32 */
   1635                            UInt imm5,      /* saturation ceiling */
   1636                            IRTemp* res,    /* OUT - Ity_I32 */
   1637                            IRTemp* resQ )  /* OUT - Ity_I32  */
   1638 {
   1639    Int ceil  =  (1 << (imm5-1)) - 1;  //  (2^(imm5-1))-1
   1640    Int floor = -(1 << (imm5-1));      // -(2^(imm5-1))
   1641 
   1642    IRTemp node0 = newTemp(Ity_I32);
   1643    IRTemp node1 = newTemp(Ity_I32);
   1644    IRTemp node2 = newTemp(Ity_I1);
   1645    IRTemp node3 = newTemp(Ity_I32);
   1646    IRTemp node4 = newTemp(Ity_I32);
   1647    IRTemp node5 = newTemp(Ity_I1);
   1648    IRTemp node6 = newTemp(Ity_I32);
   1649 
   1650    assign( node0, mkexpr(regT) );
   1651    assign( node1, mkU32(ceil) );
   1652    assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
   1653    assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
   1654                                 mkexpr(node0),  mkexpr(node1) ) );
   1655    assign( node4, mkU32(floor) );
   1656    assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
   1657    assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
   1658                                 mkexpr(node3),  mkexpr(node4) ) );
   1659    assign( *res, mkexpr(node6) );
   1660 
   1661    /* if saturation occurred, then resQ is set to some nonzero value
   1662       if sat did not occur, resQ is guaranteed to be zero. */
   1663    if (resQ) {
   1664      assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
   1665    }
   1666 }
   1667 
   1668 
   1669 /* Compute a value 0 :: I32 or 1 :: I32, indicating whether signed
   1670    overflow occurred for 32-bit addition.  Needs both args and the
   1671    result.  HD p27. */
   1672 static
   1673 IRExpr* signed_overflow_after_Add32 ( IRExpr* resE,
   1674                                       IRTemp argL, IRTemp argR )
   1675 {
   1676    IRTemp res = newTemp(Ity_I32);
   1677    assign(res, resE);
   1678    return
   1679       binop( Iop_Shr32,
   1680              binop( Iop_And32,
   1681                     binop( Iop_Xor32, mkexpr(res), mkexpr(argL) ),
   1682                     binop( Iop_Xor32, mkexpr(res), mkexpr(argR) )),
   1683              mkU8(31) );
   1684 }
   1685 
   1686 
   1687 /*------------------------------------------------------------*/
   1688 /*--- Larger helpers                                       ---*/
   1689 /*------------------------------------------------------------*/
   1690 
   1691 /* Compute both the result and new C flag value for a LSL by an imm5
   1692    or by a register operand.  May generate reads of the old C value
   1693    (hence only safe to use before any writes to guest state happen).
   1694    Are factored out so can be used by both ARM and Thumb.
   1695 
   1696    Note that in compute_result_and_C_after_{LSL,LSR,ASR}_by{imm5,reg},
   1697    "res" (the result)  is a.k.a. "shop", shifter operand
   1698    "newC" (the new C)  is a.k.a. "shco", shifter carry out
   1699 
   1700    The calling convention for res and newC is a bit funny.  They could
   1701    be passed by value, but instead are passed by ref.
   1702 
   1703    The C (shco) value computed must be zero in bits 31:1, as the IR
   1704    optimisations for flag handling (guest_arm_spechelper) rely on
   1705    that, and the slow-path handlers (armg_calculate_flags_nzcv) assert
   1706    for it.  Same applies to all these functions that compute shco
   1707    after a shift or rotate, not just this one.
   1708 */
   1709 
   1710 static void compute_result_and_C_after_LSL_by_imm5 (
   1711                /*OUT*/HChar* buf,
   1712                IRTemp* res,
   1713                IRTemp* newC,
   1714                IRTemp rMt, UInt shift_amt, /* operands */
   1715                UInt rM      /* only for debug printing */
   1716             )
   1717 {
   1718    if (shift_amt == 0) {
   1719       if (newC) {
   1720          assign( *newC, mk_armg_calculate_flag_c() );
   1721       }
   1722       assign( *res, mkexpr(rMt) );
   1723       DIS(buf, "r%u", rM);
   1724    } else {
   1725       vassert(shift_amt >= 1 && shift_amt <= 31);
   1726       if (newC) {
   1727          assign( *newC,
   1728                  binop(Iop_And32,
   1729                        binop(Iop_Shr32, mkexpr(rMt),
   1730                                         mkU8(32 - shift_amt)),
   1731                        mkU32(1)));
   1732       }
   1733       assign( *res,
   1734               binop(Iop_Shl32, mkexpr(rMt), mkU8(shift_amt)) );
   1735       DIS(buf, "r%u, LSL #%u", rM, shift_amt);
   1736    }
   1737 }
   1738 
   1739 
   1740 static void compute_result_and_C_after_LSL_by_reg (
   1741                /*OUT*/HChar* buf,
   1742                IRTemp* res,
   1743                IRTemp* newC,
   1744                IRTemp rMt, IRTemp rSt,  /* operands */
   1745                UInt rM,    UInt rS      /* only for debug printing */
   1746             )
   1747 {
   1748    // shift left in range 0 .. 255
   1749    // amt  = rS & 255
   1750    // res  = amt < 32 ?  Rm << amt  : 0
   1751    // newC = amt == 0     ? oldC  :
   1752    //        amt in 1..32 ?  Rm[32-amt]  : 0
   1753    IRTemp amtT = newTemp(Ity_I32);
   1754    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   1755    if (newC) {
   1756       /* mux0X(amt == 0,
   1757                mux0X(amt < 32,
   1758                      0,
   1759                      Rm[(32-amt) & 31]),
   1760                oldC)
   1761       */
   1762       /* About the best you can do is pray that iropt is able
   1763          to nuke most or all of the following junk. */
   1764       IRTemp oldC = newTemp(Ity_I32);
   1765       assign(oldC, mk_armg_calculate_flag_c() );
   1766       assign(
   1767          *newC,
   1768          IRExpr_Mux0X(
   1769             unop(Iop_1Uto8,
   1770                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
   1771             IRExpr_Mux0X(
   1772                unop(Iop_1Uto8,
   1773                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
   1774                mkU32(0),
   1775                binop(Iop_And32,
   1776                      binop(Iop_Shr32,
   1777                            mkexpr(rMt),
   1778                            unop(Iop_32to8,
   1779                                 binop(Iop_And32,
   1780                                       binop(Iop_Sub32,
   1781                                             mkU32(32),
   1782                                             mkexpr(amtT)),
   1783                                       mkU32(31)
   1784                                 )
   1785                            )
   1786                      ),
   1787                      mkU32(1)
   1788                )
   1789             ),
   1790             mkexpr(oldC)
   1791          )
   1792       );
   1793    }
   1794    // (Rm << (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
   1795    // Lhs of the & limits the shift to 31 bits, so as to
   1796    // give known IR semantics.  Rhs of the & is all 1s for
   1797    // Rs <= 31 and all 0s for Rs >= 32.
   1798    assign(
   1799       *res,
   1800       binop(
   1801          Iop_And32,
   1802          binop(Iop_Shl32,
   1803                mkexpr(rMt),
   1804                unop(Iop_32to8,
   1805                     binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
   1806          binop(Iop_Sar32,
   1807                binop(Iop_Sub32,
   1808                      mkexpr(amtT),
   1809                      mkU32(32)),
   1810                mkU8(31))));
   1811     DIS(buf, "r%u, LSL r%u", rM, rS);
   1812 }
   1813 
   1814 
   1815 static void compute_result_and_C_after_LSR_by_imm5 (
   1816                /*OUT*/HChar* buf,
   1817                IRTemp* res,
   1818                IRTemp* newC,
   1819                IRTemp rMt, UInt shift_amt, /* operands */
   1820                UInt rM      /* only for debug printing */
   1821             )
   1822 {
   1823    if (shift_amt == 0) {
   1824       // conceptually a 32-bit shift, however:
   1825       // res  = 0
   1826       // newC = Rm[31]
   1827       if (newC) {
   1828          assign( *newC,
   1829                  binop(Iop_And32,
   1830                        binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
   1831                        mkU32(1)));
   1832       }
   1833       assign( *res, mkU32(0) );
   1834       DIS(buf, "r%u, LSR #0(a.k.a. 32)", rM);
   1835    } else {
   1836       // shift in range 1..31
   1837       // res  = Rm >>u shift_amt
   1838       // newC = Rm[shift_amt - 1]
   1839       vassert(shift_amt >= 1 && shift_amt <= 31);
   1840       if (newC) {
   1841          assign( *newC,
   1842                  binop(Iop_And32,
   1843                        binop(Iop_Shr32, mkexpr(rMt),
   1844                                         mkU8(shift_amt - 1)),
   1845                        mkU32(1)));
   1846       }
   1847       assign( *res,
   1848               binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)) );
   1849       DIS(buf, "r%u, LSR #%u", rM, shift_amt);
   1850    }
   1851 }
   1852 
   1853 
   1854 static void compute_result_and_C_after_LSR_by_reg (
   1855                /*OUT*/HChar* buf,
   1856                IRTemp* res,
   1857                IRTemp* newC,
   1858                IRTemp rMt, IRTemp rSt,  /* operands */
   1859                UInt rM,    UInt rS      /* only for debug printing */
   1860             )
   1861 {
   1862    // shift right in range 0 .. 255
   1863    // amt = rS & 255
   1864    // res  = amt < 32 ?  Rm >>u amt  : 0
   1865    // newC = amt == 0     ? oldC  :
   1866    //        amt in 1..32 ?  Rm[amt-1]  : 0
   1867    IRTemp amtT = newTemp(Ity_I32);
   1868    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   1869    if (newC) {
   1870       /* mux0X(amt == 0,
   1871                mux0X(amt < 32,
   1872                      0,
   1873                      Rm[(amt-1) & 31]),
   1874                oldC)
   1875       */
   1876       IRTemp oldC = newTemp(Ity_I32);
   1877       assign(oldC, mk_armg_calculate_flag_c() );
   1878       assign(
   1879          *newC,
   1880          IRExpr_Mux0X(
   1881             unop(Iop_1Uto8,
   1882                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
   1883             IRExpr_Mux0X(
   1884                unop(Iop_1Uto8,
   1885                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
   1886                mkU32(0),
   1887                binop(Iop_And32,
   1888                      binop(Iop_Shr32,
   1889                            mkexpr(rMt),
   1890                            unop(Iop_32to8,
   1891                                 binop(Iop_And32,
   1892                                       binop(Iop_Sub32,
   1893                                             mkexpr(amtT),
   1894                                             mkU32(1)),
   1895                                       mkU32(31)
   1896                                 )
   1897                            )
   1898                      ),
   1899                      mkU32(1)
   1900                )
   1901             ),
   1902             mkexpr(oldC)
   1903          )
   1904       );
   1905    }
   1906    // (Rm >>u (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
   1907    // Lhs of the & limits the shift to 31 bits, so as to
   1908    // give known IR semantics.  Rhs of the & is all 1s for
   1909    // Rs <= 31 and all 0s for Rs >= 32.
   1910    assign(
   1911       *res,
   1912       binop(
   1913          Iop_And32,
   1914          binop(Iop_Shr32,
   1915                mkexpr(rMt),
   1916                unop(Iop_32to8,
   1917                     binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
   1918          binop(Iop_Sar32,
   1919                binop(Iop_Sub32,
   1920                      mkexpr(amtT),
   1921                      mkU32(32)),
   1922                mkU8(31))));
   1923     DIS(buf, "r%u, LSR r%u", rM, rS);
   1924 }
   1925 
   1926 
   1927 static void compute_result_and_C_after_ASR_by_imm5 (
   1928                /*OUT*/HChar* buf,
   1929                IRTemp* res,
   1930                IRTemp* newC,
   1931                IRTemp rMt, UInt shift_amt, /* operands */
   1932                UInt rM      /* only for debug printing */
   1933             )
   1934 {
   1935    if (shift_amt == 0) {
   1936       // conceptually a 32-bit shift, however:
   1937       // res  = Rm >>s 31
   1938       // newC = Rm[31]
   1939       if (newC) {
   1940          assign( *newC,
   1941                  binop(Iop_And32,
   1942                        binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
   1943                        mkU32(1)));
   1944       }
   1945       assign( *res, binop(Iop_Sar32, mkexpr(rMt), mkU8(31)) );
   1946       DIS(buf, "r%u, ASR #0(a.k.a. 32)", rM);
   1947    } else {
   1948       // shift in range 1..31
   1949       // res = Rm >>s shift_amt
   1950       // newC = Rm[shift_amt - 1]
   1951       vassert(shift_amt >= 1 && shift_amt <= 31);
   1952       if (newC) {
   1953          assign( *newC,
   1954                  binop(Iop_And32,
   1955                        binop(Iop_Shr32, mkexpr(rMt),
   1956                                         mkU8(shift_amt - 1)),
   1957                        mkU32(1)));
   1958       }
   1959       assign( *res,
   1960               binop(Iop_Sar32, mkexpr(rMt), mkU8(shift_amt)) );
   1961       DIS(buf, "r%u, ASR #%u", rM, shift_amt);
   1962    }
   1963 }
   1964 
   1965 
   1966 static void compute_result_and_C_after_ASR_by_reg (
   1967                /*OUT*/HChar* buf,
   1968                IRTemp* res,
   1969                IRTemp* newC,
   1970                IRTemp rMt, IRTemp rSt,  /* operands */
   1971                UInt rM,    UInt rS      /* only for debug printing */
   1972             )
   1973 {
   1974    // arithmetic shift right in range 0 .. 255
   1975    // amt = rS & 255
   1976    // res  = amt < 32 ?  Rm >>s amt  : Rm >>s 31
   1977    // newC = amt == 0     ? oldC  :
   1978    //        amt in 1..32 ?  Rm[amt-1]  : Rm[31]
   1979    IRTemp amtT = newTemp(Ity_I32);
   1980    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   1981    if (newC) {
   1982       /* mux0X(amt == 0,
   1983                mux0X(amt < 32,
   1984                      Rm[31],
   1985                      Rm[(amt-1) & 31])
   1986                oldC)
   1987       */
   1988       IRTemp oldC = newTemp(Ity_I32);
   1989       assign(oldC, mk_armg_calculate_flag_c() );
   1990       assign(
   1991          *newC,
   1992          IRExpr_Mux0X(
   1993             unop(Iop_1Uto8,
   1994                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
   1995             IRExpr_Mux0X(
   1996                unop(Iop_1Uto8,
   1997                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
   1998                binop(Iop_And32,
   1999                      binop(Iop_Shr32,
   2000                            mkexpr(rMt),
   2001                            mkU8(31)
   2002                      ),
   2003                      mkU32(1)
   2004                ),
   2005                binop(Iop_And32,
   2006                      binop(Iop_Shr32,
   2007                            mkexpr(rMt),
   2008                            unop(Iop_32to8,
   2009                                 binop(Iop_And32,
   2010                                       binop(Iop_Sub32,
   2011                                             mkexpr(amtT),
   2012                                             mkU32(1)),
   2013                                       mkU32(31)
   2014                                 )
   2015                            )
   2016                      ),
   2017                      mkU32(1)
   2018                )
   2019             ),
   2020             mkexpr(oldC)
   2021          )
   2022       );
   2023    }
   2024    // (Rm >>s (amt <u 32 ? amt : 31))
   2025    assign(
   2026       *res,
   2027       binop(
   2028          Iop_Sar32,
   2029          mkexpr(rMt),
   2030          unop(
   2031             Iop_32to8,
   2032             IRExpr_Mux0X(
   2033                unop(
   2034                  Iop_1Uto8,
   2035                  binop(Iop_CmpLT32U, mkexpr(amtT), mkU32(32))),
   2036                mkU32(31),
   2037                mkexpr(amtT)))));
   2038     DIS(buf, "r%u, ASR r%u", rM, rS);
   2039 }
   2040 
   2041 
   2042 static void compute_result_and_C_after_ROR_by_reg (
   2043                /*OUT*/HChar* buf,
   2044                IRTemp* res,
   2045                IRTemp* newC,
   2046                IRTemp rMt, IRTemp rSt,  /* operands */
   2047                UInt rM,    UInt rS      /* only for debug printing */
   2048             )
   2049 {
   2050    // rotate right in range 0 .. 255
   2051    // amt = rS & 255
   2052    // shop =  Rm `ror` (amt & 31)
   2053    // shco =  amt == 0 ? oldC : Rm[(amt-1) & 31]
   2054    IRTemp amtT = newTemp(Ity_I32);
   2055    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   2056    IRTemp amt5T = newTemp(Ity_I32);
   2057    assign( amt5T, binop(Iop_And32, mkexpr(rSt), mkU32(31)) );
   2058    IRTemp oldC = newTemp(Ity_I32);
   2059    assign(oldC, mk_armg_calculate_flag_c() );
   2060    if (newC) {
   2061       assign(
   2062          *newC,
   2063          IRExpr_Mux0X(
   2064             unop(Iop_32to8, mkexpr(amtT)),
   2065             mkexpr(oldC),
   2066             binop(Iop_And32,
   2067                   binop(Iop_Shr32,
   2068                         mkexpr(rMt),
   2069                         unop(Iop_32to8,
   2070                              binop(Iop_And32,
   2071                                    binop(Iop_Sub32,
   2072                                          mkexpr(amtT),
   2073                                          mkU32(1)
   2074                                    ),
   2075                                    mkU32(31)
   2076                              )
   2077                         )
   2078                   ),
   2079                   mkU32(1)
   2080             )
   2081          )
   2082       );
   2083    }
   2084    assign(
   2085       *res,
   2086       IRExpr_Mux0X(
   2087          unop(Iop_32to8, mkexpr(amt5T)), mkexpr(rMt),
   2088          binop(Iop_Or32,
   2089                binop(Iop_Shr32,
   2090                      mkexpr(rMt),
   2091                      unop(Iop_32to8, mkexpr(amt5T))
   2092                ),
   2093                binop(Iop_Shl32,
   2094                      mkexpr(rMt),
   2095                      unop(Iop_32to8,
   2096                           binop(Iop_Sub32, mkU32(32), mkexpr(amt5T))
   2097                      )
   2098                )
   2099          )
   2100       )
   2101    );
   2102    DIS(buf, "r%u, ROR r#%u", rM, rS);
   2103 }
   2104 
   2105 
   2106 /* Generate an expression corresponding to the immediate-shift case of
   2107    a shifter operand.  This is used both for ARM and Thumb2.
   2108 
   2109    Bind it to a temporary, and return that via *res.  If newC is
   2110    non-NULL, also compute a value for the shifter's carry out (in the
   2111    LSB of a word), bind it to a temporary, and return that via *shco.
   2112 
   2113    Generates GETs from the guest state and is therefore not safe to
   2114    use once we start doing PUTs to it, for any given instruction.
   2115 
   2116    'how' is encoded thusly:
   2117       00b LSL,  01b LSR,  10b ASR,  11b ROR
   2118    Most but not all ARM and Thumb integer insns use this encoding.
   2119    Be careful to ensure the right value is passed here.
   2120 */
   2121 static void compute_result_and_C_after_shift_by_imm5 (
   2122                /*OUT*/HChar* buf,
   2123                /*OUT*/IRTemp* res,
   2124                /*OUT*/IRTemp* newC,
   2125                IRTemp  rMt,       /* reg to shift */
   2126                UInt    how,       /* what kind of shift */
   2127                UInt    shift_amt, /* shift amount (0..31) */
   2128                UInt    rM         /* only for debug printing */
   2129             )
   2130 {
   2131    vassert(shift_amt < 32);
   2132    vassert(how < 4);
   2133 
   2134    switch (how) {
   2135 
   2136       case 0:
   2137          compute_result_and_C_after_LSL_by_imm5(
   2138             buf, res, newC, rMt, shift_amt, rM
   2139          );
   2140          break;
   2141 
   2142       case 1:
   2143          compute_result_and_C_after_LSR_by_imm5(
   2144             buf, res, newC, rMt, shift_amt, rM
   2145          );
   2146          break;
   2147 
   2148       case 2:
   2149          compute_result_and_C_after_ASR_by_imm5(
   2150             buf, res, newC, rMt, shift_amt, rM
   2151          );
   2152          break;
   2153 
   2154       case 3:
   2155          if (shift_amt == 0) {
   2156             IRTemp oldcT = newTemp(Ity_I32);
   2157             // rotate right 1 bit through carry (?)
   2158             // RRX -- described at ARM ARM A5-17
   2159             // res  = (oldC << 31) | (Rm >>u 1)
   2160             // newC = Rm[0]
   2161             if (newC) {
   2162                assign( *newC,
   2163                        binop(Iop_And32, mkexpr(rMt), mkU32(1)));
   2164             }
   2165             assign( oldcT, mk_armg_calculate_flag_c() );
   2166             assign( *res,
   2167                     binop(Iop_Or32,
   2168                           binop(Iop_Shl32, mkexpr(oldcT), mkU8(31)),
   2169                           binop(Iop_Shr32, mkexpr(rMt), mkU8(1))) );
   2170             DIS(buf, "r%u, RRX", rM);
   2171          } else {
   2172             // rotate right in range 1..31
   2173             // res  = Rm `ror` shift_amt
   2174             // newC = Rm[shift_amt - 1]
   2175             vassert(shift_amt >= 1 && shift_amt <= 31);
   2176             if (newC) {
   2177                assign( *newC,
   2178                        binop(Iop_And32,
   2179                              binop(Iop_Shr32, mkexpr(rMt),
   2180                                               mkU8(shift_amt - 1)),
   2181                              mkU32(1)));
   2182             }
   2183             assign( *res,
   2184                     binop(Iop_Or32,
   2185                           binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)),
   2186                           binop(Iop_Shl32, mkexpr(rMt),
   2187                                            mkU8(32-shift_amt))));
   2188             DIS(buf, "r%u, ROR #%u", rM, shift_amt);
   2189          }
   2190          break;
   2191 
   2192       default:
   2193          /*NOTREACHED*/
   2194          vassert(0);
   2195    }
   2196 }
   2197 
   2198 
   2199 /* Generate an expression corresponding to the register-shift case of
   2200    a shifter operand.  This is used both for ARM and Thumb2.
   2201 
   2202    Bind it to a temporary, and return that via *res.  If newC is
   2203    non-NULL, also compute a value for the shifter's carry out (in the
   2204    LSB of a word), bind it to a temporary, and return that via *shco.
   2205 
   2206    Generates GETs from the guest state and is therefore not safe to
   2207    use once we start doing PUTs to it, for any given instruction.
   2208 
   2209    'how' is encoded thusly:
   2210       00b LSL,  01b LSR,  10b ASR,  11b ROR
   2211    Most but not all ARM and Thumb integer insns use this encoding.
   2212    Be careful to ensure the right value is passed here.
   2213 */
   2214 static void compute_result_and_C_after_shift_by_reg (
   2215                /*OUT*/HChar*  buf,
   2216                /*OUT*/IRTemp* res,
   2217                /*OUT*/IRTemp* newC,
   2218                IRTemp  rMt,       /* reg to shift */
   2219                UInt    how,       /* what kind of shift */
   2220                IRTemp  rSt,       /* shift amount */
   2221                UInt    rM,        /* only for debug printing */
   2222                UInt    rS         /* only for debug printing */
   2223             )
   2224 {
   2225    vassert(how < 4);
   2226    switch (how) {
   2227       case 0: { /* LSL */
   2228          compute_result_and_C_after_LSL_by_reg(
   2229             buf, res, newC, rMt, rSt, rM, rS
   2230          );
   2231          break;
   2232       }
   2233       case 1: { /* LSR */
   2234          compute_result_and_C_after_LSR_by_reg(
   2235             buf, res, newC, rMt, rSt, rM, rS
   2236          );
   2237          break;
   2238       }
   2239       case 2: { /* ASR */
   2240          compute_result_and_C_after_ASR_by_reg(
   2241             buf, res, newC, rMt, rSt, rM, rS
   2242          );
   2243          break;
   2244       }
   2245       case 3: { /* ROR */
   2246          compute_result_and_C_after_ROR_by_reg(
   2247              buf, res, newC, rMt, rSt, rM, rS
   2248          );
   2249          break;
   2250       }
   2251       default:
   2252          /*NOTREACHED*/
   2253          vassert(0);
   2254    }
   2255 }
   2256 
   2257 
   2258 /* Generate an expression corresponding to a shifter_operand, bind it
   2259    to a temporary, and return that via *shop.  If shco is non-NULL,
   2260    also compute a value for the shifter's carry out (in the LSB of a
   2261    word), bind it to a temporary, and return that via *shco.
   2262 
   2263    If for some reason we can't come up with a shifter operand (missing
   2264    case?  not really a shifter operand?) return False.
   2265 
   2266    Generates GETs from the guest state and is therefore not safe to
   2267    use once we start doing PUTs to it, for any given instruction.
   2268 
   2269    For ARM insns only; not for Thumb.
   2270 */
   2271 static Bool mk_shifter_operand ( UInt insn_25, UInt insn_11_0,
   2272                                  /*OUT*/IRTemp* shop,
   2273                                  /*OUT*/IRTemp* shco,
   2274                                  /*OUT*/HChar* buf )
   2275 {
   2276    UInt insn_4 = (insn_11_0 >> 4) & 1;
   2277    UInt insn_7 = (insn_11_0 >> 7) & 1;
   2278    vassert(insn_25 <= 0x1);
   2279    vassert(insn_11_0 <= 0xFFF);
   2280 
   2281    vassert(shop && *shop == IRTemp_INVALID);
   2282    *shop = newTemp(Ity_I32);
   2283 
   2284    if (shco) {
   2285       vassert(*shco == IRTemp_INVALID);
   2286       *shco = newTemp(Ity_I32);
   2287    }
   2288 
   2289    /* 32-bit immediate */
   2290 
   2291    if (insn_25 == 1) {
   2292       /* immediate: (7:0) rotated right by 2 * (11:8) */
   2293       UInt imm = (insn_11_0 >> 0) & 0xFF;
   2294       UInt rot = 2 * ((insn_11_0 >> 8) & 0xF);
   2295       vassert(rot <= 30);
   2296       imm = ROR32(imm, rot);
   2297       if (shco) {
   2298          if (rot == 0) {
   2299             assign( *shco, mk_armg_calculate_flag_c() );
   2300          } else {
   2301             assign( *shco, mkU32( (imm >> 31) & 1 ) );
   2302          }
   2303       }
   2304       DIS(buf, "#0x%x", imm);
   2305       assign( *shop, mkU32(imm) );
   2306       return True;
   2307    }
   2308 
   2309    /* Shift/rotate by immediate */
   2310 
   2311    if (insn_25 == 0 && insn_4 == 0) {
   2312       /* Rm (3:0) shifted (6:5) by immediate (11:7) */
   2313       UInt shift_amt = (insn_11_0 >> 7) & 0x1F;
   2314       UInt rM        = (insn_11_0 >> 0) & 0xF;
   2315       UInt how       = (insn_11_0 >> 5) & 3;
   2316       /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
   2317       IRTemp rMt = newTemp(Ity_I32);
   2318       assign(rMt, getIRegA(rM));
   2319 
   2320       vassert(shift_amt <= 31);
   2321 
   2322       compute_result_and_C_after_shift_by_imm5(
   2323          buf, shop, shco, rMt, how, shift_amt, rM
   2324       );
   2325       return True;
   2326    }
   2327 
   2328    /* Shift/rotate by register */
   2329    if (insn_25 == 0 && insn_4 == 1) {
   2330       /* Rm (3:0) shifted (6:5) by Rs (11:8) */
   2331       UInt rM  = (insn_11_0 >> 0) & 0xF;
   2332       UInt rS  = (insn_11_0 >> 8) & 0xF;
   2333       UInt how = (insn_11_0 >> 5) & 3;
   2334       /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
   2335       IRTemp rMt = newTemp(Ity_I32);
   2336       IRTemp rSt = newTemp(Ity_I32);
   2337 
   2338       if (insn_7 == 1)
   2339          return False; /* not really a shifter operand */
   2340 
   2341       assign(rMt, getIRegA(rM));
   2342       assign(rSt, getIRegA(rS));
   2343 
   2344       compute_result_and_C_after_shift_by_reg(
   2345          buf, shop, shco, rMt, how, rSt, rM, rS
   2346       );
   2347       return True;
   2348    }
   2349 
   2350    vex_printf("mk_shifter_operand(0x%x,0x%x)\n", insn_25, insn_11_0 );
   2351    return False;
   2352 }
   2353 
   2354 
   2355 /* ARM only */
   2356 static
   2357 IRExpr* mk_EA_reg_plusminus_imm12 ( UInt rN, UInt bU, UInt imm12,
   2358                                     /*OUT*/HChar* buf )
   2359 {
   2360    vassert(rN < 16);
   2361    vassert(bU < 2);
   2362    vassert(imm12 < 0x1000);
   2363    UChar opChar = bU == 1 ? '+' : '-';
   2364    DIS(buf, "[r%u, #%c%u]", rN, opChar, imm12);
   2365    return
   2366       binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
   2367              getIRegA(rN),
   2368              mkU32(imm12) );
   2369 }
   2370 
   2371 
   2372 /* ARM only.
   2373    NB: This is "DecodeImmShift" in newer versions of the the ARM ARM.
   2374 */
   2375 static
   2376 IRExpr* mk_EA_reg_plusminus_shifted_reg ( UInt rN, UInt bU, UInt rM,
   2377                                           UInt sh2, UInt imm5,
   2378                                           /*OUT*/HChar* buf )
   2379 {
   2380    vassert(rN < 16);
   2381    vassert(bU < 2);
   2382    vassert(rM < 16);
   2383    vassert(sh2 < 4);
   2384    vassert(imm5 < 32);
   2385    UChar   opChar = bU == 1 ? '+' : '-';
   2386    IRExpr* index  = NULL;
   2387    switch (sh2) {
   2388       case 0: /* LSL */
   2389          /* imm5 can be in the range 0 .. 31 inclusive. */
   2390          index = binop(Iop_Shl32, getIRegA(rM), mkU8(imm5));
   2391          DIS(buf, "[r%u, %c r%u LSL #%u]", rN, opChar, rM, imm5);
   2392          break;
   2393       case 1: /* LSR */
   2394          if (imm5 == 0) {
   2395             index = mkU32(0);
   2396             vassert(0); // ATC
   2397          } else {
   2398             index = binop(Iop_Shr32, getIRegA(rM), mkU8(imm5));
   2399          }
   2400          DIS(buf, "[r%u, %cr%u, LSR #%u]",
   2401                   rN, opChar, rM, imm5 == 0 ? 32 : imm5);
   2402          break;
   2403       case 2: /* ASR */
   2404          /* Doesn't this just mean that the behaviour with imm5 == 0
   2405             is the same as if it had been 31 ? */
   2406          if (imm5 == 0) {
   2407             index = binop(Iop_Sar32, getIRegA(rM), mkU8(31));
   2408             vassert(0); // ATC
   2409          } else {
   2410             index = binop(Iop_Sar32, getIRegA(rM), mkU8(imm5));
   2411          }
   2412          DIS(buf, "[r%u, %cr%u, ASR #%u]",
   2413                   rN, opChar, rM, imm5 == 0 ? 32 : imm5);
   2414          break;
   2415       case 3: /* ROR or RRX */
   2416          if (imm5 == 0) {
   2417             IRTemp rmT    = newTemp(Ity_I32);
   2418             IRTemp cflagT = newTemp(Ity_I32);
   2419             assign(rmT, getIRegA(rM));
   2420             assign(cflagT, mk_armg_calculate_flag_c());
   2421             index = binop(Iop_Or32,
   2422                           binop(Iop_Shl32, mkexpr(cflagT), mkU8(31)),
   2423                           binop(Iop_Shr32, mkexpr(rmT), mkU8(1)));
   2424             DIS(buf, "[r%u, %cr%u, RRX]", rN, opChar, rM);
   2425          } else {
   2426             IRTemp rmT = newTemp(Ity_I32);
   2427             assign(rmT, getIRegA(rM));
   2428             vassert(imm5 >= 1 && imm5 <= 31);
   2429             index = binop(Iop_Or32,
   2430                           binop(Iop_Shl32, mkexpr(rmT), mkU8(32-imm5)),
   2431                           binop(Iop_Shr32, mkexpr(rmT), mkU8(imm5)));
   2432             DIS(buf, "[r%u, %cr%u, ROR #%u]", rN, opChar, rM, imm5);
   2433          }
   2434          break;
   2435       default:
   2436          vassert(0);
   2437    }
   2438    vassert(index);
   2439    return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   2440                 getIRegA(rN), index);
   2441 }
   2442 
   2443 
   2444 /* ARM only */
   2445 static
   2446 IRExpr* mk_EA_reg_plusminus_imm8 ( UInt rN, UInt bU, UInt imm8,
   2447                                    /*OUT*/HChar* buf )
   2448 {
   2449    vassert(rN < 16);
   2450    vassert(bU < 2);
   2451    vassert(imm8 < 0x100);
   2452    UChar opChar = bU == 1 ? '+' : '-';
   2453    DIS(buf, "[r%u, #%c%u]", rN, opChar, imm8);
   2454    return
   2455       binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
   2456              getIRegA(rN),
   2457              mkU32(imm8) );
   2458 }
   2459 
   2460 
   2461 /* ARM only */
   2462 static
   2463 IRExpr* mk_EA_reg_plusminus_reg ( UInt rN, UInt bU, UInt rM,
   2464                                   /*OUT*/HChar* buf )
   2465 {
   2466    vassert(rN < 16);
   2467    vassert(bU < 2);
   2468    vassert(rM < 16);
   2469    UChar   opChar = bU == 1 ? '+' : '-';
   2470    IRExpr* index  = getIRegA(rM);
   2471    DIS(buf, "[r%u, %c r%u]", rN, opChar, rM);
   2472    return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   2473                 getIRegA(rN), index);
   2474 }
   2475 
   2476 
   2477 /* irRes :: Ity_I32 holds a floating point comparison result encoded
   2478    as an IRCmpF64Result.  Generate code to convert it to an
   2479    ARM-encoded (N,Z,C,V) group in the lowest 4 bits of an I32 value.
   2480    Assign a new temp to hold that value, and return the temp. */
   2481 static
   2482 IRTemp mk_convert_IRCmpF64Result_to_NZCV ( IRTemp irRes )
   2483 {
   2484    IRTemp ix       = newTemp(Ity_I32);
   2485    IRTemp termL    = newTemp(Ity_I32);
   2486    IRTemp termR    = newTemp(Ity_I32);
   2487    IRTemp nzcv     = newTemp(Ity_I32);
   2488 
   2489    /* This is where the fun starts.  We have to convert 'irRes' from
   2490       an IR-convention return result (IRCmpF64Result) to an
   2491       ARM-encoded (N,Z,C,V) group.  The final result is in the bottom
   2492       4 bits of 'nzcv'. */
   2493    /* Map compare result from IR to ARM(nzcv) */
   2494    /*
   2495       FP cmp result | IR   | ARM(nzcv)
   2496       --------------------------------
   2497       UN              0x45   0011
   2498       LT              0x01   1000
   2499       GT              0x00   0010
   2500       EQ              0x40   0110
   2501    */
   2502    /* Now since you're probably wondering WTF ..
   2503 
   2504       ix fishes the useful bits out of the IR value, bits 6 and 0, and
   2505       places them side by side, giving a number which is 0, 1, 2 or 3.
   2506 
   2507       termL is a sequence cooked up by GNU superopt.  It converts ix
   2508          into an almost correct value NZCV value (incredibly), except
   2509          for the case of UN, where it produces 0100 instead of the
   2510          required 0011.
   2511 
   2512       termR is therefore a correction term, also computed from ix.  It
   2513          is 1 in the UN case and 0 for LT, GT and UN.  Hence, to get
   2514          the final correct value, we subtract termR from termL.
   2515 
   2516       Don't take my word for it.  There's a test program at the bottom
   2517       of this file, to try this out with.
   2518    */
   2519    assign(
   2520       ix,
   2521       binop(Iop_Or32,
   2522             binop(Iop_And32,
   2523                   binop(Iop_Shr32, mkexpr(irRes), mkU8(5)),
   2524                   mkU32(3)),
   2525             binop(Iop_And32, mkexpr(irRes), mkU32(1))));
   2526 
   2527    assign(
   2528       termL,
   2529       binop(Iop_Add32,
   2530             binop(Iop_Shr32,
   2531                   binop(Iop_Sub32,
   2532                         binop(Iop_Shl32,
   2533                               binop(Iop_Xor32, mkexpr(ix), mkU32(1)),
   2534                               mkU8(30)),
   2535                         mkU32(1)),
   2536                   mkU8(29)),
   2537             mkU32(1)));
   2538 
   2539    assign(
   2540       termR,
   2541       binop(Iop_And32,
   2542             binop(Iop_And32,
   2543                   mkexpr(ix),
   2544                   binop(Iop_Shr32, mkexpr(ix), mkU8(1))),
   2545             mkU32(1)));
   2546 
   2547    assign(nzcv, binop(Iop_Sub32, mkexpr(termL), mkexpr(termR)));
   2548    return nzcv;
   2549 }
   2550 
   2551 
   2552 /* Thumb32 only.  This is "ThumbExpandImm" in the ARM ARM.  If
   2553    updatesC is non-NULL, a boolean is written to it indicating whether
   2554    or not the C flag is updated, as per ARM ARM "ThumbExpandImm_C".
   2555 */
   2556 static UInt thumbExpandImm ( Bool* updatesC,
   2557                              UInt imm1, UInt imm3, UInt imm8 )
   2558 {
   2559    vassert(imm1 < (1<<1));
   2560    vassert(imm3 < (1<<3));
   2561    vassert(imm8 < (1<<8));
   2562    UInt i_imm3_a = (imm1 << 4) | (imm3 << 1) | ((imm8 >> 7) & 1);
   2563    UInt abcdefgh = imm8;
   2564    UInt lbcdefgh = imm8 | 0x80;
   2565    if (updatesC) {
   2566       *updatesC = i_imm3_a >= 8;
   2567    }
   2568    switch (i_imm3_a) {
   2569       case 0: case 1:
   2570          return abcdefgh;
   2571       case 2: case 3:
   2572          return (abcdefgh << 16) | abcdefgh;
   2573       case 4: case 5:
   2574          return (abcdefgh << 24) | (abcdefgh << 8);
   2575       case 6: case 7:
   2576          return (abcdefgh << 24) | (abcdefgh << 16)
   2577                 | (abcdefgh << 8) | abcdefgh;
   2578       case 8 ... 31:
   2579          return lbcdefgh << (32 - i_imm3_a);
   2580       default:
   2581          break;
   2582    }
   2583    /*NOTREACHED*/vassert(0);
   2584 }
   2585 
   2586 
   2587 /* Version of thumbExpandImm where we simply feed it the
   2588    instruction halfwords (the lowest addressed one is I0). */
   2589 static UInt thumbExpandImm_from_I0_I1 ( Bool* updatesC,
   2590                                         UShort i0s, UShort i1s )
   2591 {
   2592    UInt i0    = (UInt)i0s;
   2593    UInt i1    = (UInt)i1s;
   2594    UInt imm1  = SLICE_UInt(i0,10,10);
   2595    UInt imm3  = SLICE_UInt(i1,14,12);
   2596    UInt imm8  = SLICE_UInt(i1,7,0);
   2597    return thumbExpandImm(updatesC, imm1, imm3, imm8);
   2598 }
   2599 
   2600 
   2601 /* Thumb16 only.  Given the firstcond and mask fields from an IT
   2602    instruction, compute the 32-bit ITSTATE value implied, as described
   2603    in libvex_guest_arm.h.  This is not the ARM ARM representation.
   2604    Also produce the t/e chars for the 2nd, 3rd, 4th insns, for
   2605    disassembly printing.  Returns False if firstcond or mask
   2606    denote something invalid.
   2607 
   2608    The number and conditions for the instructions to be
   2609    conditionalised depend on firstcond and mask:
   2610 
   2611    mask      cond 1    cond 2      cond 3      cond 4
   2612 
   2613    1000      fc[3:0]
   2614    x100      fc[3:0]   fc[3:1]:x
   2615    xy10      fc[3:0]   fc[3:1]:x   fc[3:1]:y
   2616    xyz1      fc[3:0]   fc[3:1]:x   fc[3:1]:y   fc[3:1]:z
   2617 
   2618    The condition fields are assembled in *itstate backwards (cond 4 at
   2619    the top, cond 1 at the bottom).  Conditions are << 4'd and then
   2620    ^0xE'd, and those fields that correspond to instructions in the IT
   2621    block are tagged with a 1 bit.
   2622 */
   2623 static Bool compute_ITSTATE ( /*OUT*/UInt*  itstate,
   2624                               /*OUT*/UChar* ch1,
   2625                               /*OUT*/UChar* ch2,
   2626                               /*OUT*/UChar* ch3,
   2627                               UInt firstcond, UInt mask )
   2628 {
   2629    vassert(firstcond <= 0xF);
   2630    vassert(mask <= 0xF);
   2631    *itstate = 0;
   2632    *ch1 = *ch2 = *ch3 = '.';
   2633    if (mask == 0)
   2634       return False; /* the logic below actually ensures this anyway,
   2635                        but clearer to make it explicit. */
   2636    if (firstcond == 0xF)
   2637       return False; /* NV is not allowed */
   2638    if (firstcond == 0xE && popcount32(mask) != 1)
   2639       return False; /* if firstcond is AL then all the rest must be too */
   2640 
   2641    UInt m3 = (mask >> 3) & 1;
   2642    UInt m2 = (mask >> 2) & 1;
   2643    UInt m1 = (mask >> 1) & 1;
   2644    UInt m0 = (mask >> 0) & 1;
   2645 
   2646    UInt fc = (firstcond << 4) | 1/*in-IT-block*/;
   2647    UInt ni = (0xE/*AL*/ << 4) | 0/*not-in-IT-block*/;
   2648 
   2649    if (m3 == 1 && (m2|m1|m0) == 0) {
   2650       *itstate = (ni << 24) | (ni << 16) | (ni << 8) | fc;
   2651       *itstate ^= 0xE0E0E0E0;
   2652       return True;
   2653    }
   2654 
   2655    if (m2 == 1 && (m1|m0) == 0) {
   2656       *itstate = (ni << 24) | (ni << 16) | (setbit32(fc, 4, m3) << 8) | fc;
   2657       *itstate ^= 0xE0E0E0E0;
   2658       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
   2659       return True;
   2660    }
   2661 
   2662    if (m1 == 1 && m0 == 0) {
   2663       *itstate = (ni << 24)
   2664                  | (setbit32(fc, 4, m2) << 16)
   2665                  | (setbit32(fc, 4, m3) << 8) | fc;
   2666       *itstate ^= 0xE0E0E0E0;
   2667       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
   2668       *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
   2669       return True;
   2670    }
   2671 
   2672    if (m0 == 1) {
   2673       *itstate = (setbit32(fc, 4, m1) << 24)
   2674                  | (setbit32(fc, 4, m2) << 16)
   2675                  | (setbit32(fc, 4, m3) << 8) | fc;
   2676       *itstate ^= 0xE0E0E0E0;
   2677       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
   2678       *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
   2679       *ch3 = m1 == (firstcond & 1) ? 't' : 'e';
   2680       return True;
   2681    }
   2682 
   2683    return False;
   2684 }
   2685 
   2686 
   2687 /* Generate IR to do 32-bit bit reversal, a la Hacker's Delight
   2688    Chapter 7 Section 1. */
   2689 static IRTemp gen_BITREV ( IRTemp x0 )
   2690 {
   2691    IRTemp x1 = newTemp(Ity_I32);
   2692    IRTemp x2 = newTemp(Ity_I32);
   2693    IRTemp x3 = newTemp(Ity_I32);
   2694    IRTemp x4 = newTemp(Ity_I32);
   2695    IRTemp x5 = newTemp(Ity_I32);
   2696    UInt   c1 = 0x55555555;
   2697    UInt   c2 = 0x33333333;
   2698    UInt   c3 = 0x0F0F0F0F;
   2699    UInt   c4 = 0x00FF00FF;
   2700    UInt   c5 = 0x0000FFFF;
   2701    assign(x1,
   2702           binop(Iop_Or32,
   2703                 binop(Iop_Shl32,
   2704                       binop(Iop_And32, mkexpr(x0), mkU32(c1)),
   2705                       mkU8(1)),
   2706                 binop(Iop_Shr32,
   2707                       binop(Iop_And32, mkexpr(x0), mkU32(~c1)),
   2708                       mkU8(1))
   2709    ));
   2710    assign(x2,
   2711           binop(Iop_Or32,
   2712                 binop(Iop_Shl32,
   2713                       binop(Iop_And32, mkexpr(x1), mkU32(c2)),
   2714                       mkU8(2)),
   2715                 binop(Iop_Shr32,
   2716                       binop(Iop_And32, mkexpr(x1), mkU32(~c2)),
   2717                       mkU8(2))
   2718    ));
   2719    assign(x3,
   2720           binop(Iop_Or32,
   2721                 binop(Iop_Shl32,
   2722                       binop(Iop_And32, mkexpr(x2), mkU32(c3)),
   2723                       mkU8(4)),
   2724                 binop(Iop_Shr32,
   2725                       binop(Iop_And32, mkexpr(x2), mkU32(~c3)),
   2726                       mkU8(4))
   2727    ));
   2728    assign(x4,
   2729           binop(Iop_Or32,
   2730                 binop(Iop_Shl32,
   2731                       binop(Iop_And32, mkexpr(x3), mkU32(c4)),
   2732                       mkU8(8)),
   2733                 binop(Iop_Shr32,
   2734                       binop(Iop_And32, mkexpr(x3), mkU32(~c4)),
   2735                       mkU8(8))
   2736    ));
   2737    assign(x5,
   2738           binop(Iop_Or32,
   2739                 binop(Iop_Shl32,
   2740                       binop(Iop_And32, mkexpr(x4), mkU32(c5)),
   2741                       mkU8(16)),
   2742                 binop(Iop_Shr32,
   2743                       binop(Iop_And32, mkexpr(x4), mkU32(~c5)),
   2744                       mkU8(16))
   2745    ));
   2746    return x5;
   2747 }
   2748 
   2749 
   2750 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
   2751    0:1:2:3 (aka byte-swap). */
   2752 static IRTemp gen_REV ( IRTemp arg )
   2753 {
   2754    IRTemp res = newTemp(Ity_I32);
   2755    assign(res,
   2756           binop(Iop_Or32,
   2757                 binop(Iop_Shl32, mkexpr(arg), mkU8(24)),
   2758           binop(Iop_Or32,
   2759                 binop(Iop_And32, binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
   2760                                  mkU32(0x00FF0000)),
   2761           binop(Iop_Or32,
   2762                 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
   2763                                        mkU32(0x0000FF00)),
   2764                 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(24)),
   2765                                        mkU32(0x000000FF) )
   2766    ))));
   2767    return res;
   2768 }
   2769 
   2770 
   2771 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
   2772    2:3:0:1 (swap within lo and hi halves). */
   2773 static IRTemp gen_REV16 ( IRTemp arg )
   2774 {
   2775    IRTemp res = newTemp(Ity_I32);
   2776    assign(res,
   2777           binop(Iop_Or32,
   2778                 binop(Iop_And32,
   2779                       binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
   2780                       mkU32(0xFF00FF00)),
   2781                 binop(Iop_And32,
   2782                       binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
   2783                       mkU32(0x00FF00FF))));
   2784    return res;
   2785 }
   2786 
   2787 
   2788 /*------------------------------------------------------------*/
   2789 /*--- Advanced SIMD (NEON) instructions                    ---*/
   2790 /*------------------------------------------------------------*/
   2791 
   2792 /*------------------------------------------------------------*/
   2793 /*--- NEON data processing                                 ---*/
   2794 /*------------------------------------------------------------*/
   2795 
   2796 /* For all NEON DP ops, we use the normal scheme to handle conditional
   2797    writes to registers -- pass in condT and hand that on to the
   2798    put*Reg functions.  In ARM mode condT is always IRTemp_INVALID
   2799    since NEON is unconditional for ARM.  In Thumb mode condT is
   2800    derived from the ITSTATE shift register in the normal way. */
   2801 
   2802 static
   2803 UInt get_neon_d_regno(UInt theInstr)
   2804 {
   2805    UInt x = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   2806    if (theInstr & 0x40) {
   2807       if (x & 1) {
   2808          x = x + 0x100;
   2809       } else {
   2810          x = x >> 1;
   2811       }
   2812    }
   2813    return x;
   2814 }
   2815 
   2816 static
   2817 UInt get_neon_n_regno(UInt theInstr)
   2818 {
   2819    UInt x = ((theInstr >> 3) & 0x10) | ((theInstr >> 16) & 0xF);
   2820    if (theInstr & 0x40) {
   2821       if (x & 1) {
   2822          x = x + 0x100;
   2823       } else {
   2824          x = x >> 1;
   2825       }
   2826    }
   2827    return x;
   2828 }
   2829 
   2830 static
   2831 UInt get_neon_m_regno(UInt theInstr)
   2832 {
   2833    UInt x = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   2834    if (theInstr & 0x40) {
   2835       if (x & 1) {
   2836          x = x + 0x100;
   2837       } else {
   2838          x = x >> 1;
   2839       }
   2840    }
   2841    return x;
   2842 }
   2843 
   2844 static
   2845 Bool dis_neon_vext ( UInt theInstr, IRTemp condT )
   2846 {
   2847    UInt dreg = get_neon_d_regno(theInstr);
   2848    UInt mreg = get_neon_m_regno(theInstr);
   2849    UInt nreg = get_neon_n_regno(theInstr);
   2850    UInt imm4 = (theInstr >> 8) & 0xf;
   2851    UInt Q = (theInstr >> 6) & 1;
   2852    HChar reg_t = Q ? 'q' : 'd';
   2853 
   2854    if (Q) {
   2855       putQReg(dreg, triop(Iop_ExtractV128, getQReg(nreg),
   2856                getQReg(mreg), mkU8(imm4)), condT);
   2857    } else {
   2858       putDRegI64(dreg, triop(Iop_Extract64, getDRegI64(nreg),
   2859                  getDRegI64(mreg), mkU8(imm4)), condT);
   2860    }
   2861    DIP("vext.8 %c%d, %c%d, %c%d, #%d\n", reg_t, dreg, reg_t, nreg,
   2862                                          reg_t, mreg, imm4);
   2863    return True;
   2864 }
   2865 
   2866 /* VTBL, VTBX */
   2867 static
   2868 Bool dis_neon_vtb ( UInt theInstr, IRTemp condT )
   2869 {
   2870    UInt op = (theInstr >> 6) & 1;
   2871    UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
   2872    UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
   2873    UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
   2874    UInt len = (theInstr >> 8) & 3;
   2875    Int i;
   2876    IROp cmp;
   2877    ULong imm;
   2878    IRTemp arg_l;
   2879    IRTemp old_mask, new_mask, cur_mask;
   2880    IRTemp old_res, new_res;
   2881    IRTemp old_arg, new_arg;
   2882 
   2883    if (dreg >= 0x100 || mreg >= 0x100 || nreg >= 0x100)
   2884       return False;
   2885    if (nreg + len > 31)
   2886       return False;
   2887 
   2888    cmp = Iop_CmpGT8Ux8;
   2889 
   2890    old_mask = newTemp(Ity_I64);
   2891    old_res = newTemp(Ity_I64);
   2892    old_arg = newTemp(Ity_I64);
   2893    assign(old_mask, mkU64(0));
   2894    assign(old_res, mkU64(0));
   2895    assign(old_arg, getDRegI64(mreg));
   2896    imm = 8;
   2897    imm = (imm <<  8) | imm;
   2898    imm = (imm << 16) | imm;
   2899    imm = (imm << 32) | imm;
   2900 
   2901    for (i = 0; i <= len; i++) {
   2902       arg_l = newTemp(Ity_I64);
   2903       new_mask = newTemp(Ity_I64);
   2904       cur_mask = newTemp(Ity_I64);
   2905       new_res = newTemp(Ity_I64);
   2906       new_arg = newTemp(Ity_I64);
   2907       assign(arg_l, getDRegI64(nreg+i));
   2908       assign(new_arg, binop(Iop_Sub8x8, mkexpr(old_arg), mkU64(imm)));
   2909       assign(cur_mask, binop(cmp, mkU64(imm), mkexpr(old_arg)));
   2910       assign(new_mask, binop(Iop_Or64, mkexpr(old_mask), mkexpr(cur_mask)));
   2911       assign(new_res, binop(Iop_Or64,
   2912                             mkexpr(old_res),
   2913                             binop(Iop_And64,
   2914                                   binop(Iop_Perm8x8,
   2915                                         mkexpr(arg_l),
   2916                                         binop(Iop_And64,
   2917                                               mkexpr(old_arg),
   2918                                               mkexpr(cur_mask))),
   2919                                   mkexpr(cur_mask))));
   2920 
   2921       old_arg = new_arg;
   2922       old_mask = new_mask;
   2923       old_res = new_res;
   2924    }
   2925    if (op) {
   2926       new_res = newTemp(Ity_I64);
   2927       assign(new_res, binop(Iop_Or64,
   2928                             binop(Iop_And64,
   2929                                   getDRegI64(dreg),
   2930                                   unop(Iop_Not64, mkexpr(old_mask))),
   2931                             mkexpr(old_res)));
   2932       old_res = new_res;
   2933    }
   2934 
   2935    putDRegI64(dreg, mkexpr(old_res), condT);
   2936    DIP("vtb%c.8 d%u, {", op ? 'x' : 'l', dreg);
   2937    if (len > 0) {
   2938       DIP("d%u-d%u", nreg, nreg + len);
   2939    } else {
   2940       DIP("d%u", nreg);
   2941    }
   2942    DIP("}, d%u\n", mreg);
   2943    return True;
   2944 }
   2945 
   2946 /* VDUP (scalar)  */
   2947 static
   2948 Bool dis_neon_vdup ( UInt theInstr, IRTemp condT )
   2949 {
   2950    UInt Q = (theInstr >> 6) & 1;
   2951    UInt dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   2952    UInt mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   2953    UInt imm4 = (theInstr >> 16) & 0xF;
   2954    UInt index;
   2955    UInt size;
   2956    IRTemp arg_m;
   2957    IRTemp res;
   2958    IROp op, op2;
   2959 
   2960    if ((imm4 == 0) || (imm4 == 8))
   2961       return False;
   2962    if ((Q == 1) && ((dreg & 1) == 1))
   2963       return False;
   2964    if (Q)
   2965       dreg >>= 1;
   2966    arg_m = newTemp(Ity_I64);
   2967    assign(arg_m, getDRegI64(mreg));
   2968    if (Q)
   2969       res = newTemp(Ity_V128);
   2970    else
   2971       res = newTemp(Ity_I64);
   2972    if ((imm4 & 1) == 1) {
   2973       op = Q ? Iop_Dup8x16 : Iop_Dup8x8;
   2974       op2 = Iop_GetElem8x8;
   2975       index = imm4 >> 1;
   2976       size = 8;
   2977    } else if ((imm4 & 3) == 2) {
   2978       op = Q ? Iop_Dup16x8 : Iop_Dup16x4;
   2979       op2 = Iop_GetElem16x4;
   2980       index = imm4 >> 2;
   2981       size = 16;
   2982    } else if ((imm4 & 7) == 4) {
   2983       op = Q ? Iop_Dup32x4 : Iop_Dup32x2;
   2984       op2 = Iop_GetElem32x2;
   2985       index = imm4 >> 3;
   2986       size = 32;
   2987    } else {
   2988       return False; // can this ever happen?
   2989    }
   2990    assign(res, unop(op, binop(op2, mkexpr(arg_m), mkU8(index))));
   2991    if (Q) {
   2992       putQReg(dreg, mkexpr(res), condT);
   2993    } else {
   2994       putDRegI64(dreg, mkexpr(res), condT);
   2995    }
   2996    DIP("vdup.%d %c%d, d%d[%d]\n", size, Q ? 'q' : 'd', dreg, mreg, index);
   2997    return True;
   2998 }
   2999 
   3000 /* A7.4.1 Three registers of the same length */
   3001 static
   3002 Bool dis_neon_data_3same ( UInt theInstr, IRTemp condT )
   3003 {
   3004    UInt Q = (theInstr >> 6) & 1;
   3005    UInt dreg = get_neon_d_regno(theInstr);
   3006    UInt nreg = get_neon_n_regno(theInstr);
   3007    UInt mreg = get_neon_m_regno(theInstr);
   3008    UInt A = (theInstr >> 8) & 0xF;
   3009    UInt B = (theInstr >> 4) & 1;
   3010    UInt C = (theInstr >> 20) & 0x3;
   3011    UInt U = (theInstr >> 24) & 1;
   3012    UInt size = C;
   3013 
   3014    IRTemp arg_n;
   3015    IRTemp arg_m;
   3016    IRTemp res;
   3017 
   3018    if (Q) {
   3019       arg_n = newTemp(Ity_V128);
   3020       arg_m = newTemp(Ity_V128);
   3021       res = newTemp(Ity_V128);
   3022       assign(arg_n, getQReg(nreg));
   3023       assign(arg_m, getQReg(mreg));
   3024    } else {
   3025       arg_n = newTemp(Ity_I64);
   3026       arg_m = newTemp(Ity_I64);
   3027       res = newTemp(Ity_I64);
   3028       assign(arg_n, getDRegI64(nreg));
   3029       assign(arg_m, getDRegI64(mreg));
   3030    }
   3031 
   3032    switch(A) {
   3033       case 0:
   3034          if (B == 0) {
   3035             /* VHADD */
   3036             ULong imm = 0;
   3037             IRExpr *imm_val;
   3038             IROp addOp;
   3039             IROp andOp;
   3040             IROp shOp;
   3041             char regType = Q ? 'q' : 'd';
   3042 
   3043             if (size == 3)
   3044                return False;
   3045             switch(size) {
   3046                case 0: imm = 0x101010101010101LL; break;
   3047                case 1: imm = 0x1000100010001LL; break;
   3048                case 2: imm = 0x100000001LL; break;
   3049                default: vassert(0);
   3050             }
   3051             if (Q) {
   3052                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   3053                andOp = Iop_AndV128;
   3054             } else {
   3055                imm_val = mkU64(imm);
   3056                andOp = Iop_And64;
   3057             }
   3058             if (U) {
   3059                switch(size) {
   3060                   case 0:
   3061                      addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
   3062                      shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3063                      break;
   3064                   case 1:
   3065                      addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
   3066                      shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3067                      break;
   3068                   case 2:
   3069                      addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
   3070                      shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3071                      break;
   3072                   default:
   3073                      vassert(0);
   3074                }
   3075             } else {
   3076                switch(size) {
   3077                   case 0:
   3078                      addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
   3079                      shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
   3080                      break;
   3081                   case 1:
   3082                      addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
   3083                      shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
   3084                      break;
   3085                   case 2:
   3086                      addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
   3087                      shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
   3088                      break;
   3089                   default:
   3090                      vassert(0);
   3091                }
   3092             }
   3093             assign(res,
   3094                    binop(addOp,
   3095                          binop(addOp,
   3096                                binop(shOp, mkexpr(arg_m), mkU8(1)),
   3097                                binop(shOp, mkexpr(arg_n), mkU8(1))),
   3098                          binop(shOp,
   3099                                binop(addOp,
   3100                                      binop(andOp, mkexpr(arg_m), imm_val),
   3101                                      binop(andOp, mkexpr(arg_n), imm_val)),
   3102                                mkU8(1))));
   3103             DIP("vhadd.%c%d %c%d, %c%d, %c%d\n",
   3104                 U ? 'u' : 's', 8 << size, regType,
   3105                 dreg, regType, nreg, regType, mreg);
   3106          } else {
   3107             /* VQADD */
   3108             IROp op, op2;
   3109             IRTemp tmp;
   3110             char reg_t = Q ? 'q' : 'd';
   3111             if (Q) {
   3112                switch (size) {
   3113                   case 0:
   3114                      op = U ? Iop_QAdd8Ux16 : Iop_QAdd8Sx16;
   3115                      op2 = Iop_Add8x16;
   3116                      break;
   3117                   case 1:
   3118                      op = U ? Iop_QAdd16Ux8 : Iop_QAdd16Sx8;
   3119                      op2 = Iop_Add16x8;
   3120                      break;
   3121                   case 2:
   3122                      op = U ? Iop_QAdd32Ux4 : Iop_QAdd32Sx4;
   3123                      op2 = Iop_Add32x4;
   3124                      break;
   3125                   case 3:
   3126                      op = U ? Iop_QAdd64Ux2 : Iop_QAdd64Sx2;
   3127                      op2 = Iop_Add64x2;
   3128                      break;
   3129                   default:
   3130                      vassert(0);
   3131                }
   3132             } else {
   3133                switch (size) {
   3134                   case 0:
   3135                      op = U ? Iop_QAdd8Ux8 : Iop_QAdd8Sx8;
   3136                      op2 = Iop_Add8x8;
   3137                      break;
   3138                   case 1:
   3139                      op = U ? Iop_QAdd16Ux4 : Iop_QAdd16Sx4;
   3140                      op2 = Iop_Add16x4;
   3141                      break;
   3142                   case 2:
   3143                      op = U ? Iop_QAdd32Ux2 : Iop_QAdd32Sx2;
   3144                      op2 = Iop_Add32x2;
   3145                      break;
   3146                   case 3:
   3147                      op = U ? Iop_QAdd64Ux1 : Iop_QAdd64Sx1;
   3148                      op2 = Iop_Add64;
   3149                      break;
   3150                   default:
   3151                      vassert(0);
   3152                }
   3153             }
   3154             if (Q) {
   3155                tmp = newTemp(Ity_V128);
   3156             } else {
   3157                tmp = newTemp(Ity_I64);
   3158             }
   3159             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   3160 #ifndef DISABLE_QC_FLAG
   3161             assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
   3162             setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
   3163 #endif
   3164             DIP("vqadd.%c%d %c%d, %c%d, %c%d\n",
   3165                 U ? 'u' : 's',
   3166                 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3167          }
   3168          break;
   3169       case 1:
   3170          if (B == 0) {
   3171             /* VRHADD */
   3172             /* VRHADD C, A, B ::=
   3173                  C = (A >> 1) + (B >> 1) + (((A & 1) + (B & 1) + 1) >> 1) */
   3174             IROp shift_op, add_op;
   3175             IRTemp cc;
   3176             ULong one = 1;
   3177             HChar reg_t = Q ? 'q' : 'd';
   3178             switch (size) {
   3179                case 0: one = (one <<  8) | one; /* fall through */
   3180                case 1: one = (one << 16) | one; /* fall through */
   3181                case 2: one = (one << 32) | one; break;
   3182                case 3: return False;
   3183                default: vassert(0);
   3184             }
   3185             if (Q) {
   3186                switch (size) {
   3187                   case 0:
   3188                      shift_op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
   3189                      add_op = Iop_Add8x16;
   3190                      break;
   3191                   case 1:
   3192                      shift_op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   3193                      add_op = Iop_Add16x8;
   3194                      break;
   3195                   case 2:
   3196                      shift_op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   3197                      add_op = Iop_Add32x4;
   3198                      break;
   3199                   case 3:
   3200                      return False;
   3201                   default:
   3202                      vassert(0);
   3203                }
   3204             } else {
   3205                switch (size) {
   3206                   case 0:
   3207                      shift_op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
   3208                      add_op = Iop_Add8x8;
   3209                      break;
   3210                   case 1:
   3211                      shift_op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
   3212                      add_op = Iop_Add16x4;
   3213                      break;
   3214                   case 2:
   3215                      shift_op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
   3216                      add_op = Iop_Add32x2;
   3217                      break;
   3218                   case 3:
   3219                      return False;
   3220                   default:
   3221                      vassert(0);
   3222                }
   3223             }
   3224             if (Q) {
   3225                cc = newTemp(Ity_V128);
   3226                assign(cc, binop(shift_op,
   3227                                 binop(add_op,
   3228                                       binop(add_op,
   3229                                             binop(Iop_AndV128,
   3230                                                   mkexpr(arg_n),
   3231                                                   binop(Iop_64HLtoV128,
   3232                                                         mkU64(one),
   3233                                                         mkU64(one))),
   3234                                             binop(Iop_AndV128,
   3235                                                   mkexpr(arg_m),
   3236                                                   binop(Iop_64HLtoV128,
   3237                                                         mkU64(one),
   3238                                                         mkU64(one)))),
   3239                                       binop(Iop_64HLtoV128,
   3240                                             mkU64(one),
   3241                                             mkU64(one))),
   3242                                 mkU8(1)));
   3243                assign(res, binop(add_op,
   3244                                  binop(add_op,
   3245                                        binop(shift_op,
   3246                                              mkexpr(arg_n),
   3247                                              mkU8(1)),
   3248                                        binop(shift_op,
   3249                                              mkexpr(arg_m),
   3250                                              mkU8(1))),
   3251                                  mkexpr(cc)));
   3252             } else {
   3253                cc = newTemp(Ity_I64);
   3254                assign(cc, binop(shift_op,
   3255                                 binop(add_op,
   3256                                       binop(add_op,
   3257                                             binop(Iop_And64,
   3258                                                   mkexpr(arg_n),
   3259                                                   mkU64(one)),
   3260                                             binop(Iop_And64,
   3261                                                   mkexpr(arg_m),
   3262                                                   mkU64(one))),
   3263                                       mkU64(one)),
   3264                                 mkU8(1)));
   3265                assign(res, binop(add_op,
   3266                                  binop(add_op,
   3267                                        binop(shift_op,
   3268                                              mkexpr(arg_n),
   3269                                              mkU8(1)),
   3270                                        binop(shift_op,
   3271                                              mkexpr(arg_m),
   3272                                              mkU8(1))),
   3273                                  mkexpr(cc)));
   3274             }
   3275             DIP("vrhadd.%c%d %c%d, %c%d, %c%d\n",
   3276                 U ? 'u' : 's',
   3277                 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3278          } else {
   3279             if (U == 0)  {
   3280                switch(C) {
   3281                   case 0: {
   3282                      /* VAND  */
   3283                      HChar reg_t = Q ? 'q' : 'd';
   3284                      if (Q) {
   3285                         assign(res, binop(Iop_AndV128, mkexpr(arg_n),
   3286                                                        mkexpr(arg_m)));
   3287                      } else {
   3288                         assign(res, binop(Iop_And64, mkexpr(arg_n),
   3289                                                      mkexpr(arg_m)));
   3290                      }
   3291                      DIP("vand %c%d, %c%d, %c%d\n",
   3292                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3293                      break;
   3294                   }
   3295                   case 1: {
   3296                      /* VBIC  */
   3297                      HChar reg_t = Q ? 'q' : 'd';
   3298                      if (Q) {
   3299                         assign(res, binop(Iop_AndV128,mkexpr(arg_n),
   3300                                unop(Iop_NotV128, mkexpr(arg_m))));
   3301                      } else {
   3302                         assign(res, binop(Iop_And64, mkexpr(arg_n),
   3303                                unop(Iop_Not64, mkexpr(arg_m))));
   3304                      }
   3305                      DIP("vbic %c%d, %c%d, %c%d\n",
   3306                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3307                      break;
   3308                   }
   3309                   case 2:
   3310                      if ( nreg != mreg) {
   3311                         /* VORR  */
   3312                         HChar reg_t = Q ? 'q' : 'd';
   3313                         if (Q) {
   3314                            assign(res, binop(Iop_OrV128, mkexpr(arg_n),
   3315                                                          mkexpr(arg_m)));
   3316                         } else {
   3317                            assign(res, binop(Iop_Or64, mkexpr(arg_n),
   3318                                                        mkexpr(arg_m)));
   3319                         }
   3320                         DIP("vorr %c%d, %c%d, %c%d\n",
   3321                             reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3322                      } else {
   3323                         /* VMOV  */
   3324                         HChar reg_t = Q ? 'q' : 'd';
   3325                         assign(res, mkexpr(arg_m));
   3326                         DIP("vmov %c%d, %c%d\n", reg_t, dreg, reg_t, mreg);
   3327                      }
   3328                      break;
   3329                   case 3:{
   3330                      /* VORN  */
   3331                      HChar reg_t = Q ? 'q' : 'd';
   3332                      if (Q) {
   3333                         assign(res, binop(Iop_OrV128,mkexpr(arg_n),
   3334                                unop(Iop_NotV128, mkexpr(arg_m))));
   3335                      } else {
   3336                         assign(res, binop(Iop_Or64, mkexpr(arg_n),
   3337                                unop(Iop_Not64, mkexpr(arg_m))));
   3338                      }
   3339                      DIP("vorn %c%d, %c%d, %c%d\n",
   3340                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3341                      break;
   3342                   }
   3343                }
   3344             } else {
   3345                switch(C) {
   3346                   case 0:
   3347                      /* VEOR (XOR)  */
   3348                      if (Q) {
   3349                         assign(res, binop(Iop_XorV128, mkexpr(arg_n),
   3350                                                        mkexpr(arg_m)));
   3351                      } else {
   3352                         assign(res, binop(Iop_Xor64, mkexpr(arg_n),
   3353                                                      mkexpr(arg_m)));
   3354                      }
   3355                      DIP("veor %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   3356                            Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3357                      break;
   3358                   case 1:
   3359                      /* VBSL  */
   3360                      if (Q) {
   3361                         IRTemp reg_d = newTemp(Ity_V128);
   3362                         assign(reg_d, getQReg(dreg));
   3363                         assign(res,
   3364                                binop(Iop_OrV128,
   3365                                      binop(Iop_AndV128, mkexpr(arg_n),
   3366                                                         mkexpr(reg_d)),
   3367                                      binop(Iop_AndV128,
   3368                                            mkexpr(arg_m),
   3369                                            unop(Iop_NotV128,
   3370                                                  mkexpr(reg_d)) ) ) );
   3371                      } else {
   3372                         IRTemp reg_d = newTemp(Ity_I64);
   3373                         assign(reg_d, getDRegI64(dreg));
   3374                         assign(res,
   3375                                binop(Iop_Or64,
   3376                                      binop(Iop_And64, mkexpr(arg_n),
   3377                                                       mkexpr(reg_d)),
   3378                                      binop(Iop_And64,
   3379                                            mkexpr(arg_m),
   3380                                            unop(Iop_Not64, mkexpr(reg_d)))));
   3381                      }
   3382                      DIP("vbsl %c%u, %c%u, %c%u\n",
   3383                          Q ? 'q' : 'd', dreg,
   3384                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3385                      break;
   3386                   case 2:
   3387                      /* VBIT  */
   3388                      if (Q) {
   3389                         IRTemp reg_d = newTemp(Ity_V128);
   3390                         assign(reg_d, getQReg(dreg));
   3391                         assign(res,
   3392                                binop(Iop_OrV128,
   3393                                      binop(Iop_AndV128, mkexpr(arg_n),
   3394                                                         mkexpr(arg_m)),
   3395                                      binop(Iop_AndV128,
   3396                                            mkexpr(reg_d),
   3397                                            unop(Iop_NotV128, mkexpr(arg_m)))));
   3398                      } else {
   3399                         IRTemp reg_d = newTemp(Ity_I64);
   3400                         assign(reg_d, getDRegI64(dreg));
   3401                         assign(res,
   3402                                binop(Iop_Or64,
   3403                                      binop(Iop_And64, mkexpr(arg_n),
   3404                                                       mkexpr(arg_m)),
   3405                                      binop(Iop_And64,
   3406                                            mkexpr(reg_d),
   3407                                            unop(Iop_Not64, mkexpr(arg_m)))));
   3408                      }
   3409                      DIP("vbit %c%u, %c%u, %c%u\n",
   3410                          Q ? 'q' : 'd', dreg,
   3411                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3412                      break;
   3413                   case 3:
   3414                      /* VBIF  */
   3415                      if (Q) {
   3416                         IRTemp reg_d = newTemp(Ity_V128);
   3417                         assign(reg_d, getQReg(dreg));
   3418                         assign(res,
   3419                                binop(Iop_OrV128,
   3420                                      binop(Iop_AndV128, mkexpr(reg_d),
   3421                                                         mkexpr(arg_m)),
   3422                                      binop(Iop_AndV128,
   3423                                            mkexpr(arg_n),
   3424                                            unop(Iop_NotV128, mkexpr(arg_m)))));
   3425                      } else {
   3426                         IRTemp reg_d = newTemp(Ity_I64);
   3427                         assign(reg_d, getDRegI64(dreg));
   3428                         assign(res,
   3429                                binop(Iop_Or64,
   3430                                      binop(Iop_And64, mkexpr(reg_d),
   3431                                                       mkexpr(arg_m)),
   3432                                      binop(Iop_And64,
   3433                                            mkexpr(arg_n),
   3434                                            unop(Iop_Not64, mkexpr(arg_m)))));
   3435                      }
   3436                      DIP("vbif %c%u, %c%u, %c%u\n",
   3437                          Q ? 'q' : 'd', dreg,
   3438                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3439                      break;
   3440                }
   3441             }
   3442          }
   3443          break;
   3444       case 2:
   3445          if (B == 0) {
   3446             /* VHSUB */
   3447             /* (A >> 1) - (B >> 1) - (NOT (A) & B & 1)   */
   3448             ULong imm = 0;
   3449             IRExpr *imm_val;
   3450             IROp subOp;
   3451             IROp notOp;
   3452             IROp andOp;
   3453             IROp shOp;
   3454             if (size == 3)
   3455                return False;
   3456             switch(size) {
   3457                case 0: imm = 0x101010101010101LL; break;
   3458                case 1: imm = 0x1000100010001LL; break;
   3459                case 2: imm = 0x100000001LL; break;
   3460                default: vassert(0);
   3461             }
   3462             if (Q) {
   3463                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   3464                andOp = Iop_AndV128;
   3465                notOp = Iop_NotV128;
   3466             } else {
   3467                imm_val = mkU64(imm);
   3468                andOp = Iop_And64;
   3469                notOp = Iop_Not64;
   3470             }
   3471             if (U) {
   3472                switch(size) {
   3473                   case 0:
   3474                      subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3475                      shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3476                      break;
   3477                   case 1:
   3478                      subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3479                      shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3480                      break;
   3481                   case 2:
   3482                      subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3483                      shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3484                      break;
   3485                   default:
   3486                      vassert(0);
   3487                }
   3488             } else {
   3489                switch(size) {
   3490                   case 0:
   3491                      subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3492                      shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
   3493                      break;
   3494                   case 1:
   3495                      subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3496                      shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
   3497                      break;
   3498                   case 2:
   3499                      subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3500                      shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
   3501                      break;
   3502                   default:
   3503                      vassert(0);
   3504                }
   3505             }
   3506             assign(res,
   3507                    binop(subOp,
   3508                          binop(subOp,
   3509                                binop(shOp, mkexpr(arg_n), mkU8(1)),
   3510                                binop(shOp, mkexpr(arg_m), mkU8(1))),
   3511                          binop(andOp,
   3512                                binop(andOp,
   3513                                      unop(notOp, mkexpr(arg_n)),
   3514                                      mkexpr(arg_m)),
   3515                                imm_val)));
   3516             DIP("vhsub.%c%u %c%u, %c%u, %c%u\n",
   3517                 U ? 'u' : 's', 8 << size,
   3518                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3519                 mreg);
   3520          } else {
   3521             /* VQSUB */
   3522             IROp op, op2;
   3523             IRTemp tmp;
   3524             if (Q) {
   3525                switch (size) {
   3526                   case 0:
   3527                      op = U ? Iop_QSub8Ux16 : Iop_QSub8Sx16;
   3528                      op2 = Iop_Sub8x16;
   3529                      break;
   3530                   case 1:
   3531                      op = U ? Iop_QSub16Ux8 : Iop_QSub16Sx8;
   3532                      op2 = Iop_Sub16x8;
   3533                      break;
   3534                   case 2:
   3535                      op = U ? Iop_QSub32Ux4 : Iop_QSub32Sx4;
   3536                      op2 = Iop_Sub32x4;
   3537                      break;
   3538                   case 3:
   3539                      op = U ? Iop_QSub64Ux2 : Iop_QSub64Sx2;
   3540                      op2 = Iop_Sub64x2;
   3541                      break;
   3542                   default:
   3543                      vassert(0);
   3544                }
   3545             } else {
   3546                switch (size) {
   3547                   case 0:
   3548                      op = U ? Iop_QSub8Ux8 : Iop_QSub8Sx8;
   3549                      op2 = Iop_Sub8x8;
   3550                      break;
   3551                   case 1:
   3552                      op = U ? Iop_QSub16Ux4 : Iop_QSub16Sx4;
   3553                      op2 = Iop_Sub16x4;
   3554                      break;
   3555                   case 2:
   3556                      op = U ? Iop_QSub32Ux2 : Iop_QSub32Sx2;
   3557                      op2 = Iop_Sub32x2;
   3558                      break;
   3559                   case 3:
   3560                      op = U ? Iop_QSub64Ux1 : Iop_QSub64Sx1;
   3561                      op2 = Iop_Sub64;
   3562                      break;
   3563                   default:
   3564                      vassert(0);
   3565                }
   3566             }
   3567             if (Q)
   3568                tmp = newTemp(Ity_V128);
   3569             else
   3570                tmp = newTemp(Ity_I64);
   3571             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   3572 #ifndef DISABLE_QC_FLAG
   3573             assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
   3574             setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
   3575 #endif
   3576             DIP("vqsub.%c%u %c%u, %c%u, %c%u\n",
   3577                 U ? 'u' : 's', 8 << size,
   3578                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3579                 mreg);
   3580          }
   3581          break;
   3582       case 3: {
   3583             IROp op;
   3584             if (Q) {
   3585                switch (size) {
   3586                   case 0: op = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; break;
   3587                   case 1: op = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; break;
   3588                   case 2: op = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; break;
   3589                   case 3: return False;
   3590                   default: vassert(0);
   3591                }
   3592             } else {
   3593                switch (size) {
   3594                   case 0: op = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; break;
   3595                   case 1: op = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; break;
   3596                   case 2: op = U ? Iop_CmpGT32Ux2: Iop_CmpGT32Sx2; break;
   3597                   case 3: return False;
   3598                   default: vassert(0);
   3599                }
   3600             }
   3601             if (B == 0) {
   3602                /* VCGT  */
   3603                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   3604                DIP("vcgt.%c%u %c%u, %c%u, %c%u\n",
   3605                    U ? 'u' : 's', 8 << size,
   3606                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3607                    mreg);
   3608             } else {
   3609                /* VCGE  */
   3610                /* VCGE res, argn, argm
   3611                     is equal to
   3612                   VCGT tmp, argm, argn
   3613                   VNOT res, tmp */
   3614                assign(res,
   3615                       unop(Q ? Iop_NotV128 : Iop_Not64,
   3616                            binop(op, mkexpr(arg_m), mkexpr(arg_n))));
   3617                DIP("vcge.%c%u %c%u, %c%u, %c%u\n",
   3618                    U ? 'u' : 's', 8 << size,
   3619                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3620                    mreg);
   3621             }
   3622          }
   3623          break;
   3624       case 4:
   3625          if (B == 0) {
   3626             /* VSHL */
   3627             IROp op, sub_op;
   3628             IRTemp tmp;
   3629             if (U) {
   3630                switch (size) {
   3631                   case 0: op = Q ? Iop_Shl8x16 : Iop_Shl8x8; break;
   3632                   case 1: op = Q ? Iop_Shl16x8 : Iop_Shl16x4; break;
   3633                   case 2: op = Q ? Iop_Shl32x4 : Iop_Shl32x2; break;
   3634                   case 3: op = Q ? Iop_Shl64x2 : Iop_Shl64; break;
   3635                   default: vassert(0);
   3636                }
   3637             } else {
   3638                tmp = newTemp(Q ? Ity_V128 : Ity_I64);
   3639                switch (size) {
   3640                   case 0:
   3641                      op = Q ? Iop_Sar8x16 : Iop_Sar8x8;
   3642                      sub_op = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3643                      break;
   3644                   case 1:
   3645                      op = Q ? Iop_Sar16x8 : Iop_Sar16x4;
   3646                      sub_op = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3647                      break;
   3648                   case 2:
   3649                      op = Q ? Iop_Sar32x4 : Iop_Sar32x2;
   3650                      sub_op = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3651                      break;
   3652                   case 3:
   3653                      op = Q ? Iop_Sar64x2 : Iop_Sar64;
   3654                      sub_op = Q ? Iop_Sub64x2 : Iop_Sub64;
   3655                      break;
   3656                   default:
   3657                      vassert(0);
   3658                }
   3659             }
   3660             if (U) {
   3661                if (!Q && (size == 3))
   3662                   assign(res, binop(op, mkexpr(arg_m),
   3663                                         unop(Iop_64to8, mkexpr(arg_n))));
   3664                else
   3665                   assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
   3666             } else {
   3667                if (Q)
   3668                   assign(tmp, binop(sub_op,
   3669                                     binop(Iop_64HLtoV128, mkU64(0), mkU64(0)),
   3670                                     mkexpr(arg_n)));
   3671                else
   3672                   assign(tmp, binop(sub_op, mkU64(0), mkexpr(arg_n)));
   3673                if (!Q && (size == 3))
   3674                   assign(res, binop(op, mkexpr(arg_m),
   3675                                         unop(Iop_64to8, mkexpr(tmp))));
   3676                else
   3677                   assign(res, binop(op, mkexpr(arg_m), mkexpr(tmp)));
   3678             }
   3679             DIP("vshl.%c%u %c%u, %c%u, %c%u\n",
   3680                 U ? 'u' : 's', 8 << size,
   3681                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   3682                 nreg);
   3683          } else {
   3684             /* VQSHL */
   3685             IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt;
   3686             IRTemp tmp, shval, mask, old_shval;
   3687             UInt i;
   3688             ULong esize;
   3689             cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
   3690             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   3691             if (U) {
   3692                switch (size) {
   3693                   case 0:
   3694                      op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
   3695                      op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
   3696                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3697                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3698                      break;
   3699                   case 1:
   3700                      op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
   3701                      op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
   3702                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3703                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3704                      break;
   3705                   case 2:
   3706                      op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
   3707                      op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
   3708                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3709                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3710                      break;
   3711                   case 3:
   3712                      op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
   3713                      op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
   3714                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3715                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3716                      break;
   3717                   default:
   3718                      vassert(0);
   3719                }
   3720             } else {
   3721                switch (size) {
   3722                   case 0:
   3723                      op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
   3724                      op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
   3725                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3726                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3727                      break;
   3728                   case 1:
   3729                      op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
   3730                      op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
   3731                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3732                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3733                      break;
   3734                   case 2:
   3735                      op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
   3736                      op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
   3737                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3738                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3739                      break;
   3740                   case 3:
   3741                      op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
   3742                      op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
   3743                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3744                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3745                      break;
   3746                   default:
   3747                      vassert(0);
   3748                }
   3749             }
   3750             if (Q) {
   3751                tmp = newTemp(Ity_V128);
   3752                shval = newTemp(Ity_V128);
   3753                mask = newTemp(Ity_V128);
   3754             } else {
   3755                tmp = newTemp(Ity_I64);
   3756                shval = newTemp(Ity_I64);
   3757                mask = newTemp(Ity_I64);
   3758             }
   3759             assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
   3760 #ifndef DISABLE_QC_FLAG
   3761             /* Only least significant byte from second argument is used.
   3762                Copy this byte to the whole vector element. */
   3763             assign(shval, binop(op_shrn,
   3764                                 binop(op_shln,
   3765                                        mkexpr(arg_n),
   3766                                        mkU8((8 << size) - 8)),
   3767                                 mkU8((8 << size) - 8)));
   3768             for(i = 0; i < size; i++) {
   3769                old_shval = shval;
   3770                shval = newTemp(Q ? Ity_V128 : Ity_I64);
   3771                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
   3772                                    mkexpr(old_shval),
   3773                                    binop(op_shln,
   3774                                          mkexpr(old_shval),
   3775                                          mkU8(8 << i))));
   3776             }
   3777             /* If shift is greater or equal to the element size and
   3778                element is non-zero, then QC flag should be set. */
   3779             esize = (8 << size) - 1;
   3780             esize = (esize <<  8) | esize;
   3781             esize = (esize << 16) | esize;
   3782             esize = (esize << 32) | esize;
   3783             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   3784                              binop(cmp_gt, mkexpr(shval),
   3785                                            Q ? mkU128(esize) : mkU64(esize)),
   3786                              unop(cmp_neq, mkexpr(arg_m))),
   3787                        Q ? mkU128(0) : mkU64(0),
   3788                        Q, condT);
   3789             /* Othervise QC flag should be set if shift value is positive and
   3790                result beign rightshifted the same value is not equal to left
   3791                argument. */
   3792             assign(mask, binop(cmp_gt, mkexpr(shval),
   3793                                        Q ? mkU128(0) : mkU64(0)));
   3794             if (!Q && size == 3)
   3795                assign(tmp, binop(op_rev, mkexpr(res),
   3796                                          unop(Iop_64to8, mkexpr(arg_n))));
   3797             else
   3798                assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
   3799             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   3800                              mkexpr(tmp), mkexpr(mask)),
   3801                        binop(Q ? Iop_AndV128 : Iop_And64,
   3802                              mkexpr(arg_m), mkexpr(mask)),
   3803                        Q, condT);
   3804 #endif
   3805             DIP("vqshl.%c%u %c%u, %c%u, %c%u\n",
   3806                 U ? 'u' : 's', 8 << size,
   3807                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   3808                 nreg);
   3809          }
   3810          break;
   3811       case 5:
   3812          if (B == 0) {
   3813             /* VRSHL */
   3814             IROp op, op_shrn, op_shln, cmp_gt, op_add;
   3815             IRTemp shval, old_shval, imm_val, round;
   3816             UInt i;
   3817             ULong imm;
   3818             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   3819             imm = 1L;
   3820             switch (size) {
   3821                case 0: imm = (imm <<  8) | imm; /* fall through */
   3822                case 1: imm = (imm << 16) | imm; /* fall through */
   3823                case 2: imm = (imm << 32) | imm; /* fall through */
   3824                case 3: break;
   3825                default: vassert(0);
   3826             }
   3827             imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
   3828             round = newTemp(Q ? Ity_V128 : Ity_I64);
   3829             assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
   3830             if (U) {
   3831                switch (size) {
   3832                   case 0:
   3833                      op = Q ? Iop_Shl8x16 : Iop_Shl8x8;
   3834                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   3835                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3836                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3837                      break;
   3838                   case 1:
   3839                      op = Q ? Iop_Shl16x8 : Iop_Shl16x4;
   3840                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   3841                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3842                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3843                      break;
   3844                   case 2:
   3845                      op = Q ? Iop_Shl32x4 : Iop_Shl32x2;
   3846                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   3847                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3848                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3849                      break;
   3850                   case 3:
   3851                      op = Q ? Iop_Shl64x2 : Iop_Shl64;
   3852                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   3853                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3854                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3855                      break;
   3856                   default:
   3857                      vassert(0);
   3858                }
   3859             } else {
   3860                switch (size) {
   3861                   case 0:
   3862                      op = Q ? Iop_Sal8x16 : Iop_Sal8x8;
   3863                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   3864                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3865                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3866                      break;
   3867                   case 1:
   3868                      op = Q ? Iop_Sal16x8 : Iop_Sal16x4;
   3869                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   3870                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3871                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3872                      break;
   3873                   case 2:
   3874                      op = Q ? Iop_Sal32x4 : Iop_Sal32x2;
   3875                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   3876                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3877                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3878                      break;
   3879                   case 3:
   3880                      op = Q ? Iop_Sal64x2 : Iop_Sal64x1;
   3881                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   3882                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3883                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3884                      break;
   3885                   default:
   3886                      vassert(0);
   3887                }
   3888             }
   3889             if (Q) {
   3890                shval = newTemp(Ity_V128);
   3891             } else {
   3892                shval = newTemp(Ity_I64);
   3893             }
   3894             /* Only least significant byte from second argument is used.
   3895                Copy this byte to the whole vector element. */
   3896             assign(shval, binop(op_shrn,
   3897                                 binop(op_shln,
   3898                                        mkexpr(arg_n),
   3899                                        mkU8((8 << size) - 8)),
   3900                                 mkU8((8 << size) - 8)));
   3901             for (i = 0; i < size; i++) {
   3902                old_shval = shval;
   3903                shval = newTemp(Q ? Ity_V128 : Ity_I64);
   3904                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
   3905                                    mkexpr(old_shval),
   3906                                    binop(op_shln,
   3907                                          mkexpr(old_shval),
   3908                                          mkU8(8 << i))));
   3909             }
   3910             /* Compute the result */
   3911             if (!Q && size == 3 && U) {
   3912                assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
   3913                                    binop(op,
   3914                                          mkexpr(arg_m),
   3915                                          unop(Iop_64to8,
   3916                                               binop(op_add,
   3917                                                     mkexpr(arg_n),
   3918                                                     mkexpr(imm_val)))),
   3919                                    binop(Q ? Iop_AndV128 : Iop_And64,
   3920                                          mkexpr(imm_val),
   3921                                          binop(cmp_gt,
   3922                                                Q ? mkU128(0) : mkU64(0),
   3923                                                mkexpr(arg_n)))));
   3924                assign(res, binop(op_add,
   3925                                  binop(op,
   3926                                        mkexpr(arg_m),
   3927                                        unop(Iop_64to8, mkexpr(arg_n))),
   3928                                  mkexpr(round)));
   3929             } else {
   3930                assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
   3931                                    binop(op,
   3932                                          mkexpr(arg_m),
   3933                                          binop(op_add,
   3934                                                mkexpr(arg_n),
   3935                                                mkexpr(imm_val))),
   3936                                    binop(Q ? Iop_AndV128 : Iop_And64,
   3937                                          mkexpr(imm_val),
   3938                                          binop(cmp_gt,
   3939                                                Q ? mkU128(0) : mkU64(0),
   3940                                                mkexpr(arg_n)))));
   3941                assign(res, binop(op_add,
   3942                                  binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   3943                                  mkexpr(round)));
   3944             }
   3945             DIP("vrshl.%c%u %c%u, %c%u, %c%u\n",
   3946                 U ? 'u' : 's', 8 << size,
   3947                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   3948                 nreg);
   3949          } else {
   3950             /* VQRSHL */
   3951             IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt, op_add;
   3952             IRTemp tmp, shval, mask, old_shval, imm_val, round;
   3953             UInt i;
   3954             ULong esize, imm;
   3955             cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
   3956             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   3957             imm = 1L;
   3958             switch (size) {
   3959                case 0: imm = (imm <<  8) | imm; /* fall through */
   3960                case 1: imm = (imm << 16) | imm; /* fall through */
   3961                case 2: imm = (imm << 32) | imm; /* fall through */
   3962                case 3: break;
   3963                default: vassert(0);
   3964             }
   3965             imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
   3966             round = newTemp(Q ? Ity_V128 : Ity_I64);
   3967             assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
   3968             if (U) {
   3969                switch (size) {
   3970                   case 0:
   3971                      op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
   3972                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   3973                      op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
   3974                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3975                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3976                      break;
   3977                   case 1:
   3978                      op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
   3979                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   3980                      op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
   3981                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3982                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3983                      break;
   3984                   case 2:
   3985                      op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
   3986                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   3987                      op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
   3988                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3989                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3990                      break;
   3991                   case 3:
   3992                      op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
   3993                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   3994                      op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
   3995                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3996                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3997                      break;
   3998                   default:
   3999                      vassert(0);
   4000                }
   4001             } else {
   4002                switch (size) {
   4003                   case 0:
   4004                      op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
   4005                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   4006                      op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
   4007                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   4008                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   4009                      break;
   4010                   case 1:
   4011                      op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
   4012                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   4013                      op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
   4014                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   4015                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   4016                      break;
   4017                   case 2:
   4018                      op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
   4019                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   4020                      op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
   4021                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   4022                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   4023                      break;
   4024                   case 3:
   4025                      op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
   4026                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   4027                      op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
   4028                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   4029                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   4030                      break;
   4031                   default:
   4032                      vassert(0);
   4033                }
   4034             }
   4035             if (Q) {
   4036                tmp = newTemp(Ity_V128);
   4037                shval = newTemp(Ity_V128);
   4038                mask = newTemp(Ity_V128);
   4039             } else {
   4040                tmp = newTemp(Ity_I64);
   4041                shval = newTemp(Ity_I64);
   4042                mask = newTemp(Ity_I64);
   4043             }
   4044             /* Only least significant byte from second argument is used.
   4045                Copy this byte to the whole vector element. */
   4046             assign(shval, binop(op_shrn,
   4047                                 binop(op_shln,
   4048                                        mkexpr(arg_n),
   4049                                        mkU8((8 << size) - 8)),
   4050                                 mkU8((8 << size) - 8)));
   4051             for (i = 0; i < size; i++) {
   4052                old_shval = shval;
   4053                shval = newTemp(Q ? Ity_V128 : Ity_I64);
   4054                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
   4055                                    mkexpr(old_shval),
   4056                                    binop(op_shln,
   4057                                          mkexpr(old_shval),
   4058                                          mkU8(8 << i))));
   4059             }
   4060             /* Compute the result */
   4061             assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
   4062                                 binop(op,
   4063                                       mkexpr(arg_m),
   4064                                       binop(op_add,
   4065                                             mkexpr(arg_n),
   4066                                             mkexpr(imm_val))),
   4067                                 binop(Q ? Iop_AndV128 : Iop_And64,
   4068                                       mkexpr(imm_val),
   4069                                       binop(cmp_gt,
   4070                                             Q ? mkU128(0) : mkU64(0),
   4071                                             mkexpr(arg_n)))));
   4072             assign(res, binop(op_add,
   4073                               binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   4074                               mkexpr(round)));
   4075 #ifndef DISABLE_QC_FLAG
   4076             /* If shift is greater or equal to the element size and element is
   4077                non-zero, then QC flag should be set. */
   4078             esize = (8 << size) - 1;
   4079             esize = (esize <<  8) | esize;
   4080             esize = (esize << 16) | esize;
   4081             esize = (esize << 32) | esize;
   4082             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4083                              binop(cmp_gt, mkexpr(shval),
   4084                                            Q ? mkU128(esize) : mkU64(esize)),
   4085                              unop(cmp_neq, mkexpr(arg_m))),
   4086                        Q ? mkU128(0) : mkU64(0),
   4087                        Q, condT);
   4088             /* Othervise QC flag should be set if shift value is positive and
   4089                result beign rightshifted the same value is not equal to left
   4090                argument. */
   4091             assign(mask, binop(cmp_gt, mkexpr(shval),
   4092                                Q ? mkU128(0) : mkU64(0)));
   4093             if (!Q && size == 3)
   4094                assign(tmp, binop(op_rev, mkexpr(res),
   4095                                          unop(Iop_64to8, mkexpr(arg_n))));
   4096             else
   4097                assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
   4098             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4099                              mkexpr(tmp), mkexpr(mask)),
   4100                        binop(Q ? Iop_AndV128 : Iop_And64,
   4101                              mkexpr(arg_m), mkexpr(mask)),
   4102                        Q, condT);
   4103 #endif
   4104             DIP("vqrshl.%c%u %c%u, %c%u, %c%u\n",
   4105                 U ? 'u' : 's', 8 << size,
   4106                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   4107                 nreg);
   4108          }
   4109          break;
   4110       case 6:
   4111          /* VMAX, VMIN  */
   4112          if (B == 0) {
   4113             /* VMAX */
   4114             IROp op;
   4115             if (U == 0) {
   4116                switch (size) {
   4117                   case 0: op = Q ? Iop_Max8Sx16 : Iop_Max8Sx8; break;
   4118                   case 1: op = Q ? Iop_Max16Sx8 : Iop_Max16Sx4; break;
   4119                   case 2: op = Q ? Iop_Max32Sx4 : Iop_Max32Sx2; break;
   4120                   case 3: return False;
   4121                   default: vassert(0);
   4122                }
   4123             } else {
   4124                switch (size) {
   4125                   case 0: op = Q ? Iop_Max8Ux16 : Iop_Max8Ux8; break;
   4126                   case 1: op = Q ? Iop_Max16Ux8 : Iop_Max16Ux4; break;
   4127                   case 2: op = Q ? Iop_Max32Ux4 : Iop_Max32Ux2; break;
   4128                   case 3: return False;
   4129                   default: vassert(0);
   4130                }
   4131             }
   4132             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4133             DIP("vmax.%c%u %c%u, %c%u, %c%u\n",
   4134                 U ? 'u' : 's', 8 << size,
   4135                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4136                 mreg);
   4137          } else {
   4138             /* VMIN */
   4139             IROp op;
   4140             if (U == 0) {
   4141                switch (size) {
   4142                   case 0: op = Q ? Iop_Min8Sx16 : Iop_Min8Sx8; break;
   4143                   case 1: op = Q ? Iop_Min16Sx8 : Iop_Min16Sx4; break;
   4144                   case 2: op = Q ? Iop_Min32Sx4 : Iop_Min32Sx2; break;
   4145                   case 3: return False;
   4146                   default: vassert(0);
   4147                }
   4148             } else {
   4149                switch (size) {
   4150                   case 0: op = Q ? Iop_Min8Ux16 : Iop_Min8Ux8; break;
   4151                   case 1: op = Q ? Iop_Min16Ux8 : Iop_Min16Ux4; break;
   4152                   case 2: op = Q ? Iop_Min32Ux4 : Iop_Min32Ux2; break;
   4153                   case 3: return False;
   4154                   default: vassert(0);
   4155                }
   4156             }
   4157             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4158             DIP("vmin.%c%u %c%u, %c%u, %c%u\n",
   4159                 U ? 'u' : 's', 8 << size,
   4160                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4161                 mreg);
   4162          }
   4163          break;
   4164       case 7:
   4165          if (B == 0) {
   4166             /* VABD */
   4167             IROp op_cmp, op_sub;
   4168             IRTemp cond;
   4169             if ((theInstr >> 23) & 1) {
   4170                vpanic("VABDL should not be in dis_neon_data_3same\n");
   4171             }
   4172             if (Q) {
   4173                switch (size) {
   4174                   case 0:
   4175                      op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
   4176                      op_sub = Iop_Sub8x16;
   4177                      break;
   4178                   case 1:
   4179                      op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
   4180                      op_sub = Iop_Sub16x8;
   4181                      break;
   4182                   case 2:
   4183                      op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
   4184                      op_sub = Iop_Sub32x4;
   4185                      break;
   4186                   case 3:
   4187                      return False;
   4188                   default:
   4189                      vassert(0);
   4190                }
   4191             } else {
   4192                switch (size) {
   4193                   case 0:
   4194                      op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   4195                      op_sub = Iop_Sub8x8;
   4196                      break;
   4197                   case 1:
   4198                      op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   4199                      op_sub = Iop_Sub16x4;
   4200                      break;
   4201                   case 2:
   4202                      op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   4203                      op_sub = Iop_Sub32x2;
   4204                      break;
   4205                   case 3:
   4206                      return False;
   4207                   default:
   4208                      vassert(0);
   4209                }
   4210             }
   4211             if (Q) {
   4212                cond = newTemp(Ity_V128);
   4213             } else {
   4214                cond = newTemp(Ity_I64);
   4215             }
   4216             assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
   4217             assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
   4218                               binop(Q ? Iop_AndV128 : Iop_And64,
   4219                                     binop(op_sub, mkexpr(arg_n),
   4220                                                   mkexpr(arg_m)),
   4221                                     mkexpr(cond)),
   4222                               binop(Q ? Iop_AndV128 : Iop_And64,
   4223                                     binop(op_sub, mkexpr(arg_m),
   4224                                                   mkexpr(arg_n)),
   4225                                     unop(Q ? Iop_NotV128 : Iop_Not64,
   4226                                          mkexpr(cond)))));
   4227             DIP("vabd.%c%u %c%u, %c%u, %c%u\n",
   4228                 U ? 'u' : 's', 8 << size,
   4229                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4230                 mreg);
   4231          } else {
   4232             /* VABA */
   4233             IROp op_cmp, op_sub, op_add;
   4234             IRTemp cond, acc, tmp;
   4235             if ((theInstr >> 23) & 1) {
   4236                vpanic("VABAL should not be in dis_neon_data_3same");
   4237             }
   4238             if (Q) {
   4239                switch (size) {
   4240                   case 0:
   4241                      op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
   4242                      op_sub = Iop_Sub8x16;
   4243                      op_add = Iop_Add8x16;
   4244                      break;
   4245                   case 1:
   4246                      op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
   4247                      op_sub = Iop_Sub16x8;
   4248                      op_add = Iop_Add16x8;
   4249                      break;
   4250                   case 2:
   4251                      op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
   4252                      op_sub = Iop_Sub32x4;
   4253                      op_add = Iop_Add32x4;
   4254                      break;
   4255                   case 3:
   4256                      return False;
   4257                   default:
   4258                      vassert(0);
   4259                }
   4260             } else {
   4261                switch (size) {
   4262                   case 0:
   4263                      op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   4264                      op_sub = Iop_Sub8x8;
   4265                      op_add = Iop_Add8x8;
   4266                      break;
   4267                   case 1:
   4268                      op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   4269                      op_sub = Iop_Sub16x4;
   4270                      op_add = Iop_Add16x4;
   4271                      break;
   4272                   case 2:
   4273                      op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   4274                      op_sub = Iop_Sub32x2;
   4275                      op_add = Iop_Add32x2;
   4276                      break;
   4277                   case 3:
   4278                      return False;
   4279                   default:
   4280                      vassert(0);
   4281                }
   4282             }
   4283             if (Q) {
   4284                cond = newTemp(Ity_V128);
   4285                acc = newTemp(Ity_V128);
   4286                tmp = newTemp(Ity_V128);
   4287                assign(acc, getQReg(dreg));
   4288             } else {
   4289                cond = newTemp(Ity_I64);
   4290                acc = newTemp(Ity_I64);
   4291                tmp = newTemp(Ity_I64);
   4292                assign(acc, getDRegI64(dreg));
   4293             }
   4294             assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
   4295             assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
   4296                               binop(Q ? Iop_AndV128 : Iop_And64,
   4297                                     binop(op_sub, mkexpr(arg_n),
   4298                                                   mkexpr(arg_m)),
   4299                                     mkexpr(cond)),
   4300                               binop(Q ? Iop_AndV128 : Iop_And64,
   4301                                     binop(op_sub, mkexpr(arg_m),
   4302                                                   mkexpr(arg_n)),
   4303                                     unop(Q ? Iop_NotV128 : Iop_Not64,
   4304                                          mkexpr(cond)))));
   4305             assign(res, binop(op_add, mkexpr(acc), mkexpr(tmp)));
   4306             DIP("vaba.%c%u %c%u, %c%u, %c%u\n",
   4307                 U ? 'u' : 's', 8 << size,
   4308                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4309                 mreg);
   4310          }
   4311          break;
   4312       case 8:
   4313          if (B == 0) {
   4314             IROp op;
   4315             if (U == 0) {
   4316                /* VADD  */
   4317                switch (size) {
   4318                   case 0: op = Q ? Iop_Add8x16 : Iop_Add8x8; break;
   4319                   case 1: op = Q ? Iop_Add16x8 : Iop_Add16x4; break;
   4320                   case 2: op = Q ? Iop_Add32x4 : Iop_Add32x2; break;
   4321                   case 3: op = Q ? Iop_Add64x2 : Iop_Add64; break;
   4322                   default: vassert(0);
   4323                }
   4324                DIP("vadd.i%u %c%u, %c%u, %c%u\n",
   4325                    8 << size, Q ? 'q' : 'd',
   4326                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4327             } else {
   4328                /* VSUB  */
   4329                switch (size) {
   4330                   case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
   4331                   case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
   4332                   case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
   4333                   case 3: op = Q ? Iop_Sub64x2 : Iop_Sub64; break;
   4334                   default: vassert(0);
   4335                }
   4336                DIP("vsub.i%u %c%u, %c%u, %c%u\n",
   4337                    8 << size, Q ? 'q' : 'd',
   4338                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4339             }
   4340             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4341          } else {
   4342             IROp op;
   4343             switch (size) {
   4344                case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
   4345                case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
   4346                case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
   4347                case 3: op = Q ? Iop_CmpNEZ64x2 : Iop_CmpwNEZ64; break;
   4348                default: vassert(0);
   4349             }
   4350             if (U == 0) {
   4351                /* VTST  */
   4352                assign(res, unop(op, binop(Q ? Iop_AndV128 : Iop_And64,
   4353                                           mkexpr(arg_n),
   4354                                           mkexpr(arg_m))));
   4355                DIP("vtst.%u %c%u, %c%u, %c%u\n",
   4356                    8 << size, Q ? 'q' : 'd',
   4357                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4358             } else {
   4359                /* VCEQ  */
   4360                assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   4361                                 unop(op,
   4362                                      binop(Q ? Iop_XorV128 : Iop_Xor64,
   4363                                            mkexpr(arg_n),
   4364                                            mkexpr(arg_m)))));
   4365                DIP("vceq.i%u %c%u, %c%u, %c%u\n",
   4366                    8 << size, Q ? 'q' : 'd',
   4367                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4368             }
   4369          }
   4370          break;
   4371       case 9:
   4372          if (B == 0) {
   4373             /* VMLA, VMLS (integer) */
   4374             IROp op, op2;
   4375             UInt P = (theInstr >> 24) & 1;
   4376             if (P) {
   4377                switch (size) {
   4378                   case 0:
   4379                      op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
   4380                      op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   4381                      break;
   4382                   case 1:
   4383                      op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   4384                      op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   4385                      break;
   4386                   case 2:
   4387                      op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   4388                      op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   4389                      break;
   4390                   case 3:
   4391                      return False;
   4392                   default:
   4393                      vassert(0);
   4394                }
   4395             } else {
   4396                switch (size) {
   4397                   case 0:
   4398                      op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
   4399                      op2 = Q ? Iop_Add8x16 : Iop_Add8x8;
   4400                      break;
   4401                   case 1:
   4402                      op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   4403                      op2 = Q ? Iop_Add16x8 : Iop_Add16x4;
   4404                      break;
   4405                   case 2:
   4406                      op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   4407                      op2 = Q ? Iop_Add32x4 : Iop_Add32x2;
   4408                      break;
   4409                   case 3:
   4410                      return False;
   4411                   default:
   4412                      vassert(0);
   4413                }
   4414             }
   4415             assign(res, binop(op2,
   4416                               Q ? getQReg(dreg) : getDRegI64(dreg),
   4417                               binop(op, mkexpr(arg_n), mkexpr(arg_m))));
   4418             DIP("vml%c.i%u %c%u, %c%u, %c%u\n",
   4419                 P ? 's' : 'a', 8 << size,
   4420                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4421                 mreg);
   4422          } else {
   4423             /* VMUL */
   4424             IROp op;
   4425             UInt P = (theInstr >> 24) & 1;
   4426             if (P) {
   4427                switch (size) {
   4428                   case 0:
   4429                      op = Q ? Iop_PolynomialMul8x16 : Iop_PolynomialMul8x8;
   4430                      break;
   4431                   case 1: case 2: case 3: return False;
   4432                   default: vassert(0);
   4433                }
   4434             } else {
   4435                switch (size) {
   4436                   case 0: op = Q ? Iop_Mul8x16 : Iop_Mul8x8; break;
   4437                   case 1: op = Q ? Iop_Mul16x8 : Iop_Mul16x4; break;
   4438                   case 2: op = Q ? Iop_Mul32x4 : Iop_Mul32x2; break;
   4439                   case 3: return False;
   4440                   default: vassert(0);
   4441                }
   4442             }
   4443             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4444             DIP("vmul.%c%u %c%u, %c%u, %c%u\n",
   4445                 P ? 'p' : 'i', 8 << size,
   4446                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4447                 mreg);
   4448          }
   4449          break;
   4450       case 10: {
   4451          /* VPMAX, VPMIN  */
   4452          UInt P = (theInstr >> 4) & 1;
   4453          IROp op;
   4454          if (Q)
   4455             return False;
   4456          if (P) {
   4457             switch (size) {
   4458                case 0: op = U ? Iop_PwMin8Ux8  : Iop_PwMin8Sx8; break;
   4459                case 1: op = U ? Iop_PwMin16Ux4 : Iop_PwMin16Sx4; break;
   4460                case 2: op = U ? Iop_PwMin32Ux2 : Iop_PwMin32Sx2; break;
   4461                case 3: return False;
   4462                default: vassert(0);
   4463             }
   4464          } else {
   4465             switch (size) {
   4466                case 0: op = U ? Iop_PwMax8Ux8  : Iop_PwMax8Sx8; break;
   4467                case 1: op = U ? Iop_PwMax16Ux4 : Iop_PwMax16Sx4; break;
   4468                case 2: op = U ? Iop_PwMax32Ux2 : Iop_PwMax32Sx2; break;
   4469                case 3: return False;
   4470                default: vassert(0);
   4471             }
   4472          }
   4473          assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4474          DIP("vp%s.%c%u %c%u, %c%u, %c%u\n",
   4475              P ? "min" : "max", U ? 'u' : 's',
   4476              8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
   4477              Q ? 'q' : 'd', mreg);
   4478          break;
   4479       }
   4480       case 11:
   4481          if (B == 0) {
   4482             if (U == 0) {
   4483                /* VQDMULH  */
   4484                IROp op ,op2;
   4485                ULong imm;
   4486                switch (size) {
   4487                   case 0: case 3:
   4488                      return False;
   4489                   case 1:
   4490                      op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
   4491                      op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   4492                      imm = 1LL << 15;
   4493                      imm = (imm << 16) | imm;
   4494                      imm = (imm << 32) | imm;
   4495                      break;
   4496                   case 2:
   4497                      op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
   4498                      op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   4499                      imm = 1LL << 31;
   4500                      imm = (imm << 32) | imm;
   4501                      break;
   4502                   default:
   4503                      vassert(0);
   4504                }
   4505                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4506 #ifndef DISABLE_QC_FLAG
   4507                setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4508                                 binop(op2, mkexpr(arg_n),
   4509                                            Q ? mkU128(imm) : mkU64(imm)),
   4510                                 binop(op2, mkexpr(arg_m),
   4511                                            Q ? mkU128(imm) : mkU64(imm))),
   4512                           Q ? mkU128(0) : mkU64(0),
   4513                           Q, condT);
   4514 #endif
   4515                DIP("vqdmulh.s%u %c%u, %c%u, %c%u\n",
   4516                    8 << size, Q ? 'q' : 'd',
   4517                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4518             } else {
   4519                /* VQRDMULH */
   4520                IROp op ,op2;
   4521                ULong imm;
   4522                switch(size) {
   4523                   case 0: case 3:
   4524                      return False;
   4525                   case 1:
   4526                      imm = 1LL << 15;
   4527                      imm = (imm << 16) | imm;
   4528                      imm = (imm << 32) | imm;
   4529                      op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
   4530                      op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   4531                      break;
   4532                   case 2:
   4533                      imm = 1LL << 31;
   4534                      imm = (imm << 32) | imm;
   4535                      op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
   4536                      op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   4537                      break;
   4538                   default:
   4539                      vassert(0);
   4540                }
   4541                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4542 #ifndef DISABLE_QC_FLAG
   4543                setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4544                                 binop(op2, mkexpr(arg_n),
   4545                                            Q ? mkU128(imm) : mkU64(imm)),
   4546                                 binop(op2, mkexpr(arg_m),
   4547                                            Q ? mkU128(imm) : mkU64(imm))),
   4548                           Q ? mkU128(0) : mkU64(0),
   4549                           Q, condT);
   4550 #endif
   4551                DIP("vqrdmulh.s%u %c%u, %c%u, %c%u\n",
   4552                    8 << size, Q ? 'q' : 'd',
   4553                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4554             }
   4555          } else {
   4556             if (U == 0) {
   4557                /* VPADD */
   4558                IROp op;
   4559                if (Q)
   4560                   return False;
   4561                switch (size) {
   4562                   case 0: op = Q ? Iop_PwAdd8x16 : Iop_PwAdd8x8;  break;
   4563                   case 1: op = Q ? Iop_PwAdd16x8 : Iop_PwAdd16x4; break;
   4564                   case 2: op = Q ? Iop_PwAdd32x4 : Iop_PwAdd32x2; break;
   4565                   case 3: return False;
   4566                   default: vassert(0);
   4567                }
   4568                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4569                DIP("vpadd.i%d %c%u, %c%u, %c%u\n",
   4570                    8 << size, Q ? 'q' : 'd',
   4571                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4572             }
   4573          }
   4574          break;
   4575       /* Starting from here these are FP SIMD cases */
   4576       case 13:
   4577          if (B == 0) {
   4578             IROp op;
   4579             if (U == 0) {
   4580                if ((C >> 1) == 0) {
   4581                   /* VADD  */
   4582                   op = Q ? Iop_Add32Fx4 : Iop_Add32Fx2 ;
   4583                   DIP("vadd.f32 %c%u, %c%u, %c%u\n",
   4584                       Q ? 'q' : 'd', dreg,
   4585                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4586                } else {
   4587                   /* VSUB  */
   4588                   op = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2 ;
   4589                   DIP("vsub.f32 %c%u, %c%u, %c%u\n",
   4590                       Q ? 'q' : 'd', dreg,
   4591                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4592                }
   4593             } else {
   4594                if ((C >> 1) == 0) {
   4595                   /* VPADD */
   4596                   if (Q)
   4597                      return False;
   4598                   op = Iop_PwAdd32Fx2;
   4599                   DIP("vpadd.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
   4600                } else {
   4601                   /* VABD  */
   4602                   if (Q) {
   4603                      assign(res, unop(Iop_Abs32Fx4,
   4604                                       binop(Iop_Sub32Fx4,
   4605                                             mkexpr(arg_n),
   4606                                             mkexpr(arg_m))));
   4607                   } else {
   4608                      assign(res, unop(Iop_Abs32Fx2,
   4609                                       binop(Iop_Sub32Fx2,
   4610                                             mkexpr(arg_n),
   4611                                             mkexpr(arg_m))));
   4612                   }
   4613                   DIP("vabd.f32 %c%u, %c%u, %c%u\n",
   4614                       Q ? 'q' : 'd', dreg,
   4615                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4616                   break;
   4617                }
   4618             }
   4619             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4620          } else {
   4621             if (U == 0) {
   4622                /* VMLA, VMLS  */
   4623                IROp op, op2;
   4624                UInt P = (theInstr >> 21) & 1;
   4625                if (P) {
   4626                   switch (size & 1) {
   4627                      case 0:
   4628                         op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   4629                         op2 = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
   4630                         break;
   4631                      case 1: return False;
   4632                      default: vassert(0);
   4633                   }
   4634                } else {
   4635                   switch (size & 1) {
   4636                      case 0:
   4637                         op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   4638                         op2 = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
   4639                         break;
   4640                      case 1: return False;
   4641                      default: vassert(0);
   4642                   }
   4643                }
   4644                assign(res, binop(op2,
   4645                                  Q ? getQReg(dreg) : getDRegI64(dreg),
   4646                                  binop(op, mkexpr(arg_n), mkexpr(arg_m))));
   4647 
   4648                DIP("vml%c.f32 %c%u, %c%u, %c%u\n",
   4649                    P ? 's' : 'a', Q ? 'q' : 'd',
   4650                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4651             } else {
   4652                /* VMUL  */
   4653                IROp op;
   4654                if ((C >> 1) != 0)
   4655                   return False;
   4656                op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2 ;
   4657                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4658                DIP("vmul.f32 %c%u, %c%u, %c%u\n",
   4659                    Q ? 'q' : 'd', dreg,
   4660                    Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4661             }
   4662          }
   4663          break;
   4664       case 14:
   4665          if (B == 0) {
   4666             if (U == 0) {
   4667                if ((C >> 1) == 0) {
   4668                   /* VCEQ  */
   4669                   IROp op;
   4670                   if ((theInstr >> 20) & 1)
   4671                      return False;
   4672                   op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2;
   4673                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4674                   DIP("vceq.f32 %c%u, %c%u, %c%u\n",
   4675                       Q ? 'q' : 'd', dreg,
   4676                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4677                } else {
   4678                   return False;
   4679                }
   4680             } else {
   4681                if ((C >> 1) == 0) {
   4682                   /* VCGE  */
   4683                   IROp op;
   4684                   if ((theInstr >> 20) & 1)
   4685                      return False;
   4686                   op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
   4687                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4688                   DIP("vcge.f32 %c%u, %c%u, %c%u\n",
   4689                       Q ? 'q' : 'd', dreg,
   4690                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4691                } else {
   4692                   /* VCGT  */
   4693                   IROp op;
   4694                   if ((theInstr >> 20) & 1)
   4695                      return False;
   4696                   op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
   4697                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4698                   DIP("vcgt.f32 %c%u, %c%u, %c%u\n",
   4699                       Q ? 'q' : 'd', dreg,
   4700                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4701                }
   4702             }
   4703          } else {
   4704             if (U == 1) {
   4705                /* VACGE, VACGT */
   4706                UInt op_bit = (theInstr >> 21) & 1;
   4707                IROp op, op2;
   4708                op2 = Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2;
   4709                if (op_bit) {
   4710                   op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
   4711                   assign(res, binop(op,
   4712                                     unop(op2, mkexpr(arg_n)),
   4713                                     unop(op2, mkexpr(arg_m))));
   4714                } else {
   4715                   op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
   4716                   assign(res, binop(op,
   4717                                     unop(op2, mkexpr(arg_n)),
   4718                                     unop(op2, mkexpr(arg_m))));
   4719                }
   4720                DIP("vacg%c.f32 %c%u, %c%u, %c%u\n", op_bit ? 't' : 'e',
   4721                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
   4722                    Q ? 'q' : 'd', mreg);
   4723             }
   4724          }
   4725          break;
   4726       case 15:
   4727          if (B == 0) {
   4728             if (U == 0) {
   4729                /* VMAX, VMIN  */
   4730                IROp op;
   4731                if ((theInstr >> 20) & 1)
   4732                   return False;
   4733                if ((theInstr >> 21) & 1) {
   4734                   op = Q ? Iop_Min32Fx4 : Iop_Min32Fx2;
   4735                   DIP("vmin.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4736                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4737                } else {
   4738                   op = Q ? Iop_Max32Fx4 : Iop_Max32Fx2;
   4739                   DIP("vmax.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4740                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4741                }
   4742                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4743             } else {
   4744                /* VPMAX, VPMIN   */
   4745                IROp op;
   4746                if (Q)
   4747                   return False;
   4748                if ((theInstr >> 20) & 1)
   4749                   return False;
   4750                if ((theInstr >> 21) & 1) {
   4751                   op = Iop_PwMin32Fx2;
   4752                   DIP("vpmin.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
   4753                } else {
   4754                   op = Iop_PwMax32Fx2;
   4755                   DIP("vpmax.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
   4756                }
   4757                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4758             }
   4759          } else {
   4760             if (U == 0) {
   4761                if ((C >> 1) == 0) {
   4762                   /* VRECPS */
   4763                   if ((theInstr >> 20) & 1)
   4764                      return False;
   4765                   assign(res, binop(Q ? Iop_Recps32Fx4 : Iop_Recps32Fx2,
   4766                                     mkexpr(arg_n),
   4767                                     mkexpr(arg_m)));
   4768                   DIP("vrecps.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4769                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4770                } else {
   4771                   /* VRSQRTS  */
   4772                   if ((theInstr >> 20) & 1)
   4773                      return False;
   4774                   assign(res, binop(Q ? Iop_Rsqrts32Fx4 : Iop_Rsqrts32Fx2,
   4775                                     mkexpr(arg_n),
   4776                                     mkexpr(arg_m)));
   4777                   DIP("vrsqrts.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4778                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4779                }
   4780             }
   4781          }
   4782          break;
   4783    }
   4784 
   4785    if (Q) {
   4786       putQReg(dreg, mkexpr(res), condT);
   4787    } else {
   4788       putDRegI64(dreg, mkexpr(res), condT);
   4789    }
   4790 
   4791    return True;
   4792 }
   4793 
   4794 /* A7.4.2 Three registers of different length */
   4795 static
   4796 Bool dis_neon_data_3diff ( UInt theInstr, IRTemp condT )
   4797 {
   4798    UInt A = (theInstr >> 8) & 0xf;
   4799    UInt B = (theInstr >> 20) & 3;
   4800    UInt U = (theInstr >> 24) & 1;
   4801    UInt P = (theInstr >> 9) & 1;
   4802    UInt mreg = get_neon_m_regno(theInstr);
   4803    UInt nreg = get_neon_n_regno(theInstr);
   4804    UInt dreg = get_neon_d_regno(theInstr);
   4805    UInt size = B;
   4806    ULong imm;
   4807    IRTemp res, arg_m, arg_n, cond, tmp;
   4808    IROp cvt, cvt2, cmp, op, op2, sh, add;
   4809    switch (A) {
   4810       case 0: case 1: case 2: case 3:
   4811          /* VADDL, VADDW, VSUBL, VSUBW */
   4812          if (dreg & 1)
   4813             return False;
   4814          dreg >>= 1;
   4815          size = B;
   4816          switch (size) {
   4817             case 0:
   4818                cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
   4819                op = (A & 2) ? Iop_Sub16x8 : Iop_Add16x8;
   4820                break;
   4821             case 1:
   4822                cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
   4823                op = (A & 2) ? Iop_Sub32x4 : Iop_Add32x4;
   4824                break;
   4825             case 2:
   4826                cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
   4827                op = (A & 2) ? Iop_Sub64x2 : Iop_Add64x2;
   4828                break;
   4829             case 3:
   4830                return False;
   4831             default:
   4832                vassert(0);
   4833          }
   4834          arg_n = newTemp(Ity_V128);
   4835          arg_m = newTemp(Ity_V128);
   4836          if (A & 1) {
   4837             if (nreg & 1)
   4838                return False;
   4839             nreg >>= 1;
   4840             assign(arg_n, getQReg(nreg));
   4841          } else {
   4842             assign(arg_n, unop(cvt, getDRegI64(nreg)));
   4843          }
   4844          assign(arg_m, unop(cvt, getDRegI64(mreg)));
   4845          putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   4846                        condT);
   4847          DIP("v%s%c.%c%u q%u, %c%u, d%u\n", (A & 2) ? "sub" : "add",
   4848              (A & 1) ? 'w' : 'l', U ? 'u' : 's', 8 << size, dreg,
   4849              (A & 1) ? 'q' : 'd', nreg, mreg);
   4850          return True;
   4851       case 4:
   4852          /* VADDHN, VRADDHN */
   4853          if (mreg & 1)
   4854             return False;
   4855          mreg >>= 1;
   4856          if (nreg & 1)
   4857             return False;
   4858          nreg >>= 1;
   4859          size = B;
   4860          switch (size) {
   4861             case 0:
   4862                op = Iop_Add16x8;
   4863                cvt = Iop_NarrowUn16to8x8;
   4864                sh = Iop_ShrN16x8;
   4865                imm = 1U << 7;
   4866                imm = (imm << 16) | imm;
   4867                imm = (imm << 32) | imm;
   4868                break;
   4869             case 1:
   4870                op = Iop_Add32x4;
   4871                cvt = Iop_NarrowUn32to16x4;
   4872                sh = Iop_ShrN32x4;
   4873                imm = 1U << 15;
   4874                imm = (imm << 32) | imm;
   4875                break;
   4876             case 2:
   4877                op = Iop_Add64x2;
   4878                cvt = Iop_NarrowUn64to32x2;
   4879                sh = Iop_ShrN64x2;
   4880                imm = 1U << 31;
   4881                break;
   4882             case 3:
   4883                return False;
   4884             default:
   4885                vassert(0);
   4886          }
   4887          tmp = newTemp(Ity_V128);
   4888          res = newTemp(Ity_V128);
   4889          assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
   4890          if (U) {
   4891             /* VRADDHN */
   4892             assign(res, binop(op, mkexpr(tmp),
   4893                      binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
   4894          } else {
   4895             assign(res, mkexpr(tmp));
   4896          }
   4897          putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
   4898                     condT);
   4899          DIP("v%saddhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
   4900              nreg, mreg);
   4901          return True;
   4902       case 5:
   4903          /* VABAL */
   4904          if (!((theInstr >> 23) & 1)) {
   4905             vpanic("VABA should not be in dis_neon_data_3diff\n");
   4906          }
   4907          if (dreg & 1)
   4908             return False;
   4909          dreg >>= 1;
   4910          switch (size) {
   4911             case 0:
   4912                cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   4913                cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
   4914                cvt2 = Iop_Widen8Sto16x8;
   4915                op = Iop_Sub16x8;
   4916                op2 = Iop_Add16x8;
   4917                break;
   4918             case 1:
   4919                cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   4920                cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
   4921                cvt2 = Iop_Widen16Sto32x4;
   4922                op = Iop_Sub32x4;
   4923                op2 = Iop_Add32x4;
   4924                break;
   4925             case 2:
   4926                cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   4927                cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
   4928                cvt2 = Iop_Widen32Sto64x2;
   4929                op = Iop_Sub64x2;
   4930                op2 = Iop_Add64x2;
   4931                break;
   4932             case 3:
   4933                return False;
   4934             default:
   4935                vassert(0);
   4936          }
   4937          arg_n = newTemp(Ity_V128);
   4938          arg_m = newTemp(Ity_V128);
   4939          cond = newTemp(Ity_V128);
   4940          res = newTemp(Ity_V128);
   4941          assign(arg_n, unop(cvt, getDRegI64(nreg)));
   4942          assign(arg_m, unop(cvt, getDRegI64(mreg)));
   4943          assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
   4944                                             getDRegI64(mreg))));
   4945          assign(res, binop(op2,
   4946                            binop(Iop_OrV128,
   4947                                  binop(Iop_AndV128,
   4948                                        binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   4949                                        mkexpr(cond)),
   4950                                  binop(Iop_AndV128,
   4951                                        binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   4952                                        unop(Iop_NotV128, mkexpr(cond)))),
   4953                            getQReg(dreg)));
   4954          putQReg(dreg, mkexpr(res), condT);
   4955          DIP("vabal.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
   4956              nreg, mreg);
   4957          return True;
   4958       case 6:
   4959          /* VSUBHN, VRSUBHN */
   4960          if (mreg & 1)
   4961             return False;
   4962          mreg >>= 1;
   4963          if (nreg & 1)
   4964             return False;
   4965          nreg >>= 1;
   4966          size = B;
   4967          switch (size) {
   4968             case 0:
   4969                op = Iop_Sub16x8;
   4970                op2 = Iop_Add16x8;
   4971                cvt = Iop_NarrowUn16to8x8;
   4972                sh = Iop_ShrN16x8;
   4973                imm = 1U << 7;
   4974                imm = (imm << 16) | imm;
   4975                imm = (imm << 32) | imm;
   4976                break;
   4977             case 1:
   4978                op = Iop_Sub32x4;
   4979                op2 = Iop_Add32x4;
   4980                cvt = Iop_NarrowUn32to16x4;
   4981                sh = Iop_ShrN32x4;
   4982                imm = 1U << 15;
   4983                imm = (imm << 32) | imm;
   4984                break;
   4985             case 2:
   4986                op = Iop_Sub64x2;
   4987                op2 = Iop_Add64x2;
   4988                cvt = Iop_NarrowUn64to32x2;
   4989                sh = Iop_ShrN64x2;
   4990                imm = 1U << 31;
   4991                break;
   4992             case 3:
   4993                return False;
   4994             default:
   4995                vassert(0);
   4996          }
   4997          tmp = newTemp(Ity_V128);
   4998          res = newTemp(Ity_V128);
   4999          assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
   5000          if (U) {
   5001             /* VRSUBHN */
   5002             assign(res, binop(op2, mkexpr(tmp),
   5003                      binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
   5004          } else {
   5005             assign(res, mkexpr(tmp));
   5006          }
   5007          putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
   5008                     condT);
   5009          DIP("v%ssubhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
   5010              nreg, mreg);
   5011          return True;
   5012       case 7:
   5013          /* VABDL */
   5014          if (!((theInstr >> 23) & 1)) {
   5015             vpanic("VABL should not be in dis_neon_data_3diff\n");
   5016          }
   5017          if (dreg & 1)
   5018             return False;
   5019          dreg >>= 1;
   5020          switch (size) {
   5021             case 0:
   5022                cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   5023                cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
   5024                cvt2 = Iop_Widen8Sto16x8;
   5025                op = Iop_Sub16x8;
   5026                break;
   5027             case 1:
   5028                cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   5029                cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
   5030                cvt2 = Iop_Widen16Sto32x4;
   5031                op = Iop_Sub32x4;
   5032                break;
   5033             case 2:
   5034                cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   5035                cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
   5036                cvt2 = Iop_Widen32Sto64x2;
   5037                op = Iop_Sub64x2;
   5038                break;
   5039             case 3:
   5040                return False;
   5041             default:
   5042                vassert(0);
   5043          }
   5044          arg_n = newTemp(Ity_V128);
   5045          arg_m = newTemp(Ity_V128);
   5046          cond = newTemp(Ity_V128);
   5047          res = newTemp(Ity_V128);
   5048          assign(arg_n, unop(cvt, getDRegI64(nreg)));
   5049          assign(arg_m, unop(cvt, getDRegI64(mreg)));
   5050          assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
   5051                                             getDRegI64(mreg))));
   5052          assign(res, binop(Iop_OrV128,
   5053                            binop(Iop_AndV128,
   5054                                  binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   5055                                  mkexpr(cond)),
   5056                            binop(Iop_AndV128,
   5057                                  binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   5058                                  unop(Iop_NotV128, mkexpr(cond)))));
   5059          putQReg(dreg, mkexpr(res), condT);
   5060          DIP("vabdl.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
   5061              nreg, mreg);
   5062          return True;
   5063       case 8:
   5064       case 10:
   5065          /* VMLAL, VMLSL (integer) */
   5066          if (dreg & 1)
   5067             return False;
   5068          dreg >>= 1;
   5069          size = B;
   5070          switch (size) {
   5071             case 0:
   5072                op = U ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
   5073                op2 = P ? Iop_Sub16x8 : Iop_Add16x8;
   5074                break;
   5075             case 1:
   5076                op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
   5077                op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
   5078                break;
   5079             case 2:
   5080                op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
   5081                op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
   5082                break;
   5083             case 3:
   5084                return False;
   5085             default:
   5086                vassert(0);
   5087          }
   5088          res = newTemp(Ity_V128);
   5089          assign(res, binop(op, getDRegI64(nreg),getDRegI64(mreg)));
   5090          putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
   5091          DIP("vml%cl.%c%u q%u, d%u, d%u\n", P ? 's' : 'a', U ? 'u' : 's',
   5092              8 << size, dreg, nreg, mreg);
   5093          return True;
   5094       case 9:
   5095       case 11:
   5096          /* VQDMLAL, VQDMLSL */
   5097          if (U)
   5098             return False;
   5099          if (dreg & 1)
   5100             return False;
   5101          dreg >>= 1;
   5102          size = B;
   5103          switch (size) {
   5104             case 0: case 3:
   5105                return False;
   5106             case 1:
   5107                op = Iop_QDMulLong16Sx4;
   5108                cmp = Iop_CmpEQ16x4;
   5109                add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
   5110                op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
   5111                imm = 1LL << 15;
   5112                imm = (imm << 16) | imm;
   5113                imm = (imm << 32) | imm;
   5114                break;
   5115             case 2:
   5116                op = Iop_QDMulLong32Sx2;
   5117                cmp = Iop_CmpEQ32x2;
   5118                add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
   5119                op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
   5120                imm = 1LL << 31;
   5121                imm = (imm << 32) | imm;
   5122                break;
   5123             default:
   5124                vassert(0);
   5125          }
   5126          res = newTemp(Ity_V128);
   5127          tmp = newTemp(Ity_V128);
   5128          assign(res, binop(op, getDRegI64(nreg), getDRegI64(mreg)));
   5129 #ifndef DISABLE_QC_FLAG
   5130          assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
   5131          setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
   5132                     True, condT);
   5133          setFlag_QC(binop(Iop_And64,
   5134                           binop(cmp, getDRegI64(nreg), mkU64(imm)),
   5135                           binop(cmp, getDRegI64(mreg), mkU64(imm))),
   5136                     mkU64(0),
   5137                     False, condT);
   5138 #endif
   5139          putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
   5140          DIP("vqdml%cl.s%u q%u, d%u, d%u\n", P ? 's' : 'a', 8 << size, dreg,
   5141              nreg, mreg);
   5142          return True;
   5143       case 12:
   5144       case 14:
   5145          /* VMULL (integer or polynomial) */
   5146          if (dreg & 1)
   5147             return False;
   5148          dreg >>= 1;
   5149          size = B;
   5150          switch (size) {
   5151             case 0:
   5152                op = (U) ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
   5153                if (P)
   5154                   op = Iop_PolynomialMull8x8;
   5155                break;
   5156             case 1:
   5157                op = (U) ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
   5158                break;
   5159             case 2:
   5160                op = (U) ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
   5161                break;
   5162             default:
   5163                vassert(0);
   5164          }
   5165          putQReg(dreg, binop(op, getDRegI64(nreg),
   5166                                  getDRegI64(mreg)), condT);
   5167          DIP("vmull.%c%u q%u, d%u, d%u\n", P ? 'p' : (U ? 'u' : 's'),
   5168                8 << size, dreg, nreg, mreg);
   5169          return True;
   5170       case 13:
   5171          /* VQDMULL */
   5172          if (U)
   5173             return False;
   5174          if (dreg & 1)
   5175             return False;
   5176          dreg >>= 1;
   5177          size = B;
   5178          switch (size) {
   5179             case 0:
   5180             case 3:
   5181                return False;
   5182             case 1:
   5183                op = Iop_QDMulLong16Sx4;
   5184                op2 = Iop_CmpEQ16x4;
   5185                imm = 1LL << 15;
   5186                imm = (imm << 16) | imm;
   5187                imm = (imm << 32) | imm;
   5188                break;
   5189             case 2:
   5190                op = Iop_QDMulLong32Sx2;
   5191                op2 = Iop_CmpEQ32x2;
   5192                imm = 1LL << 31;
   5193                imm = (imm << 32) | imm;
   5194                break;
   5195             default:
   5196                vassert(0);
   5197          }
   5198          putQReg(dreg, binop(op, getDRegI64(nreg), getDRegI64(mreg)),
   5199                condT);
   5200 #ifndef DISABLE_QC_FLAG
   5201          setFlag_QC(binop(Iop_And64,
   5202                           binop(op2, getDRegI64(nreg), mkU64(imm)),
   5203                           binop(op2, getDRegI64(mreg), mkU64(imm))),
   5204                     mkU64(0),
   5205                     False, condT);
   5206 #endif
   5207          DIP("vqdmull.s%u q%u, d%u, d%u\n", 8 << size, dreg, nreg, mreg);
   5208          return True;
   5209       default:
   5210          return False;
   5211    }
   5212    return False;
   5213 }
   5214 
   5215 /* A7.4.3 Two registers and a scalar */
   5216 static
   5217 Bool dis_neon_data_2reg_and_scalar ( UInt theInstr, IRTemp condT )
   5218 {
   5219 #  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
   5220    UInt U = INSN(24,24);
   5221    UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
   5222    UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
   5223    UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
   5224    UInt size = INSN(21,20);
   5225    UInt index;
   5226    UInt Q = INSN(24,24);
   5227 
   5228    if (INSN(27,25) != 1 || INSN(23,23) != 1
   5229        || INSN(6,6) != 1 || INSN(4,4) != 0)
   5230       return False;
   5231 
   5232    /* VMLA, VMLS (scalar)  */
   5233    if ((INSN(11,8) & BITS4(1,0,1,0)) == BITS4(0,0,0,0)) {
   5234       IRTemp res, arg_m, arg_n;
   5235       IROp dup, get, op, op2, add, sub;
   5236       if (Q) {
   5237          if ((dreg & 1) || (nreg & 1))
   5238             return False;
   5239          dreg >>= 1;
   5240          nreg >>= 1;
   5241          res = newTemp(Ity_V128);
   5242          arg_m = newTemp(Ity_V128);
   5243          arg_n = newTemp(Ity_V128);
   5244          assign(arg_n, getQReg(nreg));
   5245          switch(size) {
   5246             case 1:
   5247                dup = Iop_Dup16x8;
   5248                get = Iop_GetElem16x4;
   5249                index = mreg >> 3;
   5250                mreg &= 7;
   5251                break;
   5252             case 2:
   5253                dup = Iop_Dup32x4;
   5254                get = Iop_GetElem32x2;
   5255                index = mreg >> 4;
   5256                mreg &= 0xf;
   5257                break;
   5258             case 0:
   5259             case 3:
   5260                return False;
   5261             default:
   5262                vassert(0);
   5263          }
   5264          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5265       } else {
   5266          res = newTemp(Ity_I64);
   5267          arg_m = newTemp(Ity_I64);
   5268          arg_n = newTemp(Ity_I64);
   5269          assign(arg_n, getDRegI64(nreg));
   5270          switch(size) {
   5271             case 1:
   5272                dup = Iop_Dup16x4;
   5273                get = Iop_GetElem16x4;
   5274                index = mreg >> 3;
   5275                mreg &= 7;
   5276                break;
   5277             case 2:
   5278                dup = Iop_Dup32x2;
   5279                get = Iop_GetElem32x2;
   5280                index = mreg >> 4;
   5281                mreg &= 0xf;
   5282                break;
   5283             case 0:
   5284             case 3:
   5285                return False;
   5286             default:
   5287                vassert(0);
   5288          }
   5289          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5290       }
   5291       if (INSN(8,8)) {
   5292          switch (size) {
   5293             case 2:
   5294                op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   5295                add = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
   5296                sub = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
   5297                break;
   5298             case 0:
   5299             case 1:
   5300             case 3:
   5301                return False;
   5302             default:
   5303                vassert(0);
   5304          }
   5305       } else {
   5306          switch (size) {
   5307             case 1:
   5308                op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   5309                add = Q ? Iop_Add16x8 : Iop_Add16x4;
   5310                sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   5311                break;
   5312             case 2:
   5313                op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   5314                add = Q ? Iop_Add32x4 : Iop_Add32x2;
   5315                sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   5316                break;
   5317             case 0:
   5318             case 3:
   5319                return False;
   5320             default:
   5321                vassert(0);
   5322          }
   5323       }
   5324       op2 = INSN(10,10) ? sub : add;
   5325       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5326       if (Q)
   5327          putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)),
   5328                condT);
   5329       else
   5330          putDRegI64(dreg, binop(op2, getDRegI64(dreg), mkexpr(res)),
   5331                     condT);
   5332       DIP("vml%c.%c%u %c%u, %c%u, d%u[%u]\n", INSN(10,10) ? 's' : 'a',
   5333             INSN(8,8) ? 'f' : 'i', 8 << size,
   5334             Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, mreg, index);
   5335       return True;
   5336    }
   5337 
   5338    /* VMLAL, VMLSL (scalar)   */
   5339    if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,0)) {
   5340       IRTemp res, arg_m, arg_n;
   5341       IROp dup, get, op, op2, add, sub;
   5342       if (dreg & 1)
   5343          return False;
   5344       dreg >>= 1;
   5345       res = newTemp(Ity_V128);
   5346       arg_m = newTemp(Ity_I64);
   5347       arg_n = newTemp(Ity_I64);
   5348       assign(arg_n, getDRegI64(nreg));
   5349       switch(size) {
   5350          case 1:
   5351             dup = Iop_Dup16x4;
   5352             get = Iop_GetElem16x4;
   5353             index = mreg >> 3;
   5354             mreg &= 7;
   5355             break;
   5356          case 2:
   5357             dup = Iop_Dup32x2;
   5358             get = Iop_GetElem32x2;
   5359             index = mreg >> 4;
   5360             mreg &= 0xf;
   5361             break;
   5362          case 0:
   5363          case 3:
   5364             return False;
   5365          default:
   5366             vassert(0);
   5367       }
   5368       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5369       switch (size) {
   5370          case 1:
   5371             op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
   5372             add = Iop_Add32x4;
   5373             sub = Iop_Sub32x4;
   5374             break;
   5375          case 2:
   5376             op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
   5377             add = Iop_Add64x2;
   5378             sub = Iop_Sub64x2;
   5379             break;
   5380          case 0:
   5381          case 3:
   5382             return False;
   5383          default:
   5384             vassert(0);
   5385       }
   5386       op2 = INSN(10,10) ? sub : add;
   5387       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5388       putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
   5389       DIP("vml%cl.%c%u q%u, d%u, d%u[%u]\n",
   5390           INSN(10,10) ? 's' : 'a', U ? 'u' : 's',
   5391           8 << size, dreg, nreg, mreg, index);
   5392       return True;
   5393    }
   5394 
   5395    /* VQDMLAL, VQDMLSL (scalar)  */
   5396    if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,1) && !U) {
   5397       IRTemp res, arg_m, arg_n, tmp;
   5398       IROp dup, get, op, op2, add, cmp;
   5399       UInt P = INSN(10,10);
   5400       ULong imm;
   5401       if (dreg & 1)
   5402          return False;
   5403       dreg >>= 1;
   5404       res = newTemp(Ity_V128);
   5405       arg_m = newTemp(Ity_I64);
   5406       arg_n = newTemp(Ity_I64);
   5407       assign(arg_n, getDRegI64(nreg));
   5408       switch(size) {
   5409          case 1:
   5410             dup = Iop_Dup16x4;
   5411             get = Iop_GetElem16x4;
   5412             index = mreg >> 3;
   5413             mreg &= 7;
   5414             break;
   5415          case 2:
   5416             dup = Iop_Dup32x2;
   5417             get = Iop_GetElem32x2;
   5418             index = mreg >> 4;
   5419             mreg &= 0xf;
   5420             break;
   5421          case 0:
   5422          case 3:
   5423             return False;
   5424          default:
   5425             vassert(0);
   5426       }
   5427       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5428       switch (size) {
   5429          case 0:
   5430          case 3:
   5431             return False;
   5432          case 1:
   5433             op = Iop_QDMulLong16Sx4;
   5434             cmp = Iop_CmpEQ16x4;
   5435             add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
   5436             op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
   5437             imm = 1LL << 15;
   5438             imm = (imm << 16) | imm;
   5439             imm = (imm << 32) | imm;
   5440             break;
   5441          case 2:
   5442             op = Iop_QDMulLong32Sx2;
   5443             cmp = Iop_CmpEQ32x2;
   5444             add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
   5445             op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
   5446             imm = 1LL << 31;
   5447             imm = (imm << 32) | imm;
   5448             break;
   5449          default:
   5450             vassert(0);
   5451       }
   5452       res = newTemp(Ity_V128);
   5453       tmp = newTemp(Ity_V128);
   5454       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5455 #ifndef DISABLE_QC_FLAG
   5456       assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
   5457       setFlag_QC(binop(Iop_And64,
   5458                        binop(cmp, mkexpr(arg_n), mkU64(imm)),
   5459                        binop(cmp, mkexpr(arg_m), mkU64(imm))),
   5460                  mkU64(0),
   5461                  False, condT);
   5462       setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
   5463                  True, condT);
   5464 #endif
   5465       putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
   5466       DIP("vqdml%cl.s%u q%u, d%u, d%u[%u]\n", P ? 's' : 'a', 8 << size,
   5467           dreg, nreg, mreg, index);
   5468       return True;
   5469    }
   5470 
   5471    /* VMUL (by scalar)  */
   5472    if ((INSN(11,8) & BITS4(1,1,1,0)) == BITS4(1,0,0,0)) {
   5473       IRTemp res, arg_m, arg_n;
   5474       IROp dup, get, op;
   5475       if (Q) {
   5476          if ((dreg & 1) || (nreg & 1))
   5477             return False;
   5478          dreg >>= 1;
   5479          nreg >>= 1;
   5480          res = newTemp(Ity_V128);
   5481          arg_m = newTemp(Ity_V128);
   5482          arg_n = newTemp(Ity_V128);
   5483          assign(arg_n, getQReg(nreg));
   5484          switch(size) {
   5485             case 1:
   5486                dup = Iop_Dup16x8;
   5487                get = Iop_GetElem16x4;
   5488                index = mreg >> 3;
   5489                mreg &= 7;
   5490                break;
   5491             case 2:
   5492                dup = Iop_Dup32x4;
   5493                get = Iop_GetElem32x2;
   5494                index = mreg >> 4;
   5495                mreg &= 0xf;
   5496                break;
   5497             case 0:
   5498             case 3:
   5499                return False;
   5500             default:
   5501                vassert(0);
   5502          }
   5503          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5504       } else {
   5505          res = newTemp(Ity_I64);
   5506          arg_m = newTemp(Ity_I64);
   5507          arg_n = newTemp(Ity_I64);
   5508          assign(arg_n, getDRegI64(nreg));
   5509          switch(size) {
   5510             case 1:
   5511                dup = Iop_Dup16x4;
   5512                get = Iop_GetElem16x4;
   5513                index = mreg >> 3;
   5514                mreg &= 7;
   5515                break;
   5516             case 2:
   5517                dup = Iop_Dup32x2;
   5518                get = Iop_GetElem32x2;
   5519                index = mreg >> 4;
   5520                mreg &= 0xf;
   5521                break;
   5522             case 0:
   5523             case 3:
   5524                return False;
   5525             default:
   5526                vassert(0);
   5527          }
   5528          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5529       }
   5530       if (INSN(8,8)) {
   5531          switch (size) {
   5532             case 2:
   5533                op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   5534                break;
   5535             case 0:
   5536             case 1:
   5537             case 3:
   5538                return False;
   5539             default:
   5540                vassert(0);
   5541          }
   5542       } else {
   5543          switch (size) {
   5544             case 1:
   5545                op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   5546                break;
   5547             case 2:
   5548                op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   5549                break;
   5550             case 0:
   5551             case 3:
   5552                return False;
   5553             default:
   5554                vassert(0);
   5555          }
   5556       }
   5557       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5558       if (Q)
   5559          putQReg(dreg, mkexpr(res), condT);
   5560       else
   5561          putDRegI64(dreg, mkexpr(res), condT);
   5562       DIP("vmul.%c%u %c%u, %c%u, d%u[%u]\n", INSN(8,8) ? 'f' : 'i',
   5563           8 << size, Q ? 'q' : 'd', dreg,
   5564           Q ? 'q' : 'd', nreg, mreg, index);
   5565       return True;
   5566    }
   5567 
   5568    /* VMULL (scalar) */
   5569    if (INSN(11,8) == BITS4(1,0,1,0)) {
   5570       IRTemp res, arg_m, arg_n;
   5571       IROp dup, get, op;
   5572       if (dreg & 1)
   5573          return False;
   5574       dreg >>= 1;
   5575       res = newTemp(Ity_V128);
   5576       arg_m = newTemp(Ity_I64);
   5577       arg_n = newTemp(Ity_I64);
   5578       assign(arg_n, getDRegI64(nreg));
   5579       switch(size) {
   5580          case 1:
   5581             dup = Iop_Dup16x4;
   5582             get = Iop_GetElem16x4;
   5583             index = mreg >> 3;
   5584             mreg &= 7;
   5585             break;
   5586          case 2:
   5587             dup = Iop_Dup32x2;
   5588             get = Iop_GetElem32x2;
   5589             index = mreg >> 4;
   5590             mreg &= 0xf;
   5591             break;
   5592          case 0:
   5593          case 3:
   5594             return False;
   5595          default:
   5596             vassert(0);
   5597       }
   5598       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5599       switch (size) {
   5600          case 1: op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; break;
   5601          case 2: op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; break;
   5602          case 0: case 3: return False;
   5603          default: vassert(0);
   5604       }
   5605       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5606       putQReg(dreg, mkexpr(res), condT);
   5607       DIP("vmull.%c%u q%u, d%u, d%u[%u]\n", U ? 'u' : 's', 8 << size, dreg,
   5608           nreg, mreg, index);
   5609       return True;
   5610    }
   5611 
   5612    /* VQDMULL */
   5613    if (INSN(11,8) == BITS4(1,0,1,1) && !U) {
   5614       IROp op ,op2, dup, get;
   5615       ULong imm;
   5616       IRTemp arg_m, arg_n;
   5617       if (dreg & 1)
   5618          return False;
   5619       dreg >>= 1;
   5620       arg_m = newTemp(Ity_I64);
   5621       arg_n = newTemp(Ity_I64);
   5622       assign(arg_n, getDRegI64(nreg));
   5623       switch(size) {
   5624          case 1:
   5625             dup = Iop_Dup16x4;
   5626             get = Iop_GetElem16x4;
   5627             index = mreg >> 3;
   5628             mreg &= 7;
   5629             break;
   5630          case 2:
   5631             dup = Iop_Dup32x2;
   5632             get = Iop_GetElem32x2;
   5633             index = mreg >> 4;
   5634             mreg &= 0xf;
   5635             break;
   5636          case 0:
   5637          case 3:
   5638             return False;
   5639          default:
   5640             vassert(0);
   5641       }
   5642       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5643       switch (size) {
   5644          case 0:
   5645          case 3:
   5646             return False;
   5647          case 1:
   5648             op = Iop_QDMulLong16Sx4;
   5649             op2 = Iop_CmpEQ16x4;
   5650             imm = 1LL << 15;
   5651             imm = (imm << 16) | imm;
   5652             imm = (imm << 32) | imm;
   5653             break;
   5654          case 2:
   5655             op = Iop_QDMulLong32Sx2;
   5656             op2 = Iop_CmpEQ32x2;
   5657             imm = 1LL << 31;
   5658             imm = (imm << 32) | imm;
   5659             break;
   5660          default:
   5661             vassert(0);
   5662       }
   5663       putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   5664             condT);
   5665 #ifndef DISABLE_QC_FLAG
   5666       setFlag_QC(binop(Iop_And64,
   5667                        binop(op2, mkexpr(arg_n), mkU64(imm)),
   5668                        binop(op2, mkexpr(arg_m), mkU64(imm))),
   5669                  mkU64(0),
   5670                  False, condT);
   5671 #endif
   5672       DIP("vqdmull.s%u q%u, d%u, d%u[%u]\n", 8 << size, dreg, nreg, mreg,
   5673           index);
   5674       return True;
   5675    }
   5676 
   5677    /* VQDMULH */
   5678    if (INSN(11,8) == BITS4(1,1,0,0)) {
   5679       IROp op ,op2, dup, get;
   5680       ULong imm;
   5681       IRTemp res, arg_m, arg_n;
   5682       if (Q) {
   5683          if ((dreg & 1) || (nreg & 1))
   5684             return False;
   5685          dreg >>= 1;
   5686          nreg >>= 1;
   5687          res = newTemp(Ity_V128);
   5688          arg_m = newTemp(Ity_V128);
   5689          arg_n = newTemp(Ity_V128);
   5690          assign(arg_n, getQReg(nreg));
   5691          switch(size) {
   5692             case 1:
   5693                dup = Iop_Dup16x8;
   5694                get = Iop_GetElem16x4;
   5695                index = mreg >> 3;
   5696                mreg &= 7;
   5697                break;
   5698             case 2:
   5699                dup = Iop_Dup32x4;
   5700                get = Iop_GetElem32x2;
   5701                index = mreg >> 4;
   5702                mreg &= 0xf;
   5703                break;
   5704             case 0:
   5705             case 3:
   5706                return False;
   5707             default:
   5708                vassert(0);
   5709          }
   5710          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5711       } else {
   5712          res = newTemp(Ity_I64);
   5713          arg_m = newTemp(Ity_I64);
   5714          arg_n = newTemp(Ity_I64);
   5715          assign(arg_n, getDRegI64(nreg));
   5716          switch(size) {
   5717             case 1:
   5718                dup = Iop_Dup16x4;
   5719                get = Iop_GetElem16x4;
   5720                index = mreg >> 3;
   5721                mreg &= 7;
   5722                break;
   5723             case 2:
   5724                dup = Iop_Dup32x2;
   5725                get = Iop_GetElem32x2;
   5726                index = mreg >> 4;
   5727                mreg &= 0xf;
   5728                break;
   5729             case 0:
   5730             case 3:
   5731                return False;
   5732             default:
   5733                vassert(0);
   5734          }
   5735          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5736       }
   5737       switch (size) {
   5738          case 0:
   5739          case 3:
   5740             return False;
   5741          case 1:
   5742             op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
   5743             op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   5744             imm = 1LL << 15;
   5745             imm = (imm << 16) | imm;
   5746             imm = (imm << 32) | imm;
   5747             break;
   5748          case 2:
   5749             op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
   5750             op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   5751             imm = 1LL << 31;
   5752             imm = (imm << 32) | imm;
   5753             break;
   5754          default:
   5755             vassert(0);
   5756       }
   5757       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5758 #ifndef DISABLE_QC_FLAG
   5759       setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   5760                        binop(op2, mkexpr(arg_n),
   5761                                   Q ? mkU128(imm) : mkU64(imm)),
   5762                        binop(op2, mkexpr(arg_m),
   5763                              Q ? mkU128(imm) : mkU64(imm))),
   5764                  Q ? mkU128(0) : mkU64(0),
   5765                  Q, condT);
   5766 #endif
   5767       if (Q)
   5768          putQReg(dreg, mkexpr(res), condT);
   5769       else
   5770          putDRegI64(dreg, mkexpr(res), condT);
   5771       DIP("vqdmulh.s%u %c%u, %c%u, d%u[%u]\n",
   5772           8 << size, Q ? 'q' : 'd', dreg,
   5773           Q ? 'q' : 'd', nreg, mreg, index);
   5774       return True;
   5775    }
   5776 
   5777    /* VQRDMULH (scalar) */
   5778    if (INSN(11,8) == BITS4(1,1,0,1)) {
   5779       IROp op ,op2, dup, get;
   5780       ULong imm;
   5781       IRTemp res, arg_m, arg_n;
   5782       if (Q) {
   5783          if ((dreg & 1) || (nreg & 1))
   5784             return False;
   5785          dreg >>= 1;
   5786          nreg >>= 1;
   5787          res = newTemp(Ity_V128);
   5788          arg_m = newTemp(Ity_V128);
   5789          arg_n = newTemp(Ity_V128);
   5790          assign(arg_n, getQReg(nreg));
   5791          switch(size) {
   5792             case 1:
   5793                dup = Iop_Dup16x8;
   5794                get = Iop_GetElem16x4;
   5795                index = mreg >> 3;
   5796                mreg &= 7;
   5797                break;
   5798             case 2:
   5799                dup = Iop_Dup32x4;
   5800                get = Iop_GetElem32x2;
   5801                index = mreg >> 4;
   5802                mreg &= 0xf;
   5803                break;
   5804             case 0:
   5805             case 3:
   5806                return False;
   5807             default:
   5808                vassert(0);
   5809          }
   5810          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5811       } else {
   5812          res = newTemp(Ity_I64);
   5813          arg_m = newTemp(Ity_I64);
   5814          arg_n = newTemp(Ity_I64);
   5815          assign(arg_n, getDRegI64(nreg));
   5816          switch(size) {
   5817             case 1:
   5818                dup = Iop_Dup16x4;
   5819                get = Iop_GetElem16x4;
   5820                index = mreg >> 3;
   5821                mreg &= 7;
   5822                break;
   5823             case 2:
   5824                dup = Iop_Dup32x2;
   5825                get = Iop_GetElem32x2;
   5826                index = mreg >> 4;
   5827                mreg &= 0xf;
   5828                break;
   5829             case 0:
   5830             case 3:
   5831                return False;
   5832             default:
   5833                vassert(0);
   5834          }
   5835          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5836       }
   5837       switch (size) {
   5838          case 0:
   5839          case 3:
   5840             return False;
   5841          case 1:
   5842             op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
   5843             op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   5844             imm = 1LL << 15;
   5845             imm = (imm << 16) | imm;
   5846             imm = (imm << 32) | imm;
   5847             break;
   5848          case 2:
   5849             op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
   5850             op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   5851             imm = 1LL << 31;
   5852             imm = (imm << 32) | imm;
   5853             break;
   5854          default:
   5855             vassert(0);
   5856       }
   5857       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5858 #ifndef DISABLE_QC_FLAG
   5859       setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   5860                        binop(op2, mkexpr(arg_n),
   5861                                   Q ? mkU128(imm) : mkU64(imm)),
   5862                        binop(op2, mkexpr(arg_m),
   5863                                   Q ? mkU128(imm) : mkU64(imm))),
   5864                  Q ? mkU128(0) : mkU64(0),
   5865                  Q, condT);
   5866 #endif
   5867       if (Q)
   5868          putQReg(dreg, mkexpr(res), condT);
   5869       else
   5870          putDRegI64(dreg, mkexpr(res), condT);
   5871       DIP("vqrdmulh.s%u %c%u, %c%u, d%u[%u]\n",
   5872           8 << size, Q ? 'q' : 'd', dreg,
   5873           Q ? 'q' : 'd', nreg, mreg, index);
   5874       return True;
   5875    }
   5876 
   5877    return False;
   5878 #  undef INSN
   5879 }
   5880 
   5881 /* A7.4.4 Two registers and a shift amount */
   5882 static
   5883 Bool dis_neon_data_2reg_and_shift ( UInt theInstr, IRTemp condT )
   5884 {
   5885    UInt A = (theInstr >> 8) & 0xf;
   5886    UInt B = (theInstr >> 6) & 1;
   5887    UInt L = (theInstr >> 7) & 1;
   5888    UInt U = (theInstr >> 24) & 1;
   5889    UInt Q = B;
   5890    UInt imm6 = (theInstr >> 16) & 0x3f;
   5891    UInt shift_imm;
   5892    UInt size = 4;
   5893    UInt tmp;
   5894    UInt mreg = get_neon_m_regno(theInstr);
   5895    UInt dreg = get_neon_d_regno(theInstr);
   5896    ULong imm = 0;
   5897    IROp op, cvt, add = Iop_INVALID, cvt2, op_rev;
   5898    IRTemp reg_m, res, mask;
   5899 
   5900    if (L == 0 && ((theInstr >> 19) & 7) == 0)
   5901       /* It is one reg and immediate */
   5902       return False;
   5903 
   5904    tmp = (L << 6) | imm6;
   5905    if (tmp & 0x40) {
   5906       size = 3;
   5907       shift_imm = 64 - imm6;
   5908    } else if (tmp & 0x20) {
   5909       size = 2;
   5910       shift_imm = 64 - imm6;
   5911    } else if (tmp & 0x10) {
   5912       size = 1;
   5913       shift_imm = 32 - imm6;
   5914    } else if (tmp & 0x8) {
   5915       size = 0;
   5916       shift_imm = 16 - imm6;
   5917    } else {
   5918       return False;
   5919    }
   5920 
   5921    switch (A) {
   5922       case 3:
   5923       case 2:
   5924          /* VRSHR, VRSRA */
   5925          if (shift_imm > 0) {
   5926             IRExpr *imm_val;
   5927             imm = 1L;
   5928             switch (size) {
   5929                case 0:
   5930                   imm = (imm << 8) | imm;
   5931                   /* fall through */
   5932                case 1:
   5933                   imm = (imm << 16) | imm;
   5934                   /* fall through */
   5935                case 2:
   5936                   imm = (imm << 32) | imm;
   5937                   /* fall through */
   5938                case 3:
   5939                   break;
   5940                default:
   5941                   vassert(0);
   5942             }
   5943             if (Q) {
   5944                reg_m = newTemp(Ity_V128);
   5945                res = newTemp(Ity_V128);
   5946                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   5947                assign(reg_m, getQReg(mreg));
   5948                switch (size) {
   5949                   case 0:
   5950                      add = Iop_Add8x16;
   5951                      op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
   5952                      break;
   5953                   case 1:
   5954                      add = Iop_Add16x8;
   5955                      op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   5956                      break;
   5957                   case 2:
   5958                      add = Iop_Add32x4;
   5959                      op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   5960                      break;
   5961                   case 3:
   5962                      add = Iop_Add64x2;
   5963                      op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
   5964                      break;
   5965                   default:
   5966                      vassert(0);
   5967                }
   5968             } else {
   5969                reg_m = newTemp(Ity_I64);
   5970                res = newTemp(Ity_I64);
   5971                imm_val = mkU64(imm);
   5972                assign(reg_m, getDRegI64(mreg));
   5973                switch (size) {
   5974                   case 0:
   5975                      add = Iop_Add8x8;
   5976                      op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
   5977                      break;
   5978                   case 1:
   5979                      add = Iop_Add16x4;
   5980                      op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
   5981                      break;
   5982                   case 2:
   5983                      add = Iop_Add32x2;
   5984                      op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
   5985                      break;
   5986                   case 3:
   5987                      add = Iop_Add64;
   5988                      op = U ? Iop_Shr64 : Iop_Sar64;
   5989                      break;
   5990                   default:
   5991                      vassert(0);
   5992                }
   5993             }
   5994             assign(res,
   5995                    binop(add,
   5996                          binop(op,
   5997                                mkexpr(reg_m),
   5998                                mkU8(shift_imm)),
   5999                          binop(Q ? Iop_AndV128 : Iop_And64,
   6000                                binop(op,
   6001                                      mkexpr(reg_m),
   6002                                      mkU8(shift_imm - 1)),
   6003                                imm_val)));
   6004          } else {
   6005             if (Q) {
   6006                res = newTemp(Ity_V128);
   6007                assign(res, getQReg(mreg));
   6008             } else {
   6009                res = newTemp(Ity_I64);
   6010                assign(res, getDRegI64(mreg));
   6011             }
   6012          }
   6013          if (A == 3) {
   6014             if (Q) {
   6015                putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
   6016                              condT);
   6017             } else {
   6018                putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
   6019                                 condT);
   6020             }
   6021             DIP("vrsra.%c%u %c%u, %c%u, #%u\n",
   6022                 U ? 'u' : 's', 8 << size,
   6023                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6024          } else {
   6025             if (Q) {
   6026                putQReg(dreg, mkexpr(res), condT);
   6027             } else {
   6028                putDRegI64(dreg, mkexpr(res), condT);
   6029             }
   6030             DIP("vrshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
   6031                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6032          }
   6033          return True;
   6034       case 1:
   6035       case 0:
   6036          /* VSHR, VSRA */
   6037          if (Q) {
   6038             reg_m = newTemp(Ity_V128);
   6039             assign(reg_m, getQReg(mreg));
   6040             res = newTemp(Ity_V128);
   6041          } else {
   6042             reg_m = newTemp(Ity_I64);
   6043             assign(reg_m, getDRegI64(mreg));
   6044             res = newTemp(Ity_I64);
   6045          }
   6046          if (Q) {
   6047             switch (size) {
   6048                case 0:
   6049                   op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
   6050                   add = Iop_Add8x16;
   6051                   break;
   6052                case 1:
   6053                   op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   6054                   add = Iop_Add16x8;
   6055                   break;
   6056                case 2:
   6057                   op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   6058                   add = Iop_Add32x4;
   6059                   break;
   6060                case 3:
   6061                   op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
   6062                   add = Iop_Add64x2;
   6063                   break;
   6064                default:
   6065                   vassert(0);
   6066             }
   6067          } else {
   6068             switch (size) {
   6069                case 0:
   6070                   op =  U ? Iop_ShrN8x8 : Iop_SarN8x8;
   6071                   add = Iop_Add8x8;
   6072                   break;
   6073                case 1:
   6074                   op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
   6075                   add = Iop_Add16x4;
   6076                   break;
   6077                case 2:
   6078                   op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
   6079                   add = Iop_Add32x2;
   6080                   break;
   6081                case 3:
   6082                   op = U ? Iop_Shr64 : Iop_Sar64;
   6083                   add = Iop_Add64;
   6084                   break;
   6085                default:
   6086                   vassert(0);
   6087             }
   6088          }
   6089          assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
   6090          if (A == 1) {
   6091             if (Q) {
   6092                putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
   6093                              condT);
   6094             } else {
   6095                putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
   6096                                 condT);
   6097             }
   6098             DIP("vsra.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
   6099                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6100          } else {
   6101             if (Q) {
   6102                putQReg(dreg, mkexpr(res), condT);
   6103             } else {
   6104                putDRegI64(dreg, mkexpr(res), condT);
   6105             }
   6106             DIP("vshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
   6107                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6108          }
   6109          return True;
   6110       case 4:
   6111          /* VSRI */
   6112          if (!U)
   6113             return False;
   6114          if (Q) {
   6115             res = newTemp(Ity_V128);
   6116             mask = newTemp(Ity_V128);
   6117          } else {
   6118             res = newTemp(Ity_I64);
   6119             mask = newTemp(Ity_I64);
   6120          }
   6121          switch (size) {
   6122             case 0: op = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; break;
   6123             case 1: op = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; break;
   6124             case 2: op = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; break;
   6125             case 3: op = Q ? Iop_ShrN64x2 : Iop_Shr64; break;
   6126             default: vassert(0);
   6127          }
   6128          if (Q) {
   6129             assign(mask, binop(op, binop(Iop_64HLtoV128,
   6130                                          mkU64(0xFFFFFFFFFFFFFFFFLL),
   6131                                          mkU64(0xFFFFFFFFFFFFFFFFLL)),
   6132                                mkU8(shift_imm)));
   6133             assign(res, binop(Iop_OrV128,
   6134                               binop(Iop_AndV128,
   6135                                     getQReg(dreg),
   6136                                     unop(Iop_NotV128,
   6137                                          mkexpr(mask))),
   6138                               binop(op,
   6139                                     getQReg(mreg),
   6140                                     mkU8(shift_imm))));
   6141             putQReg(dreg, mkexpr(res), condT);
   6142          } else {
   6143             assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
   6144                                mkU8(shift_imm)));
   6145             assign(res, binop(Iop_Or64,
   6146                               binop(Iop_And64,
   6147                                     getDRegI64(dreg),
   6148                                     unop(Iop_Not64,
   6149                                          mkexpr(mask))),
   6150                               binop(op,
   6151                                     getDRegI64(mreg),
   6152                                     mkU8(shift_imm))));
   6153             putDRegI64(dreg, mkexpr(res), condT);
   6154          }
   6155          DIP("vsri.%u %c%u, %c%u, #%u\n",
   6156              8 << size, Q ? 'q' : 'd', dreg,
   6157              Q ? 'q' : 'd', mreg, shift_imm);
   6158          return True;
   6159       case 5:
   6160          if (U) {
   6161             /* VSLI */
   6162             shift_imm = 8 * (1 << size) - shift_imm;
   6163             if (Q) {
   6164                res = newTemp(Ity_V128);
   6165                mask = newTemp(Ity_V128);
   6166             } else {
   6167                res = newTemp(Ity_I64);
   6168                mask = newTemp(Ity_I64);
   6169             }
   6170             switch (size) {
   6171                case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
   6172                case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
   6173                case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
   6174                case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
   6175                default: vassert(0);
   6176             }
   6177             if (Q) {
   6178                assign(mask, binop(op, binop(Iop_64HLtoV128,
   6179                                             mkU64(0xFFFFFFFFFFFFFFFFLL),
   6180                                             mkU64(0xFFFFFFFFFFFFFFFFLL)),
   6181                                   mkU8(shift_imm)));
   6182                assign(res, binop(Iop_OrV128,
   6183                                  binop(Iop_AndV128,
   6184                                        getQReg(dreg),
   6185                                        unop(Iop_NotV128,
   6186                                             mkexpr(mask))),
   6187                                  binop(op,
   6188                                        getQReg(mreg),
   6189                                        mkU8(shift_imm))));
   6190                putQReg(dreg, mkexpr(res), condT);
   6191             } else {
   6192                assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
   6193                                   mkU8(shift_imm)));
   6194                assign(res, binop(Iop_Or64,
   6195                                  binop(Iop_And64,
   6196                                        getDRegI64(dreg),
   6197                                        unop(Iop_Not64,
   6198                                             mkexpr(mask))),
   6199                                  binop(op,
   6200                                        getDRegI64(mreg),
   6201                                        mkU8(shift_imm))));
   6202                putDRegI64(dreg, mkexpr(res), condT);
   6203             }
   6204             DIP("vsli.%u %c%u, %c%u, #%u\n",
   6205                 8 << size, Q ? 'q' : 'd', dreg,
   6206                 Q ? 'q' : 'd', mreg, shift_imm);
   6207             return True;
   6208          } else {
   6209             /* VSHL #imm */
   6210             shift_imm = 8 * (1 << size) - shift_imm;
   6211             if (Q) {
   6212                res = newTemp(Ity_V128);
   6213             } else {
   6214                res = newTemp(Ity_I64);
   6215             }
   6216             switch (size) {
   6217                case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
   6218                case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
   6219                case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
   6220                case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
   6221                default: vassert(0);
   6222             }
   6223             assign(res, binop(op, Q ? getQReg(mreg) : getDRegI64(mreg),
   6224                      mkU8(shift_imm)));
   6225             if (Q) {
   6226                putQReg(dreg, mkexpr(res), condT);
   6227             } else {
   6228                putDRegI64(dreg, mkexpr(res), condT);
   6229             }
   6230             DIP("vshl.i%u %c%u, %c%u, #%u\n",
   6231                 8 << size, Q ? 'q' : 'd', dreg,
   6232                 Q ? 'q' : 'd', mreg, shift_imm);
   6233             return True;
   6234          }
   6235          break;
   6236       case 6:
   6237       case 7:
   6238          /* VQSHL, VQSHLU */
   6239          shift_imm = 8 * (1 << size) - shift_imm;
   6240          if (U) {
   6241             if (A & 1) {
   6242                switch (size) {
   6243                   case 0:
   6244                      op = Q ? Iop_QShlN8x16 : Iop_QShlN8x8;
   6245                      op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   6246                      break;
   6247                   case 1:
   6248                      op = Q ? Iop_QShlN16x8 : Iop_QShlN16x4;
   6249                      op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   6250                      break;
   6251                   case 2:
   6252                      op = Q ? Iop_QShlN32x4 : Iop_QShlN32x2;
   6253                      op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   6254                      break;
   6255                   case 3:
   6256                      op = Q ? Iop_QShlN64x2 : Iop_QShlN64x1;
   6257                      op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
   6258                      break;
   6259                   default:
   6260                      vassert(0);
   6261                }
   6262                DIP("vqshl.u%u %c%u, %c%u, #%u\n",
   6263                    8 << size,
   6264                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6265             } else {
   6266                switch (size) {
   6267                   case 0:
   6268                      op = Q ? Iop_QShlN8Sx16 : Iop_QShlN8Sx8;
   6269                      op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   6270                      break;
   6271                   case 1:
   6272                      op = Q ? Iop_QShlN16Sx8 : Iop_QShlN16Sx4;
   6273                      op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   6274                      break;
   6275                   case 2:
   6276                      op = Q ? Iop_QShlN32Sx4 : Iop_QShlN32Sx2;
   6277                      op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   6278                      break;
   6279                   case 3:
   6280                      op = Q ? Iop_QShlN64Sx2 : Iop_QShlN64Sx1;
   6281                      op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
   6282                      break;
   6283                   default:
   6284                      vassert(0);
   6285                }
   6286                DIP("vqshlu.s%u %c%u, %c%u, #%u\n",
   6287                    8 << size,
   6288                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6289             }
   6290          } else {
   6291             if (!(A & 1))
   6292                return False;
   6293             switch (size) {
   6294                case 0:
   6295                   op = Q ? Iop_QSalN8x16 : Iop_QSalN8x8;
   6296                   op_rev = Q ? Iop_SarN8x16 : Iop_SarN8x8;
   6297                   break;
   6298                case 1:
   6299                   op = Q ? Iop_QSalN16x8 : Iop_QSalN16x4;
   6300                   op_rev = Q ? Iop_SarN16x8 : Iop_SarN16x4;
   6301                   break;
   6302                case 2:
   6303                   op = Q ? Iop_QSalN32x4 : Iop_QSalN32x2;
   6304                   op_rev = Q ? Iop_SarN32x4 : Iop_SarN32x2;
   6305                   break;
   6306                case 3:
   6307                   op = Q ? Iop_QSalN64x2 : Iop_QSalN64x1;
   6308                   op_rev = Q ? Iop_SarN64x2 : Iop_Sar64;
   6309                   break;
   6310                default:
   6311                   vassert(0);
   6312             }
   6313             DIP("vqshl.s%u %c%u, %c%u, #%u\n",
   6314                 8 << size,
   6315                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6316          }
   6317          if (Q) {
   6318             tmp = newTemp(Ity_V128);
   6319             res = newTemp(Ity_V128);
   6320             reg_m = newTemp(Ity_V128);
   6321             assign(reg_m, getQReg(mreg));
   6322          } else {
   6323             tmp = newTemp(Ity_I64);
   6324             res = newTemp(Ity_I64);
   6325             reg_m = newTemp(Ity_I64);
   6326             assign(reg_m, getDRegI64(mreg));
   6327          }
   6328          assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
   6329 #ifndef DISABLE_QC_FLAG
   6330          assign(tmp, binop(op_rev, mkexpr(res), mkU8(shift_imm)));
   6331          setFlag_QC(mkexpr(tmp), mkexpr(reg_m), Q, condT);
   6332 #endif
   6333          if (Q)
   6334             putQReg(dreg, mkexpr(res), condT);
   6335          else
   6336             putDRegI64(dreg, mkexpr(res), condT);
   6337          return True;
   6338       case 8:
   6339          if (!U) {
   6340             if (L == 1)
   6341                return False;
   6342             size++;
   6343             dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   6344             mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   6345             if (mreg & 1)
   6346                return False;
   6347             mreg >>= 1;
   6348             if (!B) {
   6349                /* VSHRN*/
   6350                IROp narOp;
   6351                reg_m = newTemp(Ity_V128);
   6352                assign(reg_m, getQReg(mreg));
   6353                res = newTemp(Ity_I64);
   6354                switch (size) {
   6355                   case 1:
   6356                      op = Iop_ShrN16x8;
   6357                      narOp = Iop_NarrowUn16to8x8;
   6358                      break;
   6359                   case 2:
   6360                      op = Iop_ShrN32x4;
   6361                      narOp = Iop_NarrowUn32to16x4;
   6362                      break;
   6363                   case 3:
   6364                      op = Iop_ShrN64x2;
   6365                      narOp = Iop_NarrowUn64to32x2;
   6366                      break;
   6367                   default:
   6368                      vassert(0);
   6369                }
   6370                assign(res, unop(narOp,
   6371                                 binop(op,
   6372                                       mkexpr(reg_m),
   6373                                       mkU8(shift_imm))));
   6374                putDRegI64(dreg, mkexpr(res), condT);
   6375                DIP("vshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
   6376                    shift_imm);
   6377                return True;
   6378             } else {
   6379                /* VRSHRN   */
   6380                IROp addOp, shOp, narOp;
   6381                IRExpr *imm_val;
   6382                reg_m = newTemp(Ity_V128);
   6383                assign(reg_m, getQReg(mreg));
   6384                res = newTemp(Ity_I64);
   6385                imm = 1L;
   6386                switch (size) {
   6387                   case 0: imm = (imm <<  8) | imm; /* fall through */
   6388                   case 1: imm = (imm << 16) | imm; /* fall through */
   6389                   case 2: imm = (imm << 32) | imm; /* fall through */
   6390                   case 3: break;
   6391                   default: vassert(0);
   6392                }
   6393                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   6394                switch (size) {
   6395                   case 1:
   6396                      addOp = Iop_Add16x8;
   6397                      shOp = Iop_ShrN16x8;
   6398                      narOp = Iop_NarrowUn16to8x8;
   6399                      break;
   6400                   case 2:
   6401                      addOp = Iop_Add32x4;
   6402                      shOp = Iop_ShrN32x4;
   6403                      narOp = Iop_NarrowUn32to16x4;
   6404                      break;
   6405                   case 3:
   6406                      addOp = Iop_Add64x2;
   6407                      shOp = Iop_ShrN64x2;
   6408                      narOp = Iop_NarrowUn64to32x2;
   6409                      break;
   6410                   default:
   6411                      vassert(0);
   6412                }
   6413                assign(res, unop(narOp,
   6414                                 binop(addOp,
   6415                                       binop(shOp,
   6416                                             mkexpr(reg_m),
   6417                                             mkU8(shift_imm)),
   6418                                       binop(Iop_AndV128,
   6419                                             binop(shOp,
   6420                                                   mkexpr(reg_m),
   6421                                                   mkU8(shift_imm - 1)),
   6422                                             imm_val))));
   6423                putDRegI64(dreg, mkexpr(res), condT);
   6424                if (shift_imm == 0) {
   6425                   DIP("vmov%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
   6426                       shift_imm);
   6427                } else {
   6428                   DIP("vrshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
   6429                       shift_imm);
   6430                }
   6431                return True;
   6432             }
   6433          } else {
   6434             /* fall through */
   6435          }
   6436       case 9:
   6437          dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   6438          mreg = ((theInstr >>  1) & 0x10) | (theInstr & 0xF);
   6439          if (mreg & 1)
   6440             return False;
   6441          mreg >>= 1;
   6442          size++;
   6443          if ((theInstr >> 8) & 1) {
   6444             switch (size) {
   6445                case 1:
   6446                   op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   6447                   cvt = U ? Iop_QNarrowUn16Uto8Ux8 : Iop_QNarrowUn16Sto8Sx8;
   6448                   cvt2 = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
   6449                   break;
   6450                case 2:
   6451                   op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   6452                   cvt = U ? Iop_QNarrowUn32Uto16Ux4 : Iop_QNarrowUn32Sto16Sx4;
   6453                   cvt2 = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
   6454                   break;
   6455                case 3:
   6456                   op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
   6457                   cvt = U ? Iop_QNarrowUn64Uto32Ux2 : Iop_QNarrowUn64Sto32Sx2;
   6458                   cvt2 = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
   6459                   break;
   6460                default:
   6461                   vassert(0);
   6462             }
   6463             DIP("vq%sshrn.%c%u d%u, q%u, #%u\n", B ? "r" : "",
   6464                 U ? 'u' : 's', 8 << size, dreg, mreg, shift_imm);
   6465          } else {
   6466             vassert(U);
   6467             switch (size) {
   6468                case 1:
   6469                   op = Iop_SarN16x8;
   6470                   cvt = Iop_QNarrowUn16Sto8Ux8;
   6471                   cvt2 = Iop_Widen8Uto16x8;
   6472                   break;
   6473                case 2:
   6474                   op = Iop_SarN32x4;
   6475                   cvt = Iop_QNarrowUn32Sto16Ux4;
   6476                   cvt2 = Iop_Widen16Uto32x4;
   6477                   break;
   6478                case 3:
   6479                   op = Iop_SarN64x2;
   6480                   cvt = Iop_QNarrowUn64Sto32Ux2;
   6481                   cvt2 = Iop_Widen32Uto64x2;
   6482                   break;
   6483                default:
   6484                   vassert(0);
   6485             }
   6486             DIP("vq%sshrun.s%u d%u, q%u, #%u\n", B ? "r" : "",
   6487                 8 << size, dreg, mreg, shift_imm);
   6488          }
   6489          if (B) {
   6490             if (shift_imm > 0) {
   6491                imm = 1;
   6492                switch (size) {
   6493                   case 1: imm = (imm << 16) | imm; /* fall through */
   6494                   case 2: imm = (imm << 32) | imm; /* fall through */
   6495                   case 3: break;
   6496                   case 0: default: vassert(0);
   6497                }
   6498                switch (size) {
   6499                   case 1: add = Iop_Add16x8; break;
   6500                   case 2: add = Iop_Add32x4; break;
   6501                   case 3: add = Iop_Add64x2; break;
   6502                   case 0: default: vassert(0);
   6503                }
   6504             }
   6505          }
   6506          reg_m = newTemp(Ity_V128);
   6507          res = newTemp(Ity_V128);
   6508          assign(reg_m, getQReg(mreg));
   6509          if (B) {
   6510             /* VQRSHRN, VQRSHRUN */
   6511             assign(res, binop(add,
   6512                               binop(op, mkexpr(reg_m), mkU8(shift_imm)),
   6513                               binop(Iop_AndV128,
   6514                                     binop(op,
   6515                                           mkexpr(reg_m),
   6516                                           mkU8(shift_imm - 1)),
   6517                                     mkU128(imm))));
   6518          } else {
   6519             /* VQSHRN, VQSHRUN */
   6520             assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
   6521          }
   6522 #ifndef DISABLE_QC_FLAG
   6523          setFlag_QC(unop(cvt2, unop(cvt, mkexpr(res))), mkexpr(res),
   6524                     True, condT);
   6525 #endif
   6526          putDRegI64(dreg, unop(cvt, mkexpr(res)), condT);
   6527          return True;
   6528       case 10:
   6529          /* VSHLL
   6530             VMOVL ::= VSHLL #0 */
   6531          if (B)
   6532             return False;
   6533          if (dreg & 1)
   6534             return False;
   6535          dreg >>= 1;
   6536          shift_imm = (8 << size) - shift_imm;
   6537          res = newTemp(Ity_V128);
   6538          switch (size) {
   6539             case 0:
   6540                op = Iop_ShlN16x8;
   6541                cvt = U ? Iop_Widen8Uto16x8 : Iop_Widen8Sto16x8;
   6542                break;
   6543             case 1:
   6544                op = Iop_ShlN32x4;
   6545                cvt = U ? Iop_Widen16Uto32x4 : Iop_Widen16Sto32x4;
   6546                break;
   6547             case 2:
   6548                op = Iop_ShlN64x2;
   6549                cvt = U ? Iop_Widen32Uto64x2 : Iop_Widen32Sto64x2;
   6550                break;
   6551             case 3:
   6552                return False;
   6553             default:
   6554                vassert(0);
   6555          }
   6556          assign(res, binop(op, unop(cvt, getDRegI64(mreg)), mkU8(shift_imm)));
   6557          putQReg(dreg, mkexpr(res), condT);
   6558          if (shift_imm == 0) {
   6559             DIP("vmovl.%c%u q%u, d%u\n", U ? 'u' : 's', 8 << size,
   6560                 dreg, mreg);
   6561          } else {
   6562             DIP("vshll.%c%u q%u, d%u, #%u\n", U ? 'u' : 's', 8 << size,
   6563                 dreg, mreg, shift_imm);
   6564          }
   6565          return True;
   6566       case 14:
   6567       case 15:
   6568          /* VCVT floating-point <-> fixed-point */
   6569          if ((theInstr >> 8) & 1) {
   6570             if (U) {
   6571                op = Q ? Iop_F32ToFixed32Ux4_RZ : Iop_F32ToFixed32Ux2_RZ;
   6572             } else {
   6573                op = Q ? Iop_F32ToFixed32Sx4_RZ : Iop_F32ToFixed32Sx2_RZ;
   6574             }
   6575             DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
   6576                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
   6577                 64 - ((theInstr >> 16) & 0x3f));
   6578          } else {
   6579             if (U) {
   6580                op = Q ? Iop_Fixed32UToF32x4_RN : Iop_Fixed32UToF32x2_RN;
   6581             } else {
   6582                op = Q ? Iop_Fixed32SToF32x4_RN : Iop_Fixed32SToF32x2_RN;
   6583             }
   6584             DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
   6585                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
   6586                 64 - ((theInstr >> 16) & 0x3f));
   6587          }
   6588          if (((theInstr >> 21) & 1) == 0)
   6589             return False;
   6590          if (Q) {
   6591             putQReg(dreg, binop(op, getQReg(mreg),
   6592                      mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
   6593          } else {
   6594             putDRegI64(dreg, binop(op, getDRegI64(mreg),
   6595                        mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
   6596          }
   6597          return True;
   6598       default:
   6599          return False;
   6600 
   6601    }
   6602    return False;
   6603 }
   6604 
   6605 /* A7.4.5 Two registers, miscellaneous */
   6606 static
   6607 Bool dis_neon_data_2reg_misc ( UInt theInstr, IRTemp condT )
   6608 {
   6609    UInt A = (theInstr >> 16) & 3;
   6610    UInt B = (theInstr >> 6) & 0x1f;
   6611    UInt Q = (theInstr >> 6) & 1;
   6612    UInt U = (theInstr >> 24) & 1;
   6613    UInt size = (theInstr >> 18) & 3;
   6614    UInt dreg = get_neon_d_regno(theInstr);
   6615    UInt mreg = get_neon_m_regno(theInstr);
   6616    UInt F = (theInstr >> 10) & 1;
   6617    IRTemp arg_d;
   6618    IRTemp arg_m;
   6619    IRTemp res;
   6620    switch (A) {
   6621       case 0:
   6622          if (Q) {
   6623             arg_m = newTemp(Ity_V128);
   6624             res = newTemp(Ity_V128);
   6625             assign(arg_m, getQReg(mreg));
   6626          } else {
   6627             arg_m = newTemp(Ity_I64);
   6628             res = newTemp(Ity_I64);
   6629             assign(arg_m, getDRegI64(mreg));
   6630          }
   6631          switch (B >> 1) {
   6632             case 0: {
   6633                /* VREV64 */
   6634                IROp op;
   6635                switch (size) {
   6636                   case 0:
   6637                      op = Q ? Iop_Reverse64_8x16 : Iop_Reverse64_8x8;
   6638                      break;
   6639                   case 1:
   6640                      op = Q ? Iop_Reverse64_16x8 : Iop_Reverse64_16x4;
   6641                      break;
   6642                   case 2:
   6643                      op = Q ? Iop_Reverse64_32x4 : Iop_Reverse64_32x2;
   6644                      break;
   6645                   case 3:
   6646                      return False;
   6647                   default:
   6648                      vassert(0);
   6649                }
   6650                assign(res, unop(op, mkexpr(arg_m)));
   6651                DIP("vrev64.%u %c%u, %c%u\n", 8 << size,
   6652                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6653                break;
   6654             }
   6655             case 1: {
   6656                /* VREV32 */
   6657                IROp op;
   6658                switch (size) {
   6659                   case 0:
   6660                      op = Q ? Iop_Reverse32_8x16 : Iop_Reverse32_8x8;
   6661                      break;
   6662                   case 1:
   6663                      op = Q ? Iop_Reverse32_16x8 : Iop_Reverse32_16x4;
   6664                      break;
   6665                   case 2:
   6666                   case 3:
   6667                      return False;
   6668                   default:
   6669                      vassert(0);
   6670                }
   6671                assign(res, unop(op, mkexpr(arg_m)));
   6672                DIP("vrev32.%u %c%u, %c%u\n", 8 << size,
   6673                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6674                break;
   6675             }
   6676             case 2: {
   6677                /* VREV16 */
   6678                IROp op;
   6679                switch (size) {
   6680                   case 0:
   6681                      op = Q ? Iop_Reverse16_8x16 : Iop_Reverse16_8x8;
   6682                      break;
   6683                   case 1:
   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("vrev16.%u %c%u, %c%u\n", 8 << size,
   6692                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6693                break;
   6694             }
   6695             case 3:
   6696                return False;
   6697             case 4:
   6698             case 5: {
   6699                /* VPADDL */
   6700                IROp op;
   6701                U = (theInstr >> 7) & 1;
   6702                if (Q) {
   6703                   switch (size) {
   6704                      case 0: op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; break;
   6705                      case 1: op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; break;
   6706                      case 2: op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; break;
   6707                      case 3: return False;
   6708                      default: vassert(0);
   6709                   }
   6710                } else {
   6711                   switch (size) {
   6712                      case 0: op = U ? Iop_PwAddL8Ux8  : Iop_PwAddL8Sx8;  break;
   6713                      case 1: op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; break;
   6714                      case 2: op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; break;
   6715                      case 3: return False;
   6716                      default: vassert(0);
   6717                   }
   6718                }
   6719                assign(res, unop(op, mkexpr(arg_m)));
   6720                DIP("vpaddl.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
   6721                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6722                break;
   6723             }
   6724             case 6:
   6725             case 7:
   6726                return False;
   6727             case 8: {
   6728                /* VCLS */
   6729                IROp op;
   6730                switch (size) {
   6731                   case 0: op = Q ? Iop_Cls8Sx16 : Iop_Cls8Sx8; break;
   6732                   case 1: op = Q ? Iop_Cls16Sx8 : Iop_Cls16Sx4; break;
   6733                   case 2: op = Q ? Iop_Cls32Sx4 : Iop_Cls32Sx2; break;
   6734                   case 3: return False;
   6735                   default: vassert(0);
   6736                }
   6737                assign(res, unop(op, mkexpr(arg_m)));
   6738                DIP("vcls.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6739                    Q ? 'q' : 'd', mreg);
   6740                break;
   6741             }
   6742             case 9: {
   6743                /* VCLZ */
   6744                IROp op;
   6745                switch (size) {
   6746                   case 0: op = Q ? Iop_Clz8Sx16 : Iop_Clz8Sx8; break;
   6747                   case 1: op = Q ? Iop_Clz16Sx8 : Iop_Clz16Sx4; break;
   6748                   case 2: op = Q ? Iop_Clz32Sx4 : Iop_Clz32Sx2; break;
   6749                   case 3: return False;
   6750                   default: vassert(0);
   6751                }
   6752                assign(res, unop(op, mkexpr(arg_m)));
   6753                DIP("vclz.i%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6754                    Q ? 'q' : 'd', mreg);
   6755                break;
   6756             }
   6757             case 10:
   6758                /* VCNT */
   6759                assign(res, unop(Q ? Iop_Cnt8x16 : Iop_Cnt8x8, mkexpr(arg_m)));
   6760                DIP("vcnt.8 %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
   6761                    mreg);
   6762                break;
   6763             case 11:
   6764                /* VMVN */
   6765                if (Q)
   6766                   assign(res, unop(Iop_NotV128, mkexpr(arg_m)));
   6767                else
   6768                   assign(res, unop(Iop_Not64, mkexpr(arg_m)));
   6769                DIP("vmvn %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
   6770                    mreg);
   6771                break;
   6772             case 12:
   6773             case 13: {
   6774                /* VPADAL */
   6775                IROp op, add_op;
   6776                U = (theInstr >> 7) & 1;
   6777                if (Q) {
   6778                   switch (size) {
   6779                      case 0:
   6780                         op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16;
   6781                         add_op = Iop_Add16x8;
   6782                         break;
   6783                      case 1:
   6784                         op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8;
   6785                         add_op = Iop_Add32x4;
   6786                         break;
   6787                      case 2:
   6788                         op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4;
   6789                         add_op = Iop_Add64x2;
   6790                         break;
   6791                      case 3:
   6792                         return False;
   6793                      default:
   6794                         vassert(0);
   6795                   }
   6796                } else {
   6797                   switch (size) {
   6798                      case 0:
   6799                         op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8;
   6800                         add_op = Iop_Add16x4;
   6801                         break;
   6802                      case 1:
   6803                         op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4;
   6804                         add_op = Iop_Add32x2;
   6805                         break;
   6806                      case 2:
   6807                         op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2;
   6808                         add_op = Iop_Add64;
   6809                         break;
   6810                      case 3:
   6811                         return False;
   6812                      default:
   6813                         vassert(0);
   6814                   }
   6815                }
   6816                if (Q) {
   6817                   arg_d = newTemp(Ity_V128);
   6818                   assign(arg_d, getQReg(dreg));
   6819                } else {
   6820                   arg_d = newTemp(Ity_I64);
   6821                   assign(arg_d, getDRegI64(dreg));
   6822                }
   6823                assign(res, binop(add_op, unop(op, mkexpr(arg_m)),
   6824                                          mkexpr(arg_d)));
   6825                DIP("vpadal.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
   6826                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6827                break;
   6828             }
   6829             case 14: {
   6830                /* VQABS */
   6831                IROp op_sub, op_qsub, op_cmp;
   6832                IRTemp mask, tmp;
   6833                IRExpr *zero1, *zero2;
   6834                IRExpr *neg, *neg2;
   6835                if (Q) {
   6836                   zero1 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6837                   zero2 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6838                   mask = newTemp(Ity_V128);
   6839                   tmp = newTemp(Ity_V128);
   6840                } else {
   6841                   zero1 = mkU64(0);
   6842                   zero2 = mkU64(0);
   6843                   mask = newTemp(Ity_I64);
   6844                   tmp = newTemp(Ity_I64);
   6845                }
   6846                switch (size) {
   6847                   case 0:
   6848                      op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   6849                      op_qsub = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
   6850                      op_cmp = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   6851                      break;
   6852                   case 1:
   6853                      op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   6854                      op_qsub = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
   6855                      op_cmp = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4;
   6856                      break;
   6857                   case 2:
   6858                      op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   6859                      op_qsub = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
   6860                      op_cmp = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2;
   6861                      break;
   6862                   case 3:
   6863                      return False;
   6864                   default:
   6865                      vassert(0);
   6866                }
   6867                assign(mask, binop(op_cmp, mkexpr(arg_m), zero1));
   6868                neg = binop(op_qsub, zero2, mkexpr(arg_m));
   6869                neg2 = binop(op_sub, zero2, mkexpr(arg_m));
   6870                assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
   6871                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6872                                        mkexpr(mask),
   6873                                        mkexpr(arg_m)),
   6874                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6875                                        unop(Q ? Iop_NotV128 : Iop_Not64,
   6876                                             mkexpr(mask)),
   6877                                        neg)));
   6878 #ifndef DISABLE_QC_FLAG
   6879                assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
   6880                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6881                                        mkexpr(mask),
   6882                                        mkexpr(arg_m)),
   6883                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6884                                        unop(Q ? Iop_NotV128 : Iop_Not64,
   6885                                             mkexpr(mask)),
   6886                                        neg2)));
   6887                setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
   6888 #endif
   6889                DIP("vqabs.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6890                    Q ? 'q' : 'd', mreg);
   6891                break;
   6892             }
   6893             case 15: {
   6894                /* VQNEG */
   6895                IROp op, op2;
   6896                IRExpr *zero;
   6897                if (Q) {
   6898                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6899                } else {
   6900                   zero = mkU64(0);
   6901                }
   6902                switch (size) {
   6903                   case 0:
   6904                      op = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
   6905                      op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   6906                      break;
   6907                   case 1:
   6908                      op = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
   6909                      op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   6910                      break;
   6911                   case 2:
   6912                      op = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
   6913                      op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   6914                      break;
   6915                   case 3:
   6916                      return False;
   6917                   default:
   6918                      vassert(0);
   6919                }
   6920                assign(res, binop(op, zero, mkexpr(arg_m)));
   6921 #ifndef DISABLE_QC_FLAG
   6922                setFlag_QC(mkexpr(res), binop(op2, zero, mkexpr(arg_m)),
   6923                           Q, condT);
   6924 #endif
   6925                DIP("vqneg.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6926                    Q ? 'q' : 'd', mreg);
   6927                break;
   6928             }
   6929             default:
   6930                vassert(0);
   6931          }
   6932          if (Q) {
   6933             putQReg(dreg, mkexpr(res), condT);
   6934          } else {
   6935             putDRegI64(dreg, mkexpr(res), condT);
   6936          }
   6937          return True;
   6938       case 1:
   6939          if (Q) {
   6940             arg_m = newTemp(Ity_V128);
   6941             res = newTemp(Ity_V128);
   6942             assign(arg_m, getQReg(mreg));
   6943          } else {
   6944             arg_m = newTemp(Ity_I64);
   6945             res = newTemp(Ity_I64);
   6946             assign(arg_m, getDRegI64(mreg));
   6947          }
   6948          switch ((B >> 1) & 0x7) {
   6949             case 0: {
   6950                /* VCGT #0 */
   6951                IRExpr *zero;
   6952                IROp op;
   6953                if (Q) {
   6954                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6955                } else {
   6956                   zero = mkU64(0);
   6957                }
   6958                if (F) {
   6959                   switch (size) {
   6960                      case 0: case 1: case 3: return False;
   6961                      case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
   6962                      default: vassert(0);
   6963                   }
   6964                } else {
   6965                   switch (size) {
   6966                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   6967                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   6968                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   6969                      case 3: return False;
   6970                      default: vassert(0);
   6971                   }
   6972                }
   6973                assign(res, binop(op, mkexpr(arg_m), zero));
   6974                DIP("vcgt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   6975                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6976                break;
   6977             }
   6978             case 1: {
   6979                /* VCGE #0 */
   6980                IROp op;
   6981                IRExpr *zero;
   6982                if (Q) {
   6983                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6984                } else {
   6985                   zero = mkU64(0);
   6986                }
   6987                if (F) {
   6988                   switch (size) {
   6989                      case 0: case 1: case 3: return False;
   6990                      case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
   6991                      default: vassert(0);
   6992                   }
   6993                   assign(res, binop(op, mkexpr(arg_m), zero));
   6994                } else {
   6995                   switch (size) {
   6996                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   6997                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   6998                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   6999                      case 3: return False;
   7000                      default: vassert(0);
   7001                   }
   7002                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   7003                                    binop(op, zero, mkexpr(arg_m))));
   7004                }
   7005                DIP("vcge.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   7006                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7007                break;
   7008             }
   7009             case 2: {
   7010                /* VCEQ #0 */
   7011                IROp op;
   7012                IRExpr *zero;
   7013                if (F) {
   7014                   if (Q) {
   7015                      zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7016                   } else {
   7017                      zero = mkU64(0);
   7018                   }
   7019                   switch (size) {
   7020                      case 0: case 1: case 3: return False;
   7021                      case 2: op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; break;
   7022                      default: vassert(0);
   7023                   }
   7024                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7025                } else {
   7026                   switch (size) {
   7027                      case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
   7028                      case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
   7029                      case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
   7030                      case 3: return False;
   7031                      default: vassert(0);
   7032                   }
   7033                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   7034                                    unop(op, mkexpr(arg_m))));
   7035                }
   7036                DIP("vceq.%c%u %c%u, %c%u, #0\n", F ? 'f' : 'i', 8 << size,
   7037                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7038                break;
   7039             }
   7040             case 3: {
   7041                /* VCLE #0 */
   7042                IRExpr *zero;
   7043                IROp op;
   7044                if (Q) {
   7045                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7046                } else {
   7047                   zero = mkU64(0);
   7048                }
   7049                if (F) {
   7050                   switch (size) {
   7051                      case 0: case 1: case 3: return False;
   7052                      case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
   7053                      default: vassert(0);
   7054                   }
   7055                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7056                } else {
   7057                   switch (size) {
   7058                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   7059                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   7060                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   7061                      case 3: return False;
   7062                      default: vassert(0);
   7063                   }
   7064                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   7065                                    binop(op, mkexpr(arg_m), zero)));
   7066                }
   7067                DIP("vcle.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   7068                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7069                break;
   7070             }
   7071             case 4: {
   7072                /* VCLT #0 */
   7073                IROp op;
   7074                IRExpr *zero;
   7075                if (Q) {
   7076                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7077                } else {
   7078                   zero = mkU64(0);
   7079                }
   7080                if (F) {
   7081                   switch (size) {
   7082                      case 0: case 1: case 3: return False;
   7083                      case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
   7084                      default: vassert(0);
   7085                   }
   7086                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7087                } else {
   7088                   switch (size) {
   7089                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   7090                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   7091                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   7092                      case 3: return False;
   7093                      default: vassert(0);
   7094                   }
   7095                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7096                }
   7097                DIP("vclt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   7098                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7099                break;
   7100             }
   7101             case 5:
   7102                return False;
   7103             case 6: {
   7104                /* VABS */
   7105                if (!F) {
   7106                   IROp op;
   7107                   switch(size) {
   7108                      case 0: op = Q ? Iop_Abs8x16 : Iop_Abs8x8; break;
   7109                      case 1: op = Q ? Iop_Abs16x8 : Iop_Abs16x4; break;
   7110                      case 2: op = Q ? Iop_Abs32x4 : Iop_Abs32x2; break;
   7111                      case 3: return False;
   7112                      default: vassert(0);
   7113                   }
   7114                   assign(res, unop(op, mkexpr(arg_m)));
   7115                } else {
   7116                   assign(res, unop(Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2,
   7117                                    mkexpr(arg_m)));
   7118                }
   7119                DIP("vabs.%c%u %c%u, %c%u\n",
   7120                    F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
   7121                    Q ? 'q' : 'd', mreg);
   7122                break;
   7123             }
   7124             case 7: {
   7125                /* VNEG */
   7126                IROp op;
   7127                IRExpr *zero;
   7128                if (F) {
   7129                   switch (size) {
   7130                      case 0: case 1: case 3: return False;
   7131                      case 2: op = Q ? Iop_Neg32Fx4 : Iop_Neg32Fx2; break;
   7132                      default: vassert(0);
   7133                   }
   7134                   assign(res, unop(op, mkexpr(arg_m)));
   7135                } else {
   7136                   if (Q) {
   7137                      zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7138                   } else {
   7139                      zero = mkU64(0);
   7140                   }
   7141                   switch (size) {
   7142                      case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
   7143                      case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
   7144                      case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
   7145                      case 3: return False;
   7146                      default: vassert(0);
   7147                   }
   7148                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7149                }
   7150                DIP("vneg.%c%u %c%u, %c%u\n",
   7151                    F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
   7152                    Q ? 'q' : 'd', mreg);
   7153                break;
   7154             }
   7155             default:
   7156                vassert(0);
   7157          }
   7158          if (Q) {
   7159             putQReg(dreg, mkexpr(res), condT);
   7160          } else {
   7161             putDRegI64(dreg, mkexpr(res), condT);
   7162          }
   7163          return True;
   7164       case 2:
   7165          if ((B >> 1) == 0) {
   7166             /* VSWP */
   7167             if (Q) {
   7168                arg_m = newTemp(Ity_V128);
   7169                assign(arg_m, getQReg(mreg));
   7170                putQReg(mreg, getQReg(dreg), condT);
   7171                putQReg(dreg, mkexpr(arg_m), condT);
   7172             } else {
   7173                arg_m = newTemp(Ity_I64);
   7174                assign(arg_m, getDRegI64(mreg));
   7175                putDRegI64(mreg, getDRegI64(dreg), condT);
   7176                putDRegI64(dreg, mkexpr(arg_m), condT);
   7177             }
   7178             DIP("vswp %c%u, %c%u\n",
   7179                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7180             return True;
   7181          } else if ((B >> 1) == 1) {
   7182             /* VTRN */
   7183             IROp op_lo, op_hi;
   7184             IRTemp res1, res2;
   7185             if (Q) {
   7186                arg_m = newTemp(Ity_V128);
   7187                arg_d = newTemp(Ity_V128);
   7188                res1 = newTemp(Ity_V128);
   7189                res2 = newTemp(Ity_V128);
   7190                assign(arg_m, getQReg(mreg));
   7191                assign(arg_d, getQReg(dreg));
   7192             } else {
   7193                res1 = newTemp(Ity_I64);
   7194                res2 = newTemp(Ity_I64);
   7195                arg_m = newTemp(Ity_I64);
   7196                arg_d = newTemp(Ity_I64);
   7197                assign(arg_m, getDRegI64(mreg));
   7198                assign(arg_d, getDRegI64(dreg));
   7199             }
   7200             if (Q) {
   7201                switch (size) {
   7202                   case 0:
   7203                      op_lo = Iop_InterleaveOddLanes8x16;
   7204                      op_hi = Iop_InterleaveEvenLanes8x16;
   7205                      break;
   7206                   case 1:
   7207                      op_lo = Iop_InterleaveOddLanes16x8;
   7208                      op_hi = Iop_InterleaveEvenLanes16x8;
   7209                      break;
   7210                   case 2:
   7211                      op_lo = Iop_InterleaveOddLanes32x4;
   7212                      op_hi = Iop_InterleaveEvenLanes32x4;
   7213                      break;
   7214                   case 3:
   7215                      return False;
   7216                   default:
   7217                      vassert(0);
   7218                }
   7219             } else {
   7220                switch (size) {
   7221                   case 0:
   7222                      op_lo = Iop_InterleaveOddLanes8x8;
   7223                      op_hi = Iop_InterleaveEvenLanes8x8;
   7224                      break;
   7225                   case 1:
   7226                      op_lo = Iop_InterleaveOddLanes16x4;
   7227                      op_hi = Iop_InterleaveEvenLanes16x4;
   7228                      break;
   7229                   case 2:
   7230                      op_lo = Iop_InterleaveLO32x2;
   7231                      op_hi = Iop_InterleaveHI32x2;
   7232                      break;
   7233                   case 3:
   7234                      return False;
   7235                   default:
   7236                      vassert(0);
   7237                }
   7238             }
   7239             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
   7240             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
   7241             if (Q) {
   7242                putQReg(dreg, mkexpr(res1), condT);
   7243                putQReg(mreg, mkexpr(res2), condT);
   7244             } else {
   7245                putDRegI64(dreg, mkexpr(res1), condT);
   7246                putDRegI64(mreg, mkexpr(res2), condT);
   7247             }
   7248             DIP("vtrn.%u %c%u, %c%u\n",
   7249                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7250             return True;
   7251          } else if ((B >> 1) == 2) {
   7252             /* VUZP */
   7253             IROp op_lo, op_hi;
   7254             IRTemp res1, res2;
   7255             if (!Q && size == 2)
   7256                return False;
   7257             if (Q) {
   7258                arg_m = newTemp(Ity_V128);
   7259                arg_d = newTemp(Ity_V128);
   7260                res1 = newTemp(Ity_V128);
   7261                res2 = newTemp(Ity_V128);
   7262                assign(arg_m, getQReg(mreg));
   7263                assign(arg_d, getQReg(dreg));
   7264             } else {
   7265                res1 = newTemp(Ity_I64);
   7266                res2 = newTemp(Ity_I64);
   7267                arg_m = newTemp(Ity_I64);
   7268                arg_d = newTemp(Ity_I64);
   7269                assign(arg_m, getDRegI64(mreg));
   7270                assign(arg_d, getDRegI64(dreg));
   7271             }
   7272             switch (size) {
   7273                case 0:
   7274                   op_lo = Q ? Iop_CatOddLanes8x16 : Iop_CatOddLanes8x8;
   7275                   op_hi = Q ? Iop_CatEvenLanes8x16 : Iop_CatEvenLanes8x8;
   7276                   break;
   7277                case 1:
   7278                   op_lo = Q ? Iop_CatOddLanes16x8 : Iop_CatOddLanes16x4;
   7279                   op_hi = Q ? Iop_CatEvenLanes16x8 : Iop_CatEvenLanes16x4;
   7280                   break;
   7281                case 2:
   7282                   op_lo = Iop_CatOddLanes32x4;
   7283                   op_hi = Iop_CatEvenLanes32x4;
   7284                   break;
   7285                case 3:
   7286                   return False;
   7287                default:
   7288                   vassert(0);
   7289             }
   7290             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
   7291             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
   7292             if (Q) {
   7293                putQReg(dreg, mkexpr(res1), condT);
   7294                putQReg(mreg, mkexpr(res2), condT);
   7295             } else {
   7296                putDRegI64(dreg, mkexpr(res1), condT);
   7297                putDRegI64(mreg, mkexpr(res2), condT);
   7298             }
   7299             DIP("vuzp.%u %c%u, %c%u\n",
   7300                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7301             return True;
   7302          } else if ((B >> 1) == 3) {
   7303             /* VZIP */
   7304             IROp op_lo, op_hi;
   7305             IRTemp res1, res2;
   7306             if (!Q && size == 2)
   7307                return False;
   7308             if (Q) {
   7309                arg_m = newTemp(Ity_V128);
   7310                arg_d = newTemp(Ity_V128);
   7311                res1 = newTemp(Ity_V128);
   7312                res2 = newTemp(Ity_V128);
   7313                assign(arg_m, getQReg(mreg));
   7314                assign(arg_d, getQReg(dreg));
   7315             } else {
   7316                res1 = newTemp(Ity_I64);
   7317                res2 = newTemp(Ity_I64);
   7318                arg_m = newTemp(Ity_I64);
   7319                arg_d = newTemp(Ity_I64);
   7320                assign(arg_m, getDRegI64(mreg));
   7321                assign(arg_d, getDRegI64(dreg));
   7322             }
   7323             switch (size) {
   7324                case 0:
   7325                   op_lo = Q ? Iop_InterleaveHI8x16 : Iop_InterleaveHI8x8;
   7326                   op_hi = Q ? Iop_InterleaveLO8x16 : Iop_InterleaveLO8x8;
   7327                   break;
   7328                case 1:
   7329                   op_lo = Q ? Iop_InterleaveHI16x8 : Iop_InterleaveHI16x4;
   7330                   op_hi = Q ? Iop_InterleaveLO16x8 : Iop_InterleaveLO16x4;
   7331                   break;
   7332                case 2:
   7333                   op_lo = Iop_InterleaveHI32x4;
   7334                   op_hi = Iop_InterleaveLO32x4;
   7335                   break;
   7336                case 3:
   7337                   return False;
   7338                default:
   7339                   vassert(0);
   7340             }
   7341             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
   7342             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
   7343             if (Q) {
   7344                putQReg(dreg, mkexpr(res1), condT);
   7345                putQReg(mreg, mkexpr(res2), condT);
   7346             } else {
   7347                putDRegI64(dreg, mkexpr(res1), condT);
   7348                putDRegI64(mreg, mkexpr(res2), condT);
   7349             }
   7350             DIP("vzip.%u %c%u, %c%u\n",
   7351                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7352             return True;
   7353          } else if (B == 8) {
   7354             /* VMOVN */
   7355             IROp op;
   7356             mreg >>= 1;
   7357             switch (size) {
   7358                case 0: op = Iop_NarrowUn16to8x8;  break;
   7359                case 1: op = Iop_NarrowUn32to16x4; break;
   7360                case 2: op = Iop_NarrowUn64to32x2; break;
   7361                case 3: return False;
   7362                default: vassert(0);
   7363             }
   7364             putDRegI64(dreg, unop(op, getQReg(mreg)), condT);
   7365             DIP("vmovn.i%u d%u, q%u\n", 16 << size, dreg, mreg);
   7366             return True;
   7367          } else if (B == 9 || (B >> 1) == 5) {
   7368             /* VQMOVN, VQMOVUN */
   7369             IROp op, op2;
   7370             IRTemp tmp;
   7371             dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   7372             mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   7373             if (mreg & 1)
   7374                return False;
   7375             mreg >>= 1;
   7376             switch (size) {
   7377                case 0: op2 = Iop_NarrowUn16to8x8;  break;
   7378                case 1: op2 = Iop_NarrowUn32to16x4; break;
   7379                case 2: op2 = Iop_NarrowUn64to32x2; break;
   7380                case 3: return False;
   7381                default: vassert(0);
   7382             }
   7383             switch (B & 3) {
   7384                case 0:
   7385                   vassert(0);
   7386                case 1:
   7387                   switch (size) {
   7388                      case 0: op = Iop_QNarrowUn16Sto8Ux8;  break;
   7389                      case 1: op = Iop_QNarrowUn32Sto16Ux4; break;
   7390                      case 2: op = Iop_QNarrowUn64Sto32Ux2; break;
   7391                      case 3: return False;
   7392                      default: vassert(0);
   7393                   }
   7394                   DIP("vqmovun.s%u d%u, q%u\n", 16 << size, dreg, mreg);
   7395                   break;
   7396                case 2:
   7397                   switch (size) {
   7398                      case 0: op = Iop_QNarrowUn16Sto8Sx8;  break;
   7399                      case 1: op = Iop_QNarrowUn32Sto16Sx4; break;
   7400                      case 2: op = Iop_QNarrowUn64Sto32Sx2; break;
   7401                      case 3: return False;
   7402                      default: vassert(0);
   7403                   }
   7404                   DIP("vqmovn.s%u d%u, q%u\n", 16 << size, dreg, mreg);
   7405                   break;
   7406                case 3:
   7407                   switch (size) {
   7408                      case 0: op = Iop_QNarrowUn16Uto8Ux8;  break;
   7409                      case 1: op = Iop_QNarrowUn32Uto16Ux4; break;
   7410                      case 2: op = Iop_QNarrowUn64Uto32Ux2; break;
   7411                      case 3: return False;
   7412                      default: vassert(0);
   7413                   }
   7414                   DIP("vqmovn.u%u d%u, q%u\n", 16 << size, dreg, mreg);
   7415                   break;
   7416                default:
   7417                   vassert(0);
   7418             }
   7419             res = newTemp(Ity_I64);
   7420             tmp = newTemp(Ity_I64);
   7421             assign(res, unop(op, getQReg(mreg)));
   7422 #ifndef DISABLE_QC_FLAG
   7423             assign(tmp, unop(op2, getQReg(mreg)));
   7424             setFlag_QC(mkexpr(res), mkexpr(tmp), False, condT);
   7425 #endif
   7426             putDRegI64(dreg, mkexpr(res), condT);
   7427             return True;
   7428          } else if (B == 12) {
   7429             /* VSHLL (maximum shift) */
   7430             IROp op, cvt;
   7431             UInt shift_imm;
   7432             if (Q)
   7433                return False;
   7434             if (dreg & 1)
   7435                return False;
   7436             dreg >>= 1;
   7437             shift_imm = 8 << size;
   7438             res = newTemp(Ity_V128);
   7439             switch (size) {
   7440                case 0: op = Iop_ShlN16x8; cvt = Iop_Widen8Uto16x8;  break;
   7441                case 1: op = Iop_ShlN32x4; cvt = Iop_Widen16Uto32x4; break;
   7442                case 2: op = Iop_ShlN64x2; cvt = Iop_Widen32Uto64x2; break;
   7443                case 3: return False;
   7444                default: vassert(0);
   7445             }
   7446             assign(res, binop(op, unop(cvt, getDRegI64(mreg)),
   7447                                   mkU8(shift_imm)));
   7448             putQReg(dreg, mkexpr(res), condT);
   7449             DIP("vshll.i%u q%u, d%u, #%u\n", 8 << size, dreg, mreg, 8 << size);
   7450             return True;
   7451          } else if ((B >> 3) == 3 && (B & 3) == 0) {
   7452             /* VCVT (half<->single) */
   7453             /* Half-precision extensions are needed to run this */
   7454             vassert(0); // ATC
   7455             if (((theInstr >> 18) & 3) != 1)
   7456                return False;
   7457             if ((theInstr >> 8) & 1) {
   7458                if (dreg & 1)
   7459                   return False;
   7460                dreg >>= 1;
   7461                putQReg(dreg, unop(Iop_F16toF32x4, getDRegI64(mreg)),
   7462                      condT);
   7463                DIP("vcvt.f32.f16 q%u, d%u\n", dreg, mreg);
   7464             } else {
   7465                if (mreg & 1)
   7466                   return False;
   7467                mreg >>= 1;
   7468                putDRegI64(dreg, unop(Iop_F32toF16x4, getQReg(mreg)),
   7469                                 condT);
   7470                DIP("vcvt.f16.f32 d%u, q%u\n", dreg, mreg);
   7471             }
   7472             return True;
   7473          } else {
   7474             return False;
   7475          }
   7476          vassert(0);
   7477          return True;
   7478       case 3:
   7479          if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) {
   7480             /* VRECPE */
   7481             IROp op;
   7482             F = (theInstr >> 8) & 1;
   7483             if (size != 2)
   7484                return False;
   7485             if (Q) {
   7486                op = F ? Iop_Recip32Fx4 : Iop_Recip32x4;
   7487                putQReg(dreg, unop(op, getQReg(mreg)), condT);
   7488                DIP("vrecpe.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
   7489             } else {
   7490                op = F ? Iop_Recip32Fx2 : Iop_Recip32x2;
   7491                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
   7492                DIP("vrecpe.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
   7493             }
   7494             return True;
   7495          } else if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) {
   7496             /* VRSQRTE */
   7497             IROp op;
   7498             F = (B >> 2) & 1;
   7499             if (size != 2)
   7500                return False;
   7501             if (F) {
   7502                /* fp */
   7503                op = Q ? Iop_Rsqrte32Fx4 : Iop_Rsqrte32Fx2;
   7504             } else {
   7505                /* unsigned int */
   7506                op = Q ? Iop_Rsqrte32x4 : Iop_Rsqrte32x2;
   7507             }
   7508             if (Q) {
   7509                putQReg(dreg, unop(op, getQReg(mreg)), condT);
   7510                DIP("vrsqrte.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
   7511             } else {
   7512                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
   7513                DIP("vrsqrte.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
   7514             }
   7515             return True;
   7516          } else if ((B >> 3) == 3) {
   7517             /* VCVT (fp<->integer) */
   7518             IROp op;
   7519             if (size != 2)
   7520                return False;
   7521             switch ((B >> 1) & 3) {
   7522                case 0:
   7523                   op = Q ? Iop_I32StoFx4 : Iop_I32StoFx2;
   7524                   DIP("vcvt.f32.s32 %c%u, %c%u\n",
   7525                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7526                   break;
   7527                case 1:
   7528                   op = Q ? Iop_I32UtoFx4 : Iop_I32UtoFx2;
   7529                   DIP("vcvt.f32.u32 %c%u, %c%u\n",
   7530                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7531                   break;
   7532                case 2:
   7533                   op = Q ? Iop_FtoI32Sx4_RZ : Iop_FtoI32Sx2_RZ;
   7534                   DIP("vcvt.s32.f32 %c%u, %c%u\n",
   7535                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7536                   break;
   7537                case 3:
   7538                   op = Q ? Iop_FtoI32Ux4_RZ : Iop_FtoI32Ux2_RZ;
   7539                   DIP("vcvt.u32.f32 %c%u, %c%u\n",
   7540                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7541                   break;
   7542                default:
   7543                   vassert(0);
   7544             }
   7545             if (Q) {
   7546                putQReg(dreg, unop(op, getQReg(mreg)), condT);
   7547             } else {
   7548                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
   7549             }
   7550             return True;
   7551          } else {
   7552             return False;
   7553          }
   7554          vassert(0);
   7555          return True;
   7556       default:
   7557          vassert(0);
   7558    }
   7559    return False;
   7560 }
   7561 
   7562 /* A7.4.6 One register and a modified immediate value */
   7563 static
   7564 void ppNeonImm(UInt imm, UInt cmode, UInt op)
   7565 {
   7566    int i;
   7567    switch (cmode) {
   7568       case 0: case 1: case 8: case 9:
   7569          vex_printf("0x%x", imm);
   7570          break;
   7571       case 2: case 3: case 10: case 11:
   7572          vex_printf("0x%x00", imm);
   7573          break;
   7574       case 4: case 5:
   7575          vex_printf("0x%x0000", imm);
   7576          break;
   7577       case 6: case 7:
   7578          vex_printf("0x%x000000", imm);
   7579          break;
   7580       case 12:
   7581          vex_printf("0x%xff", imm);
   7582          break;
   7583       case 13:
   7584          vex_printf("0x%xffff", imm);
   7585          break;
   7586       case 14:
   7587          if (op) {
   7588             vex_printf("0x");
   7589             for (i = 7; i >= 0; i--)
   7590                vex_printf("%s", (imm & (1 << i)) ? "ff" : "00");
   7591          } else {
   7592             vex_printf("0x%x", imm);
   7593          }
   7594          break;
   7595       case 15:
   7596          vex_printf("0x%x", imm);
   7597          break;
   7598    }
   7599 }
   7600 
   7601 static
   7602 const char *ppNeonImmType(UInt cmode, UInt op)
   7603 {
   7604    switch (cmode) {
   7605       case 0 ... 7:
   7606       case 12: case 13:
   7607          return "i32";
   7608       case 8 ... 11:
   7609          return "i16";
   7610       case 14:
   7611          if (op)
   7612             return "i64";
   7613          else
   7614             return "i8";
   7615       case 15:
   7616          if (op)
   7617             vassert(0);
   7618          else
   7619             return "f32";
   7620       default:
   7621          vassert(0);
   7622    }
   7623 }
   7624 
   7625 static
   7626 void DIPimm(UInt imm, UInt cmode, UInt op,
   7627             const char *instr, UInt Q, UInt dreg)
   7628 {
   7629    if (vex_traceflags & VEX_TRACE_FE) {
   7630       vex_printf("%s.%s %c%u, #", instr,
   7631                  ppNeonImmType(cmode, op), Q ? 'q' : 'd', dreg);
   7632       ppNeonImm(imm, cmode, op);
   7633       vex_printf("\n");
   7634    }
   7635 }
   7636 
   7637 static
   7638 Bool dis_neon_data_1reg_and_imm ( UInt theInstr, IRTemp condT )
   7639 {
   7640    UInt dreg = get_neon_d_regno(theInstr);
   7641    ULong imm_raw = ((theInstr >> 17) & 0x80) | ((theInstr >> 12) & 0x70) |
   7642                   (theInstr & 0xf);
   7643    ULong imm_raw_pp = imm_raw;
   7644    UInt cmode = (theInstr >> 8) & 0xf;
   7645    UInt op_bit = (theInstr >> 5) & 1;
   7646    ULong imm = 0;
   7647    UInt Q = (theInstr >> 6) & 1;
   7648    int i, j;
   7649    UInt tmp;
   7650    IRExpr *imm_val;
   7651    IRExpr *expr;
   7652    IRTemp tmp_var;
   7653    switch(cmode) {
   7654       case 7: case 6:
   7655          imm_raw = imm_raw << 8;
   7656          /* fallthrough */
   7657       case 5: case 4:
   7658          imm_raw = imm_raw << 8;
   7659          /* fallthrough */
   7660       case 3: case 2:
   7661          imm_raw = imm_raw << 8;
   7662          /* fallthrough */
   7663       case 0: case 1:
   7664          imm = (imm_raw << 32) | imm_raw;
   7665          break;
   7666       case 11: case 10:
   7667          imm_raw = imm_raw << 8;
   7668          /* fallthrough */
   7669       case 9: case 8:
   7670          imm_raw = (imm_raw << 16) | imm_raw;
   7671          imm = (imm_raw << 32) | imm_raw;
   7672          break;
   7673       case 13:
   7674          imm_raw = (imm_raw << 8) | 0xff;
   7675          /* fallthrough */
   7676       case 12:
   7677          imm_raw = (imm_raw << 8) | 0xff;
   7678          imm = (imm_raw << 32) | imm_raw;
   7679          break;
   7680       case 14:
   7681          if (! op_bit) {
   7682             for(i = 0; i < 8; i++) {
   7683                imm = (imm << 8) | imm_raw;
   7684             }
   7685          } else {
   7686             for(i = 7; i >= 0; i--) {
   7687                tmp = 0;
   7688                for(j = 0; j < 8; j++) {
   7689                   tmp = (tmp << 1) | ((imm_raw >> i) & 1);
   7690                }
   7691                imm = (imm << 8) | tmp;
   7692             }
   7693          }
   7694          break;
   7695       case 15:
   7696          imm = (imm_raw & 0x80) << 5;
   7697          imm |= ((~imm_raw & 0x40) << 5);
   7698          for(i = 1; i <= 4; i++)
   7699             imm |= (imm_raw & 0x40) << i;
   7700          imm |= (imm_raw & 0x7f);
   7701          imm = imm << 19;
   7702          imm = (imm << 32) | imm;
   7703          break;
   7704       default:
   7705          return False;
   7706    }
   7707    if (Q) {
   7708       imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   7709    } else {
   7710       imm_val = mkU64(imm);
   7711    }
   7712    if (((op_bit == 0) &&
   7713       (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 12) == 12))) ||
   7714       ((op_bit == 1) && (cmode == 14))) {
   7715       /* VMOV (immediate) */
   7716       if (Q) {
   7717          putQReg(dreg, imm_val, condT);
   7718       } else {
   7719          putDRegI64(dreg, imm_val, condT);
   7720       }
   7721       DIPimm(imm_raw_pp, cmode, op_bit, "vmov", Q, dreg);
   7722       return True;
   7723    }
   7724    if ((op_bit == 1) &&
   7725       (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 14) == 12))) {
   7726       /* VMVN (immediate) */
   7727       if (Q) {
   7728          putQReg(dreg, unop(Iop_NotV128, imm_val), condT);
   7729       } else {
   7730          putDRegI64(dreg, unop(Iop_Not64, imm_val), condT);
   7731       }
   7732       DIPimm(imm_raw_pp, cmode, op_bit, "vmvn", Q, dreg);
   7733       return True;
   7734    }
   7735    if (Q) {
   7736       tmp_var = newTemp(Ity_V128);
   7737       assign(tmp_var, getQReg(dreg));
   7738    } else {
   7739       tmp_var = newTemp(Ity_I64);
   7740       assign(tmp_var, getDRegI64(dreg));
   7741    }
   7742    if ((op_bit == 0) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
   7743       /* VORR (immediate) */
   7744       if (Q)
   7745          expr = binop(Iop_OrV128, mkexpr(tmp_var), imm_val);
   7746       else
   7747          expr = binop(Iop_Or64, mkexpr(tmp_var), imm_val);
   7748       DIPimm(imm_raw_pp, cmode, op_bit, "vorr", Q, dreg);
   7749    } else if ((op_bit == 1) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
   7750       /* VBIC (immediate) */
   7751       if (Q)
   7752          expr = binop(Iop_AndV128, mkexpr(tmp_var),
   7753                                    unop(Iop_NotV128, imm_val));
   7754       else
   7755          expr = binop(Iop_And64, mkexpr(tmp_var), unop(Iop_Not64, imm_val));
   7756       DIPimm(imm_raw_pp, cmode, op_bit, "vbic", Q, dreg);
   7757    } else {
   7758       return False;
   7759    }
   7760    if (Q)
   7761       putQReg(dreg, expr, condT);
   7762    else
   7763       putDRegI64(dreg, expr, condT);
   7764    return True;
   7765 }
   7766 
   7767 /* A7.4 Advanced SIMD data-processing instructions */
   7768 static
   7769 Bool dis_neon_data_processing ( UInt theInstr, IRTemp condT )
   7770 {
   7771    UInt A = (theInstr >> 19) & 0x1F;
   7772    UInt B = (theInstr >>  8) & 0xF;
   7773    UInt C = (theInstr >>  4) & 0xF;
   7774    UInt U = (theInstr >> 24) & 0x1;
   7775 
   7776    if (! (A & 0x10)) {
   7777       return dis_neon_data_3same(theInstr, condT);
   7778    }
   7779    if (((A & 0x17) == 0x10) && ((C & 0x9) == 0x1)) {
   7780       return dis_neon_data_1reg_and_imm(theInstr, condT);
   7781    }
   7782    if ((C & 1) == 1) {
   7783       return dis_neon_data_2reg_and_shift(theInstr, condT);
   7784    }
   7785    if (((C & 5) == 0) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
   7786       return dis_neon_data_3diff(theInstr, condT);
   7787    }
   7788    if (((C & 5) == 4) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
   7789       return dis_neon_data_2reg_and_scalar(theInstr, condT);
   7790    }
   7791    if ((A & 0x16) == 0x16) {
   7792       if ((U == 0) && ((C & 1) == 0)) {
   7793          return dis_neon_vext(theInstr, condT);
   7794       }
   7795       if ((U != 1) || ((C & 1) == 1))
   7796          return False;
   7797       if ((B & 8) == 0) {
   7798          return dis_neon_data_2reg_misc(theInstr, condT);
   7799       }
   7800       if ((B & 12) == 8) {
   7801          return dis_neon_vtb(theInstr, condT);
   7802       }
   7803       if ((B == 12) && ((C & 9) == 0)) {
   7804          return dis_neon_vdup(theInstr, condT);
   7805       }
   7806    }
   7807    return False;
   7808 }
   7809 
   7810 
   7811 /*------------------------------------------------------------*/
   7812 /*--- NEON loads and stores                                ---*/
   7813 /*------------------------------------------------------------*/
   7814 
   7815 /* For NEON memory operations, we use the standard scheme to handle
   7816    conditionalisation: generate a jump around the instruction if the
   7817    condition is false.  That's only necessary in Thumb mode, however,
   7818    since in ARM mode NEON instructions are unconditional. */
   7819 
   7820 /* A helper function for what follows.  It assumes we already went
   7821    uncond as per comments at the top of this section. */
   7822 static
   7823 void mk_neon_elem_load_to_one_lane( UInt rD, UInt inc, UInt index,
   7824                                     UInt N, UInt size, IRTemp addr )
   7825 {
   7826    UInt i;
   7827    switch (size) {
   7828       case 0:
   7829          putDRegI64(rD, triop(Iop_SetElem8x8, getDRegI64(rD), mkU8(index),
   7830                     loadLE(Ity_I8, mkexpr(addr))), IRTemp_INVALID);
   7831          break;
   7832       case 1:
   7833          putDRegI64(rD, triop(Iop_SetElem16x4, getDRegI64(rD), mkU8(index),
   7834                     loadLE(Ity_I16, mkexpr(addr))), IRTemp_INVALID);
   7835          break;
   7836       case 2:
   7837          putDRegI64(rD, triop(Iop_SetElem32x2, getDRegI64(rD), mkU8(index),
   7838                     loadLE(Ity_I32, mkexpr(addr))), IRTemp_INVALID);
   7839          break;
   7840       default:
   7841          vassert(0);
   7842    }
   7843    for (i = 1; i <= N; i++) {
   7844       switch (size) {
   7845          case 0:
   7846             putDRegI64(rD + i * inc,
   7847                        triop(Iop_SetElem8x8,
   7848                              getDRegI64(rD + i * inc),
   7849                              mkU8(index),
   7850                              loadLE(Ity_I8, binop(Iop_Add32,
   7851                                                   mkexpr(addr),
   7852                                                   mkU32(i * 1)))),
   7853                        IRTemp_INVALID);
   7854             break;
   7855          case 1:
   7856             putDRegI64(rD + i * inc,
   7857                        triop(Iop_SetElem16x4,
   7858                              getDRegI64(rD + i * inc),
   7859                              mkU8(index),
   7860                              loadLE(Ity_I16, binop(Iop_Add32,
   7861                                                    mkexpr(addr),
   7862                                                    mkU32(i * 2)))),
   7863                        IRTemp_INVALID);
   7864             break;
   7865          case 2:
   7866             putDRegI64(rD + i * inc,
   7867                        triop(Iop_SetElem32x2,
   7868                              getDRegI64(rD + i * inc),
   7869                              mkU8(index),
   7870                              loadLE(Ity_I32, binop(Iop_Add32,
   7871                                                    mkexpr(addr),
   7872                                                    mkU32(i * 4)))),
   7873                        IRTemp_INVALID);
   7874             break;
   7875          default:
   7876             vassert(0);
   7877       }
   7878    }
   7879 }
   7880 
   7881 /* A(nother) helper function for what follows.  It assumes we already
   7882    went uncond as per comments at the top of this section. */
   7883 static
   7884 void mk_neon_elem_store_from_one_lane( UInt rD, UInt inc, UInt index,
   7885                                        UInt N, UInt size, IRTemp addr )
   7886 {
   7887    UInt i;
   7888    switch (size) {
   7889       case 0:
   7890          storeLE(mkexpr(addr),
   7891                  binop(Iop_GetElem8x8, getDRegI64(rD), mkU8(index)));
   7892          break;
   7893       case 1:
   7894          storeLE(mkexpr(addr),
   7895                  binop(Iop_GetElem16x4, getDRegI64(rD), mkU8(index)));
   7896          break;
   7897       case 2:
   7898          storeLE(mkexpr(addr),
   7899                  binop(Iop_GetElem32x2, getDRegI64(rD), mkU8(index)));
   7900          break;
   7901       default:
   7902          vassert(0);
   7903    }
   7904    for (i = 1; i <= N; i++) {
   7905       switch (size) {
   7906          case 0:
   7907             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 1)),
   7908                     binop(Iop_GetElem8x8, getDRegI64(rD + i * inc),
   7909                                           mkU8(index)));
   7910             break;
   7911          case 1:
   7912             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 2)),
   7913                     binop(Iop_GetElem16x4, getDRegI64(rD + i * inc),
   7914                                            mkU8(index)));
   7915             break;
   7916          case 2:
   7917             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 4)),
   7918                     binop(Iop_GetElem32x2, getDRegI64(rD + i * inc),
   7919                                            mkU8(index)));
   7920             break;
   7921          default:
   7922             vassert(0);
   7923       }
   7924    }
   7925 }
   7926 
   7927 /* A7.7 Advanced SIMD element or structure load/store instructions */
   7928 static
   7929 Bool dis_neon_load_or_store ( UInt theInstr,
   7930                               Bool isT, IRTemp condT )
   7931 {
   7932 #  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
   7933    UInt bA = INSN(23,23);
   7934    UInt fB = INSN(11,8);
   7935    UInt bL = INSN(21,21);
   7936    UInt rD = (INSN(22,22) << 4) | INSN(15,12);
   7937    UInt rN = INSN(19,16);
   7938    UInt rM = INSN(3,0);
   7939    UInt N, size, i, j;
   7940    UInt inc;
   7941    UInt regs = 1;
   7942 
   7943    if (isT) {
   7944       vassert(condT != IRTemp_INVALID);
   7945    } else {
   7946       vassert(condT == IRTemp_INVALID);
   7947    }
   7948    /* So now, if condT is not IRTemp_INVALID, we know we're
   7949       dealing with Thumb code. */
   7950 
   7951    if (INSN(20,20) != 0)
   7952       return False;
   7953 
   7954    IRTemp initialRn = newTemp(Ity_I32);
   7955    assign(initialRn, isT ? getIRegT(rN) : getIRegA(rN));
   7956 
   7957    IRTemp initialRm = newTemp(Ity_I32);
   7958    assign(initialRm, isT ? getIRegT(rM) : getIRegA(rM));
   7959 
   7960    /* There are 3 cases:
   7961       (1) VSTn / VLDn (n-element structure from/to one lane)
   7962       (2) VLDn (single element to all lanes)
   7963       (3) VSTn / VLDn (multiple n-element structures)
   7964    */
   7965    if (bA) {
   7966       N = fB & 3;
   7967       if ((fB >> 2) < 3) {
   7968          /* ------------ Case (1) ------------
   7969             VSTn / VLDn (n-element structure from/to one lane) */
   7970 
   7971          size = fB >> 2;
   7972 
   7973          switch (size) {
   7974             case 0: i = INSN(7,5); inc = 1; break;
   7975             case 1: i = INSN(7,6); inc = INSN(5,5) ? 2 : 1; break;
   7976             case 2: i = INSN(7,7); inc = INSN(6,6) ? 2 : 1; break;
   7977             case 3: return False;
   7978             default: vassert(0);
   7979          }
   7980 
   7981          IRTemp addr = newTemp(Ity_I32);
   7982          assign(addr, mkexpr(initialRn));
   7983 
   7984          // go uncond
   7985          if (condT != IRTemp_INVALID)
   7986             mk_skip_over_T32_if_cond_is_false(condT);
   7987          // now uncond
   7988 
   7989          if (bL)
   7990             mk_neon_elem_load_to_one_lane(rD, inc, i, N, size, addr);
   7991          else
   7992             mk_neon_elem_store_from_one_lane(rD, inc, i, N, size, addr);
   7993          DIP("v%s%u.%u {", bL ? "ld" : "st", N + 1, 8 << size);
   7994          for (j = 0; j <= N; j++) {
   7995             if (j)
   7996                DIP(", ");
   7997             DIP("d%u[%u]", rD + j * inc, i);
   7998          }
   7999          DIP("}, [r%u]", rN);
   8000          if (rM != 13 && rM != 15) {
   8001             DIP(", r%u\n", rM);
   8002          } else {
   8003             DIP("%s\n", (rM != 15) ? "!" : "");
   8004          }
   8005       } else {
   8006          /* ------------ Case (2) ------------
   8007             VLDn (single element to all lanes) */
   8008          UInt r;
   8009          if (bL == 0)
   8010             return False;
   8011 
   8012          inc = INSN(5,5) + 1;
   8013          size = INSN(7,6);
   8014 
   8015          /* size == 3 and size == 2 cases differ in alignment constraints */
   8016          if (size == 3 && N == 3 && INSN(4,4) == 1)
   8017             size = 2;
   8018 
   8019          if (size == 0 && N == 0 && INSN(4,4) == 1)
   8020             return False;
   8021          if (N == 2 && INSN(4,4) == 1)
   8022             return False;
   8023          if (size == 3)
   8024             return False;
   8025 
   8026          // go uncond
   8027          if (condT != IRTemp_INVALID)
   8028             mk_skip_over_T32_if_cond_is_false(condT);
   8029          // now uncond
   8030 
   8031          IRTemp addr = newTemp(Ity_I32);
   8032          assign(addr, mkexpr(initialRn));
   8033 
   8034          if (N == 0 && INSN(5,5))
   8035             regs = 2;
   8036 
   8037          for (r = 0; r < regs; r++) {
   8038             switch (size) {
   8039                case 0:
   8040                   putDRegI64(rD + r, unop(Iop_Dup8x8,
   8041                                           loadLE(Ity_I8, mkexpr(addr))),
   8042                              IRTemp_INVALID);
   8043                   break;
   8044                case 1:
   8045                   putDRegI64(rD + r, unop(Iop_Dup16x4,
   8046                                           loadLE(Ity_I16, mkexpr(addr))),
   8047                              IRTemp_INVALID);
   8048                   break;
   8049                case 2:
   8050                   putDRegI64(rD + r, unop(Iop_Dup32x2,
   8051                                           loadLE(Ity_I32, mkexpr(addr))),
   8052                              IRTemp_INVALID);
   8053                   break;
   8054                default:
   8055                   vassert(0);
   8056             }
   8057             for (i = 1; i <= N; i++) {
   8058                switch (size) {
   8059                   case 0:
   8060                      putDRegI64(rD + r + i * inc,
   8061                                 unop(Iop_Dup8x8,
   8062                                      loadLE(Ity_I8, binop(Iop_Add32,
   8063                                                           mkexpr(addr),
   8064                                                           mkU32(i * 1)))),
   8065                                 IRTemp_INVALID);
   8066                      break;
   8067                   case 1:
   8068                      putDRegI64(rD + r + i * inc,
   8069                                 unop(Iop_Dup16x4,
   8070                                      loadLE(Ity_I16, binop(Iop_Add32,
   8071                                                            mkexpr(addr),
   8072                                                            mkU32(i * 2)))),
   8073                                 IRTemp_INVALID);
   8074                      break;
   8075                   case 2:
   8076                      putDRegI64(rD + r + i * inc,
   8077                                 unop(Iop_Dup32x2,
   8078                                      loadLE(Ity_I32, binop(Iop_Add32,
   8079                                                            mkexpr(addr),
   8080                                                            mkU32(i * 4)))),
   8081                                 IRTemp_INVALID);
   8082                      break;
   8083                   default:
   8084                      vassert(0);
   8085                }
   8086             }
   8087          }
   8088          DIP("vld%u.%u {", N + 1, 8 << size);
   8089          for (r = 0; r < regs; r++) {
   8090             for (i = 0; i <= N; i++) {
   8091                if (i || r)
   8092                   DIP(", ");
   8093                DIP("d%u[]", rD + r + i * inc);
   8094             }
   8095          }
   8096          DIP("}, [r%u]", rN);
   8097          if (rM != 13 && rM != 15) {
   8098             DIP(", r%u\n", rM);
   8099          } else {
   8100             DIP("%s\n", (rM != 15) ? "!" : "");
   8101          }
   8102       }
   8103       /* Writeback.  We're uncond here, so no condT-ing. */
   8104       if (rM != 15) {
   8105          if (rM == 13) {
   8106             IRExpr* e = binop(Iop_Add32,
   8107                               mkexpr(initialRn),
   8108                               mkU32((1 << size) * (N + 1)));
   8109             if (isT)
   8110                putIRegT(rN, e, IRTemp_INVALID);
   8111             else
   8112                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8113          } else {
   8114             IRExpr* e = binop(Iop_Add32,
   8115                               mkexpr(initialRn),
   8116                               mkexpr(initialRm));
   8117             if (isT)
   8118                putIRegT(rN, e, IRTemp_INVALID);
   8119             else
   8120                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8121          }
   8122       }
   8123       return True;
   8124    } else {
   8125       /* ------------ Case (3) ------------
   8126          VSTn / VLDn (multiple n-element structures) */
   8127       IRTemp tmp;
   8128       UInt r, elems;
   8129       if (fB == BITS4(0,0,1,0) || fB == BITS4(0,1,1,0)
   8130           || fB == BITS4(0,1,1,1) || fB == BITS4(1,0,1,0)) {
   8131          N = 0;
   8132       } else if (fB == BITS4(0,0,1,1) || fB == BITS4(1,0,0,0)
   8133                  || fB == BITS4(1,0,0,1)) {
   8134          N = 1;
   8135       } else if (fB == BITS4(0,1,0,0) || fB == BITS4(0,1,0,1)) {
   8136          N = 2;
   8137       } else if (fB == BITS4(0,0,0,0) || fB == BITS4(0,0,0,1)) {
   8138          N = 3;
   8139       } else {
   8140          return False;
   8141       }
   8142       inc = (fB & 1) + 1;
   8143       if (N == 1 && fB == BITS4(0,0,1,1)) {
   8144          regs = 2;
   8145       } else if (N == 0) {
   8146          if (fB == BITS4(1,0,1,0)) {
   8147             regs = 2;
   8148          } else if (fB == BITS4(0,1,1,0)) {
   8149             regs = 3;
   8150          } else if (fB == BITS4(0,0,1,0)) {
   8151             regs = 4;
   8152          }
   8153       }
   8154 
   8155       size = INSN(7,6);
   8156       if (N == 0 && size == 3)
   8157          size = 2;
   8158       if (size == 3)
   8159          return False;
   8160 
   8161       elems = 8 / (1 << size);
   8162 
   8163       // go uncond
   8164       if (condT != IRTemp_INVALID)
   8165          mk_skip_over_T32_if_cond_is_false(condT);
   8166       // now uncond
   8167 
   8168       IRTemp addr = newTemp(Ity_I32);
   8169       assign(addr, mkexpr(initialRn));
   8170 
   8171       for (r = 0; r < regs; r++) {
   8172          for (i = 0; i < elems; i++) {
   8173             if (bL)
   8174                mk_neon_elem_load_to_one_lane(rD + r, inc, i, N, size, addr);
   8175             else
   8176                mk_neon_elem_store_from_one_lane(rD + r, inc, i, N, size, addr);
   8177             tmp = newTemp(Ity_I32);
   8178             assign(tmp, binop(Iop_Add32, mkexpr(addr),
   8179                                          mkU32((1 << size) * (N + 1))));
   8180             addr = tmp;
   8181          }
   8182       }
   8183       /* Writeback */
   8184       if (rM != 15) {
   8185          if (rM == 13) {
   8186             IRExpr* e = binop(Iop_Add32,
   8187                               mkexpr(initialRn),
   8188                               mkU32(8 * (N + 1) * regs));
   8189             if (isT)
   8190                putIRegT(rN, e, IRTemp_INVALID);
   8191             else
   8192                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8193          } else {
   8194             IRExpr* e = binop(Iop_Add32,
   8195                               mkexpr(initialRn),
   8196                               mkexpr(initialRm));
   8197             if (isT)
   8198                putIRegT(rN, e, IRTemp_INVALID);
   8199             else
   8200                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8201          }
   8202       }
   8203       DIP("v%s%u.%u {", bL ? "ld" : "st", N + 1, 8 << INSN(7,6));
   8204       if ((inc == 1 && regs * (N + 1) > 1)
   8205           || (inc == 2 && regs > 1 && N > 0)) {
   8206          DIP("d%u-d%u", rD, rD + regs * (N + 1) - 1);
   8207       } else {
   8208          for (r = 0; r < regs; r++) {
   8209             for (i = 0; i <= N; i++) {
   8210                if (i || r)
   8211                   DIP(", ");
   8212                DIP("d%u", rD + r + i * inc);
   8213             }
   8214          }
   8215       }
   8216       DIP("}, [r%u]", rN);
   8217       if (rM != 13 && rM != 15) {
   8218          DIP(", r%u\n", rM);
   8219       } else {
   8220          DIP("%s\n", (rM != 15) ? "!" : "");
   8221       }
   8222       return True;
   8223    }
   8224 #  undef INSN
   8225 }
   8226 
   8227 
   8228 /*------------------------------------------------------------*/
   8229 /*--- NEON, top level control                              ---*/
   8230 /*------------------------------------------------------------*/
   8231 
   8232 /* Both ARM and Thumb */
   8233 
   8234 /* Translate a NEON instruction.    If successful, returns
   8235    True and *dres may or may not be updated.  If failure, returns
   8236    False and doesn't change *dres nor create any IR.
   8237 
   8238    The Thumb and ARM encodings are similar for the 24 bottom bits, but
   8239    the top 8 bits are slightly different.  In both cases, the caller
   8240    must pass the entire 32 bits.  Callers may pass any instruction;
   8241    this ignores non-NEON ones.
   8242 
   8243    Caller must supply an IRTemp 'condT' holding the gating condition,
   8244    or IRTemp_INVALID indicating the insn is always executed.  In ARM
   8245    code, this must always be IRTemp_INVALID because NEON insns are
   8246    unconditional for ARM.
   8247 
   8248    Finally, the caller must indicate whether this occurs in ARM or in
   8249    Thumb code.
   8250 */
   8251 static Bool decode_NEON_instruction (
   8252                /*MOD*/DisResult* dres,
   8253                UInt              insn32,
   8254                IRTemp            condT,
   8255                Bool              isT
   8256             )
   8257 {
   8258 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn32, (_bMax), (_bMin))
   8259 
   8260    /* There are two kinds of instruction to deal with: load/store and
   8261       data processing.  In each case, in ARM mode we merely identify
   8262       the kind, and pass it on to the relevant sub-handler.  In Thumb
   8263       mode we identify the kind, swizzle the bits around to make it
   8264       have the same encoding as in ARM, and hand it on to the
   8265       sub-handler.
   8266    */
   8267 
   8268    /* In ARM mode, NEON instructions can't be conditional. */
   8269    if (!isT)
   8270       vassert(condT == IRTemp_INVALID);
   8271 
   8272    /* Data processing:
   8273       Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx
   8274       ARM:   1111 001U AAAA Axxx xxxx BBBB CCCC xxxx
   8275    */
   8276    if (!isT && INSN(31,25) == BITS7(1,1,1,1,0,0,1)) {
   8277       // ARM, DP
   8278       return dis_neon_data_processing(INSN(31,0), condT);
   8279    }
   8280    if (isT && INSN(31,29) == BITS3(1,1,1)
   8281        && INSN(27,24) == BITS4(1,1,1,1)) {
   8282       // Thumb, DP
   8283       UInt reformatted = INSN(23,0);
   8284       reformatted |= (INSN(28,28) << 24); // U bit
   8285       reformatted |= (BITS7(1,1,1,1,0,0,1) << 25);
   8286       return dis_neon_data_processing(reformatted, condT);
   8287    }
   8288 
   8289    /* Load/store:
   8290       Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx
   8291       ARM:   1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx
   8292    */
   8293    if (!isT && INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) {
   8294       // ARM, memory
   8295       return dis_neon_load_or_store(INSN(31,0), isT, condT);
   8296    }
   8297    if (isT && INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) {
   8298       UInt reformatted = INSN(23,0);
   8299       reformatted |= (BITS8(1,1,1,1,0,1,0,0) << 24);
   8300       return dis_neon_load_or_store(reformatted, isT, condT);
   8301    }
   8302 
   8303    /* Doesn't match. */
   8304    return False;
   8305 
   8306 #  undef INSN
   8307 }
   8308 
   8309 
   8310 /*------------------------------------------------------------*/
   8311 /*--- V6 MEDIA instructions                                ---*/
   8312 /*------------------------------------------------------------*/
   8313 
   8314 /* Both ARM and Thumb */
   8315 
   8316 /* Translate a V6 media instruction.    If successful, returns
   8317    True and *dres may or may not be updated.  If failure, returns
   8318    False and doesn't change *dres nor create any IR.
   8319 
   8320    The Thumb and ARM encodings are completely different.  In Thumb
   8321    mode, the caller must pass the entire 32 bits.  In ARM mode it must
   8322    pass the lower 28 bits.  Apart from that, callers may pass any
   8323    instruction; this function ignores anything it doesn't recognise.
   8324 
   8325    Caller must supply an IRTemp 'condT' holding the gating condition,
   8326    or IRTemp_INVALID indicating the insn is always executed.
   8327 
   8328    Caller must also supply an ARMCondcode 'cond'.  This is only used
   8329    for debug printing, no other purpose.  For ARM, this is simply the
   8330    top 4 bits of the original instruction.  For Thumb, the condition
   8331    is not (really) known until run time, and so ARMCondAL should be
   8332    passed, only so that printing of these instructions does not show
   8333    any condition.
   8334 
   8335    Finally, the caller must indicate whether this occurs in ARM or in
   8336    Thumb code.
   8337 */
   8338 static Bool decode_V6MEDIA_instruction (
   8339                /*MOD*/DisResult* dres,
   8340                UInt              insnv6m,
   8341                IRTemp            condT,
   8342                ARMCondcode       conq,
   8343                Bool              isT
   8344             )
   8345 {
   8346 #  define INSNA(_bMax,_bMin)   SLICE_UInt(insnv6m, (_bMax), (_bMin))
   8347 #  define INSNT0(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \
   8348                                            (_bMax), (_bMin) )
   8349 #  define INSNT1(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 0)  & 0xFFFF), \
   8350                                            (_bMax), (_bMin) )
   8351    HChar dis_buf[128];
   8352    dis_buf[0] = 0;
   8353 
   8354    if (isT) {
   8355       vassert(conq == ARMCondAL);
   8356    } else {
   8357       vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation
   8358       vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
   8359    }
   8360 
   8361    /* ----------- smulbb, smulbt, smultb, smultt ----------- */
   8362    {
   8363      UInt regD = 99, regM = 99, regN = 99, bitM = 0, bitN = 0;
   8364      Bool gate = False;
   8365 
   8366      if (isT) {
   8367         if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1)
   8368             && INSNT1(7,6) == BITS2(0,0)) {
   8369            regD = INSNT1(11,8);
   8370            regM = INSNT1(3,0);
   8371            regN = INSNT0(3,0);
   8372            bitM = INSNT1(4,4);
   8373            bitN = INSNT1(5,5);
   8374            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8375               gate = True;
   8376         }
   8377      } else {
   8378         if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) &&
   8379             BITS4(0,0,0,0)         == INSNA(15,12) &&
   8380             BITS4(1,0,0,0)         == (INSNA(7,4) & BITS4(1,0,0,1)) ) {
   8381            regD = INSNA(19,16);
   8382            regM = INSNA(11,8);
   8383            regN = INSNA(3,0);
   8384            bitM = INSNA(6,6);
   8385            bitN = INSNA(5,5);
   8386            if (regD != 15 && regN != 15 && regM != 15)
   8387               gate = True;
   8388         }
   8389      }
   8390 
   8391      if (gate) {
   8392         IRTemp srcN = newTemp(Ity_I32);
   8393         IRTemp srcM = newTemp(Ity_I32);
   8394         IRTemp res  = newTemp(Ity_I32);
   8395 
   8396         assign( srcN, binop(Iop_Sar32,
   8397                             binop(Iop_Shl32,
   8398                                   isT ? getIRegT(regN) : getIRegA(regN),
   8399                                   mkU8(bitN ? 0 : 16)), mkU8(16)) );
   8400         assign( srcM, binop(Iop_Sar32,
   8401                             binop(Iop_Shl32,
   8402                                   isT ? getIRegT(regM) : getIRegA(regM),
   8403                                   mkU8(bitM ? 0 : 16)), mkU8(16)) );
   8404         assign( res, binop(Iop_Mul32, mkexpr(srcN), mkexpr(srcM)) );
   8405 
   8406         if (isT)
   8407            putIRegT( regD, mkexpr(res), condT );
   8408         else
   8409            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8410 
   8411         DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN ? 't' : 'b', bitM ? 't' : 'b',
   8412              nCC(conq), regD, regN, regM );
   8413         return True;
   8414      }
   8415      /* fall through */
   8416    }
   8417 
   8418    /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */
   8419    /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */
   8420    {
   8421      UInt regD = 99, regN = 99, regM = 99, bitM = 0;
   8422      Bool gate = False;
   8423 
   8424      if (isT) {
   8425         if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1)
   8426             && INSNT1(7,5) == BITS3(0,0,0)) {
   8427           regN = INSNT0(3,0);
   8428           regD = INSNT1(11,8);
   8429           regM = INSNT1(3,0);
   8430           bitM = INSNT1(4,4);
   8431           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8432              gate = True;
   8433         }
   8434      } else {
   8435         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
   8436             INSNA(15,12) == BITS4(0,0,0,0)         &&
   8437             (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) {
   8438            regD = INSNA(19,16);
   8439            regN = INSNA(3,0);
   8440            regM = INSNA(11,8);
   8441            bitM = INSNA(6,6);
   8442            if (regD != 15 && regN != 15 && regM != 15)
   8443               gate = True;
   8444         }
   8445      }
   8446 
   8447      if (gate) {
   8448         IRTemp irt_prod = newTemp(Ity_I64);
   8449 
   8450         assign( irt_prod,
   8451                 binop(Iop_MullS32,
   8452                       isT ? getIRegT(regN) : getIRegA(regN),
   8453                       binop(Iop_Sar32,
   8454                             binop(Iop_Shl32,
   8455                                   isT ? getIRegT(regM) : getIRegA(regM),
   8456                                   mkU8(bitM ? 0 : 16)),
   8457                             mkU8(16))) );
   8458 
   8459         IRExpr* ire_result = binop(Iop_Or32,
   8460                                    binop( Iop_Shl32,
   8461                                           unop(Iop_64HIto32, mkexpr(irt_prod)),
   8462                                           mkU8(16) ),
   8463                                    binop( Iop_Shr32,
   8464                                           unop(Iop_64to32, mkexpr(irt_prod)),
   8465                                           mkU8(16) ) );
   8466 
   8467         if (isT)
   8468            putIRegT( regD, ire_result, condT );
   8469         else
   8470            putIRegA( regD, ire_result, condT, Ijk_Boring );
   8471 
   8472         DIP("smulw%c%s r%u, r%u, r%u\n",
   8473             bitM ? 't' : 'b', nCC(conq),regD,regN,regM);
   8474         return True;
   8475      }
   8476      /* fall through */
   8477    }
   8478 
   8479    /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */
   8480    /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */
   8481    {
   8482      UInt regD = 99, regN = 99, regM = 99, imm5 = 99, shift_type = 99;
   8483      Bool tbform = False;
   8484      Bool gate = False;
   8485 
   8486      if (isT) {
   8487         if (INSNT0(15,4) == 0xEAC
   8488             && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) {
   8489            regN = INSNT0(3,0);
   8490            regD = INSNT1(11,8);
   8491            regM = INSNT1(3,0);
   8492            imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6);
   8493            shift_type = (INSNT1(5,5) << 1) | 0;
   8494            tbform = (INSNT1(5,5) == 0) ? False : True;
   8495            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8496               gate = True;
   8497         }
   8498      } else {
   8499         if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
   8500             INSNA(5,4)   == BITS2(0,1)             &&
   8501             (INSNA(6,6)  == 0 || INSNA(6,6) == 1) ) {
   8502            regD = INSNA(15,12);
   8503            regN = INSNA(19,16);
   8504            regM = INSNA(3,0);
   8505            imm5 = INSNA(11,7);
   8506            shift_type = (INSNA(6,6) << 1) | 0;
   8507            tbform = (INSNA(6,6) == 0) ? False : True;
   8508            if (regD != 15 && regN != 15 && regM != 15)
   8509               gate = True;
   8510         }
   8511      }
   8512 
   8513      if (gate) {
   8514         IRTemp irt_regM       = newTemp(Ity_I32);
   8515         IRTemp irt_regM_shift = newTemp(Ity_I32);
   8516         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   8517         compute_result_and_C_after_shift_by_imm5(
   8518            dis_buf, &irt_regM_shift, NULL, irt_regM, shift_type, imm5, regM );
   8519 
   8520         UInt mask = (tbform == True) ? 0x0000FFFF : 0xFFFF0000;
   8521         IRExpr* ire_result
   8522           = binop( Iop_Or32,
   8523                    binop(Iop_And32, mkexpr(irt_regM_shift), mkU32(mask)),
   8524                    binop(Iop_And32, isT ? getIRegT(regN) : getIRegA(regN),
   8525                                     unop(Iop_Not32, mkU32(mask))) );
   8526 
   8527         if (isT)
   8528            putIRegT( regD, ire_result, condT );
   8529         else
   8530            putIRegA( regD, ire_result, condT, Ijk_Boring );
   8531 
   8532         DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform ? "tb" : "bt",
   8533              nCC(conq), regD, regN, regM, dis_buf );
   8534 
   8535         return True;
   8536      }
   8537      /* fall through */
   8538    }
   8539 
   8540    /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
   8541    {
   8542      UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
   8543      Bool gate = False;
   8544 
   8545      if (isT) {
   8546         if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0)
   8547             && INSNT0(4,4) == 0
   8548             && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
   8549            regD       = INSNT1(11,8);
   8550            regN       = INSNT0(3,0);
   8551            shift_type = (INSNT0(5,5) << 1) | 0;
   8552            imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
   8553            sat_imm    = INSNT1(4,0);
   8554            if (!isBadRegT(regD) && !isBadRegT(regN))
   8555               gate = True;
   8556            if (shift_type == BITS2(1,0) && imm5 == 0)
   8557               gate = False;
   8558         }
   8559      } else {
   8560         if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) &&
   8561             INSNA(5,4)   == BITS2(0,1)) {
   8562            regD       = INSNA(15,12);
   8563            regN       = INSNA(3,0);
   8564            shift_type = (INSNA(6,6) << 1) | 0;
   8565            imm5       = INSNA(11,7);
   8566            sat_imm    = INSNA(20,16);
   8567            if (regD != 15 && regN != 15)
   8568               gate = True;
   8569         }
   8570      }
   8571 
   8572      if (gate) {
   8573         IRTemp irt_regN       = newTemp(Ity_I32);
   8574         IRTemp irt_regN_shift = newTemp(Ity_I32);
   8575         IRTemp irt_sat_Q      = newTemp(Ity_I32);
   8576         IRTemp irt_result     = newTemp(Ity_I32);
   8577 
   8578         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   8579         compute_result_and_C_after_shift_by_imm5(
   8580                 dis_buf, &irt_regN_shift, NULL,
   8581                 irt_regN, shift_type, imm5, regN );
   8582 
   8583         armUnsignedSatQ( &irt_result, &irt_sat_Q, irt_regN_shift, sat_imm );
   8584         or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
   8585 
   8586         if (isT)
   8587            putIRegT( regD, mkexpr(irt_result), condT );
   8588         else
   8589            putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
   8590 
   8591         DIP("usat%s r%u, #0x%04x, %s\n",
   8592             nCC(conq), regD, imm5, dis_buf);
   8593         return True;
   8594      }
   8595      /* fall through */
   8596    }
   8597 
   8598   /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
   8599    {
   8600      UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
   8601      Bool gate = False;
   8602 
   8603      if (isT) {
   8604         if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
   8605             && INSNT0(4,4) == 0
   8606             && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
   8607            regD       = INSNT1(11,8);
   8608            regN       = INSNT0(3,0);
   8609            shift_type = (INSNT0(5,5) << 1) | 0;
   8610            imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
   8611            sat_imm    = INSNT1(4,0) + 1;
   8612            if (!isBadRegT(regD) && !isBadRegT(regN))
   8613               gate = True;
   8614            if (shift_type == BITS2(1,0) && imm5 == 0)
   8615               gate = False;
   8616         }
   8617      } else {
   8618         if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) &&
   8619             INSNA(5,4)   == BITS2(0,1)) {
   8620            regD       = INSNA(15,12);
   8621            regN       = INSNA(3,0);
   8622            shift_type = (INSNA(6,6) << 1) | 0;
   8623            imm5       = INSNA(11,7);
   8624            sat_imm    = INSNA(20,16) + 1;
   8625            if (regD != 15 && regN != 15)
   8626               gate = True;
   8627         }
   8628      }
   8629 
   8630      if (gate) {
   8631         IRTemp irt_regN       = newTemp(Ity_I32);
   8632         IRTemp irt_regN_shift = newTemp(Ity_I32);
   8633         IRTemp irt_sat_Q      = newTemp(Ity_I32);
   8634         IRTemp irt_result     = newTemp(Ity_I32);
   8635 
   8636         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   8637         compute_result_and_C_after_shift_by_imm5(
   8638                 dis_buf, &irt_regN_shift, NULL,
   8639                 irt_regN, shift_type, imm5, regN );
   8640 
   8641         armSignedSatQ( irt_regN_shift, sat_imm, &irt_result, &irt_sat_Q );
   8642         or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
   8643 
   8644         if (isT)
   8645            putIRegT( regD, mkexpr(irt_result), condT );
   8646         else
   8647            putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
   8648 
   8649         DIP( "ssat%s r%u, #0x%04x, %s\n",
   8650              nCC(conq), regD, imm5, dis_buf);
   8651         return True;
   8652     }
   8653     /* fall through */
   8654   }
   8655 
   8656    /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */
   8657    {
   8658      UInt regD = 99, regN = 99, sat_imm = 99;
   8659      Bool gate = False;
   8660 
   8661      if (isT) {
   8662         if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) {
   8663            regN = INSNT0(3,0);
   8664            regD = INSNT1(11,8);
   8665            sat_imm = INSNT1(3,0);
   8666            if (!isBadRegT(regD) && !isBadRegT(regN))
   8667               gate = True;
   8668        }
   8669      } else {
   8670         if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) &&
   8671             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8672             INSNA(7,4)   == BITS4(0,0,1,1)) {
   8673            regD    = INSNA(15,12);
   8674            regN    = INSNA(3,0);
   8675            sat_imm = INSNA(19,16);
   8676            if (regD != 15 && regN != 15)
   8677               gate = True;
   8678         }
   8679      }
   8680 
   8681      if (gate) {
   8682         IRTemp irt_regN    = newTemp(Ity_I32);
   8683         IRTemp irt_regN_lo = newTemp(Ity_I32);
   8684         IRTemp irt_regN_hi = newTemp(Ity_I32);
   8685         IRTemp irt_Q_lo    = newTemp(Ity_I32);
   8686         IRTemp irt_Q_hi    = newTemp(Ity_I32);
   8687         IRTemp irt_res_lo  = newTemp(Ity_I32);
   8688         IRTemp irt_res_hi  = newTemp(Ity_I32);
   8689 
   8690         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   8691         assign( irt_regN_lo, binop( Iop_Sar32,
   8692                                     binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
   8693                                     mkU8(16)) );
   8694         assign( irt_regN_hi, binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)) );
   8695 
   8696         armUnsignedSatQ( &irt_res_lo, &irt_Q_lo, irt_regN_lo, sat_imm );
   8697         or_into_QFLAG32( mkexpr(irt_Q_lo), condT );
   8698 
   8699         armUnsignedSatQ( &irt_res_hi, &irt_Q_hi, irt_regN_hi, sat_imm );
   8700         or_into_QFLAG32( mkexpr(irt_Q_hi), condT );
   8701 
   8702         IRExpr* ire_result = binop( Iop_Or32,
   8703                                     binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)),
   8704                                     mkexpr(irt_res_lo) );
   8705 
   8706         if (isT)
   8707            putIRegT( regD, ire_result, condT );
   8708         else
   8709            putIRegA( regD, ire_result, condT, Ijk_Boring );
   8710 
   8711         DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq), regD, sat_imm, regN );
   8712         return True;
   8713      }
   8714      /* fall through */
   8715    }
   8716 
   8717    /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */
   8718    {
   8719      UInt regD = 99, regN = 99, regM = 99;
   8720      Bool gate = False;
   8721 
   8722      if (isT) {
   8723         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   8724            regN = INSNT0(3,0);
   8725            regD = INSNT1(11,8);
   8726            regM = INSNT1(3,0);
   8727            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8728               gate = True;
   8729         }
   8730      } else {
   8731         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   8732             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8733             INSNA(7,4)   == BITS4(0,0,0,1)) {
   8734            regD = INSNA(15,12);
   8735            regN = INSNA(19,16);
   8736            regM = INSNA(3,0);
   8737            if (regD != 15 && regN != 15 && regM != 15)
   8738               gate = True;
   8739         }
   8740      }
   8741 
   8742      if (gate) {
   8743         IRTemp rNt  = newTemp(Ity_I32);
   8744         IRTemp rMt  = newTemp(Ity_I32);
   8745         IRTemp res  = newTemp(Ity_I32);
   8746         IRTemp reso = newTemp(Ity_I32);
   8747 
   8748         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8749         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8750 
   8751         assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
   8752         if (isT)
   8753            putIRegT( regD, mkexpr(res), condT );
   8754         else
   8755            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8756 
   8757         assign(reso, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
   8758         set_GE_32_10_from_bits_31_15(reso, condT);
   8759 
   8760         DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8761         return True;
   8762      }
   8763      /* fall through */
   8764    }
   8765 
   8766    /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */
   8767    {
   8768      UInt regD = 99, regN = 99, regM = 99;
   8769      Bool gate = False;
   8770 
   8771      if (isT) {
   8772         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   8773            regN = INSNT0(3,0);
   8774            regD = INSNT1(11,8);
   8775            regM = INSNT1(3,0);
   8776            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8777               gate = True;
   8778         }
   8779      } else {
   8780         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   8781             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8782             INSNA(7,4)   == BITS4(0,0,0,1)) {
   8783            regD = INSNA(15,12);
   8784            regN = INSNA(19,16);
   8785            regM = INSNA(3,0);
   8786            if (regD != 15 && regN != 15 && regM != 15)
   8787               gate = True;
   8788         }
   8789      }
   8790 
   8791      if (gate) {
   8792         IRTemp rNt  = newTemp(Ity_I32);
   8793         IRTemp rMt  = newTemp(Ity_I32);
   8794         IRTemp res  = newTemp(Ity_I32);
   8795         IRTemp reso = newTemp(Ity_I32);
   8796 
   8797         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8798         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8799 
   8800         assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
   8801         if (isT)
   8802            putIRegT( regD, mkexpr(res), condT );
   8803         else
   8804            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8805 
   8806         assign(reso, unop(Iop_Not32,
   8807                           binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt))));
   8808         set_GE_32_10_from_bits_31_15(reso, condT);
   8809 
   8810         DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8811         return True;
   8812      }
   8813      /* fall through */
   8814    }
   8815 
   8816    /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */
   8817    {
   8818      UInt regD = 99, regN = 99, regM = 99;
   8819      Bool gate = False;
   8820 
   8821      if (isT) {
   8822         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   8823            regN = INSNT0(3,0);
   8824            regD = INSNT1(11,8);
   8825            regM = INSNT1(3,0);
   8826            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8827               gate = True;
   8828         }
   8829      } else {
   8830         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   8831             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8832             INSNA(7,4)   == BITS4(0,1,1,1)) {
   8833            regD = INSNA(15,12);
   8834            regN = INSNA(19,16);
   8835            regM = INSNA(3,0);
   8836            if (regD != 15 && regN != 15 && regM != 15)
   8837              gate = True;
   8838         }
   8839      }
   8840 
   8841      if (gate) {
   8842         IRTemp rNt  = newTemp(Ity_I32);
   8843         IRTemp rMt  = newTemp(Ity_I32);
   8844         IRTemp res  = newTemp(Ity_I32);
   8845         IRTemp reso = newTemp(Ity_I32);
   8846 
   8847         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8848         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8849 
   8850         assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
   8851         if (isT)
   8852            putIRegT( regD, mkexpr(res), condT );
   8853         else
   8854            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8855 
   8856         assign(reso, unop(Iop_Not32,
   8857                           binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt))));
   8858         set_GE_32_10_from_bits_31_15(reso, condT);
   8859 
   8860         DIP("usub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8861         return True;
   8862      }
   8863      /* fall through */
   8864    }
   8865 
   8866    /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */
   8867    {
   8868      UInt regD = 99, regN = 99, regM = 99;
   8869      Bool gate = False;
   8870 
   8871      if (isT) {
   8872         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   8873            regN = INSNT0(3,0);
   8874            regD = INSNT1(11,8);
   8875            regM = INSNT1(3,0);
   8876            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8877               gate = True;
   8878         }
   8879      } else {
   8880         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   8881             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8882             INSNA(7,4)   == BITS4(0,1,1,1)) {
   8883            regD = INSNA(15,12);
   8884            regN = INSNA(19,16);
   8885            regM = INSNA(3,0);
   8886            if (regD != 15 && regN != 15 && regM != 15)
   8887               gate = True;
   8888         }
   8889      }
   8890 
   8891      if (gate) {
   8892         IRTemp rNt  = newTemp(Ity_I32);
   8893         IRTemp rMt  = newTemp(Ity_I32);
   8894         IRTemp res  = newTemp(Ity_I32);
   8895         IRTemp reso = newTemp(Ity_I32);
   8896 
   8897         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8898         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8899 
   8900         assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
   8901         if (isT)
   8902            putIRegT( regD, mkexpr(res), condT );
   8903         else
   8904            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8905 
   8906         assign(reso, unop(Iop_Not32,
   8907                           binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt))));
   8908         set_GE_32_10_from_bits_31_15(reso, condT);
   8909 
   8910         DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8911         return True;
   8912      }
   8913      /* fall through */
   8914    }
   8915 
   8916    /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */
   8917    {
   8918      UInt regD = 99, regN = 99, regM = 99;
   8919      Bool gate = False;
   8920 
   8921      if (isT) {
   8922         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   8923            regN = INSNT0(3,0);
   8924            regD = INSNT1(11,8);
   8925            regM = INSNT1(3,0);
   8926            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8927               gate = True;
   8928         }
   8929      } else {
   8930         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   8931             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8932             (INSNA(7,4)  == BITS4(1,0,0,1))) {
   8933            regD = INSNA(15,12);
   8934            regN = INSNA(19,16);
   8935            regM = INSNA(3,0);
   8936            if (regD != 15 && regN != 15 && regM != 15)
   8937               gate = True;
   8938         }
   8939      }
   8940 
   8941      if (gate) {
   8942         IRTemp rNt  = newTemp(Ity_I32);
   8943         IRTemp rMt  = newTemp(Ity_I32);
   8944         IRTemp res  = newTemp(Ity_I32);
   8945         IRTemp reso = newTemp(Ity_I32);
   8946 
   8947         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8948         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8949 
   8950         assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
   8951         if (isT)
   8952            putIRegT( regD, mkexpr(res), condT );
   8953         else
   8954            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8955 
   8956         assign(reso, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
   8957         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   8958 
   8959         DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8960         return True;
   8961      }
   8962      /* fall through */
   8963    }
   8964 
   8965    /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
   8966    {
   8967      UInt regD = 99, regN = 99, regM = 99;
   8968      Bool gate = False;
   8969 
   8970      if (isT) {
   8971         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   8972            regN = INSNT0(3,0);
   8973            regD = INSNT1(11,8);
   8974            regM = INSNT1(3,0);
   8975            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8976               gate = True;
   8977         }
   8978      } else {
   8979         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   8980             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8981             (INSNA(7,4)  == BITS4(1,0,0,1))) {
   8982            regD = INSNA(15,12);
   8983            regN = INSNA(19,16);
   8984            regM = INSNA(3,0);
   8985            if (regD != 15 && regN != 15 && regM != 15)
   8986               gate = True;
   8987         }
   8988      }
   8989 
   8990      if (gate) {
   8991         IRTemp rNt  = newTemp(Ity_I32);
   8992         IRTemp rMt  = newTemp(Ity_I32);
   8993         IRTemp res  = newTemp(Ity_I32);
   8994         IRTemp reso = newTemp(Ity_I32);
   8995 
   8996         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8997         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8998 
   8999         assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
   9000         if (isT)
   9001            putIRegT( regD, mkexpr(res), condT );
   9002         else
   9003            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   9004 
   9005         assign(reso, unop(Iop_Not32,
   9006                           binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt))));
   9007         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   9008 
   9009         DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9010         return True;
   9011      }
   9012      /* fall through */
   9013    }
   9014 
   9015    /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9016    {
   9017      UInt regD = 99, regN = 99, regM = 99;
   9018      Bool gate = False;
   9019 
   9020      if (isT) {
   9021         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   9022            regN = INSNT0(3,0);
   9023            regD = INSNT1(11,8);
   9024            regM = INSNT1(3,0);
   9025            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9026               gate = True;
   9027         }
   9028      } else {
   9029         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   9030             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9031             (INSNA(7,4)  == BITS4(1,1,1,1))) {
   9032            regD = INSNA(15,12);
   9033            regN = INSNA(19,16);
   9034            regM = INSNA(3,0);
   9035            if (regD != 15 && regN != 15 && regM != 15)
   9036              gate = True;
   9037         }
   9038      }
   9039 
   9040      if (gate) {
   9041         IRTemp rNt  = newTemp(Ity_I32);
   9042         IRTemp rMt  = newTemp(Ity_I32);
   9043         IRTemp res  = newTemp(Ity_I32);
   9044         IRTemp reso = newTemp(Ity_I32);
   9045 
   9046         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9047         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9048 
   9049         assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
   9050         if (isT)
   9051            putIRegT( regD, mkexpr(res), condT );
   9052         else
   9053            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   9054 
   9055         assign(reso, unop(Iop_Not32,
   9056                           binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt))));
   9057         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   9058 
   9059         DIP("usub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9060         return True;
   9061      }
   9062      /* fall through */
   9063    }
   9064 
   9065    /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9066    {
   9067      UInt regD = 99, regN = 99, regM = 99;
   9068      Bool gate = False;
   9069 
   9070      if (isT) {
   9071         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   9072            regN = INSNT0(3,0);
   9073            regD = INSNT1(11,8);
   9074            regM = INSNT1(3,0);
   9075            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9076               gate = True;
   9077         }
   9078      } else {
   9079         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   9080             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9081             INSNA(7,4)   == BITS4(1,1,1,1)) {
   9082            regD = INSNA(15,12);
   9083            regN = INSNA(19,16);
   9084            regM = INSNA(3,0);
   9085            if (regD != 15 && regN != 15 && regM != 15)
   9086               gate = True;
   9087         }
   9088      }
   9089 
   9090      if (gate) {
   9091         IRTemp rNt  = newTemp(Ity_I32);
   9092         IRTemp rMt  = newTemp(Ity_I32);
   9093         IRTemp res  = newTemp(Ity_I32);
   9094         IRTemp reso = newTemp(Ity_I32);
   9095 
   9096         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9097         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9098 
   9099         assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
   9100         if (isT)
   9101            putIRegT( regD, mkexpr(res), condT );
   9102         else
   9103            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   9104 
   9105         assign(reso, unop(Iop_Not32,
   9106                           binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt))));
   9107         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   9108 
   9109         DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9110         return True;
   9111      }
   9112      /* fall through */
   9113    }
   9114 
   9115    /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9116    {
   9117      UInt regD = 99, regN = 99, regM = 99;
   9118      Bool gate = False;
   9119 
   9120      if (isT) {
   9121         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9122            regN = INSNT0(3,0);
   9123            regD = INSNT1(11,8);
   9124            regM = INSNT1(3,0);
   9125            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9126               gate = True;
   9127         }
   9128      } else {
   9129         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9130             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9131             INSNA(7,4)   == BITS4(1,0,0,1)) {
   9132            regD = INSNA(15,12);
   9133            regN = INSNA(19,16);
   9134            regM = INSNA(3,0);
   9135            if (regD != 15 && regN != 15 && regM != 15)
   9136               gate = True;
   9137         }
   9138      }
   9139 
   9140      if (gate) {
   9141         IRTemp rNt   = newTemp(Ity_I32);
   9142         IRTemp rMt   = newTemp(Ity_I32);
   9143         IRTemp res_q = newTemp(Ity_I32);
   9144 
   9145         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9146         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9147 
   9148         assign(res_q, binop(Iop_QAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
   9149         if (isT)
   9150            putIRegT( regD, mkexpr(res_q), condT );
   9151         else
   9152            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9153 
   9154         DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9155         return True;
   9156      }
   9157      /* fall through */
   9158    }
   9159 
   9160    /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9161    {
   9162      UInt regD = 99, regN = 99, regM = 99;
   9163      Bool gate = False;
   9164 
   9165      if (isT) {
   9166         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9167            regN = INSNT0(3,0);
   9168            regD = INSNT1(11,8);
   9169            regM = INSNT1(3,0);
   9170            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9171               gate = True;
   9172         }
   9173      } else {
   9174         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9175             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9176             INSNA(7,4)   == BITS4(1,1,1,1)) {
   9177            regD = INSNA(15,12);
   9178            regN = INSNA(19,16);
   9179            regM = INSNA(3,0);
   9180            if (regD != 15 && regN != 15 && regM != 15)
   9181               gate = True;
   9182         }
   9183      }
   9184 
   9185      if (gate) {
   9186         IRTemp rNt   = newTemp(Ity_I32);
   9187         IRTemp rMt   = newTemp(Ity_I32);
   9188         IRTemp res_q = newTemp(Ity_I32);
   9189 
   9190         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9191         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9192 
   9193         assign(res_q, binop(Iop_QSub8Sx4, mkexpr(rNt), mkexpr(rMt)));
   9194         if (isT)
   9195            putIRegT( regD, mkexpr(res_q), condT );
   9196         else
   9197            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9198 
   9199         DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9200         return True;
   9201      }
   9202      /* fall through */
   9203    }
   9204 
   9205    /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9206    {
   9207      UInt regD = 99, regN = 99, regM = 99;
   9208      Bool gate = False;
   9209 
   9210      if (isT) {
   9211         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
   9212            regN = INSNT0(3,0);
   9213            regD = INSNT1(11,8);
   9214            regM = INSNT1(3,0);
   9215            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9216               gate = True;
   9217         }
   9218      } else {
   9219         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
   9220             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9221             (INSNA(7,4)  == BITS4(1,0,0,1))) {
   9222            regD = INSNA(15,12);
   9223            regN = INSNA(19,16);
   9224            regM = INSNA(3,0);
   9225            if (regD != 15 && regN != 15 && regM != 15)
   9226               gate = True;
   9227         }
   9228      }
   9229 
   9230      if (gate) {
   9231         IRTemp rNt   = newTemp(Ity_I32);
   9232         IRTemp rMt   = newTemp(Ity_I32);
   9233         IRTemp res_q = newTemp(Ity_I32);
   9234 
   9235         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9236         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9237 
   9238         assign(res_q, binop(Iop_QAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
   9239         if (isT)
   9240            putIRegT( regD, mkexpr(res_q), condT );
   9241         else
   9242            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9243 
   9244         DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9245         return True;
   9246      }
   9247      /* fall through */
   9248    }
   9249 
   9250    /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9251    {
   9252      UInt regD = 99, regN = 99, regM = 99;
   9253      Bool gate = False;
   9254 
   9255      if (isT) {
   9256         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
   9257            regN = INSNT0(3,0);
   9258            regD = INSNT1(11,8);
   9259            regM = INSNT1(3,0);
   9260            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9261               gate = True;
   9262         }
   9263      } else {
   9264         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
   9265             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9266             (INSNA(7,4)  == BITS4(1,1,1,1))) {
   9267            regD = INSNA(15,12);
   9268            regN = INSNA(19,16);
   9269            regM = INSNA(3,0);
   9270            if (regD != 15 && regN != 15 && regM != 15)
   9271              gate = True;
   9272         }
   9273      }
   9274 
   9275      if (gate) {
   9276         IRTemp rNt   = newTemp(Ity_I32);
   9277         IRTemp rMt   = newTemp(Ity_I32);
   9278         IRTemp res_q = newTemp(Ity_I32);
   9279 
   9280         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9281         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9282 
   9283         assign(res_q, binop(Iop_QSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
   9284         if (isT)
   9285            putIRegT( regD, mkexpr(res_q), condT );
   9286         else
   9287            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9288 
   9289         DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9290         return True;
   9291      }
   9292      /* fall through */
   9293    }
   9294 
   9295    /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9296    {
   9297      UInt regD = 99, regN = 99, regM = 99;
   9298      Bool gate = False;
   9299 
   9300      if (isT) {
   9301         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
   9302            regN = INSNT0(3,0);
   9303            regD = INSNT1(11,8);
   9304            regM = INSNT1(3,0);
   9305            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9306               gate = True;
   9307         }
   9308      } else {
   9309         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
   9310             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9311             INSNA(7,4)   == BITS4(1,0,0,1)) {
   9312            regD = INSNA(15,12);
   9313            regN = INSNA(19,16);
   9314            regM = INSNA(3,0);
   9315            if (regD != 15 && regN != 15 && regM != 15)
   9316               gate = True;
   9317         }
   9318      }
   9319 
   9320      if (gate) {
   9321         IRTemp rNt   = newTemp(Ity_I32);
   9322         IRTemp rMt   = newTemp(Ity_I32);
   9323         IRTemp res_q = newTemp(Ity_I32);
   9324 
   9325         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9326         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9327 
   9328         assign(res_q, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
   9329         if (isT)
   9330            putIRegT( regD, mkexpr(res_q), condT );
   9331         else
   9332            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9333 
   9334         DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9335         return True;
   9336      }
   9337      /* fall through */
   9338    }
   9339 
   9340    /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9341    {
   9342      UInt regD = 99, regN = 99, regM = 99;
   9343      Bool gate = False;
   9344 
   9345      if (isT) {
   9346         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
   9347            regN = INSNT0(3,0);
   9348            regD = INSNT1(11,8);
   9349            regM = INSNT1(3,0);
   9350            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9351               gate = True;
   9352         }
   9353      } else {
   9354         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
   9355             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9356             INSNA(7,4)   == BITS4(1,0,0,1)) {
   9357            regD = INSNA(15,12);
   9358            regN = INSNA(19,16);
   9359            regM = INSNA(3,0);
   9360            if (regD != 15 && regN != 15 && regM != 15)
   9361               gate = True;
   9362         }
   9363      }
   9364 
   9365      if (gate) {
   9366         IRTemp rNt   = newTemp(Ity_I32);
   9367         IRTemp rMt   = newTemp(Ity_I32);
   9368         IRTemp res_q = newTemp(Ity_I32);
   9369 
   9370         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9371         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9372 
   9373         assign(res_q, binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
   9374         if (isT)
   9375            putIRegT( regD, mkexpr(res_q), condT );
   9376         else
   9377            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9378 
   9379         DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9380         return True;
   9381      }
   9382      /* fall through */
   9383    }
   9384 
   9385    /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
   9386    {
   9387      UInt regD = 99, regN = 99, regM = 99;
   9388      Bool gate = False;
   9389 
   9390      if (isT) {
   9391         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9392            regN = INSNT0(3,0);
   9393            regD = INSNT1(11,8);
   9394            regM = INSNT1(3,0);
   9395            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9396               gate = True;
   9397         }
   9398      } else {
   9399         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9400             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9401             INSNA(7,4)   == BITS4(0,0,0,1)) {
   9402            regD = INSNA(15,12);
   9403            regN = INSNA(19,16);
   9404            regM = INSNA(3,0);
   9405            if (regD != 15 && regN != 15 && regM != 15)
   9406               gate = True;
   9407         }
   9408      }
   9409 
   9410      if (gate) {
   9411         IRTemp rNt   = newTemp(Ity_I32);
   9412         IRTemp rMt   = newTemp(Ity_I32);
   9413         IRTemp res_q = newTemp(Ity_I32);
   9414 
   9415         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9416         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9417 
   9418         assign(res_q, binop(Iop_QAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
   9419         if (isT)
   9420            putIRegT( regD, mkexpr(res_q), condT );
   9421         else
   9422            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9423 
   9424         DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9425         return True;
   9426      }
   9427      /* fall through */
   9428    }
   9429 
   9430    /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
   9431    {
   9432      UInt regD = 99, regN = 99, regM = 99;
   9433      Bool gate = False;
   9434 
   9435       if (isT) {
   9436         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9437            regN = INSNT0(3,0);
   9438            regD = INSNT1(11,8);
   9439            regM = INSNT1(3,0);
   9440            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9441               gate = True;
   9442         }
   9443      } else {
   9444         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9445             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9446             INSNA(7,4)   == BITS4(0,1,1,1)) {
   9447            regD = INSNA(15,12);
   9448            regN = INSNA(19,16);
   9449            regM = INSNA(3,0);
   9450            if (regD != 15 && regN != 15 && regM != 15)
   9451              gate = True;
   9452         }
   9453      }
   9454 
   9455      if (gate) {
   9456         IRTemp rNt   = newTemp(Ity_I32);
   9457         IRTemp rMt   = newTemp(Ity_I32);
   9458         IRTemp res_q = newTemp(Ity_I32);
   9459 
   9460         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9461         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9462 
   9463         assign(res_q, binop(Iop_QSub16Sx2, mkexpr(rNt), mkexpr(rMt)));
   9464         if (isT)
   9465            putIRegT( regD, mkexpr(res_q), condT );
   9466         else
   9467            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9468 
   9469         DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9470         return True;
   9471      }
   9472      /* fall through */
   9473    }
   9474 
   9475    /////////////////////////////////////////////////////////////////
   9476    /////////////////////////////////////////////////////////////////
   9477    /////////////////////////////////////////////////////////////////
   9478    /////////////////////////////////////////////////////////////////
   9479    /////////////////////////////////////////////////////////////////
   9480 
   9481    /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
   9482    /* note: the hardware seems to construct the result differently
   9483       from wot the manual says. */
   9484    {
   9485      UInt regD = 99, regN = 99, regM = 99;
   9486      Bool gate = False;
   9487 
   9488      if (isT) {
   9489         if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9490            regN = INSNT0(3,0);
   9491            regD = INSNT1(11,8);
   9492            regM = INSNT1(3,0);
   9493            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9494               gate = True;
   9495         }
   9496      } else {
   9497         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9498             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9499             INSNA(7,4)   == BITS4(0,1,0,1)) {
   9500            regD = INSNA(15,12);
   9501            regN = INSNA(19,16);
   9502            regM = INSNA(3,0);
   9503            if (regD != 15 && regN != 15 && regM != 15)
   9504               gate = True;
   9505         }
   9506      }
   9507 
   9508      if (gate) {
   9509         IRTemp irt_regN     = newTemp(Ity_I32);
   9510         IRTemp irt_regM     = newTemp(Ity_I32);
   9511         IRTemp irt_sum      = newTemp(Ity_I32);
   9512         IRTemp irt_diff     = newTemp(Ity_I32);
   9513         IRTemp irt_sum_res  = newTemp(Ity_I32);
   9514         IRTemp irt_diff_res = newTemp(Ity_I32);
   9515 
   9516         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9517         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   9518 
   9519         assign( irt_diff,
   9520                 binop( Iop_Sub32,
   9521                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9522                        binop( Iop_Sar32,
   9523                               binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
   9524                               mkU8(16) ) ) );
   9525         armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL);
   9526 
   9527         assign( irt_sum,
   9528                 binop( Iop_Add32,
   9529                        binop( Iop_Sar32,
   9530                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9531                               mkU8(16) ),
   9532                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) );
   9533         armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL );
   9534 
   9535         IRExpr* ire_result = binop( Iop_Or32,
   9536                                     binop( Iop_Shl32, mkexpr(irt_diff_res),
   9537                                            mkU8(16) ),
   9538                                     binop( Iop_And32, mkexpr(irt_sum_res),
   9539                                            mkU32(0xFFFF)) );
   9540 
   9541         if (isT)
   9542            putIRegT( regD, ire_result, condT );
   9543         else
   9544            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9545 
   9546         DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   9547         return True;
   9548      }
   9549      /* fall through */
   9550    }
   9551 
   9552    /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
   9553    {
   9554      UInt regD = 99, regN = 99, regM = 99;
   9555      Bool gate = False;
   9556 
   9557      if (isT) {
   9558         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9559            regN = INSNT0(3,0);
   9560            regD = INSNT1(11,8);
   9561            regM = INSNT1(3,0);
   9562            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9563               gate = True;
   9564         }
   9565      } else {
   9566         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9567             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9568             INSNA(7,4)   == BITS4(0,0,1,1)) {
   9569            regD = INSNA(15,12);
   9570            regN = INSNA(19,16);
   9571            regM = INSNA(3,0);
   9572            if (regD != 15 && regN != 15 && regM != 15)
   9573               gate = True;
   9574         }
   9575      }
   9576 
   9577      if (gate) {
   9578         IRTemp irt_regN     = newTemp(Ity_I32);
   9579         IRTemp irt_regM     = newTemp(Ity_I32);
   9580         IRTemp irt_sum      = newTemp(Ity_I32);
   9581         IRTemp irt_diff     = newTemp(Ity_I32);
   9582         IRTemp irt_res_sum  = newTemp(Ity_I32);
   9583         IRTemp irt_res_diff = newTemp(Ity_I32);
   9584 
   9585         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9586         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   9587 
   9588         assign( irt_diff,
   9589                 binop( Iop_Sub32,
   9590                        binop( Iop_Sar32,
   9591                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9592                               mkU8(16) ),
   9593                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
   9594         armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL );
   9595 
   9596         assign( irt_sum,
   9597                 binop( Iop_Add32,
   9598                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9599                        binop( Iop_Sar32,
   9600                               binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
   9601                               mkU8(16) ) ) );
   9602         armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL );
   9603 
   9604         IRExpr* ire_result
   9605           = binop( Iop_Or32,
   9606                    binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ),
   9607                    binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) );
   9608 
   9609         if (isT)
   9610            putIRegT( regD, ire_result, condT );
   9611         else
   9612            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9613 
   9614         DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   9615         return True;
   9616      }
   9617      /* fall through */
   9618    }
   9619 
   9620    /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
   9621    {
   9622      UInt regD = 99, regN = 99, regM = 99;
   9623      Bool gate = False;
   9624 
   9625      if (isT) {
   9626         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   9627            regN = INSNT0(3,0);
   9628            regD = INSNT1(11,8);
   9629            regM = INSNT1(3,0);
   9630            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9631               gate = True;
   9632         }
   9633      } else {
   9634         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   9635             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9636             INSNA(7,4)   == BITS4(0,0,1,1)) {
   9637            regD = INSNA(15,12);
   9638            regN = INSNA(19,16);
   9639            regM = INSNA(3,0);
   9640            if (regD != 15 && regN != 15 && regM != 15)
   9641               gate = True;
   9642         }
   9643      }
   9644 
   9645      if (gate) {
   9646         IRTemp irt_regN = newTemp(Ity_I32);
   9647         IRTemp irt_regM = newTemp(Ity_I32);
   9648         IRTemp irt_sum  = newTemp(Ity_I32);
   9649         IRTemp irt_diff = newTemp(Ity_I32);
   9650 
   9651         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9652         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   9653 
   9654         assign( irt_diff,
   9655                 binop( Iop_Sub32,
   9656                        binop( Iop_Sar32,
   9657                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9658                               mkU8(16) ),
   9659                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
   9660 
   9661         assign( irt_sum,
   9662                 binop( Iop_Add32,
   9663                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9664                        binop( Iop_Sar32,
   9665                               binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
   9666                               mkU8(16) ) ) );
   9667 
   9668         IRExpr* ire_result
   9669           = binop( Iop_Or32,
   9670                    binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ),
   9671                    binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) );
   9672 
   9673         IRTemp ge10 = newTemp(Ity_I32);
   9674         assign(ge10, unop(Iop_Not32, mkexpr(irt_diff)));
   9675         put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
   9676         put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
   9677 
   9678         IRTemp ge32 = newTemp(Ity_I32);
   9679         assign(ge32, unop(Iop_Not32, mkexpr(irt_sum)));
   9680         put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
   9681         put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
   9682 
   9683         if (isT)
   9684            putIRegT( regD, ire_result, condT );
   9685         else
   9686            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9687 
   9688         DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   9689         return True;
   9690      }
   9691      /* fall through */
   9692    }
   9693 
   9694    /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
   9695    /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */
   9696    {
   9697      UInt regD = 99, regN = 99, regM = 99, bitM = 99;
   9698      Bool gate = False, isAD = False;
   9699 
   9700      if (isT) {
   9701         if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
   9702             && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
   9703            regN = INSNT0(3,0);
   9704            regD = INSNT1(11,8);
   9705            regM = INSNT1(3,0);
   9706            bitM = INSNT1(4,4);
   9707            isAD = INSNT0(15,4) == 0xFB2;
   9708            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9709               gate = True;
   9710         }
   9711      } else {
   9712         if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
   9713             INSNA(15,12) == BITS4(1,1,1,1)         &&
   9714             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) {
   9715            regD = INSNA(19,16);
   9716            regN = INSNA(3,0);
   9717            regM = INSNA(11,8);
   9718            bitM = INSNA(5,5);
   9719            isAD = INSNA(6,6) == 0;
   9720            if (regD != 15 && regN != 15 && regM != 15)
   9721               gate = True;
   9722         }
   9723      }
   9724 
   9725      if (gate) {
   9726         IRTemp irt_regN    = newTemp(Ity_I32);
   9727         IRTemp irt_regM    = newTemp(Ity_I32);
   9728         IRTemp irt_prod_lo = newTemp(Ity_I32);
   9729         IRTemp irt_prod_hi = newTemp(Ity_I32);
   9730         IRTemp tmpM        = newTemp(Ity_I32);
   9731 
   9732         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9733 
   9734         assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
   9735         assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
   9736 
   9737         assign( irt_prod_lo,
   9738                 binop( Iop_Mul32,
   9739                        binop( Iop_Sar32,
   9740                               binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
   9741                               mkU8(16) ),
   9742                        binop( Iop_Sar32,
   9743                               binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
   9744                               mkU8(16) ) ) );
   9745         assign( irt_prod_hi, binop(Iop_Mul32,
   9746                                    binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)),
   9747                                    binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
   9748         IRExpr* ire_result
   9749            = binop( isAD ? Iop_Add32 : Iop_Sub32,
   9750                     mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) );
   9751 
   9752         if (isT)
   9753            putIRegT( regD, ire_result, condT );
   9754         else
   9755            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9756 
   9757         if (isAD) {
   9758            or_into_QFLAG32(
   9759               signed_overflow_after_Add32( ire_result,
   9760                                            irt_prod_lo, irt_prod_hi ),
   9761               condT
   9762            );
   9763         }
   9764 
   9765         DIP("smu%cd%s%s r%u, r%u, r%u\n",
   9766             isAD ? 'a' : 's',
   9767             bitM ? "x" : "", nCC(conq), regD, regN, regM);
   9768         return True;
   9769      }
   9770      /* fall through */
   9771    }
   9772 
   9773    /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
   9774    /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
   9775    {
   9776      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
   9777      Bool gate = False, isAD = False;
   9778 
   9779      if (isT) {
   9780        if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
   9781            && INSNT1(7,5) == BITS3(0,0,0)) {
   9782            regN = INSNT0(3,0);
   9783            regD = INSNT1(11,8);
   9784            regM = INSNT1(3,0);
   9785            regA = INSNT1(15,12);
   9786            bitM = INSNT1(4,4);
   9787            isAD = INSNT0(15,4) == 0xFB2;
   9788            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
   9789                && !isBadRegT(regA))
   9790               gate = True;
   9791         }
   9792      } else {
   9793         if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
   9794             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
   9795            regD = INSNA(19,16);
   9796            regA = INSNA(15,12);
   9797            regN = INSNA(3,0);
   9798            regM = INSNA(11,8);
   9799            bitM = INSNA(5,5);
   9800            isAD = INSNA(6,6) == 0;
   9801            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
   9802               gate = True;
   9803         }
   9804      }
   9805 
   9806      if (gate) {
   9807         IRTemp irt_regN    = newTemp(Ity_I32);
   9808         IRTemp irt_regM    = newTemp(Ity_I32);
   9809         IRTemp irt_regA    = newTemp(Ity_I32);
   9810         IRTemp irt_prod_lo = newTemp(Ity_I32);
   9811         IRTemp irt_prod_hi = newTemp(Ity_I32);
   9812         IRTemp irt_sum     = newTemp(Ity_I32);
   9813         IRTemp tmpM        = newTemp(Ity_I32);
   9814 
   9815         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9816         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
   9817 
   9818         assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
   9819         assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
   9820 
   9821         assign( irt_prod_lo,
   9822                 binop(Iop_Mul32,
   9823                       binop(Iop_Sar32,
   9824                             binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9825                             mkU8(16)),
   9826                       binop(Iop_Sar32,
   9827                             binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
   9828                             mkU8(16))) );
   9829         assign( irt_prod_hi,
   9830                 binop( Iop_Mul32,
   9831                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9832                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
   9833         assign( irt_sum, binop( isAD ? Iop_Add32 : Iop_Sub32,
   9834                                 mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) );
   9835 
   9836         IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA));
   9837 
   9838         if (isT)
   9839            putIRegT( regD, ire_result, condT );
   9840         else
   9841            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9842 
   9843         if (isAD) {
   9844            or_into_QFLAG32(
   9845               signed_overflow_after_Add32( mkexpr(irt_sum),
   9846                                            irt_prod_lo, irt_prod_hi ),
   9847               condT
   9848            );
   9849         }
   9850 
   9851         or_into_QFLAG32(
   9852            signed_overflow_after_Add32( ire_result, irt_sum, irt_regA ),
   9853            condT
   9854         );
   9855 
   9856         DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n",
   9857             isAD ? 'a' : 's',
   9858             bitM ? "x" : "", nCC(conq), regD, regN, regM, regA);
   9859         return True;
   9860      }
   9861      /* fall through */
   9862    }
   9863 
   9864    /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
   9865    {
   9866      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99;
   9867      Bool gate = False;
   9868 
   9869      if (isT) {
   9870         if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
   9871            regN = INSNT0(3,0);
   9872            regD = INSNT1(11,8);
   9873            regM = INSNT1(3,0);
   9874            regA = INSNT1(15,12);
   9875            bitM = INSNT1(4,4);
   9876            bitN = INSNT1(5,5);
   9877            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
   9878                && !isBadRegT(regA))
   9879               gate = True;
   9880         }
   9881      } else {
   9882         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
   9883             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
   9884            regD = INSNA(19,16);
   9885            regN = INSNA(3,0);
   9886            regM = INSNA(11,8);
   9887            regA = INSNA(15,12);
   9888            bitM = INSNA(6,6);
   9889            bitN = INSNA(5,5);
   9890            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
   9891               gate = True;
   9892         }
   9893      }
   9894 
   9895      if (gate) {
   9896         IRTemp irt_regA = newTemp(Ity_I32);
   9897         IRTemp irt_prod = newTemp(Ity_I32);
   9898 
   9899         assign( irt_prod,
   9900                 binop(Iop_Mul32,
   9901                       binop(Iop_Sar32,
   9902                             binop(Iop_Shl32,
   9903                                   isT ? getIRegT(regN) : getIRegA(regN),
   9904                                   mkU8(bitN ? 0 : 16)),
   9905                             mkU8(16)),
   9906                       binop(Iop_Sar32,
   9907                             binop(Iop_Shl32,
   9908                                   isT ? getIRegT(regM) : getIRegA(regM),
   9909                                   mkU8(bitM ? 0 : 16)),
   9910                             mkU8(16))) );
   9911 
   9912         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
   9913 
   9914         IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA));
   9915 
   9916         if (isT)
   9917            putIRegT( regD, ire_result, condT );
   9918         else
   9919            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9920 
   9921         or_into_QFLAG32(
   9922            signed_overflow_after_Add32( ire_result, irt_prod, irt_regA ),
   9923            condT
   9924         );
   9925 
   9926         DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n",
   9927              bitN ? 't' : 'b', bitM ? 't' : 'b',
   9928              nCC(conq), regD, regN, regM, regA );
   9929         return True;
   9930      }
   9931      /* fall through */
   9932    }
   9933 
   9934    /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
   9935    {
   9936      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
   9937      Bool gate = False;
   9938 
   9939      if (isT) {
   9940         if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
   9941            regN = INSNT0(3,0);
   9942            regD = INSNT1(11,8);
   9943            regM = INSNT1(3,0);
   9944            regA = INSNT1(15,12);
   9945            bitM = INSNT1(4,4);
   9946            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
   9947                && !isBadRegT(regA))
   9948               gate = True;
   9949         }
   9950      } else {
   9951         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
   9952             (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
   9953            regD = INSNA(19,16);
   9954            regN = INSNA(3,0);
   9955            regM = INSNA(11,8);
   9956            regA = INSNA(15,12);
   9957            bitM = INSNA(6,6);
   9958            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
   9959               gate = True;
   9960         }
   9961      }
   9962 
   9963      if (gate) {
   9964         IRTemp irt_regA = newTemp(Ity_I32);
   9965         IRTemp irt_prod = newTemp(Ity_I64);
   9966 
   9967         assign( irt_prod,
   9968                 binop(Iop_MullS32,
   9969                       isT ? getIRegT(regN) : getIRegA(regN),
   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         IRTemp prod32 = newTemp(Ity_I32);
   9979         assign(prod32,
   9980                binop(Iop_Or32,
   9981                      binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)),
   9982                      binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16))
   9983         ));
   9984 
   9985         IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA));
   9986 
   9987         if (isT)
   9988            putIRegT( regD, ire_result, condT );
   9989         else
   9990            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9991 
   9992         or_into_QFLAG32(
   9993            signed_overflow_after_Add32( ire_result, prod32, irt_regA ),
   9994            condT
   9995         );
   9996 
   9997         DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n",
   9998              bitM ? 't' : 'b',
   9999              nCC(conq), regD, regN, regM, regA );
   10000         return True;
   10001      }
   10002      /* fall through */
   10003    }
   10004 
   10005    /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
   10006    /* fixme: fix up the test in v6media.c so that we can pass the ge
   10007       flags as part of the test. */
   10008    {
   10009      UInt regD = 99, regN = 99, regM = 99;
   10010      Bool gate = False;
   10011 
   10012      if (isT) {
   10013         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
   10014            regN = INSNT0(3,0);
   10015            regD = INSNT1(11,8);
   10016            regM = INSNT1(3,0);
   10017            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10018               gate = True;
   10019         }
   10020      } else {
   10021         if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
   10022             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   10023             INSNA(7,4)   == BITS4(1,0,1,1)) {
   10024            regD = INSNA(15,12);
   10025            regN = INSNA(19,16);
   10026            regM = INSNA(3,0);
   10027            if (regD != 15 && regN != 15 && regM != 15)
   10028               gate = True;
   10029         }
   10030      }
   10031 
   10032      if (gate) {
   10033         IRTemp irt_ge_flag0 = newTemp(Ity_I32);
   10034         IRTemp irt_ge_flag1 = newTemp(Ity_I32);
   10035         IRTemp irt_ge_flag2 = newTemp(Ity_I32);
   10036         IRTemp irt_ge_flag3 = newTemp(Ity_I32);
   10037 
   10038         assign( irt_ge_flag0, get_GEFLAG32(0) );
   10039         assign( irt_ge_flag1, get_GEFLAG32(1) );
   10040         assign( irt_ge_flag2, get_GEFLAG32(2) );
   10041         assign( irt_ge_flag3, get_GEFLAG32(3) );
   10042 
   10043         IRExpr* ire_ge_flag0_or
   10044           = binop(Iop_Or32, mkexpr(irt_ge_flag0),
   10045                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0)));
   10046         IRExpr* ire_ge_flag1_or
   10047           = binop(Iop_Or32, mkexpr(irt_ge_flag1),
   10048                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1)));
   10049         IRExpr* ire_ge_flag2_or
   10050           = binop(Iop_Or32, mkexpr(irt_ge_flag2),
   10051                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2)));
   10052         IRExpr* ire_ge_flag3_or
   10053           = binop(Iop_Or32, mkexpr(irt_ge_flag3),
   10054                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3)));
   10055 
   10056         IRExpr* ire_ge_flags
   10057           = binop( Iop_Or32,
   10058                    binop(Iop_Or32,
   10059                          binop(Iop_And32,
   10060                                binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)),
   10061                                mkU32(0x000000ff)),
   10062                          binop(Iop_And32,
   10063                                binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)),
   10064                                mkU32(0x0000ff00))),
   10065                    binop(Iop_Or32,
   10066                          binop(Iop_And32,
   10067                                binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)),
   10068                                mkU32(0x00ff0000)),
   10069                          binop(Iop_And32,
   10070                                binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)),
   10071                                mkU32(0xff000000))) );
   10072 
   10073         IRExpr* ire_result
   10074           = binop(Iop_Or32,
   10075                   binop(Iop_And32,
   10076                         isT ? getIRegT(regN) : getIRegA(regN),
   10077                         ire_ge_flags ),
   10078                   binop(Iop_And32,
   10079                         isT ? getIRegT(regM) : getIRegA(regM),
   10080                         unop(Iop_Not32, ire_ge_flags)));
   10081 
   10082         if (isT)
   10083            putIRegT( regD, ire_result, condT );
   10084         else
   10085            putIRegA( regD, ire_result, condT, Ijk_Boring );
   10086 
   10087         DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   10088         return True;
   10089      }
   10090      /* fall through */
   10091    }
   10092 
   10093    /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
   10094    {
   10095      UInt regD = 99, regN = 99, regM = 99, rotate = 99;
   10096      Bool gate = False;
   10097 
   10098      if (isT) {
   10099         if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
   10100            regN   = INSNT0(3,0);
   10101            regD   = INSNT1(11,8);
   10102            regM   = INSNT1(3,0);
   10103            rotate = INSNT1(5,4);
   10104            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10105               gate = True;
   10106         }
   10107      } else {
   10108         if (INSNA(27,20) == BITS8(0,1,1,0,1,1,0,0) &&
   10109             INSNA(9,4)   == BITS6(0,0,0,1,1,1) ) {
   10110            regD   = INSNA(15,12);
   10111            regN   = INSNA(19,16);
   10112            regM   = INSNA(3,0);
   10113            rotate = INSNA(11,10);
   10114            if (regD != 15 && regN != 15 && regM != 15)
   10115              gate = True;
   10116         }
   10117      }
   10118 
   10119      if (gate) {
   10120         IRTemp irt_regN = newTemp(Ity_I32);
   10121         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   10122 
   10123         IRTemp irt_regM = newTemp(Ity_I32);
   10124         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   10125 
   10126         IRTemp irt_rot = newTemp(Ity_I32);
   10127         assign( irt_rot, binop(Iop_And32,
   10128                                genROR32(irt_regM, 8 * rotate),
   10129                                mkU32(0x00FF00FF)) );
   10130 
   10131         IRExpr* resLo
   10132            = binop(Iop_And32,
   10133                    binop(Iop_Add32, mkexpr(irt_regN), mkexpr(irt_rot)),
   10134                    mkU32(0x0000FFFF));
   10135 
   10136         IRExpr* resHi
   10137            = binop(Iop_Add32,
   10138                    binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF0000)),
   10139                    binop(Iop_And32, mkexpr(irt_rot),  mkU32(0xFFFF0000)));
   10140 
   10141         IRExpr* ire_result
   10142            = binop( Iop_Or32, resHi, resLo );
   10143 
   10144         if (isT)
   10145            putIRegT( regD, ire_result, condT );
   10146         else
   10147            putIRegA( regD, ire_result, condT, Ijk_Boring );
   10148 
   10149         DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n",
   10150              nCC(conq), regD, regN, regM, 8 * rotate );
   10151         return True;
   10152      }
   10153      /* fall through */
   10154    }
   10155 
   10156    /* --------------- usad8  Rd,Rn,Rm    ---------------- */
   10157    /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */
   10158    {
   10159      UInt rD = 99, rN = 99, rM = 99, rA = 99;
   10160      Bool gate = False;
   10161 
   10162      if (isT) {
   10163        if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) {
   10164            rN = INSNT0(3,0);
   10165            rA = INSNT1(15,12);
   10166            rD = INSNT1(11,8);
   10167            rM = INSNT1(3,0);
   10168            if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && rA != 13)
   10169               gate = True;
   10170         }
   10171      } else {
   10172         if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) &&
   10173             INSNA(7,4)   == BITS4(0,0,0,1) ) {
   10174            rD = INSNA(19,16);
   10175            rA = INSNA(15,12);
   10176            rM = INSNA(11,8);
   10177            rN = INSNA(3,0);
   10178            if (rD != 15 && rN != 15 && rM != 15 /* but rA can be 15 */)
   10179               gate = True;
   10180         }
   10181      }
   10182      /* We allow rA == 15, to denote the usad8 (no accumulator) case. */
   10183 
   10184      if (gate) {
   10185         IRExpr* rNe = isT ? getIRegT(rN) : getIRegA(rN);
   10186         IRExpr* rMe = isT ? getIRegT(rM) : getIRegA(rM);
   10187         IRExpr* rAe = rA == 15 ? mkU32(0)
   10188                                : (isT ? getIRegT(rA) : getIRegA(rA));
   10189         IRExpr* res = binop(Iop_Add32,
   10190                             binop(Iop_Sad8Ux4, rNe, rMe),
   10191                             rAe);
   10192         if (isT)
   10193            putIRegT( rD, res, condT );
   10194         else
   10195            putIRegA( rD, res, condT, Ijk_Boring );
   10196 
   10197         if (rA == 15) {
   10198            DIP( "usad8%s r%u, r%u, r%u\n",
   10199                 nCC(conq), rD, rN, rM );
   10200         } else {
   10201            DIP( "usada8%s r%u, r%u, r%u, r%u\n",
   10202                 nCC(conq), rD, rN, rM, rA );
   10203         }
   10204         return True;
   10205      }
   10206      /* fall through */
   10207    }
   10208 
   10209    /* ---------- Doesn't match anything. ---------- */
   10210    return False;
   10211 
   10212 #  undef INSNA
   10213 #  undef INSNT0
   10214 #  undef INSNT1
   10215 }
   10216 
   10217 
   10218 /*------------------------------------------------------------*/
   10219 /*--- LDMxx/STMxx helper (both ARM and Thumb32)            ---*/
   10220 /*------------------------------------------------------------*/
   10221 
   10222 /* Generate IR for LDMxx and STMxx.  This is complex.  Assumes it's
   10223    unconditional, so the caller must produce a jump-around before
   10224    calling this, if the insn is to be conditional.  Caller is
   10225    responsible for all validation of parameters.  For LDMxx, if PC is
   10226    amongst the values loaded, caller is also responsible for
   10227    generating the jump. */
   10228 static void mk_ldm_stm ( Bool arm,     /* True: ARM, False: Thumb */
   10229                          UInt rN,      /* base reg */
   10230                          UInt bINC,    /* 1: inc,  0: dec */
   10231                          UInt bBEFORE, /* 1: inc/dec before, 0: after */
   10232                          UInt bW,      /* 1: writeback to Rn */
   10233                          UInt bL,      /* 1: load, 0: store */
   10234                          UInt regList )
   10235 {
   10236    Int i, r, m, nRegs;
   10237    IRTemp jk = Ijk_Boring;
   10238 
   10239    /* Get hold of the old Rn value.  We might need to write its value
   10240       to memory during a store, and if it's also the writeback
   10241       register then we need to get its value now.  We can't treat it
   10242       exactly like the other registers we're going to transfer,
   10243       because for xxMDA and xxMDB writeback forms, the generated IR
   10244       updates Rn in the guest state before any transfers take place.
   10245       We have to do this as per comments below, in order that if Rn is
   10246       the stack pointer then it always has a value is below or equal
   10247       to any of the transfer addresses.  Ick. */
   10248    IRTemp oldRnT = newTemp(Ity_I32);
   10249    assign(oldRnT, arm ? getIRegA(rN) : getIRegT(rN));
   10250 
   10251    IRTemp anchorT = newTemp(Ity_I32);
   10252    /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx
   10253       ignore the bottom two bits of the address.  However, Cortex-A8
   10254       doesn't seem to care.  Hence: */
   10255    /* No .. don't force alignment .. */
   10256    /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */
   10257    /* Instead, use the potentially misaligned address directly. */
   10258    assign(anchorT, mkexpr(oldRnT));
   10259 
   10260    IROp opADDorSUB = bINC ? Iop_Add32 : Iop_Sub32;
   10261    // bINC == 1:  xxMIA, xxMIB
   10262    // bINC == 0:  xxMDA, xxMDB
   10263 
   10264    // For xxMDA and xxMDB, update Rn first if necessary.  We have
   10265    // to do this first so that, for the common idiom of the transfers
   10266    // faulting because we're pushing stuff onto a stack and the stack
   10267    // is growing down onto allocate-on-fault pages (as Valgrind simulates),
   10268    // we need to have the SP up-to-date "covering" (pointing below) the
   10269    // transfer area.  For the same reason, if we are doing xxMIA or xxMIB,
   10270    // do the transfer first, and then update rN afterwards.
   10271    nRegs = 0;
   10272    for (i = 0; i < 16; i++) {
   10273      if ((regList & (1 << i)) != 0)
   10274          nRegs++;
   10275    }
   10276    if (bW == 1 && !bINC) {
   10277       IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
   10278       if (arm)
   10279          putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
   10280       else
   10281          putIRegT( rN, e, IRTemp_INVALID );
   10282    }
   10283 
   10284    // Make up a list of the registers to transfer, and their offsets
   10285    // in memory relative to the anchor.  If the base reg (Rn) is part
   10286    // of the transfer, then do it last for a load and first for a store.
   10287    UInt xReg[16], xOff[16];
   10288    Int  nX = 0;
   10289    m = 0;
   10290    for (i = 0; i < 16; i++) {
   10291       r = bINC ? i : (15-i);
   10292       if (0 == (regList & (1<<r)))
   10293          continue;
   10294       if (bBEFORE)
   10295          m++;
   10296       /* paranoia: check we aren't transferring the writeback
   10297          register during a load. Should be assured by decode-point
   10298          check above. */
   10299       if (bW == 1 && bL == 1)
   10300          vassert(r != rN);
   10301 
   10302       xOff[nX] = 4 * m;
   10303       xReg[nX] = r;
   10304       nX++;
   10305 
   10306       if (!bBEFORE)
   10307          m++;
   10308    }
   10309    vassert(m == nRegs);
   10310    vassert(nX == nRegs);
   10311    vassert(nX <= 16);
   10312 
   10313    if (bW == 0 && (regList & (1<<rN)) != 0) {
   10314       /* Non-writeback, and basereg is to be transferred.  Do its
   10315          transfer last for a load and first for a store.  Requires
   10316          reordering xOff/xReg. */
   10317       if (0) {
   10318          vex_printf("\nREG_LIST_PRE: (rN=%d)\n", rN);
   10319          for (i = 0; i < nX; i++)
   10320             vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
   10321          vex_printf("\n");
   10322       }
   10323 
   10324       vassert(nX > 0);
   10325       for (i = 0; i < nX; i++) {
   10326          if (xReg[i] == rN)
   10327              break;
   10328       }
   10329       vassert(i < nX); /* else we didn't find it! */
   10330       UInt tReg = xReg[i];
   10331       UInt tOff = xOff[i];
   10332       if (bL == 1) {
   10333          /* load; make this transfer happen last */
   10334          if (i < nX-1) {
   10335             for (m = i+1; m < nX; m++) {
   10336                xReg[m-1] = xReg[m];
   10337                xOff[m-1] = xOff[m];
   10338             }
   10339             vassert(m == nX);
   10340             xReg[m-1] = tReg;
   10341             xOff[m-1] = tOff;
   10342          }
   10343       } else {
   10344          /* store; make this transfer happen first */
   10345          if (i > 0) {
   10346             for (m = i-1; m >= 0; m--) {
   10347                xReg[m+1] = xReg[m];
   10348                xOff[m+1] = xOff[m];
   10349             }
   10350             vassert(m == -1);
   10351             xReg[0] = tReg;
   10352             xOff[0] = tOff;
   10353          }
   10354       }
   10355 
   10356       if (0) {
   10357          vex_printf("REG_LIST_POST:\n");
   10358          for (i = 0; i < nX; i++)
   10359             vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
   10360          vex_printf("\n");
   10361       }
   10362    }
   10363 
   10364    /* According to the Cortex A8 TRM Sec. 5.2.1, LDM(1) with r13 as the base
   10365        register and PC in the register list is a return for purposes of branch
   10366        prediction.
   10367       The ARM ARM Sec. C9.10.1 further specifies that writeback must be enabled
   10368        to be counted in event 0x0E (Procedure return).*/
   10369    if (rN == 13 && bL == 1 && bINC && !bBEFORE && bW == 1) {
   10370       jk = Ijk_Ret;
   10371    }
   10372 
   10373    /* Actually generate the transfers */
   10374    for (i = 0; i < nX; i++) {
   10375       r = xReg[i];
   10376       if (bL == 1) {
   10377          IRExpr* e = loadLE(Ity_I32,
   10378                             binop(opADDorSUB, mkexpr(anchorT),
   10379                                   mkU32(xOff[i])));
   10380          if (arm) {
   10381             putIRegA( r, e, IRTemp_INVALID, jk );
   10382          } else {
   10383             // no: putIRegT( r, e, IRTemp_INVALID );
   10384             // putIRegT refuses to write to R15.  But that might happen.
   10385             // Since this is uncond, and we need to be able to
   10386             // write the PC, just use the low level put:
   10387             llPutIReg( r, e );
   10388          }
   10389       } else {
   10390          /* if we're storing Rn, make sure we use the correct
   10391             value, as per extensive comments above */
   10392          storeLE( binop(opADDorSUB, mkexpr(anchorT), mkU32(xOff[i])),
   10393                   r == rN ? mkexpr(oldRnT)
   10394                           : (arm ? getIRegA(r) : getIRegT(r) ) );
   10395       }
   10396    }
   10397 
   10398    // If we are doing xxMIA or xxMIB,
   10399    // do the transfer first, and then update rN afterwards.
   10400    if (bW == 1 && bINC) {
   10401       IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
   10402       if (arm)
   10403          putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
   10404       else
   10405          putIRegT( rN, e, IRTemp_INVALID );
   10406    }
   10407 }
   10408 
   10409 
   10410 /*------------------------------------------------------------*/
   10411 /*--- VFP (CP 10 and 11) instructions                      ---*/
   10412 /*------------------------------------------------------------*/
   10413 
   10414 /* Both ARM and Thumb */
   10415 
   10416 /* Translate a CP10 or CP11 instruction.  If successful, returns
   10417    True and *dres may or may not be updated.  If failure, returns
   10418    False and doesn't change *dres nor create any IR.
   10419 
   10420    The ARM and Thumb encodings are identical for the low 28 bits of
   10421    the insn (yay!) and that's what the caller must supply, iow, imm28
   10422    has the top 4 bits masked out.  Caller is responsible for
   10423    determining whether the masked-out bits are valid for a CP10/11
   10424    insn.  The rules for the top 4 bits are:
   10425 
   10426      ARM: 0000 to 1110 allowed, and this is the gating condition.
   10427      1111 (NV) is not allowed.
   10428 
   10429      Thumb: must be 1110.  The gating condition is taken from
   10430      ITSTATE in the normal way.
   10431 
   10432    Conditionalisation:
   10433 
   10434    Caller must supply an IRTemp 'condT' holding the gating condition,
   10435    or IRTemp_INVALID indicating the insn is always executed.
   10436 
   10437    Caller must also supply an ARMCondcode 'cond'.  This is only used
   10438    for debug printing, no other purpose.  For ARM, this is simply the
   10439    top 4 bits of the original instruction.  For Thumb, the condition
   10440    is not (really) known until run time, and so ARMCondAL should be
   10441    passed, only so that printing of these instructions does not show
   10442    any condition.
   10443 
   10444    Finally, the caller must indicate whether this occurs in ARM or
   10445    Thumb code.
   10446 */
   10447 static Bool decode_CP10_CP11_instruction (
   10448                /*MOD*/DisResult* dres,
   10449                UInt              insn28,
   10450                IRTemp            condT,
   10451                ARMCondcode       conq,
   10452                Bool              isT
   10453             )
   10454 {
   10455 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn28, (_bMax), (_bMin))
   10456 
   10457    vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation
   10458 
   10459    if (isT) {
   10460       vassert(conq == ARMCondAL);
   10461    } else {
   10462       vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
   10463    }
   10464 
   10465    /* ----------------------------------------------------------- */
   10466    /* -- VFP instructions -- double precision (mostly)         -- */
   10467    /* ----------------------------------------------------------- */
   10468 
   10469    /* --------------------- fldmx, fstmx --------------------- */
   10470    /*
   10471                                  31   27   23   19 15 11   7   0
   10472                                          P U WL
   10473       C4-100, C5-26  1  FSTMX    cond 1100 1000 Rn Dd 1011 offset
   10474       C4-100, C5-28  2  FSTMIAX  cond 1100 1010 Rn Dd 1011 offset
   10475       C4-100, C5-30  3  FSTMDBX  cond 1101 0010 Rn Dd 1011 offset
   10476 
   10477       C4-42, C5-26   1  FLDMX    cond 1100 1001 Rn Dd 1011 offset
   10478       C4-42, C5-28   2  FLDMIAX  cond 1100 1011 Rn Dd 1011 offset
   10479       C4-42, C5-30   3  FLDMDBX  cond 1101 0011 Rn Dd 1011 offset
   10480 
   10481       Regs transferred: Dd .. D(d + (offset-3)/2)
   10482       offset must be odd, must not imply a reg > 15
   10483       IA/DB: Rn is changed by (4 + 8 x # regs transferred)
   10484 
   10485       case coding:
   10486          1  at-Rn   (access at Rn)
   10487          2  ia-Rn   (access at Rn, then Rn += 4+8n)
   10488          3  db-Rn   (Rn -= 4+8n,   then access at Rn)
   10489    */
   10490    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
   10491        && INSN(11,8) == BITS4(1,0,1,1)) {
   10492       UInt bP      = (insn28 >> 24) & 1;
   10493       UInt bU      = (insn28 >> 23) & 1;
   10494       UInt bW      = (insn28 >> 21) & 1;
   10495       UInt bL      = (insn28 >> 20) & 1;
   10496       UInt offset  = (insn28 >> 0) & 0xFF;
   10497       UInt rN      = INSN(19,16);
   10498       UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
   10499       UInt nRegs   = (offset - 1) / 2;
   10500       UInt summary = 0;
   10501       Int  i;
   10502 
   10503       /**/ if (bP == 0 && bU == 1 && bW == 0) {
   10504          summary = 1;
   10505       }
   10506       else if (bP == 0 && bU == 1 && bW == 1) {
   10507          summary = 2;
   10508       }
   10509       else if (bP == 1 && bU == 0 && bW == 1) {
   10510          summary = 3;
   10511       }
   10512       else goto after_vfp_fldmx_fstmx;
   10513 
   10514       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
   10515       if (rN == 15 && (summary == 2 || summary == 3 || isT))
   10516          goto after_vfp_fldmx_fstmx;
   10517 
   10518       /* offset must be odd, and specify at least one register */
   10519       if (0 == (offset & 1) || offset < 3)
   10520          goto after_vfp_fldmx_fstmx;
   10521 
   10522       /* can't transfer regs after D15 */
   10523       if (dD + nRegs - 1 >= 32)
   10524          goto after_vfp_fldmx_fstmx;
   10525 
   10526       /* Now, we can't do a conditional load or store, since that very
   10527          likely will generate an exception.  So we have to take a side
   10528          exit at this point if the condition is false. */
   10529       if (condT != IRTemp_INVALID) {
   10530          if (isT)
   10531             mk_skip_over_T32_if_cond_is_false( condT );
   10532          else
   10533             mk_skip_over_A32_if_cond_is_false( condT );
   10534          condT = IRTemp_INVALID;
   10535       }
   10536       /* Ok, now we're unconditional.  Do the load or store. */
   10537 
   10538       /* get the old Rn value */
   10539       IRTemp rnT = newTemp(Ity_I32);
   10540       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
   10541                            rN == 15));
   10542 
   10543       /* make a new value for Rn, post-insn */
   10544       IRTemp rnTnew = IRTemp_INVALID;
   10545       if (summary == 2 || summary == 3) {
   10546          rnTnew = newTemp(Ity_I32);
   10547          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
   10548                               mkexpr(rnT),
   10549                               mkU32(4 + 8 * nRegs)));
   10550       }
   10551 
   10552       /* decide on the base transfer address */
   10553       IRTemp taT = newTemp(Ity_I32);
   10554       assign(taT,  summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
   10555 
   10556       /* update Rn if necessary -- in case 3, we're moving it down, so
   10557          update before any memory reference, in order to keep Memcheck
   10558          and V's stack-extending logic (on linux) happy */
   10559       if (summary == 3) {
   10560          if (isT)
   10561             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   10562          else
   10563             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   10564       }
   10565 
   10566       /* generate the transfers */
   10567       for (i = 0; i < nRegs; i++) {
   10568          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
   10569          if (bL) {
   10570             putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
   10571          } else {
   10572             storeLE(addr, getDReg(dD + i));
   10573          }
   10574       }
   10575 
   10576       /* update Rn if necessary -- in case 2, we're moving it up, so
   10577          update after any memory reference, in order to keep Memcheck
   10578          and V's stack-extending logic (on linux) happy */
   10579       if (summary == 2) {
   10580          if (isT)
   10581             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   10582          else
   10583             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   10584       }
   10585 
   10586       HChar* nm = bL==1 ? "ld" : "st";
   10587       switch (summary) {
   10588          case 1:  DIP("f%smx%s r%u, {d%u-d%u}\n",
   10589                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10590                   break;
   10591          case 2:  DIP("f%smiax%s r%u!, {d%u-d%u}\n",
   10592                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10593                   break;
   10594          case 3:  DIP("f%smdbx%s r%u!, {d%u-d%u}\n",
   10595                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10596                   break;
   10597          default: vassert(0);
   10598       }
   10599 
   10600       goto decode_success_vfp;
   10601       /* FIXME alignment constraints? */
   10602    }
   10603 
   10604   after_vfp_fldmx_fstmx:
   10605 
   10606    /* --------------------- fldmd, fstmd --------------------- */
   10607    /*
   10608                                  31   27   23   19 15 11   7   0
   10609                                          P U WL
   10610       C4-96, C5-26   1  FSTMD    cond 1100 1000 Rn Dd 1011 offset
   10611       C4-96, C5-28   2  FSTMDIA  cond 1100 1010 Rn Dd 1011 offset
   10612       C4-96, C5-30   3  FSTMDDB  cond 1101 0010 Rn Dd 1011 offset
   10613 
   10614       C4-38, C5-26   1  FLDMD    cond 1100 1001 Rn Dd 1011 offset
   10615       C4-38, C5-28   2  FLDMIAD  cond 1100 1011 Rn Dd 1011 offset
   10616       C4-38, C5-30   3  FLDMDBD  cond 1101 0011 Rn Dd 1011 offset
   10617 
   10618       Regs transferred: Dd .. D(d + (offset-2)/2)
   10619       offset must be even, must not imply a reg > 15
   10620       IA/DB: Rn is changed by (8 x # regs transferred)
   10621 
   10622       case coding:
   10623          1  at-Rn   (access at Rn)
   10624          2  ia-Rn   (access at Rn, then Rn += 8n)
   10625          3  db-Rn   (Rn -= 8n,     then access at Rn)
   10626    */
   10627    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
   10628        && INSN(11,8) == BITS4(1,0,1,1)) {
   10629       UInt bP      = (insn28 >> 24) & 1;
   10630       UInt bU      = (insn28 >> 23) & 1;
   10631       UInt bW      = (insn28 >> 21) & 1;
   10632       UInt bL      = (insn28 >> 20) & 1;
   10633       UInt offset  = (insn28 >> 0) & 0xFF;
   10634       UInt rN      = INSN(19,16);
   10635       UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
   10636       UInt nRegs   = offset / 2;
   10637       UInt summary = 0;
   10638       Int  i;
   10639 
   10640       /**/ if (bP == 0 && bU == 1 && bW == 0) {
   10641          summary = 1;
   10642       }
   10643       else if (bP == 0 && bU == 1 && bW == 1) {
   10644          summary = 2;
   10645       }
   10646       else if (bP == 1 && bU == 0 && bW == 1) {
   10647          summary = 3;
   10648       }
   10649       else goto after_vfp_fldmd_fstmd;
   10650 
   10651       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
   10652       if (rN == 15 && (summary == 2 || summary == 3 || isT))
   10653          goto after_vfp_fldmd_fstmd;
   10654 
   10655       /* offset must be even, and specify at least one register */
   10656       if (1 == (offset & 1) || offset < 2)
   10657          goto after_vfp_fldmd_fstmd;
   10658 
   10659       /* can't transfer regs after D15 */
   10660       if (dD + nRegs - 1 >= 32)
   10661          goto after_vfp_fldmd_fstmd;
   10662 
   10663       /* Now, we can't do a conditional load or store, since that very
   10664          likely will generate an exception.  So we have to take a side
   10665          exit at this point if the condition is false. */
   10666       if (condT != IRTemp_INVALID) {
   10667          if (isT)
   10668             mk_skip_over_T32_if_cond_is_false( condT );
   10669          else
   10670             mk_skip_over_A32_if_cond_is_false( condT );
   10671          condT = IRTemp_INVALID;
   10672       }
   10673       /* Ok, now we're unconditional.  Do the load or store. */
   10674 
   10675       /* get the old Rn value */
   10676       IRTemp rnT = newTemp(Ity_I32);
   10677       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
   10678                            rN == 15));
   10679 
   10680       /* make a new value for Rn, post-insn */
   10681       IRTemp rnTnew = IRTemp_INVALID;
   10682       if (summary == 2 || summary == 3) {
   10683          rnTnew = newTemp(Ity_I32);
   10684          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
   10685                               mkexpr(rnT),
   10686                               mkU32(8 * nRegs)));
   10687       }
   10688 
   10689       /* decide on the base transfer address */
   10690       IRTemp taT = newTemp(Ity_I32);
   10691       assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
   10692 
   10693       /* update Rn if necessary -- in case 3, we're moving it down, so
   10694          update before any memory reference, in order to keep Memcheck
   10695          and V's stack-extending logic (on linux) happy */
   10696       if (summary == 3) {
   10697          if (isT)
   10698             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   10699          else
   10700             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   10701       }
   10702 
   10703       /* generate the transfers */
   10704       for (i = 0; i < nRegs; i++) {
   10705          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
   10706          if (bL) {
   10707             putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
   10708          } else {
   10709             storeLE(addr, getDReg(dD + i));
   10710          }
   10711       }
   10712 
   10713       /* update Rn if necessary -- in case 2, we're moving it up, so
   10714          update after any memory reference, in order to keep Memcheck
   10715          and V's stack-extending logic (on linux) happy */
   10716       if (summary == 2) {
   10717          if (isT)
   10718             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   10719          else
   10720             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   10721       }
   10722 
   10723       HChar* nm = bL==1 ? "ld" : "st";
   10724       switch (summary) {
   10725          case 1:  DIP("f%smd%s r%u, {d%u-d%u}\n",
   10726                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10727                   break;
   10728          case 2:  DIP("f%smiad%s r%u!, {d%u-d%u}\n",
   10729                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10730                   break;
   10731          case 3:  DIP("f%smdbd%s r%u!, {d%u-d%u}\n",
   10732                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10733                   break;
   10734          default: vassert(0);
   10735       }
   10736 
   10737       goto decode_success_vfp;
   10738       /* FIXME alignment constraints? */
   10739    }
   10740 
   10741   after_vfp_fldmd_fstmd:
   10742 
   10743    /* ------------------- fmrx, fmxr ------------------- */
   10744    if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20)
   10745        && BITS4(1,0,1,0) == INSN(11,8)
   10746        && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
   10747       UInt rD  = INSN(15,12);
   10748       UInt reg = INSN(19,16);
   10749       if (reg == BITS4(0,0,0,1)) {
   10750          if (rD == 15) {
   10751             IRTemp nzcvT = newTemp(Ity_I32);
   10752             /* When rD is 15, we are copying the top 4 bits of FPSCR
   10753                into CPSR.  That is, set the flags thunk to COPY and
   10754                install FPSCR[31:28] as the value to copy. */
   10755             assign(nzcvT, binop(Iop_And32,
   10756                                 IRExpr_Get(OFFB_FPSCR, Ity_I32),
   10757                                 mkU32(0xF0000000)));
   10758             setFlags_D1(ARMG_CC_OP_COPY, nzcvT, condT);
   10759             DIP("fmstat%s\n", nCC(conq));
   10760          } else {
   10761             /* Otherwise, merely transfer FPSCR to r0 .. r14. */
   10762             IRExpr* e = IRExpr_Get(OFFB_FPSCR, Ity_I32);
   10763             if (isT)
   10764                putIRegT(rD, e, condT);
   10765             else
   10766                putIRegA(rD, e, condT, Ijk_Boring);
   10767             DIP("fmrx%s r%u, fpscr\n", nCC(conq), rD);
   10768          }
   10769          goto decode_success_vfp;
   10770       }
   10771       /* fall through */
   10772    }
   10773 
   10774    if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20)
   10775        && BITS4(1,0,1,0) == INSN(11,8)
   10776        && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
   10777       UInt rD  = INSN(15,12);
   10778       UInt reg = INSN(19,16);
   10779       if (reg == BITS4(0,0,0,1)) {
   10780          putMiscReg32(OFFB_FPSCR,
   10781                       isT ? getIRegT(rD) : getIRegA(rD), condT);
   10782          DIP("fmxr%s fpscr, r%u\n", nCC(conq), rD);
   10783          goto decode_success_vfp;
   10784       }
   10785       /* fall through */
   10786    }
   10787 
   10788    /* --------------------- vmov --------------------- */
   10789    // VMOV dM, rD, rN
   10790    if (0x0C400B10 == (insn28 & 0x0FF00FD0)) {
   10791       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
   10792       UInt rD = INSN(15,12); /* lo32 */
   10793       UInt rN = INSN(19,16); /* hi32 */
   10794       if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))) {
   10795          /* fall through */
   10796       } else {
   10797          putDReg(dM,
   10798                  unop(Iop_ReinterpI64asF64,
   10799                       binop(Iop_32HLto64,
   10800                             isT ? getIRegT(rN) : getIRegA(rN),
   10801                             isT ? getIRegT(rD) : getIRegA(rD))),
   10802                  condT);
   10803          DIP("vmov%s d%u, r%u, r%u\n", nCC(conq), dM, rD, rN);
   10804          goto decode_success_vfp;
   10805       }
   10806       /* fall through */
   10807    }
   10808 
   10809    // VMOV rD, rN, dM
   10810    if (0x0C500B10 == (insn28 & 0x0FF00FD0)) {
   10811       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
   10812       UInt rD = INSN(15,12); /* lo32 */
   10813       UInt rN = INSN(19,16); /* hi32 */
   10814       if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))
   10815           || rD == rN) {
   10816          /* fall through */
   10817       } else {
   10818          IRTemp i64 = newTemp(Ity_I64);
   10819          assign(i64, unop(Iop_ReinterpF64asI64, getDReg(dM)));
   10820          IRExpr* hi32 = unop(Iop_64HIto32, mkexpr(i64));
   10821          IRExpr* lo32 = unop(Iop_64to32,   mkexpr(i64));
   10822          if (isT) {
   10823             putIRegT(rN, hi32, condT);
   10824             putIRegT(rD, lo32, condT);
   10825          } else {
   10826             putIRegA(rN, hi32, condT, Ijk_Boring);
   10827             putIRegA(rD, lo32, condT, Ijk_Boring);
   10828          }
   10829          DIP("vmov%s r%u, r%u, d%u\n", nCC(conq), rD, rN, dM);
   10830          goto decode_success_vfp;
   10831       }
   10832       /* fall through */
   10833    }
   10834 
   10835    // VMOV sD, sD+1, rN, rM
   10836    if (0x0C400A10 == (insn28 & 0x0FF00FD0)) {
   10837       UInt sD = (INSN(3,0) << 1) | INSN(5,5);
   10838       UInt rN = INSN(15,12);
   10839       UInt rM = INSN(19,16);
   10840       if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
   10841           || sD == 31) {
   10842          /* fall through */
   10843       } else {
   10844          putFReg(sD,
   10845                  unop(Iop_ReinterpI32asF32, isT ? getIRegT(rN) : getIRegA(rN)),
   10846                  condT);
   10847          putFReg(sD+1,
   10848                  unop(Iop_ReinterpI32asF32, isT ? getIRegT(rM) : getIRegA(rM)),
   10849                  condT);
   10850          DIP("vmov%s, s%u, s%u, r%u, r%u\n",
   10851               nCC(conq), sD, sD + 1, rN, rM);
   10852          goto decode_success_vfp;
   10853       }
   10854    }
   10855 
   10856    // VMOV rN, rM, sD, sD+1
   10857    if (0x0C500A10 == (insn28 & 0x0FF00FD0)) {
   10858       UInt sD = (INSN(3,0) << 1) | INSN(5,5);
   10859       UInt rN = INSN(15,12);
   10860       UInt rM = INSN(19,16);
   10861       if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
   10862           || sD == 31 || rN == rM) {
   10863          /* fall through */
   10864       } else {
   10865          IRExpr* res0 = unop(Iop_ReinterpF32asI32, getFReg(sD));
   10866          IRExpr* res1 = unop(Iop_ReinterpF32asI32, getFReg(sD+1));
   10867          if (isT) {
   10868             putIRegT(rN, res0, condT);
   10869             putIRegT(rM, res1, condT);
   10870          } else {
   10871             putIRegA(rN, res0, condT, Ijk_Boring);
   10872             putIRegA(rM, res1, condT, Ijk_Boring);
   10873          }
   10874          DIP("vmov%s, r%u, r%u, s%u, s%u\n",
   10875              nCC(conq), rN, rM, sD, sD + 1);
   10876          goto decode_success_vfp;
   10877       }
   10878    }
   10879 
   10880    // VMOV rD[x], rT  (ARM core register to scalar)
   10881    if (0x0E000B10 == (insn28 & 0x0F900F1F)) {
   10882       UInt rD  = (INSN(7,7) << 4) | INSN(19,16);
   10883       UInt rT  = INSN(15,12);
   10884       UInt opc = (INSN(22,21) << 2) | INSN(6,5);
   10885       UInt index;
   10886       if (rT == 15 || (isT && rT == 13)) {
   10887          /* fall through */
   10888       } else {
   10889          if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
   10890             index = opc & 7;
   10891             putDRegI64(rD, triop(Iop_SetElem8x8,
   10892                                  getDRegI64(rD),
   10893                                  mkU8(index),
   10894                                  unop(Iop_32to8,
   10895                                       isT ? getIRegT(rT) : getIRegA(rT))),
   10896                            condT);
   10897             DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
   10898             goto decode_success_vfp;
   10899          }
   10900          else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
   10901             index = (opc >> 1) & 3;
   10902             putDRegI64(rD, triop(Iop_SetElem16x4,
   10903                                  getDRegI64(rD),
   10904                                  mkU8(index),
   10905                                  unop(Iop_32to16,
   10906                                       isT ? getIRegT(rT) : getIRegA(rT))),
   10907                            condT);
   10908             DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
   10909             goto decode_success_vfp;
   10910          }
   10911          else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0)) {
   10912             index = (opc >> 2) & 1;
   10913             putDRegI64(rD, triop(Iop_SetElem32x2,
   10914                                  getDRegI64(rD),
   10915                                  mkU8(index),
   10916                                  isT ? getIRegT(rT) : getIRegA(rT)),
   10917                            condT);
   10918             DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
   10919             goto decode_success_vfp;
   10920          } else {
   10921             /* fall through */
   10922          }
   10923       }
   10924    }
   10925 
   10926    // VMOV (scalar to ARM core register)
   10927    // VMOV rT, rD[x]
   10928    if (0x0E100B10 == (insn28 & 0x0F100F1F)) {
   10929       UInt rN  = (INSN(7,7) << 4) | INSN(19,16);
   10930       UInt rT  = INSN(15,12);
   10931       UInt U   = INSN(23,23);
   10932       UInt opc = (INSN(22,21) << 2) | INSN(6,5);
   10933       UInt index;
   10934       if (rT == 15 || (isT && rT == 13)) {
   10935          /* fall through */
   10936       } else {
   10937          if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
   10938             index = opc & 7;
   10939             IRExpr* e = unop(U ? Iop_8Uto32 : Iop_8Sto32,
   10940                              binop(Iop_GetElem8x8,
   10941                                    getDRegI64(rN),
   10942                                    mkU8(index)));
   10943             if (isT)
   10944                putIRegT(rT, e, condT);
   10945             else
   10946                putIRegA(rT, e, condT, Ijk_Boring);
   10947             DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
   10948                   rT, rN, index);
   10949             goto decode_success_vfp;
   10950          }
   10951          else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
   10952             index = (opc >> 1) & 3;
   10953             IRExpr* e = unop(U ? Iop_16Uto32 : Iop_16Sto32,
   10954                              binop(Iop_GetElem16x4,
   10955                                    getDRegI64(rN),
   10956                                    mkU8(index)));
   10957             if (isT)
   10958                putIRegT(rT, e, condT);
   10959             else
   10960                putIRegA(rT, e, condT, Ijk_Boring);
   10961             DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
   10962                   rT, rN, index);
   10963             goto decode_success_vfp;
   10964          }
   10965          else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U == 0) {
   10966             index = (opc >> 2) & 1;
   10967             IRExpr* e = binop(Iop_GetElem32x2, getDRegI64(rN), mkU8(index));
   10968             if (isT)
   10969                putIRegT(rT, e, condT);
   10970             else
   10971                putIRegA(rT, e, condT, Ijk_Boring);
   10972             DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq), rT, rN, index);
   10973             goto decode_success_vfp;
   10974          } else {
   10975             /* fall through */
   10976          }
   10977       }
   10978    }
   10979 
   10980    // VMOV.F32 sD, #imm
   10981    // FCONSTS sD, #imm
   10982    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   10983        && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) {
   10984       UInt rD   = (INSN(15,12) << 1) | INSN(22,22);
   10985       UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
   10986       UInt b    = (imm8 >> 6) & 1;
   10987       UInt imm;
   10988       imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,(imm8 >> 5) & 1) << 8)
   10989              | ((imm8 & 0x1f) << 3);
   10990       imm <<= 16;
   10991       putFReg(rD, unop(Iop_ReinterpI32asF32, mkU32(imm)), condT);
   10992       DIP("fconsts%s s%u #%u", nCC(conq), rD, imm8);
   10993       goto decode_success_vfp;
   10994    }
   10995 
   10996    // VMOV.F64 dD, #imm
   10997    // FCONSTD dD, #imm
   10998    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   10999        && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) {
   11000       UInt rD   = INSN(15,12) | (INSN(22,22) << 4);
   11001       UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
   11002       UInt b    = (imm8 >> 6) & 1;
   11003       ULong imm;
   11004       imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,b) << 8)
   11005              | BITS8(b,b,0,0,0,0,0,0) | (imm8 & 0x3f);
   11006       imm <<= 48;
   11007       putDReg(rD, unop(Iop_ReinterpI64asF64, mkU64(imm)), condT);
   11008       DIP("fconstd%s d%u #%u", nCC(conq), rD, imm8);
   11009       goto decode_success_vfp;
   11010    }
   11011 
   11012    /* ---------------------- vdup ------------------------- */
   11013    // VDUP dD, rT
   11014    // VDUP qD, rT
   11015    if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1))
   11016        && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) {
   11017       UInt rD   = (INSN(7,7) << 4) | INSN(19,16);
   11018       UInt rT   = INSN(15,12);
   11019       UInt Q    = INSN(21,21);
   11020       UInt size = (INSN(22,22) << 1) | INSN(5,5);
   11021       if (rT == 15 || (isT && rT == 13) || size == 3 || (Q && (rD & 1))) {
   11022          /* fall through */
   11023       } else {
   11024          IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT);
   11025          if (Q) {
   11026             rD >>= 1;
   11027             switch (size) {
   11028                case 0:
   11029                   putQReg(rD, unop(Iop_Dup32x4, e), condT);
   11030                   break;
   11031                case 1:
   11032                   putQReg(rD, unop(Iop_Dup16x8, unop(Iop_32to16, e)),
   11033                               condT);
   11034                   break;
   11035                case 2:
   11036                   putQReg(rD, unop(Iop_Dup8x16, unop(Iop_32to8, e)),
   11037                               condT);
   11038                   break;
   11039                default:
   11040                   vassert(0);
   11041             }
   11042             DIP("vdup.%u q%u, r%u\n", 32 / (1<<size), rD, rT);
   11043          } else {
   11044             switch (size) {
   11045                case 0:
   11046                   putDRegI64(rD, unop(Iop_Dup32x2, e), condT);
   11047                   break;
   11048                case 1:
   11049                   putDRegI64(rD, unop(Iop_Dup16x4, unop(Iop_32to16, e)),
   11050                                condT);
   11051                   break;
   11052                case 2:
   11053                   putDRegI64(rD, unop(Iop_Dup8x8, unop(Iop_32to8, e)),
   11054                                condT);
   11055                   break;
   11056                default:
   11057                   vassert(0);
   11058             }
   11059             DIP("vdup.%u d%u, r%u\n", 32 / (1<<size), rD, rT);
   11060          }
   11061          goto decode_success_vfp;
   11062       }
   11063    }
   11064 
   11065    /* --------------------- f{ld,st}d --------------------- */
   11066    // FLDD, FSTD
   11067    if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
   11068        && BITS4(1,0,1,1) == INSN(11,8)) {
   11069       UInt dD     = INSN(15,12) | (INSN(22,22) << 4);
   11070       UInt rN     = INSN(19,16);
   11071       UInt offset = (insn28 & 0xFF) << 2;
   11072       UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
   11073       UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
   11074       /* make unconditional */
   11075       if (condT != IRTemp_INVALID) {
   11076          if (isT)
   11077             mk_skip_over_T32_if_cond_is_false( condT );
   11078          else
   11079             mk_skip_over_A32_if_cond_is_false( condT );
   11080          condT = IRTemp_INVALID;
   11081       }
   11082       IRTemp ea = newTemp(Ity_I32);
   11083       assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
   11084                        align4if(isT ? getIRegT(rN) : getIRegA(rN),
   11085                                 rN == 15),
   11086                        mkU32(offset)));
   11087       if (bL) {
   11088          putDReg(dD, loadLE(Ity_F64,mkexpr(ea)), IRTemp_INVALID);
   11089       } else {
   11090          storeLE(mkexpr(ea), getDReg(dD));
   11091       }
   11092       DIP("f%sd%s d%u, [r%u, %c#%u]\n",
   11093           bL ? "ld" : "st", nCC(conq), dD, rN,
   11094           bU ? '+' : '-', offset);
   11095       goto decode_success_vfp;
   11096    }
   11097 
   11098    /* --------------------- dp insns (D) --------------------- */
   11099    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
   11100        && BITS4(1,0,1,1) == INSN(11,8)
   11101        && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
   11102       UInt    dM  = INSN(3,0)   | (INSN(5,5) << 4);       /* argR */
   11103       UInt    dD  = INSN(15,12) | (INSN(22,22) << 4);   /* dst/acc */
   11104       UInt    dN  = INSN(19,16) | (INSN(7,7) << 4);     /* argL */
   11105       UInt    bP  = (insn28 >> 23) & 1;
   11106       UInt    bQ  = (insn28 >> 21) & 1;
   11107       UInt    bR  = (insn28 >> 20) & 1;
   11108       UInt    bS  = (insn28 >> 6) & 1;
   11109       UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
   11110       IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   11111       switch (opc) {
   11112          case BITS4(0,0,0,0): /* MAC: d + n * m */
   11113             putDReg(dD, triop(Iop_AddF64, rm,
   11114                               getDReg(dD),
   11115                               triop(Iop_MulF64, rm, getDReg(dN),
   11116                                                     getDReg(dM))),
   11117                         condT);
   11118             DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11119             goto decode_success_vfp;
   11120          case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
   11121             putDReg(dD, triop(Iop_AddF64, rm,
   11122                               getDReg(dD),
   11123                               unop(Iop_NegF64,
   11124                                    triop(Iop_MulF64, rm, getDReg(dN),
   11125                                                          getDReg(dM)))),
   11126                         condT);
   11127             DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11128             goto decode_success_vfp;
   11129          case BITS4(0,0,1,0): /* MSC: - d + n * m */
   11130             putDReg(dD, triop(Iop_AddF64, rm,
   11131                               unop(Iop_NegF64, getDReg(dD)),
   11132                               triop(Iop_MulF64, rm, getDReg(dN),
   11133                                                     getDReg(dM))),
   11134                         condT);
   11135             DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11136             goto decode_success_vfp;
   11137          case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
   11138             putDReg(dD, triop(Iop_AddF64, rm,
   11139                               unop(Iop_NegF64, getDReg(dD)),
   11140                               unop(Iop_NegF64,
   11141                                    triop(Iop_MulF64, rm, getDReg(dN),
   11142                                                          getDReg(dM)))),
   11143                         condT);
   11144             DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11145             goto decode_success_vfp;
   11146          case BITS4(0,1,0,0): /* MUL: n * m */
   11147             putDReg(dD, triop(Iop_MulF64, rm, getDReg(dN), getDReg(dM)),
   11148                         condT);
   11149             DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11150             goto decode_success_vfp;
   11151          case BITS4(0,1,0,1): /* NMUL: - n * m */
   11152             putDReg(dD, unop(Iop_NegF64,
   11153                              triop(Iop_MulF64, rm, getDReg(dN),
   11154                                                    getDReg(dM))),
   11155                     condT);
   11156             DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11157             goto decode_success_vfp;
   11158          case BITS4(0,1,1,0): /* ADD: n + m */
   11159             putDReg(dD, triop(Iop_AddF64, rm, getDReg(dN), getDReg(dM)),
   11160                         condT);
   11161             DIP("faddd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11162             goto decode_success_vfp;
   11163          case BITS4(0,1,1,1): /* SUB: n - m */
   11164             putDReg(dD, triop(Iop_SubF64, rm, getDReg(dN), getDReg(dM)),
   11165                         condT);
   11166             DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11167             goto decode_success_vfp;
   11168          case BITS4(1,0,0,0): /* DIV: n / m */
   11169             putDReg(dD, triop(Iop_DivF64, rm, getDReg(dN), getDReg(dM)),
   11170                         condT);
   11171             DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11172             goto decode_success_vfp;
   11173          default:
   11174             break;
   11175       }
   11176    }
   11177 
   11178    /* --------------------- compares (D) --------------------- */
   11179    /*          31   27   23   19   15 11   7    3
   11180                  28   24   20   16 12    8    4    0
   11181       FCMPD    cond 1110 1D11 0100 Dd 1011 0100 Dm
   11182       FCMPED   cond 1110 1D11 0100 Dd 1011 1100 Dm
   11183       FCMPZD   cond 1110 1D11 0101 Dd 1011 0100 0000
   11184       FCMPZED  cond 1110 1D11 0101 Dd 1011 1100 0000
   11185                                  Z         N
   11186 
   11187       Z=0 Compare Dd vs Dm     and set FPSCR 31:28 accordingly
   11188       Z=1 Compare Dd vs zero
   11189 
   11190       N=1 generates Invalid Operation exn if either arg is any kind of NaN
   11191       N=0 generates Invalid Operation exn if either arg is a signalling NaN
   11192       (Not that we pay any attention to N here)
   11193    */
   11194    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11195        && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11196        && BITS4(1,0,1,1) == INSN(11,8)
   11197        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11198       UInt bZ = (insn28 >> 16) & 1;
   11199       UInt bN = (insn28 >> 7) & 1;
   11200       UInt dD = INSN(15,12) | (INSN(22,22) << 4);
   11201       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
   11202       if (bZ && INSN(3,0) != 0) {
   11203          /* does not decode; fall through */
   11204       } else {
   11205          IRTemp argL = newTemp(Ity_F64);
   11206          IRTemp argR = newTemp(Ity_F64);
   11207          IRTemp irRes = newTemp(Ity_I32);
   11208          assign(argL, getDReg(dD));
   11209          assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM));
   11210          assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
   11211 
   11212          IRTemp nzcv     = IRTemp_INVALID;
   11213          IRTemp oldFPSCR = newTemp(Ity_I32);
   11214          IRTemp newFPSCR = newTemp(Ity_I32);
   11215 
   11216          /* This is where the fun starts.  We have to convert 'irRes'
   11217             from an IR-convention return result (IRCmpF64Result) to an
   11218             ARM-encoded (N,Z,C,V) group.  The final result is in the
   11219             bottom 4 bits of 'nzcv'. */
   11220          /* Map compare result from IR to ARM(nzcv) */
   11221          /*
   11222             FP cmp result | IR   | ARM(nzcv)
   11223             --------------------------------
   11224             UN              0x45   0011
   11225             LT              0x01   1000
   11226             GT              0x00   0010
   11227             EQ              0x40   0110
   11228          */
   11229          nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
   11230 
   11231          /* And update FPSCR accordingly */
   11232          assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
   11233          assign(newFPSCR,
   11234                 binop(Iop_Or32,
   11235                       binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
   11236                       binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
   11237 
   11238          putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
   11239 
   11240          if (bZ) {
   11241             DIP("fcmpz%sd%s d%u\n", bN ? "e" : "", nCC(conq), dD);
   11242          } else {
   11243             DIP("fcmp%sd%s d%u, d%u\n", bN ? "e" : "", nCC(conq), dD, dM);
   11244          }
   11245          goto decode_success_vfp;
   11246       }
   11247       /* fall through */
   11248    }
   11249 
   11250    /* --------------------- unary (D) --------------------- */
   11251    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11252        && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11253        && BITS4(1,0,1,1) == INSN(11,8)
   11254        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11255       UInt dD  = INSN(15,12) | (INSN(22,22) << 4);
   11256       UInt dM  = INSN(3,0) | (INSN(5,5) << 4);
   11257       UInt b16 = (insn28 >> 16) & 1;
   11258       UInt b7  = (insn28 >> 7) & 1;
   11259       /**/ if (b16 == 0 && b7 == 0) {
   11260          // FCPYD
   11261          putDReg(dD, getDReg(dM), condT);
   11262          DIP("fcpyd%s d%u, d%u\n", nCC(conq), dD, dM);
   11263          goto decode_success_vfp;
   11264       }
   11265       else if (b16 == 0 && b7 == 1) {
   11266          // FABSD
   11267          putDReg(dD, unop(Iop_AbsF64, getDReg(dM)), condT);
   11268          DIP("fabsd%s d%u, d%u\n", nCC(conq), dD, dM);
   11269          goto decode_success_vfp;
   11270       }
   11271       else if (b16 == 1 && b7 == 0) {
   11272          // FNEGD
   11273          putDReg(dD, unop(Iop_NegF64, getDReg(dM)), condT);
   11274          DIP("fnegd%s d%u, d%u\n", nCC(conq), dD, dM);
   11275          goto decode_success_vfp;
   11276       }
   11277       else if (b16 == 1 && b7 == 1) {
   11278          // FSQRTD
   11279          IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   11280          putDReg(dD, binop(Iop_SqrtF64, rm, getDReg(dM)), condT);
   11281          DIP("fsqrtd%s d%u, d%u\n", nCC(conq), dD, dM);
   11282          goto decode_success_vfp;
   11283       }
   11284       else
   11285          vassert(0);
   11286 
   11287       /* fall through */
   11288    }
   11289 
   11290    /* ----------------- I <-> D conversions ----------------- */
   11291 
   11292    // F{S,U}ITOD dD, fM
   11293    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11294        && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
   11295        && BITS4(1,0,1,1) == INSN(11,8)
   11296        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11297       UInt bM    = (insn28 >> 5) & 1;
   11298       UInt fM    = (INSN(3,0) << 1) | bM;
   11299       UInt dD    = INSN(15,12) | (INSN(22,22) << 4);
   11300       UInt syned = (insn28 >> 7) & 1;
   11301       if (syned) {
   11302          // FSITOD
   11303          putDReg(dD, unop(Iop_I32StoF64,
   11304                           unop(Iop_ReinterpF32asI32, getFReg(fM))),
   11305                  condT);
   11306          DIP("fsitod%s d%u, s%u\n", nCC(conq), dD, fM);
   11307       } else {
   11308          // FUITOD
   11309          putDReg(dD, unop(Iop_I32UtoF64,
   11310                           unop(Iop_ReinterpF32asI32, getFReg(fM))),
   11311                  condT);
   11312          DIP("fuitod%s d%u, s%u\n", nCC(conq), dD, fM);
   11313       }
   11314       goto decode_success_vfp;
   11315    }
   11316 
   11317    // FTO{S,U}ID fD, dM
   11318    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11319        && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11320        && BITS4(1,0,1,1) == INSN(11,8)
   11321        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11322       UInt   bD    = (insn28 >> 22) & 1;
   11323       UInt   fD    = (INSN(15,12) << 1) | bD;
   11324       UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
   11325       UInt   bZ    = (insn28 >> 7) & 1;
   11326       UInt   syned = (insn28 >> 16) & 1;
   11327       IRTemp rmode = newTemp(Ity_I32);
   11328       assign(rmode, bZ ? mkU32(Irrm_ZERO)
   11329                        : mkexpr(mk_get_IR_rounding_mode()));
   11330       if (syned) {
   11331          // FTOSID
   11332          putFReg(fD, unop(Iop_ReinterpI32asF32,
   11333                           binop(Iop_F64toI32S, mkexpr(rmode),
   11334                                 getDReg(dM))),
   11335                  condT);
   11336          DIP("ftosi%sd%s s%u, d%u\n", bZ ? "z" : "",
   11337              nCC(conq), fD, dM);
   11338       } else {
   11339          // FTOUID
   11340          putFReg(fD, unop(Iop_ReinterpI32asF32,
   11341                           binop(Iop_F64toI32U, mkexpr(rmode),
   11342                                 getDReg(dM))),
   11343                  condT);
   11344          DIP("ftoui%sd%s s%u, d%u\n", bZ ? "z" : "",
   11345              nCC(conq), fD, dM);
   11346       }
   11347       goto decode_success_vfp;
   11348    }
   11349 
   11350    /* ----------------------------------------------------------- */
   11351    /* -- VFP instructions -- single precision                  -- */
   11352    /* ----------------------------------------------------------- */
   11353 
   11354    /* --------------------- fldms, fstms --------------------- */
   11355    /*
   11356                                  31   27   23   19 15 11   7   0
   11357                                          P UDWL
   11358       C4-98, C5-26   1  FSTMD    cond 1100 1x00 Rn Fd 1010 offset
   11359       C4-98, C5-28   2  FSTMDIA  cond 1100 1x10 Rn Fd 1010 offset
   11360       C4-98, C5-30   3  FSTMDDB  cond 1101 0x10 Rn Fd 1010 offset
   11361 
   11362       C4-40, C5-26   1  FLDMD    cond 1100 1x01 Rn Fd 1010 offset
   11363       C4-40, C5-26   2  FLDMIAD  cond 1100 1x11 Rn Fd 1010 offset
   11364       C4-40, C5-26   3  FLDMDBD  cond 1101 0x11 Rn Fd 1010 offset
   11365 
   11366       Regs transferred: F(Fd:D) .. F(Fd:d + offset)
   11367       offset must not imply a reg > 15
   11368       IA/DB: Rn is changed by (4 x # regs transferred)
   11369 
   11370       case coding:
   11371          1  at-Rn   (access at Rn)
   11372          2  ia-Rn   (access at Rn, then Rn += 4n)
   11373          3  db-Rn   (Rn -= 4n,     then access at Rn)
   11374    */
   11375    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
   11376        && INSN(11,8) == BITS4(1,0,1,0)) {
   11377       UInt bP      = (insn28 >> 24) & 1;
   11378       UInt bU      = (insn28 >> 23) & 1;
   11379       UInt bW      = (insn28 >> 21) & 1;
   11380       UInt bL      = (insn28 >> 20) & 1;
   11381       UInt bD      = (insn28 >> 22) & 1;
   11382       UInt offset  = (insn28 >> 0) & 0xFF;
   11383       UInt rN      = INSN(19,16);
   11384       UInt fD      = (INSN(15,12) << 1) | bD;
   11385       UInt nRegs   = offset;
   11386       UInt summary = 0;
   11387       Int  i;
   11388 
   11389       /**/ if (bP == 0 && bU == 1 && bW == 0) {
   11390          summary = 1;
   11391       }
   11392       else if (bP == 0 && bU == 1 && bW == 1) {
   11393          summary = 2;
   11394       }
   11395       else if (bP == 1 && bU == 0 && bW == 1) {
   11396          summary = 3;
   11397       }
   11398       else goto after_vfp_fldms_fstms;
   11399 
   11400       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
   11401       if (rN == 15 && (summary == 2 || summary == 3 || isT))
   11402          goto after_vfp_fldms_fstms;
   11403 
   11404       /* offset must specify at least one register */
   11405       if (offset < 1)
   11406          goto after_vfp_fldms_fstms;
   11407 
   11408       /* can't transfer regs after S31 */
   11409       if (fD + nRegs - 1 >= 32)
   11410          goto after_vfp_fldms_fstms;
   11411 
   11412       /* Now, we can't do a conditional load or store, since that very
   11413          likely will generate an exception.  So we have to take a side
   11414          exit at this point if the condition is false. */
   11415       if (condT != IRTemp_INVALID) {
   11416          if (isT)
   11417             mk_skip_over_T32_if_cond_is_false( condT );
   11418          else
   11419             mk_skip_over_A32_if_cond_is_false( condT );
   11420          condT = IRTemp_INVALID;
   11421       }
   11422       /* Ok, now we're unconditional.  Do the load or store. */
   11423 
   11424       /* get the old Rn value */
   11425       IRTemp rnT = newTemp(Ity_I32);
   11426       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
   11427                            rN == 15));
   11428 
   11429       /* make a new value for Rn, post-insn */
   11430       IRTemp rnTnew = IRTemp_INVALID;
   11431       if (summary == 2 || summary == 3) {
   11432          rnTnew = newTemp(Ity_I32);
   11433          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
   11434                               mkexpr(rnT),
   11435                               mkU32(4 * nRegs)));
   11436       }
   11437 
   11438       /* decide on the base transfer address */
   11439       IRTemp taT = newTemp(Ity_I32);
   11440       assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
   11441 
   11442       /* update Rn if necessary -- in case 3, we're moving it down, so
   11443          update before any memory reference, in order to keep Memcheck
   11444          and V's stack-extending logic (on linux) happy */
   11445       if (summary == 3) {
   11446          if (isT)
   11447             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   11448          else
   11449             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   11450       }
   11451 
   11452       /* generate the transfers */
   11453       for (i = 0; i < nRegs; i++) {
   11454          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(4*i));
   11455          if (bL) {
   11456             putFReg(fD + i, loadLE(Ity_F32, addr), IRTemp_INVALID);
   11457          } else {
   11458             storeLE(addr, getFReg(fD + i));
   11459          }
   11460       }
   11461 
   11462       /* update Rn if necessary -- in case 2, we're moving it up, so
   11463          update after any memory reference, in order to keep Memcheck
   11464          and V's stack-extending logic (on linux) happy */
   11465       if (summary == 2) {
   11466          if (isT)
   11467             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   11468          else
   11469             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   11470       }
   11471 
   11472       HChar* nm = bL==1 ? "ld" : "st";
   11473       switch (summary) {
   11474          case 1:  DIP("f%sms%s r%u, {s%u-s%u}\n",
   11475                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
   11476                   break;
   11477          case 2:  DIP("f%smias%s r%u!, {s%u-s%u}\n",
   11478                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
   11479                   break;
   11480          case 3:  DIP("f%smdbs%s r%u!, {s%u-s%u}\n",
   11481                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
   11482                   break;
   11483          default: vassert(0);
   11484       }
   11485 
   11486       goto decode_success_vfp;
   11487       /* FIXME alignment constraints? */
   11488    }
   11489 
   11490   after_vfp_fldms_fstms:
   11491 
   11492    /* --------------------- fmsr, fmrs --------------------- */
   11493    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
   11494        && BITS4(1,0,1,0) == INSN(11,8)
   11495        && BITS4(0,0,0,0) == INSN(3,0)
   11496        && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
   11497       UInt rD  = INSN(15,12);
   11498       UInt b7  = (insn28 >> 7) & 1;
   11499       UInt fN  = (INSN(19,16) << 1) | b7;
   11500       UInt b20 = (insn28 >> 20) & 1;
   11501       if (rD == 15) {
   11502          /* fall through */
   11503          /* Let's assume that no sane person would want to do
   11504             floating-point transfers to or from the program counter,
   11505             and simply decline to decode the instruction.  The ARM ARM
   11506             doesn't seem to explicitly disallow this case, though. */
   11507       } else {
   11508          if (b20) {
   11509             IRExpr* res = unop(Iop_ReinterpF32asI32, getFReg(fN));
   11510             if (isT)
   11511                putIRegT(rD, res, condT);
   11512             else
   11513                putIRegA(rD, res, condT, Ijk_Boring);
   11514             DIP("fmrs%s r%u, s%u\n", nCC(conq), rD, fN);
   11515          } else {
   11516             putFReg(fN, unop(Iop_ReinterpI32asF32,
   11517                              isT ? getIRegT(rD) : getIRegA(rD)),
   11518                         condT);
   11519             DIP("fmsr%s s%u, r%u\n", nCC(conq), fN, rD);
   11520          }
   11521          goto decode_success_vfp;
   11522       }
   11523       /* fall through */
   11524    }
   11525 
   11526    /* --------------------- f{ld,st}s --------------------- */
   11527    // FLDS, FSTS
   11528    if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
   11529        && BITS4(1,0,1,0) == INSN(11,8)) {
   11530       UInt bD     = (insn28 >> 22) & 1;
   11531       UInt fD     = (INSN(15,12) << 1) | bD;
   11532       UInt rN     = INSN(19,16);
   11533       UInt offset = (insn28 & 0xFF) << 2;
   11534       UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
   11535       UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
   11536       /* make unconditional */
   11537       if (condT != IRTemp_INVALID) {
   11538          if (isT)
   11539             mk_skip_over_T32_if_cond_is_false( condT );
   11540          else
   11541             mk_skip_over_A32_if_cond_is_false( condT );
   11542          condT = IRTemp_INVALID;
   11543       }
   11544       IRTemp ea = newTemp(Ity_I32);
   11545       assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
   11546                        align4if(isT ? getIRegT(rN) : getIRegA(rN),
   11547                                 rN == 15),
   11548                        mkU32(offset)));
   11549       if (bL) {
   11550          putFReg(fD, loadLE(Ity_F32,mkexpr(ea)), IRTemp_INVALID);
   11551       } else {
   11552          storeLE(mkexpr(ea), getFReg(fD));
   11553       }
   11554       DIP("f%ss%s s%u, [r%u, %c#%u]\n",
   11555           bL ? "ld" : "st", nCC(conq), fD, rN,
   11556           bU ? '+' : '-', offset);
   11557       goto decode_success_vfp;
   11558    }
   11559 
   11560    /* --------------------- dp insns (F) --------------------- */
   11561    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
   11562        && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
   11563        && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
   11564       UInt    bM  = (insn28 >> 5) & 1;
   11565       UInt    bD  = (insn28 >> 22) & 1;
   11566       UInt    bN  = (insn28 >> 7) & 1;
   11567       UInt    fM  = (INSN(3,0) << 1) | bM;   /* argR */
   11568       UInt    fD  = (INSN(15,12) << 1) | bD; /* dst/acc */
   11569       UInt    fN  = (INSN(19,16) << 1) | bN; /* argL */
   11570       UInt    bP  = (insn28 >> 23) & 1;
   11571       UInt    bQ  = (insn28 >> 21) & 1;
   11572       UInt    bR  = (insn28 >> 20) & 1;
   11573       UInt    bS  = (insn28 >> 6) & 1;
   11574       UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
   11575       IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   11576       switch (opc) {
   11577          case BITS4(0,0,0,0): /* MAC: d + n * m */
   11578             putFReg(fD, triop(Iop_AddF32, rm,
   11579                               getFReg(fD),
   11580                               triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
   11581                         condT);
   11582             DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11583             goto decode_success_vfp;
   11584          case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
   11585             putFReg(fD, triop(Iop_AddF32, rm,
   11586                               getFReg(fD),
   11587                               unop(Iop_NegF32,
   11588                                    triop(Iop_MulF32, rm, getFReg(fN),
   11589                                                          getFReg(fM)))),
   11590                         condT);
   11591             DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11592             goto decode_success_vfp;
   11593          case BITS4(0,0,1,0): /* MSC: - d + n * m */
   11594             putFReg(fD, triop(Iop_AddF32, rm,
   11595                               unop(Iop_NegF32, getFReg(fD)),
   11596                               triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
   11597                         condT);
   11598             DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11599             goto decode_success_vfp;
   11600          case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
   11601             putFReg(fD, triop(Iop_AddF32, rm,
   11602                               unop(Iop_NegF32, getFReg(fD)),
   11603                               unop(Iop_NegF32,
   11604                                    triop(Iop_MulF32, rm,
   11605                                                      getFReg(fN),
   11606                                                     getFReg(fM)))),
   11607                         condT);
   11608             DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11609             goto decode_success_vfp;
   11610          case BITS4(0,1,0,0): /* MUL: n * m */
   11611             putFReg(fD, triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM)),
   11612                         condT);
   11613             DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11614             goto decode_success_vfp;
   11615          case BITS4(0,1,0,1): /* NMUL: - n * m */
   11616             putFReg(fD, unop(Iop_NegF32,
   11617                              triop(Iop_MulF32, rm, getFReg(fN),
   11618                                                    getFReg(fM))),
   11619                     condT);
   11620             DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11621             goto decode_success_vfp;
   11622          case BITS4(0,1,1,0): /* ADD: n + m */
   11623             putFReg(fD, triop(Iop_AddF32, rm, getFReg(fN), getFReg(fM)),
   11624                         condT);
   11625             DIP("fadds%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11626             goto decode_success_vfp;
   11627          case BITS4(0,1,1,1): /* SUB: n - m */
   11628             putFReg(fD, triop(Iop_SubF32, rm, getFReg(fN), getFReg(fM)),
   11629                         condT);
   11630             DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11631             goto decode_success_vfp;
   11632          case BITS4(1,0,0,0): /* DIV: n / m */
   11633             putFReg(fD, triop(Iop_DivF32, rm, getFReg(fN), getFReg(fM)),
   11634                         condT);
   11635             DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11636             goto decode_success_vfp;
   11637          default:
   11638             break;
   11639       }
   11640    }
   11641 
   11642    /* --------------------- compares (S) --------------------- */
   11643    /*          31   27   23   19   15 11   7    3
   11644                  28   24   20   16 12    8    4    0
   11645       FCMPS    cond 1110 1D11 0100 Fd 1010 01M0 Fm
   11646       FCMPES   cond 1110 1D11 0100 Fd 1010 11M0 Fm
   11647       FCMPZS   cond 1110 1D11 0101 Fd 1010 0100 0000
   11648       FCMPZED  cond 1110 1D11 0101 Fd 1010 1100 0000
   11649                                  Z         N
   11650 
   11651       Z=0 Compare Fd:D vs Fm:M     and set FPSCR 31:28 accordingly
   11652       Z=1 Compare Fd:D 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,0) == 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 bD = (insn28 >> 22) & 1;
   11665       UInt bM = (insn28 >> 5) & 1;
   11666       UInt fD = (INSN(15,12) << 1) | bD;
   11667       UInt fM = (INSN(3,0) << 1) | bM;
   11668       if (bZ && (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) {
   11669          /* does not decode; fall through */
   11670       } else {
   11671          IRTemp argL = newTemp(Ity_F64);
   11672          IRTemp argR = newTemp(Ity_F64);
   11673          IRTemp irRes = newTemp(Ity_I32);
   11674 
   11675          assign(argL, unop(Iop_F32toF64, getFReg(fD)));
   11676          assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0))
   11677                          : unop(Iop_F32toF64, getFReg(fM)));
   11678          assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
   11679 
   11680          IRTemp nzcv     = IRTemp_INVALID;
   11681          IRTemp oldFPSCR = newTemp(Ity_I32);
   11682          IRTemp newFPSCR = newTemp(Ity_I32);
   11683 
   11684          /* This is where the fun starts.  We have to convert 'irRes'
   11685             from an IR-convention return result (IRCmpF64Result) to an
   11686             ARM-encoded (N,Z,C,V) group.  The final result is in the
   11687             bottom 4 bits of 'nzcv'. */
   11688          /* Map compare result from IR to ARM(nzcv) */
   11689          /*
   11690             FP cmp result | IR   | ARM(nzcv)
   11691             --------------------------------
   11692             UN              0x45   0011
   11693             LT              0x01   1000
   11694             GT              0x00   0010
   11695             EQ              0x40   0110
   11696          */
   11697          nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
   11698 
   11699          /* And update FPSCR accordingly */
   11700          assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
   11701          assign(newFPSCR,
   11702                 binop(Iop_Or32,
   11703                       binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
   11704                       binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
   11705 
   11706          putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
   11707 
   11708          if (bZ) {
   11709             DIP("fcmpz%ss%s s%u\n", bN ? "e" : "", nCC(conq), fD);
   11710          } else {
   11711             DIP("fcmp%ss%s s%u, s%u\n", bN ? "e" : "",
   11712                 nCC(conq), fD, fM);
   11713          }
   11714          goto decode_success_vfp;
   11715       }
   11716       /* fall through */
   11717    }
   11718 
   11719    /* --------------------- unary (S) --------------------- */
   11720    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11721        && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11722        && BITS4(1,0,1,0) == INSN(11,8)
   11723        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11724       UInt bD = (insn28 >> 22) & 1;
   11725       UInt bM = (insn28 >> 5) & 1;
   11726       UInt fD  = (INSN(15,12) << 1) | bD;
   11727       UInt fM  = (INSN(3,0) << 1) | bM;
   11728       UInt b16 = (insn28 >> 16) & 1;
   11729       UInt b7  = (insn28 >> 7) & 1;
   11730       /**/ if (b16 == 0 && b7 == 0) {
   11731          // FCPYS
   11732          putFReg(fD, getFReg(fM), condT);
   11733          DIP("fcpys%s s%u, s%u\n", nCC(conq), fD, fM);
   11734          goto decode_success_vfp;
   11735       }
   11736       else if (b16 == 0 && b7 == 1) {
   11737          // FABSS
   11738          putFReg(fD, unop(Iop_AbsF32, getFReg(fM)), condT);
   11739          DIP("fabss%s s%u, s%u\n", nCC(conq), fD, fM);
   11740          goto decode_success_vfp;
   11741       }
   11742       else if (b16 == 1 && b7 == 0) {
   11743          // FNEGS
   11744          putFReg(fD, unop(Iop_NegF32, getFReg(fM)), condT);
   11745          DIP("fnegs%s s%u, s%u\n", nCC(conq), fD, fM);
   11746          goto decode_success_vfp;
   11747       }
   11748       else if (b16 == 1 && b7 == 1) {
   11749          // FSQRTS
   11750          IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   11751          putFReg(fD, binop(Iop_SqrtF32, rm, getFReg(fM)), condT);
   11752          DIP("fsqrts%s s%u, s%u\n", nCC(conq), fD, fM);
   11753          goto decode_success_vfp;
   11754       }
   11755       else
   11756          vassert(0);
   11757 
   11758       /* fall through */
   11759    }
   11760 
   11761    /* ----------------- I <-> S conversions ----------------- */
   11762 
   11763    // F{S,U}ITOS fD, fM
   11764    /* These are more complex than FSITOD/FUITOD.  In the D cases, a 32
   11765       bit int will always fit within the 53 bit mantissa, so there's
   11766       no possibility of a loss of precision, but that's obviously not
   11767       the case here.  Hence this case possibly requires rounding, and
   11768       so it drags in the current rounding mode. */
   11769    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11770        && BITS4(1,0,0,0) == INSN(19,16)
   11771        && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
   11772        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11773       UInt bM    = (insn28 >> 5) & 1;
   11774       UInt bD    = (insn28 >> 22) & 1;
   11775       UInt fM    = (INSN(3,0) << 1) | bM;
   11776       UInt fD    = (INSN(15,12) << 1) | bD;
   11777       UInt syned = (insn28 >> 7) & 1;
   11778       IRTemp rmode = newTemp(Ity_I32);
   11779       assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
   11780       if (syned) {
   11781          // FSITOS
   11782          putFReg(fD, binop(Iop_F64toF32,
   11783                            mkexpr(rmode),
   11784                            unop(Iop_I32StoF64,
   11785                                 unop(Iop_ReinterpF32asI32, getFReg(fM)))),
   11786                  condT);
   11787          DIP("fsitos%s s%u, s%u\n", nCC(conq), fD, fM);
   11788       } else {
   11789          // FUITOS
   11790          putFReg(fD, binop(Iop_F64toF32,
   11791                            mkexpr(rmode),
   11792                            unop(Iop_I32UtoF64,
   11793                                 unop(Iop_ReinterpF32asI32, getFReg(fM)))),
   11794                  condT);
   11795          DIP("fuitos%s s%u, s%u\n", nCC(conq), fD, fM);
   11796       }
   11797       goto decode_success_vfp;
   11798    }
   11799 
   11800    // FTO{S,U}IS fD, fM
   11801    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11802        && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11803        && BITS4(1,0,1,0) == INSN(11,8)
   11804        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11805       UInt   bM    = (insn28 >> 5) & 1;
   11806       UInt   bD    = (insn28 >> 22) & 1;
   11807       UInt   fD    = (INSN(15,12) << 1) | bD;
   11808       UInt   fM    = (INSN(3,0) << 1) | bM;
   11809       UInt   bZ    = (insn28 >> 7) & 1;
   11810       UInt   syned = (insn28 >> 16) & 1;
   11811       IRTemp rmode = newTemp(Ity_I32);
   11812       assign(rmode, bZ ? mkU32(Irrm_ZERO)
   11813                        : mkexpr(mk_get_IR_rounding_mode()));
   11814       if (syned) {
   11815          // FTOSIS
   11816          putFReg(fD, unop(Iop_ReinterpI32asF32,
   11817                           binop(Iop_F64toI32S, mkexpr(rmode),
   11818                                 unop(Iop_F32toF64, getFReg(fM)))),
   11819                  condT);
   11820          DIP("ftosi%ss%s s%u, d%u\n", bZ ? "z" : "",
   11821              nCC(conq), fD, fM);
   11822          goto decode_success_vfp;
   11823       } else {
   11824          // FTOUIS
   11825          putFReg(fD, unop(Iop_ReinterpI32asF32,
   11826                           binop(Iop_F64toI32U, mkexpr(rmode),
   11827                                 unop(Iop_F32toF64, getFReg(fM)))),
   11828                  condT);
   11829          DIP("ftoui%ss%s s%u, d%u\n", bZ ? "z" : "",
   11830              nCC(conq), fD, fM);
   11831          goto decode_success_vfp;
   11832       }
   11833    }
   11834 
   11835    /* ----------------- S <-> D conversions ----------------- */
   11836 
   11837    // FCVTDS
   11838    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11839        && BITS4(0,1,1,1) == INSN(19,16)
   11840        && BITS4(1,0,1,0) == INSN(11,8)
   11841        && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
   11842       UInt dD = INSN(15,12) | (INSN(22,22) << 4);
   11843       UInt bM = (insn28 >> 5) & 1;
   11844       UInt fM = (INSN(3,0) << 1) | bM;
   11845       putDReg(dD, unop(Iop_F32toF64, getFReg(fM)), condT);
   11846       DIP("fcvtds%s d%u, s%u\n", nCC(conq), dD, fM);
   11847       goto decode_success_vfp;
   11848    }
   11849 
   11850    // FCVTSD
   11851    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11852        && BITS4(0,1,1,1) == INSN(19,16)
   11853        && BITS4(1,0,1,1) == INSN(11,8)
   11854        && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
   11855       UInt   bD    = (insn28 >> 22) & 1;
   11856       UInt   fD    = (INSN(15,12) << 1) | bD;
   11857       UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
   11858       IRTemp rmode = newTemp(Ity_I32);
   11859       assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
   11860       putFReg(fD, binop(Iop_F64toF32, mkexpr(rmode), getDReg(dM)),
   11861                   condT);
   11862       DIP("fcvtsd%s s%u, d%u\n", nCC(conq), fD, dM);
   11863       goto decode_success_vfp;
   11864    }
   11865 
   11866    /* FAILURE */
   11867    return False;
   11868 
   11869   decode_success_vfp:
   11870    /* Check that any accepted insn really is a CP10 or CP11 insn, iow,
   11871       assert that we aren't accepting, in this fn, insns that actually
   11872       should be handled somewhere else. */
   11873    vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011
   11874    return True;
   11875 
   11876 #  undef INSN
   11877 }
   11878 
   11879 
   11880 /*------------------------------------------------------------*/
   11881 /*--- Instructions in NV (never) space                     ---*/
   11882 /*------------------------------------------------------------*/
   11883 
   11884 /* ARM only */
   11885 /* Translate a NV space instruction.  If successful, returns True and
   11886    *dres may or may not be updated.  If failure, returns False and
   11887    doesn't change *dres nor create any IR.
   11888 
   11889    Note that all NEON instructions (in ARM mode) are handled through
   11890    here, since they are all in NV space.
   11891 */
   11892 static Bool decode_NV_instruction ( /*MOD*/DisResult* dres,
   11893                                     VexArchInfo* archinfo,
   11894                                     UInt insn )
   11895 {
   11896 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
   11897 #  define INSN_COND          SLICE_UInt(insn, 31, 28)
   11898 
   11899    HChar dis_buf[128];
   11900 
   11901    // Should only be called for NV instructions
   11902    vassert(BITS4(1,1,1,1) == INSN_COND);
   11903 
   11904    /* ------------------------ pld ------------------------ */
   11905    if (BITS8(0,1,0,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
   11906        && BITS4(1,1,1,1) == INSN(15,12)) {
   11907       UInt rN    = INSN(19,16);
   11908       UInt imm12 = INSN(11,0);
   11909       UInt bU    = INSN(23,23);
   11910       DIP("pld [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
   11911       return True;
   11912    }
   11913 
   11914    if (BITS8(0,1,1,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
   11915        && BITS4(1,1,1,1) == INSN(15,12)
   11916        && 0 == INSN(4,4)) {
   11917       UInt rN   = INSN(19,16);
   11918       UInt rM   = INSN(3,0);
   11919       UInt imm5 = INSN(11,7);
   11920       UInt sh2  = INSN(6,5);
   11921       UInt bU   = INSN(23,23);
   11922       if (rM != 15) {
   11923          IRExpr* eaE = mk_EA_reg_plusminus_shifted_reg(rN, bU, rM,
   11924                                                        sh2, imm5, dis_buf);
   11925          IRTemp eaT = newTemp(Ity_I32);
   11926          /* Bind eaE to a temp merely for debugging-vex purposes, so we
   11927             can check it's a plausible decoding.  It will get removed
   11928             by iropt a little later on. */
   11929          vassert(eaE);
   11930          assign(eaT, eaE);
   11931          DIP("pld %s\n", dis_buf);
   11932          return True;
   11933       }
   11934       /* fall through */
   11935    }
   11936 
   11937    /* ------------------------ pli ------------------------ */
   11938    if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
   11939        && BITS4(1,1,1,1) == INSN(15,12)) {
   11940       UInt rN    = INSN(19,16);
   11941       UInt imm12 = INSN(11,0);
   11942       UInt bU    = INSN(23,23);
   11943       DIP("pli [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
   11944       return True;
   11945    }
   11946 
   11947    /* --------------------- Interworking branches --------------------- */
   11948 
   11949    // BLX (1), viz, unconditional branch and link to R15+simm24
   11950    // and set CPSR.T = 1, that is, switch to Thumb mode
   11951    if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) {
   11952       UInt bitH   = INSN(24,24);
   11953       Int  uimm24 = INSN(23,0);
   11954       Int  simm24 = (((uimm24 << 8) >> 8) << 2) + (bitH << 1);
   11955       /* Now this is a bit tricky.  Since we're decoding an ARM insn,
   11956          it is implies that CPSR.T == 0.  Hence the current insn's
   11957          address is guaranteed to be of the form X--(30)--X00.  So, no
   11958          need to mask any bits off it.  But need to set the lowest bit
   11959          to 1 to denote we're in Thumb mode after this, since
   11960          guest_R15T has CPSR.T as the lowest bit.  And we can't chase
   11961          into the call, so end the block at this point. */
   11962       UInt dst = guest_R15_curr_instr_notENC + 8 + (simm24 | 1);
   11963       putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
   11964                     IRTemp_INVALID/*because AL*/, Ijk_Boring );
   11965       irsb->next     = mkU32(dst);
   11966       irsb->jumpkind = Ijk_Call;
   11967       dres->whatNext = Dis_StopHere;
   11968       DIP("blx 0x%x (and switch to Thumb mode)\n", dst - 1);
   11969       return True;
   11970    }
   11971 
   11972    /* ------------------- v7 barrier insns ------------------- */
   11973    switch (insn) {
   11974       case 0xF57FF06F: /* ISB */
   11975          stmt( IRStmt_MBE(Imbe_Fence) );
   11976          DIP("ISB\n");
   11977          return True;
   11978       case 0xF57FF04F: /* DSB sy */
   11979       case 0xF57FF04E: /* DSB st */
   11980       case 0xF57FF04B: /* DSB ish */
   11981       case 0xF57FF04A: /* DSB ishst */
   11982       case 0xF57FF047: /* DSB nsh */
   11983       case 0xF57FF046: /* DSB nshst */
   11984       case 0xF57FF043: /* DSB osh */
   11985       case 0xF57FF042: /* DSB oshst */
   11986          stmt( IRStmt_MBE(Imbe_Fence) );
   11987          DIP("DSB\n");
   11988          return True;
   11989       case 0xF57FF05F: /* DMB sy */
   11990       case 0xF57FF05E: /* DMB st */
   11991       case 0xF57FF05B: /* DMB ish */
   11992       case 0xF57FF05A: /* DMB ishst */
   11993       case 0xF57FF057: /* DMB nsh */
   11994       case 0xF57FF056: /* DMB nshst */
   11995       case 0xF57FF053: /* DMB osh */
   11996       case 0xF57FF052: /* DMB oshst */
   11997          stmt( IRStmt_MBE(Imbe_Fence) );
   11998          DIP("DMB\n");
   11999          return True;
   12000       default:
   12001          break;
   12002    }
   12003 
   12004    /* ------------------- CLREX ------------------ */
   12005    if (insn == 0xF57FF01F) {
   12006       /* AFAICS, this simply cancels a (all?) reservations made by a
   12007          (any?) preceding LDREX(es).  Arrange to hand it through to
   12008          the back end. */
   12009       stmt( IRStmt_MBE(Imbe_CancelReservation) );
   12010       DIP("clrex\n");
   12011       return True;
   12012    }
   12013 
   12014    /* ------------------- NEON ------------------- */
   12015    if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
   12016       Bool ok_neon = decode_NEON_instruction(
   12017                         dres, insn, IRTemp_INVALID/*unconditional*/,
   12018                         False/*!isT*/
   12019                      );
   12020       if (ok_neon)
   12021          return True;
   12022    }
   12023 
   12024    // unrecognised
   12025    return False;
   12026 
   12027 #  undef INSN_COND
   12028 #  undef INSN
   12029 }
   12030 
   12031 
   12032 /*------------------------------------------------------------*/
   12033 /*--- Disassemble a single ARM instruction                 ---*/
   12034 /*------------------------------------------------------------*/
   12035 
   12036 /* Disassemble a single ARM instruction into IR.  The instruction is
   12037    located in host memory at guest_instr, and has (decoded) guest IP
   12038    of guest_R15_curr_instr_notENC, which will have been set before the
   12039    call here. */
   12040 
   12041 static
   12042 DisResult disInstr_ARM_WRK (
   12043              Bool         put_IP,
   12044              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
   12045              Bool         resteerCisOk,
   12046              void*        callback_opaque,
   12047              UChar*       guest_instr,
   12048              VexArchInfo* archinfo,
   12049              VexAbiInfo*  abiinfo
   12050           )
   12051 {
   12052    // A macro to fish bits out of 'insn'.
   12053 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
   12054 #  define INSN_COND          SLICE_UInt(insn, 31, 28)
   12055 
   12056    DisResult dres;
   12057    UInt      insn;
   12058    //Bool      allow_VFP = False;
   12059    //UInt      hwcaps = archinfo->hwcaps;
   12060    IRTemp    condT; /* :: Ity_I32 */
   12061    UInt      summary;
   12062    HChar     dis_buf[128];  // big enough to hold LDMIA etc text
   12063 
   12064    /* What insn variants are we supporting today? */
   12065    //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
   12066    // etc etc
   12067 
   12068    /* Set result defaults. */
   12069    dres.whatNext   = Dis_Continue;
   12070    dres.len        = 4;
   12071    dres.continueAt = 0;
   12072 
   12073    /* Set default actions for post-insn handling of writes to r15, if
   12074       required. */
   12075    r15written = False;
   12076    r15guard   = IRTemp_INVALID; /* unconditional */
   12077    r15kind    = Ijk_Boring;
   12078 
   12079    /* At least this is simple on ARM: insns are all 4 bytes long, and
   12080       4-aligned.  So just fish the whole thing out of memory right now
   12081       and have done. */
   12082    insn = getUIntLittleEndianly( guest_instr );
   12083 
   12084    if (0) vex_printf("insn: 0x%x\n", insn);
   12085 
   12086    DIP("\t(arm) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
   12087 
   12088    /* We may be asked to update the guest R15 before going further. */
   12089    vassert(0 == (guest_R15_curr_instr_notENC & 3));
   12090    if (put_IP) {
   12091       llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
   12092    }
   12093 
   12094    /* ----------------------------------------------------------- */
   12095 
   12096    /* Spot "Special" instructions (see comment at top of file). */
   12097    {
   12098       UChar* code = (UChar*)guest_instr;
   12099       /* Spot the 16-byte preamble:
   12100 
   12101          e1a0c1ec  mov r12, r12, ROR #3
   12102          e1a0c6ec  mov r12, r12, ROR #13
   12103          e1a0ceec  mov r12, r12, ROR #29
   12104          e1a0c9ec  mov r12, r12, ROR #19
   12105       */
   12106       UInt word1 = 0xE1A0C1EC;
   12107       UInt word2 = 0xE1A0C6EC;
   12108       UInt word3 = 0xE1A0CEEC;
   12109       UInt word4 = 0xE1A0C9EC;
   12110       if (getUIntLittleEndianly(code+ 0) == word1 &&
   12111           getUIntLittleEndianly(code+ 4) == word2 &&
   12112           getUIntLittleEndianly(code+ 8) == word3 &&
   12113           getUIntLittleEndianly(code+12) == word4) {
   12114          /* Got a "Special" instruction preamble.  Which one is it? */
   12115          if (getUIntLittleEndianly(code+16) == 0xE18AA00A
   12116                                                /* orr r10,r10,r10 */) {
   12117             /* R3 = client_request ( R4 ) */
   12118             DIP("r3 = client_request ( %%r4 )\n");
   12119             irsb->next     = mkU32( guest_R15_curr_instr_notENC + 20 );
   12120             irsb->jumpkind = Ijk_ClientReq;
   12121             dres.whatNext  = Dis_StopHere;
   12122             goto decode_success;
   12123          }
   12124          else
   12125          if (getUIntLittleEndianly(code+16) == 0xE18BB00B
   12126                                                /* orr r11,r11,r11 */) {
   12127             /* R3 = guest_NRADDR */
   12128             DIP("r3 = guest_NRADDR\n");
   12129             dres.len = 20;
   12130             llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
   12131             goto decode_success;
   12132          }
   12133          else
   12134          if (getUIntLittleEndianly(code+16) == 0xE18CC00C
   12135                                                /* orr r12,r12,r12 */) {
   12136             /*  branch-and-link-to-noredir R4 */
   12137             DIP("branch-and-link-to-noredir r4\n");
   12138             llPutIReg(14, mkU32( guest_R15_curr_instr_notENC + 20) );
   12139             irsb->next     = llGetIReg(4);
   12140             irsb->jumpkind = Ijk_NoRedir;
   12141             dres.whatNext  = Dis_StopHere;
   12142             goto decode_success;
   12143          }
   12144          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   12145             can print the insn following the Special-insn preamble. */
   12146          insn = getUIntLittleEndianly(code+16);
   12147          goto decode_failure;
   12148          /*NOTREACHED*/
   12149       }
   12150 
   12151    }
   12152 
   12153    /* ----------------------------------------------------------- */
   12154 
   12155    /* Main ARM instruction decoder starts here. */
   12156 
   12157    /* Deal with the condition.  Strategy is to merely generate a
   12158       condition temporary at this point (or IRTemp_INVALID, meaning
   12159       unconditional).  We leave it to lower-level instruction decoders
   12160       to decide whether they can generate straight-line code, or
   12161       whether they must generate a side exit before the instruction.
   12162       condT :: Ity_I32 and is always either zero or one. */
   12163    condT = IRTemp_INVALID;
   12164    switch ( (ARMCondcode)INSN_COND ) {
   12165       case ARMCondNV: {
   12166          // Illegal instruction prior to v5 (see ARM ARM A3-5), but
   12167          // some cases are acceptable
   12168          Bool ok = decode_NV_instruction(&dres, archinfo, insn);
   12169          if (ok)
   12170             goto decode_success;
   12171          else
   12172             goto decode_failure;
   12173       }
   12174       case ARMCondAL: // Always executed
   12175          break;
   12176       case ARMCondEQ: case ARMCondNE: case ARMCondHS: case ARMCondLO:
   12177       case ARMCondMI: case ARMCondPL: case ARMCondVS: case ARMCondVC:
   12178       case ARMCondHI: case ARMCondLS: case ARMCondGE: case ARMCondLT:
   12179       case ARMCondGT: case ARMCondLE:
   12180          condT = newTemp(Ity_I32);
   12181          assign( condT, mk_armg_calculate_condition( INSN_COND ));
   12182          break;
   12183    }
   12184 
   12185    /* ----------------------------------------------------------- */
   12186    /* -- ARMv5 integer instructions                            -- */
   12187    /* ----------------------------------------------------------- */
   12188 
   12189    /* ---------------- Data processing ops ------------------- */
   12190 
   12191    if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0))
   12192        && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) {
   12193       IRTemp  shop = IRTemp_INVALID; /* shifter operand */
   12194       IRTemp  shco = IRTemp_INVALID; /* shifter carry out */
   12195       UInt    rD   = (insn >> 12) & 0xF; /* 15:12 */
   12196       UInt    rN   = (insn >> 16) & 0xF; /* 19:16 */
   12197       UInt    bitS = (insn >> 20) & 1; /* 20:20 */
   12198       IRTemp  rNt  = IRTemp_INVALID;
   12199       IRTemp  res  = IRTemp_INVALID;
   12200       IRTemp  oldV = IRTemp_INVALID;
   12201       IRTemp  oldC = IRTemp_INVALID;
   12202       HChar*  name = NULL;
   12203       IROp    op   = Iop_INVALID;
   12204       Bool    ok;
   12205 
   12206       switch (INSN(24,21)) {
   12207 
   12208          /* --------- ADD, SUB, AND, OR --------- */
   12209          case BITS4(0,1,0,0): /* ADD:  Rd = Rn + shifter_operand */
   12210             name = "add"; op = Iop_Add32; goto rd_eq_rn_op_SO;
   12211          case BITS4(0,0,1,0): /* SUB:  Rd = Rn - shifter_operand */
   12212             name = "sub"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
   12213          case BITS4(0,0,1,1): /* RSB:  Rd = shifter_operand - Rn */
   12214             name = "rsb"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
   12215          case BITS4(0,0,0,0): /* AND:  Rd = Rn & shifter_operand */
   12216             name = "and"; op = Iop_And32; goto rd_eq_rn_op_SO;
   12217          case BITS4(1,1,0,0): /* OR:   Rd = Rn | shifter_operand */
   12218             name = "orr"; op = Iop_Or32; goto rd_eq_rn_op_SO;
   12219          case BITS4(0,0,0,1): /* EOR:  Rd = Rn ^ shifter_operand */
   12220             name = "eor"; op = Iop_Xor32; goto rd_eq_rn_op_SO;
   12221          case BITS4(1,1,1,0): /* BIC:  Rd = Rn & ~shifter_operand */
   12222             name = "bic"; op = Iop_And32; goto rd_eq_rn_op_SO;
   12223          rd_eq_rn_op_SO: {
   12224             Bool isRSB = False;
   12225             Bool isBIC = False;
   12226             switch (INSN(24,21)) {
   12227                case BITS4(0,0,1,1):
   12228                   vassert(op == Iop_Sub32); isRSB = True; break;
   12229                case BITS4(1,1,1,0):
   12230                   vassert(op == Iop_And32); isBIC = True; break;
   12231                default:
   12232                   break;
   12233             }
   12234             rNt = newTemp(Ity_I32);
   12235             assign(rNt, getIRegA(rN));
   12236             ok = mk_shifter_operand(
   12237                     INSN(25,25), INSN(11,0),
   12238                     &shop, bitS ? &shco : NULL, dis_buf
   12239                  );
   12240             if (!ok)
   12241                break;
   12242             res = newTemp(Ity_I32);
   12243             // compute the main result
   12244             if (isRSB) {
   12245                // reverse-subtract: shifter_operand - Rn
   12246                vassert(op == Iop_Sub32);
   12247                assign(res, binop(op, mkexpr(shop), mkexpr(rNt)) );
   12248             } else if (isBIC) {
   12249                // andn: shifter_operand & ~Rn
   12250                vassert(op == Iop_And32);
   12251                assign(res, binop(op, mkexpr(rNt),
   12252                                      unop(Iop_Not32, mkexpr(shop))) );
   12253             } else {
   12254                // normal: Rn op shifter_operand
   12255                assign(res, binop(op, mkexpr(rNt), mkexpr(shop)) );
   12256             }
   12257             // but don't commit it until after we've finished
   12258             // all necessary reads from the guest state
   12259             if (bitS
   12260                 && (op == Iop_And32 || op == Iop_Or32 || op == Iop_Xor32)) {
   12261                oldV = newTemp(Ity_I32);
   12262                assign( oldV, mk_armg_calculate_flag_v() );
   12263             }
   12264             // can't safely read guest state after here
   12265             // now safe to put the main result
   12266             putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   12267             // XXXX!! not safe to read any guest state after
   12268             // this point (I think the code below doesn't do that).
   12269             if (!bitS)
   12270                vassert(shco == IRTemp_INVALID);
   12271             /* Update the flags thunk if necessary */
   12272             if (bitS) {
   12273                vassert(shco != IRTemp_INVALID);
   12274                switch (op) {
   12275                   case Iop_Add32:
   12276                      setFlags_D1_D2( ARMG_CC_OP_ADD, rNt, shop, condT );
   12277                      break;
   12278                   case Iop_Sub32:
   12279                      if (isRSB) {
   12280                         setFlags_D1_D2( ARMG_CC_OP_SUB, shop, rNt, condT );
   12281                      } else {
   12282                         setFlags_D1_D2( ARMG_CC_OP_SUB, rNt, shop, condT );
   12283                      }
   12284                      break;
   12285                   case Iop_And32: /* BIC and AND set the flags the same */
   12286                   case Iop_Or32:
   12287                   case Iop_Xor32:
   12288                      // oldV has been read just above
   12289                      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
   12290                                         res, shco, oldV, condT );
   12291                      break;
   12292                   default:
   12293                      vassert(0);
   12294                }
   12295             }
   12296             DIP("%s%s%s r%u, r%u, %s\n",
   12297                 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
   12298             goto decode_success;
   12299          }
   12300 
   12301          /* --------- MOV, MVN --------- */
   12302          case BITS4(1,1,0,1):   /* MOV: Rd = shifter_operand */
   12303          case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */
   12304             Bool isMVN = INSN(24,21) == BITS4(1,1,1,1);
   12305             IRTemp jk = Ijk_Boring;
   12306             if (rN != 0)
   12307                break; /* rN must be zero */
   12308             ok = mk_shifter_operand(
   12309                     INSN(25,25), INSN(11,0),
   12310                     &shop, bitS ? &shco : NULL, dis_buf
   12311                  );
   12312             if (!ok)
   12313                break;
   12314             res = newTemp(Ity_I32);
   12315             assign( res, isMVN ? unop(Iop_Not32, mkexpr(shop))
   12316                                : mkexpr(shop) );
   12317             if (bitS) {
   12318                vassert(shco != IRTemp_INVALID);
   12319                oldV = newTemp(Ity_I32);
   12320                assign( oldV, mk_armg_calculate_flag_v() );
   12321             } else {
   12322                vassert(shco == IRTemp_INVALID);
   12323             }
   12324             /* According to the Cortex A8 TRM Sec. 5.2.1, MOV PC, r14 is a
   12325                 return for purposes of branch prediction. */
   12326             if (!isMVN && INSN(11,0) == 14) {
   12327               jk = Ijk_Ret;
   12328             }
   12329             // can't safely read guest state after here
   12330             putIRegA( rD, mkexpr(res), condT, jk );
   12331             /* Update the flags thunk if necessary */
   12332             if (bitS) {
   12333                setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
   12334                                   res, shco, oldV, condT );
   12335             }
   12336             DIP("%s%s%s r%u, %s\n",
   12337                 isMVN ? "mvn" : "mov",
   12338                 nCC(INSN_COND), bitS ? "s" : "", rD, dis_buf );
   12339             goto decode_success;
   12340          }
   12341 
   12342          /* --------- CMP --------- */
   12343          case BITS4(1,0,1,0):   /* CMP:  (void) Rn - shifter_operand */
   12344          case BITS4(1,0,1,1): { /* CMN:  (void) Rn + shifter_operand */
   12345             Bool isCMN = INSN(24,21) == BITS4(1,0,1,1);
   12346             if (rD != 0)
   12347                break; /* rD must be zero */
   12348             if (bitS == 0)
   12349                break; /* if S (bit 20) is not set, it's not CMP/CMN */
   12350             rNt = newTemp(Ity_I32);
   12351             assign(rNt, getIRegA(rN));
   12352             ok = mk_shifter_operand(
   12353                     INSN(25,25), INSN(11,0),
   12354                     &shop, NULL, dis_buf
   12355                  );
   12356             if (!ok)
   12357                break;
   12358             // can't safely read guest state after here
   12359             /* Update the flags thunk. */
   12360             setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   12361                             rNt, shop, condT );
   12362             DIP("%s%s r%u, %s\n",
   12363                 isCMN ? "cmn" : "cmp",
   12364                 nCC(INSN_COND), rN, dis_buf );
   12365             goto decode_success;
   12366          }
   12367 
   12368          /* --------- TST --------- */
   12369          case BITS4(1,0,0,0):   /* TST:  (void) Rn & shifter_operand */
   12370          case BITS4(1,0,0,1): { /* TEQ:  (void) Rn ^ shifter_operand */
   12371             Bool isTEQ = INSN(24,21) == BITS4(1,0,0,1);
   12372             if (rD != 0)
   12373                break; /* rD must be zero */
   12374             if (bitS == 0)
   12375                break; /* if S (bit 20) is not set, it's not TST/TEQ */
   12376             rNt = newTemp(Ity_I32);
   12377             assign(rNt, getIRegA(rN));
   12378             ok = mk_shifter_operand(
   12379                     INSN(25,25), INSN(11,0),
   12380                     &shop, &shco, dis_buf
   12381                  );
   12382             if (!ok)
   12383                break;
   12384             /* Update the flags thunk. */
   12385             res = newTemp(Ity_I32);
   12386             assign( res, binop(isTEQ ? Iop_Xor32 : Iop_And32,
   12387                                mkexpr(rNt), mkexpr(shop)) );
   12388             oldV = newTemp(Ity_I32);
   12389             assign( oldV, mk_armg_calculate_flag_v() );
   12390             // can't safely read guest state after here
   12391             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
   12392                                res, shco, oldV, condT );
   12393             DIP("%s%s r%u, %s\n",
   12394                 isTEQ ? "teq" : "tst",
   12395                 nCC(INSN_COND), rN, dis_buf );
   12396             goto decode_success;
   12397          }
   12398 
   12399          /* --------- ADC, SBC, RSC --------- */
   12400          case BITS4(0,1,0,1): /* ADC:  Rd = Rn + shifter_operand + oldC */
   12401             name = "adc"; goto rd_eq_rn_op_SO_op_oldC;
   12402          case BITS4(0,1,1,0): /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
   12403             name = "sbc"; goto rd_eq_rn_op_SO_op_oldC;
   12404          case BITS4(0,1,1,1): /* RSC:  Rd = shifter_operand - Rn - (oldC ^ 1) */
   12405             name = "rsc"; goto rd_eq_rn_op_SO_op_oldC;
   12406          rd_eq_rn_op_SO_op_oldC: {
   12407             // FIXME: shco isn't used for anything.  Get rid of it.
   12408             rNt = newTemp(Ity_I32);
   12409             assign(rNt, getIRegA(rN));
   12410             ok = mk_shifter_operand(
   12411                     INSN(25,25), INSN(11,0),
   12412                     &shop, bitS ? &shco : NULL, dis_buf
   12413                  );
   12414             if (!ok)
   12415                break;
   12416             oldC = newTemp(Ity_I32);
   12417             assign( oldC, mk_armg_calculate_flag_c() );
   12418             res = newTemp(Ity_I32);
   12419             // compute the main result
   12420             switch (INSN(24,21)) {
   12421                case BITS4(0,1,0,1): /* ADC */
   12422                   assign(res,
   12423                          binop(Iop_Add32,
   12424                                binop(Iop_Add32, mkexpr(rNt), mkexpr(shop)),
   12425                                mkexpr(oldC) ));
   12426                   break;
   12427                case BITS4(0,1,1,0): /* SBC */
   12428                   assign(res,
   12429                          binop(Iop_Sub32,
   12430                                binop(Iop_Sub32, mkexpr(rNt), mkexpr(shop)),
   12431                                binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   12432                   break;
   12433                case BITS4(0,1,1,1): /* RSC */
   12434                   assign(res,
   12435                          binop(Iop_Sub32,
   12436                                binop(Iop_Sub32, mkexpr(shop), mkexpr(rNt)),
   12437                                binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   12438                   break;
   12439                default:
   12440                   vassert(0);
   12441             }
   12442             // but don't commit it until after we've finished
   12443             // all necessary reads from the guest state
   12444             // now safe to put the main result
   12445             putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   12446             // XXXX!! not safe to read any guest state after
   12447             // this point (I think the code below doesn't do that).
   12448             if (!bitS)
   12449                vassert(shco == IRTemp_INVALID);
   12450             /* Update the flags thunk if necessary */
   12451             if (bitS) {
   12452                vassert(shco != IRTemp_INVALID);
   12453                switch (INSN(24,21)) {
   12454                   case BITS4(0,1,0,1): /* ADC */
   12455                      setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
   12456                                         rNt, shop, oldC, condT );
   12457                      break;
   12458                   case BITS4(0,1,1,0): /* SBC */
   12459                      setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   12460                                         rNt, shop, oldC, condT );
   12461                      break;
   12462                   case BITS4(0,1,1,1): /* RSC */
   12463                      setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   12464                                         shop, rNt, oldC, condT );
   12465                      break;
   12466                   default:
   12467                      vassert(0);
   12468                }
   12469             }
   12470             DIP("%s%s%s r%u, r%u, %s\n",
   12471                 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
   12472             goto decode_success;
   12473          }
   12474 
   12475          /* --------- ??? --------- */
   12476          default:
   12477             break;
   12478       }
   12479    } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */
   12480 
   12481    /* --------------------- Load/store (ubyte & word) -------- */
   12482    // LDR STR LDRB STRB
   12483    /*                 31   27   23   19 15 11    6   4 3  # highest bit
   12484                         28   24   20 16 12
   12485       A5-20   1 | 16  cond 0101 UB0L Rn Rd imm12
   12486       A5-22   1 | 32  cond 0111 UBOL Rn Rd imm5  sh2 0 Rm
   12487       A5-24   2 | 16  cond 0101 UB1L Rn Rd imm12
   12488       A5-26   2 | 32  cond 0111 UB1L Rn Rd imm5  sh2 0 Rm
   12489       A5-28   3 | 16  cond 0100 UB0L Rn Rd imm12
   12490       A5-32   3 | 32  cond 0110 UB0L Rn Rd imm5  sh2 0 Rm
   12491    */
   12492    /* case coding:
   12493              1   at-ea               (access at ea)
   12494              2   at-ea-then-upd      (access at ea, then Rn = ea)
   12495              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
   12496       ea coding
   12497              16  Rn +/- imm12
   12498              32  Rn +/- Rm sh2 imm5
   12499    */
   12500    /* Quickly skip over all of this for hopefully most instructions */
   12501    if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0))
   12502       goto after_load_store_ubyte_or_word;
   12503 
   12504    summary = 0;
   12505 
   12506    /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) {
   12507       summary = 1 | 16;
   12508    }
   12509    else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0
   12510                                           && INSN(4,4) == 0) {
   12511       summary = 1 | 32;
   12512    }
   12513    else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) {
   12514       summary = 2 | 16;
   12515    }
   12516    else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1
   12517                                           && INSN(4,4) == 0) {
   12518       summary = 2 | 32;
   12519    }
   12520    else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) {
   12521       summary = 3 | 16;
   12522    }
   12523    else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0
   12524                                           && INSN(4,4) == 0) {
   12525       summary = 3 | 32;
   12526    }
   12527    else goto after_load_store_ubyte_or_word;
   12528 
   12529    { UInt rN = (insn >> 16) & 0xF; /* 19:16 */
   12530      UInt rD = (insn >> 12) & 0xF; /* 15:12 */
   12531      UInt rM = (insn >> 0)  & 0xF; /*  3:0  */
   12532      UInt bU = (insn >> 23) & 1;      /* 23 */
   12533      UInt bB = (insn >> 22) & 1;      /* 22 */
   12534      UInt bL = (insn >> 20) & 1;      /* 20 */
   12535      UInt imm12 = (insn >> 0) & 0xFFF; /* 11:0 */
   12536      UInt imm5  = (insn >> 7) & 0x1F;  /* 11:7 */
   12537      UInt sh2   = (insn >> 5) & 3;     /* 6:5 */
   12538 
   12539      /* Skip some invalid cases, which would lead to two competing
   12540         updates to the same register, or which are otherwise
   12541         disallowed by the spec. */
   12542      switch (summary) {
   12543         case 1 | 16:
   12544            break;
   12545         case 1 | 32:
   12546            if (rM == 15) goto after_load_store_ubyte_or_word;
   12547            break;
   12548         case 2 | 16: case 3 | 16:
   12549            if (rN == 15) goto after_load_store_ubyte_or_word;
   12550            if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
   12551            break;
   12552         case 2 | 32: case 3 | 32:
   12553            if (rM == 15) goto after_load_store_ubyte_or_word;
   12554            if (rN == 15) goto after_load_store_ubyte_or_word;
   12555            if (rN == rM) goto after_load_store_ubyte_or_word;
   12556            if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
   12557            break;
   12558         default:
   12559            vassert(0);
   12560      }
   12561 
   12562      /* Now, we can't do a conditional load or store, since that very
   12563         likely will generate an exception.  So we have to take a side
   12564         exit at this point if the condition is false. */
   12565      if (condT != IRTemp_INVALID) {
   12566         mk_skip_over_A32_if_cond_is_false( condT );
   12567         condT = IRTemp_INVALID;
   12568      }
   12569      /* Ok, now we're unconditional.  Do the load or store. */
   12570 
   12571      /* compute the effective address.  Bind it to a tmp since we
   12572         may need to use it twice. */
   12573      IRExpr* eaE = NULL;
   12574      switch (summary & 0xF0) {
   12575         case 16:
   12576            eaE = mk_EA_reg_plusminus_imm12( rN, bU, imm12, dis_buf );
   12577            break;
   12578         case 32:
   12579            eaE = mk_EA_reg_plusminus_shifted_reg( rN, bU, rM, sh2, imm5,
   12580                                                   dis_buf );
   12581            break;
   12582      }
   12583      vassert(eaE);
   12584      IRTemp eaT = newTemp(Ity_I32);
   12585      assign(eaT, eaE);
   12586 
   12587      /* get the old Rn value */
   12588      IRTemp rnT = newTemp(Ity_I32);
   12589      assign(rnT, getIRegA(rN));
   12590 
   12591      /* decide on the transfer address */
   12592      IRTemp taT = IRTemp_INVALID;
   12593      switch (summary & 0x0F) {
   12594         case 1: case 2: taT = eaT; break;
   12595         case 3:         taT = rnT; break;
   12596      }
   12597      vassert(taT != IRTemp_INVALID);
   12598 
   12599      if (bL == 0) {
   12600        /* Store.  If necessary, update the base register before the
   12601           store itself, so that the common idiom of "str rX, [sp,
   12602           #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push
   12603           rX") doesn't cause Memcheck to complain that the access is
   12604           below the stack pointer.  Also, not updating sp before the
   12605           store confuses Valgrind's dynamic stack-extending logic.  So
   12606           do it before the store.  Hence we need to snarf the store
   12607           data before doing the basereg update. */
   12608 
   12609         /* get hold of the data to be stored */
   12610         IRTemp rDt = newTemp(Ity_I32);
   12611         assign(rDt, getIRegA(rD));
   12612 
   12613         /* Update Rn if necessary. */
   12614         switch (summary & 0x0F) {
   12615            case 2: case 3:
   12616               putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   12617               break;
   12618         }
   12619 
   12620         /* generate the transfer */
   12621         if (bB == 0) { // word store
   12622            storeLE( mkexpr(taT), mkexpr(rDt) );
   12623         } else { // byte store
   12624            vassert(bB == 1);
   12625            storeLE( mkexpr(taT), unop(Iop_32to8, mkexpr(rDt)) );
   12626         }
   12627 
   12628      } else {
   12629         /* Load */
   12630         vassert(bL == 1);
   12631 
   12632         /* generate the transfer */
   12633         if (bB == 0) { // word load
   12634            IRTemp jk = Ijk_Boring;
   12635            /* According to the Cortex A8 TRM Sec. 5.2.1, LDR(1) with r13 as the
   12636                base register and PC as the destination register is a return for
   12637                purposes of branch prediction.
   12638               The ARM ARM Sec. C9.10.1 further specifies that it must use a
   12639                post-increment by immediate addressing mode to be counted in
   12640                event 0x0E (Procedure return).*/
   12641            if (rN == 13 && summary == (3 | 16) && bB == 0) {
   12642               jk = Ijk_Ret;
   12643            }
   12644            putIRegA( rD, loadLE(Ity_I32, mkexpr(taT)),
   12645                      IRTemp_INVALID, jk );
   12646         } else { // byte load
   12647            vassert(bB == 1);
   12648            putIRegA( rD, unop(Iop_8Uto32, loadLE(Ity_I8, mkexpr(taT))),
   12649                      IRTemp_INVALID, Ijk_Boring );
   12650         }
   12651 
   12652         /* Update Rn if necessary. */
   12653         switch (summary & 0x0F) {
   12654            case 2: case 3:
   12655               // should be assured by logic above:
   12656               if (bL == 1)
   12657                  vassert(rD != rN); /* since we just wrote rD */
   12658               putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   12659               break;
   12660         }
   12661      }
   12662 
   12663      switch (summary & 0x0F) {
   12664         case 1:  DIP("%sr%s%s r%u, %s\n",
   12665                      bL == 0 ? "st" : "ld",
   12666                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
   12667                  break;
   12668         case 2:  DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
   12669                      bL == 0 ? "st" : "ld",
   12670                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
   12671                  break;
   12672         case 3:  DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
   12673                      bL == 0 ? "st" : "ld",
   12674                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
   12675                  break;
   12676         default: vassert(0);
   12677      }
   12678 
   12679      /* XXX deal with alignment constraints */
   12680 
   12681      goto decode_success;
   12682 
   12683      /* Complications:
   12684 
   12685         For all loads: if the Amode specifies base register
   12686         writeback, and the same register is specified for Rd and Rn,
   12687         the results are UNPREDICTABLE.
   12688 
   12689         For all loads and stores: if R15 is written, branch to
   12690         that address afterwards.
   12691 
   12692         STRB: straightforward
   12693         LDRB: loaded data is zero extended
   12694         STR:  lowest 2 bits of address are ignored
   12695         LDR:  if the lowest 2 bits of the address are nonzero
   12696               then the loaded value is rotated right by 8 * the lowest 2 bits
   12697      */
   12698    }
   12699 
   12700   after_load_store_ubyte_or_word:
   12701 
   12702    /* --------------------- Load/store (sbyte & hword) -------- */
   12703    // LDRH LDRSH STRH LDRSB
   12704    /*                 31   27   23   19 15 11   7    3     # highest bit
   12705                         28   24   20 16 12    8    4    0
   12706       A5-36   1 | 16  cond 0001 U10L Rn Rd im4h 1SH1 im4l
   12707       A5-38   1 | 32  cond 0001 U00L Rn Rd 0000 1SH1 Rm
   12708       A5-40   2 | 16  cond 0001 U11L Rn Rd im4h 1SH1 im4l
   12709       A5-42   2 | 32  cond 0001 U01L Rn Rd 0000 1SH1 Rm
   12710       A5-44   3 | 16  cond 0000 U10L Rn Rd im4h 1SH1 im4l
   12711       A5-46   3 | 32  cond 0000 U00L Rn Rd 0000 1SH1 Rm
   12712    */
   12713    /* case coding:
   12714              1   at-ea               (access at ea)
   12715              2   at-ea-then-upd      (access at ea, then Rn = ea)
   12716              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
   12717       ea coding
   12718              16  Rn +/- imm8
   12719              32  Rn +/- Rm
   12720    */
   12721    /* Quickly skip over all of this for hopefully most instructions */
   12722    if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
   12723       goto after_load_store_sbyte_or_hword;
   12724 
   12725    /* Check the "1SH1" thing. */
   12726    if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1))
   12727       goto after_load_store_sbyte_or_hword;
   12728 
   12729    summary = 0;
   12730 
   12731    /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) {
   12732       summary = 1 | 16;
   12733    }
   12734    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) {
   12735       summary = 1 | 32;
   12736    }
   12737    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) {
   12738       summary = 2 | 16;
   12739    }
   12740    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) {
   12741       summary = 2 | 32;
   12742    }
   12743    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) {
   12744       summary = 3 | 16;
   12745    }
   12746    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) {
   12747       summary = 3 | 32;
   12748    }
   12749    else goto after_load_store_sbyte_or_hword;
   12750 
   12751    { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
   12752      UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
   12753      UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
   12754      UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
   12755      UInt bL   = (insn >> 20) & 1;   /* 20 L=1 load, L=0 store */
   12756      UInt bH   = (insn >> 5) & 1;    /* H=1 halfword, H=0 byte */
   12757      UInt bS   = (insn >> 6) & 1;    /* S=1 signed, S=0 unsigned */
   12758      UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
   12759 
   12760      /* Skip combinations that are either meaningless or already
   12761         handled by main word-or-unsigned-byte load-store
   12762         instructions. */
   12763      if (bS == 0 && bH == 0) /* "unsigned byte" */
   12764         goto after_load_store_sbyte_or_hword;
   12765      if (bS == 1 && bL == 0) /* "signed store" */
   12766         goto after_load_store_sbyte_or_hword;
   12767 
   12768      /* Require 11:8 == 0 for Rn +/- Rm cases */
   12769      if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
   12770         goto after_load_store_sbyte_or_hword;
   12771 
   12772      /* Skip some invalid cases, which would lead to two competing
   12773         updates to the same register, or which are otherwise
   12774         disallowed by the spec. */
   12775      switch (summary) {
   12776         case 1 | 16:
   12777            break;
   12778         case 1 | 32:
   12779            if (rM == 15) goto after_load_store_sbyte_or_hword;
   12780            break;
   12781         case 2 | 16: case 3 | 16:
   12782            if (rN == 15) goto after_load_store_sbyte_or_hword;
   12783            if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
   12784            break;
   12785         case 2 | 32: case 3 | 32:
   12786            if (rM == 15) goto after_load_store_sbyte_or_hword;
   12787            if (rN == 15) goto after_load_store_sbyte_or_hword;
   12788            if (rN == rM) goto after_load_store_sbyte_or_hword;
   12789            if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
   12790            break;
   12791         default:
   12792            vassert(0);
   12793      }
   12794 
   12795      /* Now, we can't do a conditional load or store, since that very
   12796         likely will generate an exception.  So we have to take a side
   12797         exit at this point if the condition is false. */
   12798      if (condT != IRTemp_INVALID) {
   12799         mk_skip_over_A32_if_cond_is_false( condT );
   12800         condT = IRTemp_INVALID;
   12801      }
   12802      /* Ok, now we're unconditional.  Do the load or store. */
   12803 
   12804      /* compute the effective address.  Bind it to a tmp since we
   12805         may need to use it twice. */
   12806      IRExpr* eaE = NULL;
   12807      switch (summary & 0xF0) {
   12808         case 16:
   12809            eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
   12810            break;
   12811         case 32:
   12812            eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
   12813            break;
   12814      }
   12815      vassert(eaE);
   12816      IRTemp eaT = newTemp(Ity_I32);
   12817      assign(eaT, eaE);
   12818 
   12819      /* get the old Rn value */
   12820      IRTemp rnT = newTemp(Ity_I32);
   12821      assign(rnT, getIRegA(rN));
   12822 
   12823      /* decide on the transfer address */
   12824      IRTemp taT = IRTemp_INVALID;
   12825      switch (summary & 0x0F) {
   12826         case 1: case 2: taT = eaT; break;
   12827         case 3:         taT = rnT; break;
   12828      }
   12829      vassert(taT != IRTemp_INVALID);
   12830 
   12831      /* halfword store  H 1  L 0  S 0
   12832         uhalf load      H 1  L 1  S 0
   12833         shalf load      H 1  L 1  S 1
   12834         sbyte load      H 0  L 1  S 1
   12835      */
   12836      HChar* name = NULL;
   12837      /* generate the transfer */
   12838      /**/ if (bH == 1 && bL == 0 && bS == 0) { // halfword store
   12839         storeLE( mkexpr(taT), unop(Iop_32to16, getIRegA(rD)) );
   12840         name = "strh";
   12841      }
   12842      else if (bH == 1 && bL == 1 && bS == 0) { // uhalf load
   12843         putIRegA( rD, unop(Iop_16Uto32, loadLE(Ity_I16, mkexpr(taT))),
   12844                   IRTemp_INVALID, Ijk_Boring );
   12845         name = "ldrh";
   12846      }
   12847      else if (bH == 1 && bL == 1 && bS == 1) { // shalf load
   12848         putIRegA( rD, unop(Iop_16Sto32, loadLE(Ity_I16, mkexpr(taT))),
   12849                   IRTemp_INVALID, Ijk_Boring );
   12850         name = "ldrsh";
   12851      }
   12852      else if (bH == 0 && bL == 1 && bS == 1) { // sbyte load
   12853         putIRegA( rD, unop(Iop_8Sto32, loadLE(Ity_I8, mkexpr(taT))),
   12854                   IRTemp_INVALID, Ijk_Boring );
   12855         name = "ldrsb";
   12856      }
   12857      else
   12858         vassert(0); // should be assured by logic above
   12859 
   12860      /* Update Rn if necessary. */
   12861      switch (summary & 0x0F) {
   12862         case 2: case 3:
   12863            // should be assured by logic above:
   12864            if (bL == 1)
   12865               vassert(rD != rN); /* since we just wrote rD */
   12866            putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   12867            break;
   12868      }
   12869 
   12870      switch (summary & 0x0F) {
   12871         case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
   12872                  break;
   12873         case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
   12874                      name, nCC(INSN_COND), rD, dis_buf);
   12875                  break;
   12876         case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
   12877                      name, nCC(INSN_COND), rD, dis_buf);
   12878                  break;
   12879         default: vassert(0);
   12880      }
   12881 
   12882      /* XXX deal with alignment constraints */
   12883 
   12884      goto decode_success;
   12885 
   12886      /* Complications:
   12887 
   12888         For all loads: if the Amode specifies base register
   12889         writeback, and the same register is specified for Rd and Rn,
   12890         the results are UNPREDICTABLE.
   12891 
   12892         For all loads and stores: if R15 is written, branch to
   12893         that address afterwards.
   12894 
   12895         Misaligned halfword stores => Unpredictable
   12896         Misaligned halfword loads  => Unpredictable
   12897      */
   12898    }
   12899 
   12900   after_load_store_sbyte_or_hword:
   12901 
   12902    /* --------------------- Load/store multiple -------------- */
   12903    // LD/STMIA LD/STMIB LD/STMDA LD/STMDB
   12904    // Remarkably complex and difficult to get right
   12905    // match 27:20 as 100XX0WL
   12906    if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) {
   12907       // A5-50 LD/STMIA  cond 1000 10WL Rn RegList
   12908       // A5-51 LD/STMIB  cond 1001 10WL Rn RegList
   12909       // A5-53 LD/STMDA  cond 1000 00WL Rn RegList
   12910       // A5-53 LD/STMDB  cond 1001 00WL Rn RegList
   12911       //                   28   24   20 16       0
   12912 
   12913       UInt bINC    = (insn >> 23) & 1;
   12914       UInt bBEFORE = (insn >> 24) & 1;
   12915 
   12916       UInt bL      = (insn >> 20) & 1;  /* load=1, store=0 */
   12917       UInt bW      = (insn >> 21) & 1;  /* Rn wback=1, no wback=0 */
   12918       UInt rN      = (insn >> 16) & 0xF;
   12919       UInt regList = insn & 0xFFFF;
   12920       /* Skip some invalid cases, which would lead to two competing
   12921          updates to the same register, or which are otherwise
   12922          disallowed by the spec.  Note the test above has required
   12923          that S == 0, since that looks like a kernel-mode only thing.
   12924          Done by forcing the real pattern, viz 100XXSWL to actually be
   12925          100XX0WL. */
   12926       if (rN == 15) goto after_load_store_multiple;
   12927       // reglist can't be empty
   12928       if (regList == 0) goto after_load_store_multiple;
   12929       // if requested to writeback Rn, and this is a load instruction,
   12930       // then Rn can't appear in RegList, since we'd have two competing
   12931       // new values for Rn.  We do however accept this case for store
   12932       // instructions.
   12933       if (bW == 1 && bL == 1 && ((1 << rN) & regList) > 0)
   12934          goto after_load_store_multiple;
   12935 
   12936       /* Now, we can't do a conditional load or store, since that very
   12937          likely will generate an exception.  So we have to take a side
   12938          exit at this point if the condition is false. */
   12939       if (condT != IRTemp_INVALID) {
   12940          mk_skip_over_A32_if_cond_is_false( condT );
   12941          condT = IRTemp_INVALID;
   12942       }
   12943 
   12944       /* Ok, now we're unconditional.  Generate the IR. */
   12945       mk_ldm_stm( True/*arm*/, rN, bINC, bBEFORE, bW, bL, regList );
   12946 
   12947       DIP("%sm%c%c%s r%u%s, {0x%04x}\n",
   12948           bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
   12949           nCC(INSN_COND),
   12950           rN, bW ? "!" : "", regList);
   12951 
   12952       goto decode_success;
   12953    }
   12954 
   12955   after_load_store_multiple:
   12956 
   12957    /* --------------------- Control flow --------------------- */
   12958    // B, BL (Branch, or Branch-and-Link, to immediate offset)
   12959    //
   12960    if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) {
   12961       UInt link   = (insn >> 24) & 1;
   12962       UInt uimm24 = insn & ((1<<24)-1);
   12963       Int  simm24 = (Int)uimm24;
   12964       UInt dst    = guest_R15_curr_instr_notENC + 8
   12965                     + (((simm24 << 8) >> 8) << 2);
   12966       IRJumpKind jk = link ? Ijk_Call : Ijk_Boring;
   12967       if (link) {
   12968          putIRegA(14, mkU32(guest_R15_curr_instr_notENC + 4),
   12969                       condT, Ijk_Boring);
   12970       }
   12971       if (condT == IRTemp_INVALID) {
   12972          /* unconditional transfer to 'dst'.  See if we can simply
   12973             continue tracing at the destination. */
   12974          if (resteerOkFn( callback_opaque, (Addr64)dst )) {
   12975             /* yes */
   12976             dres.whatNext   = Dis_ResteerU;
   12977             dres.continueAt = (Addr64)dst;
   12978          } else {
   12979             /* no; terminate the SB at this point. */
   12980             irsb->next     = mkU32(dst);
   12981             irsb->jumpkind = jk;
   12982             dres.whatNext  = Dis_StopHere;
   12983          }
   12984          DIP("b%s 0x%x\n", link ? "l" : "", dst);
   12985       } else {
   12986          /* conditional transfer to 'dst' */
   12987          HChar* comment = "";
   12988 
   12989          /* First see if we can do some speculative chasing into one
   12990             arm or the other.  Be conservative and only chase if
   12991             !link, that is, this is a normal conditional branch to a
   12992             known destination. */
   12993          if (!link
   12994              && resteerCisOk
   12995              && vex_control.guest_chase_cond
   12996              && dst < guest_R15_curr_instr_notENC
   12997              && resteerOkFn( callback_opaque, (Addr64)(Addr32)dst) ) {
   12998             /* Speculation: assume this backward branch is taken.  So
   12999                we need to emit a side-exit to the insn following this
   13000                one, on the negation of the condition, and continue at
   13001                the branch target address (dst). */
   13002             stmt( IRStmt_Exit( unop(Iop_Not1,
   13003                                     unop(Iop_32to1, mkexpr(condT))),
   13004                                Ijk_Boring,
   13005                                IRConst_U32(guest_R15_curr_instr_notENC+4) ));
   13006             dres.whatNext   = Dis_ResteerC;
   13007             dres.continueAt = (Addr64)(Addr32)dst;
   13008             comment = "(assumed taken)";
   13009          }
   13010          else
   13011          if (!link
   13012              && resteerCisOk
   13013              && vex_control.guest_chase_cond
   13014              && dst >= guest_R15_curr_instr_notENC
   13015              && resteerOkFn( callback_opaque,
   13016                              (Addr64)(Addr32)
   13017                                      (guest_R15_curr_instr_notENC+4)) ) {
   13018             /* Speculation: assume this forward branch is not taken.
   13019                So we need to emit a side-exit to dst (the dest) and
   13020                continue disassembling at the insn immediately
   13021                following this one. */
   13022             stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
   13023                                Ijk_Boring,
   13024                                IRConst_U32(dst) ));
   13025             dres.whatNext   = Dis_ResteerC;
   13026             dres.continueAt = (Addr64)(Addr32)
   13027                                       (guest_R15_curr_instr_notENC+4);
   13028             comment = "(assumed not taken)";
   13029          }
   13030          else {
   13031             /* Conservative default translation - end the block at
   13032                this point. */
   13033             stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
   13034                                jk, IRConst_U32(dst) ));
   13035             irsb->next     = mkU32(guest_R15_curr_instr_notENC + 4);
   13036             irsb->jumpkind = Ijk_Boring;
   13037             dres.whatNext  = Dis_StopHere;
   13038          }
   13039          DIP("b%s%s 0x%x %s\n", link ? "l" : "", nCC(INSN_COND),
   13040              dst, comment);
   13041       }
   13042       goto decode_success;
   13043    }
   13044 
   13045    // B, BL (Branch, or Branch-and-Link, to a register)
   13046    // NB: interworking branch
   13047    if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
   13048        && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1)
   13049        && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1)
   13050            || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) {
   13051       IRTemp  dst = newTemp(Ity_I32);
   13052       UInt    link = (INSN(11,4) >> 1) & 1;
   13053       UInt    rM   = INSN(3,0);
   13054       // we don't decode the case (link && rM == 15), as that's
   13055       // Unpredictable.
   13056       if (!(link && rM == 15)) {
   13057          if (condT != IRTemp_INVALID) {
   13058             mk_skip_over_A32_if_cond_is_false( condT );
   13059          }
   13060          // rM contains an interworking address exactly as we require
   13061          // (with continuation CPSR.T in bit 0), so we can use it
   13062          // as-is, with no masking.
   13063          assign( dst, getIRegA(rM) );
   13064          if (link) {
   13065             putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
   13066                       IRTemp_INVALID/*because AL*/, Ijk_Boring );
   13067          }
   13068          irsb->next     = mkexpr(dst);
   13069          irsb->jumpkind = link ? Ijk_Call
   13070                                : (rM == 14 ? Ijk_Ret : Ijk_Boring);
   13071          dres.whatNext  = Dis_StopHere;
   13072          if (condT == IRTemp_INVALID) {
   13073             DIP("b%sx r%u\n", link ? "l" : "", rM);
   13074          } else {
   13075             DIP("b%sx%s r%u\n", link ? "l" : "", nCC(INSN_COND), rM);
   13076          }
   13077          goto decode_success;
   13078       }
   13079       /* else: (link && rM == 15): just fall through */
   13080    }
   13081 
   13082    /* --- NB: ARM interworking branches are in NV space, hence
   13083       are handled elsewhere by decode_NV_instruction.
   13084       ---
   13085    */
   13086 
   13087    /* --------------------- Clz --------------------- */
   13088    // CLZ
   13089    if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0)
   13090        && INSN(19,16) == BITS4(1,1,1,1)
   13091        && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) {
   13092       UInt rD = INSN(15,12);
   13093       UInt rM = INSN(3,0);
   13094       IRTemp arg = newTemp(Ity_I32);
   13095       IRTemp res = newTemp(Ity_I32);
   13096       assign(arg, getIRegA(rM));
   13097       assign(res, IRExpr_Mux0X(
   13098                      unop(Iop_1Uto8,binop(Iop_CmpEQ32, mkexpr(arg),
   13099                                                        mkU32(0))),
   13100                      unop(Iop_Clz32, mkexpr(arg)),
   13101                      mkU32(32)
   13102             ));
   13103       putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13104       DIP("clz%s r%u, r%u\n", nCC(INSN_COND), rD, rM);
   13105       goto decode_success;
   13106    }
   13107 
   13108    /* --------------------- Mul etc --------------------- */
   13109    // MUL
   13110    if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
   13111        && INSN(15,12) == BITS4(0,0,0,0)
   13112        && INSN(7,4) == BITS4(1,0,0,1)) {
   13113       UInt bitS = (insn >> 20) & 1; /* 20:20 */
   13114       UInt rD = INSN(19,16);
   13115       UInt rS = INSN(11,8);
   13116       UInt rM = INSN(3,0);
   13117       if (rD == 15 || rM == 15 || rS == 15) {
   13118          /* Unpredictable; don't decode; fall through */
   13119       } else {
   13120          IRTemp argL = newTemp(Ity_I32);
   13121          IRTemp argR = newTemp(Ity_I32);
   13122          IRTemp res  = newTemp(Ity_I32);
   13123          IRTemp oldC = IRTemp_INVALID;
   13124          IRTemp oldV = IRTemp_INVALID;
   13125          assign( argL, getIRegA(rM));
   13126          assign( argR, getIRegA(rS));
   13127          assign( res, binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) );
   13128          if (bitS) {
   13129             oldC = newTemp(Ity_I32);
   13130             assign(oldC, mk_armg_calculate_flag_c());
   13131             oldV = newTemp(Ity_I32);
   13132             assign(oldV, mk_armg_calculate_flag_v());
   13133          }
   13134          // now update guest state
   13135          putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   13136          if (bitS) {
   13137             IRTemp pair = newTemp(Ity_I32);
   13138             assign( pair, binop(Iop_Or32,
   13139                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13140                                 mkexpr(oldV)) );
   13141             setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
   13142          }
   13143          DIP("mul%c%s r%u, r%u, r%u\n",
   13144              bitS ? 's' : ' ', nCC(INSN_COND), rD, rM, rS);
   13145          goto decode_success;
   13146       }
   13147       /* fall through */
   13148    }
   13149 
   13150    // MLA, MLS
   13151    if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13152        && INSN(7,4) == BITS4(1,0,0,1)) {
   13153       UInt bitS  = (insn >> 20) & 1; /* 20:20 */
   13154       UInt isMLS = (insn >> 22) & 1; /* 22:22 */
   13155       UInt rD = INSN(19,16);
   13156       UInt rN = INSN(15,12);
   13157       UInt rS = INSN(11,8);
   13158       UInt rM = INSN(3,0);
   13159       if (bitS == 1 && isMLS == 1) {
   13160          /* This isn't allowed (MLS that sets flags).  don't decode;
   13161             fall through */
   13162       }
   13163       else
   13164       if (rD == 15 || rM == 15 || rS == 15 || rN == 15) {
   13165          /* Unpredictable; don't decode; fall through */
   13166       } else {
   13167          IRTemp argL = newTemp(Ity_I32);
   13168          IRTemp argR = newTemp(Ity_I32);
   13169          IRTemp argP = newTemp(Ity_I32);
   13170          IRTemp res  = newTemp(Ity_I32);
   13171          IRTemp oldC = IRTemp_INVALID;
   13172          IRTemp oldV = IRTemp_INVALID;
   13173          assign( argL, getIRegA(rM));
   13174          assign( argR, getIRegA(rS));
   13175          assign( argP, getIRegA(rN));
   13176          assign( res, binop(isMLS ? Iop_Sub32 : Iop_Add32,
   13177                             mkexpr(argP),
   13178                             binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) ));
   13179          if (bitS) {
   13180             vassert(!isMLS); // guaranteed above
   13181             oldC = newTemp(Ity_I32);
   13182             assign(oldC, mk_armg_calculate_flag_c());
   13183             oldV = newTemp(Ity_I32);
   13184             assign(oldV, mk_armg_calculate_flag_v());
   13185          }
   13186          // now update guest state
   13187          putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   13188          if (bitS) {
   13189             IRTemp pair = newTemp(Ity_I32);
   13190             assign( pair, binop(Iop_Or32,
   13191                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13192                                 mkexpr(oldV)) );
   13193             setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
   13194          }
   13195          DIP("ml%c%c%s r%u, r%u, r%u, r%u\n",
   13196              isMLS ? 's' : 'a', bitS ? 's' : ' ',
   13197              nCC(INSN_COND), rD, rM, rS, rN);
   13198          goto decode_success;
   13199       }
   13200       /* fall through */
   13201    }
   13202 
   13203    // SMULL, UMULL
   13204    if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13205        && INSN(7,4) == BITS4(1,0,0,1)) {
   13206       UInt bitS = (insn >> 20) & 1; /* 20:20 */
   13207       UInt rDhi = INSN(19,16);
   13208       UInt rDlo = INSN(15,12);
   13209       UInt rS   = INSN(11,8);
   13210       UInt rM   = INSN(3,0);
   13211       UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
   13212       if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
   13213          /* Unpredictable; don't decode; fall through */
   13214       } else {
   13215          IRTemp argL  = newTemp(Ity_I32);
   13216          IRTemp argR  = newTemp(Ity_I32);
   13217          IRTemp res   = newTemp(Ity_I64);
   13218          IRTemp resHi = newTemp(Ity_I32);
   13219          IRTemp resLo = newTemp(Ity_I32);
   13220          IRTemp oldC  = IRTemp_INVALID;
   13221          IRTemp oldV  = IRTemp_INVALID;
   13222          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
   13223          assign( argL, getIRegA(rM));
   13224          assign( argR, getIRegA(rS));
   13225          assign( res, binop(mulOp, mkexpr(argL), mkexpr(argR)) );
   13226          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
   13227          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
   13228          if (bitS) {
   13229             oldC = newTemp(Ity_I32);
   13230             assign(oldC, mk_armg_calculate_flag_c());
   13231             oldV = newTemp(Ity_I32);
   13232             assign(oldV, mk_armg_calculate_flag_v());
   13233          }
   13234          // now update guest state
   13235          putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
   13236          putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
   13237          if (bitS) {
   13238             IRTemp pair = newTemp(Ity_I32);
   13239             assign( pair, binop(Iop_Or32,
   13240                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13241                                 mkexpr(oldV)) );
   13242             setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
   13243          }
   13244          DIP("%cmull%c%s r%u, r%u, r%u, r%u\n",
   13245              isS ? 's' : 'u', bitS ? 's' : ' ',
   13246              nCC(INSN_COND), rDlo, rDhi, rM, rS);
   13247          goto decode_success;
   13248       }
   13249       /* fall through */
   13250    }
   13251 
   13252    // SMLAL, UMLAL
   13253    if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13254        && INSN(7,4) == BITS4(1,0,0,1)) {
   13255       UInt bitS = (insn >> 20) & 1; /* 20:20 */
   13256       UInt rDhi = INSN(19,16);
   13257       UInt rDlo = INSN(15,12);
   13258       UInt rS   = INSN(11,8);
   13259       UInt rM   = INSN(3,0);
   13260       UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
   13261       if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
   13262          /* Unpredictable; don't decode; fall through */
   13263       } else {
   13264          IRTemp argL  = newTemp(Ity_I32);
   13265          IRTemp argR  = newTemp(Ity_I32);
   13266          IRTemp old   = newTemp(Ity_I64);
   13267          IRTemp res   = newTemp(Ity_I64);
   13268          IRTemp resHi = newTemp(Ity_I32);
   13269          IRTemp resLo = newTemp(Ity_I32);
   13270          IRTemp oldC  = IRTemp_INVALID;
   13271          IRTemp oldV  = IRTemp_INVALID;
   13272          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
   13273          assign( argL, getIRegA(rM));
   13274          assign( argR, getIRegA(rS));
   13275          assign( old, binop(Iop_32HLto64, getIRegA(rDhi), getIRegA(rDlo)) );
   13276          assign( res, binop(Iop_Add64,
   13277                             mkexpr(old),
   13278                             binop(mulOp, mkexpr(argL), mkexpr(argR))) );
   13279          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
   13280          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
   13281          if (bitS) {
   13282             oldC = newTemp(Ity_I32);
   13283             assign(oldC, mk_armg_calculate_flag_c());
   13284             oldV = newTemp(Ity_I32);
   13285             assign(oldV, mk_armg_calculate_flag_v());
   13286          }
   13287          // now update guest state
   13288          putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
   13289          putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
   13290          if (bitS) {
   13291             IRTemp pair = newTemp(Ity_I32);
   13292             assign( pair, binop(Iop_Or32,
   13293                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13294                                 mkexpr(oldV)) );
   13295             setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
   13296          }
   13297          DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n",
   13298              isS ? 's' : 'u', bitS ? 's' : ' ', nCC(INSN_COND),
   13299              rDlo, rDhi, rM, rS);
   13300          goto decode_success;
   13301       }
   13302       /* fall through */
   13303    }
   13304 
   13305    /* --------------------- Msr etc --------------------- */
   13306 
   13307    // MSR apsr, #imm
   13308    if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0)
   13309        && INSN(17,12) == BITS6(0,0,1,1,1,1)) {
   13310       UInt write_ge    = INSN(18,18);
   13311       UInt write_nzcvq = INSN(19,19);
   13312       if (write_nzcvq || write_ge) {
   13313          UInt   imm = (INSN(11,0) >> 0) & 0xFF;
   13314          UInt   rot = 2 * ((INSN(11,0) >> 8) & 0xF);
   13315          IRTemp immT = newTemp(Ity_I32);
   13316          vassert(rot <= 30);
   13317          imm = ROR32(imm, rot);
   13318          assign(immT, mkU32(imm));
   13319          desynthesise_APSR( write_nzcvq, write_ge, immT, condT );
   13320          DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND),
   13321              write_nzcvq ? "f" : "", write_ge ? "g" : "", imm);
   13322          goto decode_success;
   13323       }
   13324       /* fall through */
   13325    }
   13326 
   13327    // MSR apsr, reg
   13328    if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
   13329        && INSN(17,12) == BITS6(0,0,1,1,1,1)
   13330        && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) {
   13331       UInt rN          = INSN(3,0);
   13332       UInt write_ge    = INSN(18,18);
   13333       UInt write_nzcvq = INSN(19,19);
   13334       if (rN != 15 && (write_nzcvq || write_ge)) {
   13335          IRTemp rNt = newTemp(Ity_I32);
   13336          assign(rNt, getIRegA(rN));
   13337          desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
   13338          DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND),
   13339              write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
   13340          goto decode_success;
   13341       }
   13342       /* fall through */
   13343    }
   13344 
   13345    // MRS rD, cpsr
   13346    if ((insn & 0x0FFF0FFF) == 0x010F0000) {
   13347       UInt rD   = INSN(15,12);
   13348       if (rD != 15) {
   13349          IRTemp apsr = synthesise_APSR();
   13350          putIRegA( rD, mkexpr(apsr), condT, Ijk_Boring );
   13351          DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND), rD);
   13352          goto decode_success;
   13353       }
   13354       /* fall through */
   13355    }
   13356 
   13357    /* --------------------- Svc --------------------- */
   13358    if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) {
   13359       UInt imm24 = (insn >> 0) & 0xFFFFFF;
   13360       if (imm24 == 0) {
   13361          /* A syscall.  We can't do this conditionally, hence: */
   13362          if (condT != IRTemp_INVALID) {
   13363             mk_skip_over_A32_if_cond_is_false( condT );
   13364          }
   13365          // AL after here
   13366          irsb->next     = mkU32( guest_R15_curr_instr_notENC + 4 );
   13367          irsb->jumpkind = Ijk_Sys_syscall;
   13368          dres.whatNext  = Dis_StopHere;
   13369          DIP("svc%s #0x%08x\n", nCC(INSN_COND), imm24);
   13370          goto decode_success;
   13371       }
   13372       /* fall through */
   13373    }
   13374 
   13375    /* ------------------------ swp ------------------------ */
   13376 
   13377    // SWP, SWPB
   13378    if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   13379        && BITS4(0,0,0,0) == INSN(11,8)
   13380        && BITS4(1,0,0,1) == INSN(7,4)) {
   13381       UInt   rN   = INSN(19,16);
   13382       UInt   rD   = INSN(15,12);
   13383       UInt   rM   = INSN(3,0);
   13384       IRTemp tRn  = newTemp(Ity_I32);
   13385       IRTemp tNew = newTemp(Ity_I32);
   13386       IRTemp tOld = IRTemp_INVALID;
   13387       IRTemp tSC1 = newTemp(Ity_I1);
   13388       UInt   isB  = (insn >> 22) & 1;
   13389 
   13390       if (rD == 15 || rN == 15 || rM == 15 || rN == rM || rN == rD) {
   13391          /* undecodable; fall through */
   13392       } else {
   13393          /* make unconditional */
   13394          if (condT != IRTemp_INVALID) {
   13395             mk_skip_over_A32_if_cond_is_false( condT );
   13396             condT = IRTemp_INVALID;
   13397          }
   13398          /* Ok, now we're unconditional.  Generate a LL-SC loop. */
   13399          assign(tRn, getIRegA(rN));
   13400          assign(tNew, getIRegA(rM));
   13401          if (isB) {
   13402             /* swpb */
   13403             tOld = newTemp(Ity_I8);
   13404             stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
   13405                               NULL/*=>isLL*/) );
   13406             stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
   13407                               unop(Iop_32to8, mkexpr(tNew))) );
   13408          } else {
   13409             /* swp */
   13410             tOld = newTemp(Ity_I32);
   13411             stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
   13412                               NULL/*=>isLL*/) );
   13413             stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
   13414                               mkexpr(tNew)) );
   13415          }
   13416          stmt( IRStmt_Exit(unop(Iop_Not1, mkexpr(tSC1)),
   13417                            /*Ijk_NoRedir*/Ijk_Boring,
   13418                            IRConst_U32(guest_R15_curr_instr_notENC)) );
   13419          putIRegA(rD, isB ? unop(Iop_8Uto32, mkexpr(tOld)) : mkexpr(tOld),
   13420                       IRTemp_INVALID, Ijk_Boring);
   13421          DIP("swp%s%s r%u, r%u, [r%u]\n",
   13422              isB ? "b" : "", nCC(INSN_COND), rD, rM, rN);
   13423          goto decode_success;
   13424       }
   13425       /* fall through */
   13426    }
   13427 
   13428    /* ----------------------------------------------------------- */
   13429    /* -- ARMv6 instructions                                    -- */
   13430    /* ----------------------------------------------------------- */
   13431 
   13432    /* ------------------- {ldr,str}ex{,b,h,d} ------------------- */
   13433 
   13434    // LDREXD, LDREX, LDREXH, LDREXB
   13435    if (0x01900F9F == (insn & 0x0F900FFF)) {
   13436       UInt   rT    = INSN(15,12);
   13437       UInt   rN    = INSN(19,16);
   13438       IRType ty    = Ity_INVALID;
   13439       IROp   widen = Iop_INVALID;
   13440       HChar* nm    = NULL;
   13441       Bool   valid = True;
   13442       switch (INSN(22,21)) {
   13443          case 0: nm = "";  ty = Ity_I32; break;
   13444          case 1: nm = "d"; ty = Ity_I64; break;
   13445          case 2: nm = "b"; ty = Ity_I8;  widen = Iop_8Uto32; break;
   13446          case 3: nm = "h"; ty = Ity_I16; widen = Iop_16Uto32; break;
   13447          default: vassert(0);
   13448       }
   13449       if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
   13450          if (rT == 15 || rN == 15)
   13451             valid = False;
   13452       } else {
   13453          vassert(ty == Ity_I64);
   13454          if ((rT & 1) == 1 || rT == 14 || rN == 15)
   13455             valid = False;
   13456       }
   13457       if (valid) {
   13458          IRTemp res;
   13459          /* make unconditional */
   13460          if (condT != IRTemp_INVALID) {
   13461            mk_skip_over_A32_if_cond_is_false( condT );
   13462            condT = IRTemp_INVALID;
   13463          }
   13464          /* Ok, now we're unconditional.  Do the load. */
   13465          res = newTemp(ty);
   13466          // FIXME: assumes little-endian guest
   13467          stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN),
   13468                            NULL/*this is a load*/) );
   13469          if (ty == Ity_I64) {
   13470             // FIXME: assumes little-endian guest
   13471             putIRegA(rT+0, unop(Iop_64to32, mkexpr(res)),
   13472                            IRTemp_INVALID, Ijk_Boring);
   13473             putIRegA(rT+1, unop(Iop_64HIto32, mkexpr(res)),
   13474                            IRTemp_INVALID, Ijk_Boring);
   13475             DIP("ldrex%s%s r%u, r%u, [r%u]\n",
   13476                 nm, nCC(INSN_COND), rT+0, rT+1, rN);
   13477          } else {
   13478             putIRegA(rT, widen == Iop_INVALID
   13479                             ? mkexpr(res) : unop(widen, mkexpr(res)),
   13480                      IRTemp_INVALID, Ijk_Boring);
   13481             DIP("ldrex%s%s r%u, [r%u]\n", nm, nCC(INSN_COND), rT, rN);
   13482          }
   13483          goto decode_success;
   13484       }
   13485       /* undecodable; fall through */
   13486    }
   13487 
   13488    // STREXD, STREX, STREXH, STREXB
   13489    if (0x01800F90 == (insn & 0x0F900FF0)) {
   13490       UInt   rT     = INSN(3,0);
   13491       UInt   rN     = INSN(19,16);
   13492       UInt   rD     = INSN(15,12);
   13493       IRType ty     = Ity_INVALID;
   13494       IROp   narrow = Iop_INVALID;
   13495       HChar* nm     = NULL;
   13496       Bool   valid  = True;
   13497       switch (INSN(22,21)) {
   13498          case 0: nm = "";  ty = Ity_I32; break;
   13499          case 1: nm = "d"; ty = Ity_I64; break;
   13500          case 2: nm = "b"; ty = Ity_I8;  narrow = Iop_32to8; break;
   13501          case 3: nm = "h"; ty = Ity_I16; narrow = Iop_32to16; break;
   13502          default: vassert(0);
   13503       }
   13504       if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
   13505          if (rD == 15 || rN == 15 || rT == 15
   13506              || rD == rN || rD == rT)
   13507             valid = False;
   13508       } else {
   13509          vassert(ty == Ity_I64);
   13510          if (rD == 15 || (rT & 1) == 1 || rT == 14 || rN == 15
   13511              || rD == rN || rD == rT || rD == rT+1)
   13512             valid = False;
   13513       }
   13514       if (valid) {
   13515          IRTemp resSC1, resSC32, data;
   13516          /* make unconditional */
   13517          if (condT != IRTemp_INVALID) {
   13518             mk_skip_over_A32_if_cond_is_false( condT );
   13519             condT = IRTemp_INVALID;
   13520          }
   13521          /* Ok, now we're unconditional.  Do the store. */
   13522          data = newTemp(ty);
   13523          assign(data,
   13524                 ty == Ity_I64
   13525                    // FIXME: assumes little-endian guest
   13526                    ? binop(Iop_32HLto64, getIRegA(rT+1), getIRegA(rT+0))
   13527                    : narrow == Iop_INVALID
   13528                       ? getIRegA(rT)
   13529                       : unop(narrow, getIRegA(rT)));
   13530          resSC1 = newTemp(Ity_I1);
   13531          // FIXME: assumes little-endian guest
   13532          stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), mkexpr(data)) );
   13533 
   13534          /* Set rD to 1 on failure, 0 on success.  Currently we have
   13535             resSC1 == 0 on failure, 1 on success. */
   13536          resSC32 = newTemp(Ity_I32);
   13537          assign(resSC32,
   13538                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   13539 
   13540          putIRegA(rD, mkexpr(resSC32),
   13541                       IRTemp_INVALID, Ijk_Boring);
   13542          if (ty == Ity_I64) {
   13543             DIP("strex%s%s r%u, r%u, r%u, [r%u]\n",
   13544                 nm, nCC(INSN_COND), rD, rT, rT+1, rN);
   13545          } else {
   13546             DIP("strex%s%s r%u, r%u, [r%u]\n",
   13547                 nm, nCC(INSN_COND), rD, rT, rN);
   13548          }
   13549          goto decode_success;
   13550       }
   13551       /* fall through */
   13552    }
   13553 
   13554    /* --------------------- movw, movt --------------------- */
   13555    if (0x03000000 == (insn & 0x0FF00000)
   13556        || 0x03400000 == (insn & 0x0FF00000)) /* pray for CSE */ {
   13557       UInt rD    = INSN(15,12);
   13558       UInt imm16 = (insn & 0xFFF) | ((insn >> 4) & 0x0000F000);
   13559       UInt isT   = (insn >> 22) & 1;
   13560       if (rD == 15) {
   13561          /* forget it */
   13562       } else {
   13563          if (isT) {
   13564             putIRegA(rD,
   13565                      binop(Iop_Or32,
   13566                            binop(Iop_And32, getIRegA(rD), mkU32(0xFFFF)),
   13567                            mkU32(imm16 << 16)),
   13568                      condT, Ijk_Boring);
   13569             DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
   13570             goto decode_success;
   13571          } else {
   13572             putIRegA(rD, mkU32(imm16), condT, Ijk_Boring);
   13573             DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
   13574             goto decode_success;
   13575          }
   13576       }
   13577       /* fall through */
   13578    }
   13579 
   13580    /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */
   13581    /* FIXME: this is an exact duplicate of the Thumb version.  They
   13582       should be commoned up. */
   13583    if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0))
   13584        && BITS4(1,1,1,1) == INSN(19,16)
   13585        && BITS4(0,1,1,1) == INSN(7,4)
   13586        && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) {
   13587       UInt subopc = INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1);
   13588       if (subopc != BITS4(0,0,0,1) && subopc != BITS4(0,1,0,1)) {
   13589          Int    rot  = (INSN(11,8) >> 2) & 3;
   13590          UInt   rM   = INSN(3,0);
   13591          UInt   rD   = INSN(15,12);
   13592          IRTemp srcT = newTemp(Ity_I32);
   13593          IRTemp rotT = newTemp(Ity_I32);
   13594          IRTemp dstT = newTemp(Ity_I32);
   13595          HChar* nm   = "???";
   13596          assign(srcT, getIRegA(rM));
   13597          assign(rotT, genROR32(srcT, 8 * rot)); /* 0, 8, 16 or 24 only */
   13598          switch (subopc) {
   13599             case BITS4(0,1,1,0): // UXTB
   13600                assign(dstT, unop(Iop_8Uto32, unop(Iop_32to8, mkexpr(rotT))));
   13601                nm = "uxtb";
   13602                break;
   13603             case BITS4(0,0,1,0): // SXTB
   13604                assign(dstT, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rotT))));
   13605                nm = "sxtb";
   13606                break;
   13607             case BITS4(0,1,1,1): // UXTH
   13608                assign(dstT, unop(Iop_16Uto32, unop(Iop_32to16, mkexpr(rotT))));
   13609                nm = "uxth";
   13610                break;
   13611             case BITS4(0,0,1,1): // SXTH
   13612                assign(dstT, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rotT))));
   13613                nm = "sxth";
   13614                break;
   13615             case BITS4(0,1,0,0): // UXTB16
   13616                assign(dstT, binop(Iop_And32, mkexpr(rotT), mkU32(0x00FF00FF)));
   13617                nm = "uxtb16";
   13618                break;
   13619             case BITS4(0,0,0,0): { // SXTB16
   13620                IRTemp lo32 = newTemp(Ity_I32);
   13621                IRTemp hi32 = newTemp(Ity_I32);
   13622                assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
   13623                assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
   13624                assign(
   13625                   dstT,
   13626                   binop(Iop_Or32,
   13627                         binop(Iop_And32,
   13628                               unop(Iop_8Sto32,
   13629                                    unop(Iop_32to8, mkexpr(lo32))),
   13630                               mkU32(0xFFFF)),
   13631                         binop(Iop_Shl32,
   13632                               unop(Iop_8Sto32,
   13633                                    unop(Iop_32to8, mkexpr(hi32))),
   13634                               mkU8(16))
   13635                ));
   13636                nm = "sxtb16";
   13637                break;
   13638             }
   13639             default:
   13640                vassert(0); // guarded by "if" above
   13641          }
   13642          putIRegA(rD, mkexpr(dstT), condT, Ijk_Boring);
   13643          DIP("%s%s r%u, r%u, ROR #%u\n", nm, nCC(INSN_COND), rD, rM, rot);
   13644          goto decode_success;
   13645       }
   13646       /* fall through */
   13647    }
   13648 
   13649    /* ------------------- bfi, bfc ------------------- */
   13650    if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
   13651        && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
   13652       UInt rD  = INSN(15,12);
   13653       UInt rN  = INSN(3,0);
   13654       UInt msb = (insn >> 16) & 0x1F; /* 20:16 */
   13655       UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
   13656       if (rD == 15 || msb < lsb) {
   13657          /* undecodable; fall through */
   13658       } else {
   13659          IRTemp src    = newTemp(Ity_I32);
   13660          IRTemp olddst = newTemp(Ity_I32);
   13661          IRTemp newdst = newTemp(Ity_I32);
   13662          UInt   mask = 1 << (msb - lsb);
   13663          mask = (mask - 1) + mask;
   13664          vassert(mask != 0); // guaranteed by "msb < lsb" check above
   13665          mask <<= lsb;
   13666 
   13667          assign(src, rN == 15 ? mkU32(0) : getIRegA(rN));
   13668          assign(olddst, getIRegA(rD));
   13669          assign(newdst,
   13670                 binop(Iop_Or32,
   13671                    binop(Iop_And32,
   13672                          binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
   13673                          mkU32(mask)),
   13674                    binop(Iop_And32,
   13675                          mkexpr(olddst),
   13676                          mkU32(~mask)))
   13677                );
   13678 
   13679          putIRegA(rD, mkexpr(newdst), condT, Ijk_Boring);
   13680 
   13681          if (rN == 15) {
   13682             DIP("bfc%s r%u, #%u, #%u\n",
   13683                 nCC(INSN_COND), rD, lsb, msb-lsb+1);
   13684          } else {
   13685             DIP("bfi%s r%u, r%u, #%u, #%u\n",
   13686                 nCC(INSN_COND), rD, rN, lsb, msb-lsb+1);
   13687          }
   13688          goto decode_success;
   13689       }
   13690       /* fall through */
   13691    }
   13692 
   13693    /* ------------------- {u,s}bfx ------------------- */
   13694    if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13695        && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
   13696       UInt rD  = INSN(15,12);
   13697       UInt rN  = INSN(3,0);
   13698       UInt wm1 = (insn >> 16) & 0x1F; /* 20:16 */
   13699       UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
   13700       UInt msb = lsb + wm1;
   13701       UInt isU = (insn >> 22) & 1;    /* 22:22 */
   13702       if (rD == 15 || rN == 15 || msb >= 32) {
   13703          /* undecodable; fall through */
   13704       } else {
   13705          IRTemp src  = newTemp(Ity_I32);
   13706          IRTemp tmp  = newTemp(Ity_I32);
   13707          IRTemp res  = newTemp(Ity_I32);
   13708          UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
   13709          vassert(msb >= 0 && msb <= 31);
   13710          vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
   13711 
   13712          assign(src, getIRegA(rN));
   13713          assign(tmp, binop(Iop_And32,
   13714                            binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
   13715                            mkU32(mask)));
   13716          assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
   13717                            binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
   13718                            mkU8(31-wm1)));
   13719 
   13720          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13721 
   13722          DIP("%s%s r%u, r%u, #%u, #%u\n",
   13723              isU ? "ubfx" : "sbfx",
   13724              nCC(INSN_COND), rD, rN, lsb, wm1 + 1);
   13725          goto decode_success;
   13726       }
   13727       /* fall through */
   13728    }
   13729 
   13730    /* --------------------- Load/store doubleword ------------- */
   13731    // LDRD STRD
   13732    /*                 31   27   23   19 15 11   7    3     # highest bit
   13733                         28   24   20 16 12    8    4    0
   13734       A5-36   1 | 16  cond 0001 U100 Rn Rd im4h 11S1 im4l
   13735       A5-38   1 | 32  cond 0001 U000 Rn Rd 0000 11S1 Rm
   13736       A5-40   2 | 16  cond 0001 U110 Rn Rd im4h 11S1 im4l
   13737       A5-42   2 | 32  cond 0001 U010 Rn Rd 0000 11S1 Rm
   13738       A5-44   3 | 16  cond 0000 U100 Rn Rd im4h 11S1 im4l
   13739       A5-46   3 | 32  cond 0000 U000 Rn Rd 0000 11S1 Rm
   13740    */
   13741    /* case coding:
   13742              1   at-ea               (access at ea)
   13743              2   at-ea-then-upd      (access at ea, then Rn = ea)
   13744              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
   13745       ea coding
   13746              16  Rn +/- imm8
   13747              32  Rn +/- Rm
   13748    */
   13749    /* Quickly skip over all of this for hopefully most instructions */
   13750    if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
   13751       goto after_load_store_doubleword;
   13752 
   13753    /* Check the "11S1" thing. */
   13754    if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1))
   13755       goto after_load_store_doubleword;
   13756 
   13757    summary = 0;
   13758 
   13759    /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) {
   13760       summary = 1 | 16;
   13761    }
   13762    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) {
   13763       summary = 1 | 32;
   13764    }
   13765    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) {
   13766       summary = 2 | 16;
   13767    }
   13768    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) {
   13769       summary = 2 | 32;
   13770    }
   13771    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) {
   13772       summary = 3 | 16;
   13773    }
   13774    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) {
   13775       summary = 3 | 32;
   13776    }
   13777    else goto after_load_store_doubleword;
   13778 
   13779    { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
   13780      UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
   13781      UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
   13782      UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
   13783      UInt bS   = (insn >> 5) & 1;    /* S=1 store, S=0 load */
   13784      UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
   13785 
   13786      /* Require rD to be an even numbered register */
   13787      if ((rD & 1) != 0)
   13788         goto after_load_store_doubleword;
   13789 
   13790      /* Require 11:8 == 0 for Rn +/- Rm cases */
   13791      if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
   13792         goto after_load_store_doubleword;
   13793 
   13794      /* Skip some invalid cases, which would lead to two competing
   13795         updates to the same register, or which are otherwise
   13796         disallowed by the spec. */
   13797      switch (summary) {
   13798         case 1 | 16:
   13799            break;
   13800         case 1 | 32:
   13801            if (rM == 15) goto after_load_store_doubleword;
   13802            break;
   13803         case 2 | 16: case 3 | 16:
   13804            if (rN == 15) goto after_load_store_doubleword;
   13805            if (bS == 0 && (rN == rD || rN == rD+1))
   13806               goto after_load_store_doubleword;
   13807            break;
   13808         case 2 | 32: case 3 | 32:
   13809            if (rM == 15) goto after_load_store_doubleword;
   13810            if (rN == 15) goto after_load_store_doubleword;
   13811            if (rN == rM) goto after_load_store_doubleword;
   13812            if (bS == 0 && (rN == rD || rN == rD+1))
   13813               goto after_load_store_doubleword;
   13814            break;
   13815         default:
   13816            vassert(0);
   13817      }
   13818 
   13819      /* Now, we can't do a conditional load or store, since that very
   13820         likely will generate an exception.  So we have to take a side
   13821         exit at this point if the condition is false. */
   13822      if (condT != IRTemp_INVALID) {
   13823         mk_skip_over_A32_if_cond_is_false( condT );
   13824         condT = IRTemp_INVALID;
   13825      }
   13826      /* Ok, now we're unconditional.  Do the load or store. */
   13827 
   13828      /* compute the effective address.  Bind it to a tmp since we
   13829         may need to use it twice. */
   13830      IRExpr* eaE = NULL;
   13831      switch (summary & 0xF0) {
   13832         case 16:
   13833            eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
   13834            break;
   13835         case 32:
   13836            eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
   13837            break;
   13838      }
   13839      vassert(eaE);
   13840      IRTemp eaT = newTemp(Ity_I32);
   13841      assign(eaT, eaE);
   13842 
   13843      /* get the old Rn value */
   13844      IRTemp rnT = newTemp(Ity_I32);
   13845      assign(rnT, getIRegA(rN));
   13846 
   13847      /* decide on the transfer address */
   13848      IRTemp taT = IRTemp_INVALID;
   13849      switch (summary & 0x0F) {
   13850         case 1: case 2: taT = eaT; break;
   13851         case 3:         taT = rnT; break;
   13852      }
   13853      vassert(taT != IRTemp_INVALID);
   13854 
   13855      /* XXX deal with alignment constraints */
   13856      /* XXX: but the A8 doesn't seem to trap for misaligned loads, so,
   13857         ignore alignment issues for the time being. */
   13858 
   13859      /* doubleword store  S 1
   13860         doubleword load   S 0
   13861      */
   13862      HChar* name = NULL;
   13863      /* generate the transfers */
   13864      if (bS == 1) { // doubleword store
   13865         storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(0)), getIRegA(rD+0) );
   13866         storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(4)), getIRegA(rD+1) );
   13867         name = "strd";
   13868      } else { // doubleword load
   13869         putIRegA( rD+0,
   13870                   loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(0))),
   13871                   IRTemp_INVALID, Ijk_Boring );
   13872         putIRegA( rD+1,
   13873                   loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(4))),
   13874                   IRTemp_INVALID, Ijk_Boring );
   13875         name = "ldrd";
   13876      }
   13877 
   13878      /* Update Rn if necessary. */
   13879      switch (summary & 0x0F) {
   13880         case 2: case 3:
   13881            // should be assured by logic above:
   13882            if (bS == 0) {
   13883               vassert(rD+0 != rN); /* since we just wrote rD+0 */
   13884               vassert(rD+1 != rN); /* since we just wrote rD+1 */
   13885            }
   13886            putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   13887            break;
   13888      }
   13889 
   13890      switch (summary & 0x0F) {
   13891         case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
   13892                  break;
   13893         case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
   13894                      name, nCC(INSN_COND), rD, dis_buf);
   13895                  break;
   13896         case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
   13897                      name, nCC(INSN_COND), rD, dis_buf);
   13898                  break;
   13899         default: vassert(0);
   13900      }
   13901 
   13902      goto decode_success;
   13903    }
   13904 
   13905   after_load_store_doubleword:
   13906 
   13907    /* ------------------- {s,u}xtab ------------- */
   13908    if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   13909        && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
   13910        && BITS4(0,1,1,1) == INSN(7,4)) {
   13911       UInt rN  = INSN(19,16);
   13912       UInt rD  = INSN(15,12);
   13913       UInt rM  = INSN(3,0);
   13914       UInt rot = (insn >> 10) & 3;
   13915       UInt isU = INSN(22,22);
   13916       if (rN == 15/*it's {S,U}XTB*/ || rD == 15 || rM == 15) {
   13917          /* undecodable; fall through */
   13918       } else {
   13919          IRTemp srcL = newTemp(Ity_I32);
   13920          IRTemp srcR = newTemp(Ity_I32);
   13921          IRTemp res  = newTemp(Ity_I32);
   13922          assign(srcR, getIRegA(rM));
   13923          assign(srcL, getIRegA(rN));
   13924          assign(res,  binop(Iop_Add32,
   13925                             mkexpr(srcL),
   13926                             unop(isU ? Iop_8Uto32 : Iop_8Sto32,
   13927                                  unop(Iop_32to8,
   13928                                       genROR32(srcR, 8 * rot)))));
   13929          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13930          DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n",
   13931              isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
   13932          goto decode_success;
   13933       }
   13934       /* fall through */
   13935    }
   13936 
   13937    /* ------------------- {s,u}xtah ------------- */
   13938    if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   13939        && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
   13940        && BITS4(0,1,1,1) == INSN(7,4)) {
   13941       UInt rN  = INSN(19,16);
   13942       UInt rD  = INSN(15,12);
   13943       UInt rM  = INSN(3,0);
   13944       UInt rot = (insn >> 10) & 3;
   13945       UInt isU = INSN(22,22);
   13946       if (rN == 15/*it's {S,U}XTH*/ || rD == 15 || rM == 15) {
   13947          /* undecodable; fall through */
   13948       } else {
   13949          IRTemp srcL = newTemp(Ity_I32);
   13950          IRTemp srcR = newTemp(Ity_I32);
   13951          IRTemp res  = newTemp(Ity_I32);
   13952          assign(srcR, getIRegA(rM));
   13953          assign(srcL, getIRegA(rN));
   13954          assign(res,  binop(Iop_Add32,
   13955                             mkexpr(srcL),
   13956                             unop(isU ? Iop_16Uto32 : Iop_16Sto32,
   13957                                  unop(Iop_32to16,
   13958                                       genROR32(srcR, 8 * rot)))));
   13959          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13960 
   13961          DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n",
   13962              isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
   13963          goto decode_success;
   13964       }
   13965       /* fall through */
   13966    }
   13967 
   13968    /* ------------------- rev16, rev ------------------ */
   13969    if (INSN(27,16) == 0x6BF
   13970        && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) {
   13971       Bool isREV = INSN(11,4) == 0xF3;
   13972       UInt rM    = INSN(3,0);
   13973       UInt rD    = INSN(15,12);
   13974       if (rM != 15 && rD != 15) {
   13975          IRTemp rMt = newTemp(Ity_I32);
   13976          assign(rMt, getIRegA(rM));
   13977          IRTemp res = isREV ? gen_REV(rMt) : gen_REV16(rMt);
   13978          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13979          DIP("rev%s%s r%u, r%u\n", isREV ? "" : "16",
   13980              nCC(INSN_COND), rD, rM);
   13981          goto decode_success;
   13982       }
   13983    }
   13984 
   13985    /* ------------------- rbit ------------------ */
   13986    if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) {
   13987       UInt rD = INSN(15,12);
   13988       UInt rM = INSN(3,0);
   13989       if (rD != 15 && rM != 15) {
   13990          IRTemp arg = newTemp(Ity_I32);
   13991          assign(arg, getIRegA(rM));
   13992          IRTemp res = gen_BITREV(arg);
   13993          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13994          DIP("rbit r%u, r%u\n", rD, rM);
   13995          goto decode_success;
   13996       }
   13997    }
   13998 
   13999    /* ------------------- smmul ------------------ */
   14000    if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
   14001        && INSN(15,12) == BITS4(1,1,1,1)
   14002        && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
   14003       UInt bitR = INSN(5,5);
   14004       UInt rD = INSN(19,16);
   14005       UInt rM = INSN(11,8);
   14006       UInt rN = INSN(3,0);
   14007       if (rD != 15 && rM != 15 && rN != 15) {
   14008          IRExpr* res
   14009          = unop(Iop_64HIto32,
   14010                 binop(Iop_Add64,
   14011                       binop(Iop_MullS32, getIRegA(rN), getIRegA(rM)),
   14012                       mkU64(bitR ? 0x80000000ULL : 0ULL)));
   14013          putIRegA(rD, res, condT, Ijk_Boring);
   14014          DIP("smmul%s%s r%u, r%u, r%u\n",
   14015              nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM);
   14016          goto decode_success;
   14017       }
   14018    }
   14019 
   14020    /* ------------------- NOP ------------------ */
   14021    if (0x0320F000 == (insn & 0x0FFFFFFF)) {
   14022       DIP("nop%s\n", nCC(INSN_COND));
   14023       goto decode_success;
   14024    }
   14025 
   14026    /* ----------------------------------------------------------- */
   14027    /* -- ARMv7 instructions                                    -- */
   14028    /* ----------------------------------------------------------- */
   14029 
   14030    /* -------------- read CP15 TPIDRURO register ------------- */
   14031    /* mrc     p15, 0, r0, c13, c0, 3  up to
   14032       mrc     p15, 0, r14, c13, c0, 3
   14033    */
   14034    /* I don't know whether this is really v7-only.  But anyway, we
   14035       have to support it since arm-linux uses TPIDRURO as a thread
   14036       state register. */
   14037    if (0x0E1D0F70 == (insn & 0x0FFF0FFF)) {
   14038       UInt rD = INSN(15,12);
   14039       if (rD <= 14) {
   14040          /* skip r15, that's too stupid to handle */
   14041          putIRegA(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32),
   14042                       condT, Ijk_Boring);
   14043          DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND), rD);
   14044          goto decode_success;
   14045       }
   14046       /* fall through */
   14047    }
   14048 
   14049    /* Handle various kinds of barriers.  This is rather indiscriminate
   14050       in the sense that they are all turned into an IR Fence, which
   14051       means we don't know which they are, so the back end has to
   14052       re-emit them all when it comes acrosss an IR Fence.
   14053    */
   14054    if (0xEE070F9A == (insn & 0xFFFF0FFF)) { /* v6 */
   14055       /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7).  Data
   14056          Synch Barrier -- ensures completion of memory accesses. */
   14057       stmt( IRStmt_MBE(Imbe_Fence) );
   14058       DIP("mcr 15, 0, rX, c7, c10, 4 (data synch barrier)\n");
   14059       goto decode_success;
   14060    }
   14061    if (0xEE070FBA == (insn & 0xFFFF0FFF)) { /* v6 */
   14062       /* mcr 15, 0, r0, c7, c10, 5 (v6) equiv to DMB (v7).  Data
   14063          Memory Barrier -- ensures ordering of memory accesses. */
   14064       stmt( IRStmt_MBE(Imbe_Fence) );
   14065       DIP("mcr 15, 0, rX, c7, c10, 5 (data memory barrier)\n");
   14066       goto decode_success;
   14067    }
   14068    if (0xEE070F95 == (insn & 0xFFFF0FFF)) { /* v6 */
   14069       /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7).
   14070          Instruction Synchronisation Barrier (or Flush Prefetch
   14071          Buffer) -- a pipe flush, I think.  I suspect we could
   14072          ignore those, but to be on the safe side emit a fence
   14073          anyway. */
   14074       stmt( IRStmt_MBE(Imbe_Fence) );
   14075       DIP("mcr 15, 0, rX, c7, c5, 4 (insn synch barrier)\n");
   14076       goto decode_success;
   14077    }
   14078 
   14079    /* ----------------------------------------------------------- */
   14080    /* -- VFP (CP 10, CP 11) instructions (in ARM mode)         -- */
   14081    /* ----------------------------------------------------------- */
   14082 
   14083    if (INSN_COND != ARMCondNV) {
   14084       Bool ok_vfp = decode_CP10_CP11_instruction (
   14085                        &dres, INSN(27,0), condT, INSN_COND,
   14086                        False/*!isT*/
   14087                     );
   14088       if (ok_vfp)
   14089          goto decode_success;
   14090    }
   14091 
   14092    /* ----------------------------------------------------------- */
   14093    /* -- NEON instructions (in ARM mode)                       -- */
   14094    /* ----------------------------------------------------------- */
   14095 
   14096    /* These are all in NV space, and so are taken care of (far) above,
   14097       by a call from this function to decode_NV_instruction(). */
   14098 
   14099    /* ----------------------------------------------------------- */
   14100    /* -- v6 media instructions (in ARM mode)                   -- */
   14101    /* ----------------------------------------------------------- */
   14102 
   14103    { Bool ok_v6m = decode_V6MEDIA_instruction(
   14104                        &dres, INSN(27,0), condT, INSN_COND,
   14105                        False/*!isT*/
   14106                    );
   14107      if (ok_v6m)
   14108         goto decode_success;
   14109    }
   14110 
   14111    /* ----------------------------------------------------------- */
   14112    /* -- Undecodable                                           -- */
   14113    /* ----------------------------------------------------------- */
   14114 
   14115    goto decode_failure;
   14116    /*NOTREACHED*/
   14117 
   14118   decode_failure:
   14119    /* All decode failures end up here. */
   14120    vex_printf("disInstr(arm): unhandled instruction: "
   14121               "0x%x\n", insn);
   14122    vex_printf("                 cond=%d(0x%x) 27:20=%u(0x%02x) "
   14123                                 "4:4=%d "
   14124                                 "3:0=%u(0x%x)\n",
   14125               (Int)INSN_COND, (UInt)INSN_COND,
   14126               (Int)INSN(27,20), (UInt)INSN(27,20),
   14127               (Int)INSN(4,4),
   14128               (Int)INSN(3,0), (UInt)INSN(3,0) );
   14129 
   14130    /* Tell the dispatcher that this insn cannot be decoded, and so has
   14131       not been executed, and (is currently) the next to be executed.
   14132       R15 should be up-to-date since it made so at the start of each
   14133       insn, but nevertheless be paranoid and update it again right
   14134       now. */
   14135    vassert(0 == (guest_R15_curr_instr_notENC & 3));
   14136    llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
   14137    irsb->next     = mkU32(guest_R15_curr_instr_notENC);
   14138    irsb->jumpkind = Ijk_NoDecode;
   14139    dres.whatNext  = Dis_StopHere;
   14140    dres.len       = 0;
   14141    return dres;
   14142 
   14143   decode_success:
   14144    /* All decode successes end up here. */
   14145    DIP("\n");
   14146 
   14147    vassert(dres.len == 4 || dres.len == 20);
   14148 
   14149    /* Now then.  Do we have an implicit jump to r15 to deal with? */
   14150    if (r15written) {
   14151       /* If we get jump to deal with, we assume that there's been no
   14152          other competing branch stuff previously generated for this
   14153          insn.  That's reasonable, in the sense that the ARM insn set
   14154          appears to declare as "Unpredictable" any instruction which
   14155          generates more than one possible new value for r15.  Hence
   14156          just assert.  The decoders themselves should check against
   14157          all such instructions which are thusly Unpredictable, and
   14158          decline to decode them.  Hence we should never get here if we
   14159          have competing new values for r15, and hence it is safe to
   14160          assert here. */
   14161       vassert(dres.whatNext == Dis_Continue);
   14162       vassert(irsb->next == NULL);
   14163       vassert(irsb->jumpkind == Ijk_Boring);
   14164       /* If r15 is unconditionally written, terminate the block by
   14165          jumping to it.  If it's conditionally written, still
   14166          terminate the block (a shame, but we can't do side exits to
   14167          arbitrary destinations), but first jump to the next
   14168          instruction if the condition doesn't hold. */
   14169       /* We can't use getIReg(15) to get the destination, since that
   14170          will produce r15+8, which isn't what we want.  Must use
   14171          llGetIReg(15) instead. */
   14172       if (r15guard == IRTemp_INVALID) {
   14173          /* unconditional */
   14174       } else {
   14175          /* conditional */
   14176          stmt( IRStmt_Exit(
   14177                   unop(Iop_32to1,
   14178                        binop(Iop_Xor32,
   14179                              mkexpr(r15guard), mkU32(1))),
   14180                   r15kind,
   14181                   IRConst_U32(guest_R15_curr_instr_notENC + 4)
   14182          ));
   14183       }
   14184       irsb->next     = llGetIReg(15);
   14185       irsb->jumpkind = r15kind;
   14186       dres.whatNext  = Dis_StopHere;
   14187    }
   14188 
   14189    return dres;
   14190 
   14191 #  undef INSN_COND
   14192 #  undef INSN
   14193 }
   14194 
   14195 
   14196 /*------------------------------------------------------------*/
   14197 /*--- Disassemble a single Thumb2 instruction              ---*/
   14198 /*------------------------------------------------------------*/
   14199 
   14200 static const UChar it_length_table[256]; /* fwds */
   14201 
   14202 /* NB: in Thumb mode we do fetches of regs with getIRegT, which
   14203    automagically adds 4 to fetches of r15.  However, writes to regs
   14204    are done with putIRegT, which disallows writes to r15.  Hence any
   14205    r15 writes and associated jumps have to be done "by hand". */
   14206 
   14207 /* Disassemble a single Thumb instruction into IR.  The instruction is
   14208    located in host memory at guest_instr, and has (decoded) guest IP
   14209    of guest_R15_curr_instr_notENC, which will have been set before the
   14210    call here. */
   14211 
   14212 static
   14213 DisResult disInstr_THUMB_WRK (
   14214              Bool         put_IP,
   14215              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
   14216              Bool         resteerCisOk,
   14217              void*        callback_opaque,
   14218              UChar*       guest_instr,
   14219              VexArchInfo* archinfo,
   14220              VexAbiInfo*  abiinfo
   14221           )
   14222 {
   14223    /* A macro to fish bits out of insn0.  There's also INSN1, to fish
   14224       bits out of insn1, but that's defined only after the end of the
   14225       16-bit insn decoder, so as to stop it mistakenly being used
   14226       therein. */
   14227 #  define INSN0(_bMax,_bMin)  SLICE_UInt(((UInt)insn0), (_bMax), (_bMin))
   14228 
   14229    DisResult dres;
   14230    UShort    insn0; /* first 16 bits of the insn */
   14231    //Bool      allow_VFP = False;
   14232    //UInt      hwcaps = archinfo->hwcaps;
   14233    HChar     dis_buf[128];  // big enough to hold LDMIA etc text
   14234 
   14235    /* Summary result of the ITxxx backwards analysis: False == safe
   14236       but suboptimal. */
   14237    Bool guaranteedUnconditional = False;
   14238 
   14239    /* What insn variants are we supporting today? */
   14240    //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
   14241    // etc etc
   14242 
   14243    /* Set result defaults. */
   14244    dres.whatNext   = Dis_Continue;
   14245    dres.len        = 2;
   14246    dres.continueAt = 0;
   14247 
   14248    /* Set default actions for post-insn handling of writes to r15, if
   14249       required. */
   14250    r15written = False;
   14251    r15guard   = IRTemp_INVALID; /* unconditional */
   14252    r15kind    = Ijk_Boring;
   14253 
   14254    /* Insns could be 2 or 4 bytes long.  Just get the first 16 bits at
   14255       this point.  If we need the second 16, get them later.  We can't
   14256       get them both out immediately because it risks a fault (very
   14257       unlikely, but ..) if the second 16 bits aren't actually
   14258       necessary. */
   14259    insn0 = getUShortLittleEndianly( guest_instr );
   14260 
   14261    if (0) vex_printf("insn: 0x%x\n", insn0);
   14262 
   14263    DIP("\t(thumb) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
   14264 
   14265    /* We may be asked to update the guest R15 before going further. */
   14266    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   14267    if (put_IP) {
   14268       llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
   14269    }
   14270 
   14271    /* ----------------------------------------------------------- */
   14272    /* Spot "Special" instructions (see comment at top of file). */
   14273    {
   14274       UChar* code = (UChar*)guest_instr;
   14275       /* Spot the 16-byte preamble:
   14276 
   14277          ea4f 0cfc  mov.w   ip, ip, ror #3
   14278          ea4f 3c7c  mov.w   ip, ip, ror #13
   14279          ea4f 7c7c  mov.w   ip, ip, ror #29
   14280          ea4f 4cfc  mov.w   ip, ip, ror #19
   14281       */
   14282       UInt word1 = 0x0CFCEA4F;
   14283       UInt word2 = 0x3C7CEA4F;
   14284       UInt word3 = 0x7C7CEA4F;
   14285       UInt word4 = 0x4CFCEA4F;
   14286       if (getUIntLittleEndianly(code+ 0) == word1 &&
   14287           getUIntLittleEndianly(code+ 4) == word2 &&
   14288           getUIntLittleEndianly(code+ 8) == word3 &&
   14289           getUIntLittleEndianly(code+12) == word4) {
   14290          /* Got a "Special" instruction preamble.  Which one is it? */
   14291          // 0x 0A 0A EA 4A
   14292          if (getUIntLittleEndianly(code+16) == 0x0A0AEA4A
   14293                                                /* orr.w r10,r10,r10 */) {
   14294             /* R3 = client_request ( R4 ) */
   14295             DIP("r3 = client_request ( %%r4 )\n");
   14296             irsb->next     = mkU32( (guest_R15_curr_instr_notENC + 20) | 1 );
   14297             irsb->jumpkind = Ijk_ClientReq;
   14298             dres.whatNext  = Dis_StopHere;
   14299             goto decode_success;
   14300          }
   14301          else
   14302          // 0x 0B 0B EA 4B
   14303          if (getUIntLittleEndianly(code+16) == 0x0B0BEA4B
   14304                                                /* orr r11,r11,r11 */) {
   14305             /* R3 = guest_NRADDR */
   14306             DIP("r3 = guest_NRADDR\n");
   14307             dres.len = 20;
   14308             llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
   14309             goto decode_success;
   14310          }
   14311          else
   14312          // 0x 0C 0C EA 4C
   14313          if (getUIntLittleEndianly(code+16) == 0x0C0CEA4C
   14314                                                /* orr r12,r12,r12 */) {
   14315             /*  branch-and-link-to-noredir R4 */
   14316             DIP("branch-and-link-to-noredir r4\n");
   14317             llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ));
   14318             irsb->next     = getIRegT(4);
   14319             irsb->jumpkind = Ijk_NoRedir;
   14320             dres.whatNext  = Dis_StopHere;
   14321             goto decode_success;
   14322          }
   14323          /* We don't know what it is.  Set insn0 so decode_failure
   14324             can print the insn following the Special-insn preamble. */
   14325          insn0 = getUShortLittleEndianly(code+16);
   14326          goto decode_failure;
   14327          /*NOTREACHED*/
   14328       }
   14329 
   14330    }
   14331 
   14332    /* ----------------------------------------------------------- */
   14333 
   14334    /* Main Thumb instruction decoder starts here.  It's a series of
   14335       switches which examine ever longer bit sequences at the MSB of
   14336       the instruction word, first for 16-bit insns, then for 32-bit
   14337       insns. */
   14338 
   14339    /* --- BEGIN ITxxx optimisation analysis --- */
   14340    /* This is a crucial optimisation for the ITState boilerplate that
   14341       follows.  Examine the 9 halfwords preceding this instruction,
   14342       and if we are absolutely sure that none of them constitute an
   14343       'it' instruction, then we can be sure that this instruction is
   14344       not under the control of any 'it' instruction, and so
   14345       guest_ITSTATE must be zero.  So write zero into ITSTATE right
   14346       now, so that iropt can fold out almost all of the resulting
   14347       junk.
   14348 
   14349       If we aren't sure, we can always safely skip this step.  So be a
   14350       bit conservative about it: only poke around in the same page as
   14351       this instruction, lest we get a fault from the previous page
   14352       that would not otherwise have happened.  The saving grace is
   14353       that such skipping is pretty rare -- it only happens,
   14354       statistically, 18/4096ths of the time, so is judged unlikely to
   14355       be a performance problems.
   14356 
   14357       FIXME: do better.  Take into account the number of insns covered
   14358       by any IT insns we find, to rule out cases where an IT clearly
   14359       cannot cover this instruction.  This would improve behaviour for
   14360       branch targets immediately following an IT-guarded group that is
   14361       not of full length.  Eg, (and completely ignoring issues of 16-
   14362       vs 32-bit insn length):
   14363 
   14364              ite cond
   14365              insn1
   14366              insn2
   14367       label: insn3
   14368              insn4
   14369 
   14370       The 'it' only conditionalises insn1 and insn2.  However, the
   14371       current analysis is conservative and considers insn3 and insn4
   14372       also possibly guarded.  Hence if 'label:' is the start of a hot
   14373       loop we will get a big performance hit.
   14374    */
   14375    {
   14376       /* Summary result of this analysis: False == safe but
   14377          suboptimal. */
   14378       vassert(guaranteedUnconditional == False);
   14379 
   14380       UInt pc = guest_R15_curr_instr_notENC;
   14381       vassert(0 == (pc & 1));
   14382 
   14383       UInt pageoff = pc & 0xFFF;
   14384       if (pageoff >= 18) {
   14385          /* It's safe to poke about in the 9 halfwords preceding this
   14386             insn.  So, have a look at them. */
   14387          guaranteedUnconditional = True; /* assume no 'it' insn found,
   14388                                             till we do */
   14389          UShort* hwp = (UShort*)(HWord)pc;
   14390          Int i;
   14391          for (i = -1; i >= -9; i--) {
   14392             /* We're in the same page.  (True, but commented out due
   14393                to expense.) */
   14394             /*
   14395             vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 )
   14396                       == ( pc & 0xFFFFF000 ) );
   14397             */
   14398             /* All valid IT instructions must have the form 0xBFxy,
   14399                where x can be anything, but y must be nonzero.  Find
   14400                the number of insns covered by it (1 .. 4) and check to
   14401                see if it can possibly reach up to the instruction in
   14402                question.  Some (x,y) combinations mean UNPREDICTABLE,
   14403                and the table is constructed to be conservative by
   14404                returning 4 for those cases, so the analysis is safe
   14405                even if the code uses unpredictable IT instructions (in
   14406                which case its authors are nuts, but hey.)  */
   14407             UShort hwp_i = hwp[i];
   14408             if (UNLIKELY((hwp_i & 0xFF00) == 0xBF00 && (hwp_i & 0xF) != 0)) {
   14409                /* might be an 'it' insn. */
   14410                /* # guarded insns */
   14411                Int n_guarded = (Int)it_length_table[hwp_i & 0xFF];
   14412                vassert(n_guarded >= 1 && n_guarded <= 4);
   14413                if (n_guarded * 2 /* # guarded HWs, worst case */
   14414                    > (-(i+1)))   /* -(i+1): # remaining HWs after the IT */
   14415                    /* -(i+0) also seems to work, even though I think
   14416                       it's wrong.  I don't understand that. */
   14417                   guaranteedUnconditional = False;
   14418                break;
   14419             }
   14420          }
   14421       }
   14422    }
   14423    /* --- END ITxxx optimisation analysis --- */
   14424 
   14425    /* Generate the guarding condition for this insn, by examining
   14426       ITSTATE.  Assign it to condT.  Also, generate new
   14427       values for ITSTATE ready for stuffing back into the
   14428       guest state, but don't actually do the Put yet, since it will
   14429       need to stuffed back in only after the instruction gets to a
   14430       point where it is sure to complete.  Mostly we let the code at
   14431       decode_success handle this, but in cases where the insn contains
   14432       a side exit, we have to update them before the exit. */
   14433 
   14434    /* If the ITxxx optimisation analysis above could not prove that
   14435       this instruction is guaranteed unconditional, we insert a
   14436       lengthy IR preamble to compute the guarding condition at
   14437       runtime.  If it can prove it (which obviously we hope is the
   14438       normal case) then we insert a minimal preamble, which is
   14439       equivalent to setting guest_ITSTATE to zero and then folding
   14440       that through the full preamble (which completely disappears). */
   14441 
   14442    IRTemp condT              = IRTemp_INVALID;
   14443    IRTemp old_itstate        = IRTemp_INVALID;
   14444    IRTemp new_itstate        = IRTemp_INVALID;
   14445    IRTemp cond_AND_notInIT_T = IRTemp_INVALID;
   14446 
   14447    if (guaranteedUnconditional) {
   14448       /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
   14449 
   14450       // ITSTATE = 0 :: I32
   14451       IRTemp z32 = newTemp(Ity_I32);
   14452       assign(z32, mkU32(0));
   14453       put_ITSTATE(z32);
   14454 
   14455       // old_itstate = 0 :: I32
   14456       //
   14457       // old_itstate = get_ITSTATE();
   14458       old_itstate = z32; /* 0 :: I32 */
   14459 
   14460       // new_itstate = old_itstate >> 8
   14461       //             = 0 >> 8
   14462       //             = 0 :: I32
   14463       //
   14464       // new_itstate = newTemp(Ity_I32);
   14465       // assign(new_itstate,
   14466       //        binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
   14467       new_itstate = z32;
   14468 
   14469       // ITSTATE = 0 :: I32(again)
   14470       //
   14471       // put_ITSTATE(new_itstate);
   14472 
   14473       // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) )
   14474       //        = calc_cond_dyn( xor(0,0xE0) )
   14475       //        = calc_cond_dyn ( 0xE0 )
   14476       //        = 1 :: I32
   14477       // Not that this matters, since the computed value is not used:
   14478       // see condT folding below
   14479       //
   14480       // IRTemp condT1 = newTemp(Ity_I32);
   14481       // assign(condT1,
   14482       //        mk_armg_calculate_condition_dyn(
   14483       //           binop(Iop_Xor32,
   14484       //                 binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
   14485       //                 mkU32(0xE0))
   14486       //       )
   14487       // );
   14488 
   14489       // condT = 32to8(and32(old_itstate,0xF0)) == 0  ? 1  : condT1
   14490       //       = 32to8(and32(0,0xF0)) == 0  ? 1  : condT1
   14491       //       = 32to8(0) == 0  ? 1  : condT1
   14492       //       = 0 == 0  ? 1  : condT1
   14493       //       = 1
   14494       //
   14495       // condT = newTemp(Ity_I32);
   14496       // assign(condT, IRExpr_Mux0X(
   14497       //                  unop(Iop_32to8, binop(Iop_And32,
   14498       //                                        mkexpr(old_itstate),
   14499       //                                        mkU32(0xF0))),
   14500       //                  mkU32(1),
   14501       //                  mkexpr(condT1)
   14502       //       ));
   14503       condT = newTemp(Ity_I32);
   14504       assign(condT, mkU32(1));
   14505 
   14506       // notInITt = xor32(and32(old_itstate, 1), 1)
   14507       //          = xor32(and32(0, 1), 1)
   14508       //          = xor32(0, 1)
   14509       //          = 1 :: I32
   14510       //
   14511       // IRTemp notInITt = newTemp(Ity_I32);
   14512       // assign(notInITt,
   14513       //        binop(Iop_Xor32,
   14514       //              binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
   14515       //              mkU32(1)));
   14516 
   14517       // cond_AND_notInIT_T = and32(notInITt, condT)
   14518       //                    = and32(1, 1)
   14519       //                    = 1
   14520       //
   14521       // cond_AND_notInIT_T = newTemp(Ity_I32);
   14522       // assign(cond_AND_notInIT_T,
   14523       //        binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
   14524       cond_AND_notInIT_T = condT; /* 1 :: I32 */
   14525 
   14526       /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
   14527    } else {
   14528       /* BEGIN { STANDARD PREAMBLE; } */
   14529 
   14530       old_itstate = get_ITSTATE();
   14531 
   14532       new_itstate = newTemp(Ity_I32);
   14533       assign(new_itstate,
   14534              binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
   14535 
   14536       put_ITSTATE(new_itstate);
   14537 
   14538       /* Same strategy as for ARM insns: generate a condition
   14539          temporary at this point (or IRTemp_INVALID, meaning
   14540          unconditional).  We leave it to lower-level instruction
   14541          decoders to decide whether they can generate straight-line
   14542          code, or whether they must generate a side exit before the
   14543          instruction.  condT :: Ity_I32 and is always either zero or
   14544          one. */
   14545       IRTemp condT1 = newTemp(Ity_I32);
   14546       assign(condT1,
   14547              mk_armg_calculate_condition_dyn(
   14548                 binop(Iop_Xor32,
   14549                       binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
   14550                       mkU32(0xE0))
   14551             )
   14552       );
   14553 
   14554       /* This is a bit complex, but needed to make Memcheck understand
   14555          that, if the condition in old_itstate[7:4] denotes AL (that
   14556          is, if this instruction is to be executed unconditionally),
   14557          then condT does not depend on the results of calling the
   14558          helper.
   14559 
   14560          We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in
   14561          that case set condT directly to 1.  Else we use the results
   14562          of the helper.  Since old_itstate is always defined and
   14563          because Memcheck does lazy V-bit propagation through Mux0X,
   14564          this will cause condT to always be a defined 1 if the
   14565          condition is 'AL'.  From an execution semantics point of view
   14566          this is irrelevant since we're merely duplicating part of the
   14567          behaviour of the helper.  But it makes it clear to Memcheck,
   14568          in this case, that condT does not in fact depend on the
   14569          contents of the condition code thunk.  Without it, we get
   14570          quite a lot of false errors.
   14571 
   14572          So, just to clarify: from a straight semantics point of view,
   14573          we can simply do "assign(condT, mkexpr(condT1))", and the
   14574          simulator still runs fine.  It's just that we get loads of
   14575          false errors from Memcheck. */
   14576       condT = newTemp(Ity_I32);
   14577       assign(condT, IRExpr_Mux0X(
   14578                        unop(Iop_32to8, binop(Iop_And32,
   14579                                              mkexpr(old_itstate),
   14580                                              mkU32(0xF0))),
   14581                        mkU32(1),
   14582                        mkexpr(condT1)
   14583             ));
   14584 
   14585       /* Something we don't have in ARM: generate a 0 or 1 value
   14586          indicating whether or not we are in an IT block (NB: 0 = in
   14587          IT block, 1 = not in IT block).  This is used to gate
   14588          condition code updates in 16-bit Thumb instructions. */
   14589       IRTemp notInITt = newTemp(Ity_I32);
   14590       assign(notInITt,
   14591              binop(Iop_Xor32,
   14592                    binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
   14593                    mkU32(1)));
   14594 
   14595       /* Compute 'condT && notInITt' -- that is, the instruction is
   14596          going to execute, and we're not in an IT block.  This is the
   14597          gating condition for updating condition codes in 16-bit Thumb
   14598          instructions, except for CMP, CMN and TST. */
   14599       cond_AND_notInIT_T = newTemp(Ity_I32);
   14600       assign(cond_AND_notInIT_T,
   14601              binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
   14602       /* END { STANDARD PREAMBLE; } */
   14603    }
   14604 
   14605 
   14606    /* At this point:
   14607       * ITSTATE has been updated
   14608       * condT holds the guarding condition for this instruction (0 or 1),
   14609       * notInITt is 1 if we're in "normal" code, 0 if in an IT block
   14610       * cond_AND_notInIT_T is the AND of the above two.
   14611 
   14612       If the instruction proper can't trap, then there's nothing else
   14613       to do w.r.t. ITSTATE -- just go and and generate IR for the
   14614       insn, taking into account the guarding condition.
   14615 
   14616       If, however, the instruction might trap, then we must back up
   14617       ITSTATE to the old value, and re-update it after the potentially
   14618       trapping IR section.  A trap can happen either via a memory
   14619       reference or because we need to throw SIGILL.
   14620 
   14621       If an instruction has a side exit, we need to be sure that any
   14622       ITSTATE backup is re-updated before the side exit.
   14623    */
   14624 
   14625    /* ----------------------------------------------------------- */
   14626    /* --                                                       -- */
   14627    /* -- Thumb 16-bit integer instructions                     -- */
   14628    /* --                                                       -- */
   14629    /* -- IMPORTANT: references to insn1 or INSN1 are           -- */
   14630    /* --            not allowed in this section                -- */
   14631    /* --                                                       -- */
   14632    /* ----------------------------------------------------------- */
   14633 
   14634    /* 16-bit instructions inside an IT block, apart from CMP, CMN and
   14635       TST, do not set the condition codes.  Hence we must dynamically
   14636       test for this case for every condition code update. */
   14637 
   14638    IROp   anOp   = Iop_INVALID;
   14639    HChar* anOpNm = NULL;
   14640 
   14641    /* ================ 16-bit 15:6 cases ================ */
   14642 
   14643    switch (INSN0(15,6)) {
   14644 
   14645    case 0x10a:   // CMP
   14646    case 0x10b: { // CMN
   14647       /* ---------------- CMP Rn, Rm ---------------- */
   14648       Bool   isCMN = INSN0(15,6) == 0x10b;
   14649       UInt   rN    = INSN0(2,0);
   14650       UInt   rM    = INSN0(5,3);
   14651       IRTemp argL  = newTemp(Ity_I32);
   14652       IRTemp argR  = newTemp(Ity_I32);
   14653       assign( argL, getIRegT(rN) );
   14654       assign( argR, getIRegT(rM) );
   14655       /* Update flags regardless of whether in an IT block or not. */
   14656       setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   14657                       argL, argR, condT );
   14658       DIP("%s r%u, r%u\n", isCMN ? "cmn" : "cmp", rN, rM);
   14659       goto decode_success;
   14660    }
   14661 
   14662    case 0x108: {
   14663       /* ---------------- TST Rn, Rm ---------------- */
   14664       UInt   rN   = INSN0(2,0);
   14665       UInt   rM   = INSN0(5,3);
   14666       IRTemp oldC = newTemp(Ity_I32);
   14667       IRTemp oldV = newTemp(Ity_I32);
   14668       IRTemp res  = newTemp(Ity_I32);
   14669       assign( oldC, mk_armg_calculate_flag_c() );
   14670       assign( oldV, mk_armg_calculate_flag_v() );
   14671       assign( res,  binop(Iop_And32, getIRegT(rN), getIRegT(rM)) );
   14672       /* Update flags regardless of whether in an IT block or not. */
   14673       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
   14674       DIP("tst r%u, r%u\n", rN, rM);
   14675       goto decode_success;
   14676    }
   14677 
   14678    case 0x109: {
   14679       /* ---------------- NEGS Rd, Rm ---------------- */
   14680       /* Rd = -Rm */
   14681       UInt   rM   = INSN0(5,3);
   14682       UInt   rD   = INSN0(2,0);
   14683       IRTemp arg  = newTemp(Ity_I32);
   14684       IRTemp zero = newTemp(Ity_I32);
   14685       assign(arg, getIRegT(rM));
   14686       assign(zero, mkU32(0));
   14687       // rD can never be r15
   14688       putIRegT(rD, binop(Iop_Sub32, mkexpr(zero), mkexpr(arg)), condT);
   14689       setFlags_D1_D2( ARMG_CC_OP_SUB, zero, arg, cond_AND_notInIT_T);
   14690       DIP("negs r%u, r%u\n", rD, rM);
   14691       goto decode_success;
   14692    }
   14693 
   14694    case 0x10F: {
   14695       /* ---------------- MVNS Rd, Rm ---------------- */
   14696       /* Rd = ~Rm */
   14697       UInt   rM   = INSN0(5,3);
   14698       UInt   rD   = INSN0(2,0);
   14699       IRTemp oldV = newTemp(Ity_I32);
   14700       IRTemp oldC = newTemp(Ity_I32);
   14701       IRTemp res  = newTemp(Ity_I32);
   14702       assign( oldV, mk_armg_calculate_flag_v() );
   14703       assign( oldC, mk_armg_calculate_flag_c() );
   14704       assign(res, unop(Iop_Not32, getIRegT(rM)));
   14705       // rD can never be r15
   14706       putIRegT(rD, mkexpr(res), condT);
   14707       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   14708                          cond_AND_notInIT_T );
   14709       DIP("mvns r%u, r%u\n", rD, rM);
   14710       goto decode_success;
   14711    }
   14712 
   14713    case 0x10C:
   14714       /* ---------------- ORRS Rd, Rm ---------------- */
   14715       anOp = Iop_Or32; anOpNm = "orr"; goto and_orr_eor_mul;
   14716    case 0x100:
   14717       /* ---------------- ANDS Rd, Rm ---------------- */
   14718       anOp = Iop_And32; anOpNm = "and"; goto and_orr_eor_mul;
   14719    case 0x101:
   14720       /* ---------------- EORS Rd, Rm ---------------- */
   14721       anOp = Iop_Xor32; anOpNm = "eor"; goto and_orr_eor_mul;
   14722    case 0x10d:
   14723       /* ---------------- MULS Rd, Rm ---------------- */
   14724       anOp = Iop_Mul32; anOpNm = "mul"; goto and_orr_eor_mul;
   14725    and_orr_eor_mul: {
   14726       /* Rd = Rd `op` Rm */
   14727       UInt   rM   = INSN0(5,3);
   14728       UInt   rD   = INSN0(2,0);
   14729       IRTemp res  = newTemp(Ity_I32);
   14730       IRTemp oldV = newTemp(Ity_I32);
   14731       IRTemp oldC = newTemp(Ity_I32);
   14732       assign( oldV, mk_armg_calculate_flag_v() );
   14733       assign( oldC, mk_armg_calculate_flag_c() );
   14734       assign( res, binop(anOp, getIRegT(rD), getIRegT(rM) ));
   14735       // not safe to read guest state after here
   14736       // rD can never be r15
   14737       putIRegT(rD, mkexpr(res), condT);
   14738       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   14739                          cond_AND_notInIT_T );
   14740       DIP("%s r%u, r%u\n", anOpNm, rD, rM);
   14741       goto decode_success;
   14742    }
   14743 
   14744    case 0x10E: {
   14745       /* ---------------- BICS Rd, Rm ---------------- */
   14746       /* Rd = Rd & ~Rm */
   14747       UInt   rM   = INSN0(5,3);
   14748       UInt   rD   = INSN0(2,0);
   14749       IRTemp res  = newTemp(Ity_I32);
   14750       IRTemp oldV = newTemp(Ity_I32);
   14751       IRTemp oldC = newTemp(Ity_I32);
   14752       assign( oldV, mk_armg_calculate_flag_v() );
   14753       assign( oldC, mk_armg_calculate_flag_c() );
   14754       assign( res, binop(Iop_And32, getIRegT(rD),
   14755                                     unop(Iop_Not32, getIRegT(rM) )));
   14756       // not safe to read guest state after here
   14757       // rD can never be r15
   14758       putIRegT(rD, mkexpr(res), condT);
   14759       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   14760                          cond_AND_notInIT_T );
   14761       DIP("bics r%u, r%u\n", rD, rM);
   14762       goto decode_success;
   14763    }
   14764 
   14765    case 0x105: {
   14766       /* ---------------- ADCS Rd, Rm ---------------- */
   14767       /* Rd = Rd + Rm + oldC */
   14768       UInt   rM   = INSN0(5,3);
   14769       UInt   rD   = INSN0(2,0);
   14770       IRTemp argL = newTemp(Ity_I32);
   14771       IRTemp argR = newTemp(Ity_I32);
   14772       IRTemp oldC = newTemp(Ity_I32);
   14773       IRTemp res  = newTemp(Ity_I32);
   14774       assign(argL, getIRegT(rD));
   14775       assign(argR, getIRegT(rM));
   14776       assign(oldC, mk_armg_calculate_flag_c());
   14777       assign(res, binop(Iop_Add32,
   14778                         binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
   14779                         mkexpr(oldC)));
   14780       // rD can never be r15
   14781       putIRegT(rD, mkexpr(res), condT);
   14782       setFlags_D1_D2_ND( ARMG_CC_OP_ADC, argL, argR, oldC,
   14783                          cond_AND_notInIT_T );
   14784       DIP("adcs r%u, r%u\n", rD, rM);
   14785       goto decode_success;
   14786    }
   14787 
   14788    case 0x106: {
   14789       /* ---------------- SBCS Rd, Rm ---------------- */
   14790       /* Rd = Rd - Rm - (oldC ^ 1) */
   14791       UInt   rM   = INSN0(5,3);
   14792       UInt   rD   = INSN0(2,0);
   14793       IRTemp argL = newTemp(Ity_I32);
   14794       IRTemp argR = newTemp(Ity_I32);
   14795       IRTemp oldC = newTemp(Ity_I32);
   14796       IRTemp res  = newTemp(Ity_I32);
   14797       assign(argL, getIRegT(rD));
   14798       assign(argR, getIRegT(rM));
   14799       assign(oldC, mk_armg_calculate_flag_c());
   14800       assign(res, binop(Iop_Sub32,
   14801                         binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
   14802                         binop(Iop_Xor32, mkexpr(oldC), mkU32(1))));
   14803       // rD can never be r15
   14804       putIRegT(rD, mkexpr(res), condT);
   14805       setFlags_D1_D2_ND( ARMG_CC_OP_SBB, argL, argR, oldC,
   14806                          cond_AND_notInIT_T );
   14807       DIP("sbcs r%u, r%u\n", rD, rM);
   14808       goto decode_success;
   14809    }
   14810 
   14811    case 0x2CB: {
   14812       /* ---------------- UXTB Rd, Rm ---------------- */
   14813       /* Rd = 8Uto32(Rm) */
   14814       UInt rM = INSN0(5,3);
   14815       UInt rD = INSN0(2,0);
   14816       putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFF)),
   14817                    condT);
   14818       DIP("uxtb r%u, r%u\n", rD, rM);
   14819       goto decode_success;
   14820    }
   14821 
   14822    case 0x2C9: {
   14823       /* ---------------- SXTB Rd, Rm ---------------- */
   14824       /* Rd = 8Sto32(Rm) */
   14825       UInt rM = INSN0(5,3);
   14826       UInt rD = INSN0(2,0);
   14827       putIRegT(rD, binop(Iop_Sar32,
   14828                          binop(Iop_Shl32, getIRegT(rM), mkU8(24)),
   14829                          mkU8(24)),
   14830                    condT);
   14831       DIP("sxtb r%u, r%u\n", rD, rM);
   14832       goto decode_success;
   14833    }
   14834 
   14835    case 0x2CA: {
   14836       /* ---------------- UXTH Rd, Rm ---------------- */
   14837       /* Rd = 16Uto32(Rm) */
   14838       UInt rM = INSN0(5,3);
   14839       UInt rD = INSN0(2,0);
   14840       putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFFFF)),
   14841                    condT);
   14842       DIP("uxth r%u, r%u\n", rD, rM);
   14843       goto decode_success;
   14844    }
   14845 
   14846    case 0x2C8: {
   14847       /* ---------------- SXTH Rd, Rm ---------------- */
   14848       /* Rd = 16Sto32(Rm) */
   14849       UInt rM = INSN0(5,3);
   14850       UInt rD = INSN0(2,0);
   14851       putIRegT(rD, binop(Iop_Sar32,
   14852                          binop(Iop_Shl32, getIRegT(rM), mkU8(16)),
   14853                          mkU8(16)),
   14854                    condT);
   14855       DIP("sxth r%u, r%u\n", rD, rM);
   14856       goto decode_success;
   14857    }
   14858 
   14859    case 0x102:   // LSLS
   14860    case 0x103:   // LSRS
   14861    case 0x104:   // ASRS
   14862    case 0x107: { // RORS
   14863       /* ---------------- LSLS Rs, Rd ---------------- */
   14864       /* ---------------- LSRS Rs, Rd ---------------- */
   14865       /* ---------------- ASRS Rs, Rd ---------------- */
   14866       /* ---------------- RORS Rs, Rd ---------------- */
   14867       /* Rd = Rd `op` Rs, and set flags */
   14868       UInt   rS   = INSN0(5,3);
   14869       UInt   rD   = INSN0(2,0);
   14870       IRTemp oldV = newTemp(Ity_I32);
   14871       IRTemp rDt  = newTemp(Ity_I32);
   14872       IRTemp rSt  = newTemp(Ity_I32);
   14873       IRTemp res  = newTemp(Ity_I32);
   14874       IRTemp resC = newTemp(Ity_I32);
   14875       HChar* wot  = "???";
   14876       assign(rSt, getIRegT(rS));
   14877       assign(rDt, getIRegT(rD));
   14878       assign(oldV, mk_armg_calculate_flag_v());
   14879       /* Does not appear to be the standard 'how' encoding. */
   14880       switch (INSN0(15,6)) {
   14881          case 0x102:
   14882             compute_result_and_C_after_LSL_by_reg(
   14883                dis_buf, &res, &resC, rDt, rSt, rD, rS
   14884             );
   14885             wot = "lsl";
   14886             break;
   14887          case 0x103:
   14888             compute_result_and_C_after_LSR_by_reg(
   14889                dis_buf, &res, &resC, rDt, rSt, rD, rS
   14890             );
   14891             wot = "lsr";
   14892             break;
   14893          case 0x104:
   14894             compute_result_and_C_after_ASR_by_reg(
   14895                dis_buf, &res, &resC, rDt, rSt, rD, rS
   14896             );
   14897             wot = "asr";
   14898             break;
   14899          case 0x107:
   14900             compute_result_and_C_after_ROR_by_reg(
   14901                dis_buf, &res, &resC, rDt, rSt, rD, rS
   14902             );
   14903             wot = "ror";
   14904             break;
   14905          default:
   14906             /*NOTREACHED*/vassert(0);
   14907       }
   14908       // not safe to read guest state after this point
   14909       putIRegT(rD, mkexpr(res), condT);
   14910       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
   14911                          cond_AND_notInIT_T );
   14912       DIP("%ss r%u, r%u\n", wot, rS, rD);
   14913       goto decode_success;
   14914    }
   14915 
   14916    case 0x2E8:   // REV
   14917    case 0x2E9: { // REV16
   14918       /* ---------------- REV   Rd, Rm ---------------- */
   14919       /* ---------------- REV16 Rd, Rm ---------------- */
   14920       UInt rM = INSN0(5,3);
   14921       UInt rD = INSN0(2,0);
   14922       Bool isREV = INSN0(15,6) == 0x2E8;
   14923       IRTemp arg = newTemp(Ity_I32);
   14924       assign(arg, getIRegT(rM));
   14925       IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
   14926       putIRegT(rD, mkexpr(res), condT);
   14927       DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM);
   14928       goto decode_success;
   14929    }
   14930 
   14931    default:
   14932       break; /* examine the next shortest prefix */
   14933 
   14934    }
   14935 
   14936 
   14937    /* ================ 16-bit 15:7 cases ================ */
   14938 
   14939    switch (INSN0(15,7)) {
   14940 
   14941    case BITS9(1,0,1,1,0,0,0,0,0): {
   14942       /* ------------ ADD SP, #imm7 * 4 ------------ */
   14943       UInt uimm7 = INSN0(6,0);
   14944       putIRegT(13, binop(Iop_Add32, getIRegT(13), mkU32(uimm7 * 4)),
   14945                    condT);
   14946       DIP("add sp, #%u\n", uimm7 * 4);
   14947       goto decode_success;
   14948    }
   14949 
   14950    case BITS9(1,0,1,1,0,0,0,0,1): {
   14951       /* ------------ SUB SP, #imm7 * 4 ------------ */
   14952       UInt uimm7 = INSN0(6,0);
   14953       putIRegT(13, binop(Iop_Sub32, getIRegT(13), mkU32(uimm7 * 4)),
   14954                    condT);
   14955       DIP("sub sp, #%u\n", uimm7 * 4);
   14956       goto decode_success;
   14957    }
   14958 
   14959    case BITS9(0,1,0,0,0,1,1,1,0): {
   14960       /* ---------------- BX rM ---------------- */
   14961       /* Branch to reg, and optionally switch modes.  Reg contains a
   14962          suitably encoded address therefore (w CPSR.T at the bottom).
   14963          Have to special-case r15, as usual. */
   14964       UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
   14965       if (BITS3(0,0,0) == INSN0(2,0)) {
   14966          IRTemp dst = newTemp(Ity_I32);
   14967          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   14968          mk_skip_over_T16_if_cond_is_false(condT);
   14969          condT = IRTemp_INVALID;
   14970          // now uncond
   14971          if (rM <= 14) {
   14972             assign( dst, getIRegT(rM) );
   14973          } else {
   14974             vassert(rM == 15);
   14975             assign( dst, mkU32(guest_R15_curr_instr_notENC + 4) );
   14976          }
   14977          irsb->next     = mkexpr(dst);
   14978          irsb->jumpkind = rM == 14 ? Ijk_Ret : Ijk_Boring;
   14979          dres.whatNext  = Dis_StopHere;
   14980          DIP("bx r%u (possibly switch to ARM mode)\n", rM);
   14981          goto decode_success;
   14982       }
   14983       break;
   14984    }
   14985 
   14986    /* ---------------- BLX rM ---------------- */
   14987    /* Branch and link to interworking address in rM. */
   14988    case BITS9(0,1,0,0,0,1,1,1,1): {
   14989       if (BITS3(0,0,0) == INSN0(2,0)) {
   14990          UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
   14991          IRTemp dst = newTemp(Ity_I32);
   14992          if (rM <= 14) {
   14993             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   14994             mk_skip_over_T16_if_cond_is_false(condT);
   14995             condT = IRTemp_INVALID;
   14996             // now uncond
   14997             /* We're returning to Thumb code, hence "| 1" */
   14998             assign( dst, getIRegT(rM) );
   14999             putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ),
   15000                           IRTemp_INVALID );
   15001             irsb->next     = mkexpr(dst);
   15002             irsb->jumpkind = Ijk_Call;
   15003             dres.whatNext  = Dis_StopHere;
   15004             DIP("blx r%u (possibly switch to ARM mode)\n", rM);
   15005             goto decode_success;
   15006          }
   15007          /* else unpredictable, fall through */
   15008       }
   15009       break;
   15010    }
   15011 
   15012    default:
   15013       break; /* examine the next shortest prefix */
   15014 
   15015    }
   15016 
   15017 
   15018    /* ================ 16-bit 15:8 cases ================ */
   15019 
   15020    switch (INSN0(15,8)) {
   15021 
   15022    case BITS8(1,1,0,1,1,1,1,1): {
   15023       /* ---------------- SVC ---------------- */
   15024       UInt imm8 = INSN0(7,0);
   15025       if (imm8 == 0) {
   15026          /* A syscall.  We can't do this conditionally, hence: */
   15027          mk_skip_over_T16_if_cond_is_false( condT );
   15028          // FIXME: what if we have to back up and restart this insn?
   15029          // then ITSTATE will be wrong (we'll have it as "used")
   15030          // when it isn't.  Correct is to save ITSTATE in a
   15031          // stash pseudo-reg, and back up from that if we have to
   15032          // restart.
   15033          // uncond after here
   15034          irsb->next     = mkU32( (guest_R15_curr_instr_notENC + 2) | 1 );
   15035          irsb->jumpkind = Ijk_Sys_syscall;
   15036          dres.whatNext  = Dis_StopHere;
   15037          DIP("svc #0x%08x\n", imm8);
   15038          goto decode_success;
   15039       }
   15040       /* else fall through */
   15041       break;
   15042    }
   15043 
   15044    case BITS8(0,1,0,0,0,1,0,0): {
   15045       /* ---------------- ADD(HI) Rd, Rm ---------------- */
   15046       UInt h1 = INSN0(7,7);
   15047       UInt h2 = INSN0(6,6);
   15048       UInt rM = (h2 << 3) | INSN0(5,3);
   15049       UInt rD = (h1 << 3) | INSN0(2,0);
   15050       //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive
   15051       if (rD == 15 && rM == 15) {
   15052          // then it's invalid
   15053       } else {
   15054          IRTemp res = newTemp(Ity_I32);
   15055          assign( res, binop(Iop_Add32, getIRegT(rD), getIRegT(rM) ));
   15056          if (rD != 15) {
   15057             putIRegT( rD, mkexpr(res), condT );
   15058          } else {
   15059             /* Only allowed outside or last-in IT block; SIGILL if not so. */
   15060             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15061             /* jump over insn if not selected */
   15062             mk_skip_over_T16_if_cond_is_false(condT);
   15063             condT = IRTemp_INVALID;
   15064             // now uncond
   15065             /* non-interworking branch */
   15066             irsb->next = binop(Iop_Or32, mkexpr(res), mkU32(1));
   15067             irsb->jumpkind = Ijk_Boring;
   15068             dres.whatNext = Dis_StopHere;
   15069          }
   15070          DIP("add(hi) r%u, r%u\n", rD, rM);
   15071          goto decode_success;
   15072       }
   15073       break;
   15074    }
   15075 
   15076    case BITS8(0,1,0,0,0,1,0,1): {
   15077       /* ---------------- CMP(HI) Rd, Rm ---------------- */
   15078       UInt h1 = INSN0(7,7);
   15079       UInt h2 = INSN0(6,6);
   15080       UInt rM = (h2 << 3) | INSN0(5,3);
   15081       UInt rN = (h1 << 3) | INSN0(2,0);
   15082       if (h1 != 0 || h2 != 0) {
   15083          IRTemp argL  = newTemp(Ity_I32);
   15084          IRTemp argR  = newTemp(Ity_I32);
   15085          assign( argL, getIRegT(rN) );
   15086          assign( argR, getIRegT(rM) );
   15087          /* Update flags regardless of whether in an IT block or not. */
   15088          setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   15089          DIP("cmphi r%u, r%u\n", rN, rM);
   15090          goto decode_success;
   15091       }
   15092       break;
   15093    }
   15094 
   15095    case BITS8(0,1,0,0,0,1,1,0): {
   15096       /* ---------------- MOV(HI) Rd, Rm ---------------- */
   15097       UInt h1 = INSN0(7,7);
   15098       UInt h2 = INSN0(6,6);
   15099       UInt rM = (h2 << 3) | INSN0(5,3);
   15100       UInt rD = (h1 << 3) | INSN0(2,0);
   15101       /* The old ARM ARM seems to disallow the case where both Rd and
   15102          Rm are "low" registers, but newer versions allow it. */
   15103       if (1 /*h1 != 0 || h2 != 0*/) {
   15104          IRTemp val = newTemp(Ity_I32);
   15105          assign( val, getIRegT(rM) );
   15106          if (rD != 15) {
   15107             putIRegT( rD, mkexpr(val), condT );
   15108          } else {
   15109             /* Only allowed outside or last-in IT block; SIGILL if not so. */
   15110             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15111             /* jump over insn if not selected */
   15112             mk_skip_over_T16_if_cond_is_false(condT);
   15113             condT = IRTemp_INVALID;
   15114             // now uncond
   15115             /* non-interworking branch */
   15116             irsb->next = binop(Iop_Or32, mkexpr(val), mkU32(1));
   15117             irsb->jumpkind = rM == 14 ? Ijk_Ret : Ijk_Boring;
   15118             dres.whatNext = Dis_StopHere;
   15119          }
   15120          DIP("mov r%u, r%u\n", rD, rM);
   15121          goto decode_success;
   15122       }
   15123       break;
   15124    }
   15125 
   15126    case BITS8(1,0,1,1,1,1,1,1): {
   15127       /* ---------------- IT (if-then) ---------------- */
   15128       UInt firstcond = INSN0(7,4);
   15129       UInt mask = INSN0(3,0);
   15130       UInt newITSTATE = 0;
   15131       /* This is the ITSTATE represented as described in
   15132          libvex_guest_arm.h.  It is not the ARM ARM representation. */
   15133       UChar c1 = '.';
   15134       UChar c2 = '.';
   15135       UChar c3 = '.';
   15136       Bool valid = compute_ITSTATE( &newITSTATE, &c1, &c2, &c3,
   15137                                     firstcond, mask );
   15138       if (valid && firstcond != 0xF/*NV*/) {
   15139          /* Not allowed in an IT block; SIGILL if so. */
   15140          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   15141 
   15142          IRTemp t = newTemp(Ity_I32);
   15143          assign(t, mkU32(newITSTATE));
   15144          put_ITSTATE(t);
   15145 
   15146          DIP("it%c%c%c %s\n", c1, c2, c3, nCC(firstcond));
   15147          goto decode_success;
   15148       }
   15149       break;
   15150    }
   15151 
   15152    case BITS8(1,0,1,1,0,0,0,1):
   15153    case BITS8(1,0,1,1,0,0,1,1):
   15154    case BITS8(1,0,1,1,1,0,0,1):
   15155    case BITS8(1,0,1,1,1,0,1,1): {
   15156       /* ---------------- CB{N}Z ---------------- */
   15157       UInt rN    = INSN0(2,0);
   15158       UInt bOP   = INSN0(11,11);
   15159       UInt imm32 = (INSN0(9,9) << 6) | (INSN0(7,3) << 1);
   15160       gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   15161       /* It's a conditional branch forward. */
   15162       IRTemp kond = newTemp(Ity_I1);
   15163       assign( kond, binop(bOP ? Iop_CmpNE32 : Iop_CmpEQ32,
   15164                           getIRegT(rN), mkU32(0)) );
   15165 
   15166       vassert(0 == (guest_R15_curr_instr_notENC & 1));
   15167       /* Looks like the nearest insn we can branch to is the one after
   15168          next.  That makes sense, as there's no point in being able to
   15169          encode a conditional branch to the next instruction. */
   15170       UInt dst = (guest_R15_curr_instr_notENC + 4 + imm32) | 1;
   15171       stmt(IRStmt_Exit( mkexpr(kond),
   15172                         Ijk_Boring,
   15173                         IRConst_U32(toUInt(dst)) ));
   15174       DIP("cb%s r%u, 0x%x\n", bOP ? "nz" : "z", rN, dst - 1);
   15175       goto decode_success;
   15176    }
   15177 
   15178    default:
   15179       break; /* examine the next shortest prefix */
   15180 
   15181    }
   15182 
   15183 
   15184    /* ================ 16-bit 15:9 cases ================ */
   15185 
   15186    switch (INSN0(15,9)) {
   15187 
   15188    case BITS7(1,0,1,1,0,1,0): {
   15189       /* ---------------- PUSH ---------------- */
   15190       /* This is a bit like STMxx, but way simpler. Complications we
   15191          don't have to deal with:
   15192          * SP being one of the transferred registers
   15193          * direction (increment vs decrement)
   15194          * before-vs-after-ness
   15195       */
   15196       Int  i, nRegs;
   15197       UInt bitR    = INSN0(8,8);
   15198       UInt regList = INSN0(7,0);
   15199       if (bitR) regList |= (1 << 14);
   15200 
   15201       if (regList != 0) {
   15202          /* Since we can't generate a guaranteed non-trapping IR
   15203             sequence, (1) jump over the insn if it is gated false, and
   15204             (2) back out the ITSTATE update. */
   15205          mk_skip_over_T16_if_cond_is_false(condT);
   15206          condT = IRTemp_INVALID;
   15207          put_ITSTATE(old_itstate);
   15208          // now uncond
   15209 
   15210          nRegs = 0;
   15211          for (i = 0; i < 16; i++) {
   15212             if ((regList & (1 << i)) != 0)
   15213                nRegs++;
   15214          }
   15215          vassert(nRegs >= 1 && nRegs <= 8);
   15216 
   15217          /* Move SP down first of all, so we're "covered".  And don't
   15218             mess with its alignment. */
   15219          IRTemp newSP = newTemp(Ity_I32);
   15220          assign(newSP, binop(Iop_Sub32, getIRegT(13), mkU32(4 * nRegs)));
   15221          putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
   15222 
   15223          /* Generate a transfer base address as a forced-aligned
   15224             version of the final SP value. */
   15225          IRTemp base = newTemp(Ity_I32);
   15226          assign(base, binop(Iop_And32, mkexpr(newSP), mkU32(~3)));
   15227 
   15228          /* Now the transfers */
   15229          nRegs = 0;
   15230          for (i = 0; i < 16; i++) {
   15231             if ((regList & (1 << i)) != 0) {
   15232                storeLE( binop(Iop_Add32, mkexpr(base), mkU32(4 * nRegs)),
   15233                         getIRegT(i) );
   15234                nRegs++;
   15235             }
   15236          }
   15237 
   15238          /* Reinstate the ITSTATE update. */
   15239          put_ITSTATE(new_itstate);
   15240 
   15241          DIP("push {%s0x%04x}\n", bitR ? "lr," : "", regList & 0xFF);
   15242          goto decode_success;
   15243       }
   15244       break;
   15245    }
   15246 
   15247    case BITS7(1,0,1,1,1,1,0): {
   15248       /* ---------------- POP ---------------- */
   15249       Int  i, nRegs;
   15250       UInt bitR    = INSN0(8,8);
   15251       UInt regList = INSN0(7,0);
   15252 
   15253       if (regList != 0 || bitR) {
   15254          /* Since we can't generate a guaranteed non-trapping IR
   15255             sequence, (1) jump over the insn if it is gated false, and
   15256             (2) back out the ITSTATE update. */
   15257          mk_skip_over_T16_if_cond_is_false(condT);
   15258          condT = IRTemp_INVALID;
   15259          put_ITSTATE(old_itstate);
   15260          // now uncond
   15261 
   15262          nRegs = 0;
   15263          for (i = 0; i < 8; i++) {
   15264             if ((regList & (1 << i)) != 0)
   15265                nRegs++;
   15266          }
   15267          vassert(nRegs >= 0 && nRegs <= 7);
   15268          vassert(bitR == 0 || bitR == 1);
   15269 
   15270          IRTemp oldSP = newTemp(Ity_I32);
   15271          assign(oldSP, getIRegT(13));
   15272 
   15273          /* Generate a transfer base address as a forced-aligned
   15274             version of the original SP value. */
   15275          IRTemp base = newTemp(Ity_I32);
   15276          assign(base, binop(Iop_And32, mkexpr(oldSP), mkU32(~3)));
   15277 
   15278          /* Compute a new value for SP, but don't install it yet, so
   15279             that we're "covered" until all the transfers are done.
   15280             And don't mess with its alignment. */
   15281          IRTemp newSP = newTemp(Ity_I32);
   15282          assign(newSP, binop(Iop_Add32, mkexpr(oldSP),
   15283                                         mkU32(4 * (nRegs + bitR))));
   15284 
   15285          /* Now the transfers, not including PC */
   15286          nRegs = 0;
   15287          for (i = 0; i < 8; i++) {
   15288             if ((regList & (1 << i)) != 0) {
   15289                putIRegT(i, loadLE( Ity_I32,
   15290                                    binop(Iop_Add32, mkexpr(base),
   15291                                                     mkU32(4 * nRegs))),
   15292                            IRTemp_INVALID );
   15293                nRegs++;
   15294             }
   15295          }
   15296 
   15297          IRTemp newPC = IRTemp_INVALID;
   15298          if (bitR) {
   15299             newPC = newTemp(Ity_I32);
   15300             assign( newPC, loadLE( Ity_I32,
   15301                                    binop(Iop_Add32, mkexpr(base),
   15302                                                     mkU32(4 * nRegs))));
   15303          }
   15304 
   15305          /* Now we can safely install the new SP value */
   15306          putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
   15307 
   15308          /* Reinstate the ITSTATE update. */
   15309          put_ITSTATE(new_itstate);
   15310 
   15311          /* now, do we also have to do a branch?  If so, it turns out
   15312             that the new PC value is encoded exactly as we need it to
   15313             be -- with CPSR.T in the bottom bit.  So we can simply use
   15314             it as is, no need to mess with it.  Note, therefore, this
   15315             is an interworking return. */
   15316          if (bitR) {
   15317             irsb->next     = mkexpr(newPC);
   15318             irsb->jumpkind = Ijk_Ret;
   15319             dres.whatNext  = Dis_StopHere;
   15320          }
   15321 
   15322          DIP("pop {%s0x%04x}\n", bitR ? "pc," : "", regList & 0xFF);
   15323          goto decode_success;
   15324       }
   15325       break;
   15326    }
   15327 
   15328    case BITS7(0,0,0,1,1,1,0):   /* ADDS */
   15329    case BITS7(0,0,0,1,1,1,1): { /* SUBS */
   15330       /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */
   15331       /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */
   15332       UInt   uimm3 = INSN0(8,6);
   15333       UInt   rN    = INSN0(5,3);
   15334       UInt   rD    = INSN0(2,0);
   15335       UInt   isSub = INSN0(9,9);
   15336       IRTemp argL  = newTemp(Ity_I32);
   15337       IRTemp argR  = newTemp(Ity_I32);
   15338       assign( argL, getIRegT(rN) );
   15339       assign( argR, mkU32(uimm3) );
   15340       putIRegT(rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
   15341                          mkexpr(argL), mkexpr(argR)),
   15342                    condT);
   15343       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
   15344                       argL, argR, cond_AND_notInIT_T );
   15345       DIP("%s r%u, r%u, #%u\n", isSub ? "subs" : "adds", rD, rN, uimm3);
   15346       goto decode_success;
   15347    }
   15348 
   15349    case BITS7(0,0,0,1,1,0,0):   /* ADDS */
   15350    case BITS7(0,0,0,1,1,0,1): { /* SUBS */
   15351       /* ---------------- ADDS Rd, Rn, Rm ---------------- */
   15352       /* ---------------- SUBS Rd, Rn, Rm ---------------- */
   15353       UInt   rM    = INSN0(8,6);
   15354       UInt   rN    = INSN0(5,3);
   15355       UInt   rD    = INSN0(2,0);
   15356       UInt   isSub = INSN0(9,9);
   15357       IRTemp argL  = newTemp(Ity_I32);
   15358       IRTemp argR  = newTemp(Ity_I32);
   15359       assign( argL, getIRegT(rN) );
   15360       assign( argR, getIRegT(rM) );
   15361       putIRegT( rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
   15362                           mkexpr(argL), mkexpr(argR)),
   15363                     condT );
   15364       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
   15365                       argL, argR, cond_AND_notInIT_T );
   15366       DIP("%s r%u, r%u, r%u\n", isSub ? "subs" : "adds", rD, rN, rM);
   15367       goto decode_success;
   15368    }
   15369 
   15370    case BITS7(0,1,0,1,0,0,0):   /* STR */
   15371    case BITS7(0,1,0,1,1,0,0): { /* LDR */
   15372       /* ------------- LDR Rd, [Rn, Rm] ------------- */
   15373       /* ------------- STR Rd, [Rn, Rm] ------------- */
   15374       /* LDR/STR Rd, [Rn + Rm] */
   15375       UInt    rD   = INSN0(2,0);
   15376       UInt    rN   = INSN0(5,3);
   15377       UInt    rM   = INSN0(8,6);
   15378       UInt    isLD = INSN0(11,11);
   15379 
   15380       mk_skip_over_T16_if_cond_is_false(condT);
   15381       condT = IRTemp_INVALID;
   15382       // now uncond
   15383 
   15384       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   15385       put_ITSTATE(old_itstate); // backout
   15386       if (isLD) {
   15387          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
   15388       } else {
   15389          storeLE(ea, getIRegT(rD));
   15390       }
   15391       put_ITSTATE(new_itstate); // restore
   15392 
   15393       DIP("%s r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
   15394       goto decode_success;
   15395    }
   15396 
   15397    case BITS7(0,1,0,1,0,0,1):
   15398    case BITS7(0,1,0,1,1,0,1): {
   15399       /* ------------- LDRH Rd, [Rn, Rm] ------------- */
   15400       /* ------------- STRH Rd, [Rn, Rm] ------------- */
   15401       /* LDRH/STRH Rd, [Rn + Rm] */
   15402       UInt    rD   = INSN0(2,0);
   15403       UInt    rN   = INSN0(5,3);
   15404       UInt    rM   = INSN0(8,6);
   15405       UInt    isLD = INSN0(11,11);
   15406 
   15407       mk_skip_over_T16_if_cond_is_false(condT);
   15408       condT = IRTemp_INVALID;
   15409       // now uncond
   15410 
   15411       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   15412       put_ITSTATE(old_itstate); // backout
   15413       if (isLD) {
   15414          putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
   15415                       IRTemp_INVALID);
   15416       } else {
   15417          storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
   15418       }
   15419       put_ITSTATE(new_itstate); // restore
   15420 
   15421       DIP("%sh r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
   15422       goto decode_success;
   15423    }
   15424 
   15425    case BITS7(0,1,0,1,1,1,1): {
   15426       /* ------------- LDRSH Rd, [Rn, Rm] ------------- */
   15427       /* LDRSH Rd, [Rn + Rm] */
   15428       UInt    rD = INSN0(2,0);
   15429       UInt    rN = INSN0(5,3);
   15430       UInt    rM = INSN0(8,6);
   15431 
   15432       mk_skip_over_T16_if_cond_is_false(condT);
   15433       condT = IRTemp_INVALID;
   15434       // now uncond
   15435 
   15436       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   15437       put_ITSTATE(old_itstate); // backout
   15438       putIRegT(rD, unop(Iop_16Sto32, loadLE(Ity_I16, ea)),
   15439                    IRTemp_INVALID);
   15440       put_ITSTATE(new_itstate); // restore
   15441 
   15442       DIP("ldrsh r%u, [r%u, r%u]\n", rD, rN, rM);
   15443       goto decode_success;
   15444    }
   15445 
   15446    case BITS7(0,1,0,1,0,1,1): {
   15447       /* ------------- LDRSB Rd, [Rn, Rm] ------------- */
   15448       /* LDRSB Rd, [Rn + Rm] */
   15449       UInt    rD = INSN0(2,0);
   15450       UInt    rN = INSN0(5,3);
   15451       UInt    rM = INSN0(8,6);
   15452 
   15453       mk_skip_over_T16_if_cond_is_false(condT);
   15454       condT = IRTemp_INVALID;
   15455       // now uncond
   15456 
   15457       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   15458       put_ITSTATE(old_itstate); // backout
   15459       putIRegT(rD, unop(Iop_8Sto32, loadLE(Ity_I8, ea)),
   15460                    IRTemp_INVALID);
   15461       put_ITSTATE(new_itstate); // restore
   15462 
   15463       DIP("ldrsb r%u, [r%u, r%u]\n", rD, rN, rM);
   15464       goto decode_success;
   15465    }
   15466 
   15467    case BITS7(0,1,0,1,0,1,0):
   15468    case BITS7(0,1,0,1,1,1,0): {
   15469       /* ------------- LDRB Rd, [Rn, Rm] ------------- */
   15470       /* ------------- STRB Rd, [Rn, Rm] ------------- */
   15471       /* LDRB/STRB Rd, [Rn + Rm] */
   15472       UInt    rD   = INSN0(2,0);
   15473       UInt    rN   = INSN0(5,3);
   15474       UInt    rM   = INSN0(8,6);
   15475       UInt    isLD = INSN0(11,11);
   15476 
   15477       mk_skip_over_T16_if_cond_is_false(condT);
   15478       condT = IRTemp_INVALID;
   15479       // now uncond
   15480 
   15481       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   15482       put_ITSTATE(old_itstate); // backout
   15483       if (isLD) {
   15484          putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
   15485                   IRTemp_INVALID);
   15486       } else {
   15487          storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
   15488       }
   15489       put_ITSTATE(new_itstate); // restore
   15490 
   15491       DIP("%sb r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
   15492       goto decode_success;
   15493    }
   15494 
   15495    default:
   15496       break; /* examine the next shortest prefix */
   15497 
   15498    }
   15499 
   15500 
   15501    /* ================ 16-bit 15:11 cases ================ */
   15502 
   15503    switch (INSN0(15,11)) {
   15504 
   15505    case BITS5(0,0,1,1,0):
   15506    case BITS5(0,0,1,1,1): {
   15507       /* ---------------- ADDS Rn, #uimm8 ---------------- */
   15508       /* ---------------- SUBS Rn, #uimm8 ---------------- */
   15509       UInt   isSub = INSN0(11,11);
   15510       UInt   rN    = INSN0(10,8);
   15511       UInt   uimm8 = INSN0(7,0);
   15512       IRTemp argL  = newTemp(Ity_I32);
   15513       IRTemp argR  = newTemp(Ity_I32);
   15514       assign( argL, getIRegT(rN) );
   15515       assign( argR, mkU32(uimm8) );
   15516       putIRegT( rN, binop(isSub ? Iop_Sub32 : Iop_Add32,
   15517                           mkexpr(argL), mkexpr(argR)), condT );
   15518       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
   15519                       argL, argR, cond_AND_notInIT_T );
   15520       DIP("%s r%u, #%u\n", isSub ? "subs" : "adds", rN, uimm8);
   15521       goto decode_success;
   15522    }
   15523 
   15524    case BITS5(1,0,1,0,0): {
   15525       /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */
   15526       /* a.k.a. ADR */
   15527       /* rD = align4(PC) + imm8 * 4 */
   15528       UInt rD   = INSN0(10,8);
   15529       UInt imm8 = INSN0(7,0);
   15530       putIRegT(rD, binop(Iop_Add32,
   15531                          binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   15532                          mkU32(imm8 * 4)),
   15533                    condT);
   15534       DIP("add r%u, pc, #%u\n", rD, imm8 * 4);
   15535       goto decode_success;
   15536    }
   15537 
   15538    case BITS5(1,0,1,0,1): {
   15539       /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */
   15540       UInt rD   = INSN0(10,8);
   15541       UInt imm8 = INSN0(7,0);
   15542       putIRegT(rD, binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)),
   15543                    condT);
   15544       DIP("add r%u, r13, #%u\n", rD, imm8 * 4);
   15545       goto decode_success;
   15546    }
   15547 
   15548    case BITS5(0,0,1,0,1): {
   15549       /* ---------------- CMP Rn, #uimm8 ---------------- */
   15550       UInt   rN    = INSN0(10,8);
   15551       UInt   uimm8 = INSN0(7,0);
   15552       IRTemp argL  = newTemp(Ity_I32);
   15553       IRTemp argR  = newTemp(Ity_I32);
   15554       assign( argL, getIRegT(rN) );
   15555       assign( argR, mkU32(uimm8) );
   15556       /* Update flags regardless of whether in an IT block or not. */
   15557       setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   15558       DIP("cmp r%u, #%u\n", rN, uimm8);
   15559       goto decode_success;
   15560    }
   15561 
   15562    case BITS5(0,0,1,0,0): {
   15563       /* -------------- (T1) MOVS Rn, #uimm8 -------------- */
   15564       UInt   rD    = INSN0(10,8);
   15565       UInt   uimm8 = INSN0(7,0);
   15566       IRTemp oldV  = newTemp(Ity_I32);
   15567       IRTemp oldC  = newTemp(Ity_I32);
   15568       IRTemp res   = newTemp(Ity_I32);
   15569       assign( oldV, mk_armg_calculate_flag_v() );
   15570       assign( oldC, mk_armg_calculate_flag_c() );
   15571       assign( res, mkU32(uimm8) );
   15572       putIRegT(rD, mkexpr(res), condT);
   15573       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   15574                          cond_AND_notInIT_T );
   15575       DIP("movs r%u, #%u\n", rD, uimm8);
   15576       goto decode_success;
   15577    }
   15578 
   15579    case BITS5(0,1,0,0,1): {
   15580       /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */
   15581       /* LDR Rd, [align4(PC) + imm8 * 4] */
   15582       UInt   rD   = INSN0(10,8);
   15583       UInt   imm8 = INSN0(7,0);
   15584       IRTemp ea   = newTemp(Ity_I32);
   15585 
   15586       mk_skip_over_T16_if_cond_is_false(condT);
   15587       condT = IRTemp_INVALID;
   15588       // now uncond
   15589 
   15590       assign(ea, binop(Iop_Add32,
   15591                        binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   15592                        mkU32(imm8 * 4)));
   15593       put_ITSTATE(old_itstate); // backout
   15594       putIRegT(rD, loadLE(Ity_I32, mkexpr(ea)),
   15595                    IRTemp_INVALID);
   15596       put_ITSTATE(new_itstate); // restore
   15597 
   15598       DIP("ldr r%u, [pc, #%u]\n", rD, imm8 * 4);
   15599       goto decode_success;
   15600    }
   15601 
   15602    case BITS5(0,1,1,0,0):   /* STR */
   15603    case BITS5(0,1,1,0,1): { /* LDR */
   15604       /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */
   15605       /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */
   15606       /* LDR/STR Rd, [Rn + imm5 * 4] */
   15607       UInt    rD   = INSN0(2,0);
   15608       UInt    rN   = INSN0(5,3);
   15609       UInt    imm5 = INSN0(10,6);
   15610       UInt    isLD = INSN0(11,11);
   15611 
   15612       mk_skip_over_T16_if_cond_is_false(condT);
   15613       condT = IRTemp_INVALID;
   15614       // now uncond
   15615 
   15616       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 4));
   15617       put_ITSTATE(old_itstate); // backout
   15618       if (isLD) {
   15619          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
   15620       } else {
   15621          storeLE( ea, getIRegT(rD) );
   15622       }
   15623       put_ITSTATE(new_itstate); // restore
   15624 
   15625       DIP("%s r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 4);
   15626       goto decode_success;
   15627    }
   15628 
   15629    case BITS5(1,0,0,0,0):   /* STRH */
   15630    case BITS5(1,0,0,0,1): { /* LDRH */
   15631       /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */
   15632       /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */
   15633       /* LDRH/STRH Rd, [Rn + imm5 * 2] */
   15634       UInt    rD   = INSN0(2,0);
   15635       UInt    rN   = INSN0(5,3);
   15636       UInt    imm5 = INSN0(10,6);
   15637       UInt    isLD = INSN0(11,11);
   15638 
   15639       mk_skip_over_T16_if_cond_is_false(condT);
   15640       condT = IRTemp_INVALID;
   15641       // now uncond
   15642 
   15643       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 2));
   15644       put_ITSTATE(old_itstate); // backout
   15645       if (isLD) {
   15646          putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
   15647                   IRTemp_INVALID);
   15648       } else {
   15649          storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
   15650       }
   15651       put_ITSTATE(new_itstate); // restore
   15652 
   15653       DIP("%sh r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 2);
   15654       goto decode_success;
   15655    }
   15656 
   15657    case BITS5(0,1,1,1,0):   /* STRB */
   15658    case BITS5(0,1,1,1,1): { /* LDRB */
   15659       /* ------------- LDRB Rd, [Rn, #imm5] ------------- */
   15660       /* ------------- STRB Rd, [Rn, #imm5] ------------- */
   15661       /* LDRB/STRB Rd, [Rn + imm5] */
   15662       UInt    rD   = INSN0(2,0);
   15663       UInt    rN   = INSN0(5,3);
   15664       UInt    imm5 = INSN0(10,6);
   15665       UInt    isLD = INSN0(11,11);
   15666 
   15667       mk_skip_over_T16_if_cond_is_false(condT);
   15668       condT = IRTemp_INVALID;
   15669       // now uncond
   15670 
   15671       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5));
   15672       put_ITSTATE(old_itstate); // backout
   15673       if (isLD) {
   15674          putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
   15675                   IRTemp_INVALID);
   15676       } else {
   15677          storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
   15678       }
   15679       put_ITSTATE(new_itstate); // restore
   15680 
   15681       DIP("%sb r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5);
   15682       goto decode_success;
   15683    }
   15684 
   15685    case BITS5(1,0,0,1,0):   /* STR */
   15686    case BITS5(1,0,0,1,1): { /* LDR */
   15687       /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */
   15688       /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */
   15689       /* LDR/STR Rd, [SP + imm8 * 4] */
   15690       UInt rD    = INSN0(10,8);
   15691       UInt imm8  = INSN0(7,0);
   15692       UInt isLD  = INSN0(11,11);
   15693 
   15694       mk_skip_over_T16_if_cond_is_false(condT);
   15695       condT = IRTemp_INVALID;
   15696       // now uncond
   15697 
   15698       IRExpr* ea = binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4));
   15699       put_ITSTATE(old_itstate); // backout
   15700       if (isLD) {
   15701          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
   15702       } else {
   15703          storeLE(ea, getIRegT(rD));
   15704       }
   15705       put_ITSTATE(new_itstate); // restore
   15706 
   15707       DIP("%s r%u, [sp, #%u]\n", isLD ? "ldr" : "str", rD, imm8 * 4);
   15708       goto decode_success;
   15709    }
   15710 
   15711    case BITS5(1,1,0,0,1): {
   15712       /* ------------- LDMIA Rn!, {reglist} ------------- */
   15713       Int i, nRegs = 0;
   15714       UInt rN   = INSN0(10,8);
   15715       UInt list = INSN0(7,0);
   15716       /* Empty lists aren't allowed. */
   15717       if (list != 0) {
   15718          mk_skip_over_T16_if_cond_is_false(condT);
   15719          condT = IRTemp_INVALID;
   15720          put_ITSTATE(old_itstate);
   15721          // now uncond
   15722 
   15723          IRTemp oldRn = newTemp(Ity_I32);
   15724          IRTemp base  = newTemp(Ity_I32);
   15725          assign(oldRn, getIRegT(rN));
   15726          assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
   15727          for (i = 0; i < 8; i++) {
   15728             if (0 == (list & (1 << i)))
   15729                continue;
   15730             nRegs++;
   15731             putIRegT(
   15732                i, loadLE(Ity_I32,
   15733                          binop(Iop_Add32, mkexpr(base),
   15734                                           mkU32(nRegs * 4 - 4))),
   15735                IRTemp_INVALID
   15736             );
   15737          }
   15738          /* Only do the writeback for rN if it isn't in the list of
   15739             registers to be transferred. */
   15740          if (0 == (list & (1 << rN))) {
   15741             putIRegT(rN,
   15742                      binop(Iop_Add32, mkexpr(oldRn),
   15743                                       mkU32(nRegs * 4)),
   15744                      IRTemp_INVALID
   15745             );
   15746          }
   15747 
   15748          /* Reinstate the ITSTATE update. */
   15749          put_ITSTATE(new_itstate);
   15750 
   15751          DIP("ldmia r%u!, {0x%04x}\n", rN, list);
   15752          goto decode_success;
   15753       }
   15754       break;
   15755    }
   15756 
   15757    case BITS5(1,1,0,0,0): {
   15758       /* ------------- STMIA Rn!, {reglist} ------------- */
   15759       Int i, nRegs = 0;
   15760       UInt rN   = INSN0(10,8);
   15761       UInt list = INSN0(7,0);
   15762       /* Empty lists aren't allowed.  Also, if rN is in the list then
   15763          it must be the lowest numbered register in the list. */
   15764       Bool valid = list != 0;
   15765       if (valid && 0 != (list & (1 << rN))) {
   15766          for (i = 0; i < rN; i++) {
   15767             if (0 != (list & (1 << i)))
   15768                valid = False;
   15769          }
   15770       }
   15771       if (valid) {
   15772          mk_skip_over_T16_if_cond_is_false(condT);
   15773          condT = IRTemp_INVALID;
   15774          put_ITSTATE(old_itstate);
   15775          // now uncond
   15776 
   15777          IRTemp oldRn = newTemp(Ity_I32);
   15778          IRTemp base = newTemp(Ity_I32);
   15779          assign(oldRn, getIRegT(rN));
   15780          assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
   15781          for (i = 0; i < 8; i++) {
   15782             if (0 == (list & (1 << i)))
   15783                continue;
   15784             nRegs++;
   15785             storeLE( binop(Iop_Add32, mkexpr(base), mkU32(nRegs * 4 - 4)),
   15786                      getIRegT(i) );
   15787          }
   15788          /* Always do the writeback. */
   15789          putIRegT(rN,
   15790                   binop(Iop_Add32, mkexpr(oldRn),
   15791                                    mkU32(nRegs * 4)),
   15792                   IRTemp_INVALID);
   15793 
   15794          /* Reinstate the ITSTATE update. */
   15795          put_ITSTATE(new_itstate);
   15796 
   15797          DIP("stmia r%u!, {0x%04x}\n", rN, list);
   15798          goto decode_success;
   15799       }
   15800       break;
   15801    }
   15802 
   15803    case BITS5(0,0,0,0,0):   /* LSLS */
   15804    case BITS5(0,0,0,0,1):   /* LSRS */
   15805    case BITS5(0,0,0,1,0): { /* ASRS */
   15806       /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */
   15807       /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */
   15808       /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */
   15809       UInt   rD   = INSN0(2,0);
   15810       UInt   rM   = INSN0(5,3);
   15811       UInt   imm5 = INSN0(10,6);
   15812       IRTemp res  = newTemp(Ity_I32);
   15813       IRTemp resC = newTemp(Ity_I32);
   15814       IRTemp rMt  = newTemp(Ity_I32);
   15815       IRTemp oldV = newTemp(Ity_I32);
   15816       HChar* wot  = "???";
   15817       assign(rMt, getIRegT(rM));
   15818       assign(oldV, mk_armg_calculate_flag_v());
   15819       /* Looks like INSN0(12,11) are the standard 'how' encoding.
   15820          Could compactify if the ROR case later appears. */
   15821       switch (INSN0(15,11)) {
   15822          case BITS5(0,0,0,0,0):
   15823             compute_result_and_C_after_LSL_by_imm5(
   15824                dis_buf, &res, &resC, rMt, imm5, rM
   15825             );
   15826             wot = "lsl";
   15827             break;
   15828          case BITS5(0,0,0,0,1):
   15829             compute_result_and_C_after_LSR_by_imm5(
   15830                dis_buf, &res, &resC, rMt, imm5, rM
   15831             );
   15832             wot = "lsr";
   15833             break;
   15834          case BITS5(0,0,0,1,0):
   15835             compute_result_and_C_after_ASR_by_imm5(
   15836                dis_buf, &res, &resC, rMt, imm5, rM
   15837             );
   15838             wot = "asr";
   15839             break;
   15840          default:
   15841             /*NOTREACHED*/vassert(0);
   15842       }
   15843       // not safe to read guest state after this point
   15844       putIRegT(rD, mkexpr(res), condT);
   15845       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
   15846                          cond_AND_notInIT_T );
   15847       /* ignore buf and roll our own output */
   15848       DIP("%ss r%u, r%u, #%u\n", wot, rD, rM, imm5);
   15849       goto decode_success;
   15850    }
   15851 
   15852    case BITS5(1,1,1,0,0): {
   15853       /* ---------------- B #simm11 ---------------- */
   15854       Int  simm11 = INSN0(10,0);
   15855            simm11 = (simm11 << 21) >> 20;
   15856       UInt dst    = simm11 + guest_R15_curr_instr_notENC + 4;
   15857       /* Only allowed outside or last-in IT block; SIGILL if not so. */
   15858       gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15859       // and skip this insn if not selected; being cleverer is too
   15860       // difficult
   15861       mk_skip_over_T16_if_cond_is_false(condT);
   15862       condT = IRTemp_INVALID;
   15863       // now uncond
   15864       irsb->next     = mkU32( dst | 1 /*CPSR.T*/ );
   15865       irsb->jumpkind = Ijk_Boring;
   15866       dres.whatNext  = Dis_StopHere;
   15867       DIP("b 0x%x\n", dst);
   15868       goto decode_success;
   15869    }
   15870 
   15871    default:
   15872       break; /* examine the next shortest prefix */
   15873 
   15874    }
   15875 
   15876 
   15877    /* ================ 16-bit 15:12 cases ================ */
   15878 
   15879    switch (INSN0(15,12)) {
   15880 
   15881    case BITS4(1,1,0,1): {
   15882       /* ---------------- Bcond #simm8 ---------------- */
   15883       UInt cond  = INSN0(11,8);
   15884       Int  simm8 = INSN0(7,0);
   15885            simm8 = (simm8 << 24) >> 23;
   15886       UInt dst   = simm8 + guest_R15_curr_instr_notENC + 4;
   15887       if (cond != ARMCondAL && cond != ARMCondNV) {
   15888          /* Not allowed in an IT block; SIGILL if so. */
   15889          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   15890 
   15891          IRTemp kondT = newTemp(Ity_I32);
   15892          assign( kondT, mk_armg_calculate_condition(cond) );
   15893          stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
   15894                             Ijk_Boring,
   15895                             IRConst_U32(dst | 1/*CPSR.T*/) ));
   15896          irsb->next = mkU32( (guest_R15_curr_instr_notENC + 2)
   15897                              | 1 /*CPSR.T*/ );
   15898          irsb->jumpkind = Ijk_Boring;
   15899          dres.whatNext  = Dis_StopHere;
   15900          DIP("b%s 0x%x\n", nCC(cond), dst);
   15901          goto decode_success;
   15902       }
   15903       break;
   15904    }
   15905 
   15906    default:
   15907       break; /* hmm, nothing matched */
   15908 
   15909    }
   15910 
   15911    /* ================ 16-bit misc cases ================ */
   15912 
   15913    /* ------ NOP ------ */
   15914    if (INSN0(15,0) == 0xBF00) {
   15915       DIP("nop");
   15916       goto decode_success;
   15917    }
   15918 
   15919    /* ----------------------------------------------------------- */
   15920    /* --                                                       -- */
   15921    /* -- Thumb 32-bit integer instructions                     -- */
   15922    /* --                                                       -- */
   15923    /* ----------------------------------------------------------- */
   15924 
   15925 #  define INSN1(_bMax,_bMin)  SLICE_UInt(((UInt)insn1), (_bMax), (_bMin))
   15926 
   15927    /* second 16 bits of the instruction, if any */
   15928    UShort insn1 = getUShortLittleEndianly( guest_instr+2 );
   15929 
   15930    anOp   = Iop_INVALID; /* paranoia */
   15931    anOpNm = NULL;        /* paranoia */
   15932 
   15933    /* Change result defaults to suit 32-bit insns. */
   15934    vassert(dres.whatNext   == Dis_Continue);
   15935    vassert(dres.len        == 2);
   15936    vassert(dres.continueAt == 0);
   15937    dres.len = 4;
   15938 
   15939    /* ------------------- (T1) SMMUL{R} ------------------ */
   15940    if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,1,0)
   15941        && INSN0(6,4) == BITS3(1,0,1)
   15942        && INSN1(15,12) == BITS4(1,1,1,1)
   15943        && INSN1(7,5) == BITS3(0,0,0)) {
   15944       UInt bitR = INSN1(4,4);
   15945       UInt rD = INSN1(11,8);
   15946       UInt rM = INSN1(3,0);
   15947       UInt rN = INSN0(3,0);
   15948       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   15949         IRExpr* res = newTemp(Ity_I32);
   15950         assign(res, unop(Iop_64HIto32,
   15951                 binop(Iop_Add64,
   15952                       binop(Iop_MullS32, getIRegT(rN), getIRegT(rM)),
   15953                     mkU64(bitR ? 0x80000000ULL : 0ULL))));
   15954          putIRegT(rD, mkexpr(res), condT);
   15955          DIP("smmul%s r%u, r%u, r%u\n",
   15956              bitR ? "r" : "", rD, rN, rM);
   15957          goto decode_success;
   15958       }
   15959    }
   15960 
   15961 
   15962    /* ---------------- BL/BLX simm26 ---------------- */
   15963    if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) {
   15964       UInt isBL = INSN1(12,12);
   15965       UInt bS   = INSN0(10,10);
   15966       UInt bJ1  = INSN1(13,13);
   15967       UInt bJ2  = INSN1(11,11);
   15968       UInt bI1  = 1 ^ (bJ1 ^ bS);
   15969       UInt bI2  = 1 ^ (bJ2 ^ bS);
   15970       Int simm25
   15971          =   (bS          << (1 + 1 + 10 + 11 + 1))
   15972            | (bI1         << (1 + 10 + 11 + 1))
   15973            | (bI2         << (10 + 11 + 1))
   15974            | (INSN0(9,0)  << (11 + 1))
   15975            | (INSN1(10,0) << 1);
   15976       simm25 = (simm25 << 7) >> 7;
   15977 
   15978       vassert(0 == (guest_R15_curr_instr_notENC & 1));
   15979       UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
   15980 
   15981       /* One further validity case to check: in the case of BLX
   15982          (not-BL), that insn1[0] must be zero. */
   15983       Bool valid = True;
   15984       if (isBL == 0 && INSN1(0,0) == 1) valid = False;
   15985       if (valid) {
   15986          /* Only allowed outside or last-in IT block; SIGILL if not so. */
   15987          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15988          // and skip this insn if not selected; being cleverer is too
   15989          // difficult
   15990          mk_skip_over_T32_if_cond_is_false(condT);
   15991          condT = IRTemp_INVALID;
   15992          // now uncond
   15993 
   15994          /* We're returning to Thumb code, hence "| 1" */
   15995          putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 4) | 1 ),
   15996                    IRTemp_INVALID);
   15997          if (isBL) {
   15998             /* BL: unconditional T -> T call */
   15999             /* we're calling Thumb code, hence "| 1" */
   16000             irsb->next = mkU32( dst | 1 );
   16001             DIP("bl 0x%x (stay in Thumb mode)\n", dst);
   16002          } else {
   16003             /* BLX: unconditional T -> A call */
   16004             /* we're calling ARM code, hence "& 3" to align to a
   16005                valid ARM insn address */
   16006             irsb->next = mkU32( dst & ~3 );
   16007             DIP("blx 0x%x (switch to ARM mode)\n", dst & ~3);
   16008          }
   16009          irsb->jumpkind = Ijk_Call;
   16010          dres.whatNext = Dis_StopHere;
   16011          goto decode_success;
   16012       }
   16013    }
   16014 
   16015    /* ---------------- {LD,ST}M{IA,DB} ---------------- */
   16016    if (0x3a2 == INSN0(15,6) // {LD,ST}MIA
   16017        || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB
   16018       UInt bW      = INSN0(5,5); /* writeback Rn ? */
   16019       UInt bL      = INSN0(4,4);
   16020       UInt rN      = INSN0(3,0);
   16021       UInt bP      = INSN1(15,15); /* reglist entry for r15 */
   16022       UInt bM      = INSN1(14,14); /* reglist entry for r14 */
   16023       UInt rLmost  = INSN1(12,0);  /* reglist entry for r0 .. 12 */
   16024       UInt rL13    = INSN1(13,13); /* must be zero */
   16025       UInt regList = 0;
   16026       Bool valid   = True;
   16027 
   16028       UInt bINC    = 1;
   16029       UInt bBEFORE = 0;
   16030       if (INSN0(15,6) == 0x3a4) {
   16031          bINC    = 0;
   16032          bBEFORE = 1;
   16033       }
   16034 
   16035       /* detect statically invalid cases, and construct the final
   16036          reglist */
   16037       if (rL13 == 1)
   16038          valid = False;
   16039 
   16040       if (bL == 1) {
   16041          regList = (bP << 15) | (bM << 14) | rLmost;
   16042          if (rN == 15)                       valid = False;
   16043          if (popcount32(regList) < 2)        valid = False;
   16044          if (bP == 1 && bM == 1)             valid = False;
   16045          if (bW == 1 && (regList & (1<<rN))) valid = False;
   16046       } else {
   16047          regList = (bM << 14) | rLmost;
   16048          if (bP == 1)                        valid = False;
   16049          if (rN == 15)                       valid = False;
   16050          if (popcount32(regList) < 2)        valid = False;
   16051          if (bW == 1 && (regList & (1<<rN))) valid = False;
   16052          if (regList & (1<<rN)) {
   16053             UInt i;
   16054             /* if Rn is in the list, then it must be the
   16055                lowest numbered entry */
   16056             for (i = 0; i < rN; i++) {
   16057                if (regList & (1<<i))
   16058                   valid = False;
   16059             }
   16060          }
   16061       }
   16062 
   16063       if (valid) {
   16064          if (bL == 1 && bP == 1) {
   16065             // We'll be writing the PC.  Hence:
   16066             /* Only allowed outside or last-in IT block; SIGILL if not so. */
   16067             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   16068          }
   16069 
   16070          /* Go uncond: */
   16071          mk_skip_over_T32_if_cond_is_false(condT);
   16072          condT = IRTemp_INVALID;
   16073          // now uncond
   16074 
   16075          /* Generate the IR.  This might generate a write to R15, */
   16076          mk_ldm_stm(False/*!arm*/, rN, bINC, bBEFORE, bW, bL, regList);
   16077 
   16078          if (bL == 1 && (regList & (1<<15))) {
   16079             // If we wrote to R15, we have an interworking return to
   16080             // deal with.
   16081             irsb->next     = llGetIReg(15);
   16082             irsb->jumpkind = Ijk_Ret;
   16083             dres.whatNext  = Dis_StopHere;
   16084          }
   16085 
   16086          DIP("%sm%c%c r%u%s, {0x%04x}\n",
   16087               bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
   16088               rN, bW ? "!" : "", regList);
   16089 
   16090          goto decode_success;
   16091       }
   16092    }
   16093 
   16094    /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */
   16095    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16096        && INSN0(9,5) == BITS5(0,1,0,0,0)
   16097        && INSN1(15,15) == 0) {
   16098       UInt bS = INSN0(4,4);
   16099       UInt rN = INSN0(3,0);
   16100       UInt rD = INSN1(11,8);
   16101       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16102       /* but allow "add.w reg, sp, #constT" */
   16103       if (!valid && rN == 13 && rD != 15)
   16104          valid = True;
   16105       if (valid) {
   16106          IRTemp argL  = newTemp(Ity_I32);
   16107          IRTemp argR  = newTemp(Ity_I32);
   16108          IRTemp res   = newTemp(Ity_I32);
   16109          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16110          assign(argL, getIRegT(rN));
   16111          assign(argR, mkU32(imm32));
   16112          assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
   16113          putIRegT(rD, mkexpr(res), condT);
   16114          if (bS == 1)
   16115             setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
   16116          DIP("add%s.w r%u, r%u, #%u\n",
   16117              bS == 1 ? "s" : "", rD, rN, imm32);
   16118          goto decode_success;
   16119       }
   16120    }
   16121 
   16122    /* ---------------- (T4) ADDW Rd, Rn, #uimm12 -------------- */
   16123    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16124        && INSN0(9,4) == BITS6(1,0,0,0,0,0)
   16125        && INSN1(15,15) == 0) {
   16126       UInt rN = INSN0(3,0);
   16127       UInt rD = INSN1(11,8);
   16128       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16129       /* but allow "addw sp, sp, #uimm12" */
   16130       if (!valid && rD == 13 && rN == 13)
   16131          valid = True;
   16132       if (valid) {
   16133          IRTemp argL = newTemp(Ity_I32);
   16134          IRTemp argR = newTemp(Ity_I32);
   16135          IRTemp res  = newTemp(Ity_I32);
   16136          UInt imm12  = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
   16137          assign(argL, getIRegT(rN));
   16138          assign(argR, mkU32(imm12));
   16139          assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
   16140          putIRegT(rD, mkexpr(res), condT);
   16141          DIP("addw r%u, r%u, #%u\n", rD, rN, imm12);
   16142          goto decode_success;
   16143       }
   16144    }
   16145 
   16146    /* ---------------- (T2) CMP.W Rn, #constT ---------------- */
   16147    /* ---------------- (T2) CMN.W Rn, #constT ---------------- */
   16148    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16149        && (   INSN0(9,4) == BITS6(0,1,1,0,1,1)  // CMP
   16150            || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN
   16151        && INSN1(15,15) == 0
   16152        && INSN1(11,8) == BITS4(1,1,1,1)) {
   16153       UInt rN = INSN0(3,0);
   16154       if (rN != 15) {
   16155          IRTemp argL  = newTemp(Ity_I32);
   16156          IRTemp argR  = newTemp(Ity_I32);
   16157          Bool   isCMN = INSN0(9,4) == BITS6(0,1,0,0,0,1);
   16158          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16159          assign(argL, getIRegT(rN));
   16160          assign(argR, mkU32(imm32));
   16161          setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   16162                          argL, argR, condT );
   16163          DIP("%s.w r%u, #%u\n", isCMN ? "cmn" : "cmp", rN, imm32);
   16164          goto decode_success;
   16165       }
   16166    }
   16167 
   16168    /* -------------- (T1) TST.W Rn, #constT -------------- */
   16169    /* -------------- (T1) TEQ.W Rn, #constT -------------- */
   16170    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16171        && (   INSN0(9,4) == BITS6(0,0,0,0,0,1)  // TST
   16172            || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ
   16173        && INSN1(15,15) == 0
   16174        && INSN1(11,8) == BITS4(1,1,1,1)) {
   16175       UInt rN = INSN0(3,0);
   16176       if (!isBadRegT(rN)) { // yes, really, it's inconsistent with CMP.W
   16177          Bool  isTST  = INSN0(9,4) == BITS6(0,0,0,0,0,1);
   16178          IRTemp argL  = newTemp(Ity_I32);
   16179          IRTemp argR  = newTemp(Ity_I32);
   16180          IRTemp res   = newTemp(Ity_I32);
   16181          IRTemp oldV  = newTemp(Ity_I32);
   16182          IRTemp oldC  = newTemp(Ity_I32);
   16183          Bool   updC  = False;
   16184          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
   16185          assign(argL, getIRegT(rN));
   16186          assign(argR, mkU32(imm32));
   16187          assign(res,  binop(isTST ? Iop_And32 : Iop_Xor32,
   16188                             mkexpr(argL), mkexpr(argR)));
   16189          assign( oldV, mk_armg_calculate_flag_v() );
   16190          assign( oldC, updC
   16191                        ? mkU32((imm32 >> 31) & 1)
   16192                        : mk_armg_calculate_flag_c() );
   16193          setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
   16194          DIP("%s.w r%u, #%u\n", isTST ? "tst" : "teq", rN, imm32);
   16195          goto decode_success;
   16196       }
   16197    }
   16198 
   16199    /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */
   16200    /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */
   16201    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16202        && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB
   16203            || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB
   16204        && INSN1(15,15) == 0) {
   16205       Bool isRSB = INSN0(9,5) == BITS5(0,1,1,1,0);
   16206       UInt bS    = INSN0(4,4);
   16207       UInt rN    = INSN0(3,0);
   16208       UInt rD    = INSN1(11,8);
   16209       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16210       /* but allow "sub{s}.w reg, sp, #constT
   16211          this is (T2) of "SUB (SP minus immediate)" */
   16212       if (!valid && !isRSB && rN == 13 && rD != 15)
   16213          valid = True;
   16214       if (valid) {
   16215          IRTemp argL  = newTemp(Ity_I32);
   16216          IRTemp argR  = newTemp(Ity_I32);
   16217          IRTemp res   = newTemp(Ity_I32);
   16218          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16219          assign(argL, getIRegT(rN));
   16220          assign(argR, mkU32(imm32));
   16221          assign(res,  isRSB
   16222                       ? binop(Iop_Sub32, mkexpr(argR), mkexpr(argL))
   16223                       : binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
   16224          putIRegT(rD, mkexpr(res), condT);
   16225          if (bS == 1) {
   16226             if (isRSB)
   16227                setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
   16228             else
   16229                setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   16230          }
   16231          DIP("%s%s.w r%u, r%u, #%u\n",
   16232              isRSB ? "rsb" : "sub", bS == 1 ? "s" : "", rD, rN, imm32);
   16233          goto decode_success;
   16234       }
   16235    }
   16236 
   16237    /* -------------- (T4) SUBW Rd, Rn, #uimm12 ------------------- */
   16238    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16239        && INSN0(9,4) == BITS6(1,0,1,0,1,0)
   16240        && INSN1(15,15) == 0) {
   16241       UInt rN = INSN0(3,0);
   16242       UInt rD = INSN1(11,8);
   16243       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16244       /* but allow "subw sp, sp, #uimm12" */
   16245       if (!valid && rD == 13 && rN == 13)
   16246          valid = True;
   16247       if (valid) {
   16248          IRTemp argL  = newTemp(Ity_I32);
   16249          IRTemp argR  = newTemp(Ity_I32);
   16250          IRTemp res   = newTemp(Ity_I32);
   16251          UInt imm12   = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
   16252          assign(argL, getIRegT(rN));
   16253          assign(argR, mkU32(imm12));
   16254          assign(res,  binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
   16255          putIRegT(rD, mkexpr(res), condT);
   16256          DIP("subw r%u, r%u, #%u\n", rD, rN, imm12);
   16257          goto decode_success;
   16258       }
   16259    }
   16260 
   16261    /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */
   16262    /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */
   16263    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16264        && (   INSN0(9,5) == BITS5(0,1,0,1,0)  // ADC
   16265            || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC
   16266        && INSN1(15,15) == 0) {
   16267       /* ADC:  Rd = Rn + constT + oldC */
   16268       /* SBC:  Rd = Rn - constT - (oldC ^ 1) */
   16269       UInt bS    = INSN0(4,4);
   16270       UInt rN    = INSN0(3,0);
   16271       UInt rD    = INSN1(11,8);
   16272       if (!isBadRegT(rN) && !isBadRegT(rD)) {
   16273          IRTemp argL  = newTemp(Ity_I32);
   16274          IRTemp argR  = newTemp(Ity_I32);
   16275          IRTemp res   = newTemp(Ity_I32);
   16276          IRTemp oldC  = newTemp(Ity_I32);
   16277          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16278          assign(argL, getIRegT(rN));
   16279          assign(argR, mkU32(imm32));
   16280          assign(oldC, mk_armg_calculate_flag_c() );
   16281          HChar* nm  = "???";
   16282          switch (INSN0(9,5)) {
   16283             case BITS5(0,1,0,1,0): // ADC
   16284                nm = "adc";
   16285                assign(res,
   16286                       binop(Iop_Add32,
   16287                             binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
   16288                             mkexpr(oldC) ));
   16289                putIRegT(rD, mkexpr(res), condT);
   16290                if (bS)
   16291                   setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
   16292                                      argL, argR, oldC, condT );
   16293                break;
   16294             case BITS5(0,1,0,1,1): // SBC
   16295                nm = "sbc";
   16296                assign(res,
   16297                       binop(Iop_Sub32,
   16298                             binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
   16299                             binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   16300                putIRegT(rD, mkexpr(res), condT);
   16301                if (bS)
   16302                   setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   16303                                      argL, argR, oldC, condT );
   16304                break;
   16305             default:
   16306               vassert(0);
   16307          }
   16308          DIP("%s%s.w r%u, r%u, #%u\n",
   16309              nm, bS == 1 ? "s" : "", rD, rN, imm32);
   16310          goto decode_success;
   16311       }
   16312    }
   16313 
   16314    /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */
   16315    /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */
   16316    /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */
   16317    /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */
   16318    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16319        && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // ORR
   16320            || INSN0(9,5) == BITS5(0,0,0,0,0)  // AND
   16321            || INSN0(9,5) == BITS5(0,0,0,0,1)  // BIC
   16322            || INSN0(9,5) == BITS5(0,0,1,0,0)  // EOR
   16323            || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN
   16324        && INSN1(15,15) == 0) {
   16325       UInt bS = INSN0(4,4);
   16326       UInt rN = INSN0(3,0);
   16327       UInt rD = INSN1(11,8);
   16328       if (!isBadRegT(rN) && !isBadRegT(rD)) {
   16329          Bool   notArgR = False;
   16330          IROp   op      = Iop_INVALID;
   16331          HChar* nm      = "???";
   16332          switch (INSN0(9,5)) {
   16333             case BITS5(0,0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
   16334             case BITS5(0,0,0,0,0): op = Iop_And32; nm = "and"; break;
   16335             case BITS5(0,0,0,0,1): op = Iop_And32; nm = "bic";
   16336                                    notArgR = True; break;
   16337             case BITS5(0,0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
   16338             case BITS5(0,0,0,1,1): op = Iop_Or32;  nm = "orn";
   16339                                    notArgR = True; break;
   16340             default: vassert(0);
   16341          }
   16342          IRTemp argL  = newTemp(Ity_I32);
   16343          IRTemp argR  = newTemp(Ity_I32);
   16344          IRTemp res   = newTemp(Ity_I32);
   16345          Bool   updC  = False;
   16346          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
   16347          assign(argL, getIRegT(rN));
   16348          assign(argR, mkU32(notArgR ? ~imm32 : imm32));
   16349          assign(res,  binop(op, mkexpr(argL), mkexpr(argR)));
   16350          putIRegT(rD, mkexpr(res), condT);
   16351          if (bS) {
   16352             IRTemp oldV = newTemp(Ity_I32);
   16353             IRTemp oldC = newTemp(Ity_I32);
   16354             assign( oldV, mk_armg_calculate_flag_v() );
   16355             assign( oldC, updC
   16356                           ? mkU32((imm32 >> 31) & 1)
   16357                           : mk_armg_calculate_flag_c() );
   16358             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16359                                condT );
   16360          }
   16361          DIP("%s%s.w r%u, r%u, #%u\n",
   16362              nm, bS == 1 ? "s" : "", rD, rN, imm32);
   16363          goto decode_success;
   16364       }
   16365    }
   16366 
   16367    /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */
   16368    /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */
   16369    /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */
   16370    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16371        && (   INSN0(8,5) == BITS4(1,0,0,0)  // add subopc
   16372            || INSN0(8,5) == BITS4(1,1,0,1)  // sub subopc
   16373            || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc
   16374        && INSN1(15,15) == 0) {
   16375       UInt rN   = INSN0(3,0);
   16376       UInt rD   = INSN1(11,8);
   16377       UInt rM   = INSN1(3,0);
   16378       UInt bS   = INSN0(4,4);
   16379       UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   16380       UInt how  = INSN1(5,4);
   16381 
   16382       Bool valid = !isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM);
   16383       /* but allow "add.w reg, sp, reg   w/ no shift
   16384          (T3) "ADD (SP plus register) */
   16385       if (!valid && INSN0(8,5) == BITS4(1,0,0,0) // add
   16386           && rD != 15 && rN == 13 && imm5 == 0 && how == 0) {
   16387          valid = True;
   16388       }
   16389       /* also allow "sub.w reg, sp, reg   w/ no shift
   16390          (T1) "SUB (SP minus register) */
   16391       if (!valid && INSN0(8,5) == BITS4(1,1,0,1) // sub
   16392           && rD != 15 && rN == 13 && imm5 == 0 && how == 0) {
   16393          valid = True;
   16394       }
   16395       if (valid) {
   16396          Bool   swap = False;
   16397          IROp   op   = Iop_INVALID;
   16398          HChar* nm   = "???";
   16399          switch (INSN0(8,5)) {
   16400             case BITS4(1,0,0,0): op = Iop_Add32; nm = "add"; break;
   16401             case BITS4(1,1,0,1): op = Iop_Sub32; nm = "sub"; break;
   16402             case BITS4(1,1,1,0): op = Iop_Sub32; nm = "rsb";
   16403                                  swap = True; break;
   16404             default: vassert(0);
   16405          }
   16406 
   16407          IRTemp argL = newTemp(Ity_I32);
   16408          assign(argL, getIRegT(rN));
   16409 
   16410          IRTemp rMt = newTemp(Ity_I32);
   16411          assign(rMt, getIRegT(rM));
   16412 
   16413          IRTemp argR = newTemp(Ity_I32);
   16414          compute_result_and_C_after_shift_by_imm5(
   16415             dis_buf, &argR, NULL, rMt, how, imm5, rM
   16416          );
   16417 
   16418          IRTemp res = newTemp(Ity_I32);
   16419          assign(res, swap
   16420                      ? binop(op, mkexpr(argR), mkexpr(argL))
   16421                      : binop(op, mkexpr(argL), mkexpr(argR)));
   16422 
   16423          putIRegT(rD, mkexpr(res), condT);
   16424          if (bS) {
   16425             switch (op) {
   16426                case Iop_Add32:
   16427                   setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
   16428                   break;
   16429                case Iop_Sub32:
   16430                   if (swap)
   16431                      setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
   16432                   else
   16433                      setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   16434                   break;
   16435                default:
   16436                   vassert(0);
   16437             }
   16438          }
   16439 
   16440          DIP("%s%s.w r%u, r%u, %s\n",
   16441              nm, bS ? "s" : "", rD, rN, dis_buf);
   16442          goto decode_success;
   16443       }
   16444    }
   16445 
   16446    /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */
   16447    /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */
   16448    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16449        && (   INSN0(8,5) == BITS4(1,0,1,0)   // adc subopc
   16450            || INSN0(8,5) == BITS4(1,0,1,1))  // sbc subopc
   16451        && INSN1(15,15) == 0) {
   16452       /* ADC:  Rd = Rn + shifter_operand + oldC */
   16453       /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
   16454       UInt rN = INSN0(3,0);
   16455       UInt rD = INSN1(11,8);
   16456       UInt rM = INSN1(3,0);
   16457       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   16458          UInt bS   = INSN0(4,4);
   16459          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   16460          UInt how  = INSN1(5,4);
   16461 
   16462          IRTemp argL = newTemp(Ity_I32);
   16463          assign(argL, getIRegT(rN));
   16464 
   16465          IRTemp rMt = newTemp(Ity_I32);
   16466          assign(rMt, getIRegT(rM));
   16467 
   16468          IRTemp oldC = newTemp(Ity_I32);
   16469          assign(oldC, mk_armg_calculate_flag_c());
   16470 
   16471          IRTemp argR = newTemp(Ity_I32);
   16472          compute_result_and_C_after_shift_by_imm5(
   16473             dis_buf, &argR, NULL, rMt, how, imm5, rM
   16474          );
   16475 
   16476          HChar* nm  = "???";
   16477          IRTemp res = newTemp(Ity_I32);
   16478          switch (INSN0(8,5)) {
   16479             case BITS4(1,0,1,0): // ADC
   16480                nm = "adc";
   16481                assign(res,
   16482                       binop(Iop_Add32,
   16483                             binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
   16484                             mkexpr(oldC) ));
   16485                putIRegT(rD, mkexpr(res), condT);
   16486                if (bS)
   16487                   setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
   16488                                      argL, argR, oldC, condT );
   16489                break;
   16490             case BITS4(1,0,1,1): // SBC
   16491                nm = "sbc";
   16492                assign(res,
   16493                       binop(Iop_Sub32,
   16494                             binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
   16495                             binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   16496                putIRegT(rD, mkexpr(res), condT);
   16497                if (bS)
   16498                   setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   16499                                      argL, argR, oldC, condT );
   16500                break;
   16501             default:
   16502                vassert(0);
   16503          }
   16504 
   16505          DIP("%s%s.w r%u, r%u, %s\n",
   16506              nm, bS ? "s" : "", rD, rN, dis_buf);
   16507          goto decode_success;
   16508       }
   16509    }
   16510 
   16511    /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */
   16512    /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */
   16513    /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */
   16514    /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */
   16515    /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */
   16516    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16517        && (   INSN0(8,5) == BITS4(0,0,0,0)  // and subopc
   16518            || INSN0(8,5) == BITS4(0,0,1,0)  // orr subopc
   16519            || INSN0(8,5) == BITS4(0,1,0,0)  // eor subopc
   16520            || INSN0(8,5) == BITS4(0,0,0,1)  // bic subopc
   16521            || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc
   16522        && INSN1(15,15) == 0) {
   16523       UInt rN = INSN0(3,0);
   16524       UInt rD = INSN1(11,8);
   16525       UInt rM = INSN1(3,0);
   16526       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   16527          Bool notArgR = False;
   16528          IROp op      = Iop_INVALID;
   16529          HChar* nm  = "???";
   16530          switch (INSN0(8,5)) {
   16531             case BITS4(0,0,0,0): op = Iop_And32; nm = "and"; break;
   16532             case BITS4(0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
   16533             case BITS4(0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
   16534             case BITS4(0,0,0,1): op = Iop_And32; nm = "bic";
   16535                                  notArgR = True; break;
   16536             case BITS4(0,0,1,1): op = Iop_Or32; nm = "orn";
   16537                                  notArgR = True; break;
   16538             default: vassert(0);
   16539          }
   16540          UInt bS   = INSN0(4,4);
   16541          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   16542          UInt how  = INSN1(5,4);
   16543 
   16544          IRTemp rNt = newTemp(Ity_I32);
   16545          assign(rNt, getIRegT(rN));
   16546 
   16547          IRTemp rMt = newTemp(Ity_I32);
   16548          assign(rMt, getIRegT(rM));
   16549 
   16550          IRTemp argR = newTemp(Ity_I32);
   16551          IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   16552 
   16553          compute_result_and_C_after_shift_by_imm5(
   16554             dis_buf, &argR, bS ? &oldC : NULL, rMt, how, imm5, rM
   16555          );
   16556 
   16557          IRTemp res = newTemp(Ity_I32);
   16558          if (notArgR) {
   16559             vassert(op == Iop_And32 || op == Iop_Or32);
   16560             assign(res, binop(op, mkexpr(rNt),
   16561                                   unop(Iop_Not32, mkexpr(argR))));
   16562          } else {
   16563             assign(res, binop(op, mkexpr(rNt), mkexpr(argR)));
   16564          }
   16565 
   16566          putIRegT(rD, mkexpr(res), condT);
   16567          if (bS) {
   16568             IRTemp oldV = newTemp(Ity_I32);
   16569             assign( oldV, mk_armg_calculate_flag_v() );
   16570             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16571                                condT );
   16572          }
   16573 
   16574          DIP("%s%s.w r%u, r%u, %s\n",
   16575              nm, bS ? "s" : "", rD, rN, dis_buf);
   16576          goto decode_success;
   16577       }
   16578    }
   16579 
   16580    /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */
   16581    /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */
   16582    /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */
   16583    /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */
   16584    if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0)
   16585        && INSN1(15,12) == BITS4(1,1,1,1)
   16586        && INSN1(7,4) == BITS4(0,0,0,0)) {
   16587       UInt how = INSN0(6,5); // standard encoding
   16588       UInt rN  = INSN0(3,0);
   16589       UInt rD  = INSN1(11,8);
   16590       UInt rM  = INSN1(3,0);
   16591       UInt bS  = INSN0(4,4);
   16592       Bool valid = !isBadRegT(rN) && !isBadRegT(rM) && !isBadRegT(rD);
   16593       if (valid) {
   16594          IRTemp rNt    = newTemp(Ity_I32);
   16595          IRTemp rMt    = newTemp(Ity_I32);
   16596          IRTemp res    = newTemp(Ity_I32);
   16597          IRTemp oldC   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   16598          IRTemp oldV   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   16599          HChar* nms[4] = { "lsl", "lsr", "asr", "ror" };
   16600          HChar* nm     = nms[how];
   16601          assign(rNt, getIRegT(rN));
   16602          assign(rMt, getIRegT(rM));
   16603          compute_result_and_C_after_shift_by_reg(
   16604             dis_buf, &res, bS ? &oldC : NULL,
   16605             rNt, how, rMt, rN, rM
   16606          );
   16607          if (bS)
   16608             assign(oldV, mk_armg_calculate_flag_v());
   16609          putIRegT(rD, mkexpr(res), condT);
   16610          if (bS) {
   16611             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16612                                condT );
   16613          }
   16614          DIP("%s%s.w r%u, r%u, r%u\n",
   16615              nm, bS ? "s" : "", rD, rN, rM);
   16616          goto decode_success;
   16617       }
   16618    }
   16619 
   16620    /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */
   16621    /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */
   16622    if ((INSN0(15,0) & 0xFFCF) == 0xEA4F
   16623        && INSN1(15,15) == 0) {
   16624       UInt rD = INSN1(11,8);
   16625       UInt rN = INSN1(3,0);
   16626       if (!isBadRegT(rD) && !isBadRegT(rN)) {
   16627          UInt bS    = INSN0(4,4);
   16628          UInt isMVN = INSN0(5,5);
   16629          UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
   16630          UInt how   = INSN1(5,4);
   16631 
   16632          IRTemp rNt = newTemp(Ity_I32);
   16633          assign(rNt, getIRegT(rN));
   16634 
   16635          IRTemp oldRn = newTemp(Ity_I32);
   16636          IRTemp oldC  = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   16637          compute_result_and_C_after_shift_by_imm5(
   16638             dis_buf, &oldRn, bS ? &oldC : NULL, rNt, how, imm5, rN
   16639          );
   16640 
   16641          IRTemp res = newTemp(Ity_I32);
   16642          assign(res, isMVN ? unop(Iop_Not32, mkexpr(oldRn))
   16643                            : mkexpr(oldRn));
   16644 
   16645          putIRegT(rD, mkexpr(res), condT);
   16646          if (bS) {
   16647             IRTemp oldV = newTemp(Ity_I32);
   16648             assign( oldV, mk_armg_calculate_flag_v() );
   16649             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT);
   16650          }
   16651          DIP("%s%s.w r%u, %s\n",
   16652              isMVN ? "mvn" : "mov", bS ? "s" : "", rD, dis_buf);
   16653          goto decode_success;
   16654       }
   16655    }
   16656 
   16657    /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */
   16658    /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */
   16659    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16660        && (   INSN0(8,4) == BITS5(0,0,0,0,1)  // TST
   16661            || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ
   16662        && INSN1(15,15) == 0
   16663        && INSN1(11,8) == BITS4(1,1,1,1)) {
   16664       UInt rN = INSN0(3,0);
   16665       UInt rM = INSN1(3,0);
   16666       if (!isBadRegT(rN) && !isBadRegT(rM)) {
   16667          Bool isTST = INSN0(8,4) == BITS5(0,0,0,0,1);
   16668 
   16669          UInt how  = INSN1(5,4);
   16670          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   16671 
   16672          IRTemp argL = newTemp(Ity_I32);
   16673          assign(argL, getIRegT(rN));
   16674 
   16675          IRTemp rMt = newTemp(Ity_I32);
   16676          assign(rMt, getIRegT(rM));
   16677 
   16678          IRTemp argR = newTemp(Ity_I32);
   16679          IRTemp oldC = newTemp(Ity_I32);
   16680          compute_result_and_C_after_shift_by_imm5(
   16681             dis_buf, &argR, &oldC, rMt, how, imm5, rM
   16682          );
   16683 
   16684          IRTemp oldV = newTemp(Ity_I32);
   16685          assign( oldV, mk_armg_calculate_flag_v() );
   16686 
   16687          IRTemp res = newTemp(Ity_I32);
   16688          assign(res, binop(isTST ? Iop_And32 : Iop_Xor32,
   16689                            mkexpr(argL), mkexpr(argR)));
   16690 
   16691          setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16692                             condT );
   16693          DIP("%s.w r%u, %s\n", isTST ? "tst" : "teq", rN, dis_buf);
   16694          goto decode_success;
   16695       }
   16696    }
   16697 
   16698    /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */
   16699    /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */
   16700    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16701        && (   INSN0(8,4) == BITS5(1,1,0,1,1)  // CMP
   16702            || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN
   16703        && INSN1(15,15) == 0
   16704        && INSN1(11,8) == BITS4(1,1,1,1)) {
   16705       UInt rN = INSN0(3,0);
   16706       UInt rM = INSN1(3,0);
   16707       if (!isBadRegT(rN) && !isBadRegT(rM)) {
   16708          Bool isCMN = INSN0(8,4) == BITS5(1,0,0,0,1);
   16709          UInt how   = INSN1(5,4);
   16710          UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
   16711 
   16712          IRTemp argL = newTemp(Ity_I32);
   16713          assign(argL, getIRegT(rN));
   16714 
   16715          IRTemp rMt = newTemp(Ity_I32);
   16716          assign(rMt, getIRegT(rM));
   16717 
   16718          IRTemp argR = newTemp(Ity_I32);
   16719          compute_result_and_C_after_shift_by_imm5(
   16720             dis_buf, &argR, NULL, rMt, how, imm5, rM
   16721          );
   16722 
   16723          setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   16724                          argL, argR, condT );
   16725 
   16726          DIP("%s.w r%u, %s\n", isCMN ? "cmn" : "cmp", rN, dis_buf);
   16727          goto decode_success;
   16728       }
   16729    }
   16730 
   16731    /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */
   16732    /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */
   16733    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16734        && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // MOV
   16735            || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN
   16736        && INSN0(3,0) == BITS4(1,1,1,1)
   16737        && INSN1(15,15) == 0) {
   16738       UInt rD = INSN1(11,8);
   16739       if (!isBadRegT(rD)) {
   16740          Bool   updC  = False;
   16741          UInt   bS    = INSN0(4,4);
   16742          Bool   isMVN = INSN0(5,5) == 1;
   16743          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
   16744          IRTemp res   = newTemp(Ity_I32);
   16745          assign(res, mkU32(isMVN ? ~imm32 : imm32));
   16746          putIRegT(rD, mkexpr(res), condT);
   16747          if (bS) {
   16748             IRTemp oldV = newTemp(Ity_I32);
   16749             IRTemp oldC = newTemp(Ity_I32);
   16750             assign( oldV, mk_armg_calculate_flag_v() );
   16751             assign( oldC, updC
   16752                           ? mkU32((imm32 >> 31) & 1)
   16753                           : mk_armg_calculate_flag_c() );
   16754             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16755                                condT );
   16756          }
   16757          DIP("%s%s.w r%u, #%u\n",
   16758              isMVN ? "mvn" : "mov", bS ? "s" : "", rD, imm32);
   16759          goto decode_success;
   16760       }
   16761    }
   16762 
   16763    /* -------------- (T3) MOVW Rd, #imm16 -------------- */
   16764    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16765        && INSN0(9,4) == BITS6(1,0,0,1,0,0)
   16766        && INSN1(15,15) == 0) {
   16767       UInt rD = INSN1(11,8);
   16768       if (!isBadRegT(rD)) {
   16769          UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
   16770                       | (INSN1(14,12) << 8) | INSN1(7,0);
   16771          putIRegT(rD, mkU32(imm16), condT);
   16772          DIP("movw r%u, #%u\n", rD, imm16);
   16773          goto decode_success;
   16774       }
   16775    }
   16776 
   16777    /* ---------------- MOVT Rd, #imm16 ---------------- */
   16778    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16779        && INSN0(9,4) == BITS6(1,0,1,1,0,0)
   16780        && INSN1(15,15) == 0) {
   16781       UInt rD = INSN1(11,8);
   16782       if (!isBadRegT(rD)) {
   16783          UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
   16784                       | (INSN1(14,12) << 8) | INSN1(7,0);
   16785          IRTemp res = newTemp(Ity_I32);
   16786          assign(res,
   16787                 binop(Iop_Or32,
   16788                       binop(Iop_And32, getIRegT(rD), mkU32(0xFFFF)),
   16789                       mkU32(imm16 << 16)));
   16790          putIRegT(rD, mkexpr(res), condT);
   16791          DIP("movt r%u, #%u\n", rD, imm16);
   16792          goto decode_success;
   16793       }
   16794    }
   16795 
   16796    /* ---------------- LD/ST reg+/-#imm8 ---------------- */
   16797    /* Loads and stores of the form:
   16798          op  Rt, [Rn, #-imm8]      or
   16799          op  Rt, [Rn], #+/-imm8    or
   16800          op  Rt, [Rn, #+/-imm8]!
   16801       where op is one of
   16802          ldrb ldrh ldr  ldrsb ldrsh
   16803          strb strh str
   16804    */
   16805    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) {
   16806       Bool   valid  = True;
   16807       Bool   syned  = False;
   16808       Bool   isST   = False;
   16809       IRType ty     = Ity_I8;
   16810       HChar* nm     = "???";
   16811 
   16812       switch (INSN0(8,4)) {
   16813          case BITS5(0,0,0,0,0):   // strb
   16814             nm = "strb"; isST = True; break;
   16815          case BITS5(0,0,0,0,1):   // ldrb
   16816             nm = "ldrb"; break;
   16817          case BITS5(1,0,0,0,1):   // ldrsb
   16818             nm = "ldrsb"; syned = True; break;
   16819          case BITS5(0,0,0,1,0):   // strh
   16820             nm = "strh"; ty = Ity_I16; isST = True; break;
   16821          case BITS5(0,0,0,1,1):   // ldrh
   16822             nm = "ldrh"; ty = Ity_I16; break;
   16823          case BITS5(1,0,0,1,1):   // ldrsh
   16824             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
   16825          case BITS5(0,0,1,0,0):   // str
   16826             nm = "str"; ty = Ity_I32; isST = True; break;
   16827          case BITS5(0,0,1,0,1):
   16828             nm = "ldr"; ty = Ity_I32; break;  // ldr
   16829          default:
   16830             valid = False; break;
   16831       }
   16832 
   16833       UInt rN      = INSN0(3,0);
   16834       UInt rT      = INSN1(15,12);
   16835       UInt bP      = INSN1(10,10);
   16836       UInt bU      = INSN1(9,9);
   16837       UInt bW      = INSN1(8,8);
   16838       UInt imm8    = INSN1(7,0);
   16839       Bool loadsPC = False;
   16840 
   16841       if (valid) {
   16842          if (bP == 1 && bU == 1 && bW == 0)
   16843             valid = False;
   16844          if (bP == 0 && bW == 0)
   16845             valid = False;
   16846          if (rN == 15)
   16847             valid = False;
   16848          if (bW == 1 && rN == rT)
   16849             valid = False;
   16850          if (ty == Ity_I8 || ty == Ity_I16) {
   16851             if (isBadRegT(rT))
   16852                valid = False;
   16853          } else {
   16854             /* ty == Ity_I32 */
   16855             if (isST && rT == 15)
   16856                valid = False;
   16857             if (!isST && rT == 15)
   16858                loadsPC = True;
   16859          }
   16860       }
   16861 
   16862       if (valid) {
   16863          // if it's a branch, it can't happen in the middle of an IT block
   16864          if (loadsPC)
   16865             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   16866          // go uncond
   16867          mk_skip_over_T32_if_cond_is_false(condT);
   16868          condT = IRTemp_INVALID;
   16869          // now uncond
   16870 
   16871          IRTemp preAddr = newTemp(Ity_I32);
   16872          assign(preAddr, getIRegT(rN));
   16873 
   16874          IRTemp postAddr = newTemp(Ity_I32);
   16875          assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   16876                                 mkexpr(preAddr), mkU32(imm8)));
   16877 
   16878          IRTemp transAddr = bP == 1 ? postAddr : preAddr;
   16879 
   16880          if (isST) {
   16881 
   16882              /* Store.  If necessary, update the base register before
   16883                 the store itself, so that the common idiom of "str rX,
   16884                 [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4,
   16885                 a.k.a "push rX") doesn't cause Memcheck to complain
   16886                 that the access is below the stack pointer.  Also, not
   16887                 updating sp before the store confuses Valgrind's
   16888                 dynamic stack-extending logic.  So do it before the
   16889                 store.  Hence we need to snarf the store data before
   16890                 doing the basereg update. */
   16891 
   16892             /* get hold of the data to be stored */
   16893             IRTemp oldRt = newTemp(Ity_I32);
   16894             assign(oldRt, getIRegT(rT));
   16895 
   16896             /* Update Rn if necessary. */
   16897             if (bW == 1) {
   16898                vassert(rN != rT); // assured by validity check above
   16899                putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
   16900             }
   16901 
   16902             /* generate the transfer */
   16903             switch (ty) {
   16904                case Ity_I8:
   16905                   storeLE(mkexpr(transAddr),
   16906                                  unop(Iop_32to8, mkexpr(oldRt)));
   16907                   break;
   16908                case Ity_I16:
   16909                   storeLE(mkexpr(transAddr),
   16910                           unop(Iop_32to16, mkexpr(oldRt)));
   16911                   break;
   16912               case Ity_I32:
   16913                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
   16914                   break;
   16915               default:
   16916                  vassert(0);
   16917             }
   16918 
   16919          } else {
   16920 
   16921             /* Load. */
   16922 
   16923             /* generate the transfer */
   16924             IRTemp newRt = newTemp(Ity_I32);
   16925             IROp   widen = Iop_INVALID;
   16926             switch (ty) {
   16927                case Ity_I8:
   16928                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
   16929                case Ity_I16:
   16930                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
   16931                case Ity_I32:
   16932                   break;
   16933                default:
   16934                   vassert(0);
   16935             }
   16936             if (widen == Iop_INVALID) {
   16937                assign(newRt, loadLE(ty, mkexpr(transAddr)));
   16938             } else {
   16939                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
   16940             }
   16941             if (loadsPC) {
   16942                vassert(rT == 15);
   16943                llPutIReg(rT, mkexpr(newRt));
   16944             } else {
   16945                putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
   16946             }
   16947 
   16948             if (loadsPC) {
   16949                /* Presumably this is an interworking branch. */
   16950                irsb->next = mkexpr(newRt);
   16951                irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
   16952                dres.whatNext  = Dis_StopHere;
   16953             }
   16954 
   16955             /* Update Rn if necessary. */
   16956             if (bW == 1) {
   16957                vassert(rN != rT); // assured by validity check above
   16958                putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
   16959             }
   16960          }
   16961 
   16962          if (bP == 1 && bW == 0) {
   16963             DIP("%s.w r%u, [r%u, #%c%u]\n",
   16964                 nm, rT, rN, bU ? '+' : '-', imm8);
   16965          }
   16966          else if (bP == 1 && bW == 1) {
   16967             DIP("%s.w r%u, [r%u, #%c%u]!\n",
   16968                 nm, rT, rN, bU ? '+' : '-', imm8);
   16969          }
   16970          else {
   16971             vassert(bP == 0 && bW == 1);
   16972             DIP("%s.w r%u, [r%u], #%c%u\n",
   16973                 nm, rT, rN, bU ? '+' : '-', imm8);
   16974          }
   16975 
   16976          goto decode_success;
   16977       }
   16978    }
   16979 
   16980    /* ------------- LD/ST reg+(reg<<imm2) ------------- */
   16981    /* Loads and stores of the form:
   16982          op  Rt, [Rn, Rm, LSL #imm8]
   16983       where op is one of
   16984          ldrb ldrh ldr  ldrsb ldrsh
   16985          strb strh str
   16986    */
   16987    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)
   16988        && INSN1(11,6) == BITS6(0,0,0,0,0,0)) {
   16989       Bool   valid  = True;
   16990       Bool   syned  = False;
   16991       Bool   isST   = False;
   16992       IRType ty     = Ity_I8;
   16993       HChar* nm     = "???";
   16994 
   16995       switch (INSN0(8,4)) {
   16996          case BITS5(0,0,0,0,0):   // strb
   16997             nm = "strb"; isST = True; break;
   16998          case BITS5(0,0,0,0,1):   // ldrb
   16999             nm = "ldrb"; break;
   17000          case BITS5(1,0,0,0,1):   // ldrsb
   17001             nm = "ldrsb"; syned = True; break;
   17002          case BITS5(0,0,0,1,0):   // strh
   17003             nm = "strh"; ty = Ity_I16; isST = True; break;
   17004          case BITS5(0,0,0,1,1):   // ldrh
   17005             nm = "ldrh"; ty = Ity_I16; break;
   17006          case BITS5(1,0,0,1,1):   // ldrsh
   17007             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
   17008          case BITS5(0,0,1,0,0):   // str
   17009             nm = "str"; ty = Ity_I32; isST = True; break;
   17010          case BITS5(0,0,1,0,1):
   17011             nm = "ldr"; ty = Ity_I32; break;  // ldr
   17012          default:
   17013             valid = False; break;
   17014       }
   17015 
   17016       UInt rN      = INSN0(3,0);
   17017       UInt rM      = INSN1(3,0);
   17018       UInt rT      = INSN1(15,12);
   17019       UInt imm2    = INSN1(5,4);
   17020       Bool loadsPC = False;
   17021 
   17022       if (ty == Ity_I8 || ty == Ity_I16) {
   17023          /* all 8- and 16-bit load and store cases have the
   17024             same exclusion set. */
   17025          if (rN == 15 || isBadRegT(rT) || isBadRegT(rM))
   17026             valid = False;
   17027       } else {
   17028          vassert(ty == Ity_I32);
   17029          if (rN == 15 || isBadRegT(rM))
   17030             valid = False;
   17031          if (isST && rT == 15)
   17032             valid = False;
   17033          /* If it is a load and rT is 15, that's only allowable if we
   17034             not in an IT block, or are the last in it.  Need to insert
   17035             a dynamic check for that. */
   17036          if (!isST && rT == 15)
   17037             loadsPC = True;
   17038       }
   17039 
   17040       if (valid) {
   17041          // if it's a branch, it can't happen in the middle of an IT block
   17042          if (loadsPC)
   17043             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   17044          // go uncond
   17045          mk_skip_over_T32_if_cond_is_false(condT);
   17046          condT = IRTemp_INVALID;
   17047          // now uncond
   17048 
   17049          IRTemp transAddr = newTemp(Ity_I32);
   17050          assign(transAddr,
   17051                 binop( Iop_Add32,
   17052                        getIRegT(rN),
   17053                        binop(Iop_Shl32, getIRegT(rM), mkU8(imm2)) ));
   17054 
   17055          if (isST) {
   17056             IRTemp oldRt = newTemp(Ity_I32);
   17057             assign(oldRt, getIRegT(rT));
   17058             switch (ty) {
   17059                case Ity_I8:
   17060                   storeLE(mkexpr(transAddr),
   17061                                  unop(Iop_32to8, mkexpr(oldRt)));
   17062                   break;
   17063                case Ity_I16:
   17064                   storeLE(mkexpr(transAddr),
   17065                           unop(Iop_32to16, mkexpr(oldRt)));
   17066                   break;
   17067               case Ity_I32:
   17068                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
   17069                   break;
   17070               default:
   17071                  vassert(0);
   17072             }
   17073          } else {
   17074             IRTemp newRt = newTemp(Ity_I32);
   17075             IROp   widen = Iop_INVALID;
   17076             switch (ty) {
   17077                case Ity_I8:
   17078                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
   17079                case Ity_I16:
   17080                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
   17081                case Ity_I32:
   17082                   break;
   17083                default:
   17084                   vassert(0);
   17085             }
   17086             if (widen == Iop_INVALID) {
   17087                assign(newRt, loadLE(ty, mkexpr(transAddr)));
   17088             } else {
   17089                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
   17090             }
   17091 
   17092             /* If we're loading the PC, putIRegT will assert.  So go
   17093                direct via llPutIReg.  In all other cases use putIRegT
   17094                as it is safer (although could simply use llPutIReg for
   17095                _all_ cases here.) */
   17096             if (loadsPC) {
   17097                vassert(rT == 15);
   17098                llPutIReg(rT, mkexpr(newRt));
   17099             } else {
   17100                putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
   17101             }
   17102 
   17103             if (loadsPC) {
   17104                /* Presumably this is an interworking branch. */
   17105                irsb->next = mkexpr(newRt);
   17106                irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
   17107                dres.whatNext  = Dis_StopHere;
   17108             }
   17109          }
   17110 
   17111          DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n",
   17112              nm, rT, rN, rM, imm2);
   17113 
   17114          goto decode_success;
   17115       }
   17116    }
   17117 
   17118    /* --------------- LD/ST reg+imm12 --------------- */
   17119    /* Loads and stores of the form:
   17120          op  Rt, [Rn, +#imm12]
   17121       where op is one of
   17122          ldrb ldrh ldr  ldrsb ldrsh
   17123          strb strh str
   17124    */
   17125    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) {
   17126       Bool   valid  = True;
   17127       Bool   syned  = False;
   17128       Bool   isST   = False;
   17129       IRType ty     = Ity_I8;
   17130       HChar* nm     = "???";
   17131 
   17132       switch (INSN0(8,4)) {
   17133          case BITS5(0,1,0,0,0):   // strb
   17134             nm = "strb"; isST = True; break;
   17135          case BITS5(0,1,0,0,1):   // ldrb
   17136             nm = "ldrb"; break;
   17137          case BITS5(1,1,0,0,1):   // ldrsb
   17138             nm = "ldrsb"; syned = True; break;
   17139          case BITS5(0,1,0,1,0):   // strh
   17140             nm = "strh"; ty = Ity_I16; isST = True; break;
   17141          case BITS5(0,1,0,1,1):   // ldrh
   17142             nm = "ldrh"; ty = Ity_I16; break;
   17143          case BITS5(1,1,0,1,1):   // ldrsh
   17144             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
   17145          case BITS5(0,1,1,0,0):   // str
   17146             nm = "str"; ty = Ity_I32; isST = True; break;
   17147          case BITS5(0,1,1,0,1):
   17148             nm = "ldr"; ty = Ity_I32; break;  // ldr
   17149          default:
   17150             valid = False; break;
   17151       }
   17152 
   17153       UInt rN      = INSN0(3,0);
   17154       UInt rT      = INSN1(15,12);
   17155       UInt imm12   = INSN1(11,0);
   17156       Bool loadsPC = False;
   17157 
   17158       if (ty == Ity_I8 || ty == Ity_I16) {
   17159          /* all 8- and 16-bit load and store cases have the
   17160             same exclusion set. */
   17161          if (rN == 15 || isBadRegT(rT))
   17162             valid = False;
   17163       } else {
   17164          vassert(ty == Ity_I32);
   17165          if (isST) {
   17166             if (rN == 15 || rT == 15)
   17167                valid = False;
   17168          } else {
   17169             /* For a 32-bit load, rT == 15 is only allowable if we not
   17170                in an IT block, or are the last in it.  Need to insert
   17171                a dynamic check for that.  Also, in this particular
   17172                case, rN == 15 is allowable.  In this case however, the
   17173                value obtained for rN is (apparently)
   17174                "word-align(address of current insn + 4)". */
   17175             if (rT == 15)
   17176                loadsPC = True;
   17177          }
   17178       }
   17179 
   17180       if (valid) {
   17181          // if it's a branch, it can't happen in the middle of an IT block
   17182          if (loadsPC)
   17183             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   17184          // go uncond
   17185          mk_skip_over_T32_if_cond_is_false(condT);
   17186          condT = IRTemp_INVALID;
   17187          // now uncond
   17188 
   17189          IRTemp rNt = newTemp(Ity_I32);
   17190          if (rN == 15) {
   17191             vassert(ty == Ity_I32 && !isST);
   17192             assign(rNt, binop(Iop_And32, getIRegT(rN), mkU32(~3)));
   17193          } else {
   17194             assign(rNt, getIRegT(rN));
   17195          }
   17196 
   17197          IRTemp transAddr = newTemp(Ity_I32);
   17198          assign(transAddr,
   17199                 binop( Iop_Add32, mkexpr(rNt), mkU32(imm12) ));
   17200 
   17201          if (isST) {
   17202             IRTemp oldRt = newTemp(Ity_I32);
   17203             assign(oldRt, getIRegT(rT));
   17204             switch (ty) {
   17205                case Ity_I8:
   17206                   storeLE(mkexpr(transAddr),
   17207                                  unop(Iop_32to8, mkexpr(oldRt)));
   17208                   break;
   17209                case Ity_I16:
   17210                   storeLE(mkexpr(transAddr),
   17211                           unop(Iop_32to16, mkexpr(oldRt)));
   17212                   break;
   17213               case Ity_I32:
   17214                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
   17215                   break;
   17216               default:
   17217                  vassert(0);
   17218             }
   17219          } else {
   17220             IRTemp newRt = newTemp(Ity_I32);
   17221             IROp   widen = Iop_INVALID;
   17222             switch (ty) {
   17223                case Ity_I8:
   17224                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
   17225                case Ity_I16:
   17226                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
   17227                case Ity_I32:
   17228                   break;
   17229                default:
   17230                   vassert(0);
   17231             }
   17232             if (widen == Iop_INVALID) {
   17233                assign(newRt, loadLE(ty, mkexpr(transAddr)));
   17234             } else {
   17235                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
   17236             }
   17237             putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
   17238 
   17239             if (loadsPC) {
   17240                /* Presumably this is an interworking branch. */
   17241                irsb->next = mkexpr(newRt);
   17242                irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
   17243                dres.whatNext  = Dis_StopHere;
   17244             }
   17245          }
   17246 
   17247          DIP("%s.w r%u, [r%u, +#%u]\n", nm, rT, rN, imm12);
   17248 
   17249          goto decode_success;
   17250       }
   17251    }
   17252 
   17253    /* -------------- LDRD/STRD reg+/-#imm8 -------------- */
   17254    /* Doubleword loads and stores of the form:
   17255          ldrd/strd  Rt, Rt2, [Rn, #-imm8]      or
   17256          ldrd/strd  Rt, Rt2, [Rn], #+/-imm8    or
   17257          ldrd/strd  Rt, Rt2, [Rn, #+/-imm8]!
   17258    */
   17259    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) {
   17260       UInt bP   = INSN0(8,8);
   17261       UInt bU   = INSN0(7,7);
   17262       UInt bW   = INSN0(5,5);
   17263       UInt bL   = INSN0(4,4);  // 1: load  0: store
   17264       UInt rN   = INSN0(3,0);
   17265       UInt rT   = INSN1(15,12);
   17266       UInt rT2  = INSN1(11,8);
   17267       UInt imm8 = INSN1(7,0);
   17268 
   17269       Bool valid = True;
   17270       if (bP == 0 && bW == 0)                 valid = False;
   17271       if (bW == 1 && (rN == rT || rN == rT2)) valid = False;
   17272       if (isBadRegT(rT) || isBadRegT(rT2))    valid = False;
   17273       if (rN == 15)                           valid = False;
   17274       if (bL == 1 && rT == rT2)               valid = False;
   17275 
   17276       if (valid) {
   17277          // go uncond
   17278          mk_skip_over_T32_if_cond_is_false(condT);
   17279          condT = IRTemp_INVALID;
   17280          // now uncond
   17281 
   17282          IRTemp preAddr = newTemp(Ity_I32);
   17283          assign(preAddr, getIRegT(rN));
   17284 
   17285          IRTemp postAddr = newTemp(Ity_I32);
   17286          assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   17287                                 mkexpr(preAddr), mkU32(imm8 << 2)));
   17288 
   17289          IRTemp transAddr = bP == 1 ? postAddr : preAddr;
   17290 
   17291          if (bL == 0) {
   17292             IRTemp oldRt  = newTemp(Ity_I32);
   17293             IRTemp oldRt2 = newTemp(Ity_I32);
   17294             assign(oldRt,  getIRegT(rT));
   17295             assign(oldRt2, getIRegT(rT2));
   17296             storeLE(mkexpr(transAddr),
   17297                     mkexpr(oldRt));
   17298             storeLE(binop(Iop_Add32, mkexpr(transAddr), mkU32(4)),
   17299                     mkexpr(oldRt2));
   17300          } else {
   17301             IRTemp newRt  = newTemp(Ity_I32);
   17302             IRTemp newRt2 = newTemp(Ity_I32);
   17303             assign(newRt,
   17304                    loadLE(Ity_I32,
   17305                           mkexpr(transAddr)));
   17306             assign(newRt2,
   17307                    loadLE(Ity_I32,
   17308                           binop(Iop_Add32, mkexpr(transAddr), mkU32(4))));
   17309             putIRegT(rT,  mkexpr(newRt), IRTemp_INVALID);
   17310             putIRegT(rT2, mkexpr(newRt2), IRTemp_INVALID);
   17311          }
   17312 
   17313          if (bW == 1) {
   17314             putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
   17315          }
   17316 
   17317          HChar* nm = bL ? "ldrd" : "strd";
   17318 
   17319          if (bP == 1 && bW == 0) {
   17320             DIP("%s.w r%u, r%u, [r%u, #%c%u]\n",
   17321                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
   17322          }
   17323          else if (bP == 1 && bW == 1) {
   17324             DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n",
   17325                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
   17326          }
   17327          else {
   17328             vassert(bP == 0 && bW == 1);
   17329             DIP("%s.w r%u, r%u, [r%u], #%c%u\n",
   17330                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
   17331          }
   17332 
   17333          goto decode_success;
   17334       }
   17335    }
   17336 
   17337    /* -------------- (T3) Bcond.W label -------------- */
   17338    /* This variant carries its own condition, so can't be part of an
   17339       IT block ... */
   17340    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   17341        && INSN1(15,14) == BITS2(1,0)
   17342        && INSN1(12,12) == 0) {
   17343       UInt cond = INSN0(9,6);
   17344       if (cond != ARMCondAL && cond != ARMCondNV) {
   17345          Int simm21
   17346             =   (INSN0(10,10) << (1 + 1 + 6 + 11 + 1))
   17347               | (INSN1(11,11) << (1 + 6 + 11 + 1))
   17348               | (INSN1(13,13) << (6 + 11 + 1))
   17349               | (INSN0(5,0)   << (11 + 1))
   17350               | (INSN1(10,0)  << 1);
   17351          simm21 = (simm21 << 11) >> 11;
   17352 
   17353          vassert(0 == (guest_R15_curr_instr_notENC & 1));
   17354          UInt dst = simm21 + guest_R15_curr_instr_notENC + 4;
   17355 
   17356          /* Not allowed in an IT block; SIGILL if so. */
   17357          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   17358 
   17359          IRTemp kondT = newTemp(Ity_I32);
   17360          assign( kondT, mk_armg_calculate_condition(cond) );
   17361          stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
   17362                             Ijk_Boring,
   17363                             IRConst_U32(dst | 1/*CPSR.T*/) ));
   17364          irsb->next = mkU32( (guest_R15_curr_instr_notENC + 4)
   17365                              | 1 /*CPSR.T*/ );
   17366          irsb->jumpkind = Ijk_Boring;
   17367          dres.whatNext  = Dis_StopHere;
   17368          DIP("b%s.w 0x%x\n", nCC(cond), dst);
   17369          goto decode_success;
   17370       }
   17371    }
   17372 
   17373    /* ---------------- (T4) B.W label ---------------- */
   17374    /* ... whereas this variant doesn't carry its own condition, so it
   17375       has to be either unconditional or the conditional by virtue of
   17376       being the last in an IT block.  The upside is that there's 4
   17377       more bits available for the jump offset, so it has a 16-times
   17378       greater branch range than the T3 variant. */
   17379    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   17380        && INSN1(15,14) == BITS2(1,0)
   17381        && INSN1(12,12) == 1) {
   17382       if (1) {
   17383          UInt bS  = INSN0(10,10);
   17384          UInt bJ1 = INSN1(13,13);
   17385          UInt bJ2 = INSN1(11,11);
   17386          UInt bI1 = 1 ^ (bJ1 ^ bS);
   17387          UInt bI2 = 1 ^ (bJ2 ^ bS);
   17388          Int simm25
   17389             =   (bS          << (1 + 1 + 10 + 11 + 1))
   17390               | (bI1         << (1 + 10 + 11 + 1))
   17391               | (bI2         << (10 + 11 + 1))
   17392               | (INSN0(9,0)  << (11 + 1))
   17393               | (INSN1(10,0) << 1);
   17394          simm25 = (simm25 << 7) >> 7;
   17395 
   17396          vassert(0 == (guest_R15_curr_instr_notENC & 1));
   17397          UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
   17398 
   17399          /* If in an IT block, must be the last insn. */
   17400          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   17401 
   17402          // go uncond
   17403          mk_skip_over_T32_if_cond_is_false(condT);
   17404          condT = IRTemp_INVALID;
   17405          // now uncond
   17406 
   17407          // branch to dst
   17408          irsb->next = mkU32( dst | 1 /*CPSR.T*/ );
   17409          irsb->jumpkind = Ijk_Boring;
   17410          dres.whatNext  = Dis_StopHere;
   17411          DIP("b.w 0x%x\n", dst);
   17412          goto decode_success;
   17413       }
   17414    }
   17415 
   17416    /* ------------------ TBB, TBH ------------------ */
   17417    if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) {
   17418       UInt rN = INSN0(3,0);
   17419       UInt rM = INSN1(3,0);
   17420       UInt bH = INSN1(4,4);
   17421       if (bH/*ATC*/ || (rN != 13 && !isBadRegT(rM))) {
   17422          /* Must be last or not-in IT block */
   17423          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   17424          /* Go uncond */
   17425          mk_skip_over_T32_if_cond_is_false(condT);
   17426          condT = IRTemp_INVALID;
   17427 
   17428          IRExpr* ea
   17429              = binop(Iop_Add32,
   17430                      getIRegT(rN),
   17431                      bH ? binop(Iop_Shl32, getIRegT(rM), mkU8(1))
   17432                         : getIRegT(rM));
   17433 
   17434          IRTemp delta = newTemp(Ity_I32);
   17435          if (bH) {
   17436             assign(delta, unop(Iop_16Uto32, loadLE(Ity_I16, ea)));
   17437          } else {
   17438             assign(delta, unop(Iop_8Uto32, loadLE(Ity_I8, ea)));
   17439          }
   17440 
   17441          irsb->next
   17442             = binop(Iop_Or32,
   17443                     binop(Iop_Add32,
   17444                           getIRegT(15),
   17445                           binop(Iop_Shl32, mkexpr(delta), mkU8(1))
   17446                     ),
   17447                     mkU32(1)
   17448               );
   17449          irsb->jumpkind = Ijk_Boring;
   17450          dres.whatNext = Dis_StopHere;
   17451          DIP("tb%c [r%u, r%u%s]\n",
   17452              bH ? 'h' : 'b', rN, rM, bH ? ", LSL #1" : "");
   17453          goto decode_success;
   17454       }
   17455    }
   17456 
   17457    /* ------------------ UBFX ------------------ */
   17458    /* ------------------ SBFX ------------------ */
   17459    /* There's also ARM versions of same, but it doesn't seem worth the
   17460       hassle to common up the handling (it's only a couple of C
   17461       statements). */
   17462    if ((INSN0(15,4) == 0xF3C // UBFX
   17463         || INSN0(15,4) == 0xF34) // SBFX
   17464        && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
   17465       UInt rN  = INSN0(3,0);
   17466       UInt rD  = INSN1(11,8);
   17467       UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
   17468       UInt wm1 = INSN1(4,0);
   17469       UInt msb =  lsb + wm1;
   17470       if (!isBadRegT(rD) && !isBadRegT(rN) && msb <= 31) {
   17471          Bool   isU  = INSN0(15,4) == 0xF3C;
   17472          IRTemp src  = newTemp(Ity_I32);
   17473          IRTemp tmp  = newTemp(Ity_I32);
   17474          IRTemp res  = newTemp(Ity_I32);
   17475          UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
   17476          vassert(msb >= 0 && msb <= 31);
   17477          vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
   17478 
   17479          assign(src, getIRegT(rN));
   17480          assign(tmp, binop(Iop_And32,
   17481                            binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
   17482                            mkU32(mask)));
   17483          assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
   17484                            binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
   17485                            mkU8(31-wm1)));
   17486 
   17487          putIRegT(rD, mkexpr(res), condT);
   17488 
   17489          DIP("%s r%u, r%u, #%u, #%u\n",
   17490              isU ? "ubfx" : "sbfx", rD, rN, lsb, wm1 + 1);
   17491          goto decode_success;
   17492       }
   17493    }
   17494 
   17495    /* ------------------ UXTB ------------------ */
   17496    /* ------------------ UXTH ------------------ */
   17497    /* ------------------ SXTB ------------------ */
   17498    /* ------------------ SXTH ------------------ */
   17499    /* ----------------- UXTB16 ----------------- */
   17500    /* ----------------- SXTB16 ----------------- */
   17501    /* FIXME: this is an exact duplicate of the ARM version.  They
   17502       should be commoned up. */
   17503    if ((INSN0(15,0) == 0xFA5F     // UXTB
   17504         || INSN0(15,0) == 0xFA1F  // UXTH
   17505         || INSN0(15,0) == 0xFA4F  // SXTB
   17506         || INSN0(15,0) == 0xFA0F  // SXTH
   17507         || INSN0(15,0) == 0xFA3F  // UXTB16
   17508         || INSN0(15,0) == 0xFA2F) // SXTB16
   17509        && INSN1(15,12) == BITS4(1,1,1,1)
   17510        && INSN1(7,6) == BITS2(1,0)) {
   17511       UInt rD = INSN1(11,8);
   17512       UInt rM = INSN1(3,0);
   17513       UInt rot = INSN1(5,4);
   17514       if (!isBadRegT(rD) && !isBadRegT(rM)) {
   17515          HChar* nm = "???";
   17516          IRTemp srcT = newTemp(Ity_I32);
   17517          IRTemp rotT = newTemp(Ity_I32);
   17518          IRTemp dstT = newTemp(Ity_I32);
   17519          assign(srcT, getIRegT(rM));
   17520          assign(rotT, genROR32(srcT, 8 * rot));
   17521          switch (INSN0(15,0)) {
   17522             case 0xFA5F: // UXTB
   17523                nm = "uxtb";
   17524                assign(dstT, unop(Iop_8Uto32,
   17525                                  unop(Iop_32to8, mkexpr(rotT))));
   17526                break;
   17527             case 0xFA1F: // UXTH
   17528                nm = "uxth";
   17529                assign(dstT, unop(Iop_16Uto32,
   17530                                  unop(Iop_32to16, mkexpr(rotT))));
   17531                break;
   17532             case 0xFA4F: // SXTB
   17533                nm = "sxtb";
   17534                assign(dstT, unop(Iop_8Sto32,
   17535                                  unop(Iop_32to8, mkexpr(rotT))));
   17536                break;
   17537             case 0xFA0F: // SXTH
   17538                nm = "sxth";
   17539                assign(dstT, unop(Iop_16Sto32,
   17540                                  unop(Iop_32to16, mkexpr(rotT))));
   17541                break;
   17542             case 0xFA3F: // UXTB16
   17543                nm = "uxtb16";
   17544                assign(dstT, binop(Iop_And32, mkexpr(rotT),
   17545                                              mkU32(0x00FF00FF)));
   17546                break;
   17547             case 0xFA2F: { // SXTB16
   17548                nm = "sxtb16";
   17549                IRTemp lo32 = newTemp(Ity_I32);
   17550                IRTemp hi32 = newTemp(Ity_I32);
   17551                assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
   17552                assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
   17553                assign(
   17554                   dstT,
   17555                   binop(Iop_Or32,
   17556                         binop(Iop_And32,
   17557                               unop(Iop_8Sto32,
   17558                                    unop(Iop_32to8, mkexpr(lo32))),
   17559                               mkU32(0xFFFF)),
   17560                         binop(Iop_Shl32,
   17561                               unop(Iop_8Sto32,
   17562                                    unop(Iop_32to8, mkexpr(hi32))),
   17563                               mkU8(16))
   17564                ));
   17565                break;
   17566             }
   17567             default:
   17568                vassert(0);
   17569          }
   17570          putIRegT(rD, mkexpr(dstT), condT);
   17571          DIP("%s r%u, r%u, ror #%u\n", nm, rD, rM, 8 * rot);
   17572          goto decode_success;
   17573       }
   17574    }
   17575 
   17576    /* -------------- MUL.W Rd, Rn, Rm -------------- */
   17577    if (INSN0(15,4) == 0xFB0
   17578        && (INSN1(15,0) & 0xF0F0) == 0xF000) {
   17579       UInt rN = INSN0(3,0);
   17580       UInt rD = INSN1(11,8);
   17581       UInt rM = INSN1(3,0);
   17582       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   17583          IRTemp res = newTemp(Ity_I32);
   17584          assign(res, binop(Iop_Mul32, getIRegT(rN), getIRegT(rM)));
   17585          putIRegT(rD, mkexpr(res), condT);
   17586          DIP("mul.w r%u, r%u, r%u\n", rD, rN, rM);
   17587          goto decode_success;
   17588       }
   17589    }
   17590 
   17591    /* ------------------ {U,S}MULL ------------------ */
   17592    if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA)
   17593        && INSN1(7,4) == BITS4(0,0,0,0)) {
   17594       UInt isU  = INSN0(5,5);
   17595       UInt rN   = INSN0(3,0);
   17596       UInt rDlo = INSN1(15,12);
   17597       UInt rDhi = INSN1(11,8);
   17598       UInt rM   = INSN1(3,0);
   17599       if (!isBadRegT(rDhi) && !isBadRegT(rDlo)
   17600           && !isBadRegT(rN) && !isBadRegT(rM) && rDlo != rDhi) {
   17601          IRTemp res   = newTemp(Ity_I64);
   17602          assign(res, binop(isU ? Iop_MullU32 : Iop_MullS32,
   17603                            getIRegT(rN), getIRegT(rM)));
   17604          putIRegT( rDhi, unop(Iop_64HIto32, mkexpr(res)), condT );
   17605          putIRegT( rDlo, unop(Iop_64to32, mkexpr(res)), condT );
   17606          DIP("%cmull r%u, r%u, r%u, r%u\n",
   17607              isU ? 'u' : 's', rDlo, rDhi, rN, rM);
   17608          goto decode_success;
   17609       }
   17610    }
   17611 
   17612    /* ------------------ ML{A,S} ------------------ */
   17613    if (INSN0(15,4) == 0xFB0
   17614        && (   INSN1(7,4) == BITS4(0,0,0,0)    // MLA
   17615            || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS
   17616       UInt rN = INSN0(3,0);
   17617       UInt rA = INSN1(15,12);
   17618       UInt rD = INSN1(11,8);
   17619       UInt rM = INSN1(3,0);
   17620       if (!isBadRegT(rD) && !isBadRegT(rN)
   17621           && !isBadRegT(rM) && !isBadRegT(rA)) {
   17622          Bool   isMLA = INSN1(7,4) == BITS4(0,0,0,0);
   17623          IRTemp res   = newTemp(Ity_I32);
   17624          assign(res,
   17625                 binop(isMLA ? Iop_Add32 : Iop_Sub32,
   17626                       getIRegT(rA),
   17627                       binop(Iop_Mul32, getIRegT(rN), getIRegT(rM))));
   17628          putIRegT(rD, mkexpr(res), condT);
   17629          DIP("%s r%u, r%u, r%u, r%u\n",
   17630              isMLA ? "mla" : "mls", rD, rN, rM, rA);
   17631          goto decode_success;
   17632       }
   17633    }
   17634 
   17635    /* ------------------ (T3) ADR ------------------ */
   17636    if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F)
   17637        && INSN1(15,15) == 0) {
   17638       /* rD = align4(PC) + imm32 */
   17639       UInt rD = INSN1(11,8);
   17640       if (!isBadRegT(rD)) {
   17641          UInt imm32 = (INSN0(10,10) << 11)
   17642                       | (INSN1(14,12) << 8) | INSN1(7,0);
   17643          putIRegT(rD, binop(Iop_Add32,
   17644                             binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   17645                             mkU32(imm32)),
   17646                       condT);
   17647          DIP("add r%u, pc, #%u\n", rD, imm32);
   17648          goto decode_success;
   17649       }
   17650    }
   17651 
   17652    /* ----------------- (T1) UMLAL ----------------- */
   17653    /* ----------------- (T1) SMLAL ----------------- */
   17654    if ((INSN0(15,4) == 0xFBE // UMLAL
   17655         || INSN0(15,4) == 0xFBC) // SMLAL
   17656        && INSN1(7,4) == BITS4(0,0,0,0)) {
   17657       UInt rN   = INSN0(3,0);
   17658       UInt rDlo = INSN1(15,12);
   17659       UInt rDhi = INSN1(11,8);
   17660       UInt rM   = INSN1(3,0);
   17661       if (!isBadRegT(rDlo) && !isBadRegT(rDhi) && !isBadRegT(rN)
   17662           && !isBadRegT(rM) && rDhi != rDlo) {
   17663          Bool   isS   = INSN0(15,4) == 0xFBC;
   17664          IRTemp argL  = newTemp(Ity_I32);
   17665          IRTemp argR  = newTemp(Ity_I32);
   17666          IRTemp old   = newTemp(Ity_I64);
   17667          IRTemp res   = newTemp(Ity_I64);
   17668          IRTemp resHi = newTemp(Ity_I32);
   17669          IRTemp resLo = newTemp(Ity_I32);
   17670          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
   17671          assign( argL, getIRegT(rM));
   17672          assign( argR, getIRegT(rN));
   17673          assign( old, binop(Iop_32HLto64, getIRegT(rDhi), getIRegT(rDlo)) );
   17674          assign( res, binop(Iop_Add64,
   17675                             mkexpr(old),
   17676                             binop(mulOp, mkexpr(argL), mkexpr(argR))) );
   17677          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
   17678          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
   17679          putIRegT( rDhi, mkexpr(resHi), condT );
   17680          putIRegT( rDlo, mkexpr(resLo), condT );
   17681          DIP("%cmlal r%u, r%u, r%u, r%u\n",
   17682              isS ? 's' : 'u', rDlo, rDhi, rN, rM);
   17683          goto decode_success;
   17684       }
   17685    }
   17686 
   17687    /* ------------------ (T2) ADR ------------------ */
   17688    if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF)
   17689        && INSN1(15,15) == 0) {
   17690       /* rD = align4(PC) - imm32 */
   17691       UInt rD = INSN1(11,8);
   17692       if (!isBadRegT(rD)) {
   17693          UInt imm32 = (INSN0(10,10) << 11)
   17694                       | (INSN1(14,12) << 8) | INSN1(7,0);
   17695          putIRegT(rD, binop(Iop_Sub32,
   17696                             binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   17697                             mkU32(imm32)),
   17698                       condT);
   17699          DIP("sub r%u, pc, #%u\n", rD, imm32);
   17700          goto decode_success;
   17701       }
   17702    }
   17703 
   17704    /* ------------------- (T1) BFI ------------------- */
   17705    /* ------------------- (T1) BFC ------------------- */
   17706    if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
   17707       UInt rD  = INSN1(11,8);
   17708       UInt rN  = INSN0(3,0);
   17709       UInt msb = INSN1(4,0);
   17710       UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
   17711       if (isBadRegT(rD) || rN == 13 || msb < lsb) {
   17712          /* undecodable; fall through */
   17713       } else {
   17714          IRTemp src    = newTemp(Ity_I32);
   17715          IRTemp olddst = newTemp(Ity_I32);
   17716          IRTemp newdst = newTemp(Ity_I32);
   17717          UInt   mask = 1 << (msb - lsb);
   17718          mask = (mask - 1) + mask;
   17719          vassert(mask != 0); // guaranteed by "msb < lsb" check above
   17720          mask <<= lsb;
   17721 
   17722          assign(src, rN == 15 ? mkU32(0) : getIRegT(rN));
   17723          assign(olddst, getIRegT(rD));
   17724          assign(newdst,
   17725                 binop(Iop_Or32,
   17726                    binop(Iop_And32,
   17727                          binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
   17728                          mkU32(mask)),
   17729                    binop(Iop_And32,
   17730                          mkexpr(olddst),
   17731                          mkU32(~mask)))
   17732                );
   17733 
   17734          putIRegT(rD, mkexpr(newdst), condT);
   17735 
   17736          if (rN == 15) {
   17737             DIP("bfc r%u, #%u, #%u\n",
   17738                 rD, lsb, msb-lsb+1);
   17739          } else {
   17740             DIP("bfi r%u, r%u, #%u, #%u\n",
   17741                 rD, rN, lsb, msb-lsb+1);
   17742          }
   17743          goto decode_success;
   17744       }
   17745    }
   17746 
   17747    /* ------------------- (T1) SXTAH ------------------- */
   17748    /* ------------------- (T1) UXTAH ------------------- */
   17749    if ((INSN0(15,4) == 0xFA1      // UXTAH
   17750         || INSN0(15,4) == 0xFA0)  // SXTAH
   17751        && INSN1(15,12) == BITS4(1,1,1,1)
   17752        && INSN1(7,6) == BITS2(1,0)) {
   17753       Bool isU = INSN0(15,4) == 0xFA1;
   17754       UInt rN  = INSN0(3,0);
   17755       UInt rD  = INSN1(11,8);
   17756       UInt rM  = INSN1(3,0);
   17757       UInt rot = INSN1(5,4);
   17758       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   17759          IRTemp srcL = newTemp(Ity_I32);
   17760          IRTemp srcR = newTemp(Ity_I32);
   17761          IRTemp res  = newTemp(Ity_I32);
   17762          assign(srcR, getIRegT(rM));
   17763          assign(srcL, getIRegT(rN));
   17764          assign(res,  binop(Iop_Add32,
   17765                             mkexpr(srcL),
   17766                             unop(isU ? Iop_16Uto32 : Iop_16Sto32,
   17767                                  unop(Iop_32to16,
   17768                                       genROR32(srcR, 8 * rot)))));
   17769          putIRegT(rD, mkexpr(res), condT);
   17770          DIP("%cxtah r%u, r%u, r%u, ror #%u\n",
   17771              isU ? 'u' : 's', rD, rN, rM, rot);
   17772          goto decode_success;
   17773       }
   17774    }
   17775 
   17776    /* ------------------- (T1) SXTAB ------------------- */
   17777    /* ------------------- (T1) UXTAB ------------------- */
   17778    if ((INSN0(15,4) == 0xFA5      // UXTAB
   17779         || INSN0(15,4) == 0xFA4)  // SXTAB
   17780        && INSN1(15,12) == BITS4(1,1,1,1)
   17781        && INSN1(7,6) == BITS2(1,0)) {
   17782       Bool isU = INSN0(15,4) == 0xFA5;
   17783       UInt rN  = INSN0(3,0);
   17784       UInt rD  = INSN1(11,8);
   17785       UInt rM  = INSN1(3,0);
   17786       UInt rot = INSN1(5,4);
   17787       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   17788          IRTemp srcL = newTemp(Ity_I32);
   17789          IRTemp srcR = newTemp(Ity_I32);
   17790          IRTemp res  = newTemp(Ity_I32);
   17791          assign(srcR, getIRegT(rM));
   17792          assign(srcL, getIRegT(rN));
   17793          assign(res,  binop(Iop_Add32,
   17794                             mkexpr(srcL),
   17795                             unop(isU ? Iop_8Uto32 : Iop_8Sto32,
   17796                                  unop(Iop_32to8,
   17797                                       genROR32(srcR, 8 * rot)))));
   17798          putIRegT(rD, mkexpr(res), condT);
   17799          DIP("%cxtab r%u, r%u, r%u, ror #%u\n",
   17800              isU ? 'u' : 's', rD, rN, rM, rot);
   17801          goto decode_success;
   17802       }
   17803    }
   17804 
   17805    /* ------------------- (T1) CLZ ------------------- */
   17806    if (INSN0(15,4) == 0xFAB
   17807        && INSN1(15,12) == BITS4(1,1,1,1)
   17808        && INSN1(7,4) == BITS4(1,0,0,0)) {
   17809       UInt rM1 = INSN0(3,0);
   17810       UInt rD  = INSN1(11,8);
   17811       UInt rM2 = INSN1(3,0);
   17812       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
   17813          IRTemp arg = newTemp(Ity_I32);
   17814          IRTemp res = newTemp(Ity_I32);
   17815          assign(arg, getIRegT(rM1));
   17816          assign(res, IRExpr_Mux0X(
   17817                         unop(Iop_1Uto8,binop(Iop_CmpEQ32,
   17818                                              mkexpr(arg),
   17819                                              mkU32(0))),
   17820                         unop(Iop_Clz32, mkexpr(arg)),
   17821                         mkU32(32)
   17822          ));
   17823          putIRegT(rD, mkexpr(res), condT);
   17824          DIP("clz r%u, r%u\n", rD, rM1);
   17825          goto decode_success;
   17826       }
   17827    }
   17828 
   17829    /* ------------------- (T1) RBIT ------------------- */
   17830    if (INSN0(15,4) == 0xFA9
   17831        && INSN1(15,12) == BITS4(1,1,1,1)
   17832        && INSN1(7,4) == BITS4(1,0,1,0)) {
   17833       UInt rM1 = INSN0(3,0);
   17834       UInt rD  = INSN1(11,8);
   17835       UInt rM2 = INSN1(3,0);
   17836       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
   17837          IRTemp arg = newTemp(Ity_I32);
   17838          assign(arg, getIRegT(rM1));
   17839          IRTemp res = gen_BITREV(arg);
   17840          putIRegT(rD, mkexpr(res), condT);
   17841          DIP("rbit r%u, r%u\n", rD, rM1);
   17842          goto decode_success;
   17843       }
   17844    }
   17845 
   17846    /* ------------------- (T2) REV   ------------------- */
   17847    /* ------------------- (T2) REV16 ------------------- */
   17848    if (INSN0(15,4) == 0xFA9
   17849        && INSN1(15,12) == BITS4(1,1,1,1)
   17850        && (   INSN1(7,4) == BITS4(1,0,0,0)     // REV
   17851            || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16
   17852       UInt rM1   = INSN0(3,0);
   17853       UInt rD    = INSN1(11,8);
   17854       UInt rM2   = INSN1(3,0);
   17855       Bool isREV = INSN1(7,4) == BITS4(1,0,0,0);
   17856       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
   17857          IRTemp arg = newTemp(Ity_I32);
   17858          assign(arg, getIRegT(rM1));
   17859          IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
   17860          putIRegT(rD, mkexpr(res), condT);
   17861          DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM1);
   17862          goto decode_success;
   17863       }
   17864    }
   17865 
   17866    /* -------------- (T1) MSR apsr, reg -------------- */
   17867    if (INSN0(15,4) == 0xF38
   17868        && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) {
   17869       UInt rN          = INSN0(3,0);
   17870       UInt write_ge    = INSN1(10,10);
   17871       UInt write_nzcvq = INSN1(11,11);
   17872       if (!isBadRegT(rN) && (write_nzcvq || write_ge)) {
   17873          IRTemp rNt = newTemp(Ity_I32);
   17874          assign(rNt, getIRegT(rN));
   17875          desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
   17876          DIP("msr cpsr_%s%s, r%u\n",
   17877              write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
   17878          goto decode_success;
   17879       }
   17880    }
   17881 
   17882    /* -------------- (T1) MRS reg, apsr -------------- */
   17883    if (INSN0(15,0) == 0xF3EF
   17884        && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) {
   17885       UInt rD = INSN1(11,8);
   17886       if (!isBadRegT(rD)) {
   17887          IRTemp apsr = synthesise_APSR();
   17888          putIRegT( rD, mkexpr(apsr), condT );
   17889          DIP("mrs r%u, cpsr\n", rD);
   17890          goto decode_success;
   17891       }
   17892    }
   17893 
   17894    /* ----------------- (T1) LDREX ----------------- */
   17895    if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) {
   17896       UInt rN   = INSN0(3,0);
   17897       UInt rT   = INSN1(15,12);
   17898       UInt imm8 = INSN1(7,0);
   17899       if (!isBadRegT(rT) && rN != 15) {
   17900          IRTemp res;
   17901          // go uncond
   17902          mk_skip_over_T32_if_cond_is_false( condT );
   17903          // now uncond
   17904          res = newTemp(Ity_I32);
   17905          stmt( IRStmt_LLSC(Iend_LE,
   17906                            res,
   17907                            binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
   17908                            NULL/*this is a load*/ ));
   17909          putIRegT(rT, mkexpr(res), IRTemp_INVALID);
   17910          DIP("ldrex r%u, [r%u, #+%u]\n", rT, rN, imm8 * 4);
   17911          goto decode_success;
   17912       }
   17913    }
   17914 
   17915    /* --------------- (T1) LDREX{B,H} --------------- */
   17916    if (INSN0(15,4) == 0xE8D
   17917        && (INSN1(11,0) == 0xF4F || INSN1(11,0) == 0xF5F)) {
   17918       UInt rN  = INSN0(3,0);
   17919       UInt rT  = INSN1(15,12);
   17920       Bool isH = INSN1(11,0) == 0xF5F;
   17921       if (!isBadRegT(rT) && rN != 15) {
   17922          IRTemp res;
   17923          // go uncond
   17924          mk_skip_over_T32_if_cond_is_false( condT );
   17925          // now uncond
   17926          res = newTemp(isH ? Ity_I16 : Ity_I8);
   17927          stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN),
   17928                            NULL/*this is a load*/ ));
   17929          putIRegT(rT, unop(isH ? Iop_16Uto32 : Iop_8Uto32, mkexpr(res)),
   17930                       IRTemp_INVALID);
   17931          DIP("ldrex%c r%u, [r%u]\n", isH ? 'h' : 'b', rT, rN);
   17932          goto decode_success;
   17933       }
   17934    }
   17935 
   17936    /* --------------- (T1) LDREXD --------------- */
   17937    if (INSN0(15,4) == 0xE8D && INSN1(7,0) == 0x7F) {
   17938       UInt rN  = INSN0(3,0);
   17939       UInt rT  = INSN1(15,12);
   17940       UInt rT2 = INSN1(11,8);
   17941       if (!isBadRegT(rT) && !isBadRegT(rT2) && rT != rT2 && rN != 15) {
   17942          IRTemp res;
   17943          // go uncond
   17944          mk_skip_over_T32_if_cond_is_false( condT );
   17945          // now uncond
   17946          res = newTemp(Ity_I64);
   17947          // FIXME: assumes little-endian guest
   17948          stmt( IRStmt_LLSC(Iend_LE, res, getIRegT(rN),
   17949                            NULL/*this is a load*/ ));
   17950          // FIXME: assumes little-endian guest
   17951          putIRegT(rT,  unop(Iop_64to32,   mkexpr(res)), IRTemp_INVALID);
   17952          putIRegT(rT2, unop(Iop_64HIto32, mkexpr(res)), IRTemp_INVALID);
   17953          DIP("ldrexd r%u, r%u, [r%u]\n", rT, rT2, rN);
   17954          goto decode_success;
   17955       }
   17956    }
   17957 
   17958    /* ----------------- (T1) STREX ----------------- */
   17959    if (INSN0(15,4) == 0xE84) {
   17960       UInt rN   = INSN0(3,0);
   17961       UInt rT   = INSN1(15,12);
   17962       UInt rD   = INSN1(11,8);
   17963       UInt imm8 = INSN1(7,0);
   17964       if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15
   17965           && rD != rN && rD != rT) {
   17966          IRTemp resSC1, resSC32;
   17967          // go uncond
   17968          mk_skip_over_T32_if_cond_is_false( condT );
   17969          // now uncond
   17970          /* Ok, now we're unconditional.  Do the store. */
   17971          resSC1 = newTemp(Ity_I1);
   17972          stmt( IRStmt_LLSC(Iend_LE,
   17973                            resSC1,
   17974                            binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
   17975                            getIRegT(rT)) );
   17976          /* Set rD to 1 on failure, 0 on success.  Currently we have
   17977             resSC1 == 0 on failure, 1 on success. */
   17978          resSC32 = newTemp(Ity_I32);
   17979          assign(resSC32,
   17980                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   17981          putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
   17982          DIP("strex r%u, r%u, [r%u, #+%u]\n", rD, rT, rN, imm8 * 4);
   17983          goto decode_success;
   17984       }
   17985    }
   17986 
   17987    /* --------------- (T1) STREX{B,H} --------------- */
   17988    if (INSN0(15,4) == 0xE8C
   17989        && (INSN1(11,4) == 0xF4 || INSN1(11,4) == 0xF5)) {
   17990       UInt rN  = INSN0(3,0);
   17991       UInt rT  = INSN1(15,12);
   17992       UInt rD  = INSN1(3,0);
   17993       Bool isH = INSN1(11,4) == 0xF5;
   17994       if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15
   17995           && rD != rN && rD != rT) {
   17996          IRTemp resSC1, resSC32;
   17997          // go uncond
   17998          mk_skip_over_T32_if_cond_is_false( condT );
   17999          // now uncond
   18000          /* Ok, now we're unconditional.  Do the store. */
   18001          resSC1 = newTemp(Ity_I1);
   18002          stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN),
   18003                            unop(isH ? Iop_32to16 : Iop_32to8,
   18004                                 getIRegT(rT))) );
   18005          /* Set rD to 1 on failure, 0 on success.  Currently we have
   18006             resSC1 == 0 on failure, 1 on success. */
   18007          resSC32 = newTemp(Ity_I32);
   18008          assign(resSC32,
   18009                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   18010          putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
   18011          DIP("strex%c r%u, r%u, [r%u]\n", isH ? 'h' : 'b', rD, rT, rN);
   18012          goto decode_success;
   18013       }
   18014    }
   18015 
   18016    /* ---------------- (T1) STREXD ---------------- */
   18017    if (INSN0(15,4) == 0xE8C && INSN1(7,4) == BITS4(0,1,1,1)) {
   18018       UInt rN  = INSN0(3,0);
   18019       UInt rT  = INSN1(15,12);
   18020       UInt rT2 = INSN1(11,8);
   18021       UInt rD  = INSN1(3,0);
   18022       if (!isBadRegT(rD) && !isBadRegT(rT) && !isBadRegT(rT2)
   18023           && rN != 15 && rD != rN && rD != rT && rD != rT) {
   18024          IRTemp resSC1, resSC32, data;
   18025          // go uncond
   18026          mk_skip_over_T32_if_cond_is_false( condT );
   18027          // now uncond
   18028          /* Ok, now we're unconditional.  Do the store. */
   18029          resSC1 = newTemp(Ity_I1);
   18030          data = newTemp(Ity_I64);
   18031          // FIXME: assumes little-endian guest
   18032          assign(data, binop(Iop_32HLto64, getIRegT(rT2), getIRegT(rT)));
   18033          // FIXME: assumes little-endian guest
   18034          stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegT(rN), mkexpr(data)));
   18035          /* Set rD to 1 on failure, 0 on success.  Currently we have
   18036             resSC1 == 0 on failure, 1 on success. */
   18037          resSC32 = newTemp(Ity_I32);
   18038          assign(resSC32,
   18039                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   18040          putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
   18041          DIP("strexd r%u, r%u, r%u, [r%u]\n", rD, rT, rT2, rN);
   18042          goto decode_success;
   18043       }
   18044    }
   18045    /* -------------- v7 barrier insns -------------- */
   18046    if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) {
   18047       /* FIXME: should this be unconditional? */
   18048       /* XXX this isn't really right, is it?  The generated IR does
   18049          them unconditionally.  I guess it doesn't matter since it
   18050          doesn't do any harm to do them even when the guarding
   18051          condition is false -- it's just a performance loss. */
   18052       switch (INSN1(7,0)) {
   18053          case 0x4F: /* DSB sy */
   18054          case 0x4E: /* DSB st */
   18055          case 0x4B: /* DSB ish */
   18056          case 0x4A: /* DSB ishst */
   18057          case 0x47: /* DSB nsh */
   18058          case 0x46: /* DSB nshst */
   18059          case 0x43: /* DSB osh */
   18060          case 0x42: /* DSB oshst */
   18061             stmt( IRStmt_MBE(Imbe_Fence) );
   18062             DIP("DSB\n");
   18063             goto decode_success;
   18064          case 0x5F: /* DMB sy */
   18065          case 0x5E: /* DMB st */
   18066          case 0x5B: /* DMB ish */
   18067          case 0x5A: /* DMB ishst */
   18068          case 0x57: /* DMB nsh */
   18069          case 0x56: /* DMB nshst */
   18070          case 0x53: /* DMB osh */
   18071          case 0x52: /* DMB oshst */
   18072             stmt( IRStmt_MBE(Imbe_Fence) );
   18073             DIP("DMB\n");
   18074             goto decode_success;
   18075          case 0x6F: /* ISB */
   18076             stmt( IRStmt_MBE(Imbe_Fence) );
   18077             DIP("ISB\n");
   18078             goto decode_success;
   18079          default:
   18080             break;
   18081       }
   18082    }
   18083 
   18084    /* ---------------------- PLD{,W} ---------------------- */
   18085    if ((INSN0(15,4) & 0xFFD) == 0xF89 && INSN1(15,12) == 0xF) {
   18086       /* FIXME: should this be unconditional? */
   18087       /* PLD/PLDW immediate, encoding T1 */
   18088       UInt rN    = INSN0(3,0);
   18089       UInt bW    = INSN0(5,5);
   18090       UInt imm12 = INSN1(11,0);
   18091       DIP("pld%s [r%u, #%u]\n", bW ? "w" : "",  rN, imm12);
   18092       goto decode_success;
   18093    }
   18094 
   18095    if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,8) == 0xFC) {
   18096       /* FIXME: should this be unconditional? */
   18097       /* PLD/PLDW immediate, encoding T2 */
   18098       UInt rN    = INSN0(3,0);
   18099       UInt bW    = INSN0(5,5);
   18100       UInt imm8  = INSN1(7,0);
   18101       DIP("pld%s [r%u, #-%u]\n", bW ? "w" : "",  rN, imm8);
   18102       goto decode_success;
   18103    }
   18104 
   18105    if ((INSN0(15,4) & 0xFFD) == 0xF81 && INSN1(15,6) == 0x3C0) {
   18106       /* FIXME: should this be unconditional? */
   18107       /* PLD/PLDW register, encoding T1 */
   18108       UInt rN   = INSN0(3,0);
   18109       UInt rM   = INSN1(3,0);
   18110       UInt bW   = INSN0(5,5);
   18111       UInt imm2 = INSN1(5,4);
   18112       if (!isBadRegT(rM)) {
   18113          DIP("pld%s [r%u, r%u, lsl %d]\n", bW ? "w" : "", rN, rM, imm2);
   18114          goto decode_success;
   18115       }
   18116       /* fall through */
   18117    }
   18118 
   18119    /* -------------- read CP15 TPIDRURO register ------------- */
   18120    /* mrc     p15, 0,  r0, c13, c0, 3  up to
   18121       mrc     p15, 0, r14, c13, c0, 3
   18122    */
   18123    /* I don't know whether this is really v7-only.  But anyway, we
   18124       have to support it since arm-linux uses TPIDRURO as a thread
   18125       state register. */
   18126    if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
   18127       /* FIXME: should this be unconditional? */
   18128       UInt rD = INSN1(15,12);
   18129       if (!isBadRegT(rD)) {
   18130          putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID);
   18131          DIP("mrc p15,0, r%u, c13, c0, 3\n", rD);
   18132          goto decode_success;
   18133       }
   18134       /* fall through */
   18135    }
   18136 
   18137    /* ------------------- CLREX ------------------ */
   18138    if (INSN0(15,0) == 0xF3BF && INSN1(15,0) == 0x8F2F) {
   18139       /* AFAICS, this simply cancels a (all?) reservations made by a
   18140          (any?) preceding LDREX(es).  Arrange to hand it through to
   18141          the back end. */
   18142       mk_skip_over_T32_if_cond_is_false( condT );
   18143       stmt( IRStmt_MBE(Imbe_CancelReservation) );
   18144       DIP("clrex\n");
   18145       goto decode_success;
   18146    }
   18147 
   18148    /* ------------------- NOP ------------------ */
   18149    if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
   18150       DIP("nop\n");
   18151       goto decode_success;
   18152    }
   18153 
   18154    /* ----------------------------------------------------------- */
   18155    /* -- VFP (CP 10, CP 11) instructions (in Thumb mode)       -- */
   18156    /* ----------------------------------------------------------- */
   18157 
   18158    if (INSN0(15,12) == BITS4(1,1,1,0)) {
   18159       UInt insn28 = (INSN0(11,0) << 16) | INSN1(15,0);
   18160       Bool ok_vfp = decode_CP10_CP11_instruction (
   18161                        &dres, insn28, condT, ARMCondAL/*bogus*/,
   18162                        True/*isT*/
   18163                     );
   18164       if (ok_vfp)
   18165          goto decode_success;
   18166    }
   18167 
   18168    /* ----------------------------------------------------------- */
   18169    /* -- NEON instructions (in Thumb mode)                     -- */
   18170    /* ----------------------------------------------------------- */
   18171 
   18172    if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
   18173       UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
   18174       Bool ok_neon = decode_NEON_instruction(
   18175                         &dres, insn32, condT, True/*isT*/
   18176                      );
   18177       if (ok_neon)
   18178          goto decode_success;
   18179    }
   18180 
   18181    /* ----------------------------------------------------------- */
   18182    /* -- v6 media instructions (in Thumb mode)                 -- */
   18183    /* ----------------------------------------------------------- */
   18184 
   18185    { UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
   18186      Bool ok_v6m = decode_V6MEDIA_instruction(
   18187                       &dres, insn32, condT, ARMCondAL/*bogus*/,
   18188                       True/*isT*/
   18189                    );
   18190      if (ok_v6m)
   18191         goto decode_success;
   18192    }
   18193 
   18194    /* ----------------------------------------------------------- */
   18195    /* -- Undecodable                                           -- */
   18196    /* ----------------------------------------------------------- */
   18197 
   18198    goto decode_failure;
   18199    /*NOTREACHED*/
   18200 
   18201   decode_failure:
   18202    /* All decode failures end up here. */
   18203    vex_printf("disInstr(thumb): unhandled instruction: "
   18204               "0x%04x 0x%04x\n", (UInt)insn0, (UInt)insn1);
   18205 
   18206    /* Back up ITSTATE to the initial value for this instruction.
   18207       If we don't do that, any subsequent restart of the instruction
   18208       will restart with the wrong value. */
   18209    put_ITSTATE(old_itstate);
   18210    /* Tell the dispatcher that this insn cannot be decoded, and so has
   18211       not been executed, and (is currently) the next to be executed.
   18212       R15 should be up-to-date since it made so at the start of each
   18213       insn, but nevertheless be paranoid and update it again right
   18214       now. */
   18215    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   18216    llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
   18217    irsb->next     = mkU32(guest_R15_curr_instr_notENC | 1 /* CPSR.T */);
   18218    irsb->jumpkind = Ijk_NoDecode;
   18219    dres.whatNext  = Dis_StopHere;
   18220    dres.len       = 0;
   18221    return dres;
   18222 
   18223   decode_success:
   18224    /* All decode successes end up here. */
   18225    DIP("\n");
   18226 
   18227    vassert(dres.len == 2 || dres.len == 4 || dres.len == 20);
   18228 
   18229 #if 0
   18230    // XXX is this necessary on Thumb?
   18231    /* Now then.  Do we have an implicit jump to r15 to deal with? */
   18232    if (r15written) {
   18233       /* If we get jump to deal with, we assume that there's been no
   18234          other competing branch stuff previously generated for this
   18235          insn.  That's reasonable, in the sense that the ARM insn set
   18236          appears to declare as "Unpredictable" any instruction which
   18237          generates more than one possible new value for r15.  Hence
   18238          just assert.  The decoders themselves should check against
   18239          all such instructions which are thusly Unpredictable, and
   18240          decline to decode them.  Hence we should never get here if we
   18241          have competing new values for r15, and hence it is safe to
   18242          assert here. */
   18243       vassert(dres.whatNext == Dis_Continue);
   18244       vassert(irsb->next == NULL);
   18245       vassert(irsb->jumpkind == Ijk_Boring);
   18246       /* If r15 is unconditionally written, terminate the block by
   18247          jumping to it.  If it's conditionally written, still
   18248          terminate the block (a shame, but we can't do side exits to
   18249          arbitrary destinations), but first jump to the next
   18250          instruction if the condition doesn't hold. */
   18251       /* We can't use getIRegT(15) to get the destination, since that
   18252          will produce r15+4, which isn't what we want.  Must use
   18253          llGetIReg(15) instead. */
   18254       if (r15guard == IRTemp_INVALID) {
   18255          /* unconditional */
   18256       } else {
   18257          /* conditional */
   18258          stmt( IRStmt_Exit(
   18259                   unop(Iop_32to1,
   18260                        binop(Iop_Xor32,
   18261                              mkexpr(r15guard), mkU32(1))),
   18262                   r15kind,
   18263                   IRConst_U32(guest_R15_curr_instr_notENC + 4)
   18264          ));
   18265       }
   18266       irsb->next     = llGetIReg(15);
   18267       irsb->jumpkind = r15kind;
   18268       dres.whatNext  = Dis_StopHere;
   18269    }
   18270 #endif
   18271 
   18272    return dres;
   18273 
   18274 #  undef INSN0
   18275 #  undef INSN1
   18276 }
   18277 
   18278 #undef DIP
   18279 #undef DIS
   18280 
   18281 
   18282 /* Helper table for figuring out how many insns an IT insn
   18283    conditionalises.
   18284 
   18285    An ITxyz instruction of the format "1011 1111 firstcond mask"
   18286    conditionalises some number of instructions, as indicated by the
   18287    following table.  A value of zero indicates the instruction is
   18288    invalid in some way.
   18289 
   18290    mask = 0 means this isn't an IT instruction
   18291    fc = 15 (NV) means unpredictable
   18292 
   18293    The line fc = 14 (AL) is different from the others; there are
   18294    additional constraints in this case.
   18295 
   18296           mask(0 ..                   15)
   18297         +--------------------------------
   18298    fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18299    ..   | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18300         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18301         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18302         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18303         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18304         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18305         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18306         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18307         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18308         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18309         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18310         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18311         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18312         | 0 4 3 0 2 0 0 0 1 0 0 0 0 0 0 0
   18313    15)  | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
   18314 
   18315    To be conservative with the analysis, let's rule out the mask = 0
   18316    case, since that isn't an IT insn at all.  But for all the other
   18317    cases where the table contains zero, that means unpredictable, so
   18318    let's say 4 to be conservative.  Hence we have a safe value for any
   18319    IT (mask,fc) pair that the CPU would actually identify as an IT
   18320    instruction.  The final table is
   18321 
   18322           mask(0 ..                   15)
   18323         +--------------------------------
   18324    fc(0 | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18325    ..   | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18326         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18327         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18328         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18329         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18330         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18331         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18332         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18333         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18334         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18335         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18336         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18337         | 0 4 3 4 2 4 3 4 1 4 3 4 2 4 3 4
   18338         | 0 4 3 4 2 4 4 4 1 4 4 4 4 4 4 4
   18339    15)  | 0 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
   18340 */
   18341 static const UChar it_length_table[256]
   18342    = { 0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18343        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18344        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18345        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18346        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18347        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18348        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18349        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18350        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18351        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18352        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18353        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18354        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18355        0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4,
   18356        0, 4, 3, 4, 2, 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, 4,
   18357        0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
   18358      };
   18359 
   18360 
   18361 /*------------------------------------------------------------*/
   18362 /*--- Top-level fn                                         ---*/
   18363 /*------------------------------------------------------------*/
   18364 
   18365 /* Disassemble a single instruction into IR.  The instruction
   18366    is located in host memory at &guest_code[delta]. */
   18367 
   18368 DisResult disInstr_ARM ( IRSB*        irsb_IN,
   18369                          Bool         put_IP,
   18370                          Bool         (*resteerOkFn) ( void*, Addr64 ),
   18371                          Bool         resteerCisOk,
   18372                          void*        callback_opaque,
   18373                          UChar*       guest_code_IN,
   18374                          Long         delta_ENCODED,
   18375                          Addr64       guest_IP_ENCODED,
   18376                          VexArch      guest_arch,
   18377                          VexArchInfo* archinfo,
   18378                          VexAbiInfo*  abiinfo,
   18379                          Bool         host_bigendian_IN )
   18380 {
   18381    DisResult dres;
   18382    Bool isThumb = (Bool)(guest_IP_ENCODED & 1);
   18383 
   18384    /* Set globals (see top of this file) */
   18385    vassert(guest_arch == VexArchARM);
   18386 
   18387    irsb              = irsb_IN;
   18388    host_is_bigendian = host_bigendian_IN;
   18389    __curr_is_Thumb   = isThumb;
   18390 
   18391    if (isThumb) {
   18392       guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED - 1;
   18393    } else {
   18394       guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED;
   18395    }
   18396 
   18397    if (isThumb) {
   18398       dres = disInstr_THUMB_WRK ( put_IP, resteerOkFn,
   18399                                   resteerCisOk, callback_opaque,
   18400                                   &guest_code_IN[delta_ENCODED - 1],
   18401                                   archinfo, abiinfo );
   18402    } else {
   18403       dres = disInstr_ARM_WRK ( put_IP, resteerOkFn,
   18404                                 resteerCisOk, callback_opaque,
   18405                                 &guest_code_IN[delta_ENCODED],
   18406                                 archinfo, abiinfo );
   18407    }
   18408 
   18409    return dres;
   18410 }
   18411 
   18412 /* Test program for the conversion of IRCmpF64Result values to VFP
   18413    nzcv values.  See handling of FCMPD et al above. */
   18414 /*
   18415 UInt foo ( UInt x )
   18416 {
   18417    UInt ix    = ((x >> 5) & 3) | (x & 1);
   18418    UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1);
   18419    UInt termR = (ix & (ix >> 1) & 1);
   18420    return termL  -  termR;
   18421 }
   18422 
   18423 void try ( char* s, UInt ir, UInt req )
   18424 {
   18425    UInt act = foo(ir);
   18426    printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n",
   18427           s, ir, (req >> 3) & 1, (req >> 2) & 1,
   18428                  (req >> 1) & 1, (req >> 0) & 1,
   18429                  (act >> 3) & 1, (act >> 2) & 1,
   18430                  (act >> 1) & 1, (act >> 0) & 1, act);
   18431 
   18432 }
   18433 
   18434 int main ( void )
   18435 {
   18436    printf("\n");
   18437    try("UN", 0x45, 0b0011);
   18438    try("LT", 0x01, 0b1000);
   18439    try("GT", 0x00, 0b0010);
   18440    try("EQ", 0x40, 0b0110);
   18441    printf("\n");
   18442    return 0;
   18443 }
   18444 */
   18445 
   18446 /*--------------------------------------------------------------------*/
   18447 /*--- end                                         guest_arm_toIR.c ---*/
   18448 /*--------------------------------------------------------------------*/
   18449