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-2010 OpenWorks LLP
     11       info (at) open-works.net
     12 
     13    NEON support is
     14    Copyright (C) 2010-2010 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
   1092       bits are nonzero.  However, obviously we can't assert for
   1093       that. */
   1094 
   1095    /* So what we're constructing for the first argument is
   1096       "(cond << 4) | stored-operation-operation".  However,
   1097       as per comments above, must be supplied pre-shifted to this
   1098       function.
   1099 
   1100       This pairing scheme requires that the ARM_CC_OP_ values all fit
   1101       in 4 bits.  Hence we are passing a (COND, OP) pair in the lowest
   1102       8 bits of the first argument. */
   1103    IRExpr** args
   1104       = mkIRExprVec_4(
   1105            binop(Iop_Or32, IRExpr_Get(OFFB_CC_OP, Ity_I32), cond),
   1106            IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
   1107            IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
   1108            IRExpr_Get(OFFB_CC_NDEP, Ity_I32)
   1109         );
   1110    IRExpr* call
   1111       = mkIRExprCCall(
   1112            Ity_I32,
   1113            0/*regparm*/,
   1114            "armg_calculate_condition", &armg_calculate_condition,
   1115            args
   1116         );
   1117 
   1118    /* Exclude the requested condition, OP and NDEP from definedness
   1119       checking.  We're only interested in DEP1 and DEP2. */
   1120    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
   1121    return call;
   1122 }
   1123 
   1124 
   1125 /* Build IR to calculate some particular condition from stored
   1126    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression of type
   1127    Ity_I32, suitable for narrowing.  Although the return type is
   1128    Ity_I32, the returned value is either 0 or 1.
   1129 */
   1130 static IRExpr* mk_armg_calculate_condition ( ARMCondcode cond )
   1131 {
   1132   /* First arg is "(cond << 4) | condition".  This requires that the
   1133      ARM_CC_OP_ values all fit in 4 bits.  Hence we are passing a
   1134      (COND, OP) pair in the lowest 8 bits of the first argument. */
   1135    vassert(cond >= 0 && cond <= 15);
   1136    return mk_armg_calculate_condition_dyn( mkU32(cond << 4) );
   1137 }
   1138 
   1139 
   1140 /* Build IR to calculate just the carry flag from stored
   1141    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
   1142    Ity_I32. */
   1143 static IRExpr* mk_armg_calculate_flag_c ( void )
   1144 {
   1145    IRExpr** args
   1146       = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
   1147                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
   1148                        IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
   1149                        IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
   1150    IRExpr* call
   1151       = mkIRExprCCall(
   1152            Ity_I32,
   1153            0/*regparm*/,
   1154            "armg_calculate_flag_c", &armg_calculate_flag_c,
   1155            args
   1156         );
   1157    /* Exclude OP and NDEP from definedness checking.  We're only
   1158       interested in DEP1 and DEP2. */
   1159    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
   1160    return call;
   1161 }
   1162 
   1163 
   1164 /* Build IR to calculate just the overflow flag from stored
   1165    CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
   1166    Ity_I32. */
   1167 static IRExpr* mk_armg_calculate_flag_v ( void )
   1168 {
   1169    IRExpr** args
   1170       = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
   1171                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
   1172                        IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
   1173                        IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
   1174    IRExpr* call
   1175       = mkIRExprCCall(
   1176            Ity_I32,
   1177            0/*regparm*/,
   1178            "armg_calculate_flag_v", &armg_calculate_flag_v,
   1179            args
   1180         );
   1181    /* Exclude OP and NDEP from definedness checking.  We're only
   1182       interested in DEP1 and DEP2. */
   1183    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
   1184    return call;
   1185 }
   1186 
   1187 
   1188 /* Build IR to calculate N Z C V in bits 31:28 of the
   1189    returned word. */
   1190 static IRExpr* mk_armg_calculate_flags_nzcv ( void )
   1191 {
   1192    IRExpr** args
   1193       = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
   1194                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
   1195                        IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
   1196                        IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
   1197    IRExpr* call
   1198       = mkIRExprCCall(
   1199            Ity_I32,
   1200            0/*regparm*/,
   1201            "armg_calculate_flags_nzcv", &armg_calculate_flags_nzcv,
   1202            args
   1203         );
   1204    /* Exclude OP and NDEP from definedness checking.  We're only
   1205       interested in DEP1 and DEP2. */
   1206    call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
   1207    return call;
   1208 }
   1209 
   1210 static IRExpr* mk_armg_calculate_flag_qc ( IRExpr* resL, IRExpr* resR, Bool Q )
   1211 {
   1212    IRExpr** args1;
   1213    IRExpr** args2;
   1214    IRExpr *call1, *call2, *res;
   1215 
   1216    if (Q) {
   1217       args1 = mkIRExprVec_4 ( binop(Iop_GetElem32x4, resL, mkU8(0)),
   1218                               binop(Iop_GetElem32x4, resL, mkU8(1)),
   1219                               binop(Iop_GetElem32x4, resR, mkU8(0)),
   1220                               binop(Iop_GetElem32x4, resR, mkU8(1)) );
   1221       args2 = mkIRExprVec_4 ( binop(Iop_GetElem32x4, resL, mkU8(2)),
   1222                               binop(Iop_GetElem32x4, resL, mkU8(3)),
   1223                               binop(Iop_GetElem32x4, resR, mkU8(2)),
   1224                               binop(Iop_GetElem32x4, resR, mkU8(3)) );
   1225    } else {
   1226       args1 = mkIRExprVec_4 ( binop(Iop_GetElem32x2, resL, mkU8(0)),
   1227                               binop(Iop_GetElem32x2, resL, mkU8(1)),
   1228                               binop(Iop_GetElem32x2, resR, mkU8(0)),
   1229                               binop(Iop_GetElem32x2, resR, mkU8(1)) );
   1230    }
   1231 
   1232 #if 1
   1233    call1 = mkIRExprCCall(
   1234              Ity_I32,
   1235              0/*regparm*/,
   1236              "armg_calculate_flag_qc", &armg_calculate_flag_qc,
   1237              args1
   1238           );
   1239    if (Q) {
   1240       call2 = mkIRExprCCall(
   1241                 Ity_I32,
   1242                 0/*regparm*/,
   1243                 "armg_calculate_flag_qc", &armg_calculate_flag_qc,
   1244                 args2
   1245              );
   1246    }
   1247    if (Q) {
   1248       res = binop(Iop_Or32, call1, call2);
   1249    } else {
   1250       res = call1;
   1251    }
   1252 #else
   1253    if (Q) {
   1254       res = unop(Iop_1Uto32,
   1255                  binop(Iop_CmpNE32,
   1256                        binop(Iop_Or32,
   1257                              binop(Iop_Or32,
   1258                                    binop(Iop_Xor32,
   1259                                          args1[0],
   1260                                          args1[2]),
   1261                                    binop(Iop_Xor32,
   1262                                          args1[1],
   1263                                          args1[3])),
   1264                              binop(Iop_Or32,
   1265                                    binop(Iop_Xor32,
   1266                                          args2[0],
   1267                                          args2[2]),
   1268                                    binop(Iop_Xor32,
   1269                                          args2[1],
   1270                                          args2[3]))),
   1271                        mkU32(0)));
   1272    } else {
   1273       res = unop(Iop_1Uto32,
   1274                  binop(Iop_CmpNE32,
   1275                        binop(Iop_Or32,
   1276                              binop(Iop_Xor32,
   1277                                    args1[0],
   1278                                    args1[2]),
   1279                              binop(Iop_Xor32,
   1280                                    args1[1],
   1281                                    args1[3])),
   1282                        mkU32(0)));
   1283    }
   1284 #endif
   1285    return res;
   1286 }
   1287 
   1288 // FIXME: this is named wrongly .. looks like a sticky set of
   1289 // QC, not a write to it.
   1290 static void setFlag_QC ( IRExpr* resL, IRExpr* resR, Bool Q,
   1291                          IRTemp condT )
   1292 {
   1293    putMiscReg32 (OFFB_FPSCR,
   1294                  binop(Iop_Or32,
   1295                        IRExpr_Get(OFFB_FPSCR, Ity_I32),
   1296                        binop(Iop_Shl32,
   1297                              mk_armg_calculate_flag_qc(resL, resR, Q),
   1298                              mkU8(27))),
   1299                  condT);
   1300 }
   1301 
   1302 /* Build IR to conditionally set the flags thunk.  As with putIReg, if
   1303    guard is IRTemp_INVALID then it's unconditional, else it holds a
   1304    condition :: Ity_I32. */
   1305 static
   1306 void setFlags_D1_D2_ND ( UInt cc_op, IRTemp t_dep1,
   1307                          IRTemp t_dep2, IRTemp t_ndep,
   1308                          IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
   1309 {
   1310    IRTemp c8;
   1311    vassert(typeOfIRTemp(irsb->tyenv, t_dep1 == Ity_I32));
   1312    vassert(typeOfIRTemp(irsb->tyenv, t_dep2 == Ity_I32));
   1313    vassert(typeOfIRTemp(irsb->tyenv, t_ndep == Ity_I32));
   1314    vassert(cc_op >= ARMG_CC_OP_COPY && cc_op < ARMG_CC_OP_NUMBER);
   1315    if (guardT == IRTemp_INVALID) {
   1316       /* unconditional */
   1317       stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(cc_op) ));
   1318       stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(t_dep1) ));
   1319       stmt( IRStmt_Put( OFFB_CC_DEP2, mkexpr(t_dep2) ));
   1320       stmt( IRStmt_Put( OFFB_CC_NDEP, mkexpr(t_ndep) ));
   1321    } else {
   1322       /* conditional */
   1323       c8 = newTemp(Ity_I8);
   1324       assign( c8, unop(Iop_32to8, mkexpr(guardT)) );
   1325       stmt( IRStmt_Put(
   1326                OFFB_CC_OP,
   1327                IRExpr_Mux0X( mkexpr(c8),
   1328                              IRExpr_Get(OFFB_CC_OP, Ity_I32),
   1329                              mkU32(cc_op) )));
   1330       stmt( IRStmt_Put(
   1331                OFFB_CC_DEP1,
   1332                IRExpr_Mux0X( mkexpr(c8),
   1333                              IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
   1334                              mkexpr(t_dep1) )));
   1335       stmt( IRStmt_Put(
   1336                OFFB_CC_DEP2,
   1337                IRExpr_Mux0X( mkexpr(c8),
   1338                              IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
   1339                              mkexpr(t_dep2) )));
   1340       stmt( IRStmt_Put(
   1341                OFFB_CC_NDEP,
   1342                IRExpr_Mux0X( mkexpr(c8),
   1343                              IRExpr_Get(OFFB_CC_NDEP, Ity_I32),
   1344                              mkexpr(t_ndep) )));
   1345    }
   1346 }
   1347 
   1348 
   1349 /* Minor variant of the above that sets NDEP to zero (if it
   1350    sets it at all) */
   1351 static void setFlags_D1_D2 ( UInt cc_op, IRTemp t_dep1,
   1352                              IRTemp t_dep2,
   1353                              IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
   1354 {
   1355    IRTemp z32 = newTemp(Ity_I32);
   1356    assign( z32, mkU32(0) );
   1357    setFlags_D1_D2_ND( cc_op, t_dep1, t_dep2, z32, guardT );
   1358 }
   1359 
   1360 
   1361 /* Minor variant of the above that sets DEP2 to zero (if it
   1362    sets it at all) */
   1363 static void setFlags_D1_ND ( UInt cc_op, IRTemp t_dep1,
   1364                              IRTemp t_ndep,
   1365                              IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
   1366 {
   1367    IRTemp z32 = newTemp(Ity_I32);
   1368    assign( z32, mkU32(0) );
   1369    setFlags_D1_D2_ND( cc_op, t_dep1, z32, t_ndep, guardT );
   1370 }
   1371 
   1372 
   1373 /* Minor variant of the above that sets DEP2 and NDEP to zero (if it
   1374    sets them at all) */
   1375 static void setFlags_D1 ( UInt cc_op, IRTemp t_dep1,
   1376                           IRTemp guardT /* :: Ity_I32, 0 or 1 */ )
   1377 {
   1378    IRTemp z32 = newTemp(Ity_I32);
   1379    assign( z32, mkU32(0) );
   1380    setFlags_D1_D2_ND( cc_op, t_dep1, z32, z32, guardT );
   1381 }
   1382 
   1383 
   1384 /* ARM only */
   1385 /* Generate a side-exit to the next instruction, if the given guard
   1386    expression :: Ity_I32 is 0 (note!  the side exit is taken if the
   1387    condition is false!)  This is used to skip over conditional
   1388    instructions which we can't generate straight-line code for, either
   1389    because they are too complex or (more likely) they potentially
   1390    generate exceptions.
   1391 */
   1392 static void mk_skip_over_A32_if_cond_is_false (
   1393                IRTemp guardT /* :: Ity_I32, 0 or 1 */
   1394             )
   1395 {
   1396    ASSERT_IS_ARM;
   1397    vassert(guardT != IRTemp_INVALID);
   1398    vassert(0 == (guest_R15_curr_instr_notENC & 3));
   1399    stmt( IRStmt_Exit(
   1400             unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
   1401             Ijk_Boring,
   1402             IRConst_U32(toUInt(guest_R15_curr_instr_notENC + 4))
   1403        ));
   1404 }
   1405 
   1406 /* Thumb16 only */
   1407 /* ditto, but jump over a 16-bit thumb insn */
   1408 static void mk_skip_over_T16_if_cond_is_false (
   1409                IRTemp guardT /* :: Ity_I32, 0 or 1 */
   1410             )
   1411 {
   1412    ASSERT_IS_THUMB;
   1413    vassert(guardT != IRTemp_INVALID);
   1414    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   1415    stmt( IRStmt_Exit(
   1416             unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
   1417             Ijk_Boring,
   1418             IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 2) | 1))
   1419        ));
   1420 }
   1421 
   1422 
   1423 /* Thumb32 only */
   1424 /* ditto, but jump over a 32-bit thumb insn */
   1425 static void mk_skip_over_T32_if_cond_is_false (
   1426                IRTemp guardT /* :: Ity_I32, 0 or 1 */
   1427             )
   1428 {
   1429    ASSERT_IS_THUMB;
   1430    vassert(guardT != IRTemp_INVALID);
   1431    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   1432    stmt( IRStmt_Exit(
   1433             unop(Iop_Not1, unop(Iop_32to1, mkexpr(guardT))),
   1434             Ijk_Boring,
   1435             IRConst_U32(toUInt((guest_R15_curr_instr_notENC + 4) | 1))
   1436        ));
   1437 }
   1438 
   1439 
   1440 /* Thumb16 and Thumb32 only
   1441    Generate a SIGILL followed by a restart of the current instruction
   1442    if the given temp is nonzero. */
   1443 static void gen_SIGILL_T_if_nonzero ( IRTemp t /* :: Ity_I32 */ )
   1444 {
   1445    ASSERT_IS_THUMB;
   1446    vassert(t != IRTemp_INVALID);
   1447    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   1448    stmt(
   1449       IRStmt_Exit(
   1450          binop(Iop_CmpNE32, mkexpr(t), mkU32(0)),
   1451          Ijk_NoDecode,
   1452          IRConst_U32(toUInt(guest_R15_curr_instr_notENC | 1))
   1453       )
   1454    );
   1455 }
   1456 
   1457 
   1458 /* Inspect the old_itstate, and generate a SIGILL if it indicates that
   1459    we are currently in an IT block and are not the last in the block.
   1460    This also rolls back guest_ITSTATE to its old value before the exit
   1461    and restores it to its new value afterwards.  This is so that if
   1462    the exit is taken, we have an up to date version of ITSTATE
   1463    available.  Without doing that, we have no hope of making precise
   1464    exceptions work. */
   1465 static void gen_SIGILL_T_if_in_but_NLI_ITBlock (
   1466                IRTemp old_itstate /* :: Ity_I32 */,
   1467                IRTemp new_itstate /* :: Ity_I32 */
   1468             )
   1469 {
   1470    ASSERT_IS_THUMB;
   1471    put_ITSTATE(old_itstate); // backout
   1472    IRTemp guards_for_next3 = newTemp(Ity_I32);
   1473    assign(guards_for_next3,
   1474           binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
   1475    gen_SIGILL_T_if_nonzero(guards_for_next3);
   1476    put_ITSTATE(new_itstate); //restore
   1477 }
   1478 
   1479 
   1480 /* Simpler version of the above, which generates a SIGILL if
   1481    we're anywhere within an IT block. */
   1482 static void gen_SIGILL_T_if_in_ITBlock (
   1483                IRTemp old_itstate /* :: Ity_I32 */,
   1484                IRTemp new_itstate /* :: Ity_I32 */
   1485             )
   1486 {
   1487    put_ITSTATE(old_itstate); // backout
   1488    gen_SIGILL_T_if_nonzero(old_itstate);
   1489    put_ITSTATE(new_itstate); //restore
   1490 }
   1491 
   1492 
   1493 /* Generate an APSR value, from the NZCV thunk, and
   1494    from QFLAG32 and GEFLAG0 .. GEFLAG3. */
   1495 static IRTemp synthesise_APSR ( void )
   1496 {
   1497    IRTemp res1 = newTemp(Ity_I32);
   1498    // Get NZCV
   1499    assign( res1, mk_armg_calculate_flags_nzcv() );
   1500    // OR in the Q value
   1501    IRTemp res2 = newTemp(Ity_I32);
   1502    assign(
   1503       res2,
   1504       binop(Iop_Or32,
   1505             mkexpr(res1),
   1506             binop(Iop_Shl32,
   1507                   unop(Iop_1Uto32,
   1508                        binop(Iop_CmpNE32,
   1509                              mkexpr(get_QFLAG32()),
   1510                              mkU32(0))),
   1511                   mkU8(ARMG_CC_SHIFT_Q)))
   1512    );
   1513    // OR in GE0 .. GE3
   1514    IRExpr* ge0
   1515       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(0), mkU32(0)));
   1516    IRExpr* ge1
   1517       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(1), mkU32(0)));
   1518    IRExpr* ge2
   1519       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(2), mkU32(0)));
   1520    IRExpr* ge3
   1521       = unop(Iop_1Uto32, binop(Iop_CmpNE32, get_GEFLAG32(3), mkU32(0)));
   1522    IRTemp res3 = newTemp(Ity_I32);
   1523    assign(res3,
   1524           binop(Iop_Or32,
   1525                 mkexpr(res2),
   1526                 binop(Iop_Or32,
   1527                       binop(Iop_Or32,
   1528                             binop(Iop_Shl32, ge0, mkU8(16)),
   1529                             binop(Iop_Shl32, ge1, mkU8(17))),
   1530                       binop(Iop_Or32,
   1531                             binop(Iop_Shl32, ge2, mkU8(18)),
   1532                             binop(Iop_Shl32, ge3, mkU8(19))) )));
   1533    return res3;
   1534 }
   1535 
   1536 
   1537 /* and the inverse transformation: given an APSR value,
   1538    set the NZCV thunk, the Q flag, and the GE flags. */
   1539 static void desynthesise_APSR ( Bool write_nzcvq, Bool write_ge,
   1540                                 IRTemp apsrT, IRTemp condT )
   1541 {
   1542    vassert(write_nzcvq || write_ge);
   1543    if (write_nzcvq) {
   1544       // Do NZCV
   1545       IRTemp immT = newTemp(Ity_I32);
   1546       assign(immT, binop(Iop_And32, mkexpr(apsrT), mkU32(0xF0000000)) );
   1547       setFlags_D1(ARMG_CC_OP_COPY, immT, condT);
   1548       // Do Q
   1549       IRTemp qnewT = newTemp(Ity_I32);
   1550       assign(qnewT, binop(Iop_And32, mkexpr(apsrT), mkU32(ARMG_CC_MASK_Q)));
   1551       put_QFLAG32(qnewT, condT);
   1552    }
   1553    if (write_ge) {
   1554       // Do GE3..0
   1555       put_GEFLAG32(0, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<16)),
   1556                    condT);
   1557       put_GEFLAG32(1, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<17)),
   1558                    condT);
   1559       put_GEFLAG32(2, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<18)),
   1560                    condT);
   1561       put_GEFLAG32(3, 0, binop(Iop_And32, mkexpr(apsrT), mkU32(1<<19)),
   1562                    condT);
   1563    }
   1564 }
   1565 
   1566 
   1567 /*------------------------------------------------------------*/
   1568 /*--- Helpers for saturation                               ---*/
   1569 /*------------------------------------------------------------*/
   1570 
   1571 /* FIXME: absolutely the only diff. between (a) armUnsignedSatQ and
   1572    (b) armSignedSatQ is that in (a) the floor is set to 0, whereas in
   1573    (b) the floor is computed from the value of imm5.  these two fnsn
   1574    should be commoned up. */
   1575 
   1576 /* UnsignedSatQ(): 'clamp' each value so it lies between 0 <= x <= (2^N)-1
   1577    Optionally return flag resQ saying whether saturation occurred.
   1578    See definition in manual, section A2.2.1, page 41
   1579    (bits(N), boolean) UnsignedSatQ( integer i, integer N )
   1580    {
   1581      if ( i > (2^N)-1 ) { result = (2^N)-1; saturated = TRUE; }
   1582      elsif ( i < 0 )    { result = 0; saturated = TRUE; }
   1583      else               { result = i; saturated = FALSE; }
   1584      return ( result<N-1:0>, saturated );
   1585    }
   1586 */
   1587 static void armUnsignedSatQ( IRTemp* res,  /* OUT - Ity_I32 */
   1588                              IRTemp* resQ, /* OUT - Ity_I32  */
   1589                              IRTemp regT,  /* value to clamp - Ity_I32 */
   1590                              UInt imm5 )   /* saturation ceiling */
   1591 {
   1592    UInt ceil  = (1 << imm5) - 1;    // (2^imm5)-1
   1593    UInt floor = 0;
   1594 
   1595    IRTemp node0 = newTemp(Ity_I32);
   1596    IRTemp node1 = newTemp(Ity_I32);
   1597    IRTemp node2 = newTemp(Ity_I1);
   1598    IRTemp node3 = newTemp(Ity_I32);
   1599    IRTemp node4 = newTemp(Ity_I32);
   1600    IRTemp node5 = newTemp(Ity_I1);
   1601    IRTemp node6 = newTemp(Ity_I32);
   1602 
   1603    assign( node0, mkexpr(regT) );
   1604    assign( node1, mkU32(ceil) );
   1605    assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
   1606    assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
   1607                                 mkexpr(node0),
   1608                                 mkexpr(node1) ) );
   1609    assign( node4, mkU32(floor) );
   1610    assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
   1611    assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
   1612                                 mkexpr(node3),
   1613                                 mkexpr(node4) ) );
   1614    assign( *res, mkexpr(node6) );
   1615 
   1616    /* if saturation occurred, then resQ is set to some nonzero value
   1617       if sat did not occur, resQ is guaranteed to be zero. */
   1618    if (resQ) {
   1619       assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
   1620    }
   1621 }
   1622 
   1623 
   1624 /* SignedSatQ(): 'clamp' each value so it lies between  -2^N <= x <= (2^N) - 1
   1625    Optionally return flag resQ saying whether saturation occurred.
   1626    - see definition in manual, section A2.2.1, page 41
   1627    (bits(N), boolean ) SignedSatQ( integer i, integer N )
   1628    {
   1629      if ( i > 2^(N-1) - 1 )    { result = 2^(N-1) - 1; saturated = TRUE; }
   1630      elsif ( i < -(2^(N-1)) )  { result = -(2^(N-1));  saturated = FALSE; }
   1631      else                      { result = i;           saturated = FALSE; }
   1632      return ( result[N-1:0], saturated );
   1633    }
   1634 */
   1635 static void armSignedSatQ( IRTemp regT,    /* value to clamp - Ity_I32 */
   1636                            UInt imm5,      /* saturation ceiling */
   1637                            IRTemp* res,    /* OUT - Ity_I32 */
   1638                            IRTemp* resQ )  /* OUT - Ity_I32  */
   1639 {
   1640    Int ceil  =  (1 << (imm5-1)) - 1;  //  (2^(imm5-1))-1
   1641    Int floor = -(1 << (imm5-1));      // -(2^(imm5-1))
   1642 
   1643    IRTemp node0 = newTemp(Ity_I32);
   1644    IRTemp node1 = newTemp(Ity_I32);
   1645    IRTemp node2 = newTemp(Ity_I1);
   1646    IRTemp node3 = newTemp(Ity_I32);
   1647    IRTemp node4 = newTemp(Ity_I32);
   1648    IRTemp node5 = newTemp(Ity_I1);
   1649    IRTemp node6 = newTemp(Ity_I32);
   1650 
   1651    assign( node0, mkexpr(regT) );
   1652    assign( node1, mkU32(ceil) );
   1653    assign( node2, binop( Iop_CmpLT32S, mkexpr(node1), mkexpr(node0) ) );
   1654    assign( node3, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node2)),
   1655                                 mkexpr(node0),  mkexpr(node1) ) );
   1656    assign( node4, mkU32(floor) );
   1657    assign( node5, binop( Iop_CmpLT32S, mkexpr(node3), mkexpr(node4) ) );
   1658    assign( node6, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(node5)),
   1659                                 mkexpr(node3),  mkexpr(node4) ) );
   1660    assign( *res, mkexpr(node6) );
   1661 
   1662    /* if saturation occurred, then resQ is set to some nonzero value
   1663       if sat did not occur, resQ is guaranteed to be zero. */
   1664    if (resQ) {
   1665      assign( *resQ, binop(Iop_Xor32, mkexpr(*res), mkexpr(regT)) );
   1666    }
   1667 }
   1668 
   1669 
   1670 /* Compute a value 0 :: I32 or 1 :: I32, indicating whether signed
   1671    overflow occurred for 32-bit addition.  Needs both args and the
   1672    result.  HD p27. */
   1673 static
   1674 IRExpr* signed_overflow_after_Add32 ( IRExpr* resE,
   1675                                       IRTemp argL, IRTemp argR )
   1676 {
   1677    IRTemp res = newTemp(Ity_I32);
   1678    assign(res, resE);
   1679    return
   1680       binop( Iop_Shr32,
   1681              binop( Iop_And32,
   1682                     binop( Iop_Xor32, mkexpr(res), mkexpr(argL) ),
   1683                     binop( Iop_Xor32, mkexpr(res), mkexpr(argR) )),
   1684              mkU8(31) );
   1685 }
   1686 
   1687 
   1688 /*------------------------------------------------------------*/
   1689 /*--- Larger helpers                                       ---*/
   1690 /*------------------------------------------------------------*/
   1691 
   1692 /* Compute both the result and new C flag value for a LSL by an imm5
   1693    or by a register operand.  May generate reads of the old C value
   1694    (hence only safe to use before any writes to guest state happen).
   1695    Are factored out so can be used by both ARM and Thumb.
   1696 
   1697    Note that in compute_result_and_C_after_{LSL,LSR,ASR}_by{imm5,reg},
   1698    "res" (the result)  is a.k.a. "shop", shifter operand
   1699    "newC" (the new C)  is a.k.a. "shco", shifter carry out
   1700 
   1701    The calling convention for res and newC is a bit funny.  They could
   1702    be passed by value, but instead are passed by ref.
   1703 */
   1704 
   1705 static void compute_result_and_C_after_LSL_by_imm5 (
   1706                /*OUT*/HChar* buf,
   1707                IRTemp* res,
   1708                IRTemp* newC,
   1709                IRTemp rMt, UInt shift_amt, /* operands */
   1710                UInt rM      /* only for debug printing */
   1711             )
   1712 {
   1713    if (shift_amt == 0) {
   1714       if (newC) {
   1715          assign( *newC, mk_armg_calculate_flag_c() );
   1716       }
   1717       assign( *res, mkexpr(rMt) );
   1718       DIS(buf, "r%u", rM);
   1719    } else {
   1720       vassert(shift_amt >= 1 && shift_amt <= 31);
   1721       if (newC) {
   1722          assign( *newC,
   1723                  binop(Iop_And32,
   1724                        binop(Iop_Shr32, mkexpr(rMt),
   1725                                         mkU8(32 - shift_amt)),
   1726                        mkU32(1)));
   1727       }
   1728       assign( *res,
   1729               binop(Iop_Shl32, mkexpr(rMt), mkU8(shift_amt)) );
   1730       DIS(buf, "r%u, LSL #%u", rM, shift_amt);
   1731    }
   1732 }
   1733 
   1734 
   1735 static void compute_result_and_C_after_LSL_by_reg (
   1736                /*OUT*/HChar* buf,
   1737                IRTemp* res,
   1738                IRTemp* newC,
   1739                IRTemp rMt, IRTemp rSt,  /* operands */
   1740                UInt rM,    UInt rS      /* only for debug printing */
   1741             )
   1742 {
   1743    // shift left in range 0 .. 255
   1744    // amt  = rS & 255
   1745    // res  = amt < 32 ?  Rm << amt  : 0
   1746    // newC = amt == 0     ? oldC  :
   1747    //        amt in 1..32 ?  Rm[32-amt]  : 0
   1748    IRTemp amtT = newTemp(Ity_I32);
   1749    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   1750    if (newC) {
   1751       /* mux0X(amt == 0,
   1752                mux0X(amt < 32,
   1753                      0,
   1754                      Rm[(32-amt) & 31])
   1755                oldC)
   1756       */
   1757       /* About the best you can do is pray that iropt is able
   1758          to nuke most or all of the following junk. */
   1759       IRTemp oldC = newTemp(Ity_I32);
   1760       assign(oldC, mk_armg_calculate_flag_c() );
   1761       assign(
   1762          *newC,
   1763          IRExpr_Mux0X(
   1764             unop(Iop_1Uto8,
   1765                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
   1766             IRExpr_Mux0X(
   1767                unop(Iop_1Uto8,
   1768                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
   1769                mkU32(0),
   1770                binop(Iop_Shr32,
   1771                      mkexpr(rMt),
   1772                      unop(Iop_32to8,
   1773                           binop(Iop_And32,
   1774                                 binop(Iop_Sub32,
   1775                                       mkU32(32),
   1776                                       mkexpr(amtT)),
   1777                                 mkU32(31)
   1778                           )
   1779                      )
   1780                )
   1781             ),
   1782             mkexpr(oldC)
   1783          )
   1784       );
   1785    }
   1786    // (Rm << (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
   1787    // Lhs of the & limits the shift to 31 bits, so as to
   1788    // give known IR semantics.  Rhs of the & is all 1s for
   1789    // Rs <= 31 and all 0s for Rs >= 32.
   1790    assign(
   1791       *res,
   1792       binop(
   1793          Iop_And32,
   1794          binop(Iop_Shl32,
   1795                mkexpr(rMt),
   1796                unop(Iop_32to8,
   1797                     binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
   1798          binop(Iop_Sar32,
   1799                binop(Iop_Sub32,
   1800                      mkexpr(amtT),
   1801                      mkU32(32)),
   1802                mkU8(31))));
   1803     DIS(buf, "r%u, LSL r%u", rM, rS);
   1804 }
   1805 
   1806 
   1807 static void compute_result_and_C_after_LSR_by_imm5 (
   1808                /*OUT*/HChar* buf,
   1809                IRTemp* res,
   1810                IRTemp* newC,
   1811                IRTemp rMt, UInt shift_amt, /* operands */
   1812                UInt rM      /* only for debug printing */
   1813             )
   1814 {
   1815    if (shift_amt == 0) {
   1816       // conceptually a 32-bit shift, however:
   1817       // res  = 0
   1818       // newC = Rm[31]
   1819       if (newC) {
   1820          assign( *newC,
   1821                  binop(Iop_And32,
   1822                        binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
   1823                        mkU32(1)));
   1824       }
   1825       assign( *res, mkU32(0) );
   1826       DIS(buf, "r%u, LSR #0(a.k.a. 32)", rM);
   1827    } else {
   1828       // shift in range 1..31
   1829       // res  = Rm >>u shift_amt
   1830       // newC = Rm[shift_amt - 1]
   1831       vassert(shift_amt >= 1 && shift_amt <= 31);
   1832       if (newC) {
   1833          assign( *newC,
   1834                  binop(Iop_And32,
   1835                        binop(Iop_Shr32, mkexpr(rMt),
   1836                                         mkU8(shift_amt - 1)),
   1837                        mkU32(1)));
   1838       }
   1839       assign( *res,
   1840               binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)) );
   1841       DIS(buf, "r%u, LSR #%u", rM, shift_amt);
   1842    }
   1843 }
   1844 
   1845 
   1846 static void compute_result_and_C_after_LSR_by_reg (
   1847                /*OUT*/HChar* buf,
   1848                IRTemp* res,
   1849                IRTemp* newC,
   1850                IRTemp rMt, IRTemp rSt,  /* operands */
   1851                UInt rM,    UInt rS      /* only for debug printing */
   1852             )
   1853 {
   1854    // shift right in range 0 .. 255
   1855    // amt = rS & 255
   1856    // res  = amt < 32 ?  Rm >>u amt  : 0
   1857    // newC = amt == 0     ? oldC  :
   1858    //        amt in 1..32 ?  Rm[amt-1]  : 0
   1859    IRTemp amtT = newTemp(Ity_I32);
   1860    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   1861    if (newC) {
   1862       /* mux0X(amt == 0,
   1863                mux0X(amt < 32,
   1864                      0,
   1865                      Rm[(amt-1) & 31])
   1866                oldC)
   1867       */
   1868       IRTemp oldC = newTemp(Ity_I32);
   1869       assign(oldC, mk_armg_calculate_flag_c() );
   1870       assign(
   1871          *newC,
   1872          IRExpr_Mux0X(
   1873             unop(Iop_1Uto8,
   1874                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
   1875             IRExpr_Mux0X(
   1876                unop(Iop_1Uto8,
   1877                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
   1878                mkU32(0),
   1879                binop(Iop_Shr32,
   1880                      mkexpr(rMt),
   1881                      unop(Iop_32to8,
   1882                           binop(Iop_And32,
   1883                                 binop(Iop_Sub32,
   1884                                       mkexpr(amtT),
   1885                                       mkU32(1)),
   1886                                 mkU32(31)
   1887                           )
   1888                      )
   1889                )
   1890             ),
   1891             mkexpr(oldC)
   1892          )
   1893       );
   1894    }
   1895    // (Rm >>u (Rs & 31))  &  (((Rs & 255) - 32) >>s 31)
   1896    // Lhs of the & limits the shift to 31 bits, so as to
   1897    // give known IR semantics.  Rhs of the & is all 1s for
   1898    // Rs <= 31 and all 0s for Rs >= 32.
   1899    assign(
   1900       *res,
   1901       binop(
   1902          Iop_And32,
   1903          binop(Iop_Shr32,
   1904                mkexpr(rMt),
   1905                unop(Iop_32to8,
   1906                     binop(Iop_And32, mkexpr(rSt), mkU32(31)))),
   1907          binop(Iop_Sar32,
   1908                binop(Iop_Sub32,
   1909                      mkexpr(amtT),
   1910                      mkU32(32)),
   1911                mkU8(31))));
   1912     DIS(buf, "r%u, LSR r%u", rM, rS);
   1913 }
   1914 
   1915 
   1916 static void compute_result_and_C_after_ASR_by_imm5 (
   1917                /*OUT*/HChar* buf,
   1918                IRTemp* res,
   1919                IRTemp* newC,
   1920                IRTemp rMt, UInt shift_amt, /* operands */
   1921                UInt rM      /* only for debug printing */
   1922             )
   1923 {
   1924    if (shift_amt == 0) {
   1925       // conceptually a 32-bit shift, however:
   1926       // res  = Rm >>s 31
   1927       // newC = Rm[31]
   1928       if (newC) {
   1929          assign( *newC,
   1930                  binop(Iop_And32,
   1931                        binop(Iop_Shr32, mkexpr(rMt), mkU8(31)),
   1932                        mkU32(1)));
   1933       }
   1934       assign( *res, binop(Iop_Sar32, mkexpr(rMt), mkU8(31)) );
   1935       DIS(buf, "r%u, ASR #0(a.k.a. 32)", rM);
   1936    } else {
   1937       // shift in range 1..31
   1938       // res = Rm >>s shift_amt
   1939       // newC = Rm[shift_amt - 1]
   1940       vassert(shift_amt >= 1 && shift_amt <= 31);
   1941       if (newC) {
   1942          assign( *newC,
   1943                  binop(Iop_And32,
   1944                        binop(Iop_Shr32, mkexpr(rMt),
   1945                                         mkU8(shift_amt - 1)),
   1946                        mkU32(1)));
   1947       }
   1948       assign( *res,
   1949               binop(Iop_Sar32, mkexpr(rMt), mkU8(shift_amt)) );
   1950       DIS(buf, "r%u, ASR #%u", rM, shift_amt);
   1951    }
   1952 }
   1953 
   1954 
   1955 static void compute_result_and_C_after_ASR_by_reg (
   1956                /*OUT*/HChar* buf,
   1957                IRTemp* res,
   1958                IRTemp* newC,
   1959                IRTemp rMt, IRTemp rSt,  /* operands */
   1960                UInt rM,    UInt rS      /* only for debug printing */
   1961             )
   1962 {
   1963    // arithmetic shift right in range 0 .. 255
   1964    // amt = rS & 255
   1965    // res  = amt < 32 ?  Rm >>s amt  : Rm >>s 31
   1966    // newC = amt == 0     ? oldC  :
   1967    //        amt in 1..32 ?  Rm[amt-1]  : Rm[31]
   1968    IRTemp amtT = newTemp(Ity_I32);
   1969    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   1970    if (newC) {
   1971       /* mux0X(amt == 0,
   1972                mux0X(amt < 32,
   1973                      Rm[31],
   1974                      Rm[(amt-1) & 31])
   1975                oldC)
   1976       */
   1977       IRTemp oldC = newTemp(Ity_I32);
   1978       assign(oldC, mk_armg_calculate_flag_c() );
   1979       assign(
   1980          *newC,
   1981          IRExpr_Mux0X(
   1982             unop(Iop_1Uto8,
   1983                  binop(Iop_CmpEQ32, mkexpr(amtT), mkU32(0))),
   1984             IRExpr_Mux0X(
   1985                unop(Iop_1Uto8,
   1986                     binop(Iop_CmpLE32U, mkexpr(amtT), mkU32(32))),
   1987                binop(Iop_Shr32,
   1988                      mkexpr(rMt),
   1989                      mkU8(31)
   1990                ),
   1991                binop(Iop_Shr32,
   1992                      mkexpr(rMt),
   1993                      unop(Iop_32to8,
   1994                           binop(Iop_And32,
   1995                                 binop(Iop_Sub32,
   1996                                       mkexpr(amtT),
   1997                                       mkU32(1)),
   1998                                 mkU32(31)
   1999                           )
   2000                      )
   2001                )
   2002             ),
   2003             mkexpr(oldC)
   2004          )
   2005       );
   2006    }
   2007    // (Rm >>s (amt <u 32 ? amt : 31))
   2008    assign(
   2009       *res,
   2010       binop(
   2011          Iop_Sar32,
   2012          mkexpr(rMt),
   2013          unop(
   2014             Iop_32to8,
   2015             IRExpr_Mux0X(
   2016                unop(
   2017                  Iop_1Uto8,
   2018                  binop(Iop_CmpLT32U, mkexpr(amtT), mkU32(32))),
   2019                mkU32(31),
   2020                mkexpr(amtT)))));
   2021     DIS(buf, "r%u, ASR r%u", rM, rS);
   2022 }
   2023 
   2024 
   2025 static void compute_result_and_C_after_ROR_by_reg (
   2026                /*OUT*/HChar* buf,
   2027                IRTemp* res,
   2028                IRTemp* newC,
   2029                IRTemp rMt, IRTemp rSt,  /* operands */
   2030                UInt rM,    UInt rS      /* only for debug printing */
   2031             )
   2032 {
   2033    // rotate right in range 0 .. 255
   2034    // amt = rS & 255
   2035    // shop =  Rm `ror` (amt & 31)
   2036    // shco =  amt == 0 ? oldC : Rm[(amt-1) & 31]
   2037    IRTemp amtT = newTemp(Ity_I32);
   2038    assign( amtT, binop(Iop_And32, mkexpr(rSt), mkU32(255)) );
   2039    IRTemp amt5T = newTemp(Ity_I32);
   2040    assign( amt5T, binop(Iop_And32, mkexpr(rSt), mkU32(31)) );
   2041    IRTemp oldC = newTemp(Ity_I32);
   2042    assign(oldC, mk_armg_calculate_flag_c() );
   2043    if (newC) {
   2044       assign(
   2045          *newC,
   2046          IRExpr_Mux0X(
   2047             unop(Iop_32to8, mkexpr(amtT)),
   2048             mkexpr(oldC),
   2049             binop(Iop_And32,
   2050                   binop(Iop_Shr32,
   2051                         mkexpr(rMt),
   2052                         unop(Iop_32to8,
   2053                              binop(Iop_And32,
   2054                                    binop(Iop_Sub32,
   2055                                          mkexpr(amtT),
   2056                                          mkU32(1)
   2057                                    ),
   2058                                    mkU32(31)
   2059                              )
   2060                         )
   2061                   ),
   2062                   mkU32(1)
   2063             )
   2064          )
   2065       );
   2066    }
   2067    assign(
   2068       *res,
   2069       IRExpr_Mux0X(
   2070          unop(Iop_32to8, mkexpr(amt5T)), mkexpr(rMt),
   2071          binop(Iop_Or32,
   2072                binop(Iop_Shr32,
   2073                      mkexpr(rMt),
   2074                      unop(Iop_32to8, mkexpr(amt5T))
   2075                ),
   2076                binop(Iop_Shl32,
   2077                      mkexpr(rMt),
   2078                      unop(Iop_32to8,
   2079                           binop(Iop_Sub32, mkU32(32), mkexpr(amt5T))
   2080                      )
   2081                )
   2082          )
   2083       )
   2084    );
   2085    DIS(buf, "r%u, ROR r#%u", rM, rS);
   2086 }
   2087 
   2088 
   2089 /* Generate an expression corresponding to the immediate-shift case of
   2090    a shifter operand.  This is used both for ARM and Thumb2.
   2091 
   2092    Bind it to a temporary, and return that via *res.  If newC is
   2093    non-NULL, also compute a value for the shifter's carry out (in the
   2094    LSB of a word), bind it to a temporary, and return that via *shco.
   2095 
   2096    Generates GETs from the guest state and is therefore not safe to
   2097    use once we start doing PUTs to it, for any given instruction.
   2098 
   2099    'how' is encoded thusly:
   2100       00b LSL,  01b LSR,  10b ASR,  11b ROR
   2101    Most but not all ARM and Thumb integer insns use this encoding.
   2102    Be careful to ensure the right value is passed here.
   2103 */
   2104 static void compute_result_and_C_after_shift_by_imm5 (
   2105                /*OUT*/HChar* buf,
   2106                /*OUT*/IRTemp* res,
   2107                /*OUT*/IRTemp* newC,
   2108                IRTemp  rMt,       /* reg to shift */
   2109                UInt    how,       /* what kind of shift */
   2110                UInt    shift_amt, /* shift amount (0..31) */
   2111                UInt    rM         /* only for debug printing */
   2112             )
   2113 {
   2114    vassert(shift_amt < 32);
   2115    vassert(how < 4);
   2116 
   2117    switch (how) {
   2118 
   2119       case 0:
   2120          compute_result_and_C_after_LSL_by_imm5(
   2121             buf, res, newC, rMt, shift_amt, rM
   2122          );
   2123          break;
   2124 
   2125       case 1:
   2126          compute_result_and_C_after_LSR_by_imm5(
   2127             buf, res, newC, rMt, shift_amt, rM
   2128          );
   2129          break;
   2130 
   2131       case 2:
   2132          compute_result_and_C_after_ASR_by_imm5(
   2133             buf, res, newC, rMt, shift_amt, rM
   2134          );
   2135          break;
   2136 
   2137       case 3:
   2138          if (shift_amt == 0) {
   2139             IRTemp oldcT = newTemp(Ity_I32);
   2140             // rotate right 1 bit through carry (?)
   2141             // RRX -- described at ARM ARM A5-17
   2142             // res  = (oldC << 31) | (Rm >>u 1)
   2143             // newC = Rm[0]
   2144             if (newC) {
   2145                assign( *newC,
   2146                        binop(Iop_And32, mkexpr(rMt), mkU32(1)));
   2147             }
   2148             assign( oldcT, mk_armg_calculate_flag_c() );
   2149             assign( *res,
   2150                     binop(Iop_Or32,
   2151                           binop(Iop_Shl32, mkexpr(oldcT), mkU8(31)),
   2152                           binop(Iop_Shr32, mkexpr(rMt), mkU8(1))) );
   2153             DIS(buf, "r%u, RRX", rM);
   2154          } else {
   2155             // rotate right in range 1..31
   2156             // res  = Rm `ror` shift_amt
   2157             // newC = Rm[shift_amt - 1]
   2158             vassert(shift_amt >= 1 && shift_amt <= 31);
   2159             if (newC) {
   2160                assign( *newC,
   2161                        binop(Iop_And32,
   2162                              binop(Iop_Shr32, mkexpr(rMt),
   2163                                               mkU8(shift_amt - 1)),
   2164                              mkU32(1)));
   2165             }
   2166             assign( *res,
   2167                     binop(Iop_Or32,
   2168                           binop(Iop_Shr32, mkexpr(rMt), mkU8(shift_amt)),
   2169                           binop(Iop_Shl32, mkexpr(rMt),
   2170                                            mkU8(32-shift_amt))));
   2171             DIS(buf, "r%u, ROR #%u", rM, shift_amt);
   2172          }
   2173          break;
   2174 
   2175       default:
   2176          /*NOTREACHED*/
   2177          vassert(0);
   2178    }
   2179 }
   2180 
   2181 
   2182 /* Generate an expression corresponding to the register-shift case of
   2183    a shifter operand.  This is used both for ARM and Thumb2.
   2184 
   2185    Bind it to a temporary, and return that via *res.  If newC is
   2186    non-NULL, also compute a value for the shifter's carry out (in the
   2187    LSB of a word), bind it to a temporary, and return that via *shco.
   2188 
   2189    Generates GETs from the guest state and is therefore not safe to
   2190    use once we start doing PUTs to it, for any given instruction.
   2191 
   2192    'how' is encoded thusly:
   2193       00b LSL,  01b LSR,  10b ASR,  11b ROR
   2194    Most but not all ARM and Thumb integer insns use this encoding.
   2195    Be careful to ensure the right value is passed here.
   2196 */
   2197 static void compute_result_and_C_after_shift_by_reg (
   2198                /*OUT*/HChar*  buf,
   2199                /*OUT*/IRTemp* res,
   2200                /*OUT*/IRTemp* newC,
   2201                IRTemp  rMt,       /* reg to shift */
   2202                UInt    how,       /* what kind of shift */
   2203                IRTemp  rSt,       /* shift amount */
   2204                UInt    rM,        /* only for debug printing */
   2205                UInt    rS         /* only for debug printing */
   2206             )
   2207 {
   2208    vassert(how < 4);
   2209    switch (how) {
   2210       case 0: { /* LSL */
   2211          compute_result_and_C_after_LSL_by_reg(
   2212             buf, res, newC, rMt, rSt, rM, rS
   2213          );
   2214          break;
   2215       }
   2216       case 1: { /* LSR */
   2217          compute_result_and_C_after_LSR_by_reg(
   2218             buf, res, newC, rMt, rSt, rM, rS
   2219          );
   2220          break;
   2221       }
   2222       case 2: { /* ASR */
   2223          compute_result_and_C_after_ASR_by_reg(
   2224             buf, res, newC, rMt, rSt, rM, rS
   2225          );
   2226          break;
   2227       }
   2228       case 3: { /* ROR */
   2229          compute_result_and_C_after_ROR_by_reg(
   2230              buf, res, newC, rMt, rSt, rM, rS
   2231          );
   2232          break;
   2233       }
   2234       default:
   2235          /*NOTREACHED*/
   2236          vassert(0);
   2237    }
   2238 }
   2239 
   2240 
   2241 /* Generate an expression corresponding to a shifter_operand, bind it
   2242    to a temporary, and return that via *shop.  If shco is non-NULL,
   2243    also compute a value for the shifter's carry out (in the LSB of a
   2244    word), bind it to a temporary, and return that via *shco.
   2245 
   2246    If for some reason we can't come up with a shifter operand (missing
   2247    case?  not really a shifter operand?) return False.
   2248 
   2249    Generates GETs from the guest state and is therefore not safe to
   2250    use once we start doing PUTs to it, for any given instruction.
   2251 
   2252    For ARM insns only; not for Thumb.
   2253 */
   2254 static Bool mk_shifter_operand ( UInt insn_25, UInt insn_11_0,
   2255                                  /*OUT*/IRTemp* shop,
   2256                                  /*OUT*/IRTemp* shco,
   2257                                  /*OUT*/HChar* buf )
   2258 {
   2259    UInt insn_4 = (insn_11_0 >> 4) & 1;
   2260    UInt insn_7 = (insn_11_0 >> 7) & 1;
   2261    vassert(insn_25 <= 0x1);
   2262    vassert(insn_11_0 <= 0xFFF);
   2263 
   2264    vassert(shop && *shop == IRTemp_INVALID);
   2265    *shop = newTemp(Ity_I32);
   2266 
   2267    if (shco) {
   2268       vassert(*shco == IRTemp_INVALID);
   2269       *shco = newTemp(Ity_I32);
   2270    }
   2271 
   2272    /* 32-bit immediate */
   2273 
   2274    if (insn_25 == 1) {
   2275       /* immediate: (7:0) rotated right by 2 * (11:8) */
   2276       UInt imm = (insn_11_0 >> 0) & 0xFF;
   2277       UInt rot = 2 * ((insn_11_0 >> 8) & 0xF);
   2278       vassert(rot <= 30);
   2279       imm = ROR32(imm, rot);
   2280       if (shco) {
   2281          if (rot == 0) {
   2282             assign( *shco, mk_armg_calculate_flag_c() );
   2283          } else {
   2284             assign( *shco, mkU32( (imm >> 31) & 1 ) );
   2285          }
   2286       }
   2287       DIS(buf, "#0x%x", imm);
   2288       assign( *shop, mkU32(imm) );
   2289       return True;
   2290    }
   2291 
   2292    /* Shift/rotate by immediate */
   2293 
   2294    if (insn_25 == 0 && insn_4 == 0) {
   2295       /* Rm (3:0) shifted (6:5) by immediate (11:7) */
   2296       UInt shift_amt = (insn_11_0 >> 7) & 0x1F;
   2297       UInt rM        = (insn_11_0 >> 0) & 0xF;
   2298       UInt how       = (insn_11_0 >> 5) & 3;
   2299       /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
   2300       IRTemp rMt = newTemp(Ity_I32);
   2301       assign(rMt, getIRegA(rM));
   2302 
   2303       vassert(shift_amt <= 31);
   2304 
   2305       compute_result_and_C_after_shift_by_imm5(
   2306          buf, shop, shco, rMt, how, shift_amt, rM
   2307       );
   2308       return True;
   2309    }
   2310 
   2311    /* Shift/rotate by register */
   2312    if (insn_25 == 0 && insn_4 == 1) {
   2313       /* Rm (3:0) shifted (6:5) by Rs (11:8) */
   2314       UInt rM  = (insn_11_0 >> 0) & 0xF;
   2315       UInt rS  = (insn_11_0 >> 8) & 0xF;
   2316       UInt how = (insn_11_0 >> 5) & 3;
   2317       /* how: 00 = Shl, 01 = Shr, 10 = Sar, 11 = Ror */
   2318       IRTemp rMt = newTemp(Ity_I32);
   2319       IRTemp rSt = newTemp(Ity_I32);
   2320 
   2321       if (insn_7 == 1)
   2322          return False; /* not really a shifter operand */
   2323 
   2324       assign(rMt, getIRegA(rM));
   2325       assign(rSt, getIRegA(rS));
   2326 
   2327       compute_result_and_C_after_shift_by_reg(
   2328          buf, shop, shco, rMt, how, rSt, rM, rS
   2329       );
   2330       return True;
   2331    }
   2332 
   2333    vex_printf("mk_shifter_operand(0x%x,0x%x)\n", insn_25, insn_11_0 );
   2334    return False;
   2335 }
   2336 
   2337 
   2338 /* ARM only */
   2339 static
   2340 IRExpr* mk_EA_reg_plusminus_imm12 ( UInt rN, UInt bU, UInt imm12,
   2341                                     /*OUT*/HChar* buf )
   2342 {
   2343    vassert(rN < 16);
   2344    vassert(bU < 2);
   2345    vassert(imm12 < 0x1000);
   2346    UChar opChar = bU == 1 ? '+' : '-';
   2347    DIS(buf, "[r%u, #%c%u]", rN, opChar, imm12);
   2348    return
   2349       binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
   2350              getIRegA(rN),
   2351              mkU32(imm12) );
   2352 }
   2353 
   2354 
   2355 /* ARM only.
   2356    NB: This is "DecodeImmShift" in newer versions of the the ARM ARM.
   2357 */
   2358 static
   2359 IRExpr* mk_EA_reg_plusminus_shifted_reg ( UInt rN, UInt bU, UInt rM,
   2360                                           UInt sh2, UInt imm5,
   2361                                           /*OUT*/HChar* buf )
   2362 {
   2363    vassert(rN < 16);
   2364    vassert(bU < 2);
   2365    vassert(rM < 16);
   2366    vassert(sh2 < 4);
   2367    vassert(imm5 < 32);
   2368    UChar   opChar = bU == 1 ? '+' : '-';
   2369    IRExpr* index  = NULL;
   2370    switch (sh2) {
   2371       case 0: /* LSL */
   2372          /* imm5 can be in the range 0 .. 31 inclusive. */
   2373          index = binop(Iop_Shl32, getIRegA(rM), mkU8(imm5));
   2374          DIS(buf, "[r%u, %c r%u LSL #%u]", rN, opChar, rM, imm5);
   2375          break;
   2376       case 1: /* LSR */
   2377          if (imm5 == 0) {
   2378             index = mkU32(0);
   2379             vassert(0); // ATC
   2380          } else {
   2381             index = binop(Iop_Shr32, getIRegA(rM), mkU8(imm5));
   2382          }
   2383          DIS(buf, "[r%u, %cr%u, LSR #%u]",
   2384                   rN, opChar, rM, imm5 == 0 ? 32 : imm5);
   2385          break;
   2386       case 2: /* ASR */
   2387          /* Doesn't this just mean that the behaviour with imm5 == 0
   2388             is the same as if it had been 31 ? */
   2389          if (imm5 == 0) {
   2390             index = binop(Iop_Sar32, getIRegA(rM), mkU8(31));
   2391             vassert(0); // ATC
   2392          } else {
   2393             index = binop(Iop_Sar32, getIRegA(rM), mkU8(imm5));
   2394          }
   2395          DIS(buf, "[r%u, %cr%u, ASR #%u]",
   2396                   rN, opChar, rM, imm5 == 0 ? 32 : imm5);
   2397          break;
   2398       case 3: /* ROR or RRX */
   2399          if (imm5 == 0) {
   2400             IRTemp rmT    = newTemp(Ity_I32);
   2401             IRTemp cflagT = newTemp(Ity_I32);
   2402             assign(rmT, getIRegA(rM));
   2403             assign(cflagT, mk_armg_calculate_flag_c());
   2404             index = binop(Iop_Or32,
   2405                           binop(Iop_Shl32, mkexpr(cflagT), mkU8(31)),
   2406                           binop(Iop_Shr32, mkexpr(rmT), mkU8(1)));
   2407             DIS(buf, "[r%u, %cr%u, RRX]", rN, opChar, rM);
   2408          } else {
   2409             IRTemp rmT = newTemp(Ity_I32);
   2410             assign(rmT, getIRegA(rM));
   2411             vassert(imm5 >= 1 && imm5 <= 31);
   2412             index = binop(Iop_Or32,
   2413                           binop(Iop_Shl32, mkexpr(rmT), mkU8(32-imm5)),
   2414                           binop(Iop_Shr32, mkexpr(rmT), mkU8(imm5)));
   2415             DIS(buf, "[r%u, %cr%u, ROR #%u]", rN, opChar, rM, imm5);
   2416          }
   2417          break;
   2418       default:
   2419          vassert(0);
   2420    }
   2421    vassert(index);
   2422    return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   2423                 getIRegA(rN), index);
   2424 }
   2425 
   2426 
   2427 /* ARM only */
   2428 static
   2429 IRExpr* mk_EA_reg_plusminus_imm8 ( UInt rN, UInt bU, UInt imm8,
   2430                                    /*OUT*/HChar* buf )
   2431 {
   2432    vassert(rN < 16);
   2433    vassert(bU < 2);
   2434    vassert(imm8 < 0x100);
   2435    UChar opChar = bU == 1 ? '+' : '-';
   2436    DIS(buf, "[r%u, #%c%u]", rN, opChar, imm8);
   2437    return
   2438       binop( (bU == 1 ? Iop_Add32 : Iop_Sub32),
   2439              getIRegA(rN),
   2440              mkU32(imm8) );
   2441 }
   2442 
   2443 
   2444 /* ARM only */
   2445 static
   2446 IRExpr* mk_EA_reg_plusminus_reg ( UInt rN, UInt bU, UInt rM,
   2447                                   /*OUT*/HChar* buf )
   2448 {
   2449    vassert(rN < 16);
   2450    vassert(bU < 2);
   2451    vassert(rM < 16);
   2452    UChar   opChar = bU == 1 ? '+' : '-';
   2453    IRExpr* index  = getIRegA(rM);
   2454    DIS(buf, "[r%u, %c r%u]", rN, opChar, rM);
   2455    return binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   2456                 getIRegA(rN), index);
   2457 }
   2458 
   2459 
   2460 /* irRes :: Ity_I32 holds a floating point comparison result encoded
   2461    as an IRCmpF64Result.  Generate code to convert it to an
   2462    ARM-encoded (N,Z,C,V) group in the lowest 4 bits of an I32 value.
   2463    Assign a new temp to hold that value, and return the temp. */
   2464 static
   2465 IRTemp mk_convert_IRCmpF64Result_to_NZCV ( IRTemp irRes )
   2466 {
   2467    IRTemp ix       = newTemp(Ity_I32);
   2468    IRTemp termL    = newTemp(Ity_I32);
   2469    IRTemp termR    = newTemp(Ity_I32);
   2470    IRTemp nzcv     = newTemp(Ity_I32);
   2471 
   2472    /* This is where the fun starts.  We have to convert 'irRes' from
   2473       an IR-convention return result (IRCmpF64Result) to an
   2474       ARM-encoded (N,Z,C,V) group.  The final result is in the bottom
   2475       4 bits of 'nzcv'. */
   2476    /* Map compare result from IR to ARM(nzcv) */
   2477    /*
   2478       FP cmp result | IR   | ARM(nzcv)
   2479       --------------------------------
   2480       UN              0x45   0011
   2481       LT              0x01   1000
   2482       GT              0x00   0010
   2483       EQ              0x40   0110
   2484    */
   2485    /* Now since you're probably wondering WTF ..
   2486 
   2487       ix fishes the useful bits out of the IR value, bits 6 and 0, and
   2488       places them side by side, giving a number which is 0, 1, 2 or 3.
   2489 
   2490       termL is a sequence cooked up by GNU superopt.  It converts ix
   2491          into an almost correct value NZCV value (incredibly), except
   2492          for the case of UN, where it produces 0100 instead of the
   2493          required 0011.
   2494 
   2495       termR is therefore a correction term, also computed from ix.  It
   2496          is 1 in the UN case and 0 for LT, GT and UN.  Hence, to get
   2497          the final correct value, we subtract termR from termL.
   2498 
   2499       Don't take my word for it.  There's a test program at the bottom
   2500       of this file, to try this out with.
   2501    */
   2502    assign(
   2503       ix,
   2504       binop(Iop_Or32,
   2505             binop(Iop_And32,
   2506                   binop(Iop_Shr32, mkexpr(irRes), mkU8(5)),
   2507                   mkU32(3)),
   2508             binop(Iop_And32, mkexpr(irRes), mkU32(1))));
   2509 
   2510    assign(
   2511       termL,
   2512       binop(Iop_Add32,
   2513             binop(Iop_Shr32,
   2514                   binop(Iop_Sub32,
   2515                         binop(Iop_Shl32,
   2516                               binop(Iop_Xor32, mkexpr(ix), mkU32(1)),
   2517                               mkU8(30)),
   2518                         mkU32(1)),
   2519                   mkU8(29)),
   2520             mkU32(1)));
   2521 
   2522    assign(
   2523       termR,
   2524       binop(Iop_And32,
   2525             binop(Iop_And32,
   2526                   mkexpr(ix),
   2527                   binop(Iop_Shr32, mkexpr(ix), mkU8(1))),
   2528             mkU32(1)));
   2529 
   2530    assign(nzcv, binop(Iop_Sub32, mkexpr(termL), mkexpr(termR)));
   2531    return nzcv;
   2532 }
   2533 
   2534 
   2535 /* Thumb32 only.  This is "ThumbExpandImm" in the ARM ARM.  If
   2536    updatesC is non-NULL, a boolean is written to it indicating whether
   2537    or not the C flag is updated, as per ARM ARM "ThumbExpandImm_C".
   2538 */
   2539 static UInt thumbExpandImm ( Bool* updatesC,
   2540                              UInt imm1, UInt imm3, UInt imm8 )
   2541 {
   2542    vassert(imm1 < (1<<1));
   2543    vassert(imm3 < (1<<3));
   2544    vassert(imm8 < (1<<8));
   2545    UInt i_imm3_a = (imm1 << 4) | (imm3 << 1) | ((imm8 >> 7) & 1);
   2546    UInt abcdefgh = imm8;
   2547    UInt lbcdefgh = imm8 | 0x80;
   2548    if (updatesC) {
   2549       *updatesC = i_imm3_a >= 8;
   2550    }
   2551    switch (i_imm3_a) {
   2552       case 0: case 1:
   2553          return abcdefgh;
   2554       case 2: case 3:
   2555          return (abcdefgh << 16) | abcdefgh;
   2556       case 4: case 5:
   2557          return (abcdefgh << 24) | (abcdefgh << 8);
   2558       case 6: case 7:
   2559          return (abcdefgh << 24) | (abcdefgh << 16)
   2560                 | (abcdefgh << 8) | abcdefgh;
   2561       case 8 ... 31:
   2562          return lbcdefgh << (32 - i_imm3_a);
   2563       default:
   2564          break;
   2565    }
   2566    /*NOTREACHED*/vassert(0);
   2567 }
   2568 
   2569 
   2570 /* Version of thumbExpandImm where we simply feed it the
   2571    instruction halfwords (the lowest addressed one is I0). */
   2572 static UInt thumbExpandImm_from_I0_I1 ( Bool* updatesC,
   2573                                         UShort i0s, UShort i1s )
   2574 {
   2575    UInt i0    = (UInt)i0s;
   2576    UInt i1    = (UInt)i1s;
   2577    UInt imm1  = SLICE_UInt(i0,10,10);
   2578    UInt imm3  = SLICE_UInt(i1,14,12);
   2579    UInt imm8  = SLICE_UInt(i1,7,0);
   2580    return thumbExpandImm(updatesC, imm1, imm3, imm8);
   2581 }
   2582 
   2583 
   2584 /* Thumb16 only.  Given the firstcond and mask fields from an IT
   2585    instruction, compute the 32-bit ITSTATE value implied, as described
   2586    in libvex_guest_arm.h.  This is not the ARM ARM representation.
   2587    Also produce the t/e chars for the 2nd, 3rd, 4th insns, for
   2588    disassembly printing.  Returns False if firstcond or mask
   2589    denote something invalid.
   2590 
   2591    The number and conditions for the instructions to be
   2592    conditionalised depend on firstcond and mask:
   2593 
   2594    mask      cond 1    cond 2      cond 3      cond 4
   2595 
   2596    1000      fc[3:0]
   2597    x100      fc[3:0]   fc[3:1]:x
   2598    xy10      fc[3:0]   fc[3:1]:x   fc[3:1]:y
   2599    xyz1      fc[3:0]   fc[3:1]:x   fc[3:1]:y   fc[3:1]:z
   2600 
   2601    The condition fields are assembled in *itstate backwards (cond 4 at
   2602    the top, cond 1 at the bottom).  Conditions are << 4'd and then
   2603    ^0xE'd, and those fields that correspond to instructions in the IT
   2604    block are tagged with a 1 bit.
   2605 */
   2606 static Bool compute_ITSTATE ( /*OUT*/UInt*  itstate,
   2607                               /*OUT*/UChar* ch1,
   2608                               /*OUT*/UChar* ch2,
   2609                               /*OUT*/UChar* ch3,
   2610                               UInt firstcond, UInt mask )
   2611 {
   2612    vassert(firstcond <= 0xF);
   2613    vassert(mask <= 0xF);
   2614    *itstate = 0;
   2615    *ch1 = *ch2 = *ch3 = '.';
   2616    if (mask == 0)
   2617       return False; /* the logic below actually ensures this anyway,
   2618                        but clearer to make it explicit. */
   2619    if (firstcond == 0xF)
   2620       return False; /* NV is not allowed */
   2621    if (firstcond == 0xE && popcount32(mask) != 1)
   2622       return False; /* if firstcond is AL then all the rest must be too */
   2623 
   2624    UInt m3 = (mask >> 3) & 1;
   2625    UInt m2 = (mask >> 2) & 1;
   2626    UInt m1 = (mask >> 1) & 1;
   2627    UInt m0 = (mask >> 0) & 1;
   2628 
   2629    UInt fc = (firstcond << 4) | 1/*in-IT-block*/;
   2630    UInt ni = (0xE/*AL*/ << 4) | 0/*not-in-IT-block*/;
   2631 
   2632    if (m3 == 1 && (m2|m1|m0) == 0) {
   2633       *itstate = (ni << 24) | (ni << 16) | (ni << 8) | fc;
   2634       *itstate ^= 0xE0E0E0E0;
   2635       return True;
   2636    }
   2637 
   2638    if (m2 == 1 && (m1|m0) == 0) {
   2639       *itstate = (ni << 24) | (ni << 16) | (setbit32(fc, 4, m3) << 8) | fc;
   2640       *itstate ^= 0xE0E0E0E0;
   2641       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
   2642       return True;
   2643    }
   2644 
   2645    if (m1 == 1 && m0 == 0) {
   2646       *itstate = (ni << 24)
   2647                  | (setbit32(fc, 4, m2) << 16)
   2648                  | (setbit32(fc, 4, m3) << 8) | fc;
   2649       *itstate ^= 0xE0E0E0E0;
   2650       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
   2651       *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
   2652       return True;
   2653    }
   2654 
   2655    if (m0 == 1) {
   2656       *itstate = (setbit32(fc, 4, m1) << 24)
   2657                  | (setbit32(fc, 4, m2) << 16)
   2658                  | (setbit32(fc, 4, m3) << 8) | fc;
   2659       *itstate ^= 0xE0E0E0E0;
   2660       *ch1 = m3 == (firstcond & 1) ? 't' : 'e';
   2661       *ch2 = m2 == (firstcond & 1) ? 't' : 'e';
   2662       *ch3 = m1 == (firstcond & 1) ? 't' : 'e';
   2663       return True;
   2664    }
   2665 
   2666    return False;
   2667 }
   2668 
   2669 
   2670 /* Generate IR to do 32-bit bit reversal, a la Hacker's Delight
   2671    Chapter 7 Section 1. */
   2672 static IRTemp gen_BITREV ( IRTemp x0 )
   2673 {
   2674    IRTemp x1 = newTemp(Ity_I32);
   2675    IRTemp x2 = newTemp(Ity_I32);
   2676    IRTemp x3 = newTemp(Ity_I32);
   2677    IRTemp x4 = newTemp(Ity_I32);
   2678    IRTemp x5 = newTemp(Ity_I32);
   2679    UInt   c1 = 0x55555555;
   2680    UInt   c2 = 0x33333333;
   2681    UInt   c3 = 0x0F0F0F0F;
   2682    UInt   c4 = 0x00FF00FF;
   2683    UInt   c5 = 0x0000FFFF;
   2684    assign(x1,
   2685           binop(Iop_Or32,
   2686                 binop(Iop_Shl32,
   2687                       binop(Iop_And32, mkexpr(x0), mkU32(c1)),
   2688                       mkU8(1)),
   2689                 binop(Iop_Shr32,
   2690                       binop(Iop_And32, mkexpr(x0), mkU32(~c1)),
   2691                       mkU8(1))
   2692    ));
   2693    assign(x2,
   2694           binop(Iop_Or32,
   2695                 binop(Iop_Shl32,
   2696                       binop(Iop_And32, mkexpr(x1), mkU32(c2)),
   2697                       mkU8(2)),
   2698                 binop(Iop_Shr32,
   2699                       binop(Iop_And32, mkexpr(x1), mkU32(~c2)),
   2700                       mkU8(2))
   2701    ));
   2702    assign(x3,
   2703           binop(Iop_Or32,
   2704                 binop(Iop_Shl32,
   2705                       binop(Iop_And32, mkexpr(x2), mkU32(c3)),
   2706                       mkU8(4)),
   2707                 binop(Iop_Shr32,
   2708                       binop(Iop_And32, mkexpr(x2), mkU32(~c3)),
   2709                       mkU8(4))
   2710    ));
   2711    assign(x4,
   2712           binop(Iop_Or32,
   2713                 binop(Iop_Shl32,
   2714                       binop(Iop_And32, mkexpr(x3), mkU32(c4)),
   2715                       mkU8(8)),
   2716                 binop(Iop_Shr32,
   2717                       binop(Iop_And32, mkexpr(x3), mkU32(~c4)),
   2718                       mkU8(8))
   2719    ));
   2720    assign(x5,
   2721           binop(Iop_Or32,
   2722                 binop(Iop_Shl32,
   2723                       binop(Iop_And32, mkexpr(x4), mkU32(c5)),
   2724                       mkU8(16)),
   2725                 binop(Iop_Shr32,
   2726                       binop(Iop_And32, mkexpr(x4), mkU32(~c5)),
   2727                       mkU8(16))
   2728    ));
   2729    return x5;
   2730 }
   2731 
   2732 
   2733 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
   2734    0:1:2:3 (aka byte-swap). */
   2735 static IRTemp gen_REV ( IRTemp arg )
   2736 {
   2737    IRTemp res = newTemp(Ity_I32);
   2738    assign(res,
   2739           binop(Iop_Or32,
   2740                 binop(Iop_Shl32, mkexpr(arg), mkU8(24)),
   2741           binop(Iop_Or32,
   2742                 binop(Iop_And32, binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
   2743                                  mkU32(0x00FF0000)),
   2744           binop(Iop_Or32,
   2745                 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
   2746                                        mkU32(0x0000FF00)),
   2747                 binop(Iop_And32, binop(Iop_Shr32, mkexpr(arg), mkU8(24)),
   2748                                        mkU32(0x000000FF) )
   2749    ))));
   2750    return res;
   2751 }
   2752 
   2753 
   2754 /* Generate IR to do rearrange bytes 3:2:1:0 in a word in to the order
   2755    2:3:0:1 (swap within lo and hi halves). */
   2756 static IRTemp gen_REV16 ( IRTemp arg )
   2757 {
   2758    IRTemp res = newTemp(Ity_I32);
   2759    assign(res,
   2760           binop(Iop_Or32,
   2761                 binop(Iop_And32,
   2762                       binop(Iop_Shl32, mkexpr(arg), mkU8(8)),
   2763                       mkU32(0xFF00FF00)),
   2764                 binop(Iop_And32,
   2765                       binop(Iop_Shr32, mkexpr(arg), mkU8(8)),
   2766                       mkU32(0x00FF00FF))));
   2767    return res;
   2768 }
   2769 
   2770 
   2771 /*------------------------------------------------------------*/
   2772 /*--- Advanced SIMD (NEON) instructions                    ---*/
   2773 /*------------------------------------------------------------*/
   2774 
   2775 /*------------------------------------------------------------*/
   2776 /*--- NEON data processing                                 ---*/
   2777 /*------------------------------------------------------------*/
   2778 
   2779 /* For all NEON DP ops, we use the normal scheme to handle conditional
   2780    writes to registers -- pass in condT and hand that on to the
   2781    put*Reg functions.  In ARM mode condT is always IRTemp_INVALID
   2782    since NEON is unconditional for ARM.  In Thumb mode condT is
   2783    derived from the ITSTATE shift register in the normal way. */
   2784 
   2785 static
   2786 UInt get_neon_d_regno(UInt theInstr)
   2787 {
   2788    UInt x = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   2789    if (theInstr & 0x40) {
   2790       if (x & 1) {
   2791          x = x + 0x100;
   2792       } else {
   2793          x = x >> 1;
   2794       }
   2795    }
   2796    return x;
   2797 }
   2798 
   2799 static
   2800 UInt get_neon_n_regno(UInt theInstr)
   2801 {
   2802    UInt x = ((theInstr >> 3) & 0x10) | ((theInstr >> 16) & 0xF);
   2803    if (theInstr & 0x40) {
   2804       if (x & 1) {
   2805          x = x + 0x100;
   2806       } else {
   2807          x = x >> 1;
   2808       }
   2809    }
   2810    return x;
   2811 }
   2812 
   2813 static
   2814 UInt get_neon_m_regno(UInt theInstr)
   2815 {
   2816    UInt x = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   2817    if (theInstr & 0x40) {
   2818       if (x & 1) {
   2819          x = x + 0x100;
   2820       } else {
   2821          x = x >> 1;
   2822       }
   2823    }
   2824    return x;
   2825 }
   2826 
   2827 static
   2828 Bool dis_neon_vext ( UInt theInstr, IRTemp condT )
   2829 {
   2830    UInt dreg = get_neon_d_regno(theInstr);
   2831    UInt mreg = get_neon_m_regno(theInstr);
   2832    UInt nreg = get_neon_n_regno(theInstr);
   2833    UInt imm4 = (theInstr >> 8) & 0xf;
   2834    UInt Q = (theInstr >> 6) & 1;
   2835    HChar reg_t = Q ? 'q' : 'd';
   2836 
   2837    if (Q) {
   2838       putQReg(dreg, triop(Iop_ExtractV128, getQReg(nreg),
   2839                getQReg(mreg), mkU8(imm4)), condT);
   2840    } else {
   2841       putDRegI64(dreg, triop(Iop_Extract64, getDRegI64(nreg),
   2842                  getDRegI64(mreg), mkU8(imm4)), condT);
   2843    }
   2844    DIP("vext.8 %c%d, %c%d, %c%d, #%d\n", reg_t, dreg, reg_t, nreg,
   2845                                          reg_t, mreg, imm4);
   2846    return True;
   2847 }
   2848 
   2849 /* VTBL, VTBX */
   2850 static
   2851 Bool dis_neon_vtb ( UInt theInstr, IRTemp condT )
   2852 {
   2853    UInt op = (theInstr >> 6) & 1;
   2854    UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
   2855    UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
   2856    UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
   2857    UInt len = (theInstr >> 8) & 3;
   2858    Int i;
   2859    IROp cmp;
   2860    ULong imm;
   2861    IRTemp arg_l;
   2862    IRTemp old_mask, new_mask, cur_mask;
   2863    IRTemp old_res, new_res;
   2864    IRTemp old_arg, new_arg;
   2865 
   2866    if (dreg >= 0x100 || mreg >= 0x100 || nreg >= 0x100)
   2867       return False;
   2868    if (nreg + len > 31)
   2869       return False;
   2870 
   2871    cmp = Iop_CmpGT8Ux8;
   2872 
   2873    old_mask = newTemp(Ity_I64);
   2874    old_res = newTemp(Ity_I64);
   2875    old_arg = newTemp(Ity_I64);
   2876    assign(old_mask, mkU64(0));
   2877    assign(old_res, mkU64(0));
   2878    assign(old_arg, getDRegI64(mreg));
   2879    imm = 8;
   2880    imm = (imm <<  8) | imm;
   2881    imm = (imm << 16) | imm;
   2882    imm = (imm << 32) | imm;
   2883 
   2884    for (i = 0; i <= len; i++) {
   2885       arg_l = newTemp(Ity_I64);
   2886       new_mask = newTemp(Ity_I64);
   2887       cur_mask = newTemp(Ity_I64);
   2888       new_res = newTemp(Ity_I64);
   2889       new_arg = newTemp(Ity_I64);
   2890       assign(arg_l, getDRegI64(nreg+i));
   2891       assign(new_arg, binop(Iop_Sub8x8, mkexpr(old_arg), mkU64(imm)));
   2892       assign(cur_mask, binop(cmp, mkU64(imm), mkexpr(old_arg)));
   2893       assign(new_mask, binop(Iop_Or64, mkexpr(old_mask), mkexpr(cur_mask)));
   2894       assign(new_res, binop(Iop_Or64,
   2895                             mkexpr(old_res),
   2896                             binop(Iop_And64,
   2897                                   binop(Iop_Perm8x8,
   2898                                         mkexpr(arg_l),
   2899                                         binop(Iop_And64,
   2900                                               mkexpr(old_arg),
   2901                                               mkexpr(cur_mask))),
   2902                                   mkexpr(cur_mask))));
   2903 
   2904       old_arg = new_arg;
   2905       old_mask = new_mask;
   2906       old_res = new_res;
   2907    }
   2908    if (op) {
   2909       new_res = newTemp(Ity_I64);
   2910       assign(new_res, binop(Iop_Or64,
   2911                             binop(Iop_And64,
   2912                                   getDRegI64(dreg),
   2913                                   unop(Iop_Not64, mkexpr(old_mask))),
   2914                             mkexpr(old_res)));
   2915       old_res = new_res;
   2916    }
   2917 
   2918    putDRegI64(dreg, mkexpr(old_res), condT);
   2919    DIP("vtb%c.8 d%u, {", op ? 'x' : 'l', dreg);
   2920    if (len > 0) {
   2921       DIP("d%u-d%u", nreg, nreg + len);
   2922    } else {
   2923       DIP("d%u", nreg);
   2924    }
   2925    DIP("}, d%u\n", mreg);
   2926    return True;
   2927 }
   2928 
   2929 /* VDUP (scalar)  */
   2930 static
   2931 Bool dis_neon_vdup ( UInt theInstr, IRTemp condT )
   2932 {
   2933    UInt Q = (theInstr >> 6) & 1;
   2934    UInt dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   2935    UInt mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   2936    UInt imm4 = (theInstr >> 16) & 0xF;
   2937    UInt index;
   2938    UInt size;
   2939    IRTemp arg_m;
   2940    IRTemp res;
   2941    IROp op, op2;
   2942 
   2943    if ((imm4 == 0) || (imm4 == 8))
   2944       return False;
   2945    if ((Q == 1) && ((dreg & 1) == 1))
   2946       return False;
   2947    if (Q)
   2948       dreg >>= 1;
   2949    arg_m = newTemp(Ity_I64);
   2950    assign(arg_m, getDRegI64(mreg));
   2951    if (Q)
   2952       res = newTemp(Ity_V128);
   2953    else
   2954       res = newTemp(Ity_I64);
   2955    if ((imm4 & 1) == 1) {
   2956       op = Q ? Iop_Dup8x16 : Iop_Dup8x8;
   2957       op2 = Iop_GetElem8x8;
   2958       index = imm4 >> 1;
   2959       size = 8;
   2960    } else if ((imm4 & 3) == 2) {
   2961       op = Q ? Iop_Dup16x8 : Iop_Dup16x4;
   2962       op2 = Iop_GetElem16x4;
   2963       index = imm4 >> 2;
   2964       size = 16;
   2965    } else if ((imm4 & 7) == 4) {
   2966       op = Q ? Iop_Dup32x4 : Iop_Dup32x2;
   2967       op2 = Iop_GetElem32x2;
   2968       index = imm4 >> 3;
   2969       size = 32;
   2970    } else {
   2971       return False; // can this ever happen?
   2972    }
   2973    assign(res, unop(op, binop(op2, mkexpr(arg_m), mkU8(index))));
   2974    if (Q) {
   2975       putQReg(dreg, mkexpr(res), condT);
   2976    } else {
   2977       putDRegI64(dreg, mkexpr(res), condT);
   2978    }
   2979    DIP("vdup.%d %c%d, d%d[%d]\n", size, Q ? 'q' : 'd', dreg, mreg, index);
   2980    return True;
   2981 }
   2982 
   2983 /* A7.4.1 Three registers of the same length */
   2984 static
   2985 Bool dis_neon_data_3same ( UInt theInstr, IRTemp condT )
   2986 {
   2987    UInt Q = (theInstr >> 6) & 1;
   2988    UInt dreg = get_neon_d_regno(theInstr);
   2989    UInt nreg = get_neon_n_regno(theInstr);
   2990    UInt mreg = get_neon_m_regno(theInstr);
   2991    UInt A = (theInstr >> 8) & 0xF;
   2992    UInt B = (theInstr >> 4) & 1;
   2993    UInt C = (theInstr >> 20) & 0x3;
   2994    UInt U = (theInstr >> 24) & 1;
   2995    UInt size = C;
   2996 
   2997    IRTemp arg_n;
   2998    IRTemp arg_m;
   2999    IRTemp res;
   3000 
   3001    if (Q) {
   3002       arg_n = newTemp(Ity_V128);
   3003       arg_m = newTemp(Ity_V128);
   3004       res = newTemp(Ity_V128);
   3005       assign(arg_n, getQReg(nreg));
   3006       assign(arg_m, getQReg(mreg));
   3007    } else {
   3008       arg_n = newTemp(Ity_I64);
   3009       arg_m = newTemp(Ity_I64);
   3010       res = newTemp(Ity_I64);
   3011       assign(arg_n, getDRegI64(nreg));
   3012       assign(arg_m, getDRegI64(mreg));
   3013    }
   3014 
   3015    switch(A) {
   3016       case 0:
   3017          if (B == 0) {
   3018             /* VHADD */
   3019             ULong imm = 0;
   3020             IRExpr *imm_val;
   3021             IROp addOp;
   3022             IROp andOp;
   3023             IROp shOp;
   3024             char regType = Q ? 'q' : 'd';
   3025 
   3026             if (size == 3)
   3027                return False;
   3028             switch(size) {
   3029                case 0: imm = 0x101010101010101LL; break;
   3030                case 1: imm = 0x1000100010001LL; break;
   3031                case 2: imm = 0x100000001LL; break;
   3032                default: vassert(0);
   3033             }
   3034             if (Q) {
   3035                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   3036                andOp = Iop_AndV128;
   3037             } else {
   3038                imm_val = mkU64(imm);
   3039                andOp = Iop_And64;
   3040             }
   3041             if (U) {
   3042                switch(size) {
   3043                   case 0:
   3044                      addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
   3045                      shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3046                      break;
   3047                   case 1:
   3048                      addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
   3049                      shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3050                      break;
   3051                   case 2:
   3052                      addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
   3053                      shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3054                      break;
   3055                   default:
   3056                      vassert(0);
   3057                }
   3058             } else {
   3059                switch(size) {
   3060                   case 0:
   3061                      addOp = Q ? Iop_Add8x16 : Iop_Add8x8;
   3062                      shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
   3063                      break;
   3064                   case 1:
   3065                      addOp = Q ? Iop_Add16x8 : Iop_Add16x4;
   3066                      shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
   3067                      break;
   3068                   case 2:
   3069                      addOp = Q ? Iop_Add32x4 : Iop_Add32x2;
   3070                      shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
   3071                      break;
   3072                   default:
   3073                      vassert(0);
   3074                }
   3075             }
   3076             assign(res,
   3077                    binop(addOp,
   3078                          binop(addOp,
   3079                                binop(shOp, mkexpr(arg_m), mkU8(1)),
   3080                                binop(shOp, mkexpr(arg_n), mkU8(1))),
   3081                          binop(shOp,
   3082                                binop(addOp,
   3083                                      binop(andOp, mkexpr(arg_m), imm_val),
   3084                                      binop(andOp, mkexpr(arg_n), imm_val)),
   3085                                mkU8(1))));
   3086             DIP("vhadd.%c%d %c%d, %c%d, %c%d\n",
   3087                 U ? 'u' : 's', 8 << size, regType,
   3088                 dreg, regType, nreg, regType, mreg);
   3089          } else {
   3090             /* VQADD */
   3091             IROp op, op2;
   3092             IRTemp tmp;
   3093             char reg_t = Q ? 'q' : 'd';
   3094             if (Q) {
   3095                switch (size) {
   3096                   case 0:
   3097                      op = U ? Iop_QAdd8Ux16 : Iop_QAdd8Sx16;
   3098                      op2 = Iop_Add8x16;
   3099                      break;
   3100                   case 1:
   3101                      op = U ? Iop_QAdd16Ux8 : Iop_QAdd16Sx8;
   3102                      op2 = Iop_Add16x8;
   3103                      break;
   3104                   case 2:
   3105                      op = U ? Iop_QAdd32Ux4 : Iop_QAdd32Sx4;
   3106                      op2 = Iop_Add32x4;
   3107                      break;
   3108                   case 3:
   3109                      op = U ? Iop_QAdd64Ux2 : Iop_QAdd64Sx2;
   3110                      op2 = Iop_Add64x2;
   3111                      break;
   3112                   default:
   3113                      vassert(0);
   3114                }
   3115             } else {
   3116                switch (size) {
   3117                   case 0:
   3118                      op = U ? Iop_QAdd8Ux8 : Iop_QAdd8Sx8;
   3119                      op2 = Iop_Add8x8;
   3120                      break;
   3121                   case 1:
   3122                      op = U ? Iop_QAdd16Ux4 : Iop_QAdd16Sx4;
   3123                      op2 = Iop_Add16x4;
   3124                      break;
   3125                   case 2:
   3126                      op = U ? Iop_QAdd32Ux2 : Iop_QAdd32Sx2;
   3127                      op2 = Iop_Add32x2;
   3128                      break;
   3129                   case 3:
   3130                      op = U ? Iop_QAdd64Ux1 : Iop_QAdd64Sx1;
   3131                      op2 = Iop_Add64;
   3132                      break;
   3133                   default:
   3134                      vassert(0);
   3135                }
   3136             }
   3137             if (Q) {
   3138                tmp = newTemp(Ity_V128);
   3139             } else {
   3140                tmp = newTemp(Ity_I64);
   3141             }
   3142             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   3143 #ifndef DISABLE_QC_FLAG
   3144             assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
   3145             setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
   3146 #endif
   3147             DIP("vqadd.%c%d %c%d, %c%d, %c%d\n",
   3148                 U ? 'u' : 's',
   3149                 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3150          }
   3151          break;
   3152       case 1:
   3153          if (B == 0) {
   3154             /* VRHADD */
   3155             /* VRHADD C, A, B ::=
   3156                  C = (A >> 1) + (B >> 1) + (((A & 1) + (B & 1) + 1) >> 1) */
   3157             IROp shift_op, add_op;
   3158             IRTemp cc;
   3159             ULong one = 1;
   3160             HChar reg_t = Q ? 'q' : 'd';
   3161             switch (size) {
   3162                case 0: one = (one <<  8) | one; /* fall through */
   3163                case 1: one = (one << 16) | one; /* fall through */
   3164                case 2: one = (one << 32) | one; break;
   3165                case 3: return False;
   3166                default: vassert(0);
   3167             }
   3168             if (Q) {
   3169                switch (size) {
   3170                   case 0:
   3171                      shift_op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
   3172                      add_op = Iop_Add8x16;
   3173                      break;
   3174                   case 1:
   3175                      shift_op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   3176                      add_op = Iop_Add16x8;
   3177                      break;
   3178                   case 2:
   3179                      shift_op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   3180                      add_op = Iop_Add32x4;
   3181                      break;
   3182                   case 3:
   3183                      return False;
   3184                   default:
   3185                      vassert(0);
   3186                }
   3187             } else {
   3188                switch (size) {
   3189                   case 0:
   3190                      shift_op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
   3191                      add_op = Iop_Add8x8;
   3192                      break;
   3193                   case 1:
   3194                      shift_op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
   3195                      add_op = Iop_Add16x4;
   3196                      break;
   3197                   case 2:
   3198                      shift_op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
   3199                      add_op = Iop_Add32x2;
   3200                      break;
   3201                   case 3:
   3202                      return False;
   3203                   default:
   3204                      vassert(0);
   3205                }
   3206             }
   3207             if (Q) {
   3208                cc = newTemp(Ity_V128);
   3209                assign(cc, binop(shift_op,
   3210                                 binop(add_op,
   3211                                       binop(add_op,
   3212                                             binop(Iop_AndV128,
   3213                                                   mkexpr(arg_n),
   3214                                                   binop(Iop_64HLtoV128,
   3215                                                         mkU64(one),
   3216                                                         mkU64(one))),
   3217                                             binop(Iop_AndV128,
   3218                                                   mkexpr(arg_m),
   3219                                                   binop(Iop_64HLtoV128,
   3220                                                         mkU64(one),
   3221                                                         mkU64(one)))),
   3222                                       binop(Iop_64HLtoV128,
   3223                                             mkU64(one),
   3224                                             mkU64(one))),
   3225                                 mkU8(1)));
   3226                assign(res, binop(add_op,
   3227                                  binop(add_op,
   3228                                        binop(shift_op,
   3229                                              mkexpr(arg_n),
   3230                                              mkU8(1)),
   3231                                        binop(shift_op,
   3232                                              mkexpr(arg_m),
   3233                                              mkU8(1))),
   3234                                  mkexpr(cc)));
   3235             } else {
   3236                cc = newTemp(Ity_I64);
   3237                assign(cc, binop(shift_op,
   3238                                 binop(add_op,
   3239                                       binop(add_op,
   3240                                             binop(Iop_And64,
   3241                                                   mkexpr(arg_n),
   3242                                                   mkU64(one)),
   3243                                             binop(Iop_And64,
   3244                                                   mkexpr(arg_m),
   3245                                                   mkU64(one))),
   3246                                       mkU64(one)),
   3247                                 mkU8(1)));
   3248                assign(res, binop(add_op,
   3249                                  binop(add_op,
   3250                                        binop(shift_op,
   3251                                              mkexpr(arg_n),
   3252                                              mkU8(1)),
   3253                                        binop(shift_op,
   3254                                              mkexpr(arg_m),
   3255                                              mkU8(1))),
   3256                                  mkexpr(cc)));
   3257             }
   3258             DIP("vrhadd.%c%d %c%d, %c%d, %c%d\n",
   3259                 U ? 'u' : 's',
   3260                 8 << size, reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3261          } else {
   3262             if (U == 0)  {
   3263                switch(C) {
   3264                   case 0: {
   3265                      /* VAND  */
   3266                      HChar reg_t = Q ? 'q' : 'd';
   3267                      if (Q) {
   3268                         assign(res, binop(Iop_AndV128, mkexpr(arg_n),
   3269                                                        mkexpr(arg_m)));
   3270                      } else {
   3271                         assign(res, binop(Iop_And64, mkexpr(arg_n),
   3272                                                      mkexpr(arg_m)));
   3273                      }
   3274                      DIP("vand %c%d, %c%d, %c%d\n",
   3275                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3276                      break;
   3277                   }
   3278                   case 1: {
   3279                      /* VBIC  */
   3280                      HChar reg_t = Q ? 'q' : 'd';
   3281                      if (Q) {
   3282                         assign(res, binop(Iop_AndV128,mkexpr(arg_n),
   3283                                unop(Iop_NotV128, mkexpr(arg_m))));
   3284                      } else {
   3285                         assign(res, binop(Iop_And64, mkexpr(arg_n),
   3286                                unop(Iop_Not64, mkexpr(arg_m))));
   3287                      }
   3288                      DIP("vbic %c%d, %c%d, %c%d\n",
   3289                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3290                      break;
   3291                   }
   3292                   case 2:
   3293                      if ( nreg != mreg) {
   3294                         /* VORR  */
   3295                         HChar reg_t = Q ? 'q' : 'd';
   3296                         if (Q) {
   3297                            assign(res, binop(Iop_OrV128, mkexpr(arg_n),
   3298                                                          mkexpr(arg_m)));
   3299                         } else {
   3300                            assign(res, binop(Iop_Or64, mkexpr(arg_n),
   3301                                                        mkexpr(arg_m)));
   3302                         }
   3303                         DIP("vorr %c%d, %c%d, %c%d\n",
   3304                             reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3305                      } else {
   3306                         /* VMOV  */
   3307                         HChar reg_t = Q ? 'q' : 'd';
   3308                         assign(res, mkexpr(arg_m));
   3309                         DIP("vmov %c%d, %c%d\n", reg_t, dreg, reg_t, mreg);
   3310                      }
   3311                      break;
   3312                   case 3:{
   3313                      /* VORN  */
   3314                      HChar reg_t = Q ? 'q' : 'd';
   3315                      if (Q) {
   3316                         assign(res, binop(Iop_OrV128,mkexpr(arg_n),
   3317                                unop(Iop_NotV128, mkexpr(arg_m))));
   3318                      } else {
   3319                         assign(res, binop(Iop_Or64, mkexpr(arg_n),
   3320                                unop(Iop_Not64, mkexpr(arg_m))));
   3321                      }
   3322                      DIP("vorn %c%d, %c%d, %c%d\n",
   3323                          reg_t, dreg, reg_t, nreg, reg_t, mreg);
   3324                      break;
   3325                   }
   3326                }
   3327             } else {
   3328                switch(C) {
   3329                   case 0:
   3330                      /* VEOR (XOR)  */
   3331                      if (Q) {
   3332                         assign(res, binop(Iop_XorV128, mkexpr(arg_n),
   3333                                                        mkexpr(arg_m)));
   3334                      } else {
   3335                         assign(res, binop(Iop_Xor64, mkexpr(arg_n),
   3336                                                      mkexpr(arg_m)));
   3337                      }
   3338                      DIP("veor %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   3339                            Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3340                      break;
   3341                   case 1:
   3342                      /* VBSL  */
   3343                      if (Q) {
   3344                         IRTemp reg_d = newTemp(Ity_V128);
   3345                         assign(reg_d, getQReg(dreg));
   3346                         assign(res,
   3347                                binop(Iop_OrV128,
   3348                                      binop(Iop_AndV128, mkexpr(arg_n),
   3349                                                         mkexpr(reg_d)),
   3350                                      binop(Iop_AndV128,
   3351                                            mkexpr(arg_m),
   3352                                            unop(Iop_NotV128,
   3353                                                  mkexpr(reg_d)) ) ) );
   3354                      } else {
   3355                         IRTemp reg_d = newTemp(Ity_I64);
   3356                         assign(reg_d, getDRegI64(dreg));
   3357                         assign(res,
   3358                                binop(Iop_Or64,
   3359                                      binop(Iop_And64, mkexpr(arg_n),
   3360                                                       mkexpr(reg_d)),
   3361                                      binop(Iop_And64,
   3362                                            mkexpr(arg_m),
   3363                                            unop(Iop_Not64, mkexpr(reg_d)))));
   3364                      }
   3365                      DIP("vbsl %c%u, %c%u, %c%u\n",
   3366                          Q ? 'q' : 'd', dreg,
   3367                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3368                      break;
   3369                   case 2:
   3370                      /* VBIT  */
   3371                      if (Q) {
   3372                         IRTemp reg_d = newTemp(Ity_V128);
   3373                         assign(reg_d, getQReg(dreg));
   3374                         assign(res,
   3375                                binop(Iop_OrV128,
   3376                                      binop(Iop_AndV128, mkexpr(arg_n),
   3377                                                         mkexpr(arg_m)),
   3378                                      binop(Iop_AndV128,
   3379                                            mkexpr(reg_d),
   3380                                            unop(Iop_NotV128, mkexpr(arg_m)))));
   3381                      } else {
   3382                         IRTemp reg_d = newTemp(Ity_I64);
   3383                         assign(reg_d, getDRegI64(dreg));
   3384                         assign(res,
   3385                                binop(Iop_Or64,
   3386                                      binop(Iop_And64, mkexpr(arg_n),
   3387                                                       mkexpr(arg_m)),
   3388                                      binop(Iop_And64,
   3389                                            mkexpr(reg_d),
   3390                                            unop(Iop_Not64, mkexpr(arg_m)))));
   3391                      }
   3392                      DIP("vbit %c%u, %c%u, %c%u\n",
   3393                          Q ? 'q' : 'd', dreg,
   3394                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3395                      break;
   3396                   case 3:
   3397                      /* VBIF  */
   3398                      if (Q) {
   3399                         IRTemp reg_d = newTemp(Ity_V128);
   3400                         assign(reg_d, getQReg(dreg));
   3401                         assign(res,
   3402                                binop(Iop_OrV128,
   3403                                      binop(Iop_AndV128, mkexpr(reg_d),
   3404                                                         mkexpr(arg_m)),
   3405                                      binop(Iop_AndV128,
   3406                                            mkexpr(arg_n),
   3407                                            unop(Iop_NotV128, mkexpr(arg_m)))));
   3408                      } else {
   3409                         IRTemp reg_d = newTemp(Ity_I64);
   3410                         assign(reg_d, getDRegI64(dreg));
   3411                         assign(res,
   3412                                binop(Iop_Or64,
   3413                                      binop(Iop_And64, mkexpr(reg_d),
   3414                                                       mkexpr(arg_m)),
   3415                                      binop(Iop_And64,
   3416                                            mkexpr(arg_n),
   3417                                            unop(Iop_Not64, mkexpr(arg_m)))));
   3418                      }
   3419                      DIP("vbif %c%u, %c%u, %c%u\n",
   3420                          Q ? 'q' : 'd', dreg,
   3421                          Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   3422                      break;
   3423                }
   3424             }
   3425          }
   3426          break;
   3427       case 2:
   3428          if (B == 0) {
   3429             /* VHSUB */
   3430             /* (A >> 1) - (B >> 1) - (NOT (A) & B & 1)   */
   3431             ULong imm = 0;
   3432             IRExpr *imm_val;
   3433             IROp subOp;
   3434             IROp notOp;
   3435             IROp andOp;
   3436             IROp shOp;
   3437             if (size == 3)
   3438                return False;
   3439             switch(size) {
   3440                case 0: imm = 0x101010101010101LL; break;
   3441                case 1: imm = 0x1000100010001LL; break;
   3442                case 2: imm = 0x100000001LL; break;
   3443                default: vassert(0);
   3444             }
   3445             if (Q) {
   3446                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   3447                andOp = Iop_AndV128;
   3448                notOp = Iop_NotV128;
   3449             } else {
   3450                imm_val = mkU64(imm);
   3451                andOp = Iop_And64;
   3452                notOp = Iop_Not64;
   3453             }
   3454             if (U) {
   3455                switch(size) {
   3456                   case 0:
   3457                      subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3458                      shOp = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3459                      break;
   3460                   case 1:
   3461                      subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3462                      shOp = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3463                      break;
   3464                   case 2:
   3465                      subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3466                      shOp = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3467                      break;
   3468                   default:
   3469                      vassert(0);
   3470                }
   3471             } else {
   3472                switch(size) {
   3473                   case 0:
   3474                      subOp = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3475                      shOp = Q ? Iop_SarN8x16 : Iop_SarN8x8;
   3476                      break;
   3477                   case 1:
   3478                      subOp = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3479                      shOp = Q ? Iop_SarN16x8 : Iop_SarN16x4;
   3480                      break;
   3481                   case 2:
   3482                      subOp = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3483                      shOp = Q ? Iop_SarN32x4 : Iop_SarN32x2;
   3484                      break;
   3485                   default:
   3486                      vassert(0);
   3487                }
   3488             }
   3489             assign(res,
   3490                    binop(subOp,
   3491                          binop(subOp,
   3492                                binop(shOp, mkexpr(arg_n), mkU8(1)),
   3493                                binop(shOp, mkexpr(arg_m), mkU8(1))),
   3494                          binop(andOp,
   3495                                binop(andOp,
   3496                                      unop(notOp, mkexpr(arg_n)),
   3497                                      mkexpr(arg_m)),
   3498                                imm_val)));
   3499             DIP("vhsub.%c%u %c%u, %c%u, %c%u\n",
   3500                 U ? 'u' : 's', 8 << size,
   3501                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3502                 mreg);
   3503          } else {
   3504             /* VQSUB */
   3505             IROp op, op2;
   3506             IRTemp tmp;
   3507             if (Q) {
   3508                switch (size) {
   3509                   case 0:
   3510                      op = U ? Iop_QSub8Ux16 : Iop_QSub8Sx16;
   3511                      op2 = Iop_Sub8x16;
   3512                      break;
   3513                   case 1:
   3514                      op = U ? Iop_QSub16Ux8 : Iop_QSub16Sx8;
   3515                      op2 = Iop_Sub16x8;
   3516                      break;
   3517                   case 2:
   3518                      op = U ? Iop_QSub32Ux4 : Iop_QSub32Sx4;
   3519                      op2 = Iop_Sub32x4;
   3520                      break;
   3521                   case 3:
   3522                      op = U ? Iop_QSub64Ux2 : Iop_QSub64Sx2;
   3523                      op2 = Iop_Sub64x2;
   3524                      break;
   3525                   default:
   3526                      vassert(0);
   3527                }
   3528             } else {
   3529                switch (size) {
   3530                   case 0:
   3531                      op = U ? Iop_QSub8Ux8 : Iop_QSub8Sx8;
   3532                      op2 = Iop_Sub8x8;
   3533                      break;
   3534                   case 1:
   3535                      op = U ? Iop_QSub16Ux4 : Iop_QSub16Sx4;
   3536                      op2 = Iop_Sub16x4;
   3537                      break;
   3538                   case 2:
   3539                      op = U ? Iop_QSub32Ux2 : Iop_QSub32Sx2;
   3540                      op2 = Iop_Sub32x2;
   3541                      break;
   3542                   case 3:
   3543                      op = U ? Iop_QSub64Ux1 : Iop_QSub64Sx1;
   3544                      op2 = Iop_Sub64;
   3545                      break;
   3546                   default:
   3547                      vassert(0);
   3548                }
   3549             }
   3550             if (Q)
   3551                tmp = newTemp(Ity_V128);
   3552             else
   3553                tmp = newTemp(Ity_I64);
   3554             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   3555 #ifndef DISABLE_QC_FLAG
   3556             assign(tmp, binop(op2, mkexpr(arg_n), mkexpr(arg_m)));
   3557             setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
   3558 #endif
   3559             DIP("vqsub.%c%u %c%u, %c%u, %c%u\n",
   3560                 U ? 'u' : 's', 8 << size,
   3561                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3562                 mreg);
   3563          }
   3564          break;
   3565       case 3: {
   3566             IROp op;
   3567             if (Q) {
   3568                switch (size) {
   3569                   case 0: op = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16; break;
   3570                   case 1: op = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8; break;
   3571                   case 2: op = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4; break;
   3572                   case 3: return False;
   3573                   default: vassert(0);
   3574                }
   3575             } else {
   3576                switch (size) {
   3577                   case 0: op = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8; break;
   3578                   case 1: op = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4; break;
   3579                   case 2: op = U ? Iop_CmpGT32Ux2: Iop_CmpGT32Sx2; break;
   3580                   case 3: return False;
   3581                   default: vassert(0);
   3582                }
   3583             }
   3584             if (B == 0) {
   3585                /* VCGT  */
   3586                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   3587                DIP("vcgt.%c%u %c%u, %c%u, %c%u\n",
   3588                    U ? 'u' : 's', 8 << size,
   3589                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3590                    mreg);
   3591             } else {
   3592                /* VCGE  */
   3593                /* VCGE res, argn, argm
   3594                     is equal to
   3595                   VCGT tmp, argm, argn
   3596                   VNOT res, tmp */
   3597                assign(res,
   3598                       unop(Q ? Iop_NotV128 : Iop_Not64,
   3599                            binop(op, mkexpr(arg_m), mkexpr(arg_n))));
   3600                DIP("vcge.%c%u %c%u, %c%u, %c%u\n",
   3601                    U ? 'u' : 's', 8 << size,
   3602                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   3603                    mreg);
   3604             }
   3605          }
   3606          break;
   3607       case 4:
   3608          if (B == 0) {
   3609             /* VSHL */
   3610             IROp op, sub_op;
   3611             IRTemp tmp;
   3612             if (U) {
   3613                switch (size) {
   3614                   case 0: op = Q ? Iop_Shl8x16 : Iop_Shl8x8; break;
   3615                   case 1: op = Q ? Iop_Shl16x8 : Iop_Shl16x4; break;
   3616                   case 2: op = Q ? Iop_Shl32x4 : Iop_Shl32x2; break;
   3617                   case 3: op = Q ? Iop_Shl64x2 : Iop_Shl64; break;
   3618                   default: vassert(0);
   3619                }
   3620             } else {
   3621                tmp = newTemp(Q ? Ity_V128 : Ity_I64);
   3622                switch (size) {
   3623                   case 0:
   3624                      op = Q ? Iop_Sar8x16 : Iop_Sar8x8;
   3625                      sub_op = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3626                      break;
   3627                   case 1:
   3628                      op = Q ? Iop_Sar16x8 : Iop_Sar16x4;
   3629                      sub_op = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3630                      break;
   3631                   case 2:
   3632                      op = Q ? Iop_Sar32x4 : Iop_Sar32x2;
   3633                      sub_op = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3634                      break;
   3635                   case 3:
   3636                      op = Q ? Iop_Sar64x2 : Iop_Sar64;
   3637                      sub_op = Q ? Iop_Sub64x2 : Iop_Sub64;
   3638                      break;
   3639                   default:
   3640                      vassert(0);
   3641                }
   3642             }
   3643             if (U) {
   3644                if (!Q && (size == 3))
   3645                   assign(res, binop(op, mkexpr(arg_m),
   3646                                         unop(Iop_64to8, mkexpr(arg_n))));
   3647                else
   3648                   assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
   3649             } else {
   3650                if (Q)
   3651                   assign(tmp, binop(sub_op,
   3652                                     binop(Iop_64HLtoV128, mkU64(0), mkU64(0)),
   3653                                     mkexpr(arg_n)));
   3654                else
   3655                   assign(tmp, binop(sub_op, mkU64(0), mkexpr(arg_n)));
   3656                if (!Q && (size == 3))
   3657                   assign(res, binop(op, mkexpr(arg_m),
   3658                                         unop(Iop_64to8, mkexpr(tmp))));
   3659                else
   3660                   assign(res, binop(op, mkexpr(arg_m), mkexpr(tmp)));
   3661             }
   3662             DIP("vshl.%c%u %c%u, %c%u, %c%u\n",
   3663                 U ? 'u' : 's', 8 << size,
   3664                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   3665                 nreg);
   3666          } else {
   3667             /* VQSHL */
   3668             IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt;
   3669             IRTemp tmp, shval, mask, old_shval;
   3670             UInt i;
   3671             ULong esize;
   3672             cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
   3673             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   3674             if (U) {
   3675                switch (size) {
   3676                   case 0:
   3677                      op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
   3678                      op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
   3679                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3680                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3681                      break;
   3682                   case 1:
   3683                      op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
   3684                      op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
   3685                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3686                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3687                      break;
   3688                   case 2:
   3689                      op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
   3690                      op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
   3691                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3692                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3693                      break;
   3694                   case 3:
   3695                      op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
   3696                      op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
   3697                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3698                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3699                      break;
   3700                   default:
   3701                      vassert(0);
   3702                }
   3703             } else {
   3704                switch (size) {
   3705                   case 0:
   3706                      op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
   3707                      op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
   3708                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3709                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3710                      break;
   3711                   case 1:
   3712                      op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
   3713                      op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
   3714                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3715                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3716                      break;
   3717                   case 2:
   3718                      op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
   3719                      op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
   3720                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3721                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3722                      break;
   3723                   case 3:
   3724                      op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
   3725                      op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
   3726                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3727                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3728                      break;
   3729                   default:
   3730                      vassert(0);
   3731                }
   3732             }
   3733             if (Q) {
   3734                tmp = newTemp(Ity_V128);
   3735                shval = newTemp(Ity_V128);
   3736                mask = newTemp(Ity_V128);
   3737             } else {
   3738                tmp = newTemp(Ity_I64);
   3739                shval = newTemp(Ity_I64);
   3740                mask = newTemp(Ity_I64);
   3741             }
   3742             assign(res, binop(op, mkexpr(arg_m), mkexpr(arg_n)));
   3743 #ifndef DISABLE_QC_FLAG
   3744             /* Only least significant byte from second argument is used.
   3745                Copy this byte to the whole vector element. */
   3746             assign(shval, binop(op_shrn,
   3747                                 binop(op_shln,
   3748                                        mkexpr(arg_n),
   3749                                        mkU8((8 << size) - 8)),
   3750                                 mkU8((8 << size) - 8)));
   3751             for(i = 0; i < size; i++) {
   3752                old_shval = shval;
   3753                shval = newTemp(Q ? Ity_V128 : Ity_I64);
   3754                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
   3755                                    mkexpr(old_shval),
   3756                                    binop(op_shln,
   3757                                          mkexpr(old_shval),
   3758                                          mkU8(8 << i))));
   3759             }
   3760             /* If shift is greater or equal to the element size and
   3761                element is non-zero, then QC flag should be set. */
   3762             esize = (8 << size) - 1;
   3763             esize = (esize <<  8) | esize;
   3764             esize = (esize << 16) | esize;
   3765             esize = (esize << 32) | esize;
   3766             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   3767                              binop(cmp_gt, mkexpr(shval),
   3768                                            Q ? mkU128(esize) : mkU64(esize)),
   3769                              unop(cmp_neq, mkexpr(arg_m))),
   3770                        Q ? mkU128(0) : mkU64(0),
   3771                        Q, condT);
   3772             /* Othervise QC flag should be set if shift value is positive and
   3773                result beign rightshifted the same value is not equal to left
   3774                argument. */
   3775             assign(mask, binop(cmp_gt, mkexpr(shval),
   3776                                        Q ? mkU128(0) : mkU64(0)));
   3777             if (!Q && size == 3)
   3778                assign(tmp, binop(op_rev, mkexpr(res),
   3779                                          unop(Iop_64to8, mkexpr(arg_n))));
   3780             else
   3781                assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
   3782             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   3783                              mkexpr(tmp), mkexpr(mask)),
   3784                        binop(Q ? Iop_AndV128 : Iop_And64,
   3785                              mkexpr(arg_m), mkexpr(mask)),
   3786                        Q, condT);
   3787 #endif
   3788             DIP("vqshl.%c%u %c%u, %c%u, %c%u\n",
   3789                 U ? 'u' : 's', 8 << size,
   3790                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   3791                 nreg);
   3792          }
   3793          break;
   3794       case 5:
   3795          if (B == 0) {
   3796             /* VRSHL */
   3797             IROp op, op_shrn, op_shln, cmp_gt, op_sub, op_add;
   3798             IRTemp shval, old_shval, imm_val, round;
   3799             UInt i;
   3800             ULong imm;
   3801             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   3802             imm = 1L;
   3803             switch (size) {
   3804                case 0: imm = (imm <<  8) | imm; /* fall through */
   3805                case 1: imm = (imm << 16) | imm; /* fall through */
   3806                case 2: imm = (imm << 32) | imm; /* fall through */
   3807                case 3: break;
   3808                default: vassert(0);
   3809             }
   3810             imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
   3811             round = newTemp(Q ? Ity_V128 : Ity_I64);
   3812             assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
   3813             if (U) {
   3814                switch (size) {
   3815                   case 0:
   3816                      op = Q ? Iop_Shl8x16 : Iop_Shl8x8;
   3817                      op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3818                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   3819                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3820                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3821                      break;
   3822                   case 1:
   3823                      op = Q ? Iop_Shl16x8 : Iop_Shl16x4;
   3824                      op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3825                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   3826                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3827                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3828                      break;
   3829                   case 2:
   3830                      op = Q ? Iop_Shl32x4 : Iop_Shl32x2;
   3831                      op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3832                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   3833                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3834                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3835                      break;
   3836                   case 3:
   3837                      op = Q ? Iop_Shl64x2 : Iop_Shl64;
   3838                      op_sub = Q ? Iop_Sub64x2 : Iop_Sub64;
   3839                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   3840                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3841                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3842                      break;
   3843                   default:
   3844                      vassert(0);
   3845                }
   3846             } else {
   3847                switch (size) {
   3848                   case 0:
   3849                      op = Q ? Iop_Sal8x16 : Iop_Sal8x8;
   3850                      op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3851                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   3852                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3853                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3854                      break;
   3855                   case 1:
   3856                      op = Q ? Iop_Sal16x8 : Iop_Sal16x4;
   3857                      op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3858                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   3859                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3860                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3861                      break;
   3862                   case 2:
   3863                      op = Q ? Iop_Sal32x4 : Iop_Sal32x2;
   3864                      op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3865                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   3866                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3867                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3868                      break;
   3869                   case 3:
   3870                      op = Q ? Iop_Sal64x2 : Iop_Sal64x1;
   3871                      op_sub = Q ? Iop_Sub64x2 : Iop_Sub64;
   3872                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   3873                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3874                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3875                      break;
   3876                   default:
   3877                      vassert(0);
   3878                }
   3879             }
   3880             if (Q) {
   3881                shval = newTemp(Ity_V128);
   3882             } else {
   3883                shval = newTemp(Ity_I64);
   3884             }
   3885             /* Only least significant byte from second argument is used.
   3886                Copy this byte to the whole vector element. */
   3887             assign(shval, binop(op_shrn,
   3888                                 binop(op_shln,
   3889                                        mkexpr(arg_n),
   3890                                        mkU8((8 << size) - 8)),
   3891                                 mkU8((8 << size) - 8)));
   3892             for (i = 0; i < size; i++) {
   3893                old_shval = shval;
   3894                shval = newTemp(Q ? Ity_V128 : Ity_I64);
   3895                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
   3896                                    mkexpr(old_shval),
   3897                                    binop(op_shln,
   3898                                          mkexpr(old_shval),
   3899                                          mkU8(8 << i))));
   3900             }
   3901             /* Compute the result */
   3902             if (!Q && size == 3 && U) {
   3903                assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
   3904                                    binop(op,
   3905                                          mkexpr(arg_m),
   3906                                          unop(Iop_64to8,
   3907                                               binop(op_add,
   3908                                                     mkexpr(arg_n),
   3909                                                     mkexpr(imm_val)))),
   3910                                    binop(Q ? Iop_AndV128 : Iop_And64,
   3911                                          mkexpr(imm_val),
   3912                                          binop(cmp_gt,
   3913                                                Q ? mkU128(0) : mkU64(0),
   3914                                                mkexpr(arg_n)))));
   3915                assign(res, binop(op_add,
   3916                                  binop(op,
   3917                                        mkexpr(arg_m),
   3918                                        unop(Iop_64to8, mkexpr(arg_n))),
   3919                                  mkexpr(round)));
   3920             } else {
   3921                assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
   3922                                    binop(op,
   3923                                          mkexpr(arg_m),
   3924                                          binop(op_add,
   3925                                                mkexpr(arg_n),
   3926                                                mkexpr(imm_val))),
   3927                                    binop(Q ? Iop_AndV128 : Iop_And64,
   3928                                          mkexpr(imm_val),
   3929                                          binop(cmp_gt,
   3930                                                Q ? mkU128(0) : mkU64(0),
   3931                                                mkexpr(arg_n)))));
   3932                assign(res, binop(op_add,
   3933                                  binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   3934                                  mkexpr(round)));
   3935             }
   3936             DIP("vrshl.%c%u %c%u, %c%u, %c%u\n",
   3937                 U ? 'u' : 's', 8 << size,
   3938                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   3939                 nreg);
   3940          } else {
   3941             /* VQRSHL */
   3942             IROp op, op_rev, op_shrn, op_shln, cmp_neq, cmp_gt, op_sub, op_add;
   3943             IRTemp tmp, shval, mask, old_shval, imm_val, round;
   3944             UInt i;
   3945             ULong esize, imm;
   3946             cmp_neq = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8;
   3947             cmp_gt = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   3948             imm = 1L;
   3949             switch (size) {
   3950                case 0: imm = (imm <<  8) | imm; /* fall through */
   3951                case 1: imm = (imm << 16) | imm; /* fall through */
   3952                case 2: imm = (imm << 32) | imm; /* fall through */
   3953                case 3: break;
   3954                default: vassert(0);
   3955             }
   3956             imm_val = newTemp(Q ? Ity_V128 : Ity_I64);
   3957             round = newTemp(Q ? Ity_V128 : Ity_I64);
   3958             assign(imm_val, Q ? mkU128(imm) : mkU64(imm));
   3959             if (U) {
   3960                switch (size) {
   3961                   case 0:
   3962                      op = Q ? Iop_QShl8x16 : Iop_QShl8x8;
   3963                      op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   3964                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   3965                      op_rev = Q ? Iop_Shr8x16 : Iop_Shr8x8;
   3966                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   3967                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   3968                      break;
   3969                   case 1:
   3970                      op = Q ? Iop_QShl16x8 : Iop_QShl16x4;
   3971                      op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   3972                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   3973                      op_rev = Q ? Iop_Shr16x8 : Iop_Shr16x4;
   3974                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   3975                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   3976                      break;
   3977                   case 2:
   3978                      op = Q ? Iop_QShl32x4 : Iop_QShl32x2;
   3979                      op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   3980                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   3981                      op_rev = Q ? Iop_Shr32x4 : Iop_Shr32x2;
   3982                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   3983                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   3984                      break;
   3985                   case 3:
   3986                      op = Q ? Iop_QShl64x2 : Iop_QShl64x1;
   3987                      op_sub = Q ? Iop_Sub64x2 : Iop_Sub64;
   3988                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   3989                      op_rev = Q ? Iop_Shr64x2 : Iop_Shr64;
   3990                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   3991                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   3992                      break;
   3993                   default:
   3994                      vassert(0);
   3995                }
   3996             } else {
   3997                switch (size) {
   3998                   case 0:
   3999                      op = Q ? Iop_QSal8x16 : Iop_QSal8x8;
   4000                      op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   4001                      op_add = Q ? Iop_Add8x16 : Iop_Add8x8;
   4002                      op_rev = Q ? Iop_Sar8x16 : Iop_Sar8x8;
   4003                      op_shrn = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   4004                      op_shln = Q ? Iop_ShlN8x16 : Iop_ShlN8x8;
   4005                      break;
   4006                   case 1:
   4007                      op = Q ? Iop_QSal16x8 : Iop_QSal16x4;
   4008                      op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   4009                      op_add = Q ? Iop_Add16x8 : Iop_Add16x4;
   4010                      op_rev = Q ? Iop_Sar16x8 : Iop_Sar16x4;
   4011                      op_shrn = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   4012                      op_shln = Q ? Iop_ShlN16x8 : Iop_ShlN16x4;
   4013                      break;
   4014                   case 2:
   4015                      op = Q ? Iop_QSal32x4 : Iop_QSal32x2;
   4016                      op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   4017                      op_add = Q ? Iop_Add32x4 : Iop_Add32x2;
   4018                      op_rev = Q ? Iop_Sar32x4 : Iop_Sar32x2;
   4019                      op_shrn = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   4020                      op_shln = Q ? Iop_ShlN32x4 : Iop_ShlN32x2;
   4021                      break;
   4022                   case 3:
   4023                      op = Q ? Iop_QSal64x2 : Iop_QSal64x1;
   4024                      op_sub = Q ? Iop_Sub64x2 : Iop_Sub64;
   4025                      op_add = Q ? Iop_Add64x2 : Iop_Add64;
   4026                      op_rev = Q ? Iop_Sar64x2 : Iop_Sar64;
   4027                      op_shrn = Q ? Iop_ShrN64x2 : Iop_Shr64;
   4028                      op_shln = Q ? Iop_ShlN64x2 : Iop_Shl64;
   4029                      break;
   4030                   default:
   4031                      vassert(0);
   4032                }
   4033             }
   4034             if (Q) {
   4035                tmp = newTemp(Ity_V128);
   4036                shval = newTemp(Ity_V128);
   4037                mask = newTemp(Ity_V128);
   4038             } else {
   4039                tmp = newTemp(Ity_I64);
   4040                shval = newTemp(Ity_I64);
   4041                mask = newTemp(Ity_I64);
   4042             }
   4043             /* Only least significant byte from second argument is used.
   4044                Copy this byte to the whole vector element. */
   4045             assign(shval, binop(op_shrn,
   4046                                 binop(op_shln,
   4047                                        mkexpr(arg_n),
   4048                                        mkU8((8 << size) - 8)),
   4049                                 mkU8((8 << size) - 8)));
   4050             for (i = 0; i < size; i++) {
   4051                old_shval = shval;
   4052                shval = newTemp(Q ? Ity_V128 : Ity_I64);
   4053                assign(shval, binop(Q ? Iop_OrV128 : Iop_Or64,
   4054                                    mkexpr(old_shval),
   4055                                    binop(op_shln,
   4056                                          mkexpr(old_shval),
   4057                                          mkU8(8 << i))));
   4058             }
   4059             /* Compute the result */
   4060             assign(round, binop(Q ? Iop_AndV128 : Iop_And64,
   4061                                 binop(op,
   4062                                       mkexpr(arg_m),
   4063                                       binop(op_add,
   4064                                             mkexpr(arg_n),
   4065                                             mkexpr(imm_val))),
   4066                                 binop(Q ? Iop_AndV128 : Iop_And64,
   4067                                       mkexpr(imm_val),
   4068                                       binop(cmp_gt,
   4069                                             Q ? mkU128(0) : mkU64(0),
   4070                                             mkexpr(arg_n)))));
   4071             assign(res, binop(op_add,
   4072                               binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   4073                               mkexpr(round)));
   4074 #ifndef DISABLE_QC_FLAG
   4075             /* If shift is greater or equal to the element size and element is
   4076                non-zero, then QC flag should be set. */
   4077             esize = (8 << size) - 1;
   4078             esize = (esize <<  8) | esize;
   4079             esize = (esize << 16) | esize;
   4080             esize = (esize << 32) | esize;
   4081             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4082                              binop(cmp_gt, mkexpr(shval),
   4083                                            Q ? mkU128(esize) : mkU64(esize)),
   4084                              unop(cmp_neq, mkexpr(arg_m))),
   4085                        Q ? mkU128(0) : mkU64(0),
   4086                        Q, condT);
   4087             /* Othervise QC flag should be set if shift value is positive and
   4088                result beign rightshifted the same value is not equal to left
   4089                argument. */
   4090             assign(mask, binop(cmp_gt, mkexpr(shval),
   4091                                Q ? mkU128(0) : mkU64(0)));
   4092             if (!Q && size == 3)
   4093                assign(tmp, binop(op_rev, mkexpr(res),
   4094                                          unop(Iop_64to8, mkexpr(arg_n))));
   4095             else
   4096                assign(tmp, binop(op_rev, mkexpr(res), mkexpr(arg_n)));
   4097             setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4098                              mkexpr(tmp), mkexpr(mask)),
   4099                        binop(Q ? Iop_AndV128 : Iop_And64,
   4100                              mkexpr(arg_m), mkexpr(mask)),
   4101                        Q, condT);
   4102 #endif
   4103             DIP("vqrshl.%c%u %c%u, %c%u, %c%u\n",
   4104                 U ? 'u' : 's', 8 << size,
   4105                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, Q ? 'q' : 'd',
   4106                 nreg);
   4107          }
   4108          break;
   4109       case 6:
   4110          /* VMAX, VMIN  */
   4111          if (B == 0) {
   4112             /* VMAX */
   4113             IROp op;
   4114             if (U == 0) {
   4115                switch (size) {
   4116                   case 0: op = Q ? Iop_Max8Sx16 : Iop_Max8Sx8; break;
   4117                   case 1: op = Q ? Iop_Max16Sx8 : Iop_Max16Sx4; break;
   4118                   case 2: op = Q ? Iop_Max32Sx4 : Iop_Max32Sx2; break;
   4119                   case 3: return False;
   4120                   default: vassert(0);
   4121                }
   4122             } else {
   4123                switch (size) {
   4124                   case 0: op = Q ? Iop_Max8Ux16 : Iop_Max8Ux8; break;
   4125                   case 1: op = Q ? Iop_Max16Ux8 : Iop_Max16Ux4; break;
   4126                   case 2: op = Q ? Iop_Max32Ux4 : Iop_Max32Ux2; break;
   4127                   case 3: return False;
   4128                   default: vassert(0);
   4129                }
   4130             }
   4131             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4132             DIP("vmax.%c%u %c%u, %c%u, %c%u\n",
   4133                 U ? 'u' : 's', 8 << size,
   4134                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4135                 mreg);
   4136          } else {
   4137             /* VMIN */
   4138             IROp op;
   4139             if (U == 0) {
   4140                switch (size) {
   4141                   case 0: op = Q ? Iop_Min8Sx16 : Iop_Min8Sx8; break;
   4142                   case 1: op = Q ? Iop_Min16Sx8 : Iop_Min16Sx4; break;
   4143                   case 2: op = Q ? Iop_Min32Sx4 : Iop_Min32Sx2; break;
   4144                   case 3: return False;
   4145                   default: vassert(0);
   4146                }
   4147             } else {
   4148                switch (size) {
   4149                   case 0: op = Q ? Iop_Min8Ux16 : Iop_Min8Ux8; break;
   4150                   case 1: op = Q ? Iop_Min16Ux8 : Iop_Min16Ux4; break;
   4151                   case 2: op = Q ? Iop_Min32Ux4 : Iop_Min32Ux2; break;
   4152                   case 3: return False;
   4153                   default: vassert(0);
   4154                }
   4155             }
   4156             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4157             DIP("vmin.%c%u %c%u, %c%u, %c%u\n",
   4158                 U ? 'u' : 's', 8 << size,
   4159                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4160                 mreg);
   4161          }
   4162          break;
   4163       case 7:
   4164          if (B == 0) {
   4165             /* VABD */
   4166             IROp op_cmp, op_sub;
   4167             IRTemp cond;
   4168             if ((theInstr >> 23) & 1) {
   4169                vpanic("VABDL should not be in dis_neon_data_3same\n");
   4170             }
   4171             if (Q) {
   4172                switch (size) {
   4173                   case 0:
   4174                      op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
   4175                      op_sub = Iop_Sub8x16;
   4176                      break;
   4177                   case 1:
   4178                      op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
   4179                      op_sub = Iop_Sub16x8;
   4180                      break;
   4181                   case 2:
   4182                      op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
   4183                      op_sub = Iop_Sub32x4;
   4184                      break;
   4185                   case 3:
   4186                      return False;
   4187                   default:
   4188                      vassert(0);
   4189                }
   4190             } else {
   4191                switch (size) {
   4192                   case 0:
   4193                      op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   4194                      op_sub = Iop_Sub8x8;
   4195                      break;
   4196                   case 1:
   4197                      op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   4198                      op_sub = Iop_Sub16x4;
   4199                      break;
   4200                   case 2:
   4201                      op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   4202                      op_sub = Iop_Sub32x2;
   4203                      break;
   4204                   case 3:
   4205                      return False;
   4206                   default:
   4207                      vassert(0);
   4208                }
   4209             }
   4210             if (Q) {
   4211                cond = newTemp(Ity_V128);
   4212             } else {
   4213                cond = newTemp(Ity_I64);
   4214             }
   4215             assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
   4216             assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
   4217                               binop(Q ? Iop_AndV128 : Iop_And64,
   4218                                     binop(op_sub, mkexpr(arg_n),
   4219                                                   mkexpr(arg_m)),
   4220                                     mkexpr(cond)),
   4221                               binop(Q ? Iop_AndV128 : Iop_And64,
   4222                                     binop(op_sub, mkexpr(arg_m),
   4223                                                   mkexpr(arg_n)),
   4224                                     unop(Q ? Iop_NotV128 : Iop_Not64,
   4225                                          mkexpr(cond)))));
   4226             DIP("vabd.%c%u %c%u, %c%u, %c%u\n",
   4227                 U ? 'u' : 's', 8 << size,
   4228                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4229                 mreg);
   4230          } else {
   4231             /* VABA */
   4232             IROp op_cmp, op_sub, op_add;
   4233             IRTemp cond, acc, tmp;
   4234             if ((theInstr >> 23) & 1) {
   4235                vpanic("VABAL should not be in dis_neon_data_3same");
   4236             }
   4237             if (Q) {
   4238                switch (size) {
   4239                   case 0:
   4240                      op_cmp = U ? Iop_CmpGT8Ux16 : Iop_CmpGT8Sx16;
   4241                      op_sub = Iop_Sub8x16;
   4242                      op_add = Iop_Add8x16;
   4243                      break;
   4244                   case 1:
   4245                      op_cmp = U ? Iop_CmpGT16Ux8 : Iop_CmpGT16Sx8;
   4246                      op_sub = Iop_Sub16x8;
   4247                      op_add = Iop_Add16x8;
   4248                      break;
   4249                   case 2:
   4250                      op_cmp = U ? Iop_CmpGT32Ux4 : Iop_CmpGT32Sx4;
   4251                      op_sub = Iop_Sub32x4;
   4252                      op_add = Iop_Add32x4;
   4253                      break;
   4254                   case 3:
   4255                      return False;
   4256                   default:
   4257                      vassert(0);
   4258                }
   4259             } else {
   4260                switch (size) {
   4261                   case 0:
   4262                      op_cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   4263                      op_sub = Iop_Sub8x8;
   4264                      op_add = Iop_Add8x8;
   4265                      break;
   4266                   case 1:
   4267                      op_cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   4268                      op_sub = Iop_Sub16x4;
   4269                      op_add = Iop_Add16x4;
   4270                      break;
   4271                   case 2:
   4272                      op_cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   4273                      op_sub = Iop_Sub32x2;
   4274                      op_add = Iop_Add32x2;
   4275                      break;
   4276                   case 3:
   4277                      return False;
   4278                   default:
   4279                      vassert(0);
   4280                }
   4281             }
   4282             if (Q) {
   4283                cond = newTemp(Ity_V128);
   4284                acc = newTemp(Ity_V128);
   4285                tmp = newTemp(Ity_V128);
   4286                assign(acc, getQReg(dreg));
   4287             } else {
   4288                cond = newTemp(Ity_I64);
   4289                acc = newTemp(Ity_I64);
   4290                tmp = newTemp(Ity_I64);
   4291                assign(acc, getDRegI64(dreg));
   4292             }
   4293             assign(cond, binop(op_cmp, mkexpr(arg_n), mkexpr(arg_m)));
   4294             assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
   4295                               binop(Q ? Iop_AndV128 : Iop_And64,
   4296                                     binop(op_sub, mkexpr(arg_n),
   4297                                                   mkexpr(arg_m)),
   4298                                     mkexpr(cond)),
   4299                               binop(Q ? Iop_AndV128 : Iop_And64,
   4300                                     binop(op_sub, mkexpr(arg_m),
   4301                                                   mkexpr(arg_n)),
   4302                                     unop(Q ? Iop_NotV128 : Iop_Not64,
   4303                                          mkexpr(cond)))));
   4304             assign(res, binop(op_add, mkexpr(acc), mkexpr(tmp)));
   4305             DIP("vaba.%c%u %c%u, %c%u, %c%u\n",
   4306                 U ? 'u' : 's', 8 << size,
   4307                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4308                 mreg);
   4309          }
   4310          break;
   4311       case 8:
   4312          if (B == 0) {
   4313             IROp op;
   4314             if (U == 0) {
   4315                /* VADD  */
   4316                switch (size) {
   4317                   case 0: op = Q ? Iop_Add8x16 : Iop_Add8x8; break;
   4318                   case 1: op = Q ? Iop_Add16x8 : Iop_Add16x4; break;
   4319                   case 2: op = Q ? Iop_Add32x4 : Iop_Add32x2; break;
   4320                   case 3: op = Q ? Iop_Add64x2 : Iop_Add64; break;
   4321                   default: vassert(0);
   4322                }
   4323                DIP("vadd.i%u %c%u, %c%u, %c%u\n",
   4324                    8 << size, Q ? 'q' : 'd',
   4325                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4326             } else {
   4327                /* VSUB  */
   4328                switch (size) {
   4329                   case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
   4330                   case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
   4331                   case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
   4332                   case 3: op = Q ? Iop_Sub64x2 : Iop_Sub64; break;
   4333                   default: vassert(0);
   4334                }
   4335                DIP("vsub.i%u %c%u, %c%u, %c%u\n",
   4336                    8 << size, Q ? 'q' : 'd',
   4337                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4338             }
   4339             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4340          } else {
   4341             IROp op;
   4342             switch (size) {
   4343                case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
   4344                case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
   4345                case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
   4346                case 3: op = Q ? Iop_CmpNEZ64x2 : Iop_CmpwNEZ64; break;
   4347                default: vassert(0);
   4348             }
   4349             if (U == 0) {
   4350                /* VTST  */
   4351                assign(res, unop(op, binop(Q ? Iop_AndV128 : Iop_And64,
   4352                                           mkexpr(arg_n),
   4353                                           mkexpr(arg_m))));
   4354                DIP("vtst.%u %c%u, %c%u, %c%u\n",
   4355                    8 << size, Q ? 'q' : 'd',
   4356                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4357             } else {
   4358                /* VCEQ  */
   4359                assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   4360                                 unop(op,
   4361                                      binop(Q ? Iop_XorV128 : Iop_Xor64,
   4362                                            mkexpr(arg_n),
   4363                                            mkexpr(arg_m)))));
   4364                DIP("vceq.i%u %c%u, %c%u, %c%u\n",
   4365                    8 << size, Q ? 'q' : 'd',
   4366                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4367             }
   4368          }
   4369          break;
   4370       case 9:
   4371          if (B == 0) {
   4372             /* VMLA, VMLS (integer) */
   4373             IROp op, op2;
   4374             UInt P = (theInstr >> 24) & 1;
   4375             if (P) {
   4376                switch (size) {
   4377                   case 0:
   4378                      op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
   4379                      op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   4380                      break;
   4381                   case 1:
   4382                      op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   4383                      op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   4384                      break;
   4385                   case 2:
   4386                      op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   4387                      op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   4388                      break;
   4389                   case 3:
   4390                      return False;
   4391                   default:
   4392                      vassert(0);
   4393                }
   4394             } else {
   4395                switch (size) {
   4396                   case 0:
   4397                      op = Q ? Iop_Mul8x16 : Iop_Mul8x8;
   4398                      op2 = Q ? Iop_Add8x16 : Iop_Add8x8;
   4399                      break;
   4400                   case 1:
   4401                      op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   4402                      op2 = Q ? Iop_Add16x8 : Iop_Add16x4;
   4403                      break;
   4404                   case 2:
   4405                      op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   4406                      op2 = Q ? Iop_Add32x4 : Iop_Add32x2;
   4407                      break;
   4408                   case 3:
   4409                      return False;
   4410                   default:
   4411                      vassert(0);
   4412                }
   4413             }
   4414             assign(res, binop(op2,
   4415                               Q ? getQReg(dreg) : getDRegI64(dreg),
   4416                               binop(op, mkexpr(arg_n), mkexpr(arg_m))));
   4417             DIP("vml%c.i%u %c%u, %c%u, %c%u\n",
   4418                 P ? 's' : 'a', 8 << size,
   4419                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4420                 mreg);
   4421          } else {
   4422             /* VMUL */
   4423             IROp op;
   4424             UInt P = (theInstr >> 24) & 1;
   4425             if (P) {
   4426                switch (size) {
   4427                   case 0:
   4428                      op = Q ? Iop_PolynomialMul8x16 : Iop_PolynomialMul8x8;
   4429                      break;
   4430                   case 1: case 2: case 3: return False;
   4431                   default: vassert(0);
   4432                }
   4433             } else {
   4434                switch (size) {
   4435                   case 0: op = Q ? Iop_Mul8x16 : Iop_Mul8x8; break;
   4436                   case 1: op = Q ? Iop_Mul16x8 : Iop_Mul16x4; break;
   4437                   case 2: op = Q ? Iop_Mul32x4 : Iop_Mul32x2; break;
   4438                   case 3: return False;
   4439                   default: vassert(0);
   4440                }
   4441             }
   4442             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4443             DIP("vmul.%c%u %c%u, %c%u, %c%u\n",
   4444                 P ? 'p' : 'i', 8 << size,
   4445                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd',
   4446                 mreg);
   4447          }
   4448          break;
   4449       case 10: {
   4450          /* VPMAX, VPMIN  */
   4451          UInt P = (theInstr >> 4) & 1;
   4452          IROp op;
   4453          if (Q)
   4454             return False;
   4455          if (P) {
   4456             switch (size) {
   4457                case 0: op = U ? Iop_PwMin8Ux8  : Iop_PwMin8Sx8; break;
   4458                case 1: op = U ? Iop_PwMin16Ux4 : Iop_PwMin16Sx4; break;
   4459                case 2: op = U ? Iop_PwMin32Ux2 : Iop_PwMin32Sx2; break;
   4460                case 3: return False;
   4461                default: vassert(0);
   4462             }
   4463          } else {
   4464             switch (size) {
   4465                case 0: op = U ? Iop_PwMax8Ux8  : Iop_PwMax8Sx8; break;
   4466                case 1: op = U ? Iop_PwMax16Ux4 : Iop_PwMax16Sx4; break;
   4467                case 2: op = U ? Iop_PwMax32Ux2 : Iop_PwMax32Sx2; break;
   4468                case 3: return False;
   4469                default: vassert(0);
   4470             }
   4471          }
   4472          assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4473          DIP("vp%s.%c%u %c%u, %c%u, %c%u\n",
   4474              P ? "min" : "max", U ? 'u' : 's',
   4475              8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
   4476              Q ? 'q' : 'd', mreg);
   4477          break;
   4478       }
   4479       case 11:
   4480          if (B == 0) {
   4481             if (U == 0) {
   4482                /* VQDMULH  */
   4483                IROp op ,op2;
   4484                ULong imm;
   4485                switch (size) {
   4486                   case 0: case 3:
   4487                      return False;
   4488                   case 1:
   4489                      op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
   4490                      op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   4491                      imm = 1LL << 15;
   4492                      imm = (imm << 16) | imm;
   4493                      imm = (imm << 32) | imm;
   4494                      break;
   4495                   case 2:
   4496                      op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
   4497                      op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   4498                      imm = 1LL << 31;
   4499                      imm = (imm << 32) | imm;
   4500                      break;
   4501                   default:
   4502                      vassert(0);
   4503                }
   4504                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4505 #ifndef DISABLE_QC_FLAG
   4506                setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4507                                 binop(op2, mkexpr(arg_n),
   4508                                            Q ? mkU128(imm) : mkU64(imm)),
   4509                                 binop(op2, mkexpr(arg_m),
   4510                                            Q ? mkU128(imm) : mkU64(imm))),
   4511                           Q ? mkU128(0) : mkU64(0),
   4512                           Q, condT);
   4513 #endif
   4514                DIP("vqdmulh.s%u %c%u, %c%u, %c%u\n",
   4515                    8 << size, Q ? 'q' : 'd',
   4516                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4517             } else {
   4518                /* VQRDMULH */
   4519                IROp op ,op2;
   4520                ULong imm;
   4521                switch(size) {
   4522                   case 0: case 3:
   4523                      return False;
   4524                   case 1:
   4525                      imm = 1LL << 15;
   4526                      imm = (imm << 16) | imm;
   4527                      imm = (imm << 32) | imm;
   4528                      op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
   4529                      op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   4530                      break;
   4531                   case 2:
   4532                      imm = 1LL << 31;
   4533                      imm = (imm << 32) | imm;
   4534                      op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
   4535                      op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   4536                      break;
   4537                   default:
   4538                      vassert(0);
   4539                }
   4540                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4541 #ifndef DISABLE_QC_FLAG
   4542                setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   4543                                 binop(op2, mkexpr(arg_n),
   4544                                            Q ? mkU128(imm) : mkU64(imm)),
   4545                                 binop(op2, mkexpr(arg_m),
   4546                                            Q ? mkU128(imm) : mkU64(imm))),
   4547                           Q ? mkU128(0) : mkU64(0),
   4548                           Q, condT);
   4549 #endif
   4550                DIP("vqrdmulh.s%u %c%u, %c%u, %c%u\n",
   4551                    8 << size, Q ? 'q' : 'd',
   4552                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4553             }
   4554          } else {
   4555             if (U == 0) {
   4556                /* VPADD */
   4557                IROp op;
   4558                if (Q)
   4559                   return False;
   4560                switch (size) {
   4561                   case 0: op = Q ? Iop_PwAdd8x16 : Iop_PwAdd8x8;  break;
   4562                   case 1: op = Q ? Iop_PwAdd16x8 : Iop_PwAdd16x4; break;
   4563                   case 2: op = Q ? Iop_PwAdd32x4 : Iop_PwAdd32x2; break;
   4564                   case 3: return False;
   4565                   default: vassert(0);
   4566                }
   4567                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4568                DIP("vpadd.i%d %c%u, %c%u, %c%u\n",
   4569                    8 << size, Q ? 'q' : 'd',
   4570                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4571             }
   4572          }
   4573          break;
   4574       /* Starting from here these are FP SIMD cases */
   4575       case 13:
   4576          if (B == 0) {
   4577             IROp op;
   4578             if (U == 0) {
   4579                if ((C >> 1) == 0) {
   4580                   /* VADD  */
   4581                   op = Q ? Iop_Add32Fx4 : Iop_Add32Fx2 ;
   4582                   DIP("vadd.f32 %c%u, %c%u, %c%u\n",
   4583                       Q ? 'q' : 'd', dreg,
   4584                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4585                } else {
   4586                   /* VSUB  */
   4587                   op = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2 ;
   4588                   DIP("vsub.f32 %c%u, %c%u, %c%u\n",
   4589                       Q ? 'q' : 'd', dreg,
   4590                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4591                }
   4592             } else {
   4593                if ((C >> 1) == 0) {
   4594                   /* VPADD */
   4595                   if (Q)
   4596                      return False;
   4597                   op = Iop_PwAdd32Fx2;
   4598                   DIP("vpadd.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
   4599                } else {
   4600                   /* VABD  */
   4601                   if (Q) {
   4602                      assign(res, unop(Iop_Abs32Fx4,
   4603                                       binop(Iop_Sub32Fx4,
   4604                                             mkexpr(arg_n),
   4605                                             mkexpr(arg_m))));
   4606                   } else {
   4607                      assign(res, unop(Iop_Abs32Fx2,
   4608                                       binop(Iop_Sub32Fx2,
   4609                                             mkexpr(arg_n),
   4610                                             mkexpr(arg_m))));
   4611                   }
   4612                   DIP("vabd.f32 %c%u, %c%u, %c%u\n",
   4613                       Q ? 'q' : 'd', dreg,
   4614                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4615                   break;
   4616                }
   4617             }
   4618             assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4619          } else {
   4620             if (U == 0) {
   4621                /* VMLA, VMLS  */
   4622                IROp op, op2;
   4623                UInt P = (theInstr >> 21) & 1;
   4624                if (P) {
   4625                   switch (size & 1) {
   4626                      case 0:
   4627                         op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   4628                         op2 = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
   4629                         break;
   4630                      case 1: return False;
   4631                      default: vassert(0);
   4632                   }
   4633                } else {
   4634                   switch (size & 1) {
   4635                      case 0:
   4636                         op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   4637                         op2 = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
   4638                         break;
   4639                      case 1: return False;
   4640                      default: vassert(0);
   4641                   }
   4642                }
   4643                assign(res, binop(op2,
   4644                                  Q ? getQReg(dreg) : getDRegI64(dreg),
   4645                                  binop(op, mkexpr(arg_n), mkexpr(arg_m))));
   4646 
   4647                DIP("vml%c.f32 %c%u, %c%u, %c%u\n",
   4648                    P ? 's' : 'a', Q ? 'q' : 'd',
   4649                    dreg, Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4650             } else {
   4651                /* VMUL  */
   4652                IROp op;
   4653                if ((C >> 1) != 0)
   4654                   return False;
   4655                op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2 ;
   4656                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4657                DIP("vmul.f32 %c%u, %c%u, %c%u\n",
   4658                    Q ? 'q' : 'd', dreg,
   4659                    Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4660             }
   4661          }
   4662          break;
   4663       case 14:
   4664          if (B == 0) {
   4665             if (U == 0) {
   4666                if ((C >> 1) == 0) {
   4667                   /* VCEQ  */
   4668                   IROp op;
   4669                   if ((theInstr >> 20) & 1)
   4670                      return False;
   4671                   op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2;
   4672                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4673                   DIP("vceq.f32 %c%u, %c%u, %c%u\n",
   4674                       Q ? 'q' : 'd', dreg,
   4675                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4676                } else {
   4677                   return False;
   4678                }
   4679             } else {
   4680                if ((C >> 1) == 0) {
   4681                   /* VCGE  */
   4682                   IROp op;
   4683                   if ((theInstr >> 20) & 1)
   4684                      return False;
   4685                   op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
   4686                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4687                   DIP("vcge.f32 %c%u, %c%u, %c%u\n",
   4688                       Q ? 'q' : 'd', dreg,
   4689                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4690                } else {
   4691                   /* VCGT  */
   4692                   IROp op;
   4693                   if ((theInstr >> 20) & 1)
   4694                      return False;
   4695                   op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
   4696                   assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4697                   DIP("vcgt.f32 %c%u, %c%u, %c%u\n",
   4698                       Q ? 'q' : 'd', dreg,
   4699                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4700                }
   4701             }
   4702          } else {
   4703             if (U == 1) {
   4704                /* VACGE, VACGT */
   4705                UInt op_bit = (theInstr >> 21) & 1;
   4706                IROp op, op2;
   4707                op2 = Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2;
   4708                if (op_bit) {
   4709                   op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2;
   4710                   assign(res, binop(op,
   4711                                     unop(op2, mkexpr(arg_n)),
   4712                                     unop(op2, mkexpr(arg_m))));
   4713                } else {
   4714                   op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2;
   4715                   assign(res, binop(op,
   4716                                     unop(op2, mkexpr(arg_n)),
   4717                                     unop(op2, mkexpr(arg_m))));
   4718                }
   4719                DIP("vacg%c.f32 %c%u, %c%u, %c%u\n", op_bit ? 't' : 'e',
   4720                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg,
   4721                    Q ? 'q' : 'd', mreg);
   4722             }
   4723          }
   4724          break;
   4725       case 15:
   4726          if (B == 0) {
   4727             if (U == 0) {
   4728                /* VMAX, VMIN  */
   4729                IROp op;
   4730                if ((theInstr >> 20) & 1)
   4731                   return False;
   4732                if ((theInstr >> 21) & 1) {
   4733                   op = Q ? Iop_Min32Fx4 : Iop_Min32Fx2;
   4734                   DIP("vmin.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4735                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4736                } else {
   4737                   op = Q ? Iop_Max32Fx4 : Iop_Max32Fx2;
   4738                   DIP("vmax.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4739                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4740                }
   4741                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4742             } else {
   4743                /* VPMAX, VPMIN   */
   4744                IROp op;
   4745                if (Q)
   4746                   return False;
   4747                if ((theInstr >> 20) & 1)
   4748                   return False;
   4749                if ((theInstr >> 21) & 1) {
   4750                   op = Iop_PwMin32Fx2;
   4751                   DIP("vpmin.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
   4752                } else {
   4753                   op = Iop_PwMax32Fx2;
   4754                   DIP("vpmax.f32 d%u, d%u, d%u\n", dreg, nreg, mreg);
   4755                }
   4756                assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   4757             }
   4758          } else {
   4759             if (U == 0) {
   4760                if ((C >> 1) == 0) {
   4761                   /* VRECPS */
   4762                   if ((theInstr >> 20) & 1)
   4763                      return False;
   4764                   assign(res, binop(Q ? Iop_Recps32Fx4 : Iop_Recps32Fx2,
   4765                                     mkexpr(arg_n),
   4766                                     mkexpr(arg_m)));
   4767                   DIP("vrecps.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4768                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4769                } else {
   4770                   /* VRSQRTS  */
   4771                   if ((theInstr >> 20) & 1)
   4772                      return False;
   4773                   assign(res, binop(Q ? Iop_Rsqrts32Fx4 : Iop_Rsqrts32Fx2,
   4774                                     mkexpr(arg_n),
   4775                                     mkexpr(arg_m)));
   4776                   DIP("vrsqrts.f32 %c%u, %c%u, %c%u\n", Q ? 'q' : 'd', dreg,
   4777                       Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
   4778                }
   4779             }
   4780          }
   4781          break;
   4782    }
   4783 
   4784    if (Q) {
   4785       putQReg(dreg, mkexpr(res), condT);
   4786    } else {
   4787       putDRegI64(dreg, mkexpr(res), condT);
   4788    }
   4789 
   4790    return True;
   4791 }
   4792 
   4793 /* A7.4.2 Three registers of different length */
   4794 static
   4795 Bool dis_neon_data_3diff ( UInt theInstr, IRTemp condT )
   4796 {
   4797    UInt A = (theInstr >> 8) & 0xf;
   4798    UInt B = (theInstr >> 20) & 3;
   4799    UInt U = (theInstr >> 24) & 1;
   4800    UInt P = (theInstr >> 9) & 1;
   4801    UInt mreg = get_neon_m_regno(theInstr);
   4802    UInt nreg = get_neon_n_regno(theInstr);
   4803    UInt dreg = get_neon_d_regno(theInstr);
   4804    UInt size = B;
   4805    ULong imm;
   4806    IRTemp res, arg_m, arg_n, cond, tmp;
   4807    IROp cvt, cvt2, cmp, op, op2, sh, add;
   4808    switch (A) {
   4809       case 0: case 1: case 2: case 3:
   4810          /* VADDL, VADDW, VSUBL, VSUBW */
   4811          if (dreg & 1)
   4812             return False;
   4813          dreg >>= 1;
   4814          size = B;
   4815          switch (size) {
   4816             case 0:
   4817                cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
   4818                op = (A & 2) ? Iop_Sub16x8 : Iop_Add16x8;
   4819                break;
   4820             case 1:
   4821                cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
   4822                op = (A & 2) ? Iop_Sub32x4 : Iop_Add32x4;
   4823                break;
   4824             case 2:
   4825                cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
   4826                op = (A & 2) ? Iop_Sub64x2 : Iop_Add64x2;
   4827                break;
   4828             case 3:
   4829                return False;
   4830             default:
   4831                vassert(0);
   4832          }
   4833          arg_n = newTemp(Ity_V128);
   4834          arg_m = newTemp(Ity_V128);
   4835          if (A & 1) {
   4836             if (nreg & 1)
   4837                return False;
   4838             nreg >>= 1;
   4839             assign(arg_n, getQReg(nreg));
   4840          } else {
   4841             assign(arg_n, unop(cvt, getDRegI64(nreg)));
   4842          }
   4843          assign(arg_m, unop(cvt, getDRegI64(mreg)));
   4844          putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   4845                        condT);
   4846          DIP("v%s%c.%c%u q%u, %c%u, d%u\n", (A & 2) ? "sub" : "add",
   4847              (A & 1) ? 'w' : 'l', U ? 'u' : 's', 8 << size, dreg,
   4848              (A & 1) ? 'q' : 'd', nreg, mreg);
   4849          return True;
   4850       case 4:
   4851          /* VADDHN, VRADDHN */
   4852          if (mreg & 1)
   4853             return False;
   4854          mreg >>= 1;
   4855          if (nreg & 1)
   4856             return False;
   4857          nreg >>= 1;
   4858          size = B;
   4859          switch (size) {
   4860             case 0:
   4861                op = Iop_Add16x8;
   4862                cvt = Iop_Shorten16x8;
   4863                sh = Iop_ShrN16x8;
   4864                imm = 1U << 7;
   4865                imm = (imm << 16) | imm;
   4866                imm = (imm << 32) | imm;
   4867                break;
   4868             case 1:
   4869                op = Iop_Add32x4;
   4870                cvt = Iop_Shorten32x4;
   4871                sh = Iop_ShrN32x4;
   4872                imm = 1U << 15;
   4873                imm = (imm << 32) | imm;
   4874                break;
   4875             case 2:
   4876                op = Iop_Add64x2;
   4877                cvt = Iop_Shorten64x2;
   4878                sh = Iop_ShrN64x2;
   4879                imm = 1U << 31;
   4880                break;
   4881             case 3:
   4882                return False;
   4883             default:
   4884                vassert(0);
   4885          }
   4886          tmp = newTemp(Ity_V128);
   4887          res = newTemp(Ity_V128);
   4888          assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
   4889          if (U) {
   4890             /* VRADDHN */
   4891             assign(res, binop(op, mkexpr(tmp),
   4892                      binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
   4893          } else {
   4894             assign(res, mkexpr(tmp));
   4895          }
   4896          putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
   4897                     condT);
   4898          DIP("v%saddhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
   4899              nreg, mreg);
   4900          return True;
   4901       case 5:
   4902          /* VABAL */
   4903          if (!((theInstr >> 23) & 1)) {
   4904             vpanic("VABA should not be in dis_neon_data_3diff\n");
   4905          }
   4906          if (dreg & 1)
   4907             return False;
   4908          dreg >>= 1;
   4909          switch (size) {
   4910             case 0:
   4911                cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   4912                cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
   4913                cvt2 = Iop_Longen8Sx8;
   4914                op = Iop_Sub16x8;
   4915                op2 = Iop_Add16x8;
   4916                break;
   4917             case 1:
   4918                cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   4919                cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
   4920                cvt2 = Iop_Longen16Sx4;
   4921                op = Iop_Sub32x4;
   4922                op2 = Iop_Add32x4;
   4923                break;
   4924             case 2:
   4925                cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   4926                cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
   4927                cvt2 = Iop_Longen32Sx2;
   4928                op = Iop_Sub64x2;
   4929                op2 = Iop_Add64x2;
   4930                break;
   4931             case 3:
   4932                return False;
   4933             default:
   4934                vassert(0);
   4935          }
   4936          arg_n = newTemp(Ity_V128);
   4937          arg_m = newTemp(Ity_V128);
   4938          cond = newTemp(Ity_V128);
   4939          res = newTemp(Ity_V128);
   4940          assign(arg_n, unop(cvt, getDRegI64(nreg)));
   4941          assign(arg_m, unop(cvt, getDRegI64(mreg)));
   4942          assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
   4943                                             getDRegI64(mreg))));
   4944          assign(res, binop(op2,
   4945                            binop(Iop_OrV128,
   4946                                  binop(Iop_AndV128,
   4947                                        binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   4948                                        mkexpr(cond)),
   4949                                  binop(Iop_AndV128,
   4950                                        binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   4951                                        unop(Iop_NotV128, mkexpr(cond)))),
   4952                            getQReg(dreg)));
   4953          putQReg(dreg, mkexpr(res), condT);
   4954          DIP("vabal.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
   4955              nreg, mreg);
   4956          return True;
   4957       case 6:
   4958          /* VSUBHN, VRSUBHN */
   4959          if (mreg & 1)
   4960             return False;
   4961          mreg >>= 1;
   4962          if (nreg & 1)
   4963             return False;
   4964          nreg >>= 1;
   4965          size = B;
   4966          switch (size) {
   4967             case 0:
   4968                op = Iop_Sub16x8;
   4969                op2 = Iop_Add16x8;
   4970                cvt = Iop_Shorten16x8;
   4971                sh = Iop_ShrN16x8;
   4972                imm = 1U << 7;
   4973                imm = (imm << 16) | imm;
   4974                imm = (imm << 32) | imm;
   4975                break;
   4976             case 1:
   4977                op = Iop_Sub32x4;
   4978                op2 = Iop_Add32x4;
   4979                cvt = Iop_Shorten32x4;
   4980                sh = Iop_ShrN32x4;
   4981                imm = 1U << 15;
   4982                imm = (imm << 32) | imm;
   4983                break;
   4984             case 2:
   4985                op = Iop_Sub64x2;
   4986                op2 = Iop_Add64x2;
   4987                cvt = Iop_Shorten64x2;
   4988                sh = Iop_ShrN64x2;
   4989                imm = 1U << 31;
   4990                break;
   4991             case 3:
   4992                return False;
   4993             default:
   4994                vassert(0);
   4995          }
   4996          tmp = newTemp(Ity_V128);
   4997          res = newTemp(Ity_V128);
   4998          assign(tmp, binop(op, getQReg(nreg), getQReg(mreg)));
   4999          if (U) {
   5000             /* VRSUBHN */
   5001             assign(res, binop(op2, mkexpr(tmp),
   5002                      binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm))));
   5003          } else {
   5004             assign(res, mkexpr(tmp));
   5005          }
   5006          putDRegI64(dreg, unop(cvt, binop(sh, mkexpr(res), mkU8(8 << size))),
   5007                     condT);
   5008          DIP("v%ssubhn.i%u d%u, q%u, q%u\n", U ? "r" : "", 16 << size, dreg,
   5009              nreg, mreg);
   5010          return True;
   5011       case 7:
   5012          /* VABDL */
   5013          if (!((theInstr >> 23) & 1)) {
   5014             vpanic("VABL should not be in dis_neon_data_3diff\n");
   5015          }
   5016          if (dreg & 1)
   5017             return False;
   5018          dreg >>= 1;
   5019          switch (size) {
   5020             case 0:
   5021                cmp = U ? Iop_CmpGT8Ux8 : Iop_CmpGT8Sx8;
   5022                cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
   5023                cvt2 = Iop_Longen8Sx8;
   5024                op = Iop_Sub16x8;
   5025                break;
   5026             case 1:
   5027                cmp = U ? Iop_CmpGT16Ux4 : Iop_CmpGT16Sx4;
   5028                cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
   5029                cvt2 = Iop_Longen16Sx4;
   5030                op = Iop_Sub32x4;
   5031                break;
   5032             case 2:
   5033                cmp = U ? Iop_CmpGT32Ux2 : Iop_CmpGT32Sx2;
   5034                cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
   5035                cvt2 = Iop_Longen32Sx2;
   5036                op = Iop_Sub64x2;
   5037                break;
   5038             case 3:
   5039                return False;
   5040             default:
   5041                vassert(0);
   5042          }
   5043          arg_n = newTemp(Ity_V128);
   5044          arg_m = newTemp(Ity_V128);
   5045          cond = newTemp(Ity_V128);
   5046          res = newTemp(Ity_V128);
   5047          assign(arg_n, unop(cvt, getDRegI64(nreg)));
   5048          assign(arg_m, unop(cvt, getDRegI64(mreg)));
   5049          assign(cond, unop(cvt2, binop(cmp, getDRegI64(nreg),
   5050                                             getDRegI64(mreg))));
   5051          assign(res, binop(Iop_OrV128,
   5052                            binop(Iop_AndV128,
   5053                                  binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   5054                                  mkexpr(cond)),
   5055                            binop(Iop_AndV128,
   5056                                  binop(op, mkexpr(arg_m), mkexpr(arg_n)),
   5057                                  unop(Iop_NotV128, mkexpr(cond)))));
   5058          putQReg(dreg, mkexpr(res), condT);
   5059          DIP("vabdl.%c%u q%u, d%u, d%u\n", U ? 'u' : 's', 8 << size, dreg,
   5060              nreg, mreg);
   5061          return True;
   5062       case 8:
   5063       case 10:
   5064          /* VMLAL, VMLSL (integer) */
   5065          if (dreg & 1)
   5066             return False;
   5067          dreg >>= 1;
   5068          size = B;
   5069          switch (size) {
   5070             case 0:
   5071                op = U ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
   5072                op2 = P ? Iop_Sub16x8 : Iop_Add16x8;
   5073                break;
   5074             case 1:
   5075                op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
   5076                op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
   5077                break;
   5078             case 2:
   5079                op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
   5080                op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
   5081                break;
   5082             case 3:
   5083                return False;
   5084             default:
   5085                vassert(0);
   5086          }
   5087          res = newTemp(Ity_V128);
   5088          assign(res, binop(op, getDRegI64(nreg),getDRegI64(mreg)));
   5089          putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
   5090          DIP("vml%cl.%c%u q%u, d%u, d%u\n", P ? 's' : 'a', U ? 'u' : 's',
   5091              8 << size, dreg, nreg, mreg);
   5092          return True;
   5093       case 9:
   5094       case 11:
   5095          /* VQDMLAL, VQDMLSL */
   5096          if (U)
   5097             return False;
   5098          if (dreg & 1)
   5099             return False;
   5100          dreg >>= 1;
   5101          size = B;
   5102          switch (size) {
   5103             case 0: case 3:
   5104                return False;
   5105             case 1:
   5106                op = Iop_QDMulLong16Sx4;
   5107                cmp = Iop_CmpEQ16x4;
   5108                add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
   5109                op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
   5110                imm = 1LL << 15;
   5111                imm = (imm << 16) | imm;
   5112                imm = (imm << 32) | imm;
   5113                break;
   5114             case 2:
   5115                op = Iop_QDMulLong32Sx2;
   5116                cmp = Iop_CmpEQ32x2;
   5117                add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
   5118                op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
   5119                imm = 1LL << 31;
   5120                imm = (imm << 32) | imm;
   5121                break;
   5122             default:
   5123                vassert(0);
   5124          }
   5125          res = newTemp(Ity_V128);
   5126          tmp = newTemp(Ity_V128);
   5127          assign(res, binop(op, getDRegI64(nreg), getDRegI64(mreg)));
   5128 #ifndef DISABLE_QC_FLAG
   5129          assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
   5130          setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
   5131                     True, condT);
   5132          setFlag_QC(binop(Iop_And64,
   5133                           binop(cmp, getDRegI64(nreg), mkU64(imm)),
   5134                           binop(cmp, getDRegI64(mreg), mkU64(imm))),
   5135                     mkU64(0),
   5136                     False, condT);
   5137 #endif
   5138          putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
   5139          DIP("vqdml%cl.s%u q%u, d%u, d%u\n", P ? 's' : 'a', 8 << size, dreg,
   5140              nreg, mreg);
   5141          return True;
   5142       case 12:
   5143       case 14:
   5144          /* VMULL (integer or polynomial) */
   5145          if (dreg & 1)
   5146             return False;
   5147          dreg >>= 1;
   5148          size = B;
   5149          switch (size) {
   5150             case 0:
   5151                op = (U) ? Iop_Mull8Ux8 : Iop_Mull8Sx8;
   5152                if (P)
   5153                   op = Iop_PolynomialMull8x8;
   5154                break;
   5155             case 1:
   5156                op = (U) ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
   5157                break;
   5158             case 2:
   5159                op = (U) ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
   5160                break;
   5161             default:
   5162                vassert(0);
   5163          }
   5164          putQReg(dreg, binop(op, getDRegI64(nreg),
   5165                                  getDRegI64(mreg)), condT);
   5166          DIP("vmull.%c%u q%u, d%u, d%u\n", P ? 'p' : (U ? 'u' : 's'),
   5167                8 << size, dreg, nreg, mreg);
   5168          return True;
   5169       case 13:
   5170          /* VQDMULL */
   5171          if (U)
   5172             return False;
   5173          if (dreg & 1)
   5174             return False;
   5175          dreg >>= 1;
   5176          size = B;
   5177          switch (size) {
   5178             case 0:
   5179             case 3:
   5180                return False;
   5181             case 1:
   5182                op = Iop_QDMulLong16Sx4;
   5183                op2 = Iop_CmpEQ16x4;
   5184                imm = 1LL << 15;
   5185                imm = (imm << 16) | imm;
   5186                imm = (imm << 32) | imm;
   5187                break;
   5188             case 2:
   5189                op = Iop_QDMulLong32Sx2;
   5190                op2 = Iop_CmpEQ32x2;
   5191                imm = 1LL << 31;
   5192                imm = (imm << 32) | imm;
   5193                break;
   5194             default:
   5195                vassert(0);
   5196          }
   5197          putQReg(dreg, binop(op, getDRegI64(nreg), getDRegI64(mreg)),
   5198                condT);
   5199 #ifndef DISABLE_QC_FLAG
   5200          setFlag_QC(binop(Iop_And64,
   5201                           binop(op2, getDRegI64(nreg), mkU64(imm)),
   5202                           binop(op2, getDRegI64(mreg), mkU64(imm))),
   5203                     mkU64(0),
   5204                     False, condT);
   5205 #endif
   5206          DIP("vqdmull.s%u q%u, d%u, d%u\n", 8 << size, dreg, nreg, mreg);
   5207          return True;
   5208       default:
   5209          return False;
   5210    }
   5211    return False;
   5212 }
   5213 
   5214 /* A7.4.3 Two registers and a scalar */
   5215 static
   5216 Bool dis_neon_data_2reg_and_scalar ( UInt theInstr, IRTemp condT )
   5217 {
   5218 #  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
   5219    UInt U = INSN(24,24);
   5220    UInt dreg = get_neon_d_regno(theInstr & ~(1 << 6));
   5221    UInt nreg = get_neon_n_regno(theInstr & ~(1 << 6));
   5222    UInt mreg = get_neon_m_regno(theInstr & ~(1 << 6));
   5223    UInt size = INSN(21,20);
   5224    UInt index;
   5225    UInt Q = INSN(24,24);
   5226 
   5227    if (INSN(27,25) != 1 || INSN(23,23) != 1
   5228        || INSN(6,6) != 1 || INSN(4,4) != 0)
   5229       return False;
   5230 
   5231    /* VMLA, VMLS (scalar)  */
   5232    if ((INSN(11,8) & BITS4(1,0,1,0)) == BITS4(0,0,0,0)) {
   5233       IRTemp res, arg_m, arg_n;
   5234       IROp dup, get, op, op2, add, sub;
   5235       if (Q) {
   5236          if ((dreg & 1) || (nreg & 1))
   5237             return False;
   5238          dreg >>= 1;
   5239          nreg >>= 1;
   5240          res = newTemp(Ity_V128);
   5241          arg_m = newTemp(Ity_V128);
   5242          arg_n = newTemp(Ity_V128);
   5243          assign(arg_n, getQReg(nreg));
   5244          switch(size) {
   5245             case 1:
   5246                dup = Iop_Dup16x8;
   5247                get = Iop_GetElem16x4;
   5248                index = mreg >> 3;
   5249                mreg &= 7;
   5250                break;
   5251             case 2:
   5252                dup = Iop_Dup32x4;
   5253                get = Iop_GetElem32x2;
   5254                index = mreg >> 4;
   5255                mreg &= 0xf;
   5256                break;
   5257             case 0:
   5258             case 3:
   5259                return False;
   5260             default:
   5261                vassert(0);
   5262          }
   5263          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5264       } else {
   5265          res = newTemp(Ity_I64);
   5266          arg_m = newTemp(Ity_I64);
   5267          arg_n = newTemp(Ity_I64);
   5268          assign(arg_n, getDRegI64(nreg));
   5269          switch(size) {
   5270             case 1:
   5271                dup = Iop_Dup16x4;
   5272                get = Iop_GetElem16x4;
   5273                index = mreg >> 3;
   5274                mreg &= 7;
   5275                break;
   5276             case 2:
   5277                dup = Iop_Dup32x2;
   5278                get = Iop_GetElem32x2;
   5279                index = mreg >> 4;
   5280                mreg &= 0xf;
   5281                break;
   5282             case 0:
   5283             case 3:
   5284                return False;
   5285             default:
   5286                vassert(0);
   5287          }
   5288          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5289       }
   5290       if (INSN(8,8)) {
   5291          switch (size) {
   5292             case 2:
   5293                op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2;
   5294                add = Q ? Iop_Add32Fx4 : Iop_Add32Fx2;
   5295                sub = Q ? Iop_Sub32Fx4 : Iop_Sub32Fx2;
   5296                break;
   5297             case 0:
   5298             case 1:
   5299             case 3:
   5300                return False;
   5301             default:
   5302                vassert(0);
   5303          }
   5304       } else {
   5305          switch (size) {
   5306             case 1:
   5307                op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   5308                add = Q ? Iop_Add16x8 : Iop_Add16x4;
   5309                sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   5310                break;
   5311             case 2:
   5312                op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   5313                add = Q ? Iop_Add32x4 : Iop_Add32x2;
   5314                sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   5315                break;
   5316             case 0:
   5317             case 3:
   5318                return False;
   5319             default:
   5320                vassert(0);
   5321          }
   5322       }
   5323       op2 = INSN(10,10) ? sub : add;
   5324       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5325       if (Q)
   5326          putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)),
   5327                condT);
   5328       else
   5329          putDRegI64(dreg, binop(op2, getDRegI64(dreg), mkexpr(res)),
   5330                     condT);
   5331       DIP("vml%c.%c%u %c%u, %c%u, d%u[%u]\n", INSN(10,10) ? 's' : 'a',
   5332             INSN(8,8) ? 'f' : 'i', 8 << size,
   5333             Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', nreg, mreg, index);
   5334       return True;
   5335    }
   5336 
   5337    /* VMLAL, VMLSL (scalar)   */
   5338    if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,0)) {
   5339       IRTemp res, arg_m, arg_n;
   5340       IROp dup, get, op, op2, add, sub;
   5341       if (dreg & 1)
   5342          return False;
   5343       dreg >>= 1;
   5344       res = newTemp(Ity_V128);
   5345       arg_m = newTemp(Ity_I64);
   5346       arg_n = newTemp(Ity_I64);
   5347       assign(arg_n, getDRegI64(nreg));
   5348       switch(size) {
   5349          case 1:
   5350             dup = Iop_Dup16x4;
   5351             get = Iop_GetElem16x4;
   5352             index = mreg >> 3;
   5353             mreg &= 7;
   5354             break;
   5355          case 2:
   5356             dup = Iop_Dup32x2;
   5357             get = Iop_GetElem32x2;
   5358             index = mreg >> 4;
   5359             mreg &= 0xf;
   5360             break;
   5361          case 0:
   5362          case 3:
   5363             return False;
   5364          default:
   5365             vassert(0);
   5366       }
   5367       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5368       switch (size) {
   5369          case 1:
   5370             op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4;
   5371             add = Iop_Add32x4;
   5372             sub = Iop_Sub32x4;
   5373             break;
   5374          case 2:
   5375             op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2;
   5376             add = Iop_Add64x2;
   5377             sub = Iop_Sub64x2;
   5378             break;
   5379          case 0:
   5380          case 3:
   5381             return False;
   5382          default:
   5383             vassert(0);
   5384       }
   5385       op2 = INSN(10,10) ? sub : add;
   5386       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5387       putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)), condT);
   5388       DIP("vml%cl.%c%u q%u, d%u, d%u[%u]\n",
   5389           INSN(10,10) ? 's' : 'a', U ? 'u' : 's',
   5390           8 << size, dreg, nreg, mreg, index);
   5391       return True;
   5392    }
   5393 
   5394    /* VQDMLAL, VQDMLSL (scalar)  */
   5395    if ((INSN(11,8) & BITS4(1,0,1,1)) == BITS4(0,0,1,1) && !U) {
   5396       IRTemp res, arg_m, arg_n, tmp;
   5397       IROp dup, get, op, op2, add, cmp;
   5398       UInt P = INSN(10,10);
   5399       ULong imm;
   5400       if (dreg & 1)
   5401          return False;
   5402       dreg >>= 1;
   5403       res = newTemp(Ity_V128);
   5404       arg_m = newTemp(Ity_I64);
   5405       arg_n = newTemp(Ity_I64);
   5406       assign(arg_n, getDRegI64(nreg));
   5407       switch(size) {
   5408          case 1:
   5409             dup = Iop_Dup16x4;
   5410             get = Iop_GetElem16x4;
   5411             index = mreg >> 3;
   5412             mreg &= 7;
   5413             break;
   5414          case 2:
   5415             dup = Iop_Dup32x2;
   5416             get = Iop_GetElem32x2;
   5417             index = mreg >> 4;
   5418             mreg &= 0xf;
   5419             break;
   5420          case 0:
   5421          case 3:
   5422             return False;
   5423          default:
   5424             vassert(0);
   5425       }
   5426       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5427       switch (size) {
   5428          case 0:
   5429          case 3:
   5430             return False;
   5431          case 1:
   5432             op = Iop_QDMulLong16Sx4;
   5433             cmp = Iop_CmpEQ16x4;
   5434             add = P ? Iop_QSub32Sx4 : Iop_QAdd32Sx4;
   5435             op2 = P ? Iop_Sub32x4 : Iop_Add32x4;
   5436             imm = 1LL << 15;
   5437             imm = (imm << 16) | imm;
   5438             imm = (imm << 32) | imm;
   5439             break;
   5440          case 2:
   5441             op = Iop_QDMulLong32Sx2;
   5442             cmp = Iop_CmpEQ32x2;
   5443             add = P ? Iop_QSub64Sx2 : Iop_QAdd64Sx2;
   5444             op2 = P ? Iop_Sub64x2 : Iop_Add64x2;
   5445             imm = 1LL << 31;
   5446             imm = (imm << 32) | imm;
   5447             break;
   5448          default:
   5449             vassert(0);
   5450       }
   5451       res = newTemp(Ity_V128);
   5452       tmp = newTemp(Ity_V128);
   5453       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5454 #ifndef DISABLE_QC_FLAG
   5455       assign(tmp, binop(op2, getQReg(dreg), mkexpr(res)));
   5456       setFlag_QC(binop(Iop_And64,
   5457                        binop(cmp, mkexpr(arg_n), mkU64(imm)),
   5458                        binop(cmp, mkexpr(arg_m), mkU64(imm))),
   5459                  mkU64(0),
   5460                  False, condT);
   5461       setFlag_QC(mkexpr(tmp), binop(add, getQReg(dreg), mkexpr(res)),
   5462                  True, condT);
   5463 #endif
   5464       putQReg(dreg, binop(add, getQReg(dreg), mkexpr(res)), condT);
   5465       DIP("vqdml%cl.s%u q%u, d%u, d%u[%u]\n", P ? 's' : 'a', 8 << size,
   5466           dreg, nreg, mreg, index);
   5467       return True;
   5468    }
   5469 
   5470    /* VMUL (by scalar)  */
   5471    if ((INSN(11,8) & BITS4(1,1,1,0)) == BITS4(1,0,0,0)) {
   5472       IRTemp res, arg_m, arg_n;
   5473       IROp dup, get, op;
   5474       if (Q) {
   5475          if ((dreg & 1) || (nreg & 1))
   5476             return False;
   5477          dreg >>= 1;
   5478          nreg >>= 1;
   5479          res = newTemp(Ity_V128);
   5480          arg_m = newTemp(Ity_V128);
   5481          arg_n = newTemp(Ity_V128);
   5482          assign(arg_n, getQReg(nreg));
   5483          switch(size) {
   5484             case 1:
   5485                dup = Iop_Dup16x8;
   5486                get = Iop_GetElem16x4;
   5487                index = mreg >> 3;
   5488                mreg &= 7;
   5489                break;
   5490             case 2:
   5491                dup = Iop_Dup32x4;
   5492                get = Iop_GetElem32x2;
   5493                index = mreg >> 4;
   5494                mreg &= 0xf;
   5495                break;
   5496             case 0:
   5497             case 3:
   5498                return False;
   5499             default:
   5500                vassert(0);
   5501          }
   5502          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5503       } else {
   5504          res = newTemp(Ity_I64);
   5505          arg_m = newTemp(Ity_I64);
   5506          arg_n = newTemp(Ity_I64);
   5507          assign(arg_n, getDRegI64(nreg));
   5508          switch(size) {
   5509             case 1:
   5510                dup = Iop_Dup16x4;
   5511                get = Iop_GetElem16x4;
   5512                index = mreg >> 3;
   5513                mreg &= 7;
   5514                break;
   5515             case 2:
   5516                dup = Iop_Dup32x2;
   5517                get = Iop_GetElem32x2;
   5518                index = mreg >> 4;
   5519                mreg &= 0xf;
   5520                break;
   5521             case 0:
   5522             case 3:
   5523                return False;
   5524             default:
   5525                vassert(0);
   5526          }
   5527          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5528       }
   5529       switch (size) {
   5530          case 1:
   5531             op = Q ? Iop_Mul16x8 : Iop_Mul16x4;
   5532             break;
   5533          case 2:
   5534             op = Q ? Iop_Mul32x4 : Iop_Mul32x2;
   5535             break;
   5536          case 0:
   5537          case 3:
   5538             return False;
   5539          default:
   5540             vassert(0);
   5541       }
   5542       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5543       if (Q)
   5544          putQReg(dreg, mkexpr(res), condT);
   5545       else
   5546          putDRegI64(dreg, mkexpr(res), condT);
   5547       DIP("vmul.i%u %c%u, %c%u, d%u[%u]\n", 8 << size, Q ? 'q' : 'd', dreg,
   5548           Q ? 'q' : 'd', nreg, mreg, index);
   5549       return True;
   5550    }
   5551 
   5552    /* VMULL (scalar) */
   5553    if (INSN(11,8) == BITS4(1,0,1,0)) {
   5554       IRTemp res, arg_m, arg_n;
   5555       IROp dup, get, op;
   5556       if (dreg & 1)
   5557          return False;
   5558       dreg >>= 1;
   5559       res = newTemp(Ity_V128);
   5560       arg_m = newTemp(Ity_I64);
   5561       arg_n = newTemp(Ity_I64);
   5562       assign(arg_n, getDRegI64(nreg));
   5563       switch(size) {
   5564          case 1:
   5565             dup = Iop_Dup16x4;
   5566             get = Iop_GetElem16x4;
   5567             index = mreg >> 3;
   5568             mreg &= 7;
   5569             break;
   5570          case 2:
   5571             dup = Iop_Dup32x2;
   5572             get = Iop_GetElem32x2;
   5573             index = mreg >> 4;
   5574             mreg &= 0xf;
   5575             break;
   5576          case 0:
   5577          case 3:
   5578             return False;
   5579          default:
   5580             vassert(0);
   5581       }
   5582       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5583       switch (size) {
   5584          case 1: op = U ? Iop_Mull16Ux4 : Iop_Mull16Sx4; break;
   5585          case 2: op = U ? Iop_Mull32Ux2 : Iop_Mull32Sx2; break;
   5586          case 0: case 3: return False;
   5587          default: vassert(0);
   5588       }
   5589       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5590       putQReg(dreg, mkexpr(res), condT);
   5591       DIP("vmull.%c%u q%u, d%u, d%u[%u]\n", U ? 'u' : 's', 8 << size, dreg,
   5592           nreg, mreg, index);
   5593       return True;
   5594    }
   5595 
   5596    /* VQDMULL */
   5597    if (INSN(11,8) == BITS4(1,0,1,1) && !U) {
   5598       IROp op ,op2, dup, get;
   5599       ULong imm;
   5600       IRTemp res, arg_m, arg_n;
   5601       if (dreg & 1)
   5602          return False;
   5603       dreg >>= 1;
   5604       res = newTemp(Ity_V128);
   5605       arg_m = newTemp(Ity_I64);
   5606       arg_n = newTemp(Ity_I64);
   5607       assign(arg_n, getDRegI64(nreg));
   5608       switch(size) {
   5609          case 1:
   5610             dup = Iop_Dup16x4;
   5611             get = Iop_GetElem16x4;
   5612             index = mreg >> 3;
   5613             mreg &= 7;
   5614             break;
   5615          case 2:
   5616             dup = Iop_Dup32x2;
   5617             get = Iop_GetElem32x2;
   5618             index = mreg >> 4;
   5619             mreg &= 0xf;
   5620             break;
   5621          case 0:
   5622          case 3:
   5623             return False;
   5624          default:
   5625             vassert(0);
   5626       }
   5627       assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5628       switch (size) {
   5629          case 0:
   5630          case 3:
   5631             return False;
   5632          case 1:
   5633             op = Iop_QDMulLong16Sx4;
   5634             op2 = Iop_CmpEQ16x4;
   5635             imm = 1LL << 15;
   5636             imm = (imm << 16) | imm;
   5637             imm = (imm << 32) | imm;
   5638             break;
   5639          case 2:
   5640             op = Iop_QDMulLong32Sx2;
   5641             op2 = Iop_CmpEQ32x2;
   5642             imm = 1LL << 31;
   5643             imm = (imm << 32) | imm;
   5644             break;
   5645          default:
   5646             vassert(0);
   5647       }
   5648       putQReg(dreg, binop(op, mkexpr(arg_n), mkexpr(arg_m)),
   5649             condT);
   5650 #ifndef DISABLE_QC_FLAG
   5651       setFlag_QC(binop(Iop_And64,
   5652                        binop(op2, mkexpr(arg_n), mkU64(imm)),
   5653                        binop(op2, mkexpr(arg_m), mkU64(imm))),
   5654                  mkU64(0),
   5655                  False, condT);
   5656 #endif
   5657       DIP("vqdmull.s%u q%u, d%u, d%u[%u]\n", 8 << size, dreg, nreg, mreg,
   5658           index);
   5659       return True;
   5660    }
   5661 
   5662    /* VQDMULH */
   5663    if (INSN(11,8) == BITS4(1,1,0,0)) {
   5664       IROp op ,op2, dup, get;
   5665       ULong imm;
   5666       IRTemp res, arg_m, arg_n;
   5667       if (Q) {
   5668          if ((dreg & 1) || (nreg & 1))
   5669             return False;
   5670          dreg >>= 1;
   5671          nreg >>= 1;
   5672          res = newTemp(Ity_V128);
   5673          arg_m = newTemp(Ity_V128);
   5674          arg_n = newTemp(Ity_V128);
   5675          assign(arg_n, getQReg(nreg));
   5676          switch(size) {
   5677             case 1:
   5678                dup = Iop_Dup16x8;
   5679                get = Iop_GetElem16x4;
   5680                index = mreg >> 3;
   5681                mreg &= 7;
   5682                break;
   5683             case 2:
   5684                dup = Iop_Dup32x4;
   5685                get = Iop_GetElem32x2;
   5686                index = mreg >> 4;
   5687                mreg &= 0xf;
   5688                break;
   5689             case 0:
   5690             case 3:
   5691                return False;
   5692             default:
   5693                vassert(0);
   5694          }
   5695          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5696       } else {
   5697          res = newTemp(Ity_I64);
   5698          arg_m = newTemp(Ity_I64);
   5699          arg_n = newTemp(Ity_I64);
   5700          assign(arg_n, getDRegI64(nreg));
   5701          switch(size) {
   5702             case 1:
   5703                dup = Iop_Dup16x4;
   5704                get = Iop_GetElem16x4;
   5705                index = mreg >> 3;
   5706                mreg &= 7;
   5707                break;
   5708             case 2:
   5709                dup = Iop_Dup32x2;
   5710                get = Iop_GetElem32x2;
   5711                index = mreg >> 4;
   5712                mreg &= 0xf;
   5713                break;
   5714             case 0:
   5715             case 3:
   5716                return False;
   5717             default:
   5718                vassert(0);
   5719          }
   5720          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5721       }
   5722       switch (size) {
   5723          case 0:
   5724          case 3:
   5725             return False;
   5726          case 1:
   5727             op = Q ? Iop_QDMulHi16Sx8 : Iop_QDMulHi16Sx4;
   5728             op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   5729             imm = 1LL << 15;
   5730             imm = (imm << 16) | imm;
   5731             imm = (imm << 32) | imm;
   5732             break;
   5733          case 2:
   5734             op = Q ? Iop_QDMulHi32Sx4 : Iop_QDMulHi32Sx2;
   5735             op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   5736             imm = 1LL << 31;
   5737             imm = (imm << 32) | imm;
   5738             break;
   5739          default:
   5740             vassert(0);
   5741       }
   5742       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5743 #ifndef DISABLE_QC_FLAG
   5744       setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   5745                        binop(op2, mkexpr(arg_n),
   5746                                   Q ? mkU128(imm) : mkU64(imm)),
   5747                        binop(op2, mkexpr(arg_m),
   5748                              Q ? mkU128(imm) : mkU64(imm))),
   5749                  Q ? mkU128(0) : mkU64(0),
   5750                  Q, condT);
   5751 #endif
   5752       if (Q)
   5753          putQReg(dreg, mkexpr(res), condT);
   5754       else
   5755          putDRegI64(dreg, mkexpr(res), condT);
   5756       DIP("vqdmulh.s%u %c%u, %c%u, d%u[%u]\n",
   5757           8 << size, Q ? 'q' : 'd', dreg,
   5758           Q ? 'q' : 'd', nreg, mreg, index);
   5759       return True;
   5760    }
   5761 
   5762    /* VQRDMULH (scalar) */
   5763    if (INSN(11,8) == BITS4(1,1,0,1)) {
   5764       IROp op ,op2, dup, get;
   5765       ULong imm;
   5766       IRTemp res, arg_m, arg_n;
   5767       if (Q) {
   5768          if ((dreg & 1) || (nreg & 1))
   5769             return False;
   5770          dreg >>= 1;
   5771          nreg >>= 1;
   5772          res = newTemp(Ity_V128);
   5773          arg_m = newTemp(Ity_V128);
   5774          arg_n = newTemp(Ity_V128);
   5775          assign(arg_n, getQReg(nreg));
   5776          switch(size) {
   5777             case 1:
   5778                dup = Iop_Dup16x8;
   5779                get = Iop_GetElem16x4;
   5780                index = mreg >> 3;
   5781                mreg &= 7;
   5782                break;
   5783             case 2:
   5784                dup = Iop_Dup32x4;
   5785                get = Iop_GetElem32x2;
   5786                index = mreg >> 4;
   5787                mreg &= 0xf;
   5788                break;
   5789             case 0:
   5790             case 3:
   5791                return False;
   5792             default:
   5793                vassert(0);
   5794          }
   5795          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5796       } else {
   5797          res = newTemp(Ity_I64);
   5798          arg_m = newTemp(Ity_I64);
   5799          arg_n = newTemp(Ity_I64);
   5800          assign(arg_n, getDRegI64(nreg));
   5801          switch(size) {
   5802             case 1:
   5803                dup = Iop_Dup16x4;
   5804                get = Iop_GetElem16x4;
   5805                index = mreg >> 3;
   5806                mreg &= 7;
   5807                break;
   5808             case 2:
   5809                dup = Iop_Dup32x2;
   5810                get = Iop_GetElem32x2;
   5811                index = mreg >> 4;
   5812                mreg &= 0xf;
   5813                break;
   5814             case 0:
   5815             case 3:
   5816                return False;
   5817             default:
   5818                vassert(0);
   5819          }
   5820          assign(arg_m, unop(dup, binop(get, getDRegI64(mreg), mkU8(index))));
   5821       }
   5822       switch (size) {
   5823          case 0:
   5824          case 3:
   5825             return False;
   5826          case 1:
   5827             op = Q ? Iop_QRDMulHi16Sx8 : Iop_QRDMulHi16Sx4;
   5828             op2 = Q ? Iop_CmpEQ16x8 : Iop_CmpEQ16x4;
   5829             imm = 1LL << 15;
   5830             imm = (imm << 16) | imm;
   5831             imm = (imm << 32) | imm;
   5832             break;
   5833          case 2:
   5834             op = Q ? Iop_QRDMulHi32Sx4 : Iop_QRDMulHi32Sx2;
   5835             op2 = Q ? Iop_CmpEQ32x4 : Iop_CmpEQ32x2;
   5836             imm = 1LL << 31;
   5837             imm = (imm << 32) | imm;
   5838             break;
   5839          default:
   5840             vassert(0);
   5841       }
   5842       assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
   5843 #ifndef DISABLE_QC_FLAG
   5844       setFlag_QC(binop(Q ? Iop_AndV128 : Iop_And64,
   5845                        binop(op2, mkexpr(arg_n),
   5846                                   Q ? mkU128(imm) : mkU64(imm)),
   5847                        binop(op2, mkexpr(arg_m),
   5848                                   Q ? mkU128(imm) : mkU64(imm))),
   5849                  Q ? mkU128(0) : mkU64(0),
   5850                  Q, condT);
   5851 #endif
   5852       if (Q)
   5853          putQReg(dreg, mkexpr(res), condT);
   5854       else
   5855          putDRegI64(dreg, mkexpr(res), condT);
   5856       DIP("vqrdmulh.s%u %c%u, %c%u, d%u[%u]\n",
   5857           8 << size, Q ? 'q' : 'd', dreg,
   5858           Q ? 'q' : 'd', nreg, mreg, index);
   5859       return True;
   5860    }
   5861 
   5862    return False;
   5863 #  undef INSN
   5864 }
   5865 
   5866 /* A7.4.4 Two registers and a shift amount */
   5867 static
   5868 Bool dis_neon_data_2reg_and_shift ( UInt theInstr, IRTemp condT )
   5869 {
   5870    UInt A = (theInstr >> 8) & 0xf;
   5871    UInt B = (theInstr >> 6) & 1;
   5872    UInt L = (theInstr >> 7) & 1;
   5873    UInt U = (theInstr >> 24) & 1;
   5874    UInt Q = B;
   5875    UInt imm6 = (theInstr >> 16) & 0x3f;
   5876    UInt shift_imm;
   5877    UInt size = 4;
   5878    UInt tmp;
   5879    UInt mreg = get_neon_m_regno(theInstr);
   5880    UInt dreg = get_neon_d_regno(theInstr);
   5881    ULong imm = 0;
   5882    IROp op, cvt, add = Iop_INVALID, cvt2, op_rev;
   5883    IRTemp reg_m, res, mask;
   5884 
   5885    if (L == 0 && ((theInstr >> 19) & 7) == 0)
   5886       /* It is one reg and immediate */
   5887       return False;
   5888 
   5889    tmp = (L << 6) | imm6;
   5890    if (tmp & 0x40) {
   5891       size = 3;
   5892       shift_imm = 64 - imm6;
   5893    } else if (tmp & 0x20) {
   5894       size = 2;
   5895       shift_imm = 64 - imm6;
   5896    } else if (tmp & 0x10) {
   5897       size = 1;
   5898       shift_imm = 32 - imm6;
   5899    } else if (tmp & 0x8) {
   5900       size = 0;
   5901       shift_imm = 16 - imm6;
   5902    } else {
   5903       return False;
   5904    }
   5905 
   5906    switch (A) {
   5907       case 3:
   5908       case 2:
   5909          /* VRSHR, VRSRA */
   5910          if (shift_imm > 0) {
   5911             IRExpr *imm_val;
   5912             imm = 1L;
   5913             switch (size) {
   5914                case 0:
   5915                   imm = (imm << 8) | imm;
   5916                   /* fall through */
   5917                case 1:
   5918                   imm = (imm << 16) | imm;
   5919                   /* fall through */
   5920                case 2:
   5921                   imm = (imm << 32) | imm;
   5922                   /* fall through */
   5923                case 3:
   5924                   break;
   5925                default:
   5926                   vassert(0);
   5927             }
   5928             if (Q) {
   5929                reg_m = newTemp(Ity_V128);
   5930                res = newTemp(Ity_V128);
   5931                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   5932                assign(reg_m, getQReg(mreg));
   5933                switch (size) {
   5934                   case 0:
   5935                      add = Iop_Add8x16;
   5936                      op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
   5937                      break;
   5938                   case 1:
   5939                      add = Iop_Add16x8;
   5940                      op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   5941                      break;
   5942                   case 2:
   5943                      add = Iop_Add32x4;
   5944                      op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   5945                      break;
   5946                   case 3:
   5947                      add = Iop_Add64x2;
   5948                      op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
   5949                      break;
   5950                   default:
   5951                      vassert(0);
   5952                }
   5953             } else {
   5954                reg_m = newTemp(Ity_I64);
   5955                res = newTemp(Ity_I64);
   5956                imm_val = mkU64(imm);
   5957                assign(reg_m, getDRegI64(mreg));
   5958                switch (size) {
   5959                   case 0:
   5960                      add = Iop_Add8x8;
   5961                      op = U ? Iop_ShrN8x8 : Iop_SarN8x8;
   5962                      break;
   5963                   case 1:
   5964                      add = Iop_Add16x4;
   5965                      op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
   5966                      break;
   5967                   case 2:
   5968                      add = Iop_Add32x2;
   5969                      op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
   5970                      break;
   5971                   case 3:
   5972                      add = Iop_Add64;
   5973                      op = U ? Iop_Shr64 : Iop_Sar64;
   5974                      break;
   5975                   default:
   5976                      vassert(0);
   5977                }
   5978             }
   5979             assign(res,
   5980                    binop(add,
   5981                          binop(op,
   5982                                mkexpr(reg_m),
   5983                                mkU8(shift_imm)),
   5984                          binop(Q ? Iop_AndV128 : Iop_And64,
   5985                                binop(op,
   5986                                      mkexpr(reg_m),
   5987                                      mkU8(shift_imm - 1)),
   5988                                imm_val)));
   5989          } else {
   5990             if (Q) {
   5991                res = newTemp(Ity_V128);
   5992                assign(res, getQReg(mreg));
   5993             } else {
   5994                res = newTemp(Ity_I64);
   5995                assign(res, getDRegI64(mreg));
   5996             }
   5997          }
   5998          if (A == 3) {
   5999             if (Q) {
   6000                putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
   6001                              condT);
   6002             } else {
   6003                putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
   6004                                 condT);
   6005             }
   6006             DIP("vrsra.%c%u %c%u, %c%u, #%u\n",
   6007                 U ? 'u' : 's', 8 << size,
   6008                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6009          } else {
   6010             if (Q) {
   6011                putQReg(dreg, mkexpr(res), condT);
   6012             } else {
   6013                putDRegI64(dreg, mkexpr(res), condT);
   6014             }
   6015             DIP("vrshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
   6016                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6017          }
   6018          return True;
   6019       case 1:
   6020       case 0:
   6021          /* VSHR, VSRA */
   6022          if (Q) {
   6023             reg_m = newTemp(Ity_V128);
   6024             assign(reg_m, getQReg(mreg));
   6025             res = newTemp(Ity_V128);
   6026          } else {
   6027             reg_m = newTemp(Ity_I64);
   6028             assign(reg_m, getDRegI64(mreg));
   6029             res = newTemp(Ity_I64);
   6030          }
   6031          if (Q) {
   6032             switch (size) {
   6033                case 0:
   6034                   op = U ? Iop_ShrN8x16 : Iop_SarN8x16;
   6035                   add = Iop_Add8x16;
   6036                   break;
   6037                case 1:
   6038                   op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   6039                   add = Iop_Add16x8;
   6040                   break;
   6041                case 2:
   6042                   op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   6043                   add = Iop_Add32x4;
   6044                   break;
   6045                case 3:
   6046                   op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
   6047                   add = Iop_Add64x2;
   6048                   break;
   6049                default:
   6050                   vassert(0);
   6051             }
   6052          } else {
   6053             switch (size) {
   6054                case 0:
   6055                   op =  U ? Iop_ShrN8x8 : Iop_SarN8x8;
   6056                   add = Iop_Add8x8;
   6057                   break;
   6058                case 1:
   6059                   op = U ? Iop_ShrN16x4 : Iop_SarN16x4;
   6060                   add = Iop_Add16x4;
   6061                   break;
   6062                case 2:
   6063                   op = U ? Iop_ShrN32x2 : Iop_SarN32x2;
   6064                   add = Iop_Add32x2;
   6065                   break;
   6066                case 3:
   6067                   op = U ? Iop_Shr64 : Iop_Sar64;
   6068                   add = Iop_Add64;
   6069                   break;
   6070                default:
   6071                   vassert(0);
   6072             }
   6073          }
   6074          assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
   6075          if (A == 1) {
   6076             if (Q) {
   6077                putQReg(dreg, binop(add, mkexpr(res), getQReg(dreg)),
   6078                              condT);
   6079             } else {
   6080                putDRegI64(dreg, binop(add, mkexpr(res), getDRegI64(dreg)),
   6081                                 condT);
   6082             }
   6083             DIP("vsra.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
   6084                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6085          } else {
   6086             if (Q) {
   6087                putQReg(dreg, mkexpr(res), condT);
   6088             } else {
   6089                putDRegI64(dreg, mkexpr(res), condT);
   6090             }
   6091             DIP("vshr.%c%u %c%u, %c%u, #%u\n", U ? 'u' : 's', 8 << size,
   6092                   Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6093          }
   6094          return True;
   6095       case 4:
   6096          /* VSRI */
   6097          if (!U)
   6098             return False;
   6099          if (Q) {
   6100             res = newTemp(Ity_V128);
   6101             mask = newTemp(Ity_V128);
   6102          } else {
   6103             res = newTemp(Ity_I64);
   6104             mask = newTemp(Ity_I64);
   6105          }
   6106          switch (size) {
   6107             case 0: op = Q ? Iop_ShrN8x16 : Iop_ShrN8x8; break;
   6108             case 1: op = Q ? Iop_ShrN16x8 : Iop_ShrN16x4; break;
   6109             case 2: op = Q ? Iop_ShrN32x4 : Iop_ShrN32x2; break;
   6110             case 3: op = Q ? Iop_ShrN64x2 : Iop_Shr64; break;
   6111             default: vassert(0);
   6112          }
   6113          if (Q) {
   6114             assign(mask, binop(op, binop(Iop_64HLtoV128,
   6115                                          mkU64(0xFFFFFFFFFFFFFFFFLL),
   6116                                          mkU64(0xFFFFFFFFFFFFFFFFLL)),
   6117                                mkU8(shift_imm)));
   6118             assign(res, binop(Iop_OrV128,
   6119                               binop(Iop_AndV128,
   6120                                     getQReg(dreg),
   6121                                     unop(Iop_NotV128,
   6122                                          mkexpr(mask))),
   6123                               binop(op,
   6124                                     getQReg(mreg),
   6125                                     mkU8(shift_imm))));
   6126             putQReg(dreg, mkexpr(res), condT);
   6127          } else {
   6128             assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
   6129                                mkU8(shift_imm)));
   6130             assign(res, binop(Iop_Or64,
   6131                               binop(Iop_And64,
   6132                                     getDRegI64(dreg),
   6133                                     unop(Iop_Not64,
   6134                                          mkexpr(mask))),
   6135                               binop(op,
   6136                                     getDRegI64(mreg),
   6137                                     mkU8(shift_imm))));
   6138             putDRegI64(dreg, mkexpr(res), condT);
   6139          }
   6140          DIP("vsri.%u %c%u, %c%u, #%u\n",
   6141              8 << size, Q ? 'q' : 'd', dreg,
   6142              Q ? 'q' : 'd', mreg, shift_imm);
   6143          return True;
   6144       case 5:
   6145          if (U) {
   6146             /* VSLI */
   6147             shift_imm = 8 * (1 << size) - shift_imm;
   6148             if (Q) {
   6149                res = newTemp(Ity_V128);
   6150                mask = newTemp(Ity_V128);
   6151             } else {
   6152                res = newTemp(Ity_I64);
   6153                mask = newTemp(Ity_I64);
   6154             }
   6155             switch (size) {
   6156                case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
   6157                case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
   6158                case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
   6159                case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
   6160                default: vassert(0);
   6161             }
   6162             if (Q) {
   6163                assign(mask, binop(op, binop(Iop_64HLtoV128,
   6164                                             mkU64(0xFFFFFFFFFFFFFFFFLL),
   6165                                             mkU64(0xFFFFFFFFFFFFFFFFLL)),
   6166                                   mkU8(shift_imm)));
   6167                assign(res, binop(Iop_OrV128,
   6168                                  binop(Iop_AndV128,
   6169                                        getQReg(dreg),
   6170                                        unop(Iop_NotV128,
   6171                                             mkexpr(mask))),
   6172                                  binop(op,
   6173                                        getQReg(mreg),
   6174                                        mkU8(shift_imm))));
   6175                putQReg(dreg, mkexpr(res), condT);
   6176             } else {
   6177                assign(mask, binop(op, mkU64(0xFFFFFFFFFFFFFFFFLL),
   6178                                   mkU8(shift_imm)));
   6179                assign(res, binop(Iop_Or64,
   6180                                  binop(Iop_And64,
   6181                                        getDRegI64(dreg),
   6182                                        unop(Iop_Not64,
   6183                                             mkexpr(mask))),
   6184                                  binop(op,
   6185                                        getDRegI64(mreg),
   6186                                        mkU8(shift_imm))));
   6187                putDRegI64(dreg, mkexpr(res), condT);
   6188             }
   6189             DIP("vsli.%u %c%u, %c%u, #%u\n",
   6190                 8 << size, Q ? 'q' : 'd', dreg,
   6191                 Q ? 'q' : 'd', mreg, shift_imm);
   6192             return True;
   6193          } else {
   6194             /* VSHL #imm */
   6195             shift_imm = 8 * (1 << size) - shift_imm;
   6196             if (Q) {
   6197                res = newTemp(Ity_V128);
   6198             } else {
   6199                res = newTemp(Ity_I64);
   6200             }
   6201             switch (size) {
   6202                case 0: op = Q ? Iop_ShlN8x16 : Iop_ShlN8x8; break;
   6203                case 1: op = Q ? Iop_ShlN16x8 : Iop_ShlN16x4; break;
   6204                case 2: op = Q ? Iop_ShlN32x4 : Iop_ShlN32x2; break;
   6205                case 3: op = Q ? Iop_ShlN64x2 : Iop_Shl64; break;
   6206                default: vassert(0);
   6207             }
   6208             assign(res, binop(op, Q ? getQReg(mreg) : getDRegI64(mreg),
   6209                      mkU8(shift_imm)));
   6210             if (Q) {
   6211                putQReg(dreg, mkexpr(res), condT);
   6212             } else {
   6213                putDRegI64(dreg, mkexpr(res), condT);
   6214             }
   6215             DIP("vshl.i%u %c%u, %c%u, #%u\n",
   6216                 8 << size, Q ? 'q' : 'd', dreg,
   6217                 Q ? 'q' : 'd', mreg, shift_imm);
   6218             return True;
   6219          }
   6220          break;
   6221       case 6:
   6222       case 7:
   6223          /* VQSHL, VQSHLU */
   6224          shift_imm = 8 * (1 << size) - shift_imm;
   6225          if (U) {
   6226             if (A & 1) {
   6227                switch (size) {
   6228                   case 0:
   6229                      op = Q ? Iop_QShlN8x16 : Iop_QShlN8x8;
   6230                      op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   6231                      break;
   6232                   case 1:
   6233                      op = Q ? Iop_QShlN16x8 : Iop_QShlN16x4;
   6234                      op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   6235                      break;
   6236                   case 2:
   6237                      op = Q ? Iop_QShlN32x4 : Iop_QShlN32x2;
   6238                      op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   6239                      break;
   6240                   case 3:
   6241                      op = Q ? Iop_QShlN64x2 : Iop_QShlN64x1;
   6242                      op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
   6243                      break;
   6244                   default:
   6245                      vassert(0);
   6246                }
   6247                DIP("vqshl.u%u %c%u, %c%u, #%u\n",
   6248                    8 << size,
   6249                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6250             } else {
   6251                switch (size) {
   6252                   case 0:
   6253                      op = Q ? Iop_QShlN8Sx16 : Iop_QShlN8Sx8;
   6254                      op_rev = Q ? Iop_ShrN8x16 : Iop_ShrN8x8;
   6255                      break;
   6256                   case 1:
   6257                      op = Q ? Iop_QShlN16Sx8 : Iop_QShlN16Sx4;
   6258                      op_rev = Q ? Iop_ShrN16x8 : Iop_ShrN16x4;
   6259                      break;
   6260                   case 2:
   6261                      op = Q ? Iop_QShlN32Sx4 : Iop_QShlN32Sx2;
   6262                      op_rev = Q ? Iop_ShrN32x4 : Iop_ShrN32x2;
   6263                      break;
   6264                   case 3:
   6265                      op = Q ? Iop_QShlN64Sx2 : Iop_QShlN64Sx1;
   6266                      op_rev = Q ? Iop_ShrN64x2 : Iop_Shr64;
   6267                      break;
   6268                   default:
   6269                      vassert(0);
   6270                }
   6271                DIP("vqshlu.s%u %c%u, %c%u, #%u\n",
   6272                    8 << size,
   6273                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6274             }
   6275          } else {
   6276             if (!(A & 1))
   6277                return False;
   6278             switch (size) {
   6279                case 0:
   6280                   op = Q ? Iop_QSalN8x16 : Iop_QSalN8x8;
   6281                   op_rev = Q ? Iop_SarN8x16 : Iop_SarN8x8;
   6282                   break;
   6283                case 1:
   6284                   op = Q ? Iop_QSalN16x8 : Iop_QSalN16x4;
   6285                   op_rev = Q ? Iop_SarN16x8 : Iop_SarN16x4;
   6286                   break;
   6287                case 2:
   6288                   op = Q ? Iop_QSalN32x4 : Iop_QSalN32x2;
   6289                   op_rev = Q ? Iop_SarN32x4 : Iop_SarN32x2;
   6290                   break;
   6291                case 3:
   6292                   op = Q ? Iop_QSalN64x2 : Iop_QSalN64x1;
   6293                   op_rev = Q ? Iop_SarN64x2 : Iop_Sar64;
   6294                   break;
   6295                default:
   6296                   vassert(0);
   6297             }
   6298             DIP("vqshl.s%u %c%u, %c%u, #%u\n",
   6299                 8 << size,
   6300                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg, shift_imm);
   6301          }
   6302          if (Q) {
   6303             tmp = newTemp(Ity_V128);
   6304             res = newTemp(Ity_V128);
   6305             reg_m = newTemp(Ity_V128);
   6306             assign(reg_m, getQReg(mreg));
   6307          } else {
   6308             tmp = newTemp(Ity_I64);
   6309             res = newTemp(Ity_I64);
   6310             reg_m = newTemp(Ity_I64);
   6311             assign(reg_m, getDRegI64(mreg));
   6312          }
   6313          assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
   6314 #ifndef DISABLE_QC_FLAG
   6315          assign(tmp, binop(op_rev, mkexpr(res), mkU8(shift_imm)));
   6316          setFlag_QC(mkexpr(tmp), mkexpr(reg_m), Q, condT);
   6317 #endif
   6318          if (Q)
   6319             putQReg(dreg, mkexpr(res), condT);
   6320          else
   6321             putDRegI64(dreg, mkexpr(res), condT);
   6322          return True;
   6323       case 8:
   6324          if (!U) {
   6325             if (L == 1)
   6326                return False;
   6327             size++;
   6328             dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   6329             mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   6330             if (mreg & 1)
   6331                return False;
   6332             mreg >>= 1;
   6333             if (!B) {
   6334                /* VSHRN*/
   6335                IROp narOp;
   6336                reg_m = newTemp(Ity_V128);
   6337                assign(reg_m, getQReg(mreg));
   6338                res = newTemp(Ity_I64);
   6339                switch (size) {
   6340                   case 1:
   6341                      op = Iop_ShrN16x8;
   6342                      narOp = Iop_Shorten16x8;
   6343                      break;
   6344                   case 2:
   6345                      op = Iop_ShrN32x4;
   6346                      narOp = Iop_Shorten32x4;
   6347                      break;
   6348                   case 3:
   6349                      op = Iop_ShrN64x2;
   6350                      narOp = Iop_Shorten64x2;
   6351                      break;
   6352                   default:
   6353                      vassert(0);
   6354                }
   6355                assign(res, unop(narOp,
   6356                                 binop(op,
   6357                                       mkexpr(reg_m),
   6358                                       mkU8(shift_imm))));
   6359                putDRegI64(dreg, mkexpr(res), condT);
   6360                DIP("vshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
   6361                    shift_imm);
   6362                return True;
   6363             } else {
   6364                /* VRSHRN   */
   6365                IROp addOp, shOp, narOp;
   6366                IRExpr *imm_val;
   6367                reg_m = newTemp(Ity_V128);
   6368                assign(reg_m, getQReg(mreg));
   6369                res = newTemp(Ity_I64);
   6370                imm = 1L;
   6371                switch (size) {
   6372                   case 0: imm = (imm <<  8) | imm; /* fall through */
   6373                   case 1: imm = (imm << 16) | imm; /* fall through */
   6374                   case 2: imm = (imm << 32) | imm; /* fall through */
   6375                   case 3: break;
   6376                   default: vassert(0);
   6377                }
   6378                imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   6379                switch (size) {
   6380                   case 1:
   6381                      addOp = Iop_Add16x8;
   6382                      shOp = Iop_ShrN16x8;
   6383                      narOp = Iop_Shorten16x8;
   6384                      break;
   6385                   case 2:
   6386                      addOp = Iop_Add32x4;
   6387                      shOp = Iop_ShrN32x4;
   6388                      narOp = Iop_Shorten32x4;
   6389                      break;
   6390                   case 3:
   6391                      addOp = Iop_Add64x2;
   6392                      shOp = Iop_ShrN64x2;
   6393                      narOp = Iop_Shorten64x2;
   6394                      break;
   6395                   default:
   6396                      vassert(0);
   6397                }
   6398                assign(res, unop(narOp,
   6399                                 binop(addOp,
   6400                                       binop(shOp,
   6401                                             mkexpr(reg_m),
   6402                                             mkU8(shift_imm)),
   6403                                       binop(Iop_AndV128,
   6404                                             binop(shOp,
   6405                                                   mkexpr(reg_m),
   6406                                                   mkU8(shift_imm - 1)),
   6407                                             imm_val))));
   6408                putDRegI64(dreg, mkexpr(res), condT);
   6409                if (shift_imm == 0) {
   6410                   DIP("vmov%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
   6411                       shift_imm);
   6412                } else {
   6413                   DIP("vrshrn.i%u d%u, q%u, #%u\n", 8 << size, dreg, mreg,
   6414                       shift_imm);
   6415                }
   6416                return True;
   6417             }
   6418          } else {
   6419             /* fall through */
   6420          }
   6421       case 9:
   6422          dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   6423          mreg = ((theInstr >>  1) & 0x10) | (theInstr & 0xF);
   6424          if (mreg & 1)
   6425             return False;
   6426          mreg >>= 1;
   6427          size++;
   6428          if ((theInstr >> 8) & 1) {
   6429             switch (size) {
   6430                case 1:
   6431                   op = U ? Iop_ShrN16x8 : Iop_SarN16x8;
   6432                   cvt = U ? Iop_QShortenU16Ux8 : Iop_QShortenS16Sx8;
   6433                   cvt2 = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
   6434                   break;
   6435                case 2:
   6436                   op = U ? Iop_ShrN32x4 : Iop_SarN32x4;
   6437                   cvt = U ? Iop_QShortenU32Ux4 : Iop_QShortenS32Sx4;
   6438                   cvt2 = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
   6439                   break;
   6440                case 3:
   6441                   op = U ? Iop_ShrN64x2 : Iop_SarN64x2;
   6442                   cvt = U ? Iop_QShortenU64Ux2 : Iop_QShortenS64Sx2;
   6443                   cvt2 = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
   6444                   break;
   6445                default:
   6446                   vassert(0);
   6447             }
   6448             DIP("vq%sshrn.%c%u d%u, q%u, #%u\n", B ? "r" : "",
   6449                 U ? 'u' : 's', 8 << size, dreg, mreg, shift_imm);
   6450          } else {
   6451             vassert(U);
   6452             switch (size) {
   6453                case 1:
   6454                   op = Iop_SarN16x8;
   6455                   cvt = Iop_QShortenU16Sx8;
   6456                   cvt2 = Iop_Longen8Ux8;
   6457                   break;
   6458                case 2:
   6459                   op = Iop_SarN32x4;
   6460                   cvt = Iop_QShortenU32Sx4;
   6461                   cvt2 = Iop_Longen16Ux4;
   6462                   break;
   6463                case 3:
   6464                   op = Iop_SarN64x2;
   6465                   cvt = Iop_QShortenU64Sx2;
   6466                   cvt2 = Iop_Longen32Ux2;
   6467                   break;
   6468                default:
   6469                   vassert(0);
   6470             }
   6471             DIP("vq%sshrun.s%u d%u, q%u, #%u\n", B ? "r" : "",
   6472                 8 << size, dreg, mreg, shift_imm);
   6473          }
   6474          if (B) {
   6475             if (shift_imm > 0) {
   6476                imm = 1;
   6477                switch (size) {
   6478                   case 1: imm = (imm << 16) | imm; /* fall through */
   6479                   case 2: imm = (imm << 32) | imm; /* fall through */
   6480                   case 3: break;
   6481                   case 0: default: vassert(0);
   6482                }
   6483                switch (size) {
   6484                   case 1: add = Iop_Add16x8; break;
   6485                   case 2: add = Iop_Add32x4; break;
   6486                   case 3: add = Iop_Add64x2; break;
   6487                   case 0: default: vassert(0);
   6488                }
   6489             }
   6490          }
   6491          reg_m = newTemp(Ity_V128);
   6492          res = newTemp(Ity_V128);
   6493          assign(reg_m, getQReg(mreg));
   6494          if (B) {
   6495             /* VQRSHRN, VQRSHRUN */
   6496             assign(res, binop(add,
   6497                               binop(op, mkexpr(reg_m), mkU8(shift_imm)),
   6498                               binop(Iop_AndV128,
   6499                                     binop(op,
   6500                                           mkexpr(reg_m),
   6501                                           mkU8(shift_imm - 1)),
   6502                                     mkU128(imm))));
   6503          } else {
   6504             /* VQSHRN, VQSHRUN */
   6505             assign(res, binop(op, mkexpr(reg_m), mkU8(shift_imm)));
   6506          }
   6507 #ifndef DISABLE_QC_FLAG
   6508          setFlag_QC(unop(cvt2, unop(cvt, mkexpr(res))), mkexpr(res),
   6509                     True, condT);
   6510 #endif
   6511          putDRegI64(dreg, unop(cvt, mkexpr(res)), condT);
   6512          return True;
   6513       case 10:
   6514          /* VSHLL
   6515             VMOVL ::= VSHLL #0 */
   6516          if (B)
   6517             return False;
   6518          if (dreg & 1)
   6519             return False;
   6520          dreg >>= 1;
   6521          shift_imm = (8 << size) - shift_imm;
   6522          res = newTemp(Ity_V128);
   6523          switch (size) {
   6524             case 0:
   6525                op = Iop_ShlN16x8;
   6526                cvt = U ? Iop_Longen8Ux8 : Iop_Longen8Sx8;
   6527                break;
   6528             case 1:
   6529                op = Iop_ShlN32x4;
   6530                cvt = U ? Iop_Longen16Ux4 : Iop_Longen16Sx4;
   6531                break;
   6532             case 2:
   6533                op = Iop_ShlN64x2;
   6534                cvt = U ? Iop_Longen32Ux2 : Iop_Longen32Sx2;
   6535                break;
   6536             case 3:
   6537                return False;
   6538             default:
   6539                vassert(0);
   6540          }
   6541          assign(res, binop(op, unop(cvt, getDRegI64(mreg)), mkU8(shift_imm)));
   6542          putQReg(dreg, mkexpr(res), condT);
   6543          if (shift_imm == 0) {
   6544             DIP("vmovl.%c%u q%u, d%u\n", U ? 'u' : 's', 8 << size,
   6545                 dreg, mreg);
   6546          } else {
   6547             DIP("vshll.%c%u q%u, d%u, #%u\n", U ? 'u' : 's', 8 << size,
   6548                 dreg, mreg, shift_imm);
   6549          }
   6550          return True;
   6551       case 14:
   6552       case 15:
   6553          /* VCVT floating-point <-> fixed-point */
   6554          if ((theInstr >> 8) & 1) {
   6555             if (U) {
   6556                op = Q ? Iop_F32ToFixed32Ux4_RZ : Iop_F32ToFixed32Ux2_RZ;
   6557             } else {
   6558                op = Q ? Iop_F32ToFixed32Sx4_RZ : Iop_F32ToFixed32Sx2_RZ;
   6559             }
   6560             DIP("vcvt.%c32.f32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
   6561                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
   6562                 64 - ((theInstr >> 16) & 0x3f));
   6563          } else {
   6564             if (U) {
   6565                op = Q ? Iop_Fixed32UToF32x4_RN : Iop_Fixed32UToF32x2_RN;
   6566             } else {
   6567                op = Q ? Iop_Fixed32SToF32x4_RN : Iop_Fixed32SToF32x2_RN;
   6568             }
   6569             DIP("vcvt.f32.%c32 %c%u, %c%u, #%u\n", U ? 'u' : 's',
   6570                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg,
   6571                 64 - ((theInstr >> 16) & 0x3f));
   6572          }
   6573          if (((theInstr >> 21) & 1) == 0)
   6574             return False;
   6575          if (Q) {
   6576             putQReg(dreg, binop(op, getQReg(mreg),
   6577                      mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
   6578          } else {
   6579             putDRegI64(dreg, binop(op, getDRegI64(mreg),
   6580                        mkU8(64 - ((theInstr >> 16) & 0x3f))), condT);
   6581          }
   6582          return True;
   6583       default:
   6584          return False;
   6585 
   6586    }
   6587    return False;
   6588 }
   6589 
   6590 /* A7.4.5 Two registers, miscellaneous */
   6591 static
   6592 Bool dis_neon_data_2reg_misc ( UInt theInstr, IRTemp condT )
   6593 {
   6594    UInt A = (theInstr >> 16) & 3;
   6595    UInt B = (theInstr >> 6) & 0x1f;
   6596    UInt Q = (theInstr >> 6) & 1;
   6597    UInt U = (theInstr >> 24) & 1;
   6598    UInt size = (theInstr >> 18) & 3;
   6599    UInt dreg = get_neon_d_regno(theInstr);
   6600    UInt mreg = get_neon_m_regno(theInstr);
   6601    UInt F = (theInstr >> 10) & 1;
   6602    IRTemp arg_d;
   6603    IRTemp arg_m;
   6604    IRTemp res;
   6605    switch (A) {
   6606       case 0:
   6607          if (Q) {
   6608             arg_m = newTemp(Ity_V128);
   6609             res = newTemp(Ity_V128);
   6610             assign(arg_m, getQReg(mreg));
   6611          } else {
   6612             arg_m = newTemp(Ity_I64);
   6613             res = newTemp(Ity_I64);
   6614             assign(arg_m, getDRegI64(mreg));
   6615          }
   6616          switch (B >> 1) {
   6617             case 0: {
   6618                /* VREV64 */
   6619                IROp op;
   6620                switch (size) {
   6621                   case 0:
   6622                      op = Q ? Iop_Reverse64_8x16 : Iop_Reverse64_8x8;
   6623                      break;
   6624                   case 1:
   6625                      op = Q ? Iop_Reverse64_16x8 : Iop_Reverse64_16x4;
   6626                      break;
   6627                   case 2:
   6628                      op = Q ? Iop_Reverse64_32x4 : Iop_Reverse64_32x2;
   6629                      break;
   6630                   case 3:
   6631                      return False;
   6632                   default:
   6633                      vassert(0);
   6634                }
   6635                assign(res, unop(op, mkexpr(arg_m)));
   6636                DIP("vrev64.%u %c%u, %c%u\n", 8 << size,
   6637                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6638                break;
   6639             }
   6640             case 1: {
   6641                /* VREV32 */
   6642                IROp op;
   6643                switch (size) {
   6644                   case 0:
   6645                      op = Q ? Iop_Reverse32_8x16 : Iop_Reverse32_8x8;
   6646                      break;
   6647                   case 1:
   6648                      op = Q ? Iop_Reverse32_16x8 : Iop_Reverse32_16x4;
   6649                      break;
   6650                   case 2:
   6651                   case 3:
   6652                      return False;
   6653                   default:
   6654                      vassert(0);
   6655                }
   6656                assign(res, unop(op, mkexpr(arg_m)));
   6657                DIP("vrev32.%u %c%u, %c%u\n", 8 << size,
   6658                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6659                break;
   6660             }
   6661             case 2: {
   6662                /* VREV16 */
   6663                IROp op;
   6664                switch (size) {
   6665                   case 0:
   6666                      op = Q ? Iop_Reverse16_8x16 : Iop_Reverse16_8x8;
   6667                      break;
   6668                   case 1:
   6669                   case 2:
   6670                   case 3:
   6671                      return False;
   6672                   default:
   6673                      vassert(0);
   6674                }
   6675                assign(res, unop(op, mkexpr(arg_m)));
   6676                DIP("vrev16.%u %c%u, %c%u\n", 8 << size,
   6677                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6678                break;
   6679             }
   6680             case 3:
   6681                return False;
   6682             case 4:
   6683             case 5: {
   6684                /* VPADDL */
   6685                IROp op;
   6686                U = (theInstr >> 7) & 1;
   6687                if (Q) {
   6688                   switch (size) {
   6689                      case 0: op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16; break;
   6690                      case 1: op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8; break;
   6691                      case 2: op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4; break;
   6692                      case 3: return False;
   6693                      default: vassert(0);
   6694                   }
   6695                } else {
   6696                   switch (size) {
   6697                      case 0: op = U ? Iop_PwAddL8Ux8  : Iop_PwAddL8Sx8;  break;
   6698                      case 1: op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4; break;
   6699                      case 2: op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2; break;
   6700                      case 3: return False;
   6701                      default: vassert(0);
   6702                   }
   6703                }
   6704                assign(res, unop(op, mkexpr(arg_m)));
   6705                DIP("vpaddl.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
   6706                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6707                break;
   6708             }
   6709             case 6:
   6710             case 7:
   6711                return False;
   6712             case 8: {
   6713                /* VCLS */
   6714                IROp op;
   6715                switch (size) {
   6716                   case 0: op = Q ? Iop_Cls8Sx16 : Iop_Cls8Sx8; break;
   6717                   case 1: op = Q ? Iop_Cls16Sx8 : Iop_Cls16Sx4; break;
   6718                   case 2: op = Q ? Iop_Cls32Sx4 : Iop_Cls32Sx2; break;
   6719                   case 3: return False;
   6720                   default: vassert(0);
   6721                }
   6722                assign(res, unop(op, mkexpr(arg_m)));
   6723                DIP("vcls.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6724                    Q ? 'q' : 'd', mreg);
   6725                break;
   6726             }
   6727             case 9: {
   6728                /* VCLZ */
   6729                IROp op;
   6730                switch (size) {
   6731                   case 0: op = Q ? Iop_Clz8Sx16 : Iop_Clz8Sx8; break;
   6732                   case 1: op = Q ? Iop_Clz16Sx8 : Iop_Clz16Sx4; break;
   6733                   case 2: op = Q ? Iop_Clz32Sx4 : Iop_Clz32Sx2; break;
   6734                   case 3: return False;
   6735                   default: vassert(0);
   6736                }
   6737                assign(res, unop(op, mkexpr(arg_m)));
   6738                DIP("vclz.i%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6739                    Q ? 'q' : 'd', mreg);
   6740                break;
   6741             }
   6742             case 10:
   6743                /* VCNT */
   6744                assign(res, unop(Q ? Iop_Cnt8x16 : Iop_Cnt8x8, mkexpr(arg_m)));
   6745                DIP("vcnt.8 %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
   6746                    mreg);
   6747                break;
   6748             case 11:
   6749                /* VMVN */
   6750                if (Q)
   6751                   assign(res, unop(Iop_NotV128, mkexpr(arg_m)));
   6752                else
   6753                   assign(res, unop(Iop_Not64, mkexpr(arg_m)));
   6754                DIP("vmvn %c%u, %c%u\n", Q ? 'q' : 'd', dreg, Q ? 'q' : 'd',
   6755                    mreg);
   6756                break;
   6757             case 12:
   6758             case 13: {
   6759                /* VPADAL */
   6760                IROp op, add_op;
   6761                U = (theInstr >> 7) & 1;
   6762                if (Q) {
   6763                   switch (size) {
   6764                      case 0:
   6765                         op = U ? Iop_PwAddL8Ux16 : Iop_PwAddL8Sx16;
   6766                         add_op = Iop_Add16x8;
   6767                         break;
   6768                      case 1:
   6769                         op = U ? Iop_PwAddL16Ux8 : Iop_PwAddL16Sx8;
   6770                         add_op = Iop_Add32x4;
   6771                         break;
   6772                      case 2:
   6773                         op = U ? Iop_PwAddL32Ux4 : Iop_PwAddL32Sx4;
   6774                         add_op = Iop_Add64x2;
   6775                         break;
   6776                      case 3:
   6777                         return False;
   6778                      default:
   6779                         vassert(0);
   6780                   }
   6781                } else {
   6782                   switch (size) {
   6783                      case 0:
   6784                         op = U ? Iop_PwAddL8Ux8 : Iop_PwAddL8Sx8;
   6785                         add_op = Iop_Add16x4;
   6786                         break;
   6787                      case 1:
   6788                         op = U ? Iop_PwAddL16Ux4 : Iop_PwAddL16Sx4;
   6789                         add_op = Iop_Add32x2;
   6790                         break;
   6791                      case 2:
   6792                         op = U ? Iop_PwAddL32Ux2 : Iop_PwAddL32Sx2;
   6793                         add_op = Iop_Add64;
   6794                         break;
   6795                      case 3:
   6796                         return False;
   6797                      default:
   6798                         vassert(0);
   6799                   }
   6800                }
   6801                if (Q) {
   6802                   arg_d = newTemp(Ity_V128);
   6803                   assign(arg_d, getQReg(dreg));
   6804                } else {
   6805                   arg_d = newTemp(Ity_I64);
   6806                   assign(arg_d, getDRegI64(dreg));
   6807                }
   6808                assign(res, binop(add_op, unop(op, mkexpr(arg_m)),
   6809                                          mkexpr(arg_d)));
   6810                DIP("vpadal.%c%u %c%u, %c%u\n", U ? 'u' : 's', 8 << size,
   6811                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6812                break;
   6813             }
   6814             case 14: {
   6815                /* VQABS */
   6816                IROp op_sub, op_qsub, op_cmp;
   6817                IRTemp mask, tmp;
   6818                IRExpr *zero1, *zero2;
   6819                IRExpr *neg, *neg2;
   6820                if (Q) {
   6821                   zero1 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6822                   zero2 = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6823                   mask = newTemp(Ity_V128);
   6824                   tmp = newTemp(Ity_V128);
   6825                } else {
   6826                   zero1 = mkU64(0);
   6827                   zero2 = mkU64(0);
   6828                   mask = newTemp(Ity_I64);
   6829                   tmp = newTemp(Ity_I64);
   6830                }
   6831                switch (size) {
   6832                   case 0:
   6833                      op_sub = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   6834                      op_qsub = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
   6835                      op_cmp = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8;
   6836                      break;
   6837                   case 1:
   6838                      op_sub = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   6839                      op_qsub = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
   6840                      op_cmp = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4;
   6841                      break;
   6842                   case 2:
   6843                      op_sub = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   6844                      op_qsub = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
   6845                      op_cmp = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2;
   6846                      break;
   6847                   case 3:
   6848                      return False;
   6849                   default:
   6850                      vassert(0);
   6851                }
   6852                assign(mask, binop(op_cmp, mkexpr(arg_m), zero1));
   6853                neg = binop(op_qsub, zero2, mkexpr(arg_m));
   6854                neg2 = binop(op_sub, zero2, mkexpr(arg_m));
   6855                assign(res, binop(Q ? Iop_OrV128 : Iop_Or64,
   6856                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6857                                        mkexpr(mask),
   6858                                        mkexpr(arg_m)),
   6859                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6860                                        unop(Q ? Iop_NotV128 : Iop_Not64,
   6861                                             mkexpr(mask)),
   6862                                        neg)));
   6863 #ifndef DISABLE_QC_FLAG
   6864                assign(tmp, binop(Q ? Iop_OrV128 : Iop_Or64,
   6865                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6866                                        mkexpr(mask),
   6867                                        mkexpr(arg_m)),
   6868                                  binop(Q ? Iop_AndV128 : Iop_And64,
   6869                                        unop(Q ? Iop_NotV128 : Iop_Not64,
   6870                                             mkexpr(mask)),
   6871                                        neg2)));
   6872                setFlag_QC(mkexpr(res), mkexpr(tmp), Q, condT);
   6873 #endif
   6874                DIP("vqabs.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6875                    Q ? 'q' : 'd', mreg);
   6876                break;
   6877             }
   6878             case 15: {
   6879                /* VQNEG */
   6880                IROp op, op2;
   6881                IRExpr *zero;
   6882                if (Q) {
   6883                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6884                } else {
   6885                   zero = mkU64(0);
   6886                }
   6887                switch (size) {
   6888                   case 0:
   6889                      op = Q ? Iop_QSub8Sx16 : Iop_QSub8Sx8;
   6890                      op2 = Q ? Iop_Sub8x16 : Iop_Sub8x8;
   6891                      break;
   6892                   case 1:
   6893                      op = Q ? Iop_QSub16Sx8 : Iop_QSub16Sx4;
   6894                      op2 = Q ? Iop_Sub16x8 : Iop_Sub16x4;
   6895                      break;
   6896                   case 2:
   6897                      op = Q ? Iop_QSub32Sx4 : Iop_QSub32Sx2;
   6898                      op2 = Q ? Iop_Sub32x4 : Iop_Sub32x2;
   6899                      break;
   6900                   case 3:
   6901                      return False;
   6902                   default:
   6903                      vassert(0);
   6904                }
   6905                assign(res, binop(op, zero, mkexpr(arg_m)));
   6906 #ifndef DISABLE_QC_FLAG
   6907                setFlag_QC(mkexpr(res), binop(op2, zero, mkexpr(arg_m)),
   6908                           Q, condT);
   6909 #endif
   6910                DIP("vqneg.s%u %c%u, %c%u\n", 8 << size, Q ? 'q' : 'd', dreg,
   6911                    Q ? 'q' : 'd', mreg);
   6912                break;
   6913             }
   6914             default:
   6915                vassert(0);
   6916          }
   6917          if (Q) {
   6918             putQReg(dreg, mkexpr(res), condT);
   6919          } else {
   6920             putDRegI64(dreg, mkexpr(res), condT);
   6921          }
   6922          return True;
   6923       case 1:
   6924          if (Q) {
   6925             arg_m = newTemp(Ity_V128);
   6926             res = newTemp(Ity_V128);
   6927             assign(arg_m, getQReg(mreg));
   6928          } else {
   6929             arg_m = newTemp(Ity_I64);
   6930             res = newTemp(Ity_I64);
   6931             assign(arg_m, getDRegI64(mreg));
   6932          }
   6933          switch ((B >> 1) & 0x7) {
   6934             case 0: {
   6935                /* VCGT #0 */
   6936                IRExpr *zero;
   6937                IROp op;
   6938                if (Q) {
   6939                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6940                } else {
   6941                   zero = mkU64(0);
   6942                }
   6943                if (F) {
   6944                   switch (size) {
   6945                      case 0: case 1: case 3: return False;
   6946                      case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
   6947                      default: vassert(0);
   6948                   }
   6949                } else {
   6950                   switch (size) {
   6951                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   6952                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   6953                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   6954                      case 3: return False;
   6955                      default: vassert(0);
   6956                   }
   6957                }
   6958                assign(res, binop(op, mkexpr(arg_m), zero));
   6959                DIP("vcgt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   6960                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6961                break;
   6962             }
   6963             case 1: {
   6964                /* VCGE #0 */
   6965                IROp op;
   6966                IRExpr *zero;
   6967                if (Q) {
   6968                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   6969                } else {
   6970                   zero = mkU64(0);
   6971                }
   6972                if (F) {
   6973                   switch (size) {
   6974                      case 0: case 1: case 3: return False;
   6975                      case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
   6976                      default: vassert(0);
   6977                   }
   6978                   assign(res, binop(op, mkexpr(arg_m), zero));
   6979                } else {
   6980                   switch (size) {
   6981                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   6982                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   6983                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   6984                      case 3: return False;
   6985                      default: vassert(0);
   6986                   }
   6987                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   6988                                    binop(op, zero, mkexpr(arg_m))));
   6989                }
   6990                DIP("vcge.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   6991                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   6992                break;
   6993             }
   6994             case 2: {
   6995                /* VCEQ #0 */
   6996                IROp op;
   6997                IRExpr *zero;
   6998                if (F) {
   6999                   if (Q) {
   7000                      zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7001                   } else {
   7002                      zero = mkU64(0);
   7003                   }
   7004                   switch (size) {
   7005                      case 0: case 1: case 3: return False;
   7006                      case 2: op = Q ? Iop_CmpEQ32Fx4 : Iop_CmpEQ32Fx2; break;
   7007                      default: vassert(0);
   7008                   }
   7009                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7010                } else {
   7011                   switch (size) {
   7012                      case 0: op = Q ? Iop_CmpNEZ8x16 : Iop_CmpNEZ8x8; break;
   7013                      case 1: op = Q ? Iop_CmpNEZ16x8 : Iop_CmpNEZ16x4; break;
   7014                      case 2: op = Q ? Iop_CmpNEZ32x4 : Iop_CmpNEZ32x2; break;
   7015                      case 3: return False;
   7016                      default: vassert(0);
   7017                   }
   7018                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   7019                                    unop(op, mkexpr(arg_m))));
   7020                }
   7021                DIP("vceq.%c%u %c%u, %c%u, #0\n", F ? 'f' : 'i', 8 << size,
   7022                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7023                break;
   7024             }
   7025             case 3: {
   7026                /* VCLE #0 */
   7027                IRExpr *zero;
   7028                IROp op;
   7029                if (Q) {
   7030                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7031                } else {
   7032                   zero = mkU64(0);
   7033                }
   7034                if (F) {
   7035                   switch (size) {
   7036                      case 0: case 1: case 3: return False;
   7037                      case 2: op = Q ? Iop_CmpGE32Fx4 : Iop_CmpGE32Fx2; break;
   7038                      default: vassert(0);
   7039                   }
   7040                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7041                } else {
   7042                   switch (size) {
   7043                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   7044                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   7045                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   7046                      case 3: return False;
   7047                      default: vassert(0);
   7048                   }
   7049                   assign(res, unop(Q ? Iop_NotV128 : Iop_Not64,
   7050                                    binop(op, mkexpr(arg_m), zero)));
   7051                }
   7052                DIP("vcle.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   7053                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7054                break;
   7055             }
   7056             case 4: {
   7057                /* VCLT #0 */
   7058                IROp op;
   7059                IRExpr *zero;
   7060                if (Q) {
   7061                   zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7062                } else {
   7063                   zero = mkU64(0);
   7064                }
   7065                if (F) {
   7066                   switch (size) {
   7067                      case 0: case 1: case 3: return False;
   7068                      case 2: op = Q ? Iop_CmpGT32Fx4 : Iop_CmpGT32Fx2; break;
   7069                      default: vassert(0);
   7070                   }
   7071                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7072                } else {
   7073                   switch (size) {
   7074                      case 0: op = Q ? Iop_CmpGT8Sx16 : Iop_CmpGT8Sx8; break;
   7075                      case 1: op = Q ? Iop_CmpGT16Sx8 : Iop_CmpGT16Sx4; break;
   7076                      case 2: op = Q ? Iop_CmpGT32Sx4 : Iop_CmpGT32Sx2; break;
   7077                      case 3: return False;
   7078                      default: vassert(0);
   7079                   }
   7080                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7081                }
   7082                DIP("vclt.%c%u %c%u, %c%u, #0\n", F ? 'f' : 's', 8 << size,
   7083                    Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7084                break;
   7085             }
   7086             case 5:
   7087                return False;
   7088             case 6: {
   7089                /* VABS */
   7090                if (!F) {
   7091                   IROp op;
   7092                   switch(size) {
   7093                      case 0: op = Q ? Iop_Abs8x16 : Iop_Abs8x8; break;
   7094                      case 1: op = Q ? Iop_Abs16x8 : Iop_Abs16x4; break;
   7095                      case 2: op = Q ? Iop_Abs32x4 : Iop_Abs32x2; break;
   7096                      case 3: return False;
   7097                      default: vassert(0);
   7098                   }
   7099                   assign(res, unop(op, mkexpr(arg_m)));
   7100                } else {
   7101                   assign(res, unop(Q ? Iop_Abs32Fx4 : Iop_Abs32Fx2,
   7102                                    mkexpr(arg_m)));
   7103                }
   7104                DIP("vabs.%c%u %c%u, %c%u\n",
   7105                    F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
   7106                    Q ? 'q' : 'd', mreg);
   7107                break;
   7108             }
   7109             case 7: {
   7110                /* VNEG */
   7111                IROp op;
   7112                IRExpr *zero;
   7113                if (F) {
   7114                   switch (size) {
   7115                      case 0: case 1: case 3: return False;
   7116                      case 2: op = Q ? Iop_Neg32Fx4 : Iop_Neg32Fx2; break;
   7117                      default: vassert(0);
   7118                   }
   7119                   assign(res, unop(op, mkexpr(arg_m)));
   7120                } else {
   7121                   if (Q) {
   7122                      zero = binop(Iop_64HLtoV128, mkU64(0), mkU64(0));
   7123                   } else {
   7124                      zero = mkU64(0);
   7125                   }
   7126                   switch (size) {
   7127                      case 0: op = Q ? Iop_Sub8x16 : Iop_Sub8x8; break;
   7128                      case 1: op = Q ? Iop_Sub16x8 : Iop_Sub16x4; break;
   7129                      case 2: op = Q ? Iop_Sub32x4 : Iop_Sub32x2; break;
   7130                      case 3: return False;
   7131                      default: vassert(0);
   7132                   }
   7133                   assign(res, binop(op, zero, mkexpr(arg_m)));
   7134                }
   7135                DIP("vneg.%c%u %c%u, %c%u\n",
   7136                    F ? 'f' : 's', 8 << size, Q ? 'q' : 'd', dreg,
   7137                    Q ? 'q' : 'd', mreg);
   7138                break;
   7139             }
   7140             default:
   7141                vassert(0);
   7142          }
   7143          if (Q) {
   7144             putQReg(dreg, mkexpr(res), condT);
   7145          } else {
   7146             putDRegI64(dreg, mkexpr(res), condT);
   7147          }
   7148          return True;
   7149       case 2:
   7150          if ((B >> 1) == 0) {
   7151             /* VSWP */
   7152             if (Q) {
   7153                arg_m = newTemp(Ity_V128);
   7154                assign(arg_m, getQReg(mreg));
   7155                putQReg(mreg, getQReg(dreg), condT);
   7156                putQReg(dreg, mkexpr(arg_m), condT);
   7157             } else {
   7158                arg_m = newTemp(Ity_I64);
   7159                assign(arg_m, getDRegI64(mreg));
   7160                putDRegI64(mreg, getDRegI64(dreg), condT);
   7161                putDRegI64(dreg, mkexpr(arg_m), condT);
   7162             }
   7163             DIP("vswp %c%u, %c%u\n",
   7164                 Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7165             return True;
   7166          } else if ((B >> 1) == 1) {
   7167             /* VTRN */
   7168             IROp op_lo, op_hi;
   7169             IRTemp res1, res2;
   7170             if (Q) {
   7171                arg_m = newTemp(Ity_V128);
   7172                arg_d = newTemp(Ity_V128);
   7173                res1 = newTemp(Ity_V128);
   7174                res2 = newTemp(Ity_V128);
   7175                assign(arg_m, getQReg(mreg));
   7176                assign(arg_d, getQReg(dreg));
   7177             } else {
   7178                res1 = newTemp(Ity_I64);
   7179                res2 = newTemp(Ity_I64);
   7180                arg_m = newTemp(Ity_I64);
   7181                arg_d = newTemp(Ity_I64);
   7182                assign(arg_m, getDRegI64(mreg));
   7183                assign(arg_d, getDRegI64(dreg));
   7184             }
   7185             if (Q) {
   7186                switch (size) {
   7187                   case 0:
   7188                      op_lo = Iop_InterleaveOddLanes8x16;
   7189                      op_hi = Iop_InterleaveEvenLanes8x16;
   7190                      break;
   7191                   case 1:
   7192                      op_lo = Iop_InterleaveOddLanes16x8;
   7193                      op_hi = Iop_InterleaveEvenLanes16x8;
   7194                      break;
   7195                   case 2:
   7196                      op_lo = Iop_InterleaveOddLanes32x4;
   7197                      op_hi = Iop_InterleaveEvenLanes32x4;
   7198                      break;
   7199                   case 3:
   7200                      return False;
   7201                   default:
   7202                      vassert(0);
   7203                }
   7204             } else {
   7205                switch (size) {
   7206                   case 0:
   7207                      op_lo = Iop_InterleaveOddLanes8x8;
   7208                      op_hi = Iop_InterleaveEvenLanes8x8;
   7209                      break;
   7210                   case 1:
   7211                      op_lo = Iop_InterleaveOddLanes16x4;
   7212                      op_hi = Iop_InterleaveEvenLanes16x4;
   7213                      break;
   7214                   case 2:
   7215                      op_lo = Iop_InterleaveLO32x2;
   7216                      op_hi = Iop_InterleaveHI32x2;
   7217                      break;
   7218                   case 3:
   7219                      return False;
   7220                   default:
   7221                      vassert(0);
   7222                }
   7223             }
   7224             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
   7225             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
   7226             if (Q) {
   7227                putQReg(dreg, mkexpr(res1), condT);
   7228                putQReg(mreg, mkexpr(res2), condT);
   7229             } else {
   7230                putDRegI64(dreg, mkexpr(res1), condT);
   7231                putDRegI64(mreg, mkexpr(res2), condT);
   7232             }
   7233             DIP("vtrn.%u %c%u, %c%u\n",
   7234                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7235             return True;
   7236          } else if ((B >> 1) == 2) {
   7237             /* VUZP */
   7238             IROp op_lo, op_hi;
   7239             IRTemp res1, res2;
   7240             if (!Q && size == 2)
   7241                return False;
   7242             if (Q) {
   7243                arg_m = newTemp(Ity_V128);
   7244                arg_d = newTemp(Ity_V128);
   7245                res1 = newTemp(Ity_V128);
   7246                res2 = newTemp(Ity_V128);
   7247                assign(arg_m, getQReg(mreg));
   7248                assign(arg_d, getQReg(dreg));
   7249             } else {
   7250                res1 = newTemp(Ity_I64);
   7251                res2 = newTemp(Ity_I64);
   7252                arg_m = newTemp(Ity_I64);
   7253                arg_d = newTemp(Ity_I64);
   7254                assign(arg_m, getDRegI64(mreg));
   7255                assign(arg_d, getDRegI64(dreg));
   7256             }
   7257             switch (size) {
   7258                case 0:
   7259                   op_lo = Q ? Iop_CatOddLanes8x16 : Iop_CatOddLanes8x8;
   7260                   op_hi = Q ? Iop_CatEvenLanes8x16 : Iop_CatEvenLanes8x8;
   7261                   break;
   7262                case 1:
   7263                   op_lo = Q ? Iop_CatOddLanes16x8 : Iop_CatOddLanes16x4;
   7264                   op_hi = Q ? Iop_CatEvenLanes16x8 : Iop_CatEvenLanes16x4;
   7265                   break;
   7266                case 2:
   7267                   op_lo = Iop_CatOddLanes32x4;
   7268                   op_hi = Iop_CatEvenLanes32x4;
   7269                   break;
   7270                case 3:
   7271                   return False;
   7272                default:
   7273                   vassert(0);
   7274             }
   7275             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
   7276             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
   7277             if (Q) {
   7278                putQReg(dreg, mkexpr(res1), condT);
   7279                putQReg(mreg, mkexpr(res2), condT);
   7280             } else {
   7281                putDRegI64(dreg, mkexpr(res1), condT);
   7282                putDRegI64(mreg, mkexpr(res2), condT);
   7283             }
   7284             DIP("vuzp.%u %c%u, %c%u\n",
   7285                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7286             return True;
   7287          } else if ((B >> 1) == 3) {
   7288             /* VZIP */
   7289             IROp op_lo, op_hi;
   7290             IRTemp res1, res2;
   7291             if (!Q && size == 2)
   7292                return False;
   7293             if (Q) {
   7294                arg_m = newTemp(Ity_V128);
   7295                arg_d = newTemp(Ity_V128);
   7296                res1 = newTemp(Ity_V128);
   7297                res2 = newTemp(Ity_V128);
   7298                assign(arg_m, getQReg(mreg));
   7299                assign(arg_d, getQReg(dreg));
   7300             } else {
   7301                res1 = newTemp(Ity_I64);
   7302                res2 = newTemp(Ity_I64);
   7303                arg_m = newTemp(Ity_I64);
   7304                arg_d = newTemp(Ity_I64);
   7305                assign(arg_m, getDRegI64(mreg));
   7306                assign(arg_d, getDRegI64(dreg));
   7307             }
   7308             switch (size) {
   7309                case 0:
   7310                   op_lo = Q ? Iop_InterleaveHI8x16 : Iop_InterleaveHI8x8;
   7311                   op_hi = Q ? Iop_InterleaveLO8x16 : Iop_InterleaveLO8x8;
   7312                   break;
   7313                case 1:
   7314                   op_lo = Q ? Iop_InterleaveHI16x8 : Iop_InterleaveHI16x4;
   7315                   op_hi = Q ? Iop_InterleaveLO16x8 : Iop_InterleaveLO16x4;
   7316                   break;
   7317                case 2:
   7318                   op_lo = Iop_InterleaveHI32x4;
   7319                   op_hi = Iop_InterleaveLO32x4;
   7320                   break;
   7321                case 3:
   7322                   return False;
   7323                default:
   7324                   vassert(0);
   7325             }
   7326             assign(res1, binop(op_lo, mkexpr(arg_m), mkexpr(arg_d)));
   7327             assign(res2, binop(op_hi, mkexpr(arg_m), mkexpr(arg_d)));
   7328             if (Q) {
   7329                putQReg(dreg, mkexpr(res1), condT);
   7330                putQReg(mreg, mkexpr(res2), condT);
   7331             } else {
   7332                putDRegI64(dreg, mkexpr(res1), condT);
   7333                putDRegI64(mreg, mkexpr(res2), condT);
   7334             }
   7335             DIP("vzip.%u %c%u, %c%u\n",
   7336                 8 << size, Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7337             return True;
   7338          } else if (B == 8) {
   7339             /* VMOVN */
   7340             IROp op;
   7341             mreg >>= 1;
   7342             switch (size) {
   7343                case 0: op = Iop_Shorten16x8; break;
   7344                case 1: op = Iop_Shorten32x4; break;
   7345                case 2: op = Iop_Shorten64x2; break;
   7346                case 3: return False;
   7347                default: vassert(0);
   7348             }
   7349             putDRegI64(dreg, unop(op, getQReg(mreg)), condT);
   7350             DIP("vmovn.i%u d%u, q%u\n", 16 << size, dreg, mreg);
   7351             return True;
   7352          } else if (B == 9 || (B >> 1) == 5) {
   7353             /* VQMOVN, VQMOVUN */
   7354             IROp op, op2;
   7355             IRTemp tmp;
   7356             dreg = ((theInstr >> 18) & 0x10) | ((theInstr >> 12) & 0xF);
   7357             mreg = ((theInstr >> 1) & 0x10) | (theInstr & 0xF);
   7358             if (mreg & 1)
   7359                return False;
   7360             mreg >>= 1;
   7361             switch (size) {
   7362                case 0: op2 = Iop_Shorten16x8; break;
   7363                case 1: op2 = Iop_Shorten32x4; break;
   7364                case 2: op2 = Iop_Shorten64x2; break;
   7365                case 3: return False;
   7366                default: vassert(0);
   7367             }
   7368             switch (B & 3) {
   7369                case 0:
   7370                   vassert(0);
   7371                case 1:
   7372                   switch (size) {
   7373                      case 0: op = Iop_QShortenU16Sx8; break;
   7374                      case 1: op = Iop_QShortenU32Sx4; break;
   7375                      case 2: op = Iop_QShortenU64Sx2; break;
   7376                      case 3: return False;
   7377                      default: vassert(0);
   7378                   }
   7379                   DIP("vqmovun.s%u d%u, q%u\n", 16 << size, dreg, mreg);
   7380                   break;
   7381                case 2:
   7382                   switch (size) {
   7383                      case 0: op = Iop_QShortenS16Sx8; break;
   7384                      case 1: op = Iop_QShortenS32Sx4; break;
   7385                      case 2: op = Iop_QShortenS64Sx2; break;
   7386                      case 3: return False;
   7387                      default: vassert(0);
   7388                   }
   7389                   DIP("vqmovn.s%u d%u, q%u\n", 16 << size, dreg, mreg);
   7390                   break;
   7391                case 3:
   7392                   switch (size) {
   7393                      case 0: op = Iop_QShortenU16Ux8; break;
   7394                      case 1: op = Iop_QShortenU32Ux4; break;
   7395                      case 2: op = Iop_QShortenU64Ux2; break;
   7396                      case 3: return False;
   7397                      default: vassert(0);
   7398                   }
   7399                   DIP("vqmovn.u%u d%u, q%u\n", 16 << size, dreg, mreg);
   7400                   break;
   7401                default:
   7402                   vassert(0);
   7403             }
   7404             res = newTemp(Ity_I64);
   7405             tmp = newTemp(Ity_I64);
   7406             assign(res, unop(op, getQReg(mreg)));
   7407 #ifndef DISABLE_QC_FLAG
   7408             assign(tmp, unop(op2, getQReg(mreg)));
   7409             setFlag_QC(mkexpr(res), mkexpr(tmp), False, condT);
   7410 #endif
   7411             putDRegI64(dreg, mkexpr(res), condT);
   7412             return True;
   7413          } else if (B == 12) {
   7414             /* VSHLL (maximum shift) */
   7415             IROp op, cvt;
   7416             UInt shift_imm;
   7417             if (Q)
   7418                return False;
   7419             if (dreg & 1)
   7420                return False;
   7421             dreg >>= 1;
   7422             shift_imm = 8 << size;
   7423             res = newTemp(Ity_V128);
   7424             switch (size) {
   7425                case 0: op = Iop_ShlN16x8; cvt = Iop_Longen8Ux8; break;
   7426                case 1: op = Iop_ShlN32x4; cvt = Iop_Longen16Ux4; break;
   7427                case 2: op = Iop_ShlN64x2; cvt = Iop_Longen32Ux2; break;
   7428                case 3: return False;
   7429                default: vassert(0);
   7430             }
   7431             assign(res, binop(op, unop(cvt, getDRegI64(mreg)),
   7432                                   mkU8(shift_imm)));
   7433             putQReg(dreg, mkexpr(res), condT);
   7434             DIP("vshll.i%u q%u, d%u, #%u\n", 8 << size, dreg, mreg, 8 << size);
   7435             return True;
   7436          } else if ((B >> 3) == 3 && (B & 3) == 0) {
   7437             /* VCVT (half<->single) */
   7438             /* Half-precision extensions are needed to run this */
   7439             vassert(0); // ATC
   7440             if (((theInstr >> 18) & 3) != 1)
   7441                return False;
   7442             if ((theInstr >> 8) & 1) {
   7443                if (dreg & 1)
   7444                   return False;
   7445                dreg >>= 1;
   7446                putQReg(dreg, unop(Iop_F16toF32x4, getDRegI64(mreg)),
   7447                      condT);
   7448                DIP("vcvt.f32.f16 q%u, d%u\n", dreg, mreg);
   7449             } else {
   7450                if (mreg & 1)
   7451                   return False;
   7452                mreg >>= 1;
   7453                putDRegI64(dreg, unop(Iop_F32toF16x4, getQReg(mreg)),
   7454                                 condT);
   7455                DIP("vcvt.f16.f32 d%u, q%u\n", dreg, mreg);
   7456             }
   7457             return True;
   7458          } else {
   7459             return False;
   7460          }
   7461          vassert(0);
   7462          return True;
   7463       case 3:
   7464          if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,0)) {
   7465             /* VRECPE */
   7466             IROp op;
   7467             F = (theInstr >> 8) & 1;
   7468             if (size != 2)
   7469                return False;
   7470             if (Q) {
   7471                op = F ? Iop_Recip32Fx4 : Iop_Recip32x4;
   7472                putQReg(dreg, unop(op, getQReg(mreg)), condT);
   7473                DIP("vrecpe.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
   7474             } else {
   7475                op = F ? Iop_Recip32Fx2 : Iop_Recip32x2;
   7476                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
   7477                DIP("vrecpe.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
   7478             }
   7479             return True;
   7480          } else if (((B >> 1) & BITS4(1,1,0,1)) == BITS4(1,0,0,1)) {
   7481             /* VRSQRTE */
   7482             IROp op;
   7483             F = (B >> 2) & 1;
   7484             if (size != 2)
   7485                return False;
   7486             if (F) {
   7487                /* fp */
   7488                op = Q ? Iop_Rsqrte32Fx4 : Iop_Rsqrte32Fx2;
   7489             } else {
   7490                /* unsigned int */
   7491                op = Q ? Iop_Rsqrte32x4 : Iop_Rsqrte32x2;
   7492             }
   7493             if (Q) {
   7494                putQReg(dreg, unop(op, getQReg(mreg)), condT);
   7495                DIP("vrsqrte.%c32 q%u, q%u\n", F ? 'f' : 'u', dreg, mreg);
   7496             } else {
   7497                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
   7498                DIP("vrsqrte.%c32 d%u, d%u\n", F ? 'f' : 'u', dreg, mreg);
   7499             }
   7500             return True;
   7501          } else if ((B >> 3) == 3) {
   7502             /* VCVT (fp<->integer) */
   7503             IROp op;
   7504             if (size != 2)
   7505                return False;
   7506             switch ((B >> 1) & 3) {
   7507                case 0:
   7508                   op = Q ? Iop_I32StoFx4 : Iop_I32StoFx2;
   7509                   DIP("vcvt.f32.s32 %c%u, %c%u\n",
   7510                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7511                   break;
   7512                case 1:
   7513                   op = Q ? Iop_I32UtoFx4 : Iop_I32UtoFx2;
   7514                   DIP("vcvt.f32.u32 %c%u, %c%u\n",
   7515                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7516                   break;
   7517                case 2:
   7518                   op = Q ? Iop_FtoI32Sx4_RZ : Iop_FtoI32Sx2_RZ;
   7519                   DIP("vcvt.s32.f32 %c%u, %c%u\n",
   7520                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7521                   break;
   7522                case 3:
   7523                   op = Q ? Iop_FtoI32Ux4_RZ : Iop_FtoI32Ux2_RZ;
   7524                   DIP("vcvt.u32.f32 %c%u, %c%u\n",
   7525                       Q ? 'q' : 'd', dreg, Q ? 'q' : 'd', mreg);
   7526                   break;
   7527                default:
   7528                   vassert(0);
   7529             }
   7530             if (Q) {
   7531                putQReg(dreg, unop(op, getQReg(mreg)), condT);
   7532             } else {
   7533                putDRegI64(dreg, unop(op, getDRegI64(mreg)), condT);
   7534             }
   7535             return True;
   7536          } else {
   7537             return False;
   7538          }
   7539          vassert(0);
   7540          return True;
   7541       default:
   7542          vassert(0);
   7543    }
   7544    return False;
   7545 }
   7546 
   7547 /* A7.4.6 One register and a modified immediate value */
   7548 static
   7549 void ppNeonImm(UInt imm, UInt cmode, UInt op)
   7550 {
   7551    int i;
   7552    switch (cmode) {
   7553       case 0: case 1: case 8: case 9:
   7554          vex_printf("0x%x", imm);
   7555          break;
   7556       case 2: case 3: case 10: case 11:
   7557          vex_printf("0x%x00", imm);
   7558          break;
   7559       case 4: case 5:
   7560          vex_printf("0x%x0000", imm);
   7561          break;
   7562       case 6: case 7:
   7563          vex_printf("0x%x000000", imm);
   7564          break;
   7565       case 12:
   7566          vex_printf("0x%xff", imm);
   7567          break;
   7568       case 13:
   7569          vex_printf("0x%xffff", imm);
   7570          break;
   7571       case 14:
   7572          if (op) {
   7573             vex_printf("0x");
   7574             for (i = 7; i >= 0; i--)
   7575                vex_printf("%s", (imm & (1 << i)) ? "ff" : "00");
   7576          } else {
   7577             vex_printf("0x%x", imm);
   7578          }
   7579          break;
   7580       case 15:
   7581          vex_printf("0x%x", imm);
   7582          break;
   7583    }
   7584 }
   7585 
   7586 static
   7587 const char *ppNeonImmType(UInt cmode, UInt op)
   7588 {
   7589    switch (cmode) {
   7590       case 0 ... 7:
   7591       case 12: case 13:
   7592          return "i32";
   7593       case 8 ... 11:
   7594          return "i16";
   7595       case 14:
   7596          if (op)
   7597             return "i64";
   7598          else
   7599             return "i8";
   7600       case 15:
   7601          if (op)
   7602             vassert(0);
   7603          else
   7604             return "f32";
   7605       default:
   7606          vassert(0);
   7607    }
   7608 }
   7609 
   7610 static
   7611 void DIPimm(UInt imm, UInt cmode, UInt op,
   7612             const char *instr, UInt Q, UInt dreg)
   7613 {
   7614    if (vex_traceflags & VEX_TRACE_FE) {
   7615       vex_printf("%s.%s %c%u, #", instr,
   7616                  ppNeonImmType(cmode, op), Q ? 'q' : 'd', dreg);
   7617       ppNeonImm(imm, cmode, op);
   7618       vex_printf("\n");
   7619    }
   7620 }
   7621 
   7622 static
   7623 Bool dis_neon_data_1reg_and_imm ( UInt theInstr, IRTemp condT )
   7624 {
   7625    UInt dreg = get_neon_d_regno(theInstr);
   7626    ULong imm_raw = ((theInstr >> 17) & 0x80) | ((theInstr >> 12) & 0x70) |
   7627                   (theInstr & 0xf);
   7628    ULong imm_raw_pp = imm_raw;
   7629    UInt cmode = (theInstr >> 8) & 0xf;
   7630    UInt op_bit = (theInstr >> 5) & 1;
   7631    ULong imm = 0;
   7632    UInt Q = (theInstr >> 6) & 1;
   7633    int i, j;
   7634    UInt tmp;
   7635    IRExpr *imm_val;
   7636    IRExpr *expr;
   7637    IRTemp tmp_var;
   7638    switch(cmode) {
   7639       case 7: case 6:
   7640          imm_raw = imm_raw << 8;
   7641          /* fallthrough */
   7642       case 5: case 4:
   7643          imm_raw = imm_raw << 8;
   7644          /* fallthrough */
   7645       case 3: case 2:
   7646          imm_raw = imm_raw << 8;
   7647          /* fallthrough */
   7648       case 0: case 1:
   7649          imm = (imm_raw << 32) | imm_raw;
   7650          break;
   7651       case 11: case 10:
   7652          imm_raw = imm_raw << 8;
   7653          /* fallthrough */
   7654       case 9: case 8:
   7655          imm_raw = (imm_raw << 16) | imm_raw;
   7656          imm = (imm_raw << 32) | imm_raw;
   7657          break;
   7658       case 13:
   7659          imm_raw = (imm_raw << 8) | 0xff;
   7660          /* fallthrough */
   7661       case 12:
   7662          imm_raw = (imm_raw << 8) | 0xff;
   7663          imm = (imm_raw << 32) | imm_raw;
   7664          break;
   7665       case 14:
   7666          if (! op_bit) {
   7667             for(i = 0; i < 8; i++) {
   7668                imm = (imm << 8) | imm_raw;
   7669             }
   7670          } else {
   7671             for(i = 7; i >= 0; i--) {
   7672                tmp = 0;
   7673                for(j = 0; j < 8; j++) {
   7674                   tmp = (tmp << 1) | ((imm_raw >> i) & 1);
   7675                }
   7676                imm = (imm << 8) | tmp;
   7677             }
   7678          }
   7679          break;
   7680       case 15:
   7681          imm = (imm_raw & 0x80) << 5;
   7682          imm |= ~((imm_raw & 0x40) << 5);
   7683          for(i = 1; i <= 4; i++)
   7684             imm |= (imm_raw & 0x40) << i;
   7685          imm |= (imm_raw & 0x7f);
   7686          imm = imm << 19;
   7687          imm = (imm << 32) | imm;
   7688          break;
   7689       default:
   7690          return False;
   7691    }
   7692    if (Q) {
   7693       imm_val = binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm));
   7694    } else {
   7695       imm_val = mkU64(imm);
   7696    }
   7697    if (((op_bit == 0) &&
   7698       (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 12) == 12))) ||
   7699       ((op_bit == 1) && (cmode == 14))) {
   7700       /* VMOV (immediate) */
   7701       if (Q) {
   7702          putQReg(dreg, imm_val, condT);
   7703       } else {
   7704          putDRegI64(dreg, imm_val, condT);
   7705       }
   7706       DIPimm(imm_raw_pp, cmode, op_bit, "vmov", Q, dreg);
   7707       return True;
   7708    }
   7709    if ((op_bit == 1) &&
   7710       (((cmode & 9) == 0) || ((cmode & 13) == 8) || ((cmode & 14) == 12))) {
   7711       /* VMVN (immediate) */
   7712       if (Q) {
   7713          putQReg(dreg, unop(Iop_NotV128, imm_val), condT);
   7714       } else {
   7715          putDRegI64(dreg, unop(Iop_Not64, imm_val), condT);
   7716       }
   7717       DIPimm(imm_raw_pp, cmode, op_bit, "vmvn", Q, dreg);
   7718       return True;
   7719    }
   7720    if (Q) {
   7721       tmp_var = newTemp(Ity_V128);
   7722       assign(tmp_var, getQReg(dreg));
   7723    } else {
   7724       tmp_var = newTemp(Ity_I64);
   7725       assign(tmp_var, getDRegI64(dreg));
   7726    }
   7727    if ((op_bit == 0) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
   7728       /* VORR (immediate) */
   7729       if (Q)
   7730          expr = binop(Iop_OrV128, mkexpr(tmp_var), imm_val);
   7731       else
   7732          expr = binop(Iop_Or64, mkexpr(tmp_var), imm_val);
   7733       DIPimm(imm_raw_pp, cmode, op_bit, "vorr", Q, dreg);
   7734    } else if ((op_bit == 1) && (((cmode & 9) == 1) || ((cmode & 13) == 9))) {
   7735       /* VBIC (immediate) */
   7736       if (Q)
   7737          expr = binop(Iop_AndV128, mkexpr(tmp_var),
   7738                                    unop(Iop_NotV128, imm_val));
   7739       else
   7740          expr = binop(Iop_And64, mkexpr(tmp_var), unop(Iop_Not64, imm_val));
   7741       DIPimm(imm_raw_pp, cmode, op_bit, "vbic", Q, dreg);
   7742    } else {
   7743       return False;
   7744    }
   7745    if (Q)
   7746       putQReg(dreg, expr, condT);
   7747    else
   7748       putDRegI64(dreg, expr, condT);
   7749    return True;
   7750 }
   7751 
   7752 /* A7.4 Advanced SIMD data-processing instructions */
   7753 static
   7754 Bool dis_neon_data_processing ( UInt theInstr, IRTemp condT )
   7755 {
   7756    UInt A = (theInstr >> 19) & 0x1F;
   7757    UInt B = (theInstr >>  8) & 0xF;
   7758    UInt C = (theInstr >>  4) & 0xF;
   7759    UInt U = (theInstr >> 24) & 0x1;
   7760 
   7761    if (! (A & 0x10)) {
   7762       return dis_neon_data_3same(theInstr, condT);
   7763    }
   7764    if (((A & 0x17) == 0x10) && ((C & 0x9) == 0x1)) {
   7765       return dis_neon_data_1reg_and_imm(theInstr, condT);
   7766    }
   7767    if ((C & 1) == 1) {
   7768       return dis_neon_data_2reg_and_shift(theInstr, condT);
   7769    }
   7770    if (((C & 5) == 0) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
   7771       return dis_neon_data_3diff(theInstr, condT);
   7772    }
   7773    if (((C & 5) == 4) && (((A & 0x14) == 0x10) || ((A & 0x16) == 0x14))) {
   7774       return dis_neon_data_2reg_and_scalar(theInstr, condT);
   7775    }
   7776    if ((A & 0x16) == 0x16) {
   7777       if ((U == 0) && ((C & 1) == 0)) {
   7778          return dis_neon_vext(theInstr, condT);
   7779       }
   7780       if ((U != 1) || ((C & 1) == 1))
   7781          return False;
   7782       if ((B & 8) == 0) {
   7783          return dis_neon_data_2reg_misc(theInstr, condT);
   7784       }
   7785       if ((B & 12) == 8) {
   7786          return dis_neon_vtb(theInstr, condT);
   7787       }
   7788       if ((B == 12) && ((C & 9) == 0)) {
   7789          return dis_neon_vdup(theInstr, condT);
   7790       }
   7791    }
   7792    return False;
   7793 }
   7794 
   7795 
   7796 /*------------------------------------------------------------*/
   7797 /*--- NEON loads and stores                                ---*/
   7798 /*------------------------------------------------------------*/
   7799 
   7800 /* For NEON memory operations, we use the standard scheme to handle
   7801    conditionalisation: generate a jump around the instruction if the
   7802    condition is false.  That's only necessary in Thumb mode, however,
   7803    since in ARM mode NEON instructions are unconditional. */
   7804 
   7805 /* A helper function for what follows.  It assumes we already went
   7806    uncond as per comments at the top of this section. */
   7807 static
   7808 void mk_neon_elem_load_to_one_lane( UInt rD, UInt inc, UInt index,
   7809                                     UInt N, UInt size, IRTemp addr )
   7810 {
   7811    UInt i;
   7812    switch (size) {
   7813       case 0:
   7814          putDRegI64(rD, triop(Iop_SetElem8x8, getDRegI64(rD), mkU8(index),
   7815                     loadLE(Ity_I8, mkexpr(addr))), IRTemp_INVALID);
   7816          break;
   7817       case 1:
   7818          putDRegI64(rD, triop(Iop_SetElem16x4, getDRegI64(rD), mkU8(index),
   7819                     loadLE(Ity_I16, mkexpr(addr))), IRTemp_INVALID);
   7820          break;
   7821       case 2:
   7822          putDRegI64(rD, triop(Iop_SetElem32x2, getDRegI64(rD), mkU8(index),
   7823                     loadLE(Ity_I32, mkexpr(addr))), IRTemp_INVALID);
   7824          break;
   7825       default:
   7826          vassert(0);
   7827    }
   7828    for (i = 1; i <= N; i++) {
   7829       switch (size) {
   7830          case 0:
   7831             putDRegI64(rD + i * inc,
   7832                        triop(Iop_SetElem8x8,
   7833                              getDRegI64(rD + i * inc),
   7834                              mkU8(index),
   7835                              loadLE(Ity_I8, binop(Iop_Add32,
   7836                                                   mkexpr(addr),
   7837                                                   mkU32(i * 1)))),
   7838                        IRTemp_INVALID);
   7839             break;
   7840          case 1:
   7841             putDRegI64(rD + i * inc,
   7842                        triop(Iop_SetElem16x4,
   7843                              getDRegI64(rD + i * inc),
   7844                              mkU8(index),
   7845                              loadLE(Ity_I16, binop(Iop_Add32,
   7846                                                    mkexpr(addr),
   7847                                                    mkU32(i * 2)))),
   7848                        IRTemp_INVALID);
   7849             break;
   7850          case 2:
   7851             putDRegI64(rD + i * inc,
   7852                        triop(Iop_SetElem32x2,
   7853                              getDRegI64(rD + i * inc),
   7854                              mkU8(index),
   7855                              loadLE(Ity_I32, binop(Iop_Add32,
   7856                                                    mkexpr(addr),
   7857                                                    mkU32(i * 4)))),
   7858                        IRTemp_INVALID);
   7859             break;
   7860          default:
   7861             vassert(0);
   7862       }
   7863    }
   7864 }
   7865 
   7866 /* A(nother) helper function for what follows.  It assumes we already
   7867    went uncond as per comments at the top of this section. */
   7868 static
   7869 void mk_neon_elem_store_from_one_lane( UInt rD, UInt inc, UInt index,
   7870                                        UInt N, UInt size, IRTemp addr )
   7871 {
   7872    UInt i;
   7873    switch (size) {
   7874       case 0:
   7875          storeLE(mkexpr(addr),
   7876                  binop(Iop_GetElem8x8, getDRegI64(rD), mkU8(index)));
   7877          break;
   7878       case 1:
   7879          storeLE(mkexpr(addr),
   7880                  binop(Iop_GetElem16x4, getDRegI64(rD), mkU8(index)));
   7881          break;
   7882       case 2:
   7883          storeLE(mkexpr(addr),
   7884                  binop(Iop_GetElem32x2, getDRegI64(rD), mkU8(index)));
   7885          break;
   7886       default:
   7887          vassert(0);
   7888    }
   7889    for (i = 1; i <= N; i++) {
   7890       switch (size) {
   7891          case 0:
   7892             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 1)),
   7893                     binop(Iop_GetElem8x8, getDRegI64(rD + i * inc),
   7894                                           mkU8(index)));
   7895             break;
   7896          case 1:
   7897             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 2)),
   7898                     binop(Iop_GetElem16x4, getDRegI64(rD + i * inc),
   7899                                            mkU8(index)));
   7900             break;
   7901          case 2:
   7902             storeLE(binop(Iop_Add32, mkexpr(addr), mkU32(i * 4)),
   7903                     binop(Iop_GetElem32x2, getDRegI64(rD + i * inc),
   7904                                            mkU8(index)));
   7905             break;
   7906          default:
   7907             vassert(0);
   7908       }
   7909    }
   7910 }
   7911 
   7912 /* A7.7 Advanced SIMD element or structure load/store instructions */
   7913 static
   7914 Bool dis_neon_elem_or_struct_load ( UInt theInstr,
   7915                                     Bool isT, IRTemp condT )
   7916 {
   7917 #  define INSN(_bMax,_bMin)  SLICE_UInt(theInstr, (_bMax), (_bMin))
   7918    UInt A = INSN(23,23);
   7919    UInt B = INSN(11,8);
   7920    UInt L = INSN(21,21);
   7921    UInt rD = (INSN(22,22) << 4) | INSN(15,12);
   7922    UInt rN = INSN(19,16);
   7923    UInt rM = INSN(3,0);
   7924    UInt N, size, i, j;
   7925    UInt inc;
   7926    UInt regs = 1;
   7927 
   7928    if (isT) {
   7929       vassert(condT != IRTemp_INVALID);
   7930    } else {
   7931       vassert(condT == IRTemp_INVALID);
   7932    }
   7933    /* So now, if condT is not IRTemp_INVALID, we know we're
   7934       dealing with Thumb code. */
   7935 
   7936    if (INSN(20,20) != 0)
   7937       return False;
   7938 
   7939    IRTemp initialRn = newTemp(Ity_I32);
   7940    assign(initialRn, isT ? getIRegT(rN) : getIRegA(rN));
   7941 
   7942    IRTemp initialRm = newTemp(Ity_I32);
   7943    assign(initialRm, isT ? getIRegT(rM) : getIRegA(rM));
   7944 
   7945    if (A) {
   7946       N = B & 3;
   7947       if ((B >> 2) < 3) {
   7948          /* VSTn / VLDn (n-element structure from/to one lane) */
   7949 
   7950          size = B >> 2;
   7951 
   7952          switch (size) {
   7953             case 0: i = INSN(7,5); inc = 1; break;
   7954             case 1: i = INSN(7,6); inc = INSN(5,5) ? 2 : 1; break;
   7955             case 2: i = INSN(7,7); inc = INSN(6,6) ? 2 : 1; break;
   7956             case 3: return False;
   7957             default: vassert(0);
   7958          }
   7959 
   7960          IRTemp addr = newTemp(Ity_I32);
   7961          assign(addr, mkexpr(initialRn));
   7962 
   7963          // go uncond
   7964          if (condT != IRTemp_INVALID)
   7965             mk_skip_over_T32_if_cond_is_false(condT);
   7966          // now uncond
   7967 
   7968          if (L)
   7969             mk_neon_elem_load_to_one_lane(rD, inc, i, N, size, addr);
   7970          else
   7971             mk_neon_elem_store_from_one_lane(rD, inc, i, N, size, addr);
   7972          DIP("v%s%u.%u {", L ? "ld" : "st", N + 1, 8 << size);
   7973          for (j = 0; j <= N; j++) {
   7974             if (j)
   7975                DIP(", ");
   7976             DIP("d%u[%u]", rD + j * inc, i);
   7977          }
   7978          DIP("}, [r%u]", rN);
   7979          if (rM != 13 && rM != 15) {
   7980             DIP(", r%u\n", rM);
   7981          } else {
   7982             DIP("%s\n", (rM != 15) ? "!" : "");
   7983          }
   7984       } else {
   7985          /* VLDn (single element to all lanes) */
   7986          UInt r;
   7987          if (L == 0)
   7988             return False;
   7989 
   7990          inc = INSN(5,5) + 1;
   7991          size = INSN(7,6);
   7992 
   7993          /* size == 3 and size == 2 cases differ in alignment constraints */
   7994          if (size == 3 && N == 3 && INSN(4,4) == 1)
   7995             size = 2;
   7996 
   7997          if (size == 0 && N == 0 && INSN(4,4) == 1)
   7998             return False;
   7999          if (N == 2 && INSN(4,4) == 1)
   8000             return False;
   8001          if (size == 3)
   8002             return False;
   8003 
   8004          // go uncond
   8005          if (condT != IRTemp_INVALID)
   8006             mk_skip_over_T32_if_cond_is_false(condT);
   8007          // now uncond
   8008 
   8009          IRTemp addr = newTemp(Ity_I32);
   8010          assign(addr, mkexpr(initialRn));
   8011 
   8012          if (N == 0 && INSN(5,5))
   8013             regs = 2;
   8014 
   8015          for (r = 0; r < regs; r++) {
   8016             switch (size) {
   8017                case 0:
   8018                   putDRegI64(rD + r, unop(Iop_Dup8x8,
   8019                                           loadLE(Ity_I8, mkexpr(addr))),
   8020                              IRTemp_INVALID);
   8021                   break;
   8022                case 1:
   8023                   putDRegI64(rD + r, unop(Iop_Dup16x4,
   8024                                           loadLE(Ity_I16, mkexpr(addr))),
   8025                              IRTemp_INVALID);
   8026                   break;
   8027                case 2:
   8028                   putDRegI64(rD + r, unop(Iop_Dup32x2,
   8029                                           loadLE(Ity_I32, mkexpr(addr))),
   8030                              IRTemp_INVALID);
   8031                   break;
   8032                default:
   8033                   vassert(0);
   8034             }
   8035             for (i = 1; i <= N; i++) {
   8036                switch (size) {
   8037                   case 0:
   8038                      putDRegI64(rD + r + i * inc,
   8039                                 unop(Iop_Dup8x8,
   8040                                      loadLE(Ity_I8, binop(Iop_Add32,
   8041                                                           mkexpr(addr),
   8042                                                           mkU32(i * 1)))),
   8043                                 IRTemp_INVALID);
   8044                      break;
   8045                   case 1:
   8046                      putDRegI64(rD + r + i * inc,
   8047                                 unop(Iop_Dup16x4,
   8048                                      loadLE(Ity_I16, binop(Iop_Add32,
   8049                                                            mkexpr(addr),
   8050                                                            mkU32(i * 2)))),
   8051                                 IRTemp_INVALID);
   8052                      break;
   8053                   case 2:
   8054                      putDRegI64(rD + r + i * inc,
   8055                                 unop(Iop_Dup32x2,
   8056                                      loadLE(Ity_I32, binop(Iop_Add32,
   8057                                                            mkexpr(addr),
   8058                                                            mkU32(i * 4)))),
   8059                                 IRTemp_INVALID);
   8060                      break;
   8061                   default:
   8062                      vassert(0);
   8063                }
   8064             }
   8065          }
   8066          DIP("vld%u.%u {", N + 1, 8 << size);
   8067          for (r = 0; r < regs; r++) {
   8068             for (i = 0; i <= N; i++) {
   8069                if (i || r)
   8070                   DIP(", ");
   8071                DIP("d%u[]", rD + r + i * inc);
   8072             }
   8073          }
   8074          DIP("}, [r%u]", rN);
   8075          if (rM != 13 && rM != 15) {
   8076             DIP(", r%u\n", rM);
   8077          } else {
   8078             DIP("%s\n", (rM != 15) ? "!" : "");
   8079          }
   8080       }
   8081       /* Writeback.  We're uncond here, so no condT-ing. */
   8082       if (rM != 15) {
   8083          if (rM == 13) {
   8084             IRExpr* e = binop(Iop_Add32,
   8085                               mkexpr(initialRn),
   8086                               mkU32((1 << size) * (N + 1)));
   8087             if (isT)
   8088                putIRegT(rN, e, IRTemp_INVALID);
   8089             else
   8090                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8091          } else {
   8092             IRExpr* e = binop(Iop_Add32,
   8093                               mkexpr(initialRn),
   8094                               mkexpr(initialRm));
   8095             if (isT)
   8096                putIRegT(rN, e, IRTemp_INVALID);
   8097             else
   8098                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8099          }
   8100       }
   8101       return True;
   8102    } else {
   8103       IRTemp tmp;
   8104       UInt r, elems;
   8105       /* VSTn / VLDn (multiple n-element structures) */
   8106       if (B == BITS4(0,0,1,0) || B == BITS4(0,1,1,0)
   8107           || B == BITS4(0,1,1,1) || B == BITS4(1,0,1,0)) {
   8108          N = 0;
   8109       } else if (B == BITS4(0,0,1,1) || B == BITS4(1,0,0,0)
   8110                  || B == BITS4(1,0,0,1)) {
   8111          N = 1;
   8112       } else if (B == BITS4(0,1,0,0) || B == BITS4(0,1,0,1)) {
   8113          N = 2;
   8114       } else if (B == BITS4(0,0,0,0) || B == BITS4(0,0,0,1)) {
   8115          N = 3;
   8116       } else {
   8117          return False;
   8118       }
   8119       inc = (B & 1) + 1;
   8120       if (N == 1 && B == BITS4(0,0,1,1)) {
   8121          regs = 2;
   8122       } else if (N == 0) {
   8123          if (B == BITS4(1,0,1,0)) {
   8124             regs = 2;
   8125          } else if (B == BITS4(0,1,1,0)) {
   8126             regs = 3;
   8127          } else if (B == BITS4(0,0,1,0)) {
   8128             regs = 4;
   8129          }
   8130       }
   8131 
   8132       size = INSN(7,6);
   8133       if (N == 0 && size == 3)
   8134          size = 2;
   8135       if (size == 3)
   8136          return False;
   8137 
   8138       elems = 8 / (1 << size);
   8139 
   8140       // go uncond
   8141       if (condT != IRTemp_INVALID)
   8142          mk_skip_over_T32_if_cond_is_false(condT);
   8143       // now uncond
   8144 
   8145       IRTemp addr = newTemp(Ity_I32);
   8146       assign(addr, mkexpr(initialRn));
   8147 
   8148       for (r = 0; r < regs; r++) {
   8149          for (i = 0; i < elems; i++) {
   8150             if (L)
   8151                mk_neon_elem_load_to_one_lane(rD + r, inc, i, N, size, addr);
   8152             else
   8153                mk_neon_elem_store_from_one_lane(rD + r, inc, i, N, size, addr);
   8154             tmp = newTemp(Ity_I32);
   8155             assign(tmp, binop(Iop_Add32, mkexpr(addr),
   8156                                          mkU32((1 << size) * (N + 1))));
   8157             addr = tmp;
   8158          }
   8159       }
   8160       /* Writeback */
   8161       if (rM != 15) {
   8162          if (rM == 13) {
   8163             IRExpr* e = binop(Iop_Add32,
   8164                               mkexpr(initialRn),
   8165                               mkU32(8 * (N + 1) * regs));
   8166             if (isT)
   8167                putIRegT(rN, e, IRTemp_INVALID);
   8168             else
   8169                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8170          } else {
   8171             IRExpr* e = binop(Iop_Add32,
   8172                               mkexpr(initialRn),
   8173                               mkexpr(initialRm));
   8174             if (isT)
   8175                putIRegT(rN, e, IRTemp_INVALID);
   8176             else
   8177                putIRegA(rN, e, IRTemp_INVALID, Ijk_Boring);
   8178          }
   8179       }
   8180       DIP("v%s%u.%u {", L ? "ld" : "st", N + 1, 8 << INSN(7,6));
   8181       if ((inc == 1 && regs * (N + 1) > 1)
   8182           || (inc == 2 && regs > 1 && N > 0)) {
   8183          DIP("d%u-d%u", rD, rD + regs * (N + 1) - 1);
   8184       } else {
   8185          for (r = 0; r < regs; r++) {
   8186             for (i = 0; i <= N; i++) {
   8187                if (i || r)
   8188                   DIP(", ");
   8189                DIP("d%u", rD + r + i * inc);
   8190             }
   8191          }
   8192       }
   8193       DIP("}, [r%u]", rN);
   8194       if (rM != 13 && rM != 15) {
   8195          DIP(", r%u\n", rM);
   8196       } else {
   8197          DIP("%s\n", (rM != 15) ? "!" : "");
   8198       }
   8199       return True;
   8200    }
   8201 #  undef INSN
   8202 }
   8203 
   8204 
   8205 /*------------------------------------------------------------*/
   8206 /*--- NEON, top level control                              ---*/
   8207 /*------------------------------------------------------------*/
   8208 
   8209 /* Both ARM and Thumb */
   8210 
   8211 /* Translate a NEON instruction.    If successful, returns
   8212    True and *dres may or may not be updated.  If failure, returns
   8213    False and doesn't change *dres nor create any IR.
   8214 
   8215    The Thumb and ARM encodings are similar for the 24 bottom bits, but
   8216    the top 8 bits are slightly different.  In both cases, the caller
   8217    must pass the entire 32 bits.  Callers may pass any instruction;
   8218    this ignores non-NEON ones.
   8219 
   8220    Caller must supply an IRTemp 'condT' holding the gating condition,
   8221    or IRTemp_INVALID indicating the insn is always executed.  In ARM
   8222    code, this must always be IRTemp_INVALID because NEON insns are
   8223    unconditional for ARM.
   8224 
   8225    Finally, the caller must indicate whether this occurs in ARM or in
   8226    Thumb code.
   8227 */
   8228 static Bool decode_NEON_instruction (
   8229                /*MOD*/DisResult* dres,
   8230                UInt              insn32,
   8231                IRTemp            condT,
   8232                Bool              isT
   8233             )
   8234 {
   8235 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn32, (_bMax), (_bMin))
   8236 
   8237    /* There are two kinds of instruction to deal with: load/store and
   8238       data processing.  In each case, in ARM mode we merely identify
   8239       the kind, and pass it on to the relevant sub-handler.  In Thumb
   8240       mode we identify the kind, swizzle the bits around to make it
   8241       have the same encoding as in ARM, and hand it on to the
   8242       sub-handler.
   8243    */
   8244 
   8245    /* In ARM mode, NEON instructions can't be conditional. */
   8246    if (!isT)
   8247       vassert(condT == IRTemp_INVALID);
   8248 
   8249    /* Data processing:
   8250       Thumb: 111U 1111 AAAA Axxx xxxx BBBB CCCC xxxx
   8251       ARM:   1111 001U AAAA Axxx xxxx BBBB CCCC xxxx
   8252    */
   8253    if (!isT && INSN(31,25) == BITS7(1,1,1,1,0,0,1)) {
   8254       // ARM, DP
   8255       return dis_neon_data_processing(INSN(31,0), condT);
   8256    }
   8257    if (isT && INSN(31,29) == BITS3(1,1,1)
   8258        && INSN(27,24) == BITS4(1,1,1,1)) {
   8259       // Thumb, DP
   8260       UInt reformatted = INSN(23,0);
   8261       reformatted |= (INSN(28,28) << 24); // U bit
   8262       reformatted |= (BITS7(1,1,1,1,0,0,1) << 25);
   8263       return dis_neon_data_processing(reformatted, condT);
   8264    }
   8265 
   8266    /* Load/store:
   8267       Thumb: 1111 1001 AxL0 xxxx xxxx BBBB xxxx xxxx
   8268       ARM:   1111 0100 AxL0 xxxx xxxx BBBB xxxx xxxx
   8269    */
   8270    if (!isT && INSN(31,24) == BITS8(1,1,1,1,0,1,0,0)) {
   8271       // ARM, memory
   8272       return dis_neon_elem_or_struct_load(INSN(31,0), isT, condT);
   8273    }
   8274    if (isT && INSN(31,24) == BITS8(1,1,1,1,1,0,0,1)) {
   8275       UInt reformatted = INSN(23,0);
   8276       reformatted |= (BITS8(1,1,1,1,0,1,0,0) << 24);
   8277       return dis_neon_elem_or_struct_load(reformatted, isT, condT);
   8278    }
   8279 
   8280    /* Doesn't match. */
   8281    return False;
   8282 
   8283 #  undef INSN
   8284 }
   8285 
   8286 
   8287 /*------------------------------------------------------------*/
   8288 /*--- V6 MEDIA instructions                                ---*/
   8289 /*------------------------------------------------------------*/
   8290 
   8291 /* Both ARM and Thumb */
   8292 
   8293 /* Translate a V6 media instruction.    If successful, returns
   8294    True and *dres may or may not be updated.  If failure, returns
   8295    False and doesn't change *dres nor create any IR.
   8296 
   8297    The Thumb and ARM encodings are completely different.  In Thumb
   8298    mode, the caller must pass the entire 32 bits.  In ARM mode it must
   8299    pass the lower 28 bits.  Apart from that, callers may pass any
   8300    instruction; this function ignores anything it doesn't recognise.
   8301 
   8302    Caller must supply an IRTemp 'condT' holding the gating condition,
   8303    or IRTemp_INVALID indicating the insn is always executed.
   8304 
   8305    Caller must also supply an ARMCondcode 'cond'.  This is only used
   8306    for debug printing, no other purpose.  For ARM, this is simply the
   8307    top 4 bits of the original instruction.  For Thumb, the condition
   8308    is not (really) known until run time, and so ARMCondAL should be
   8309    passed, only so that printing of these instructions does not show
   8310    any condition.
   8311 
   8312    Finally, the caller must indicate whether this occurs in ARM or in
   8313    Thumb code.
   8314 */
   8315 static Bool decode_V6MEDIA_instruction (
   8316                /*MOD*/DisResult* dres,
   8317                UInt              insnv6m,
   8318                IRTemp            condT,
   8319                ARMCondcode       conq,
   8320                Bool              isT
   8321             )
   8322 {
   8323 #  define INSNA(_bMax,_bMin)   SLICE_UInt(insnv6m, (_bMax), (_bMin))
   8324 #  define INSNT0(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 16) & 0xFFFF), \
   8325                                            (_bMax), (_bMin) )
   8326 #  define INSNT1(_bMax,_bMin)  SLICE_UInt( ((insnv6m >> 0)  & 0xFFFF), \
   8327                                            (_bMax), (_bMin) )
   8328    HChar dis_buf[128];
   8329    dis_buf[0] = 0;
   8330 
   8331    if (isT) {
   8332       vassert(conq == ARMCondAL);
   8333    } else {
   8334       vassert(INSNA(31,28) == BITS4(0,0,0,0)); // caller's obligation
   8335       vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
   8336    }
   8337 
   8338    /* ----------- smulbb, smulbt, smultb, smultt ----------- */
   8339    {
   8340      UInt regD = 99, regM = 99, regN = 99, bitM = 0, bitN = 0;
   8341      Bool gate = False;
   8342 
   8343      if (isT) {
   8344         if (INSNT0(15,4) == 0xFB1 && INSNT1(15,12) == BITS4(1,1,1,1)
   8345             && INSNT1(7,6) == BITS2(0,0)) {
   8346            regD = INSNT1(11,8);
   8347            regM = INSNT1(3,0);
   8348            regN = INSNT0(3,0);
   8349            bitM = INSNT1(4,4);
   8350            bitN = INSNT1(5,5);
   8351            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8352               gate = True;
   8353         }
   8354      } else {
   8355         if (BITS8(0,0,0,1,0,1,1,0) == INSNA(27,20) &&
   8356             BITS4(0,0,0,0)         == INSNA(15,12) &&
   8357             BITS4(1,0,0,0)         == (INSNA(7,4) & BITS4(1,0,0,1)) ) {
   8358            regD = INSNA(19,16);
   8359            regM = INSNA(11,8);
   8360            regN = INSNA(3,0);
   8361            bitM = INSNA(6,6);
   8362            bitN = INSNA(5,5);
   8363            if (regD != 15 && regN != 15 && regM != 15)
   8364               gate = True;
   8365         }
   8366      }
   8367 
   8368      if (gate) {
   8369         IRTemp srcN = newTemp(Ity_I32);
   8370         IRTemp srcM = newTemp(Ity_I32);
   8371         IRTemp res  = newTemp(Ity_I32);
   8372 
   8373         assign( srcN, binop(Iop_Sar32,
   8374                             binop(Iop_Shl32,
   8375                                   isT ? getIRegT(regN) : getIRegA(regN),
   8376                                   mkU8(bitN ? 0 : 16)), mkU8(16)) );
   8377         assign( srcM, binop(Iop_Sar32,
   8378                             binop(Iop_Shl32,
   8379                                   isT ? getIRegT(regM) : getIRegA(regM),
   8380                                   mkU8(bitM ? 0 : 16)), mkU8(16)) );
   8381         assign( res, binop(Iop_Mul32, mkexpr(srcN), mkexpr(srcM)) );
   8382 
   8383         if (isT)
   8384            putIRegT( regD, mkexpr(res), condT );
   8385         else
   8386            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8387 
   8388         DIP( "smul%c%c%s r%u, r%u, r%u\n", bitN ? 't' : 'b', bitM ? 't' : 'b',
   8389              nCC(conq), regD, regN, regM );
   8390         return True;
   8391      }
   8392      /* fall through */
   8393    }
   8394 
   8395    /* ------------ smulwb<y><c> <Rd>,<Rn>,<Rm> ------------- */
   8396    /* ------------ smulwt<y><c> <Rd>,<Rn>,<Rm> ------------- */
   8397    {
   8398      UInt regD = 99, regN = 99, regM = 99, bitM = 0;
   8399      Bool gate = False;
   8400 
   8401      if (isT) {
   8402         if (INSNT0(15,4) == 0xFB3 && INSNT1(15,12) == BITS4(1,1,1,1)
   8403             && INSNT1(7,5) == BITS3(0,0,0)) {
   8404           regN = INSNT0(3,0);
   8405           regD = INSNT1(11,8);
   8406           regM = INSNT1(3,0);
   8407           bitM = INSNT1(4,4);
   8408           if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8409              gate = True;
   8410         }
   8411      } else {
   8412         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
   8413             INSNA(15,12) == BITS4(0,0,0,0)         &&
   8414             (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,1,0)) {
   8415            regD = INSNA(19,16);
   8416            regN = INSNA(3,0);
   8417            regM = INSNA(11,8);
   8418            bitM = INSNA(6,6);
   8419            if (regD != 15 && regN != 15 && regM != 15)
   8420               gate = True;
   8421         }
   8422      }
   8423 
   8424      if (gate) {
   8425         IRTemp irt_prod = newTemp(Ity_I64);
   8426 
   8427         assign( irt_prod,
   8428                 binop(Iop_MullS32,
   8429                       isT ? getIRegT(regN) : getIRegA(regN),
   8430                       binop(Iop_Sar32,
   8431                             binop(Iop_Shl32,
   8432                                   isT ? getIRegT(regM) : getIRegA(regM),
   8433                                   mkU8(bitM ? 0 : 16)),
   8434                             mkU8(16))) );
   8435 
   8436         IRExpr* ire_result = binop(Iop_Or32,
   8437                                    binop( Iop_Shl32,
   8438                                           unop(Iop_64HIto32, mkexpr(irt_prod)),
   8439                                           mkU8(16) ),
   8440                                    binop( Iop_Shr32,
   8441                                           unop(Iop_64to32, mkexpr(irt_prod)),
   8442                                           mkU8(16) ) );
   8443 
   8444         if (isT)
   8445            putIRegT( regD, ire_result, condT );
   8446         else
   8447            putIRegA( regD, ire_result, condT, Ijk_Boring );
   8448 
   8449         DIP("smulw%c%s r%u, r%u, r%u\n",
   8450             bitM ? 't' : 'b', nCC(conq),regD,regN,regM);
   8451         return True;
   8452      }
   8453      /* fall through */
   8454    }
   8455 
   8456    /* ------------ pkhbt<c> Rd, Rn, Rm {,LSL #imm} ------------- */
   8457    /* ------------ pkhtb<c> Rd, Rn, Rm {,ASR #imm} ------------- */
   8458    {
   8459      UInt regD = 99, regN = 99, regM = 99, imm5 = 99, shift_type = 99;
   8460      Bool tbform = False;
   8461      Bool gate = False;
   8462 
   8463      if (isT) {
   8464         if (INSNT0(15,4) == 0xEAC
   8465             && INSNT1(15,15) == 0 && INSNT1(4,4) == 0) {
   8466            regN = INSNT0(3,0);
   8467            regD = INSNT1(11,8);
   8468            regM = INSNT1(3,0);
   8469            imm5 = (INSNT1(14,12) << 2) | INSNT1(7,6);
   8470            shift_type = (INSNT1(5,5) << 1) | 0;
   8471            tbform = (INSNT1(5,5) == 0) ? False : True;
   8472            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8473               gate = True;
   8474         }
   8475      } else {
   8476         if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
   8477             INSNA(5,4)   == BITS2(0,1)             &&
   8478             (INSNA(6,6)  == 0 || INSNA(6,6) == 1) ) {
   8479            regD = INSNA(15,12);
   8480            regN = INSNA(19,16);
   8481            regM = INSNA(3,0);
   8482            imm5 = INSNA(11,7);
   8483            shift_type = (INSNA(6,6) << 1) | 0;
   8484            tbform = (INSNA(6,6) == 0) ? False : True;
   8485            if (regD != 15 && regN != 15 && regM != 15)
   8486               gate = True;
   8487         }
   8488      }
   8489 
   8490      if (gate) {
   8491         IRTemp irt_regM       = newTemp(Ity_I32);
   8492         IRTemp irt_regM_shift = newTemp(Ity_I32);
   8493         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   8494         compute_result_and_C_after_shift_by_imm5(
   8495            dis_buf, &irt_regM_shift, NULL, irt_regM, shift_type, imm5, regM );
   8496 
   8497         UInt mask = (tbform == True) ? 0x0000FFFF : 0xFFFF0000;
   8498         IRExpr* ire_result
   8499           = binop( Iop_Or32,
   8500                    binop(Iop_And32, mkexpr(irt_regM_shift), mkU32(mask)),
   8501                    binop(Iop_And32, isT ? getIRegT(regN) : getIRegA(regN),
   8502                                     unop(Iop_Not32, mkU32(mask))) );
   8503 
   8504         if (isT)
   8505            putIRegT( regD, ire_result, condT );
   8506         else
   8507            putIRegA( regD, ire_result, condT, Ijk_Boring );
   8508 
   8509         DIP( "pkh%s%s r%u, r%u, r%u %s\n", tbform ? "tb" : "bt",
   8510              nCC(conq), regD, regN, regM, dis_buf );
   8511 
   8512         return True;
   8513      }
   8514      /* fall through */
   8515    }
   8516 
   8517    /* ---------- usat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
   8518    {
   8519      UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
   8520      Bool gate = False;
   8521 
   8522      if (isT) {
   8523         if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,1,0)
   8524             && INSNT0(4,4) == 0
   8525             && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
   8526            regD       = INSNT1(11,8);
   8527            regN       = INSNT0(3,0);
   8528            shift_type = (INSNT0(5,5) << 1) | 0;
   8529            imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
   8530            sat_imm    = INSNT1(4,0);
   8531            if (!isBadRegT(regD) && !isBadRegT(regN))
   8532               gate = True;
   8533            if (shift_type == BITS2(1,0) && imm5 == 0)
   8534               gate = False;
   8535         }
   8536      } else {
   8537         if (INSNA(27,21) == BITS7(0,1,1,0,1,1,1) &&
   8538             INSNA(5,4)   == BITS2(0,1)) {
   8539            regD       = INSNA(15,12);
   8540            regN       = INSNA(3,0);
   8541            shift_type = (INSNA(6,6) << 1) | 0;
   8542            imm5       = INSNA(11,7);
   8543            sat_imm    = INSNA(20,16);
   8544            if (regD != 15 && regN != 15)
   8545               gate = True;
   8546         }
   8547      }
   8548 
   8549      if (gate) {
   8550         IRTemp irt_regN       = newTemp(Ity_I32);
   8551         IRTemp irt_regN_shift = newTemp(Ity_I32);
   8552         IRTemp irt_sat_Q      = newTemp(Ity_I32);
   8553         IRTemp irt_result     = newTemp(Ity_I32);
   8554 
   8555         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   8556         compute_result_and_C_after_shift_by_imm5(
   8557                 dis_buf, &irt_regN_shift, NULL,
   8558                 irt_regN, shift_type, imm5, regN );
   8559 
   8560         armUnsignedSatQ( &irt_result, &irt_sat_Q, irt_regN_shift, sat_imm );
   8561         or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
   8562 
   8563         if (isT)
   8564            putIRegT( regD, mkexpr(irt_result), condT );
   8565         else
   8566            putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
   8567 
   8568         DIP("usat%s r%u, #0x%04x, %s\n",
   8569             nCC(conq), regD, imm5, dis_buf);
   8570         return True;
   8571      }
   8572      /* fall through */
   8573    }
   8574 
   8575   /* ----------- ssat<c> <Rd>,#<imm5>,<Rn>{,<shift>} ----------- */
   8576    {
   8577      UInt regD = 99, regN = 99, shift_type = 99, imm5 = 99, sat_imm = 99;
   8578      Bool gate = False;
   8579 
   8580      if (isT) {
   8581         if (INSNT0(15,6) == BITS10(1,1,1,1,0,0,1,1,0,0)
   8582             && INSNT0(4,4) == 0
   8583             && INSNT1(15,15) == 0 && INSNT1(5,5) == 0) {
   8584            regD       = INSNT1(11,8);
   8585            regN       = INSNT0(3,0);
   8586            shift_type = (INSNT0(5,5) << 1) | 0;
   8587            imm5       = (INSNT1(14,12) << 2) | INSNT1(7,6);
   8588            sat_imm    = INSNT1(4,0) + 1;
   8589            if (!isBadRegT(regD) && !isBadRegT(regN))
   8590               gate = True;
   8591            if (shift_type == BITS2(1,0) && imm5 == 0)
   8592               gate = False;
   8593         }
   8594      } else {
   8595         if (INSNA(27,21) == BITS7(0,1,1,0,1,0,1) &&
   8596             INSNA(5,4)   == BITS2(0,1)) {
   8597            regD       = INSNA(15,12);
   8598            regN       = INSNA(3,0);
   8599            shift_type = (INSNA(6,6) << 1) | 0;
   8600            imm5       = INSNA(11,7);
   8601            sat_imm    = INSNA(20,16) + 1;
   8602            if (regD != 15 && regN != 15)
   8603               gate = True;
   8604         }
   8605      }
   8606 
   8607      if (gate) {
   8608         IRTemp irt_regN       = newTemp(Ity_I32);
   8609         IRTemp irt_regN_shift = newTemp(Ity_I32);
   8610         IRTemp irt_sat_Q      = newTemp(Ity_I32);
   8611         IRTemp irt_result     = newTemp(Ity_I32);
   8612 
   8613         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   8614         compute_result_and_C_after_shift_by_imm5(
   8615                 dis_buf, &irt_regN_shift, NULL,
   8616                 irt_regN, shift_type, imm5, regN );
   8617 
   8618         armSignedSatQ( irt_regN_shift, sat_imm, &irt_result, &irt_sat_Q );
   8619         or_into_QFLAG32( mkexpr(irt_sat_Q), condT );
   8620 
   8621         if (isT)
   8622            putIRegT( regD, mkexpr(irt_result), condT );
   8623         else
   8624            putIRegA( regD, mkexpr(irt_result), condT, Ijk_Boring );
   8625 
   8626         DIP( "ssat%s r%u, #0x%04x, %s\n",
   8627              nCC(conq), regD, imm5, dis_buf);
   8628         return True;
   8629     }
   8630     /* fall through */
   8631   }
   8632 
   8633    /* -------------- usat16<c> <Rd>,#<imm4>,<Rn> --------------- */
   8634    {
   8635      UInt regD = 99, regN = 99, sat_imm = 99;
   8636      Bool gate = False;
   8637 
   8638      if (isT) {
   8639         if (INSNT0(15,4) == 0xF3A && (INSNT1(15,0) & 0xF0F0) == 0x0000) {
   8640            regN = INSNT0(3,0);
   8641            regD = INSNT1(11,8);
   8642            sat_imm = INSNT1(3,0);
   8643            if (!isBadRegT(regD) && !isBadRegT(regN))
   8644               gate = True;
   8645        }
   8646      } else {
   8647         if (INSNA(27,20) == BITS8(0,1,1,0,1,1,1,0) &&
   8648             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8649             INSNA(7,4)   == BITS4(0,0,1,1)) {
   8650            regD    = INSNA(15,12);
   8651            regN    = INSNA(3,0);
   8652            sat_imm = INSNA(19,16);
   8653            if (regD != 15 && regN != 15)
   8654               gate = True;
   8655         }
   8656      }
   8657 
   8658      if (gate) {
   8659         IRTemp irt_regN    = newTemp(Ity_I32);
   8660         IRTemp irt_regN_lo = newTemp(Ity_I32);
   8661         IRTemp irt_regN_hi = newTemp(Ity_I32);
   8662         IRTemp irt_Q_lo    = newTemp(Ity_I32);
   8663         IRTemp irt_Q_hi    = newTemp(Ity_I32);
   8664         IRTemp irt_res_lo  = newTemp(Ity_I32);
   8665         IRTemp irt_res_hi  = newTemp(Ity_I32);
   8666 
   8667         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   8668         assign( irt_regN_lo, binop( Iop_Sar32,
   8669                                     binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
   8670                                     mkU8(16)) );
   8671         assign( irt_regN_hi, binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)) );
   8672 
   8673         armUnsignedSatQ( &irt_res_lo, &irt_Q_lo, irt_regN_lo, sat_imm );
   8674         or_into_QFLAG32( mkexpr(irt_Q_lo), condT );
   8675 
   8676         armUnsignedSatQ( &irt_res_hi, &irt_Q_hi, irt_regN_hi, sat_imm );
   8677         or_into_QFLAG32( mkexpr(irt_Q_hi), condT );
   8678 
   8679         IRExpr* ire_result = binop( Iop_Or32,
   8680                                     binop(Iop_Shl32, mkexpr(irt_res_hi), mkU8(16)),
   8681                                     mkexpr(irt_res_lo) );
   8682 
   8683         if (isT)
   8684            putIRegT( regD, ire_result, condT );
   8685         else
   8686            putIRegA( regD, ire_result, condT, Ijk_Boring );
   8687 
   8688         DIP( "usat16%s r%u, #0x%04x, r%u\n", nCC(conq), regD, sat_imm, regN );
   8689         return True;
   8690      }
   8691      /* fall through */
   8692    }
   8693 
   8694    /* -------------- uadd16<c> <Rd>,<Rn>,<Rm> -------------- */
   8695    {
   8696      UInt regD = 99, regN = 99, regM = 99;
   8697      Bool gate = False;
   8698 
   8699      if (isT) {
   8700         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   8701            regN = INSNT0(3,0);
   8702            regD = INSNT1(11,8);
   8703            regM = INSNT1(3,0);
   8704            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8705               gate = True;
   8706         }
   8707      } else {
   8708         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   8709             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8710             INSNA(7,4)   == BITS4(0,0,0,1)) {
   8711            regD = INSNA(15,12);
   8712            regN = INSNA(19,16);
   8713            regM = INSNA(3,0);
   8714            if (regD != 15 && regN != 15 && regM != 15)
   8715               gate = True;
   8716         }
   8717      }
   8718 
   8719      if (gate) {
   8720         IRTemp rNt  = newTemp(Ity_I32);
   8721         IRTemp rMt  = newTemp(Ity_I32);
   8722         IRTemp res  = newTemp(Ity_I32);
   8723         IRTemp reso = newTemp(Ity_I32);
   8724 
   8725         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8726         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8727 
   8728         assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
   8729         if (isT)
   8730            putIRegT( regD, mkexpr(res), condT );
   8731         else
   8732            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8733 
   8734         assign(reso, binop(Iop_HAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
   8735         set_GE_32_10_from_bits_31_15(reso, condT);
   8736 
   8737         DIP("uadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8738         return True;
   8739      }
   8740      /* fall through */
   8741    }
   8742 
   8743    /* -------------- sadd16<c> <Rd>,<Rn>,<Rm> -------------- */
   8744    {
   8745      UInt regD = 99, regN = 99, regM = 99;
   8746      Bool gate = False;
   8747 
   8748      if (isT) {
   8749         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   8750            regN = INSNT0(3,0);
   8751            regD = INSNT1(11,8);
   8752            regM = INSNT1(3,0);
   8753            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8754               gate = True;
   8755         }
   8756      } else {
   8757         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   8758             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8759             INSNA(7,4)   == BITS4(0,0,0,1)) {
   8760            regD = INSNA(15,12);
   8761            regN = INSNA(19,16);
   8762            regM = INSNA(3,0);
   8763            if (regD != 15 && regN != 15 && regM != 15)
   8764               gate = True;
   8765         }
   8766      }
   8767 
   8768      if (gate) {
   8769         IRTemp rNt  = newTemp(Ity_I32);
   8770         IRTemp rMt  = newTemp(Ity_I32);
   8771         IRTemp res  = newTemp(Ity_I32);
   8772         IRTemp reso = newTemp(Ity_I32);
   8773 
   8774         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8775         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8776 
   8777         assign(res, binop(Iop_Add16x2, mkexpr(rNt), mkexpr(rMt)));
   8778         if (isT)
   8779            putIRegT( regD, mkexpr(res), condT );
   8780         else
   8781            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8782 
   8783         assign(reso, unop(Iop_Not32,
   8784                           binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt))));
   8785         set_GE_32_10_from_bits_31_15(reso, condT);
   8786 
   8787         DIP("sadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8788         return True;
   8789      }
   8790      /* fall through */
   8791    }
   8792 
   8793    /* ---------------- usub16<c> <Rd>,<Rn>,<Rm> ---------------- */
   8794    {
   8795      UInt regD = 99, regN = 99, regM = 99;
   8796      Bool gate = False;
   8797 
   8798      if (isT) {
   8799         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   8800            regN = INSNT0(3,0);
   8801            regD = INSNT1(11,8);
   8802            regM = INSNT1(3,0);
   8803            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8804               gate = True;
   8805         }
   8806      } else {
   8807         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   8808             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8809             INSNA(7,4)   == BITS4(0,1,1,1)) {
   8810            regD = INSNA(15,12);
   8811            regN = INSNA(19,16);
   8812            regM = INSNA(3,0);
   8813            if (regD != 15 && regN != 15 && regM != 15)
   8814              gate = True;
   8815         }
   8816      }
   8817 
   8818      if (gate) {
   8819         IRTemp rNt  = newTemp(Ity_I32);
   8820         IRTemp rMt  = newTemp(Ity_I32);
   8821         IRTemp res  = newTemp(Ity_I32);
   8822         IRTemp reso = newTemp(Ity_I32);
   8823 
   8824         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8825         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8826 
   8827         assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
   8828         if (isT)
   8829            putIRegT( regD, mkexpr(res), condT );
   8830         else
   8831            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8832 
   8833         assign(reso, unop(Iop_Not32,
   8834                           binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt))));
   8835         set_GE_32_10_from_bits_31_15(reso, condT);
   8836 
   8837         DIP("usub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8838         return True;
   8839      }
   8840      /* fall through */
   8841    }
   8842 
   8843    /* -------------- ssub16<c> <Rd>,<Rn>,<Rm> -------------- */
   8844    {
   8845      UInt regD = 99, regN = 99, regM = 99;
   8846      Bool gate = False;
   8847 
   8848      if (isT) {
   8849         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   8850            regN = INSNT0(3,0);
   8851            regD = INSNT1(11,8);
   8852            regM = INSNT1(3,0);
   8853            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8854               gate = True;
   8855         }
   8856      } else {
   8857         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   8858             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8859             INSNA(7,4)   == BITS4(0,1,1,1)) {
   8860            regD = INSNA(15,12);
   8861            regN = INSNA(19,16);
   8862            regM = INSNA(3,0);
   8863            if (regD != 15 && regN != 15 && regM != 15)
   8864               gate = True;
   8865         }
   8866      }
   8867 
   8868      if (gate) {
   8869         IRTemp rNt  = newTemp(Ity_I32);
   8870         IRTemp rMt  = newTemp(Ity_I32);
   8871         IRTemp res  = newTemp(Ity_I32);
   8872         IRTemp reso = newTemp(Ity_I32);
   8873 
   8874         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8875         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8876 
   8877         assign(res, binop(Iop_Sub16x2, mkexpr(rNt), mkexpr(rMt)));
   8878         if (isT)
   8879            putIRegT( regD, mkexpr(res), condT );
   8880         else
   8881            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8882 
   8883         assign(reso, unop(Iop_Not32,
   8884                           binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt))));
   8885         set_GE_32_10_from_bits_31_15(reso, condT);
   8886 
   8887         DIP("ssub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8888         return True;
   8889      }
   8890      /* fall through */
   8891    }
   8892 
   8893    /* ----------------- uadd8<c> <Rd>,<Rn>,<Rm> ---------------- */
   8894    {
   8895      UInt regD = 99, regN = 99, regM = 99;
   8896      Bool gate = False;
   8897 
   8898      if (isT) {
   8899         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   8900            regN = INSNT0(3,0);
   8901            regD = INSNT1(11,8);
   8902            regM = INSNT1(3,0);
   8903            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8904               gate = True;
   8905         }
   8906      } else {
   8907         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   8908             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8909             (INSNA(7,4)  == BITS4(1,0,0,1))) {
   8910            regD = INSNA(15,12);
   8911            regN = INSNA(19,16);
   8912            regM = INSNA(3,0);
   8913            if (regD != 15 && regN != 15 && regM != 15)
   8914               gate = True;
   8915         }
   8916      }
   8917 
   8918      if (gate) {
   8919         IRTemp rNt  = newTemp(Ity_I32);
   8920         IRTemp rMt  = newTemp(Ity_I32);
   8921         IRTemp res  = newTemp(Ity_I32);
   8922         IRTemp reso = newTemp(Ity_I32);
   8923 
   8924         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8925         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8926 
   8927         assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
   8928         if (isT)
   8929            putIRegT( regD, mkexpr(res), condT );
   8930         else
   8931            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8932 
   8933         assign(reso, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
   8934         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   8935 
   8936         DIP("uadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8937         return True;
   8938      }
   8939      /* fall through */
   8940    }
   8941 
   8942    /* ------------------- sadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
   8943    {
   8944      UInt regD = 99, regN = 99, regM = 99;
   8945      Bool gate = False;
   8946 
   8947      if (isT) {
   8948         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   8949            regN = INSNT0(3,0);
   8950            regD = INSNT1(11,8);
   8951            regM = INSNT1(3,0);
   8952            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   8953               gate = True;
   8954         }
   8955      } else {
   8956         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   8957             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   8958             (INSNA(7,4)  == BITS4(1,0,0,1))) {
   8959            regD = INSNA(15,12);
   8960            regN = INSNA(19,16);
   8961            regM = INSNA(3,0);
   8962            if (regD != 15 && regN != 15 && regM != 15)
   8963               gate = True;
   8964         }
   8965      }
   8966 
   8967      if (gate) {
   8968         IRTemp rNt  = newTemp(Ity_I32);
   8969         IRTemp rMt  = newTemp(Ity_I32);
   8970         IRTemp res  = newTemp(Ity_I32);
   8971         IRTemp reso = newTemp(Ity_I32);
   8972 
   8973         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   8974         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   8975 
   8976         assign(res, binop(Iop_Add8x4, mkexpr(rNt), mkexpr(rMt)));
   8977         if (isT)
   8978            putIRegT( regD, mkexpr(res), condT );
   8979         else
   8980            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   8981 
   8982         assign(reso, unop(Iop_Not32,
   8983                           binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt))));
   8984         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   8985 
   8986         DIP("sadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   8987         return True;
   8988      }
   8989      /* fall through */
   8990    }
   8991 
   8992    /* ------------------- usub8<c> <Rd>,<Rn>,<Rm> ------------------ */
   8993    {
   8994      UInt regD = 99, regN = 99, regM = 99;
   8995      Bool gate = False;
   8996 
   8997      if (isT) {
   8998         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
   8999            regN = INSNT0(3,0);
   9000            regD = INSNT1(11,8);
   9001            regM = INSNT1(3,0);
   9002            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9003               gate = True;
   9004         }
   9005      } else {
   9006         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
   9007             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9008             (INSNA(7,4)  == BITS4(1,1,1,1))) {
   9009            regD = INSNA(15,12);
   9010            regN = INSNA(19,16);
   9011            regM = INSNA(3,0);
   9012            if (regD != 15 && regN != 15 && regM != 15)
   9013              gate = True;
   9014         }
   9015      }
   9016 
   9017      if (gate) {
   9018         IRTemp rNt  = newTemp(Ity_I32);
   9019         IRTemp rMt  = newTemp(Ity_I32);
   9020         IRTemp res  = newTemp(Ity_I32);
   9021         IRTemp reso = newTemp(Ity_I32);
   9022 
   9023         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9024         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9025 
   9026         assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
   9027         if (isT)
   9028            putIRegT( regD, mkexpr(res), condT );
   9029         else
   9030            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   9031 
   9032         assign(reso, unop(Iop_Not32,
   9033                           binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt))));
   9034         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   9035 
   9036         DIP("usub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9037         return True;
   9038      }
   9039      /* fall through */
   9040    }
   9041 
   9042    /* ------------------- ssub8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9043    {
   9044      UInt regD = 99, regN = 99, regM = 99;
   9045      Bool gate = False;
   9046 
   9047      if (isT) {
   9048         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   9049            regN = INSNT0(3,0);
   9050            regD = INSNT1(11,8);
   9051            regM = INSNT1(3,0);
   9052            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9053               gate = True;
   9054         }
   9055      } else {
   9056         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   9057             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9058             INSNA(7,4)   == BITS4(1,1,1,1)) {
   9059            regD = INSNA(15,12);
   9060            regN = INSNA(19,16);
   9061            regM = INSNA(3,0);
   9062            if (regD != 15 && regN != 15 && regM != 15)
   9063               gate = True;
   9064         }
   9065      }
   9066 
   9067      if (gate) {
   9068         IRTemp rNt  = newTemp(Ity_I32);
   9069         IRTemp rMt  = newTemp(Ity_I32);
   9070         IRTemp res  = newTemp(Ity_I32);
   9071         IRTemp reso = newTemp(Ity_I32);
   9072 
   9073         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9074         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9075 
   9076         assign(res, binop(Iop_Sub8x4, mkexpr(rNt), mkexpr(rMt)));
   9077         if (isT)
   9078            putIRegT( regD, mkexpr(res), condT );
   9079         else
   9080            putIRegA( regD, mkexpr(res), condT, Ijk_Boring );
   9081 
   9082         assign(reso, unop(Iop_Not32,
   9083                           binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt))));
   9084         set_GE_3_2_1_0_from_bits_31_23_15_7(reso, condT);
   9085 
   9086         DIP("ssub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9087         return True;
   9088      }
   9089      /* fall through */
   9090    }
   9091 
   9092    /* ------------------ qadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9093    {
   9094      UInt regD = 99, regN = 99, regM = 99;
   9095      Bool gate = False;
   9096 
   9097      if (isT) {
   9098         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9099            regN = INSNT0(3,0);
   9100            regD = INSNT1(11,8);
   9101            regM = INSNT1(3,0);
   9102            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9103               gate = True;
   9104         }
   9105      } else {
   9106         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9107             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9108             INSNA(7,4)   == BITS4(1,0,0,1)) {
   9109            regD = INSNA(15,12);
   9110            regN = INSNA(19,16);
   9111            regM = INSNA(3,0);
   9112            if (regD != 15 && regN != 15 && regM != 15)
   9113               gate = True;
   9114         }
   9115      }
   9116 
   9117      if (gate) {
   9118         IRTemp rNt   = newTemp(Ity_I32);
   9119         IRTemp rMt   = newTemp(Ity_I32);
   9120         IRTemp res_q = newTemp(Ity_I32);
   9121 
   9122         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9123         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9124 
   9125         assign(res_q, binop(Iop_QAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
   9126         if (isT)
   9127            putIRegT( regD, mkexpr(res_q), condT );
   9128         else
   9129            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9130 
   9131         DIP("qadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9132         return True;
   9133      }
   9134      /* fall through */
   9135    }
   9136 
   9137    /* ------------------ qsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9138    {
   9139      UInt regD = 99, regN = 99, regM = 99;
   9140      Bool gate = False;
   9141 
   9142      if (isT) {
   9143         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9144            regN = INSNT0(3,0);
   9145            regD = INSNT1(11,8);
   9146            regM = INSNT1(3,0);
   9147            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9148               gate = True;
   9149         }
   9150      } else {
   9151         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9152             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9153             INSNA(7,4)   == BITS4(1,1,1,1)) {
   9154            regD = INSNA(15,12);
   9155            regN = INSNA(19,16);
   9156            regM = INSNA(3,0);
   9157            if (regD != 15 && regN != 15 && regM != 15)
   9158               gate = True;
   9159         }
   9160      }
   9161 
   9162      if (gate) {
   9163         IRTemp rNt   = newTemp(Ity_I32);
   9164         IRTemp rMt   = newTemp(Ity_I32);
   9165         IRTemp res_q = newTemp(Ity_I32);
   9166 
   9167         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9168         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9169 
   9170         assign(res_q, binop(Iop_QSub8Sx4, mkexpr(rNt), mkexpr(rMt)));
   9171         if (isT)
   9172            putIRegT( regD, mkexpr(res_q), condT );
   9173         else
   9174            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9175 
   9176         DIP("qsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9177         return True;
   9178      }
   9179      /* fall through */
   9180    }
   9181 
   9182    /* ------------------ uqadd8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9183    {
   9184      UInt regD = 99, regN = 99, regM = 99;
   9185      Bool gate = False;
   9186 
   9187      if (isT) {
   9188         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
   9189            regN = INSNT0(3,0);
   9190            regD = INSNT1(11,8);
   9191            regM = INSNT1(3,0);
   9192            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9193               gate = True;
   9194         }
   9195      } else {
   9196         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
   9197             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9198             (INSNA(7,4)  == BITS4(1,0,0,1))) {
   9199            regD = INSNA(15,12);
   9200            regN = INSNA(19,16);
   9201            regM = INSNA(3,0);
   9202            if (regD != 15 && regN != 15 && regM != 15)
   9203               gate = True;
   9204         }
   9205      }
   9206 
   9207      if (gate) {
   9208         IRTemp rNt   = newTemp(Ity_I32);
   9209         IRTemp rMt   = newTemp(Ity_I32);
   9210         IRTemp res_q = newTemp(Ity_I32);
   9211 
   9212         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9213         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9214 
   9215         assign(res_q, binop(Iop_QAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
   9216         if (isT)
   9217            putIRegT( regD, mkexpr(res_q), condT );
   9218         else
   9219            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9220 
   9221         DIP("uqadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9222         return True;
   9223      }
   9224      /* fall through */
   9225    }
   9226 
   9227    /* ------------------ uqsub8<c> <Rd>,<Rn>,<Rm> ------------------ */
   9228    {
   9229      UInt regD = 99, regN = 99, regM = 99;
   9230      Bool gate = False;
   9231 
   9232      if (isT) {
   9233         if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
   9234            regN = INSNT0(3,0);
   9235            regD = INSNT1(11,8);
   9236            regM = INSNT1(3,0);
   9237            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9238               gate = True;
   9239         }
   9240      } else {
   9241         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
   9242             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9243             (INSNA(7,4)  == BITS4(1,1,1,1))) {
   9244            regD = INSNA(15,12);
   9245            regN = INSNA(19,16);
   9246            regM = INSNA(3,0);
   9247            if (regD != 15 && regN != 15 && regM != 15)
   9248              gate = True;
   9249         }
   9250      }
   9251 
   9252      if (gate) {
   9253         IRTemp rNt   = newTemp(Ity_I32);
   9254         IRTemp rMt   = newTemp(Ity_I32);
   9255         IRTemp res_q = newTemp(Ity_I32);
   9256 
   9257         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9258         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9259 
   9260         assign(res_q, binop(Iop_QSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
   9261         if (isT)
   9262            putIRegT( regD, mkexpr(res_q), condT );
   9263         else
   9264            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9265 
   9266         DIP("uqsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9267         return True;
   9268      }
   9269      /* fall through */
   9270    }
   9271 
   9272    /* ----------------- uhadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9273    {
   9274      UInt regD = 99, regN = 99, regM = 99;
   9275      Bool gate = False;
   9276 
   9277      if (isT) {
   9278         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
   9279            regN = INSNT0(3,0);
   9280            regD = INSNT1(11,8);
   9281            regM = INSNT1(3,0);
   9282            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9283               gate = True;
   9284         }
   9285      } else {
   9286         if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
   9287             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9288             INSNA(7,4)   == BITS4(1,0,0,1)) {
   9289            regD = INSNA(15,12);
   9290            regN = INSNA(19,16);
   9291            regM = INSNA(3,0);
   9292            if (regD != 15 && regN != 15 && regM != 15)
   9293               gate = True;
   9294         }
   9295      }
   9296 
   9297      if (gate) {
   9298         IRTemp rNt   = newTemp(Ity_I32);
   9299         IRTemp rMt   = newTemp(Ity_I32);
   9300         IRTemp res_q = newTemp(Ity_I32);
   9301 
   9302         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9303         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9304 
   9305         assign(res_q, binop(Iop_HAdd8Ux4, mkexpr(rNt), mkexpr(rMt)));
   9306         if (isT)
   9307            putIRegT( regD, mkexpr(res_q), condT );
   9308         else
   9309            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9310 
   9311         DIP("uhadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9312         return True;
   9313      }
   9314      /* fall through */
   9315    }
   9316 
   9317    /* ----------------- shadd8<c> <Rd>,<Rn>,<Rm> ------------------- */
   9318    {
   9319      UInt regD = 99, regN = 99, regM = 99;
   9320      Bool gate = False;
   9321 
   9322      if (isT) {
   9323         if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
   9324            regN = INSNT0(3,0);
   9325            regD = INSNT1(11,8);
   9326            regM = INSNT1(3,0);
   9327            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9328               gate = True;
   9329         }
   9330      } else {
   9331         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
   9332             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9333             INSNA(7,4)   == BITS4(1,0,0,1)) {
   9334            regD = INSNA(15,12);
   9335            regN = INSNA(19,16);
   9336            regM = INSNA(3,0);
   9337            if (regD != 15 && regN != 15 && regM != 15)
   9338               gate = True;
   9339         }
   9340      }
   9341 
   9342      if (gate) {
   9343         IRTemp rNt   = newTemp(Ity_I32);
   9344         IRTemp rMt   = newTemp(Ity_I32);
   9345         IRTemp res_q = newTemp(Ity_I32);
   9346 
   9347         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9348         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9349 
   9350         assign(res_q, binop(Iop_HAdd8Sx4, mkexpr(rNt), mkexpr(rMt)));
   9351         if (isT)
   9352            putIRegT( regD, mkexpr(res_q), condT );
   9353         else
   9354            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9355 
   9356         DIP("shadd8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9357         return True;
   9358      }
   9359      /* fall through */
   9360    }
   9361 
   9362    /* ------------------ qadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
   9363    {
   9364      UInt regD = 99, regN = 99, regM = 99;
   9365      Bool gate = False;
   9366 
   9367      if (isT) {
   9368         if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9369            regN = INSNT0(3,0);
   9370            regD = INSNT1(11,8);
   9371            regM = INSNT1(3,0);
   9372            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9373               gate = True;
   9374         }
   9375      } else {
   9376         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9377             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9378             INSNA(7,4)   == BITS4(0,0,0,1)) {
   9379            regD = INSNA(15,12);
   9380            regN = INSNA(19,16);
   9381            regM = INSNA(3,0);
   9382            if (regD != 15 && regN != 15 && regM != 15)
   9383               gate = True;
   9384         }
   9385      }
   9386 
   9387      if (gate) {
   9388         IRTemp rNt   = newTemp(Ity_I32);
   9389         IRTemp rMt   = newTemp(Ity_I32);
   9390         IRTemp res_q = newTemp(Ity_I32);
   9391 
   9392         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9393         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9394 
   9395         assign(res_q, binop(Iop_QAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
   9396         if (isT)
   9397            putIRegT( regD, mkexpr(res_q), condT );
   9398         else
   9399            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9400 
   9401         DIP("qadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9402         return True;
   9403      }
   9404      /* fall through */
   9405    }
   9406 
   9407    /* ------------------ qsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
   9408    {
   9409      UInt regD = 99, regN = 99, regM = 99;
   9410      Bool gate = False;
   9411 
   9412       if (isT) {
   9413         if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9414            regN = INSNT0(3,0);
   9415            regD = INSNT1(11,8);
   9416            regM = INSNT1(3,0);
   9417            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9418               gate = True;
   9419         }
   9420      } else {
   9421         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9422             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9423             INSNA(7,4)   == BITS4(0,1,1,1)) {
   9424            regD = INSNA(15,12);
   9425            regN = INSNA(19,16);
   9426            regM = INSNA(3,0);
   9427            if (regD != 15 && regN != 15 && regM != 15)
   9428              gate = True;
   9429         }
   9430      }
   9431 
   9432      if (gate) {
   9433         IRTemp rNt   = newTemp(Ity_I32);
   9434         IRTemp rMt   = newTemp(Ity_I32);
   9435         IRTemp res_q = newTemp(Ity_I32);
   9436 
   9437         assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
   9438         assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
   9439 
   9440         assign(res_q, binop(Iop_QSub16Sx2, mkexpr(rNt), mkexpr(rMt)));
   9441         if (isT)
   9442            putIRegT( regD, mkexpr(res_q), condT );
   9443         else
   9444            putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
   9445 
   9446         DIP("qsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
   9447         return True;
   9448      }
   9449      /* fall through */
   9450    }
   9451 
   9452    /////////////////////////////////////////////////////////////////
   9453    /////////////////////////////////////////////////////////////////
   9454    /////////////////////////////////////////////////////////////////
   9455    /////////////////////////////////////////////////////////////////
   9456    /////////////////////////////////////////////////////////////////
   9457 
   9458    /* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
   9459    /* note: the hardware seems to construct the result differently
   9460       from wot the manual says. */
   9461    {
   9462      UInt regD = 99, regN = 99, regM = 99;
   9463      Bool gate = False;
   9464 
   9465      if (isT) {
   9466         if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9467            regN = INSNT0(3,0);
   9468            regD = INSNT1(11,8);
   9469            regM = INSNT1(3,0);
   9470            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9471               gate = True;
   9472         }
   9473      } else {
   9474         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9475             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9476             INSNA(7,4)   == BITS4(0,1,0,1)) {
   9477            regD = INSNA(15,12);
   9478            regN = INSNA(19,16);
   9479            regM = INSNA(3,0);
   9480            if (regD != 15 && regN != 15 && regM != 15)
   9481               gate = True;
   9482         }
   9483      }
   9484 
   9485      if (gate) {
   9486         IRTemp irt_regN     = newTemp(Ity_I32);
   9487         IRTemp irt_regM     = newTemp(Ity_I32);
   9488         IRTemp irt_sum      = newTemp(Ity_I32);
   9489         IRTemp irt_diff     = newTemp(Ity_I32);
   9490         IRTemp irt_sum_res  = newTemp(Ity_I32);
   9491         IRTemp irt_diff_res = newTemp(Ity_I32);
   9492 
   9493         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9494         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   9495 
   9496         assign( irt_diff,
   9497                 binop( Iop_Sub32,
   9498                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9499                        binop( Iop_Sar32,
   9500                               binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
   9501                               mkU8(16) ) ) );
   9502         armSignedSatQ( irt_diff, 0x10, &irt_diff_res, NULL);
   9503 
   9504         assign( irt_sum,
   9505                 binop( Iop_Add32,
   9506                        binop( Iop_Sar32,
   9507                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9508                               mkU8(16) ),
   9509                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) )) );
   9510         armSignedSatQ( irt_sum, 0x10, &irt_sum_res, NULL );
   9511 
   9512         IRExpr* ire_result = binop( Iop_Or32,
   9513                                     binop( Iop_Shl32, mkexpr(irt_diff_res),
   9514                                            mkU8(16) ),
   9515                                     binop( Iop_And32, mkexpr(irt_sum_res),
   9516                                            mkU32(0xFFFF)) );
   9517 
   9518         if (isT)
   9519            putIRegT( regD, ire_result, condT );
   9520         else
   9521            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9522 
   9523         DIP( "qsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   9524         return True;
   9525      }
   9526      /* fall through */
   9527    }
   9528 
   9529    /* ------------------- qasx<c> <Rd>,<Rn>,<Rm> ------------------- */
   9530    {
   9531      UInt regD = 99, regN = 99, regM = 99;
   9532      Bool gate = False;
   9533 
   9534      if (isT) {
   9535         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF010) {
   9536            regN = INSNT0(3,0);
   9537            regD = INSNT1(11,8);
   9538            regM = INSNT1(3,0);
   9539            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9540               gate = True;
   9541         }
   9542      } else {
   9543         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,0) &&
   9544             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9545             INSNA(7,4)   == BITS4(0,0,1,1)) {
   9546            regD = INSNA(15,12);
   9547            regN = INSNA(19,16);
   9548            regM = INSNA(3,0);
   9549            if (regD != 15 && regN != 15 && regM != 15)
   9550               gate = True;
   9551         }
   9552      }
   9553 
   9554      if (gate) {
   9555         IRTemp irt_regN     = newTemp(Ity_I32);
   9556         IRTemp irt_regM     = newTemp(Ity_I32);
   9557         IRTemp irt_sum      = newTemp(Ity_I32);
   9558         IRTemp irt_diff     = newTemp(Ity_I32);
   9559         IRTemp irt_res_sum  = newTemp(Ity_I32);
   9560         IRTemp irt_res_diff = newTemp(Ity_I32);
   9561 
   9562         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9563         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   9564 
   9565         assign( irt_diff,
   9566                 binop( Iop_Sub32,
   9567                        binop( Iop_Sar32,
   9568                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9569                               mkU8(16) ),
   9570                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
   9571         armSignedSatQ( irt_diff, 0x10, &irt_res_diff, NULL );
   9572 
   9573         assign( irt_sum,
   9574                 binop( Iop_Add32,
   9575                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9576                        binop( Iop_Sar32,
   9577                               binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
   9578                               mkU8(16) ) ) );
   9579         armSignedSatQ( irt_sum, 0x10, &irt_res_sum, NULL );
   9580 
   9581         IRExpr* ire_result
   9582           = binop( Iop_Or32,
   9583                    binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ),
   9584                    binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) );
   9585 
   9586         if (isT)
   9587            putIRegT( regD, ire_result, condT );
   9588         else
   9589            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9590 
   9591         DIP( "qasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   9592         return True;
   9593      }
   9594      /* fall through */
   9595    }
   9596 
   9597    /* ------------------- sasx<c> <Rd>,<Rn>,<Rm> ------------------- */
   9598    {
   9599      UInt regD = 99, regN = 99, regM = 99;
   9600      Bool gate = False;
   9601 
   9602      if (isT) {
   9603         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
   9604            regN = INSNT0(3,0);
   9605            regD = INSNT1(11,8);
   9606            regM = INSNT1(3,0);
   9607            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9608               gate = True;
   9609         }
   9610      } else {
   9611         if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
   9612             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   9613             INSNA(7,4)   == BITS4(0,0,1,1)) {
   9614            regD = INSNA(15,12);
   9615            regN = INSNA(19,16);
   9616            regM = INSNA(3,0);
   9617            if (regD != 15 && regN != 15 && regM != 15)
   9618               gate = True;
   9619         }
   9620      }
   9621 
   9622      if (gate) {
   9623         IRTemp irt_regN = newTemp(Ity_I32);
   9624         IRTemp irt_regM = newTemp(Ity_I32);
   9625         IRTemp irt_sum  = newTemp(Ity_I32);
   9626         IRTemp irt_diff = newTemp(Ity_I32);
   9627 
   9628         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9629         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   9630 
   9631         assign( irt_diff,
   9632                 binop( Iop_Sub32,
   9633                        binop( Iop_Sar32,
   9634                               binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9635                               mkU8(16) ),
   9636                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
   9637 
   9638         assign( irt_sum,
   9639                 binop( Iop_Add32,
   9640                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9641                        binop( Iop_Sar32,
   9642                               binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
   9643                               mkU8(16) ) ) );
   9644 
   9645         IRExpr* ire_result
   9646           = binop( Iop_Or32,
   9647                    binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ),
   9648                    binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) );
   9649 
   9650         IRTemp ge10 = newTemp(Ity_I32);
   9651         assign(ge10, unop(Iop_Not32, mkexpr(irt_diff)));
   9652         put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
   9653         put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
   9654 
   9655         IRTemp ge32 = newTemp(Ity_I32);
   9656         assign(ge32, unop(Iop_Not32, mkexpr(irt_sum)));
   9657         put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
   9658         put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
   9659 
   9660         if (isT)
   9661            putIRegT( regD, ire_result, condT );
   9662         else
   9663            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9664 
   9665         DIP( "sasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   9666         return True;
   9667      }
   9668      /* fall through */
   9669    }
   9670 
   9671    /* --------------- smuad, smuadx<c><Rd>,<Rn>,<Rm> --------------- */
   9672    /* --------------- smsad, smsadx<c><Rd>,<Rn>,<Rm> --------------- */
   9673    {
   9674      UInt regD = 99, regN = 99, regM = 99, bitM = 99;
   9675      Bool gate = False, isAD = False;
   9676 
   9677      if (isT) {
   9678         if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
   9679             && (INSNT1(15,0) & 0xF0E0) == 0xF000) {
   9680            regN = INSNT0(3,0);
   9681            regD = INSNT1(11,8);
   9682            regM = INSNT1(3,0);
   9683            bitM = INSNT1(4,4);
   9684            isAD = INSNT0(15,4) == 0xFB2;
   9685            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9686               gate = True;
   9687         }
   9688      } else {
   9689         if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
   9690             INSNA(15,12) == BITS4(1,1,1,1)         &&
   9691             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1) ) {
   9692            regD = INSNA(19,16);
   9693            regN = INSNA(3,0);
   9694            regM = INSNA(11,8);
   9695            bitM = INSNA(5,5);
   9696            isAD = INSNA(6,6) == 0;
   9697            if (regD != 15 && regN != 15 && regM != 15)
   9698               gate = True;
   9699         }
   9700      }
   9701 
   9702      if (gate) {
   9703         IRTemp irt_regN    = newTemp(Ity_I32);
   9704         IRTemp irt_regM    = newTemp(Ity_I32);
   9705         IRTemp irt_prod_lo = newTemp(Ity_I32);
   9706         IRTemp irt_prod_hi = newTemp(Ity_I32);
   9707         IRTemp tmpM        = newTemp(Ity_I32);
   9708 
   9709         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9710 
   9711         assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
   9712         assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
   9713 
   9714         assign( irt_prod_lo,
   9715                 binop( Iop_Mul32,
   9716                        binop( Iop_Sar32,
   9717                               binop(Iop_Shl32, mkexpr(irt_regN), mkU8(16)),
   9718                               mkU8(16) ),
   9719                        binop( Iop_Sar32,
   9720                               binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
   9721                               mkU8(16) ) ) );
   9722         assign( irt_prod_hi, binop(Iop_Mul32,
   9723                                    binop(Iop_Sar32, mkexpr(irt_regN), mkU8(16)),
   9724                                    binop(Iop_Sar32, mkexpr(irt_regM), mkU8(16))) );
   9725         IRExpr* ire_result
   9726            = binop( isAD ? Iop_Add32 : Iop_Sub32,
   9727                     mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) );
   9728 
   9729         if (isT)
   9730            putIRegT( regD, ire_result, condT );
   9731         else
   9732            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9733 
   9734         if (isAD) {
   9735            or_into_QFLAG32(
   9736               signed_overflow_after_Add32( ire_result,
   9737                                            irt_prod_lo, irt_prod_hi ),
   9738               condT
   9739            );
   9740         }
   9741 
   9742         DIP("smu%cd%s%s r%u, r%u, r%u\n",
   9743             isAD ? 'a' : 's',
   9744             bitM ? "x" : "", nCC(conq), regD, regN, regM);
   9745         return True;
   9746      }
   9747      /* fall through */
   9748    }
   9749 
   9750    /* --------------- smlad{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
   9751    /* --------------- smlsd{X}<c> <Rd>,<Rn>,<Rm>,<Ra> -------------- */
   9752    {
   9753      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
   9754      Bool gate = False, isAD = False;
   9755 
   9756      if (isT) {
   9757        if ((INSNT0(15,4) == 0xFB2 || INSNT0(15,4) == 0xFB4)
   9758            && INSNT1(7,5) == BITS3(0,0,0)) {
   9759            regN = INSNT0(3,0);
   9760            regD = INSNT1(11,8);
   9761            regM = INSNT1(3,0);
   9762            regA = INSNT1(15,12);
   9763            bitM = INSNT1(4,4);
   9764            isAD = INSNT0(15,4) == 0xFB2;
   9765            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
   9766                && !isBadRegT(regA))
   9767               gate = True;
   9768         }
   9769      } else {
   9770         if (INSNA(27,20) == BITS8(0,1,1,1,0,0,0,0) &&
   9771             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
   9772            regD = INSNA(19,16);
   9773            regA = INSNA(15,12);
   9774            regN = INSNA(3,0);
   9775            regM = INSNA(11,8);
   9776            bitM = INSNA(5,5);
   9777            isAD = INSNA(6,6) == 0;
   9778            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
   9779               gate = True;
   9780         }
   9781      }
   9782 
   9783      if (gate) {
   9784         IRTemp irt_regN    = newTemp(Ity_I32);
   9785         IRTemp irt_regM    = newTemp(Ity_I32);
   9786         IRTemp irt_regA    = newTemp(Ity_I32);
   9787         IRTemp irt_prod_lo = newTemp(Ity_I32);
   9788         IRTemp irt_prod_hi = newTemp(Ity_I32);
   9789         IRTemp irt_sum     = newTemp(Ity_I32);
   9790         IRTemp tmpM        = newTemp(Ity_I32);
   9791 
   9792         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   9793         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
   9794 
   9795         assign( tmpM, isT ? getIRegT(regM) : getIRegA(regM) );
   9796         assign( irt_regM, genROR32(tmpM, (bitM & 1) ? 16 : 0) );
   9797 
   9798         assign( irt_prod_lo,
   9799                 binop(Iop_Mul32,
   9800                       binop(Iop_Sar32,
   9801                             binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
   9802                             mkU8(16)),
   9803                       binop(Iop_Sar32,
   9804                             binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
   9805                             mkU8(16))) );
   9806         assign( irt_prod_hi,
   9807                 binop( Iop_Mul32,
   9808                        binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
   9809                        binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
   9810         assign( irt_sum, binop( isAD ? Iop_Add32 : Iop_Sub32,
   9811                                 mkexpr(irt_prod_lo), mkexpr(irt_prod_hi) ) );
   9812 
   9813         IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_sum), mkexpr(irt_regA));
   9814 
   9815         if (isT)
   9816            putIRegT( regD, ire_result, condT );
   9817         else
   9818            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9819 
   9820         if (isAD) {
   9821            or_into_QFLAG32(
   9822               signed_overflow_after_Add32( mkexpr(irt_sum),
   9823                                            irt_prod_lo, irt_prod_hi ),
   9824               condT
   9825            );
   9826         }
   9827 
   9828         or_into_QFLAG32(
   9829            signed_overflow_after_Add32( ire_result, irt_sum, irt_regA ),
   9830            condT
   9831         );
   9832 
   9833         DIP("sml%cd%s%s r%u, r%u, r%u, r%u\n",
   9834             isAD ? 'a' : 's',
   9835             bitM ? "x" : "", nCC(conq), regD, regN, regM, regA);
   9836         return True;
   9837      }
   9838      /* fall through */
   9839    }
   9840 
   9841    /* ----- smlabb, smlabt, smlatb, smlatt <Rd>,<Rn>,<Rm>,<Ra> ----- */
   9842    {
   9843      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99, bitN = 99;
   9844      Bool gate = False;
   9845 
   9846      if (isT) {
   9847         if (INSNT0(15,4) == 0xFB1 && INSNT1(7,6) == BITS2(0,0)) {
   9848            regN = INSNT0(3,0);
   9849            regD = INSNT1(11,8);
   9850            regM = INSNT1(3,0);
   9851            regA = INSNT1(15,12);
   9852            bitM = INSNT1(4,4);
   9853            bitN = INSNT1(5,5);
   9854            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
   9855                && !isBadRegT(regA))
   9856               gate = True;
   9857         }
   9858      } else {
   9859         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,0,0) &&
   9860             (INSNA(7,4) & BITS4(1,0,0,1)) == BITS4(1,0,0,0)) {
   9861            regD = INSNA(19,16);
   9862            regN = INSNA(3,0);
   9863            regM = INSNA(11,8);
   9864            regA = INSNA(15,12);
   9865            bitM = INSNA(6,6);
   9866            bitN = INSNA(5,5);
   9867            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
   9868               gate = True;
   9869         }
   9870      }
   9871 
   9872      if (gate) {
   9873         IRTemp irt_regA = newTemp(Ity_I32);
   9874         IRTemp irt_prod = newTemp(Ity_I32);
   9875 
   9876         assign( irt_prod,
   9877                 binop(Iop_Mul32,
   9878                       binop(Iop_Sar32,
   9879                             binop(Iop_Shl32,
   9880                                   isT ? getIRegT(regN) : getIRegA(regN),
   9881                                   mkU8(bitN ? 0 : 16)),
   9882                             mkU8(16)),
   9883                       binop(Iop_Sar32,
   9884                             binop(Iop_Shl32,
   9885                                   isT ? getIRegT(regM) : getIRegA(regM),
   9886                                   mkU8(bitM ? 0 : 16)),
   9887                             mkU8(16))) );
   9888 
   9889         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
   9890 
   9891         IRExpr* ire_result = binop(Iop_Add32, mkexpr(irt_prod), mkexpr(irt_regA));
   9892 
   9893         if (isT)
   9894            putIRegT( regD, ire_result, condT );
   9895         else
   9896            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9897 
   9898         or_into_QFLAG32(
   9899            signed_overflow_after_Add32( ire_result, irt_prod, irt_regA ),
   9900            condT
   9901         );
   9902 
   9903         DIP( "smla%c%c%s r%u, r%u, r%u, r%u\n",
   9904              bitN ? 't' : 'b', bitM ? 't' : 'b',
   9905              nCC(conq), regD, regN, regM, regA );
   9906         return True;
   9907      }
   9908      /* fall through */
   9909    }
   9910 
   9911    /* ----- smlawb, smlawt <Rd>,<Rn>,<Rm>,<Ra> ----- */
   9912    {
   9913      UInt regD = 99, regN = 99, regM = 99, regA = 99, bitM = 99;
   9914      Bool gate = False;
   9915 
   9916      if (isT) {
   9917         if (INSNT0(15,4) == 0xFB3 && INSNT1(7,5) == BITS3(0,0,0)) {
   9918            regN = INSNT0(3,0);
   9919            regD = INSNT1(11,8);
   9920            regM = INSNT1(3,0);
   9921            regA = INSNT1(15,12);
   9922            bitM = INSNT1(4,4);
   9923            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM)
   9924                && !isBadRegT(regA))
   9925               gate = True;
   9926         }
   9927      } else {
   9928         if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
   9929             (INSNA(7,4) & BITS4(1,0,1,1)) == BITS4(1,0,0,0)) {
   9930            regD = INSNA(19,16);
   9931            regN = INSNA(3,0);
   9932            regM = INSNA(11,8);
   9933            regA = INSNA(15,12);
   9934            bitM = INSNA(6,6);
   9935            if (regD != 15 && regN != 15 && regM != 15 && regA != 15)
   9936               gate = True;
   9937         }
   9938      }
   9939 
   9940      if (gate) {
   9941         IRTemp irt_regA = newTemp(Ity_I32);
   9942         IRTemp irt_prod = newTemp(Ity_I64);
   9943 
   9944         assign( irt_prod,
   9945                 binop(Iop_MullS32,
   9946                       isT ? getIRegT(regN) : getIRegA(regN),
   9947                       binop(Iop_Sar32,
   9948                             binop(Iop_Shl32,
   9949                                   isT ? getIRegT(regM) : getIRegA(regM),
   9950                                   mkU8(bitM ? 0 : 16)),
   9951                             mkU8(16))) );
   9952 
   9953         assign( irt_regA, isT ? getIRegT(regA) : getIRegA(regA) );
   9954 
   9955         IRTemp prod32 = newTemp(Ity_I32);
   9956         assign(prod32,
   9957                binop(Iop_Or32,
   9958                      binop(Iop_Shl32, unop(Iop_64HIto32, mkexpr(irt_prod)), mkU8(16)),
   9959                      binop(Iop_Shr32, unop(Iop_64to32, mkexpr(irt_prod)), mkU8(16))
   9960         ));
   9961 
   9962         IRExpr* ire_result = binop(Iop_Add32, mkexpr(prod32), mkexpr(irt_regA));
   9963 
   9964         if (isT)
   9965            putIRegT( regD, ire_result, condT );
   9966         else
   9967            putIRegA( regD, ire_result, condT, Ijk_Boring );
   9968 
   9969         or_into_QFLAG32(
   9970            signed_overflow_after_Add32( ire_result, prod32, irt_regA ),
   9971            condT
   9972         );
   9973 
   9974         DIP( "smlaw%c%s r%u, r%u, r%u, r%u\n",
   9975              bitM ? 't' : 'b',
   9976              nCC(conq), regD, regN, regM, regA );
   9977         return True;
   9978      }
   9979      /* fall through */
   9980    }
   9981 
   9982    /* ------------------- sel<c> <Rd>,<Rn>,<Rm> -------------------- */
   9983    /* fixme: fix up the test in v6media.c so that we can pass the ge
   9984       flags as part of the test. */
   9985    {
   9986      UInt regD = 99, regN = 99, regM = 99;
   9987      Bool gate = False;
   9988 
   9989      if (isT) {
   9990         if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF080) {
   9991            regN = INSNT0(3,0);
   9992            regD = INSNT1(11,8);
   9993            regM = INSNT1(3,0);
   9994            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   9995               gate = True;
   9996         }
   9997      } else {
   9998         if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
   9999             INSNA(11,8)  == BITS4(1,1,1,1)         &&
   10000             INSNA(7,4)   == BITS4(1,0,1,1)) {
   10001            regD = INSNA(15,12);
   10002            regN = INSNA(19,16);
   10003            regM = INSNA(3,0);
   10004            if (regD != 15 && regN != 15 && regM != 15)
   10005               gate = True;
   10006         }
   10007      }
   10008 
   10009      if (gate) {
   10010         IRTemp irt_ge_flag0 = newTemp(Ity_I32);
   10011         IRTemp irt_ge_flag1 = newTemp(Ity_I32);
   10012         IRTemp irt_ge_flag2 = newTemp(Ity_I32);
   10013         IRTemp irt_ge_flag3 = newTemp(Ity_I32);
   10014 
   10015         assign( irt_ge_flag0, get_GEFLAG32(0) );
   10016         assign( irt_ge_flag1, get_GEFLAG32(1) );
   10017         assign( irt_ge_flag2, get_GEFLAG32(2) );
   10018         assign( irt_ge_flag3, get_GEFLAG32(3) );
   10019 
   10020         IRExpr* ire_ge_flag0_or
   10021           = binop(Iop_Or32, mkexpr(irt_ge_flag0),
   10022                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag0)));
   10023         IRExpr* ire_ge_flag1_or
   10024           = binop(Iop_Or32, mkexpr(irt_ge_flag1),
   10025                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag1)));
   10026         IRExpr* ire_ge_flag2_or
   10027           = binop(Iop_Or32, mkexpr(irt_ge_flag2),
   10028                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag2)));
   10029         IRExpr* ire_ge_flag3_or
   10030           = binop(Iop_Or32, mkexpr(irt_ge_flag3),
   10031                   binop(Iop_Sub32, mkU32(0), mkexpr(irt_ge_flag3)));
   10032 
   10033         IRExpr* ire_ge_flags
   10034           = binop( Iop_Or32,
   10035                    binop(Iop_Or32,
   10036                          binop(Iop_And32,
   10037                                binop(Iop_Sar32, ire_ge_flag0_or, mkU8(31)),
   10038                                mkU32(0x000000ff)),
   10039                          binop(Iop_And32,
   10040                                binop(Iop_Sar32, ire_ge_flag1_or, mkU8(31)),
   10041                                mkU32(0x0000ff00))),
   10042                    binop(Iop_Or32,
   10043                          binop(Iop_And32,
   10044                                binop(Iop_Sar32, ire_ge_flag2_or, mkU8(31)),
   10045                                mkU32(0x00ff0000)),
   10046                          binop(Iop_And32,
   10047                                binop(Iop_Sar32, ire_ge_flag3_or, mkU8(31)),
   10048                                mkU32(0xff000000))) );
   10049 
   10050         IRExpr* ire_result
   10051           = binop(Iop_Or32,
   10052                   binop(Iop_And32,
   10053                         isT ? getIRegT(regN) : getIRegA(regN),
   10054                         ire_ge_flags ),
   10055                   binop(Iop_And32,
   10056                         isT ? getIRegT(regM) : getIRegA(regM),
   10057                         unop(Iop_Not32, ire_ge_flags)));
   10058 
   10059         if (isT)
   10060            putIRegT( regD, ire_result, condT );
   10061         else
   10062            putIRegA( regD, ire_result, condT, Ijk_Boring );
   10063 
   10064         DIP("sel%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
   10065         return True;
   10066      }
   10067      /* fall through */
   10068    }
   10069 
   10070    /* ----------------- uxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
   10071    {
   10072      UInt regD = 99, regN = 99, regM = 99, rotate = 99;
   10073      Bool gate = False;
   10074 
   10075      if (isT) {
   10076         if (INSNT0(15,4) == 0xFA3 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
   10077            regN   = INSNT0(3,0);
   10078            regD   = INSNT1(11,8);
   10079            regM   = INSNT1(3,0);
   10080            rotate = INSNT1(5,4);
   10081            if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
   10082               gate = True;
   10083         }
   10084      } else {
   10085         if (INSNA(27,20) == BITS8(0,1,1,0,1,1,0,0) &&
   10086             INSNA(9,4)   == BITS6(0,0,0,1,1,1) ) {
   10087            regD   = INSNA(15,12);
   10088            regN   = INSNA(19,16);
   10089            regM   = INSNA(3,0);
   10090            rotate = INSNA(11,10);
   10091            if (regD != 15 && regN != 15 && regM != 15)
   10092              gate = True;
   10093         }
   10094      }
   10095 
   10096      if (gate) {
   10097         IRTemp irt_regN = newTemp(Ity_I32);
   10098         assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
   10099 
   10100         IRTemp irt_regM = newTemp(Ity_I32);
   10101         assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
   10102 
   10103         IRTemp irt_rot = newTemp(Ity_I32);
   10104         assign( irt_rot, binop(Iop_And32,
   10105                                genROR32(irt_regM, 8 * rotate),
   10106                                mkU32(0x00FF00FF)) );
   10107 
   10108         IRExpr* resLo
   10109            = binop(Iop_And32,
   10110                    binop(Iop_Add32, mkexpr(irt_regN), mkexpr(irt_rot)),
   10111                    mkU32(0x0000FFFF));
   10112 
   10113         IRExpr* resHi
   10114            = binop(Iop_Add32,
   10115                    binop(Iop_And32, mkexpr(irt_regN), mkU32(0xFFFF0000)),
   10116                    binop(Iop_And32, mkexpr(irt_rot),  mkU32(0xFFFF0000)));
   10117 
   10118         IRExpr* ire_result
   10119            = binop( Iop_Or32, resHi, resLo );
   10120 
   10121         if (isT)
   10122            putIRegT( regD, ire_result, condT );
   10123         else
   10124            putIRegA( regD, ire_result, condT, Ijk_Boring );
   10125 
   10126         DIP( "uxtab16%s r%u, r%u, r%u, ROR #%u\n",
   10127              nCC(conq), regD, regN, regM, 8 * rotate );
   10128         return True;
   10129      }
   10130      /* fall through */
   10131    }
   10132 
   10133    /* --------------- usad8  Rd,Rn,Rm    ---------------- */
   10134    /* --------------- usada8 Rd,Rn,Rm,Ra ---------------- */
   10135    {
   10136      UInt rD = 99, rN = 99, rM = 99, rA = 99;
   10137      Bool gate = False;
   10138 
   10139      if (isT) {
   10140        if (INSNT0(15,4) == 0xFB7 && INSNT1(7,4) == BITS4(0,0,0,0)) {
   10141            rN = INSNT0(3,0);
   10142            rA = INSNT1(15,12);
   10143            rD = INSNT1(11,8);
   10144            rM = INSNT1(3,0);
   10145            if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM) && rA != 13)
   10146               gate = True;
   10147         }
   10148      } else {
   10149         if (INSNA(27,20) == BITS8(0,1,1,1,1,0,0,0) &&
   10150             INSNA(7,4)   == BITS4(0,0,0,1) ) {
   10151            rD = INSNA(19,16);
   10152            rA = INSNA(15,12);
   10153            rM = INSNA(11,8);
   10154            rN = INSNA(3,0);
   10155            if (rD != 15 && rN != 15 && rM != 15 /* but rA can be 15 */)
   10156               gate = True;
   10157         }
   10158      }
   10159      /* We allow rA == 15, to denote the usad8 (no accumulator) case. */
   10160 
   10161      if (gate) {
   10162         IRExpr* rNe = isT ? getIRegT(rN) : getIRegA(rN);
   10163         IRExpr* rMe = isT ? getIRegT(rM) : getIRegA(rM);
   10164         IRExpr* rAe = rA == 15 ? mkU32(0)
   10165                                : (isT ? getIRegT(rA) : getIRegA(rA));
   10166         IRExpr* res = binop(Iop_Add32,
   10167                             binop(Iop_Sad8Ux4, rNe, rMe),
   10168                             rAe);
   10169         if (isT)
   10170            putIRegT( rD, res, condT );
   10171         else
   10172            putIRegA( rD, res, condT, Ijk_Boring );
   10173 
   10174         if (rA == 15) {
   10175            DIP( "usad8%s r%u, r%u, r%u\n",
   10176                 nCC(conq), rD, rN, rM );
   10177         } else {
   10178            DIP( "usada8%s r%u, r%u, r%u, r%u\n",
   10179                 nCC(conq), rD, rN, rM, rA );
   10180         }
   10181         return True;
   10182      }
   10183      /* fall through */
   10184    }
   10185 
   10186    /* ---------- Doesn't match anything. ---------- */
   10187    return False;
   10188 
   10189 #  undef INSNA
   10190 #  undef INSNT0
   10191 #  undef INSNT1
   10192 }
   10193 
   10194 
   10195 /*------------------------------------------------------------*/
   10196 /*--- LDMxx/STMxx helper (both ARM and Thumb32)            ---*/
   10197 /*------------------------------------------------------------*/
   10198 
   10199 /* Generate IR for LDMxx and STMxx.  This is complex.  Assumes it's
   10200    unconditional, so the caller must produce a jump-around before
   10201    calling this, if the insn is to be conditional.  Caller is
   10202    responsible for all validation of parameters.  For LDMxx, if PC is
   10203    amongst the values loaded, caller is also responsible for
   10204    generating the jump. */
   10205 static void mk_ldm_stm ( Bool arm,     /* True: ARM, False: Thumb */
   10206                          UInt rN,      /* base reg */
   10207                          UInt bINC,    /* 1: inc,  0: dec */
   10208                          UInt bBEFORE, /* 1: inc/dec before, 0: after */
   10209                          UInt bW,      /* 1: writeback to Rn */
   10210                          UInt bL,      /* 1: load, 0: store */
   10211                          UInt regList )
   10212 {
   10213    Int i, r, m, nRegs;
   10214 
   10215    /* Get hold of the old Rn value.  We might need to write its value
   10216       to memory during a store, and if it's also the writeback
   10217       register then we need to get its value now.  We can't treat it
   10218       exactly like the other registers we're going to transfer,
   10219       because for xxMDA and xxMDB writeback forms, the generated IR
   10220       updates Rn in the guest state before any transfers take place.
   10221       We have to do this as per comments below, in order that if Rn is
   10222       the stack pointer then it always has a value is below or equal
   10223       to any of the transfer addresses.  Ick. */
   10224    IRTemp oldRnT = newTemp(Ity_I32);
   10225    assign(oldRnT, arm ? getIRegA(rN) : getIRegT(rN));
   10226 
   10227    IRTemp anchorT = newTemp(Ity_I32);
   10228    /* The old (Addison-Wesley) ARM ARM seems to say that LDMxx/STMxx
   10229       ignore the bottom two bits of the address.  However, Cortex-A8
   10230       doesn't seem to care.  Hence: */
   10231    /* No .. don't force alignment .. */
   10232    /* assign(anchorT, binop(Iop_And32, mkexpr(oldRnT), mkU32(~3U))); */
   10233    /* Instead, use the potentially misaligned address directly. */
   10234    assign(anchorT, mkexpr(oldRnT));
   10235 
   10236    IROp opADDorSUB = bINC ? Iop_Add32 : Iop_Sub32;
   10237    // bINC == 1:  xxMIA, xxMIB
   10238    // bINC == 0:  xxMDA, xxMDB
   10239 
   10240    // For xxMDA and xxMDB, update Rn first if necessary.  We have
   10241    // to do this first so that, for the common idiom of the transfers
   10242    // faulting because we're pushing stuff onto a stack and the stack
   10243    // is growing down onto allocate-on-fault pages (as Valgrind simulates),
   10244    // we need to have the SP up-to-date "covering" (pointing below) the
   10245    // transfer area.  For the same reason, if we are doing xxMIA or xxMIB,
   10246    // do the transfer first, and then update rN afterwards.
   10247    nRegs = 0;
   10248    for (i = 0; i < 16; i++) {
   10249      if ((regList & (1 << i)) != 0)
   10250          nRegs++;
   10251    }
   10252    if (bW == 1 && !bINC) {
   10253       IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
   10254       if (arm)
   10255          putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
   10256       else
   10257          putIRegT( rN, e, IRTemp_INVALID );
   10258    }
   10259 
   10260    // Make up a list of the registers to transfer, and their offsets
   10261    // in memory relative to the anchor.  If the base reg (Rn) is part
   10262    // of the transfer, then do it last for a load and first for a store.
   10263    UInt xReg[16], xOff[16];
   10264    Int  nX = 0;
   10265    m = 0;
   10266    for (i = 0; i < 16; i++) {
   10267       r = bINC ? i : (15-i);
   10268       if (0 == (regList & (1<<r)))
   10269          continue;
   10270       if (bBEFORE)
   10271          m++;
   10272       /* paranoia: check we aren't transferring the writeback
   10273          register during a load. Should be assured by decode-point
   10274          check above. */
   10275       if (bW == 1 && bL == 1)
   10276          vassert(r != rN);
   10277 
   10278       xOff[nX] = 4 * m;
   10279       xReg[nX] = r;
   10280       nX++;
   10281 
   10282       if (!bBEFORE)
   10283          m++;
   10284    }
   10285    vassert(m == nRegs);
   10286    vassert(nX == nRegs);
   10287    vassert(nX <= 16);
   10288 
   10289    if (bW == 0 && (regList & (1<<rN)) != 0) {
   10290       /* Non-writeback, and basereg is to be transferred.  Do its
   10291          transfer last for a load and first for a store.  Requires
   10292          reordering xOff/xReg. */
   10293       if (0) {
   10294          vex_printf("\nREG_LIST_PRE: (rN=%d)\n", rN);
   10295          for (i = 0; i < nX; i++)
   10296             vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
   10297          vex_printf("\n");
   10298       }
   10299 
   10300       vassert(nX > 0);
   10301       for (i = 0; i < nX; i++) {
   10302          if (xReg[i] == rN)
   10303              break;
   10304       }
   10305       vassert(i < nX); /* else we didn't find it! */
   10306       UInt tReg = xReg[i];
   10307       UInt tOff = xOff[i];
   10308       if (bL == 1) {
   10309          /* load; make this transfer happen last */
   10310          if (i < nX-1) {
   10311             for (m = i+1; m < nX; m++) {
   10312                xReg[m-1] = xReg[m];
   10313                xOff[m-1] = xOff[m];
   10314             }
   10315             vassert(m == nX);
   10316             xReg[m-1] = tReg;
   10317             xOff[m-1] = tOff;
   10318          }
   10319       } else {
   10320          /* store; make this transfer happen first */
   10321          if (i > 0) {
   10322             for (m = i-1; m >= 0; m--) {
   10323                xReg[m+1] = xReg[m];
   10324                xOff[m+1] = xOff[m];
   10325             }
   10326             vassert(m == -1);
   10327             xReg[0] = tReg;
   10328             xOff[0] = tOff;
   10329          }
   10330       }
   10331 
   10332       if (0) {
   10333          vex_printf("REG_LIST_POST:\n");
   10334          for (i = 0; i < nX; i++)
   10335             vex_printf("reg %d   off %d\n", xReg[i], xOff[i]);
   10336          vex_printf("\n");
   10337       }
   10338    }
   10339 
   10340    /* Actually generate the transfers */
   10341    for (i = 0; i < nX; i++) {
   10342       r = xReg[i];
   10343       if (bL == 1) {
   10344          IRExpr* e = loadLE(Ity_I32,
   10345                             binop(opADDorSUB, mkexpr(anchorT),
   10346                                   mkU32(xOff[i])));
   10347          if (arm) {
   10348             putIRegA( r, e, IRTemp_INVALID, Ijk_Ret );
   10349          } else {
   10350             // no: putIRegT( r, e, IRTemp_INVALID );
   10351             // putIRegT refuses to write to R15.  But that might happen.
   10352             // Since this is uncond, and we need to be able to
   10353             // write the PC, just use the low level put:
   10354             llPutIReg( r, e );
   10355          }
   10356       } else {
   10357          /* if we're storing Rn, make sure we use the correct
   10358             value, as per extensive comments above */
   10359          storeLE( binop(opADDorSUB, mkexpr(anchorT), mkU32(xOff[i])),
   10360                   r == rN ? mkexpr(oldRnT)
   10361                           : (arm ? getIRegA(r) : getIRegT(r) ) );
   10362       }
   10363    }
   10364 
   10365    // If we are doing xxMIA or xxMIB,
   10366    // do the transfer first, and then update rN afterwards.
   10367    if (bW == 1 && bINC) {
   10368       IRExpr* e = binop(opADDorSUB, mkexpr(oldRnT), mkU32(4*nRegs));
   10369       if (arm)
   10370          putIRegA( rN, e, IRTemp_INVALID, Ijk_Boring );
   10371       else
   10372          putIRegT( rN, e, IRTemp_INVALID );
   10373    }
   10374 }
   10375 
   10376 
   10377 /*------------------------------------------------------------*/
   10378 /*--- VFP (CP 10 and 11) instructions                      ---*/
   10379 /*------------------------------------------------------------*/
   10380 
   10381 /* Both ARM and Thumb */
   10382 
   10383 /* Translate a CP10 or CP11 instruction.  If successful, returns
   10384    True and *dres may or may not be updated.  If failure, returns
   10385    False and doesn't change *dres nor create any IR.
   10386 
   10387    The ARM and Thumb encodings are identical for the low 28 bits of
   10388    the insn (yay!) and that's what the caller must supply, iow, imm28
   10389    has the top 4 bits masked out.  Caller is responsible for
   10390    determining whether the masked-out bits are valid for a CP10/11
   10391    insn.  The rules for the top 4 bits are:
   10392 
   10393      ARM: 0000 to 1110 allowed, and this is the gating condition.
   10394      1111 (NV) is not allowed.
   10395 
   10396      Thumb: must be 1110.  The gating condition is taken from
   10397      ITSTATE in the normal way.
   10398 
   10399    Conditionalisation:
   10400 
   10401    Caller must supply an IRTemp 'condT' holding the gating condition,
   10402    or IRTemp_INVALID indicating the insn is always executed.
   10403 
   10404    Caller must also supply an ARMCondcode 'cond'.  This is only used
   10405    for debug printing, no other purpose.  For ARM, this is simply the
   10406    top 4 bits of the original instruction.  For Thumb, the condition
   10407    is not (really) known until run time, and so ARMCondAL should be
   10408    passed, only so that printing of these instructions does not show
   10409    any condition.
   10410 
   10411    Finally, the caller must indicate whether this occurs in ARM or
   10412    Thumb code.
   10413 */
   10414 static Bool decode_CP10_CP11_instruction (
   10415                /*MOD*/DisResult* dres,
   10416                UInt              insn28,
   10417                IRTemp            condT,
   10418                ARMCondcode       conq,
   10419                Bool              isT
   10420             )
   10421 {
   10422 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn28, (_bMax), (_bMin))
   10423 
   10424    vassert(INSN(31,28) == BITS4(0,0,0,0)); // caller's obligation
   10425 
   10426    if (isT) {
   10427       vassert(conq == ARMCondAL);
   10428    } else {
   10429       vassert(conq >= ARMCondEQ && conq <= ARMCondAL);
   10430    }
   10431 
   10432    /* ----------------------------------------------------------- */
   10433    /* -- VFP instructions -- double precision (mostly)         -- */
   10434    /* ----------------------------------------------------------- */
   10435 
   10436    /* --------------------- fldmx, fstmx --------------------- */
   10437    /*
   10438                                  31   27   23   19 15 11   7   0
   10439                                          P U WL
   10440       C4-100, C5-26  1  FSTMX    cond 1100 1000 Rn Dd 1011 offset
   10441       C4-100, C5-28  2  FSTMIAX  cond 1100 1010 Rn Dd 1011 offset
   10442       C4-100, C5-30  3  FSTMDBX  cond 1101 0010 Rn Dd 1011 offset
   10443 
   10444       C4-42, C5-26   1  FLDMX    cond 1100 1001 Rn Dd 1011 offset
   10445       C4-42, C5-28   2  FLDMIAX  cond 1100 1011 Rn Dd 1011 offset
   10446       C4-42, C5-30   3  FLDMDBX  cond 1101 0011 Rn Dd 1011 offset
   10447 
   10448       Regs transferred: Dd .. D(d + (offset-3)/2)
   10449       offset must be odd, must not imply a reg > 15
   10450       IA/DB: Rn is changed by (4 + 8 x # regs transferred)
   10451 
   10452       case coding:
   10453          1  at-Rn   (access at Rn)
   10454          2  ia-Rn   (access at Rn, then Rn += 4+8n)
   10455          3  db-Rn   (Rn -= 4+8n,   then access at Rn)
   10456    */
   10457    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
   10458        && INSN(11,8) == BITS4(1,0,1,1)) {
   10459       UInt bP      = (insn28 >> 24) & 1;
   10460       UInt bU      = (insn28 >> 23) & 1;
   10461       UInt bW      = (insn28 >> 21) & 1;
   10462       UInt bL      = (insn28 >> 20) & 1;
   10463       UInt offset  = (insn28 >> 0) & 0xFF;
   10464       UInt rN      = INSN(19,16);
   10465       UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
   10466       UInt nRegs   = (offset - 1) / 2;
   10467       UInt summary = 0;
   10468       Int  i;
   10469 
   10470       /**/ if (bP == 0 && bU == 1 && bW == 0) {
   10471          summary = 1;
   10472       }
   10473       else if (bP == 0 && bU == 1 && bW == 1) {
   10474          summary = 2;
   10475       }
   10476       else if (bP == 1 && bU == 0 && bW == 1) {
   10477          summary = 3;
   10478       }
   10479       else goto after_vfp_fldmx_fstmx;
   10480 
   10481       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
   10482       if (rN == 15 && (summary == 2 || summary == 3 || isT))
   10483          goto after_vfp_fldmx_fstmx;
   10484 
   10485       /* offset must be odd, and specify at least one register */
   10486       if (0 == (offset & 1) || offset < 3)
   10487          goto after_vfp_fldmx_fstmx;
   10488 
   10489       /* can't transfer regs after D15 */
   10490       if (dD + nRegs - 1 >= 32)
   10491          goto after_vfp_fldmx_fstmx;
   10492 
   10493       /* Now, we can't do a conditional load or store, since that very
   10494          likely will generate an exception.  So we have to take a side
   10495          exit at this point if the condition is false. */
   10496       if (condT != IRTemp_INVALID) {
   10497          if (isT)
   10498             mk_skip_over_T32_if_cond_is_false( condT );
   10499          else
   10500             mk_skip_over_A32_if_cond_is_false( condT );
   10501          condT = IRTemp_INVALID;
   10502       }
   10503       /* Ok, now we're unconditional.  Do the load or store. */
   10504 
   10505       /* get the old Rn value */
   10506       IRTemp rnT = newTemp(Ity_I32);
   10507       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
   10508                            rN == 15));
   10509 
   10510       /* make a new value for Rn, post-insn */
   10511       IRTemp rnTnew = IRTemp_INVALID;
   10512       if (summary == 2 || summary == 3) {
   10513          rnTnew = newTemp(Ity_I32);
   10514          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
   10515                               mkexpr(rnT),
   10516                               mkU32(4 + 8 * nRegs)));
   10517       }
   10518 
   10519       /* decide on the base transfer address */
   10520       IRTemp taT = newTemp(Ity_I32);
   10521       assign(taT,  summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
   10522 
   10523       /* update Rn if necessary -- in case 3, we're moving it down, so
   10524          update before any memory reference, in order to keep Memcheck
   10525          and V's stack-extending logic (on linux) happy */
   10526       if (summary == 3) {
   10527          if (isT)
   10528             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   10529          else
   10530             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   10531       }
   10532 
   10533       /* generate the transfers */
   10534       for (i = 0; i < nRegs; i++) {
   10535          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
   10536          if (bL) {
   10537             putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
   10538          } else {
   10539             storeLE(addr, getDReg(dD + i));
   10540          }
   10541       }
   10542 
   10543       /* update Rn if necessary -- in case 2, we're moving it up, so
   10544          update after any memory reference, in order to keep Memcheck
   10545          and V's stack-extending logic (on linux) happy */
   10546       if (summary == 2) {
   10547          if (isT)
   10548             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   10549          else
   10550             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   10551       }
   10552 
   10553       HChar* nm = bL==1 ? "ld" : "st";
   10554       switch (summary) {
   10555          case 1:  DIP("f%smx%s r%u, {d%u-d%u}\n",
   10556                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10557                   break;
   10558          case 2:  DIP("f%smiax%s r%u!, {d%u-d%u}\n",
   10559                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10560                   break;
   10561          case 3:  DIP("f%smdbx%s r%u!, {d%u-d%u}\n",
   10562                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10563                   break;
   10564          default: vassert(0);
   10565       }
   10566 
   10567       goto decode_success_vfp;
   10568       /* FIXME alignment constraints? */
   10569    }
   10570 
   10571   after_vfp_fldmx_fstmx:
   10572 
   10573    /* --------------------- fldmd, fstmd --------------------- */
   10574    /*
   10575                                  31   27   23   19 15 11   7   0
   10576                                          P U WL
   10577       C4-96, C5-26   1  FSTMD    cond 1100 1000 Rn Dd 1011 offset
   10578       C4-96, C5-28   2  FSTMDIA  cond 1100 1010 Rn Dd 1011 offset
   10579       C4-96, C5-30   3  FSTMDDB  cond 1101 0010 Rn Dd 1011 offset
   10580 
   10581       C4-38, C5-26   1  FLDMD    cond 1100 1001 Rn Dd 1011 offset
   10582       C4-38, C5-28   2  FLDMIAD  cond 1100 1011 Rn Dd 1011 offset
   10583       C4-38, C5-30   3  FLDMDBD  cond 1101 0011 Rn Dd 1011 offset
   10584 
   10585       Regs transferred: Dd .. D(d + (offset-2)/2)
   10586       offset must be even, must not imply a reg > 15
   10587       IA/DB: Rn is changed by (8 x # regs transferred)
   10588 
   10589       case coding:
   10590          1  at-Rn   (access at Rn)
   10591          2  ia-Rn   (access at Rn, then Rn += 8n)
   10592          3  db-Rn   (Rn -= 8n,     then access at Rn)
   10593    */
   10594    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
   10595        && INSN(11,8) == BITS4(1,0,1,1)) {
   10596       UInt bP      = (insn28 >> 24) & 1;
   10597       UInt bU      = (insn28 >> 23) & 1;
   10598       UInt bW      = (insn28 >> 21) & 1;
   10599       UInt bL      = (insn28 >> 20) & 1;
   10600       UInt offset  = (insn28 >> 0) & 0xFF;
   10601       UInt rN      = INSN(19,16);
   10602       UInt dD      = (INSN(22,22) << 4) | INSN(15,12);
   10603       UInt nRegs   = offset / 2;
   10604       UInt summary = 0;
   10605       Int  i;
   10606 
   10607       /**/ if (bP == 0 && bU == 1 && bW == 0) {
   10608          summary = 1;
   10609       }
   10610       else if (bP == 0 && bU == 1 && bW == 1) {
   10611          summary = 2;
   10612       }
   10613       else if (bP == 1 && bU == 0 && bW == 1) {
   10614          summary = 3;
   10615       }
   10616       else goto after_vfp_fldmd_fstmd;
   10617 
   10618       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
   10619       if (rN == 15 && (summary == 2 || summary == 3 || isT))
   10620          goto after_vfp_fldmd_fstmd;
   10621 
   10622       /* offset must be even, and specify at least one register */
   10623       if (1 == (offset & 1) || offset < 2)
   10624          goto after_vfp_fldmd_fstmd;
   10625 
   10626       /* can't transfer regs after D15 */
   10627       if (dD + nRegs - 1 >= 32)
   10628          goto after_vfp_fldmd_fstmd;
   10629 
   10630       /* Now, we can't do a conditional load or store, since that very
   10631          likely will generate an exception.  So we have to take a side
   10632          exit at this point if the condition is false. */
   10633       if (condT != IRTemp_INVALID) {
   10634          if (isT)
   10635             mk_skip_over_T32_if_cond_is_false( condT );
   10636          else
   10637             mk_skip_over_A32_if_cond_is_false( condT );
   10638          condT = IRTemp_INVALID;
   10639       }
   10640       /* Ok, now we're unconditional.  Do the load or store. */
   10641 
   10642       /* get the old Rn value */
   10643       IRTemp rnT = newTemp(Ity_I32);
   10644       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
   10645                            rN == 15));
   10646 
   10647       /* make a new value for Rn, post-insn */
   10648       IRTemp rnTnew = IRTemp_INVALID;
   10649       if (summary == 2 || summary == 3) {
   10650          rnTnew = newTemp(Ity_I32);
   10651          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
   10652                               mkexpr(rnT),
   10653                               mkU32(8 * nRegs)));
   10654       }
   10655 
   10656       /* decide on the base transfer address */
   10657       IRTemp taT = newTemp(Ity_I32);
   10658       assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
   10659 
   10660       /* update Rn if necessary -- in case 3, we're moving it down, so
   10661          update before any memory reference, in order to keep Memcheck
   10662          and V's stack-extending logic (on linux) happy */
   10663       if (summary == 3) {
   10664          if (isT)
   10665             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   10666          else
   10667             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   10668       }
   10669 
   10670       /* generate the transfers */
   10671       for (i = 0; i < nRegs; i++) {
   10672          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(8*i));
   10673          if (bL) {
   10674             putDReg(dD + i, loadLE(Ity_F64, addr), IRTemp_INVALID);
   10675          } else {
   10676             storeLE(addr, getDReg(dD + i));
   10677          }
   10678       }
   10679 
   10680       /* update Rn if necessary -- in case 2, we're moving it up, so
   10681          update after any memory reference, in order to keep Memcheck
   10682          and V's stack-extending logic (on linux) happy */
   10683       if (summary == 2) {
   10684          if (isT)
   10685             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   10686          else
   10687             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   10688       }
   10689 
   10690       HChar* nm = bL==1 ? "ld" : "st";
   10691       switch (summary) {
   10692          case 1:  DIP("f%smd%s r%u, {d%u-d%u}\n",
   10693                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10694                   break;
   10695          case 2:  DIP("f%smiad%s r%u!, {d%u-d%u}\n",
   10696                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10697                   break;
   10698          case 3:  DIP("f%smdbd%s r%u!, {d%u-d%u}\n",
   10699                       nm, nCC(conq), rN, dD, dD + nRegs - 1);
   10700                   break;
   10701          default: vassert(0);
   10702       }
   10703 
   10704       goto decode_success_vfp;
   10705       /* FIXME alignment constraints? */
   10706    }
   10707 
   10708   after_vfp_fldmd_fstmd:
   10709 
   10710    /* ------------------- fmrx, fmxr ------------------- */
   10711    if (BITS8(1,1,1,0,1,1,1,1) == INSN(27,20)
   10712        && BITS4(1,0,1,0) == INSN(11,8)
   10713        && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
   10714       UInt rD  = INSN(15,12);
   10715       UInt reg = INSN(19,16);
   10716       if (reg == BITS4(0,0,0,1)) {
   10717          if (rD == 15) {
   10718             IRTemp nzcvT = newTemp(Ity_I32);
   10719             /* When rD is 15, we are copying the top 4 bits of FPSCR
   10720                into CPSR.  That is, set the flags thunk to COPY and
   10721                install FPSCR[31:28] as the value to copy. */
   10722             assign(nzcvT, binop(Iop_And32,
   10723                                 IRExpr_Get(OFFB_FPSCR, Ity_I32),
   10724                                 mkU32(0xF0000000)));
   10725             setFlags_D1(ARMG_CC_OP_COPY, nzcvT, condT);
   10726             DIP("fmstat%s\n", nCC(conq));
   10727          } else {
   10728             /* Otherwise, merely transfer FPSCR to r0 .. r14. */
   10729             IRExpr* e = IRExpr_Get(OFFB_FPSCR, Ity_I32);
   10730             if (isT)
   10731                putIRegT(rD, e, condT);
   10732             else
   10733                putIRegA(rD, e, condT, Ijk_Boring);
   10734             DIP("fmrx%s r%u, fpscr\n", nCC(conq), rD);
   10735          }
   10736          goto decode_success_vfp;
   10737       }
   10738       /* fall through */
   10739    }
   10740 
   10741    if (BITS8(1,1,1,0,1,1,1,0) == INSN(27,20)
   10742        && BITS4(1,0,1,0) == INSN(11,8)
   10743        && BITS8(0,0,0,1,0,0,0,0) == (insn28 & 0xFF)) {
   10744       UInt rD  = INSN(15,12);
   10745       UInt reg = INSN(19,16);
   10746       if (reg == BITS4(0,0,0,1)) {
   10747          putMiscReg32(OFFB_FPSCR,
   10748                       isT ? getIRegT(rD) : getIRegA(rD), condT);
   10749          DIP("fmxr%s fpscr, r%u\n", nCC(conq), rD);
   10750          goto decode_success_vfp;
   10751       }
   10752       /* fall through */
   10753    }
   10754 
   10755    /* --------------------- vmov --------------------- */
   10756    // VMOV dM, rD, rN
   10757    if (0x0C400B10 == (insn28 & 0x0FF00FD0)) {
   10758       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
   10759       UInt rD = INSN(15,12); /* lo32 */
   10760       UInt rN = INSN(19,16); /* hi32 */
   10761       if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))) {
   10762          /* fall through */
   10763       } else {
   10764          putDReg(dM,
   10765                  unop(Iop_ReinterpI64asF64,
   10766                       binop(Iop_32HLto64,
   10767                             isT ? getIRegT(rN) : getIRegA(rN),
   10768                             isT ? getIRegT(rD) : getIRegA(rD))),
   10769                  condT);
   10770          DIP("vmov%s d%u, r%u, r%u\n", nCC(conq), dM, rD, rN);
   10771          goto decode_success_vfp;
   10772       }
   10773       /* fall through */
   10774    }
   10775 
   10776    // VMOV rD, rN, dM
   10777    if (0x0C500B10 == (insn28 & 0x0FF00FD0)) {
   10778       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
   10779       UInt rD = INSN(15,12); /* lo32 */
   10780       UInt rN = INSN(19,16); /* hi32 */
   10781       if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))
   10782           || rD == rN) {
   10783          /* fall through */
   10784       } else {
   10785          IRTemp i64 = newTemp(Ity_I64);
   10786          assign(i64, unop(Iop_ReinterpF64asI64, getDReg(dM)));
   10787          IRExpr* hi32 = unop(Iop_64HIto32, mkexpr(i64));
   10788          IRExpr* lo32 = unop(Iop_64to32,   mkexpr(i64));
   10789          if (isT) {
   10790             putIRegT(rN, hi32, condT);
   10791             putIRegT(rD, lo32, condT);
   10792          } else {
   10793             putIRegA(rN, hi32, condT, Ijk_Boring);
   10794             putIRegA(rD, lo32, condT, Ijk_Boring);
   10795          }
   10796          DIP("vmov%s r%u, r%u, d%u\n", nCC(conq), rD, rN, dM);
   10797          goto decode_success_vfp;
   10798       }
   10799       /* fall through */
   10800    }
   10801 
   10802    // VMOV sD, sD+1, rN, rM
   10803    if (0x0C400A10 == (insn28 & 0x0FF00FD0)) {
   10804       UInt sD = (INSN(3,0) << 1) | INSN(5,5);
   10805       UInt rN = INSN(15,12);
   10806       UInt rM = INSN(19,16);
   10807       if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
   10808           || sD == 31) {
   10809          /* fall through */
   10810       } else {
   10811          putFReg(sD,
   10812                  unop(Iop_ReinterpI32asF32, isT ? getIRegT(rN) : getIRegA(rN)),
   10813                  condT);
   10814          putFReg(sD+1,
   10815                  unop(Iop_ReinterpI32asF32, isT ? getIRegT(rM) : getIRegA(rM)),
   10816                  condT);
   10817          DIP("vmov%s, s%u, s%u, r%u, r%u\n",
   10818               nCC(conq), sD, sD + 1, rN, rM);
   10819          goto decode_success_vfp;
   10820       }
   10821    }
   10822 
   10823    // VMOV rN, rM, sD, sD+1
   10824    if (0x0C500A10 == (insn28 & 0x0FF00FD0)) {
   10825       UInt sD = (INSN(3,0) << 1) | INSN(5,5);
   10826       UInt rN = INSN(15,12);
   10827       UInt rM = INSN(19,16);
   10828       if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
   10829           || sD == 31 || rN == rM) {
   10830          /* fall through */
   10831       } else {
   10832          IRExpr* res0 = unop(Iop_ReinterpF32asI32, getFReg(sD));
   10833          IRExpr* res1 = unop(Iop_ReinterpF32asI32, getFReg(sD+1));
   10834          if (isT) {
   10835             putIRegT(rN, res0, condT);
   10836             putIRegT(rM, res1, condT);
   10837          } else {
   10838             putIRegA(rN, res0, condT, Ijk_Boring);
   10839             putIRegA(rM, res1, condT, Ijk_Boring);
   10840          }
   10841          DIP("vmov%s, r%u, r%u, s%u, s%u\n",
   10842              nCC(conq), rN, rM, sD, sD + 1);
   10843          goto decode_success_vfp;
   10844       }
   10845    }
   10846 
   10847    // VMOV rD[x], rT  (ARM core register to scalar)
   10848    if (0x0E000B10 == (insn28 & 0x0F900F1F)) {
   10849       UInt rD  = (INSN(7,7) << 4) | INSN(19,16);
   10850       UInt rT  = INSN(15,12);
   10851       UInt opc = (INSN(22,21) << 2) | INSN(6,5);
   10852       UInt index;
   10853       if (rT == 15 || (isT && rT == 13)) {
   10854          /* fall through */
   10855       } else {
   10856          if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
   10857             index = opc & 7;
   10858             putDRegI64(rD, triop(Iop_SetElem8x8,
   10859                                  getDRegI64(rD),
   10860                                  mkU8(index),
   10861                                  unop(Iop_32to8,
   10862                                       isT ? getIRegT(rT) : getIRegA(rT))),
   10863                            condT);
   10864             DIP("vmov%s.8 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
   10865             goto decode_success_vfp;
   10866          }
   10867          else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
   10868             index = (opc >> 1) & 3;
   10869             putDRegI64(rD, triop(Iop_SetElem16x4,
   10870                                  getDRegI64(rD),
   10871                                  mkU8(index),
   10872                                  unop(Iop_32to16,
   10873                                       isT ? getIRegT(rT) : getIRegA(rT))),
   10874                            condT);
   10875             DIP("vmov%s.16 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
   10876             goto decode_success_vfp;
   10877          }
   10878          else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0)) {
   10879             index = (opc >> 2) & 1;
   10880             putDRegI64(rD, triop(Iop_SetElem32x2,
   10881                                  getDRegI64(rD),
   10882                                  mkU8(index),
   10883                                  isT ? getIRegT(rT) : getIRegA(rT)),
   10884                            condT);
   10885             DIP("vmov%s.32 d%u[%u], r%u\n", nCC(conq), rD, index, rT);
   10886             goto decode_success_vfp;
   10887          } else {
   10888             /* fall through */
   10889          }
   10890       }
   10891    }
   10892 
   10893    // VMOV (scalar to ARM core register)
   10894    // VMOV rT, rD[x]
   10895    if (0x0E100B10 == (insn28 & 0x0F100F1F)) {
   10896       UInt rN  = (INSN(7,7) << 4) | INSN(19,16);
   10897       UInt rT  = INSN(15,12);
   10898       UInt U   = INSN(23,23);
   10899       UInt opc = (INSN(22,21) << 2) | INSN(6,5);
   10900       UInt index;
   10901       if (rT == 15 || (isT && rT == 13)) {
   10902          /* fall through */
   10903       } else {
   10904          if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
   10905             index = opc & 7;
   10906             IRExpr* e = unop(U ? Iop_8Uto32 : Iop_8Sto32,
   10907                              binop(Iop_GetElem8x8,
   10908                                    getDRegI64(rN),
   10909                                    mkU8(index)));
   10910             if (isT)
   10911                putIRegT(rT, e, condT);
   10912             else
   10913                putIRegA(rT, e, condT, Ijk_Boring);
   10914             DIP("vmov%s.%c8 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
   10915                   rT, rN, index);
   10916             goto decode_success_vfp;
   10917          }
   10918          else if ((opc & BITS4(1,0,0,1)) == BITS4(0,0,0,1)) {
   10919             index = (opc >> 1) & 3;
   10920             IRExpr* e = unop(U ? Iop_16Uto32 : Iop_16Sto32,
   10921                              binop(Iop_GetElem16x4,
   10922                                    getDRegI64(rN),
   10923                                    mkU8(index)));
   10924             if (isT)
   10925                putIRegT(rT, e, condT);
   10926             else
   10927                putIRegA(rT, e, condT, Ijk_Boring);
   10928             DIP("vmov%s.%c16 r%u, d%u[%u]\n", nCC(conq), U ? 'u' : 's',
   10929                   rT, rN, index);
   10930             goto decode_success_vfp;
   10931          }
   10932          else if ((opc & BITS4(1,0,1,1)) == BITS4(0,0,0,0) && U == 0) {
   10933             index = (opc >> 2) & 1;
   10934             IRExpr* e = binop(Iop_GetElem32x2, getDRegI64(rN), mkU8(index));
   10935             if (isT)
   10936                putIRegT(rT, e, condT);
   10937             else
   10938                putIRegA(rT, e, condT, Ijk_Boring);
   10939             DIP("vmov%s.32 r%u, d%u[%u]\n", nCC(conq), rT, rN, index);
   10940             goto decode_success_vfp;
   10941          } else {
   10942             /* fall through */
   10943          }
   10944       }
   10945    }
   10946 
   10947    // VMOV.F32 sD, #imm
   10948    // FCONSTS sD, #imm
   10949    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   10950        && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,0)) {
   10951       UInt rD   = (INSN(15,12) << 1) | INSN(22,22);
   10952       UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
   10953       UInt b    = (imm8 >> 6) & 1;
   10954       UInt imm;
   10955       imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,(imm8 >> 5) & 1) << 8)
   10956              | ((imm8 & 0x1f) << 3);
   10957       imm <<= 16;
   10958       putFReg(rD, unop(Iop_ReinterpI32asF32, mkU32(imm)), condT);
   10959       DIP("fconsts%s s%u #%u", nCC(conq), rD, imm8);
   10960       goto decode_success_vfp;
   10961    }
   10962 
   10963    // VMOV.F64 dD, #imm
   10964    // FCONSTD dD, #imm
   10965    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   10966        && BITS4(0,0,0,0) == INSN(7,4) && INSN(11,8) == BITS4(1,0,1,1)) {
   10967       UInt rD   = INSN(15,12) | (INSN(22,22) << 4);
   10968       UInt imm8 = (INSN(19,16) << 4) | INSN(3,0);
   10969       UInt b    = (imm8 >> 6) & 1;
   10970       ULong imm;
   10971       imm = (BITS8((imm8 >> 7) & 1,(~b) & 1,b,b,b,b,b,b) << 8)
   10972              | BITS8(b,b,0,0,0,0,0,0) | (imm8 & 0x3f);
   10973       imm <<= 48;
   10974       putDReg(rD, unop(Iop_ReinterpI64asF64, mkU64(imm)), condT);
   10975       DIP("fconstd%s d%u #%u", nCC(conq), rD, imm8);
   10976       goto decode_success_vfp;
   10977    }
   10978 
   10979    /* ---------------------- vdup ------------------------- */
   10980    // VDUP dD, rT
   10981    // VDUP qD, rT
   10982    if (BITS8(1,1,1,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,1))
   10983        && BITS4(1,0,1,1) == INSN(11,8) && INSN(6,6) == 0 && INSN(4,4) == 1) {
   10984       UInt rD   = (INSN(7,7) << 4) | INSN(19,16);
   10985       UInt rT   = INSN(15,12);
   10986       UInt Q    = INSN(21,21);
   10987       UInt size = (INSN(22,22) << 1) | INSN(5,5);
   10988       if (rT == 15 || (isT && rT == 13) || size == 3 || (Q && (rD & 1))) {
   10989          /* fall through */
   10990       } else {
   10991          IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT);
   10992          if (Q) {
   10993             rD >>= 1;
   10994             switch (size) {
   10995                case 0:
   10996                   putQReg(rD, unop(Iop_Dup32x4, e), condT);
   10997                   break;
   10998                case 1:
   10999                   putQReg(rD, unop(Iop_Dup16x8, unop(Iop_32to16, e)),
   11000                               condT);
   11001                   break;
   11002                case 2:
   11003                   putQReg(rD, unop(Iop_Dup8x16, unop(Iop_32to8, e)),
   11004                               condT);
   11005                   break;
   11006                default:
   11007                   vassert(0);
   11008             }
   11009             DIP("vdup.%u q%u, r%u\n", 32 / (1<<size), rD, rT);
   11010          } else {
   11011             switch (size) {
   11012                case 0:
   11013                   putDRegI64(rD, unop(Iop_Dup32x2, e), condT);
   11014                   break;
   11015                case 1:
   11016                   putDRegI64(rD, unop(Iop_Dup16x4, unop(Iop_32to16, e)),
   11017                                condT);
   11018                   break;
   11019                case 2:
   11020                   putDRegI64(rD, unop(Iop_Dup8x8, unop(Iop_32to8, e)),
   11021                                condT);
   11022                   break;
   11023                default:
   11024                   vassert(0);
   11025             }
   11026             DIP("vdup.%u d%u, r%u\n", 32 / (1<<size), rD, rT);
   11027          }
   11028          goto decode_success_vfp;
   11029       }
   11030    }
   11031 
   11032    /* --------------------- f{ld,st}d --------------------- */
   11033    // FLDD, FSTD
   11034    if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
   11035        && BITS4(1,0,1,1) == INSN(11,8)) {
   11036       UInt dD     = INSN(15,12) | (INSN(22,22) << 4);
   11037       UInt rN     = INSN(19,16);
   11038       UInt offset = (insn28 & 0xFF) << 2;
   11039       UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
   11040       UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
   11041       /* make unconditional */
   11042       if (condT != IRTemp_INVALID) {
   11043          if (isT)
   11044             mk_skip_over_T32_if_cond_is_false( condT );
   11045          else
   11046             mk_skip_over_A32_if_cond_is_false( condT );
   11047          condT = IRTemp_INVALID;
   11048       }
   11049       IRTemp ea = newTemp(Ity_I32);
   11050       assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
   11051                        align4if(isT ? getIRegT(rN) : getIRegA(rN),
   11052                                 rN == 15),
   11053                        mkU32(offset)));
   11054       if (bL) {
   11055          putDReg(dD, loadLE(Ity_F64,mkexpr(ea)), IRTemp_INVALID);
   11056       } else {
   11057          storeLE(mkexpr(ea), getDReg(dD));
   11058       }
   11059       DIP("f%sd%s d%u, [r%u, %c#%u]\n",
   11060           bL ? "ld" : "st", nCC(conq), dD, rN,
   11061           bU ? '+' : '-', offset);
   11062       goto decode_success_vfp;
   11063    }
   11064 
   11065    /* --------------------- dp insns (D) --------------------- */
   11066    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
   11067        && BITS4(1,0,1,1) == INSN(11,8)
   11068        && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
   11069       UInt    dM  = INSN(3,0)   | (INSN(5,5) << 4);       /* argR */
   11070       UInt    dD  = INSN(15,12) | (INSN(22,22) << 4);   /* dst/acc */
   11071       UInt    dN  = INSN(19,16) | (INSN(7,7) << 4);     /* argL */
   11072       UInt    bP  = (insn28 >> 23) & 1;
   11073       UInt    bQ  = (insn28 >> 21) & 1;
   11074       UInt    bR  = (insn28 >> 20) & 1;
   11075       UInt    bS  = (insn28 >> 6) & 1;
   11076       UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
   11077       IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   11078       switch (opc) {
   11079          case BITS4(0,0,0,0): /* MAC: d + n * m */
   11080             putDReg(dD, triop(Iop_AddF64, rm,
   11081                               getDReg(dD),
   11082                               triop(Iop_MulF64, rm, getDReg(dN),
   11083                                                     getDReg(dM))),
   11084                         condT);
   11085             DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11086             goto decode_success_vfp;
   11087          case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
   11088             putDReg(dD, triop(Iop_AddF64, rm,
   11089                               getDReg(dD),
   11090                               unop(Iop_NegF64,
   11091                                    triop(Iop_MulF64, rm, getDReg(dN),
   11092                                                          getDReg(dM)))),
   11093                         condT);
   11094             DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11095             goto decode_success_vfp;
   11096          case BITS4(0,0,1,0): /* MSC: - d + n * m */
   11097             putDReg(dD, triop(Iop_AddF64, rm,
   11098                               unop(Iop_NegF64, getDReg(dD)),
   11099                               triop(Iop_MulF64, rm, getDReg(dN),
   11100                                                     getDReg(dM))),
   11101                         condT);
   11102             DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11103             goto decode_success_vfp;
   11104          case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
   11105             putDReg(dD, triop(Iop_AddF64, rm,
   11106                               unop(Iop_NegF64, getDReg(dD)),
   11107                               unop(Iop_NegF64,
   11108                                    triop(Iop_MulF64, rm, getDReg(dN),
   11109                                                          getDReg(dM)))),
   11110                         condT);
   11111             DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11112             goto decode_success_vfp;
   11113          case BITS4(0,1,0,0): /* MUL: n * m */
   11114             putDReg(dD, triop(Iop_MulF64, rm, getDReg(dN), getDReg(dM)),
   11115                         condT);
   11116             DIP("fmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11117             goto decode_success_vfp;
   11118          case BITS4(0,1,0,1): /* NMUL: - n * m */
   11119             putDReg(dD, unop(Iop_NegF64,
   11120                              triop(Iop_MulF64, rm, getDReg(dN),
   11121                                                    getDReg(dM))),
   11122                     condT);
   11123             DIP("fnmuld%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11124             goto decode_success_vfp;
   11125          case BITS4(0,1,1,0): /* ADD: n + m */
   11126             putDReg(dD, triop(Iop_AddF64, rm, getDReg(dN), getDReg(dM)),
   11127                         condT);
   11128             DIP("faddd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11129             goto decode_success_vfp;
   11130          case BITS4(0,1,1,1): /* SUB: n - m */
   11131             putDReg(dD, triop(Iop_SubF64, rm, getDReg(dN), getDReg(dM)),
   11132                         condT);
   11133             DIP("fsubd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11134             goto decode_success_vfp;
   11135          case BITS4(1,0,0,0): /* DIV: n / m */
   11136             putDReg(dD, triop(Iop_DivF64, rm, getDReg(dN), getDReg(dM)),
   11137                         condT);
   11138             DIP("fdivd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
   11139             goto decode_success_vfp;
   11140          default:
   11141             break;
   11142       }
   11143    }
   11144 
   11145    /* --------------------- compares (D) --------------------- */
   11146    /*          31   27   23   19   15 11   7    3
   11147                  28   24   20   16 12    8    4    0
   11148       FCMPD    cond 1110 1D11 0100 Dd 1011 0100 Dm
   11149       FCMPED   cond 1110 1D11 0100 Dd 1011 1100 Dm
   11150       FCMPZD   cond 1110 1D11 0101 Dd 1011 0100 0000
   11151       FCMPZED  cond 1110 1D11 0101 Dd 1011 1100 0000
   11152                                  Z         N
   11153 
   11154       Z=0 Compare Dd vs Dm     and set FPSCR 31:28 accordingly
   11155       Z=1 Compare Dd vs zero
   11156 
   11157       N=1 generates Invalid Operation exn if either arg is any kind of NaN
   11158       N=0 generates Invalid Operation exn if either arg is a signalling NaN
   11159       (Not that we pay any attention to N here)
   11160    */
   11161    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11162        && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11163        && BITS4(1,0,1,1) == INSN(11,8)
   11164        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11165       UInt bZ = (insn28 >> 16) & 1;
   11166       UInt bN = (insn28 >> 7) & 1;
   11167       UInt dD = INSN(15,12) | (INSN(22,22) << 4);
   11168       UInt dM = INSN(3,0) | (INSN(5,5) << 4);
   11169       if (bZ && INSN(3,0) != 0) {
   11170          /* does not decode; fall through */
   11171       } else {
   11172          IRTemp argL = newTemp(Ity_F64);
   11173          IRTemp argR = newTemp(Ity_F64);
   11174          IRTemp irRes = newTemp(Ity_I32);
   11175          assign(argL, getDReg(dD));
   11176          assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0)) : getDReg(dM));
   11177          assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
   11178 
   11179          IRTemp nzcv     = IRTemp_INVALID;
   11180          IRTemp oldFPSCR = newTemp(Ity_I32);
   11181          IRTemp newFPSCR = newTemp(Ity_I32);
   11182 
   11183          /* This is where the fun starts.  We have to convert 'irRes'
   11184             from an IR-convention return result (IRCmpF64Result) to an
   11185             ARM-encoded (N,Z,C,V) group.  The final result is in the
   11186             bottom 4 bits of 'nzcv'. */
   11187          /* Map compare result from IR to ARM(nzcv) */
   11188          /*
   11189             FP cmp result | IR   | ARM(nzcv)
   11190             --------------------------------
   11191             UN              0x45   0011
   11192             LT              0x01   1000
   11193             GT              0x00   0010
   11194             EQ              0x40   0110
   11195          */
   11196          nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
   11197 
   11198          /* And update FPSCR accordingly */
   11199          assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
   11200          assign(newFPSCR,
   11201                 binop(Iop_Or32,
   11202                       binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
   11203                       binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
   11204 
   11205          putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
   11206 
   11207          if (bZ) {
   11208             DIP("fcmpz%sd%s d%u\n", bN ? "e" : "", nCC(conq), dD);
   11209          } else {
   11210             DIP("fcmp%sd%s d%u, d%u\n", bN ? "e" : "", nCC(conq), dD, dM);
   11211          }
   11212          goto decode_success_vfp;
   11213       }
   11214       /* fall through */
   11215    }
   11216 
   11217    /* --------------------- unary (D) --------------------- */
   11218    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11219        && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11220        && BITS4(1,0,1,1) == INSN(11,8)
   11221        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11222       UInt dD  = INSN(15,12) | (INSN(22,22) << 4);
   11223       UInt dM  = INSN(3,0) | (INSN(5,5) << 4);
   11224       UInt b16 = (insn28 >> 16) & 1;
   11225       UInt b7  = (insn28 >> 7) & 1;
   11226       /**/ if (b16 == 0 && b7 == 0) {
   11227          // FCPYD
   11228          putDReg(dD, getDReg(dM), condT);
   11229          DIP("fcpyd%s d%u, d%u\n", nCC(conq), dD, dM);
   11230          goto decode_success_vfp;
   11231       }
   11232       else if (b16 == 0 && b7 == 1) {
   11233          // FABSD
   11234          putDReg(dD, unop(Iop_AbsF64, getDReg(dM)), condT);
   11235          DIP("fabsd%s d%u, d%u\n", nCC(conq), dD, dM);
   11236          goto decode_success_vfp;
   11237       }
   11238       else if (b16 == 1 && b7 == 0) {
   11239          // FNEGD
   11240          putDReg(dD, unop(Iop_NegF64, getDReg(dM)), condT);
   11241          DIP("fnegd%s d%u, d%u\n", nCC(conq), dD, dM);
   11242          goto decode_success_vfp;
   11243       }
   11244       else if (b16 == 1 && b7 == 1) {
   11245          // FSQRTD
   11246          IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   11247          putDReg(dD, binop(Iop_SqrtF64, rm, getDReg(dM)), condT);
   11248          DIP("fsqrtd%s d%u, d%u\n", nCC(conq), dD, dM);
   11249          goto decode_success_vfp;
   11250       }
   11251       else
   11252          vassert(0);
   11253 
   11254       /* fall through */
   11255    }
   11256 
   11257    /* ----------------- I <-> D conversions ----------------- */
   11258 
   11259    // F{S,U}ITOD dD, fM
   11260    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11261        && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
   11262        && BITS4(1,0,1,1) == INSN(11,8)
   11263        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11264       UInt bM    = (insn28 >> 5) & 1;
   11265       UInt fM    = (INSN(3,0) << 1) | bM;
   11266       UInt dD    = INSN(15,12) | (INSN(22,22) << 4);
   11267       UInt syned = (insn28 >> 7) & 1;
   11268       if (syned) {
   11269          // FSITOD
   11270          putDReg(dD, unop(Iop_I32StoF64,
   11271                           unop(Iop_ReinterpF32asI32, getFReg(fM))),
   11272                  condT);
   11273          DIP("fsitod%s d%u, s%u\n", nCC(conq), dD, fM);
   11274       } else {
   11275          // FUITOD
   11276          putDReg(dD, unop(Iop_I32UtoF64,
   11277                           unop(Iop_ReinterpF32asI32, getFReg(fM))),
   11278                  condT);
   11279          DIP("fuitod%s d%u, s%u\n", nCC(conq), dD, fM);
   11280       }
   11281       goto decode_success_vfp;
   11282    }
   11283 
   11284    // FTO{S,U}ID fD, dM
   11285    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11286        && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11287        && BITS4(1,0,1,1) == INSN(11,8)
   11288        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11289       UInt   bD    = (insn28 >> 22) & 1;
   11290       UInt   fD    = (INSN(15,12) << 1) | bD;
   11291       UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
   11292       UInt   bZ    = (insn28 >> 7) & 1;
   11293       UInt   syned = (insn28 >> 16) & 1;
   11294       IRTemp rmode = newTemp(Ity_I32);
   11295       assign(rmode, bZ ? mkU32(Irrm_ZERO)
   11296                        : mkexpr(mk_get_IR_rounding_mode()));
   11297       if (syned) {
   11298          // FTOSID
   11299          putFReg(fD, unop(Iop_ReinterpI32asF32,
   11300                           binop(Iop_F64toI32S, mkexpr(rmode),
   11301                                 getDReg(dM))),
   11302                  condT);
   11303          DIP("ftosi%sd%s s%u, d%u\n", bZ ? "z" : "",
   11304              nCC(conq), fD, dM);
   11305       } else {
   11306          // FTOUID
   11307          putFReg(fD, unop(Iop_ReinterpI32asF32,
   11308                           binop(Iop_F64toI32U, mkexpr(rmode),
   11309                                 getDReg(dM))),
   11310                  condT);
   11311          DIP("ftoui%sd%s s%u, d%u\n", bZ ? "z" : "",
   11312              nCC(conq), fD, dM);
   11313       }
   11314       goto decode_success_vfp;
   11315    }
   11316 
   11317    /* ----------------------------------------------------------- */
   11318    /* -- VFP instructions -- single precision                  -- */
   11319    /* ----------------------------------------------------------- */
   11320 
   11321    /* --------------------- fldms, fstms --------------------- */
   11322    /*
   11323                                  31   27   23   19 15 11   7   0
   11324                                          P UDWL
   11325       C4-98, C5-26   1  FSTMD    cond 1100 1x00 Rn Fd 1010 offset
   11326       C4-98, C5-28   2  FSTMDIA  cond 1100 1x10 Rn Fd 1010 offset
   11327       C4-98, C5-30   3  FSTMDDB  cond 1101 0x10 Rn Fd 1010 offset
   11328 
   11329       C4-40, C5-26   1  FLDMD    cond 1100 1x01 Rn Fd 1010 offset
   11330       C4-40, C5-26   2  FLDMIAD  cond 1100 1x11 Rn Fd 1010 offset
   11331       C4-40, C5-26   3  FLDMDBD  cond 1101 0x11 Rn Fd 1010 offset
   11332 
   11333       Regs transferred: F(Fd:D) .. F(Fd:d + offset)
   11334       offset must not imply a reg > 15
   11335       IA/DB: Rn is changed by (4 x # regs transferred)
   11336 
   11337       case coding:
   11338          1  at-Rn   (access at Rn)
   11339          2  ia-Rn   (access at Rn, then Rn += 4n)
   11340          3  db-Rn   (Rn -= 4n,     then access at Rn)
   11341    */
   11342    if (BITS8(1,1,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))
   11343        && INSN(11,8) == BITS4(1,0,1,0)) {
   11344       UInt bP      = (insn28 >> 24) & 1;
   11345       UInt bU      = (insn28 >> 23) & 1;
   11346       UInt bW      = (insn28 >> 21) & 1;
   11347       UInt bL      = (insn28 >> 20) & 1;
   11348       UInt bD      = (insn28 >> 22) & 1;
   11349       UInt offset  = (insn28 >> 0) & 0xFF;
   11350       UInt rN      = INSN(19,16);
   11351       UInt fD      = (INSN(15,12) << 1) | bD;
   11352       UInt nRegs   = offset;
   11353       UInt summary = 0;
   11354       Int  i;
   11355 
   11356       /**/ if (bP == 0 && bU == 1 && bW == 0) {
   11357          summary = 1;
   11358       }
   11359       else if (bP == 0 && bU == 1 && bW == 1) {
   11360          summary = 2;
   11361       }
   11362       else if (bP == 1 && bU == 0 && bW == 1) {
   11363          summary = 3;
   11364       }
   11365       else goto after_vfp_fldms_fstms;
   11366 
   11367       /* no writebacks to r15 allowed.  No use of r15 in thumb mode. */
   11368       if (rN == 15 && (summary == 2 || summary == 3 || isT))
   11369          goto after_vfp_fldms_fstms;
   11370 
   11371       /* offset must specify at least one register */
   11372       if (offset < 1)
   11373          goto after_vfp_fldms_fstms;
   11374 
   11375       /* can't transfer regs after S31 */
   11376       if (fD + nRegs - 1 >= 32)
   11377          goto after_vfp_fldms_fstms;
   11378 
   11379       /* Now, we can't do a conditional load or store, since that very
   11380          likely will generate an exception.  So we have to take a side
   11381          exit at this point if the condition is false. */
   11382       if (condT != IRTemp_INVALID) {
   11383          if (isT)
   11384             mk_skip_over_T32_if_cond_is_false( condT );
   11385          else
   11386             mk_skip_over_A32_if_cond_is_false( condT );
   11387          condT = IRTemp_INVALID;
   11388       }
   11389       /* Ok, now we're unconditional.  Do the load or store. */
   11390 
   11391       /* get the old Rn value */
   11392       IRTemp rnT = newTemp(Ity_I32);
   11393       assign(rnT, align4if(isT ? getIRegT(rN) : getIRegA(rN),
   11394                            rN == 15));
   11395 
   11396       /* make a new value for Rn, post-insn */
   11397       IRTemp rnTnew = IRTemp_INVALID;
   11398       if (summary == 2 || summary == 3) {
   11399          rnTnew = newTemp(Ity_I32);
   11400          assign(rnTnew, binop(summary == 2 ? Iop_Add32 : Iop_Sub32,
   11401                               mkexpr(rnT),
   11402                               mkU32(4 * nRegs)));
   11403       }
   11404 
   11405       /* decide on the base transfer address */
   11406       IRTemp taT = newTemp(Ity_I32);
   11407       assign(taT, summary == 3 ? mkexpr(rnTnew) : mkexpr(rnT));
   11408 
   11409       /* update Rn if necessary -- in case 3, we're moving it down, so
   11410          update before any memory reference, in order to keep Memcheck
   11411          and V's stack-extending logic (on linux) happy */
   11412       if (summary == 3) {
   11413          if (isT)
   11414             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   11415          else
   11416             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   11417       }
   11418 
   11419       /* generate the transfers */
   11420       for (i = 0; i < nRegs; i++) {
   11421          IRExpr* addr = binop(Iop_Add32, mkexpr(taT), mkU32(4*i));
   11422          if (bL) {
   11423             putFReg(fD + i, loadLE(Ity_F32, addr), IRTemp_INVALID);
   11424          } else {
   11425             storeLE(addr, getFReg(fD + i));
   11426          }
   11427       }
   11428 
   11429       /* update Rn if necessary -- in case 2, we're moving it up, so
   11430          update after any memory reference, in order to keep Memcheck
   11431          and V's stack-extending logic (on linux) happy */
   11432       if (summary == 2) {
   11433          if (isT)
   11434             putIRegT(rN, mkexpr(rnTnew), IRTemp_INVALID);
   11435          else
   11436             putIRegA(rN, mkexpr(rnTnew), IRTemp_INVALID, Ijk_Boring);
   11437       }
   11438 
   11439       HChar* nm = bL==1 ? "ld" : "st";
   11440       switch (summary) {
   11441          case 1:  DIP("f%sms%s r%u, {s%u-s%u}\n",
   11442                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
   11443                   break;
   11444          case 2:  DIP("f%smias%s r%u!, {s%u-s%u}\n",
   11445                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
   11446                   break;
   11447          case 3:  DIP("f%smdbs%s r%u!, {s%u-s%u}\n",
   11448                       nm, nCC(conq), rN, fD, fD + nRegs - 1);
   11449                   break;
   11450          default: vassert(0);
   11451       }
   11452 
   11453       goto decode_success_vfp;
   11454       /* FIXME alignment constraints? */
   11455    }
   11456 
   11457   after_vfp_fldms_fstms:
   11458 
   11459    /* --------------------- fmsr, fmrs --------------------- */
   11460    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
   11461        && BITS4(1,0,1,0) == INSN(11,8)
   11462        && BITS4(0,0,0,0) == INSN(3,0)
   11463        && BITS4(0,0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
   11464       UInt rD  = INSN(15,12);
   11465       UInt b7  = (insn28 >> 7) & 1;
   11466       UInt fN  = (INSN(19,16) << 1) | b7;
   11467       UInt b20 = (insn28 >> 20) & 1;
   11468       if (rD == 15) {
   11469          /* fall through */
   11470          /* Let's assume that no sane person would want to do
   11471             floating-point transfers to or from the program counter,
   11472             and simply decline to decode the instruction.  The ARM ARM
   11473             doesn't seem to explicitly disallow this case, though. */
   11474       } else {
   11475          if (b20) {
   11476             IRExpr* res = unop(Iop_ReinterpF32asI32, getFReg(fN));
   11477             if (isT)
   11478                putIRegT(rD, res, condT);
   11479             else
   11480                putIRegA(rD, res, condT, Ijk_Boring);
   11481             DIP("fmrs%s r%u, s%u\n", nCC(conq), rD, fN);
   11482          } else {
   11483             putFReg(fN, unop(Iop_ReinterpI32asF32,
   11484                              isT ? getIRegT(rD) : getIRegA(rD)),
   11485                         condT);
   11486             DIP("fmsr%s s%u, r%u\n", nCC(conq), fN, rD);
   11487          }
   11488          goto decode_success_vfp;
   11489       }
   11490       /* fall through */
   11491    }
   11492 
   11493    /* --------------------- f{ld,st}s --------------------- */
   11494    // FLDS, FSTS
   11495    if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
   11496        && BITS4(1,0,1,0) == INSN(11,8)) {
   11497       UInt bD     = (insn28 >> 22) & 1;
   11498       UInt fD     = (INSN(15,12) << 1) | bD;
   11499       UInt rN     = INSN(19,16);
   11500       UInt offset = (insn28 & 0xFF) << 2;
   11501       UInt bU     = (insn28 >> 23) & 1; /* 1: +offset  0: -offset */
   11502       UInt bL     = (insn28 >> 20) & 1; /* 1: load  0: store */
   11503       /* make unconditional */
   11504       if (condT != IRTemp_INVALID) {
   11505          if (isT)
   11506             mk_skip_over_T32_if_cond_is_false( condT );
   11507          else
   11508             mk_skip_over_A32_if_cond_is_false( condT );
   11509          condT = IRTemp_INVALID;
   11510       }
   11511       IRTemp ea = newTemp(Ity_I32);
   11512       assign(ea, binop(bU ? Iop_Add32 : Iop_Sub32,
   11513                        align4if(isT ? getIRegT(rN) : getIRegA(rN),
   11514                                 rN == 15),
   11515                        mkU32(offset)));
   11516       if (bL) {
   11517          putFReg(fD, loadLE(Ity_F32,mkexpr(ea)), IRTemp_INVALID);
   11518       } else {
   11519          storeLE(mkexpr(ea), getFReg(fD));
   11520       }
   11521       DIP("f%ss%s s%u, [r%u, %c#%u]\n",
   11522           bL ? "ld" : "st", nCC(conq), fD, rN,
   11523           bU ? '+' : '-', offset);
   11524       goto decode_success_vfp;
   11525    }
   11526 
   11527    /* --------------------- dp insns (F) --------------------- */
   11528    if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
   11529        && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
   11530        && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
   11531       UInt    bM  = (insn28 >> 5) & 1;
   11532       UInt    bD  = (insn28 >> 22) & 1;
   11533       UInt    bN  = (insn28 >> 7) & 1;
   11534       UInt    fM  = (INSN(3,0) << 1) | bM;   /* argR */
   11535       UInt    fD  = (INSN(15,12) << 1) | bD; /* dst/acc */
   11536       UInt    fN  = (INSN(19,16) << 1) | bN; /* argL */
   11537       UInt    bP  = (insn28 >> 23) & 1;
   11538       UInt    bQ  = (insn28 >> 21) & 1;
   11539       UInt    bR  = (insn28 >> 20) & 1;
   11540       UInt    bS  = (insn28 >> 6) & 1;
   11541       UInt    opc = (bP << 3) | (bQ << 2) | (bR << 1) | bS;
   11542       IRExpr* rm  = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   11543       switch (opc) {
   11544          case BITS4(0,0,0,0): /* MAC: d + n * m */
   11545             putFReg(fD, triop(Iop_AddF32, rm,
   11546                               getFReg(fD),
   11547                               triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
   11548                         condT);
   11549             DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11550             goto decode_success_vfp;
   11551          case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
   11552             putFReg(fD, triop(Iop_AddF32, rm,
   11553                               getFReg(fD),
   11554                               unop(Iop_NegF32,
   11555                                    triop(Iop_MulF32, rm, getFReg(fN),
   11556                                                          getFReg(fM)))),
   11557                         condT);
   11558             DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11559             goto decode_success_vfp;
   11560          case BITS4(0,0,1,0): /* MSC: - d + n * m */
   11561             putFReg(fD, triop(Iop_AddF32, rm,
   11562                               unop(Iop_NegF32, getFReg(fD)),
   11563                               triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
   11564                         condT);
   11565             DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11566             goto decode_success_vfp;
   11567          case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
   11568             putFReg(fD, triop(Iop_AddF32, rm,
   11569                               unop(Iop_NegF32, getFReg(fD)),
   11570                               unop(Iop_NegF32,
   11571                                    triop(Iop_MulF32, rm,
   11572                                                      getFReg(fN),
   11573                                                     getFReg(fM)))),
   11574                         condT);
   11575             DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11576             goto decode_success_vfp;
   11577          case BITS4(0,1,0,0): /* MUL: n * m */
   11578             putFReg(fD, triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM)),
   11579                         condT);
   11580             DIP("fmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11581             goto decode_success_vfp;
   11582          case BITS4(0,1,0,1): /* NMUL: - n * m */
   11583             putFReg(fD, unop(Iop_NegF32,
   11584                              triop(Iop_MulF32, rm, getFReg(fN),
   11585                                                    getFReg(fM))),
   11586                     condT);
   11587             DIP("fnmuls%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11588             goto decode_success_vfp;
   11589          case BITS4(0,1,1,0): /* ADD: n + m */
   11590             putFReg(fD, triop(Iop_AddF32, rm, getFReg(fN), getFReg(fM)),
   11591                         condT);
   11592             DIP("fadds%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11593             goto decode_success_vfp;
   11594          case BITS4(0,1,1,1): /* SUB: n - m */
   11595             putFReg(fD, triop(Iop_SubF32, rm, getFReg(fN), getFReg(fM)),
   11596                         condT);
   11597             DIP("fsubs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11598             goto decode_success_vfp;
   11599          case BITS4(1,0,0,0): /* DIV: n / m */
   11600             putFReg(fD, triop(Iop_DivF32, rm, getFReg(fN), getFReg(fM)),
   11601                         condT);
   11602             DIP("fdivs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
   11603             goto decode_success_vfp;
   11604          default:
   11605             break;
   11606       }
   11607    }
   11608 
   11609    /* --------------------- compares (S) --------------------- */
   11610    /*          31   27   23   19   15 11   7    3
   11611                  28   24   20   16 12    8    4    0
   11612       FCMPS    cond 1110 1D11 0100 Fd 1010 01M0 Fm
   11613       FCMPES   cond 1110 1D11 0100 Fd 1010 11M0 Fm
   11614       FCMPZS   cond 1110 1D11 0101 Fd 1010 0100 0000
   11615       FCMPZED  cond 1110 1D11 0101 Fd 1010 1100 0000
   11616                                  Z         N
   11617 
   11618       Z=0 Compare Fd:D vs Fm:M     and set FPSCR 31:28 accordingly
   11619       Z=1 Compare Fd:D vs zero
   11620 
   11621       N=1 generates Invalid Operation exn if either arg is any kind of NaN
   11622       N=0 generates Invalid Operation exn if either arg is a signalling NaN
   11623       (Not that we pay any attention to N here)
   11624    */
   11625    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11626        && BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11627        && BITS4(1,0,1,0) == INSN(11,8)
   11628        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11629       UInt bZ = (insn28 >> 16) & 1;
   11630       UInt bN = (insn28 >> 7) & 1;
   11631       UInt bD = (insn28 >> 22) & 1;
   11632       UInt bM = (insn28 >> 5) & 1;
   11633       UInt fD = (INSN(15,12) << 1) | bD;
   11634       UInt fM = (INSN(3,0) << 1) | bM;
   11635       if (bZ && (INSN(3,0) != 0 || (INSN(7,4) & 3) != 0)) {
   11636          /* does not decode; fall through */
   11637       } else {
   11638          IRTemp argL = newTemp(Ity_F64);
   11639          IRTemp argR = newTemp(Ity_F64);
   11640          IRTemp irRes = newTemp(Ity_I32);
   11641 
   11642          assign(argL, unop(Iop_F32toF64, getFReg(fD)));
   11643          assign(argR, bZ ? IRExpr_Const(IRConst_F64i(0))
   11644                          : unop(Iop_F32toF64, getFReg(fM)));
   11645          assign(irRes, binop(Iop_CmpF64, mkexpr(argL), mkexpr(argR)));
   11646 
   11647          IRTemp nzcv     = IRTemp_INVALID;
   11648          IRTemp oldFPSCR = newTemp(Ity_I32);
   11649          IRTemp newFPSCR = newTemp(Ity_I32);
   11650 
   11651          /* This is where the fun starts.  We have to convert 'irRes'
   11652             from an IR-convention return result (IRCmpF64Result) to an
   11653             ARM-encoded (N,Z,C,V) group.  The final result is in the
   11654             bottom 4 bits of 'nzcv'. */
   11655          /* Map compare result from IR to ARM(nzcv) */
   11656          /*
   11657             FP cmp result | IR   | ARM(nzcv)
   11658             --------------------------------
   11659             UN              0x45   0011
   11660             LT              0x01   1000
   11661             GT              0x00   0010
   11662             EQ              0x40   0110
   11663          */
   11664          nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
   11665 
   11666          /* And update FPSCR accordingly */
   11667          assign(oldFPSCR, IRExpr_Get(OFFB_FPSCR, Ity_I32));
   11668          assign(newFPSCR,
   11669                 binop(Iop_Or32,
   11670                       binop(Iop_And32, mkexpr(oldFPSCR), mkU32(0x0FFFFFFF)),
   11671                       binop(Iop_Shl32, mkexpr(nzcv), mkU8(28))));
   11672 
   11673          putMiscReg32(OFFB_FPSCR, mkexpr(newFPSCR), condT);
   11674 
   11675          if (bZ) {
   11676             DIP("fcmpz%ss%s s%u\n", bN ? "e" : "", nCC(conq), fD);
   11677          } else {
   11678             DIP("fcmp%ss%s s%u, s%u\n", bN ? "e" : "",
   11679                 nCC(conq), fD, fM);
   11680          }
   11681          goto decode_success_vfp;
   11682       }
   11683       /* fall through */
   11684    }
   11685 
   11686    /* --------------------- unary (S) --------------------- */
   11687    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11688        && BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11689        && BITS4(1,0,1,0) == INSN(11,8)
   11690        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11691       UInt bD = (insn28 >> 22) & 1;
   11692       UInt bM = (insn28 >> 5) & 1;
   11693       UInt fD  = (INSN(15,12) << 1) | bD;
   11694       UInt fM  = (INSN(3,0) << 1) | bM;
   11695       UInt b16 = (insn28 >> 16) & 1;
   11696       UInt b7  = (insn28 >> 7) & 1;
   11697       /**/ if (b16 == 0 && b7 == 0) {
   11698          // FCPYS
   11699          putFReg(fD, getFReg(fM), condT);
   11700          DIP("fcpys%s s%u, s%u\n", nCC(conq), fD, fM);
   11701          goto decode_success_vfp;
   11702       }
   11703       else if (b16 == 0 && b7 == 1) {
   11704          // FABSS
   11705          putFReg(fD, unop(Iop_AbsF32, getFReg(fM)), condT);
   11706          DIP("fabss%s s%u, s%u\n", nCC(conq), fD, fM);
   11707          goto decode_success_vfp;
   11708       }
   11709       else if (b16 == 1 && b7 == 0) {
   11710          // FNEGS
   11711          putFReg(fD, unop(Iop_NegF32, getFReg(fM)), condT);
   11712          DIP("fnegs%s s%u, s%u\n", nCC(conq), fD, fM);
   11713          goto decode_success_vfp;
   11714       }
   11715       else if (b16 == 1 && b7 == 1) {
   11716          // FSQRTS
   11717          IRExpr* rm = get_FAKE_roundingmode(); /* XXXROUNDINGFIXME */
   11718          putFReg(fD, binop(Iop_SqrtF32, rm, getFReg(fM)), condT);
   11719          DIP("fsqrts%s s%u, s%u\n", nCC(conq), fD, fM);
   11720          goto decode_success_vfp;
   11721       }
   11722       else
   11723          vassert(0);
   11724 
   11725       /* fall through */
   11726    }
   11727 
   11728    /* ----------------- I <-> S conversions ----------------- */
   11729 
   11730    // F{S,U}ITOS fD, fM
   11731    /* These are more complex than FSITOD/FUITOD.  In the D cases, a 32
   11732       bit int will always fit within the 53 bit mantissa, so there's
   11733       no possibility of a loss of precision, but that's obviously not
   11734       the case here.  Hence this case possibly requires rounding, and
   11735       so it drags in the current rounding mode. */
   11736    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11737        && BITS4(1,0,0,0) == INSN(19,16)
   11738        && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
   11739        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11740       UInt bM    = (insn28 >> 5) & 1;
   11741       UInt bD    = (insn28 >> 22) & 1;
   11742       UInt fM    = (INSN(3,0) << 1) | bM;
   11743       UInt fD    = (INSN(15,12) << 1) | bD;
   11744       UInt syned = (insn28 >> 7) & 1;
   11745       IRTemp rmode = newTemp(Ity_I32);
   11746       assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
   11747       if (syned) {
   11748          // FSITOS
   11749          putFReg(fD, binop(Iop_F64toF32,
   11750                            mkexpr(rmode),
   11751                            unop(Iop_I32StoF64,
   11752                                 unop(Iop_ReinterpF32asI32, getFReg(fM)))),
   11753                  condT);
   11754          DIP("fsitos%s s%u, s%u\n", nCC(conq), fD, fM);
   11755       } else {
   11756          // FUITOS
   11757          putFReg(fD, binop(Iop_F64toF32,
   11758                            mkexpr(rmode),
   11759                            unop(Iop_I32UtoF64,
   11760                                 unop(Iop_ReinterpF32asI32, getFReg(fM)))),
   11761                  condT);
   11762          DIP("fuitos%s s%u, s%u\n", nCC(conq), fD, fM);
   11763       }
   11764       goto decode_success_vfp;
   11765    }
   11766 
   11767    // FTO{S,U}IS fD, fM
   11768    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11769        && BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
   11770        && BITS4(1,0,1,0) == INSN(11,8)
   11771        && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
   11772       UInt   bM    = (insn28 >> 5) & 1;
   11773       UInt   bD    = (insn28 >> 22) & 1;
   11774       UInt   fD    = (INSN(15,12) << 1) | bD;
   11775       UInt   fM    = (INSN(3,0) << 1) | bM;
   11776       UInt   bZ    = (insn28 >> 7) & 1;
   11777       UInt   syned = (insn28 >> 16) & 1;
   11778       IRTemp rmode = newTemp(Ity_I32);
   11779       assign(rmode, bZ ? mkU32(Irrm_ZERO)
   11780                        : mkexpr(mk_get_IR_rounding_mode()));
   11781       if (syned) {
   11782          // FTOSIS
   11783          putFReg(fD, unop(Iop_ReinterpI32asF32,
   11784                           binop(Iop_F64toI32S, mkexpr(rmode),
   11785                                 unop(Iop_F32toF64, getFReg(fM)))),
   11786                  condT);
   11787          DIP("ftosi%ss%s s%u, d%u\n", bZ ? "z" : "",
   11788              nCC(conq), fD, fM);
   11789          goto decode_success_vfp;
   11790       } else {
   11791          // FTOUIS
   11792          putFReg(fD, unop(Iop_ReinterpI32asF32,
   11793                           binop(Iop_F64toI32U, mkexpr(rmode),
   11794                                 unop(Iop_F32toF64, getFReg(fM)))),
   11795                  condT);
   11796          DIP("ftoui%ss%s s%u, d%u\n", bZ ? "z" : "",
   11797              nCC(conq), fD, fM);
   11798          goto decode_success_vfp;
   11799       }
   11800    }
   11801 
   11802    /* ----------------- S <-> D conversions ----------------- */
   11803 
   11804    // FCVTDS
   11805    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11806        && BITS4(0,1,1,1) == INSN(19,16)
   11807        && BITS4(1,0,1,0) == INSN(11,8)
   11808        && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
   11809       UInt dD = INSN(15,12) | (INSN(22,22) << 4);
   11810       UInt bM = (insn28 >> 5) & 1;
   11811       UInt fM = (INSN(3,0) << 1) | bM;
   11812       putDReg(dD, unop(Iop_F32toF64, getFReg(fM)), condT);
   11813       DIP("fcvtds%s d%u, s%u\n", nCC(conq), dD, fM);
   11814       goto decode_success_vfp;
   11815    }
   11816 
   11817    // FCVTSD
   11818    if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   11819        && BITS4(0,1,1,1) == INSN(19,16)
   11820        && BITS4(1,0,1,1) == INSN(11,8)
   11821        && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
   11822       UInt   bD    = (insn28 >> 22) & 1;
   11823       UInt   fD    = (INSN(15,12) << 1) | bD;
   11824       UInt   dM    = INSN(3,0) | (INSN(5,5) << 4);
   11825       IRTemp rmode = newTemp(Ity_I32);
   11826       assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
   11827       putFReg(fD, binop(Iop_F64toF32, mkexpr(rmode), getDReg(dM)),
   11828                   condT);
   11829       DIP("fcvtsd%s s%u, d%u\n", nCC(conq), fD, dM);
   11830       goto decode_success_vfp;
   11831    }
   11832 
   11833    /* FAILURE */
   11834    return False;
   11835 
   11836   decode_success_vfp:
   11837    /* Check that any accepted insn really is a CP10 or CP11 insn, iow,
   11838       assert that we aren't accepting, in this fn, insns that actually
   11839       should be handled somewhere else. */
   11840    vassert(INSN(11,9) == BITS3(1,0,1)); // 11:8 = 1010 or 1011
   11841    return True;
   11842 
   11843 #  undef INSN
   11844 }
   11845 
   11846 
   11847 /*------------------------------------------------------------*/
   11848 /*--- Instructions in NV (never) space                     ---*/
   11849 /*------------------------------------------------------------*/
   11850 
   11851 /* ARM only */
   11852 /* Translate a NV space instruction.  If successful, returns True and
   11853    *dres may or may not be updated.  If failure, returns False and
   11854    doesn't change *dres nor create any IR.
   11855 
   11856    Note that all NEON instructions (in ARM mode) are handled through
   11857    here, since they are all in NV space.
   11858 */
   11859 static Bool decode_NV_instruction ( /*MOD*/DisResult* dres,
   11860                                     VexArchInfo* archinfo,
   11861                                     UInt insn )
   11862 {
   11863 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
   11864 #  define INSN_COND          SLICE_UInt(insn, 31, 28)
   11865 
   11866    HChar dis_buf[128];
   11867 
   11868    // Should only be called for NV instructions
   11869    vassert(BITS4(1,1,1,1) == INSN_COND);
   11870 
   11871    /* ------------------------ pld ------------------------ */
   11872    if (BITS8(0,1,0,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
   11873        && BITS4(1,1,1,1) == INSN(15,12)) {
   11874       UInt rN    = INSN(19,16);
   11875       UInt imm12 = INSN(11,0);
   11876       UInt bU    = INSN(23,23);
   11877       DIP("pld [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
   11878       return True;
   11879    }
   11880 
   11881    if (BITS8(0,1,1,1, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
   11882        && BITS4(1,1,1,1) == INSN(15,12)
   11883        && 0 == INSN(4,4)) {
   11884       UInt rN   = INSN(19,16);
   11885       UInt rM   = INSN(3,0);
   11886       UInt imm5 = INSN(11,7);
   11887       UInt sh2  = INSN(6,5);
   11888       UInt bU   = INSN(23,23);
   11889       if (rM != 15) {
   11890          IRExpr* eaE = mk_EA_reg_plusminus_shifted_reg(rN, bU, rM,
   11891                                                        sh2, imm5, dis_buf);
   11892          IRTemp eaT = newTemp(Ity_I32);
   11893          /* Bind eaE to a temp merely for debugging-vex purposes, so we
   11894             can check it's a plausible decoding.  It will get removed
   11895             by iropt a little later on. */
   11896          vassert(eaE);
   11897          assign(eaT, eaE);
   11898          DIP("pld %s\n", dis_buf);
   11899          return True;
   11900       }
   11901       /* fall through */
   11902    }
   11903 
   11904    /* ------------------------ pli ------------------------ */
   11905    if (BITS8(0,1,0,0, 0, 1,0,1) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,1))
   11906        && BITS4(1,1,1,1) == INSN(15,12)) {
   11907       UInt rN    = INSN(19,16);
   11908       UInt imm12 = INSN(11,0);
   11909       UInt bU    = INSN(23,23);
   11910       DIP("pli [r%u, #%c%u]\n", rN, bU ? '+' : '-', imm12);
   11911       return True;
   11912    }
   11913 
   11914    /* --------------------- Interworking branches --------------------- */
   11915 
   11916    // BLX (1), viz, unconditional branch and link to R15+simm24
   11917    // and set CPSR.T = 1, that is, switch to Thumb mode
   11918    if (INSN(31,25) == BITS7(1,1,1,1,1,0,1)) {
   11919       UInt bitH   = INSN(24,24);
   11920       Int  uimm24 = INSN(23,0);
   11921       Int  simm24 = (((uimm24 << 8) >> 8) << 2) + (bitH << 1);
   11922       /* Now this is a bit tricky.  Since we're decoding an ARM insn,
   11923          it is implies that CPSR.T == 0.  Hence the current insn's
   11924          address is guaranteed to be of the form X--(30)--X00.  So, no
   11925          need to mask any bits off it.  But need to set the lowest bit
   11926          to 1 to denote we're in Thumb mode after this, since
   11927          guest_R15T has CPSR.T as the lowest bit.  And we can't chase
   11928          into the call, so end the block at this point. */
   11929       UInt dst = guest_R15_curr_instr_notENC + 8 + (simm24 | 1);
   11930       putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
   11931                     IRTemp_INVALID/*because AL*/, Ijk_Boring );
   11932       irsb->next     = mkU32(dst);
   11933       irsb->jumpkind = Ijk_Call;
   11934       dres->whatNext = Dis_StopHere;
   11935       DIP("blx 0x%x (and switch to Thumb mode)\n", dst - 1);
   11936       return True;
   11937    }
   11938 
   11939    /* ------------------- v7 barrier insns ------------------- */
   11940    switch (insn) {
   11941       case 0xF57FF06F: /* ISB */
   11942          stmt( IRStmt_MBE(Imbe_Fence) );
   11943          DIP("ISB\n");
   11944          return True;
   11945       case 0xF57FF04F: /* DSB sy */
   11946       case 0xF57FF04E: /* DSB st */
   11947       case 0xF57FF04B: /* DSB ish */
   11948       case 0xF57FF04A: /* DSB ishst */
   11949       case 0xF57FF047: /* DSB nsh */
   11950       case 0xF57FF046: /* DSB nshst */
   11951       case 0xF57FF043: /* DSB osh */
   11952       case 0xF57FF042: /* DSB oshst */
   11953          stmt( IRStmt_MBE(Imbe_Fence) );
   11954          DIP("DSB\n");
   11955          return True;
   11956       case 0xF57FF05F: /* DMB sy */
   11957       case 0xF57FF05E: /* DMB st */
   11958       case 0xF57FF05B: /* DMB ish */
   11959       case 0xF57FF05A: /* DMB ishst */
   11960       case 0xF57FF057: /* DMB nsh */
   11961       case 0xF57FF056: /* DMB nshst */
   11962       case 0xF57FF053: /* DMB osh */
   11963       case 0xF57FF052: /* DMB oshst */
   11964          stmt( IRStmt_MBE(Imbe_Fence) );
   11965          DIP("DMB\n");
   11966          return True;
   11967       default:
   11968          break;
   11969    }
   11970 
   11971    /* ------------------- NEON ------------------- */
   11972    if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
   11973       Bool ok_neon = decode_NEON_instruction(
   11974                         dres, insn, IRTemp_INVALID/*unconditional*/,
   11975                         False/*!isT*/
   11976                      );
   11977       if (ok_neon)
   11978          return True;
   11979    }
   11980 
   11981    // unrecognised
   11982    return False;
   11983 
   11984 #  undef INSN_COND
   11985 #  undef INSN
   11986 }
   11987 
   11988 
   11989 /*------------------------------------------------------------*/
   11990 /*--- Disassemble a single ARM instruction                 ---*/
   11991 /*------------------------------------------------------------*/
   11992 
   11993 /* Disassemble a single ARM instruction into IR.  The instruction is
   11994    located in host memory at guest_instr, and has (decoded) guest IP
   11995    of guest_R15_curr_instr_notENC, which will have been set before the
   11996    call here. */
   11997 
   11998 static
   11999 DisResult disInstr_ARM_WRK (
   12000              Bool         put_IP,
   12001              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
   12002              Bool         resteerCisOk,
   12003              void*        callback_opaque,
   12004              UChar*       guest_instr,
   12005              VexArchInfo* archinfo,
   12006              VexAbiInfo*  abiinfo
   12007           )
   12008 {
   12009    // A macro to fish bits out of 'insn'.
   12010 #  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
   12011 #  define INSN_COND          SLICE_UInt(insn, 31, 28)
   12012 
   12013    DisResult dres;
   12014    UInt      insn;
   12015    //Bool      allow_VFP = False;
   12016    //UInt      hwcaps = archinfo->hwcaps;
   12017    IRTemp    condT; /* :: Ity_I32 */
   12018    UInt      summary;
   12019    HChar     dis_buf[128];  // big enough to hold LDMIA etc text
   12020 
   12021    /* What insn variants are we supporting today? */
   12022    //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
   12023    // etc etc
   12024 
   12025    /* Set result defaults. */
   12026    dres.whatNext   = Dis_Continue;
   12027    dres.len        = 4;
   12028    dres.continueAt = 0;
   12029 
   12030    /* Set default actions for post-insn handling of writes to r15, if
   12031       required. */
   12032    r15written = False;
   12033    r15guard   = IRTemp_INVALID; /* unconditional */
   12034    r15kind    = Ijk_Boring;
   12035 
   12036    /* At least this is simple on ARM: insns are all 4 bytes long, and
   12037       4-aligned.  So just fish the whole thing out of memory right now
   12038       and have done. */
   12039    insn = getUIntLittleEndianly( guest_instr );
   12040 
   12041    if (0) vex_printf("insn: 0x%x\n", insn);
   12042 
   12043    DIP("\t(arm) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
   12044 
   12045    /* We may be asked to update the guest R15 before going further. */
   12046    vassert(0 == (guest_R15_curr_instr_notENC & 3));
   12047    if (put_IP) {
   12048       llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
   12049    }
   12050 
   12051    /* ----------------------------------------------------------- */
   12052 
   12053    /* Spot "Special" instructions (see comment at top of file). */
   12054    {
   12055       UChar* code = (UChar*)guest_instr;
   12056       /* Spot the 16-byte preamble:
   12057 
   12058          e1a0c1ec  mov r12, r12, ROR #3
   12059          e1a0c6ec  mov r12, r12, ROR #13
   12060          e1a0ceec  mov r12, r12, ROR #29
   12061          e1a0c9ec  mov r12, r12, ROR #19
   12062       */
   12063       UInt word1 = 0xE1A0C1EC;
   12064       UInt word2 = 0xE1A0C6EC;
   12065       UInt word3 = 0xE1A0CEEC;
   12066       UInt word4 = 0xE1A0C9EC;
   12067       if (getUIntLittleEndianly(code+ 0) == word1 &&
   12068           getUIntLittleEndianly(code+ 4) == word2 &&
   12069           getUIntLittleEndianly(code+ 8) == word3 &&
   12070           getUIntLittleEndianly(code+12) == word4) {
   12071          /* Got a "Special" instruction preamble.  Which one is it? */
   12072          if (getUIntLittleEndianly(code+16) == 0xE18AA00A
   12073                                                /* orr r10,r10,r10 */) {
   12074             /* R3 = client_request ( R4 ) */
   12075             DIP("r3 = client_request ( %%r4 )\n");
   12076             irsb->next     = mkU32( guest_R15_curr_instr_notENC + 20 );
   12077             irsb->jumpkind = Ijk_ClientReq;
   12078             dres.whatNext  = Dis_StopHere;
   12079             goto decode_success;
   12080          }
   12081          else
   12082          if (getUIntLittleEndianly(code+16) == 0xE18BB00B
   12083                                                /* orr r11,r11,r11 */) {
   12084             /* R3 = guest_NRADDR */
   12085             DIP("r3 = guest_NRADDR\n");
   12086             dres.len = 20;
   12087             llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
   12088             goto decode_success;
   12089          }
   12090          else
   12091          if (getUIntLittleEndianly(code+16) == 0xE18CC00C
   12092                                                /* orr r12,r12,r12 */) {
   12093             /*  branch-and-link-to-noredir R4 */
   12094             DIP("branch-and-link-to-noredir r4\n");
   12095             llPutIReg(14, mkU32( guest_R15_curr_instr_notENC + 20) );
   12096             irsb->next     = llGetIReg(4);
   12097             irsb->jumpkind = Ijk_NoRedir;
   12098             dres.whatNext  = Dis_StopHere;
   12099             goto decode_success;
   12100          }
   12101          /* We don't know what it is.  Set opc1/opc2 so decode_failure
   12102             can print the insn following the Special-insn preamble. */
   12103          insn = getUIntLittleEndianly(code+16);
   12104          goto decode_failure;
   12105          /*NOTREACHED*/
   12106       }
   12107 
   12108    }
   12109 
   12110    /* ----------------------------------------------------------- */
   12111 
   12112    /* Main ARM instruction decoder starts here. */
   12113 
   12114    /* Deal with the condition.  Strategy is to merely generate a
   12115       condition temporary at this point (or IRTemp_INVALID, meaning
   12116       unconditional).  We leave it to lower-level instruction decoders
   12117       to decide whether they can generate straight-line code, or
   12118       whether they must generate a side exit before the instruction.
   12119       condT :: Ity_I32 and is always either zero or one. */
   12120    condT = IRTemp_INVALID;
   12121    switch ( (ARMCondcode)INSN_COND ) {
   12122       case ARMCondNV: {
   12123          // Illegal instruction prior to v5 (see ARM ARM A3-5), but
   12124          // some cases are acceptable
   12125          Bool ok = decode_NV_instruction(&dres, archinfo, insn);
   12126          if (ok)
   12127             goto decode_success;
   12128          else
   12129             goto decode_failure;
   12130       }
   12131       case ARMCondAL: // Always executed
   12132          break;
   12133       case ARMCondEQ: case ARMCondNE: case ARMCondHS: case ARMCondLO:
   12134       case ARMCondMI: case ARMCondPL: case ARMCondVS: case ARMCondVC:
   12135       case ARMCondHI: case ARMCondLS: case ARMCondGE: case ARMCondLT:
   12136       case ARMCondGT: case ARMCondLE:
   12137          condT = newTemp(Ity_I32);
   12138          assign( condT, mk_armg_calculate_condition( INSN_COND ));
   12139          break;
   12140    }
   12141 
   12142    /* ----------------------------------------------------------- */
   12143    /* -- ARMv5 integer instructions                            -- */
   12144    /* ----------------------------------------------------------- */
   12145 
   12146    /* ---------------- Data processing ops ------------------- */
   12147 
   12148    if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0))
   12149        && !(INSN(25,25) == 0 && INSN(7,7) == 1 && INSN(4,4) == 1)) {
   12150       IRTemp  shop = IRTemp_INVALID; /* shifter operand */
   12151       IRTemp  shco = IRTemp_INVALID; /* shifter carry out */
   12152       UInt    rD   = (insn >> 12) & 0xF; /* 15:12 */
   12153       UInt    rN   = (insn >> 16) & 0xF; /* 19:16 */
   12154       UInt    bitS = (insn >> 20) & 1; /* 20:20 */
   12155       IRTemp  rNt  = IRTemp_INVALID;
   12156       IRTemp  res  = IRTemp_INVALID;
   12157       IRTemp  oldV = IRTemp_INVALID;
   12158       IRTemp  oldC = IRTemp_INVALID;
   12159       HChar*  name = NULL;
   12160       IROp    op   = Iop_INVALID;
   12161       Bool    ok;
   12162 
   12163       switch (INSN(24,21)) {
   12164 
   12165          /* --------- ADD, SUB, AND, OR --------- */
   12166          case BITS4(0,1,0,0): /* ADD:  Rd = Rn + shifter_operand */
   12167             name = "add"; op = Iop_Add32; goto rd_eq_rn_op_SO;
   12168          case BITS4(0,0,1,0): /* SUB:  Rd = Rn - shifter_operand */
   12169             name = "sub"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
   12170          case BITS4(0,0,1,1): /* RSB:  Rd = shifter_operand - Rn */
   12171             name = "rsb"; op = Iop_Sub32; goto rd_eq_rn_op_SO;
   12172          case BITS4(0,0,0,0): /* AND:  Rd = Rn & shifter_operand */
   12173             name = "and"; op = Iop_And32; goto rd_eq_rn_op_SO;
   12174          case BITS4(1,1,0,0): /* OR:   Rd = Rn | shifter_operand */
   12175             name = "orr"; op = Iop_Or32; goto rd_eq_rn_op_SO;
   12176          case BITS4(0,0,0,1): /* EOR:  Rd = Rn ^ shifter_operand */
   12177             name = "eor"; op = Iop_Xor32; goto rd_eq_rn_op_SO;
   12178          case BITS4(1,1,1,0): /* BIC:  Rd = Rn & ~shifter_operand */
   12179             name = "bic"; op = Iop_And32; goto rd_eq_rn_op_SO;
   12180          rd_eq_rn_op_SO: {
   12181             Bool isRSB = False;
   12182             Bool isBIC = False;
   12183             switch (INSN(24,21)) {
   12184                case BITS4(0,0,1,1):
   12185                   vassert(op == Iop_Sub32); isRSB = True; break;
   12186                case BITS4(1,1,1,0):
   12187                   vassert(op == Iop_And32); isBIC = True; break;
   12188                default:
   12189                   break;
   12190             }
   12191             rNt = newTemp(Ity_I32);
   12192             assign(rNt, getIRegA(rN));
   12193             ok = mk_shifter_operand(
   12194                     INSN(25,25), INSN(11,0),
   12195                     &shop, bitS ? &shco : NULL, dis_buf
   12196                  );
   12197             if (!ok)
   12198                break;
   12199             res = newTemp(Ity_I32);
   12200             // compute the main result
   12201             if (isRSB) {
   12202                // reverse-subtract: shifter_operand - Rn
   12203                vassert(op == Iop_Sub32);
   12204                assign(res, binop(op, mkexpr(shop), mkexpr(rNt)) );
   12205             } else if (isBIC) {
   12206                // andn: shifter_operand & ~Rn
   12207                vassert(op == Iop_And32);
   12208                assign(res, binop(op, mkexpr(rNt),
   12209                                      unop(Iop_Not32, mkexpr(shop))) );
   12210             } else {
   12211                // normal: Rn op shifter_operand
   12212                assign(res, binop(op, mkexpr(rNt), mkexpr(shop)) );
   12213             }
   12214             // but don't commit it until after we've finished
   12215             // all necessary reads from the guest state
   12216             if (bitS
   12217                 && (op == Iop_And32 || op == Iop_Or32 || op == Iop_Xor32)) {
   12218                oldV = newTemp(Ity_I32);
   12219                assign( oldV, mk_armg_calculate_flag_v() );
   12220             }
   12221             // can't safely read guest state after here
   12222             // now safe to put the main result
   12223             putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   12224             // XXXX!! not safe to read any guest state after
   12225             // this point (I think the code below doesn't do that).
   12226             if (!bitS)
   12227                vassert(shco == IRTemp_INVALID);
   12228             /* Update the flags thunk if necessary */
   12229             if (bitS) {
   12230                vassert(shco != IRTemp_INVALID);
   12231                switch (op) {
   12232                   case Iop_Add32:
   12233                      setFlags_D1_D2( ARMG_CC_OP_ADD, rNt, shop, condT );
   12234                      break;
   12235                   case Iop_Sub32:
   12236                      if (isRSB) {
   12237                         setFlags_D1_D2( ARMG_CC_OP_SUB, shop, rNt, condT );
   12238                      } else {
   12239                         setFlags_D1_D2( ARMG_CC_OP_SUB, rNt, shop, condT );
   12240                      }
   12241                      break;
   12242                   case Iop_And32: /* BIC and AND set the flags the same */
   12243                   case Iop_Or32:
   12244                   case Iop_Xor32:
   12245                      // oldV has been read just above
   12246                      setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
   12247                                         res, shco, oldV, condT );
   12248                      break;
   12249                   default:
   12250                      vassert(0);
   12251                }
   12252             }
   12253             DIP("%s%s%s r%u, r%u, %s\n",
   12254                 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
   12255             goto decode_success;
   12256          }
   12257 
   12258          /* --------- MOV, MVN --------- */
   12259          case BITS4(1,1,0,1):   /* MOV: Rd = shifter_operand */
   12260          case BITS4(1,1,1,1): { /* MVN: Rd = not(shifter_operand) */
   12261             Bool isMVN = INSN(24,21) == BITS4(1,1,1,1);
   12262             if (rN != 0)
   12263                break; /* rN must be zero */
   12264             ok = mk_shifter_operand(
   12265                     INSN(25,25), INSN(11,0),
   12266                     &shop, bitS ? &shco : NULL, dis_buf
   12267                  );
   12268             if (!ok)
   12269                break;
   12270             res = newTemp(Ity_I32);
   12271             assign( res, isMVN ? unop(Iop_Not32, mkexpr(shop))
   12272                                : mkexpr(shop) );
   12273             if (bitS) {
   12274                vassert(shco != IRTemp_INVALID);
   12275                oldV = newTemp(Ity_I32);
   12276                assign( oldV, mk_armg_calculate_flag_v() );
   12277             } else {
   12278                vassert(shco == IRTemp_INVALID);
   12279             }
   12280             // can't safely read guest state after here
   12281             putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   12282             /* Update the flags thunk if necessary */
   12283             if (bitS) {
   12284                setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
   12285                                   res, shco, oldV, condT );
   12286             }
   12287             DIP("%s%s%s r%u, %s\n",
   12288                 isMVN ? "mvn" : "mov",
   12289                 nCC(INSN_COND), bitS ? "s" : "", rD, dis_buf );
   12290             goto decode_success;
   12291          }
   12292 
   12293          /* --------- CMP --------- */
   12294          case BITS4(1,0,1,0):   /* CMP:  (void) Rn - shifter_operand */
   12295          case BITS4(1,0,1,1): { /* CMN:  (void) Rn + shifter_operand */
   12296             Bool isCMN = INSN(24,21) == BITS4(1,0,1,1);
   12297             if (rD != 0)
   12298                break; /* rD must be zero */
   12299             if (bitS == 0)
   12300                break; /* if S (bit 20) is not set, it's not CMP/CMN */
   12301             rNt = newTemp(Ity_I32);
   12302             assign(rNt, getIRegA(rN));
   12303             ok = mk_shifter_operand(
   12304                     INSN(25,25), INSN(11,0),
   12305                     &shop, NULL, dis_buf
   12306                  );
   12307             if (!ok)
   12308                break;
   12309             // can't safely read guest state after here
   12310             /* Update the flags thunk. */
   12311             setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   12312                             rNt, shop, condT );
   12313             DIP("%s%s r%u, %s\n",
   12314                 isCMN ? "cmn" : "cmp",
   12315                 nCC(INSN_COND), rN, dis_buf );
   12316             goto decode_success;
   12317          }
   12318 
   12319          /* --------- TST --------- */
   12320          case BITS4(1,0,0,0):   /* TST:  (void) Rn & shifter_operand */
   12321          case BITS4(1,0,0,1): { /* TEQ:  (void) Rn ^ shifter_operand */
   12322             Bool isTEQ = INSN(24,21) == BITS4(1,0,0,1);
   12323             if (rD != 0)
   12324                break; /* rD must be zero */
   12325             if (bitS == 0)
   12326                break; /* if S (bit 20) is not set, it's not TST/TEQ */
   12327             rNt = newTemp(Ity_I32);
   12328             assign(rNt, getIRegA(rN));
   12329             ok = mk_shifter_operand(
   12330                     INSN(25,25), INSN(11,0),
   12331                     &shop, &shco, dis_buf
   12332                  );
   12333             if (!ok)
   12334                break;
   12335             /* Update the flags thunk. */
   12336             res = newTemp(Ity_I32);
   12337             assign( res, binop(isTEQ ? Iop_Xor32 : Iop_And32,
   12338                                mkexpr(rNt), mkexpr(shop)) );
   12339             oldV = newTemp(Ity_I32);
   12340             assign( oldV, mk_armg_calculate_flag_v() );
   12341             // can't safely read guest state after here
   12342             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC,
   12343                                res, shco, oldV, condT );
   12344             DIP("%s%s r%u, %s\n",
   12345                 isTEQ ? "teq" : "tst",
   12346                 nCC(INSN_COND), rN, dis_buf );
   12347             goto decode_success;
   12348          }
   12349 
   12350          /* --------- ADC, SBC, RSC --------- */
   12351          case BITS4(0,1,0,1): /* ADC:  Rd = Rn + shifter_operand + oldC */
   12352             name = "adc"; goto rd_eq_rn_op_SO_op_oldC;
   12353          case BITS4(0,1,1,0): /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
   12354             name = "sbc"; goto rd_eq_rn_op_SO_op_oldC;
   12355          case BITS4(0,1,1,1): /* RSC:  Rd = shifter_operand - Rn - (oldC ^ 1) */
   12356             name = "rsc"; goto rd_eq_rn_op_SO_op_oldC;
   12357          rd_eq_rn_op_SO_op_oldC: {
   12358             // FIXME: shco isn't used for anything.  Get rid of it.
   12359             rNt = newTemp(Ity_I32);
   12360             assign(rNt, getIRegA(rN));
   12361             ok = mk_shifter_operand(
   12362                     INSN(25,25), INSN(11,0),
   12363                     &shop, bitS ? &shco : NULL, dis_buf
   12364                  );
   12365             if (!ok)
   12366                break;
   12367             oldC = newTemp(Ity_I32);
   12368             assign( oldC, mk_armg_calculate_flag_c() );
   12369             res = newTemp(Ity_I32);
   12370             // compute the main result
   12371             switch (INSN(24,21)) {
   12372                case BITS4(0,1,0,1): /* ADC */
   12373                   assign(res,
   12374                          binop(Iop_Add32,
   12375                                binop(Iop_Add32, mkexpr(rNt), mkexpr(shop)),
   12376                                mkexpr(oldC) ));
   12377                   break;
   12378                case BITS4(0,1,1,0): /* SBC */
   12379                   assign(res,
   12380                          binop(Iop_Sub32,
   12381                                binop(Iop_Sub32, mkexpr(rNt), mkexpr(shop)),
   12382                                binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   12383                   break;
   12384                case BITS4(0,1,1,1): /* RSC */
   12385                   assign(res,
   12386                          binop(Iop_Sub32,
   12387                                binop(Iop_Sub32, mkexpr(shop), mkexpr(rNt)),
   12388                                binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   12389                   break;
   12390                default:
   12391                   vassert(0);
   12392             }
   12393             // but don't commit it until after we've finished
   12394             // all necessary reads from the guest state
   12395             // now safe to put the main result
   12396             putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   12397             // XXXX!! not safe to read any guest state after
   12398             // this point (I think the code below doesn't do that).
   12399             if (!bitS)
   12400                vassert(shco == IRTemp_INVALID);
   12401             /* Update the flags thunk if necessary */
   12402             if (bitS) {
   12403                vassert(shco != IRTemp_INVALID);
   12404                switch (INSN(24,21)) {
   12405                   case BITS4(0,1,0,1): /* ADC */
   12406                      setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
   12407                                         rNt, shop, oldC, condT );
   12408                      break;
   12409                   case BITS4(0,1,1,0): /* SBC */
   12410                      setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   12411                                         rNt, shop, oldC, condT );
   12412                      break;
   12413                   case BITS4(0,1,1,1): /* RSC */
   12414                      setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   12415                                         shop, rNt, oldC, condT );
   12416                      break;
   12417                   default:
   12418                      vassert(0);
   12419                }
   12420             }
   12421             DIP("%s%s%s r%u, r%u, %s\n",
   12422                 name, nCC(INSN_COND), bitS ? "s" : "", rD, rN, dis_buf );
   12423             goto decode_success;
   12424          }
   12425 
   12426          /* --------- ??? --------- */
   12427          default:
   12428             break;
   12429       }
   12430    } /* if (0 == (INSN(27,20) & BITS8(1,1,0,0,0,0,0,0)) */
   12431 
   12432    /* --------------------- Load/store (ubyte & word) -------- */
   12433    // LDR STR LDRB STRB
   12434    /*                 31   27   23   19 15 11    6   4 3  # highest bit
   12435                         28   24   20 16 12
   12436       A5-20   1 | 16  cond 0101 UB0L Rn Rd imm12
   12437       A5-22   1 | 32  cond 0111 UBOL Rn Rd imm5  sh2 0 Rm
   12438       A5-24   2 | 16  cond 0101 UB1L Rn Rd imm12
   12439       A5-26   2 | 32  cond 0111 UB1L Rn Rd imm5  sh2 0 Rm
   12440       A5-28   3 | 16  cond 0100 UB0L Rn Rd imm12
   12441       A5-32   3 | 32  cond 0110 UB0L Rn Rd imm5  sh2 0 Rm
   12442    */
   12443    /* case coding:
   12444              1   at-ea               (access at ea)
   12445              2   at-ea-then-upd      (access at ea, then Rn = ea)
   12446              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
   12447       ea coding
   12448              16  Rn +/- imm12
   12449              32  Rn +/- Rm sh2 imm5
   12450    */
   12451    /* Quickly skip over all of this for hopefully most instructions */
   12452    if ((INSN(27,24) & BITS4(1,1,0,0)) != BITS4(0,1,0,0))
   12453       goto after_load_store_ubyte_or_word;
   12454 
   12455    summary = 0;
   12456 
   12457    /**/ if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 0) {
   12458       summary = 1 | 16;
   12459    }
   12460    else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 0
   12461                                           && INSN(4,4) == 0) {
   12462       summary = 1 | 32;
   12463    }
   12464    else if (INSN(27,24) == BITS4(0,1,0,1) && INSN(21,21) == 1) {
   12465       summary = 2 | 16;
   12466    }
   12467    else if (INSN(27,24) == BITS4(0,1,1,1) && INSN(21,21) == 1
   12468                                           && INSN(4,4) == 0) {
   12469       summary = 2 | 32;
   12470    }
   12471    else if (INSN(27,24) == BITS4(0,1,0,0) && INSN(21,21) == 0) {
   12472       summary = 3 | 16;
   12473    }
   12474    else if (INSN(27,24) == BITS4(0,1,1,0) && INSN(21,21) == 0
   12475                                           && INSN(4,4) == 0) {
   12476       summary = 3 | 32;
   12477    }
   12478    else goto after_load_store_ubyte_or_word;
   12479 
   12480    { UInt rN = (insn >> 16) & 0xF; /* 19:16 */
   12481      UInt rD = (insn >> 12) & 0xF; /* 15:12 */
   12482      UInt rM = (insn >> 0)  & 0xF; /*  3:0  */
   12483      UInt bU = (insn >> 23) & 1;      /* 23 */
   12484      UInt bB = (insn >> 22) & 1;      /* 22 */
   12485      UInt bL = (insn >> 20) & 1;      /* 20 */
   12486      UInt imm12 = (insn >> 0) & 0xFFF; /* 11:0 */
   12487      UInt imm5  = (insn >> 7) & 0x1F;  /* 11:7 */
   12488      UInt sh2   = (insn >> 5) & 3;     /* 6:5 */
   12489 
   12490      /* Skip some invalid cases, which would lead to two competing
   12491         updates to the same register, or which are otherwise
   12492         disallowed by the spec. */
   12493      switch (summary) {
   12494         case 1 | 16:
   12495            break;
   12496         case 1 | 32:
   12497            if (rM == 15) goto after_load_store_ubyte_or_word;
   12498            break;
   12499         case 2 | 16: case 3 | 16:
   12500            if (rN == 15) goto after_load_store_ubyte_or_word;
   12501            if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
   12502            break;
   12503         case 2 | 32: case 3 | 32:
   12504            if (rM == 15) goto after_load_store_ubyte_or_word;
   12505            if (rN == 15) goto after_load_store_ubyte_or_word;
   12506            if (rN == rM) goto after_load_store_ubyte_or_word;
   12507            if (bL == 1 && rN == rD) goto after_load_store_ubyte_or_word;
   12508            break;
   12509         default:
   12510            vassert(0);
   12511      }
   12512 
   12513      /* Now, we can't do a conditional load or store, since that very
   12514         likely will generate an exception.  So we have to take a side
   12515         exit at this point if the condition is false. */
   12516      if (condT != IRTemp_INVALID) {
   12517         mk_skip_over_A32_if_cond_is_false( condT );
   12518         condT = IRTemp_INVALID;
   12519      }
   12520      /* Ok, now we're unconditional.  Do the load or store. */
   12521 
   12522      /* compute the effective address.  Bind it to a tmp since we
   12523         may need to use it twice. */
   12524      IRExpr* eaE = NULL;
   12525      switch (summary & 0xF0) {
   12526         case 16:
   12527            eaE = mk_EA_reg_plusminus_imm12( rN, bU, imm12, dis_buf );
   12528            break;
   12529         case 32:
   12530            eaE = mk_EA_reg_plusminus_shifted_reg( rN, bU, rM, sh2, imm5,
   12531                                                   dis_buf );
   12532            break;
   12533      }
   12534      vassert(eaE);
   12535      IRTemp eaT = newTemp(Ity_I32);
   12536      assign(eaT, eaE);
   12537 
   12538      /* get the old Rn value */
   12539      IRTemp rnT = newTemp(Ity_I32);
   12540      assign(rnT, getIRegA(rN));
   12541 
   12542      /* decide on the transfer address */
   12543      IRTemp taT = IRTemp_INVALID;
   12544      switch (summary & 0x0F) {
   12545         case 1: case 2: taT = eaT; break;
   12546         case 3:         taT = rnT; break;
   12547      }
   12548      vassert(taT != IRTemp_INVALID);
   12549 
   12550      if (bL == 0) {
   12551        /* Store.  If necessary, update the base register before the
   12552           store itself, so that the common idiom of "str rX, [sp,
   12553           #-4]!" (store rX at sp-4, then do new sp = sp-4, a.k.a "push
   12554           rX") doesn't cause Memcheck to complain that the access is
   12555           below the stack pointer.  Also, not updating sp before the
   12556           store confuses Valgrind's dynamic stack-extending logic.  So
   12557           do it before the store.  Hence we need to snarf the store
   12558           data before doing the basereg update. */
   12559 
   12560         /* get hold of the data to be stored */
   12561         IRTemp rDt = newTemp(Ity_I32);
   12562         assign(rDt, getIRegA(rD));
   12563 
   12564         /* Update Rn if necessary. */
   12565         switch (summary & 0x0F) {
   12566            case 2: case 3:
   12567               putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   12568               break;
   12569         }
   12570 
   12571         /* generate the transfer */
   12572         if (bB == 0) { // word store
   12573            storeLE( mkexpr(taT), mkexpr(rDt) );
   12574         } else { // byte store
   12575            vassert(bB == 1);
   12576            storeLE( mkexpr(taT), unop(Iop_32to8, mkexpr(rDt)) );
   12577         }
   12578 
   12579      } else {
   12580         /* Load */
   12581         vassert(bL == 1);
   12582 
   12583         /* generate the transfer */
   12584         if (bB == 0) { // word load
   12585            putIRegA( rD, loadLE(Ity_I32, mkexpr(taT)),
   12586                      IRTemp_INVALID, Ijk_Boring );
   12587         } else { // byte load
   12588            vassert(bB == 1);
   12589            putIRegA( rD, unop(Iop_8Uto32, loadLE(Ity_I8, mkexpr(taT))),
   12590                      IRTemp_INVALID, Ijk_Boring );
   12591         }
   12592 
   12593         /* Update Rn if necessary. */
   12594         switch (summary & 0x0F) {
   12595            case 2: case 3:
   12596               // should be assured by logic above:
   12597               if (bL == 1)
   12598                  vassert(rD != rN); /* since we just wrote rD */
   12599               putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   12600               break;
   12601         }
   12602      }
   12603 
   12604      switch (summary & 0x0F) {
   12605         case 1:  DIP("%sr%s%s r%u, %s\n",
   12606                      bL == 0 ? "st" : "ld",
   12607                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
   12608                  break;
   12609         case 2:  DIP("%sr%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
   12610                      bL == 0 ? "st" : "ld",
   12611                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
   12612                  break;
   12613         case 3:  DIP("%sr%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
   12614                      bL == 0 ? "st" : "ld",
   12615                      bB == 0 ? "" : "b", nCC(INSN_COND), rD, dis_buf);
   12616                  break;
   12617         default: vassert(0);
   12618      }
   12619 
   12620      /* XXX deal with alignment constraints */
   12621 
   12622      goto decode_success;
   12623 
   12624      /* Complications:
   12625 
   12626         For all loads: if the Amode specifies base register
   12627         writeback, and the same register is specified for Rd and Rn,
   12628         the results are UNPREDICTABLE.
   12629 
   12630         For all loads and stores: if R15 is written, branch to
   12631         that address afterwards.
   12632 
   12633         STRB: straightforward
   12634         LDRB: loaded data is zero extended
   12635         STR:  lowest 2 bits of address are ignored
   12636         LDR:  if the lowest 2 bits of the address are nonzero
   12637               then the loaded value is rotated right by 8 * the lowest 2 bits
   12638      */
   12639    }
   12640 
   12641   after_load_store_ubyte_or_word:
   12642 
   12643    /* --------------------- Load/store (sbyte & hword) -------- */
   12644    // LDRH LDRSH STRH LDRSB
   12645    /*                 31   27   23   19 15 11   7    3     # highest bit
   12646                         28   24   20 16 12    8    4    0
   12647       A5-36   1 | 16  cond 0001 U10L Rn Rd im4h 1SH1 im4l
   12648       A5-38   1 | 32  cond 0001 U00L Rn Rd 0000 1SH1 Rm
   12649       A5-40   2 | 16  cond 0001 U11L Rn Rd im4h 1SH1 im4l
   12650       A5-42   2 | 32  cond 0001 U01L Rn Rd 0000 1SH1 Rm
   12651       A5-44   3 | 16  cond 0000 U10L Rn Rd im4h 1SH1 im4l
   12652       A5-46   3 | 32  cond 0000 U00L Rn Rd 0000 1SH1 Rm
   12653    */
   12654    /* case coding:
   12655              1   at-ea               (access at ea)
   12656              2   at-ea-then-upd      (access at ea, then Rn = ea)
   12657              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
   12658       ea coding
   12659              16  Rn +/- imm8
   12660              32  Rn +/- Rm
   12661    */
   12662    /* Quickly skip over all of this for hopefully most instructions */
   12663    if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
   12664       goto after_load_store_sbyte_or_hword;
   12665 
   12666    /* Check the "1SH1" thing. */
   12667    if ((INSN(7,4) & BITS4(1,0,0,1)) != BITS4(1,0,0,1))
   12668       goto after_load_store_sbyte_or_hword;
   12669 
   12670    summary = 0;
   12671 
   12672    /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,0)) {
   12673       summary = 1 | 16;
   12674    }
   12675    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,0)) {
   12676       summary = 1 | 32;
   12677    }
   12678    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(1,1)) {
   12679       summary = 2 | 16;
   12680    }
   12681    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,21) == BITS2(0,1)) {
   12682       summary = 2 | 32;
   12683    }
   12684    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(1,0)) {
   12685       summary = 3 | 16;
   12686    }
   12687    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,21) == BITS2(0,0)) {
   12688       summary = 3 | 32;
   12689    }
   12690    else goto after_load_store_sbyte_or_hword;
   12691 
   12692    { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
   12693      UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
   12694      UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
   12695      UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
   12696      UInt bL   = (insn >> 20) & 1;   /* 20 L=1 load, L=0 store */
   12697      UInt bH   = (insn >> 5) & 1;    /* H=1 halfword, H=0 byte */
   12698      UInt bS   = (insn >> 6) & 1;    /* S=1 signed, S=0 unsigned */
   12699      UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
   12700 
   12701      /* Skip combinations that are either meaningless or already
   12702         handled by main word-or-unsigned-byte load-store
   12703         instructions. */
   12704      if (bS == 0 && bH == 0) /* "unsigned byte" */
   12705         goto after_load_store_sbyte_or_hword;
   12706      if (bS == 1 && bL == 0) /* "signed store" */
   12707         goto after_load_store_sbyte_or_hword;
   12708 
   12709      /* Require 11:8 == 0 for Rn +/- Rm cases */
   12710      if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
   12711         goto after_load_store_sbyte_or_hword;
   12712 
   12713      /* Skip some invalid cases, which would lead to two competing
   12714         updates to the same register, or which are otherwise
   12715         disallowed by the spec. */
   12716      switch (summary) {
   12717         case 1 | 16:
   12718            break;
   12719         case 1 | 32:
   12720            if (rM == 15) goto after_load_store_sbyte_or_hword;
   12721            break;
   12722         case 2 | 16: case 3 | 16:
   12723            if (rN == 15) goto after_load_store_sbyte_or_hword;
   12724            if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
   12725            break;
   12726         case 2 | 32: case 3 | 32:
   12727            if (rM == 15) goto after_load_store_sbyte_or_hword;
   12728            if (rN == 15) goto after_load_store_sbyte_or_hword;
   12729            if (rN == rM) goto after_load_store_sbyte_or_hword;
   12730            if (bL == 1 && rN == rD) goto after_load_store_sbyte_or_hword;
   12731            break;
   12732         default:
   12733            vassert(0);
   12734      }
   12735 
   12736      /* Now, we can't do a conditional load or store, since that very
   12737         likely will generate an exception.  So we have to take a side
   12738         exit at this point if the condition is false. */
   12739      if (condT != IRTemp_INVALID) {
   12740         mk_skip_over_A32_if_cond_is_false( condT );
   12741         condT = IRTemp_INVALID;
   12742      }
   12743      /* Ok, now we're unconditional.  Do the load or store. */
   12744 
   12745      /* compute the effective address.  Bind it to a tmp since we
   12746         may need to use it twice. */
   12747      IRExpr* eaE = NULL;
   12748      switch (summary & 0xF0) {
   12749         case 16:
   12750            eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
   12751            break;
   12752         case 32:
   12753            eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
   12754            break;
   12755      }
   12756      vassert(eaE);
   12757      IRTemp eaT = newTemp(Ity_I32);
   12758      assign(eaT, eaE);
   12759 
   12760      /* get the old Rn value */
   12761      IRTemp rnT = newTemp(Ity_I32);
   12762      assign(rnT, getIRegA(rN));
   12763 
   12764      /* decide on the transfer address */
   12765      IRTemp taT = IRTemp_INVALID;
   12766      switch (summary & 0x0F) {
   12767         case 1: case 2: taT = eaT; break;
   12768         case 3:         taT = rnT; break;
   12769      }
   12770      vassert(taT != IRTemp_INVALID);
   12771 
   12772      /* halfword store  H 1  L 0  S 0
   12773         uhalf load      H 1  L 1  S 0
   12774         shalf load      H 1  L 1  S 1
   12775         sbyte load      H 0  L 1  S 1
   12776      */
   12777      HChar* name = NULL;
   12778      /* generate the transfer */
   12779      /**/ if (bH == 1 && bL == 0 && bS == 0) { // halfword store
   12780         storeLE( mkexpr(taT), unop(Iop_32to16, getIRegA(rD)) );
   12781         name = "strh";
   12782      }
   12783      else if (bH == 1 && bL == 1 && bS == 0) { // uhalf load
   12784         putIRegA( rD, unop(Iop_16Uto32, loadLE(Ity_I16, mkexpr(taT))),
   12785                   IRTemp_INVALID, Ijk_Boring );
   12786         name = "ldrh";
   12787      }
   12788      else if (bH == 1 && bL == 1 && bS == 1) { // shalf load
   12789         putIRegA( rD, unop(Iop_16Sto32, loadLE(Ity_I16, mkexpr(taT))),
   12790                   IRTemp_INVALID, Ijk_Boring );
   12791         name = "ldrsh";
   12792      }
   12793      else if (bH == 0 && bL == 1 && bS == 1) { // sbyte load
   12794         putIRegA( rD, unop(Iop_8Sto32, loadLE(Ity_I8, mkexpr(taT))),
   12795                   IRTemp_INVALID, Ijk_Boring );
   12796         name = "ldrsb";
   12797      }
   12798      else
   12799         vassert(0); // should be assured by logic above
   12800 
   12801      /* Update Rn if necessary. */
   12802      switch (summary & 0x0F) {
   12803         case 2: case 3:
   12804            // should be assured by logic above:
   12805            if (bL == 1)
   12806               vassert(rD != rN); /* since we just wrote rD */
   12807            putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   12808            break;
   12809      }
   12810 
   12811      switch (summary & 0x0F) {
   12812         case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
   12813                  break;
   12814         case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
   12815                      name, nCC(INSN_COND), rD, dis_buf);
   12816                  break;
   12817         case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
   12818                      name, nCC(INSN_COND), rD, dis_buf);
   12819                  break;
   12820         default: vassert(0);
   12821      }
   12822 
   12823      /* XXX deal with alignment constraints */
   12824 
   12825      goto decode_success;
   12826 
   12827      /* Complications:
   12828 
   12829         For all loads: if the Amode specifies base register
   12830         writeback, and the same register is specified for Rd and Rn,
   12831         the results are UNPREDICTABLE.
   12832 
   12833         For all loads and stores: if R15 is written, branch to
   12834         that address afterwards.
   12835 
   12836         Misaligned halfword stores => Unpredictable
   12837         Misaligned halfword loads  => Unpredictable
   12838      */
   12839    }
   12840 
   12841   after_load_store_sbyte_or_hword:
   12842 
   12843    /* --------------------- Load/store multiple -------------- */
   12844    // LD/STMIA LD/STMIB LD/STMDA LD/STMDB
   12845    // Remarkably complex and difficult to get right
   12846    // match 27:20 as 100XX0WL
   12847    if (BITS8(1,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,1,0,0))) {
   12848       // A5-50 LD/STMIA  cond 1000 10WL Rn RegList
   12849       // A5-51 LD/STMIB  cond 1001 10WL Rn RegList
   12850       // A5-53 LD/STMDA  cond 1000 00WL Rn RegList
   12851       // A5-53 LD/STMDB  cond 1001 00WL Rn RegList
   12852       //                   28   24   20 16       0
   12853 
   12854       UInt bINC    = (insn >> 23) & 1;
   12855       UInt bBEFORE = (insn >> 24) & 1;
   12856 
   12857       UInt bL      = (insn >> 20) & 1;  /* load=1, store=0 */
   12858       UInt bW      = (insn >> 21) & 1;  /* Rn wback=1, no wback=0 */
   12859       UInt rN      = (insn >> 16) & 0xF;
   12860       UInt regList = insn & 0xFFFF;
   12861       /* Skip some invalid cases, which would lead to two competing
   12862          updates to the same register, or which are otherwise
   12863          disallowed by the spec.  Note the test above has required
   12864          that S == 0, since that looks like a kernel-mode only thing.
   12865          Done by forcing the real pattern, viz 100XXSWL to actually be
   12866          100XX0WL. */
   12867       if (rN == 15) goto after_load_store_multiple;
   12868       // reglist can't be empty
   12869       if (regList == 0) goto after_load_store_multiple;
   12870       // if requested to writeback Rn, and this is a load instruction,
   12871       // then Rn can't appear in RegList, since we'd have two competing
   12872       // new values for Rn.  We do however accept this case for store
   12873       // instructions.
   12874       if (bW == 1 && bL == 1 && ((1 << rN) & regList) > 0)
   12875          goto after_load_store_multiple;
   12876 
   12877       /* Now, we can't do a conditional load or store, since that very
   12878          likely will generate an exception.  So we have to take a side
   12879          exit at this point if the condition is false. */
   12880       if (condT != IRTemp_INVALID) {
   12881          mk_skip_over_A32_if_cond_is_false( condT );
   12882          condT = IRTemp_INVALID;
   12883       }
   12884 
   12885       /* Ok, now we're unconditional.  Generate the IR. */
   12886       mk_ldm_stm( True/*arm*/, rN, bINC, bBEFORE, bW, bL, regList );
   12887 
   12888       DIP("%sm%c%c%s r%u%s, {0x%04x}\n",
   12889           bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
   12890           nCC(INSN_COND),
   12891           rN, bW ? "!" : "", regList);
   12892 
   12893       goto decode_success;
   12894    }
   12895 
   12896   after_load_store_multiple:
   12897 
   12898    /* --------------------- Control flow --------------------- */
   12899    // B, BL (Branch, or Branch-and-Link, to immediate offset)
   12900    //
   12901    if (BITS8(1,0,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,0,0,0,0,0))) {
   12902       UInt link   = (insn >> 24) & 1;
   12903       UInt uimm24 = insn & ((1<<24)-1);
   12904       Int  simm24 = (Int)uimm24;
   12905       UInt dst    = guest_R15_curr_instr_notENC + 8
   12906                     + (((simm24 << 8) >> 8) << 2);
   12907       IRJumpKind jk = link ? Ijk_Call : Ijk_Boring;
   12908       if (link) {
   12909          putIRegA(14, mkU32(guest_R15_curr_instr_notENC + 4),
   12910                       condT, Ijk_Boring);
   12911       }
   12912       if (condT == IRTemp_INVALID) {
   12913          /* unconditional transfer to 'dst'.  See if we can simply
   12914             continue tracing at the destination. */
   12915          if (resteerOkFn( callback_opaque, (Addr64)dst )) {
   12916             /* yes */
   12917             dres.whatNext   = Dis_ResteerU;
   12918             dres.continueAt = (Addr64)dst;
   12919          } else {
   12920             /* no; terminate the SB at this point. */
   12921             irsb->next     = mkU32(dst);
   12922             irsb->jumpkind = jk;
   12923             dres.whatNext  = Dis_StopHere;
   12924          }
   12925          DIP("b%s 0x%x\n", link ? "l" : "", dst);
   12926       } else {
   12927          /* conditional transfer to 'dst' */
   12928          HChar* comment = "";
   12929 
   12930          /* First see if we can do some speculative chasing into one
   12931             arm or the other.  Be conservative and only chase if
   12932             !link, that is, this is a normal conditional branch to a
   12933             known destination. */
   12934          if (!link
   12935              && resteerCisOk
   12936              && vex_control.guest_chase_cond
   12937              && dst < guest_R15_curr_instr_notENC
   12938              && resteerOkFn( callback_opaque, (Addr64)(Addr32)dst) ) {
   12939             /* Speculation: assume this backward branch is taken.  So
   12940                we need to emit a side-exit to the insn following this
   12941                one, on the negation of the condition, and continue at
   12942                the branch target address (dst). */
   12943             stmt( IRStmt_Exit( unop(Iop_Not1,
   12944                                     unop(Iop_32to1, mkexpr(condT))),
   12945                                Ijk_Boring,
   12946                                IRConst_U32(guest_R15_curr_instr_notENC+4) ));
   12947             dres.whatNext   = Dis_ResteerC;
   12948             dres.continueAt = (Addr64)(Addr32)dst;
   12949             comment = "(assumed taken)";
   12950          }
   12951          else
   12952          if (!link
   12953              && resteerCisOk
   12954              && vex_control.guest_chase_cond
   12955              && dst >= guest_R15_curr_instr_notENC
   12956              && resteerOkFn( callback_opaque,
   12957                              (Addr64)(Addr32)
   12958                                      (guest_R15_curr_instr_notENC+4)) ) {
   12959             /* Speculation: assume this forward branch is not taken.
   12960                So we need to emit a side-exit to dst (the dest) and
   12961                continue disassembling at the insn immediately
   12962                following this one. */
   12963             stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
   12964                                Ijk_Boring,
   12965                                IRConst_U32(dst) ));
   12966             dres.whatNext   = Dis_ResteerC;
   12967             dres.continueAt = (Addr64)(Addr32)
   12968                                       (guest_R15_curr_instr_notENC+4);
   12969             comment = "(assumed not taken)";
   12970          }
   12971          else {
   12972             /* Conservative default translation - end the block at
   12973                this point. */
   12974             stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(condT)),
   12975                                jk, IRConst_U32(dst) ));
   12976             irsb->next     = mkU32(guest_R15_curr_instr_notENC + 4);
   12977             irsb->jumpkind = jk;
   12978             dres.whatNext  = Dis_StopHere;
   12979          }
   12980          DIP("b%s%s 0x%x %s\n", link ? "l" : "", nCC(INSN_COND),
   12981              dst, comment);
   12982       }
   12983       goto decode_success;
   12984    }
   12985 
   12986    // B, BL (Branch, or Branch-and-Link, to a register)
   12987    // NB: interworking branch
   12988    if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
   12989        && INSN(19,12) == BITS8(1,1,1,1,1,1,1,1)
   12990        && (INSN(11,4) == BITS8(1,1,1,1,0,0,1,1)
   12991            || INSN(11,4) == BITS8(1,1,1,1,0,0,0,1))) {
   12992       IRExpr* dst;
   12993       UInt    link = (INSN(11,4) >> 1) & 1;
   12994       UInt    rM   = INSN(3,0);
   12995       // we don't decode the case (link && rM == 15), as that's
   12996       // Unpredictable.
   12997       if (!(link && rM == 15)) {
   12998          if (condT != IRTemp_INVALID) {
   12999             mk_skip_over_A32_if_cond_is_false( condT );
   13000          }
   13001          // rM contains an interworking address exactly as we require
   13002          // (with continuation CPSR.T in bit 0), so we can use it
   13003          // as-is, with no masking.
   13004          dst = getIRegA(rM);
   13005          if (link) {
   13006             putIRegA( 14, mkU32(guest_R15_curr_instr_notENC + 4),
   13007                       IRTemp_INVALID/*because AL*/, Ijk_Boring );
   13008          }
   13009          irsb->next     = dst;
   13010          irsb->jumpkind = link ? Ijk_Call
   13011                                : (rM == 14 ? Ijk_Ret : Ijk_Boring);
   13012          dres.whatNext  = Dis_StopHere;
   13013          if (condT == IRTemp_INVALID) {
   13014             DIP("b%sx r%u\n", link ? "l" : "", rM);
   13015          } else {
   13016             DIP("b%sx%s r%u\n", link ? "l" : "", nCC(INSN_COND), rM);
   13017          }
   13018          goto decode_success;
   13019       }
   13020       /* else: (link && rM == 15): just fall through */
   13021    }
   13022 
   13023    /* --- NB: ARM interworking branches are in NV space, hence
   13024       are handled elsewhere by decode_NV_instruction.
   13025       ---
   13026    */
   13027 
   13028    /* --------------------- Clz --------------------- */
   13029    // CLZ
   13030    if (INSN(27,20) == BITS8(0,0,0,1,0,1,1,0)
   13031        && INSN(19,16) == BITS4(1,1,1,1)
   13032        && INSN(11,4) == BITS8(1,1,1,1,0,0,0,1)) {
   13033       UInt rD = INSN(15,12);
   13034       UInt rM = INSN(3,0);
   13035       IRTemp arg = newTemp(Ity_I32);
   13036       IRTemp res = newTemp(Ity_I32);
   13037       assign(arg, getIRegA(rM));
   13038       assign(res, IRExpr_Mux0X(
   13039                      unop(Iop_1Uto8,binop(Iop_CmpEQ32, mkexpr(arg),
   13040                                                        mkU32(0))),
   13041                      unop(Iop_Clz32, mkexpr(arg)),
   13042                      mkU32(32)
   13043             ));
   13044       putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13045       DIP("clz%s r%u, r%u\n", nCC(INSN_COND), rD, rM);
   13046       goto decode_success;
   13047    }
   13048 
   13049    /* --------------------- Mul etc --------------------- */
   13050    // MUL
   13051    if (BITS8(0,0,0,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
   13052        && INSN(15,12) == BITS4(0,0,0,0)
   13053        && INSN(7,4) == BITS4(1,0,0,1)) {
   13054       UInt bitS = (insn >> 20) & 1; /* 20:20 */
   13055       UInt rD = INSN(19,16);
   13056       UInt rS = INSN(11,8);
   13057       UInt rM = INSN(3,0);
   13058       if (rD == 15 || rM == 15 || rS == 15) {
   13059          /* Unpredictable; don't decode; fall through */
   13060       } else {
   13061          IRTemp argL = newTemp(Ity_I32);
   13062          IRTemp argR = newTemp(Ity_I32);
   13063          IRTemp res  = newTemp(Ity_I32);
   13064          IRTemp oldC = IRTemp_INVALID;
   13065          IRTemp oldV = IRTemp_INVALID;
   13066          assign( argL, getIRegA(rM));
   13067          assign( argR, getIRegA(rS));
   13068          assign( res, binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) );
   13069          if (bitS) {
   13070             oldC = newTemp(Ity_I32);
   13071             assign(oldC, mk_armg_calculate_flag_c());
   13072             oldV = newTemp(Ity_I32);
   13073             assign(oldV, mk_armg_calculate_flag_v());
   13074          }
   13075          // now update guest state
   13076          putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   13077          if (bitS) {
   13078             IRTemp pair = newTemp(Ity_I32);
   13079             assign( pair, binop(Iop_Or32,
   13080                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13081                                 mkexpr(oldV)) );
   13082             setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
   13083          }
   13084          DIP("mul%c%s r%u, r%u, r%u\n",
   13085              bitS ? 's' : ' ', nCC(INSN_COND), rD, rM, rS);
   13086          goto decode_success;
   13087       }
   13088       /* fall through */
   13089    }
   13090 
   13091    // MLA, MLS
   13092    if (BITS8(0,0,0,0,0,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13093        && INSN(7,4) == BITS4(1,0,0,1)) {
   13094       UInt bitS  = (insn >> 20) & 1; /* 20:20 */
   13095       UInt isMLS = (insn >> 22) & 1; /* 22:22 */
   13096       UInt rD = INSN(19,16);
   13097       UInt rN = INSN(15,12);
   13098       UInt rS = INSN(11,8);
   13099       UInt rM = INSN(3,0);
   13100       if (bitS == 1 && isMLS == 1) {
   13101          /* This isn't allowed (MLS that sets flags).  don't decode;
   13102             fall through */
   13103       }
   13104       else
   13105       if (rD == 15 || rM == 15 || rS == 15 || rN == 15) {
   13106          /* Unpredictable; don't decode; fall through */
   13107       } else {
   13108          IRTemp argL = newTemp(Ity_I32);
   13109          IRTemp argR = newTemp(Ity_I32);
   13110          IRTemp argP = newTemp(Ity_I32);
   13111          IRTemp res  = newTemp(Ity_I32);
   13112          IRTemp oldC = IRTemp_INVALID;
   13113          IRTemp oldV = IRTemp_INVALID;
   13114          assign( argL, getIRegA(rM));
   13115          assign( argR, getIRegA(rS));
   13116          assign( argP, getIRegA(rN));
   13117          assign( res, binop(isMLS ? Iop_Sub32 : Iop_Add32,
   13118                             mkexpr(argP),
   13119                             binop(Iop_Mul32, mkexpr(argL), mkexpr(argR)) ));
   13120          if (bitS) {
   13121             vassert(!isMLS); // guaranteed above
   13122             oldC = newTemp(Ity_I32);
   13123             assign(oldC, mk_armg_calculate_flag_c());
   13124             oldV = newTemp(Ity_I32);
   13125             assign(oldV, mk_armg_calculate_flag_v());
   13126          }
   13127          // now update guest state
   13128          putIRegA( rD, mkexpr(res), condT, Ijk_Boring );
   13129          if (bitS) {
   13130             IRTemp pair = newTemp(Ity_I32);
   13131             assign( pair, binop(Iop_Or32,
   13132                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13133                                 mkexpr(oldV)) );
   13134             setFlags_D1_ND( ARMG_CC_OP_MUL, res, pair, condT );
   13135          }
   13136          DIP("ml%c%c%s r%u, r%u, r%u, r%u\n",
   13137              isMLS ? 's' : 'a', bitS ? 's' : ' ',
   13138              nCC(INSN_COND), rD, rM, rS, rN);
   13139          goto decode_success;
   13140       }
   13141       /* fall through */
   13142    }
   13143 
   13144    // SMULL, UMULL
   13145    if (BITS8(0,0,0,0,1,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13146        && INSN(7,4) == BITS4(1,0,0,1)) {
   13147       UInt bitS = (insn >> 20) & 1; /* 20:20 */
   13148       UInt rDhi = INSN(19,16);
   13149       UInt rDlo = INSN(15,12);
   13150       UInt rS   = INSN(11,8);
   13151       UInt rM   = INSN(3,0);
   13152       UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
   13153       if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
   13154          /* Unpredictable; don't decode; fall through */
   13155       } else {
   13156          IRTemp argL  = newTemp(Ity_I32);
   13157          IRTemp argR  = newTemp(Ity_I32);
   13158          IRTemp res   = newTemp(Ity_I64);
   13159          IRTemp resHi = newTemp(Ity_I32);
   13160          IRTemp resLo = newTemp(Ity_I32);
   13161          IRTemp oldC  = IRTemp_INVALID;
   13162          IRTemp oldV  = IRTemp_INVALID;
   13163          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
   13164          assign( argL, getIRegA(rM));
   13165          assign( argR, getIRegA(rS));
   13166          assign( res, binop(mulOp, mkexpr(argL), mkexpr(argR)) );
   13167          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
   13168          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
   13169          if (bitS) {
   13170             oldC = newTemp(Ity_I32);
   13171             assign(oldC, mk_armg_calculate_flag_c());
   13172             oldV = newTemp(Ity_I32);
   13173             assign(oldV, mk_armg_calculate_flag_v());
   13174          }
   13175          // now update guest state
   13176          putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
   13177          putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
   13178          if (bitS) {
   13179             IRTemp pair = newTemp(Ity_I32);
   13180             assign( pair, binop(Iop_Or32,
   13181                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13182                                 mkexpr(oldV)) );
   13183             setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
   13184          }
   13185          DIP("%cmull%c%s r%u, r%u, r%u, r%u\n",
   13186              isS ? 's' : 'u', bitS ? 's' : ' ',
   13187              nCC(INSN_COND), rDlo, rDhi, rM, rS);
   13188          goto decode_success;
   13189       }
   13190       /* fall through */
   13191    }
   13192 
   13193    // SMLAL, UMLAL
   13194    if (BITS8(0,0,0,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13195        && INSN(7,4) == BITS4(1,0,0,1)) {
   13196       UInt bitS = (insn >> 20) & 1; /* 20:20 */
   13197       UInt rDhi = INSN(19,16);
   13198       UInt rDlo = INSN(15,12);
   13199       UInt rS   = INSN(11,8);
   13200       UInt rM   = INSN(3,0);
   13201       UInt isS  = (INSN(27,20) >> 2) & 1; /* 22:22 */
   13202       if (rDhi == 15 || rDlo == 15 || rM == 15 || rS == 15 || rDhi == rDlo)  {
   13203          /* Unpredictable; don't decode; fall through */
   13204       } else {
   13205          IRTemp argL  = newTemp(Ity_I32);
   13206          IRTemp argR  = newTemp(Ity_I32);
   13207          IRTemp old   = newTemp(Ity_I64);
   13208          IRTemp res   = newTemp(Ity_I64);
   13209          IRTemp resHi = newTemp(Ity_I32);
   13210          IRTemp resLo = newTemp(Ity_I32);
   13211          IRTemp oldC  = IRTemp_INVALID;
   13212          IRTemp oldV  = IRTemp_INVALID;
   13213          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
   13214          assign( argL, getIRegA(rM));
   13215          assign( argR, getIRegA(rS));
   13216          assign( old, binop(Iop_32HLto64, getIRegA(rDhi), getIRegA(rDlo)) );
   13217          assign( res, binop(Iop_Add64,
   13218                             mkexpr(old),
   13219                             binop(mulOp, mkexpr(argL), mkexpr(argR))) );
   13220          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
   13221          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
   13222          if (bitS) {
   13223             oldC = newTemp(Ity_I32);
   13224             assign(oldC, mk_armg_calculate_flag_c());
   13225             oldV = newTemp(Ity_I32);
   13226             assign(oldV, mk_armg_calculate_flag_v());
   13227          }
   13228          // now update guest state
   13229          putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
   13230          putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
   13231          if (bitS) {
   13232             IRTemp pair = newTemp(Ity_I32);
   13233             assign( pair, binop(Iop_Or32,
   13234                                 binop(Iop_Shl32, mkexpr(oldC), mkU8(1)),
   13235                                 mkexpr(oldV)) );
   13236             setFlags_D1_D2_ND( ARMG_CC_OP_MULL, resLo, resHi, pair, condT );
   13237          }
   13238          DIP("%cmlal%c%s r%u, r%u, r%u, r%u\n",
   13239              isS ? 's' : 'u', bitS ? 's' : ' ', nCC(INSN_COND),
   13240              rDlo, rDhi, rM, rS);
   13241          goto decode_success;
   13242       }
   13243       /* fall through */
   13244    }
   13245 
   13246    /* --------------------- Msr etc --------------------- */
   13247 
   13248    // MSR apsr, #imm
   13249    if (INSN(27,20) == BITS8(0,0,1,1,0,0,1,0)
   13250        && INSN(17,12) == BITS6(0,0,1,1,1,1)) {
   13251       UInt write_ge    = INSN(18,18);
   13252       UInt write_nzcvq = INSN(19,19);
   13253       if (write_nzcvq || write_ge) {
   13254          UInt   imm = (INSN(11,0) >> 0) & 0xFF;
   13255          UInt   rot = 2 * ((INSN(11,0) >> 8) & 0xF);
   13256          IRTemp immT = newTemp(Ity_I32);
   13257          vassert(rot <= 30);
   13258          imm = ROR32(imm, rot);
   13259          assign(immT, mkU32(imm));
   13260          desynthesise_APSR( write_nzcvq, write_ge, immT, condT );
   13261          DIP("msr%s cpsr%s%sf, #0x%08x\n", nCC(INSN_COND),
   13262              write_nzcvq ? "f" : "", write_ge ? "g" : "", imm);
   13263          goto decode_success;
   13264       }
   13265       /* fall through */
   13266    }
   13267 
   13268    // MSR apsr, reg
   13269    if (INSN(27,20) == BITS8(0,0,0,1,0,0,1,0)
   13270        && INSN(17,12) == BITS6(0,0,1,1,1,1)
   13271        && INSN(11,4) == BITS8(0,0,0,0,0,0,0,0)) {
   13272       UInt rN          = INSN(3,0);
   13273       UInt write_ge    = INSN(18,18);
   13274       UInt write_nzcvq = INSN(19,19);
   13275       if (rN != 15 && (write_nzcvq || write_ge)) {
   13276          IRTemp rNt = newTemp(Ity_I32);
   13277          assign(rNt, getIRegA(rN));
   13278          desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
   13279          DIP("msr%s cpsr_%s%s, r%u\n", nCC(INSN_COND),
   13280              write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
   13281          goto decode_success;
   13282       }
   13283       /* fall through */
   13284    }
   13285 
   13286    // MRS rD, cpsr
   13287    if ((insn & 0x0FFF0FFF) == 0x010F0000) {
   13288       UInt rD   = INSN(15,12);
   13289       if (rD != 15) {
   13290          IRTemp apsr = synthesise_APSR();
   13291          putIRegA( rD, mkexpr(apsr), condT, Ijk_Boring );
   13292          DIP("mrs%s r%u, cpsr\n", nCC(INSN_COND), rD);
   13293          goto decode_success;
   13294       }
   13295       /* fall through */
   13296    }
   13297 
   13298    /* --------------------- Svc --------------------- */
   13299    if (BITS8(1,1,1,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))) {
   13300       UInt imm24 = (insn >> 0) & 0xFFFFFF;
   13301       if (imm24 == 0) {
   13302          /* A syscall.  We can't do this conditionally, hence: */
   13303          if (condT != IRTemp_INVALID) {
   13304             mk_skip_over_A32_if_cond_is_false( condT );
   13305          }
   13306          // AL after here
   13307          irsb->next     = mkU32( guest_R15_curr_instr_notENC + 4 );
   13308          irsb->jumpkind = Ijk_Sys_syscall;
   13309          dres.whatNext  = Dis_StopHere;
   13310          DIP("svc%s #0x%08x\n", nCC(INSN_COND), imm24);
   13311          goto decode_success;
   13312       }
   13313       /* fall through */
   13314    }
   13315 
   13316    /* ------------------------ swp ------------------------ */
   13317 
   13318    // SWP, SWPB
   13319    if (BITS8(0,0,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   13320        && BITS4(0,0,0,0) == INSN(11,8)
   13321        && BITS4(1,0,0,1) == INSN(7,4)) {
   13322       UInt   rN   = INSN(19,16);
   13323       UInt   rD   = INSN(15,12);
   13324       UInt   rM   = INSN(3,0);
   13325       IRTemp tRn  = newTemp(Ity_I32);
   13326       IRTemp tNew = newTemp(Ity_I32);
   13327       IRTemp tOld = IRTemp_INVALID;
   13328       IRTemp tSC1 = newTemp(Ity_I1);
   13329       UInt   isB  = (insn >> 22) & 1;
   13330 
   13331       if (rD == 15 || rN == 15 || rM == 15 || rN == rM || rN == rD) {
   13332          /* undecodable; fall through */
   13333       } else {
   13334          /* make unconditional */
   13335          if (condT != IRTemp_INVALID) {
   13336             mk_skip_over_A32_if_cond_is_false( condT );
   13337             condT = IRTemp_INVALID;
   13338          }
   13339          /* Ok, now we're unconditional.  Generate a LL-SC loop. */
   13340          assign(tRn, getIRegA(rN));
   13341          assign(tNew, getIRegA(rM));
   13342          if (isB) {
   13343             /* swpb */
   13344             tOld = newTemp(Ity_I8);
   13345             stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
   13346                               NULL/*=>isLL*/) );
   13347             stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
   13348                               unop(Iop_32to8, mkexpr(tNew))) );
   13349          } else {
   13350             /* swp */
   13351             tOld = newTemp(Ity_I32);
   13352             stmt( IRStmt_LLSC(Iend_LE, tOld, mkexpr(tRn),
   13353                               NULL/*=>isLL*/) );
   13354             stmt( IRStmt_LLSC(Iend_LE, tSC1, mkexpr(tRn),
   13355                               mkexpr(tNew)) );
   13356          }
   13357          stmt( IRStmt_Exit(unop(Iop_Not1, mkexpr(tSC1)),
   13358                            /*Ijk_NoRedir*/Ijk_Boring,
   13359                            IRConst_U32(guest_R15_curr_instr_notENC)) );
   13360          putIRegA(rD, isB ? unop(Iop_8Uto32, mkexpr(tOld)) : mkexpr(tOld),
   13361                       IRTemp_INVALID, Ijk_Boring);
   13362          DIP("swp%s%s r%u, r%u, [r%u]\n",
   13363              isB ? "b" : "", nCC(INSN_COND), rD, rM, rN);
   13364          goto decode_success;
   13365       }
   13366       /* fall through */
   13367    }
   13368 
   13369    /* ----------------------------------------------------------- */
   13370    /* -- ARMv6 instructions                                    -- */
   13371    /* ----------------------------------------------------------- */
   13372 
   13373    /* --------------------- ldrex, strex --------------------- */
   13374 
   13375    // LDREX
   13376    if (0x01900F9F == (insn & 0x0FF00FFF)) {
   13377       UInt rT = INSN(15,12);
   13378       UInt rN = INSN(19,16);
   13379       if (rT == 15 || rN == 15) {
   13380          /* undecodable; fall through */
   13381       } else {
   13382          IRTemp res;
   13383          /* make unconditional */
   13384          if (condT != IRTemp_INVALID) {
   13385             mk_skip_over_A32_if_cond_is_false( condT );
   13386             condT = IRTemp_INVALID;
   13387          }
   13388          /* Ok, now we're unconditional.  Do the load. */
   13389          res = newTemp(Ity_I32);
   13390          stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN),
   13391                            NULL/*this is a load*/) );
   13392          putIRegA(rT, mkexpr(res), IRTemp_INVALID, Ijk_Boring);
   13393          DIP("ldrex%s r%u, [r%u]\n", nCC(INSN_COND), rT, rN);
   13394          goto decode_success;
   13395       }
   13396       /* fall through */
   13397    }
   13398 
   13399    // STREX
   13400    if (0x01800F90 == (insn & 0x0FF00FF0)) {
   13401       UInt rT = INSN(3,0);
   13402       UInt rN = INSN(19,16);
   13403       UInt rD = INSN(15,12);
   13404       if (rT == 15 || rN == 15 || rD == 15
   13405           || rD == rT || rD == rN) {
   13406          /* undecodable; fall through */
   13407       } else {
   13408          IRTemp resSC1, resSC32;
   13409 
   13410          /* make unconditional */
   13411          if (condT != IRTemp_INVALID) {
   13412             mk_skip_over_A32_if_cond_is_false( condT );
   13413             condT = IRTemp_INVALID;
   13414          }
   13415 
   13416          /* Ok, now we're unconditional.  Do the store. */
   13417          resSC1 = newTemp(Ity_I1);
   13418          stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), getIRegA(rT)) );
   13419 
   13420          /* Set rD to 1 on failure, 0 on success.  Currently we have
   13421             resSC1 == 0 on failure, 1 on success. */
   13422          resSC32 = newTemp(Ity_I32);
   13423          assign(resSC32,
   13424                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   13425 
   13426          putIRegA(rD, mkexpr(resSC32),
   13427                       IRTemp_INVALID, Ijk_Boring);
   13428          DIP("strex%s r%u, r%u, [r%u]\n", nCC(INSN_COND), rD, rT, rN);
   13429          goto decode_success;
   13430       }
   13431       /* fall through */
   13432    }
   13433 
   13434    /* --------------------- movw, movt --------------------- */
   13435    if (0x03000000 == (insn & 0x0FF00000)
   13436        || 0x03400000 == (insn & 0x0FF00000)) /* pray for CSE */ {
   13437       UInt rD    = INSN(15,12);
   13438       UInt imm16 = (insn & 0xFFF) | ((insn >> 4) & 0x0000F000);
   13439       UInt isT   = (insn >> 22) & 1;
   13440       if (rD == 15) {
   13441          /* forget it */
   13442       } else {
   13443          if (isT) {
   13444             putIRegA(rD,
   13445                      binop(Iop_Or32,
   13446                            binop(Iop_And32, getIRegA(rD), mkU32(0xFFFF)),
   13447                            mkU32(imm16 << 16)),
   13448                      condT, Ijk_Boring);
   13449             DIP("movt%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
   13450             goto decode_success;
   13451          } else {
   13452             putIRegA(rD, mkU32(imm16), condT, Ijk_Boring);
   13453             DIP("movw%s r%u, #0x%04x\n", nCC(INSN_COND), rD, imm16);
   13454             goto decode_success;
   13455          }
   13456       }
   13457       /* fall through */
   13458    }
   13459 
   13460    /* ----------- uxtb, sxtb, uxth, sxth, uxtb16, sxtb16 ----------- */
   13461    /* FIXME: this is an exact duplicate of the Thumb version.  They
   13462       should be commoned up. */
   13463    if (BITS8(0,1,1,0,1, 0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,0,0))
   13464        && BITS4(1,1,1,1) == INSN(19,16)
   13465        && BITS4(0,1,1,1) == INSN(7,4)
   13466        && BITS4(0,0, 0,0) == (INSN(11,8) & BITS4(0,0,1,1))) {
   13467       UInt subopc = INSN(27,20) & BITS8(0,0,0,0,0, 1,1,1);
   13468       if (subopc != BITS4(0,0,0,1) && subopc != BITS4(0,1,0,1)) {
   13469          Int    rot  = (INSN(11,8) >> 2) & 3;
   13470          UInt   rM   = INSN(3,0);
   13471          UInt   rD   = INSN(15,12);
   13472          IRTemp srcT = newTemp(Ity_I32);
   13473          IRTemp rotT = newTemp(Ity_I32);
   13474          IRTemp dstT = newTemp(Ity_I32);
   13475          HChar* nm   = "???";
   13476          assign(srcT, getIRegA(rM));
   13477          assign(rotT, genROR32(srcT, 8 * rot)); /* 0, 8, 16 or 24 only */
   13478          switch (subopc) {
   13479             case BITS4(0,1,1,0): // UXTB
   13480                assign(dstT, unop(Iop_8Uto32, unop(Iop_32to8, mkexpr(rotT))));
   13481                nm = "uxtb";
   13482                break;
   13483             case BITS4(0,0,1,0): // SXTB
   13484                assign(dstT, unop(Iop_8Sto32, unop(Iop_32to8, mkexpr(rotT))));
   13485                nm = "sxtb";
   13486                break;
   13487             case BITS4(0,1,1,1): // UXTH
   13488                assign(dstT, unop(Iop_16Uto32, unop(Iop_32to16, mkexpr(rotT))));
   13489                nm = "uxth";
   13490                break;
   13491             case BITS4(0,0,1,1): // SXTH
   13492                assign(dstT, unop(Iop_16Sto32, unop(Iop_32to16, mkexpr(rotT))));
   13493                nm = "sxth";
   13494                break;
   13495             case BITS4(0,1,0,0): // UXTB16
   13496                assign(dstT, binop(Iop_And32, mkexpr(rotT), mkU32(0x00FF00FF)));
   13497                nm = "uxtb16";
   13498                break;
   13499             case BITS4(0,0,0,0): { // SXTB16
   13500                IRTemp lo32 = newTemp(Ity_I32);
   13501                IRTemp hi32 = newTemp(Ity_I32);
   13502                assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
   13503                assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
   13504                assign(
   13505                   dstT,
   13506                   binop(Iop_Or32,
   13507                         binop(Iop_And32,
   13508                               unop(Iop_8Sto32,
   13509                                    unop(Iop_32to8, mkexpr(lo32))),
   13510                               mkU32(0xFFFF)),
   13511                         binop(Iop_Shl32,
   13512                               unop(Iop_8Sto32,
   13513                                    unop(Iop_32to8, mkexpr(hi32))),
   13514                               mkU8(16))
   13515                ));
   13516                nm = "sxtb16";
   13517                break;
   13518             }
   13519             default:
   13520                vassert(0); // guarded by "if" above
   13521          }
   13522          putIRegA(rD, mkexpr(dstT), condT, Ijk_Boring);
   13523          DIP("%s%s r%u, r%u, ROR #%u\n", nm, nCC(INSN_COND), rD, rM, rot);
   13524          goto decode_success;
   13525       }
   13526       /* fall through */
   13527    }
   13528 
   13529    /* ------------------- bfi, bfc ------------------- */
   13530    if (BITS8(0,1,1,1,1,1,0, 0) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,0))
   13531        && BITS4(0, 0,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
   13532       UInt rD  = INSN(15,12);
   13533       UInt rN  = INSN(3,0);
   13534       UInt msb = (insn >> 16) & 0x1F; /* 20:16 */
   13535       UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
   13536       if (rD == 15 || msb < lsb) {
   13537          /* undecodable; fall through */
   13538       } else {
   13539          IRTemp src    = newTemp(Ity_I32);
   13540          IRTemp olddst = newTemp(Ity_I32);
   13541          IRTemp newdst = newTemp(Ity_I32);
   13542          UInt   mask = 1 << (msb - lsb);
   13543          mask = (mask - 1) + mask;
   13544          vassert(mask != 0); // guaranteed by "msb < lsb" check above
   13545          mask <<= lsb;
   13546 
   13547          assign(src, rN == 15 ? mkU32(0) : getIRegA(rN));
   13548          assign(olddst, getIRegA(rD));
   13549          assign(newdst,
   13550                 binop(Iop_Or32,
   13551                    binop(Iop_And32,
   13552                          binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
   13553                          mkU32(mask)),
   13554                    binop(Iop_And32,
   13555                          mkexpr(olddst),
   13556                          mkU32(~mask)))
   13557                );
   13558 
   13559          putIRegA(rD, mkexpr(newdst), condT, Ijk_Boring);
   13560 
   13561          if (rN == 15) {
   13562             DIP("bfc%s r%u, #%u, #%u\n",
   13563                 nCC(INSN_COND), rD, lsb, msb-lsb+1);
   13564          } else {
   13565             DIP("bfi%s r%u, r%u, #%u, #%u\n",
   13566                 nCC(INSN_COND), rD, rN, lsb, msb-lsb+1);
   13567          }
   13568          goto decode_success;
   13569       }
   13570       /* fall through */
   13571    }
   13572 
   13573    /* ------------------- {u,s}bfx ------------------- */
   13574    if (BITS8(0,1,1,1,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,0))
   13575        && BITS4(0,1,0,1) == (INSN(7,4) & BITS4(0,1,1,1))) {
   13576       UInt rD  = INSN(15,12);
   13577       UInt rN  = INSN(3,0);
   13578       UInt wm1 = (insn >> 16) & 0x1F; /* 20:16 */
   13579       UInt lsb = (insn >> 7) & 0x1F;  /* 11:7 */
   13580       UInt msb = lsb + wm1;
   13581       UInt isU = (insn >> 22) & 1;    /* 22:22 */
   13582       if (rD == 15 || rN == 15 || msb >= 32) {
   13583          /* undecodable; fall through */
   13584       } else {
   13585          IRTemp src  = newTemp(Ity_I32);
   13586          IRTemp tmp  = newTemp(Ity_I32);
   13587          IRTemp res  = newTemp(Ity_I32);
   13588          UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
   13589          vassert(msb >= 0 && msb <= 31);
   13590          vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
   13591 
   13592          assign(src, getIRegA(rN));
   13593          assign(tmp, binop(Iop_And32,
   13594                            binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
   13595                            mkU32(mask)));
   13596          assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
   13597                            binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
   13598                            mkU8(31-wm1)));
   13599 
   13600          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13601 
   13602          DIP("%s%s r%u, r%u, #%u, #%u\n",
   13603              isU ? "ubfx" : "sbfx",
   13604              nCC(INSN_COND), rD, rN, lsb, wm1 + 1);
   13605          goto decode_success;
   13606       }
   13607       /* fall through */
   13608    }
   13609 
   13610    /* --------------------- Load/store doubleword ------------- */
   13611    // LDRD STRD
   13612    /*                 31   27   23   19 15 11   7    3     # highest bit
   13613                         28   24   20 16 12    8    4    0
   13614       A5-36   1 | 16  cond 0001 U100 Rn Rd im4h 11S1 im4l
   13615       A5-38   1 | 32  cond 0001 U000 Rn Rd 0000 11S1 Rm
   13616       A5-40   2 | 16  cond 0001 U110 Rn Rd im4h 11S1 im4l
   13617       A5-42   2 | 32  cond 0001 U010 Rn Rd 0000 11S1 Rm
   13618       A5-44   3 | 16  cond 0000 U100 Rn Rd im4h 11S1 im4l
   13619       A5-46   3 | 32  cond 0000 U000 Rn Rd 0000 11S1 Rm
   13620    */
   13621    /* case coding:
   13622              1   at-ea               (access at ea)
   13623              2   at-ea-then-upd      (access at ea, then Rn = ea)
   13624              3   at-Rn-then-upd      (access at Rn, then Rn = ea)
   13625       ea coding
   13626              16  Rn +/- imm8
   13627              32  Rn +/- Rm
   13628    */
   13629    /* Quickly skip over all of this for hopefully most instructions */
   13630    if ((INSN(27,24) & BITS4(1,1,1,0)) != BITS4(0,0,0,0))
   13631       goto after_load_store_doubleword;
   13632 
   13633    /* Check the "11S1" thing. */
   13634    if ((INSN(7,4) & BITS4(1,1,0,1)) != BITS4(1,1,0,1))
   13635       goto after_load_store_doubleword;
   13636 
   13637    summary = 0;
   13638 
   13639    /**/ if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,0,0)) {
   13640       summary = 1 | 16;
   13641    }
   13642    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,0,0)) {
   13643       summary = 1 | 32;
   13644    }
   13645    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(1,1,0)) {
   13646       summary = 2 | 16;
   13647    }
   13648    else if (INSN(27,24) == BITS4(0,0,0,1) && INSN(22,20) == BITS3(0,1,0)) {
   13649       summary = 2 | 32;
   13650    }
   13651    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(1,0,0)) {
   13652       summary = 3 | 16;
   13653    }
   13654    else if (INSN(27,24) == BITS4(0,0,0,0) && INSN(22,20) == BITS3(0,0,0)) {
   13655       summary = 3 | 32;
   13656    }
   13657    else goto after_load_store_doubleword;
   13658 
   13659    { UInt rN   = (insn >> 16) & 0xF; /* 19:16 */
   13660      UInt rD   = (insn >> 12) & 0xF; /* 15:12 */
   13661      UInt rM   = (insn >> 0)  & 0xF; /*  3:0  */
   13662      UInt bU   = (insn >> 23) & 1;   /* 23 U=1 offset+, U=0 offset- */
   13663      UInt bS   = (insn >> 5) & 1;    /* S=1 store, S=0 load */
   13664      UInt imm8 = ((insn >> 4) & 0xF0) | (insn & 0xF); /* 11:8, 3:0 */
   13665 
   13666      /* Require rD to be an even numbered register */
   13667      if ((rD & 1) != 0)
   13668         goto after_load_store_doubleword;
   13669 
   13670      /* Require 11:8 == 0 for Rn +/- Rm cases */
   13671      if ((summary & 32) != 0 && (imm8 & 0xF0) != 0)
   13672         goto after_load_store_doubleword;
   13673 
   13674      /* Skip some invalid cases, which would lead to two competing
   13675         updates to the same register, or which are otherwise
   13676         disallowed by the spec. */
   13677      switch (summary) {
   13678         case 1 | 16:
   13679            break;
   13680         case 1 | 32:
   13681            if (rM == 15) goto after_load_store_doubleword;
   13682            break;
   13683         case 2 | 16: case 3 | 16:
   13684            if (rN == 15) goto after_load_store_doubleword;
   13685            if (bS == 0 && (rN == rD || rN == rD+1))
   13686               goto after_load_store_doubleword;
   13687            break;
   13688         case 2 | 32: case 3 | 32:
   13689            if (rM == 15) goto after_load_store_doubleword;
   13690            if (rN == 15) goto after_load_store_doubleword;
   13691            if (rN == rM) goto after_load_store_doubleword;
   13692            if (bS == 0 && (rN == rD || rN == rD+1))
   13693               goto after_load_store_doubleword;
   13694            break;
   13695         default:
   13696            vassert(0);
   13697      }
   13698 
   13699      /* Now, we can't do a conditional load or store, since that very
   13700         likely will generate an exception.  So we have to take a side
   13701         exit at this point if the condition is false. */
   13702      if (condT != IRTemp_INVALID) {
   13703         mk_skip_over_A32_if_cond_is_false( condT );
   13704         condT = IRTemp_INVALID;
   13705      }
   13706      /* Ok, now we're unconditional.  Do the load or store. */
   13707 
   13708      /* compute the effective address.  Bind it to a tmp since we
   13709         may need to use it twice. */
   13710      IRExpr* eaE = NULL;
   13711      switch (summary & 0xF0) {
   13712         case 16:
   13713            eaE = mk_EA_reg_plusminus_imm8( rN, bU, imm8, dis_buf );
   13714            break;
   13715         case 32:
   13716            eaE = mk_EA_reg_plusminus_reg( rN, bU, rM, dis_buf );
   13717            break;
   13718      }
   13719      vassert(eaE);
   13720      IRTemp eaT = newTemp(Ity_I32);
   13721      assign(eaT, eaE);
   13722 
   13723      /* get the old Rn value */
   13724      IRTemp rnT = newTemp(Ity_I32);
   13725      assign(rnT, getIRegA(rN));
   13726 
   13727      /* decide on the transfer address */
   13728      IRTemp taT = IRTemp_INVALID;
   13729      switch (summary & 0x0F) {
   13730         case 1: case 2: taT = eaT; break;
   13731         case 3:         taT = rnT; break;
   13732      }
   13733      vassert(taT != IRTemp_INVALID);
   13734 
   13735      /* XXX deal with alignment constraints */
   13736      /* XXX: but the A8 doesn't seem to trap for misaligned loads, so,
   13737         ignore alignment issues for the time being. */
   13738 
   13739      /* doubleword store  S 1
   13740         doubleword load   S 0
   13741      */
   13742      HChar* name = NULL;
   13743      /* generate the transfers */
   13744      if (bS == 1) { // doubleword store
   13745         storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(0)), getIRegA(rD+0) );
   13746         storeLE( binop(Iop_Add32, mkexpr(taT), mkU32(4)), getIRegA(rD+1) );
   13747         name = "strd";
   13748      } else { // doubleword load
   13749         putIRegA( rD+0,
   13750                   loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(0))),
   13751                   IRTemp_INVALID, Ijk_Boring );
   13752         putIRegA( rD+1,
   13753                   loadLE(Ity_I32, binop(Iop_Add32, mkexpr(taT), mkU32(4))),
   13754                   IRTemp_INVALID, Ijk_Boring );
   13755         name = "ldrd";
   13756      }
   13757 
   13758      /* Update Rn if necessary. */
   13759      switch (summary & 0x0F) {
   13760         case 2: case 3:
   13761            // should be assured by logic above:
   13762            if (bS == 0) {
   13763               vassert(rD+0 != rN); /* since we just wrote rD+0 */
   13764               vassert(rD+1 != rN); /* since we just wrote rD+1 */
   13765            }
   13766            putIRegA( rN, mkexpr(eaT), IRTemp_INVALID, Ijk_Boring );
   13767            break;
   13768      }
   13769 
   13770      switch (summary & 0x0F) {
   13771         case 1:  DIP("%s%s r%u, %s\n", name, nCC(INSN_COND), rD, dis_buf);
   13772                  break;
   13773         case 2:  DIP("%s%s r%u, %s! (at-EA-then-Rn=EA)\n",
   13774                      name, nCC(INSN_COND), rD, dis_buf);
   13775                  break;
   13776         case 3:  DIP("%s%s r%u, %s! (at-Rn-then-Rn=EA)\n",
   13777                      name, nCC(INSN_COND), rD, dis_buf);
   13778                  break;
   13779         default: vassert(0);
   13780      }
   13781 
   13782      goto decode_success;
   13783    }
   13784 
   13785   after_load_store_doubleword:
   13786 
   13787    /* ------------------- {s,u}xtab ------------- */
   13788    if (BITS8(0,1,1,0,1,0,1,0) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   13789        && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
   13790        && BITS4(0,1,1,1) == INSN(7,4)) {
   13791       UInt rN  = INSN(19,16);
   13792       UInt rD  = INSN(15,12);
   13793       UInt rM  = INSN(3,0);
   13794       UInt rot = (insn >> 10) & 3;
   13795       UInt isU = INSN(22,22);
   13796       if (rN == 15/*it's {S,U}XTB*/ || rD == 15 || rM == 15) {
   13797          /* undecodable; fall through */
   13798       } else {
   13799          IRTemp srcL = newTemp(Ity_I32);
   13800          IRTemp srcR = newTemp(Ity_I32);
   13801          IRTemp res  = newTemp(Ity_I32);
   13802          assign(srcR, getIRegA(rM));
   13803          assign(srcL, getIRegA(rN));
   13804          assign(res,  binop(Iop_Add32,
   13805                             mkexpr(srcL),
   13806                             unop(isU ? Iop_8Uto32 : Iop_8Sto32,
   13807                                  unop(Iop_32to8,
   13808                                       genROR32(srcR, 8 * rot)))));
   13809          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13810          DIP("%cxtab%s r%u, r%u, r%u, ror #%u\n",
   13811              isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
   13812          goto decode_success;
   13813       }
   13814       /* fall through */
   13815    }
   13816 
   13817    /* ------------------- {s,u}xtah ------------- */
   13818    if (BITS8(0,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
   13819        && BITS4(0,0,0,0) == (INSN(11,8) & BITS4(0,0,1,1))
   13820        && BITS4(0,1,1,1) == INSN(7,4)) {
   13821       UInt rN  = INSN(19,16);
   13822       UInt rD  = INSN(15,12);
   13823       UInt rM  = INSN(3,0);
   13824       UInt rot = (insn >> 10) & 3;
   13825       UInt isU = INSN(22,22);
   13826       if (rN == 15/*it's {S,U}XTH*/ || rD == 15 || rM == 15) {
   13827          /* undecodable; fall through */
   13828       } else {
   13829          IRTemp srcL = newTemp(Ity_I32);
   13830          IRTemp srcR = newTemp(Ity_I32);
   13831          IRTemp res  = newTemp(Ity_I32);
   13832          assign(srcR, getIRegA(rM));
   13833          assign(srcL, getIRegA(rN));
   13834          assign(res,  binop(Iop_Add32,
   13835                             mkexpr(srcL),
   13836                             unop(isU ? Iop_16Uto32 : Iop_16Sto32,
   13837                                  unop(Iop_32to16,
   13838                                       genROR32(srcR, 8 * rot)))));
   13839          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13840 
   13841          DIP("%cxtah%s r%u, r%u, r%u, ror #%u\n",
   13842              isU ? 'u' : 's', nCC(INSN_COND), rD, rN, rM, rot);
   13843          goto decode_success;
   13844       }
   13845       /* fall through */
   13846    }
   13847 
   13848    /* ------------------- rev16, rev ------------------ */
   13849    if (INSN(27,16) == 0x6BF
   13850        && (INSN(11,4) == 0xFB/*rev16*/ || INSN(11,4) == 0xF3/*rev*/)) {
   13851       Bool isREV = INSN(11,4) == 0xF3;
   13852       UInt rM    = INSN(3,0);
   13853       UInt rD    = INSN(15,12);
   13854       if (rM != 15 && rD != 15) {
   13855          IRTemp rMt = newTemp(Ity_I32);
   13856          assign(rMt, getIRegA(rM));
   13857          IRTemp res = isREV ? gen_REV(rMt) : gen_REV16(rMt);
   13858          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13859          DIP("rev%s%s r%u, r%u\n", isREV ? "" : "16",
   13860              nCC(INSN_COND), rD, rM);
   13861          goto decode_success;
   13862       }
   13863    }
   13864 
   13865    /* ------------------- rbit ------------------ */
   13866    if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) {
   13867       UInt rD = INSN(15,12);
   13868       UInt rM = INSN(3,0);
   13869       if (rD != 15 && rM != 15) {
   13870          IRTemp arg = newTemp(Ity_I32);
   13871          assign(arg, getIRegA(rM));
   13872          IRTemp res = gen_BITREV(arg);
   13873          putIRegA(rD, mkexpr(res), condT, Ijk_Boring);
   13874          DIP("rbit r%u, r%u\n", rD, rM);
   13875          goto decode_success;
   13876       }
   13877    }
   13878 
   13879    /* ------------------- smmul ------------------ */
   13880    if (INSN(27,20) == BITS8(0,1,1,1,0,1,0,1)
   13881        && INSN(15,12) == BITS4(1,1,1,1)
   13882        && (INSN(7,4) & BITS4(1,1,0,1)) == BITS4(0,0,0,1)) {
   13883       UInt bitR = INSN(5,5);
   13884       UInt rD = INSN(19,16);
   13885       UInt rM = INSN(11,8);
   13886       UInt rN = INSN(3,0);
   13887       if (rD != 15 && rM != 15 && rN != 15) {
   13888          IRExpr* res
   13889          = unop(Iop_64HIto32,
   13890                 binop(Iop_Add64,
   13891                       binop(Iop_MullS32, getIRegA(rN), getIRegA(rM)),
   13892                       mkU64(bitR ? 0x80000000ULL : 0ULL)));
   13893          putIRegA(rD, res, condT, Ijk_Boring);
   13894          DIP("smmul%s%s r%u, r%u, r%u\n",
   13895              nCC(INSN_COND), bitR ? "r" : "", rD, rN, rM);
   13896          goto decode_success;
   13897       }
   13898    }
   13899 
   13900    /* ------------------- NOP ------------------ */
   13901    if (0x0320F000 == (insn & 0x0FFFFFFF)) {
   13902       DIP("nop%s\n", nCC(INSN_COND));
   13903       goto decode_success;
   13904    }
   13905 
   13906    /* ----------------------------------------------------------- */
   13907    /* -- ARMv7 instructions                                    -- */
   13908    /* ----------------------------------------------------------- */
   13909 
   13910    /* -------------- read CP15 TPIDRURO register ------------- */
   13911    /* mrc     p15, 0, r0, c13, c0, 3  up to
   13912       mrc     p15, 0, r14, c13, c0, 3
   13913    */
   13914    /* I don't know whether this is really v7-only.  But anyway, we
   13915       have to support it since arm-linux uses TPIDRURO as a thread
   13916       state register. */
   13917    if (0x0E1D0F70 == (insn & 0x0FFF0FFF)) {
   13918       UInt rD = INSN(15,12);
   13919       if (rD <= 14) {
   13920          /* skip r15, that's too stupid to handle */
   13921          putIRegA(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32),
   13922                       condT, Ijk_Boring);
   13923          DIP("mrc%s p15,0, r%u, c13, c0, 3\n", nCC(INSN_COND), rD);
   13924          goto decode_success;
   13925       }
   13926       /* fall through */
   13927    }
   13928 
   13929    /* Handle various kinds of barriers.  This is rather indiscriminate
   13930       in the sense that they are all turned into an IR Fence, which
   13931       means we don't know which they are, so the back end has to
   13932       re-emit them all when it comes acrosss an IR Fence.
   13933    */
   13934    if (0xEE070F9A == (insn & 0xFFFF0FFF)) { /* v6 */
   13935       /* mcr 15, 0, r0, c7, c10, 4 (v6) equiv to DSB (v7).  Data
   13936          Synch Barrier -- ensures completion of memory accesses. */
   13937       stmt( IRStmt_MBE(Imbe_Fence) );
   13938       DIP("mcr 15, 0, rX, c7, c10, 4 (data synch barrier)\n");
   13939       goto decode_success;
   13940    }
   13941    if (0xEE070FBA == (insn & 0xFFFF0FFF)) { /* v6 */
   13942       /* mcr 15, 0, r0, c7, c10, 5 (v6) equiv to DMB (v7).  Data
   13943          Memory Barrier -- ensures ordering of memory accesses. */
   13944       stmt( IRStmt_MBE(Imbe_Fence) );
   13945       DIP("mcr 15, 0, rX, c7, c10, 5 (data memory barrier)\n");
   13946       goto decode_success;
   13947    }
   13948    if (0xEE070F95 == (insn & 0xFFFF0FFF)) { /* v6 */
   13949       /* mcr 15, 0, r0, c7, c5, 4 (v6) equiv to ISB (v7).
   13950          Instruction Synchronisation Barrier (or Flush Prefetch
   13951          Buffer) -- a pipe flush, I think.  I suspect we could
   13952          ignore those, but to be on the safe side emit a fence
   13953          anyway. */
   13954       stmt( IRStmt_MBE(Imbe_Fence) );
   13955       DIP("mcr 15, 0, rX, c7, c5, 4 (insn synch barrier)\n");
   13956       goto decode_success;
   13957    }
   13958 
   13959    // LDREXD
   13960    if (0x01B00F9F == (insn & 0x0FF00FFF)) {
   13961       UInt rT = INSN(15,12);
   13962       UInt rN = INSN(19,16);
   13963       if ((rT & 1) == 1 || rT == BITS4(1,1,1,0) || rN == 15) {
   13964          /* undecodable; fall through */
   13965       } else {
   13966          IRTemp res;
   13967          /* make unconditional */
   13968          if (condT != IRTemp_INVALID) {
   13969             mk_skip_over_A32_if_cond_is_false( condT );
   13970             condT = IRTemp_INVALID;
   13971          }
   13972          /* Ok, now we're unconditional.  Do the load. */
   13973          res = newTemp(Ity_I64);
   13974          stmt( IRStmt_LLSC(Iend_LE, res, getIRegA(rN),
   13975                            NULL/*this is a load*/) );
   13976          putIRegA(rT+0, unop(Iop_64HIto32, mkexpr(res)), IRTemp_INVALID, Ijk_Boring);
   13977          putIRegA(rT+1, unop(Iop_64to32, mkexpr(res)), IRTemp_INVALID, Ijk_Boring);
   13978 
   13979          DIP("ldrexd%s r%u, r%u, [r%u]\n", nCC(INSN_COND), rT+0, rT+1, rN);
   13980          goto decode_success;
   13981       }
   13982       /* fall through */
   13983    }
   13984 
   13985    // STREXD
   13986    if (0x01A00F90 == (insn & 0xFF00FF0)) {
   13987       UInt rT = INSN(3,0);
   13988       UInt rD = INSN(15,12);
   13989       UInt rN = INSN(19,16);
   13990       if (rD == 15 || (rT & 1) == 1 || rT == BITS4(1,1,1,0) || rN == 15
   13991           || rD == rN || rD == rT || rD == rT+1) {
   13992          /* undecodable; fall through */
   13993       } else {
   13994          IRTemp data;
   13995          IRTemp resSC1, resSC32;
   13996 
   13997          if (condT != IRTemp_INVALID) {
   13998             mk_skip_over_A32_if_cond_is_false( condT );
   13999             condT = IRTemp_INVALID;
   14000          }
   14001 
   14002          /* Ok, now we're unconditional. Do the store. */
   14003          data = newTemp(Ity_I64);
   14004          assign( data, binop(Iop_32HLto64, getIRegA(rT+0), getIRegA(rT+1)) );
   14005          resSC1 = newTemp(Ity_I1);
   14006          stmt( IRStmt_LLSC(Iend_LE, resSC1, getIRegA(rN), mkexpr(data)) );
   14007 
   14008          /* Set rD to 1 on failure, 0 on success.  Currently we have
   14009             resSC1 == 0 on failure, 1 on success. */
   14010          resSC32 = newTemp(Ity_I32);
   14011          assign(resSC32,
   14012                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   14013 
   14014          putIRegA(rD, mkexpr(resSC32),
   14015                       IRTemp_INVALID, Ijk_Boring);
   14016          DIP("strexd%s r%u, r%u, r%u, [r%u]\n", nCC(INSN_COND), rD, rT+0, rT+1, rN);
   14017          goto decode_success;
   14018       }
   14019       /* fall through */
   14020    }
   14021 
   14022    /* ----------------------------------------------------------- */
   14023    /* -- VFP (CP 10, CP 11) instructions (in ARM mode)         -- */
   14024    /* ----------------------------------------------------------- */
   14025 
   14026    if (INSN_COND != ARMCondNV) {
   14027       Bool ok_vfp = decode_CP10_CP11_instruction (
   14028                        &dres, INSN(27,0), condT, INSN_COND,
   14029                        False/*!isT*/
   14030                     );
   14031       if (ok_vfp)
   14032          goto decode_success;
   14033    }
   14034 
   14035    /* ----------------------------------------------------------- */
   14036    /* -- NEON instructions (in ARM mode)                       -- */
   14037    /* ----------------------------------------------------------- */
   14038 
   14039    /* These are all in NV space, and so are taken care of (far) above,
   14040       by a call from this function to decode_NV_instruction(). */
   14041 
   14042    /* ----------------------------------------------------------- */
   14043    /* -- v6 media instructions (in ARM mode)                   -- */
   14044    /* ----------------------------------------------------------- */
   14045 
   14046    { Bool ok_v6m = decode_V6MEDIA_instruction(
   14047                        &dres, INSN(27,0), condT, INSN_COND,
   14048                        False/*!isT*/
   14049                    );
   14050      if (ok_v6m)
   14051         goto decode_success;
   14052    }
   14053 
   14054    /* ----------------------------------------------------------- */
   14055    /* -- Undecodable                                           -- */
   14056    /* ----------------------------------------------------------- */
   14057 
   14058    goto decode_failure;
   14059    /*NOTREACHED*/
   14060 
   14061   decode_failure:
   14062    /* All decode failures end up here. */
   14063    vex_printf("disInstr(arm): unhandled instruction: "
   14064               "0x%x\n", insn);
   14065    vex_printf("                 cond=%d(0x%x) 27:20=%u(0x%02x) "
   14066                                 "4:4=%d "
   14067                                 "3:0=%u(0x%x)\n",
   14068               (Int)INSN_COND, (UInt)INSN_COND,
   14069               (Int)INSN(27,20), (UInt)INSN(27,20),
   14070               (Int)INSN(4,4),
   14071               (Int)INSN(3,0), (UInt)INSN(3,0) );
   14072 
   14073    /* Tell the dispatcher that this insn cannot be decoded, and so has
   14074       not been executed, and (is currently) the next to be executed.
   14075       R15 should be up-to-date since it made so at the start of each
   14076       insn, but nevertheless be paranoid and update it again right
   14077       now. */
   14078    vassert(0 == (guest_R15_curr_instr_notENC & 3));
   14079    llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC) );
   14080    irsb->next     = mkU32(guest_R15_curr_instr_notENC);
   14081    irsb->jumpkind = Ijk_NoDecode;
   14082    dres.whatNext  = Dis_StopHere;
   14083    dres.len       = 0;
   14084    return dres;
   14085 
   14086   decode_success:
   14087    /* All decode successes end up here. */
   14088    DIP("\n");
   14089 
   14090    vassert(dres.len == 4 || dres.len == 20);
   14091 
   14092    /* Now then.  Do we have an implicit jump to r15 to deal with? */
   14093    if (r15written) {
   14094       /* If we get jump to deal with, we assume that there's been no
   14095          other competing branch stuff previously generated for this
   14096          insn.  That's reasonable, in the sense that the ARM insn set
   14097          appears to declare as "Unpredictable" any instruction which
   14098          generates more than one possible new value for r15.  Hence
   14099          just assert.  The decoders themselves should check against
   14100          all such instructions which are thusly Unpredictable, and
   14101          decline to decode them.  Hence we should never get here if we
   14102          have competing new values for r15, and hence it is safe to
   14103          assert here. */
   14104       vassert(dres.whatNext == Dis_Continue);
   14105       vassert(irsb->next == NULL);
   14106       vassert(irsb->jumpkind = Ijk_Boring);
   14107       /* If r15 is unconditionally written, terminate the block by
   14108          jumping to it.  If it's conditionally written, still
   14109          terminate the block (a shame, but we can't do side exits to
   14110          arbitrary destinations), but first jump to the next
   14111          instruction if the condition doesn't hold. */
   14112       /* We can't use getIReg(15) to get the destination, since that
   14113          will produce r15+8, which isn't what we want.  Must use
   14114          llGetIReg(15) instead. */
   14115       if (r15guard == IRTemp_INVALID) {
   14116          /* unconditional */
   14117       } else {
   14118          /* conditional */
   14119          stmt( IRStmt_Exit(
   14120                   unop(Iop_32to1,
   14121                        binop(Iop_Xor32,
   14122                              mkexpr(r15guard), mkU32(1))),
   14123                   r15kind,
   14124                   IRConst_U32(guest_R15_curr_instr_notENC + 4)
   14125          ));
   14126       }
   14127       irsb->next     = llGetIReg(15);
   14128       irsb->jumpkind = r15kind;
   14129       dres.whatNext  = Dis_StopHere;
   14130    }
   14131 
   14132    return dres;
   14133 
   14134 #  undef INSN_COND
   14135 #  undef INSN
   14136 }
   14137 
   14138 
   14139 /*------------------------------------------------------------*/
   14140 /*--- Disassemble a single Thumb2 instruction              ---*/
   14141 /*------------------------------------------------------------*/
   14142 
   14143 /* NB: in Thumb mode we do fetches of regs with getIRegT, which
   14144    automagically adds 4 to fetches of r15.  However, writes to regs
   14145    are done with putIRegT, which disallows writes to r15.  Hence any
   14146    r15 writes and associated jumps have to be done "by hand". */
   14147 
   14148 /* Disassemble a single Thumb instruction into IR.  The instruction is
   14149    located in host memory at guest_instr, and has (decoded) guest IP
   14150    of guest_R15_curr_instr_notENC, which will have been set before the
   14151    call here. */
   14152 
   14153 static
   14154 DisResult disInstr_THUMB_WRK (
   14155              Bool         put_IP,
   14156              Bool         (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
   14157              Bool         resteerCisOk,
   14158              void*        callback_opaque,
   14159              UChar*       guest_instr,
   14160              VexArchInfo* archinfo,
   14161              VexAbiInfo*  abiinfo
   14162           )
   14163 {
   14164    /* A macro to fish bits out of insn0.  There's also INSN1, to fish
   14165       bits out of insn1, but that's defined only after the end of the
   14166       16-bit insn decoder, so as to stop it mistakenly being used
   14167       therein. */
   14168 #  define INSN0(_bMax,_bMin)  SLICE_UInt(((UInt)insn0), (_bMax), (_bMin))
   14169 
   14170    DisResult dres;
   14171    UShort    insn0; /* first 16 bits of the insn */
   14172    //Bool      allow_VFP = False;
   14173    //UInt      hwcaps = archinfo->hwcaps;
   14174    HChar     dis_buf[128];  // big enough to hold LDMIA etc text
   14175 
   14176    /* Summary result of the ITxxx backwards analysis: False == safe
   14177       but suboptimal. */
   14178    Bool guaranteedUnconditional = False;
   14179 
   14180    /* What insn variants are we supporting today? */
   14181    //allow_VFP  = (0 != (hwcaps & VEX_HWCAPS_ARM_VFP));
   14182    // etc etc
   14183 
   14184    /* Set result defaults. */
   14185    dres.whatNext   = Dis_Continue;
   14186    dres.len        = 2;
   14187    dres.continueAt = 0;
   14188 
   14189    /* Set default actions for post-insn handling of writes to r15, if
   14190       required. */
   14191    r15written = False;
   14192    r15guard   = IRTemp_INVALID; /* unconditional */
   14193    r15kind    = Ijk_Boring;
   14194 
   14195    /* Insns could be 2 or 4 bytes long.  Just get the first 16 bits at
   14196       this point.  If we need the second 16, get them later.  We can't
   14197       get them both out immediately because it risks a fault (very
   14198       unlikely, but ..) if the second 16 bits aren't actually
   14199       necessary. */
   14200    insn0 = getUShortLittleEndianly( guest_instr );
   14201 
   14202    if (0) vex_printf("insn: 0x%x\n", insn0);
   14203 
   14204    DIP("\t(thumb) 0x%x:  ", (UInt)guest_R15_curr_instr_notENC);
   14205 
   14206    /* We may be asked to update the guest R15 before going further. */
   14207    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   14208    if (put_IP) {
   14209       llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
   14210    }
   14211 
   14212    /* ----------------------------------------------------------- */
   14213    /* Spot "Special" instructions (see comment at top of file). */
   14214    {
   14215       UChar* code = (UChar*)guest_instr;
   14216       /* Spot the 16-byte preamble:
   14217 
   14218          ea4f 0cfc  mov.w   ip, ip, ror #3
   14219          ea4f 3c7c  mov.w   ip, ip, ror #13
   14220          ea4f 7c7c  mov.w   ip, ip, ror #29
   14221          ea4f 4cfc  mov.w   ip, ip, ror #19
   14222       */
   14223       UInt word1 = 0x0CFCEA4F;
   14224       UInt word2 = 0x3C7CEA4F;
   14225       UInt word3 = 0x7C7CEA4F;
   14226       UInt word4 = 0x4CFCEA4F;
   14227       if (getUIntLittleEndianly(code+ 0) == word1 &&
   14228           getUIntLittleEndianly(code+ 4) == word2 &&
   14229           getUIntLittleEndianly(code+ 8) == word3 &&
   14230           getUIntLittleEndianly(code+12) == word4) {
   14231          /* Got a "Special" instruction preamble.  Which one is it? */
   14232          // 0x 0A 0A EA 4A
   14233          if (getUIntLittleEndianly(code+16) == 0x0A0AEA4A
   14234                                                /* orr.w r10,r10,r10 */) {
   14235             /* R3 = client_request ( R4 ) */
   14236             DIP("r3 = client_request ( %%r4 )\n");
   14237             irsb->next     = mkU32( (guest_R15_curr_instr_notENC + 20) | 1 );
   14238             irsb->jumpkind = Ijk_ClientReq;
   14239             dres.whatNext  = Dis_StopHere;
   14240             goto decode_success;
   14241          }
   14242          else
   14243          // 0x 0B 0B EA 4B
   14244          if (getUIntLittleEndianly(code+16) == 0x0B0BEA4B
   14245                                                /* orr r11,r11,r11 */) {
   14246             /* R3 = guest_NRADDR */
   14247             DIP("r3 = guest_NRADDR\n");
   14248             dres.len = 20;
   14249             llPutIReg(3, IRExpr_Get( OFFB_NRADDR, Ity_I32 ));
   14250             goto decode_success;
   14251          }
   14252          else
   14253          // 0x 0C 0C EA 4C
   14254          if (getUIntLittleEndianly(code+16) == 0x0C0CEA4C
   14255                                                /* orr r12,r12,r12 */) {
   14256             /*  branch-and-link-to-noredir R4 */
   14257             DIP("branch-and-link-to-noredir r4\n");
   14258             llPutIReg(14, mkU32( (guest_R15_curr_instr_notENC + 20) | 1 ));
   14259             irsb->next     = getIRegT(4);
   14260             irsb->jumpkind = Ijk_NoRedir;
   14261             dres.whatNext  = Dis_StopHere;
   14262             goto decode_success;
   14263          }
   14264          /* We don't know what it is.  Set insn0 so decode_failure
   14265             can print the insn following the Special-insn preamble. */
   14266          insn0 = getUShortLittleEndianly(code+16);
   14267          goto decode_failure;
   14268          /*NOTREACHED*/
   14269       }
   14270 
   14271    }
   14272 
   14273    /* ----------------------------------------------------------- */
   14274 
   14275    /* Main Thumb instruction decoder starts here.  It's a series of
   14276       switches which examine ever longer bit sequences at the MSB of
   14277       the instruction word, first for 16-bit insns, then for 32-bit
   14278       insns. */
   14279 
   14280    /* --- BEGIN ITxxx optimisation analysis --- */
   14281    /* This is a crucial optimisation for the ITState boilerplate that
   14282       follows.  Examine the 9 halfwords preceding this instruction,
   14283       and if we are absolutely sure that none of them constitute an
   14284       'it' instruction, then we can be sure that this instruction is
   14285       not under the control of any 'it' instruction, and so
   14286       guest_ITSTATE must be zero.  So write zero into ITSTATE right
   14287       now, so that iropt can fold out almost all of the resulting
   14288       junk.
   14289 
   14290       If we aren't sure, we can always safely skip this step.  So be a
   14291       bit conservative about it: only poke around in the same page as
   14292       this instruction, lest we get a fault from the previous page
   14293       that would not otherwise have happened.  The saving grace is
   14294       that such skipping is pretty rare -- it only happens,
   14295       statistically, 18/4096ths of the time, so is judged unlikely to
   14296       be a performance problems.
   14297 
   14298       FIXME: do better.  Take into account the number of insns covered
   14299       by any IT insns we find, to rule out cases where an IT clearly
   14300       cannot cover this instruction.  This would improve behaviour for
   14301       branch targets immediately following an IT-guarded group that is
   14302       not of full length.  Eg, (and completely ignoring issues of 16-
   14303       vs 32-bit insn length):
   14304 
   14305              ite cond
   14306              insn1
   14307              insn2
   14308       label: insn3
   14309              insn4
   14310 
   14311       The 'it' only conditionalises insn1 and insn2.  However, the
   14312       current analysis is conservative and considers insn3 and insn4
   14313       also possibly guarded.  Hence if 'label:' is the start of a hot
   14314       loop we will get a big performance hit.
   14315    */
   14316    {
   14317       /* Summary result of this analysis: False == safe but
   14318          suboptimal. */
   14319       vassert(guaranteedUnconditional == False);
   14320 
   14321       UInt pc = guest_R15_curr_instr_notENC;
   14322       vassert(0 == (pc & 1));
   14323 
   14324       UInt pageoff = pc & 0xFFF;
   14325       if (pageoff >= 18) {
   14326          /* It's safe to poke about in the 9 halfwords preceding this
   14327             insn.  So, have a look at them. */
   14328          guaranteedUnconditional = True; /* assume no 'it' insn found, till we do */
   14329 
   14330          UShort* hwp = (UShort*)(HWord)pc;
   14331          Int i;
   14332          for (i = -1; i >= -9; i--) {
   14333             /* We're in the same page.  (True, but commented out due
   14334                to expense.) */
   14335             /*
   14336             vassert( ( ((UInt)(&hwp[i])) & 0xFFFFF000 )
   14337                       == ( pc & 0xFFFFF000 ) );
   14338             */
   14339             /* All valid IT instructions must have the form 0xBFxy,
   14340                where x can be anything, but y must be nonzero. */
   14341             if ((hwp[i] & 0xFF00) == 0xBF00 && (hwp[i] & 0xF) != 0) {
   14342                /* might be an 'it' insn.  Play safe. */
   14343                guaranteedUnconditional = False;
   14344                break;
   14345             }
   14346          }
   14347       }
   14348    }
   14349    /* --- END ITxxx optimisation analysis --- */
   14350 
   14351    /* Generate the guarding condition for this insn, by examining
   14352       ITSTATE.  Assign it to condT.  Also, generate new
   14353       values for ITSTATE ready for stuffing back into the
   14354       guest state, but don't actually do the Put yet, since it will
   14355       need to stuffed back in only after the instruction gets to a
   14356       point where it is sure to complete.  Mostly we let the code at
   14357       decode_success handle this, but in cases where the insn contains
   14358       a side exit, we have to update them before the exit. */
   14359 
   14360    /* If the ITxxx optimisation analysis above could not prove that
   14361       this instruction is guaranteed unconditional, we insert a
   14362       lengthy IR preamble to compute the guarding condition at
   14363       runtime.  If it can prove it (which obviously we hope is the
   14364       normal case) then we insert a minimal preamble, which is
   14365       equivalent to setting guest_ITSTATE to zero and then folding
   14366       that through the full preamble (which completely disappears). */
   14367 
   14368    IRTemp condT              = IRTemp_INVALID;
   14369    IRTemp old_itstate        = IRTemp_INVALID;
   14370    IRTemp new_itstate        = IRTemp_INVALID;
   14371    IRTemp cond_AND_notInIT_T = IRTemp_INVALID;
   14372 
   14373    if (guaranteedUnconditional) {
   14374       /* BEGIN "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
   14375 
   14376       // ITSTATE = 0 :: I32
   14377       IRTemp z32 = newTemp(Ity_I32);
   14378       assign(z32, mkU32(0));
   14379       put_ITSTATE(z32);
   14380 
   14381       // old_itstate = 0 :: I32
   14382       //
   14383       // old_itstate = get_ITSTATE();
   14384       old_itstate = z32; /* 0 :: I32 */
   14385 
   14386       // new_itstate = old_itstate >> 8
   14387       //             = 0 >> 8
   14388       //             = 0 :: I32
   14389       //
   14390       // new_itstate = newTemp(Ity_I32);
   14391       // assign(new_itstate,
   14392       //        binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
   14393       new_itstate = z32;
   14394 
   14395       // ITSTATE = 0 :: I32(again)
   14396       //
   14397       // put_ITSTATE(new_itstate);
   14398 
   14399       // condT1 = calc_cond_dyn( xor(and(old_istate,0xF0), 0xE0) )
   14400       //        = calc_cond_dyn( xor(0,0xE0) )
   14401       //        = calc_cond_dyn ( 0xE0 )
   14402       //        = 1 :: I32
   14403       // Not that this matters, since the computed value is not used:
   14404       // see condT folding below
   14405       //
   14406       // IRTemp condT1 = newTemp(Ity_I32);
   14407       // assign(condT1,
   14408       //        mk_armg_calculate_condition_dyn(
   14409       //           binop(Iop_Xor32,
   14410       //                 binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
   14411       //                 mkU32(0xE0))
   14412       //       )
   14413       // );
   14414 
   14415       // condT = 32to8(and32(old_itstate,0xF0)) == 0  ? 1  : condT1
   14416       //       = 32to8(and32(0,0xF0)) == 0  ? 1  : condT1
   14417       //       = 32to8(0) == 0  ? 1  : condT1
   14418       //       = 0 == 0  ? 1  : condT1
   14419       //       = 1
   14420       //
   14421       // condT = newTemp(Ity_I32);
   14422       // assign(condT, IRExpr_Mux0X(
   14423       //                  unop(Iop_32to8, binop(Iop_And32,
   14424       //                                        mkexpr(old_itstate),
   14425       //                                        mkU32(0xF0))),
   14426       //                  mkU32(1),
   14427       //                  mkexpr(condT1)
   14428       //       ));
   14429       condT = newTemp(Ity_I32);
   14430       assign(condT, mkU32(1));
   14431 
   14432       // notInITt = xor32(and32(old_itstate, 1), 1)
   14433       //          = xor32(and32(0, 1), 1)
   14434       //          = xor32(0, 1)
   14435       //          = 1 :: I32
   14436       //
   14437       // IRTemp notInITt = newTemp(Ity_I32);
   14438       // assign(notInITt,
   14439       //        binop(Iop_Xor32,
   14440       //              binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
   14441       //              mkU32(1)));
   14442 
   14443       // cond_AND_notInIT_T = and32(notInITt, condT)
   14444       //                    = and32(1, 1)
   14445       //                    = 1
   14446       //
   14447       // cond_AND_notInIT_T = newTemp(Ity_I32);
   14448       // assign(cond_AND_notInIT_T,
   14449       //        binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
   14450       cond_AND_notInIT_T = condT; /* 1 :: I32 */
   14451 
   14452       /* END "partial eval { ITSTATE = 0; STANDARD_PREAMBLE; }" */
   14453    } else {
   14454       /* BEGIN { STANDARD PREAMBLE; } */
   14455 
   14456       old_itstate = get_ITSTATE();
   14457 
   14458       new_itstate = newTemp(Ity_I32);
   14459       assign(new_itstate,
   14460              binop(Iop_Shr32, mkexpr(old_itstate), mkU8(8)));
   14461 
   14462       put_ITSTATE(new_itstate);
   14463 
   14464       /* Same strategy as for ARM insns: generate a condition
   14465          temporary at this point (or IRTemp_INVALID, meaning
   14466          unconditional).  We leave it to lower-level instruction
   14467          decoders to decide whether they can generate straight-line
   14468          code, or whether they must generate a side exit before the
   14469          instruction.  condT :: Ity_I32 and is always either zero or
   14470          one. */
   14471       IRTemp condT1 = newTemp(Ity_I32);
   14472       assign(condT1,
   14473              mk_armg_calculate_condition_dyn(
   14474                 binop(Iop_Xor32,
   14475                       binop(Iop_And32, mkexpr(old_itstate), mkU32(0xF0)),
   14476                       mkU32(0xE0))
   14477             )
   14478       );
   14479 
   14480       /* This is a bit complex, but needed to make Memcheck understand
   14481          that, if the condition in old_itstate[7:4] denotes AL (that
   14482          is, if this instruction is to be executed unconditionally),
   14483          then condT does not depend on the results of calling the
   14484          helper.
   14485 
   14486          We test explicitly for old_itstate[7:4] == AL ^ 0xE, and in
   14487          that case set condT directly to 1.  Else we use the results
   14488          of the helper.  Since old_itstate is always defined and
   14489          because Memcheck does lazy V-bit propagation through Mux0X,
   14490          this will cause condT to always be a defined 1 if the
   14491          condition is 'AL'.  From an execution semantics point of view
   14492          this is irrelevant since we're merely duplicating part of the
   14493          behaviour of the helper.  But it makes it clear to Memcheck,
   14494          in this case, that condT does not in fact depend on the
   14495          contents of the condition code thunk.  Without it, we get
   14496          quite a lot of false errors.
   14497 
   14498          So, just to clarify: from a straight semantics point of view,
   14499          we can simply do "assign(condT, mkexpr(condT1))", and the
   14500          simulator still runs fine.  It's just that we get loads of
   14501          false errors from Memcheck. */
   14502       condT = newTemp(Ity_I32);
   14503       assign(condT, IRExpr_Mux0X(
   14504                        unop(Iop_32to8, binop(Iop_And32,
   14505                                              mkexpr(old_itstate),
   14506                                              mkU32(0xF0))),
   14507                        mkU32(1),
   14508                        mkexpr(condT1)
   14509             ));
   14510 
   14511       /* Something we don't have in ARM: generate a 0 or 1 value
   14512          indicating whether or not we are in an IT block (NB: 0 = in
   14513          IT block, 1 = not in IT block).  This is used to gate
   14514          condition code updates in 16-bit Thumb instructions. */
   14515       IRTemp notInITt = newTemp(Ity_I32);
   14516       assign(notInITt,
   14517              binop(Iop_Xor32,
   14518                    binop(Iop_And32, mkexpr(old_itstate), mkU32(1)),
   14519                    mkU32(1)));
   14520 
   14521       /* Compute 'condT && notInITt' -- that is, the instruction is
   14522          going to execute, and we're not in an IT block.  This is the
   14523          gating condition for updating condition codes in 16-bit Thumb
   14524          instructions, except for CMP, CMN and TST. */
   14525       cond_AND_notInIT_T = newTemp(Ity_I32);
   14526       assign(cond_AND_notInIT_T,
   14527              binop(Iop_And32, mkexpr(notInITt), mkexpr(condT)));
   14528       /* END { STANDARD PREAMBLE; } */
   14529    }
   14530 
   14531 
   14532    /* At this point:
   14533       * ITSTATE has been updated
   14534       * condT holds the guarding condition for this instruction (0 or 1),
   14535       * notInITt is 1 if we're in "normal" code, 0 if in an IT block
   14536       * cond_AND_notInIT_T is the AND of the above two.
   14537 
   14538       If the instruction proper can't trap, then there's nothing else
   14539       to do w.r.t. ITSTATE -- just go and and generate IR for the
   14540       insn, taking into account the guarding condition.
   14541 
   14542       If, however, the instruction might trap, then we must back up
   14543       ITSTATE to the old value, and re-update it after the potentially
   14544       trapping IR section.  A trap can happen either via a memory
   14545       reference or because we need to throw SIGILL.
   14546 
   14547       If an instruction has a side exit, we need to be sure that any
   14548       ITSTATE backup is re-updated before the side exit.
   14549    */
   14550 
   14551    /* ----------------------------------------------------------- */
   14552    /* --                                                       -- */
   14553    /* -- Thumb 16-bit integer instructions                     -- */
   14554    /* --                                                       -- */
   14555    /* -- IMPORTANT: references to insn1 or INSN1 are           -- */
   14556    /* --            not allowed in this section                -- */
   14557    /* --                                                       -- */
   14558    /* ----------------------------------------------------------- */
   14559 
   14560    /* 16-bit instructions inside an IT block, apart from CMP, CMN and
   14561       TST, do not set the condition codes.  Hence we must dynamically
   14562       test for this case for every condition code update. */
   14563 
   14564    IROp   anOp   = Iop_INVALID;
   14565    HChar* anOpNm = NULL;
   14566 
   14567    /* ================ 16-bit 15:6 cases ================ */
   14568 
   14569    switch (INSN0(15,6)) {
   14570 
   14571    case 0x10a:   // CMP
   14572    case 0x10b: { // CMN
   14573       /* ---------------- CMP Rn, Rm ---------------- */
   14574       Bool   isCMN = INSN0(15,6) == 0x10b;
   14575       UInt   rN    = INSN0(2,0);
   14576       UInt   rM    = INSN0(5,3);
   14577       IRTemp argL  = newTemp(Ity_I32);
   14578       IRTemp argR  = newTemp(Ity_I32);
   14579       assign( argL, getIRegT(rN) );
   14580       assign( argR, getIRegT(rM) );
   14581       /* Update flags regardless of whether in an IT block or not. */
   14582       setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   14583                       argL, argR, condT );
   14584       DIP("%s r%u, r%u\n", isCMN ? "cmn" : "cmp", rN, rM);
   14585       goto decode_success;
   14586    }
   14587 
   14588    case 0x108: {
   14589       /* ---------------- TST Rn, Rm ---------------- */
   14590       UInt   rN   = INSN0(2,0);
   14591       UInt   rM   = INSN0(5,3);
   14592       IRTemp oldC = newTemp(Ity_I32);
   14593       IRTemp oldV = newTemp(Ity_I32);
   14594       IRTemp res  = newTemp(Ity_I32);
   14595       assign( oldC, mk_armg_calculate_flag_c() );
   14596       assign( oldV, mk_armg_calculate_flag_v() );
   14597       assign( res,  binop(Iop_And32, getIRegT(rN), getIRegT(rM)) );
   14598       /* Update flags regardless of whether in an IT block or not. */
   14599       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
   14600       DIP("tst r%u, r%u\n", rN, rM);
   14601       goto decode_success;
   14602    }
   14603 
   14604    case 0x109: {
   14605       /* ---------------- NEGS Rd, Rm ---------------- */
   14606       /* Rd = -Rm */
   14607       UInt   rM   = INSN0(5,3);
   14608       UInt   rD   = INSN0(2,0);
   14609       IRTemp arg  = newTemp(Ity_I32);
   14610       IRTemp zero = newTemp(Ity_I32);
   14611       assign(arg, getIRegT(rM));
   14612       assign(zero, mkU32(0));
   14613       // rD can never be r15
   14614       putIRegT(rD, binop(Iop_Sub32, mkexpr(zero), mkexpr(arg)), condT);
   14615       setFlags_D1_D2( ARMG_CC_OP_SUB, zero, arg, cond_AND_notInIT_T);
   14616       DIP("negs r%u, r%u\n", rD, rM);
   14617       goto decode_success;
   14618    }
   14619 
   14620    case 0x10F: {
   14621       /* ---------------- MVNS Rd, Rm ---------------- */
   14622       /* Rd = ~Rm */
   14623       UInt   rM   = INSN0(5,3);
   14624       UInt   rD   = INSN0(2,0);
   14625       IRTemp oldV = newTemp(Ity_I32);
   14626       IRTemp oldC = newTemp(Ity_I32);
   14627       IRTemp res  = newTemp(Ity_I32);
   14628       assign( oldV, mk_armg_calculate_flag_v() );
   14629       assign( oldC, mk_armg_calculate_flag_c() );
   14630       assign(res, unop(Iop_Not32, getIRegT(rM)));
   14631       // rD can never be r15
   14632       putIRegT(rD, mkexpr(res), condT);
   14633       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   14634                          cond_AND_notInIT_T );
   14635       DIP("mvns r%u, r%u\n", rD, rM);
   14636       goto decode_success;
   14637    }
   14638 
   14639    case 0x10C:
   14640       /* ---------------- ORRS Rd, Rm ---------------- */
   14641       anOp = Iop_Or32; anOpNm = "orr"; goto and_orr_eor_mul;
   14642    case 0x100:
   14643       /* ---------------- ANDS Rd, Rm ---------------- */
   14644       anOp = Iop_And32; anOpNm = "and"; goto and_orr_eor_mul;
   14645    case 0x101:
   14646       /* ---------------- EORS Rd, Rm ---------------- */
   14647       anOp = Iop_Xor32; anOpNm = "eor"; goto and_orr_eor_mul;
   14648    case 0x10d:
   14649       /* ---------------- MULS Rd, Rm ---------------- */
   14650       anOp = Iop_Mul32; anOpNm = "mul"; goto and_orr_eor_mul;
   14651    and_orr_eor_mul: {
   14652       /* Rd = Rd `op` Rm */
   14653       UInt   rM   = INSN0(5,3);
   14654       UInt   rD   = INSN0(2,0);
   14655       IRTemp res  = newTemp(Ity_I32);
   14656       IRTemp oldV = newTemp(Ity_I32);
   14657       IRTemp oldC = newTemp(Ity_I32);
   14658       assign( oldV, mk_armg_calculate_flag_v() );
   14659       assign( oldC, mk_armg_calculate_flag_c() );
   14660       assign( res, binop(anOp, getIRegT(rD), getIRegT(rM) ));
   14661       // not safe to read guest state after here
   14662       // rD can never be r15
   14663       putIRegT(rD, mkexpr(res), condT);
   14664       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   14665                          cond_AND_notInIT_T );
   14666       DIP("%s r%u, r%u\n", anOpNm, rD, rM);
   14667       goto decode_success;
   14668    }
   14669 
   14670    case 0x10E: {
   14671       /* ---------------- BICS Rd, Rm ---------------- */
   14672       /* Rd = Rd & ~Rm */
   14673       UInt   rM   = INSN0(5,3);
   14674       UInt   rD   = INSN0(2,0);
   14675       IRTemp res  = newTemp(Ity_I32);
   14676       IRTemp oldV = newTemp(Ity_I32);
   14677       IRTemp oldC = newTemp(Ity_I32);
   14678       assign( oldV, mk_armg_calculate_flag_v() );
   14679       assign( oldC, mk_armg_calculate_flag_c() );
   14680       assign( res, binop(Iop_And32, getIRegT(rD),
   14681                                     unop(Iop_Not32, getIRegT(rM) )));
   14682       // not safe to read guest state after here
   14683       // rD can never be r15
   14684       putIRegT(rD, mkexpr(res), condT);
   14685       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   14686                          cond_AND_notInIT_T );
   14687       DIP("bics r%u, r%u\n", rD, rM);
   14688       goto decode_success;
   14689    }
   14690 
   14691    case 0x105: {
   14692       /* ---------------- ADCS Rd, Rm ---------------- */
   14693       /* Rd = Rd + Rm + oldC */
   14694       UInt   rM   = INSN0(5,3);
   14695       UInt   rD   = INSN0(2,0);
   14696       IRTemp argL = newTemp(Ity_I32);
   14697       IRTemp argR = newTemp(Ity_I32);
   14698       IRTemp oldC = newTemp(Ity_I32);
   14699       IRTemp res  = newTemp(Ity_I32);
   14700       assign(argL, getIRegT(rD));
   14701       assign(argR, getIRegT(rM));
   14702       assign(oldC, mk_armg_calculate_flag_c());
   14703       assign(res, binop(Iop_Add32,
   14704                         binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
   14705                         mkexpr(oldC)));
   14706       // rD can never be r15
   14707       putIRegT(rD, mkexpr(res), condT);
   14708       setFlags_D1_D2_ND( ARMG_CC_OP_ADC, argL, argR, oldC,
   14709                          cond_AND_notInIT_T );
   14710       DIP("adcs r%u, r%u\n", rD, rM);
   14711       goto decode_success;
   14712    }
   14713 
   14714    case 0x106: {
   14715       /* ---------------- SBCS Rd, Rm ---------------- */
   14716       /* Rd = Rd - Rm - (oldC ^ 1) */
   14717       UInt   rM   = INSN0(5,3);
   14718       UInt   rD   = INSN0(2,0);
   14719       IRTemp argL = newTemp(Ity_I32);
   14720       IRTemp argR = newTemp(Ity_I32);
   14721       IRTemp oldC = newTemp(Ity_I32);
   14722       IRTemp res  = newTemp(Ity_I32);
   14723       assign(argL, getIRegT(rD));
   14724       assign(argR, getIRegT(rM));
   14725       assign(oldC, mk_armg_calculate_flag_c());
   14726       assign(res, binop(Iop_Sub32,
   14727                         binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
   14728                         binop(Iop_Xor32, mkexpr(oldC), mkU32(1))));
   14729       // rD can never be r15
   14730       putIRegT(rD, mkexpr(res), condT);
   14731       setFlags_D1_D2_ND( ARMG_CC_OP_SBB, argL, argR, oldC,
   14732                          cond_AND_notInIT_T );
   14733       DIP("sbcs r%u, r%u\n", rD, rM);
   14734       goto decode_success;
   14735    }
   14736 
   14737    case 0x2CB: {
   14738       /* ---------------- UXTB Rd, Rm ---------------- */
   14739       /* Rd = 8Uto32(Rm) */
   14740       UInt rM = INSN0(5,3);
   14741       UInt rD = INSN0(2,0);
   14742       putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFF)),
   14743                    condT);
   14744       DIP("uxtb r%u, r%u\n", rD, rM);
   14745       goto decode_success;
   14746    }
   14747 
   14748    case 0x2C9: {
   14749       /* ---------------- SXTB Rd, Rm ---------------- */
   14750       /* Rd = 8Sto32(Rm) */
   14751       UInt rM = INSN0(5,3);
   14752       UInt rD = INSN0(2,0);
   14753       putIRegT(rD, binop(Iop_Sar32,
   14754                          binop(Iop_Shl32, getIRegT(rM), mkU8(24)),
   14755                          mkU8(24)),
   14756                    condT);
   14757       DIP("sxtb r%u, r%u\n", rD, rM);
   14758       goto decode_success;
   14759    }
   14760 
   14761    case 0x2CA: {
   14762       /* ---------------- UXTH Rd, Rm ---------------- */
   14763       /* Rd = 16Uto32(Rm) */
   14764       UInt rM = INSN0(5,3);
   14765       UInt rD = INSN0(2,0);
   14766       putIRegT(rD, binop(Iop_And32, getIRegT(rM), mkU32(0xFFFF)),
   14767                    condT);
   14768       DIP("uxth r%u, r%u\n", rD, rM);
   14769       goto decode_success;
   14770    }
   14771 
   14772    case 0x2C8: {
   14773       /* ---------------- SXTH Rd, Rm ---------------- */
   14774       /* Rd = 16Sto32(Rm) */
   14775       UInt rM = INSN0(5,3);
   14776       UInt rD = INSN0(2,0);
   14777       putIRegT(rD, binop(Iop_Sar32,
   14778                          binop(Iop_Shl32, getIRegT(rM), mkU8(16)),
   14779                          mkU8(16)),
   14780                    condT);
   14781       DIP("sxth r%u, r%u\n", rD, rM);
   14782       goto decode_success;
   14783    }
   14784 
   14785    case 0x102:   // LSLS
   14786    case 0x103:   // LSRS
   14787    case 0x104:   // ASRS
   14788    case 0x107: { // RORS
   14789       /* ---------------- LSLS Rs, Rd ---------------- */
   14790       /* ---------------- LSRS Rs, Rd ---------------- */
   14791       /* ---------------- ASRS Rs, Rd ---------------- */
   14792       /* ---------------- RORS Rs, Rd ---------------- */
   14793       /* Rd = Rd `op` Rs, and set flags */
   14794       UInt   rS   = INSN0(5,3);
   14795       UInt   rD   = INSN0(2,0);
   14796       IRTemp oldV = newTemp(Ity_I32);
   14797       IRTemp rDt  = newTemp(Ity_I32);
   14798       IRTemp rSt  = newTemp(Ity_I32);
   14799       IRTemp res  = newTemp(Ity_I32);
   14800       IRTemp resC = newTemp(Ity_I32);
   14801       HChar* wot  = "???";
   14802       assign(rSt, getIRegT(rS));
   14803       assign(rDt, getIRegT(rD));
   14804       assign(oldV, mk_armg_calculate_flag_v());
   14805       /* Does not appear to be the standard 'how' encoding. */
   14806       switch (INSN0(15,6)) {
   14807          case 0x102:
   14808             compute_result_and_C_after_LSL_by_reg(
   14809                dis_buf, &res, &resC, rDt, rSt, rD, rS
   14810             );
   14811             wot = "lsl";
   14812             break;
   14813          case 0x103:
   14814             compute_result_and_C_after_LSR_by_reg(
   14815                dis_buf, &res, &resC, rDt, rSt, rD, rS
   14816             );
   14817             wot = "lsr";
   14818             break;
   14819          case 0x104:
   14820             compute_result_and_C_after_ASR_by_reg(
   14821                dis_buf, &res, &resC, rDt, rSt, rD, rS
   14822             );
   14823             wot = "asr";
   14824             break;
   14825          case 0x107:
   14826             compute_result_and_C_after_ROR_by_reg(
   14827                dis_buf, &res, &resC, rDt, rSt, rD, rS
   14828             );
   14829             wot = "ror";
   14830             break;
   14831          default:
   14832             /*NOTREACHED*/vassert(0);
   14833       }
   14834       // not safe to read guest state after this point
   14835       putIRegT(rD, mkexpr(res), condT);
   14836       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
   14837                          cond_AND_notInIT_T );
   14838       DIP("%ss r%u, r%u\n", wot, rS, rD);
   14839       goto decode_success;
   14840    }
   14841 
   14842    case 0x2E8:   // REV
   14843    case 0x2E9: { // REV16
   14844       /* ---------------- REV   Rd, Rm ---------------- */
   14845       /* ---------------- REV16 Rd, Rm ---------------- */
   14846       UInt rM = INSN0(5,3);
   14847       UInt rD = INSN0(2,0);
   14848       Bool isREV = INSN0(15,6) == 0x2E8;
   14849       IRTemp arg = newTemp(Ity_I32);
   14850       assign(arg, getIRegT(rM));
   14851       IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
   14852       putIRegT(rD, mkexpr(res), condT);
   14853       DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM);
   14854       goto decode_success;
   14855    }
   14856 
   14857    default:
   14858       break; /* examine the next shortest prefix */
   14859 
   14860    }
   14861 
   14862 
   14863    /* ================ 16-bit 15:7 cases ================ */
   14864 
   14865    switch (INSN0(15,7)) {
   14866 
   14867    case BITS9(1,0,1,1,0,0,0,0,0): {
   14868       /* ------------ ADD SP, #imm7 * 4 ------------ */
   14869       UInt uimm7 = INSN0(6,0);
   14870       putIRegT(13, binop(Iop_Add32, getIRegT(13), mkU32(uimm7 * 4)),
   14871                    condT);
   14872       DIP("add sp, #%u\n", uimm7 * 4);
   14873       goto decode_success;
   14874    }
   14875 
   14876    case BITS9(1,0,1,1,0,0,0,0,1): {
   14877       /* ------------ SUB SP, #imm7 * 4 ------------ */
   14878       UInt uimm7 = INSN0(6,0);
   14879       putIRegT(13, binop(Iop_Sub32, getIRegT(13), mkU32(uimm7 * 4)),
   14880                    condT);
   14881       DIP("sub sp, #%u\n", uimm7 * 4);
   14882       goto decode_success;
   14883    }
   14884 
   14885    case BITS9(0,1,0,0,0,1,1,1,0): {
   14886       /* ---------------- BX rM ---------------- */
   14887       /* Branch to reg, and optionally switch modes.  Reg contains a
   14888          suitably encoded address therefore (w CPSR.T at the bottom).
   14889          Have to special-case r15, as usual. */
   14890       UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
   14891       if (BITS3(0,0,0) == INSN0(2,0)) {
   14892          IRTemp dst = newTemp(Ity_I32);
   14893          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   14894          mk_skip_over_T16_if_cond_is_false(condT);
   14895          condT = IRTemp_INVALID;
   14896          // now uncond
   14897          if (rM <= 14) {
   14898             assign( dst, getIRegT(rM) );
   14899          } else {
   14900             vassert(rM == 15);
   14901             assign( dst, mkU32(guest_R15_curr_instr_notENC + 4) );
   14902          }
   14903          irsb->next     = mkexpr(dst);
   14904          irsb->jumpkind = Ijk_Boring;
   14905          dres.whatNext  = Dis_StopHere;
   14906          DIP("bx r%u (possibly switch to ARM mode)\n", rM);
   14907          goto decode_success;
   14908       }
   14909       break;
   14910    }
   14911 
   14912    /* ---------------- BLX rM ---------------- */
   14913    /* Branch and link to interworking address in rM. */
   14914    case BITS9(0,1,0,0,0,1,1,1,1): {
   14915       if (BITS3(0,0,0) == INSN0(2,0)) {
   14916          UInt rM = (INSN0(6,6) << 3) | INSN0(5,3);
   14917          IRTemp dst = newTemp(Ity_I32);
   14918          if (rM <= 14) {
   14919             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   14920             mk_skip_over_T16_if_cond_is_false(condT);
   14921             condT = IRTemp_INVALID;
   14922             // now uncond
   14923             /* We're returning to Thumb code, hence "| 1" */
   14924             assign( dst, getIRegT(rM) );
   14925             putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 2) | 1 ),
   14926                           IRTemp_INVALID );
   14927             irsb->next     = mkexpr(dst);
   14928             irsb->jumpkind = Ijk_Call;
   14929             dres.whatNext  = Dis_StopHere;
   14930             DIP("blx r%u (possibly switch to ARM mode)\n", rM);
   14931             goto decode_success;
   14932          }
   14933          /* else unpredictable, fall through */
   14934       }
   14935       break;
   14936    }
   14937 
   14938    default:
   14939       break; /* examine the next shortest prefix */
   14940 
   14941    }
   14942 
   14943 
   14944    /* ================ 16-bit 15:8 cases ================ */
   14945 
   14946    switch (INSN0(15,8)) {
   14947 
   14948    case BITS8(1,1,0,1,1,1,1,1): {
   14949       /* ---------------- SVC ---------------- */
   14950       UInt imm8 = INSN0(7,0);
   14951       if (imm8 == 0) {
   14952          /* A syscall.  We can't do this conditionally, hence: */
   14953          mk_skip_over_T16_if_cond_is_false( condT );
   14954          // FIXME: what if we have to back up and restart this insn?
   14955          // then ITSTATE will be wrong (we'll have it as "used")
   14956          // when it isn't.  Correct is to save ITSTATE in a
   14957          // stash pseudo-reg, and back up from that if we have to
   14958          // restart.
   14959          // uncond after here
   14960          irsb->next     = mkU32( (guest_R15_curr_instr_notENC + 2) | 1 );
   14961          irsb->jumpkind = Ijk_Sys_syscall;
   14962          dres.whatNext  = Dis_StopHere;
   14963          DIP("svc #0x%08x\n", imm8);
   14964          goto decode_success;
   14965       }
   14966       /* else fall through */
   14967       break;
   14968    }
   14969 
   14970    case BITS8(0,1,0,0,0,1,0,0): {
   14971       /* ---------------- ADD(HI) Rd, Rm ---------------- */
   14972       UInt h1 = INSN0(7,7);
   14973       UInt h2 = INSN0(6,6);
   14974       UInt rM = (h2 << 3) | INSN0(5,3);
   14975       UInt rD = (h1 << 3) | INSN0(2,0);
   14976       //if (h1 == 0 && h2 == 0) { // Original T1 was more restrictive
   14977       if (rD == 15 && rM == 15) {
   14978          // then it's invalid
   14979       } else {
   14980          IRTemp res = newTemp(Ity_I32);
   14981          assign( res, binop(Iop_Add32, getIRegT(rD), getIRegT(rM) ));
   14982          if (rD != 15) {
   14983             putIRegT( rD, mkexpr(res), condT );
   14984          } else {
   14985             /* Only allowed outside or last-in IT block; SIGILL if not so. */
   14986             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   14987             /* jump over insn if not selected */
   14988             mk_skip_over_T16_if_cond_is_false(condT);
   14989             condT = IRTemp_INVALID;
   14990             // now uncond
   14991             /* non-interworking branch */
   14992             irsb->next = binop(Iop_Or32, mkexpr(res), mkU32(1));
   14993             irsb->jumpkind = Ijk_Boring;
   14994             dres.whatNext = Dis_StopHere;
   14995          }
   14996          DIP("add(hi) r%u, r%u\n", rD, rM);
   14997          goto decode_success;
   14998       }
   14999       break;
   15000    }
   15001 
   15002    case BITS8(0,1,0,0,0,1,0,1): {
   15003       /* ---------------- CMP(HI) Rd, Rm ---------------- */
   15004       UInt h1 = INSN0(7,7);
   15005       UInt h2 = INSN0(6,6);
   15006       UInt rM = (h2 << 3) | INSN0(5,3);
   15007       UInt rN = (h1 << 3) | INSN0(2,0);
   15008       if (h1 != 0 || h2 != 0) {
   15009          IRTemp argL  = newTemp(Ity_I32);
   15010          IRTemp argR  = newTemp(Ity_I32);
   15011          assign( argL, getIRegT(rN) );
   15012          assign( argR, getIRegT(rM) );
   15013          /* Update flags regardless of whether in an IT block or not. */
   15014          setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   15015          DIP("cmphi r%u, r%u\n", rN, rM);
   15016          goto decode_success;
   15017       }
   15018       break;
   15019    }
   15020 
   15021    case BITS8(0,1,0,0,0,1,1,0): {
   15022       /* ---------------- MOV(HI) Rd, Rm ---------------- */
   15023       UInt h1 = INSN0(7,7);
   15024       UInt h2 = INSN0(6,6);
   15025       UInt rM = (h2 << 3) | INSN0(5,3);
   15026       UInt rD = (h1 << 3) | INSN0(2,0);
   15027       /* The old ARM ARM seems to disallow the case where both Rd and
   15028          Rm are "low" registers, but newer versions allow it. */
   15029       if (1 /*h1 != 0 || h2 != 0*/) {
   15030          IRTemp val = newTemp(Ity_I32);
   15031          assign( val, getIRegT(rM) );
   15032          if (rD != 15) {
   15033             putIRegT( rD, mkexpr(val), condT );
   15034          } else {
   15035             /* Only allowed outside or last-in IT block; SIGILL if not so. */
   15036             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15037             /* jump over insn if not selected */
   15038             mk_skip_over_T16_if_cond_is_false(condT);
   15039             condT = IRTemp_INVALID;
   15040             // now uncond
   15041             /* non-interworking branch */
   15042             irsb->next = binop(Iop_Or32, mkexpr(val), mkU32(1));
   15043             irsb->jumpkind = Ijk_Boring;
   15044             dres.whatNext = Dis_StopHere;
   15045          }
   15046          DIP("mov r%u, r%u\n", rD, rM);
   15047          goto decode_success;
   15048       }
   15049       break;
   15050    }
   15051 
   15052    case BITS8(1,0,1,1,1,1,1,1): {
   15053       /* ---------------- IT (if-then) ---------------- */
   15054       UInt firstcond = INSN0(7,4);
   15055       UInt mask = INSN0(3,0);
   15056       UInt newITSTATE = 0;
   15057       /* This is the ITSTATE represented as described in
   15058          libvex_guest_arm.h.  It is not the ARM ARM representation. */
   15059       UChar c1 = '.';
   15060       UChar c2 = '.';
   15061       UChar c3 = '.';
   15062       Bool valid = compute_ITSTATE( &newITSTATE, &c1, &c2, &c3,
   15063                                     firstcond, mask );
   15064       if (valid && firstcond != 0xF/*NV*/) {
   15065          /* Not allowed in an IT block; SIGILL if so. */
   15066          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   15067 
   15068          IRTemp t = newTemp(Ity_I32);
   15069          assign(t, mkU32(newITSTATE));
   15070          put_ITSTATE(t);
   15071 
   15072          DIP("it%c%c%c %s\n", c1, c2, c3, nCC(firstcond));
   15073          goto decode_success;
   15074       }
   15075       break;
   15076    }
   15077 
   15078    case BITS8(1,0,1,1,0,0,0,1):
   15079    case BITS8(1,0,1,1,0,0,1,1):
   15080    case BITS8(1,0,1,1,1,0,0,1):
   15081    case BITS8(1,0,1,1,1,0,1,1): {
   15082       /* ---------------- CB{N}Z ---------------- */
   15083       UInt rN    = INSN0(2,0);
   15084       UInt bOP   = INSN0(11,11);
   15085       UInt imm32 = (INSN0(9,9) << 6) | (INSN0(7,3) << 1);
   15086       gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   15087       /* It's a conditional branch forward. */
   15088       IRTemp kond = newTemp(Ity_I1);
   15089       assign( kond, binop(bOP ? Iop_CmpNE32 : Iop_CmpEQ32,
   15090                           getIRegT(rN), mkU32(0)) );
   15091 
   15092       vassert(0 == (guest_R15_curr_instr_notENC & 1));
   15093       /* Looks like the nearest insn we can branch to is the one after
   15094          next.  That makes sense, as there's no point in being able to
   15095          encode a conditional branch to the next instruction. */
   15096       UInt dst = (guest_R15_curr_instr_notENC + 4 + imm32) | 1;
   15097       stmt(IRStmt_Exit( mkexpr(kond),
   15098                         Ijk_Boring,
   15099                         IRConst_U32(toUInt(dst)) ));
   15100       DIP("cb%s r%u, 0x%x\n", bOP ? "nz" : "z", rN, dst - 1);
   15101       goto decode_success;
   15102    }
   15103 
   15104    default:
   15105       break; /* examine the next shortest prefix */
   15106 
   15107    }
   15108 
   15109 
   15110    /* ================ 16-bit 15:9 cases ================ */
   15111 
   15112    switch (INSN0(15,9)) {
   15113 
   15114    case BITS7(1,0,1,1,0,1,0): {
   15115       /* ---------------- PUSH ---------------- */
   15116       /* This is a bit like STMxx, but way simpler. Complications we
   15117          don't have to deal with:
   15118          * SP being one of the transferred registers
   15119          * direction (increment vs decrement)
   15120          * before-vs-after-ness
   15121       */
   15122       Int  i, nRegs;
   15123       UInt bitR    = INSN0(8,8);
   15124       UInt regList = INSN0(7,0);
   15125       if (bitR) regList |= (1 << 14);
   15126 
   15127       if (regList != 0) {
   15128          /* Since we can't generate a guaranteed non-trapping IR
   15129             sequence, (1) jump over the insn if it is gated false, and
   15130             (2) back out the ITSTATE update. */
   15131          mk_skip_over_T16_if_cond_is_false(condT);
   15132          condT = IRTemp_INVALID;
   15133          put_ITSTATE(old_itstate);
   15134          // now uncond
   15135 
   15136          nRegs = 0;
   15137          for (i = 0; i < 16; i++) {
   15138             if ((regList & (1 << i)) != 0)
   15139                nRegs++;
   15140          }
   15141          vassert(nRegs >= 1 && nRegs <= 8);
   15142 
   15143          /* Move SP down first of all, so we're "covered".  And don't
   15144             mess with its alignment. */
   15145          IRTemp newSP = newTemp(Ity_I32);
   15146          assign(newSP, binop(Iop_Sub32, getIRegT(13), mkU32(4 * nRegs)));
   15147          putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
   15148 
   15149          /* Generate a transfer base address as a forced-aligned
   15150             version of the final SP value. */
   15151          IRTemp base = newTemp(Ity_I32);
   15152          assign(base, binop(Iop_And32, mkexpr(newSP), mkU32(~3)));
   15153 
   15154          /* Now the transfers */
   15155          nRegs = 0;
   15156          for (i = 0; i < 16; i++) {
   15157             if ((regList & (1 << i)) != 0) {
   15158                storeLE( binop(Iop_Add32, mkexpr(base), mkU32(4 * nRegs)),
   15159                         getIRegT(i) );
   15160                nRegs++;
   15161             }
   15162          }
   15163 
   15164          /* Reinstate the ITSTATE update. */
   15165          put_ITSTATE(new_itstate);
   15166 
   15167          DIP("push {%s0x%04x}\n", bitR ? "lr," : "", regList & 0xFF);
   15168          goto decode_success;
   15169       }
   15170       break;
   15171    }
   15172 
   15173    case BITS7(1,0,1,1,1,1,0): {
   15174       /* ---------------- POP ---------------- */
   15175       Int  i, nRegs;
   15176       UInt bitR    = INSN0(8,8);
   15177       UInt regList = INSN0(7,0);
   15178 
   15179       if (regList != 0 || bitR) {
   15180          /* Since we can't generate a guaranteed non-trapping IR
   15181             sequence, (1) jump over the insn if it is gated false, and
   15182             (2) back out the ITSTATE update. */
   15183          mk_skip_over_T16_if_cond_is_false(condT);
   15184          condT = IRTemp_INVALID;
   15185          put_ITSTATE(old_itstate);
   15186          // now uncond
   15187 
   15188          nRegs = 0;
   15189          for (i = 0; i < 8; i++) {
   15190             if ((regList & (1 << i)) != 0)
   15191                nRegs++;
   15192          }
   15193          vassert(nRegs >= 0 && nRegs <= 7);
   15194          vassert(bitR == 0 || bitR == 1);
   15195 
   15196          IRTemp oldSP = newTemp(Ity_I32);
   15197          assign(oldSP, getIRegT(13));
   15198 
   15199          /* Generate a transfer base address as a forced-aligned
   15200             version of the original SP value. */
   15201          IRTemp base = newTemp(Ity_I32);
   15202          assign(base, binop(Iop_And32, mkexpr(oldSP), mkU32(~3)));
   15203 
   15204          /* Compute a new value for SP, but don't install it yet, so
   15205             that we're "covered" until all the transfers are done.
   15206             And don't mess with its alignment. */
   15207          IRTemp newSP = newTemp(Ity_I32);
   15208          assign(newSP, binop(Iop_Add32, mkexpr(oldSP),
   15209                                         mkU32(4 * (nRegs + bitR))));
   15210 
   15211          /* Now the transfers, not including PC */
   15212          nRegs = 0;
   15213          for (i = 0; i < 8; i++) {
   15214             if ((regList & (1 << i)) != 0) {
   15215                putIRegT(i, loadLE( Ity_I32,
   15216                                    binop(Iop_Add32, mkexpr(base),
   15217                                                     mkU32(4 * nRegs))),
   15218                            IRTemp_INVALID );
   15219                nRegs++;
   15220             }
   15221          }
   15222 
   15223          IRTemp newPC = IRTemp_INVALID;
   15224          if (bitR) {
   15225             newPC = newTemp(Ity_I32);
   15226             assign( newPC, loadLE( Ity_I32,
   15227                                    binop(Iop_Add32, mkexpr(base),
   15228                                                     mkU32(4 * nRegs))));
   15229          }
   15230 
   15231          /* Now we can safely install the new SP value */
   15232          putIRegT(13, mkexpr(newSP), IRTemp_INVALID);
   15233 
   15234          /* Reinstate the ITSTATE update. */
   15235          put_ITSTATE(new_itstate);
   15236 
   15237          /* now, do we also have to do a branch?  If so, it turns out
   15238             that the new PC value is encoded exactly as we need it to
   15239             be -- with CPSR.T in the bottom bit.  So we can simply use
   15240             it as is, no need to mess with it.  Note, therefore, this
   15241             is an interworking return. */
   15242          if (bitR) {
   15243             irsb->next     = mkexpr(newPC);
   15244             irsb->jumpkind = Ijk_Ret;
   15245             dres.whatNext  = Dis_StopHere;
   15246          }
   15247 
   15248          DIP("pop {%s0x%04x}\n", bitR ? "pc," : "", regList & 0xFF);
   15249          goto decode_success;
   15250       }
   15251       break;
   15252    }
   15253 
   15254    case BITS7(0,0,0,1,1,1,0):   /* ADDS */
   15255    case BITS7(0,0,0,1,1,1,1): { /* SUBS */
   15256       /* ---------------- ADDS Rd, Rn, #uimm3 ---------------- */
   15257       /* ---------------- SUBS Rd, Rn, #uimm3 ---------------- */
   15258       UInt   uimm3 = INSN0(8,6);
   15259       UInt   rN    = INSN0(5,3);
   15260       UInt   rD    = INSN0(2,0);
   15261       UInt   isSub = INSN0(9,9);
   15262       IRTemp argL  = newTemp(Ity_I32);
   15263       IRTemp argR  = newTemp(Ity_I32);
   15264       assign( argL, getIRegT(rN) );
   15265       assign( argR, mkU32(uimm3) );
   15266       putIRegT(rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
   15267                          mkexpr(argL), mkexpr(argR)),
   15268                    condT);
   15269       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
   15270                       argL, argR, cond_AND_notInIT_T );
   15271       DIP("%s r%u, r%u, #%u\n", isSub ? "subs" : "adds", rD, rN, uimm3);
   15272       goto decode_success;
   15273    }
   15274 
   15275    case BITS7(0,0,0,1,1,0,0):   /* ADDS */
   15276    case BITS7(0,0,0,1,1,0,1): { /* SUBS */
   15277       /* ---------------- ADDS Rd, Rn, Rm ---------------- */
   15278       /* ---------------- SUBS Rd, Rn, Rm ---------------- */
   15279       UInt   rM    = INSN0(8,6);
   15280       UInt   rN    = INSN0(5,3);
   15281       UInt   rD    = INSN0(2,0);
   15282       UInt   isSub = INSN0(9,9);
   15283       IRTemp argL  = newTemp(Ity_I32);
   15284       IRTemp argR  = newTemp(Ity_I32);
   15285       assign( argL, getIRegT(rN) );
   15286       assign( argR, getIRegT(rM) );
   15287       putIRegT( rD, binop(isSub ? Iop_Sub32 : Iop_Add32,
   15288                           mkexpr(argL), mkexpr(argR)),
   15289                     condT );
   15290       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
   15291                       argL, argR, cond_AND_notInIT_T );
   15292       DIP("%s r%u, r%u, r%u\n", isSub ? "subs" : "adds", rD, rN, rM);
   15293       goto decode_success;
   15294    }
   15295 
   15296    case BITS7(0,1,0,1,0,0,0):   /* STR */
   15297    case BITS7(0,1,0,1,1,0,0): { /* LDR */
   15298       /* ------------- LDR Rd, [Rn, Rm] ------------- */
   15299       /* ------------- STR Rd, [Rn, Rm] ------------- */
   15300       /* LDR/STR Rd, [Rn + Rm] */
   15301       UInt    rD   = INSN0(2,0);
   15302       UInt    rN   = INSN0(5,3);
   15303       UInt    rM   = INSN0(8,6);
   15304       UInt    isLD = INSN0(11,11);
   15305 
   15306       mk_skip_over_T16_if_cond_is_false(condT);
   15307       condT = IRTemp_INVALID;
   15308       // now uncond
   15309 
   15310       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   15311       put_ITSTATE(old_itstate); // backout
   15312       if (isLD) {
   15313          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
   15314       } else {
   15315          storeLE(ea, getIRegT(rD));
   15316       }
   15317       put_ITSTATE(new_itstate); // restore
   15318 
   15319       DIP("%s r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
   15320       goto decode_success;
   15321    }
   15322 
   15323    case BITS7(0,1,0,1,0,0,1):
   15324    case BITS7(0,1,0,1,1,0,1): {
   15325       /* ------------- LDRH Rd, [Rn, Rm] ------------- */
   15326       /* ------------- STRH Rd, [Rn, Rm] ------------- */
   15327       /* LDRH/STRH Rd, [Rn + Rm] */
   15328       UInt    rD   = INSN0(2,0);
   15329       UInt    rN   = INSN0(5,3);
   15330       UInt    rM   = INSN0(8,6);
   15331       UInt    isLD = INSN0(11,11);
   15332 
   15333       mk_skip_over_T16_if_cond_is_false(condT);
   15334       condT = IRTemp_INVALID;
   15335       // now uncond
   15336 
   15337       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   15338       put_ITSTATE(old_itstate); // backout
   15339       if (isLD) {
   15340          putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
   15341                       IRTemp_INVALID);
   15342       } else {
   15343          storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
   15344       }
   15345       put_ITSTATE(new_itstate); // restore
   15346 
   15347       DIP("%sh r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
   15348       goto decode_success;
   15349    }
   15350 
   15351    case BITS7(0,1,0,1,1,1,1): {
   15352       /* ------------- LDRSH Rd, [Rn, Rm] ------------- */
   15353       /* LDRSH Rd, [Rn + Rm] */
   15354       UInt    rD = INSN0(2,0);
   15355       UInt    rN = INSN0(5,3);
   15356       UInt    rM = INSN0(8,6);
   15357 
   15358       mk_skip_over_T16_if_cond_is_false(condT);
   15359       condT = IRTemp_INVALID;
   15360       // now uncond
   15361 
   15362       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   15363       put_ITSTATE(old_itstate); // backout
   15364       putIRegT(rD, unop(Iop_16Sto32, loadLE(Ity_I16, ea)),
   15365                    IRTemp_INVALID);
   15366       put_ITSTATE(new_itstate); // restore
   15367 
   15368       DIP("ldrsh r%u, [r%u, r%u]\n", rD, rN, rM);
   15369       goto decode_success;
   15370    }
   15371 
   15372    case BITS7(0,1,0,1,0,1,1): {
   15373       /* ------------- LDRSB Rd, [Rn, Rm] ------------- */
   15374       /* LDRSB Rd, [Rn + Rm] */
   15375       UInt    rD = INSN0(2,0);
   15376       UInt    rN = INSN0(5,3);
   15377       UInt    rM = INSN0(8,6);
   15378 
   15379       mk_skip_over_T16_if_cond_is_false(condT);
   15380       condT = IRTemp_INVALID;
   15381       // now uncond
   15382 
   15383       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   15384       put_ITSTATE(old_itstate); // backout
   15385       putIRegT(rD, unop(Iop_8Sto32, loadLE(Ity_I8, ea)),
   15386                    IRTemp_INVALID);
   15387       put_ITSTATE(new_itstate); // restore
   15388 
   15389       DIP("ldrsb r%u, [r%u, r%u]\n", rD, rN, rM);
   15390       goto decode_success;
   15391    }
   15392 
   15393    case BITS7(0,1,0,1,0,1,0):
   15394    case BITS7(0,1,0,1,1,1,0): {
   15395       /* ------------- LDRB Rd, [Rn, Rm] ------------- */
   15396       /* ------------- STRB Rd, [Rn, Rm] ------------- */
   15397       /* LDRB/STRB Rd, [Rn + Rm] */
   15398       UInt    rD   = INSN0(2,0);
   15399       UInt    rN   = INSN0(5,3);
   15400       UInt    rM   = INSN0(8,6);
   15401       UInt    isLD = INSN0(11,11);
   15402 
   15403       mk_skip_over_T16_if_cond_is_false(condT);
   15404       condT = IRTemp_INVALID;
   15405       // now uncond
   15406 
   15407       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), getIRegT(rM));
   15408       put_ITSTATE(old_itstate); // backout
   15409       if (isLD) {
   15410          putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
   15411                   IRTemp_INVALID);
   15412       } else {
   15413          storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
   15414       }
   15415       put_ITSTATE(new_itstate); // restore
   15416 
   15417       DIP("%sb r%u, [r%u, r%u]\n", isLD ? "ldr" : "str", rD, rN, rM);
   15418       goto decode_success;
   15419    }
   15420 
   15421    default:
   15422       break; /* examine the next shortest prefix */
   15423 
   15424    }
   15425 
   15426 
   15427    /* ================ 16-bit 15:11 cases ================ */
   15428 
   15429    switch (INSN0(15,11)) {
   15430 
   15431    case BITS5(0,0,1,1,0):
   15432    case BITS5(0,0,1,1,1): {
   15433       /* ---------------- ADDS Rn, #uimm8 ---------------- */
   15434       /* ---------------- SUBS Rn, #uimm8 ---------------- */
   15435       UInt   isSub = INSN0(11,11);
   15436       UInt   rN    = INSN0(10,8);
   15437       UInt   uimm8 = INSN0(7,0);
   15438       IRTemp argL  = newTemp(Ity_I32);
   15439       IRTemp argR  = newTemp(Ity_I32);
   15440       assign( argL, getIRegT(rN) );
   15441       assign( argR, mkU32(uimm8) );
   15442       putIRegT( rN, binop(isSub ? Iop_Sub32 : Iop_Add32,
   15443                           mkexpr(argL), mkexpr(argR)), condT );
   15444       setFlags_D1_D2( isSub ? ARMG_CC_OP_SUB : ARMG_CC_OP_ADD,
   15445                       argL, argR, cond_AND_notInIT_T );
   15446       DIP("%s r%u, #%u\n", isSub ? "subs" : "adds", rN, uimm8);
   15447       goto decode_success;
   15448    }
   15449 
   15450    case BITS5(1,0,1,0,0): {
   15451       /* ---------------- ADD rD, PC, #imm8 * 4 ---------------- */
   15452       /* a.k.a. ADR */
   15453       /* rD = align4(PC) + imm8 * 4 */
   15454       UInt rD   = INSN0(10,8);
   15455       UInt imm8 = INSN0(7,0);
   15456       putIRegT(rD, binop(Iop_Add32,
   15457                          binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   15458                          mkU32(imm8 * 4)),
   15459                    condT);
   15460       DIP("add r%u, pc, #%u\n", rD, imm8 * 4);
   15461       goto decode_success;
   15462    }
   15463 
   15464    case BITS5(1,0,1,0,1): {
   15465       /* ---------------- ADD rD, SP, #imm8 * 4 ---------------- */
   15466       UInt rD   = INSN0(10,8);
   15467       UInt imm8 = INSN0(7,0);
   15468       putIRegT(rD, binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4)),
   15469                    condT);
   15470       DIP("add r%u, r13, #%u\n", rD, imm8 * 4);
   15471       goto decode_success;
   15472    }
   15473 
   15474    case BITS5(0,0,1,0,1): {
   15475       /* ---------------- CMP Rn, #uimm8 ---------------- */
   15476       UInt   rN    = INSN0(10,8);
   15477       UInt   uimm8 = INSN0(7,0);
   15478       IRTemp argL  = newTemp(Ity_I32);
   15479       IRTemp argR  = newTemp(Ity_I32);
   15480       assign( argL, getIRegT(rN) );
   15481       assign( argR, mkU32(uimm8) );
   15482       /* Update flags regardless of whether in an IT block or not. */
   15483       setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   15484       DIP("cmp r%u, #%u\n", rN, uimm8);
   15485       goto decode_success;
   15486    }
   15487 
   15488    case BITS5(0,0,1,0,0): {
   15489       /* -------------- (T1) MOVS Rn, #uimm8 -------------- */
   15490       UInt   rD    = INSN0(10,8);
   15491       UInt   uimm8 = INSN0(7,0);
   15492       IRTemp oldV  = newTemp(Ity_I32);
   15493       IRTemp oldC  = newTemp(Ity_I32);
   15494       IRTemp res   = newTemp(Ity_I32);
   15495       assign( oldV, mk_armg_calculate_flag_v() );
   15496       assign( oldC, mk_armg_calculate_flag_c() );
   15497       assign( res, mkU32(uimm8) );
   15498       putIRegT(rD, mkexpr(res), condT);
   15499       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   15500                          cond_AND_notInIT_T );
   15501       DIP("movs r%u, #%u\n", rD, uimm8);
   15502       goto decode_success;
   15503    }
   15504 
   15505    case BITS5(0,1,0,0,1): {
   15506       /* ------------- LDR Rd, [PC, #imm8 * 4] ------------- */
   15507       /* LDR Rd, [align4(PC) + imm8 * 4] */
   15508       UInt   rD   = INSN0(10,8);
   15509       UInt   imm8 = INSN0(7,0);
   15510       IRTemp ea   = newTemp(Ity_I32);
   15511 
   15512       mk_skip_over_T16_if_cond_is_false(condT);
   15513       condT = IRTemp_INVALID;
   15514       // now uncond
   15515 
   15516       assign(ea, binop(Iop_Add32,
   15517                        binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   15518                        mkU32(imm8 * 4)));
   15519       put_ITSTATE(old_itstate); // backout
   15520       putIRegT(rD, loadLE(Ity_I32, mkexpr(ea)),
   15521                    IRTemp_INVALID);
   15522       put_ITSTATE(new_itstate); // restore
   15523 
   15524       DIP("ldr r%u, [pc, #%u]\n", rD, imm8 * 4);
   15525       goto decode_success;
   15526    }
   15527 
   15528    case BITS5(0,1,1,0,0):   /* STR */
   15529    case BITS5(0,1,1,0,1): { /* LDR */
   15530       /* ------------- LDR Rd, [Rn, #imm5 * 4] ------------- */
   15531       /* ------------- STR Rd, [Rn, #imm5 * 4] ------------- */
   15532       /* LDR/STR Rd, [Rn + imm5 * 4] */
   15533       UInt    rD   = INSN0(2,0);
   15534       UInt    rN   = INSN0(5,3);
   15535       UInt    imm5 = INSN0(10,6);
   15536       UInt    isLD = INSN0(11,11);
   15537 
   15538       mk_skip_over_T16_if_cond_is_false(condT);
   15539       condT = IRTemp_INVALID;
   15540       // now uncond
   15541 
   15542       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 4));
   15543       put_ITSTATE(old_itstate); // backout
   15544       if (isLD) {
   15545          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
   15546       } else {
   15547          storeLE( ea, getIRegT(rD) );
   15548       }
   15549       put_ITSTATE(new_itstate); // restore
   15550 
   15551       DIP("%s r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 4);
   15552       goto decode_success;
   15553    }
   15554 
   15555    case BITS5(1,0,0,0,0):   /* STRH */
   15556    case BITS5(1,0,0,0,1): { /* LDRH */
   15557       /* ------------- LDRH Rd, [Rn, #imm5 * 2] ------------- */
   15558       /* ------------- STRH Rd, [Rn, #imm5 * 2] ------------- */
   15559       /* LDRH/STRH Rd, [Rn + imm5 * 2] */
   15560       UInt    rD   = INSN0(2,0);
   15561       UInt    rN   = INSN0(5,3);
   15562       UInt    imm5 = INSN0(10,6);
   15563       UInt    isLD = INSN0(11,11);
   15564 
   15565       mk_skip_over_T16_if_cond_is_false(condT);
   15566       condT = IRTemp_INVALID;
   15567       // now uncond
   15568 
   15569       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5 * 2));
   15570       put_ITSTATE(old_itstate); // backout
   15571       if (isLD) {
   15572          putIRegT(rD, unop(Iop_16Uto32, loadLE(Ity_I16, ea)),
   15573                   IRTemp_INVALID);
   15574       } else {
   15575          storeLE( ea, unop(Iop_32to16, getIRegT(rD)) );
   15576       }
   15577       put_ITSTATE(new_itstate); // restore
   15578 
   15579       DIP("%sh r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5 * 2);
   15580       goto decode_success;
   15581    }
   15582 
   15583    case BITS5(0,1,1,1,0):   /* STRB */
   15584    case BITS5(0,1,1,1,1): { /* LDRB */
   15585       /* ------------- LDRB Rd, [Rn, #imm5] ------------- */
   15586       /* ------------- STRB Rd, [Rn, #imm5] ------------- */
   15587       /* LDRB/STRB Rd, [Rn + imm5] */
   15588       UInt    rD   = INSN0(2,0);
   15589       UInt    rN   = INSN0(5,3);
   15590       UInt    imm5 = INSN0(10,6);
   15591       UInt    isLD = INSN0(11,11);
   15592 
   15593       mk_skip_over_T16_if_cond_is_false(condT);
   15594       condT = IRTemp_INVALID;
   15595       // now uncond
   15596 
   15597       IRExpr* ea = binop(Iop_Add32, getIRegT(rN), mkU32(imm5));
   15598       put_ITSTATE(old_itstate); // backout
   15599       if (isLD) {
   15600          putIRegT(rD, unop(Iop_8Uto32, loadLE(Ity_I8, ea)),
   15601                   IRTemp_INVALID);
   15602       } else {
   15603          storeLE( ea, unop(Iop_32to8, getIRegT(rD)) );
   15604       }
   15605       put_ITSTATE(new_itstate); // restore
   15606 
   15607       DIP("%sb r%u, [r%u, #%u]\n", isLD ? "ldr" : "str", rD, rN, imm5);
   15608       goto decode_success;
   15609    }
   15610 
   15611    case BITS5(1,0,0,1,0):   /* STR */
   15612    case BITS5(1,0,0,1,1): { /* LDR */
   15613       /* ------------- LDR Rd, [SP, #imm8 * 4] ------------- */
   15614       /* ------------- STR Rd, [SP, #imm8 * 4] ------------- */
   15615       /* LDR/STR Rd, [SP + imm8 * 4] */
   15616       UInt rD    = INSN0(10,8);
   15617       UInt imm8  = INSN0(7,0);
   15618       UInt isLD  = INSN0(11,11);
   15619 
   15620       mk_skip_over_T16_if_cond_is_false(condT);
   15621       condT = IRTemp_INVALID;
   15622       // now uncond
   15623 
   15624       IRExpr* ea = binop(Iop_Add32, getIRegT(13), mkU32(imm8 * 4));
   15625       put_ITSTATE(old_itstate); // backout
   15626       if (isLD) {
   15627          putIRegT(rD, loadLE(Ity_I32, ea), IRTemp_INVALID);
   15628       } else {
   15629          storeLE(ea, getIRegT(rD));
   15630       }
   15631       put_ITSTATE(new_itstate); // restore
   15632 
   15633       DIP("%s r%u, [sp, #%u]\n", isLD ? "ldr" : "str", rD, imm8 * 4);
   15634       goto decode_success;
   15635    }
   15636 
   15637    case BITS5(1,1,0,0,1): {
   15638       /* ------------- LDMIA Rn!, {reglist} ------------- */
   15639       Int i, nRegs = 0;
   15640       UInt rN   = INSN0(10,8);
   15641       UInt list = INSN0(7,0);
   15642       /* Empty lists aren't allowed. */
   15643       if (list != 0) {
   15644          mk_skip_over_T16_if_cond_is_false(condT);
   15645          condT = IRTemp_INVALID;
   15646          put_ITSTATE(old_itstate);
   15647          // now uncond
   15648 
   15649          IRTemp oldRn = newTemp(Ity_I32);
   15650          IRTemp base  = newTemp(Ity_I32);
   15651          assign(oldRn, getIRegT(rN));
   15652          assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
   15653          for (i = 0; i < 8; i++) {
   15654             if (0 == (list & (1 << i)))
   15655                continue;
   15656             nRegs++;
   15657             putIRegT(
   15658                i, loadLE(Ity_I32,
   15659                          binop(Iop_Add32, mkexpr(base),
   15660                                           mkU32(nRegs * 4 - 4))),
   15661                IRTemp_INVALID
   15662             );
   15663          }
   15664          /* Only do the writeback for rN if it isn't in the list of
   15665             registers to be transferred. */
   15666          if (0 == (list & (1 << rN))) {
   15667             putIRegT(rN,
   15668                      binop(Iop_Add32, mkexpr(oldRn),
   15669                                       mkU32(nRegs * 4)),
   15670                      IRTemp_INVALID
   15671             );
   15672          }
   15673 
   15674          /* Reinstate the ITSTATE update. */
   15675          put_ITSTATE(new_itstate);
   15676 
   15677          DIP("ldmia r%u!, {0x%04x}\n", rN, list);
   15678          goto decode_success;
   15679       }
   15680       break;
   15681    }
   15682 
   15683    case BITS5(1,1,0,0,0): {
   15684       /* ------------- STMIA Rn!, {reglist} ------------- */
   15685       Int i, nRegs = 0;
   15686       UInt rN   = INSN0(10,8);
   15687       UInt list = INSN0(7,0);
   15688       /* Empty lists aren't allowed.  Also, if rN is in the list then
   15689          it must be the lowest numbered register in the list. */
   15690       Bool valid = list != 0;
   15691       if (valid && 0 != (list & (1 << rN))) {
   15692          for (i = 0; i < rN; i++) {
   15693             if (0 != (list & (1 << i)))
   15694                valid = False;
   15695          }
   15696       }
   15697       if (valid) {
   15698          mk_skip_over_T16_if_cond_is_false(condT);
   15699          condT = IRTemp_INVALID;
   15700          put_ITSTATE(old_itstate);
   15701          // now uncond
   15702 
   15703          IRTemp oldRn = newTemp(Ity_I32);
   15704          IRTemp base = newTemp(Ity_I32);
   15705          assign(oldRn, getIRegT(rN));
   15706          assign(base, binop(Iop_And32, mkexpr(oldRn), mkU32(~3U)));
   15707          for (i = 0; i < 8; i++) {
   15708             if (0 == (list & (1 << i)))
   15709                continue;
   15710             nRegs++;
   15711             storeLE( binop(Iop_Add32, mkexpr(base), mkU32(nRegs * 4 - 4)),
   15712                      getIRegT(i) );
   15713          }
   15714          /* Always do the writeback. */
   15715          putIRegT(rN,
   15716                   binop(Iop_Add32, mkexpr(oldRn),
   15717                                    mkU32(nRegs * 4)),
   15718                   IRTemp_INVALID);
   15719 
   15720          /* Reinstate the ITSTATE update. */
   15721          put_ITSTATE(new_itstate);
   15722 
   15723          DIP("stmia r%u!, {0x%04x}\n", rN, list);
   15724          goto decode_success;
   15725       }
   15726       break;
   15727    }
   15728 
   15729    case BITS5(0,0,0,0,0):   /* LSLS */
   15730    case BITS5(0,0,0,0,1):   /* LSRS */
   15731    case BITS5(0,0,0,1,0): { /* ASRS */
   15732       /* ---------------- LSLS Rd, Rm, #imm5 ---------------- */
   15733       /* ---------------- LSRS Rd, Rm, #imm5 ---------------- */
   15734       /* ---------------- ASRS Rd, Rm, #imm5 ---------------- */
   15735       UInt   rD   = INSN0(2,0);
   15736       UInt   rM   = INSN0(5,3);
   15737       UInt   imm5 = INSN0(10,6);
   15738       IRTemp res  = newTemp(Ity_I32);
   15739       IRTemp resC = newTemp(Ity_I32);
   15740       IRTemp rMt  = newTemp(Ity_I32);
   15741       IRTemp oldV = newTemp(Ity_I32);
   15742       HChar* wot  = "???";
   15743       assign(rMt, getIRegT(rM));
   15744       assign(oldV, mk_armg_calculate_flag_v());
   15745       /* Looks like INSN0(12,11) are the standard 'how' encoding.
   15746          Could compactify if the ROR case later appears. */
   15747       switch (INSN0(15,11)) {
   15748          case BITS5(0,0,0,0,0):
   15749             compute_result_and_C_after_LSL_by_imm5(
   15750                dis_buf, &res, &resC, rMt, imm5, rM
   15751             );
   15752             wot = "lsl";
   15753             break;
   15754          case BITS5(0,0,0,0,1):
   15755             compute_result_and_C_after_LSR_by_imm5(
   15756                dis_buf, &res, &resC, rMt, imm5, rM
   15757             );
   15758             wot = "lsr";
   15759             break;
   15760          case BITS5(0,0,0,1,0):
   15761             compute_result_and_C_after_ASR_by_imm5(
   15762                dis_buf, &res, &resC, rMt, imm5, rM
   15763             );
   15764             wot = "asr";
   15765             break;
   15766          default:
   15767             /*NOTREACHED*/vassert(0);
   15768       }
   15769       // not safe to read guest state after this point
   15770       putIRegT(rD, mkexpr(res), condT);
   15771       setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, resC, oldV,
   15772                          cond_AND_notInIT_T );
   15773       /* ignore buf and roll our own output */
   15774       DIP("%ss r%u, r%u, #%u\n", wot, rD, rM, imm5);
   15775       goto decode_success;
   15776    }
   15777 
   15778    case BITS5(1,1,1,0,0): {
   15779       /* ---------------- B #simm11 ---------------- */
   15780       Int  simm11 = INSN0(10,0);
   15781            simm11 = (simm11 << 21) >> 20;
   15782       UInt dst    = simm11 + guest_R15_curr_instr_notENC + 4;
   15783       /* Only allowed outside or last-in IT block; SIGILL if not so. */
   15784       gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15785       // and skip this insn if not selected; being cleverer is too
   15786       // difficult
   15787       mk_skip_over_T16_if_cond_is_false(condT);
   15788       condT = IRTemp_INVALID;
   15789       // now uncond
   15790       irsb->next     = mkU32( dst | 1 /*CPSR.T*/ );
   15791       irsb->jumpkind = Ijk_Boring;
   15792       dres.whatNext  = Dis_StopHere;
   15793       DIP("b 0x%x\n", dst);
   15794       goto decode_success;
   15795    }
   15796 
   15797    default:
   15798       break; /* examine the next shortest prefix */
   15799 
   15800    }
   15801 
   15802 
   15803    /* ================ 16-bit 15:12 cases ================ */
   15804 
   15805    switch (INSN0(15,12)) {
   15806 
   15807    case BITS4(1,1,0,1): {
   15808       /* ---------------- Bcond #simm8 ---------------- */
   15809       UInt cond  = INSN0(11,8);
   15810       Int  simm8 = INSN0(7,0);
   15811            simm8 = (simm8 << 24) >> 23;
   15812       UInt dst   = simm8 + guest_R15_curr_instr_notENC + 4;
   15813       if (cond != ARMCondAL && cond != ARMCondNV) {
   15814          /* Not allowed in an IT block; SIGILL if so. */
   15815          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   15816 
   15817          IRTemp kondT = newTemp(Ity_I32);
   15818          assign( kondT, mk_armg_calculate_condition(cond) );
   15819          stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
   15820                             Ijk_Boring,
   15821                             IRConst_U32(dst | 1/*CPSR.T*/) ));
   15822          irsb->next = mkU32( (guest_R15_curr_instr_notENC + 2)
   15823                              | 1 /*CPSR.T*/ );
   15824          irsb->jumpkind = Ijk_Boring;
   15825          dres.whatNext  = Dis_StopHere;
   15826          DIP("b%s 0x%x\n", nCC(cond), dst);
   15827          goto decode_success;
   15828       }
   15829       break;
   15830    }
   15831 
   15832    default:
   15833       break; /* hmm, nothing matched */
   15834 
   15835    }
   15836 
   15837    /* ================ 16-bit misc cases ================ */
   15838 
   15839    /* ------ NOP ------ */
   15840    if (INSN0(15,0) == 0xBF00) {
   15841       DIP("nop");
   15842       goto decode_success;
   15843    }
   15844 
   15845    /* ----------------------------------------------------------- */
   15846    /* --                                                       -- */
   15847    /* -- Thumb 32-bit integer instructions                     -- */
   15848    /* --                                                       -- */
   15849    /* ----------------------------------------------------------- */
   15850 
   15851 #  define INSN1(_bMax,_bMin)  SLICE_UInt(((UInt)insn1), (_bMax), (_bMin))
   15852 
   15853    /* second 16 bits of the instruction, if any */
   15854    UShort insn1 = getUShortLittleEndianly( guest_instr+2 );
   15855 
   15856    anOp   = Iop_INVALID; /* paranoia */
   15857    anOpNm = NULL;        /* paranoia */
   15858 
   15859    /* Change result defaults to suit 32-bit insns. */
   15860    vassert(dres.whatNext   == Dis_Continue);
   15861    vassert(dres.len        == 2);
   15862    vassert(dres.continueAt == 0);
   15863    dres.len = 4;
   15864 
   15865    /* ---------------- BL/BLX simm26 ---------------- */
   15866    if (BITS5(1,1,1,1,0) == INSN0(15,11) && BITS2(1,1) == INSN1(15,14)) {
   15867       UInt isBL = INSN1(12,12);
   15868       UInt bS   = INSN0(10,10);
   15869       UInt bJ1  = INSN1(13,13);
   15870       UInt bJ2  = INSN1(11,11);
   15871       UInt bI1  = 1 ^ (bJ1 ^ bS);
   15872       UInt bI2  = 1 ^ (bJ2 ^ bS);
   15873       Int simm25
   15874          =   (bS          << (1 + 1 + 10 + 11 + 1))
   15875            | (bI1         << (1 + 10 + 11 + 1))
   15876            | (bI2         << (10 + 11 + 1))
   15877            | (INSN0(9,0)  << (11 + 1))
   15878            | (INSN1(10,0) << 1);
   15879       simm25 = (simm25 << 7) >> 7;
   15880 
   15881       vassert(0 == (guest_R15_curr_instr_notENC & 1));
   15882       UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
   15883 
   15884       /* One further validity case to check: in the case of BLX
   15885          (not-BL), that insn1[0] must be zero. */
   15886       Bool valid = True;
   15887       if (isBL == 0 && INSN1(0,0) == 1) valid = False;
   15888       if (valid) {
   15889          /* Only allowed outside or last-in IT block; SIGILL if not so. */
   15890          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15891          // and skip this insn if not selected; being cleverer is too
   15892          // difficult
   15893          mk_skip_over_T32_if_cond_is_false(condT);
   15894          condT = IRTemp_INVALID;
   15895          // now uncond
   15896 
   15897          /* We're returning to Thumb code, hence "| 1" */
   15898          putIRegT( 14, mkU32( (guest_R15_curr_instr_notENC + 4) | 1 ),
   15899                    IRTemp_INVALID);
   15900          if (isBL) {
   15901             /* BL: unconditional T -> T call */
   15902             /* we're calling Thumb code, hence "| 1" */
   15903             irsb->next = mkU32( dst | 1 );
   15904             DIP("bl 0x%x (stay in Thumb mode)\n", dst);
   15905          } else {
   15906             /* BLX: unconditional T -> A call */
   15907             /* we're calling ARM code, hence "& 3" to align to a
   15908                valid ARM insn address */
   15909             irsb->next = mkU32( dst & ~3 );
   15910             DIP("blx 0x%x (switch to ARM mode)\n", dst & ~3);
   15911          }
   15912          irsb->jumpkind = Ijk_Call;
   15913          dres.whatNext = Dis_StopHere;
   15914          goto decode_success;
   15915       }
   15916    }
   15917 
   15918    /* ---------------- {LD,ST}M{IA,DB} ---------------- */
   15919    if (0x3a2 == INSN0(15,6) // {LD,ST}MIA
   15920        || 0x3a4 == INSN0(15,6)) { // {LD,ST}MDB
   15921       UInt bW      = INSN0(5,5); /* writeback Rn ? */
   15922       UInt bL      = INSN0(4,4);
   15923       UInt rN      = INSN0(3,0);
   15924       UInt bP      = INSN1(15,15); /* reglist entry for r15 */
   15925       UInt bM      = INSN1(14,14); /* reglist entry for r14 */
   15926       UInt rLmost  = INSN1(12,0);  /* reglist entry for r0 .. 12 */
   15927       UInt rL13    = INSN1(13,13); /* must be zero */
   15928       UInt regList = 0;
   15929       Bool valid   = True;
   15930 
   15931       UInt bINC    = 1;
   15932       UInt bBEFORE = 0;
   15933       if (INSN0(15,6) == 0x3a4) {
   15934          bINC    = 0;
   15935          bBEFORE = 1;
   15936       }
   15937 
   15938       /* detect statically invalid cases, and construct the final
   15939          reglist */
   15940       if (rL13 == 1)
   15941          valid = False;
   15942 
   15943       if (bL == 1) {
   15944          regList = (bP << 15) | (bM << 14) | rLmost;
   15945          if (rN == 15)                       valid = False;
   15946          if (popcount32(regList) < 2)        valid = False;
   15947          if (bP == 1 && bM == 1)             valid = False;
   15948          if (bW == 1 && (regList & (1<<rN))) valid = False;
   15949       } else {
   15950          regList = (bM << 14) | rLmost;
   15951          if (bP == 1)                        valid = False;
   15952          if (rN == 15)                       valid = False;
   15953          if (popcount32(regList) < 2)        valid = False;
   15954          if (bW == 1 && (regList & (1<<rN))) valid = False;
   15955          if (regList & (1<<rN)) {
   15956             UInt i;
   15957             /* if Rn is in the list, then it must be the
   15958                lowest numbered entry */
   15959             for (i = 0; i < rN; i++) {
   15960                if (regList & (1<<i))
   15961                   valid = False;
   15962             }
   15963          }
   15964       }
   15965 
   15966       if (valid) {
   15967          if (bL == 1 && bP == 1) {
   15968             // We'll be writing the PC.  Hence:
   15969             /* Only allowed outside or last-in IT block; SIGILL if not so. */
   15970             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   15971          }
   15972 
   15973          /* Go uncond: */
   15974          mk_skip_over_T32_if_cond_is_false(condT);
   15975          condT = IRTemp_INVALID;
   15976          // now uncond
   15977 
   15978          /* Generate the IR.  This might generate a write to R15, */
   15979          mk_ldm_stm(False/*!arm*/, rN, bINC, bBEFORE, bW, bL, regList);
   15980 
   15981          if (bL == 1 && (regList & (1<<15))) {
   15982             // If we wrote to R15, we have an interworking return to
   15983             // deal with.
   15984             irsb->next     = llGetIReg(15);
   15985             irsb->jumpkind = Ijk_Ret;
   15986             dres.whatNext  = Dis_StopHere;
   15987          }
   15988 
   15989          DIP("%sm%c%c r%u%s, {0x%04x}\n",
   15990               bL == 1 ? "ld" : "st", bINC ? 'i' : 'd', bBEFORE ? 'b' : 'a',
   15991               rN, bW ? "!" : "", regList);
   15992 
   15993          goto decode_success;
   15994       }
   15995    }
   15996 
   15997    /* -------------- (T3) ADD{S}.W Rd, Rn, #constT -------------- */
   15998    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   15999        && INSN0(9,5) == BITS5(0,1,0,0,0)
   16000        && INSN1(15,15) == 0) {
   16001       UInt bS = INSN0(4,4);
   16002       UInt rN = INSN0(3,0);
   16003       UInt rD = INSN1(11,8);
   16004       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16005       /* but allow "add.w reg, sp, #constT" */
   16006       if (!valid && rN == 13)
   16007          valid = True;
   16008       if (valid) {
   16009          IRTemp argL  = newTemp(Ity_I32);
   16010          IRTemp argR  = newTemp(Ity_I32);
   16011          IRTemp res   = newTemp(Ity_I32);
   16012          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16013          assign(argL, getIRegT(rN));
   16014          assign(argR, mkU32(imm32));
   16015          assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
   16016          putIRegT(rD, mkexpr(res), condT);
   16017          if (bS == 1)
   16018             setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
   16019          DIP("add%s.w r%u, r%u, #%u\n",
   16020              bS == 1 ? "s" : "", rD, rN, imm32);
   16021          goto decode_success;
   16022       }
   16023    }
   16024 
   16025    /* ---------------- (T4) ADDW Rd, Rn, #imm12 -------------- */
   16026    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16027        && INSN0(9,4) == BITS6(1,0,0,0,0,0)
   16028        && INSN1(15,15) == 0) {
   16029       UInt rN = INSN0(3,0);
   16030       UInt rD = INSN1(11,8);
   16031       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16032       /* but allow "addw reg, sp, #imm12" */
   16033       if (!valid && rN == 13)
   16034          valid = True;
   16035       if (valid) {
   16036          IRTemp argL = newTemp(Ity_I32);
   16037          IRTemp argR = newTemp(Ity_I32);
   16038          IRTemp res  = newTemp(Ity_I32);
   16039          UInt imm1   = INSN0(10,10);
   16040          UInt imm3   = INSN1(14,12);
   16041          UInt imm8   = INSN1(7,0);
   16042          UInt imm12  = (imm1 << 11) | (imm3 << 8) | imm8;
   16043          assign(argL, getIRegT(rN));
   16044          assign(argR, mkU32(imm12));
   16045          assign(res,  binop(Iop_Add32, mkexpr(argL), mkexpr(argR)));
   16046          putIRegT(rD, mkexpr(res), condT);
   16047          DIP("addw r%u, r%u, #%u\n", rD, rN, imm12);
   16048          goto decode_success;
   16049       }
   16050    }
   16051 
   16052    /* ---------------- (T2) CMP.W Rn, #constT ---------------- */
   16053    /* ---------------- (T2) CMN.W Rn, #constT ---------------- */
   16054    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16055        && (   INSN0(9,4) == BITS6(0,1,1,0,1,1)  // CMP
   16056            || INSN0(9,4) == BITS6(0,1,0,0,0,1)) // CMN
   16057        && INSN1(15,15) == 0
   16058        && INSN1(11,8) == BITS4(1,1,1,1)) {
   16059       UInt rN = INSN0(3,0);
   16060       if (rN != 15) {
   16061          IRTemp argL  = newTemp(Ity_I32);
   16062          IRTemp argR  = newTemp(Ity_I32);
   16063          Bool   isCMN = INSN0(9,4) == BITS6(0,1,0,0,0,1);
   16064          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16065          assign(argL, getIRegT(rN));
   16066          assign(argR, mkU32(imm32));
   16067          setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   16068                          argL, argR, condT );
   16069          DIP("%s.w r%u, #%u\n", isCMN ? "cmn" : "cmp", rN, imm32);
   16070          goto decode_success;
   16071       }
   16072    }
   16073 
   16074    /* -------------- (T1) TST.W Rn, #constT -------------- */
   16075    /* -------------- (T1) TEQ.W Rn, #constT -------------- */
   16076    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16077        && (   INSN0(9,4) == BITS6(0,0,0,0,0,1)  // TST
   16078            || INSN0(9,4) == BITS6(0,0,1,0,0,1)) // TEQ
   16079        && INSN1(15,15) == 0
   16080        && INSN1(11,8) == BITS4(1,1,1,1)) {
   16081       UInt rN = INSN0(3,0);
   16082       if (!isBadRegT(rN)) { // yes, really, it's inconsistent with CMP.W
   16083          Bool  isTST  = INSN0(9,4) == BITS6(0,0,0,0,0,1);
   16084          IRTemp argL  = newTemp(Ity_I32);
   16085          IRTemp argR  = newTemp(Ity_I32);
   16086          IRTemp res   = newTemp(Ity_I32);
   16087          IRTemp oldV  = newTemp(Ity_I32);
   16088          IRTemp oldC  = newTemp(Ity_I32);
   16089          Bool   updC  = False;
   16090          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
   16091          assign(argL, getIRegT(rN));
   16092          assign(argR, mkU32(imm32));
   16093          assign(res,  binop(isTST ? Iop_And32 : Iop_Xor32,
   16094                             mkexpr(argL), mkexpr(argR)));
   16095          assign( oldV, mk_armg_calculate_flag_v() );
   16096          assign( oldC, updC
   16097                        ? mkU32((imm32 >> 31) & 1)
   16098                        : mk_armg_calculate_flag_c() );
   16099          setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT );
   16100          DIP("%s.w r%u, #%u\n", isTST ? "tst" : "teq", rN, imm32);
   16101          goto decode_success;
   16102       }
   16103    }
   16104 
   16105    /* -------------- (T3) SUB{S}.W Rd, Rn, #constT -------------- */
   16106    /* -------------- (T3) RSB{S}.W Rd, Rn, #constT -------------- */
   16107    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16108        && (INSN0(9,5) == BITS5(0,1,1,0,1) // SUB
   16109            || INSN0(9,5) == BITS5(0,1,1,1,0)) // RSB
   16110        && INSN1(15,15) == 0) {
   16111       Bool isRSB = INSN0(9,5) == BITS5(0,1,1,1,0);
   16112       UInt bS    = INSN0(4,4);
   16113       UInt rN    = INSN0(3,0);
   16114       UInt rD    = INSN1(11,8);
   16115       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16116       /* but allow "sub.w sp, sp, #constT" */
   16117       if (!valid && !isRSB && rN == 13 && rD == 13)
   16118          valid = True;
   16119       if (valid) {
   16120          IRTemp argL  = newTemp(Ity_I32);
   16121          IRTemp argR  = newTemp(Ity_I32);
   16122          IRTemp res   = newTemp(Ity_I32);
   16123          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16124          assign(argL, getIRegT(rN));
   16125          assign(argR, mkU32(imm32));
   16126          assign(res,  isRSB
   16127                       ? binop(Iop_Sub32, mkexpr(argR), mkexpr(argL))
   16128                       : binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
   16129          putIRegT(rD, mkexpr(res), condT);
   16130          if (bS == 1) {
   16131             if (isRSB)
   16132                setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
   16133             else
   16134                setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   16135          }
   16136          DIP("%s%s.w r%u, r%u, #%u\n",
   16137              isRSB ? "rsb" : "sub", bS == 1 ? "s" : "", rD, rN, imm32);
   16138          goto decode_success;
   16139       }
   16140    }
   16141 
   16142    /* -------------- (T4) SUBW Rd, Rn, #imm12 ------------------- */
   16143    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16144        && INSN0(9,4) == BITS6(1,0,1,0,1,0)
   16145        && INSN1(15,15) == 0) {
   16146       UInt rN = INSN0(3,0);
   16147       UInt rD = INSN1(11,8);
   16148       Bool valid = !isBadRegT(rN) && !isBadRegT(rD);
   16149       if (!valid && rN == 13 && rD == 13)
   16150          valid = True;
   16151       if (valid) {
   16152          IRTemp argL  = newTemp(Ity_I32);
   16153          IRTemp argR  = newTemp(Ity_I32);
   16154          IRTemp res   = newTemp(Ity_I32);
   16155          UInt imm12   = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
   16156          assign(argL, getIRegT(rN));
   16157          assign(argR, mkU32(imm12));
   16158          assign(res,  binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
   16159          putIRegT(rD, mkexpr(res), condT);
   16160          DIP("subw r%u, r%u, #%u\n", rD, rN, imm12);
   16161          goto decode_success;
   16162       }
   16163    }
   16164 
   16165    /* -------------- (T2) SUB{S}.W Rd, SP, #constT ------------------- */
   16166    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16167        && INSN0(9,5) == BITS5(0,1,1,0,1)
   16168        && INSN0(3,0) == BITS4(1,1,0,1)
   16169        && INSN1(15,15) == 0) {
   16170       UInt rN = 13; // SP
   16171       UInt rD = INSN1(11,8);
   16172       UInt bS    = INSN0(4,4);
   16173       Bool valid = !isBadRegT(rD);
   16174       if (valid) {
   16175          IRTemp argL  = newTemp(Ity_I32);
   16176          IRTemp argR  = newTemp(Ity_I32);
   16177          IRTemp res   = newTemp(Ity_I32);
   16178          UInt imm12   = (INSN0(10,10) << 11) | (INSN1(14,12) << 8) | INSN1(7,0);
   16179          assign(argL, getIRegT(rN));
   16180          assign(argR, mkU32(imm12));
   16181          assign(res,  binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)));
   16182          putIRegT(rD, mkexpr(res), condT);
   16183          if (bS == 1) {
   16184                setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   16185          }
   16186          DIP("sub%s.w r%u, sp, #%u\n",
   16187              bS == 1 ? "s" : "", rD, imm12);
   16188          goto decode_success;
   16189       }
   16190    }
   16191 
   16192    /* -------------- (T1) ADC{S}.W Rd, Rn, #constT -------------- */
   16193    /* -------------- (T1) SBC{S}.W Rd, Rn, #constT -------------- */
   16194    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16195        && (   INSN0(9,5) == BITS5(0,1,0,1,0)  // ADC
   16196            || INSN0(9,5) == BITS5(0,1,0,1,1)) // SBC
   16197        && INSN1(15,15) == 0) {
   16198       /* ADC:  Rd = Rn + constT + oldC */
   16199       /* SBC:  Rd = Rn - constT - (oldC ^ 1) */
   16200       UInt bS    = INSN0(4,4);
   16201       UInt rN    = INSN0(3,0);
   16202       UInt rD    = INSN1(11,8);
   16203       if (!isBadRegT(rN) && !isBadRegT(rD)) {
   16204          IRTemp argL  = newTemp(Ity_I32);
   16205          IRTemp argR  = newTemp(Ity_I32);
   16206          IRTemp res   = newTemp(Ity_I32);
   16207          IRTemp oldC  = newTemp(Ity_I32);
   16208          UInt   imm32 = thumbExpandImm_from_I0_I1(NULL, insn0, insn1);
   16209          assign(argL, getIRegT(rN));
   16210          assign(argR, mkU32(imm32));
   16211          assign(oldC, mk_armg_calculate_flag_c() );
   16212          HChar* nm  = "???";
   16213          switch (INSN0(9,5)) {
   16214             case BITS5(0,1,0,1,0): // ADC
   16215                nm = "adc";
   16216                assign(res,
   16217                       binop(Iop_Add32,
   16218                             binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
   16219                             mkexpr(oldC) ));
   16220                putIRegT(rD, mkexpr(res), condT);
   16221                if (bS)
   16222                   setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
   16223                                      argL, argR, oldC, condT );
   16224                break;
   16225             case BITS5(0,1,0,1,1): // SBC
   16226                nm = "sbc";
   16227                assign(res,
   16228                       binop(Iop_Sub32,
   16229                             binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
   16230                             binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   16231                putIRegT(rD, mkexpr(res), condT);
   16232                if (bS)
   16233                   setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   16234                                      argL, argR, oldC, condT );
   16235                break;
   16236             default:
   16237               vassert(0);
   16238          }
   16239          DIP("%s%s.w r%u, r%u, #%u\n",
   16240              nm, bS == 1 ? "s" : "", rD, rN, imm32);
   16241          goto decode_success;
   16242       }
   16243    }
   16244 
   16245    /* -------------- (T1) ORR{S}.W Rd, Rn, #constT -------------- */
   16246    /* -------------- (T1) AND{S}.W Rd, Rn, #constT -------------- */
   16247    /* -------------- (T1) BIC{S}.W Rd, Rn, #constT -------------- */
   16248    /* -------------- (T1) EOR{S}.W Rd, Rn, #constT -------------- */
   16249    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16250        && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // ORR
   16251            || INSN0(9,5) == BITS5(0,0,0,0,0)  // AND
   16252            || INSN0(9,5) == BITS5(0,0,0,0,1)  // BIC
   16253            || INSN0(9,5) == BITS5(0,0,1,0,0)  // EOR
   16254            || INSN0(9,5) == BITS5(0,0,0,1,1)) // ORN
   16255        && INSN1(15,15) == 0) {
   16256       UInt bS = INSN0(4,4);
   16257       UInt rN = INSN0(3,0);
   16258       UInt rD = INSN1(11,8);
   16259       if (!isBadRegT(rN) && !isBadRegT(rD)) {
   16260          Bool   notArgR = False;
   16261          IROp   op      = Iop_INVALID;
   16262          HChar* nm      = "???";
   16263          switch (INSN0(9,5)) {
   16264             case BITS5(0,0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
   16265             case BITS5(0,0,0,0,0): op = Iop_And32; nm = "and"; break;
   16266             case BITS5(0,0,0,0,1): op = Iop_And32; nm = "bic";
   16267                                    notArgR = True; break;
   16268             case BITS5(0,0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
   16269             case BITS5(0,0,0,1,1): op = Iop_Or32;  nm = "orn";
   16270                                    notArgR = True; break;
   16271             default: vassert(0);
   16272          }
   16273          IRTemp argL  = newTemp(Ity_I32);
   16274          IRTemp argR  = newTemp(Ity_I32);
   16275          IRTemp res   = newTemp(Ity_I32);
   16276          Bool   updC  = False;
   16277          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
   16278          assign(argL, getIRegT(rN));
   16279          assign(argR, mkU32(notArgR ? ~imm32 : imm32));
   16280          assign(res,  binop(op, mkexpr(argL), mkexpr(argR)));
   16281          putIRegT(rD, mkexpr(res), condT);
   16282          if (bS) {
   16283             IRTemp oldV = newTemp(Ity_I32);
   16284             IRTemp oldC = newTemp(Ity_I32);
   16285             assign( oldV, mk_armg_calculate_flag_v() );
   16286             assign( oldC, updC
   16287                           ? mkU32((imm32 >> 31) & 1)
   16288                           : mk_armg_calculate_flag_c() );
   16289             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16290                                condT );
   16291          }
   16292          DIP("%s%s.w r%u, r%u, #%u\n",
   16293              nm, bS == 1 ? "s" : "", rD, rN, imm32);
   16294          goto decode_success;
   16295       }
   16296    }
   16297 
   16298    /* ---------- (T3) ADD{S}.W Rd, Rn, Rm, {shift} ---------- */
   16299    /* ---------- (T3) SUB{S}.W Rd, Rn, Rm, {shift} ---------- */
   16300    /* ---------- (T3) RSB{S}.W Rd, Rn, Rm, {shift} ---------- */
   16301    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16302        && (   INSN0(8,5) == BITS4(1,0,0,0)  // add subopc
   16303            || INSN0(8,5) == BITS4(1,1,0,1)  // sub subopc
   16304            || INSN0(8,5) == BITS4(1,1,1,0)) // rsb subopc
   16305        && INSN1(15,15) == 0) {
   16306       UInt rN   = INSN0(3,0);
   16307       UInt rD   = INSN1(11,8);
   16308       UInt rM   = INSN1(3,0);
   16309       UInt bS   = INSN0(4,4);
   16310       UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   16311       UInt how  = INSN1(5,4);
   16312 
   16313       Bool valid = !isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM);
   16314       /* but allow "add.w reg, sp, reg   w/ no shift */
   16315       if (!valid && INSN0(8,5) == BITS4(1,0,0,0) // add
   16316           && rN == 13 && imm5 == 0 && how == 0) {
   16317          valid = True;
   16318       }
   16319       /* also allow "sub.w sp, sp, reg   w/ no shift */
   16320       if (!valid && INSN0(8,5) == BITS4(1,1,0,1) // add
   16321           && rD == 13 && rN == 13 && imm5 == 0 && how == 0) {
   16322          valid = True;
   16323       }
   16324       if (valid) {
   16325          Bool   swap = False;
   16326          IROp   op   = Iop_INVALID;
   16327          HChar* nm   = "???";
   16328          switch (INSN0(8,5)) {
   16329             case BITS4(1,0,0,0): op = Iop_Add32; nm = "add"; break;
   16330             case BITS4(1,1,0,1): op = Iop_Sub32; nm = "sub"; break;
   16331             case BITS4(1,1,1,0): op = Iop_Sub32; nm = "rsb";
   16332                                  swap = True; break;
   16333             default: vassert(0);
   16334          }
   16335 
   16336          IRTemp argL = newTemp(Ity_I32);
   16337          assign(argL, getIRegT(rN));
   16338 
   16339          IRTemp rMt = newTemp(Ity_I32);
   16340          assign(rMt, getIRegT(rM));
   16341 
   16342          IRTemp argR = newTemp(Ity_I32);
   16343          compute_result_and_C_after_shift_by_imm5(
   16344             dis_buf, &argR, NULL, rMt, how, imm5, rM
   16345          );
   16346 
   16347          IRTemp res = newTemp(Ity_I32);
   16348          assign(res, swap
   16349                      ? binop(op, mkexpr(argR), mkexpr(argL))
   16350                      : binop(op, mkexpr(argL), mkexpr(argR)));
   16351 
   16352          putIRegT(rD, mkexpr(res), condT);
   16353          if (bS) {
   16354             switch (op) {
   16355                case Iop_Add32:
   16356                   setFlags_D1_D2( ARMG_CC_OP_ADD, argL, argR, condT );
   16357                   break;
   16358                case Iop_Sub32:
   16359                   if (swap)
   16360                      setFlags_D1_D2( ARMG_CC_OP_SUB, argR, argL, condT );
   16361                   else
   16362                      setFlags_D1_D2( ARMG_CC_OP_SUB, argL, argR, condT );
   16363                   break;
   16364                default:
   16365                   vassert(0);
   16366             }
   16367          }
   16368 
   16369          DIP("%s%s.w r%u, r%u, %s\n",
   16370              nm, bS ? "s" : "", rD, rN, dis_buf);
   16371          goto decode_success;
   16372       }
   16373    }
   16374 
   16375    /* ---------- (T3) ADC{S}.W Rd, Rn, Rm, {shift} ---------- */
   16376    /* ---------- (T2) SBC{S}.W Rd, Rn, Rm, {shift} ---------- */
   16377    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16378        && (   INSN0(8,5) == BITS4(1,0,1,0)   // adc subopc
   16379            || INSN0(8,5) == BITS4(1,0,1,1))  // sbc subopc
   16380        && INSN1(15,15) == 0) {
   16381       /* ADC:  Rd = Rn + shifter_operand + oldC */
   16382       /* SBC:  Rd = Rn - shifter_operand - (oldC ^ 1) */
   16383       UInt rN = INSN0(3,0);
   16384       UInt rD = INSN1(11,8);
   16385       UInt rM = INSN1(3,0);
   16386       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   16387          UInt bS   = INSN0(4,4);
   16388          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   16389          UInt how  = INSN1(5,4);
   16390 
   16391          IRTemp argL = newTemp(Ity_I32);
   16392          assign(argL, getIRegT(rN));
   16393 
   16394          IRTemp rMt = newTemp(Ity_I32);
   16395          assign(rMt, getIRegT(rM));
   16396 
   16397          IRTemp oldC = newTemp(Ity_I32);
   16398          assign(oldC, mk_armg_calculate_flag_c());
   16399 
   16400          IRTemp argR = newTemp(Ity_I32);
   16401          compute_result_and_C_after_shift_by_imm5(
   16402             dis_buf, &argR, NULL, rMt, how, imm5, rM
   16403          );
   16404 
   16405          HChar* nm  = "???";
   16406          IRTemp res = newTemp(Ity_I32);
   16407          switch (INSN0(8,5)) {
   16408             case BITS4(1,0,1,0): // ADC
   16409                nm = "adc";
   16410                assign(res,
   16411                       binop(Iop_Add32,
   16412                             binop(Iop_Add32, mkexpr(argL), mkexpr(argR)),
   16413                             mkexpr(oldC) ));
   16414                putIRegT(rD, mkexpr(res), condT);
   16415                if (bS)
   16416                   setFlags_D1_D2_ND( ARMG_CC_OP_ADC,
   16417                                      argL, argR, oldC, condT );
   16418                break;
   16419             case BITS4(1,0,1,1): // SBC
   16420                nm = "sbc";
   16421                assign(res,
   16422                       binop(Iop_Sub32,
   16423                             binop(Iop_Sub32, mkexpr(argL), mkexpr(argR)),
   16424                             binop(Iop_Xor32, mkexpr(oldC), mkU32(1)) ));
   16425                putIRegT(rD, mkexpr(res), condT);
   16426                if (bS)
   16427                   setFlags_D1_D2_ND( ARMG_CC_OP_SBB,
   16428                                      argL, argR, oldC, condT );
   16429                break;
   16430             default:
   16431                vassert(0);
   16432          }
   16433 
   16434          DIP("%s%s.w r%u, r%u, %s\n",
   16435              nm, bS ? "s" : "", rD, rN, dis_buf);
   16436          goto decode_success;
   16437       }
   16438    }
   16439 
   16440    /* ---------- (T3) AND{S}.W Rd, Rn, Rm, {shift} ---------- */
   16441    /* ---------- (T3) ORR{S}.W Rd, Rn, Rm, {shift} ---------- */
   16442    /* ---------- (T3) EOR{S}.W Rd, Rn, Rm, {shift} ---------- */
   16443    /* ---------- (T3) BIC{S}.W Rd, Rn, Rm, {shift} ---------- */
   16444    /* ---------- (T1) ORN{S}.W Rd, Rn, Rm, {shift} ---------- */
   16445    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16446        && (   INSN0(8,5) == BITS4(0,0,0,0)  // and subopc
   16447            || INSN0(8,5) == BITS4(0,0,1,0)  // orr subopc
   16448            || INSN0(8,5) == BITS4(0,1,0,0)  // eor subopc
   16449            || INSN0(8,5) == BITS4(0,0,0,1)  // bic subopc
   16450            || INSN0(8,5) == BITS4(0,0,1,1)) // orn subopc
   16451        && INSN1(15,15) == 0) {
   16452       UInt rN = INSN0(3,0);
   16453       UInt rD = INSN1(11,8);
   16454       UInt rM = INSN1(3,0);
   16455       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   16456          Bool notArgR = False;
   16457          IROp op      = Iop_INVALID;
   16458          HChar* nm  = "???";
   16459          switch (INSN0(8,5)) {
   16460             case BITS4(0,0,0,0): op = Iop_And32; nm = "and"; break;
   16461             case BITS4(0,0,1,0): op = Iop_Or32;  nm = "orr"; break;
   16462             case BITS4(0,1,0,0): op = Iop_Xor32; nm = "eor"; break;
   16463             case BITS4(0,0,0,1): op = Iop_And32; nm = "bic";
   16464                                  notArgR = True; break;
   16465             case BITS4(0,0,1,1): op = Iop_Or32; nm = "orn";
   16466                                  notArgR = True; break;
   16467             default: vassert(0);
   16468          }
   16469          UInt bS   = INSN0(4,4);
   16470          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   16471          UInt how  = INSN1(5,4);
   16472 
   16473          IRTemp rNt = newTemp(Ity_I32);
   16474          assign(rNt, getIRegT(rN));
   16475 
   16476          IRTemp rMt = newTemp(Ity_I32);
   16477          assign(rMt, getIRegT(rM));
   16478 
   16479          IRTemp argR = newTemp(Ity_I32);
   16480          IRTemp oldC = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   16481 
   16482          compute_result_and_C_after_shift_by_imm5(
   16483             dis_buf, &argR, bS ? &oldC : NULL, rMt, how, imm5, rM
   16484          );
   16485 
   16486          IRTemp res = newTemp(Ity_I32);
   16487          if (notArgR) {
   16488             vassert(op == Iop_And32 || op == Iop_Or32);
   16489             assign(res, binop(op, mkexpr(rNt),
   16490                                   unop(Iop_Not32, mkexpr(argR))));
   16491          } else {
   16492             assign(res, binop(op, mkexpr(rNt), mkexpr(argR)));
   16493          }
   16494 
   16495          putIRegT(rD, mkexpr(res), condT);
   16496          if (bS) {
   16497             IRTemp oldV = newTemp(Ity_I32);
   16498             assign( oldV, mk_armg_calculate_flag_v() );
   16499             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16500                                condT );
   16501          }
   16502 
   16503          DIP("%s%s.w r%u, r%u, %s\n",
   16504              nm, bS ? "s" : "", rD, rN, dis_buf);
   16505          goto decode_success;
   16506       }
   16507    }
   16508 
   16509    /* -------------- (T?) LSL{S}.W Rd, Rn, Rm -------------- */
   16510    /* -------------- (T?) LSR{S}.W Rd, Rn, Rm -------------- */
   16511    /* -------------- (T?) ASR{S}.W Rd, Rn, Rm -------------- */
   16512    /* -------------- (T?) ROR{S}.W Rd, Rn, Rm -------------- */
   16513    if (INSN0(15,7) == BITS9(1,1,1,1,1,0,1,0,0)
   16514        && INSN1(15,12) == BITS4(1,1,1,1)
   16515        && INSN1(7,4) == BITS4(0,0,0,0)) {
   16516       UInt how = INSN0(6,5); // standard encoding
   16517       UInt rN  = INSN0(3,0);
   16518       UInt rD  = INSN1(11,8);
   16519       UInt rM  = INSN1(3,0);
   16520       UInt bS  = INSN0(4,4);
   16521       Bool valid = !isBadRegT(rN) && !isBadRegT(rM) && !isBadRegT(rD);
   16522       if (how == 3) valid = False; //ATC
   16523       if (valid) {
   16524          IRTemp rNt    = newTemp(Ity_I32);
   16525          IRTemp rMt    = newTemp(Ity_I32);
   16526          IRTemp res    = newTemp(Ity_I32);
   16527          IRTemp oldC   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   16528          IRTemp oldV   = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   16529          HChar* nms[4] = { "lsl", "lsr", "asr", "ror" };
   16530          HChar* nm     = nms[how];
   16531          assign(rNt, getIRegT(rN));
   16532          assign(rMt, getIRegT(rM));
   16533          compute_result_and_C_after_shift_by_reg(
   16534             dis_buf, &res, bS ? &oldC : NULL,
   16535             rNt, how, rMt, rN, rM
   16536          );
   16537          if (bS)
   16538             assign(oldV, mk_armg_calculate_flag_v());
   16539          putIRegT(rD, mkexpr(res), condT);
   16540          if (bS) {
   16541             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16542                                condT );
   16543          }
   16544          DIP("%s%s.w r%u, r%u, r%u\n",
   16545              nm, bS ? "s" : "", rD, rN, rM);
   16546          goto decode_success;
   16547       }
   16548    }
   16549 
   16550    /* ------------ (T?) MOV{S}.W Rd, Rn, {shift} ------------ */
   16551    /* ------------ (T?) MVN{S}.W Rd, Rn, {shift} ------------ */
   16552    if ((INSN0(15,0) & 0xFFCF) == 0xEA4F
   16553        && INSN1(15,15) == 0) {
   16554       UInt rD = INSN1(11,8);
   16555       UInt rN = INSN1(3,0);
   16556       if (!isBadRegT(rD) && !isBadRegT(rN)) {
   16557          UInt bS    = INSN0(4,4);
   16558          UInt isMVN = INSN0(5,5);
   16559          UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
   16560          UInt how   = INSN1(5,4);
   16561 
   16562          IRTemp rNt = newTemp(Ity_I32);
   16563          assign(rNt, getIRegT(rN));
   16564 
   16565          IRTemp oldRn = newTemp(Ity_I32);
   16566          IRTemp oldC  = bS ? newTemp(Ity_I32) : IRTemp_INVALID;
   16567          compute_result_and_C_after_shift_by_imm5(
   16568             dis_buf, &oldRn, bS ? &oldC : NULL, rNt, how, imm5, rN
   16569          );
   16570 
   16571          IRTemp res = newTemp(Ity_I32);
   16572          assign(res, isMVN ? unop(Iop_Not32, mkexpr(oldRn))
   16573                            : mkexpr(oldRn));
   16574 
   16575          putIRegT(rD, mkexpr(res), condT);
   16576          if (bS) {
   16577             IRTemp oldV = newTemp(Ity_I32);
   16578             assign( oldV, mk_armg_calculate_flag_v() );
   16579             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV, condT);
   16580          }
   16581          DIP("%s%s.w r%u, %s\n",
   16582              isMVN ? "mvn" : "mov", bS ? "s" : "", rD, dis_buf);
   16583          goto decode_success;
   16584       }
   16585    }
   16586 
   16587    /* -------------- (T?) TST.W Rn, Rm, {shift} -------------- */
   16588    /* -------------- (T?) TEQ.W Rn, Rm, {shift} -------------- */
   16589    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16590        && (   INSN0(8,4) == BITS5(0,0,0,0,1)  // TST
   16591            || INSN0(8,4) == BITS5(0,1,0,0,1)) // TEQ
   16592        && INSN1(15,15) == 0
   16593        && INSN1(11,8) == BITS4(1,1,1,1)) {
   16594       UInt rN = INSN0(3,0);
   16595       UInt rM = INSN1(3,0);
   16596       if (!isBadRegT(rN) && !isBadRegT(rM)) {
   16597          Bool isTST = INSN0(8,4) == BITS5(0,0,0,0,1);
   16598 
   16599          UInt how  = INSN1(5,4);
   16600          UInt imm5 = (INSN1(14,12) << 2) | INSN1(7,6);
   16601 
   16602          IRTemp argL = newTemp(Ity_I32);
   16603          assign(argL, getIRegT(rN));
   16604 
   16605          IRTemp rMt = newTemp(Ity_I32);
   16606          assign(rMt, getIRegT(rM));
   16607 
   16608          IRTemp argR = newTemp(Ity_I32);
   16609          IRTemp oldC = newTemp(Ity_I32);
   16610          compute_result_and_C_after_shift_by_imm5(
   16611             dis_buf, &argR, &oldC, rMt, how, imm5, rM
   16612          );
   16613 
   16614          IRTemp oldV = newTemp(Ity_I32);
   16615          assign( oldV, mk_armg_calculate_flag_v() );
   16616 
   16617          IRTemp res = newTemp(Ity_I32);
   16618          assign(res, binop(isTST ? Iop_And32 : Iop_Xor32,
   16619                            mkexpr(argL), mkexpr(argR)));
   16620 
   16621          setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16622                             condT );
   16623          DIP("%s.w r%u, %s\n", isTST ? "tst" : "teq", rN, dis_buf);
   16624          goto decode_success;
   16625       }
   16626    }
   16627 
   16628    /* -------------- (T3) CMP.W Rn, Rm, {shift} -------------- */
   16629    /* -------------- (T2) CMN.W Rn, Rm, {shift} -------------- */
   16630    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,1)
   16631        && (   INSN0(8,4) == BITS5(1,1,0,1,1)  // CMP
   16632            || INSN0(8,4) == BITS5(1,0,0,0,1)) // CMN
   16633        && INSN1(15,15) == 0
   16634        && INSN1(11,8) == BITS4(1,1,1,1)) {
   16635       UInt rN = INSN0(3,0);
   16636       UInt rM = INSN1(3,0);
   16637       if (!isBadRegT(rN) && !isBadRegT(rM)) {
   16638          Bool isCMN = INSN0(8,4) == BITS5(1,0,0,0,1);
   16639          UInt how   = INSN1(5,4);
   16640          UInt imm5  = (INSN1(14,12) << 2) | INSN1(7,6);
   16641 
   16642          IRTemp argL = newTemp(Ity_I32);
   16643          assign(argL, getIRegT(rN));
   16644 
   16645          IRTemp rMt = newTemp(Ity_I32);
   16646          assign(rMt, getIRegT(rM));
   16647 
   16648          IRTemp argR = newTemp(Ity_I32);
   16649          compute_result_and_C_after_shift_by_imm5(
   16650             dis_buf, &argR, NULL, rMt, how, imm5, rM
   16651          );
   16652 
   16653          setFlags_D1_D2( isCMN ? ARMG_CC_OP_ADD : ARMG_CC_OP_SUB,
   16654                          argL, argR, condT );
   16655 
   16656          DIP("%s.w r%u, %s\n", isCMN ? "cmn" : "cmp", rN, dis_buf);
   16657          goto decode_success;
   16658       }
   16659    }
   16660 
   16661    /* -------------- (T2) MOV{S}.W Rd, #constT -------------- */
   16662    /* -------------- (T2) MVN{S}.W Rd, #constT -------------- */
   16663    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16664        && (   INSN0(9,5) == BITS5(0,0,0,1,0)  // MOV
   16665            || INSN0(9,5) == BITS5(0,0,0,1,1)) // MVN
   16666        && INSN0(3,0) == BITS4(1,1,1,1)
   16667        && INSN1(15,15) == 0) {
   16668       UInt rD = INSN1(11,8);
   16669       if (!isBadRegT(rD)) {
   16670          Bool   updC  = False;
   16671          UInt   bS    = INSN0(4,4);
   16672          Bool   isMVN = INSN0(5,5) == 1;
   16673          UInt   imm32 = thumbExpandImm_from_I0_I1(&updC, insn0, insn1);
   16674          IRTemp res   = newTemp(Ity_I32);
   16675          assign(res, mkU32(isMVN ? ~imm32 : imm32));
   16676          putIRegT(rD, mkexpr(res), condT);
   16677          if (bS) {
   16678             IRTemp oldV = newTemp(Ity_I32);
   16679             IRTemp oldC = newTemp(Ity_I32);
   16680             assign( oldV, mk_armg_calculate_flag_v() );
   16681             assign( oldC, updC
   16682                           ? mkU32((imm32 >> 31) & 1)
   16683                           : mk_armg_calculate_flag_c() );
   16684             setFlags_D1_D2_ND( ARMG_CC_OP_LOGIC, res, oldC, oldV,
   16685                                condT );
   16686          }
   16687          DIP("%s%s.w r%u, #%u\n",
   16688              isMVN ? "mvn" : "mov", bS ? "s" : "", rD, imm32);
   16689          goto decode_success;
   16690       }
   16691    }
   16692 
   16693    /* -------------- (T3) MOVW Rd, #imm16 -------------- */
   16694    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16695        && INSN0(9,4) == BITS6(1,0,0,1,0,0)
   16696        && INSN1(15,15) == 0) {
   16697       UInt rD = INSN1(11,8);
   16698       if (!isBadRegT(rD)) {
   16699          UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
   16700                       | (INSN1(14,12) << 8) | INSN1(7,0);
   16701          putIRegT(rD, mkU32(imm16), condT);
   16702          DIP("movw r%u, #%u\n", rD, imm16);
   16703          goto decode_success;
   16704       }
   16705    }
   16706 
   16707    /* ---------------- MOVT Rd, #imm16 ---------------- */
   16708    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   16709        && INSN0(9,4) == BITS6(1,0,1,1,0,0)
   16710        && INSN1(15,15) == 0) {
   16711       UInt rD = INSN1(11,8);
   16712       if (!isBadRegT(rD)) {
   16713          UInt imm16 = (INSN0(3,0) << 12) | (INSN0(10,10) << 11)
   16714                       | (INSN1(14,12) << 8) | INSN1(7,0);
   16715          IRTemp res = newTemp(Ity_I32);
   16716          assign(res,
   16717                 binop(Iop_Or32,
   16718                       binop(Iop_And32, getIRegT(rD), mkU32(0xFFFF)),
   16719                       mkU32(imm16 << 16)));
   16720          putIRegT(rD, mkexpr(res), condT);
   16721          DIP("movt r%u, #%u\n", rD, imm16);
   16722          goto decode_success;
   16723       }
   16724    }
   16725 
   16726    /* ---------------- LD/ST reg+/-#imm8 ---------------- */
   16727    /* Loads and stores of the form:
   16728          op  Rt, [Rn, #-imm8]      or
   16729          op  Rt, [Rn], #+/-imm8    or
   16730          op  Rt, [Rn, #+/-imm8]!
   16731       where op is one of
   16732          ldrb ldrh ldr  ldrsb ldrsh
   16733          strb strh str
   16734    */
   16735    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0) && INSN1(11,11) == 1) {
   16736       Bool   valid  = True;
   16737       Bool   syned  = False;
   16738       Bool   isST   = False;
   16739       IRType ty     = Ity_I8;
   16740       HChar* nm     = "???";
   16741 
   16742       switch (INSN0(8,4)) {
   16743          case BITS5(0,0,0,0,0):   // strb
   16744             nm = "strb"; isST = True; break;
   16745          case BITS5(0,0,0,0,1):   // ldrb
   16746             nm = "ldrb"; break;
   16747          case BITS5(1,0,0,0,1):   // ldrsb
   16748             nm = "ldrsb"; syned = True; break;
   16749          case BITS5(0,0,0,1,0):   // strh
   16750             nm = "strh"; ty = Ity_I16; isST = True; break;
   16751          case BITS5(0,0,0,1,1):   // ldrh
   16752             nm = "ldrh"; ty = Ity_I16; break;
   16753          case BITS5(1,0,0,1,1):   // ldrsh
   16754             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
   16755          case BITS5(0,0,1,0,0):   // str
   16756             nm = "str"; ty = Ity_I32; isST = True; break;
   16757          case BITS5(0,0,1,0,1):
   16758             nm = "ldr"; ty = Ity_I32; break;  // ldr
   16759          default:
   16760             valid = False; break;
   16761       }
   16762 
   16763       UInt rN      = INSN0(3,0);
   16764       UInt rT      = INSN1(15,12);
   16765       UInt bP      = INSN1(10,10);
   16766       UInt bU      = INSN1(9,9);
   16767       UInt bW      = INSN1(8,8);
   16768       UInt imm8    = INSN1(7,0);
   16769       Bool loadsPC = False;
   16770 
   16771       if (valid) {
   16772          if (bP == 1 && bU == 1 && bW == 0)
   16773             valid = False;
   16774          if (bP == 0 && bW == 0)
   16775             valid = False;
   16776          if (rN == 15)
   16777             valid = False;
   16778          if (bW == 1 && rN == rT)
   16779             valid = False;
   16780          if (ty == Ity_I8 || ty == Ity_I16) {
   16781             if (isBadRegT(rT))
   16782                valid = False;
   16783          } else {
   16784             /* ty == Ity_I32 */
   16785             if (isST && rT == 15)
   16786                valid = False;
   16787             if (!isST && rT == 15)
   16788                loadsPC = True;
   16789          }
   16790       }
   16791 
   16792       if (valid) {
   16793          // if it's a branch, it can't happen in the middle of an IT block
   16794          if (loadsPC)
   16795             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   16796          // go uncond
   16797          mk_skip_over_T32_if_cond_is_false(condT);
   16798          condT = IRTemp_INVALID;
   16799          // now uncond
   16800 
   16801          IRTemp preAddr = newTemp(Ity_I32);
   16802          assign(preAddr, getIRegT(rN));
   16803 
   16804          IRTemp postAddr = newTemp(Ity_I32);
   16805          assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   16806                                 mkexpr(preAddr), mkU32(imm8)));
   16807 
   16808          IRTemp transAddr = bP == 1 ? postAddr : preAddr;
   16809 
   16810          if (isST) {
   16811 
   16812              /* Store.  If necessary, update the base register before
   16813                 the store itself, so that the common idiom of "str rX,
   16814                 [sp, #-4]!" (store rX at sp-4, then do new sp = sp-4,
   16815                 a.k.a "push rX") doesn't cause Memcheck to complain
   16816                 that the access is below the stack pointer.  Also, not
   16817                 updating sp before the store confuses Valgrind's
   16818                 dynamic stack-extending logic.  So do it before the
   16819                 store.  Hence we need to snarf the store data before
   16820                 doing the basereg update. */
   16821 
   16822             /* get hold of the data to be stored */
   16823             IRTemp oldRt = newTemp(Ity_I32);
   16824             assign(oldRt, getIRegT(rT));
   16825 
   16826             /* Update Rn if necessary. */
   16827             if (bW == 1) {
   16828                vassert(rN != rT); // assured by validity check above
   16829                putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
   16830             }
   16831 
   16832             /* generate the transfer */
   16833             switch (ty) {
   16834                case Ity_I8:
   16835                   storeLE(mkexpr(transAddr),
   16836                                  unop(Iop_32to8, mkexpr(oldRt)));
   16837                   break;
   16838                case Ity_I16:
   16839                   storeLE(mkexpr(transAddr),
   16840                           unop(Iop_32to16, mkexpr(oldRt)));
   16841                   break;
   16842               case Ity_I32:
   16843                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
   16844                   break;
   16845               default:
   16846                  vassert(0);
   16847             }
   16848 
   16849          } else {
   16850 
   16851             /* Load. */
   16852 
   16853             /* generate the transfer */
   16854             IRTemp newRt = newTemp(Ity_I32);
   16855             IROp   widen = Iop_INVALID;
   16856             switch (ty) {
   16857                case Ity_I8:
   16858                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
   16859                case Ity_I16:
   16860                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
   16861                case Ity_I32:
   16862                   break;
   16863                default:
   16864                   vassert(0);
   16865             }
   16866             if (widen == Iop_INVALID) {
   16867                assign(newRt, loadLE(ty, mkexpr(transAddr)));
   16868             } else {
   16869                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
   16870             }
   16871             if (loadsPC) {
   16872                vassert(rT == 15);
   16873                llPutIReg(rT, mkexpr(newRt));
   16874             } else {
   16875                putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
   16876             }
   16877 
   16878             if (loadsPC) {
   16879                /* Presumably this is an interworking branch. */
   16880                irsb->next = mkexpr(newRt);
   16881                irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
   16882                dres.whatNext  = Dis_StopHere;
   16883             }
   16884 
   16885             /* Update Rn if necessary. */
   16886             if (bW == 1) {
   16887                vassert(rN != rT); // assured by validity check above
   16888                putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
   16889             }
   16890          }
   16891 
   16892          if (bP == 1 && bW == 0) {
   16893             DIP("%s.w r%u, [r%u, #%c%u]\n",
   16894                 nm, rT, rN, bU ? '+' : '-', imm8);
   16895          }
   16896          else if (bP == 1 && bW == 1) {
   16897             DIP("%s.w r%u, [r%u, #%c%u]!\n",
   16898                 nm, rT, rN, bU ? '+' : '-', imm8);
   16899          }
   16900          else {
   16901             vassert(bP == 0 && bW == 1);
   16902             DIP("%s.w r%u, [r%u], #%c%u\n",
   16903                 nm, rT, rN, bU ? '+' : '-', imm8);
   16904          }
   16905 
   16906          goto decode_success;
   16907       }
   16908    }
   16909 
   16910    /* ------------- LD/ST reg+(reg<<imm2) ------------- */
   16911    /* Loads and stores of the form:
   16912          op  Rt, [Rn, Rm, LSL #imm8]
   16913       where op is one of
   16914          ldrb ldrh ldr  ldrsb ldrsh
   16915          strb strh str
   16916    */
   16917    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)
   16918        && INSN1(11,6) == BITS6(0,0,0,0,0,0)) {
   16919       Bool   valid  = True;
   16920       Bool   syned  = False;
   16921       Bool   isST   = False;
   16922       IRType ty     = Ity_I8;
   16923       HChar* nm     = "???";
   16924 
   16925       switch (INSN0(8,4)) {
   16926          case BITS5(0,0,0,0,0):   // strb
   16927             nm = "strb"; isST = True; break;
   16928          case BITS5(0,0,0,0,1):   // ldrb
   16929             nm = "ldrb"; break;
   16930          case BITS5(1,0,0,0,1):   // ldrsb
   16931             nm = "ldrsb"; syned = True; break;
   16932          case BITS5(0,0,0,1,0):   // strh
   16933             nm = "strh"; ty = Ity_I16; isST = True; break;
   16934          case BITS5(0,0,0,1,1):   // ldrh
   16935             nm = "ldrh"; ty = Ity_I16; break;
   16936          case BITS5(1,0,0,1,1):   // ldrsh
   16937             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
   16938          case BITS5(0,0,1,0,0):   // str
   16939             nm = "str"; ty = Ity_I32; isST = True; break;
   16940          case BITS5(0,0,1,0,1):
   16941             nm = "ldr"; ty = Ity_I32; break;  // ldr
   16942          default:
   16943             valid = False; break;
   16944       }
   16945 
   16946       UInt rN      = INSN0(3,0);
   16947       UInt rM      = INSN1(3,0);
   16948       UInt rT      = INSN1(15,12);
   16949       UInt imm2    = INSN1(5,4);
   16950       Bool loadsPC = False;
   16951 
   16952       if (ty == Ity_I8 || ty == Ity_I16) {
   16953          /* all 8- and 16-bit load and store cases have the
   16954             same exclusion set. */
   16955          if (rN == 15 || isBadRegT(rT) || isBadRegT(rM))
   16956             valid = False;
   16957       } else {
   16958          vassert(ty == Ity_I32);
   16959          if (rN == 15 || isBadRegT(rM))
   16960             valid = False;
   16961          if (isST && rT == 15)
   16962             valid = False;
   16963          /* If it is a load and rT is 15, that's only allowable if we
   16964             not in an IT block, or are the last in it.  Need to insert
   16965             a dynamic check for that. */
   16966          if (!isST && rT == 15)
   16967             loadsPC = True;
   16968       }
   16969 
   16970       if (valid) {
   16971          // if it's a branch, it can't happen in the middle of an IT block
   16972          if (loadsPC)
   16973             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   16974          // go uncond
   16975          mk_skip_over_T32_if_cond_is_false(condT);
   16976          condT = IRTemp_INVALID;
   16977          // now uncond
   16978 
   16979          IRTemp transAddr = newTemp(Ity_I32);
   16980          assign(transAddr,
   16981                 binop( Iop_Add32,
   16982                        getIRegT(rN),
   16983                        binop(Iop_Shl32, getIRegT(rM), mkU8(imm2)) ));
   16984 
   16985          if (isST) {
   16986             IRTemp oldRt = newTemp(Ity_I32);
   16987             assign(oldRt, getIRegT(rT));
   16988             switch (ty) {
   16989                case Ity_I8:
   16990                   storeLE(mkexpr(transAddr),
   16991                                  unop(Iop_32to8, mkexpr(oldRt)));
   16992                   break;
   16993                case Ity_I16:
   16994                   storeLE(mkexpr(transAddr),
   16995                           unop(Iop_32to16, mkexpr(oldRt)));
   16996                   break;
   16997               case Ity_I32:
   16998                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
   16999                   break;
   17000               default:
   17001                  vassert(0);
   17002             }
   17003          } else {
   17004             IRTemp newRt = newTemp(Ity_I32);
   17005             IROp   widen = Iop_INVALID;
   17006             switch (ty) {
   17007                case Ity_I8:
   17008                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
   17009                case Ity_I16:
   17010                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
   17011                case Ity_I32:
   17012                   break;
   17013                default:
   17014                   vassert(0);
   17015             }
   17016             if (widen == Iop_INVALID) {
   17017                assign(newRt, loadLE(ty, mkexpr(transAddr)));
   17018             } else {
   17019                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
   17020             }
   17021 
   17022             /* If we're loading the PC, putIRegT will assert.  So go
   17023                direct via llPutIReg.  In all other cases use putIRegT
   17024                as it is safer (although could simply use llPutIReg for
   17025                _all_ cases here.) */
   17026             if (loadsPC) {
   17027                vassert(rT == 15);
   17028                llPutIReg(rT, mkexpr(newRt));
   17029             } else {
   17030                putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
   17031             }
   17032 
   17033             if (loadsPC) {
   17034                /* Presumably this is an interworking branch. */
   17035                irsb->next = mkexpr(newRt);
   17036                irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
   17037                dres.whatNext  = Dis_StopHere;
   17038             }
   17039          }
   17040 
   17041          DIP("%s.w r%u, [r%u, r%u, LSL #%u]\n",
   17042              nm, rT, rN, rM, imm2);
   17043 
   17044          goto decode_success;
   17045       }
   17046    }
   17047 
   17048    /* --------------- LD/ST reg+imm12 --------------- */
   17049    /* Loads and stores of the form:
   17050          op  Rt, [Rn, +#imm12]
   17051       where op is one of
   17052          ldrb ldrh ldr  ldrsb ldrsh
   17053          strb strh str
   17054    */
   17055    if (INSN0(15,9) == BITS7(1,1,1,1,1,0,0)) {
   17056       Bool   valid  = True;
   17057       Bool   syned  = False;
   17058       Bool   isST   = False;
   17059       IRType ty     = Ity_I8;
   17060       HChar* nm     = "???";
   17061 
   17062       switch (INSN0(8,4)) {
   17063          case BITS5(0,1,0,0,0):   // strb
   17064             nm = "strb"; isST = True; break;
   17065          case BITS5(0,1,0,0,1):   // ldrb
   17066             nm = "ldrb"; break;
   17067          case BITS5(1,1,0,0,1):   // ldrsb
   17068             nm = "ldrsb"; syned = True; break;
   17069          case BITS5(0,1,0,1,0):   // strh
   17070             nm = "strh"; ty = Ity_I16; isST = True; break;
   17071          case BITS5(0,1,0,1,1):   // ldrh
   17072             nm = "ldrh"; ty = Ity_I16; break;
   17073          case BITS5(1,1,0,1,1):   // ldrsh
   17074             nm = "ldrsh"; ty = Ity_I16; syned = True; break;
   17075          case BITS5(0,1,1,0,0):   // str
   17076             nm = "str"; ty = Ity_I32; isST = True; break;
   17077          case BITS5(0,1,1,0,1):
   17078             nm = "ldr"; ty = Ity_I32; break;  // ldr
   17079          default:
   17080             valid = False; break;
   17081       }
   17082 
   17083       UInt rN      = INSN0(3,0);
   17084       UInt rT      = INSN1(15,12);
   17085       UInt imm12   = INSN1(11,0);
   17086       Bool loadsPC = False;
   17087 
   17088       if (ty == Ity_I8 || ty == Ity_I16) {
   17089          /* all 8- and 16-bit load and store cases have the
   17090             same exclusion set. */
   17091          if (rN == 15 || isBadRegT(rT))
   17092             valid = False;
   17093       } else {
   17094          vassert(ty == Ity_I32);
   17095          if (isST) {
   17096             if (rN == 15 || rT == 15)
   17097                valid = False;
   17098          } else {
   17099             /* For a 32-bit load, rT == 15 is only allowable if we not
   17100                in an IT block, or are the last in it.  Need to insert
   17101                a dynamic check for that.  Also, in this particular
   17102                case, rN == 15 is allowable.  In this case however, the
   17103                value obtained for rN is (apparently)
   17104                "word-align(address of current insn + 4)". */
   17105             if (rT == 15)
   17106                loadsPC = True;
   17107          }
   17108       }
   17109 
   17110       if (valid) {
   17111          // if it's a branch, it can't happen in the middle of an IT block
   17112          if (loadsPC)
   17113             gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   17114          // go uncond
   17115          mk_skip_over_T32_if_cond_is_false(condT);
   17116          condT = IRTemp_INVALID;
   17117          // now uncond
   17118 
   17119          IRTemp rNt = newTemp(Ity_I32);
   17120          if (rN == 15) {
   17121             vassert(ty == Ity_I32 && !isST);
   17122             assign(rNt, binop(Iop_And32, getIRegT(rN), mkU32(~3)));
   17123          } else {
   17124             assign(rNt, getIRegT(rN));
   17125          }
   17126 
   17127          IRTemp transAddr = newTemp(Ity_I32);
   17128          assign(transAddr,
   17129                 binop( Iop_Add32, mkexpr(rNt), mkU32(imm12) ));
   17130 
   17131          if (isST) {
   17132             IRTemp oldRt = newTemp(Ity_I32);
   17133             assign(oldRt, getIRegT(rT));
   17134             switch (ty) {
   17135                case Ity_I8:
   17136                   storeLE(mkexpr(transAddr),
   17137                                  unop(Iop_32to8, mkexpr(oldRt)));
   17138                   break;
   17139                case Ity_I16:
   17140                   storeLE(mkexpr(transAddr),
   17141                           unop(Iop_32to16, mkexpr(oldRt)));
   17142                   break;
   17143               case Ity_I32:
   17144                   storeLE(mkexpr(transAddr), mkexpr(oldRt));
   17145                   break;
   17146               default:
   17147                  vassert(0);
   17148             }
   17149          } else {
   17150             IRTemp newRt = newTemp(Ity_I32);
   17151             IROp   widen = Iop_INVALID;
   17152             switch (ty) {
   17153                case Ity_I8:
   17154                   widen = syned ? Iop_8Sto32 : Iop_8Uto32; break;
   17155                case Ity_I16:
   17156                   widen = syned ? Iop_16Sto32 : Iop_16Uto32; break;
   17157                case Ity_I32:
   17158                   break;
   17159                default:
   17160                   vassert(0);
   17161             }
   17162             if (widen == Iop_INVALID) {
   17163                assign(newRt, loadLE(ty, mkexpr(transAddr)));
   17164             } else {
   17165                assign(newRt, unop(widen, loadLE(ty, mkexpr(transAddr))));
   17166             }
   17167             putIRegT(rT, mkexpr(newRt), IRTemp_INVALID);
   17168 
   17169             if (loadsPC) {
   17170                /* Presumably this is an interworking branch. */
   17171                irsb->next = mkexpr(newRt);
   17172                irsb->jumpkind = Ijk_Boring;  /* or _Ret ? */
   17173                dres.whatNext  = Dis_StopHere;
   17174             }
   17175          }
   17176 
   17177          DIP("%s.w r%u, [r%u, +#%u]\n", nm, rT, rN, imm12);
   17178 
   17179          goto decode_success;
   17180       }
   17181    }
   17182 
   17183    /* -------------- LDRD/STRD reg+/-#imm8 -------------- */
   17184    /* Doubleword loads and stores of the form:
   17185          ldrd/strd  Rt, Rt2, [Rn, #-imm8]      or
   17186          ldrd/strd  Rt, Rt2, [Rn], #+/-imm8    or
   17187          ldrd/strd  Rt, Rt2, [Rn, #+/-imm8]!
   17188    */
   17189    if (INSN0(15,9) == BITS7(1,1,1,0,1,0,0) && INSN0(6,6) == 1) {
   17190       UInt bP   = INSN0(8,8);
   17191       UInt bU   = INSN0(7,7);
   17192       UInt bW   = INSN0(5,5);
   17193       UInt bL   = INSN0(4,4);  // 1: load  0: store
   17194       UInt rN   = INSN0(3,0);
   17195       UInt rT   = INSN1(15,12);
   17196       UInt rT2  = INSN1(11,8);
   17197       UInt imm8 = INSN1(7,0);
   17198 
   17199       Bool valid = True;
   17200       if (bP == 0 && bW == 0)                 valid = False;
   17201       if (bW == 1 && (rN == rT || rN == rT2)) valid = False;
   17202       if (isBadRegT(rT) || isBadRegT(rT2))    valid = False;
   17203       if (rN == 15)                           valid = False;
   17204       if (bL == 1 && rT == rT2)               valid = False;
   17205 
   17206       if (valid) {
   17207          // go uncond
   17208          mk_skip_over_T32_if_cond_is_false(condT);
   17209          condT = IRTemp_INVALID;
   17210          // now uncond
   17211 
   17212          IRTemp preAddr = newTemp(Ity_I32);
   17213          assign(preAddr, getIRegT(rN));
   17214 
   17215          IRTemp postAddr = newTemp(Ity_I32);
   17216          assign(postAddr, binop(bU == 1 ? Iop_Add32 : Iop_Sub32,
   17217                                 mkexpr(preAddr), mkU32(imm8 << 2)));
   17218 
   17219          IRTemp transAddr = bP == 1 ? postAddr : preAddr;
   17220 
   17221          if (bL == 0) {
   17222             IRTemp oldRt  = newTemp(Ity_I32);
   17223             IRTemp oldRt2 = newTemp(Ity_I32);
   17224             assign(oldRt,  getIRegT(rT));
   17225             assign(oldRt2, getIRegT(rT2));
   17226             storeLE(mkexpr(transAddr),
   17227                     mkexpr(oldRt));
   17228             storeLE(binop(Iop_Add32, mkexpr(transAddr), mkU32(4)),
   17229                     mkexpr(oldRt2));
   17230          } else {
   17231             IRTemp newRt  = newTemp(Ity_I32);
   17232             IRTemp newRt2 = newTemp(Ity_I32);
   17233             assign(newRt,
   17234                    loadLE(Ity_I32,
   17235                           mkexpr(transAddr)));
   17236             assign(newRt2,
   17237                    loadLE(Ity_I32,
   17238                           binop(Iop_Add32, mkexpr(transAddr), mkU32(4))));
   17239             putIRegT(rT,  mkexpr(newRt), IRTemp_INVALID);
   17240             putIRegT(rT2, mkexpr(newRt2), IRTemp_INVALID);
   17241          }
   17242 
   17243          if (bW == 1) {
   17244             putIRegT(rN, mkexpr(postAddr), IRTemp_INVALID);
   17245          }
   17246 
   17247          HChar* nm = bL ? "ldrd" : "strd";
   17248 
   17249          if (bP == 1 && bW == 0) {
   17250             DIP("%s.w r%u, r%u, [r%u, #%c%u]\n",
   17251                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
   17252          }
   17253          else if (bP == 1 && bW == 1) {
   17254             DIP("%s.w r%u, r%u, [r%u, #%c%u]!\n",
   17255                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
   17256          }
   17257          else {
   17258             vassert(bP == 0 && bW == 1);
   17259             DIP("%s.w r%u, r%u, [r%u], #%c%u\n",
   17260                 nm, rT, rT2, rN, bU ? '+' : '-', imm8 << 2);
   17261          }
   17262 
   17263          goto decode_success;
   17264       }
   17265    }
   17266 
   17267    /* -------------- (T3) Bcond.W label -------------- */
   17268    /* This variant carries its own condition, so can't be part of an
   17269       IT block ... */
   17270    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   17271        && INSN1(15,14) == BITS2(1,0)
   17272        && INSN1(12,12) == 0) {
   17273       UInt cond = INSN0(9,6);
   17274       if (cond != ARMCondAL && cond != ARMCondNV) {
   17275          Int simm21
   17276             =   (INSN0(10,10) << (1 + 1 + 6 + 11 + 1))
   17277               | (INSN1(11,11) << (1 + 6 + 11 + 1))
   17278               | (INSN1(13,13) << (6 + 11 + 1))
   17279               | (INSN0(5,0)   << (11 + 1))
   17280               | (INSN1(10,0)  << 1);
   17281          simm21 = (simm21 << 11) >> 11;
   17282 
   17283          vassert(0 == (guest_R15_curr_instr_notENC & 1));
   17284          UInt dst = simm21 + guest_R15_curr_instr_notENC + 4;
   17285 
   17286          /* Not allowed in an IT block; SIGILL if so. */
   17287          gen_SIGILL_T_if_in_ITBlock(old_itstate, new_itstate);
   17288 
   17289          IRTemp kondT = newTemp(Ity_I32);
   17290          assign( kondT, mk_armg_calculate_condition(cond) );
   17291          stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(kondT)),
   17292                             Ijk_Boring,
   17293                             IRConst_U32(dst | 1/*CPSR.T*/) ));
   17294          irsb->next = mkU32( (guest_R15_curr_instr_notENC + 4)
   17295                              | 1 /*CPSR.T*/ );
   17296          irsb->jumpkind = Ijk_Boring;
   17297          dres.whatNext  = Dis_StopHere;
   17298          DIP("b%s.w 0x%x\n", nCC(cond), dst);
   17299          goto decode_success;
   17300       }
   17301    }
   17302 
   17303    /* ---------------- (T4) B.W label ---------------- */
   17304    /* ... whereas this variant doesn't carry its own condition, so it
   17305       has to be either unconditional or the conditional by virtue of
   17306       being the last in an IT block.  The upside is that there's 4
   17307       more bits available for the jump offset, so it has a 16-times
   17308       greater branch range than the T3 variant. */
   17309    if (INSN0(15,11) == BITS5(1,1,1,1,0)
   17310        && INSN1(15,14) == BITS2(1,0)
   17311        && INSN1(12,12) == 1) {
   17312       if (1) {
   17313          UInt bS  = INSN0(10,10);
   17314          UInt bJ1 = INSN1(13,13);
   17315          UInt bJ2 = INSN1(11,11);
   17316          UInt bI1 = 1 ^ (bJ1 ^ bS);
   17317          UInt bI2 = 1 ^ (bJ2 ^ bS);
   17318          Int simm25
   17319             =   (bS          << (1 + 1 + 10 + 11 + 1))
   17320               | (bI1         << (1 + 10 + 11 + 1))
   17321               | (bI2         << (10 + 11 + 1))
   17322               | (INSN0(9,0)  << (11 + 1))
   17323               | (INSN1(10,0) << 1);
   17324          simm25 = (simm25 << 7) >> 7;
   17325 
   17326          vassert(0 == (guest_R15_curr_instr_notENC & 1));
   17327          UInt dst = simm25 + guest_R15_curr_instr_notENC + 4;
   17328 
   17329          /* If in an IT block, must be the last insn. */
   17330          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   17331 
   17332          // go uncond
   17333          mk_skip_over_T32_if_cond_is_false(condT);
   17334          condT = IRTemp_INVALID;
   17335          // now uncond
   17336 
   17337          // branch to dst
   17338          irsb->next = mkU32( dst | 1 /*CPSR.T*/ );
   17339          irsb->jumpkind = Ijk_Boring;
   17340          dres.whatNext  = Dis_StopHere;
   17341          DIP("b.w 0x%x\n", dst);
   17342          goto decode_success;
   17343       }
   17344    }
   17345 
   17346    /* ------------------ TBB, TBH ------------------ */
   17347    if (INSN0(15,4) == 0xE8D && INSN1(15,5) == 0x780) {
   17348       UInt rN = INSN0(3,0);
   17349       UInt rM = INSN1(3,0);
   17350       UInt bH = INSN1(4,4);
   17351       if (bH/*ATC*/ || (rN != 13 && !isBadRegT(rM))) {
   17352          /* Must be last or not-in IT block */
   17353          gen_SIGILL_T_if_in_but_NLI_ITBlock(old_itstate, new_itstate);
   17354          /* Go uncond */
   17355          mk_skip_over_T32_if_cond_is_false(condT);
   17356          condT = IRTemp_INVALID;
   17357 
   17358          IRExpr* ea
   17359              = binop(Iop_Add32,
   17360                      getIRegT(rN),
   17361                      bH ? binop(Iop_Shl32, getIRegT(rM), mkU8(1))
   17362                         : getIRegT(rM));
   17363 
   17364          IRTemp delta = newTemp(Ity_I32);
   17365          if (bH) {
   17366             assign(delta, unop(Iop_16Uto32, loadLE(Ity_I16, ea)));
   17367          } else {
   17368             assign(delta, unop(Iop_8Uto32, loadLE(Ity_I8, ea)));
   17369          }
   17370 
   17371          irsb->next
   17372             = binop(Iop_Or32,
   17373                     binop(Iop_Add32,
   17374                           getIRegT(15),
   17375                           binop(Iop_Shl32, mkexpr(delta), mkU8(1))
   17376                     ),
   17377                     mkU32(1)
   17378               );
   17379          irsb->jumpkind = Ijk_Boring;
   17380          dres.whatNext = Dis_StopHere;
   17381          DIP("tb%c [r%u, r%u%s]\n",
   17382              bH ? 'h' : 'b', rN, rM, bH ? ", LSL #1" : "");
   17383          goto decode_success;
   17384       }
   17385    }
   17386 
   17387    /* ------------------ UBFX ------------------ */
   17388    /* ------------------ SBFX ------------------ */
   17389    /* There's also ARM versions of same, but it doesn't seem worth the
   17390       hassle to common up the handling (it's only a couple of C
   17391       statements). */
   17392    if ((INSN0(15,4) == 0xF3C // UBFX
   17393         || INSN0(15,4) == 0xF34) // SBFX
   17394        && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
   17395       UInt rN  = INSN0(3,0);
   17396       UInt rD  = INSN1(11,8);
   17397       UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
   17398       UInt wm1 = INSN1(4,0);
   17399       UInt msb =  lsb + wm1;
   17400       if (!isBadRegT(rD) && !isBadRegT(rN) && msb <= 31) {
   17401          Bool   isU  = INSN0(15,4) == 0xF3C;
   17402          IRTemp src  = newTemp(Ity_I32);
   17403          IRTemp tmp  = newTemp(Ity_I32);
   17404          IRTemp res  = newTemp(Ity_I32);
   17405          UInt   mask = ((1 << wm1) - 1) + (1 << wm1);
   17406          vassert(msb >= 0 && msb <= 31);
   17407          vassert(mask != 0); // guaranteed by msb being in 0 .. 31 inclusive
   17408 
   17409          assign(src, getIRegT(rN));
   17410          assign(tmp, binop(Iop_And32,
   17411                            binop(Iop_Shr32, mkexpr(src), mkU8(lsb)),
   17412                            mkU32(mask)));
   17413          assign(res, binop(isU ? Iop_Shr32 : Iop_Sar32,
   17414                            binop(Iop_Shl32, mkexpr(tmp), mkU8(31-wm1)),
   17415                            mkU8(31-wm1)));
   17416 
   17417          putIRegT(rD, mkexpr(res), condT);
   17418 
   17419          DIP("%s r%u, r%u, #%u, #%u\n",
   17420              isU ? "ubfx" : "sbfx", rD, rN, lsb, wm1 + 1);
   17421          goto decode_success;
   17422       }
   17423    }
   17424 
   17425    /* ------------------ UXTB ------------------ */
   17426    /* ------------------ UXTH ------------------ */
   17427    /* ------------------ SXTB ------------------ */
   17428    /* ------------------ SXTH ------------------ */
   17429    /* ----------------- UXTB16 ----------------- */
   17430    /* ----------------- SXTB16 ----------------- */
   17431    /* FIXME: this is an exact duplicate of the ARM version.  They
   17432       should be commoned up. */
   17433    if ((INSN0(15,0) == 0xFA5F     // UXTB
   17434         || INSN0(15,0) == 0xFA1F  // UXTH
   17435         || INSN0(15,0) == 0xFA4F  // SXTB
   17436         || INSN0(15,0) == 0xFA0F  // SXTH
   17437         || INSN0(15,0) == 0xFA3F  // UXTB16
   17438         || INSN0(15,0) == 0xFA2F) // SXTB16
   17439        && INSN1(15,12) == BITS4(1,1,1,1)
   17440        && INSN1(7,6) == BITS2(1,0)) {
   17441       UInt rD = INSN1(11,8);
   17442       UInt rM = INSN1(3,0);
   17443       UInt rot = INSN1(5,4);
   17444       if (!isBadRegT(rD) && !isBadRegT(rM)) {
   17445          HChar* nm = "???";
   17446          IRTemp srcT = newTemp(Ity_I32);
   17447          IRTemp rotT = newTemp(Ity_I32);
   17448          IRTemp dstT = newTemp(Ity_I32);
   17449          assign(srcT, getIRegT(rM));
   17450          assign(rotT, genROR32(srcT, 8 * rot));
   17451          switch (INSN0(15,0)) {
   17452             case 0xFA5F: // UXTB
   17453                nm = "uxtb";
   17454                assign(dstT, unop(Iop_8Uto32,
   17455                                  unop(Iop_32to8, mkexpr(rotT))));
   17456                break;
   17457             case 0xFA1F: // UXTH
   17458                nm = "uxth";
   17459                assign(dstT, unop(Iop_16Uto32,
   17460                                  unop(Iop_32to16, mkexpr(rotT))));
   17461                break;
   17462             case 0xFA4F: // SXTB
   17463                nm = "sxtb";
   17464                assign(dstT, unop(Iop_8Sto32,
   17465                                  unop(Iop_32to8, mkexpr(rotT))));
   17466                break;
   17467             case 0xFA0F: // SXTH
   17468                nm = "sxth";
   17469                assign(dstT, unop(Iop_16Sto32,
   17470                                  unop(Iop_32to16, mkexpr(rotT))));
   17471                break;
   17472             case 0xFA3F: // UXTB16
   17473                nm = "uxtb16";
   17474                assign(dstT, binop(Iop_And32, mkexpr(rotT),
   17475                                              mkU32(0x00FF00FF)));
   17476                break;
   17477             case 0xFA2F: { // SXTB16
   17478                nm = "sxtb16";
   17479                IRTemp lo32 = newTemp(Ity_I32);
   17480                IRTemp hi32 = newTemp(Ity_I32);
   17481                assign(lo32, binop(Iop_And32, mkexpr(rotT), mkU32(0xFF)));
   17482                assign(hi32, binop(Iop_Shr32, mkexpr(rotT), mkU8(16)));
   17483                assign(
   17484                   dstT,
   17485                   binop(Iop_Or32,
   17486                         binop(Iop_And32,
   17487                               unop(Iop_8Sto32,
   17488                                    unop(Iop_32to8, mkexpr(lo32))),
   17489                               mkU32(0xFFFF)),
   17490                         binop(Iop_Shl32,
   17491                               unop(Iop_8Sto32,
   17492                                    unop(Iop_32to8, mkexpr(hi32))),
   17493                               mkU8(16))
   17494                ));
   17495                break;
   17496             }
   17497             default:
   17498                vassert(0);
   17499          }
   17500          putIRegT(rD, mkexpr(dstT), condT);
   17501          DIP("%s r%u, r%u, ror #%u\n", nm, rD, rM, 8 * rot);
   17502          goto decode_success;
   17503       }
   17504    }
   17505 
   17506    /* -------------- MUL.W Rd, Rn, Rm -------------- */
   17507    if (INSN0(15,4) == 0xFB0
   17508        && (INSN1(15,0) & 0xF0F0) == 0xF000) {
   17509       UInt rN = INSN0(3,0);
   17510       UInt rD = INSN1(11,8);
   17511       UInt rM = INSN1(3,0);
   17512       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   17513          IRTemp res = newTemp(Ity_I32);
   17514          assign(res, binop(Iop_Mul32, getIRegT(rN), getIRegT(rM)));
   17515          putIRegT(rD, mkexpr(res), condT);
   17516          DIP("mul.w r%u, r%u, r%u\n", rD, rN, rM);
   17517          goto decode_success;
   17518       }
   17519    }
   17520 
   17521    /* ------------------ {U,S}MULL ------------------ */
   17522    if ((INSN0(15,4) == 0xFB8 || INSN0(15,4) == 0xFBA)
   17523        && INSN1(7,4) == BITS4(0,0,0,0)) {
   17524       UInt isU  = INSN0(5,5);
   17525       UInt rN   = INSN0(3,0);
   17526       UInt rDlo = INSN1(15,12);
   17527       UInt rDhi = INSN1(11,8);
   17528       UInt rM   = INSN1(3,0);
   17529       if (!isBadRegT(rDhi) && !isBadRegT(rDlo)
   17530           && !isBadRegT(rN) && !isBadRegT(rM) && rDlo != rDhi) {
   17531          IRTemp res   = newTemp(Ity_I64);
   17532          assign(res, binop(isU ? Iop_MullU32 : Iop_MullS32,
   17533                            getIRegT(rN), getIRegT(rM)));
   17534          putIRegT( rDhi, unop(Iop_64HIto32, mkexpr(res)), condT );
   17535          putIRegT( rDlo, unop(Iop_64to32, mkexpr(res)), condT );
   17536          DIP("%cmull r%u, r%u, r%u, r%u\n",
   17537              isU ? 'u' : 's', rDlo, rDhi, rN, rM);
   17538          goto decode_success;
   17539       }
   17540    }
   17541 
   17542    /* ------------------ ML{A,S} ------------------ */
   17543    if (INSN0(15,4) == 0xFB0
   17544        && (   INSN1(7,4) == BITS4(0,0,0,0)    // MLA
   17545            || INSN1(7,4) == BITS4(0,0,0,1))) { // MLS
   17546       UInt rN = INSN0(3,0);
   17547       UInt rA = INSN1(15,12);
   17548       UInt rD = INSN1(11,8);
   17549       UInt rM = INSN1(3,0);
   17550       if (!isBadRegT(rD) && !isBadRegT(rN)
   17551           && !isBadRegT(rM) && !isBadRegT(rA)) {
   17552          Bool   isMLA = INSN1(7,4) == BITS4(0,0,0,0);
   17553          IRTemp res   = newTemp(Ity_I32);
   17554          assign(res,
   17555                 binop(isMLA ? Iop_Add32 : Iop_Sub32,
   17556                       getIRegT(rA),
   17557                       binop(Iop_Mul32, getIRegT(rN), getIRegT(rM))));
   17558          putIRegT(rD, mkexpr(res), condT);
   17559          DIP("%s r%u, r%u, r%u, r%u\n",
   17560              isMLA ? "mla" : "mls", rD, rN, rM, rA);
   17561          goto decode_success;
   17562       }
   17563    }
   17564 
   17565    /* ------------------ (T3) ADR ------------------ */
   17566    if ((INSN0(15,0) == 0xF20F || INSN0(15,0) == 0xF60F)
   17567        && INSN1(15,15) == 0) {
   17568       /* rD = align4(PC) + imm32 */
   17569       UInt rD = INSN1(11,8);
   17570       if (!isBadRegT(rD)) {
   17571          UInt imm32 = (INSN0(10,10) << 11)
   17572                       | (INSN1(14,12) << 8) | INSN1(7,0);
   17573          putIRegT(rD, binop(Iop_Add32,
   17574                             binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   17575                             mkU32(imm32)),
   17576                       condT);
   17577          DIP("add r%u, pc, #%u\n", rD, imm32);
   17578          goto decode_success;
   17579       }
   17580    }
   17581 
   17582    /* ----------------- (T1) UMLAL ----------------- */
   17583    /* ----------------- (T1) SMLAL ----------------- */
   17584    if ((INSN0(15,4) == 0xFBE // UMLAL
   17585         || INSN0(15,4) == 0xFBC) // SMLAL
   17586        && INSN1(7,4) == BITS4(0,0,0,0)) {
   17587       UInt rN   = INSN0(3,0);
   17588       UInt rDlo = INSN1(15,12);
   17589       UInt rDhi = INSN1(11,8);
   17590       UInt rM   = INSN1(3,0);
   17591       if (!isBadRegT(rDlo) && !isBadRegT(rDhi) && !isBadRegT(rN)
   17592           && !isBadRegT(rM) && rDhi != rDlo) {
   17593          Bool   isS   = INSN0(15,4) == 0xFBC;
   17594          IRTemp argL  = newTemp(Ity_I32);
   17595          IRTemp argR  = newTemp(Ity_I32);
   17596          IRTemp old   = newTemp(Ity_I64);
   17597          IRTemp res   = newTemp(Ity_I64);
   17598          IRTemp resHi = newTemp(Ity_I32);
   17599          IRTemp resLo = newTemp(Ity_I32);
   17600          IROp   mulOp = isS ? Iop_MullS32 : Iop_MullU32;
   17601          assign( argL, getIRegT(rM));
   17602          assign( argR, getIRegT(rN));
   17603          assign( old, binop(Iop_32HLto64, getIRegT(rDhi), getIRegT(rDlo)) );
   17604          assign( res, binop(Iop_Add64,
   17605                             mkexpr(old),
   17606                             binop(mulOp, mkexpr(argL), mkexpr(argR))) );
   17607          assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
   17608          assign( resLo, unop(Iop_64to32, mkexpr(res)) );
   17609          putIRegT( rDhi, mkexpr(resHi), condT );
   17610          putIRegT( rDlo, mkexpr(resLo), condT );
   17611          DIP("%cmlal r%u, r%u, r%u, r%u\n",
   17612              isS ? 's' : 'u', rDlo, rDhi, rN, rM);
   17613          goto decode_success;
   17614       }
   17615    }
   17616 
   17617    /* ------------------ (T2) ADR ------------------ */
   17618    if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF)
   17619        && INSN1(15,15) == 0) {
   17620       /* rD = align4(PC) - imm32 */
   17621       UInt rD = INSN1(11,8);
   17622       if (!isBadRegT(rD)) {
   17623          UInt imm32 = (INSN0(10,10) << 11)
   17624                       | (INSN1(14,12) << 8) | INSN1(7,0);
   17625          putIRegT(rD, binop(Iop_Sub32,
   17626                             binop(Iop_And32, getIRegT(15), mkU32(~3U)),
   17627                             mkU32(imm32)),
   17628                       condT);
   17629          DIP("sub r%u, pc, #%u\n", rD, imm32);
   17630          goto decode_success;
   17631       }
   17632    }
   17633 
   17634    /* ------------------- (T1) BFI ------------------- */
   17635    /* ------------------- (T1) BFC ------------------- */
   17636    if (INSN0(15,4) == 0xF36 && INSN1(15,15) == 0 && INSN1(5,5) == 0) {
   17637       UInt rD  = INSN1(11,8);
   17638       UInt rN  = INSN0(3,0);
   17639       UInt msb = INSN1(4,0);
   17640       UInt lsb = (INSN1(14,12) << 2) | INSN1(7,6);
   17641       if (isBadRegT(rD) || rN == 13 || msb < lsb) {
   17642          /* undecodable; fall through */
   17643       } else {
   17644          IRTemp src    = newTemp(Ity_I32);
   17645          IRTemp olddst = newTemp(Ity_I32);
   17646          IRTemp newdst = newTemp(Ity_I32);
   17647          UInt   mask = 1 << (msb - lsb);
   17648          mask = (mask - 1) + mask;
   17649          vassert(mask != 0); // guaranteed by "msb < lsb" check above
   17650          mask <<= lsb;
   17651 
   17652          assign(src, rN == 15 ? mkU32(0) : getIRegT(rN));
   17653          assign(olddst, getIRegT(rD));
   17654          assign(newdst,
   17655                 binop(Iop_Or32,
   17656                    binop(Iop_And32,
   17657                          binop(Iop_Shl32, mkexpr(src), mkU8(lsb)),
   17658                          mkU32(mask)),
   17659                    binop(Iop_And32,
   17660                          mkexpr(olddst),
   17661                          mkU32(~mask)))
   17662                );
   17663 
   17664          putIRegT(rD, mkexpr(newdst), condT);
   17665 
   17666          if (rN == 15) {
   17667             DIP("bfc r%u, #%u, #%u\n",
   17668                 rD, lsb, msb-lsb+1);
   17669          } else {
   17670             DIP("bfi r%u, r%u, #%u, #%u\n",
   17671                 rD, rN, lsb, msb-lsb+1);
   17672          }
   17673          goto decode_success;
   17674       }
   17675    }
   17676 
   17677    /* ------------------- (T1) SXTAH ------------------- */
   17678    /* ------------------- (T1) UXTAH ------------------- */
   17679    if ((INSN0(15,4) == 0xFA1      // UXTAH
   17680         || INSN0(15,4) == 0xFA0)  // SXTAH
   17681        && INSN1(15,12) == BITS4(1,1,1,1)
   17682        && INSN1(7,6) == BITS2(1,0)) {
   17683       Bool isU = INSN0(15,4) == 0xFA1;
   17684       UInt rN  = INSN0(3,0);
   17685       UInt rD  = INSN1(11,8);
   17686       UInt rM  = INSN1(3,0);
   17687       UInt rot = INSN1(5,4);
   17688       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   17689          IRTemp srcL = newTemp(Ity_I32);
   17690          IRTemp srcR = newTemp(Ity_I32);
   17691          IRTemp res  = newTemp(Ity_I32);
   17692          assign(srcR, getIRegT(rM));
   17693          assign(srcL, getIRegT(rN));
   17694          assign(res,  binop(Iop_Add32,
   17695                             mkexpr(srcL),
   17696                             unop(isU ? Iop_16Uto32 : Iop_16Sto32,
   17697                                  unop(Iop_32to16,
   17698                                       genROR32(srcR, 8 * rot)))));
   17699          putIRegT(rD, mkexpr(res), condT);
   17700          DIP("%cxtah r%u, r%u, r%u, ror #%u\n",
   17701              isU ? 'u' : 's', rD, rN, rM, rot);
   17702          goto decode_success;
   17703       }
   17704    }
   17705 
   17706    /* ------------------- (T1) SXTAB ------------------- */
   17707    /* ------------------- (T1) UXTAB ------------------- */
   17708    if ((INSN0(15,4) == 0xFA5      // UXTAB
   17709         || INSN0(15,4) == 0xFA4)  // SXTAB
   17710        && INSN1(15,12) == BITS4(1,1,1,1)
   17711        && INSN1(7,6) == BITS2(1,0)) {
   17712       Bool isU = INSN0(15,4) == 0xFA5;
   17713       UInt rN  = INSN0(3,0);
   17714       UInt rD  = INSN1(11,8);
   17715       UInt rM  = INSN1(3,0);
   17716       UInt rot = INSN1(5,4);
   17717       if (!isBadRegT(rD) && !isBadRegT(rN) && !isBadRegT(rM)) {
   17718          IRTemp srcL = newTemp(Ity_I32);
   17719          IRTemp srcR = newTemp(Ity_I32);
   17720          IRTemp res  = newTemp(Ity_I32);
   17721          assign(srcR, getIRegT(rM));
   17722          assign(srcL, getIRegT(rN));
   17723          assign(res,  binop(Iop_Add32,
   17724                             mkexpr(srcL),
   17725                             unop(isU ? Iop_8Uto32 : Iop_8Sto32,
   17726                                  unop(Iop_32to8,
   17727                                       genROR32(srcR, 8 * rot)))));
   17728          putIRegT(rD, mkexpr(res), condT);
   17729          DIP("%cxtab r%u, r%u, r%u, ror #%u\n",
   17730              isU ? 'u' : 's', rD, rN, rM, rot);
   17731          goto decode_success;
   17732       }
   17733    }
   17734 
   17735    /* ------------------- (T1) CLZ ------------------- */
   17736    if (INSN0(15,4) == 0xFAB
   17737        && INSN1(15,12) == BITS4(1,1,1,1)
   17738        && INSN1(7,4) == BITS4(1,0,0,0)) {
   17739       UInt rM1 = INSN0(3,0);
   17740       UInt rD  = INSN1(11,8);
   17741       UInt rM2 = INSN1(3,0);
   17742       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
   17743          IRTemp arg = newTemp(Ity_I32);
   17744          IRTemp res = newTemp(Ity_I32);
   17745          assign(arg, getIRegT(rM1));
   17746          assign(res, IRExpr_Mux0X(
   17747                         unop(Iop_1Uto8,binop(Iop_CmpEQ32,
   17748                                              mkexpr(arg),
   17749                                              mkU32(0))),
   17750                         unop(Iop_Clz32, mkexpr(arg)),
   17751                         mkU32(32)
   17752          ));
   17753          putIRegT(rD, mkexpr(res), condT);
   17754          DIP("clz r%u, r%u\n", rD, rM1);
   17755          goto decode_success;
   17756       }
   17757    }
   17758 
   17759    /* ------------------- (T1) RBIT ------------------- */
   17760    if (INSN0(15,4) == 0xFA9
   17761        && INSN1(15,12) == BITS4(1,1,1,1)
   17762        && INSN1(7,4) == BITS4(1,0,1,0)) {
   17763       UInt rM1 = INSN0(3,0);
   17764       UInt rD  = INSN1(11,8);
   17765       UInt rM2 = INSN1(3,0);
   17766       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
   17767          IRTemp arg = newTemp(Ity_I32);
   17768          assign(arg, getIRegT(rM1));
   17769          IRTemp res = gen_BITREV(arg);
   17770          putIRegT(rD, mkexpr(res), condT);
   17771          DIP("rbit r%u, r%u\n", rD, rM1);
   17772          goto decode_success;
   17773       }
   17774    }
   17775 
   17776    /* ------------------- (T2) REV   ------------------- */
   17777    /* ------------------- (T2) REV16 ------------------- */
   17778    if (INSN0(15,4) == 0xFA9
   17779        && INSN1(15,12) == BITS4(1,1,1,1)
   17780        && (   INSN1(7,4) == BITS4(1,0,0,0)     // REV
   17781            || INSN1(7,4) == BITS4(1,0,0,1))) { // REV16
   17782       UInt rM1   = INSN0(3,0);
   17783       UInt rD    = INSN1(11,8);
   17784       UInt rM2   = INSN1(3,0);
   17785       Bool isREV = INSN1(7,4) == BITS4(1,0,0,0);
   17786       if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
   17787          IRTemp arg = newTemp(Ity_I32);
   17788          assign(arg, getIRegT(rM1));
   17789          IRTemp res = isREV ? gen_REV(arg) : gen_REV16(arg);
   17790          putIRegT(rD, mkexpr(res), condT);
   17791          DIP("rev%s r%u, r%u\n", isREV ? "" : "16", rD, rM1);
   17792          goto decode_success;
   17793       }
   17794    }
   17795 
   17796    /* -------------- (T1) MSR apsr, reg -------------- */
   17797    if (INSN0(15,4) == 0xF38
   17798        && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) {
   17799       UInt rN          = INSN0(3,0);
   17800       UInt write_ge    = INSN1(10,10);
   17801       UInt write_nzcvq = INSN1(11,11);
   17802       if (!isBadRegT(rN) && (write_nzcvq || write_ge)) {
   17803          IRTemp rNt = newTemp(Ity_I32);
   17804          assign(rNt, getIRegT(rN));
   17805          desynthesise_APSR( write_nzcvq, write_ge, rNt, condT );
   17806          DIP("msr cpsr_%s%s, r%u\n",
   17807              write_nzcvq ? "f" : "", write_ge ? "g" : "", rN);
   17808          goto decode_success;
   17809       }
   17810    }
   17811 
   17812    /* -------------- (T1) MRS reg, apsr -------------- */
   17813    if (INSN0(15,0) == 0xF3EF
   17814        && INSN1(15,12) == BITS4(1,0,0,0) && INSN1(7,0) == 0x00) {
   17815       UInt rD = INSN1(11,8);
   17816       if (!isBadRegT(rD)) {
   17817          IRTemp apsr = synthesise_APSR();
   17818          putIRegT( rD, mkexpr(apsr), condT );
   17819          DIP("mrs r%u, cpsr\n", rD);
   17820          goto decode_success;
   17821       }
   17822    }
   17823 
   17824    /* ----------------- (T1) LDREX ----------------- */
   17825    if (INSN0(15,4) == 0xE85 && INSN1(11,8) == BITS4(1,1,1,1)) {
   17826       UInt rN   = INSN0(3,0);
   17827       UInt rT   = INSN1(15,12);
   17828       UInt imm8 = INSN1(7,0);
   17829       if (!isBadRegT(rT) && rN != 15) {
   17830          IRTemp res;
   17831          // go uncond
   17832          mk_skip_over_T32_if_cond_is_false( condT );
   17833          // now uncond
   17834          res = newTemp(Ity_I32);
   17835          stmt( IRStmt_LLSC(Iend_LE,
   17836                            res,
   17837                            binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
   17838                            NULL/*this is a load*/ ));
   17839          putIRegT(rT, mkexpr(res), IRTemp_INVALID);
   17840          DIP("ldrex r%u, [r%u, #+%u]\n", rT, rN, imm8 * 4);
   17841          goto decode_success;
   17842       }
   17843    }
   17844 
   17845    /* ----------------- (T1) STREX ----------------- */
   17846    if (INSN0(15,4) == 0xE84) {
   17847       UInt rN   = INSN0(3,0);
   17848       UInt rT   = INSN1(15,12);
   17849       UInt rD   = INSN1(11,8);
   17850       UInt imm8 = INSN1(7,0);
   17851       if (!isBadRegT(rD) && !isBadRegT(rT) && rN != 15
   17852           && rD != rN && rD != rT) {
   17853          IRTemp resSC1, resSC32;
   17854 
   17855          // go uncond
   17856          mk_skip_over_T32_if_cond_is_false( condT );
   17857          // now uncond
   17858 
   17859          /* Ok, now we're unconditional.  Do the store. */
   17860          resSC1 = newTemp(Ity_I1);
   17861          stmt( IRStmt_LLSC(Iend_LE,
   17862                            resSC1,
   17863                            binop(Iop_Add32, getIRegT(rN), mkU32(imm8 * 4)),
   17864                            getIRegT(rT)) );
   17865 
   17866          /* Set rD to 1 on failure, 0 on success.  Currently we have
   17867             resSC1 == 0 on failure, 1 on success. */
   17868          resSC32 = newTemp(Ity_I32);
   17869          assign(resSC32,
   17870                 unop(Iop_1Uto32, unop(Iop_Not1, mkexpr(resSC1))));
   17871 
   17872          putIRegT(rD, mkexpr(resSC32), IRTemp_INVALID);
   17873          DIP("strex r%u, r%u, [r%u, #+%u]\n", rD, rT, rN, imm8 * 4);
   17874          goto decode_success;
   17875       }
   17876    }
   17877 
   17878    /* -------------- read CP15 TPIDRURO register ------------- */
   17879    /* mrc     p15, 0, r0, c13, c0, 3  up to
   17880       mrc     p15, 0, r14, c13, c0, 3
   17881    */
   17882    /* I don't know whether this is really v7-only.  But anyway, we
   17883       have to support it since arm-linux uses TPIDRURO as a thread
   17884       state register. */
   17885    if (INSN0(15,0) == 0xEE1D && INSN1(11,0) == 0xF70) {
   17886       UInt rD = INSN1(15,12);
   17887       if (rD <= 14) {
   17888          /* skip r15, that's too stupid to handle */
   17889          putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32),
   17890                       condT);
   17891          DIP("mrc p15,0, r%u, c13, c0, 3\n", rD);
   17892          goto decode_success;
   17893       }
   17894    }
   17895 
   17896    /* -------------- v7 barrier insns -------------- */
   17897    if (INSN0(15,0) == 0xF3BF && (INSN1(15,0) & 0xFF00) == 0x8F00) {
   17898       /* XXX this isn't really right, is it?  The generated IR does
   17899          them unconditionally.  I guess it doesn't matter since it
   17900          doesn't do any harm to do them even when the guarding
   17901          condition is false -- it's just a performance loss. */
   17902       switch (INSN1(7,0)) {
   17903          case 0x4F: /* DSB sy */
   17904          case 0x4E: /* DSB st */
   17905          case 0x4B: /* DSB ish */
   17906          case 0x4A: /* DSB ishst */
   17907          case 0x47: /* DSB nsh */
   17908          case 0x46: /* DSB nshst */
   17909          case 0x43: /* DSB osh */
   17910          case 0x42: /* DSB oshst */
   17911             stmt( IRStmt_MBE(Imbe_Fence) );
   17912             DIP("DSB\n");
   17913             goto decode_success;
   17914          case 0x5F: /* DMB sy */
   17915          case 0x5E: /* DMB st */
   17916          case 0x5B: /* DMB ish */
   17917          case 0x5A: /* DMB ishst */
   17918          case 0x57: /* DMB nsh */
   17919          case 0x56: /* DMB nshst */
   17920          case 0x53: /* DMB osh */
   17921          case 0x52: /* DMB oshst */
   17922             stmt( IRStmt_MBE(Imbe_Fence) );
   17923             DIP("DMB\n");
   17924             goto decode_success;
   17925          case 0x6F: /* ISB */
   17926             stmt( IRStmt_MBE(Imbe_Fence) );
   17927             DIP("ISB\n");
   17928             goto decode_success;
   17929          default:
   17930             break;
   17931       }
   17932    }
   17933 
   17934    /* -------------- read CP15 TPIDRURO register ------------- */
   17935    /* mrc     p15, 0,  r0, c13, c0, 3  up to
   17936       mrc     p15, 0, r14, c13, c0, 3
   17937    */
   17938    /* I don't know whether this is really v7-only.  But anyway, we
   17939       have to support it since arm-linux uses TPIDRURO as a thread
   17940       state register. */
   17941 
   17942    if ((INSN0(15,0) == 0xEE1D) && (INSN1(11,0) == 0x0F70)) {
   17943       UInt rD = INSN1(15,12);
   17944       if (!isBadRegT(rD)) {
   17945          putIRegT(rD, IRExpr_Get(OFFB_TPIDRURO, Ity_I32), IRTemp_INVALID);
   17946          DIP("mrc p15,0, r%u, c13, c0, 3\n", rD);
   17947          goto decode_success;
   17948       }
   17949       /* fall through */
   17950    }
   17951 
   17952    /* ------------------- NOP ------------------ */
   17953    if (INSN0(15,0) == 0xF3AF && INSN1(15,0) == 0x8000) {
   17954       DIP("nop\n");
   17955       goto decode_success;
   17956    }
   17957 
   17958    /* ----------------------------------------------------------- */
   17959    /* -- VFP (CP 10, CP 11) instructions (in Thumb mode)       -- */
   17960    /* ----------------------------------------------------------- */
   17961 
   17962    if (INSN0(15,12) == BITS4(1,1,1,0)) {
   17963       UInt insn28 = (INSN0(11,0) << 16) | INSN1(15,0);
   17964       Bool ok_vfp = decode_CP10_CP11_instruction (
   17965                        &dres, insn28, condT, ARMCondAL/*bogus*/,
   17966                        True/*isT*/
   17967                     );
   17968       if (ok_vfp)
   17969          goto decode_success;
   17970    }
   17971 
   17972    /* ----------------------------------------------------------- */
   17973    /* -- NEON instructions (in Thumb mode)                     -- */
   17974    /* ----------------------------------------------------------- */
   17975 
   17976    if (archinfo->hwcaps & VEX_HWCAPS_ARM_NEON) {
   17977       UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
   17978       Bool ok_neon = decode_NEON_instruction(
   17979                         &dres, insn32, condT, True/*isT*/
   17980                      );
   17981       if (ok_neon)
   17982          goto decode_success;
   17983    }
   17984 
   17985    /* ----------------------------------------------------------- */
   17986    /* -- v6 media instructions (in Thumb mode)                 -- */
   17987    /* ----------------------------------------------------------- */
   17988 
   17989    { UInt insn32 = (INSN0(15,0) << 16) | INSN1(15,0);
   17990      Bool ok_v6m = decode_V6MEDIA_instruction(
   17991                       &dres, insn32, condT, ARMCondAL/*bogus*/,
   17992                       True/*isT*/
   17993                    );
   17994      if (ok_v6m)
   17995         goto decode_success;
   17996    }
   17997 
   17998    /* ----------------------------------------------------------- */
   17999    /* -- Undecodable                                           -- */
   18000    /* ----------------------------------------------------------- */
   18001 
   18002    goto decode_failure;
   18003    /*NOTREACHED*/
   18004 
   18005   decode_failure:
   18006    /* All decode failures end up here. */
   18007    vex_printf("disInstr(thumb): unhandled instruction: "
   18008               "0x%04x 0x%04x\n", (UInt)insn0, (UInt)insn1);
   18009 
   18010    /* Back up ITSTATE to the initial value for this instruction.
   18011       If we don't do that, any subsequent restart of the instruction
   18012       will restart with the wrong value. */
   18013    put_ITSTATE(old_itstate);
   18014    /* Tell the dispatcher that this insn cannot be decoded, and so has
   18015       not been executed, and (is currently) the next to be executed.
   18016       R15 should be up-to-date since it made so at the start of each
   18017       insn, but nevertheless be paranoid and update it again right
   18018       now. */
   18019    vassert(0 == (guest_R15_curr_instr_notENC & 1));
   18020    llPutIReg( 15, mkU32(guest_R15_curr_instr_notENC | 1) );
   18021    irsb->next     = mkU32(guest_R15_curr_instr_notENC | 1 /* CPSR.T */);
   18022    irsb->jumpkind = Ijk_NoDecode;
   18023    dres.whatNext  = Dis_StopHere;
   18024    dres.len       = 0;
   18025    return dres;
   18026 
   18027   decode_success:
   18028    /* All decode successes end up here. */
   18029    DIP("\n");
   18030 
   18031    vassert(dres.len == 2 || dres.len == 4 || dres.len == 20);
   18032 
   18033 #if 0
   18034    // XXX is this necessary on Thumb?
   18035    /* Now then.  Do we have an implicit jump to r15 to deal with? */
   18036    if (r15written) {
   18037       /* If we get jump to deal with, we assume that there's been no
   18038          other competing branch stuff previously generated for this
   18039          insn.  That's reasonable, in the sense that the ARM insn set
   18040          appears to declare as "Unpredictable" any instruction which
   18041          generates more than one possible new value for r15.  Hence
   18042          just assert.  The decoders themselves should check against
   18043          all such instructions which are thusly Unpredictable, and
   18044          decline to decode them.  Hence we should never get here if we
   18045          have competing new values for r15, and hence it is safe to
   18046          assert here. */
   18047       vassert(dres.whatNext == Dis_Continue);
   18048       vassert(irsb->next == NULL);
   18049       vassert(irsb->jumpkind = Ijk_Boring);
   18050       /* If r15 is unconditionally written, terminate the block by
   18051          jumping to it.  If it's conditionally written, still
   18052          terminate the block (a shame, but we can't do side exits to
   18053          arbitrary destinations), but first jump to the next
   18054          instruction if the condition doesn't hold. */
   18055       /* We can't use getIRegT(15) to get the destination, since that
   18056          will produce r15+4, which isn't what we want.  Must use
   18057          llGetIReg(15) instead. */
   18058       if (r15guard == IRTemp_INVALID) {
   18059          /* unconditional */
   18060       } else {
   18061          /* conditional */
   18062          stmt( IRStmt_Exit(
   18063                   unop(Iop_32to1,
   18064                        binop(Iop_Xor32,
   18065                              mkexpr(r15guard), mkU32(1))),
   18066                   r15kind,
   18067                   IRConst_U32(guest_R15_curr_instr_notENC + 4)
   18068          ));
   18069       }
   18070       irsb->next     = llGetIReg(15);
   18071       irsb->jumpkind = r15kind;
   18072       dres.whatNext  = Dis_StopHere;
   18073    }
   18074 #endif
   18075 
   18076    return dres;
   18077 
   18078 #  undef INSN0
   18079 #  undef INSN1
   18080 }
   18081 
   18082 #undef DIP
   18083 #undef DIS
   18084 
   18085 
   18086 /*------------------------------------------------------------*/
   18087 /*--- Top-level fn                                         ---*/
   18088 /*------------------------------------------------------------*/
   18089 
   18090 /* Disassemble a single instruction into IR.  The instruction
   18091    is located in host memory at &guest_code[delta]. */
   18092 
   18093 DisResult disInstr_ARM ( IRSB*        irsb_IN,
   18094                          Bool         put_IP,
   18095                          Bool         (*resteerOkFn) ( void*, Addr64 ),
   18096                          Bool         resteerCisOk,
   18097                          void*        callback_opaque,
   18098                          UChar*       guest_code_IN,
   18099                          Long         delta_ENCODED,
   18100                          Addr64       guest_IP_ENCODED,
   18101                          VexArch      guest_arch,
   18102                          VexArchInfo* archinfo,
   18103                          VexAbiInfo*  abiinfo,
   18104                          Bool         host_bigendian_IN )
   18105 {
   18106    DisResult dres;
   18107    Bool isThumb = (Bool)(guest_IP_ENCODED & 1);
   18108 
   18109    /* Set globals (see top of this file) */
   18110    vassert(guest_arch == VexArchARM);
   18111 
   18112    irsb              = irsb_IN;
   18113    host_is_bigendian = host_bigendian_IN;
   18114    __curr_is_Thumb   = isThumb;
   18115 
   18116    if (isThumb) {
   18117       guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED - 1;
   18118    } else {
   18119       guest_R15_curr_instr_notENC = (Addr32)guest_IP_ENCODED;
   18120    }
   18121 
   18122    if (isThumb) {
   18123       dres = disInstr_THUMB_WRK ( put_IP, resteerOkFn,
   18124                                   resteerCisOk, callback_opaque,
   18125                                   &guest_code_IN[delta_ENCODED - 1],
   18126                                   archinfo, abiinfo );
   18127    } else {
   18128       dres = disInstr_ARM_WRK ( put_IP, resteerOkFn,
   18129                                 resteerCisOk, callback_opaque,
   18130                                 &guest_code_IN[delta_ENCODED],
   18131                                 archinfo, abiinfo );
   18132    }
   18133 
   18134    return dres;
   18135 }
   18136 
   18137 /* Test program for the conversion of IRCmpF64Result values to VFP
   18138    nzcv values.  See handling of FCMPD et al above. */
   18139 /*
   18140 UInt foo ( UInt x )
   18141 {
   18142    UInt ix    = ((x >> 5) & 3) | (x & 1);
   18143    UInt termL = (((((ix ^ 1) << 30) - 1) >> 29) + 1);
   18144    UInt termR = (ix & (ix >> 1) & 1);
   18145    return termL  -  termR;
   18146 }
   18147 
   18148 void try ( char* s, UInt ir, UInt req )
   18149 {
   18150    UInt act = foo(ir);
   18151    printf("%s 0x%02x -> req %d%d%d%d act %d%d%d%d (0x%x)\n",
   18152           s, ir, (req >> 3) & 1, (req >> 2) & 1,
   18153                  (req >> 1) & 1, (req >> 0) & 1,
   18154                  (act >> 3) & 1, (act >> 2) & 1,
   18155                  (act >> 1) & 1, (act >> 0) & 1, act);
   18156 
   18157 }
   18158 
   18159 int main ( void )
   18160 {
   18161    printf("\n");
   18162    try("UN", 0x45, 0b0011);
   18163    try("LT", 0x01, 0b1000);
   18164    try("GT", 0x00, 0b0010);
   18165    try("EQ", 0x40, 0b0110);
   18166    printf("\n");
   18167    return 0;
   18168 }
   18169 */
   18170 
   18171 /*--------------------------------------------------------------------*/
   18172 /*--- end                                         guest_arm_toIR.c ---*/
   18173 /*--------------------------------------------------------------------*/
   18174