]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Remove the old SIMD decoder entirely.
authorJulian Seward <jseward@acm.org>
Thu, 12 Jun 2014 10:15:46 +0000 (10:15 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 12 Jun 2014 10:15:46 +0000 (10:15 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@2873

VEX/priv/guest_arm64_toIR.c

index 91c1c86aeda47081bbadcf922820f154cc78339c..cd83232bec0a0d9a32632bb3618e8e712f8bab8c 100644 (file)
@@ -5011,7 +5011,6 @@ static Bool AdvSIMDExpandImm ( /*OUT*/ULong* res,
    return True;
 }
 
-
 /* Help a bit for decoding laneage for vector operations that can be
    of the form 4x32, 2x64 or 2x32-and-zero-upper-half, as encoded by Q
    and SZ bits, typically for vector floating point. */
@@ -5050,34 +5049,6 @@ static Bool getLaneInfo_Q_SZ ( /*OUT*/IRType* tyI,  /*OUT*/IRType* tyF,
    return False;
 }
 
-/* Helper for decoding laneage for simple vector operations,
-   eg integer add. */
-static Bool getLaneInfo_SIMPLE ( /*OUT*/Bool* zeroUpper,
-                                 /*OUT*/const HChar** arrSpec,
-                                 Bool bitQ, UInt szBlg2 )
-{
-   vassert(bitQ == True || bitQ == False);
-   vassert(szBlg2 < 4);
-   Bool zu = False;
-   const HChar* as = NULL;
-   switch ((szBlg2 << 1) | (bitQ ? 1 : 0)) {
-      case 0: zu = True;  as = "8b";  break;
-      case 1: zu = False; as = "16b"; break;
-      case 2: zu = True;  as = "4h";  break;
-      case 3: zu = False; as = "8h";  break;
-      case 4: zu = True;  as = "2s";  break;
-      case 5: zu = False; as = "4s";  break;
-      case 6: return False; // impliedly 1x64
-      case 7: zu = False; as = "2d";  break;
-      default: vassert(0);
-   }
-   vassert(as);
-   if (arrSpec)   *arrSpec = as;
-   if (zeroUpper) *zeroUpper = zu;
-   return True;
-}
-
-
 /* Helper for decoding laneage for shift-style vector operations 
    that involve an immediate shift amount. */
 static Bool getLaneInfo_IMMH_IMMB ( /*OUT*/UInt* shift, /*OUT*/UInt* szBlg2,
@@ -5109,7 +5080,6 @@ static Bool getLaneInfo_IMMH_IMMB ( /*OUT*/UInt* shift, /*OUT*/UInt* szBlg2,
    return False;
 }
 
-
 /* Generate IR to fold all lanes of the V128 value in 'src' as
    characterised by the operator 'op', and return the result in the
    bottom bits of a V128, with all other bits set to zero. */
@@ -5845,14 +5815,15 @@ Bool dis_AdvSIMD_modified_immediate(/*MB_OUT*/DisResult* dres, UInt insn)
    /* -------- {FMOV,MOVI} (vector, immediate) -------- */
    /* Allowable op:cmode
         FMOV = 1:1111
-        MOVI = 0:xx00, 1:0x00, 1:10x0, 1:110x, x:1110
+        MOVI = 0:xx00, 0:0010, 1:0x00, 1:10x0, 1:110x, x:1110,
    */
    ULong imm64lo  = 0;
    UInt  op_cmode = (bitOP << 4) | cmode;
    Bool  ok       = False;
    switch (op_cmode) {
       case BITS5(1,1,1,1,1): // 1:1111
-      case BITS5(0,0,0,0,0): case BITS5(0,0,1,0,0):
+      case BITS5(0,0,0,0,0): case BITS5(0,0,1,0,0): // 0:0x00
+      case BITS5(0,0,0,1,0):                        // 1:0010
       case BITS5(0,1,0,0,0): case BITS5(0,1,1,0,0): // 0:xx00
       case BITS5(1,0,0,0,0): case BITS5(1,0,1,0,0): // 1:0x00
       case BITS5(1,1,0,0,0): case BITS5(1,1,0,1,0): // 1:10x0
@@ -5886,6 +5857,7 @@ Bool dis_AdvSIMD_scalar_copy(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_scalar_pairwise(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -5894,6 +5866,7 @@ Bool dis_AdvSIMD_scalar_pairwise(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_scalar_shift_by_imm(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -5914,6 +5887,19 @@ Bool dis_AdvSIMD_scalar_shift_by_imm(/*MB_OUT*/DisResult* dres, UInt insn)
    UInt dd     = INSN(4,0);
    UInt immhb  = (immh << 3) | immb;
 
+   if (bitU == 1 && (immh & 8) == 8 && opcode == BITS5(0,0,0,0,0)) {
+      /* -------- 1,1xxx,00000 SHR d_d_#imm -------- */
+      UInt sh = 128 - immhb;
+      vassert(sh >= 1 && sh <= 64);
+      /* Don't generate an out of range IR shift */
+      putQReg128(dd, sh == 64
+                        ? mkV128(0x0000)
+                        : unop(Iop_ZeroHI64ofV128,
+                               binop(Iop_ShrN64x2, getQReg128(nn), mkU8(sh))));
+      DIP("shr d%u, d%u, #%u\n", dd, nn, sh);
+      return True;
+   }
+
    if (bitU == 0 && (immh & 8) == 8 && opcode == BITS5(0,1,0,1,0)) {
       /* -------- 0,1xxx,01010 SHL d_d_#imm -------- */
       UInt sh = immhb - 64;
@@ -5929,6 +5915,7 @@ Bool dis_AdvSIMD_scalar_shift_by_imm(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_scalar_three_different(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -6031,6 +6018,7 @@ Bool dis_AdvSIMD_scalar_two_reg_misc(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_scalar_x_indexed_element(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -6039,6 +6027,7 @@ Bool dis_AdvSIMD_scalar_x_indexed_element(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_shift_by_immediate(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -6205,6 +6194,7 @@ Bool dis_AdvSIMD_shift_by_immediate(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_three_different(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -6848,6 +6838,7 @@ Bool dis_AdvSIMD_two_reg_misc(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_vector_x_indexed_elem(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -6856,6 +6847,7 @@ Bool dis_AdvSIMD_vector_x_indexed_elem(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_crypto_aes(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -6864,6 +6856,7 @@ Bool dis_AdvSIMD_crypto_aes(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_crypto_three_reg_sha(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -6872,6 +6865,7 @@ Bool dis_AdvSIMD_crypto_three_reg_sha(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_crypto_two_reg_sha(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -6964,6 +6958,7 @@ Bool dis_AdvSIMD_fp_conditional_compare(/*MB_OUT*/DisResult* dres, UInt insn)
 #  undef INSN
 }
 
+
 static
 Bool dis_AdvSIMD_fp_conditional_select(/*MB_OUT*/DisResult* dres, UInt insn)
 {
@@ -7602,1681 +7597,6 @@ Bool dis_ARM64_simd_and_fp(/*MB_OUT*/DisResult* dres, UInt insn)
    return False;
 }
 
-static
-Bool dis_ARM64_simd_and_fp_OLD(/*MB_OUT*/DisResult* dres, UInt insn)
-{
-#  define INSN(_bMax,_bMin)  SLICE_UInt(insn, (_bMax), (_bMin))
-
-   /* -------------- FMOV (scalar, immediate) -------------- */
-   /* 31  28    23   20   12  9     4
-      000 11110 00 1 imm8 100 00000 d  FMOV Sd, #imm
-      000 11110 01 1 imm8 100 00000 d  FMOV Dd, #imm
-   */
-   if (INSN(31,23) == BITS9(0,0,0,1,1,1,1,0,0)
-       && INSN(21,21) == 1 && INSN(12,5) == BITS8(1,0,0,0,0,0,0,0)) {
-      Bool  isD  = INSN(22,22) == 1;
-      UInt  imm8 = INSN(20,13);
-      UInt  dd   = INSN(4,0);
-      ULong imm  = VFPExpandImm(imm8, isD ? 64 : 32);
-      if (!isD) {
-         vassert(0 == (imm & 0xFFFFFFFF00000000ULL));
-      }
-      putQReg128(dd, mkV128(0));
-      putQRegLO(dd, isD ? mkU64(imm) : mkU32(imm & 0xFFFFFFFFULL));
-      DIP("fmov %s, #0x%llx\n",
-          nameQRegLO(dd, isD ? Ity_F64 : Ity_F32), imm);
-      return True;
-   }
-
-   /* -------------- {S,U}CVTF (scalar, integer) -------------- */
-   /* 31  28    23 21 20 18  15     9 4                  ix
-      000 11110 00 1  00 010 000000 n d  SCVTF Sd, Wn    0
-      000 11110 01 1  00 010 000000 n d  SCVTF Dd, Wn    1
-      100 11110 00 1  00 010 000000 n d  SCVTF Sd, Xn    2
-      100 11110 01 1  00 010 000000 n d  SCVTF Dd, Xn    3
-
-      000 11110 00 1  00 011 000000 n d  UCVTF Sd, Wn    4
-      000 11110 01 1  00 011 000000 n d  UCVTF Dd, Wn    5
-      100 11110 00 1  00 011 000000 n d  UCVTF Sd, Xn    6
-      100 11110 01 1  00 011 000000 n d  UCVTF Dd, Xn    7
-
-      These are signed/unsigned conversion from integer registers to
-      FP registers, all 4 32/64-bit combinations, rounded per FPCR.
-   */
-   if (INSN(30,23) == BITS8(0,0,1,1,1,1,0,0) && INSN(21,17) == BITS5(1,0,0,0,1)
-       && INSN(15,10) == BITS6(0,0,0,0,0,0)) {
-      Bool isI64 = INSN(31,31) == 1;
-      Bool isF64 = INSN(22,22) == 1;
-      Bool isU   = INSN(16,16) == 1;
-      UInt nn    = INSN(9,5);
-      UInt dd    = INSN(4,0);
-      UInt ix    = (isU ? 4 : 0) | (isI64 ? 2 : 0) | (isF64 ? 1 : 0);
-      const IROp ops[8]
-        = { Iop_I32StoF32, Iop_I32StoF64, Iop_I64StoF32, Iop_I64StoF64,
-            Iop_I32UtoF32, Iop_I32UtoF64, Iop_I64UtoF32, Iop_I64UtoF64 };
-      IRExpr* src = getIRegOrZR(isI64, nn);
-      IRExpr* res = (isF64 && !isI64) 
-                       ? unop(ops[ix], src)
-                       : binop(ops[ix], mkexpr(mk_get_IR_rounding_mode()), src);
-      putQReg128(dd, mkV128(0));
-      putQRegLO(dd, res);
-      DIP("%ccvtf %s, %s\n",
-          isU ? 'u' : 's', nameQRegLO(dd, isF64 ? Ity_F64 : Ity_F32), 
-          nameIRegOrZR(isI64, nn));
-      return True;
-   }
-
-   /* ------------ F{ADD,SUB,MUL,DIV,NMUL} (scalar) ------------ */
-   /* 31        23  20 15   11 9 4
-      ---------------- 0000 ------   FMUL  --------
-      000 11110 001 m  0001 10 n d   FDIV  Sd,Sn,Sm
-      000 11110 011 m  0001 10 n d   FDIV  Dd,Dn,Dm
-      ---------------- 0010 ------   FADD  --------
-      ---------------- 0011 ------   FSUB  --------
-      ---------------- 1000 ------   FNMUL --------
-   */
-   if (INSN(31,23) == BITS9(0,0,0,1,1,1,1,0,0)
-       && INSN(21,21) == 1 && INSN(11,10) == BITS2(1,0)) {
-      Bool   isD = INSN(22,22) == 1;
-      UInt   mm  = INSN(20,16);
-      UInt   op  = INSN(15,12);
-      UInt   nn  = INSN(9,5);
-      UInt   dd  = INSN(4,0);
-      IROp   iop = Iop_INVALID;
-      IRType ty  = isD ? Ity_F64 : Ity_F32;
-      Bool   neg = False;
-      const HChar* nm = "???";
-      switch (op) {
-         case BITS4(0,0,0,0): nm = "fmul";  iop = mkMULF(ty); break;
-         case BITS4(0,0,0,1): nm = "fdiv";  iop = mkDIVF(ty); break;
-         case BITS4(0,0,1,0): nm = "fadd";  iop = mkADDF(ty); break;
-         case BITS4(0,0,1,1): nm = "fsub";  iop = mkSUBF(ty); break;
-         case BITS4(1,0,0,0): nm = "fnmul"; iop = mkMULF(ty);
-                              neg = True; break;
-         default:             return False;
-      }
-      vassert(iop != Iop_INVALID);
-      IRExpr* resE = triop(iop, mkexpr(mk_get_IR_rounding_mode()),
-                           getQRegLO(nn, ty), getQRegLO(mm, ty));
-      IRTemp res = newTemp(ty);
-      assign(res, neg ? unop(mkNEGF(ty),resE) : resE);
-      putQReg128(dd, mkV128(0));
-      putQRegLO(dd, mkexpr(res));
-      DIP("%s %s, %s, %s\n",
-          nm, nameQRegLO(dd, ty), nameQRegLO(nn, ty), nameQRegLO(mm, ty));
-      return True;
-   }
-
-   /* ------------ F{MOV,ABS,NEG,SQRT} D/D or S/S ------------ */
-   /* 31        23 21    16 14    9 4
-      000 11110 00 10000 00 10000 n d  FMOV Sd, Sn
-      000 11110 01 10000 00 10000 n d  FMOV Dd, Dn
-      ------------------ 01 ---------  FABS ------
-      ------------------ 10 ---------  FNEG ------
-      ------------------ 11 ---------  FSQRT -----
-   */
-   if (INSN(31,23) == BITS9(0,0,0,1,1,1,1,0,0)
-       && INSN(21,17) == BITS5(1,0,0,0,0)
-       && INSN(14,10) == BITS5(1,0,0,0,0)) {
-      Bool   isD = INSN(22,22) == 1;
-      UInt   opc = INSN(16,15);
-      UInt   nn  = INSN(9,5);
-      UInt   dd  = INSN(4,0);
-      IRType ty  = isD ? Ity_F64 : Ity_F32;
-      IRTemp res = newTemp(ty);
-      if (opc == BITS2(0,0)) {
-         assign(res, getQRegLO(nn, ty));
-         putQReg128(dd, mkV128(0x0000));
-         putQRegLO(dd, mkexpr(res));
-         DIP("fmov %s, %s\n",
-             nameQRegLO(dd, ty), nameQRegLO(nn, ty));
-         return True;
-      }
-      if (opc == BITS2(1,0) || opc == BITS2(0,1)) {
-         Bool isAbs = opc == BITS2(0,1);
-         IROp op    = isAbs ? mkABSF(ty) : mkNEGF(ty);
-         assign(res, unop(op, getQRegLO(nn, ty)));
-         putQReg128(dd, mkV128(0x0000));
-         putQRegLO(dd, mkexpr(res));
-         DIP("%s %s, %s\n", isAbs ? "fabs" : "fneg",
-             nameQRegLO(dd, ty), nameQRegLO(nn, ty));
-         return True;
-      }
-      if (opc == BITS2(1,1)) {
-         assign(res,
-                binop(mkSQRTF(ty),
-                      mkexpr(mk_get_IR_rounding_mode()), getQRegLO(nn, ty)));
-         putQReg128(dd, mkV128(0x0000));
-         putQRegLO(dd, mkexpr(res));
-         DIP("fsqrt %s, %s\n", nameQRegLO(dd, ty), nameQRegLO(nn, ty));
-         return True;
-      }
-      /* else fall through; other cases are ATC */
-   }
-
-   /* ---------------- F{ABS,NEG} (vector) ---------------- */
-   /* 31  28      22 21    16       9 4
-      0q0 01110 1 sz 10000 01111 10 n d  FABS Vd.T, Vn.T
-      0q1 01110 1 sz 10000 01111 10 n d  FNEG Vd.T, Vn.T
-   */
-   if (INSN(31,31) == 0 && INSN(28,23) == BITS6(0,1,1,1,0,1)
-       && INSN(21,17) == BITS5(1,0,0,0,0)
-       && INSN(16,10) == BITS7(0,1,1,1,1,1,0)) {
-      UInt bitQ   = INSN(30,30);
-      UInt bitSZ  = INSN(22,22);
-      Bool isFNEG = INSN(29,29) == 1;
-      UInt nn     = INSN(9,5);
-      UInt dd     = INSN(4,0);
-      const HChar* ar = "??";
-      IRType tyF    = Ity_INVALID;
-      Bool   zeroHI = False;
-      Bool   ok     = getLaneInfo_Q_SZ(NULL, &tyF, NULL, &zeroHI, &ar,
-                                       (Bool)bitQ, (Bool)bitSZ);
-      if (ok) {
-         vassert(tyF == Ity_F64 || tyF == Ity_F32);
-         IROp op = (tyF == Ity_F64) ? (isFNEG ? Iop_Neg64Fx2 : Iop_Abs64Fx2)
-                                    : (isFNEG ? Iop_Neg32Fx4 : Iop_Abs32Fx4);
-         IRTemp res = newTemp(Ity_V128);
-         assign(res, unop(op, getQReg128(nn)));
-         putQReg128(dd, zeroHI ? unop(Iop_ZeroHI64ofV128, mkexpr(res))
-                               : mkexpr(res));
-         DIP("%s %s.%s, %s.%s\n", isFNEG ? "fneg" : "fabs",
-             nameQReg128(dd), ar, nameQReg128(nn), ar);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* -------------------- FCMP,FCMPE -------------------- */
-   /* 31        23   20    15      9 4
-      000 11110 01 1     m 00 1000 n 10 000  FCMPE Dn, Dm
-      000 11110 01 1 00000 00 1000 n 11 000  FCMPE Dn, #0.0
-      000 11110 01 1     m 00 1000 n 00 000  FCMP  Dn, Dm
-      000 11110 01 1 00000 00 1000 n 01 000  FCMP  Dn, #0.0
-
-      000 11110 00 1     m 00 1000 n 10 000  FCMPE Sn, Sm
-      000 11110 00 1 00000 00 1000 n 11 000  FCMPE Sn, #0.0
-      000 11110 00 1     m 00 1000 n 00 000  FCMP  Sn, Sm
-      000 11110 00 1 00000 00 1000 n 01 000  FCMP  Sn, #0.0
-
-      FCMPE generates Invalid Operation exn if either arg is any kind
-      of NaN.  FCMP generates Invalid Operation exn if either arg is a
-      signalling NaN.  We ignore this detail here and produce the same
-      IR for both.
-   */
-   if (INSN(31,23) == BITS9(0,0,0,1,1,1,1,0,0) && INSN(21,21) == 1 
-       && INSN(15,10) == BITS6(0,0,1,0,0,0) && INSN(2,0) == BITS3(0,0,0)) {
-      Bool   isD     = INSN(22,22) == 1;
-      UInt   mm      = INSN(20,16);
-      UInt   nn      = INSN(9,5);
-      Bool   isCMPE  = INSN(4,4) == 1;
-      Bool   cmpZero = INSN(3,3) == 1;
-      IRType ty      = isD ? Ity_F64 : Ity_F32;
-      Bool   valid   = True;
-      if (cmpZero && mm != 0) valid = False;
-      if (valid) {
-         IRTemp argL  = newTemp(ty);
-         IRTemp argR  = newTemp(ty);
-         IRTemp irRes = newTemp(Ity_I32);
-         assign(argL, getQRegLO(nn, ty));
-         assign(argR,
-                cmpZero 
-                   ? (IRExpr_Const(isD ? IRConst_F64i(0) : IRConst_F32i(0)))
-                   : getQRegLO(mm, ty));
-         assign(irRes, binop(isD ? Iop_CmpF64 : Iop_CmpF32,
-                             mkexpr(argL), mkexpr(argR)));
-         IRTemp nzcv = mk_convert_IRCmpF64Result_to_NZCV(irRes);
-         IRTemp nzcv_28x0 = newTemp(Ity_I64);
-         assign(nzcv_28x0, binop(Iop_Shl64, mkexpr(nzcv), mkU8(28)));
-         setFlags_COPY(nzcv_28x0);
-         DIP("fcmp%s %s, %s\n", isCMPE ? "e" : "", nameQRegLO(nn, ty),
-             cmpZero ? "#0.0" : nameQRegLO(mm, ty));
-         return True;
-      }
-   }
-
-   /* -------------------- F{N}M{ADD,SUB} -------------------- */
-   /* 31          22   20 15 14 9 4   ix
-      000 11111 0 sz 0 m  0  a  n d   0   FMADD  Fd,Fn,Fm,Fa
-      000 11111 0 sz 0 m  1  a  n d   1   FMSUB  Fd,Fn,Fm,Fa
-      000 11111 0 sz 1 m  0  a  n d   2   FNMADD Fd,Fn,Fm,Fa
-      000 11111 0 sz 1 m  1  a  n d   3   FNMSUB Fd,Fn,Fm,Fa
-      where Fx=Dx when sz=1, Fx=Sx when sz=0
-
-               -----SPEC------    ----IMPL----
-      fmadd       a +    n * m    a + n * m
-      fmsub       a + (-n) * m    a - n * m
-      fnmadd   (-a) + (-n) * m    -(a + n * m)
-      fnmsub   (-a) +    n * m    -(a - n * m)
-   */
-   if (INSN(31,23) == BITS9(0,0,0,1,1,1,1,1,0)) {
-      Bool    isD   = INSN(22,22) == 1;
-      UInt    mm    = INSN(20,16);
-      UInt    aa    = INSN(14,10);
-      UInt    nn    = INSN(9,5);
-      UInt    dd    = INSN(4,0);
-      UInt    ix    = (INSN(21,21) << 1) | INSN(15,15);
-      IRType  ty    = isD ? Ity_F64 : Ity_F32;
-      IROp    opADD = mkADDF(ty);
-      IROp    opSUB = mkSUBF(ty);
-      IROp    opMUL = mkMULF(ty);
-      IROp    opNEG = mkNEGF(ty);
-      IRTemp  res   = newTemp(ty);
-      IRExpr* eA    = getQRegLO(aa, ty);
-      IRExpr* eN    = getQRegLO(nn, ty);
-      IRExpr* eM    = getQRegLO(mm, ty);
-      IRExpr* rm    = mkexpr(mk_get_IR_rounding_mode());
-      IRExpr* eNxM  = triop(opMUL, rm, eN, eM);
-      switch (ix) {
-         case 0:  assign(res, triop(opADD, rm, eA, eNxM)); break;
-         case 1:  assign(res, triop(opSUB, rm, eA, eNxM)); break;
-         case 2:  assign(res, unop(opNEG, triop(opADD, rm, eA, eNxM))); break;
-         case 3:  assign(res, unop(opNEG, triop(opSUB, rm, eA, eNxM))); break;
-         default: vassert(0);
-      }
-      putQReg128(dd, mkV128(0x0000));
-      putQRegLO(dd, mkexpr(res));
-      const HChar* names[4] = { "fmadd", "fmsub", "fnmadd", "fnmsub" };
-      DIP("%s %s, %s, %s, %s\n",
-          names[ix], nameQRegLO(dd, ty), nameQRegLO(nn, ty),
-                     nameQRegLO(mm, ty), nameQRegLO(aa, ty));
-      return True;
-   }
-
-   /* -------- FCVT{N,P,M,Z}{S,U} (scalar, integer) -------- */
-   /*    30       23   20 18  15     9 4
-      sf 00 11110 0x 1 00 000 000000 n d  FCVTNS Rd, Fn (round to
-      sf 00 11110 0x 1 00 001 000000 n d  FCVTNU Rd, Fn  nearest)
-      ---------------- 01 --------------  FCVTP-------- (round to +inf)
-      ---------------- 10 --------------  FCVTM-------- (round to -inf)
-      ---------------- 11 --------------  FCVTZ-------- (round to zero)
-
-      Rd is Xd when sf==1, Wd when sf==0
-      Fn is Dn when x==1, Sn when x==0
-      20:19 carry the rounding mode, using the same encoding as FPCR
-   */
-   if (INSN(30,23) == BITS8(0,0,1,1,1,1,0,0) && INSN(21,21) == 1
-       && INSN(18,17) == BITS2(0,0) && INSN(15,10) == BITS6(0,0,0,0,0,0)) {
-      Bool isI64 = INSN(31,31) == 1;
-      Bool isF64 = INSN(22,22) == 1;
-      UInt rm    = INSN(20,19);
-      Bool isU   = INSN(16,16) == 1;
-      UInt nn    = INSN(9,5);
-      UInt dd    = INSN(4,0);
-      /* Decide on the IR rounding mode to use. */
-      IRRoundingMode irrm = 8; /*impossible*/
-      HChar ch = '?';
-      switch (rm) {
-         case BITS2(0,0): ch = 'n'; irrm = Irrm_NEAREST; break;
-         case BITS2(0,1): ch = 'p'; irrm = Irrm_PosINF; break;
-         case BITS2(1,0): ch = 'm'; irrm = Irrm_NegINF; break;
-         case BITS2(1,1): ch = 'z'; irrm = Irrm_ZERO; break;
-         default: vassert(0);
-      }
-      vassert(irrm != 8);
-      /* Decide on the conversion primop, based on the source size,
-         dest size and signedness (8 possibilities).  Case coding:
-            F32 ->s I32   0
-            F32 ->u I32   1
-            F32 ->s I64   2
-            F32 ->u I64   3
-            F64 ->s I32   4
-            F64 ->u I32   5
-            F64 ->s I64   6
-            F64 ->u I64   7
-      */
-      UInt ix = (isF64 ? 4 : 0) | (isI64 ? 2 : 0) | (isU ? 1 : 0);
-      vassert(ix < 8);
-      const IROp ops[8] 
-         = { Iop_F32toI32S, Iop_F32toI32U, Iop_F32toI64S, Iop_F32toI64U,
-             Iop_F64toI32S, Iop_F64toI32U, Iop_F64toI64S, Iop_F64toI64U };
-      IROp op = ops[ix];
-      // A bit of ATCery: bounce all cases we haven't seen an example of.
-      if (/* F32toI32S */
-             (op == Iop_F32toI32S && irrm == Irrm_ZERO)   /* FCVTZS Wd,Sn */
-          || (op == Iop_F32toI32S && irrm == Irrm_NegINF) /* FCVTMS Wd,Sn */
-          || (op == Iop_F32toI32S && irrm == Irrm_PosINF) /* FCVTPS Wd,Sn */
-          /* F32toI32U */
-          || (op == Iop_F32toI32U && irrm == Irrm_ZERO)   /* FCVTZU Wd,Sn */
-          || (op == Iop_F32toI32U && irrm == Irrm_NegINF) /* FCVTMU Wd,Sn */
-          /* F32toI64S */
-          || (op == Iop_F32toI64S && irrm == Irrm_ZERO)   /* FCVTZS Xd,Sn */
-          /* F32toI64U */
-          || (op == Iop_F32toI64U && irrm == Irrm_ZERO)   /* FCVTZU Xd,Sn */
-          /* F64toI32S */
-          || (op == Iop_F64toI32S && irrm == Irrm_ZERO)   /* FCVTZS Wd,Dn */
-          || (op == Iop_F64toI32S && irrm == Irrm_NegINF) /* FCVTMS Wd,Dn */
-          || (op == Iop_F64toI32S && irrm == Irrm_PosINF) /* FCVTPS Wd,Dn */
-          /* F64toI32U */
-          || (op == Iop_F64toI32U && irrm == Irrm_ZERO)   /* FCVTZU Wd,Dn */
-          || (op == Iop_F64toI32U && irrm == Irrm_NegINF) /* FCVTMU Wd,Dn */
-          || (op == Iop_F64toI32U && irrm == Irrm_PosINF) /* FCVTPU Wd,Dn */
-          /* F64toI64S */
-          || (op == Iop_F64toI64S && irrm == Irrm_ZERO)   /* FCVTZS Xd,Dn */
-          || (op == Iop_F64toI64S && irrm == Irrm_NegINF) /* FCVTMS Xd,Dn */
-          || (op == Iop_F64toI64S && irrm == Irrm_PosINF) /* FCVTPS Xd,Dn */
-          /* F64toI64U */
-          || (op == Iop_F64toI64U && irrm == Irrm_ZERO)   /* FCVTZU Xd,Dn */
-          || (op == Iop_F64toI64U && irrm == Irrm_PosINF) /* FCVTPU Xd,Dn */
-         ) {
-        /* validated */
-      } else {
-        return False;
-      }
-      IRType srcTy  = isF64 ? Ity_F64 : Ity_F32;
-      IRType dstTy  = isI64 ? Ity_I64 : Ity_I32;
-      IRTemp src    = newTemp(srcTy);
-      IRTemp dst    = newTemp(dstTy);
-      assign(src, getQRegLO(nn, srcTy));
-      assign(dst, binop(op, mkU32(irrm), mkexpr(src)));
-      putIRegOrZR(isI64, dd, mkexpr(dst));
-      DIP("fcvt%c%c %s, %s\n", ch, isU ? 'u' : 's',
-          nameIRegOrZR(isI64, dd), nameQRegLO(nn, srcTy));
-      return True;
-   }
-
-   /* -------- FCVTAS (KLUDGED) (scalar, integer) -------- */
-   /*   30       23   20 18  15     9 4
-      1 00 11110 0x 1 00 100 000000 n d  FCVTAS Xd, Fn
-      0 00 11110 0x 1 00 100 000000 n d  FCVTAS Wd, Fn
-      Fn is Dn when x==1, Sn when x==0
-   */
-   if (INSN(30,23) == BITS8(0,0,1,1,1,1,0,0)
-       && INSN(21,16) == BITS6(1,0,0,1,0,0)
-       && INSN(15,10) == BITS6(0,0,0,0,0,0)) {
-      Bool isI64 = INSN(31,31) == 1;
-      Bool isF64 = INSN(22,22) == 1;
-      UInt nn    = INSN(9,5);
-      UInt dd    = INSN(4,0);
-      /* Decide on the IR rounding mode to use. */
-      /* KLUDGE: should be Irrm_NEAREST_TIE_AWAY_0 */
-      IRRoundingMode irrm = Irrm_NEAREST;
-      /* Decide on the conversion primop. */
-      IROp   op    = isI64 ? (isF64 ? Iop_F64toI64S :  Iop_F32toI64S)
-                           : (isF64 ? Iop_F64toI32S :  Iop_F32toI32S);
-      IRType srcTy = isF64 ? Ity_F64 : Ity_F32;
-      IRType dstTy = isI64 ? Ity_I64 : Ity_I32;
-      IRTemp src   = newTemp(srcTy);
-      IRTemp dst   = newTemp(dstTy);
-      assign(src, getQRegLO(nn, srcTy));
-      assign(dst, binop(op, mkU32(irrm), mkexpr(src)));
-      putIRegOrZR(isI64, dd, mkexpr(dst));
-      DIP("fcvtas %s, %s (KLUDGED)\n",
-          nameIRegOrZR(isI64, dd), nameQRegLO(nn, srcTy));
-      return True;
-   }
-
-   /* ---------------- FRINT{I,M,P,Z} (scalar) ---------------- */
-   /* 31        23 21   17  14    9 4
-      000 11110 0x 1001 111 10000 n d  FRINTI Fd, Fm (round per FPCR)
-                        rm
-      x==0 => S-registers, x==1 => D-registers
-      rm (17:15) encodings:
-         111 per FPCR  (FRINTI)
-         001 +inf      (FRINTP)
-         010 -inf      (FRINTM)
-         011 zero      (FRINTZ)
-         000 tieeven
-         100 tieaway   (FRINTA) -- !! FIXME KLUDGED !!
-         110 per FPCR + "exact = TRUE"
-         101 unallocated
-   */
-   if (INSN(31,23) == BITS9(0,0,0,1,1,1,1,0,0)
-       && INSN(21,18) == BITS4(1,0,0,1) && INSN(14,10) == BITS5(1,0,0,0,0)) {
-      Bool    isD   = INSN(22,22) == 1;
-      UInt    rm    = INSN(17,15);
-      UInt    nn    = INSN(9,5);
-      UInt    dd    = INSN(4,0);
-      IRType  ty    = isD ? Ity_F64 : Ity_F32;
-      IRExpr* irrmE = NULL;
-      UChar   ch    = '?';
-      switch (rm) {
-         case BITS3(0,1,1): ch = 'z'; irrmE = mkU32(Irrm_ZERO); break;
-         case BITS3(0,1,0): ch = 'm'; irrmE = mkU32(Irrm_NegINF); break;
-         case BITS3(0,0,1): ch = 'p'; irrmE = mkU32(Irrm_PosINF); break;
-         // The following is a kludge.  Should be: Irrm_NEAREST_TIE_AWAY_0
-         case BITS3(1,0,0): ch = 'a'; irrmE = mkU32(Irrm_NEAREST); break;
-         default: break;
-      }
-      if (irrmE) {
-         IRTemp src = newTemp(ty);
-         IRTemp dst = newTemp(ty);
-         assign(src, getQRegLO(nn, ty));
-         assign(dst, binop(isD ? Iop_RoundF64toInt : Iop_RoundF32toInt,
-                           irrmE, mkexpr(src)));
-         putQReg128(dd, mkV128(0x0000));
-         putQRegLO(dd, mkexpr(dst));
-         DIP("frint%c %s, %s\n",
-             ch, nameQRegLO(dd, ty), nameQRegLO(nn, ty));
-         return True;
-      }
-      /* else unhandled rounding mode case -- fall through */
-   }
-
-   /* ------------------ FCVT (scalar) ------------------ */
-   /* 31        23 21    16 14    9 4
-      000 11110 11 10001 00 10000 n d   FCVT Sd, Hn (unimp)
-      --------- 11 ----- 01 ---------   FCVT Dd, Hn (unimp)
-      --------- 00 ----- 11 ---------   FCVT Hd, Sn (unimp)
-      --------- 00 ----- 01 ---------   FCVT Dd, Sn
-      --------- 01 ----- 11 ---------   FCVT Hd, Dn (unimp)
-      --------- 01 ----- 00 ---------   FCVT Sd, Dn
-      Rounding, when dst is smaller than src, is per the FPCR.
-   */
-   if (INSN(31,24) == BITS8(0,0,0,1,1,1,1,0)
-       && INSN(21,17) == BITS5(1,0,0,0,1) 
-       && INSN(14,10) == BITS5(1,0,0,0,0)) {
-      UInt b2322 = INSN(23,22);
-      UInt b1615 = INSN(16,15);
-      UInt nn    = INSN(9,5);
-      UInt dd    = INSN(4,0);
-      if (b2322 == BITS2(0,0) && b1615 == BITS2(0,1)) {
-         /* Convert S to D */
-         IRTemp res = newTemp(Ity_F64);
-         assign(res, unop(Iop_F32toF64, getQRegLO(nn, Ity_F32)));
-         putQReg128(dd, mkV128(0x0000));
-         putQRegLO(dd, mkexpr(res));
-         DIP("fcvt %s, %s\n",
-             nameQRegLO(dd, Ity_F64), nameQRegLO(nn, Ity_F32));
-         return True;
-      }
-      if (b2322 == BITS2(0,1) && b1615 == BITS2(0,0)) {
-         /* Convert D to S */
-         IRTemp res = newTemp(Ity_F32);
-         assign(res, binop(Iop_F64toF32, mkexpr(mk_get_IR_rounding_mode()),
-                                         getQRegLO(nn, Ity_F64)));
-         putQReg128(dd, mkV128(0x0000));
-         putQRegLO(dd, mkexpr(res));
-         DIP("fcvt %s, %s\n",
-             nameQRegLO(dd, Ity_F32), nameQRegLO(nn, Ity_F64));
-         return True;
-      }
-      /* else unhandled */
-   }
-
-   /* ------------------ FABD (scalar) ------------------ */
-   /* 31        23  20 15     9 4
-      011 11110 111 m  110101 n d  FABD  Dd, Dn, Dm
-      011 11110 101 m  110101 n d  FABD  Sd, Sn, Sm
-   */
-   if (INSN(31,23) == BITS9(0,1,1,1,1,1,1,0,1) && INSN(21,21) == 1
-       && INSN(15,10) == BITS6(1,1,0,1,0,1)) {
-      Bool   isD = INSN(22,22) == 1;
-      UInt   mm  = INSN(20,16);
-      UInt   nn  = INSN(9,5);
-      UInt   dd  = INSN(4,0);
-      IRType ty  = isD ? Ity_F64 : Ity_F32;
-      IRTemp res = newTemp(ty);
-      assign(res, unop(mkABSF(ty),
-                       triop(mkSUBF(ty),
-                             mkexpr(mk_get_IR_rounding_mode()),
-                             getQRegLO(nn,ty), getQRegLO(mm,ty))));
-      putQReg128(dd, mkV128(0x0000));
-      putQRegLO(dd, mkexpr(res));
-      DIP("fabd %s, %s, %s\n",
-          nameQRegLO(dd, ty), nameQRegLO(nn, ty), nameQRegLO(mm, ty));
-      return True;
-   }
-
-   /* -------------- {S,U}CVTF (vector, integer) -------------- */
-   /* 31  28      22 21       15     9 4
-      0q0 01110 0 sz 1  00001 110110 n d  SCVTF Vd, Vn
-      0q1 01110 0 sz 1  00001 110110 n d  UCVTF Vd, Vn
-      with laneage:
-      case sz:Q of 00 -> 2S, zero upper, 01 -> 4S, 10 -> illegal, 11 -> 2D
-   */
-   if (INSN(31,31) == 0 && INSN(28,23) == BITS6(0,1,1,1,0,0)
-       && INSN(21,16) == BITS6(1,0,0,0,0,1)
-       && INSN(15,10) == BITS6(1,1,0,1,1,0)) {
-      Bool isQ   = INSN(30,30) == 1;
-      Bool isU   = INSN(29,29) == 1;
-      Bool isF64 = INSN(22,22) == 1;
-      UInt nn    = INSN(9,5);
-      UInt dd    = INSN(4,0);
-      if (isQ || !isF64) {
-         IRType tyF = Ity_INVALID, tyI = Ity_INVALID;
-         UInt   nLanes = 0;
-         Bool   zeroHI = False;
-         const HChar* arrSpec = NULL;
-         Bool   ok = getLaneInfo_Q_SZ(&tyI, &tyF, &nLanes, &zeroHI, &arrSpec,
-                                      isQ, isF64 );
-         IROp   op = isU ? (isF64 ? Iop_I64UtoF64 : Iop_I32UtoF32)
-                         : (isF64 ? Iop_I64StoF64 : Iop_I32StoF32);
-         IRTemp rm = mk_get_IR_rounding_mode();
-         UInt   i;
-         vassert(ok); /* the 'if' above should ensure this */
-         for (i = 0; i < nLanes; i++) {
-            putQRegLane(dd, i,
-                        binop(op, mkexpr(rm), getQRegLane(nn, i, tyI)));
-         }
-         if (zeroHI) {
-            putQRegLane(dd, 1, mkU64(0));
-         }
-         DIP("%ccvtf %s.%s, %s.%s\n", isU ? 'u' : 's',
-             nameQReg128(dd), arrSpec, nameQReg128(nn), arrSpec);
-         return True;      }
-      /* else fall through */
-   }
-
-   /* ---------- F{ADD,SUB,MUL,DIV,MLA,MLS} (vector) ---------- */
-   /* 31  28      22 21 20 15     9 4                  case
-      0q0 01110 0 sz 1  m  110101 n d  FADD Vd,Vn,Vm   1
-      0q0 01110 1 sz 1  m  110101 n d  FSUB Vd,Vn,Vm   2
-      0q1 01110 0 sz 1  m  110111 n d  FMUL Vd,Vn,Vm   3
-      0q1 01110 0 sz 1  m  111111 n d  FDIV Vd,Vn,Vm   4
-      0q0 01110 0 sz 1  m  110011 n d  FMLA Vd,Vn,Vm   5
-      0q0 01110 1 sz 1  m  110011 n d  FMLS Vd,Vn,Vm   6
-      0q1 01110 1 sz 1  m  110101 n d  FABD Vd,Vn,Vm   7
-   */
-   if (INSN(31,31) == 0
-       && INSN(28,24) == BITS5(0,1,1,1,0) && INSN(21,21) == 1) {
-      Bool isQ   = INSN(30,30) == 1;
-      UInt b29   = INSN(29,29);
-      UInt b23   = INSN(23,23);
-      Bool isF64 = INSN(22,22) == 1;
-      UInt mm    = INSN(20,16);
-      UInt b1510 = INSN(15,10);
-      UInt nn    = INSN(9,5);
-      UInt dd    = INSN(4,0);
-      UInt ix    = 0;
-      /**/ if (b29 == 0 && b23 == 0 && b1510 == BITS6(1,1,0,1,0,1)) ix = 1;
-      else if (b29 == 0 && b23 == 1 && b1510 == BITS6(1,1,0,1,0,1)) ix = 2;
-      else if (b29 == 1 && b23 == 0 && b1510 == BITS6(1,1,0,1,1,1)) ix = 3;
-      else if (b29 == 1 && b23 == 0 && b1510 == BITS6(1,1,1,1,1,1)) ix = 4;
-      else if (b29 == 0 && b23 == 0 && b1510 == BITS6(1,1,0,0,1,1)) ix = 5;
-      else if (b29 == 0 && b23 == 1 && b1510 == BITS6(1,1,0,0,1,1)) ix = 6;
-      else if (b29 == 1 && b23 == 1 && b1510 == BITS6(1,1,0,1,0,1)) ix = 7;
-      IRType laneTy = Ity_INVALID;
-      Bool   zeroHI = False;
-      const HChar* arr = "??";
-      Bool ok
-         = getLaneInfo_Q_SZ(NULL, &laneTy, NULL, &zeroHI, &arr, isQ, isF64);
-      /* Skip MLA/MLS for the time being */
-      if (ok && ix >= 1 && ix <= 4) {
-         const IROp ops64[4]
-            = { Iop_Add64Fx2, Iop_Sub64Fx2, Iop_Mul64Fx2, Iop_Div64Fx2 };
-         const IROp ops32[4]
-            = { Iop_Add32Fx4, Iop_Sub32Fx4, Iop_Mul32Fx4, Iop_Div32Fx4 };
-         const HChar* names[4]
-            = { "fadd", "fsub", "fmul", "fdiv" };
-         IROp   op = laneTy==Ity_F64 ? ops64[ix-1] : ops32[ix-1];
-         IRTemp rm = mk_get_IR_rounding_mode();
-         IRTemp t1 = newTemp(Ity_V128);
-         IRTemp t2 = newTemp(Ity_V128);
-         assign(t1, triop(op, mkexpr(rm), getQReg128(nn), getQReg128(mm)));
-         assign(t2, zeroHI ? unop(Iop_ZeroHI64ofV128, mkexpr(t1))
-                           : mkexpr(t1));
-         putQReg128(dd, mkexpr(t2));
-         DIP("%s %s.%s, %s.%s, %s.%s\n", names[ix-1],
-             nameQReg128(dd), arr, nameQReg128(nn), arr, nameQReg128(mm), arr);
-         return True;
-      }
-      if (ok && ix >= 5 && ix <= 6) {
-         IROp opADD = laneTy==Ity_F64 ? Iop_Add64Fx2 : Iop_Add32Fx4;
-         IROp opSUB = laneTy==Ity_F64 ? Iop_Sub64Fx2 : Iop_Sub32Fx4;
-         IROp opMUL = laneTy==Ity_F64 ? Iop_Mul64Fx2 : Iop_Mul32Fx4;
-         IRTemp rm = mk_get_IR_rounding_mode();
-         IRTemp t1 = newTemp(Ity_V128);
-         IRTemp t2 = newTemp(Ity_V128);
-         // FIXME: double rounding; use FMA primops instead
-         assign(t1, triop(opMUL,
-                          mkexpr(rm), getQReg128(nn), getQReg128(mm)));
-         assign(t2, triop(ix == 5 ? opADD : opSUB,
-                          mkexpr(rm), getQReg128(dd), mkexpr(t1)));
-         putQReg128(dd, zeroHI ? unop(Iop_ZeroHI64ofV128, mkexpr(t2))
-                               : mkexpr(t2));
-         DIP("%s %s.%s, %s.%s, %s.%s\n", ix == 5 ? "fmla" : "fmls",
-             nameQReg128(dd), arr, nameQReg128(nn), arr, nameQReg128(mm), arr);
-         return True;
-      }
-      if (ok && ix == 7) {
-         IROp opSUB = laneTy==Ity_F64 ? Iop_Sub64Fx2 : Iop_Sub32Fx4;
-         IROp opABS = laneTy==Ity_F64 ? Iop_Abs64Fx2 : Iop_Abs32Fx4;
-         IRTemp rm = mk_get_IR_rounding_mode();
-         IRTemp t1 = newTemp(Ity_V128);
-         IRTemp t2 = newTemp(Ity_V128);
-         // FIXME: use Abd primop instead?
-         assign(t1, triop(opSUB,
-                          mkexpr(rm), getQReg128(nn), getQReg128(mm)));
-         assign(t2, unop(opABS, mkexpr(t1)));
-         putQReg128(dd, zeroHI ? unop(Iop_ZeroHI64ofV128, mkexpr(t2))
-                               : mkexpr(t2));
-         DIP("fabd %s.%s, %s.%s, %s.%s\n",
-             nameQReg128(dd), arr, nameQReg128(nn), arr, nameQReg128(mm), arr);
-         return True;
-      }
-   }
-
-   /* ------------ FCM{EQ,GE,GT}, FAC{GE,GT} (vector) ------------ */
-   /* 31  28      22   20 15     9 4                  case
-      0q1 01110 0 sz 1 m  111011 n d  FACGE Vd, Vn, Vm
-      0q1 01110 1 sz 1 m  111011 n d  FACGT Vd, Vn, Vm
-      0q0 01110 0 sz 1 m  111001 n d  FCMEQ Vd, Vn, Vm
-      0q1 01110 0 sz 1 m  111001 n d  FCMGE Vd, Vn, Vm
-      0q1 01110 1 sz 1 m  111001 n d  FCMGT Vd, Vn, Vm
-   */
-   if (INSN(31,31) == 0 && INSN(28,24) == BITS5(0,1,1,1,0) && INSN(21,21) == 1
-       && INSN(15,12) == BITS4(1,1,1,0) && INSN(10,10) == 1) {
-      Bool isQ   = INSN(30,30) == 1;
-      UInt U     = INSN(29,29);
-      UInt E     = INSN(23,23);
-      Bool isF64 = INSN(22,22) == 1;
-      UInt ac    = INSN(11,11);
-      UInt mm    = INSN(20,16);
-      UInt nn    = INSN(9,5);
-      UInt dd    = INSN(4,0);
-      /* */
-      UInt   EUac   = (E << 2) | (U << 1) | ac;
-      IROp   opABS  = Iop_INVALID;
-      IROp   opCMP  = Iop_INVALID;
-      IRType laneTy = Ity_INVALID;
-      Bool   zeroHI = False;
-      Bool   swap   = True;
-      const HChar* arr = "??";
-      const HChar* nm  = "??";
-      Bool ok
-         = getLaneInfo_Q_SZ(NULL, &laneTy, NULL, &zeroHI, &arr, isQ, isF64);
-      if (ok) {
-         vassert((isF64 && laneTy == Ity_F64) || (!isF64 && laneTy == Ity_F32));
-         switch (EUac) {
-            case BITS3(0,0,0):
-               nm    = "fcmeq";
-               opCMP = isF64 ? Iop_CmpEQ64Fx2 : Iop_CmpEQ32Fx4;
-               swap  = False;
-               break;
-            case BITS3(0,1,0):
-               nm    = "fcmge";
-               opCMP = isF64 ? Iop_CmpLE64Fx2 : Iop_CmpLE32Fx4;
-               break;
-            case BITS3(0,1,1):
-               nm    = "facge";
-               opCMP = isF64 ? Iop_CmpLE64Fx2 : Iop_CmpLE32Fx4;
-               opABS = isF64 ? Iop_Abs64Fx2 : Iop_Abs32Fx4;
-               break;
-            case BITS3(1,1,0):
-               nm    = "fcmgt";
-               opCMP = isF64 ? Iop_CmpLT64Fx2 : Iop_CmpLT32Fx4;
-               break;
-            case BITS3(1,1,1):
-               nm    = "facgt";
-               opCMP = isF64 ? Iop_CmpLE64Fx2 : Iop_CmpLE32Fx4; // wrong?
-               opABS = isF64 ? Iop_Abs64Fx2 : Iop_Abs32Fx4;
-               break;
-            default:
-               break;
-         }
-      }
-      if (opCMP != Iop_INVALID) {
-         IRExpr* argN = getQReg128(nn);
-         IRExpr* argM = getQReg128(mm);
-         if (opABS != Iop_INVALID) {
-            argN = unop(opABS, argN);
-            argM = unop(opABS, argM);
-         }
-         IRExpr* res = swap ? binop(opCMP, argM, argN)
-                            : binop(opCMP, argN, argM);
-         if (zeroHI) {
-            res = unop(Iop_ZeroHI64ofV128, res);
-         }
-         putQReg128(dd, res);
-         DIP("%s %s.%s, %s.%s, %s.%s\n", nm,
-             nameQReg128(dd), arr, nameQReg128(nn), arr, nameQReg128(mm), arr);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* -------------------- FCVTN -------------------- */
-   /* 31  28    23  20    15     9 4
-      0q0 01110 0s1 00001 011010 n d  FCVTN Vd, Vn
-      where case q:s of 00: 16Fx4(lo) <- 32Fx4
-                        01: 32Fx2(lo) <- 64Fx2
-                        10: 16Fx4(hi) <- 32Fx4
-                        11: 32Fx2(hi) <- 64Fx2
-      Only deals with the 32Fx2 <- 64Fx2 version (s==1)
-   */
-   if (INSN(31,31) == 0 && INSN(29,23) == BITS7(0,0,1,1,1,0,0)
-       && INSN(21,10) == BITS12(1,0,0,0,0,1,0,1,1,0,1,0)) {
-      UInt bQ = INSN(30,30);
-      UInt bS = INSN(22,22);
-      UInt nn = INSN(9,5);
-      UInt dd = INSN(4,0);
-      if (bS == 1) {
-         IRTemp  rm    = mk_get_IR_rounding_mode();
-         IRExpr* srcLo = getQRegLane(nn, 0, Ity_F64);
-         IRExpr* srcHi = getQRegLane(nn, 1, Ity_F64);
-         putQRegLane(dd, 2 * bQ + 0, binop(Iop_F64toF32, mkexpr(rm), srcLo));
-         putQRegLane(dd, 2 * bQ + 1, binop(Iop_F64toF32, mkexpr(rm), srcHi));
-         if (bQ == 0) {
-            putQRegLane(dd, 1, mkU64(0));
-         }
-         DIP("fcvtn%s %s.%s, %s.2d\n", bQ ? "2" : "",
-             nameQReg128(dd), bQ ? "4s" : "2s", nameQReg128(nn));
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* ---------------- ADD/SUB (vector) ---------------- */
-   /* 31  28    23   21 20 15     9 4
-      0q0 01110 size 1  m  100001 n d  ADD Vd.T, Vn.T, Vm.T
-      0q1 01110 size 1  m  100001 n d  SUB Vd.T, Vn.T, Vm.T
-   */
-   if (INSN(31,31) == 0 && INSN(28,24) == BITS5(0,1,1,1,0)
-       && INSN(21,21) == 1 && INSN(15,10) == BITS6(1,0,0,0,0,1)) {
-      Bool isQ    = INSN(30,30) == 1;
-      UInt szBlg2 = INSN(23,22);
-      Bool isSUB  = INSN(29,29) == 1;
-      UInt mm     = INSN(20,16);
-      UInt nn     = INSN(9,5);
-      UInt dd     = INSN(4,0);
-      Bool zeroHI = False;
-      const HChar* arrSpec = "";
-      Bool ok = getLaneInfo_SIMPLE(&zeroHI, &arrSpec, isQ, szBlg2 );
-      if (ok) {
-         const IROp opsADD[4]
-            = { Iop_Add8x16, Iop_Add16x8, Iop_Add32x4, Iop_Add64x2 };
-         const IROp opsSUB[4]
-            = { Iop_Sub8x16, Iop_Sub16x8, Iop_Sub32x4, Iop_Sub64x2 };
-         vassert(szBlg2 < 4);
-         IROp   op = isSUB ? opsSUB[szBlg2] : opsADD[szBlg2];
-         IRTemp t  = newTemp(Ity_V128);
-         assign(t, binop(op, getQReg128(nn), getQReg128(mm)));
-         putQReg128(dd, zeroHI ? unop(Iop_ZeroHI64ofV128, mkexpr(t))
-                               : mkexpr(t));
-         const HChar* nm = isSUB ? "sub" : "add";
-         DIP("%s %s.%s, %s.%s, %s.%s\n", nm,
-             nameQReg128(dd), arrSpec, 
-             nameQReg128(nn), arrSpec, nameQReg128(mm), arrSpec);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* ---------------- ADD/SUB (scalar) ---------------- */
-   /* 31  28    23 21 20 15     9 4
-      010 11110 11 1  m  100001 n d  ADD Dd, Dn, Dm
-      011 11110 11 1  m  100001 n d  SUB Dd, Dn, Dm
-   */
-   if (INSN(31,30) == BITS2(0,1) && INSN(28,21) == BITS8(1,1,1,1,0,1,1,1)
-       && INSN(15,10) == BITS6(1,0,0,0,0,1)) {
-      Bool isSUB = INSN(29,29) == 1;
-      UInt mm    = INSN(20,16);
-      UInt nn    = INSN(9,5);
-      UInt dd    = INSN(4,0);
-      IRTemp res = newTemp(Ity_I64);
-      assign(res, binop(isSUB ? Iop_Sub64 : Iop_Add64,
-                        getQRegLane(nn, 0, Ity_I64),
-                        getQRegLane(mm, 0, Ity_I64)));
-      putQRegLane(dd, 0, mkexpr(res));
-      putQRegLane(dd, 1, mkU64(0));
-      DIP("%s %s, %s, %s\n", isSUB ? "sub" : "add",
-          nameQRegLO(dd, Ity_I64),
-          nameQRegLO(nn, Ity_I64), nameQRegLO(mm, Ity_I64));
-      return True;
-   }
-
-   /* ------------ MUL/PMUL/MLA/MLS (vector) ------------ */
-   /* 31  28    23   21 20 15     9 4
-      0q0 01110 size 1  m  100111 n d  MUL  Vd.T, Vn.T, Vm.T  B/H/S only
-      0q1 01110 size 1  m  100111 n d  PMUL Vd.T, Vn.T, Vm.T  B only
-      0q0 01110 size 1  m  100101 n d  MLA  Vd.T, Vn.T, Vm.T  B/H/S only
-      0q1 01110 size 1  m  100101 n d  MLS  Vd.T, Vn.T, Vm.T  B/H/S only
-   */
-   if (INSN(31,31) == 0 && INSN(28,24) == BITS5(0,1,1,1,0)
-       && INSN(21,21) == 1 
-       && (INSN(15,10) & BITS6(1,1,1,1,0,1)) == BITS6(1,0,0,1,0,1)) {
-      Bool isQ    = INSN(30,30) == 1;
-      UInt szBlg2 = INSN(23,22);
-      UInt bit29  = INSN(29,29);
-      UInt mm     = INSN(20,16);
-      UInt nn     = INSN(9,5);
-      UInt dd     = INSN(4,0);
-      Bool isMLAS = INSN(11,11) == 0;
-      const IROp opsADD[4]
-         = { Iop_Add8x16, Iop_Add16x8, Iop_Add32x4, Iop_INVALID };
-      const IROp opsSUB[4]
-         = { Iop_Sub8x16, Iop_Sub16x8, Iop_Sub32x4, Iop_INVALID };
-      const IROp opsMUL[4]
-         = { Iop_Mul8x16, Iop_Mul16x8, Iop_Mul32x4, Iop_INVALID };
-      const IROp opsPMUL[4]
-         = { Iop_PolynomialMul8x16, Iop_INVALID, Iop_INVALID, Iop_INVALID };
-      /* Set opMUL and, if necessary, opACC.  A result value of
-         Iop_INVALID for opMUL indicates that the instruction is
-         invalid. */
-      Bool zeroHI = False;
-      const HChar* arrSpec = "";
-      Bool ok = getLaneInfo_SIMPLE(&zeroHI, &arrSpec, isQ, szBlg2 );
-      vassert(szBlg2 < 4);
-      IROp opACC = Iop_INVALID;
-      IROp opMUL = Iop_INVALID;
-      if (ok) {
-         opMUL = (bit29 == 1 && !isMLAS) ? opsPMUL[szBlg2]
-                                         : opsMUL[szBlg2];
-         opACC = isMLAS ? (bit29 == 1 ? opsSUB[szBlg2] : opsADD[szBlg2])
-                        : Iop_INVALID;
-      }
-      if (ok && opMUL != Iop_INVALID) {
-         IRTemp t1 = newTemp(Ity_V128);
-         assign(t1, binop(opMUL, getQReg128(nn), getQReg128(mm)));
-         IRTemp t2 = newTemp(Ity_V128);
-         assign(t2, opACC == Iop_INVALID
-                       ? mkexpr(t1)
-                       : binop(opACC, getQReg128(dd), mkexpr(t1)));
-         putQReg128(dd, zeroHI ? unop(Iop_ZeroHI64ofV128, mkexpr(t2))
-                               : mkexpr(t2));
-         const HChar* nm = isMLAS ? (bit29 == 1 ? "mls" : "mla")
-                                  : (bit29 == 1 ? "pmul" : "mul");
-         DIP("%s %s.%s, %s.%s, %s.%s\n", nm,
-             nameQReg128(dd), arrSpec, 
-             nameQReg128(nn), arrSpec, nameQReg128(mm), arrSpec);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* ---------------- {S,U}{MIN,MAX} (vector) ---------------- */
-   /* 31  28    23   21 20 15     9 4
-      0q0 01110 size 1  m  011011 n d  SMIN Vd.T, Vn.T, Vm.T
-      0q1 01110 size 1  m  011011 n d  UMIN Vd.T, Vn.T, Vm.T
-      0q0 01110 size 1  m  011001 n d  SMAX Vd.T, Vn.T, Vm.T
-      0q1 01110 size 1  m  011001 n d  UMAX Vd.T, Vn.T, Vm.T
-   */
-   if (INSN(31,31) == 0 && INSN(28,24) == BITS5(0,1,1,1,0)
-       && INSN(21,21) == 1
-       && ((INSN(15,10) & BITS6(1,1,1,1,0,1)) == BITS6(0,1,1,0,0,1))) {
-      Bool isQ    = INSN(30,30) == 1;
-      Bool isU    = INSN(29,29) == 1;
-      UInt szBlg2 = INSN(23,22);
-      Bool isMAX  = INSN(11,11) == 0;
-      UInt mm     = INSN(20,16);
-      UInt nn     = INSN(9,5);
-      UInt dd     = INSN(4,0);
-      Bool zeroHI = False;
-      const HChar* arrSpec = "";
-      Bool ok = getLaneInfo_SIMPLE(&zeroHI, &arrSpec, isQ, szBlg2 );
-      if (ok) {
-         const IROp opMINS[4]
-            = { Iop_Min8Sx16, Iop_Min16Sx8, Iop_Min32Sx4, Iop_Min64Sx2 };
-         const IROp opMINU[4]
-            = { Iop_Min8Ux16, Iop_Min16Ux8, Iop_Min32Ux4, Iop_Min64Ux2 };
-         const IROp opMAXS[4]
-            = { Iop_Max8Sx16, Iop_Max16Sx8, Iop_Max32Sx4, Iop_Max64Sx2 };
-         const IROp opMAXU[4]
-            = { Iop_Max8Ux16, Iop_Max16Ux8, Iop_Max32Ux4, Iop_Max64Ux2 };
-         vassert(szBlg2 < 4);
-         IROp op = isMAX ? (isU ? opMAXU[szBlg2] : opMAXS[szBlg2])
-                         : (isU ? opMINU[szBlg2] : opMINS[szBlg2]);
-         IRTemp t = newTemp(Ity_V128);
-         assign(t, binop(op, getQReg128(nn), getQReg128(mm)));
-         putQReg128(dd, zeroHI ? unop(Iop_ZeroHI64ofV128, mkexpr(t))
-                               : mkexpr(t));
-         const HChar* nm = isMAX ? (isU ? "umax" : "smax")
-                                 : (isU ? "umin" : "smin");
-         DIP("%s %s.%s, %s.%s, %s.%s\n", nm,
-             nameQReg128(dd), arrSpec, 
-             nameQReg128(nn), arrSpec, nameQReg128(mm), arrSpec);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* -------------------- {S,U}{MIN,MAX}V -------------------- */
-   /* 31  28    23   21    16 15     9 4
-      0q0 01110 size 11000 1  101010 n d  SMINV Vd, Vn.T
-      0q1 01110 size 11000 1  101010 n d  UMINV Vd, Vn.T
-      0q0 01110 size 11000 0  101010 n d  SMAXV Vd, Vn.T
-      0q1 01110 size 11000 0  101010 n d  UMAXV Vd, Vn.T
-   */
-   if (INSN(31,31) == 0 && INSN(28,24) == BITS5(0,1,1,1,0)
-       && INSN(21,17) == BITS5(1,1,0,0,0)
-       && INSN(15,10) == BITS6(1,0,1,0,1,0)) {
-      Bool isQ    = INSN(30,30) == 1;
-      Bool isU    = INSN(29,29) == 1;
-      UInt szBlg2 = INSN(23,22);
-      Bool isMAX  = INSN(16,16) == 0;
-      UInt nn     = INSN(9,5);
-      UInt dd     = INSN(4,0);
-      Bool zeroHI = False;
-      const HChar* arrSpec = "";
-      Bool ok = getLaneInfo_SIMPLE(&zeroHI, &arrSpec, isQ, szBlg2);
-      if (ok) {
-         if (szBlg2 == 3)         ok = False;
-         if (szBlg2 == 2 && !isQ) ok = False;
-      }
-      if (ok) {
-         const IROp opMINS[3]
-            = { Iop_Min8Sx16, Iop_Min16Sx8, Iop_Min32Sx4 };
-         const IROp opMINU[3]
-            = { Iop_Min8Ux16, Iop_Min16Ux8, Iop_Min32Ux4 };
-         const IROp opMAXS[3]
-            = { Iop_Max8Sx16, Iop_Max16Sx8, Iop_Max32Sx4 };
-         const IROp opMAXU[3]
-            = { Iop_Max8Ux16, Iop_Max16Ux8, Iop_Max32Ux4 };
-         vassert(szBlg2 < 3);
-         IROp op = isMAX ? (isU ? opMAXU[szBlg2] : opMAXS[szBlg2])
-                         : (isU ? opMINU[szBlg2] : opMINS[szBlg2]);
-         IRTemp tN1 = newTemp(Ity_V128);
-         assign(tN1, getQReg128(nn));
-         /* If Q == 0, we're just folding lanes in the lower half of
-            the value.  In which case, copy the lower half of the
-            source into the upper half, so we can then treat it the
-            same as the full width case. */
-         IRTemp tN2 = newTemp(Ity_V128);
-         assign(tN2, zeroHI ? mk_CatEvenLanes64x2(tN1,tN1) : mkexpr(tN1));
-         IRTemp res = math_MINMAXV(tN2, op);
-         if (res == IRTemp_INVALID)
-            return False; /* means math_MINMAXV
-                             doesn't handle this case yet */
-         putQReg128(dd, mkexpr(res));
-         const HChar* nm = isMAX ? (isU ? "umaxv" : "smaxv")
-                                 : (isU ? "uminv" : "sminv");
-         const IRType tys[3] = { Ity_I8, Ity_I16, Ity_I32 };
-         IRType laneTy = tys[szBlg2];
-         DIP("%s %s, %s.%s\n", nm,
-             nameQRegLO(dd, laneTy), nameQReg128(nn), arrSpec);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* ------------ {AND,BIC,ORR,ORN} (vector) ------------ */
-   /* 31  28    23  20 15     9 4
-      0q0 01110 001 m  000111 n d  AND Vd.T, Vn.T, Vm.T
-      0q0 01110 011 m  000111 n d  BIC Vd.T, Vn.T, Vm.T
-      0q0 01110 101 m  000111 n d  ORR Vd.T, Vn.T, Vm.T
-      0q0 01110 111 m  000111 n d  ORN Vd.T, Vn.T, Vm.T
-      T is 16b when q==1, 8b when q==0
-   */
-   if (INSN(31,31) == 0 && INSN(29,24) == BITS6(0,0,1,1,1,0)
-       && INSN(21,21) == 1 && INSN(15,10) == BITS6(0,0,0,1,1,1)) {
-      Bool   isQ    = INSN(30,30) == 1;
-      Bool   isORR  = INSN(23,23) == 1;
-      Bool   invert = INSN(22,22) == 1;
-      UInt   mm     = INSN(20,16);
-      UInt   nn     = INSN(9,5);
-      UInt   dd     = INSN(4,0);
-      IRTemp res    = newTemp(Ity_V128);
-      assign(res, binop(isORR ? Iop_OrV128 : Iop_AndV128,
-                        getQReg128(nn),
-                        invert ? unop(Iop_NotV128, getQReg128(mm))
-                               : getQReg128(mm)));
-      putQReg128(dd, isQ ? mkexpr(res)
-                         : unop(Iop_ZeroHI64ofV128, mkexpr(res)));
-      const HChar* names[4] = { "and", "bic", "orr", "orn" };
-      const HChar* ar = isQ ? "16b" : "8b";
-      DIP("%s %s.%s, %s.%s, %s.%s\n", names[INSN(23,22)],
-          nameQReg128(dd), ar, nameQReg128(nn), ar, nameQReg128(mm), ar);
-      return True;
-   }
-
-   /* ---------- CM{EQ,HI,HS,GE,GT,TST,LE,LT} (vector) ---------- */
-   /* 31  28    23   21     15     9 4                          ix 
-      0q1 01110 size 1  m   100011 n d  CMEQ  Vd.T, Vn.T, Vm.T  (1) ==
-      0q0 01110 size 1  m   100011 n d  CMTST Vd.T, Vn.T, Vm.T  (2) &, != 0
-
-      0q1 01110 size 1  m   001101 n d  CMHI Vd.T, Vn.T, Vm.T   (3) >u
-      0q0 01110 size 1  m   001101 n d  CMGT Vd.T, Vn.T, Vm.T   (4) >s
-
-      0q1 01110 size 1  m   001111 n d  CMHS Vd.T, Vn.T, Vm.T   (5) >=u
-      0q0 01110 size 1  m   001111 n d  CMGE Vd.T, Vn.T, Vm.T   (6) >=s
-
-      0q1 01110 size 100000 100010 n d  CMGE Vd.T, Vn.T, #0     (7) >=s 0
-      0q0 01110 size 100000 100010 n d  CMGT Vd.T, Vn.T, #0     (8) >s 0
-
-      0q1 01110 size 100000 100110 n d  CMLE Vd.T, Vn.T, #0     (9) <=s 0
-      0q0 01110 size 100000 100110 n d  CMEQ Vd.T, Vn.T, #0     (10) == 0
-
-      0q0 01110 size 100000 101010 n d  CMLT Vd.T, Vn.T, #0     (11) <s 0
-   */
-   if (INSN(31,31) == 0
-       && INSN(28,24) == BITS5(0,1,1,1,0) && INSN(21,21) == 1) {
-      Bool isQ    = INSN(30,30) == 1;
-      UInt bit29  = INSN(29,29);
-      UInt szBlg2 = INSN(23,22);
-      UInt mm     = INSN(20,16);
-      UInt b1510  = INSN(15,10);
-      UInt nn     = INSN(9,5);
-      UInt dd     = INSN(4,0);
-      const IROp opsEQ[4]
-         = { Iop_CmpEQ8x16,  Iop_CmpEQ16x8,  Iop_CmpEQ32x4,  Iop_CmpEQ64x2 };
-      const IROp opsGTS[4]
-         = { Iop_CmpGT8Sx16, Iop_CmpGT16Sx8, Iop_CmpGT32Sx4, Iop_CmpGT64Sx2 };
-      const IROp opsGTU[4]
-         = { Iop_CmpGT8Ux16, Iop_CmpGT16Ux8, Iop_CmpGT32Ux4, Iop_CmpGT64Ux2 };
-      Bool zeroHI = False;
-      const HChar* arrSpec = "??";
-      Bool ok = getLaneInfo_SIMPLE(&zeroHI, &arrSpec, isQ, szBlg2);
-      UInt ix = 0;
-      if (ok) {
-         switch (b1510) {
-            case BITS6(1,0,0,0,1,1): ix = bit29 ? 1 : 2; break;
-            case BITS6(0,0,1,1,0,1): ix = bit29 ? 3 : 4; break;
-            case BITS6(0,0,1,1,1,1): ix = bit29 ? 5 : 6; break;
-            case BITS6(1,0,0,0,1,0):
-               if (mm == 0) { ix = bit29 ? 7 : 8; }; break;
-            case BITS6(1,0,0,1,1,0):
-               if (mm == 0) { ix = bit29 ? 9 : 10; }; break;
-            case BITS6(1,0,1,0,1,0):
-               if (mm == 0 && bit29 == 0) { ix = 11; }; break;
-            default: break;
-         }
-      }
-      if (ix != 0) {
-         vassert(ok && szBlg2 < 4);
-         IRExpr* argL = getQReg128(nn);
-         IRExpr* argR = (ix <= 6) ? getQReg128(mm) : mkV128(0x0000);
-         IRExpr* res  = NULL;
-         /* Some useful identities:
-               x >  y   can be expressed directly
-               x <  y   ==   y > x
-               x <= y   ==   not (x > y)
-               x >= y   ==   not (y > x)
-         */
-         switch (ix) {
-            case 1: res = binop(opsEQ[szBlg2], argL, argR); break;
-            case 2: res = unop(Iop_NotV128, binop(opsEQ[szBlg2],
-                                            binop(Iop_AndV128, argL, argR), 
-                                                  mkV128(0x0000)));
-                    break;
-            case 3: res = binop(opsGTU[szBlg2], argL, argR); break;
-            case 4: res = binop(opsGTS[szBlg2], argL, argR); break;
-            case 5: res = unop(Iop_NotV128, binop(opsGTU[szBlg2], argR, argL));
-                    break;
-            case 6: res = unop(Iop_NotV128, binop(opsGTS[szBlg2], argR, argL));
-                    break;
-            case 7: res = unop(Iop_NotV128, binop(opsGTS[szBlg2], argR, argL));
-                    break;
-            case 8: res = binop(opsGTS[szBlg2], argL, argR); break;
-            case 9: res = unop(Iop_NotV128,
-                               binop(opsGTS[szBlg2], argL, argR));
-                    break;
-            case 10: res = binop(opsEQ[szBlg2],  argL, argR); break;
-            case 11: res = binop(opsGTS[szBlg2], argR, argL); break;
-            default: vassert(0);
-         }
-         vassert(res);
-         putQReg128(dd, zeroHI ? unop(Iop_ZeroHI64ofV128, res) : res);
-         const HChar* nms[11] = { "eq", "tst", "hi", "gt", "hs", "ge",
-                                  "ge", "gt", "le", "eq", "lt" };
-         if (ix <= 6) {
-            DIP("cm%s %s.%s, %s.%s, %s.%s\n", nms[ix-1],
-                nameQReg128(dd), arrSpec,
-                nameQReg128(nn), arrSpec, nameQReg128(mm), arrSpec);
-         } else {
-            DIP("cm%s %s.%s, %s.%s, #0\n", nms[ix-1],
-                nameQReg128(dd), arrSpec, nameQReg128(nn), arrSpec);
-         }
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* -------------- {EOR,BSL,BIT,BIF} (vector) -------------- */
-   /* 31  28    23   20 15     9 4
-      0q1 01110 00 1 m  000111 n d  EOR Vd.T, Vm.T, Vn.T
-      0q1 01110 01 1 m  000111 n d  BSL Vd.T, Vm.T, Vn.T
-      0q1 01110 10 1 m  000111 n d  BIT Vd.T, Vm.T, Vn.T
-      0q1 01110 11 1 m  000111 n d  BIF Vd.T, Vm.T, Vn.T
-   */
-   if (INSN(31,31) == 0 && INSN(29,24) == BITS6(1,0,1,1,1,0)
-       && INSN(21,21) == 1 && INSN(15,10) == BITS6(0,0,0,1,1,1)) {
-      Bool   isQ  = INSN(30,30) == 1;
-      UInt   op   = INSN(23,22);
-      UInt   mm   = INSN(20,16);
-      UInt   nn   = INSN(9,5);
-      UInt   dd   = INSN(4,0);
-      IRTemp argD = newTemp(Ity_V128);
-      IRTemp argN = newTemp(Ity_V128);
-      IRTemp argM = newTemp(Ity_V128);
-      assign(argD, getQReg128(dd));
-      assign(argN, getQReg128(nn));
-      assign(argM, getQReg128(mm));
-      const IROp opXOR = Iop_XorV128;
-      const IROp opAND = Iop_AndV128;
-      const IROp opNOT = Iop_NotV128;
-      IRExpr* res = NULL;
-      switch (op) {
-         case BITS2(0,0): /* EOR */
-            res = binop(opXOR, mkexpr(argM), mkexpr(argN));
-            break;
-         case BITS2(0,1): /* BSL */
-            res = binop(opXOR, mkexpr(argM),
-                               binop(opAND,
-                                     binop(opXOR, mkexpr(argM), mkexpr(argN)),
-                                     mkexpr(argD)));
-            break;
-         case BITS2(1,0): /* BIT */
-            res = binop(opXOR, mkexpr(argD),
-                               binop(opAND,
-                                     binop(opXOR, mkexpr(argD), mkexpr(argN)),
-                                     mkexpr(argM)));
-            break;
-         case BITS2(1,1): /* BIF */
-            res = binop(opXOR, mkexpr(argD),
-                               binop(opAND,
-                                     binop(opXOR, mkexpr(argD), mkexpr(argN)),
-                                     unop(opNOT, mkexpr(argM))));
-            break;
-         default:
-            vassert(0);
-      }
-      vassert(res);
-      putQReg128(dd, isQ ? res : unop(Iop_ZeroHI64ofV128, res));
-      const HChar* nms[4] = { "eor", "bsl", "bit", "bif" };
-      const HChar* arr = isQ ? "16b" : "8b";
-      vassert(op < 4);
-      DIP("%s %s.%s, %s.%s, %s.%s\n", nms[op],
-          nameQReg128(dd), arr, nameQReg128(nn), arr, nameQReg128(mm), arr);
-      return True;
-   }
-
-   /* ------------ {USHR,SSHR,SHL} (vector, immediate) ------------ */
-   /* 31  28     22   18   15     9 4
-      0q1 011110 immh immb 000001 n d  USHR Vd.T, Vn.T, #shift (1)
-      0q0 011110 immh immb 000001 n d  SSHR Vd.T, Vn.T, #shift (2)
-      0q0 011110 immh immb 010101 n d  SHL  Vd.T, Vn.T, #shift (3)
-      laneTy, shift = case immh:immb of
-                         0001:xxx -> B, SHR:8-xxx,    SHL:xxx
-                         001x:xxx -> H, SHR:16-xxxx   SHL:xxxx
-                         01xx:xxx -> S, SHR:32-xxxxx  SHL:xxxxx
-                         1xxx:xxx -> D, SHR:64-xxxxxx SHL:xxxxxx
-                         other    -> invalid
-      As usual the case laneTy==D && q==0 is not allowed.
-   */
-   if (INSN(31,31) == 0 && INSN(28,23) == BITS6(0,1,1,1,1,0)
-       && INSN(10,10) == 1) {
-      UInt ix = 0;
-      /**/ if (INSN(29,29) == 1 && INSN(15,11) == BITS5(0,0,0,0,0)) ix = 1;
-      else if (INSN(29,29) == 0 && INSN(15,11) == BITS5(0,0,0,0,0)) ix = 2;
-      else if (INSN(29,29) == 0 && INSN(15,11) == BITS5(0,1,0,1,0)) ix = 3;
-      if (ix > 0) {
-         Bool isQ  = INSN(30,30) == 1;
-         UInt immh = INSN(22,19);
-         UInt immb = INSN(18,16);
-         UInt nn   = INSN(9,5);
-         UInt dd   = INSN(4,0);
-         const IROp opsSHRN[4]
-            = { Iop_ShrN8x16, Iop_ShrN16x8, Iop_ShrN32x4, Iop_ShrN64x2 };
-         const IROp opsSARN[4]
-            = { Iop_SarN8x16, Iop_SarN16x8, Iop_SarN32x4, Iop_SarN64x2 };
-         const IROp opsSHLN[4]
-            = { Iop_ShlN8x16, Iop_ShlN16x8, Iop_ShlN32x4, Iop_ShlN64x2 };
-         UInt szBlg2 = 0;
-         UInt shift  = 0;
-         Bool ok     = getLaneInfo_IMMH_IMMB(&shift, &szBlg2, immh, immb);
-         if (ix == 3) {
-            /* The shift encoding has opposite sign for the leftwards
-               case.  Adjust shift to compensate. */
-            shift = (8 << szBlg2) - shift;
-         }
-         if (ok && szBlg2 < 4 && shift > 0 && shift < (8 << szBlg2)
-             && !(szBlg2 == 3/*64bit*/ && !isQ)) {
-            IROp op = Iop_INVALID;
-            const HChar* nm = NULL;
-            switch (ix) {
-               case 1: op = opsSHRN[szBlg2]; nm = "ushr"; break;
-               case 2: op = opsSARN[szBlg2]; nm = "sshr"; break;
-               case 3: op = opsSHLN[szBlg2]; nm = "shl";  break;
-               default: vassert(0);
-            }
-            IRExpr* src = getQReg128(nn);
-            IRExpr* res = binop(op, src, mkU8(shift));
-            putQReg128(dd, isQ ? res : unop(Iop_ZeroHI64ofV128, res));
-            HChar laneCh = "bhsd"[szBlg2];
-            UInt  nLanes = (isQ ? 128 : 64) / (8 << szBlg2);
-            DIP("%s %s.%u%c, %s.%u%c, #%u\n", nm,
-                nameQReg128(dd), nLanes, laneCh,
-                nameQReg128(nn), nLanes, laneCh, shift);
-            return True;
-         }
-         /* else fall through */
-      }
-   }
-
-   /* -------------------- {U,S}SHLL{,2} -------------------- */
-   /* 31  28     22   18   15     9 4
-      0q0 011110 immh immb 101001 n d  SSHLL Vd.Ta, Vn.Tb, #sh
-      0q1 011110 immh immb 101001 n d  USHLL Vd.Ta, Vn.Tb, #sh
-      where Ta,Tb,sh
-        = case immh of 1xxx -> invalid
-                       01xx -> 2d, 2s(q0)/4s(q1),  immh:immb - 32 (0..31)
-                       001x -> 4s, 4h(q0)/8h(q1),  immh:immb - 16 (0..15)
-                       0001 -> 8h, 8b(q0)/16b(q1), immh:immb - 8  (0..7)
-                       0000 -> AdvSIMD modified immediate (???)
-   */
-   if (INSN(31,31) == 0 && INSN(28,23) == BITS6(0,1,1,1,1,0)
-       && INSN(15,10) == BITS6(1,0,1,0,0,1)) {
-      Bool isQ   = INSN(30,30) == 1;
-      Bool isU   = INSN(29,29) == 1;
-      UInt immh  = INSN(22,19);
-      UInt immb  = INSN(18,16);
-      UInt nn    = INSN(9,5);
-      UInt dd    = INSN(4,0);
-      UInt immhb = (immh << 3) | immb;
-      IRTemp  src  = newTemp(Ity_V128);
-      IRTemp  zero = newTemp(Ity_V128);
-      IRExpr* res  = NULL;
-      UInt    sh   = 0;
-      const HChar* ta = "??";
-      const HChar* tb = "??";
-      assign(src, getQReg128(nn));
-      assign(zero, mkV128(0x0000));
-      if (immh & 8) {
-         /* invalid; don't assign to res */
-      }
-      else if (immh & 4) {
-         sh = immhb - 32;
-         vassert(sh < 32); /* so 32-sh is 1..32 */
-         ta = "2d";
-         tb = isQ ? "4s" : "2s";
-         IRExpr* tmp = isQ ? mk_InterleaveHI32x4(src, zero) 
-                           : mk_InterleaveLO32x4(src, zero);
-         res = binop(isU ? Iop_ShrN64x2 : Iop_SarN64x2, tmp, mkU8(32-sh));
-      }
-      else if (immh & 2) {
-         sh = immhb - 16;
-         vassert(sh < 16); /* so 16-sh is 1..16 */
-         ta = "4s";
-         tb = isQ ? "8h" : "4h";
-         IRExpr* tmp = isQ ? mk_InterleaveHI16x8(src, zero) 
-                           : mk_InterleaveLO16x8(src, zero);
-         res = binop(isU ? Iop_ShrN32x4 : Iop_SarN32x4, tmp, mkU8(16-sh));
-      }
-      else if (immh & 1) {
-         sh = immhb - 8;
-         vassert(sh < 8); /* so 8-sh is 1..8 */
-         ta = "8h";
-         tb = isQ ? "16b" : "8b";
-         IRExpr* tmp = isQ ? mk_InterleaveHI8x16(src, zero) 
-                           : mk_InterleaveLO8x16(src, zero);
-         res = binop(isU ? Iop_ShrN16x8 : Iop_SarN16x8, tmp, mkU8(8-sh));
-      } else {
-         vassert(immh == 0);
-         /* invalid; don't assign to res */
-      }
-      /* */
-      if (res) {
-         putQReg128(dd, res);
-         DIP("%cshll%s %s.%s, %s.%s, #%d\n",
-             isU ? 'u' : 's', isQ ? "2" : "",
-             nameQReg128(dd), ta, nameQReg128(nn), tb, sh);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* -------------------- XTN{,2} -------------------- */
-   /* 31  28    23   21     15     9 4  XTN{,2} Vd.Tb, Vn.Ta
-      0q0 01110 size 100001 001010 n d
-   */
-   if (INSN(31,31) == 0 && INSN(29,24) == BITS6(0,0,1,1,1,0)
-       && INSN(21,16) == BITS6(1,0,0,0,0,1)
-       && INSN(15,10) == BITS6(0,0,1,0,1,0)) {
-      Bool isQ  = INSN(30,30) == 1;
-      UInt size = INSN(23,22);
-      UInt nn   = INSN(9,5);
-      UInt dd   = INSN(4,0);
-      IROp op   = Iop_INVALID;
-      const HChar* tb = NULL;
-      const HChar* ta = NULL;
-      switch ((size << 1) | (isQ ? 1 : 0)) {
-         case 0: tb = "8b";  ta = "8h"; op = Iop_NarrowUn16to8x8;  break;
-         case 1: tb = "16b"; ta = "8h"; op = Iop_NarrowUn16to8x8;  break;
-         case 2: tb = "4h";  ta = "4s"; op = Iop_NarrowUn32to16x4; break;
-         case 3: tb = "8h";  ta = "4s"; op = Iop_NarrowUn32to16x4; break;
-         case 4: tb = "2s";  ta = "2d"; op = Iop_NarrowUn64to32x2; break;
-         case 5: tb = "4s";  ta = "2d"; op = Iop_NarrowUn64to32x2; break;
-         case 6: break;
-         case 7: break;
-         default: vassert(0);
-      }
-      if (op != Iop_INVALID) {
-         if (!isQ) {
-            putQRegLane(dd, 1, mkU64(0));
-         }
-         putQRegLane(dd, isQ ? 1 : 0, unop(op, getQReg128(nn)));
-         DIP("xtn%s %s.%s, %s.%s\n", isQ ? "2" : "",
-             nameQReg128(dd), tb, nameQReg128(nn), ta);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* ---------------- DUP (element, vector) ---------------- */
-   /* 31  28       20   15     9 4
-      0q0 01110000 imm5 000001 n d  DUP Vd.T, Vn.Ts[index]
-   */
-   if (INSN(31,31) == 0 && INSN(29,21) == BITS9(0,0,1,1,1,0,0,0,0)
-       && INSN(15,10) == BITS6(0,0,0,0,0,1)) {
-      Bool   isQ  = INSN(30,30) == 1;
-      UInt   imm5 = INSN(20,16);
-      UInt   nn   = INSN(9,5);
-      UInt   dd   = INSN(4,0);
-      IRTemp w0   = newTemp(Ity_I64);
-      const HChar* arT  = "??";
-      const HChar* arTs = "??";
-      IRType laneTy = Ity_INVALID;
-      UInt   laneNo = 16; /* invalid */
-      if (imm5 & 1) {
-         arT    = isQ ? "16b" : "8b";
-         arTs   = "b";
-         laneNo = (imm5 >> 1) & 15;
-         laneTy = Ity_I8;
-         assign(w0, unop(Iop_8Uto64, getQRegLane(nn, laneNo, laneTy)));
-      }
-      else if (imm5 & 2) {
-         arT    = isQ ? "8h" : "4h";
-         arTs   = "h";
-         laneNo = (imm5 >> 2) & 7;
-         laneTy = Ity_I16;
-         assign(w0, unop(Iop_16Uto64, getQRegLane(nn, laneNo, laneTy)));
-      }
-      else if (imm5 & 4) {
-         arT    = isQ ? "4s" : "2s";
-         arTs   = "s";
-         laneNo = (imm5 >> 3) & 3;
-         laneTy = Ity_I32;
-         assign(w0, unop(Iop_32Uto64, getQRegLane(nn, laneNo, laneTy)));
-      }
-      else if ((imm5 & 8) && isQ) {
-         arT  = "2d";
-         arTs = "d";
-         laneNo = (imm5 >> 4) & 1;
-         laneTy = Ity_I64;
-         assign(w0, getQRegLane(nn, laneNo, laneTy));
-      }
-      else {
-         /* invalid; leave laneTy unchanged. */
-      }
-      /* */
-      if (laneTy != Ity_INVALID) {
-         vassert(laneNo < 16);
-         IRTemp w1 = math_DUP_TO_64(w0, laneTy);
-         putQReg128(dd, binop(Iop_64HLtoV128,
-                              isQ ? mkexpr(w1) : mkU64(0), mkexpr(w1)));
-         DIP("dup %s.%s, %s.%s[%u]\n",
-             nameQReg128(dd), arT, nameQReg128(nn), arTs, laneNo);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* ---------------------- {S,U}MOV ---------------------- */
-   /* 31  28        20   15     9 4
-      0q0 01110 000 imm5 001111 n d  UMOV Xd/Wd, Vn.Ts[index]
-      0q0 01110 000 imm5 001011 n d  SMOV Xd/Wd, Vn.Ts[index]
-      dest is Xd when q==1, Wd when q==0
-      UMOV:
-         Ts,index,ops = case q:imm5 of
-                          0:xxxx1 -> B, xxxx, 8Uto64
-                          1:xxxx1 -> invalid
-                          0:xxx10 -> H, xxx,  16Uto64
-                          1:xxx10 -> invalid
-                          0:xx100 -> S, xx,   32Uto64
-                          1:xx100 -> invalid
-                          1:x1000 -> D, x,    copy64
-                          other   -> invalid
-      SMOV:
-         Ts,index,ops = case q:imm5 of
-                          0:xxxx1 -> B, xxxx, (32Uto64 . 8Sto32)
-                          1:xxxx1 -> B, xxxx, 8Sto64
-                          0:xxx10 -> H, xxx,  (32Uto64 . 16Sto32)
-                          1:xxx10 -> H, xxx,  16Sto64
-                          0:xx100 -> invalid
-                          1:xx100 -> S, xx,   32Sto64
-                          1:x1000 -> invalid
-                          other   -> invalid
-   */
-   if (INSN(31,31) == 0 && INSN(29,21) == BITS9(0,0,1,1,1,0,0,0,0)
-       && (INSN(15,10) & BITS6(1,1,1,0,1,1)) == BITS6(0,0,1,0,1,1)) {
-      UInt bitQ = INSN(30,30) == 1;
-      UInt imm5 = INSN(20,16);
-      UInt nn   = INSN(9,5);
-      UInt dd   = INSN(4,0);
-      Bool isU  = INSN(12,12) == 1;
-      const HChar* arTs = "??";
-      UInt    laneNo = 16; /* invalid */
-      // Setting 'res' to non-NULL determines valid/invalid
-      IRExpr* res    = NULL;
-      if (!bitQ && (imm5 & 1)) { // 0:xxxx1
-         laneNo = (imm5 >> 1) & 15;
-         IRExpr* lane = getQRegLane(nn, laneNo, Ity_I8);
-         res = isU ? unop(Iop_8Uto64, lane)
-                   : unop(Iop_32Uto64, unop(Iop_8Sto32, lane));
-         arTs = "b";
-      }
-      else if (bitQ && (imm5 & 1)) { // 1:xxxx1
-         laneNo = (imm5 >> 1) & 15;
-         IRExpr* lane = getQRegLane(nn, laneNo, Ity_I8);
-         res = isU ? NULL
-                   : unop(Iop_8Sto64, lane);
-         arTs = "b";
-      }
-      else if (!bitQ && (imm5 & 2)) { // 0:xxx10
-         laneNo = (imm5 >> 2) & 7;
-         IRExpr* lane = getQRegLane(nn, laneNo, Ity_I16);
-         res = isU ? unop(Iop_16Uto64, lane)
-                   : unop(Iop_32Uto64, unop(Iop_16Sto32, lane));
-         arTs = "h";
-      }
-      else if (bitQ && (imm5 & 2)) { // 1:xxx10
-         laneNo = (imm5 >> 2) & 7;
-         IRExpr* lane = getQRegLane(nn, laneNo, Ity_I16);
-         res = isU ? NULL
-                   : unop(Iop_16Sto64, lane);
-         arTs = "h";
-      }
-      else if (!bitQ && (imm5 & 4)) { // 0:xx100
-         laneNo = (imm5 >> 3) & 3;
-         IRExpr* lane = getQRegLane(nn, laneNo, Ity_I32);
-         res = isU ? unop(Iop_32Uto64, lane)
-                   : NULL;
-         arTs = "s";
-      }
-      else if (bitQ && (imm5 & 4)) { // 1:xxx10
-         laneNo = (imm5 >> 3) & 3;
-         IRExpr* lane = getQRegLane(nn, laneNo, Ity_I32);
-         res = isU ? NULL
-                   : unop(Iop_32Sto64, lane);
-         arTs = "s";
-      }
-      else if (bitQ && (imm5 & 8)) { // 1:x1000
-         laneNo = (imm5 >> 4) & 1;
-         IRExpr* lane = getQRegLane(nn, laneNo, Ity_I64);
-         res = isU ? lane
-                   : NULL;
-         arTs = "d";
-      }
-      /* */
-      if (res) {
-         vassert(laneNo < 16);
-         putIReg64orZR(dd, res);
-         DIP("%cmov %s, %s.%s[%u]\n", isU ? 'u' : 's',
-             nameIRegOrZR(bitQ == 1, dd),
-             nameQReg128(nn), arTs, laneNo);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* -------------------- INS (general) -------------------- */
-   /* 31  28       20   15     9 4
-      010 01110000 imm5 000111 n d  INS Vd.Ts[ix], Rn
-      where Ts,ix = case imm5 of xxxx1 -> B, xxxx
-                                 xxx10 -> H, xxx
-                                 xx100 -> S, xx
-                                 x1000 -> D, x
-   */
-   if (INSN(31,21) == BITS11(0,1,0,0,1,1,1,0,0,0,0)
-       && INSN(15,10) == BITS6(0,0,0,1,1,1)) {
-      UInt    imm5   = INSN(20,16);
-      UInt    nn     = INSN(9,5);
-      UInt    dd     = INSN(4,0);
-      HChar   ts     = '?';
-      UInt    laneNo = 16;
-      IRExpr* src    = NULL;
-      if (imm5 & 1) {
-         src    = unop(Iop_64to8, getIReg64orZR(nn));
-         laneNo = (imm5 >> 1) & 15;
-         ts     = 'b';
-      }
-      else if (imm5 & 2) {
-         src    = unop(Iop_64to16, getIReg64orZR(nn));
-         laneNo = (imm5 >> 2) & 7;
-         ts     = 'h';
-      }
-      else if (imm5 & 4) {
-         src    = unop(Iop_64to32, getIReg64orZR(nn));
-         laneNo = (imm5 >> 3) & 3;
-         ts     = 's';
-      }
-      else if (imm5 & 8) {
-         src    = getIReg64orZR(nn);
-         laneNo = (imm5 >> 4) & 1;
-         ts     = 'd';
-      }
-      /* */
-      if (src) {
-         vassert(laneNo < 16);
-         putQRegLane(dd, laneNo, src);
-         DIP("ins %s.%c[%u], %s\n",
-             nameQReg128(dd), ts, laneNo, nameIReg64orZR(nn));
-         return True;
-      }
-      /* else invalid; fall through */
-   }
-
-   /* -------------------- NEG (vector) -------------------- */
-   /* 31  28    23 21    16      9 4
-      0q1 01110 sz 10000 0101110 n d  NEG Vd, Vn
-      sz is laneSz, q:sz == 011 is disallowed, as usual
-   */
-   if (INSN(31,31) == 0 && INSN(29,24) == BITS6(1,0,1,1,1,0)
-       && INSN(21,10) == BITS12(1,0,0,0,0,0,1,0,1,1,1,0)) {
-      Bool isQ    = INSN(30,30) == 1;
-      UInt szBlg2 = INSN(23,22);
-      UInt nn     = INSN(9,5);
-      UInt dd     = INSN(4,0);
-      Bool zeroHI = False;
-      const HChar* arrSpec = "";
-      Bool ok = getLaneInfo_SIMPLE(&zeroHI, &arrSpec, isQ, szBlg2 );
-      if (ok) {
-         const IROp opSUB[4]
-            = { Iop_Sub8x16, Iop_Sub16x8, Iop_Sub32x4, Iop_Sub64x2 };
-         IRTemp res = newTemp(Ity_V128);
-         vassert(szBlg2 < 4);
-         assign(res, binop(opSUB[szBlg2], mkV128(0x0000), getQReg128(nn)));
-         putQReg128(dd, zeroHI ? unop(Iop_ZeroHI64ofV128, mkexpr(res))
-                               : mkexpr(res));
-         DIP("neg %s.%s, %s.%s\n",
-             nameQReg128(dd), arrSpec, nameQReg128(nn), arrSpec);
-         return True;
-      }
-      /* else fall through */
-   }
-
-   /* -------------------- TBL, TBX -------------------- */
-   /* 31  28        20 15 14  12  9 4
-      0q0 01110 000 m  0  len 000 n d  TBL Vd.Ta, {Vn .. V(n+len)%32}, Vm.Ta
-      0q0 01110 000 m  0  len 100 n d  TBX Vd.Ta, {Vn .. V(n+len)%32}, Vm.Ta
-      where Ta = 16b(q=1) or 8b(q=0)
-   */
-   if (INSN(31,31) == 0 && INSN(29,21) == BITS9(0,0,1,1,1,0,0,0,0)
-       && INSN(15,15) == 0 && INSN(11,10) == BITS2(0,0)) {
-      Bool isQ   = INSN(30,30) == 1;
-      Bool isTBX = INSN(12,12) == 1;
-      UInt mm    = INSN(20,16);
-      UInt len   = INSN(14,13);
-      UInt nn    = INSN(9,5);
-      UInt dd    = INSN(4,0);
-      /* The out-of-range values to use. */
-      IRTemp oor_values = newTemp(Ity_V128);
-      assign(oor_values, isTBX ? getQReg128(dd) : mkV128(0));
-      /* src value */
-      IRTemp src = newTemp(Ity_V128);
-      assign(src, getQReg128(mm));
-      /* The table values */
-      IRTemp tab[4];
-      UInt   i;
-      for (i = 0; i <= len; i++) {
-         vassert(i < 4);
-         tab[i] = newTemp(Ity_V128);
-         assign(tab[i], getQReg128((nn + i) % 32));
-      }
-      IRTemp res = math_TBL_TBX(tab, len, src, oor_values);
-      putQReg128(dd, isQ ? mkexpr(res)
-                         : unop(Iop_ZeroHI64ofV128, mkexpr(res)) );
-      const HChar* Ta = isQ ? "16b" : "8b";
-      const HChar* nm = isTBX ? "tbx" : "tbl";
-      DIP("%s %s.%s, {v%d.16b .. v%d.16b}, %s.%s\n",
-          nm, nameQReg128(dd), Ta, nn, (nn + len) % 32, nameQReg128(mm), Ta);
-      return True;
-   }
-   /* FIXME Temporary hacks to get through ld.so FIXME */
-
-   /* ------------------ movi vD.4s, #0x0 ------------------ */
-   /* 0x4F 0x00 0x04 000 vD */
-   if ((insn & 0xFFFFFFE0) == 0x4F000400) {
-      UInt vD = INSN(4,0);
-      putQReg128(vD, mkV128(0x0000));
-      DIP("movi v%u.4s, #0x0\n", vD);
-      return True;
-   }
-
-   /* ---------------- MOV vD.16b, vN.16b ---------------- */
-   /* 31        23  20 15     9 4
-      010 01110 101 m  000111 n d   ORR vD.16b, vN.16b, vM.16b
-      This only handles the N == M case.
-   */
-   if (INSN(31,24) == BITS8(0,1,0,0,1,1,1,0)
-       && INSN(23,21) == BITS3(1,0,1) && INSN(15,10) == BITS6(0,0,0,1,1,1)) {
-      UInt mm = INSN(20,16);
-      UInt nn = INSN(9,5);
-      UInt dd = INSN(4,0);
-      if (mm == nn) {
-         putQReg128(dd, getQReg128(nn));
-         DIP("mov v%u.16b, v%u.16b\n", dd, nn);
-         return True;
-      }
-      /* else it's really an ORR; fall through. */
-   }
-
-   /* ---------------- CMEQ_d_d_#0 ---------------- */
-   /* 
-      010 11110 11 10000 0100 110 n d   CMEQ Dd, Dn, #0
-   */
-   if ((INSN(31,0) & 0xFFFFFC00) == 0x5EE09800) {
-      UInt nn = INSN(9,5);
-      UInt dd = INSN(4,0);
-      putQReg128(dd, unop(Iop_ZeroHI64ofV128,
-                          binop(Iop_CmpEQ64x2, getQReg128(nn),
-                                mkV128(0x0000))));
-      DIP("cmeq d%u, d%u, #0\n", dd, nn);
-      return True;
-   }
-
-   /* ---------------- SHL_d_d_#imm ---------------- */
-   /* 31         22 21  18 15     9 4
-      010 111110 1  ih3 ib 010101 n d  SHL Dd, Dn, #(ih3:ib)
-   */
-   if (INSN(31,22) == BITS10(0,1,0,1,1,1,1,1,0,1)
-       && INSN(15,10) == BITS6(0,1,0,1,0,1)) {
-      UInt nn = INSN(9,5);
-      UInt dd = INSN(4,0);
-      UInt sh = INSN(21,16);
-      vassert(sh < 64);
-      putQReg128(dd, unop(Iop_ZeroHI64ofV128,
-                          binop(Iop_ShlN64x2, getQReg128(nn), mkU8(sh))));
-      DIP("shl d%u, d%u, #%u\n", dd, nn, sh);
-      return True;
-   }
-
-   vex_printf("ARM64 front end: simd_and_fp\n");
-   return False;
-#  undef INSN
-}
-
 
 /*------------------------------------------------------------*/
 /*--- Disassemble a single ARM64 instruction               ---*/