LCOV - code coverage report
Current view: top level - asmjit - a64assembler.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 0 1914 0.0 %
Date: 2026-11-05 10:19:06 Functions: 0 24 0.0 %

          Line data    Source code
       1             : #ifdef __PLUMED_HAS_ASMJIT
       2             : // This file is part of AsmJit project <https://asmjit.com>
       3             : //
       4             : // See asmjit.h or LICENSE.md for license and copyright information
       5             : // SPDX-License-Identifier: Zlib
       6             : 
       7             : #include "api-build_p.h"
       8             : #if !defined(ASMJIT_NO_AARCH64)
       9             : 
      10             : #include "codewriter_p.h"
      11             : #include "cpuinfo.h"
      12             : #include "emitterutils_p.h"
      13             : #include "formatter.h"
      14             : #include "logger.h"
      15             : #include "misc_p.h"
      16             : #include "support.h"
      17             : #include "armformatter_p.h"
      18             : #include "a64assembler.h"
      19             : #include "a64emithelper_p.h"
      20             : #include "a64instdb_p.h"
      21             : #include "a64utils.h"
      22             : 
      23             : ASMJIT_BEGIN_SUB_NAMESPACE(a64)
      24             : 
      25             : // a64::Assembler - Cond
      26             : // =====================
      27             : 
      28             : static inline uint32_t condCodeToOpcodeCond(uint32_t cond) noexcept {
      29           0 :   return (uint32_t(cond) - 2u) & 0xFu;
      30             : }
      31             : 
      32             : // a64::Assembler - Bits
      33             : // =====================
      34             : 
      35             : template<typename T>
      36             : static inline constexpr uint32_t B(const T& index) noexcept { return uint32_t(1u) << uint32_t(index); }
      37             : 
      38             : static constexpr uint32_t kSP = Gp::kIdSp;
      39             : static constexpr uint32_t kZR = Gp::kIdZr;
      40             : static constexpr uint32_t kWX = InstDB::kWX;
      41             : 
      42             : // a64::Assembler - ShiftOpToLdStOptMap
      43             : // ====================================
      44             : 
      45             : // Table that maps ShiftOp to OPT part in LD/ST (register) opcode.
      46             : #define VALUE(index) index == uint32_t(ShiftOp::kUXTW) ? 2u : \
      47             :                      index == uint32_t(ShiftOp::kLSL)  ? 3u : \
      48             :                      index == uint32_t(ShiftOp::kSXTW) ? 6u : \
      49             :                      index == uint32_t(ShiftOp::kSXTX) ? 7u : 0xFF
      50             : static const uint8_t armShiftOpToLdStOptMap[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) };
      51             : #undef VALUE
      52             : 
      53             : static inline constexpr uint32_t diff(RegType a, RegType b) noexcept {
      54           0 :   return uint32_t(a) - uint32_t(b);
      55             : }
      56             : 
      57             : // asmjit::a64::Assembler - SizeOp
      58             : // ===============================
      59             : 
      60             : //! Struct that contains Size (2 bits), Q flag, and S (scalar) flag. These values
      61             : //! are used to encode Q, Size, and Scalar fields in an opcode.
      62             : struct SizeOp {
      63             :   enum : uint8_t {
      64             :     k128BitShift = 0,
      65             :     kScalarShift = 1,
      66             :     kSizeShift = 2,
      67             : 
      68             :     kQ = uint8_t(1u << k128BitShift),
      69             :     kS = uint8_t(1u << kScalarShift),
      70             : 
      71             :     k00 = uint8_t(0 << kSizeShift),
      72             :     k01 = uint8_t(1 << kSizeShift),
      73             :     k10 = uint8_t(2 << kSizeShift),
      74             :     k11 = uint8_t(3 << kSizeShift),
      75             : 
      76             :     k00Q = k00 | kQ,
      77             :     k01Q = k01 | kQ,
      78             :     k10Q = k10 | kQ,
      79             :     k11Q = k11 | kQ,
      80             : 
      81             :     k00S = k00 | kS,
      82             :     k01S = k01 | kS,
      83             :     k10S = k10 | kS,
      84             :     k11S = k11 | kS,
      85             : 
      86             :     kInvalid = 0xFFu,
      87             : 
      88             :     // Masks used by SizeOpMap.
      89             :     kSzQ = (0x3u << kSizeShift) | kQ,
      90             :     kSzS = (0x3u << kSizeShift) | kS,
      91             :     kSzQS = (0x3u << kSizeShift) | kQ | kS
      92             :   };
      93             : 
      94             :   uint8_t value;
      95             : 
      96             :   inline bool isValid() const noexcept { return value != kInvalid; }
      97           0 :   inline void makeInvalid() noexcept { value = kInvalid; }
      98             : 
      99           0 :   inline uint32_t q() const noexcept { return (value >> k128BitShift) & 0x1u; }
     100           0 :   inline uint32_t qs() const noexcept { return ((value >> k128BitShift) | (value >> kScalarShift)) & 0x1u; }
     101           0 :   inline uint32_t scalar() const noexcept { return (value >> kScalarShift) & 0x1u; }
     102           0 :   inline uint32_t size() const noexcept { return (value >> kSizeShift) & 0x3u; }
     103             : 
     104             :   inline void decrementSize() noexcept {
     105             :     ASMJIT_ASSERT(size() > 0);
     106           0 :     value = uint8_t(value - (1u << kSizeShift));
     107           0 :   }
     108             : };
     109             : 
     110             : struct SizeOpTable {
     111             :   enum TableId : uint8_t {
     112             :     kTableBin = 0,
     113             :     kTableAny,
     114             :     kCount
     115             :   };
     116             : 
     117             :   // 40 elements for each combination.
     118             :   SizeOp array[(uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB) + 1) * 8];
     119             : };
     120             : 
     121             : #define VALUE_BIN(x) { \
     122             :   x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00  : \
     123             :   x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00Q : \
     124             :   x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB   )) ? SizeOp::k00  : \
     125             :   x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB   )) ? SizeOp::k00Q : SizeOp::kInvalid \
     126             : }
     127             : 
     128             : #define VALUE_ANY(x) { \
     129             :   x == (((uint32_t(RegType::kARM_VecB) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00S : \
     130             :   x == (((uint32_t(RegType::kARM_VecH) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k01S : \
     131             :   x == (((uint32_t(RegType::kARM_VecS) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k10S : \
     132             :   x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k11S : \
     133             :   x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB   )) ? SizeOp::k00  : \
     134             :   x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB   )) ? SizeOp::k00Q : \
     135             :   x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH   )) ? SizeOp::k01  : \
     136             :   x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH   )) ? SizeOp::k01Q : \
     137             :   x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS   )) ? SizeOp::k10  : \
     138             :   x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS   )) ? SizeOp::k10Q : \
     139             :   x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD   )) ? SizeOp::k11S : \
     140             :   x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD   )) ? SizeOp::k11Q : SizeOp::kInvalid \
     141             : }
     142             : 
     143             : static const SizeOpTable sizeOpTable[SizeOpTable::kCount] = {
     144             :   {{ ASMJIT_LOOKUP_TABLE_40(VALUE_BIN, 0) }},
     145             :   {{ ASMJIT_LOOKUP_TABLE_40(VALUE_ANY, 0) }}
     146             : };
     147             : 
     148             : #undef VALUE_ANY
     149             : #undef VALUE_BIN
     150             : 
     151             : struct SizeOpMap {
     152             :   uint8_t tableId;
     153             :   uint8_t sizeOpMask;
     154             :   uint16_t acceptMask;
     155             : };
     156             : 
     157             : static const constexpr SizeOpMap sizeOpMap[InstDB::kVO_Count] = {
     158             :   { // kVO_V_B:
     159             :     SizeOpTable::kTableBin, SizeOp::kQ   , uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q))
     160             :   },
     161             : 
     162             :   { // kVO_V_BH:
     163             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q))
     164             :   },
     165             : 
     166             :   { // kVO_V_BH_4S:
     167             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10Q))
     168             :   },
     169             : 
     170             :   { // kVO_V_BHS:
     171             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q))
     172             :   },
     173             : 
     174             :   { // kVO_V_BHS_D2:
     175             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k11Q))
     176             :   },
     177             : 
     178             :   { // kVO_V_HS:
     179             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q))
     180             :   },
     181             : 
     182             :   { // kVO_V_S:
     183             :     SizeOpTable::kTableAny, SizeOp::kQ   , uint16_t(B(SizeOp::k10) | B(SizeOp::k10Q))
     184             :   },
     185             : 
     186             :   { // kVO_V_B8H4:
     187             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k01))
     188             :   },
     189             : 
     190             :   { // kVO_V_B8H4S2:
     191             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k01) | B(SizeOp::k10))
     192             :   },
     193             : 
     194             :   { // kVO_V_B8D1:
     195             :     SizeOpTable::kTableAny, SizeOp::kSzQ , uint16_t(B(SizeOp::k00) | B(SizeOp::k11S))
     196             :   },
     197             : 
     198             :   { // kVO_V_H4S2:
     199             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k10))
     200             :   },
     201             : 
     202             :   { // kVO_V_B16:
     203             :     SizeOpTable::kTableBin, SizeOp::kQ   , uint16_t(B(SizeOp::k00Q))
     204             :   },
     205             : 
     206             :   { // kVO_V_B16H8:
     207             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k01Q))
     208             :   },
     209             : 
     210             :   { // kVO_V_B16H8S4:
     211             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k01Q) | B(SizeOp::k10Q))
     212             :   },
     213             : 
     214             :   { // kVO_V_B16D2:
     215             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k11Q))
     216             :   },
     217             : 
     218             :   { // kVO_V_H8S4:
     219             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01Q) | B(SizeOp::k10Q))
     220             :   },
     221             : 
     222             :   { // kVO_V_S4:
     223             :     SizeOpTable::kTableAny, 0            , uint16_t(B(SizeOp::k10Q))
     224             :   },
     225             : 
     226             :   { // kVO_V_D2:
     227             :     SizeOpTable::kTableAny, 0            , uint16_t(B(SizeOp::k11Q))
     228             :   },
     229             : 
     230             :   { // kVO_SV_BHS:
     231             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k00S) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k10S))
     232             :   },
     233             : 
     234             :   { // kVO_SV_B8H4S2:
     235             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00S) | B(SizeOp::k01) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10S))
     236             :   },
     237             : 
     238             :   { // kVO_SV_HS:
     239             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k10S))
     240             :   },
     241             : 
     242             :   { // kVO_V_Any:
     243             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k11S) | B(SizeOp::k11Q))
     244             :   },
     245             : 
     246             :   { // kVO_SV_Any:
     247             :     SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k00S) |
     248             :                                                     B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k01S) |
     249             :                                                     B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k10S) |
     250             :                                                     B(SizeOp::k11) | B(SizeOp::k11Q) | B(SizeOp::k11S))
     251             :   }
     252             : };
     253             : 
     254           0 : static const Operand_& significantSimdOp(const Operand_& o0, const Operand_& o1, uint32_t instFlags) noexcept {
     255           0 :   return !(instFlags & InstDB::kInstFlagLong) ? o0 : o1;
     256             : }
     257             : 
     258           0 : static inline SizeOp armElementTypeToSizeOp(uint32_t vecOpType, RegType regType, uint32_t elementType) noexcept {
     259             :   // Instruction data or Assembler is wrong if this triggers an assertion failure.
     260             :   ASMJIT_ASSERT(vecOpType < InstDB::kVO_Count);
     261             :   // ElementType uses 3 bits in the operand signature, it should never overflow.
     262             :   ASMJIT_ASSERT(elementType <= 0x7u);
     263             : 
     264             :   const SizeOpMap& map = sizeOpMap[vecOpType];
     265           0 :   const SizeOpTable& table = sizeOpTable[map.tableId];
     266             : 
     267           0 :   size_t index = (Support::min<uint32_t>(diff(regType, RegType::kARM_VecB), diff(RegType::kARM_VecV, RegType::kARM_VecB) + 1) << 3) | elementType;
     268           0 :   SizeOp op = table.array[index];
     269           0 :   SizeOp modifiedOp { uint8_t(op.value & map.sizeOpMask) };
     270             : 
     271           0 :   if (!Support::bitTest(map.acceptMask, op.value))
     272             :     modifiedOp.makeInvalid();
     273             : 
     274           0 :   return modifiedOp;
     275             : }
     276             : 
     277             : // a64::Assembler - Immediate Encoding Utilities (Integral)
     278             : // ========================================================
     279             : 
     280             : using Utils::LogicalImm;
     281             : 
     282             : struct HalfWordImm {
     283             :   uint32_t hw;
     284             :   uint32_t inv;
     285             :   uint32_t imm;
     286             : };
     287             : 
     288             : struct LMHImm {
     289             :   uint32_t lm;
     290             :   uint32_t h;
     291             :   uint32_t maxRmId;
     292             : };
     293             : 
     294           0 : static inline uint32_t countZeroHalfWords64(uint64_t imm) noexcept {
     295           0 :   return uint32_t((imm & 0x000000000000FFFFu) == 0) +
     296           0 :          uint32_t((imm & 0x00000000FFFF0000u) == 0) +
     297           0 :          uint32_t((imm & 0x0000FFFF00000000u) == 0) +
     298           0 :          uint32_t((imm & 0xFFFF000000000000u) == 0) ;
     299             : }
     300             : 
     301           0 : static uint32_t encodeMovSequence32(uint32_t out[2], uint32_t imm, uint32_t rd, uint32_t x) noexcept {
     302             :   ASMJIT_ASSERT(rd <= 31);
     303             : 
     304           0 :   uint32_t kMovZ = 0b01010010100000000000000000000000 | (x << 31);
     305             :   uint32_t kMovN = 0b00010010100000000000000000000000;
     306             :   uint32_t kMovK = 0b01110010100000000000000000000000;
     307             : 
     308           0 :   if ((imm & 0xFFFF0000u) == 0x00000000u) {
     309           0 :     out[0] = kMovZ | (0 << 21) | ((imm & 0xFFFFu) << 5) | rd;
     310           0 :     return 1;
     311             :   }
     312             : 
     313           0 :   if ((imm & 0xFFFF0000u) == 0xFFFF0000u) {
     314           0 :     out[0] = kMovN | (0 << 21) | ((~imm & 0xFFFFu) << 5) | rd;
     315           0 :     return 1;
     316             :   }
     317             : 
     318           0 :   if ((imm & 0x0000FFFFu) == 0x00000000u) {
     319           0 :     out[0] = kMovZ | (1 << 21) | ((imm >> 16) << 5) | rd;
     320           0 :     return 1;
     321             :   }
     322             : 
     323           0 :   if ((imm & 0x0000FFFFu) == 0x0000FFFFu) {
     324           0 :     out[0] = kMovN | (1 << 21) | ((~imm >> 16) << 5) | rd;
     325           0 :     return 1;
     326             :   }
     327             : 
     328           0 :   out[0] = kMovZ | (0 << 21) | ((imm & 0xFFFFu) << 5) | rd;
     329           0 :   out[1] = kMovK | (1 << 21) | ((imm     >> 16) << 5) | rd;
     330           0 :   return 2;
     331             : }
     332             : 
     333           0 : static uint32_t encodeMovSequence64(uint32_t out[4], uint64_t imm, uint32_t rd, uint32_t x) noexcept {
     334             :   ASMJIT_ASSERT(rd <= 31);
     335             : 
     336             :   uint32_t kMovZ = 0b11010010100000000000000000000000;
     337             :   uint32_t kMovN = 0b10010010100000000000000000000000;
     338             :   uint32_t kMovK = 0b11110010100000000000000000000000;
     339             : 
     340           0 :   if (imm <= 0xFFFFFFFFu)
     341           0 :     return encodeMovSequence32(out, uint32_t(imm), rd, x);
     342             : 
     343           0 :   uint32_t zhw = countZeroHalfWords64( imm);
     344           0 :   uint32_t ohw = countZeroHalfWords64(~imm);
     345             : 
     346           0 :   if (zhw >= ohw) {
     347             :     uint32_t op = kMovZ;
     348             :     uint32_t count = 0;
     349             : 
     350           0 :     for (uint32_t hwIndex = 0; hwIndex < 4; hwIndex++, imm >>= 16) {
     351           0 :       uint32_t hwImm = uint32_t(imm & 0xFFFFu);
     352           0 :       if (hwImm == 0)
     353           0 :         continue;
     354             : 
     355           0 :       out[count++] = op | (hwIndex << 21) | (hwImm << 5) | rd;
     356             :       op = kMovK;
     357             :     }
     358             : 
     359             :     // This should not happen - zero should be handled by encodeMovSequence32().
     360             :     ASMJIT_ASSERT(count > 0);
     361             : 
     362             :     return count;
     363             :   }
     364             :   else {
     365             :     uint32_t op = kMovN;
     366             :     uint32_t count = 0;
     367             :     uint32_t negMask = 0xFFFFu;
     368             : 
     369           0 :     for (uint32_t hwIndex = 0; hwIndex < 4; hwIndex++, imm >>= 16) {
     370           0 :       uint32_t hwImm = uint32_t(imm & 0xFFFFu);
     371           0 :       if (hwImm == 0xFFFFu)
     372           0 :         continue;
     373             : 
     374           0 :       out[count++] = op | (hwIndex << 21) | ((hwImm ^ negMask) << 5) | rd;
     375             :       op = kMovK;
     376             :       negMask = 0;
     377             :     }
     378             : 
     379           0 :     if (count == 0) {
     380           0 :       out[count++] = kMovN | ((0xFFFF ^ negMask) << 5) | rd;
     381             :     }
     382             : 
     383           0 :     return count;
     384             :   }
     385             : }
     386             : 
     387           0 : static inline bool encodeLMH(uint32_t sizeField, uint32_t elementIndex, LMHImm* out) noexcept {
     388           0 :   if (sizeField != 1 && sizeField != 2)
     389             :     return false;
     390             : 
     391           0 :   uint32_t hShift = 3u - sizeField;
     392             :   uint32_t lmShift = sizeField - 1u;
     393           0 :   uint32_t maxElementIndex = 15u >> sizeField;
     394             : 
     395           0 :   out->h = elementIndex >> hShift;
     396           0 :   out->lm = (elementIndex << lmShift) & 0x3u;
     397           0 :   out->maxRmId = (8u << sizeField) - 1;
     398             : 
     399           0 :   return elementIndex <= maxElementIndex;
     400             : }
     401             : 
     402             : // [.......A|B.......|.......C|D.......|.......E|F.......|.......G|H.......]
     403           0 : static inline uint32_t encodeImm64ByteMaskToImm8(uint64_t imm) noexcept {
     404           0 :   return uint32_t(((imm >> (7  - 0)) & 0b00000011) | // [.......G|H.......]
     405           0 :                   ((imm >> (23 - 2)) & 0b00001100) | // [.......E|F.......]
     406           0 :                   ((imm >> (39 - 4)) & 0b00110000) | // [.......C|D.......]
     407           0 :                   ((imm >> (55 - 6)) & 0b11000000)); // [.......A|B.......]
     408             : }
     409             : 
     410             : // a64::Assembler - Opcode
     411             : // =======================
     412             : 
     413             : //! Helper class to store and manipulate ARM opcode.
     414             : struct Opcode {
     415             :   uint32_t v;
     416             : 
     417             :   enum Bits : uint32_t {
     418             :     kN = (1u << 22),
     419             :     kQ = (1u << 30),
     420             :     kX = (1u << 31)
     421             :   };
     422             : 
     423             :   // --------------------------------------------------------------------------
     424             :   // [Opcode Builder]
     425             :   // --------------------------------------------------------------------------
     426             : 
     427           0 :   inline uint32_t get() const noexcept { return v; }
     428           0 :   inline void reset(uint32_t value) noexcept { v = value; }
     429             : 
     430           0 :   inline bool hasQ() const noexcept { return (v & kQ) != 0; }
     431             :   inline bool hasX() const noexcept { return (v & kX) != 0; }
     432             : 
     433             :   template<typename T>
     434           0 :   inline Opcode& addImm(T value, uint32_t bitIndex) noexcept { return operator|=(uint32_t(value) << bitIndex); }
     435             : 
     436             :   template<typename T>
     437           0 :   inline Opcode& xorImm(T value, uint32_t bitIndex) noexcept { return operator^=(uint32_t(value) << bitIndex); }
     438             : 
     439             :   template<typename T, typename Condition>
     440             :   inline Opcode& addIf(T value, const Condition& condition) noexcept { return operator|=(condition ? uint32_t(value) : uint32_t(0)); }
     441             : 
     442           0 :   inline Opcode& addLogicalImm(const LogicalImm& logicalImm) noexcept {
     443           0 :     addImm(logicalImm.n, 22);
     444           0 :     addImm(logicalImm.r, 16);
     445           0 :     addImm(logicalImm.s, 10);
     446           0 :     return *this;
     447             :   }
     448             : 
     449           0 :   inline Opcode& addReg(uint32_t id, uint32_t bitIndex) noexcept { return operator|=((id & 31u) << bitIndex); }
     450             :   inline Opcode& addReg(const Operand_& op, uint32_t bitIndex) noexcept { return addReg(op.id(), bitIndex); }
     451             : 
     452             :   inline Opcode& operator=(uint32_t x) noexcept { v = x; return *this; }
     453             :   inline Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; }
     454           0 :   inline Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; }
     455           0 :   inline Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; }
     456             : 
     457             :   inline uint32_t operator&(uint32_t x) const noexcept { return v & x; }
     458             :   inline uint32_t operator|(uint32_t x) const noexcept { return v | x; }
     459             :   inline uint32_t operator^(uint32_t x) const noexcept { return v ^ x; }
     460             : };
     461             : 
     462             : // a64::Assembler - Signature Utilities
     463             : // ====================================
     464             : 
     465             : // TODO: [ARM] Deprecate matchSignature.
     466             : static inline bool matchSignature(const Operand_& o0, const Operand_& o1, uint32_t instFlags) noexcept {
     467           0 :   if (!(instFlags & (InstDB::kInstFlagLong | InstDB::kInstFlagNarrow)))
     468             :     return o0.signature() == o1.signature();
     469             : 
     470             :   // TODO: [ARM] Something smart to validate this.
     471             :   return true;
     472             : }
     473             : 
     474             : static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t instFlags) noexcept {
     475           0 :   return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature();
     476             : }
     477             : 
     478             : static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, uint32_t instFlags) noexcept {
     479           0 :   return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature() && o2.signature() == o3.signature();;
     480             : }
     481             : 
     482             : // Memory must be either:
     483             : // 1. Absolute address, which will be converted to relative.
     484             : // 2. Relative displacement (Label).
     485             : // 3. Base register + either offset or index.
     486           0 : static inline bool armCheckMemBaseIndexRel(const Mem& mem) noexcept {
     487             :   // Allowed base types (Nothing, Label, and GpX).
     488             :   constexpr uint32_t kBaseMask  = B(0) |
     489             :                                   B(RegType::kLabelTag) |
     490             :                                   B(RegType::kARM_GpX);
     491             : 
     492             :   // Allowed index types (Nothing, GpW, and GpX).
     493             :   constexpr uint32_t kIndexMask = B(0) |
     494             :                                   B(RegType::kARM_GpW) |
     495             :                                   B(RegType::kARM_GpX) ;
     496             : 
     497             :   RegType baseType = mem.baseType();
     498             :   RegType indexType = mem.indexType();
     499             : 
     500           0 :   if (!Support::bitTest(kBaseMask, baseType))
     501             :     return false;
     502             : 
     503           0 :   if (baseType > RegType::kLabelTag) {
     504             :     // Index allows either GpW or GpX.
     505           0 :     if (!Support::bitTest(kIndexMask, indexType))
     506             :       return false;
     507             : 
     508           0 :     if (indexType == RegType::kNone)
     509             :       return true;
     510             :     else
     511           0 :       return !mem.hasOffset();
     512             :   }
     513             :   else {
     514             :     // No index register allowed if this is a PC relative address (literal).
     515           0 :     return indexType == RegType::kNone;
     516             :   }
     517             : }
     518             : 
     519             : struct EncodeFpOpcodeBits {
     520             :   uint32_t sizeMask;
     521             :   uint32_t mask[3];
     522             : };
     523             : 
     524           0 : static inline bool pickFpOpcode(const Vec& reg, uint32_t sOp, uint32_t sHf, uint32_t vOp, uint32_t vHf, Opcode* opcode, uint32_t* szOut) noexcept {
     525             :   static constexpr uint32_t kQBitIndex = 30;
     526             : 
     527             :   static const EncodeFpOpcodeBits szBits[InstDB::kHF_Count] = {
     528             :     { B(2) | B(1)       , { 0u                           , 0u, B(22) } },
     529             :     { B(2) | B(1) | B(0), { 0u                           , 0u, 0u    } },
     530             :     { B(2) | B(1) | B(0), { B(23) | B(22)                , 0u, B(22) } },
     531             :     { B(2) | B(1) | B(0), { B(22) | B(20) | B(19)        , 0u, B(22) } },
     532             :     { B(2) | B(1) | B(0), { B(22) | B(21) | B(15) | B(14), 0u, B(22) } },
     533             :     { B(2) | B(1) | B(0), { B(23)                        , 0u, B(22) } }
     534             :   };
     535             : 
     536           0 :   if (!reg.hasElementType()) {
     537             :     // Scalar operation [HSD].
     538             :     uint32_t sz = diff(reg.type(), RegType::kARM_VecH);
     539           0 :     if (sz > 2u || !Support::bitTest(szBits[sHf].sizeMask, sz))
     540             :       return false;
     541             : 
     542           0 :     opcode->reset(szBits[sHf].mask[sz] ^ sOp);
     543           0 :     *szOut = sz;
     544           0 :     return sOp != 0;
     545             :   }
     546             :   else {
     547             :     // Vector operation [HSD].
     548             :     uint32_t q = diff(reg.type(), RegType::kARM_VecD);
     549           0 :     uint32_t sz = reg.elementType() - Vec::kElementTypeH;
     550             : 
     551           0 :     if (q > 1u || sz > 2u || !Support::bitTest(szBits[vHf].sizeMask, sz))
     552             :       return false;
     553             : 
     554           0 :     opcode->reset(szBits[vHf].mask[sz] ^ (vOp | (q << kQBitIndex)));
     555           0 :     *szOut = sz;
     556           0 :     return vOp != 0;
     557             :   }
     558             : }
     559             : 
     560             : static inline bool pickFpOpcode(const Vec& reg, uint32_t sOp, uint32_t sHf, uint32_t vOp, uint32_t vHf, Opcode* opcode) noexcept {
     561             :   uint32_t sz;
     562           0 :   return pickFpOpcode(reg, sOp, sHf, vOp, vHf, opcode, &sz);
     563             : }
     564             : 
     565             : // a64::Assembler - Operand Checks
     566             : // ===============================
     567             : 
     568             : // Checks whether all operands have the same signature.
     569             : static inline bool checkSignature(const Operand_& o0, const Operand_& o1) noexcept {
     570             :   return o0.signature() == o1.signature();
     571             : }
     572             : 
     573             : static inline bool checkSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept {
     574           0 :   return o0.signature() == o1.signature() &&
     575             :          o1.signature() == o2.signature();
     576             : }
     577             : 
     578             : static inline bool checkSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept {
     579           0 :   return o0.signature() == o1.signature() &&
     580           0 :          o1.signature() == o2.signature() &&
     581             :          o2.signature() == o3.signature();
     582             : }
     583             : 
     584             : // Checks whether the register is GP register of the allowed types.
     585             : //
     586             : // Allowed is a 2-bit mask, where the first bits allows GpW and the second bit
     587             : // allows GpX. These bits are usually stored within the instruction, but could
     588             : // be also hardcoded in the assembler for instructions where GP types are not
     589             : // selectable.
     590             : static inline bool checkGpType(const Operand_& op, uint32_t allowed) noexcept {
     591             :   RegType type = op.as<Reg>().type();
     592           0 :   return Support::bitTest(allowed << uint32_t(RegType::kARM_GpW), type);
     593             : }
     594             : 
     595             : static inline bool checkGpType(const Operand_& op, uint32_t allowed, uint32_t* x) noexcept {
     596             :   // NOTE: We set 'x' to one only when GpW is allowed, otherwise the X is part
     597             :   // of the opcode and we cannot set it. This is why this works without requiring
     598             :   // additional logic.
     599             :   RegType type = op.as<Reg>().type();
     600           0 :   *x = diff(type, RegType::kARM_GpW) & allowed;
     601           0 :   return Support::bitTest(allowed << uint32_t(RegType::kARM_GpW), type);
     602             : }
     603             : 
     604           0 : static inline bool checkGpType(const Operand_& o0, const Operand_& o1, uint32_t allowed, uint32_t* x) noexcept {
     605           0 :   return checkGpType(o0, allowed, x) && checkSignature(o0, o1);
     606             : }
     607             : 
     608           0 : static inline bool checkGpType(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t allowed, uint32_t* x) noexcept {
     609           0 :   return checkGpType(o0, allowed, x) && checkSignature(o0, o1, o2);
     610             : }
     611             : 
     612             : static inline bool checkGpId(const Operand_& op, uint32_t hiId = kZR) noexcept {
     613             :   uint32_t id = op.as<Reg>().id();
     614           0 :   return id < 31u || id == hiId;
     615             : }
     616             : 
     617             : static inline bool checkGpId(const Operand_& o0, const Operand_& o1, uint32_t hiId = kZR) noexcept {
     618             :   uint32_t id0 = o0.as<Reg>().id();
     619             :   uint32_t id1 = o1.as<Reg>().id();
     620             : 
     621           0 :   return (id0 < 31u || id0 == hiId) && (id1 < 31u || id1 == hiId);
     622             : }
     623             : 
     624           0 : static inline bool checkGpId(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t hiId = kZR) noexcept {
     625             :   uint32_t id0 = o0.as<Reg>().id();
     626             :   uint32_t id1 = o1.as<Reg>().id();
     627             :   uint32_t id2 = o2.as<Reg>().id();
     628             : 
     629           0 :   return (id0 < 31u || id0 == hiId) && (id1 < 31u || id1 == hiId) && (id2 < 31u || id2 == hiId);
     630             : }
     631             : 
     632             : static inline bool checkVecId(const Operand_& op) noexcept {
     633             :   uint32_t id = op.as<Reg>().id();
     634             :   return id <= 31u;
     635             : }
     636             : 
     637             : static inline bool checkVecId(const Operand_& o0, const Operand_& o1) noexcept {
     638             :   uint32_t id0 = o0.as<Reg>().id();
     639             :   uint32_t id1 = o1.as<Reg>().id();
     640             : 
     641           0 :   return (id0 | id1) <= 31u;
     642             : }
     643             : 
     644             : /* Unused at the moment.
     645             : static inline bool checkVecId(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept {
     646             :   uint32_t id0 = o0.as<Reg>().id();
     647             :   uint32_t id1 = o1.as<Reg>().id();
     648             :   uint32_t id2 = o2.as<Reg>().id();
     649             : 
     650             :   return (id0 | id1 | id2) <= 31u;
     651             : }
     652             : 
     653             : static inline bool checkVecId(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept {
     654             :   uint32_t id0 = o0.as<Reg>().id();
     655             :   uint32_t id1 = o1.as<Reg>().id();
     656             :   uint32_t id2 = o2.as<Reg>().id();
     657             :   uint32_t id3 = o3.as<Reg>().id();
     658             : 
     659             :   return (id0 | id1 | id2 | id3) <= 31u;
     660             : }
     661             : */
     662             : 
     663             : static inline bool checkMemBase(const Mem& mem) noexcept {
     664           0 :   return mem.baseType() == RegType::kARM_GpX && mem.baseId() <= 31;
     665             : }
     666             : 
     667             : static inline bool checkEven(const Operand_& o0, const Operand_& o1) noexcept {
     668           0 :   return ((o0.id() | o1.id()) & 1) == 0;
     669             : }
     670             : 
     671             : static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1) noexcept {
     672           0 :   return ((o0.id() + 1u) & 0x1Fu) == o1.id();
     673             : }
     674             : 
     675             : static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept {
     676           0 :   return ((o0.id() + 1u) & 0x1Fu) == o1.id() &&
     677           0 :          ((o0.id() + 2u) & 0x1Fu) == o2.id();
     678             : }
     679             : 
     680           0 : static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept {
     681           0 :   return ((o0.id() + 1u) & 0x1Fu) == o1.id() &&
     682           0 :          ((o0.id() + 2u) & 0x1Fu) == o2.id() &&
     683           0 :          ((o0.id() + 3u) & 0x1Fu) == o3.id();
     684             : }
     685             : 
     686             : // a64::Assembler - CheckReg
     687             : // =========================
     688             : 
     689             : #define V(index) (index == uint32_t(RegType::kARM_GpW)  ? Gp::kIdZr :  \
     690             :                   index == uint32_t(RegType::kARM_GpX)  ? Gp::kIdZr :  \
     691             :                   index == uint32_t(RegType::kARM_VecB) ? 31u       :  \
     692             :                   index == uint32_t(RegType::kARM_VecH) ? 31u       :  \
     693             :                   index == uint32_t(RegType::kARM_VecS) ? 31u       :  \
     694             :                   index == uint32_t(RegType::kARM_VecD) ? 31u       :  \
     695             :                   index == uint32_t(RegType::kARM_VecV) ? 31u       : 0)
     696             : static const Support::Array<uint8_t, 32> commonHiRegIdOfType = {{
     697             :   ASMJIT_LOOKUP_TABLE_32(V, 0)
     698             : }};
     699             : #undef V
     700             : 
     701             : static inline bool checkValidRegs(const Operand_& o0) noexcept {
     702           0 :   return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()]));
     703             : }
     704             : 
     705           0 : static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1) noexcept {
     706           0 :   return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) &
     707           0 :          ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) ;
     708             : }
     709             : 
     710           0 : static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept {
     711           0 :   return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) &
     712           0 :          ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) &
     713           0 :          ((o2.id() < 31) | (o2.id() == commonHiRegIdOfType[o2.as<Reg>().type()])) ;
     714             : }
     715             : 
     716           0 : static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept {
     717           0 :   return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) &
     718           0 :          ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) &
     719           0 :          ((o2.id() < 31) | (o2.id() == commonHiRegIdOfType[o2.as<Reg>().type()])) &
     720           0 :          ((o3.id() < 31) | (o3.id() == commonHiRegIdOfType[o3.as<Reg>().type()])) ;
     721             : }
     722             : 
     723             : // a64::Assembler - Construction & Destruction
     724             : // ===========================================
     725             : 
     726           0 : Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() {
     727           0 :   _archMask = uint64_t(1) << uint32_t(Arch::kAArch64);
     728           0 :   assignEmitterFuncs(this);
     729             : 
     730           0 :   if (code)
     731           0 :     code->attach(this);
     732           0 : }
     733             : 
     734           0 : Assembler::~Assembler() noexcept {}
     735             : 
     736             : // a64::Assembler - Emit
     737             : // =====================
     738             : 
     739             : #define ENC_OPS1(OP0) \
     740             :   (uint32_t(OperandType::k##OP0))
     741             : 
     742             : #define ENC_OPS2(OP0, OP1) \
     743             :   (uint32_t(OperandType::k##OP0) + \
     744             :   (uint32_t(OperandType::k##OP1) << 3))
     745             : 
     746             : #define ENC_OPS3(OP0, OP1, OP2) \
     747             :   (uint32_t(OperandType::k##OP0) + \
     748             :   (uint32_t(OperandType::k##OP1) << 3) + \
     749             :   (uint32_t(OperandType::k##OP2) << 6))
     750             : 
     751             : #define ENC_OPS4(OP0, OP1, OP2, OP3) \
     752             :   (uint32_t(OperandType::k##OP0) + \
     753             :   (uint32_t(OperandType::k##OP1) << 3) + \
     754             :   (uint32_t(OperandType::k##OP2) << 6) + \
     755             :   (uint32_t(OperandType::k##OP3) << 9))
     756             : 
     757           0 : Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) {
     758             :   // Logging/Validation/Error.
     759             :   constexpr InstOptions kRequiresSpecialHandling = InstOptions::kReserved;
     760             : 
     761             :   Error err;
     762             :   CodeWriter writer(this);
     763             : 
     764             :   // Combine all instruction options and also check whether the instruction
     765             :   // is valid. All options that require special handling (including invalid
     766             :   // instruction) are handled by the next branch.
     767           0 :   InstOptions options = InstOptions(instId - 1 >= Inst::_kIdCount - 1) | InstOptions((size_t)(_bufferEnd - writer.cursor()) < 4) | instOptions() | forcedInstOptions();
     768             : 
     769             :   CondCode instCC = BaseInst::extractARMCondCode(instId);
     770           0 :   instId = instId & uint32_t(InstIdParts::kRealId);
     771             : 
     772           0 :   if (instId >= Inst::_kIdCount)
     773             :     instId = 0;
     774             : 
     775             :   const InstDB::InstInfo* instInfo = &InstDB::_instInfoTable[instId];
     776           0 :   uint32_t encodingIndex = instInfo->_encodingDataIndex;
     777             : 
     778             :   Opcode opcode;
     779             :   uint32_t isign4;
     780             :   uint32_t instFlags;
     781             : 
     782             :   const Operand_& o3 = opExt[EmitterUtils::kOp3];
     783             :   const Operand_* rmRel = nullptr;
     784             : 
     785             :   uint32_t multipleOpData[4];
     786             :   uint32_t multipleOpCount;
     787             : 
     788             :   // These are only used when instruction uses a relative displacement.
     789             :   OffsetFormat offsetFormat;     // Offset format.
     790             :   uint64_t offsetValue;          // Offset value (if known).
     791             : 
     792           0 :   if (ASMJIT_UNLIKELY(Support::test(options, kRequiresSpecialHandling))) {
     793           0 :     if (ASMJIT_UNLIKELY(!_code))
     794           0 :       return reportError(DebugUtils::errored(kErrorNotInitialized));
     795             : 
     796             :     // Unknown instruction.
     797           0 :     if (ASMJIT_UNLIKELY(instId == 0))
     798           0 :       goto InvalidInstruction;
     799             : 
     800             :     // Condition code can only be used with 'B' instruction.
     801           0 :     if (ASMJIT_UNLIKELY(instCC != CondCode::kAL && instId != Inst::kIdB))
     802           0 :       goto InvalidInstruction;
     803             : 
     804             :     // Grow request, happens rarely.
     805             :     err = writer.ensureSpace(this, 4);
     806           0 :     if (ASMJIT_UNLIKELY(err))
     807           0 :       goto Failed;
     808             : 
     809             : #ifndef ASMJIT_NO_VALIDATION
     810             :     // Strict validation.
     811           0 :     if (hasDiagnosticOption(DiagnosticOptions::kValidateAssembler)) {
     812             :       Operand_ opArray[Globals::kMaxOpCount];
     813             :       EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt);
     814             : 
     815           0 :       err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone);
     816           0 :       if (ASMJIT_UNLIKELY(err))
     817           0 :         goto Failed;
     818             :     }
     819             : #endif
     820             :   }
     821             : 
     822             :   // Signature of the first 4 operands.
     823           0 :   isign4 = (uint32_t(o0.opType())     ) +
     824           0 :            (uint32_t(o1.opType()) << 3) +
     825           0 :            (uint32_t(o2.opType()) << 6) +
     826           0 :            (uint32_t(o3.opType()) << 9);
     827             :   instFlags = instInfo->flags();
     828             : 
     829           0 :   switch (instInfo->_encoding) {
     830             :     // ------------------------------------------------------------------------
     831             :     // [Base - Universal]
     832             :     // ------------------------------------------------------------------------
     833             : 
     834           0 :     case InstDB::kEncodingBaseOp: {
     835             :       const InstDB::EncodingData::BaseOp& opData = InstDB::EncodingData::baseOp[encodingIndex];
     836             : 
     837           0 :       if (isign4 == 0) {
     838           0 :         opcode.reset(opData.opcode);
     839           0 :         goto EmitOp;
     840             :       }
     841             : 
     842             :       break;
     843             :     }
     844             : 
     845           0 :     case InstDB::kEncodingBaseOpImm: {
     846             :       const InstDB::EncodingData::BaseOpImm& opData = InstDB::EncodingData::baseOpImm[encodingIndex];
     847             : 
     848           0 :       if (isign4 == ENC_OPS1(Imm)) {
     849             :         uint64_t imm = o0.as<Imm>().valueAs<uint64_t>();
     850           0 :         uint32_t immMax = 1u << opData.immBits;
     851             : 
     852           0 :         if (imm >= immMax)
     853           0 :           goto InvalidImmediate;
     854             : 
     855           0 :         opcode.reset(opData.opcode);
     856           0 :         opcode.addImm(imm, opData.immOffset);
     857           0 :         goto EmitOp;
     858             :       }
     859             : 
     860             :       break;
     861             :     }
     862             : 
     863           0 :     case InstDB::kEncodingBaseR: {
     864             :       const InstDB::EncodingData::BaseR& opData = InstDB::EncodingData::baseR[encodingIndex];
     865             : 
     866           0 :       if (isign4 == ENC_OPS1(Reg)) {
     867           0 :         if (!checkGpType(o0, opData.rType))
     868           0 :           goto InvalidInstruction;
     869             : 
     870           0 :         if (!checkGpId(o0, opData.rHiId))
     871           0 :           goto InvalidPhysId;
     872             : 
     873           0 :         opcode.reset(opData.opcode);
     874           0 :         opcode.addReg(o0, opData.rShift);
     875           0 :         goto EmitOp;
     876             :       }
     877             : 
     878             :       break;
     879             :     }
     880             : 
     881           0 :     case InstDB::kEncodingBaseRR: {
     882             :       const InstDB::EncodingData::BaseRR& opData = InstDB::EncodingData::baseRR[encodingIndex];
     883             : 
     884           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
     885             :         uint32_t x;
     886           0 :         if (!checkGpType(o0, opData.aType, &x))
     887           0 :           goto InvalidInstruction;
     888             : 
     889           0 :         if (!checkGpType(o1, opData.bType))
     890           0 :           goto InvalidInstruction;
     891             : 
     892           0 :         if (opData.uniform && !checkSignature(o0, o1))
     893           0 :           goto InvalidInstruction;
     894             : 
     895           0 :         if (!checkGpId(o0, opData.aHiId))
     896           0 :           goto InvalidPhysId;
     897             : 
     898           0 :         if (!checkGpId(o1, opData.bHiId))
     899           0 :           goto InvalidPhysId;
     900             : 
     901           0 :         opcode.reset(opData.opcode);
     902             :         opcode.addImm(x, 31);
     903           0 :         opcode.addReg(o1, opData.bShift);
     904           0 :         opcode.addReg(o0, opData.aShift);
     905           0 :         goto EmitOp;
     906             :       }
     907             : 
     908             :       break;
     909             :     }
     910             : 
     911           0 :     case InstDB::kEncodingBaseRRR: {
     912             :       const InstDB::EncodingData::BaseRRR& opData = InstDB::EncodingData::baseRRR[encodingIndex];
     913             : 
     914           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
     915             :         uint32_t x;
     916           0 :         if (!checkGpType(o0, opData.aType, &x))
     917           0 :           goto InvalidInstruction;
     918             : 
     919           0 :         if (!checkGpType(o1, opData.bType))
     920           0 :           goto InvalidInstruction;
     921             : 
     922           0 :         if (!checkGpType(o2, opData.cType))
     923           0 :           goto InvalidInstruction;
     924             : 
     925           0 :         if (opData.uniform && !checkSignature(o0, o1, o2))
     926           0 :           goto InvalidInstruction;
     927             : 
     928           0 :         if (!checkGpId(o0, opData.aHiId))
     929           0 :           goto InvalidPhysId;
     930             : 
     931           0 :         if (!checkGpId(o1, opData.bHiId))
     932           0 :           goto InvalidPhysId;
     933             : 
     934           0 :         if (!checkGpId(o2, opData.cHiId))
     935           0 :           goto InvalidPhysId;
     936             : 
     937             :         opcode.reset(opData.opcode());
     938             :         opcode.addImm(x, 31);
     939             :         opcode.addReg(o2, 16);
     940             :         opcode.addReg(o1, 5);
     941             :         opcode.addReg(o0, 0);
     942           0 :         goto EmitOp;
     943             :       }
     944             : 
     945             :       break;
     946             :     }
     947             : 
     948           0 :     case InstDB::kEncodingBaseRRRR: {
     949             :       const InstDB::EncodingData::BaseRRRR& opData = InstDB::EncodingData::baseRRRR[encodingIndex];
     950             : 
     951           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
     952             :         uint32_t x;
     953           0 :         if (!checkGpType(o0, opData.aType, &x))
     954           0 :           goto InvalidInstruction;
     955             : 
     956           0 :         if (!checkGpType(o1, opData.bType))
     957           0 :           goto InvalidInstruction;
     958             : 
     959           0 :         if (!checkGpType(o2, opData.cType))
     960           0 :           goto InvalidInstruction;
     961             : 
     962           0 :         if (!checkGpType(o3, opData.dType))
     963           0 :           goto InvalidInstruction;
     964             : 
     965           0 :         if (opData.uniform && !checkSignature(o0, o1, o2, o3))
     966           0 :           goto InvalidInstruction;
     967             : 
     968           0 :         if (!checkGpId(o0, opData.aHiId))
     969           0 :           goto InvalidPhysId;
     970             : 
     971           0 :         if (!checkGpId(o1, opData.bHiId))
     972           0 :           goto InvalidPhysId;
     973             : 
     974           0 :         if (!checkGpId(o2, opData.cHiId))
     975           0 :           goto InvalidPhysId;
     976             : 
     977           0 :         if (!checkGpId(o3, opData.dHiId))
     978           0 :           goto InvalidPhysId;
     979             : 
     980             :         opcode.reset(opData.opcode());
     981             :         opcode.addImm(x, 31);
     982             :         opcode.addReg(o2, 16);
     983             :         opcode.addReg(o3, 10);
     984             :         opcode.addReg(o1, 5);
     985             :         opcode.addReg(o0, 0);
     986           0 :         goto EmitOp;
     987             :       }
     988             : 
     989             :       break;
     990             :     }
     991             : 
     992           0 :     case InstDB::kEncodingBaseRRII: {
     993             :       const InstDB::EncodingData::BaseRRII& opData = InstDB::EncodingData::baseRRII[encodingIndex];
     994             : 
     995           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
     996           0 :         if (!checkGpType(o0, opData.aType))
     997           0 :           goto InvalidInstruction;
     998             : 
     999           0 :         if (!checkGpType(o1, opData.bType))
    1000           0 :           goto InvalidInstruction;
    1001             : 
    1002           0 :         if (!checkGpId(o0, opData.aHiId))
    1003           0 :           goto InvalidPhysId;
    1004             : 
    1005           0 :         if (!checkGpId(o1, opData.bHiId))
    1006           0 :           goto InvalidPhysId;
    1007             : 
    1008           0 :         if (o2.as<Imm>().valueAs<uint64_t>() >= Support::bitMask(opData.aImmSize + opData.aImmDiscardLsb) ||
    1009           0 :             o3.as<Imm>().valueAs<uint64_t>() >= Support::bitMask(opData.bImmSize + opData.bImmDiscardLsb))
    1010           0 :           goto InvalidImmediate;
    1011             : 
    1012           0 :         uint32_t aImm = o2.as<Imm>().valueAs<uint32_t>() >> opData.aImmDiscardLsb;
    1013           0 :         uint32_t bImm = o3.as<Imm>().valueAs<uint32_t>() >> opData.bImmDiscardLsb;
    1014             : 
    1015           0 :         if ((aImm << opData.aImmDiscardLsb) != o2.as<Imm>().valueAs<uint32_t>() ||
    1016           0 :             (bImm << opData.bImmDiscardLsb) != o3.as<Imm>().valueAs<uint32_t>())
    1017           0 :           goto InvalidImmediate;
    1018             : 
    1019             :         opcode.reset(opData.opcode());
    1020           0 :         opcode.addImm(aImm, opData.aImmOffset);
    1021           0 :         opcode.addImm(bImm, opData.bImmOffset);
    1022             :         opcode.addReg(o1, 5);
    1023             :         opcode.addReg(o0, 0);
    1024           0 :         goto EmitOp;
    1025             :       }
    1026             : 
    1027             :       break;
    1028             :     }
    1029             : 
    1030             :     // ------------------------------------------------------------------------
    1031             :     // [Base - Mov]
    1032             :     // ------------------------------------------------------------------------
    1033             : 
    1034             :     case InstDB::kEncodingBaseMov: {
    1035             :       // MOV is a pseudo instruction that uses various instructions depending on its signature.
    1036             :       uint32_t x = diff(o0.as<Reg>().type(), RegType::kARM_GpW);
    1037           0 :       if (x > 1)
    1038           0 :         goto InvalidInstruction;
    1039             : 
    1040           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    1041           0 :         if (!o0.as<Reg>().isGp())
    1042           0 :           goto InvalidInstruction;
    1043             : 
    1044           0 :         if (!checkSignature(o0, o1))
    1045           0 :           goto InvalidInstruction;
    1046             : 
    1047           0 :         bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP();
    1048             :         if (hasSP) {
    1049             :           // Cannot be combined with ZR.
    1050           0 :           if (!checkGpId(o0, o1, kSP))
    1051           0 :             goto InvalidPhysId;
    1052             : 
    1053             :           // MOV Rd, Rm -> ADD Rd, Rn, #0.
    1054             :           opcode.reset(0b00010001000000000000000000000000);
    1055             :           opcode.addImm(x, 31);
    1056             :           opcode.addReg(o1, 5);
    1057             :           opcode.addReg(o0, 0);
    1058           0 :           goto EmitOp;
    1059             :         }
    1060             :         else {
    1061           0 :           if (!checkGpId(o0, o1, kZR))
    1062           0 :             goto InvalidPhysId;
    1063             : 
    1064             :           // MOV Rd, Rm -> ORR Rd, <ZR>, Rm.
    1065             :           opcode.reset(0b00101010000000000000001111100000);
    1066             :           opcode.addImm(x, 31);
    1067             :           opcode.addReg(o1, 16);
    1068             :           opcode.addReg(o0, 0);
    1069           0 :           goto EmitOp;
    1070             :         }
    1071             :       }
    1072             : 
    1073           0 :       if (isign4 == ENC_OPS2(Reg, Imm)) {
    1074           0 :         if (!o0.as<Reg>().isGp())
    1075           0 :           goto InvalidInstruction;
    1076             : 
    1077             :         uint64_t immValue = o1.as<Imm>().valueAs<uint64_t>();
    1078           0 :         if (!x)
    1079           0 :           immValue &= 0xFFFFFFFFu;
    1080             : 
    1081             :         // Prefer a single MOVN/MOVZ instruction over a logical instruction.
    1082           0 :         multipleOpCount = encodeMovSequence64(multipleOpData, immValue, o0.id() & 31, x);
    1083           0 :         if (multipleOpCount == 1 && !o0.as<Gp>().isSP()) {
    1084           0 :           opcode.reset(multipleOpData[0]);
    1085           0 :           goto EmitOp;
    1086             :         }
    1087             : 
    1088             :         // Logical instructions use 13-bit immediate pattern encoded as N:ImmR:ImmS.
    1089             :         LogicalImm logicalImm;
    1090           0 :         if (!o0.as<Gp>().isZR()) {
    1091           0 :           if (Utils::encodeLogicalImm(immValue, x ? 64 : 32, &logicalImm)) {
    1092           0 :             if (!checkGpId(o0, kSP))
    1093           0 :               goto InvalidPhysId;
    1094             : 
    1095             :             opcode.reset(0b00110010000000000000001111100000);
    1096             :             opcode.addImm(x, 31);
    1097           0 :             opcode.addLogicalImm(logicalImm);
    1098             :             opcode.addReg(o0, 0);
    1099           0 :             goto EmitOp;
    1100             :           }
    1101             :         }
    1102             : 
    1103           0 :         if (!checkGpId(o0, kZR))
    1104           0 :           goto InvalidPhysId;
    1105             : 
    1106           0 :         goto EmitOp_Multiple;
    1107             :       }
    1108             : 
    1109             :       break;
    1110             :     }
    1111             : 
    1112           0 :     case InstDB::kEncodingBaseMovKNZ: {
    1113             :       const InstDB::EncodingData::BaseMovKNZ& opData = InstDB::EncodingData::baseMovKNZ[encodingIndex];
    1114             : 
    1115             :       uint32_t x = diff(o0.as<Reg>().type(), RegType::kARM_GpW);
    1116           0 :       if (x > 1)
    1117           0 :         goto InvalidInstruction;
    1118             : 
    1119           0 :       if (!checkGpId(o0, kZR))
    1120           0 :         goto InvalidPhysId;
    1121             : 
    1122           0 :       opcode.reset(opData.opcode);
    1123             :       opcode.addImm(x, 31);
    1124             : 
    1125           0 :       if (isign4 == ENC_OPS2(Reg, Imm)) {
    1126             :         uint64_t imm16 = o1.as<Imm>().valueAs<uint64_t>();
    1127           0 :         if (imm16 > 0xFFFFu)
    1128           0 :           goto InvalidImmediate;
    1129             : 
    1130             :         opcode.addImm(imm16, 5);
    1131             :         opcode.addReg(o0, 0);
    1132           0 :         goto EmitOp;
    1133             :       }
    1134             : 
    1135           0 :       if (isign4 == ENC_OPS3(Reg, Imm, Imm)) {
    1136             :         uint64_t imm16 = o1.as<Imm>().valueAs<uint64_t>();
    1137             :         uint32_t shiftType = o2.as<Imm>().predicate();
    1138             :         uint64_t shiftValue = o2.as<Imm>().valueAs<uint64_t>();
    1139             : 
    1140           0 :         if (imm16 > 0xFFFFu || shiftValue > 48 || shiftType != uint32_t(ShiftOp::kLSL))
    1141           0 :           goto InvalidImmediate;
    1142             : 
    1143             :         // Convert shift value to 'hw' field.
    1144           0 :         uint32_t hw = uint32_t(shiftValue) >> 4;
    1145           0 :         if ((hw << 4) != uint32_t(shiftValue))
    1146           0 :           goto InvalidImmediate;
    1147             : 
    1148             :         opcode.addImm(hw, 21);
    1149             :         opcode.addImm(imm16, 5);
    1150             :         opcode.addReg(o0, 0);
    1151             : 
    1152           0 :         if (!x && hw > 1u)
    1153           0 :           goto InvalidImmediate;
    1154             : 
    1155           0 :         goto EmitOp;
    1156             :       }
    1157             : 
    1158             :       break;
    1159             :     }
    1160             : 
    1161             :     // ------------------------------------------------------------------------
    1162             :     // [Base - Adr]
    1163             :     // ------------------------------------------------------------------------
    1164             : 
    1165           0 :     case InstDB::kEncodingBaseAdr: {
    1166             :       const InstDB::EncodingData::BaseAdr& opData = InstDB::EncodingData::baseAdr[encodingIndex];
    1167             : 
    1168           0 :       if (isign4 == ENC_OPS2(Reg, Label) || isign4 == ENC_OPS2(Reg, Imm)) {
    1169           0 :         if (!o0.as<Reg>().isGpX())
    1170           0 :           goto InvalidInstruction;
    1171             : 
    1172           0 :         if (!checkGpId(o0, kZR))
    1173           0 :           goto InvalidPhysId;
    1174             : 
    1175             :         opcode.reset(opData.opcode());
    1176             :         opcode.addReg(o0, 0);
    1177           0 :         offsetFormat.resetToImmValue(opData.offsetType, 4, 5, 21, 0);
    1178             : 
    1179           0 :         if (instId == Inst::kIdAdrp)
    1180           0 :           offsetFormat._immDiscardLsb = 12;
    1181             : 
    1182             :         rmRel = &o1;
    1183           0 :         goto EmitOp_Rel;
    1184             :       }
    1185             : 
    1186             :       break;
    1187             :     }
    1188             : 
    1189             :     // ------------------------------------------------------------------------
    1190             :     // [Base - Arithmetic and Logical]
    1191             :     // ------------------------------------------------------------------------
    1192             : 
    1193           0 :     case InstDB::kEncodingBaseAddSub: {
    1194             :       const InstDB::EncodingData::BaseAddSub& opData = InstDB::EncodingData::baseAddSub[encodingIndex];
    1195             : 
    1196             :       uint32_t x;
    1197             :       if (!checkGpType(o0, o1, kWX, &x))
    1198           0 :         goto InvalidInstruction;
    1199             : 
    1200           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm) || isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
    1201           0 :         opcode.reset(uint32_t(opData.immediateOp) << 24);
    1202             : 
    1203             :         // ADD | SUB (immediate) - ZR is not allowed.
    1204             :         // ADDS|SUBS (immediate) - ZR allowed in Rd, SP allowed in Rn.
    1205           0 :         uint32_t aHiId = opcode.get() & B(29) ? kZR : kSP;
    1206             :         uint32_t bHiId = kSP;
    1207             : 
    1208           0 :         if (!checkGpId(o0, aHiId) || !checkGpId(o1, bHiId))
    1209           0 :           goto InvalidPhysId;
    1210             : 
    1211             :         // ADD|SUB (immediate) use 12-bit immediate optionally shifted by 'LSL #12'.
    1212             :         uint64_t imm = o2.as<Imm>().valueAs<uint64_t>();
    1213             :         uint32_t shift = 0;
    1214             : 
    1215           0 :         if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
    1216           0 :           if (o3.as<Imm>().predicate() != uint32_t(ShiftOp::kLSL))
    1217           0 :             goto InvalidImmediate;
    1218             : 
    1219           0 :           if (o3.as<Imm>().value() != 0 && o3.as<Imm>().value() != 12)
    1220           0 :             goto InvalidImmediate;
    1221             : 
    1222           0 :           shift = uint32_t(o3.as<Imm>().value() != 0);
    1223             :         }
    1224             : 
    1225             :         // Accept immediate value of '0x00XXX000' by setting 'shift' to 12.
    1226           0 :         if (imm > 0xFFFu) {
    1227           0 :           if (shift || (imm & ~uint64_t(0xFFFu << 12)) != 0)
    1228           0 :             goto InvalidImmediate;
    1229             :           shift = 1;
    1230           0 :           imm >>= 12;
    1231             :         }
    1232             : 
    1233             :         opcode.addImm(x, 31);
    1234             :         opcode.addImm(shift, 22);
    1235             :         opcode.addImm(imm, 10);
    1236             :         opcode.addReg(o1, 5);
    1237             :         opcode.addReg(o0, 0);
    1238           0 :         goto EmitOp;
    1239             :       }
    1240             : 
    1241           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    1242           0 :         if (!checkSignature(o1, o2))
    1243           0 :           goto InvalidInstruction;
    1244             : 
    1245           0 :         uint32_t opSize = x ? 64 : 32;
    1246             :         uint64_t shift = 0;
    1247             :         uint32_t sType = uint32_t(ShiftOp::kLSL);
    1248             : 
    1249           0 :         if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    1250             :           sType = o3.as<Imm>().predicate();
    1251             :           shift = o3.as<Imm>().valueAs<uint64_t>();
    1252             :         }
    1253             : 
    1254           0 :         if (!checkGpId(o2, kZR))
    1255           0 :           goto InvalidPhysId;
    1256             : 
    1257             :         // Shift operation - LSL, LSR, ASR.
    1258           0 :         if (sType <= uint32_t(ShiftOp::kASR)) {
    1259           0 :           bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP();
    1260             :           if (!hasSP) {
    1261           0 :             if (!checkGpId(o0, o1, kZR))
    1262           0 :               goto InvalidPhysId;
    1263             : 
    1264           0 :             if (shift >= opSize)
    1265           0 :               goto InvalidImmediate;
    1266             : 
    1267           0 :             opcode.reset(uint32_t(opData.shiftedOp) << 21);
    1268             :             opcode.addImm(x, 31);
    1269             :             opcode.addImm(sType, 22);
    1270             :             opcode.addReg(o2, 16);
    1271             :             opcode.addImm(shift, 10);
    1272             :             opcode.addReg(o1, 5);
    1273             :             opcode.addReg(o0, 0);
    1274           0 :             goto EmitOp;
    1275             :           }
    1276             : 
    1277             :           // SP register can only be used with LSL or Extend.
    1278           0 :           if (sType != uint32_t(ShiftOp::kLSL))
    1279           0 :             goto InvalidImmediate;
    1280           0 :           sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW);
    1281             :         }
    1282             : 
    1283             :         // Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX.
    1284           0 :         opcode.reset(uint32_t(opData.extendedOp) << 21);
    1285           0 :         sType -= uint32_t(ShiftOp::kUXTB);
    1286             : 
    1287           0 :         if (sType > 7 || shift > 4)
    1288           0 :           goto InvalidImmediate;
    1289             : 
    1290           0 :         if (!(opcode.get() & B(29))) {
    1291             :           // ADD|SUB (extend) - ZR is not allowed.
    1292           0 :           if (!checkGpId(o0, o1, kSP))
    1293           0 :             goto InvalidPhysId;
    1294             :         }
    1295             :         else {
    1296             :           // ADDS|SUBS (extend) - ZR allowed in Rd, SP allowed in Rn.
    1297           0 :           if (!checkGpId(o0, kZR) || !checkGpId(o1, kSP))
    1298           0 :             goto InvalidPhysId;
    1299             :         }
    1300             : 
    1301             :         opcode.addImm(x, 31);
    1302             :         opcode.addReg(o2, 16);
    1303             :         opcode.addImm(sType, 13);
    1304             :         opcode.addImm(shift, 10);
    1305             :         opcode.addReg(o1, 5);
    1306             :         opcode.addReg(o0, 0);
    1307           0 :         goto EmitOp;
    1308             :       }
    1309             : 
    1310             :       break;
    1311             :     }
    1312             : 
    1313           0 :     case InstDB::kEncodingBaseLogical: {
    1314             :       const InstDB::EncodingData::BaseLogical& opData = InstDB::EncodingData::baseLogical[encodingIndex];
    1315             : 
    1316             :       uint32_t x;
    1317             :       if (!checkGpType(o0, o1, kWX, &x))
    1318           0 :         goto InvalidInstruction;
    1319             : 
    1320           0 :       if (!checkSignature(o0, o1))
    1321           0 :         goto InvalidInstruction;
    1322             : 
    1323           0 :       uint32_t opSize = x ? 64 : 32;
    1324             : 
    1325           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp != 0) {
    1326           0 :         opcode.reset(uint32_t(opData.immediateOp) << 23);
    1327             : 
    1328             :         // AND|ANDS|BIC|BICS|ORR|EOR (immediate) uses a LogicalImm format described by N:R:S values.
    1329             :         uint64_t immMask = Support::lsbMask<uint64_t>(opSize);
    1330             :         uint64_t immValue = o2.as<Imm>().valueAs<uint64_t>();
    1331             : 
    1332           0 :         if (opData.negateImm)
    1333           0 :           immValue ^= immMask;
    1334             : 
    1335             :         // Logical instructions use 13-bit immediate pattern encoded as N:ImmS:ImmR.
    1336             :         LogicalImm logicalImm;
    1337           0 :         if (!Utils::encodeLogicalImm(immValue & immMask, opSize, &logicalImm))
    1338           0 :           goto InvalidImmediate;
    1339             : 
    1340             :         // AND|BIC|ORR|EOR (immediate) can have SP on destination, but ANDS|BICS (immediate) cannot.
    1341             :         uint32_t kOpANDS = 0x3 << 29;
    1342           0 :         bool isANDS = (opcode.get() & kOpANDS) == kOpANDS;
    1343             : 
    1344           0 :         if (!checkGpId(o0, isANDS ? kZR : kSP) || !checkGpId(o1, kZR))
    1345           0 :           goto InvalidPhysId;
    1346             : 
    1347             :         opcode.addImm(x, 31);
    1348           0 :         opcode.addLogicalImm(logicalImm);
    1349             :         opcode.addReg(o1, 5);
    1350             :         opcode.addReg(o0, 0);
    1351           0 :         goto EmitOp;
    1352             :       }
    1353             : 
    1354           0 :       if (!checkSignature(o1, o2))
    1355           0 :         goto InvalidInstruction;
    1356             : 
    1357           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    1358           0 :         if (!checkGpId(o0, o1, o2, kZR))
    1359           0 :           goto InvalidPhysId;
    1360             : 
    1361           0 :         opcode.reset(uint32_t(opData.shiftedOp) << 21);
    1362             :         opcode.addImm(x, 31);
    1363             :         opcode.addReg(o2, 16);
    1364             :         opcode.addReg(o1, 5);
    1365             :         opcode.addReg(o0, 0);
    1366           0 :         goto EmitOp;
    1367             :       }
    1368             : 
    1369           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    1370           0 :         if (!checkGpId(o0, o1, o2, kZR))
    1371           0 :           goto InvalidPhysId;
    1372             : 
    1373             :         uint32_t shiftType = o3.as<Imm>().predicate();
    1374             :         uint64_t opShift = o3.as<Imm>().valueAs<uint64_t>();
    1375             : 
    1376           0 :         if (shiftType > 0x3 || opShift >= opSize)
    1377           0 :           goto InvalidImmediate;
    1378             : 
    1379           0 :         opcode.reset(uint32_t(opData.shiftedOp) << 21);
    1380             :         opcode.addImm(x, 31);
    1381             :         opcode.addImm(shiftType, 22);
    1382             :         opcode.addReg(o2, 16);
    1383             :         opcode.addImm(opShift, 10);
    1384             :         opcode.addReg(o1, 5);
    1385             :         opcode.addReg(o0, 0);
    1386           0 :         goto EmitOp;
    1387             :       }
    1388             : 
    1389             :       break;
    1390             :     }
    1391             : 
    1392           0 :     case InstDB::kEncodingBaseCmpCmn: {
    1393             :       const InstDB::EncodingData::BaseCmpCmn& opData = InstDB::EncodingData::baseCmpCmn[encodingIndex];
    1394             : 
    1395             :       uint32_t x;
    1396           0 :       if (!checkGpType(o0, kWX, &x))
    1397           0 :         goto InvalidInstruction;
    1398             : 
    1399           0 :       if (isign4 == ENC_OPS2(Reg, Imm)) {
    1400             :         // CMN|CMP (immediate) - ZR is not allowed.
    1401           0 :         if (!checkGpId(o0, kSP))
    1402           0 :           goto InvalidPhysId;
    1403             : 
    1404             :         // CMN|CMP (immediate) use 12-bit immediate optionally shifted by 'LSL #12'.
    1405             :         const Imm& imm12 = o1.as<Imm>();
    1406             :         uint32_t immShift = 0;
    1407             :         uint64_t immValue = imm12.valueAs<uint64_t>();
    1408             : 
    1409           0 :         if (immValue > 0xFFFu) {
    1410           0 :           if ((immValue & ~uint64_t(0xFFFu << 12)) != 0)
    1411           0 :             goto InvalidImmediate;
    1412             :           immShift = 1;
    1413           0 :           immValue >>= 12;
    1414             :         }
    1415             : 
    1416           0 :         opcode.reset(uint32_t(opData.immediateOp) << 24);
    1417             :         opcode.addImm(x, 31);
    1418             :         opcode.addImm(immShift, 22);
    1419             :         opcode.addImm(immValue, 10);
    1420             :         opcode.addReg(o0, 5);
    1421             :         opcode.addReg(Gp::kIdZr, 0);
    1422           0 :         goto EmitOp;
    1423             :       }
    1424             : 
    1425           0 :       if (isign4 == ENC_OPS2(Reg, Reg) || isign4 == ENC_OPS3(Reg, Reg, Imm)) {
    1426           0 :         if (!checkSignature(o0, o1))
    1427           0 :           goto InvalidInstruction;
    1428             : 
    1429           0 :         uint32_t opSize = x ? 64 : 32;
    1430             :         uint32_t sType = 0;
    1431             :         uint64_t shift = 0;
    1432             : 
    1433           0 :         if (isign4 == ENC_OPS3(Reg, Reg, Imm)) {
    1434             :           sType = o2.as<Imm>().predicate();
    1435             :           shift = o2.as<Imm>().valueAs<uint64_t>();
    1436             :         }
    1437             : 
    1438           0 :         bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP();
    1439             : 
    1440             :         // Shift operation - LSL, LSR, ASR.
    1441           0 :         if (sType <= uint32_t(ShiftOp::kASR)) {
    1442           0 :           if (!hasSP) {
    1443           0 :             if (shift >= opSize)
    1444           0 :               goto InvalidImmediate;
    1445             : 
    1446           0 :             opcode.reset(uint32_t(opData.shiftedOp) << 21);
    1447             :             opcode.addImm(x, 31);
    1448             :             opcode.addImm(sType, 22);
    1449             :             opcode.addReg(o1, 16);
    1450             :             opcode.addImm(shift, 10);
    1451             :             opcode.addReg(o0, 5);
    1452             :             opcode.addReg(Gp::kIdZr, 0);
    1453           0 :             goto EmitOp;
    1454             :           }
    1455             : 
    1456             :           // SP register can only be used with LSL or Extend.
    1457           0 :           if (sType != uint32_t(ShiftOp::kLSL))
    1458           0 :             goto InvalidImmediate;
    1459             : 
    1460           0 :           sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW);
    1461             :         }
    1462             : 
    1463             :         // Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX.
    1464           0 :         sType -= uint32_t(ShiftOp::kUXTB);
    1465           0 :         if (sType > 7 || shift > 4)
    1466           0 :           goto InvalidImmediate;
    1467             : 
    1468           0 :         opcode.reset(uint32_t(opData.extendedOp) << 21);
    1469             :         opcode.addImm(x, 31);
    1470             :         opcode.addReg(o1, 16);
    1471             :         opcode.addImm(sType, 13);
    1472             :         opcode.addImm(shift, 10);
    1473             :         opcode.addReg(o0, 5);
    1474             :         opcode.addReg(Gp::kIdZr, 0);
    1475           0 :         goto EmitOp;
    1476             :       }
    1477             : 
    1478             :       break;
    1479             :     }
    1480             : 
    1481           0 :     case InstDB::kEncodingBaseMvnNeg: {
    1482             :       const InstDB::EncodingData::BaseMvnNeg& opData = InstDB::EncodingData::baseMvnNeg[encodingIndex];
    1483             : 
    1484             :       uint32_t x;
    1485             :       if (!checkGpType(o0, o1, kWX, &x))
    1486           0 :         goto InvalidInstruction;
    1487             : 
    1488           0 :       opcode.reset(opData.opcode);
    1489             :       opcode.addImm(x, 31);
    1490             :       opcode.addReg(o1, 16);
    1491             :       opcode.addReg(o0, 0);
    1492             : 
    1493           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    1494           0 :         if (!checkGpId(o0, o1, kZR))
    1495           0 :           goto InvalidPhysId;
    1496             : 
    1497           0 :         goto EmitOp;
    1498             :       }
    1499             : 
    1500           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm)) {
    1501           0 :         if (!checkGpId(o0, o1, kZR))
    1502           0 :           goto InvalidPhysId;
    1503             : 
    1504           0 :         uint32_t opSize = x ? 64 : 32;
    1505             :         uint32_t shiftType = o2.as<Imm>().predicate();
    1506             :         uint64_t opShift = o2.as<Imm>().valueAs<uint64_t>();
    1507             : 
    1508           0 :         if (shiftType > uint32_t(ShiftOp::kROR) || opShift >= opSize)
    1509           0 :           goto InvalidImmediate;
    1510             : 
    1511             :         opcode.addImm(shiftType, 22);
    1512             :         opcode.addImm(opShift, 10);
    1513           0 :         goto EmitOp;
    1514             :       }
    1515             : 
    1516             :       break;
    1517             :     }
    1518             : 
    1519           0 :     case InstDB::kEncodingBaseTst: {
    1520             :       const InstDB::EncodingData::BaseTst& opData = InstDB::EncodingData::baseTst[encodingIndex];
    1521             : 
    1522             :       uint32_t x;
    1523           0 :       if (!checkGpType(o0, kWX, &x))
    1524           0 :         goto InvalidInstruction;
    1525             : 
    1526           0 :       uint32_t opSize = x ? 64 : 32;
    1527             : 
    1528           0 :       if (isign4 == ENC_OPS2(Reg, Imm) && opData.immediateOp != 0) {
    1529           0 :         if (!checkGpId(o0, kZR))
    1530           0 :           goto InvalidPhysId;
    1531             : 
    1532             :         // TST (immediate) uses a LogicalImm format described by N:R:S values.
    1533             :         uint64_t immMask = Support::lsbMask<uint64_t>(opSize);
    1534             :         uint64_t immValue = o1.as<Imm>().valueAs<uint64_t>();
    1535             : 
    1536             :         // Logical instructions use 13-bit immediate pattern encoded as N:ImmS:ImmR.
    1537             :         LogicalImm logicalImm;
    1538           0 :         if (!Utils::encodeLogicalImm(immValue & immMask, opSize, &logicalImm))
    1539           0 :           goto InvalidImmediate;
    1540             : 
    1541           0 :         opcode.reset(uint32_t(opData.immediateOp) << 22);
    1542           0 :         opcode.addLogicalImm(logicalImm);
    1543             :         opcode.addImm(x, 31);
    1544             :         opcode.addReg(o0, 5);
    1545             :         opcode.addReg(Gp::kIdZr, 0);
    1546           0 :         goto EmitOp;
    1547             :       }
    1548             : 
    1549           0 :       opcode.reset(uint32_t(opData.shiftedOp) << 21);
    1550             :       opcode.addImm(x, 31);
    1551             :       opcode.addReg(o1, 16);
    1552             :       opcode.addReg(o0, 5);
    1553             :       opcode.addReg(Gp::kIdZr, 0);
    1554             : 
    1555           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    1556           0 :         if (!checkGpId(o0, o1, kZR))
    1557           0 :           goto InvalidPhysId;
    1558             : 
    1559           0 :         goto EmitOp;
    1560             :       }
    1561             : 
    1562           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm)) {
    1563           0 :         if (!checkGpId(o0, o1, kZR))
    1564           0 :           goto InvalidPhysId;
    1565             : 
    1566             :         uint32_t shiftType = o2.as<Imm>().predicate();
    1567             :         uint64_t opShift = o2.as<Imm>().valueAs<uint64_t>();
    1568             : 
    1569           0 :         if (shiftType > 0x3 || opShift >= opSize)
    1570           0 :           goto InvalidImmediate;
    1571             : 
    1572             :         opcode.addImm(shiftType, 22);
    1573             :         opcode.addImm(opShift, 10);
    1574           0 :         goto EmitOp;
    1575             :       }
    1576             : 
    1577             :       break;
    1578             :     }
    1579             : 
    1580             :     // ------------------------------------------------------------------------
    1581             :     // [Base - Bit Manipulation]
    1582             :     // ------------------------------------------------------------------------
    1583             : 
    1584           0 :     case InstDB::kEncodingBaseBfc: {
    1585             :       const InstDB::EncodingData::BaseBfc& opData = InstDB::EncodingData::baseBfc[encodingIndex];
    1586             : 
    1587           0 :       if (isign4 == ENC_OPS3(Reg, Imm, Imm)) {
    1588             :         uint32_t x;
    1589           0 :         if (!checkGpType(o0, InstDB::kWX, &x))
    1590           0 :           goto InvalidInstruction;
    1591             : 
    1592           0 :         if (!checkGpId(o0))
    1593           0 :           goto InvalidPhysId;
    1594             : 
    1595             :         uint64_t lsb = o1.as<Imm>().valueAs<uint64_t>();
    1596             :         uint64_t width = o2.as<Imm>().valueAs<uint64_t>();
    1597           0 :         uint32_t opSize = x ? 64 : 32;
    1598             : 
    1599           0 :         if (lsb >= opSize || width == 0 || width > opSize)
    1600           0 :           goto InvalidImmediate;
    1601             : 
    1602           0 :         uint32_t lsb32 = Support::neg(uint32_t(lsb)) & (opSize - 1);
    1603           0 :         uint32_t width32 = uint32_t(width) - 1;
    1604             : 
    1605           0 :         opcode.reset(opData.opcode);
    1606             :         opcode.addImm(x, 31);
    1607             :         opcode.addImm(x, 22);
    1608             :         opcode.addImm(lsb32, 16);
    1609             :         opcode.addImm(width32, 10);
    1610             :         opcode.addReg(o0, 0);
    1611           0 :         goto EmitOp;
    1612             :       }
    1613             : 
    1614             :       break;
    1615             :     }
    1616             : 
    1617           0 :     case InstDB::kEncodingBaseBfi: {
    1618             :       const InstDB::EncodingData::BaseBfi& opData = InstDB::EncodingData::baseBfi[encodingIndex];
    1619             : 
    1620           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
    1621             :         uint32_t x;
    1622           0 :         if (!checkGpType(o0, InstDB::kWX, &x))
    1623           0 :           goto InvalidInstruction;
    1624             : 
    1625           0 :         if (!checkSignature(o0, o1))
    1626           0 :           goto InvalidInstruction;
    1627             : 
    1628           0 :         if (!checkGpId(o0, o1))
    1629           0 :           goto InvalidPhysId;
    1630             : 
    1631             :         uint64_t lsb = o2.as<Imm>().valueAs<uint64_t>();
    1632             :         uint64_t width = o3.as<Imm>().valueAs<uint64_t>();
    1633           0 :         uint32_t opSize = x ? 64 : 32;
    1634             : 
    1635           0 :         if (lsb >= opSize || width == 0 || width > opSize)
    1636           0 :           goto InvalidImmediate;
    1637             : 
    1638           0 :         uint32_t lImm = Support::neg(uint32_t(lsb)) & (opSize - 1);
    1639           0 :         uint32_t wImm = uint32_t(width) - 1;
    1640             : 
    1641           0 :         opcode.reset(opData.opcode);
    1642             :         opcode.addImm(x, 31);
    1643             :         opcode.addImm(x, 22);
    1644             :         opcode.addImm(lImm, 16);
    1645             :         opcode.addImm(wImm, 10);
    1646             :         opcode.addReg(o1, 5);
    1647             :         opcode.addReg(o0, 0);
    1648           0 :         goto EmitOp;
    1649             :       }
    1650             : 
    1651             :       break;
    1652             :     }
    1653             : 
    1654           0 :     case InstDB::kEncodingBaseBfm: {
    1655             :       const InstDB::EncodingData::BaseBfm& opData = InstDB::EncodingData::baseBfm[encodingIndex];
    1656             : 
    1657           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
    1658             :         uint32_t x;
    1659           0 :         if (!checkGpType(o0, InstDB::kWX, &x))
    1660           0 :           goto InvalidInstruction;
    1661             : 
    1662           0 :         if (!checkSignature(o0, o1))
    1663           0 :           goto InvalidInstruction;
    1664             : 
    1665           0 :         if (!checkGpId(o0, o1))
    1666           0 :           goto InvalidPhysId;
    1667             : 
    1668             :         uint64_t immR = o2.as<Imm>().valueAs<uint64_t>();
    1669             :         uint64_t immS = o3.as<Imm>().valueAs<uint64_t>();
    1670           0 :         uint32_t opSize = x ? 64 : 32;
    1671             : 
    1672           0 :         if ((immR | immS) >= opSize)
    1673           0 :           goto InvalidImmediate;
    1674             : 
    1675           0 :         opcode.reset(opData.opcode);
    1676             :         opcode.addImm(x, 31);
    1677             :         opcode.addImm(x, 22);
    1678             :         opcode.addImm(immR, 16);
    1679             :         opcode.addImm(immS, 10);
    1680             :         opcode.addReg(o1, 5);
    1681             :         opcode.addReg(o0, 0);
    1682           0 :         goto EmitOp;
    1683             :       }
    1684             : 
    1685             :       break;
    1686             :     }
    1687             : 
    1688           0 :     case InstDB::kEncodingBaseBfx: {
    1689             :       const InstDB::EncodingData::BaseBfx& opData = InstDB::EncodingData::baseBfx[encodingIndex];
    1690             : 
    1691           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
    1692             :         uint32_t x;
    1693           0 :         if (!checkGpType(o0, InstDB::kWX, &x))
    1694           0 :           goto InvalidInstruction;
    1695             : 
    1696           0 :         if (!checkSignature(o0, o1))
    1697           0 :           goto InvalidInstruction;
    1698             : 
    1699           0 :         if (!checkGpId(o0, o1))
    1700           0 :           goto InvalidPhysId;
    1701             : 
    1702             :         uint64_t lsb = o2.as<Imm>().valueAs<uint64_t>();
    1703             :         uint64_t width = o3.as<Imm>().valueAs<uint64_t>();
    1704           0 :         uint32_t opSize = x ? 64 : 32;
    1705             : 
    1706           0 :         if (lsb >= opSize || width == 0 || width > opSize)
    1707           0 :           goto InvalidImmediate;
    1708             : 
    1709           0 :         uint32_t lsb32 = uint32_t(lsb);
    1710           0 :         uint32_t width32 = lsb32 + uint32_t(width) - 1u;
    1711             : 
    1712           0 :         if (width32 >= opSize)
    1713           0 :           goto InvalidImmediate;
    1714             : 
    1715           0 :         opcode.reset(opData.opcode);
    1716             :         opcode.addImm(x, 31);
    1717             :         opcode.addImm(x, 22);
    1718             :         opcode.addImm(lsb32, 16);
    1719             :         opcode.addImm(width32, 10);
    1720             :         opcode.addReg(o1, 5);
    1721             :         opcode.addReg(o0, 0);
    1722           0 :         goto EmitOp;
    1723             :       }
    1724             : 
    1725             :       break;
    1726             :     }
    1727             : 
    1728           0 :     case InstDB::kEncodingBaseExtend: {
    1729             :       const InstDB::EncodingData::BaseExtend& opData = InstDB::EncodingData::baseExtend[encodingIndex];
    1730             : 
    1731           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    1732             :         uint32_t x;
    1733           0 :         if (!checkGpType(o0, opData.rType, &x))
    1734           0 :           goto InvalidInstruction;
    1735             : 
    1736           0 :         if (!o1.as<Reg>().isGpW())
    1737           0 :           goto InvalidInstruction;
    1738             : 
    1739           0 :         if (!checkGpId(o0, o1))
    1740           0 :           goto InvalidPhysId;
    1741             : 
    1742             :         opcode.reset(opData.opcode());
    1743             :         opcode.addImm(x, 31);
    1744             :         opcode.addImm(x, 22);
    1745             :         opcode.addReg(o1, 5);
    1746             :         opcode.addReg(o0, 0);
    1747           0 :         goto EmitOp;
    1748             :       }
    1749             : 
    1750             :       break;
    1751             :     }
    1752             : 
    1753           0 :     case InstDB::kEncodingBaseExtract: {
    1754             :       const InstDB::EncodingData::BaseExtract& opData = InstDB::EncodingData::baseExtract[encodingIndex];
    1755             : 
    1756           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    1757             :         uint32_t x;
    1758           0 :         if (!checkGpType(o0, kWX, &x))
    1759           0 :           goto InvalidInstruction;
    1760             : 
    1761             :         if (!checkSignature(o0, o1, o2))
    1762           0 :           goto InvalidInstruction;
    1763             : 
    1764           0 :         if (!checkGpId(o0, o1, o2))
    1765           0 :           goto InvalidPhysId;
    1766             : 
    1767             :         uint64_t lsb = o3.as<Imm>().valueAs<uint64_t>();
    1768           0 :         uint32_t opSize = x ? 64 : 32;
    1769             : 
    1770           0 :         if (lsb >= opSize)
    1771           0 :           goto InvalidImmediate;
    1772             : 
    1773           0 :         opcode.reset(opData.opcode);
    1774             :         opcode.addImm(x, 31);
    1775             :         opcode.addImm(x, 22);
    1776             :         opcode.addReg(o2, 16);
    1777             :         opcode.addImm(lsb, 10);
    1778             :         opcode.addReg(o1, 5);
    1779             :         opcode.addReg(o0, 0);
    1780           0 :         goto EmitOp;
    1781             :       }
    1782             : 
    1783             :       break;
    1784             :     }
    1785             : 
    1786           0 :     case InstDB::kEncodingBaseRev: {
    1787           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    1788             :         uint32_t x;
    1789           0 :         if (!checkGpType(o0, InstDB::kWX, &x))
    1790           0 :           goto InvalidInstruction;
    1791             : 
    1792           0 :         if (!checkSignature(o0, o1))
    1793           0 :           goto InvalidInstruction;
    1794             : 
    1795           0 :         if (!checkGpId(o0, o1))
    1796           0 :           goto InvalidPhysId;
    1797             : 
    1798             :         opcode.reset(0b01011010110000000000100000000000);
    1799             :         opcode.addImm(x, 31);
    1800             :         opcode.addImm(x, 10);
    1801             :         opcode.addReg(o1, 5);
    1802             :         opcode.addReg(o0, 0);
    1803           0 :         goto EmitOp;
    1804             :       }
    1805             : 
    1806             :       break;
    1807             :     }
    1808             : 
    1809           0 :     case InstDB::kEncodingBaseShift: {
    1810             :       const InstDB::EncodingData::BaseShift& opData = InstDB::EncodingData::baseShift[encodingIndex];
    1811             : 
    1812             :       uint32_t x;
    1813           0 :       if (!checkGpType(o0, kWX, &x))
    1814           0 :         goto InvalidInstruction;
    1815             : 
    1816           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    1817             :         if (!checkSignature(o0, o1, o2))
    1818           0 :           goto InvalidInstruction;
    1819             : 
    1820           0 :         if (!checkGpId(o0, o1, o2, kZR))
    1821           0 :           goto InvalidPhysId;
    1822             : 
    1823             :         opcode.reset(opData.registerOp());
    1824             :         opcode.addImm(x, 31);
    1825             :         opcode.addReg(o2, 16);
    1826             :         opcode.addReg(o1, 5);
    1827             :         opcode.addReg(o0, 0);
    1828           0 :         goto EmitOp;
    1829             :       }
    1830             : 
    1831           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp()) {
    1832           0 :         if (!checkSignature(o0, o1))
    1833           0 :           goto InvalidInstruction;
    1834             : 
    1835           0 :         if (!checkGpId(o0, o1, kZR))
    1836           0 :           goto InvalidPhysId;
    1837             : 
    1838             :         uint64_t immR = o2.as<Imm>().valueAs<uint64_t>();
    1839           0 :         uint32_t opSize = x ? 64 : 32;
    1840             : 
    1841           0 :         if (immR >= opSize)
    1842           0 :           goto InvalidImmediate;
    1843             : 
    1844             :         opcode.reset(opData.immediateOp());
    1845             :         opcode.addImm(x, 31);
    1846             :         opcode.addImm(x, 22);
    1847             :         opcode.addReg(o1, 5);
    1848             :         opcode.addReg(o0, 0);
    1849             : 
    1850           0 :         if (opcode.get() & B(10)) {
    1851             :           // ASR and LSR (immediate) has the same logic.
    1852             :           opcode.addImm(x, 15);
    1853             :           opcode.addImm(immR, 16);
    1854           0 :           goto EmitOp;
    1855             :         }
    1856             : 
    1857           0 :         if (opData.ror == 0) {
    1858             :           // LSL (immediate) is an alias to UBFM
    1859           0 :           uint32_t ubfmImmR = Support::neg(uint32_t(immR)) & (opSize - 1);
    1860           0 :           uint32_t ubfmImmS = opSize - 1 - uint32_t(immR);
    1861             : 
    1862             :           opcode.addImm(ubfmImmR, 16);
    1863             :           opcode.addImm(ubfmImmS, 10);
    1864           0 :           goto EmitOp;
    1865             :         }
    1866             :         else {
    1867             :           // ROR (immediate) is an alias to EXTR.
    1868             :           opcode.addImm(immR, 10);
    1869             :           opcode.addReg(o1, 16);
    1870           0 :           goto EmitOp;
    1871             :         }
    1872             :       }
    1873             : 
    1874             :       break;
    1875             :     }
    1876             : 
    1877             :     // ------------------------------------------------------------------------
    1878             :     // [Base - Conditionals]
    1879             :     // ------------------------------------------------------------------------
    1880             : 
    1881           0 :     case InstDB::kEncodingBaseCCmp: {
    1882             :       const InstDB::EncodingData::BaseCCmp& opData = InstDB::EncodingData::baseCCmp[encodingIndex];
    1883             : 
    1884           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm) || isign4 == ENC_OPS4(Reg, Imm, Imm, Imm)) {
    1885             :         uint32_t x;
    1886           0 :         if (!checkGpType(o0, InstDB::kWX, &x))
    1887           0 :           goto InvalidInstruction;
    1888             : 
    1889           0 :         if (!checkGpId(o0, kZR))
    1890           0 :           goto InvalidPhysId;
    1891             : 
    1892             :         uint64_t nzcv = o2.as<Imm>().valueAs<uint64_t>();
    1893             :         uint64_t cond = o3.as<Imm>().valueAs<uint64_t>();
    1894             : 
    1895           0 :         if ((nzcv | cond) > 0xFu)
    1896           0 :           goto InvalidImmediate;
    1897             : 
    1898           0 :         opcode.reset(opData.opcode);
    1899             :         opcode.addImm(x, 31);
    1900           0 :         opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12);
    1901             :         opcode.addImm(nzcv, 0);
    1902             : 
    1903           0 :         if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
    1904             :           // CCMN|CCMP (register) form.
    1905           0 :           if (!checkSignature(o0, o1))
    1906           0 :             goto InvalidInstruction;
    1907             : 
    1908           0 :           if (!checkGpId(o1, kZR))
    1909           0 :             goto InvalidPhysId;
    1910             : 
    1911             :           opcode.addReg(o1, 16);
    1912             :           opcode.addReg(o0, 5);
    1913           0 :           goto EmitOp;
    1914             :         }
    1915             :         else {
    1916             :           // CCMN|CCMP (immediate) form.
    1917             :           uint64_t imm5 = o1.as<Imm>().valueAs<uint64_t>();
    1918           0 :           if (imm5 > 0x1F)
    1919           0 :             goto InvalidImmediate;
    1920             : 
    1921             :           opcode.addImm(1, 11);
    1922             :           opcode.addImm(imm5, 16);
    1923             :           opcode.addReg(o0, 5);
    1924           0 :           goto EmitOp;
    1925             :         }
    1926             :       }
    1927             : 
    1928             :       break;
    1929             :     }
    1930             : 
    1931           0 :     case InstDB::kEncodingBaseCInc: {
    1932             :       const InstDB::EncodingData::BaseCInc& opData = InstDB::EncodingData::baseCInc[encodingIndex];
    1933             : 
    1934           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm)) {
    1935             :         uint32_t x;
    1936             :         if (!checkGpType(o0, o1, InstDB::kWX, &x))
    1937           0 :           goto InvalidInstruction;
    1938             : 
    1939           0 :         if (!checkGpId(o0, o1, kZR))
    1940           0 :           goto InvalidPhysId;
    1941             : 
    1942             :         uint64_t cond = o2.as<Imm>().valueAs<uint64_t>();
    1943           0 :         if (cond - 2u > 0xEu)
    1944           0 :           goto InvalidImmediate;
    1945             : 
    1946           0 :         opcode.reset(opData.opcode);
    1947             :         opcode.addImm(x, 31);
    1948             :         opcode.addReg(o1, 16);
    1949           0 :         opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)) ^ 1u, 12);
    1950             :         opcode.addReg(o1, 5);
    1951             :         opcode.addReg(o0, 0);
    1952           0 :         goto EmitOp;
    1953             :       }
    1954             : 
    1955             :       break;
    1956             :     }
    1957             : 
    1958           0 :     case InstDB::kEncodingBaseCSel: {
    1959             :       const InstDB::EncodingData::BaseCSel& opData = InstDB::EncodingData::baseCSel[encodingIndex];
    1960             : 
    1961           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    1962             :         uint32_t x;
    1963           0 :         if (!checkGpType(o0, o1, o2, InstDB::kWX, &x))
    1964           0 :           goto InvalidInstruction;
    1965             : 
    1966           0 :         if (!checkGpId(o0, o1, o2, kZR))
    1967           0 :           goto InvalidPhysId;
    1968             : 
    1969             :         uint64_t cond = o3.as<Imm>().valueAs<uint64_t>();
    1970           0 :         if (cond > 0xFu)
    1971           0 :           goto InvalidImmediate;
    1972             : 
    1973           0 :         opcode.reset(opData.opcode);
    1974           0 :         opcode.addImm(x, 31);
    1975             :         opcode.addReg(o2, 16);
    1976           0 :         opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12);
    1977             :         opcode.addReg(o1, 5);
    1978             :         opcode.addReg(o0, 0);
    1979           0 :         goto EmitOp;
    1980             :       }
    1981             : 
    1982             :       break;
    1983             :     }
    1984             : 
    1985           0 :     case InstDB::kEncodingBaseCSet: {
    1986             :       const InstDB::EncodingData::BaseCSet& opData = InstDB::EncodingData::baseCSet[encodingIndex];
    1987             : 
    1988           0 :       if (isign4 == ENC_OPS2(Reg, Imm)) {
    1989             :         uint32_t x;
    1990           0 :         if (!checkGpType(o0, InstDB::kWX, &x))
    1991           0 :           goto InvalidInstruction;
    1992             : 
    1993           0 :         if (!checkGpId(o0, kZR))
    1994           0 :           goto InvalidPhysId;
    1995             : 
    1996             :         uint64_t cond = o1.as<Imm>().valueAs<uint64_t>();
    1997           0 :         if (cond - 2u >= 0xEu)
    1998           0 :           goto InvalidImmediate;
    1999             : 
    2000           0 :         opcode.reset(opData.opcode);
    2001             :         opcode.addImm(x, 31);
    2002           0 :         opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)) ^ 1u, 12);
    2003             :         opcode.addReg(o0, 0);
    2004           0 :         goto EmitOp;
    2005             :       }
    2006             : 
    2007             :       break;
    2008             :     }
    2009             : 
    2010             :     // ------------------------------------------------------------------------
    2011             :     // [Base - Special]
    2012             :     // ------------------------------------------------------------------------
    2013             : 
    2014           0 :     case InstDB::kEncodingBaseAtDcIcTlbi: {
    2015             :       const InstDB::EncodingData::BaseAtDcIcTlbi& opData = InstDB::EncodingData::baseAtDcIcTlbi[encodingIndex];
    2016             : 
    2017           0 :       if (isign4 == ENC_OPS1(Imm) || isign4 == ENC_OPS2(Imm, Reg)) {
    2018           0 :         if (opData.mandatoryReg && isign4 != ENC_OPS2(Imm, Reg))
    2019           0 :           goto InvalidInstruction;
    2020             : 
    2021           0 :         if (o0.as<Imm>().valueAs<uint64_t>() > 0x7FFFu)
    2022           0 :           goto InvalidImmediate;
    2023             : 
    2024             :         uint32_t imm = o0.as<Imm>().valueAs<uint32_t>();
    2025           0 :         if ((imm & opData.immVerifyMask) != opData.immVerifyData)
    2026           0 :           goto InvalidImmediate;
    2027             : 
    2028             :         uint32_t rt = 31;
    2029           0 :         if (o1.isReg()) {
    2030           0 :           if (!o1.as<Reg>().isGpX())
    2031           0 :             goto InvalidInstruction;
    2032             : 
    2033           0 :           if (!checkGpId(o1, kZR))
    2034           0 :             goto InvalidPhysId;
    2035             : 
    2036           0 :           rt = o1.id() & 31;
    2037             :         }
    2038             : 
    2039             :         opcode.reset(0b11010101000010000000000000000000);
    2040             :         opcode.addImm(imm, 5);
    2041             :         opcode.addReg(rt, 0);
    2042           0 :         goto EmitOp;
    2043             :       }
    2044             :       break;
    2045             :     }
    2046             : 
    2047           0 :     case InstDB::kEncodingBaseMrs: {
    2048           0 :       if (isign4 == ENC_OPS2(Reg, Imm)) {
    2049           0 :         if (!o0.as<Reg>().isGpX())
    2050           0 :           goto InvalidInstruction;
    2051             : 
    2052           0 :         if (!checkGpId(o0, kZR))
    2053           0 :           goto InvalidPhysId;
    2054             : 
    2055           0 :         if (o1.as<Imm>().valueAs<uint64_t>() > 0xFFFFu)
    2056           0 :           goto InvalidImmediate;
    2057             : 
    2058             :         uint32_t imm = o1.as<Imm>().valueAs<uint32_t>();
    2059           0 :         if (!(imm & B(15)))
    2060           0 :           goto InvalidImmediate;
    2061             : 
    2062             :         opcode.reset(0b11010101001100000000000000000000);
    2063             :         opcode.addImm(imm, 5);
    2064             :         opcode.addReg(o0, 0);
    2065           0 :         goto EmitOp;
    2066             :       }
    2067             : 
    2068             :       break;
    2069             :     }
    2070             : 
    2071           0 :     case InstDB::kEncodingBaseMsr: {
    2072           0 :       if (isign4 == ENC_OPS2(Imm, Reg)) {
    2073           0 :         if (!o1.as<Reg>().isGpX())
    2074           0 :           goto InvalidInstruction;
    2075             : 
    2076           0 :         if (o0.as<Imm>().valueAs<uint64_t>() > 0xFFFFu)
    2077           0 :           goto InvalidImmediate;
    2078             : 
    2079             :         uint32_t imm = o0.as<Imm>().valueAs<uint32_t>();
    2080           0 :         if (!(imm & B(15)))
    2081           0 :           goto InvalidImmediate;
    2082             : 
    2083           0 :         if (!checkGpId(o1, kZR))
    2084           0 :           goto InvalidPhysId;
    2085             : 
    2086             :         opcode.reset(0b11010101000100000000000000000000);
    2087             :         opcode.addImm(imm, 5);
    2088             :         opcode.addReg(o1, 0);
    2089           0 :         goto EmitOp;
    2090             :       }
    2091             : 
    2092           0 :       if (isign4 == ENC_OPS2(Imm, Imm)) {
    2093           0 :         if (o0.as<Imm>().valueAs<uint64_t>() > 0x1Fu)
    2094           0 :           goto InvalidImmediate;
    2095             : 
    2096           0 :         if (o1.as<Imm>().valueAs<uint64_t>() > 0xFu)
    2097           0 :           goto InvalidImmediate;
    2098             : 
    2099             :         uint32_t op = o0.as<Imm>().valueAs<uint32_t>();
    2100             :         uint32_t cRm = o1.as<Imm>().valueAs<uint32_t>();
    2101             : 
    2102           0 :         uint32_t op1 = uint32_t(op) >> 3;
    2103             :         uint32_t op2 = uint32_t(op) & 0x7u;
    2104             : 
    2105             :         opcode.reset(0b11010101000000000100000000011111);
    2106             :         opcode.addImm(op1, 16);
    2107             :         opcode.addImm(cRm, 8);
    2108             :         opcode.addImm(op2, 5);
    2109           0 :         goto EmitOp;
    2110             :       }
    2111             : 
    2112             :       break;
    2113             :     }
    2114             : 
    2115           0 :     case InstDB::kEncodingBaseSys: {
    2116           0 :       if (isign4 == ENC_OPS4(Imm, Imm, Imm, Imm)) {
    2117           0 :         if (o0.as<Imm>().valueAs<uint64_t>() > 0x7u ||
    2118           0 :             o1.as<Imm>().valueAs<uint64_t>() > 0xFu ||
    2119           0 :             o2.as<Imm>().valueAs<uint64_t>() > 0xFu ||
    2120             :             o3.as<Imm>().valueAs<uint64_t>() > 0x7u)
    2121           0 :           goto InvalidImmediate;
    2122             : 
    2123             :         uint32_t op1 = o0.as<Imm>().valueAs<uint32_t>();
    2124             :         uint32_t cRn = o1.as<Imm>().valueAs<uint32_t>();
    2125             :         uint32_t cRm = o2.as<Imm>().valueAs<uint32_t>();
    2126             :         uint32_t op2 = o3.as<Imm>().valueAs<uint32_t>();
    2127             :         uint32_t rt = 31;
    2128             : 
    2129             :         const Operand_& o4 = opExt[EmitterUtils::kOp4];
    2130           0 :         if (o4.isReg()) {
    2131           0 :           if (!o4.as<Reg>().isGpX())
    2132           0 :             goto InvalidInstruction;
    2133             : 
    2134           0 :           if (!checkGpId(o4, kZR))
    2135           0 :             goto InvalidPhysId;
    2136             : 
    2137           0 :           rt = o4.id() & 31;
    2138             :         }
    2139           0 :         else if (!o4.isNone()) {
    2140           0 :           goto InvalidInstruction;
    2141             :         }
    2142             : 
    2143             :         opcode.reset(0b11010101000010000000000000000000);
    2144             :         opcode.addImm(op1, 16);
    2145             :         opcode.addImm(cRn, 12);
    2146             :         opcode.addImm(cRm, 8);
    2147             :         opcode.addImm(op2, 5);
    2148             :         opcode.addImm(rt, 0);
    2149           0 :         goto EmitOp;
    2150             :       }
    2151             : 
    2152             :       break;
    2153             :     }
    2154             : 
    2155             :     // ------------------------------------------------------------------------
    2156             :     // [Base - Branch]
    2157             :     // ------------------------------------------------------------------------
    2158             : 
    2159           0 :     case InstDB::kEncodingBaseBranchReg: {
    2160             :       const InstDB::EncodingData::BaseBranchReg& opData = InstDB::EncodingData::baseBranchReg[encodingIndex];
    2161             : 
    2162           0 :       if (isign4 == ENC_OPS1(Reg)) {
    2163           0 :         if (!o0.as<Reg>().isGpX())
    2164           0 :           goto InvalidInstruction;
    2165             : 
    2166           0 :         if (!checkGpId(o0, kZR))
    2167           0 :           goto InvalidPhysId;
    2168             : 
    2169           0 :         opcode.reset(opData.opcode);
    2170             :         opcode.addReg(o0, 5);
    2171           0 :         goto EmitOp;
    2172             :       }
    2173             : 
    2174             :       break;
    2175             :     }
    2176             : 
    2177           0 :     case InstDB::kEncodingBaseBranchRel: {
    2178             :       const InstDB::EncodingData::BaseBranchRel& opData = InstDB::EncodingData::baseBranchRel[encodingIndex];
    2179             : 
    2180           0 :       if (isign4 == ENC_OPS1(Label) || isign4 == ENC_OPS1(Imm)) {
    2181           0 :         opcode.reset(opData.opcode);
    2182             :         rmRel = &o0;
    2183             : 
    2184           0 :         if (instCC != CondCode::kAL) {
    2185             :           opcode |= B(30);
    2186           0 :           opcode.addImm(condCodeToOpcodeCond(uint32_t(instCC)), 0);
    2187             :           offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2);
    2188           0 :           goto EmitOp_Rel;
    2189             :         }
    2190             : 
    2191             :         offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 0, 26, 2);
    2192           0 :         goto EmitOp_Rel;
    2193             :       }
    2194             : 
    2195             :       break;
    2196             :     }
    2197             : 
    2198           0 :     case InstDB::kEncodingBaseBranchCmp: {
    2199             :       const InstDB::EncodingData::BaseBranchCmp& opData = InstDB::EncodingData::baseBranchCmp[encodingIndex];
    2200             : 
    2201           0 :       if (isign4 == ENC_OPS2(Reg, Label) || isign4 == ENC_OPS2(Reg, Imm)) {
    2202             :         uint32_t x;
    2203           0 :         if (!checkGpType(o0, kWX, &x))
    2204           0 :           goto InvalidInstruction;
    2205             : 
    2206           0 :         if (!checkGpId(o0, kZR))
    2207           0 :           goto InvalidPhysId;
    2208             : 
    2209           0 :         opcode.reset(opData.opcode);
    2210             :         opcode.addImm(x, 31);
    2211             :         opcode.addReg(o0, 0);
    2212             :         offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2);
    2213             : 
    2214             :         rmRel = &o1;
    2215           0 :         goto EmitOp_Rel;
    2216             :       }
    2217             : 
    2218             :       break;
    2219             :     }
    2220             : 
    2221           0 :     case InstDB::kEncodingBaseBranchTst: {
    2222             :       const InstDB::EncodingData::BaseBranchTst& opData = InstDB::EncodingData::baseBranchTst[encodingIndex];
    2223             : 
    2224           0 :       if (isign4 == ENC_OPS3(Reg, Imm, Label) || isign4 == ENC_OPS3(Reg, Imm, Imm)) {
    2225             :         uint32_t x;
    2226           0 :         if (!checkGpType(o0, kWX, &x))
    2227           0 :           goto InvalidInstruction;
    2228             : 
    2229           0 :         if (!checkGpId(o0, kZR))
    2230           0 :           goto InvalidPhysId;
    2231             : 
    2232             :         uint64_t imm = o1.as<Imm>().valueAs<uint64_t>();
    2233             : 
    2234           0 :         opcode.reset(opData.opcode);
    2235           0 :         if (imm >= 32) {
    2236           0 :           if (!x)
    2237           0 :             goto InvalidImmediate;
    2238             :           opcode.addImm(x, 31);
    2239           0 :           imm &= 0x1F;
    2240             :         }
    2241             : 
    2242             :         opcode.addReg(o0, 0);
    2243             :         opcode.addImm(imm, 19);
    2244             :         offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 14, 2);
    2245             : 
    2246             :         rmRel = &o2;
    2247           0 :         goto EmitOp_Rel;
    2248             :       }
    2249             : 
    2250             :       break;
    2251             :     }
    2252             : 
    2253             :     // ------------------------------------------------------------------------
    2254             :     // [Base - Load / Store]
    2255             :     // ------------------------------------------------------------------------
    2256             : 
    2257           0 :     case InstDB::kEncodingBaseLdSt: {
    2258             :       const InstDB::EncodingData::BaseLdSt& opData = InstDB::EncodingData::baseLdSt[encodingIndex];
    2259             : 
    2260           0 :       if (isign4 == ENC_OPS2(Reg, Mem)) {
    2261             :         const Mem& m = o1.as<Mem>();
    2262           0 :         rmRel = &m;
    2263             : 
    2264             :         uint32_t x;
    2265           0 :         if (!checkGpType(o0, opData.rType, &x))
    2266           0 :           goto InvalidInstruction;
    2267             : 
    2268           0 :         if (!checkGpId(o0, kZR))
    2269           0 :           goto InvalidPhysId;
    2270             : 
    2271             :         // Instructions that work with either word or dword have the unsigned
    2272             :         // offset shift set to 2 (word), so we set it to 3 (dword) if this is
    2273             :         // X version of the instruction.
    2274           0 :         uint32_t xShiftMask = uint32_t(opData.uOffsetShift == 2);
    2275           0 :         uint32_t immShift = uint32_t(opData.uOffsetShift) + (x & xShiftMask);
    2276             : 
    2277           0 :         if (!armCheckMemBaseIndexRel(m))
    2278           0 :           goto InvalidAddress;
    2279             : 
    2280             :         int64_t offset = m.offset();
    2281           0 :         if (m.hasBaseReg()) {
    2282             :           // [Base {Offset | Index}]
    2283           0 :           if (m.hasIndex()) {
    2284           0 :             uint32_t opt = armShiftOpToLdStOptMap[m.predicate()];
    2285           0 :             if (opt == 0xFF)
    2286           0 :               goto InvalidAddress;
    2287             : 
    2288             :             uint32_t shift = m.shift();
    2289           0 :             uint32_t s = shift != 0;
    2290             : 
    2291           0 :             if (s && shift != immShift)
    2292           0 :               goto InvalidAddressScale;
    2293             : 
    2294           0 :             opcode.reset(uint32_t(opData.registerOp) << 21);
    2295           0 :             opcode.xorImm(x, opData.xOffset);
    2296             :             opcode.addImm(opt, 13);
    2297             :             opcode.addImm(s, 12);
    2298             :             opcode |= B(11);
    2299             :             opcode.addReg(o0, 0);
    2300           0 :             goto EmitOp_MemBaseIndex_Rn5_Rm16;
    2301             :           }
    2302             : 
    2303             :           // Makes it easier to work with the offset especially on 32-bit arch.
    2304             :           if (!Support::isInt32(offset))
    2305           0 :             goto InvalidDisplacement;
    2306           0 :           int32_t offset32 = int32_t(offset);
    2307             : 
    2308           0 :           if (m.isPreOrPost()) {
    2309             :             if (!Support::isInt9(offset32))
    2310           0 :               goto InvalidDisplacement;
    2311             : 
    2312           0 :             opcode.reset(uint32_t(opData.prePostOp) << 21);
    2313           0 :             opcode.xorImm(x, opData.xOffset);
    2314             :             opcode.addImm(offset32 & 0x1FF, 12);
    2315             :             opcode.addImm(m.isPreIndex(), 11);
    2316             :             opcode |= B(10);
    2317             :             opcode.addReg(o0, 0);
    2318           0 :             goto EmitOp_MemBase_Rn5;
    2319             :           }
    2320             :           else {
    2321           0 :             uint32_t imm12 = uint32_t(offset32) >> immShift;
    2322             : 
    2323             :             // Alternative form of LDUR/STUR and related instructions as described by AArch64 reference manual:
    2324             :             //
    2325             :             // If this instruction is not encodable with scaled unsigned offset, try unscaled signed offset.
    2326           0 :             if (!Support::isUInt12(imm12) || (imm12 << immShift) != uint32_t(offset32)) {
    2327           0 :               instId = opData.uAltInstId;
    2328             :               instInfo = &InstDB::_instInfoTable[instId];
    2329           0 :               encodingIndex = instInfo->_encodingDataIndex;
    2330           0 :               goto Case_BaseLdurStur;
    2331             :             }
    2332             : 
    2333           0 :             opcode.reset(uint32_t(opData.uOffsetOp) << 22);
    2334           0 :             opcode.xorImm(x, opData.xOffset);
    2335             :             opcode.addImm(imm12, 10);
    2336             :             opcode.addReg(o0, 0);
    2337           0 :             goto EmitOp_MemBase_Rn5;
    2338             :           }
    2339             :         }
    2340             :         else {
    2341           0 :           if (!opData.literalOp)
    2342           0 :             goto InvalidAddress;
    2343             : 
    2344           0 :           opcode.reset(uint32_t(opData.literalOp) << 24);
    2345           0 :           opcode.xorImm(x, opData.xOffset);
    2346             :           opcode.addReg(o0, 0);
    2347             :           offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2);
    2348           0 :           goto EmitOp_Rel;
    2349             :         }
    2350             :       }
    2351             : 
    2352             :       break;
    2353             :     }
    2354             : 
    2355           0 :     case InstDB::kEncodingBaseLdpStp: {
    2356             :       const InstDB::EncodingData::BaseLdpStp& opData = InstDB::EncodingData::baseLdpStp[encodingIndex];
    2357             : 
    2358           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
    2359             :         const Mem& m = o2.as<Mem>();
    2360           0 :         rmRel = &m;
    2361             : 
    2362             :         uint32_t x;
    2363           0 :         if (!checkGpType(o0, o1, opData.rType, &x))
    2364           0 :           goto InvalidInstruction;
    2365             : 
    2366           0 :         if (!checkGpId(o0, o1, kZR))
    2367           0 :           goto InvalidPhysId;
    2368             : 
    2369           0 :         if (m.baseType() != RegType::kARM_GpX || m.hasIndex())
    2370           0 :           goto InvalidAddress;
    2371             : 
    2372           0 :         if (m.isOffset64Bit())
    2373           0 :           goto InvalidDisplacement;
    2374             : 
    2375           0 :         uint32_t offsetShift = opData.offsetShift + x;
    2376           0 :         int32_t offset32 = m.offsetLo32() >> offsetShift;
    2377             : 
    2378             :         // Make sure we didn't lose bits by applying the mandatory offset shift.
    2379           0 :         if (uint32_t(offset32) << offsetShift != uint32_t(m.offsetLo32()))
    2380           0 :           goto InvalidDisplacement;
    2381             : 
    2382             :         // Offset is encoded as 7-bit immediate.
    2383             :         if (!Support::isInt7(offset32))
    2384           0 :           goto InvalidDisplacement;
    2385             : 
    2386           0 :         if (m.isPreOrPost() && offset32 != 0) {
    2387           0 :           if (!opData.prePostOp)
    2388           0 :             goto InvalidAddress;
    2389             : 
    2390           0 :           opcode.reset(uint32_t(opData.prePostOp) << 22);
    2391             :           opcode.addImm(m.isPreIndex(), 24);
    2392             :         }
    2393             :         else {
    2394           0 :           opcode.reset(uint32_t(opData.offsetOp) << 22);
    2395             :         }
    2396             : 
    2397           0 :         opcode.addImm(x, opData.xOffset);
    2398             :         opcode.addImm(offset32 & 0x7F, 15);
    2399             :         opcode.addReg(o1, 10);
    2400             :         opcode.addReg(o0, 0);
    2401           0 :         goto EmitOp_MemBase_Rn5;
    2402             :       }
    2403             : 
    2404             :       break;
    2405             :     }
    2406             : 
    2407           0 :     case InstDB::kEncodingBaseStx: {
    2408             :       const InstDB::EncodingData::BaseStx& opData = InstDB::EncodingData::baseStx[encodingIndex];
    2409             : 
    2410           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
    2411             :         const Mem& m = o2.as<Mem>();
    2412             :         uint32_t x;
    2413             : 
    2414           0 :         if (!o0.as<Reg>().isGpW() || !checkGpType(o1, opData.rType, &x))
    2415           0 :           goto InvalidInstruction;
    2416             : 
    2417           0 :         if (!checkGpId(o0, o1, kZR))
    2418           0 :           goto InvalidPhysId;
    2419             : 
    2420             :         opcode.reset(opData.opcode());
    2421           0 :         opcode.addImm(x, opData.xOffset);
    2422             :         opcode.addReg(o0, 16);
    2423             :         opcode.addReg(o1, 0);
    2424             : 
    2425           0 :         rmRel = &m;
    2426           0 :         goto EmitOp_MemBaseNoImm_Rn5;
    2427             :       }
    2428             : 
    2429             :       break;
    2430             :     }
    2431             : 
    2432           0 :     case InstDB::kEncodingBaseLdxp: {
    2433             :       const InstDB::EncodingData::BaseLdxp& opData = InstDB::EncodingData::baseLdxp[encodingIndex];
    2434             : 
    2435           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
    2436             :         const Mem& m = o2.as<Mem>();
    2437             :         uint32_t x;
    2438             : 
    2439           0 :         if (!checkGpType(o0, opData.rType, &x) || !checkSignature(o0, o1))
    2440           0 :           goto InvalidInstruction;
    2441             : 
    2442           0 :         if (!checkGpId(o0, o1, kZR))
    2443           0 :           goto InvalidPhysId;
    2444             : 
    2445             :         opcode.reset(opData.opcode());
    2446           0 :         opcode.addImm(x, opData.xOffset);
    2447             :         opcode.addReg(o1, 10);
    2448             :         opcode.addReg(o0, 0);
    2449             : 
    2450           0 :         rmRel = &m;
    2451           0 :         goto EmitOp_MemBaseNoImm_Rn5;
    2452             :       }
    2453             : 
    2454             :       break;
    2455             :     }
    2456             : 
    2457           0 :     case InstDB::kEncodingBaseStxp: {
    2458             :       const InstDB::EncodingData::BaseStxp& opData = InstDB::EncodingData::baseStxp[encodingIndex];
    2459             : 
    2460           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem)) {
    2461             :         const Mem& m = o3.as<Mem>();
    2462             :         uint32_t x;
    2463             : 
    2464           0 :         if (!o0.as<Reg>().isGpW() || !checkGpType(o1, opData.rType, &x) || !checkSignature(o1, o2))
    2465           0 :           goto InvalidInstruction;
    2466             : 
    2467           0 :         if (!checkGpId(o0, o1, o2, kZR))
    2468           0 :           goto InvalidPhysId;
    2469             : 
    2470             :         opcode.reset(opData.opcode());
    2471           0 :         opcode.addImm(x, opData.xOffset);
    2472             :         opcode.addReg(o0, 16);
    2473             :         opcode.addReg(o2, 10);
    2474             :         opcode.addReg(o1, 0);
    2475             : 
    2476           0 :         rmRel = &m;
    2477           0 :         goto EmitOp_MemBaseNoImm_Rn5;
    2478             :       }
    2479             : 
    2480             :       break;
    2481             :     }
    2482             : 
    2483           0 :     case InstDB::kEncodingBaseRM_NoImm: {
    2484             :       const InstDB::EncodingData::BaseRM_NoImm& opData = InstDB::EncodingData::baseRM_NoImm[encodingIndex];
    2485             : 
    2486           0 :       if (isign4 == ENC_OPS2(Reg, Mem)) {
    2487             :         const Mem& m = o1.as<Mem>();
    2488           0 :         rmRel = &m;
    2489             : 
    2490             :         uint32_t x;
    2491           0 :         if (!checkGpType(o0, opData.rType, &x))
    2492           0 :           goto InvalidInstruction;
    2493             : 
    2494           0 :         if (!checkGpId(o0, opData.rHiId))
    2495           0 :           goto InvalidPhysId;
    2496             : 
    2497             :         opcode.reset(opData.opcode());
    2498           0 :         opcode.addImm(x, opData.xOffset);
    2499             :         opcode.addReg(o0, 0);
    2500           0 :         goto EmitOp_MemBaseNoImm_Rn5;
    2501             :       }
    2502             : 
    2503             :       break;
    2504             :     }
    2505             : 
    2506             :     case InstDB::kEncodingBaseRM_SImm9: {
    2507           0 : Case_BaseLdurStur:
    2508             :       const InstDB::EncodingData::BaseRM_SImm9& opData = InstDB::EncodingData::baseRM_SImm9[encodingIndex];
    2509             : 
    2510           0 :       if (isign4 == ENC_OPS2(Reg, Mem)) {
    2511             :         const Mem& m = o1.as<Mem>();
    2512           0 :         rmRel = &m;
    2513             : 
    2514             :         uint32_t x;
    2515           0 :         if (!checkGpType(o0, opData.rType, &x))
    2516           0 :           goto InvalidInstruction;
    2517             : 
    2518           0 :         if (!checkGpId(o0, opData.rHiId))
    2519           0 :           goto InvalidPhysId;
    2520             : 
    2521           0 :         if (m.hasBaseReg() && !m.hasIndex()) {
    2522           0 :           if (m.isOffset64Bit())
    2523           0 :             goto InvalidDisplacement;
    2524             : 
    2525           0 :           int32_t offset32 = m.offsetLo32() >> opData.immShift;
    2526           0 :           if (Support::shl(offset32, opData.immShift) != m.offsetLo32())
    2527           0 :             goto InvalidDisplacement;
    2528             : 
    2529             :           if (!Support::isInt9(offset32))
    2530           0 :             goto InvalidDisplacement;
    2531             : 
    2532           0 :           if (m.isFixedOffset()) {
    2533             :             opcode.reset(opData.offsetOp());
    2534             :           }
    2535             :           else {
    2536           0 :             if (!opData.prePostOp())
    2537           0 :               goto InvalidInstruction;
    2538             : 
    2539             :             opcode.reset(opData.prePostOp());
    2540             :             opcode.xorImm(m.isPreIndex(), 11);
    2541             :           }
    2542             : 
    2543           0 :           opcode.xorImm(x, opData.xOffset);
    2544             :           opcode.addImm(offset32 & 0x1FF, 12);
    2545             :           opcode.addReg(o0, 0);
    2546           0 :           goto EmitOp_MemBase_Rn5;
    2547             :         }
    2548             : 
    2549           0 :         goto InvalidAddress;
    2550             :       }
    2551             : 
    2552             :       break;
    2553             :     }
    2554             : 
    2555           0 :     case InstDB::kEncodingBaseRM_SImm10: {
    2556             :       const InstDB::EncodingData::BaseRM_SImm10& opData = InstDB::EncodingData::baseRM_SImm10[encodingIndex];
    2557             : 
    2558           0 :       if (isign4 == ENC_OPS2(Reg, Mem)) {
    2559             :         const Mem& m = o1.as<Mem>();
    2560           0 :         rmRel = &m;
    2561             : 
    2562             :         uint32_t x;
    2563           0 :         if (!checkGpType(o0, opData.rType, &x))
    2564           0 :           goto InvalidInstruction;
    2565             : 
    2566           0 :         if (!checkGpId(o0, opData.rHiId))
    2567           0 :           goto InvalidPhysId;
    2568             : 
    2569           0 :         if (m.hasBaseReg() && !m.hasIndex()) {
    2570           0 :           if (m.isOffset64Bit())
    2571           0 :             goto InvalidDisplacement;
    2572             : 
    2573           0 :           int32_t offset32 = m.offsetLo32() >> opData.immShift;
    2574           0 :           if (Support::shl(offset32, opData.immShift) != m.offsetLo32())
    2575           0 :             goto InvalidDisplacement;
    2576             : 
    2577             :           if (!Support::isInt10(offset32))
    2578           0 :             goto InvalidDisplacement;
    2579             : 
    2580           0 :           if (m.isPostIndex())
    2581           0 :             goto InvalidAddress;
    2582             : 
    2583             :           // Offset has 10 bits, sign is stored in the 10th bit.
    2584           0 :           offset32 &= 0x3FF;
    2585             : 
    2586             :           opcode.reset(opData.opcode());
    2587             :           opcode.xorImm(m.isPreIndex(), 11);
    2588           0 :           opcode.xorImm(x, opData.xOffset);
    2589           0 :           opcode.addImm(offset32 >> 9, 22);
    2590             :           opcode.addImm(offset32, 12);
    2591             :           opcode.addReg(o0, 0);
    2592           0 :           goto EmitOp_MemBase_Rn5;
    2593             :         }
    2594             : 
    2595           0 :         goto InvalidAddress;
    2596             :       }
    2597             : 
    2598             :       break;
    2599             :     }
    2600             : 
    2601           0 :     case InstDB::kEncodingBaseAtomicOp: {
    2602             :       const InstDB::EncodingData::BaseAtomicOp& opData = InstDB::EncodingData::baseAtomicOp[encodingIndex];
    2603             : 
    2604           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
    2605             :         const Mem& m = o2.as<Mem>();
    2606             :         uint32_t x;
    2607             : 
    2608           0 :         if (!checkGpType(o0, opData.rType, &x) || !checkSignature(o0, o1))
    2609           0 :           goto InvalidInstruction;
    2610             : 
    2611           0 :         if (!checkGpId(o0, o1, kZR))
    2612           0 :           goto InvalidInstruction;
    2613             : 
    2614             :         opcode.reset(opData.opcode());
    2615           0 :         opcode.addImm(x, opData.xOffset);
    2616             :         opcode.addReg(o0, 16);
    2617             :         opcode.addReg(o1, 0);
    2618             : 
    2619           0 :         rmRel = &m;
    2620           0 :         goto EmitOp_MemBaseNoImm_Rn5;
    2621             :       }
    2622             : 
    2623             :       break;
    2624             :     }
    2625             : 
    2626           0 :     case InstDB::kEncodingBaseAtomicSt: {
    2627             :       const InstDB::EncodingData::BaseAtomicSt& opData = InstDB::EncodingData::baseAtomicSt[encodingIndex];
    2628             : 
    2629           0 :       if (isign4 == ENC_OPS2(Reg, Mem)) {
    2630             :         const Mem& m = o1.as<Mem>();
    2631             :         uint32_t x;
    2632             : 
    2633           0 :         if (!checkGpType(o0, opData.rType, &x))
    2634           0 :           goto InvalidInstruction;
    2635             : 
    2636           0 :         if (!checkGpId(o0, kZR))
    2637           0 :           goto InvalidPhysId;
    2638             : 
    2639             :         opcode.reset(opData.opcode());
    2640           0 :         opcode.addImm(x, opData.xOffset);
    2641             :         opcode.addReg(o0, 16);
    2642             :         opcode.addReg(Gp::kIdZr, 0);
    2643             : 
    2644           0 :         rmRel = &m;
    2645           0 :         goto EmitOp_MemBaseNoImm_Rn5;
    2646             :       }
    2647             : 
    2648             :       break;
    2649             :     }
    2650             : 
    2651           0 :     case InstDB::kEncodingBaseAtomicCasp: {
    2652             :       const InstDB::EncodingData::BaseAtomicCasp& opData = InstDB::EncodingData::baseAtomicCasp[encodingIndex];
    2653             :       const Operand_& o4 = opExt[EmitterUtils::kOp4];
    2654             : 
    2655           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg) && o4.isMem()) {
    2656             :         const Mem& m = o4.as<Mem>();
    2657             :         uint32_t x;
    2658             : 
    2659           0 :         if (!checkGpType(o0, opData.rType, &x))
    2660           0 :           goto InvalidInstruction;
    2661             : 
    2662             :         if (!checkSignature(o0, o1, o2, o3))
    2663           0 :           goto InvalidInstruction;
    2664             : 
    2665           0 :         if (!checkEven(o0, o2) || !checkGpId(o0, o2, kZR))
    2666           0 :           goto InvalidPhysId;
    2667             : 
    2668           0 :         if (!checkConsecutive(o0, o1) || !checkConsecutive(o2, o3))
    2669           0 :           goto InvalidPhysId;
    2670             : 
    2671             :         opcode.reset(opData.opcode());
    2672           0 :         opcode.addImm(x, opData.xOffset);
    2673             :         opcode.addReg(o0, 16);
    2674             :         opcode.addReg(o2, 0);
    2675             : 
    2676           0 :         rmRel = &m;
    2677           0 :         goto EmitOp_MemBaseNoImm_Rn5;
    2678             :       }
    2679             : 
    2680             :       break;
    2681             :     }
    2682             : 
    2683             :     // ------------------------------------------------------------------------
    2684             :     // [FSimd - Instructions]
    2685             :     // ------------------------------------------------------------------------
    2686             : 
    2687           0 :     case InstDB::kEncodingFSimdSV: {
    2688             :       const InstDB::EncodingData::FSimdSV& opData = InstDB::EncodingData::fSimdSV[encodingIndex];
    2689             : 
    2690           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    2691             :         uint32_t q = diff(o1.as<Reg>().type(), RegType::kARM_VecD);
    2692           0 :         if (q > 1)
    2693           0 :           goto InvalidInstruction;
    2694             : 
    2695           0 :         if (o0.as<Vec>().hasElementType())
    2696           0 :           goto InvalidInstruction;
    2697             : 
    2698             :         // This operation is only defined for:
    2699             :         //   hD, vS.{4|8}h (16-bit)
    2700             :         //   sD, vS.4s     (32-bit)
    2701             :         uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
    2702           0 :         uint32_t elementSz = o1.as<Vec>().elementType() - Vec::kElementTypeH;
    2703             : 
    2704             :         // Size greater than 1 means 64-bit elements, not supported.
    2705           0 :         if ((sz | elementSz) > 1 || sz != elementSz)
    2706           0 :           goto InvalidInstruction;
    2707             : 
    2708             :         // Size 1 (32-bit float) requires at least 4 elements.
    2709           0 :         if (sz && !q)
    2710           0 :           goto InvalidInstruction;
    2711             : 
    2712             :         // Bit flipping according to sz.
    2713             :         static const uint32_t szBits[] = { B(29), 0 };
    2714             : 
    2715           0 :         opcode.reset(opData.opcode << 10);
    2716           0 :         opcode ^= szBits[sz];
    2717             :         opcode.addImm(q, 30);
    2718           0 :         goto EmitOp_Rd0_Rn5;
    2719             :       }
    2720             : 
    2721             :       break;
    2722             :     }
    2723             : 
    2724           0 :     case InstDB::kEncodingFSimdVV: {
    2725             :       const InstDB::EncodingData::FSimdVV& opData = InstDB::EncodingData::fSimdVV[encodingIndex];
    2726             : 
    2727           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    2728           0 :         if (!matchSignature(o0, o1, instFlags))
    2729           0 :           goto InvalidInstruction;
    2730             : 
    2731           0 :         if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode))
    2732           0 :           goto InvalidInstruction;
    2733             : 
    2734           0 :         goto EmitOp_Rd0_Rn5;
    2735             :       }
    2736             : 
    2737             :       break;
    2738             :     }
    2739             : 
    2740           0 :     case InstDB::kEncodingFSimdVVV: {
    2741             :       const InstDB::EncodingData::FSimdVVV& opData = InstDB::EncodingData::fSimdVVV[encodingIndex];
    2742             : 
    2743           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    2744             :         if (!matchSignature(o0, o1, o2, instFlags))
    2745           0 :           goto InvalidInstruction;
    2746             : 
    2747           0 :         if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode))
    2748           0 :           goto InvalidInstruction;
    2749             : 
    2750           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    2751             :       }
    2752             : 
    2753             :       break;
    2754             :     }
    2755             : 
    2756           0 :     case InstDB::kEncodingFSimdVVVe: {
    2757             :       const InstDB::EncodingData::FSimdVVVe& opData = InstDB::EncodingData::fSimdVVVe[encodingIndex];
    2758             : 
    2759           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    2760           0 :         if (!o2.as<Vec>().hasElementIndex()) {
    2761             :           if (!matchSignature(o0, o1, o2, instFlags))
    2762           0 :             goto InvalidInstruction;
    2763             : 
    2764           0 :           if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode))
    2765           0 :             goto InvalidInstruction;
    2766             : 
    2767           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    2768             :         }
    2769             :         else {
    2770           0 :           if (!matchSignature(o0, o1, instFlags))
    2771           0 :             goto InvalidInstruction;
    2772             : 
    2773           0 :           uint32_t q = o1.as<Reg>().isVecQ();
    2774             :           uint32_t sz;
    2775             : 
    2776           0 :           if (!pickFpOpcode(o0.as<Vec>(), opData.elementScalarOp(), InstDB::kHF_D, opData.elementVectorOp(), InstDB::kHF_D, &opcode, &sz))
    2777           0 :             goto InvalidInstruction;
    2778             : 
    2779           0 :           if (sz == 0 && o2.as<Reg>().id() > 15)
    2780           0 :             goto InvalidPhysId;
    2781             : 
    2782             :           uint32_t elementIndex = o2.as<Vec>().elementIndex();
    2783           0 :           if (elementIndex > (7u >> sz))
    2784           0 :             goto InvalidElementIndex;
    2785             : 
    2786           0 :           uint32_t hlm = elementIndex << sz;
    2787             :           opcode.addImm(q, 30);
    2788             :           opcode.addImm(hlm & 3u, 20);
    2789           0 :           opcode.addImm(hlm >> 2, 11);
    2790           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    2791             :         }
    2792             :       }
    2793             : 
    2794             :       break;
    2795             :     }
    2796             : 
    2797           0 :     case InstDB::kEncodingFSimdVVVV: {
    2798             :       const InstDB::EncodingData::FSimdVVVV& opData = InstDB::EncodingData::fSimdVVVV[encodingIndex];
    2799             : 
    2800           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
    2801             :         if (!matchSignature(o0, o1, o2, o3, instFlags))
    2802           0 :           goto InvalidInstruction;
    2803             : 
    2804           0 :         if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode))
    2805           0 :           goto InvalidInstruction;
    2806             : 
    2807           0 :         goto EmitOp_Rd0_Rn5_Rm16_Ra10;
    2808             :       }
    2809             : 
    2810             :       break;
    2811             :     }
    2812             : 
    2813           0 :     case InstDB::kEncodingSimdFcadd: {
    2814             :       const InstDB::EncodingData::SimdFcadd& opData = InstDB::EncodingData::simdFcadd[encodingIndex];
    2815             : 
    2816           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    2817           0 :         if (!checkSignature(o0, o1, o2) || o0.as<Vec>().hasElementIndex())
    2818           0 :           goto InvalidInstruction;
    2819             : 
    2820             :         uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
    2821           0 :         if (q > 1)
    2822           0 :           goto InvalidInstruction;
    2823             : 
    2824           0 :         uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeB;
    2825           0 :         if (sz == 0 || sz > 3)
    2826           0 :           goto InvalidInstruction;
    2827             : 
    2828             :         // 0 <- 90deg.
    2829             :         // 1 <- 270deg.
    2830             :         uint32_t rot = 0;
    2831           0 :         if (o3.as<Imm>().value() == 270)
    2832             :           rot = 1;
    2833           0 :         else if (o3.as<Imm>().value() != 90)
    2834           0 :           goto InvalidImmediate;
    2835             : 
    2836             :         opcode.reset(opData.opcode());
    2837             :         opcode.addImm(q, 30);
    2838             :         opcode.addImm(sz, 22);
    2839             :         opcode.addImm(rot, 12);
    2840           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    2841             :       }
    2842             : 
    2843             :       break;
    2844             :     }
    2845             : 
    2846           0 :     case InstDB::kEncodingSimdFccmpFccmpe: {
    2847             :       const InstDB::EncodingData::SimdFccmpFccmpe& opData = InstDB::EncodingData::simdFccmpFccmpe[encodingIndex];
    2848             : 
    2849           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
    2850             :         uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
    2851           0 :         if (sz > 2)
    2852           0 :           goto InvalidInstruction;
    2853             : 
    2854           0 :         if (!checkSignature(o0, o1) || o0.as<Vec>().hasElementType())
    2855           0 :           goto InvalidInstruction;
    2856             : 
    2857             :         uint64_t nzcv = o2.as<Imm>().valueAs<uint64_t>();
    2858             :         uint64_t cond = o3.as<Imm>().valueAs<uint64_t>();
    2859             : 
    2860           0 :         if ((nzcv | cond) > 0xFu)
    2861           0 :           goto InvalidImmediate;
    2862             : 
    2863           0 :         uint32_t type = (sz - 1) & 0x3u;
    2864             : 
    2865             :         opcode.reset(opData.opcode());
    2866             :         opcode.addImm(type, 22);
    2867           0 :         opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12);
    2868             :         opcode.addImm(nzcv, 0);
    2869             : 
    2870           0 :         goto EmitOp_Rn5_Rm16;
    2871             :       }
    2872             : 
    2873             :       break;
    2874             :     }
    2875             : 
    2876           0 :     case InstDB::kEncodingSimdFcm: {
    2877             :       const InstDB::EncodingData::SimdFcm& opData = InstDB::EncodingData::simdFcm[encodingIndex];
    2878             : 
    2879           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.hasRegisterOp()) {
    2880             :         if (!matchSignature(o0, o1, o2, instFlags))
    2881           0 :           goto InvalidInstruction;
    2882             : 
    2883           0 :         if (!pickFpOpcode(o0.as<Vec>(), opData.registerScalarOp(), opData.registerScalarHf(), opData.registerVectorOp(), opData.registerVectorHf(), &opcode))
    2884           0 :           goto InvalidInstruction;
    2885             : 
    2886           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    2887             :       }
    2888             : 
    2889           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.hasZeroOp()) {
    2890           0 :         if (!checkSignature(o0, o1))
    2891           0 :           goto InvalidInstruction;
    2892             : 
    2893           0 :         if (o2.as<Imm>().value() != 0 || o2.as<Imm>().predicate() != 0)
    2894           0 :           goto InvalidImmediate;
    2895             : 
    2896           0 :         if (!pickFpOpcode(o0.as<Vec>(), opData.zeroScalarOp(), InstDB::kHF_B, opData.zeroVectorOp(), InstDB::kHF_B, &opcode))
    2897           0 :           goto InvalidInstruction;
    2898             : 
    2899           0 :         goto EmitOp_Rd0_Rn5;
    2900             :       }
    2901             : 
    2902             :       break;
    2903             :     }
    2904             : 
    2905           0 :     case InstDB::kEncodingSimdFcmla: {
    2906             :       const InstDB::EncodingData::SimdFcmla& opData = InstDB::EncodingData::simdFcmla[encodingIndex];
    2907             : 
    2908           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    2909           0 :         if (!checkSignature(o0, o1))
    2910           0 :           goto InvalidInstruction;
    2911             : 
    2912             :         uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
    2913           0 :         if (q > 1)
    2914           0 :           goto InvalidInstruction;
    2915             : 
    2916           0 :         uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeB;
    2917           0 :         if (sz == 0 || sz > 3)
    2918           0 :           goto InvalidInstruction;
    2919             : 
    2920             :         uint32_t rot = 0;
    2921           0 :         switch (o3.as<Imm>().value()) {
    2922             :           case 0  : rot = 0; break;
    2923           0 :           case 90 : rot = 1; break;
    2924           0 :           case 180: rot = 2; break;
    2925           0 :           case 270: rot = 3; break;
    2926           0 :           default:
    2927           0 :             goto InvalidImmediate;
    2928             :         }
    2929             : 
    2930           0 :         if (!o2.as<Vec>().hasElementIndex()) {
    2931           0 :           if (!checkSignature(o1, o2))
    2932           0 :             goto InvalidInstruction;
    2933             : 
    2934             :           opcode.reset(opData.regularOp());
    2935             :           opcode.addImm(q, 30);
    2936             :           opcode.addImm(sz, 22);
    2937             :           opcode.addImm(rot, 11);
    2938           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    2939             :         }
    2940             :         else {
    2941           0 :           if (o0.as<Vec>().elementType() != o2.as<Vec>().elementType())
    2942           0 :             goto InvalidInstruction;
    2943             : 
    2944             :           // Only allowed vectors are: 4H, 8H, and 4S.
    2945           0 :           if (!(sz == 1 || (q == 1 && sz == 2)))
    2946           0 :             goto InvalidInstruction;
    2947             : 
    2948             :           // Element index ranges:
    2949             :           //   4H - ElementIndex[0..1] (index 2..3 is UNDEFINED).
    2950             :           //   8H - ElementIndex[0..3].
    2951             :           //   4S - ElementIndex[0..1].
    2952             :           uint32_t elementIndex = o2.as<Vec>().elementIndex();
    2953           0 :           uint32_t hlFieldShift = sz == 1 ? 0u : 1u;
    2954           0 :           uint32_t maxElementIndex = q == 1 && sz == 1 ? 3u : 1u;
    2955             : 
    2956           0 :           if (elementIndex > maxElementIndex)
    2957           0 :             goto InvalidElementIndex;
    2958             : 
    2959           0 :           uint32_t hl = elementIndex << hlFieldShift;
    2960             : 
    2961             :           opcode.reset(opData.elementOp());
    2962             :           opcode.addImm(q, 30);
    2963             :           opcode.addImm(sz, 22);
    2964             :           opcode.addImm(hl & 1u, 21); // L field.
    2965           0 :           opcode.addImm(hl >> 1, 11); // H field.
    2966             :           opcode.addImm(rot, 13);
    2967           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    2968             :         }
    2969             :       }
    2970             : 
    2971             :       break;
    2972             :     }
    2973             : 
    2974           0 :     case InstDB::kEncodingSimdFcmpFcmpe: {
    2975             :       const InstDB::EncodingData::SimdFcmpFcmpe& opData = InstDB::EncodingData::simdFcmpFcmpe[encodingIndex];
    2976             : 
    2977             :       uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
    2978           0 :       uint32_t type = (sz - 1) & 0x3u;
    2979             : 
    2980           0 :       if (sz > 2)
    2981           0 :         goto InvalidInstruction;
    2982             : 
    2983           0 :       if (o0.as<Vec>().hasElementType())
    2984           0 :         goto InvalidInstruction;
    2985             : 
    2986             :       opcode.reset(opData.opcode());
    2987             :       opcode.addImm(type, 22);
    2988             : 
    2989           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    2990           0 :         if (!checkSignature(o0, o1))
    2991           0 :           goto InvalidInstruction;
    2992             : 
    2993           0 :         goto EmitOp_Rn5_Rm16;
    2994             :       }
    2995             : 
    2996           0 :       if (isign4 == ENC_OPS2(Reg, Imm)) {
    2997           0 :         if (o1.as<Imm>().value() != 0 || o1.as<Imm>().predicate() != 0)
    2998           0 :           goto InvalidInstruction;
    2999             : 
    3000             :         opcode |= B(3);
    3001           0 :         goto EmitOp_Rn5;
    3002             :       }
    3003             : 
    3004             :       break;
    3005             :     }
    3006             : 
    3007           0 :     case InstDB::kEncodingSimdFcsel: {
    3008           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    3009             :         if (!checkSignature(o0, o1, o2))
    3010           0 :           goto InvalidInstruction;
    3011             : 
    3012             :         uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
    3013           0 :         uint32_t type = (sz - 1) & 0x3u;
    3014             : 
    3015           0 :         if (sz > 2 || o0.as<Vec>().hasElementType())
    3016           0 :           goto InvalidInstruction;
    3017             : 
    3018             :         uint64_t cond = o3.as<Imm>().valueAs<uint64_t>();
    3019           0 :         if (cond > 0xFu)
    3020           0 :           goto InvalidImmediate;
    3021             : 
    3022             :         opcode.reset(0b00011110001000000000110000000000);
    3023             :         opcode.addImm(type, 22);
    3024           0 :         opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12);
    3025           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    3026             :       }
    3027             : 
    3028             :       break;
    3029             :     }
    3030             : 
    3031           0 :     case InstDB::kEncodingSimdFcvt: {
    3032           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    3033             :         uint32_t dstSz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
    3034             :         uint32_t srcSz = diff(o1.as<Reg>().type(), RegType::kARM_VecH);
    3035             : 
    3036           0 :         if ((dstSz | srcSz) > 3)
    3037           0 :           goto InvalidInstruction;
    3038             : 
    3039           0 :         if (o0.as<Vec>().hasElementType() || o1.as<Vec>().hasElementType())
    3040           0 :           goto InvalidInstruction;
    3041             : 
    3042             :         // Table that provides 'type' and 'opc' according to the dst/src combination.
    3043             :         static const uint8_t table[] = {
    3044             :           0xFFu, // H <- H (Invalid).
    3045             :           0x03u, // H <- S (type=00 opc=11).
    3046             :           0x13u, // H <- D (type=01 opc=11).
    3047             :           0xFFu, // H <- Q (Invalid).
    3048             :           0x30u, // S <- H (type=11 opc=00).
    3049             :           0xFFu, // S <- S (Invalid).
    3050             :           0x10u, // S <- D (type=01 opc=00).
    3051             :           0xFFu, // S <- Q (Invalid).
    3052             :           0x31u, // D <- H (type=11 opc=01).
    3053             :           0x01u, // D <- S (type=00 opc=01).
    3054             :           0xFFu, // D <- D (Invalid).
    3055             :           0xFFu, // D <- Q (Invalid).
    3056             :           0xFFu, // Q <- H (Invalid).
    3057             :           0xFFu, // Q <- S (Invalid).
    3058             :           0xFFu, // Q <- D (Invalid).
    3059             :           0xFFu  // Q <- Q (Invalid).
    3060             :         };
    3061             : 
    3062           0 :         uint32_t typeOpc = table[(dstSz << 2) | srcSz];
    3063             :         opcode.reset(0b0001111000100010010000 << 10);
    3064           0 :         opcode.addImm(typeOpc >> 4, 22);
    3065           0 :         opcode.addImm(typeOpc & 15, 15);
    3066           0 :         goto EmitOp_Rd0_Rn5;
    3067             :       }
    3068             : 
    3069             :       break;
    3070             :     }
    3071             : 
    3072           0 :     case InstDB::kEncodingSimdFcvtLN: {
    3073             :       const InstDB::EncodingData::SimdFcvtLN& opData = InstDB::EncodingData::simdFcvtLN[encodingIndex];
    3074             : 
    3075           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    3076             :         // Scalar form - only FCVTXN.
    3077           0 :         if (o0.as<Vec>().isVecS() && o1.as<Vec>().isVecD()) {
    3078           0 :           if (!opData.hasScalar())
    3079           0 :             goto InvalidInstruction;
    3080             : 
    3081           0 :           if (o0.as<Vec>().hasElementType() || o1.as<Vec>().hasElementType())
    3082           0 :             goto InvalidInstruction;
    3083             : 
    3084             :           opcode.reset(opData.scalarOp());
    3085             :           opcode |= B(22); // sz bit must be 1, the only supported combination of FCVTXN.
    3086           0 :           goto EmitOp_Rd0_Rn5;
    3087             :         }
    3088             : 
    3089             :         opcode.reset(opData.vectorOp());
    3090             : 
    3091           0 :         const Vec& rL = (instFlags & InstDB::kInstFlagLong) ? o0.as<Vec>() : o1.as<Vec>();
    3092           0 :         const Vec& rN = (instFlags & InstDB::kInstFlagLong) ? o1.as<Vec>() : o0.as<Vec>();
    3093             : 
    3094             :         uint32_t q = diff(rN.type(), RegType::kARM_VecD);
    3095           0 :         if (uint32_t(opcode.hasQ()) != q)
    3096           0 :           goto InvalidInstruction;
    3097             : 
    3098           0 :         if (rL.isVecS4() && rN.elementType() == Vec::kElementTypeH && !opData.isCvtxn()) {
    3099           0 :           goto EmitOp_Rd0_Rn5;
    3100             :         }
    3101             : 
    3102           0 :         if (rL.isVecD2() && rN.elementType() == Vec::kElementTypeS) {
    3103             :           opcode |= B(22);
    3104           0 :           goto EmitOp_Rd0_Rn5;
    3105             :         }
    3106             :       }
    3107             : 
    3108             :       break;
    3109             :     }
    3110             : 
    3111           0 :     case InstDB::kEncodingSimdFcvtSV: {
    3112             :       const InstDB::EncodingData::SimdFcvtSV& opData = InstDB::EncodingData::simdFcvtSV[encodingIndex];
    3113             : 
    3114             :       // So we can support both IntToFloat and FloatToInt conversions.
    3115           0 :       const Operand_& oGp = opData.isFloatToInt() ? o0 : o1;
    3116           0 :       const Operand_& oVec = opData.isFloatToInt() ? o1 : o0;
    3117             : 
    3118           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    3119           0 :         if (oGp.as<Reg>().isGp() && oVec.as<Reg>().isVec()) {
    3120           0 :           uint32_t x = oGp.as<Reg>().isGpX();
    3121             :           uint32_t type = diff(oVec.as<Reg>().type(), RegType::kARM_VecH);
    3122             : 
    3123           0 :           if (type > 2u)
    3124           0 :             goto InvalidInstruction;
    3125             : 
    3126           0 :           type = (type - 1u) & 0x3;
    3127             :           opcode.reset(opData.generalOp());
    3128             :           opcode.addImm(type, 22);
    3129             :           opcode.addImm(x, 31);
    3130           0 :           goto EmitOp_Rd0_Rn5;
    3131             :         }
    3132             : 
    3133           0 :         if (o0.as<Reg>().isVec() && o1.as<Reg>().isVec()) {
    3134           0 :           if (!checkSignature(o0, o1))
    3135           0 :             goto InvalidInstruction;
    3136             : 
    3137           0 :           if (!pickFpOpcode(o0.as<Vec>(), opData.scalarIntOp(), InstDB::kHF_B, opData.vectorIntOp(), InstDB::kHF_B, &opcode))
    3138           0 :             goto InvalidInstruction;
    3139             : 
    3140           0 :           goto EmitOp_Rd0_Rn5;
    3141             :         }
    3142             :       }
    3143             : 
    3144           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.isFixedPoint()) {
    3145           0 :         if (o2.as<Imm>().valueAs<uint64_t>() >= 64)
    3146           0 :           goto InvalidInstruction;
    3147             : 
    3148             :         uint32_t scale = o2.as<Imm>().valueAs<uint32_t>();
    3149           0 :         if (scale == 0)
    3150           0 :           goto InvalidInstruction;
    3151             : 
    3152           0 :         if (oGp.as<Reg>().isGp() && oVec.as<Reg>().isVec()) {
    3153           0 :           uint32_t x = oGp.as<Reg>().isGpX();
    3154             :           uint32_t type = diff(oVec.as<Reg>().type(), RegType::kARM_VecH);
    3155             : 
    3156           0 :           uint32_t scaleLimit = 32u << x;
    3157           0 :           if (scale > scaleLimit)
    3158           0 :             goto InvalidInstruction;
    3159             : 
    3160           0 :           type = (type - 1u) & 0x3;
    3161           0 :           opcode.reset(opData.generalOp() ^ B(21));
    3162             :           opcode.addImm(type, 22);
    3163             :           opcode.addImm(x, 31);
    3164           0 :           opcode.addImm(64u - scale, 10);
    3165           0 :           goto EmitOp_Rd0_Rn5;
    3166             :         }
    3167             : 
    3168           0 :         if (o0.as<Reg>().isVec() && o1.as<Reg>().isVec()) {
    3169           0 :           if (!checkSignature(o0, o1))
    3170           0 :             goto InvalidInstruction;
    3171             : 
    3172             :           uint32_t sz;
    3173           0 :           if (!pickFpOpcode(o0.as<Vec>(), opData.scalarFpOp(), InstDB::kHF_0, opData.vectorFpOp(), InstDB::kHF_0, &opcode, &sz))
    3174           0 :             goto InvalidInstruction;
    3175             : 
    3176           0 :           uint32_t scaleLimit = 16u << sz;
    3177           0 :           if (scale > scaleLimit)
    3178           0 :             goto InvalidInstruction;
    3179             : 
    3180           0 :           uint32_t imm = Support::neg(scale) & Support::lsbMask<uint32_t>(sz + 4 + 1);
    3181             :           opcode.addImm(imm, 16);
    3182           0 :           goto EmitOp_Rd0_Rn5;
    3183             :         }
    3184             :       }
    3185             : 
    3186             :       break;
    3187             :     }
    3188             : 
    3189           0 :     case InstDB::kEncodingSimdFmlal: {
    3190             :       const InstDB::EncodingData::SimdFmlal& opData = InstDB::EncodingData::simdFmlal[encodingIndex];
    3191             : 
    3192           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    3193             :         uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
    3194             :         uint32_t qIsOptional = opData.optionalQ();
    3195             : 
    3196           0 :         if (qIsOptional) {
    3197             :           // This instruction works with either 64-bit or 128-bit registers,
    3198             :           // encoded by Q bit.
    3199           0 :           if (q > 1)
    3200           0 :             goto InvalidInstruction;
    3201             :         }
    3202             :         else {
    3203             :           // This instruction requires 128-bit vector registers.
    3204           0 :           if (q != 1)
    3205           0 :             goto InvalidInstruction;
    3206             : 
    3207             :           // The instruction is ehtier B (bottom) or T (top), which is part of
    3208             :           // the opcode, which uses Q bit, so we have to clear it explicitly.
    3209             :           q = 0;
    3210             :         }
    3211             : 
    3212           0 :         if (uint32_t(o0.as<Reg>().type()) != uint32_t(o1.as<Reg>().type()) + qIsOptional ||
    3213           0 :             o0.as<Vec>().elementType() != opData.tA ||
    3214           0 :             o1.as<Vec>().elementType() != opData.tB)
    3215           0 :           goto InvalidInstruction;
    3216             : 
    3217           0 :         if (!o2.as<Vec>().hasElementIndex()) {
    3218           0 :           if (!checkSignature(o1, o2))
    3219           0 :             goto InvalidInstruction;
    3220             : 
    3221             :           opcode.reset(opData.vectorOp());
    3222             :           opcode.addImm(q, 30);
    3223           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    3224             :         }
    3225             :         else {
    3226           0 :           if (o2.as<Vec>().elementType() != opData.tElement)
    3227           0 :             goto InvalidInstruction;
    3228             : 
    3229           0 :           if (o2.as<Reg>().id() > 15)
    3230           0 :             goto InvalidPhysId;
    3231             : 
    3232             :           uint32_t elementIndex = o2.as<Vec>().elementIndex();
    3233           0 :           if (elementIndex > 7u)
    3234           0 :             goto InvalidElementIndex;
    3235             : 
    3236             :           opcode.reset(opData.elementOp());
    3237             :           opcode.addImm(q, 30);
    3238             :           opcode.addImm(elementIndex & 3u, 20);
    3239           0 :           opcode.addImm(elementIndex >> 2, 11);
    3240           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    3241             :         }
    3242             :       }
    3243             : 
    3244             :       break;
    3245             :     }
    3246             : 
    3247           0 :     case InstDB::kEncodingSimdFmov: {
    3248           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    3249             :         // FMOV Gp <-> Vec opcode:
    3250             :         opcode.reset(0b00011110001001100000000000000000);
    3251             : 
    3252           0 :         if (o0.as<Reg>().isGp() && o1.as<Reg>().isVec()) {
    3253             :           // FMOV Wd, Hn      (sf=0 type=11 rmode=00 op=110)
    3254             :           // FMOV Xd, Hn      (sf=1 type=11 rmode=00 op=110)
    3255             :           // FMOV Wd, Sn      (sf=0 type=00 rmode=00 op=110)
    3256             :           // FMOV Xd, Dn      (sf=1 type=11 rmode=00 op=110)
    3257             :           // FMOV Xd, Vn.d[1] (sf=1 type=10 rmode=01 op=110)
    3258           0 :           uint32_t x = o0.as<Reg>().isGpX();
    3259             :           uint32_t sz = diff(o1.as<Reg>().type(), RegType::kARM_VecH);
    3260             : 
    3261           0 :           uint32_t type = (sz - 1) & 0x3u;
    3262             :           uint32_t rModeOp = 0b00110;
    3263             : 
    3264           0 :           if (o1.as<Vec>().hasElementIndex()) {
    3265             :             // Special case.
    3266           0 :             if (!x || !o1.as<Vec>().isVecD2() || o1.as<Vec>().elementIndex() != 1)
    3267           0 :               goto InvalidInstruction;
    3268             :             type = 0b10;
    3269             :             rModeOp = 0b01110;
    3270             :           }
    3271             :           else {
    3272             :             // Must be scalar.
    3273           0 :             if (sz > 2)
    3274           0 :               goto InvalidInstruction;
    3275             : 
    3276           0 :             if (o1.as<Vec>().hasElementType())
    3277           0 :               goto InvalidInstruction;
    3278             : 
    3279           0 :             if (o1.as<Vec>().isVecS() && x)
    3280           0 :               goto InvalidInstruction;
    3281             : 
    3282           0 :             if (o1.as<Vec>().isVecD() && !x)
    3283           0 :               goto InvalidInstruction;
    3284             :           }
    3285             : 
    3286             :           opcode.addImm(x, 31);
    3287             :           opcode.addImm(type, 22);
    3288             :           opcode.addImm(rModeOp, 16);
    3289           0 :           goto EmitOp_Rd0_Rn5;
    3290             :         }
    3291             : 
    3292           0 :         if (o0.as<Reg>().isVec() && o1.as<Reg>().isGp()) {
    3293             :           // FMOV Hd, Wn      (sf=0 type=11 rmode=00 op=111)
    3294             :           // FMOV Hd, Xn      (sf=1 type=11 rmode=00 op=111)
    3295             :           // FMOV Sd, Wn      (sf=0 type=00 rmode=00 op=111)
    3296             :           // FMOV Dd, Xn      (sf=1 type=11 rmode=00 op=111)
    3297             :           // FMOV Vd.d[1], Xn (sf=1 type=10 rmode=01 op=111)
    3298           0 :           uint32_t x = o1.as<Reg>().isGpX();
    3299             :           uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
    3300             : 
    3301           0 :           uint32_t type = (sz - 1) & 0x3u;
    3302             :           uint32_t rModeOp = 0b00111;
    3303             : 
    3304           0 :           if (o0.as<Vec>().hasElementIndex()) {
    3305             :             // Special case.
    3306           0 :             if (!x || !o0.as<Vec>().isVecD2() || o0.as<Vec>().elementIndex() != 1)
    3307           0 :               goto InvalidInstruction;
    3308             :             type = 0b10;
    3309             :             rModeOp = 0b01111;
    3310             :           }
    3311             :           else {
    3312             :             // Must be scalar.
    3313           0 :             if (sz > 2)
    3314           0 :               goto InvalidInstruction;
    3315             : 
    3316           0 :             if (o0.as<Vec>().hasElementType())
    3317           0 :               goto InvalidInstruction;
    3318             : 
    3319           0 :             if (o0.as<Vec>().isVecS() && x)
    3320           0 :               goto InvalidInstruction;
    3321             : 
    3322           0 :             if (o0.as<Vec>().isVecD() && !x)
    3323           0 :               goto InvalidInstruction;
    3324             :           }
    3325             : 
    3326             :           opcode.addImm(x, 31);
    3327             :           opcode.addImm(type, 22);
    3328             :           opcode.addImm(rModeOp, 16);
    3329           0 :           goto EmitOp_Rd0_Rn5;
    3330             :         }
    3331             : 
    3332           0 :         if (checkSignature(o0, o1)) {
    3333             :           uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
    3334           0 :           if (sz > 2)
    3335           0 :             goto InvalidInstruction;
    3336             : 
    3337           0 :           if (o0.as<Vec>().hasElementType())
    3338           0 :             goto InvalidInstruction;
    3339             : 
    3340           0 :           uint32_t type = (sz - 1) & 0x3;
    3341             :           opcode.reset(0b00011110001000000100000000000000);
    3342             :           opcode.addImm(type, 22);
    3343           0 :           goto EmitOp_Rd0_Rn5;
    3344             :         }
    3345             :       }
    3346             : 
    3347           0 :       if (isign4 == ENC_OPS2(Reg, Imm)) {
    3348           0 :         if (o0.as<Reg>().isVec()) {
    3349             :           double fpValue;
    3350           0 :           if (o1.as<Imm>().isDouble())
    3351             :             fpValue = o1.as<Imm>().valueAs<double>();
    3352           0 :           else if (o1.as<Imm>().isInt32())
    3353           0 :             fpValue = o1.as<Imm>().valueAs<int32_t>();
    3354             :           else
    3355           0 :             goto InvalidImmediate;
    3356             : 
    3357             :           if (!Utils::isFP64Imm8(fpValue))
    3358           0 :             goto InvalidImmediate;
    3359             : 
    3360             :           uint32_t imm8 = Utils::encodeFP64ToImm8(fpValue);
    3361           0 :           if (!o0.as<Vec>().hasElementType()) {
    3362             :             // FMOV (scalar, immediate).
    3363             :             uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
    3364           0 :             uint32_t type = (sz - 1u) & 0x3u;
    3365             : 
    3366           0 :             if (sz > 2)
    3367           0 :               goto InvalidInstruction;
    3368             : 
    3369             :             opcode.reset(0b00011110001000000001000000000000);
    3370             :             opcode.addImm(type, 22);
    3371             :             opcode.addImm(imm8, 13);
    3372           0 :             goto EmitOp_Rd0;
    3373             :           }
    3374             :           else {
    3375             :             uint32_t q = diff(o0.as<Vec>().type(), RegType::kARM_VecD);
    3376           0 :             uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeH;
    3377             : 
    3378           0 :             if (q > 1 || sz > 2)
    3379           0 :               goto InvalidInstruction;
    3380             : 
    3381             :             static const uint32_t szBits[3] = { B(11), B(0), B(29) };
    3382             :             opcode.reset(0b00001111000000001111010000000000);
    3383           0 :             opcode ^= szBits[sz];
    3384             :             opcode.addImm(q, 30);
    3385           0 :             opcode.addImm(imm8 >> 5, 16);
    3386             :             opcode.addImm(imm8 & 31, 5);
    3387           0 :             goto EmitOp_Rd0;
    3388             :           }
    3389             :         }
    3390             :       }
    3391             : 
    3392             :       break;
    3393             :     }
    3394             : 
    3395           0 :     case InstDB::kEncodingFSimdPair: {
    3396             :       const InstDB::EncodingData::FSimdPair& opData = InstDB::EncodingData::fSimdPair[encodingIndex];
    3397             : 
    3398           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    3399             :         // This operation is only defined for:
    3400             :         //   hD, vS.2h (16-bit)
    3401             :         //   sD, vS.2s (32-bit)
    3402             :         //   dD, vS.2d (64-bit)
    3403             :         uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH);
    3404           0 :         if (sz > 2)
    3405           0 :           goto InvalidInstruction;
    3406             : 
    3407             :         static const uint32_t szSignatures[3] = {
    3408             :           VecS::kSignature | (Vec::kSignatureElementH),
    3409             :           VecD::kSignature | (Vec::kSignatureElementS),
    3410             :           VecV::kSignature | (Vec::kSignatureElementD)
    3411             :         };
    3412             : 
    3413           0 :         if (o1.signature() != szSignatures[sz])
    3414           0 :           goto InvalidInstruction;
    3415             : 
    3416             :         static const uint32_t szBits[] = { B(29), 0, B(22) };
    3417             :         opcode.reset(opData.scalarOp());
    3418           0 :         opcode ^= szBits[sz];
    3419           0 :         goto EmitOp_Rd0_Rn5;
    3420             :       }
    3421             : 
    3422           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    3423             :         if (!checkSignature(o0, o1, o2))
    3424           0 :           goto InvalidInstruction;
    3425             : 
    3426             :         uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
    3427           0 :         if (q > 1)
    3428           0 :           goto InvalidInstruction;
    3429             : 
    3430           0 :         uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeH;
    3431           0 :         if (sz > 2)
    3432           0 :           goto InvalidInstruction;
    3433             : 
    3434             :         static const uint32_t szBits[3] = { B(22) | B(21) | B(15) | B(14), 0, B(22) };
    3435             :         opcode.reset(opData.vectorOp());
    3436           0 :         opcode ^= szBits[sz];
    3437             :         opcode.addImm(q, 30);
    3438           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    3439             :       }
    3440             : 
    3441             :       break;
    3442             :     }
    3443             : 
    3444             :     // ------------------------------------------------------------------------
    3445             :     // [ISimd - Instructions]
    3446             :     // ------------------------------------------------------------------------
    3447             : 
    3448           0 :     case InstDB::kEncodingISimdSV: {
    3449             :       const InstDB::EncodingData::ISimdSV& opData = InstDB::EncodingData::iSimdSV[encodingIndex];
    3450             : 
    3451           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    3452             :         // The first destination operand is scalar, which matches element-type of source vectors.
    3453           0 :         uint32_t L = (instFlags & InstDB::kInstFlagLong) != 0;
    3454           0 :         if (diff(o0.as<Vec>().type(), RegType::kARM_VecB) != o1.as<Vec>().elementType() - Vec::kElementTypeB + L)
    3455           0 :           goto InvalidInstruction;
    3456             : 
    3457           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType());
    3458           0 :         if (!sizeOp.isValid())
    3459           0 :           goto InvalidInstruction;
    3460             : 
    3461             :         opcode.reset(opData.opcode());
    3462             :         opcode.addImm(sizeOp.q(), 30);
    3463             :         opcode.addImm(sizeOp.size(), 22);
    3464           0 :         goto EmitOp_Rd0_Rn5;
    3465             :       }
    3466             : 
    3467             :       break;
    3468             :     }
    3469             : 
    3470           0 :     case InstDB::kEncodingISimdVV: {
    3471             :       const InstDB::EncodingData::ISimdVV& opData = InstDB::EncodingData::iSimdVV[encodingIndex];
    3472             : 
    3473           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    3474           0 :         const Operand_& sop = significantSimdOp(o0, o1, instFlags);
    3475           0 :         if (!matchSignature(o0, o1, instFlags))
    3476           0 :           goto InvalidInstruction;
    3477             : 
    3478           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
    3479           0 :         if (!sizeOp.isValid())
    3480           0 :           goto InvalidInstruction;
    3481             : 
    3482             :         opcode.reset(opData.opcode());
    3483             :         opcode.addImm(sizeOp.qs(), 30);
    3484             :         opcode.addImm(sizeOp.scalar(), 28);
    3485             :         opcode.addImm(sizeOp.size(), 22);
    3486           0 :         goto EmitOp_Rd0_Rn5;
    3487             :       }
    3488             : 
    3489             :       break;
    3490             :     }
    3491             : 
    3492           0 :     case InstDB::kEncodingISimdVVx: {
    3493             :       const InstDB::EncodingData::ISimdVVx& opData = InstDB::EncodingData::iSimdVVx[encodingIndex];
    3494             : 
    3495           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    3496           0 :         if (o0.signature() != opData.op0Signature ||
    3497           0 :             o1.signature() != opData.op1Signature)
    3498           0 :           goto InvalidInstruction;
    3499             : 
    3500             :         opcode.reset(opData.opcode());
    3501           0 :         goto EmitOp_Rd0_Rn5;
    3502             :       }
    3503             : 
    3504             :       break;
    3505             :     }
    3506             : 
    3507           0 :     case InstDB::kEncodingISimdVVV: {
    3508             :       const InstDB::EncodingData::ISimdVVV& opData = InstDB::EncodingData::iSimdVVV[encodingIndex];
    3509             : 
    3510           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    3511           0 :         const Operand_& sop = significantSimdOp(o0, o1, instFlags);
    3512             :         if (!matchSignature(o0, o1, o2, instFlags))
    3513           0 :           goto InvalidInstruction;
    3514             : 
    3515           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
    3516           0 :         if (!sizeOp.isValid())
    3517           0 :           goto InvalidInstruction;
    3518             : 
    3519             :         opcode.reset(opData.opcode());
    3520             :         opcode.addImm(sizeOp.qs(), 30);
    3521             :         opcode.addImm(sizeOp.scalar(), 28);
    3522             :         opcode.addImm(sizeOp.size(), 22);
    3523           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    3524             :       }
    3525             : 
    3526             :       break;
    3527             :     }
    3528             : 
    3529           0 :     case InstDB::kEncodingISimdVVVx: {
    3530             :       const InstDB::EncodingData::ISimdVVVx& opData = InstDB::EncodingData::iSimdVVVx[encodingIndex];
    3531             : 
    3532           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    3533           0 :         if (o0.signature() != opData.op0Signature ||
    3534           0 :             o1.signature() != opData.op1Signature ||
    3535           0 :             o2.signature() != opData.op2Signature)
    3536           0 :           goto InvalidInstruction;
    3537             : 
    3538             :         opcode.reset(opData.opcode());
    3539           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    3540             :       }
    3541             : 
    3542             :       break;
    3543             :     }
    3544             : 
    3545           0 :     case InstDB::kEncodingISimdWWV: {
    3546             :       // Special case for wide add/sub [s|b][add|sub][w]{2}.
    3547             :       const InstDB::EncodingData::ISimdWWV& opData = InstDB::EncodingData::iSimdWWV[encodingIndex];
    3548             : 
    3549           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    3550           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o2.as<Reg>().type(), o2.as<Vec>().elementType());
    3551           0 :         if (!sizeOp.isValid())
    3552           0 :           goto InvalidInstruction;
    3553             : 
    3554           0 :         if (!checkSignature(o0, o1) || !o0.as<Reg>().isVecV() || o0.as<Vec>().elementType() != o2.as<Vec>().elementType() + 1)
    3555           0 :           goto InvalidInstruction;
    3556             : 
    3557             :         opcode.reset(opData.opcode());
    3558             :         opcode.addImm(sizeOp.qs(), 30);
    3559             :         opcode.addImm(sizeOp.scalar(), 28);
    3560             :         opcode.addImm(sizeOp.size(), 22);
    3561           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    3562             :       }
    3563             : 
    3564             :       break;
    3565             :     }
    3566             : 
    3567           0 :     case InstDB::kEncodingISimdVVVe: {
    3568             :       const InstDB::EncodingData::ISimdVVVe& opData = InstDB::EncodingData::iSimdVVVe[encodingIndex];
    3569             : 
    3570           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    3571           0 :         const Operand_& sop = significantSimdOp(o0, o1, instFlags);
    3572           0 :         if (!matchSignature(o0, o1, instFlags))
    3573           0 :           goto InvalidInstruction;
    3574             : 
    3575           0 :         if (!o2.as<Vec>().hasElementIndex()) {
    3576           0 :           SizeOp sizeOp = armElementTypeToSizeOp(opData.regularVecType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
    3577           0 :           if (!sizeOp.isValid())
    3578           0 :             goto InvalidInstruction;
    3579             : 
    3580           0 :           if (!checkSignature(o1, o2))
    3581           0 :             goto InvalidInstruction;
    3582             : 
    3583           0 :           opcode.reset(uint32_t(opData.regularOp) << 10);
    3584             :           opcode.addImm(sizeOp.qs(), 30);
    3585             :           opcode.addImm(sizeOp.scalar(), 28);
    3586             :           opcode.addImm(sizeOp.size(), 22);
    3587           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    3588             :         }
    3589             :         else {
    3590           0 :           SizeOp sizeOp = armElementTypeToSizeOp(opData.elementVecType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
    3591           0 :           if (!sizeOp.isValid())
    3592           0 :             goto InvalidInstruction;
    3593             : 
    3594             :           uint32_t elementIndex = o2.as<Vec>().elementIndex();
    3595             :           LMHImm lmh;
    3596             : 
    3597           0 :           if (!encodeLMH(sizeOp.size(), elementIndex, &lmh))
    3598           0 :             goto InvalidElementIndex;
    3599             : 
    3600           0 :           if (o2.as<Reg>().id() > lmh.maxRmId)
    3601           0 :             goto InvalidPhysId;
    3602             : 
    3603           0 :           opcode.reset(uint32_t(opData.elementOp) << 10);
    3604             :           opcode.addImm(sizeOp.q(), 30);
    3605             :           opcode.addImm(sizeOp.size(), 22);
    3606           0 :           opcode.addImm(lmh.lm, 20);
    3607           0 :           opcode.addImm(lmh.h, 11);
    3608           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    3609             :         }
    3610             :       }
    3611             : 
    3612             :       break;
    3613             :     }
    3614             : 
    3615           0 :     case InstDB::kEncodingISimdVVVI: {
    3616             :       const InstDB::EncodingData::ISimdVVVI& opData = InstDB::EncodingData::iSimdVVVI[encodingIndex];
    3617             : 
    3618           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) {
    3619           0 :         const Operand_& sop = significantSimdOp(o0, o1, instFlags);
    3620             :         if (!matchSignature(o0, o1, o2, instFlags))
    3621           0 :           goto InvalidInstruction;
    3622             : 
    3623           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
    3624           0 :         if (!sizeOp.isValid())
    3625           0 :           goto InvalidInstruction;
    3626             : 
    3627             :         uint64_t immValue = o3.as<Imm>().valueAs<uint64_t>();
    3628           0 :         uint32_t immSize = opData.immSize;
    3629             : 
    3630           0 :         if (opData.imm64HasOneBitLess && !sizeOp.q())
    3631           0 :           immSize--;
    3632             : 
    3633           0 :         uint32_t immMax = 1u << immSize;
    3634           0 :         if (immValue >= immMax)
    3635           0 :           goto InvalidImmediate;
    3636             : 
    3637             :         opcode.reset(opData.opcode());
    3638             :         opcode.addImm(sizeOp.qs(), 30);
    3639             :         opcode.addImm(sizeOp.scalar(), 28);
    3640             :         opcode.addImm(sizeOp.size(), 22);
    3641           0 :         opcode.addImm(immValue, opData.immShift);
    3642           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    3643             :       }
    3644             : 
    3645             :       break;
    3646             :     }
    3647             : 
    3648           0 :     case InstDB::kEncodingISimdVVVV: {
    3649             :       const InstDB::EncodingData::ISimdVVVV& opData = InstDB::EncodingData::iSimdVVVV[encodingIndex];
    3650             : 
    3651           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
    3652           0 :         const Operand_& sop = significantSimdOp(o0, o1, instFlags);
    3653             :         if (!matchSignature(o0, o1, o2, o3, instFlags))
    3654           0 :           goto InvalidInstruction;
    3655             : 
    3656           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
    3657           0 :         if (!sizeOp.isValid())
    3658           0 :           goto InvalidInstruction;
    3659             : 
    3660           0 :         opcode.reset(uint32_t(opData.opcode) << 10);
    3661             :         opcode.addImm(sizeOp.qs(), 30);
    3662             :         opcode.addImm(sizeOp.scalar(), 28);
    3663             :         opcode.addImm(sizeOp.size(), 22);
    3664           0 :         goto EmitOp_Rd0_Rn5_Rm16_Ra10;
    3665             :       }
    3666             : 
    3667             :       break;
    3668             :     }
    3669             : 
    3670           0 :     case InstDB::kEncodingISimdVVVVx: {
    3671             :       const InstDB::EncodingData::ISimdVVVVx& opData = InstDB::EncodingData::iSimdVVVVx[encodingIndex];
    3672             : 
    3673           0 :       if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
    3674           0 :         if (o0.signature() != opData.op0Signature ||
    3675           0 :             o1.signature() != opData.op1Signature ||
    3676           0 :             o2.signature() != opData.op2Signature ||
    3677           0 :             o3.signature() != opData.op3Signature)
    3678           0 :           goto InvalidInstruction;
    3679             : 
    3680           0 :         opcode.reset(uint32_t(opData.opcode) << 10);
    3681           0 :         goto EmitOp_Rd0_Rn5_Rm16_Ra10;
    3682             :       }
    3683             : 
    3684             :       break;
    3685             :     }
    3686             : 
    3687             : 
    3688           0 :     case InstDB::kEncodingISimdPair: {
    3689             :       const InstDB::EncodingData::ISimdPair& opData = InstDB::EncodingData::iSimdPair[encodingIndex];
    3690             : 
    3691           0 :       if (isign4 == ENC_OPS2(Reg, Reg) && opData.opcode2) {
    3692           0 :         if (o0.as<Vec>().isVecD1() && o1.as<Vec>().isVecD2()) {
    3693           0 :           opcode.reset(uint32_t(opData.opcode2) << 10);
    3694             :           opcode.addImm(0x3, 22); // size.
    3695           0 :           goto EmitOp_Rd0_Rn5;
    3696             :         }
    3697             :       }
    3698             : 
    3699           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    3700             :         if (!matchSignature(o0, o1, o2, instFlags))
    3701           0 :           goto InvalidInstruction;
    3702             : 
    3703           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.opType3, o0.as<Reg>().type(), o0.as<Vec>().elementType());
    3704           0 :         if (!sizeOp.isValid())
    3705           0 :           goto InvalidInstruction;
    3706             : 
    3707           0 :         opcode.reset(uint32_t(opData.opcode3) << 10);
    3708             :         opcode.addImm(sizeOp.qs(), 30);
    3709             :         opcode.addImm(sizeOp.scalar(), 28);
    3710             :         opcode.addImm(sizeOp.size(), 22);
    3711           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    3712             :       }
    3713             : 
    3714             :       break;
    3715             :     }
    3716             : 
    3717           0 :     case InstDB::kEncodingSimdBicOrr: {
    3718             :       const InstDB::EncodingData::SimdBicOrr& opData = InstDB::EncodingData::simdBicOrr[encodingIndex];
    3719             : 
    3720           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    3721             :         if (!matchSignature(o0, o1, o2, instFlags))
    3722           0 :           goto InvalidInstruction;
    3723             : 
    3724           0 :         SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_B, o0.as<Reg>().type(), o0.as<Vec>().elementType());
    3725           0 :         if (!sizeOp.isValid())
    3726           0 :           goto InvalidInstruction;
    3727             : 
    3728           0 :         opcode.reset(uint32_t(opData.registerOp) << 10);
    3729             :         opcode.addImm(sizeOp.q(), 30);
    3730           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    3731             :       }
    3732             : 
    3733           0 :       if (isign4 == ENC_OPS2(Reg, Imm) || isign4 == ENC_OPS3(Reg, Imm, Imm)) {
    3734           0 :         SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_HS, o0.as<Reg>().type(), o0.as<Vec>().elementType());
    3735           0 :         if (!sizeOp.isValid())
    3736           0 :           goto InvalidInstruction;
    3737             : 
    3738           0 :         if (o1.as<Imm>().valueAs<uint64_t>() > 0xFFFFFFFFu)
    3739           0 :           goto InvalidImmediate;
    3740             : 
    3741             :         uint32_t imm = o1.as<Imm>().valueAs<uint32_t>();
    3742             :         uint32_t shift = 0;
    3743           0 :         uint32_t maxShift = (8u << sizeOp.size()) - 8u;
    3744             : 
    3745           0 :         if (o2.isImm()) {
    3746           0 :           if (o2.as<Imm>().predicate() != uint32_t(ShiftOp::kLSL))
    3747           0 :             goto InvalidImmediate;
    3748             : 
    3749           0 :           if (imm > 0xFFu || o2.as<Imm>().valueAs<uint64_t>() > maxShift)
    3750           0 :             goto InvalidImmediate;
    3751             : 
    3752             :           shift = o2.as<Imm>().valueAs<uint32_t>();
    3753           0 :           if ((shift & 0x7u) != 0u)
    3754           0 :             goto InvalidImmediate;
    3755             :         }
    3756           0 :         else if (imm) {
    3757           0 :           shift = Support::ctz(imm) & 0x7u;
    3758           0 :           imm >>= shift;
    3759             : 
    3760           0 :           if (imm > 0xFFu || shift > maxShift)
    3761           0 :             goto InvalidImmediate;
    3762             :         }
    3763             : 
    3764           0 :         uint32_t cmode = 0x1u | ((shift / 8u) << 1);
    3765           0 :         if (sizeOp.size() == 1)
    3766           0 :           cmode |= B(3);
    3767             : 
    3768             :         // The immediate value is split into ABC and DEFGH parts.
    3769           0 :         uint32_t abc = (imm >> 5) & 0x7u;
    3770             :         uint32_t defgh = imm & 0x1Fu;
    3771             : 
    3772           0 :         opcode.reset(uint32_t(opData.immediateOp) << 10);
    3773             :         opcode.addImm(sizeOp.q(), 30);
    3774             :         opcode.addImm(abc, 16);
    3775             :         opcode.addImm(cmode, 12);
    3776             :         opcode.addImm(defgh, 5);
    3777           0 :         goto EmitOp_Rd0;
    3778             :       }
    3779             : 
    3780             :       break;
    3781             :     }
    3782             : 
    3783           0 :     case InstDB::kEncodingSimdCmp: {
    3784             :       const InstDB::EncodingData::SimdCmp& opData = InstDB::EncodingData::simdCmp[encodingIndex];
    3785             : 
    3786           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.regOp) {
    3787             :         if (!matchSignature(o0, o1, o2, instFlags))
    3788           0 :           goto InvalidInstruction;
    3789             : 
    3790           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o0.as<Reg>().type(), o0.as<Vec>().elementType());
    3791           0 :         if (!sizeOp.isValid())
    3792           0 :           goto InvalidInstruction;
    3793             : 
    3794           0 :         opcode.reset(uint32_t(opData.regOp) << 10);
    3795             :         opcode.addImm(sizeOp.qs(), 30);
    3796             :         opcode.addImm(sizeOp.scalar(), 28);
    3797             :         opcode.addImm(sizeOp.size(), 22);
    3798           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    3799             :       }
    3800             : 
    3801           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.zeroOp) {
    3802           0 :         if (!matchSignature(o0, o1, instFlags))
    3803           0 :           goto InvalidInstruction;
    3804             : 
    3805           0 :         if (o2.as<Imm>().value() != 0)
    3806           0 :           goto InvalidImmediate;
    3807             : 
    3808           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o0.as<Reg>().type(), o0.as<Vec>().elementType());
    3809           0 :         if (!sizeOp.isValid())
    3810           0 :           goto InvalidInstruction;
    3811             : 
    3812           0 :         opcode.reset(uint32_t(opData.zeroOp) << 10);
    3813             :         opcode.addImm(sizeOp.qs(), 30);
    3814             :         opcode.addImm(sizeOp.scalar(), 28);
    3815             :         opcode.addImm(sizeOp.size(), 22);
    3816           0 :         goto EmitOp_Rd0_Rn5;
    3817             :       }
    3818             : 
    3819             :       break;
    3820             :     }
    3821             : 
    3822           0 :     case InstDB::kEncodingSimdDot: {
    3823             :       const InstDB::EncodingData::SimdDot& opData = InstDB::EncodingData::simdDot[encodingIndex];
    3824             : 
    3825           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    3826             :         uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
    3827             :         uint32_t size = 2;
    3828             : 
    3829           0 :         if (q > 1u)
    3830           0 :           goto InvalidInstruction;
    3831             : 
    3832           0 :         if (!o2.as<Vec>().hasElementIndex()) {
    3833           0 :           if (!opData.vectorOp)
    3834           0 :             goto InvalidInstruction;
    3835             : 
    3836           0 :           if (o0.as<Reg>().type() != o1.as<Reg>().type() || o1.as<Reg>().type() != o2.as<Reg>().type())
    3837           0 :             goto InvalidInstruction;
    3838             : 
    3839           0 :           if (o0.as<Vec>().elementType() != opData.tA ||
    3840           0 :               o1.as<Vec>().elementType() != opData.tB ||
    3841             :               o2.as<Vec>().elementType() != opData.tB)
    3842           0 :             goto InvalidInstruction;
    3843             : 
    3844           0 :           opcode.reset(uint32_t(opData.vectorOp) << 10);
    3845             :           opcode.addImm(q, 30);
    3846           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    3847             :         }
    3848             :         else {
    3849           0 :           if (!opData.elementOp)
    3850           0 :             goto InvalidInstruction;
    3851             : 
    3852           0 :           if (o0.as<Reg>().type() != o1.as<Reg>().type() || !o2.as<Reg>().isVecV())
    3853           0 :             goto InvalidInstruction;
    3854             : 
    3855           0 :           if (o0.as<Vec>().elementType() != opData.tA ||
    3856           0 :               o1.as<Vec>().elementType() != opData.tB ||
    3857           0 :               o2.as<Vec>().elementType() != opData.tElement)
    3858           0 :             goto InvalidInstruction;
    3859             : 
    3860             :           uint32_t elementIndex = o2.as<Vec>().elementIndex();
    3861             :           LMHImm lmh;
    3862             : 
    3863           0 :           if (!encodeLMH(size, elementIndex, &lmh))
    3864           0 :             goto InvalidElementIndex;
    3865             : 
    3866           0 :           if (o2.as<Reg>().id() > lmh.maxRmId)
    3867           0 :             goto InvalidPhysId;
    3868             : 
    3869           0 :           opcode.reset(uint32_t(opData.elementOp) << 10);
    3870             :           opcode.addImm(q, 30);
    3871           0 :           opcode.addImm(lmh.lm, 20);
    3872           0 :           opcode.addImm(lmh.h, 11);
    3873           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    3874             :         }
    3875             :       }
    3876             : 
    3877             :       break;
    3878             :     }
    3879             : 
    3880           0 :     case InstDB::kEncodingSimdDup: SimdDup: {
    3881           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    3882             :         // Truth table of valid encodings of `Q:1|ElementType:3`
    3883             :         uint32_t kValidEncodings = B(Vec::kElementTypeB + 0) |
    3884             :                                    B(Vec::kElementTypeH + 0) |
    3885             :                                    B(Vec::kElementTypeS + 0) |
    3886             :                                    B(Vec::kElementTypeB + 8) |
    3887             :                                    B(Vec::kElementTypeH + 8) |
    3888             :                                    B(Vec::kElementTypeS + 8) |
    3889             :                                    B(Vec::kElementTypeD + 8) ;
    3890             : 
    3891             :         uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
    3892             : 
    3893           0 :         if (o1.as<Reg>().isGp()) {
    3894             :           // DUP - Vec (scalar|vector) <- GP register.
    3895             :           //
    3896             :           // NOTE: This is only scalar for `dup d, x` case, otherwise the value
    3897             :           // would be duplicated across all vector elements (1, 2, 4, 8, or 16).
    3898             :           uint32_t elementType = o0.as<Vec>().elementType();
    3899           0 :           if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType))
    3900           0 :             goto InvalidInstruction;
    3901             : 
    3902           0 :           uint32_t lsbIndex = elementType - 1u;
    3903           0 :           uint32_t imm5 = 1u << lsbIndex;
    3904             : 
    3905             :           opcode.reset(0b0000111000000000000011 << 10);
    3906             :           opcode.addImm(q, 30);
    3907             :           opcode.addImm(imm5, 16);
    3908           0 :           goto EmitOp_Rd0_Rn5;
    3909             :         }
    3910             : 
    3911           0 :         if (!o1.as<Reg>().isVec() || !o1.as<Vec>().hasElementIndex())
    3912           0 :           goto InvalidInstruction;
    3913             : 
    3914             :         uint32_t dstIndex = o1.as<Vec>().elementIndex();
    3915           0 :         if (!o0.as<Vec>().hasElementType()) {
    3916             :           // DUP - Vec (scalar) <- Vec[N].
    3917             :           uint32_t lsbIndex = diff(o0.as<Reg>().type(), RegType::kARM_VecB);
    3918             : 
    3919           0 :           if (lsbIndex != o1.as<Vec>().elementType() - Vec::kElementTypeB || lsbIndex > 3)
    3920           0 :             goto InvalidInstruction;
    3921             : 
    3922           0 :           uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex;
    3923           0 :           if (imm5 > 31)
    3924           0 :             goto InvalidElementIndex;
    3925             : 
    3926             :           opcode.reset(0b0101111000000000000001 << 10);
    3927             :           opcode.addImm(imm5, 16);
    3928           0 :           goto EmitOp_Rd0_Rn5;
    3929             :         }
    3930             :         else {
    3931             :           // DUP - Vec (all) <- Vec[N].
    3932             :           uint32_t elementType = o0.as<Vec>().elementType();
    3933           0 :           if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType))
    3934           0 :             goto InvalidInstruction;
    3935             : 
    3936           0 :           uint32_t lsbIndex = elementType - 1u;
    3937           0 :           uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex;
    3938             : 
    3939           0 :           if (imm5 > 31)
    3940           0 :             goto InvalidElementIndex;
    3941             : 
    3942             :           opcode.reset(0b0000111000000000000001 << 10);
    3943             :           opcode.addImm(q, 30);
    3944             :           opcode.addImm(imm5, 16);
    3945           0 :           goto EmitOp_Rd0_Rn5;
    3946             :         }
    3947             :       }
    3948             : 
    3949             :       break;
    3950             :     }
    3951             : 
    3952           0 :     case InstDB::kEncodingSimdIns: SimdIns: {
    3953           0 :       if (isign4 == ENC_OPS2(Reg, Reg) && o0.as<Reg>().isVecV()) {
    3954           0 :         if (!o0.as<Vec>().hasElementIndex())
    3955           0 :           goto InvalidInstruction;
    3956             : 
    3957             :         uint32_t elementType = o0.as<Vec>().elementType();
    3958             :         uint32_t dstIndex = o0.as<Vec>().elementIndex();
    3959           0 :         uint32_t lsbIndex = elementType - 1u;
    3960             : 
    3961           0 :         uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex;
    3962           0 :         if (imm5 > 31)
    3963           0 :           goto InvalidElementIndex;
    3964             : 
    3965           0 :         if (o1.as<Reg>().isGp()) {
    3966             :           // INS - Vec[N] <- GP register.
    3967             :           opcode.reset(0b0100111000000000000111 << 10);
    3968             :           opcode.addImm(imm5, 16);
    3969           0 :           goto EmitOp_Rd0_Rn5;
    3970             :         }
    3971           0 :         else if (o1.as<Reg>().isVecV() && o1.as<Vec>().hasElementIndex()) {
    3972             :           // INS - Vec[N] <- Vec[M].
    3973           0 :           if (o0.as<Vec>().elementType() != o1.as<Vec>().elementType())
    3974           0 :             goto InvalidInstruction;
    3975             : 
    3976             :           uint32_t srcIndex = o1.as<Vec>().elementIndex();
    3977           0 :           if (o0.as<Reg>().type() != o1.as<Reg>().type())
    3978           0 :             goto InvalidInstruction;
    3979             : 
    3980           0 :           uint32_t imm4 = srcIndex << lsbIndex;
    3981           0 :           if (imm4 > 15)
    3982           0 :             goto InvalidElementIndex;
    3983             : 
    3984             :           opcode.reset(0b0110111000000000000001 << 10);
    3985             :           opcode.addImm(imm5, 16);
    3986             :           opcode.addImm(imm4, 11);
    3987           0 :           goto EmitOp_Rd0_Rn5;
    3988             :         }
    3989             :       }
    3990             : 
    3991             :       break;
    3992             :     }
    3993             : 
    3994           0 :     case InstDB::kEncodingSimdMov: {
    3995           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    3996           0 :         if (o0.as<Reg>().isVec() && o1.as<Reg>().isVec()) {
    3997             :           // INS v.x[index], v.x[index].
    3998           0 :           if (o0.as<Vec>().hasElementIndex() && o1.as<Vec>().hasElementIndex())
    3999           0 :             goto SimdIns;
    4000             : 
    4001             :           // DUP {b|h|s|d}, v.{b|h|s|d}[index].
    4002           0 :           if (o1.as<Vec>().hasElementIndex())
    4003           0 :             goto SimdDup;
    4004             : 
    4005           0 :           if (!checkSignature(o0, o1))
    4006           0 :             goto InvalidInstruction;
    4007             : 
    4008             :           // ORR Vd, Vn, Vm
    4009             :           uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
    4010           0 :           if (q > 1)
    4011           0 :             goto InvalidInstruction;
    4012             : 
    4013             :           opcode.reset(0b0000111010100000000111 << 10);
    4014             :           opcode.addImm(q, 30);
    4015             :           opcode.addReg(o1, 16); // Vn == Vm.
    4016           0 :           goto EmitOp_Rd0_Rn5;
    4017             :         }
    4018             : 
    4019           0 :         if (o0.as<Reg>().isVec() && o1.as<Reg>().isGp()) {
    4020             :           // INS v.x[index], Rn.
    4021           0 :           if (o0.as<Vec>().hasElementIndex())
    4022           0 :             goto SimdIns;
    4023             : 
    4024           0 :           goto InvalidInstruction;
    4025             :         }
    4026             : 
    4027           0 :         if (o0.as<Reg>().isGp() && o1.as<Reg>().isVec()) {
    4028             :           // UMOV Rd, V.{s|d}[index].
    4029             :           encodingIndex = 1;
    4030           0 :           goto SimdUmov;
    4031             :         }
    4032             :       }
    4033             : 
    4034             :       break;
    4035             :     }
    4036             : 
    4037           0 :     case InstDB::kEncodingSimdMoviMvni: {
    4038             :       const InstDB::EncodingData::SimdMoviMvni& opData = InstDB::EncodingData::simdMoviMvni[encodingIndex];
    4039             : 
    4040           0 :       if (isign4 == ENC_OPS2(Reg, Imm) || isign4 == ENC_OPS3(Reg, Imm, Imm)) {
    4041           0 :         SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_Any, o0.as<Reg>().type(), o0.as<Vec>().elementType());
    4042           0 :         if (!sizeOp.isValid())
    4043           0 :           goto InvalidInstruction;
    4044             : 
    4045             :         uint64_t imm64 = o1.as<Imm>().valueAs<uint64_t>();
    4046             :         uint32_t imm8 = 0;
    4047             :         uint32_t cmode = 0;
    4048           0 :         uint32_t inverted = opData.inverted;
    4049             :         uint32_t op = 0;
    4050             :         uint32_t shift = 0;
    4051             :         uint32_t shiftOp = uint32_t(ShiftOp::kLSL);
    4052             : 
    4053           0 :         if (sizeOp.size() == 3u) {
    4054             :           // The second immediate should not be present, however, we accept
    4055             :           // an immediate value of zero as some user code may still pass it.
    4056           0 :           if (o2.isImm() && o0.as<Imm>().value() != 0)
    4057           0 :             goto InvalidImmediate;
    4058             : 
    4059           0 :           if (Utils::isByteMaskImm8(imm64)) {
    4060           0 :             imm8 = encodeImm64ByteMaskToImm8(imm64);
    4061             :           }
    4062             :           else {
    4063             :             // Change from D to S and from 64-bit imm to 32-bit imm if this
    4064             :             // is not a byte-mask pattern.
    4065           0 :             if ((imm64 >> 32) == (imm64 & 0xFFFFFFFFu)) {
    4066             :               imm64 &= 0xFFFFFFFFu;
    4067             :               sizeOp.decrementSize();
    4068             :             }
    4069             :             else {
    4070           0 :               goto InvalidImmediate;
    4071             :             }
    4072             :           }
    4073             :         }
    4074             : 
    4075           0 :         if (sizeOp.size() < 3u) {
    4076           0 :           if (imm64 > 0xFFFFFFFFu)
    4077           0 :             goto InvalidImmediate;
    4078           0 :           imm8 = uint32_t(imm64);
    4079             : 
    4080           0 :           if (sizeOp.size() == 2) {
    4081           0 :             if ((imm8 >> 16) == (imm8 & 0xFFFFu)) {
    4082             :               imm8 >>= 16;
    4083             :               sizeOp.decrementSize();
    4084             :             }
    4085             :           }
    4086             : 
    4087           0 :           if (sizeOp.size() == 1) {
    4088           0 :             if (imm8 > 0xFFFFu)
    4089           0 :               goto InvalidImmediate;
    4090             : 
    4091           0 :             if ((imm8 >> 8) == (imm8 & 0xFFu)) {
    4092             :               imm8 >>= 8;
    4093             :               sizeOp.decrementSize();
    4094             :             }
    4095             :           }
    4096             : 
    4097           0 :           uint32_t maxShift = (8u << sizeOp.size()) - 8u;
    4098           0 :           if (o2.isImm()) {
    4099           0 :             if (imm8 > 0xFFu || o2.as<Imm>().valueAs<uint64_t>() > maxShift)
    4100           0 :               goto InvalidImmediate;
    4101             : 
    4102             :             shift = o2.as<Imm>().valueAs<uint32_t>();
    4103             :             shiftOp = o2.as<Imm>().predicate();
    4104             :           }
    4105           0 :           else if (imm8) {
    4106           0 :             shift = Support::ctz(imm8) & ~0x7u;
    4107           0 :             imm8 >>= shift;
    4108             : 
    4109           0 :             if (imm8 > 0xFFu || shift > maxShift)
    4110           0 :               goto InvalidImmediate;
    4111             :           }
    4112             : 
    4113           0 :           if ((shift & 0x7u) != 0u)
    4114           0 :             goto InvalidImmediate;
    4115             :         }
    4116             : 
    4117           0 :         shift /= 8u;
    4118             : 
    4119           0 :         switch (sizeOp.size()) {
    4120           0 :           case 0:
    4121           0 :             if (shiftOp != uint32_t(ShiftOp::kLSL))
    4122           0 :               goto InvalidImmediate;
    4123             : 
    4124           0 :             if (inverted) {
    4125           0 :               imm8 = ~imm8 & 0xFFu;
    4126             :               inverted = 0;
    4127             :             }
    4128             : 
    4129             :             cmode = B(3) | B(2) | B(1);
    4130             :             break;
    4131             : 
    4132           0 :           case 1:
    4133           0 :             if (shiftOp != uint32_t(ShiftOp::kLSL))
    4134           0 :               goto InvalidImmediate;
    4135             : 
    4136           0 :             cmode = B(3) | (shift << 1);
    4137             :             op = inverted;
    4138           0 :             break;
    4139             : 
    4140           0 :           case 2:
    4141           0 :             if (shiftOp == uint32_t(ShiftOp::kLSL)) {
    4142           0 :               cmode = shift << 1;
    4143             :             }
    4144           0 :             else if (shiftOp == uint32_t(ShiftOp::kMSL)) {
    4145           0 :               if (shift == 0 || shift > 2)
    4146           0 :                 goto InvalidImmediate;
    4147           0 :               cmode = B(3) | B(2) | (shift - 1u);
    4148             :             }
    4149             :             else {
    4150           0 :               goto InvalidImmediate;
    4151             :             }
    4152             : 
    4153             :             op = inverted;
    4154             :             break;
    4155             : 
    4156           0 :           case 3:
    4157           0 :             if (inverted) {
    4158           0 :               imm8 = ~imm8 & 0xFFu;
    4159             :               inverted = 0;
    4160             :             }
    4161             : 
    4162             :             op = 1;
    4163             :             cmode = B(3) | B(2) | B(1);
    4164             :             break;
    4165             :         }
    4166             : 
    4167             :         // The immediate value is split into ABC and DEFGH parts.
    4168           0 :         uint32_t abc = (imm8 >> 5) & 0x7u;
    4169             :         uint32_t defgh = imm8 & 0x1Fu;
    4170             : 
    4171           0 :         opcode.reset(uint32_t(opData.opcode) << 10);
    4172             :         opcode.addImm(sizeOp.q(), 30);
    4173             :         opcode.addImm(op, 29);
    4174             :         opcode.addImm(abc, 16);
    4175             :         opcode.addImm(cmode, 12);
    4176             :         opcode.addImm(defgh, 5);
    4177           0 :         goto EmitOp_Rd0;
    4178             :       }
    4179             : 
    4180             :       break;
    4181             :     }
    4182             : 
    4183           0 :     case InstDB::kEncodingSimdShift: {
    4184             :       const InstDB::EncodingData::SimdShift& opData = InstDB::EncodingData::simdShift[encodingIndex];
    4185             : 
    4186           0 :       const Operand_& sop = significantSimdOp(o0, o1, instFlags);
    4187           0 :       SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType());
    4188             : 
    4189           0 :       if (!sizeOp.isValid())
    4190           0 :         goto InvalidInstruction;
    4191             : 
    4192           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp) {
    4193           0 :         if (!matchSignature(o0, o1, instFlags))
    4194           0 :           goto InvalidInstruction;
    4195             : 
    4196           0 :         if (o2.as<Imm>().valueAs<uint64_t>() > 63)
    4197           0 :           goto InvalidImmediate;
    4198             : 
    4199           0 :         uint32_t lsbShift = sizeOp.size() + 3u;
    4200           0 :         uint32_t lsbMask = (1u << lsbShift) - 1u;
    4201             :         uint32_t imm = o2.as<Imm>().valueAs<uint32_t>();
    4202             : 
    4203             :         // Some instructions use IMM and some X - IMM, so negate if required.
    4204           0 :         if (opData.invertedImm) {
    4205           0 :           if (imm == 0 || imm > (1u << lsbShift))
    4206           0 :             goto InvalidImmediate;
    4207           0 :           imm = Support::neg(imm) & lsbMask;
    4208             :         }
    4209             : 
    4210           0 :         if (imm > lsbMask)
    4211           0 :           goto InvalidImmediate;
    4212           0 :         imm |= (1u << lsbShift);
    4213             : 
    4214           0 :         opcode.reset(uint32_t(opData.immediateOp) << 10);
    4215             :         opcode.addImm(sizeOp.qs(), 30);
    4216             :         opcode.addImm(sizeOp.scalar(), 28);
    4217             :         opcode.addImm(imm, 16);
    4218           0 :         goto EmitOp_Rd0_Rn5;
    4219             :       }
    4220             : 
    4221           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.registerOp) {
    4222             :         if (!matchSignature(o0, o1, o2, instFlags))
    4223           0 :           goto InvalidInstruction;
    4224             : 
    4225           0 :         opcode.reset(uint32_t(opData.registerOp) << 10);
    4226             :         opcode.addImm(sizeOp.qs(), 30);
    4227             :         opcode.addImm(sizeOp.scalar(), 28);
    4228             :         opcode.addImm(sizeOp.size(), 22);
    4229           0 :         goto EmitOp_Rd0_Rn5_Rm16;
    4230             :       }
    4231             : 
    4232             :       break;
    4233             :     }
    4234             : 
    4235           0 :     case InstDB::kEncodingSimdShiftES: {
    4236             :       const InstDB::EncodingData::SimdShiftES& opData = InstDB::EncodingData::simdShiftES[encodingIndex];
    4237             : 
    4238           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Imm)) {
    4239           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType());
    4240           0 :         if (!sizeOp.isValid())
    4241           0 :           goto InvalidInstruction;
    4242             : 
    4243           0 :         if (!matchSignature(o0, o1, instFlags))
    4244           0 :           goto InvalidInstruction;
    4245             : 
    4246             :         // The immediate value must match the element size.
    4247             :         uint64_t shift = o2.as<Imm>().valueAs<uint64_t>();
    4248             :         uint32_t shiftOp = o2.as<Imm>().predicate();
    4249             : 
    4250           0 :         if (shift != (8u << sizeOp.size()) || shiftOp != uint32_t(ShiftOp::kLSL))
    4251           0 :           goto InvalidImmediate;
    4252             : 
    4253           0 :         opcode.reset(uint32_t(opData.opcode) << 10);
    4254             :         opcode.addImm(sizeOp.q(), 30);
    4255             :         opcode.addImm(sizeOp.size(), 22);
    4256           0 :         goto EmitOp_Rd0_Rn5;
    4257             :       }
    4258             : 
    4259             :       break;
    4260             :     }
    4261             : 
    4262           0 :     case InstDB::kEncodingSimdSm3tt: {
    4263             :       const InstDB::EncodingData::SimdSm3tt& opData = InstDB::EncodingData::simdSm3tt[encodingIndex];
    4264             : 
    4265           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg)) {
    4266           0 :         if (o0.as<Vec>().isVecS4() && o1.as<Vec>().isVecS4() && o2.as<Vec>().isVecS4() && o2.as<Vec>().hasElementIndex()) {
    4267             :           uint32_t imm2 = o2.as<Vec>().elementIndex();
    4268           0 :           if (imm2 > 3)
    4269           0 :             goto InvalidElementIndex;
    4270             : 
    4271           0 :           opcode.reset(uint32_t(opData.opcode) << 10);
    4272             :           opcode.addImm(imm2, 12);
    4273           0 :           goto EmitOp_Rd0_Rn5_Rm16;
    4274             :         }
    4275             :       }
    4276             : 
    4277             :       break;
    4278             :     }
    4279             : 
    4280             : 
    4281           0 :     case InstDB::kEncodingSimdSmovUmov: SimdUmov: {
    4282             :       const InstDB::EncodingData::SimdSmovUmov& opData = InstDB::EncodingData::simdSmovUmov[encodingIndex];
    4283             : 
    4284           0 :       if (isign4 == ENC_OPS2(Reg, Reg) && o0.as<Reg>().isGp() && o1.as<Reg>().isVec()) {
    4285           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType());
    4286           0 :         if (!sizeOp.isValid())
    4287           0 :           goto InvalidInstruction;
    4288             : 
    4289           0 :         if (!o1.as<Vec>().hasElementIndex())
    4290           0 :           goto InvalidInstruction;
    4291             : 
    4292           0 :         uint32_t x = o0.as<Gp>().isGpX();
    4293           0 :         uint32_t gpMustBeX = uint32_t(sizeOp.size() >= 3u - opData.isSigned);
    4294             : 
    4295           0 :         if (opData.isSigned) {
    4296           0 :           if (gpMustBeX && !x)
    4297           0 :             goto InvalidInstruction;
    4298             :         }
    4299             :         else {
    4300           0 :           if (x != gpMustBeX)
    4301           0 :             goto InvalidInstruction;
    4302             :         }
    4303             : 
    4304             :         uint32_t elementIndex = o1.as<Vec>().elementIndex();
    4305           0 :         uint32_t maxElementIndex = 15u >> sizeOp.size();
    4306             : 
    4307           0 :         if (elementIndex > maxElementIndex)
    4308           0 :           goto InvalidElementIndex;
    4309             : 
    4310           0 :         uint32_t imm5 = (1u | (elementIndex << 1)) << sizeOp.size();
    4311             : 
    4312           0 :         opcode.reset(uint32_t(opData.opcode) << 10);
    4313             :         opcode.addImm(x, 30);
    4314             :         opcode.addImm(imm5, 16);
    4315           0 :         goto EmitOp_Rd0_Rn5;
    4316             :       }
    4317             : 
    4318             :       break;
    4319             :     }
    4320             : 
    4321           0 :     case InstDB::kEncodingSimdSxtlUxtl: {
    4322             :       const InstDB::EncodingData::SimdSxtlUxtl& opData = InstDB::EncodingData::simdSxtlUxtl[encodingIndex];
    4323             : 
    4324           0 :       if (isign4 == ENC_OPS2(Reg, Reg)) {
    4325           0 :         SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType());
    4326           0 :         if (!sizeOp.isValid())
    4327           0 :           goto InvalidInstruction;
    4328             : 
    4329           0 :         if (!matchSignature(o0, o1, instFlags))
    4330           0 :           goto InvalidInstruction;
    4331             : 
    4332           0 :         opcode.reset(uint32_t(opData.opcode) << 10);
    4333             :         opcode.addImm(sizeOp.q(), 30);
    4334           0 :         opcode.addImm(1u, sizeOp.size() + 19);
    4335           0 :         goto EmitOp_Rd0_Rn5;
    4336             :       }
    4337             : 
    4338             :       break;
    4339             :     }
    4340             : 
    4341           0 :     case InstDB::kEncodingSimdTblTbx: {
    4342             :       const InstDB::EncodingData::SimdTblTbx& opData = InstDB::EncodingData::simdTblTbx[encodingIndex];
    4343             : 
    4344           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
    4345             :         // TBL/TBX <Vd>.<Ta>, { <Vn>.16B }, <Vm>.<Ta>
    4346             :         // TBL/TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B }, <Vm>.<Ta>
    4347             :         // TBL/TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta>
    4348             :         // TBL/TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B, <Vn+3>.16B }, <Vm>.<Ta>
    4349           0 :         opcode.reset(uint32_t(opData.opcode) << 10);
    4350             : 
    4351             :         const Operand_& o4 = opExt[EmitterUtils::kOp4];
    4352             :         const Operand_& o5 = opExt[EmitterUtils::kOp5];
    4353             : 
    4354             :         uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD);
    4355           0 :         if (q > 1 || o0.as<Vec>().hasElementIndex())
    4356           0 :           goto InvalidInstruction;
    4357             : 
    4358           0 :         if (!o1.as<Vec>().isVecB16() || o1.as<Vec>().hasElementIndex())
    4359           0 :           goto InvalidInstruction;
    4360             : 
    4361           0 :         uint32_t len = uint32_t(!o3.isNone()) + uint32_t(!o4.isNone()) + uint32_t(!o5.isNone());
    4362             :         opcode.addImm(q, 30);
    4363             :         opcode.addImm(len, 13);
    4364             : 
    4365           0 :         switch (len) {
    4366             :           case 0:
    4367           0 :             if (!checkSignature(o0, o2))
    4368           0 :               goto InvalidInstruction;
    4369             : 
    4370           0 :             if (o2.id() > 31)
    4371           0 :               goto InvalidPhysId;
    4372             : 
    4373             :             opcode.addReg(o2, 16);
    4374           0 :             goto EmitOp_Rd0_Rn5;
    4375             : 
    4376             :           case 1:
    4377           0 :             if (!checkSignature(o0, o3))
    4378           0 :               goto InvalidInstruction;
    4379             : 
    4380           0 :             if (o3.id() > 31)
    4381           0 :               goto InvalidPhysId;
    4382             : 
    4383             :             opcode.addReg(o3, 16);
    4384           0 :             goto EmitOp_Rd0_Rn5;
    4385             : 
    4386             :           case 2:
    4387           0 :             if (!checkSignature(o0, o4))
    4388           0 :               goto InvalidInstruction;
    4389             : 
    4390           0 :             if (o4.id() > 31)
    4391           0 :               goto InvalidPhysId;
    4392             : 
    4393             :             opcode.addReg(o4, 16);
    4394           0 :             goto EmitOp_Rd0_Rn5;
    4395             : 
    4396             :           case 3:
    4397           0 :             if (!checkSignature(o0, o5))
    4398           0 :               goto InvalidInstruction;
    4399             : 
    4400           0 :             if (o5.id() > 31)
    4401           0 :               goto InvalidPhysId;
    4402             : 
    4403             :             opcode.addReg(o5, 16);
    4404           0 :             goto EmitOp_Rd0_Rn5;
    4405             : 
    4406           0 :           default:
    4407             :             // Should never happen.
    4408           0 :             goto InvalidInstruction;
    4409             :         }
    4410             :       }
    4411             : 
    4412             :       break;
    4413             :     }
    4414             : 
    4415             :     // ------------------------------------------------------------------------
    4416             :     // [Simd - Load / Store]
    4417             :     // ------------------------------------------------------------------------
    4418             : 
    4419           0 :     case InstDB::kEncodingSimdLdSt: {
    4420             :       const InstDB::EncodingData::SimdLdSt& opData = InstDB::EncodingData::simdLdSt[encodingIndex];
    4421             : 
    4422           0 :       if (isign4 == ENC_OPS2(Reg, Mem)) {
    4423             :         const Mem& m = o1.as<Mem>();
    4424           0 :         rmRel = &m;
    4425             : 
    4426             :         // Width  |       SZ |        XY | XSZ
    4427             :         // -------+----------+-----------+-----
    4428             :         // 8-bit  | size==00 | opc == 01 | 000
    4429             :         // 16-bit | size==01 | opc == 01 | 001
    4430             :         // 32-bit | size==10 | opc == 01 | 010
    4431             :         // 64-bit | size==11 | opc == 01 | 011
    4432             :         // 128-bit| size==00 | opc == 11 | 100
    4433             :         uint32_t xsz = diff(o0.as<Reg>().type(), RegType::kARM_VecB);
    4434           0 :         if (xsz > 4u || o0.as<Vec>().hasElementIndex())
    4435           0 :           goto InvalidRegType;
    4436             : 
    4437           0 :         if (!checkVecId(o0))
    4438           0 :           goto InvalidPhysId;
    4439             : 
    4440           0 :         if (!armCheckMemBaseIndexRel(m))
    4441           0 :           goto InvalidAddress;
    4442             : 
    4443             :         int64_t offset = m.offset();
    4444           0 :         if (m.hasBaseReg()) {
    4445             :           // [Base {Offset | Index}]
    4446           0 :           if (m.hasIndex()) {
    4447           0 :             uint32_t opt = armShiftOpToLdStOptMap[m.predicate()];
    4448           0 :             if (opt == 0xFFu)
    4449           0 :               goto InvalidAddress;
    4450             : 
    4451             :             uint32_t shift = m.shift();
    4452           0 :             uint32_t s = (shift != 0);
    4453             : 
    4454           0 :             if (s && shift != xsz)
    4455           0 :               goto InvalidAddressScale;
    4456             : 
    4457           0 :             opcode.reset(uint32_t(opData.registerOp) << 21);
    4458             :             opcode.addImm(xsz & 3u, 30);
    4459           0 :             opcode.addImm(xsz >> 2, 23);
    4460             :             opcode.addImm(opt, 13);
    4461             :             opcode.addImm(s, 12);
    4462             :             opcode |= B(11);
    4463             :             opcode.addReg(o0, 0);
    4464           0 :             goto EmitOp_MemBaseIndex_Rn5_Rm16;
    4465             :           }
    4466             : 
    4467             :           // Makes it easier to work with the offset especially on 32-bit arch.
    4468             :           if (!Support::isInt32(offset))
    4469           0 :             goto InvalidDisplacement;
    4470           0 :           int32_t offset32 = int32_t(offset);
    4471             : 
    4472           0 :           if (m.isPreOrPost()) {
    4473             :             if (!Support::isInt9(offset32))
    4474           0 :               goto InvalidDisplacement;
    4475             : 
    4476           0 :             opcode.reset(uint32_t(opData.prePostOp) << 21);
    4477             :             opcode.addImm(xsz & 3u, 30);
    4478           0 :             opcode.addImm(xsz >> 2, 23);
    4479             :             opcode.addImm(offset32 & 0x1FF, 12);
    4480             :             opcode.addImm(m.isPreIndex(), 11);
    4481             :             opcode |= B(10);
    4482             :             opcode.addReg(o0, 0);
    4483           0 :             goto EmitOp_MemBase_Rn5;
    4484             :           }
    4485             :           else {
    4486           0 :             uint32_t imm12 = uint32_t(offset32) >> xsz;
    4487             : 
    4488             :             // If this instruction is not encodable with scaled unsigned offset, try unscaled signed offset.
    4489           0 :             if (!Support::isUInt12(imm12) || (imm12 << xsz) != uint32_t(offset32)) {
    4490           0 :               instId = opData.uAltInstId;
    4491             :               instInfo = &InstDB::_instInfoTable[instId];
    4492           0 :               encodingIndex = instInfo->_encodingDataIndex;
    4493           0 :               goto Case_SimdLdurStur;
    4494             :             }
    4495             : 
    4496           0 :             opcode.reset(uint32_t(opData.uOffsetOp) << 22);
    4497             :             opcode.addImm(xsz & 3u, 30);
    4498           0 :             opcode.addImm(xsz >> 2, 23);
    4499             :             opcode.addImm(imm12, 10);
    4500             :             opcode.addReg(o0, 0);
    4501           0 :             goto EmitOp_MemBase_Rn5;
    4502             :           }
    4503             :         }
    4504             :         else {
    4505           0 :           if (!opData.literalOp)
    4506           0 :             goto InvalidAddress;
    4507             : 
    4508           0 :           if (xsz < 2u)
    4509           0 :             goto InvalidRegType;
    4510             : 
    4511           0 :           uint32_t opc = xsz - 2u;
    4512           0 :           opcode.reset(uint32_t(opData.literalOp) << 24);
    4513             :           opcode.addImm(opc, 30);
    4514             :           opcode.addReg(o0, 0);
    4515             :           offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2);
    4516           0 :           goto EmitOp_Rel;
    4517             :         }
    4518             :       }
    4519             : 
    4520             :       break;
    4521             :     }
    4522             : 
    4523           0 :     case InstDB::kEncodingSimdLdpStp: {
    4524             :       const InstDB::EncodingData::SimdLdpStp& opData = InstDB::EncodingData::simdLdpStp[encodingIndex];
    4525             : 
    4526           0 :       if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
    4527             :         const Mem& m = o2.as<Mem>();
    4528           0 :         rmRel = &m;
    4529             : 
    4530             :         uint32_t opc = diff(o0.as<Reg>().type(), RegType::kARM_VecS);
    4531           0 :         if (opc > 2u || o0.as<Vec>().hasElementTypeOrIndex())
    4532           0 :           goto InvalidInstruction;
    4533             : 
    4534           0 :         if (!checkSignature(o0, o1))
    4535           0 :           goto InvalidInstruction;
    4536             : 
    4537           0 :         if (!checkVecId(o0, o1))
    4538           0 :           goto InvalidPhysId;
    4539             : 
    4540           0 :         if (m.baseType() != RegType::kARM_GpX || m.hasIndex())
    4541           0 :           goto InvalidAddress;
    4542             : 
    4543           0 :         if (m.isOffset64Bit())
    4544           0 :           goto InvalidDisplacement;
    4545             : 
    4546           0 :         uint32_t offsetShift = 2u + opc;
    4547           0 :         int32_t offset32 = m.offsetLo32() >> offsetShift;
    4548             : 
    4549             :         // Make sure we didn't lose bits by applying the mandatory offset shift.
    4550           0 :         if (Support::shl(offset32, offsetShift) != m.offsetLo32())
    4551           0 :           goto InvalidDisplacement;
    4552             : 
    4553             :         // Offset is encoded as a 7-bit immediate.
    4554             :         if (!Support::isInt7(offset32))
    4555           0 :           goto InvalidDisplacement;
    4556             : 
    4557           0 :         if (m.isPreOrPost() && offset32 != 0) {
    4558           0 :           if (!opData.prePostOp)
    4559           0 :             goto InvalidAddress;
    4560             : 
    4561           0 :           opcode.reset(uint32_t(opData.prePostOp) << 22);
    4562             :           opcode.addImm(m.isPreIndex(), 24);
    4563             :         }
    4564             :         else {
    4565           0 :           opcode.reset(uint32_t(opData.offsetOp) << 22);
    4566             :         }
    4567             : 
    4568             :         opcode.addImm(opc, 30);
    4569             :         opcode.addImm(offset32 & 0x7F, 15);
    4570             :         opcode.addReg(o1, 10);
    4571             :         opcode.addReg(o0, 0);
    4572           0 :         goto EmitOp_MemBase_Rn5;
    4573             :       }
    4574             : 
    4575             :       break;
    4576             :     }
    4577             : 
    4578             :     case InstDB::kEncodingSimdLdurStur: {
    4579           0 : Case_SimdLdurStur:
    4580             :       const InstDB::EncodingData::SimdLdurStur& opData = InstDB::EncodingData::simdLdurStur[encodingIndex];
    4581             : 
    4582           0 :       if (isign4 == ENC_OPS2(Reg, Mem)) {
    4583             :         const Mem& m = o1.as<Mem>();
    4584           0 :         rmRel = &m;
    4585             : 
    4586             :         uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecB);
    4587           0 :         if (sz > 4 || o0.as<Vec>().hasElementTypeOrIndex())
    4588           0 :           goto InvalidInstruction;
    4589             : 
    4590           0 :         if (!checkVecId(o0))
    4591           0 :           goto InvalidPhysId;
    4592             : 
    4593           0 :         if (!armCheckMemBaseIndexRel(m))
    4594           0 :           goto InvalidAddress;
    4595             : 
    4596           0 :         if (m.hasBaseReg() && !m.hasIndex() && !m.isPreOrPost()) {
    4597           0 :           if (m.isOffset64Bit())
    4598           0 :             goto InvalidDisplacement;
    4599             : 
    4600             :           int32_t offset32 = m.offsetLo32();
    4601             :           if (!Support::isInt9(offset32))
    4602           0 :             goto InvalidDisplacement;
    4603             : 
    4604           0 :           opcode.reset(uint32_t(opData.opcode) << 10);
    4605             :           opcode.addImm(sz & 3u, 30);
    4606           0 :           opcode.addImm(sz >> 2, 23);
    4607             :           opcode.addImm(offset32 & 0x1FF, 12);
    4608             :           opcode.addReg(o0, 0);
    4609           0 :           goto EmitOp_MemBase_Rn5;
    4610             :         }
    4611             : 
    4612           0 :         goto InvalidAddress;
    4613             :       }
    4614             : 
    4615             :       break;
    4616             :     }
    4617             : 
    4618           0 :     case InstDB::kEncodingSimdLdNStN: {
    4619             :       const InstDB::EncodingData::SimdLdNStN& opData = InstDB::EncodingData::simdLdNStN[encodingIndex];
    4620           0 :       const Operand_& o4 = opExt[EmitterUtils::kOp4];
    4621             : 
    4622             :       uint32_t n = 1;
    4623             : 
    4624           0 :       if (isign4 == ENC_OPS2(Reg, Mem)) {
    4625           0 :         if (opData.n != 1)
    4626           0 :           goto InvalidInstruction;
    4627             : 
    4628             :         rmRel = &o1;
    4629             :       }
    4630           0 :       else if (isign4 == ENC_OPS3(Reg, Reg, Mem)) {
    4631           0 :         if (opData.n != 1 && opData.n != 2)
    4632           0 :           goto InvalidInstruction;
    4633             : 
    4634           0 :         if (!checkSignature(o0, o1) || !checkConsecutive(o0, o1))
    4635           0 :           goto InvalidInstruction;
    4636             : 
    4637             :         n = 2;
    4638             :         rmRel = &o2;
    4639             :       }
    4640           0 :       else if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem) && o4.isNone()) {
    4641           0 :         if (opData.n != 1 && opData.n != 3)
    4642           0 :           goto InvalidInstruction;
    4643             : 
    4644             :         if (!checkSignature(o0, o1, o2) || !checkConsecutive(o0, o1, o2))
    4645           0 :           goto InvalidInstruction;
    4646             : 
    4647             :         n = 3;
    4648             :         rmRel = &o3;
    4649             :       }
    4650           0 :       else if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg) && o4.isMem()) {
    4651           0 :         if (opData.n != 1 && opData.n != 4)
    4652           0 :           goto InvalidInstruction;
    4653             : 
    4654           0 :         if (!checkSignature(o0, o1, o2, o3) || !checkConsecutive(o0, o1, o2, o3))
    4655           0 :           goto InvalidInstruction;
    4656             : 
    4657             :         n = 4;
    4658             :         rmRel = &o4;
    4659             :       }
    4660             :       else {
    4661           0 :         goto InvalidInstruction;
    4662             :       }
    4663             : 
    4664             :       // We will use `v` and `m` from now as those are relevant for encoding.
    4665             :       const Vec& v = o0.as<Vec>();
    4666             :       const Mem& m = rmRel->as<Mem>();
    4667             : 
    4668             :       uint32_t q = 0;
    4669             :       uint32_t rm = 0;
    4670             :       uint32_t rn = m.baseId();
    4671           0 :       uint32_t sz = v.elementType() - Vec::kElementTypeB;
    4672             :       uint32_t opcSsize = sz;
    4673             :       uint32_t offsetPossibility = 0;
    4674             : 
    4675           0 :       if (sz > 3)
    4676           0 :         goto InvalidInstruction;
    4677             : 
    4678           0 :       if (m.baseType() != RegType::kARM_GpX)
    4679           0 :         goto InvalidAddress;
    4680             : 
    4681             :       // Rn cannot be ZR, but can be SP.
    4682           0 :       if (rn > 30 && rn != Gp::kIdSp)
    4683           0 :         goto InvalidAddress;
    4684             : 
    4685             :       rn &= 31;
    4686             : 
    4687           0 :       if (opData.replicate) {
    4688           0 :         if (n != opData.n)
    4689           0 :           goto InvalidInstruction;
    4690             : 
    4691             :         // Replicates to the whole register, element index cannot be used.
    4692           0 :         if (v.hasElementIndex())
    4693           0 :           goto InvalidInstruction;
    4694             : 
    4695             :         q = diff(v.type(), RegType::kARM_VecD);
    4696           0 :         if (q > 1)
    4697           0 :           goto InvalidInstruction;
    4698             : 
    4699           0 :         opcode.reset(uint32_t(opData.singleOp) << 10);
    4700           0 :         offsetPossibility = (1u << sz) * n;
    4701             :       }
    4702           0 :       else if (v.hasElementIndex()) {
    4703           0 :         if (n != opData.n)
    4704           0 :           goto InvalidInstruction;
    4705             : 
    4706             :         // LDx/STx (single structure).
    4707             :         static const uint8_t opcSsizeBySzS[] = { 0x0u << 3, 0x2u << 3, 0x4u << 3, (0x4u << 3) | 1u };
    4708             : 
    4709           0 :         opcode.reset(uint32_t(opData.singleOp) << 10);
    4710           0 :         opcSsize = opcSsizeBySzS[sz];
    4711           0 :         offsetPossibility =  (1u << sz) * opData.n;
    4712             : 
    4713             :         uint32_t elementIndex = v.elementIndex();
    4714           0 :         uint32_t maxElementIndex = 15 >> sz;
    4715             : 
    4716           0 :         if (elementIndex > maxElementIndex)
    4717           0 :           goto InvalidElementIndex;
    4718             : 
    4719           0 :         elementIndex <<= sz;
    4720           0 :         q = elementIndex >> 3;
    4721           0 :         opcSsize |= elementIndex & 0x7u;
    4722             :       }
    4723             :       else {
    4724             :         // LDx/STx (multiple structures).
    4725             :         static const uint8_t opcSsizeByN[] = { 0u, 0x7u << 2, 0xAu << 2, 0x6u << 2, 0x2u << 2 };
    4726             : 
    4727             :         q = diff(v.type(), RegType::kARM_VecD);
    4728           0 :         if (q > 1)
    4729           0 :           goto InvalidInstruction;
    4730             : 
    4731           0 :         if (opData.n == 1)
    4732           0 :           opcSsize |= opcSsizeByN[n];
    4733             : 
    4734           0 :         opcode.reset(uint32_t(opData.multipleOp) << 10);
    4735           0 :         offsetPossibility = (8u << q) * n;
    4736             :       }
    4737             : 
    4738           0 :       if (m.hasIndex()) {
    4739           0 :         if (m.hasOffset() || !m.isPostIndex())
    4740           0 :           goto InvalidAddress;
    4741             : 
    4742             :         rm = m.indexId();
    4743           0 :         if (rm > 30)
    4744           0 :           goto InvalidAddress;
    4745             : 
    4746             :         // Bit 23 - PostIndex.
    4747             :         opcode |= B(23);
    4748             :       }
    4749             :       else {
    4750           0 :         if (m.hasOffset()) {
    4751           0 :           if (m.offset() != int32_t(offsetPossibility) || !m.isPostIndex())
    4752           0 :             goto InvalidAddress;
    4753             :           rm = 31;
    4754             : 
    4755             :           // Bit 23 - PostIndex.
    4756             :           opcode |= B(23);
    4757             :         }
    4758             :       }
    4759             : 
    4760             :       opcode.addImm(q, 30);
    4761             :       opcode.addImm(rm, 16);
    4762             :       opcode.addImm(opcSsize, 10);
    4763             :       opcode.addImm(rn, 5);
    4764           0 :       goto EmitOp_Rd0;
    4765             :     }
    4766             : 
    4767             :     default:
    4768             :       break;
    4769             :   }
    4770             : 
    4771           0 :   goto InvalidInstruction;
    4772             : 
    4773             :   // --------------------------------------------------------------------------
    4774             :   // [EmitGp - Single]
    4775             :   // --------------------------------------------------------------------------
    4776             : 
    4777           0 : EmitOp_Rd0:
    4778           0 :   if (!checkValidRegs(o0))
    4779           0 :     goto InvalidPhysId;
    4780             : 
    4781             :   opcode.addReg(o0, 0);
    4782           0 :   goto EmitOp;
    4783             : 
    4784             : EmitOp_Rn5:
    4785           0 :   if (!checkValidRegs(o0))
    4786           0 :     goto InvalidPhysId;
    4787             : 
    4788             :   opcode.addReg(o0, 5);
    4789           0 :   goto EmitOp;
    4790             : 
    4791           0 : EmitOp_Rn5_Rm16:
    4792           0 :   if (!checkValidRegs(o0, o1))
    4793           0 :     goto InvalidPhysId;
    4794             : 
    4795             :   opcode.addReg(o0, 5);
    4796             :   opcode.addReg(o1, 16);
    4797           0 :   goto EmitOp;
    4798             : 
    4799           0 : EmitOp_Rd0_Rn5:
    4800           0 :   if (!checkValidRegs(o0, o1))
    4801           0 :     goto InvalidPhysId;
    4802             : 
    4803             :   opcode.addReg(o0, 0);
    4804             :   opcode.addReg(o1, 5);
    4805           0 :   goto EmitOp;
    4806             : 
    4807           0 : EmitOp_Rd0_Rn5_Rm16_Ra10:
    4808           0 :   if (!checkValidRegs(o0, o1, o2, o3))
    4809           0 :     goto InvalidPhysId;
    4810             : 
    4811             :   opcode.addReg(o0, 0);
    4812             :   opcode.addReg(o1, 5);
    4813             :   opcode.addReg(o2, 16);
    4814             :   opcode.addReg(o3, 10);
    4815           0 :   goto EmitOp;
    4816             : 
    4817           0 : EmitOp_Rd0_Rn5_Rm16:
    4818           0 :   if (!checkValidRegs(o0, o1, o3))
    4819           0 :     goto InvalidPhysId;
    4820             : 
    4821             :   opcode.addReg(o0, 0);
    4822             :   opcode.addReg(o1, 5);
    4823             :   opcode.addReg(o2, 16);
    4824           0 :   goto EmitOp;
    4825             : 
    4826             :   // --------------------------------------------------------------------------
    4827             :   // [EmitGp - Multiple]
    4828             :   // --------------------------------------------------------------------------
    4829             : 
    4830             : EmitOp_Multiple:
    4831             :   {
    4832             :     ASMJIT_ASSERT(multipleOpCount > 0);
    4833           0 :     err = writer.ensureSpace(this, multipleOpCount * 4u);
    4834           0 :     if (ASMJIT_UNLIKELY(err))
    4835           0 :       goto Failed;
    4836             : 
    4837           0 :     for (uint32_t i = 0; i < multipleOpCount; i++)
    4838           0 :       writer.emit32uLE(multipleOpData[i]);
    4839             : 
    4840           0 :     goto EmitDone;
    4841             :   }
    4842             : 
    4843             :   // --------------------------------------------------------------------------
    4844             :   // [EmitGp - Memory]
    4845             :   // --------------------------------------------------------------------------
    4846             : 
    4847           0 : EmitOp_MemBase_Rn5:
    4848             :   if (!checkMemBase(rmRel->as<Mem>()))
    4849           0 :     goto InvalidAddress;
    4850             : 
    4851             :   opcode.addReg(rmRel->as<Mem>().baseId(), 5);
    4852           0 :   goto EmitOp;
    4853             : 
    4854           0 : EmitOp_MemBaseNoImm_Rn5:
    4855           0 :   if (!checkMemBase(rmRel->as<Mem>()) || rmRel->as<Mem>().hasIndex())
    4856           0 :     goto InvalidAddress;
    4857             : 
    4858           0 :   if (rmRel->as<Mem>().hasOffset())
    4859           0 :     goto InvalidDisplacement;
    4860             : 
    4861             :   opcode.addReg(rmRel->as<Mem>().baseId(), 5);
    4862           0 :   goto EmitOp;
    4863             : 
    4864           0 : EmitOp_MemBaseIndex_Rn5_Rm16:
    4865           0 :   if (!rmRel->as<Mem>().hasBaseReg())
    4866           0 :     goto InvalidAddress;
    4867             : 
    4868           0 :   if (rmRel->as<Mem>().indexId() > 30 && rmRel->as<Mem>().indexId() != Gp::kIdZr)
    4869           0 :     goto InvalidPhysId;
    4870             : 
    4871             :   opcode.addReg(rmRel->as<Mem>().indexId(), 16);
    4872             :   opcode.addReg(rmRel->as<Mem>().baseId(), 5);
    4873           0 :   goto EmitOp;
    4874             : 
    4875             :   // --------------------------------------------------------------------------
    4876             :   // [EmitOp - PC Relative]
    4877             :   // --------------------------------------------------------------------------
    4878             : 
    4879           0 : EmitOp_Rel:
    4880             :   {
    4881           0 :     if (rmRel->isLabel() || rmRel->isMem()) {
    4882             :       uint32_t labelId;
    4883             :       int64_t labelOffset = 0;
    4884             : 
    4885           0 :       if (rmRel->isLabel()) {
    4886             :         labelId = rmRel->as<Label>().id();
    4887             :       }
    4888             :       else {
    4889             :         labelId = rmRel->as<Mem>().baseId();
    4890             :         labelOffset = rmRel->as<Mem>().offset();
    4891             :       }
    4892             : 
    4893           0 :       LabelEntry* label = _code->labelEntry(labelId);
    4894           0 :       if (ASMJIT_UNLIKELY(!label))
    4895           0 :         goto InvalidLabel;
    4896             : 
    4897             :       if (offsetFormat.type() == OffsetType::kAArch64_ADRP) {
    4898             :         // TODO: [ARM] Always create relocation entry.
    4899             :       }
    4900             : 
    4901           0 :       if (label->isBoundTo(_section)) {
    4902             :         // Label bound to the current section.
    4903           0 :         offsetValue = label->offset() - uint64_t(offset()) + uint64_t(labelOffset);
    4904           0 :         goto EmitOp_DispImm;
    4905             :       }
    4906             :       else {
    4907             :         // Record non-bound label.
    4908           0 :         size_t codeOffset = writer.offsetFrom(_bufferData);
    4909           0 :         LabelLink* link = _code->newLabelLink(label, _section->id(), codeOffset, intptr_t(labelOffset), offsetFormat);
    4910             : 
    4911           0 :         if (ASMJIT_UNLIKELY(!link))
    4912           0 :           goto OutOfMemory;
    4913             : 
    4914           0 :         goto EmitOp;
    4915             :       }
    4916             :     }
    4917             :   }
    4918             : 
    4919           0 :   if (rmRel->isImm()) {
    4920           0 :     uint64_t baseAddress = _code->baseAddress();
    4921             :     uint64_t targetOffset = rmRel->as<Imm>().valueAs<uint64_t>();
    4922             : 
    4923           0 :     size_t codeOffset = writer.offsetFrom(_bufferData);
    4924             : 
    4925           0 :     if (baseAddress == Globals::kNoBaseAddress || _section->id() != 0) {
    4926             :       // Create a new RelocEntry as we cannot calculate the offset right now.
    4927             :       RelocEntry* re;
    4928           0 :       err = _code->newRelocEntry(&re, RelocType::kAbsToRel);
    4929           0 :       if (err)
    4930           0 :         goto Failed;
    4931             : 
    4932           0 :       re->_sourceSectionId = _section->id();
    4933           0 :       re->_sourceOffset = codeOffset;
    4934           0 :       re->_format = offsetFormat;
    4935           0 :       re->_payload = rmRel->as<Imm>().valueAs<uint64_t>() + 4u;
    4936           0 :       goto EmitOp;
    4937             :     }
    4938             :     else {
    4939           0 :       uint64_t pc = baseAddress + codeOffset;
    4940             : 
    4941           0 :       if (offsetFormat.type() == OffsetType::kAArch64_ADRP)
    4942           0 :         pc &= ~uint64_t(4096 - 1);
    4943             : 
    4944           0 :       offsetValue = targetOffset - pc;
    4945           0 :       goto EmitOp_DispImm;
    4946             :     }
    4947             :   }
    4948             : 
    4949           0 :   goto InvalidInstruction;
    4950             : 
    4951           0 : EmitOp_DispImm:
    4952             :   {
    4953           0 :     if ((offsetValue & Support::lsbMask<uint32_t>(offsetFormat.immDiscardLsb())) != 0)
    4954           0 :       goto InvalidDisplacement;
    4955             : 
    4956           0 :     int64_t dispImm64 = int64_t(offsetValue) >> offsetFormat.immDiscardLsb();
    4957           0 :     if (!Support::isEncodableOffset64(dispImm64, offsetFormat.immBitCount()))
    4958           0 :       goto InvalidDisplacement;
    4959             : 
    4960           0 :     uint32_t dispImm32 = uint32_t(dispImm64 & Support::lsbMask<uint32_t>(offsetFormat.immBitCount()));
    4961           0 :     switch (offsetFormat.type()) {
    4962             :       case OffsetType::kSignedOffset: {
    4963             :         opcode.addImm(dispImm32, offsetFormat.immBitShift());
    4964           0 :         goto EmitOp;
    4965             :       }
    4966             : 
    4967           0 :       case OffsetType::kAArch64_ADR:
    4968             :       case OffsetType::kAArch64_ADRP: {
    4969             :         uint32_t immLo = dispImm32 & 0x3u;
    4970           0 :         uint32_t immHi = dispImm32 >> 2;
    4971             :         opcode.addImm(immLo, 29);
    4972             :         opcode.addImm(immHi, 5);
    4973           0 :         goto EmitOp;
    4974             :       }
    4975             : 
    4976           0 :       default:
    4977           0 :         goto InvalidDisplacement;
    4978             :     }
    4979             :   }
    4980             : 
    4981             :   // --------------------------------------------------------------------------
    4982             :   // [EmitOp - Opcode]
    4983             :   // --------------------------------------------------------------------------
    4984             : 
    4985           0 : EmitOp:
    4986             :   writer.emit32uLE(opcode.get());
    4987           0 :   goto EmitDone;
    4988             : 
    4989             :   // --------------------------------------------------------------------------
    4990             :   // [Done]
    4991             :   // --------------------------------------------------------------------------
    4992             : 
    4993           0 : EmitDone:
    4994           0 :   if (Support::test(options, InstOptions::kReserved)) {
    4995             : #ifndef ASMJIT_NO_LOGGING
    4996           0 :     if (_logger)
    4997           0 :       EmitterUtils::logInstructionEmitted(this, BaseInst::composeARMInstId(instId, instCC), options, o0, o1, o2, opExt, 0, 0, writer.cursor());
    4998             : #endif
    4999             :   }
    5000             : 
    5001             :   resetExtraReg();
    5002             :   resetInstOptions();
    5003             :   resetInlineComment();
    5004             : 
    5005             :   writer.done(this);
    5006           0 :   return kErrorOk;
    5007             : 
    5008             :   // --------------------------------------------------------------------------
    5009             :   // [Error Handler]
    5010             :   // --------------------------------------------------------------------------
    5011             : 
    5012             : #define ERROR_HANDLER(ERR) ERR: err = DebugUtils::errored(kError##ERR); goto Failed;
    5013           0 :   ERROR_HANDLER(OutOfMemory)
    5014           0 :   ERROR_HANDLER(InvalidAddress)
    5015           0 :   ERROR_HANDLER(InvalidAddressScale)
    5016           0 :   ERROR_HANDLER(InvalidDisplacement)
    5017           0 :   ERROR_HANDLER(InvalidElementIndex)
    5018           0 :   ERROR_HANDLER(InvalidLabel)
    5019           0 :   ERROR_HANDLER(InvalidImmediate)
    5020           0 :   ERROR_HANDLER(InvalidInstruction)
    5021           0 :   ERROR_HANDLER(InvalidPhysId)
    5022           0 :   ERROR_HANDLER(InvalidRegType)
    5023             : #undef ERROR_HANDLER
    5024             : 
    5025           0 : Failed:
    5026             : #ifndef ASMJIT_NO_LOGGING
    5027           0 :   return EmitterUtils::logInstructionFailed(this, err, instId, options, o0, o1, o2, opExt);
    5028             : #else
    5029             :   resetExtraReg();
    5030             :   resetInstOptions();
    5031             :   resetInlineComment();
    5032             :   return reportError(err);
    5033             : #endif
    5034             : }
    5035             : 
    5036             : #undef ENC_OPS1
    5037             : #undef ENC_OPS2
    5038             : #undef ENC_OPS3
    5039             : #undef ENC_OPS4
    5040             : 
    5041             : // a64::Assembler - Align
    5042             : // ======================
    5043             : 
    5044           0 : Error Assembler::align(AlignMode alignMode, uint32_t alignment) {
    5045             :   constexpr uint32_t kNopA64 = 0xD503201Fu; // [11010101|00000011|00100000|00011111].
    5046             : 
    5047           0 :   if (ASMJIT_UNLIKELY(!_code))
    5048           0 :     return reportError(DebugUtils::errored(kErrorNotInitialized));
    5049             : 
    5050           0 :   if (ASMJIT_UNLIKELY(uint32_t(alignMode) > uint32_t(AlignMode::kMaxValue)))
    5051           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
    5052             : 
    5053           0 :   if (alignment <= 1)
    5054             :     return kErrorOk;
    5055             : 
    5056           0 :   if (ASMJIT_UNLIKELY(alignment > Globals::kMaxAlignment || !Support::isPowerOf2(alignment)))
    5057           0 :     return reportError(DebugUtils::errored(kErrorInvalidArgument));
    5058             : 
    5059           0 :   uint32_t i = uint32_t(Support::alignUpDiff<size_t>(offset(), alignment));
    5060           0 :   if (i == 0)
    5061             :     return kErrorOk;
    5062             : 
    5063             :   CodeWriter writer(this);
    5064           0 :   ASMJIT_PROPAGATE(writer.ensureSpace(this, i));
    5065             : 
    5066           0 :   switch (alignMode) {
    5067           0 :     case AlignMode::kCode: {
    5068             :       uint32_t pattern = kNopA64;
    5069             : 
    5070           0 :       if (ASMJIT_UNLIKELY(offset() & 0x3u))
    5071             :         return DebugUtils::errored(kErrorInvalidState);
    5072             : 
    5073           0 :       while (i >= 4) {
    5074             :         writer.emit32uLE(pattern);
    5075           0 :         i -= 4;
    5076             :       }
    5077             : 
    5078             :       ASMJIT_ASSERT(i == 0);
    5079             :       break;
    5080             :     }
    5081             : 
    5082           0 :     case AlignMode::kData:
    5083             :     case AlignMode::kZero:
    5084             :       writer.emitZeros(i);
    5085             :       break;
    5086             :   }
    5087             : 
    5088             :   writer.done(this);
    5089             : 
    5090             : #ifndef ASMJIT_NO_LOGGING
    5091           0 :   if (_logger) {
    5092             :     StringTmp<128> sb;
    5093           0 :     sb.appendChars(' ', _logger->indentation(FormatIndentationGroup::kCode));
    5094             :     sb.appendFormat("align %u\n", alignment);
    5095           0 :     _logger->log(sb);
    5096             :   }
    5097             : #endif
    5098             : 
    5099             :   return kErrorOk;
    5100             : }
    5101             : 
    5102             : // a64::Assembler - Events
    5103             : // =======================
    5104             : 
    5105           0 : Error Assembler::onAttach(CodeHolder* code) noexcept {
    5106           0 :   ASMJIT_PROPAGATE(Base::onAttach(code));
    5107             :   return kErrorOk;
    5108             : }
    5109             : 
    5110           0 : Error Assembler::onDetach(CodeHolder* code) noexcept {
    5111           0 :   return Base::onDetach(code);
    5112             : }
    5113             : 
    5114             : ASMJIT_END_SUB_NAMESPACE
    5115             : 
    5116             : #endif // !ASMJIT_NO_AARCH64
    5117             : 
    5118             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16