diff options
author | kobalicek <kobalicek.petr@gmail.com> | 2022-02-08 18:25:47 +0300 |
---|---|---|
committer | kobalicek <kobalicek.petr@gmail.com> | 2022-02-09 19:08:40 +0300 |
commit | 23ddf56b00f47d8aa0c82ad225e4b3a92661da7e (patch) | |
tree | 0cac2b45f63164b13273b61273f858d3b3dd5ccd | |
parent | 45b01147814594cca69d6cb9d93ed9eb049243cf (diff) |
[ABI] Initial AArch64 support
81 files changed, 22011 insertions, 256 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 554722c..50c9bcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,14 @@ if (NOT DEFINED ASMJIT_NO_X86) set(ASMJIT_NO_X86 FALSE) endif() +if (NOT DEFINED ASMJIT_NO_AARCH32) + set(ASMJIT_NO_AARCH32 FALSE) +endif() + +if (NOT DEFINED ASMJIT_NO_AARCH64) + set(ASMJIT_NO_AARCH64 FALSE) +endif() + if (NOT DEFINED ASMJIT_NO_FOREIGN) set(ASMJIT_NO_FOREIGN FALSE) endif() @@ -78,7 +86,9 @@ set(ASMJIT_EMBED "${ASMJIT_EMBED}" CACHE BOOL "Embed 'asmjit set(ASMJIT_STATIC "${ASMJIT_STATIC}" CACHE BOOL "Build 'asmjit' library as static") set(ASMJIT_SANITIZE "${ASMJIT_SANITIZE}" CACHE STRING "Build with sanitizers: 'address', 'undefined', etc...") set(ASMJIT_NO_X86 "${ASMJIT_NO_X86}" CACHE BOOL "Disable X86/X64 backend") -set(ASMJIT_NO_FOREIGN "${ASMJIT_NO_FOREIGN}" CACHE BOOL "Disable all foreign architectures (builds only host backend)") +set(ASMJIT_NO_AARCH32 "${ASMJIT_NO_AARCH32}" CACHE BOOL "Disable AArch32 backend (ARM and THUMB)") +set(ASMJIT_NO_AARCH64 "${ASMJIT_NO_AARCH64}" CACHE BOOL "Disable AArch64 backend") +set(ASMJIT_NO_FOREIGN "${ASMJIT_NO_FOREIGN}" CACHE BOOL "Disable all foreign architectures (enables only a native architecture)") set(ASMJIT_NO_NATVIS "${ASMJIT_NO_NATVIS}" CACHE BOOL "Disable natvis support (embedding asmjit.natvis in PDB)") set(ASMJIT_NO_CUSTOM_FLAGS "${ASMJIT_NO_CUSTOM_FLAGS}" CACHE BOOL "Disable extra compilation flags added by AsmJit to its targets") @@ -189,6 +199,7 @@ if (NOT ASMJIT_NO_CUSTOM_FLAGS) list(APPEND ASMJIT_PRIVATE_CFLAGS -MP # [+] Multi-Process Compilation. -GF # [+] Eliminate duplicate strings. + -Zc:__cplusplus # [+] Conforming __cplusplus definition. -Zc:inline # [+] Remove unreferenced COMDAT. -Zc:strictStrings # [+] Strict const qualification of string literals. -Zc:threadSafeInit- # [-] Thread-safe statics. @@ -262,6 +273,8 @@ endif() foreach(build_option ASMJIT_STATIC # AsmJit backends selection. ASMJIT_NO_X86 + ASMJIT_NO_AARCH32 + ASMJIT_NO_AARCH64 ASMJIT_NO_FOREIGN # AsmJit features selection. ASMJIT_NO_DEPRECATED @@ -381,6 +394,36 @@ set(ASMJIT_SRC_LIST asmjit/core/zonevector.cpp asmjit/core/zonevector.h + asmjit/arm.h + asmjit/arm/armformatter.cpp + asmjit/arm/armformatter_p.h + asmjit/arm/armglobals.h + asmjit/arm/armoperand.h + asmjit/arm/a64archtraits_p.h + asmjit/arm/a64assembler.cpp + asmjit/arm/a64assembler.h + asmjit/arm/a64builder.cpp + asmjit/arm/a64builder.h + asmjit/arm/a64compiler.cpp + asmjit/arm/a64compiler.h + asmjit/arm/a64emithelper.cpp + asmjit/arm/a64emithelper_p.h + asmjit/arm/a64emitter.h + asmjit/arm/a64formatter.cpp + asmjit/arm/a64formatter_p.h + asmjit/arm/a64func.cpp + asmjit/arm/a64func_p.h + asmjit/arm/a64globals.h + asmjit/arm/a64instapi.cpp + asmjit/arm/a64instapi_p.h + asmjit/arm/a64instdb.cpp + asmjit/arm/a64instdb.h + asmjit/arm/a64operand.cpp + asmjit/arm/a64operand.h + asmjit/arm/a64rapass.cpp + asmjit/arm/a64rapass_p.h + asmjit/arm/a64utils.h + asmjit/x86.h asmjit/x86/x86archtraits_p.h asmjit/x86/x86assembler.cpp @@ -504,9 +547,10 @@ if (NOT ASMJIT_EMBED) asmjit_add_target(asmjit_test_assembler TEST SOURCES test/asmjit_test_assembler.cpp + test/asmjit_test_assembler.h + test/asmjit_test_assembler_a64.cpp test/asmjit_test_assembler_x64.cpp test/asmjit_test_assembler_x86.cpp - test/asmjit_test_assembler.h LIBRARIES asmjit::asmjit CFLAGS ${ASMJIT_PRIVATE_CFLAGS} CFLAGS_DBG ${ASMJIT_PRIVATE_CFLAGS_DBG} @@ -514,6 +558,7 @@ if (NOT ASMJIT_EMBED) asmjit_add_target(asmjit_test_perf EXECUTABLE SOURCES test/asmjit_test_perf.cpp + test/asmjit_test_perf_a64.cpp test/asmjit_test_perf_x86.cpp SOURCES test/asmjit_test_perf.h LIBRARIES asmjit::asmjit @@ -550,8 +595,9 @@ if (NOT ASMJIT_EMBED) endif() asmjit_add_target(asmjit_test_compiler TEST SOURCES test/asmjit_test_compiler.cpp - test/asmjit_test_compiler_x86.cpp test/asmjit_test_compiler.h + test/asmjit_test_compiler_a64.cpp + test/asmjit_test_compiler_x86.cpp LIBRARIES asmjit::asmjit CFLAGS ${ASMJIT_PRIVATE_CFLAGS} ${sse2_flags} CFLAGS_DBG ${ASMJIT_PRIVATE_CFLAGS_DBG} diff --git a/src/asmjit/a64.h b/src/asmjit/a64.h new file mode 100644 index 0000000..ea4d304 --- /dev/null +++ b/src/asmjit/a64.h @@ -0,0 +1,62 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_A64_H_INCLUDED +#define ASMJIT_A64_H_INCLUDED + +//! \addtogroup asmjit_a64 +//! +//! ### Emitters +//! +//! - \ref a64::Assembler - AArch64 assembler (must read, provides examples). +//! - \ref a64::Builder - AArch64 builder. +//! - \ref a64::Compiler - AArch64 compiler. +//! - \ref a64::Emitter - AArch64 emitter (abstract). +//! +//! ### Supported Instructions +//! +//! - Emitters: +//! - \ref a64::EmitterExplicitT - Provides all instructions that use explicit +//! operands, provides also utility functions. The member functions provided +//! are part of all ARM/AArch64 emitters. +//! +//! - Instruction representation: +//! - \ref a64::Inst::Id - instruction identifiers. +//! +//! ### Register Operands +//! +//! - \ref arm::Reg - Base class for any AArch32/AArch64 register. +//! - \ref arm::Gp - General purpose register: +//! - \ref arm::GpW - 32-bit register. +//! - \ref arm::GpX - 64-bit register. +//! - \ref arm::Vec - Vector (SIMD) register: +//! - \ref arm::VecB - 8-bit SIMD register (AArch64 only). +//! - \ref arm::VecH - 16-bit SIMD register (AArch64 only). +//! - \ref arm::VecS - 32-bit SIMD register. +//! - \ref arm::VecD - 64-bit SIMD register. +//! - \ref arm::VecV - 128-bit SIMD register. +//! +//! ### Memory Operands +//! +//! - \ref arm::Mem - AArch32/AArch64 memory operand that provides support for all ARM addressing features +//! including base, index, pre/post increment, and ARM-specific shift addressing and index extending. +//! +//! ### Other +//! +//! - \ref arm::Shift - Shift operation and value. +//! - \ref a64::Utils - Utilities that can help during code generation for AArch64. + +#include "./arm.h" +#include "./arm/a64assembler.h" +#include "./arm/a64builder.h" +#include "./arm/a64compiler.h" +#include "./arm/a64emitter.h" +#include "./arm/a64globals.h" +#include "./arm/a64instdb.h" +#include "./arm/a64operand.h" +#include "./arm/a64utils.h" + +#endif // ASMJIT_A64_H_INCLUDED + diff --git a/src/asmjit/arm.h b/src/asmjit/arm.h new file mode 100644 index 0000000..57ffa81 --- /dev/null +++ b/src/asmjit/arm.h @@ -0,0 +1,62 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_H_INCLUDED +#define ASMJIT_ARM_H_INCLUDED + +//! \addtogroup asmjit_arm +//! +//! ### Namespaces +//! +//! - \ref arm - arm namespace provides common functionality for both AArch32 and AArch64 backends. +//! - \ref a64 - a64 namespace provides support for AArch64 architecture. In addition it includes +//! \ref arm namespace, so you can only use a single namespace when targeting AArch64 architecture. +//! +//! ### Emitters +//! +//! - AArch64 +//! - \ref a64::Assembler - AArch64 assembler (must read, provides examples). +//! - \ref a64::Builder - AArch64 builder. +//! - \ref a64::Compiler - AArch64 compiler. +//! - \ref a64::Emitter - AArch64 emitter (abstract). +//! +//! ### Supported Instructions +//! +//! - AArch64: +//! - Emitters: +//! - \ref a64::EmitterExplicitT - Provides all instructions that use explicit operands, provides also +//! utility functions. The member functions provided are part of all AArch64 emitters. +//! - Instruction representation: +//! - \ref a64::Inst::Id - instruction identifiers. +//! +//! ### Register Operands +//! +//! - \ref arm::Reg - Base class for any AArch32/AArch64 register. +//! - \ref arm::Gp - General purpose register: +//! - \ref arm::GpW - 32-bit register. +//! - \ref arm::GpX - 64-bit register. +//! - \ref arm::Vec - Vector (SIMD) register: +//! - \ref arm::VecB - 8-bit SIMD register (AArch64 only). +//! - \ref arm::VecH - 16-bit SIMD register (AArch64 only). +//! - \ref arm::VecS - 32-bit SIMD register. +//! - \ref arm::VecD - 64-bit SIMD register. +//! - \ref arm::VecV - 128-bit SIMD register. +//! +//! ### Memory Operands +//! +//! - \ref arm::Mem - AArch32/AArch64 memory operand that provides support for all ARM addressing features +//! including base, index, pre/post increment, and ARM-specific shift addressing and index extending. +//! +//! ### Other +//! +//! - \ref arm::Shift - Shift operation and value (both AArch32 and AArch64). +//! - \ref arm::DataType - Data type that is part of an instruction in AArch32 mode. +//! - \ref a64::Utils - Utilities that can help during code generation for AArch64. + +#include "./core.h" +#include "./arm/armglobals.h" +#include "./arm/armoperand.h" + +#endif // ASMJIT_ARM_H_INCLUDED diff --git a/src/asmjit/arm/a64archtraits_p.h b/src/asmjit/arm/a64archtraits_p.h new file mode 100644 index 0000000..87559c7 --- /dev/null +++ b/src/asmjit/arm/a64archtraits_p.h @@ -0,0 +1,81 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64ARCHTRAITS_P_H_INCLUDED +#define ASMJIT_ARM_A64ARCHTRAITS_P_H_INCLUDED + +#include "../core/archtraits.h" +#include "../core/misc_p.h" +#include "../core/type.h" +#include "../arm/a64operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \cond INTERNAL +//! \addtogroup asmjit_a64 +//! \{ + +static const constexpr ArchTraits a64ArchTraits = { + // SP/FP/LR/PC. + Gp::kIdSp, Gp::kIdFp, Gp::kIdLr, 0xFF, + + // Reserved. + { 0, 0, 0 }, + + // HW stack alignment (AArch64 requires stack aligned to 64 bytes). + 16, + + // Min/max stack offset - byte addressing is the worst, VecQ addressing the best. + 4095, 65520, + + // Instruction hints [Gp, Vec, ExtraVirt2, ExtraVirt3]. + {{ + InstHints::kPushPop, + InstHints::kPushPop, + InstHints::kNoHints, + InstHints::kNoHints + }}, + + // RegInfo. + #define V(index) OperandSignature{arm::RegTraits<RegType(index)>::kSignature} + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, + #undef V + + // RegTypeToTypeId. + #define V(index) TypeId(arm::RegTraits<RegType(index)>::kTypeId) + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, + #undef V + + // TypeIdToRegType. + #define V(index) (index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt8) ? RegType::kARM_GpW : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt8) ? RegType::kARM_GpW : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt16) ? RegType::kARM_GpW : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt16) ? RegType::kARM_GpW : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt32) ? RegType::kARM_GpW : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt32) ? RegType::kARM_GpW : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kInt64) ? RegType::kARM_GpX : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUInt64) ? RegType::kARM_GpX : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kIntPtr) ? RegType::kARM_GpX : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kUIntPtr) ? RegType::kARM_GpX : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kFloat32) ? RegType::kARM_VecS : \ + index + uint32_t(TypeId::_kBaseStart) == uint32_t(TypeId::kFloat64) ? RegType::kARM_VecD : RegType::kNone) + {{ ASMJIT_LOOKUP_TABLE_32(V, 0) }}, + #undef V + + // Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities. + { + ArchTypeNameId::kByte, + ArchTypeNameId::kHWord, + ArchTypeNameId::kWord, + ArchTypeNameId::kXWord + } +}; + +//! \} +//! \endcond + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_A64ARCHTRAITS_P_H_INCLUDED diff --git a/src/asmjit/arm/a64assembler.cpp b/src/asmjit/arm/a64assembler.cpp new file mode 100644 index 0000000..9f8c9b1 --- /dev/null +++ b/src/asmjit/arm/a64assembler.cpp @@ -0,0 +1,5115 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#if !defined(ASMJIT_NO_AARCH64) + +#include "../core/codewriter_p.h" +#include "../core/cpuinfo.h" +#include "../core/emitterutils_p.h" +#include "../core/formatter.h" +#include "../core/logger.h" +#include "../core/misc_p.h" +#include "../core/support.h" +#include "../arm/armformatter_p.h" +#include "../arm/a64assembler.h" +#include "../arm/a64emithelper_p.h" +#include "../arm/a64instdb_p.h" +#include "../arm/a64utils.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +// a64::Assembler - Cond +// ===================== + +static inline uint32_t condCodeToOpcodeCond(uint32_t cond) noexcept { + return (uint32_t(cond) - 2u) & 0xFu; +} + +// a64::Assembler - Bits +// ===================== + +template<typename T> +static inline constexpr uint32_t B(const T& index) noexcept { return uint32_t(1u) << uint32_t(index); } + +static constexpr uint32_t kSP = Gp::kIdSp; +static constexpr uint32_t kZR = Gp::kIdZr; +static constexpr uint32_t kWX = InstDB::kWX; + +// a64::Assembler - ShiftOpToLdStOptMap +// ==================================== + +// Table that maps ShiftOp to OPT part in LD/ST (register) opcode. +#define VALUE(index) index == uint32_t(ShiftOp::kUXTW) ? 2u : \ + index == uint32_t(ShiftOp::kLSL) ? 3u : \ + index == uint32_t(ShiftOp::kSXTW) ? 6u : \ + index == uint32_t(ShiftOp::kSXTX) ? 7u : 0xFF +static const uint8_t armShiftOpToLdStOptMap[] = { ASMJIT_LOOKUP_TABLE_16(VALUE, 0) }; +#undef VALUE + +static inline constexpr uint32_t diff(RegType a, RegType b) noexcept { + return uint32_t(a) - uint32_t(b); +} + +// asmjit::a64::Assembler - SizeOp +// =============================== + +//! Struct that contains Size (2 bits), Q flag, and S (scalar) flag. These values +//! are used to encode Q, Size, and Scalar fields in an opcode. +struct SizeOp { + enum : uint8_t { + k128BitShift = 0, + kScalarShift = 1, + kSizeShift = 2, + + kQ = uint8_t(1u << k128BitShift), + kS = uint8_t(1u << kScalarShift), + + k00 = uint8_t(0 << kSizeShift), + k01 = uint8_t(1 << kSizeShift), + k10 = uint8_t(2 << kSizeShift), + k11 = uint8_t(3 << kSizeShift), + + k00Q = k00 | kQ, + k01Q = k01 | kQ, + k10Q = k10 | kQ, + k11Q = k11 | kQ, + + k00S = k00 | kS, + k01S = k01 | kS, + k10S = k10 | kS, + k11S = k11 | kS, + + kInvalid = 0xFFu, + + // Masks used by SizeOpMap. + kSzQ = (0x3u << kSizeShift) | kQ, + kSzS = (0x3u << kSizeShift) | kS, + kSzQS = (0x3u << kSizeShift) | kQ | kS + }; + + uint8_t value; + + inline bool isValid() const noexcept { return value != kInvalid; } + inline void makeInvalid() noexcept { value = kInvalid; } + + inline uint32_t q() const noexcept { return (value >> k128BitShift) & 0x1u; } + inline uint32_t qs() const noexcept { return ((value >> k128BitShift) | (value >> kScalarShift)) & 0x1u; } + inline uint32_t scalar() const noexcept { return (value >> kScalarShift) & 0x1u; } + inline uint32_t size() const noexcept { return (value >> kSizeShift) & 0x3u; } + + inline void decrementSize() noexcept { + ASMJIT_ASSERT(size() > 0); + value = uint8_t(value - (1u << kSizeShift)); + } +}; + +struct SizeOpTable { + enum TableId : uint8_t { + kTableBin = 0, + kTableAny, + kCount + }; + + // 40 elements for each combination. + SizeOp array[(uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB) + 1) * 8]; +}; + +#define VALUE_BIN(x) { \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00Q : SizeOp::kInvalid \ +} + +#define VALUE_ANY(x) { \ + x == (((uint32_t(RegType::kARM_VecB) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k00S : \ + x == (((uint32_t(RegType::kARM_VecH) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k01S : \ + x == (((uint32_t(RegType::kARM_VecS) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k10S : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeNone)) ? SizeOp::k11S : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeB )) ? SizeOp::k00Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH )) ? SizeOp::k01 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeH )) ? SizeOp::k01Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS )) ? SizeOp::k10 : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeS )) ? SizeOp::k10Q : \ + x == (((uint32_t(RegType::kARM_VecD) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD )) ? SizeOp::k11S : \ + x == (((uint32_t(RegType::kARM_VecV) - uint32_t(RegType::kARM_VecB)) << 3) | (Vec::kElementTypeD )) ? SizeOp::k11Q : SizeOp::kInvalid \ +} + +static const SizeOpTable sizeOpTable[SizeOpTable::kCount] = { + {{ ASMJIT_LOOKUP_TABLE_40(VALUE_BIN, 0) }}, + {{ ASMJIT_LOOKUP_TABLE_40(VALUE_ANY, 0) }} +}; + +#undef VALUE_ANY +#undef VALUE_BIN + +struct SizeOpMap { + uint8_t tableId; + uint8_t sizeOpMask; + uint16_t acceptMask; +}; + +static const constexpr SizeOpMap sizeOpMap[InstDB::kVO_Count] = { + { // kVO_V_B: + SizeOpTable::kTableBin, SizeOp::kQ , uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q)) + }, + + { // kVO_V_BH: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q)) + }, + + { // kVO_V_BH_4S: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10Q)) + }, + + { // kVO_V_BHS: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00Q) | B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q)) + }, + + { // kVO_V_BHS_D2: + 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)) + }, + + { // kVO_V_HS: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k10) | B(SizeOp::k10Q)) + }, + + { // kVO_V_S: + SizeOpTable::kTableAny, SizeOp::kQ , uint16_t(B(SizeOp::k10) | B(SizeOp::k10Q)) + }, + + { // kVO_V_B8H4: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k01)) + }, + + { // kVO_V_B8H4S2: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k01) | B(SizeOp::k10)) + }, + + { // kVO_V_B8D1: + SizeOpTable::kTableAny, SizeOp::kSzQ , uint16_t(B(SizeOp::k00) | B(SizeOp::k11S)) + }, + + { // kVO_V_H4S2: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k10)) + }, + + { // kVO_V_B16: + SizeOpTable::kTableBin, SizeOp::kQ , uint16_t(B(SizeOp::k00Q)) + }, + + { // kVO_V_B16H8: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k01Q)) + }, + + { // kVO_V_B16H8S4: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k01Q) | B(SizeOp::k10Q)) + }, + + { // kVO_V_B16D2: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00Q) | B(SizeOp::k11Q)) + }, + + { // kVO_V_H8S4: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01Q) | B(SizeOp::k10Q)) + }, + + { // kVO_V_S4: + SizeOpTable::kTableAny, 0 , uint16_t(B(SizeOp::k10Q)) + }, + + { // kVO_V_D2: + SizeOpTable::kTableAny, 0 , uint16_t(B(SizeOp::k11Q)) + }, + + { // kVO_SV_BHS: + 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)) + }, + + { // kVO_SV_B8H4S2: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k00) | B(SizeOp::k00S) | B(SizeOp::k01) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10S)) + }, + + { // kVO_SV_HS: + SizeOpTable::kTableAny, SizeOp::kSzQS, uint16_t(B(SizeOp::k01) | B(SizeOp::k01Q) | B(SizeOp::k01S) | B(SizeOp::k10) | B(SizeOp::k10Q) | B(SizeOp::k10S)) + }, + + { // kVO_V_Any: + 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)) + }, + + { // kVO_SV_Any: + 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) | + B(SizeOp::k11) | B(SizeOp::k11Q) | B(SizeOp::k11S)) + } +}; + +static const Operand_& significantSimdOp(const Operand_& o0, const Operand_& o1, uint32_t instFlags) noexcept { + return !(instFlags & InstDB::kInstFlagLong) ? o0 : o1; +} + +static inline SizeOp armElementTypeToSizeOp(uint32_t vecOpType, RegType regType, uint32_t elementType) noexcept { + // Instruction data or Assembler is wrong if this triggers an assertion failure. + ASMJIT_ASSERT(vecOpType < InstDB::kVO_Count); + // ElementType uses 3 bits in the operand signature, it should never overflow. + ASMJIT_ASSERT(elementType <= 0x7u); + + const SizeOpMap& map = sizeOpMap[vecOpType]; + const SizeOpTable& table = sizeOpTable[map.tableId]; + + size_t index = (Support::min<uint32_t>(diff(regType, RegType::kARM_VecB), diff(RegType::kARM_VecV, RegType::kARM_VecB) + 1) << 3) | elementType; + SizeOp op = table.array[index]; + SizeOp modifiedOp { uint8_t(op.value & map.sizeOpMask) }; + + if (!Support::bitTest(map.acceptMask, op.value)) + modifiedOp.makeInvalid(); + + return modifiedOp; +} + +// a64::Assembler - Immediate Encoding Utilities (Integral) +// ======================================================== + +using Utils::LogicalImm; + +struct HalfWordImm { + uint32_t hw; + uint32_t inv; + uint32_t imm; +}; + +struct LMHImm { + uint32_t lm; + uint32_t h; + uint32_t maxRmId; +}; + +static inline uint32_t countZeroHalfWords64(uint64_t imm) noexcept { + return uint32_t((imm & 0x000000000000FFFFu) == 0) + + uint32_t((imm & 0x00000000FFFF0000u) == 0) + + uint32_t((imm & 0x0000FFFF00000000u) == 0) + + uint32_t((imm & 0xFFFF000000000000u) == 0) ; +} + +static uint32_t encodeMovSequence32(uint32_t out[2], uint32_t imm, uint32_t rd, uint32_t x) noexcept { + ASMJIT_ASSERT(rd <= 31); + + uint32_t kMovZ = 0b01010010100000000000000000000000 | (x << 31); + uint32_t kMovN = 0b00010010100000000000000000000000; + uint32_t kMovK = 0b01110010100000000000000000000000; + + if ((imm & 0xFFFF0000u) == 0x00000000u) { + out[0] = kMovZ | (0 << 21) | ((imm & 0xFFFFu) << 5) | rd; + return 1; + } + + if ((imm & 0xFFFF0000u) == 0xFFFF0000u) { + out[0] = kMovN | (0 << 21) | ((~imm & 0xFFFFu) << 5) | rd; + return 1; + } + + if ((imm & 0x0000FFFFu) == 0x00000000u) { + out[0] = kMovZ | (1 << 21) | ((imm >> 16) << 5) | rd; + return 1; + } + + if ((imm & 0x0000FFFFu) == 0x0000FFFFu) { + out[0] = kMovN | (1 << 21) | ((~imm >> 16) << 5) | rd; + return 1; + } + + out[0] = kMovZ | (0 << 21) | ((imm & 0xFFFFu) << 5) | rd; + out[1] = kMovK | (1 << 21) | ((imm >> 16) << 5) | rd; + return 2; +} + +static uint32_t encodeMovSequence64(uint32_t out[4], uint64_t imm, uint32_t rd, uint32_t x) noexcept { + ASMJIT_ASSERT(rd <= 31); + + uint32_t kMovZ = 0b11010010100000000000000000000000; + uint32_t kMovN = 0b10010010100000000000000000000000; + uint32_t kMovK = 0b11110010100000000000000000000000; + + if (imm <= 0xFFFFFFFFu) + return encodeMovSequence32(out, uint32_t(imm), rd, x); + + uint32_t zhw = countZeroHalfWords64( imm); + uint32_t ohw = countZeroHalfWords64(~imm); + + if (zhw >= ohw) { + uint32_t op = kMovZ; + uint32_t count = 0; + + for (uint32_t hwIndex = 0; hwIndex < 4; hwIndex++, imm >>= 16) { + uint32_t hwImm = uint32_t(imm & 0xFFFFu); + if (hwImm == 0) + continue; + + out[count++] = op | (hwIndex << 21) | (hwImm << 5) | rd; + op = kMovK; + } + + // This should not happen - zero should be handled by encodeMovSequence32(). + ASMJIT_ASSERT(count > 0); + + return count; + } + else { + uint32_t op = kMovN; + uint32_t count = 0; + uint32_t negMask = 0xFFFFu; + + for (uint32_t hwIndex = 0; hwIndex < 4; hwIndex++, imm >>= 16) { + uint32_t hwImm = uint32_t(imm & 0xFFFFu); + if (hwImm == 0xFFFFu) + continue; + + out[count++] = op | (hwIndex << 21) | ((hwImm ^ negMask) << 5) | rd; + op = kMovK; + negMask = 0; + } + + if (count == 0) { + out[count++] = kMovN | ((0xFFFF ^ negMask) << 5) | rd; + } + + return count; + } +} + +static inline bool encodeLMH(uint32_t sizeField, uint32_t elementIndex, LMHImm* out) noexcept { + if (sizeField != 1 && sizeField != 2) + return false; + + uint32_t hShift = 3u - sizeField; + uint32_t lmShift = sizeField - 1u; + uint32_t maxElementIndex = 15u >> sizeField; + + out->h = elementIndex >> hShift; + out->lm = (elementIndex << lmShift) & 0x3u; + out->maxRmId = (8u << sizeField) - 1; + + return elementIndex <= maxElementIndex; +} + +// [.......A|B.......|.......C|D.......|.......E|F.......|.......G|H.......] +static inline uint32_t encodeImm64ByteMaskToImm8(uint64_t imm) noexcept { + return uint32_t(((imm >> (7 - 0)) & 0b00000011) | // [.......G|H.......] + ((imm >> (23 - 2)) & 0b00001100) | // [.......E|F.......] + ((imm >> (39 - 4)) & 0b00110000) | // [.......C|D.......] + ((imm >> (55 - 6)) & 0b11000000)); // [.......A|B.......] +} + +// a64::Assembler - Opcode +// ======================= + +//! Helper class to store and manipulate ARM opcode. +struct Opcode { + uint32_t v; + + enum Bits : uint32_t { + kN = (1u << 22), + kQ = (1u << 30), + kX = (1u << 31) + }; + + // -------------------------------------------------------------------------- + // [Opcode Builder] + // -------------------------------------------------------------------------- + + inline uint32_t get() const noexcept { return v; } + inline void reset(uint32_t value) noexcept { v = value; } + + inline bool hasQ() const noexcept { return (v & kQ) != 0; } + inline bool hasX() const noexcept { return (v & kX) != 0; } + + template<typename T> + inline Opcode& addImm(T value, uint32_t bitIndex) noexcept { return operator|=(uint32_t(value) << bitIndex); } + + template<typename T> + inline Opcode& xorImm(T value, uint32_t bitIndex) noexcept { return operator^=(uint32_t(value) << bitIndex); } + + template<typename T, typename Condition> + inline Opcode& addIf(T value, const Condition& condition) noexcept { return operator|=(condition ? uint32_t(value) : uint32_t(0)); } + + inline Opcode& addLogicalImm(const LogicalImm& logicalImm) noexcept { + addImm(logicalImm.n, 22); + addImm(logicalImm.r, 16); + addImm(logicalImm.s, 10); + return *this; + } + + inline Opcode& addReg(uint32_t id, uint32_t bitIndex) noexcept { return operator|=((id & 31u) << bitIndex); } + inline Opcode& addReg(const Operand_& op, uint32_t bitIndex) noexcept { return addReg(op.id(), bitIndex); } + + inline Opcode& operator=(uint32_t x) noexcept { v = x; return *this; } + inline Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; } + inline Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; } + inline Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; } + + inline uint32_t operator&(uint32_t x) const noexcept { return v & x; } + inline uint32_t operator|(uint32_t x) const noexcept { return v | x; } + inline uint32_t operator^(uint32_t x) const noexcept { return v ^ x; } +}; + +// a64::Assembler - Signature Utilities +// ==================================== + +// TODO: [ARM] Deprecate matchSignature. +static inline bool matchSignature(const Operand_& o0, const Operand_& o1, uint32_t instFlags) noexcept { + if (!(instFlags & (InstDB::kInstFlagLong | InstDB::kInstFlagNarrow))) + return o0.signature() == o1.signature(); + + // TODO: [ARM] Something smart to validate this. + return true; +} + +static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t instFlags) noexcept { + return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature(); +} + +static inline bool matchSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, uint32_t instFlags) noexcept { + return matchSignature(o0, o1, instFlags) && o1.signature() == o2.signature() && o2.signature() == o3.signature();; +} + +// Memory must be either: +// 1. Absolute address, which will be converted to relative. +// 2. Relative displacement (Label). +// 3. Base register + either offset or index. +static inline bool armCheckMemBaseIndexRel(const Mem& mem) noexcept { + // Allowed base types (Nothing, Label, and GpX). + constexpr uint32_t kBaseMask = B(0) | + B(RegType::kLabelTag) | + B(RegType::kARM_GpX); + + // Allowed index types (Nothing, GpW, and GpX). + constexpr uint32_t kIndexMask = B(0) | + B(RegType::kARM_GpW) | + B(RegType::kARM_GpX) ; + + RegType baseType = mem.baseType(); + RegType indexType = mem.indexType(); + + if (!Support::bitTest(kBaseMask, baseType)) + return false; + + if (baseType > RegType::kLabelTag) { + // Index allows either GpW or GpX. + if (!Support::bitTest(kIndexMask, indexType)) + return false; + + if (indexType == RegType::kNone) + return true; + else + return !mem.hasOffset(); + } + else { + // No index register allowed if this is a PC relative address (literal). + return indexType == RegType::kNone; + } +} + +struct EncodeFpOpcodeBits { + uint32_t sizeMask; + uint32_t mask[3]; +}; + +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 { + static constexpr uint32_t kQBitIndex = 30; + + static const EncodeFpOpcodeBits szBits[InstDB::kHF_Count] = { + { B(2) | B(1) , { 0u , 0u, B(22) } }, + { B(2) | B(1) | B(0), { 0u , 0u, 0u } }, + { B(2) | B(1) | B(0), { B(23) | B(22) , 0u, B(22) } }, + { B(2) | B(1) | B(0), { B(22) | B(20) | B(19) , 0u, B(22) } }, + { B(2) | B(1) | B(0), { B(22) | B(21) | B(15) | B(14), 0u, B(22) } }, + { B(2) | B(1) | B(0), { B(23) , 0u, B(22) } } + }; + + if (!reg.hasElementType()) { + // Scalar operation [HSD]. + uint32_t sz = diff(reg.type(), RegType::kARM_VecH); + if (sz > 2u || !Support::bitTest(szBits[sHf].sizeMask, sz)) + return false; + + opcode->reset(szBits[sHf].mask[sz] ^ sOp); + *szOut = sz; + return sOp != 0; + } + else { + // Vector operation [HSD]. + uint32_t q = diff(reg.type(), RegType::kARM_VecD); + uint32_t sz = reg.elementType() - Vec::kElementTypeH; + + if (q > 1u || sz > 2u || !Support::bitTest(szBits[vHf].sizeMask, sz)) + return false; + + opcode->reset(szBits[vHf].mask[sz] ^ (vOp | (q << kQBitIndex))); + *szOut = sz; + return vOp != 0; + } +} + +static inline bool pickFpOpcode(const Vec& reg, uint32_t sOp, uint32_t sHf, uint32_t vOp, uint32_t vHf, Opcode* opcode) noexcept { + uint32_t sz; + return pickFpOpcode(reg, sOp, sHf, vOp, vHf, opcode, &sz); +} + +// a64::Assembler - Operand Checks +// =============================== + +// Checks whether all operands have the same signature. +static inline bool checkSignature(const Operand_& o0, const Operand_& o1) noexcept { + return o0.signature() == o1.signature(); +} + +static inline bool checkSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept { + return o0.signature() == o1.signature() && + o1.signature() == o2.signature(); +} + +static inline bool checkSignature(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept { + return o0.signature() == o1.signature() && + o1.signature() == o2.signature() && + o2.signature() == o3.signature(); +} + +// Checks whether the register is GP register of the allowed types. +// +// Allowed is a 2-bit mask, where the first bits allows GpW and the second bit +// allows GpX. These bits are usually stored within the instruction, but could +// be also hardcoded in the assembler for instructions where GP types are not +// selectable. +static inline bool checkGpType(const Operand_& op, uint32_t allowed) noexcept { + RegType type = op.as<Reg>().type(); + return Support::bitTest(allowed << uint32_t(RegType::kARM_GpW), type); +} + +static inline bool checkGpType(const Operand_& op, uint32_t allowed, uint32_t* x) noexcept { + // NOTE: We set 'x' to one only when GpW is allowed, otherwise the X is part + // of the opcode and we cannot set it. This is why this works without requiring + // additional logic. + RegType type = op.as<Reg>().type(); + *x = diff(type, RegType::kARM_GpW) & allowed; + return Support::bitTest(allowed << uint32_t(RegType::kARM_GpW), type); +} + +static inline bool checkGpType(const Operand_& o0, const Operand_& o1, uint32_t allowed, uint32_t* x) noexcept { + return checkGpType(o0, allowed, x) && checkSignature(o0, o1); +} + +static inline bool checkGpType(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t allowed, uint32_t* x) noexcept { + return checkGpType(o0, allowed, x) && checkSignature(o0, o1, o2); +} + +static inline bool checkGpId(const Operand_& op, uint32_t hiId = kZR) noexcept { + uint32_t id = op.as<Reg>().id(); + return id < 31u || id == hiId; +} + +static inline bool checkGpId(const Operand_& o0, const Operand_& o1, uint32_t hiId = kZR) noexcept { + uint32_t id0 = o0.as<Reg>().id(); + uint32_t id1 = o1.as<Reg>().id(); + + return (id0 < 31u || id0 == hiId) && (id1 < 31u || id1 == hiId); +} + +static inline bool checkGpId(const Operand_& o0, const Operand_& o1, const Operand_& o2, uint32_t hiId = kZR) noexcept { + uint32_t id0 = o0.as<Reg>().id(); + uint32_t id1 = o1.as<Reg>().id(); + uint32_t id2 = o2.as<Reg>().id(); + + return (id0 < 31u || id0 == hiId) && (id1 < 31u || id1 == hiId) && (id2 < 31u || id2 == hiId); +} + +static inline bool checkVecId(const Operand_& op) noexcept { + uint32_t id = op.as<Reg>().id(); + return id <= 31u; +} + +static inline bool checkVecId(const Operand_& o0, const Operand_& o1) noexcept { + uint32_t id0 = o0.as<Reg>().id(); + uint32_t id1 = o1.as<Reg>().id(); + + return (id0 | id1) <= 31u; +} + +/* Unused at the moment. +static inline bool checkVecId(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept { + uint32_t id0 = o0.as<Reg>().id(); + uint32_t id1 = o1.as<Reg>().id(); + uint32_t id2 = o2.as<Reg>().id(); + + return (id0 | id1 | id2) <= 31u; +} + +static inline bool checkVecId(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept { + uint32_t id0 = o0.as<Reg>().id(); + uint32_t id1 = o1.as<Reg>().id(); + uint32_t id2 = o2.as<Reg>().id(); + uint32_t id3 = o3.as<Reg>().id(); + + return (id0 | id1 | id2 | id3) <= 31u; +} +*/ + +static inline bool checkMemBase(const Mem& mem) noexcept { + return mem.baseType() == RegType::kARM_GpX && mem.baseId() <= 31; +} + +static inline bool checkEven(const Operand_& o0, const Operand_& o1) noexcept { + return ((o0.id() | o1.id()) & 1) == 0; +} + +static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1) noexcept { + return ((o0.id() + 1u) & 0x1Fu) == o1.id(); +} + +static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept { + return ((o0.id() + 1u) & 0x1Fu) == o1.id() && + ((o0.id() + 2u) & 0x1Fu) == o2.id(); +} + +static inline bool checkConsecutive(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept { + return ((o0.id() + 1u) & 0x1Fu) == o1.id() && + ((o0.id() + 2u) & 0x1Fu) == o2.id() && + ((o0.id() + 3u) & 0x1Fu) == o3.id(); +} + +// a64::Assembler - CheckReg +// ========================= + +#define V(index) (index == uint32_t(RegType::kARM_GpW) ? Gp::kIdZr : \ + index == uint32_t(RegType::kARM_GpX) ? Gp::kIdZr : \ + index == uint32_t(RegType::kARM_VecB) ? 31u : \ + index == uint32_t(RegType::kARM_VecH) ? 31u : \ + index == uint32_t(RegType::kARM_VecS) ? 31u : \ + index == uint32_t(RegType::kARM_VecD) ? 31u : \ + index == uint32_t(RegType::kARM_VecV) ? 31u : 0) +static const Support::Array<uint8_t, 32> commonHiRegIdOfType = {{ + ASMJIT_LOOKUP_TABLE_32(V, 0) +}}; +#undef V + +static inline bool checkValidRegs(const Operand_& o0) noexcept { + return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])); +} + +static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1) noexcept { + return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) & + ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) ; +} + +static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Operand_& o2) noexcept { + return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) & + ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) & + ((o2.id() < 31) | (o2.id() == commonHiRegIdOfType[o2.as<Reg>().type()])) ; +} + +static inline bool checkValidRegs(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) noexcept { + return ((o0.id() < 31) | (o0.id() == commonHiRegIdOfType[o0.as<Reg>().type()])) & + ((o1.id() < 31) | (o1.id() == commonHiRegIdOfType[o1.as<Reg>().type()])) & + ((o2.id() < 31) | (o2.id() == commonHiRegIdOfType[o2.as<Reg>().type()])) & + ((o3.id() < 31) | (o3.id() == commonHiRegIdOfType[o3.as<Reg>().type()])) ; +} + +// a64::Assembler - Construction & Destruction +// =========================================== + +Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() { + _archMask = uint64_t(1) << uint32_t(Arch::kAArch64); + assignEmitterFuncs(this); + + if (code) + code->attach(this); +} + +Assembler::~Assembler() noexcept {} + +// a64::Assembler - Emit +// ===================== + +#define ENC_OPS1(OP0) \ + (uint32_t(OperandType::k##OP0)) + +#define ENC_OPS2(OP0, OP1) \ + (uint32_t(OperandType::k##OP0) + \ + (uint32_t(OperandType::k##OP1) << 3)) + +#define ENC_OPS3(OP0, OP1, OP2) \ + (uint32_t(OperandType::k##OP0) + \ + (uint32_t(OperandType::k##OP1) << 3) + \ + (uint32_t(OperandType::k##OP2) << 6)) + +#define ENC_OPS4(OP0, OP1, OP2, OP3) \ + (uint32_t(OperandType::k##OP0) + \ + (uint32_t(OperandType::k##OP1) << 3) + \ + (uint32_t(OperandType::k##OP2) << 6) + \ + (uint32_t(OperandType::k##OP3) << 9)) + +Error Assembler::_emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { + // Logging/Validation/Error. + constexpr InstOptions kRequiresSpecialHandling = InstOptions::kReserved; + + Error err; + CodeWriter writer(this); + + // Combine all instruction options and also check whether the instruction + // is valid. All options that require special handling (including invalid + // instruction) are handled by the next branch. + InstOptions options = InstOptions(instId - 1 >= Inst::_kIdCount - 1) | InstOptions((size_t)(_bufferEnd - writer.cursor()) < 4) | instOptions() | forcedInstOptions(); + + CondCode instCC = BaseInst::extractARMCondCode(instId); + instId = instId & uint32_t(InstIdParts::kRealId); + + if (instId >= Inst::_kIdCount) + instId = 0; + + const InstDB::InstInfo* instInfo = &InstDB::_instInfoTable[instId]; + uint32_t encodingIndex = instInfo->_encodingDataIndex; + + Opcode opcode; + uint32_t isign4; + uint32_t instFlags; + + const Operand_& o3 = opExt[EmitterUtils::kOp3]; + const Operand_* rmRel = nullptr; + + uint32_t multipleOpData[4]; + uint32_t multipleOpCount; + + // These are only used when instruction uses a relative displacement. + OffsetFormat offsetFormat; // Offset format. + uint64_t offsetValue; // Offset value (if known). + + if (ASMJIT_UNLIKELY(Support::test(options, kRequiresSpecialHandling))) { + if (ASMJIT_UNLIKELY(!_code)) + return reportError(DebugUtils::errored(kErrorNotInitialized)); + + // Unknown instruction. + if (ASMJIT_UNLIKELY(instId == 0)) + goto InvalidInstruction; + + // Condition code can only be used with 'B' instruction. + if (ASMJIT_UNLIKELY(instCC != CondCode::kAL && instId != Inst::kIdB)) + goto InvalidInstruction; + + // Grow request, happens rarely. + err = writer.ensureSpace(this, 4); + if (ASMJIT_UNLIKELY(err)) + goto Failed; + +#ifndef ASMJIT_NO_VALIDATION + // Strict validation. + if (hasDiagnosticOption(DiagnosticOptions::kValidateAssembler)) { + Operand_ opArray[Globals::kMaxOpCount]; + EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); + + err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); + if (ASMJIT_UNLIKELY(err)) + goto Failed; + } +#endif + } + + // Signature of the first 4 operands. + isign4 = (uint32_t(o0.opType()) ) + + (uint32_t(o1.opType()) << 3) + + (uint32_t(o2.opType()) << 6) + + (uint32_t(o3.opType()) << 9); + instFlags = instInfo->flags(); + + switch (instInfo->_encoding) { + // ------------------------------------------------------------------------ + // [Base - Universal] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBaseOp: { + const InstDB::EncodingData::BaseOp& opData = InstDB::EncodingData::baseOp[encodingIndex]; + + if (isign4 == 0) { + opcode.reset(opData.opcode); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseOpImm: { + const InstDB::EncodingData::BaseOpImm& opData = InstDB::EncodingData::baseOpImm[encodingIndex]; + + if (isign4 == ENC_OPS1(Imm)) { + uint64_t imm = o0.as<Imm>().valueAs<uint64_t>(); + uint32_t immMax = 1u << opData.immBits; + + if (imm >= immMax) + goto InvalidImmediate; + + opcode.reset(opData.opcode); + opcode.addImm(imm, opData.immOffset); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseR: { + const InstDB::EncodingData::BaseR& opData = InstDB::EncodingData::baseR[encodingIndex]; + + if (isign4 == ENC_OPS1(Reg)) { + if (!checkGpType(o0, opData.rType)) + goto InvalidInstruction; + + if (!checkGpId(o0, opData.rHiId)) + goto InvalidPhysId; + + opcode.reset(opData.opcode); + opcode.addReg(o0, opData.rShift); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseRR: { + const InstDB::EncodingData::BaseRR& opData = InstDB::EncodingData::baseRR[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + uint32_t x; + if (!checkGpType(o0, opData.aType, &x)) + goto InvalidInstruction; + + if (!checkGpType(o1, opData.bType)) + goto InvalidInstruction; + + if (opData.uniform && !checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!checkGpId(o0, opData.aHiId)) + goto InvalidPhysId; + + if (!checkGpId(o1, opData.bHiId)) + goto InvalidPhysId; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addReg(o1, opData.bShift); + opcode.addReg(o0, opData.aShift); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseRRR: { + const InstDB::EncodingData::BaseRRR& opData = InstDB::EncodingData::baseRRR[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + uint32_t x; + if (!checkGpType(o0, opData.aType, &x)) + goto InvalidInstruction; + + if (!checkGpType(o1, opData.bType)) + goto InvalidInstruction; + + if (!checkGpType(o2, opData.cType)) + goto InvalidInstruction; + + if (opData.uniform && !checkSignature(o0, o1, o2)) + goto InvalidInstruction; + + if (!checkGpId(o0, opData.aHiId)) + goto InvalidPhysId; + + if (!checkGpId(o1, opData.bHiId)) + goto InvalidPhysId; + + if (!checkGpId(o2, opData.cHiId)) + goto InvalidPhysId; + + opcode.reset(opData.opcode()); + opcode.addImm(x, 31); + opcode.addReg(o2, 16); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseRRRR: { + const InstDB::EncodingData::BaseRRRR& opData = InstDB::EncodingData::baseRRRR[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { + uint32_t x; + if (!checkGpType(o0, opData.aType, &x)) + goto InvalidInstruction; + + if (!checkGpType(o1, opData.bType)) + goto InvalidInstruction; + + if (!checkGpType(o2, opData.cType)) + goto InvalidInstruction; + + if (!checkGpType(o3, opData.dType)) + goto InvalidInstruction; + + if (opData.uniform && !checkSignature(o0, o1, o2, o3)) + goto InvalidInstruction; + + if (!checkGpId(o0, opData.aHiId)) + goto InvalidPhysId; + + if (!checkGpId(o1, opData.bHiId)) + goto InvalidPhysId; + + if (!checkGpId(o2, opData.cHiId)) + goto InvalidPhysId; + + if (!checkGpId(o3, opData.dHiId)) + goto InvalidPhysId; + + opcode.reset(opData.opcode()); + opcode.addImm(x, 31); + opcode.addReg(o2, 16); + opcode.addReg(o3, 10); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseRRII: { + const InstDB::EncodingData::BaseRRII& opData = InstDB::EncodingData::baseRRII[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { + if (!checkGpType(o0, opData.aType)) + goto InvalidInstruction; + + if (!checkGpType(o1, opData.bType)) + goto InvalidInstruction; + + if (!checkGpId(o0, opData.aHiId)) + goto InvalidPhysId; + + if (!checkGpId(o1, opData.bHiId)) + goto InvalidPhysId; + + if (o2.as<Imm>().valueAs<uint64_t>() >= Support::bitMask(opData.aImmSize + opData.aImmDiscardLsb) || + o3.as<Imm>().valueAs<uint64_t>() >= Support::bitMask(opData.bImmSize + opData.bImmDiscardLsb)) + goto InvalidImmediate; + + uint32_t aImm = o2.as<Imm>().valueAs<uint32_t>() >> opData.aImmDiscardLsb; + uint32_t bImm = o3.as<Imm>().valueAs<uint32_t>() >> opData.bImmDiscardLsb; + + if ((aImm << opData.aImmDiscardLsb) != o2.as<Imm>().valueAs<uint32_t>() || + (bImm << opData.bImmDiscardLsb) != o3.as<Imm>().valueAs<uint32_t>()) + goto InvalidImmediate; + + opcode.reset(opData.opcode()); + opcode.addImm(aImm, opData.aImmOffset); + opcode.addImm(bImm, opData.bImmOffset); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + // ------------------------------------------------------------------------ + // [Base - Mov] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBaseMov: { + // MOV is a pseudo instruction that uses various instructions depending on its signature. + uint32_t x = diff(o0.as<Reg>().type(), RegType::kARM_GpW); + if (x > 1) + goto InvalidInstruction; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + if (!o0.as<Reg>().isGp()) + goto InvalidInstruction; + + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP(); + if (hasSP) { + // Cannot be combined with ZR. + if (!checkGpId(o0, o1, kSP)) + goto InvalidPhysId; + + // MOV Rd, Rm -> ADD Rd, Rn, #0. + opcode.reset(0b00010001000000000000000000000000); + opcode.addImm(x, 31); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + else { + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + // MOV Rd, Rm -> ORR Rd, <ZR>, Rm. + opcode.reset(0b00101010000000000000001111100000); + opcode.addImm(x, 31); + opcode.addReg(o1, 16); + opcode.addReg(o0, 0); + goto EmitOp; + } + } + + if (isign4 == ENC_OPS2(Reg, Imm)) { + if (!o0.as<Reg>().isGp()) + goto InvalidInstruction; + + uint64_t immValue = o1.as<Imm>().valueAs<uint64_t>(); + if (!x) + immValue &= 0xFFFFFFFFu; + + // Prefer a single MOVN/MOVZ instruction over a logical instruction. + multipleOpCount = encodeMovSequence64(multipleOpData, immValue, o0.id() & 31, x); + if (multipleOpCount == 1 && !o0.as<Gp>().isSP()) { + opcode.reset(multipleOpData[0]); + goto EmitOp; + } + + // Logical instructions use 13-bit immediate pattern encoded as N:ImmR:ImmS. + LogicalImm logicalImm; + if (!o0.as<Gp>().isZR()) { + if (Utils::encodeLogicalImm(immValue, x ? 64 : 32, &logicalImm)) { + if (!checkGpId(o0, kSP)) + goto InvalidPhysId; + + opcode.reset(0b00110010000000000000001111100000); + opcode.addImm(x, 31); + opcode.addLogicalImm(logicalImm); + opcode.addReg(o0, 0); + goto EmitOp; + } + } + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + goto EmitOp_Multiple; + } + + break; + } + + case InstDB::kEncodingBaseMovKNZ: { + const InstDB::EncodingData::BaseMovKNZ& opData = InstDB::EncodingData::baseMovKNZ[encodingIndex]; + + uint32_t x = diff(o0.as<Reg>().type(), RegType::kARM_GpW); + if (x > 1) + goto InvalidInstruction; + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + + if (isign4 == ENC_OPS2(Reg, Imm)) { + uint64_t imm16 = o1.as<Imm>().valueAs<uint64_t>(); + if (imm16 > 0xFFFFu) + goto InvalidImmediate; + + opcode.addImm(imm16, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + if (isign4 == ENC_OPS3(Reg, Imm, Imm)) { + uint64_t imm16 = o1.as<Imm>().valueAs<uint64_t>(); + uint32_t shiftType = o2.as<Imm>().predicate(); + uint64_t shiftValue = o2.as<Imm>().valueAs<uint64_t>(); + + if (imm16 > 0xFFFFu || shiftValue > 48 || shiftType != uint32_t(ShiftOp::kLSL)) + goto InvalidImmediate; + + // Convert shift value to 'hw' field. + uint32_t hw = uint32_t(shiftValue) >> 4; + if ((hw << 4) != uint32_t(shiftValue)) + goto InvalidImmediate; + + opcode.addImm(hw, 21); + opcode.addImm(imm16, 5); + opcode.addReg(o0, 0); + + if (!x && hw > 1u) + goto InvalidImmediate; + + goto EmitOp; + } + + break; + } + + // ------------------------------------------------------------------------ + // [Base - Adr] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBaseAdr: { + const InstDB::EncodingData::BaseAdr& opData = InstDB::EncodingData::baseAdr[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Label) || isign4 == ENC_OPS2(Reg, Imm)) { + if (!o0.as<Reg>().isGpX()) + goto InvalidInstruction; + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + opcode.reset(opData.opcode()); + opcode.addReg(o0, 0); + offsetFormat.resetToImmValue(opData.offsetType, 4, 5, 21, 0); + + if (instId == Inst::kIdAdrp) + offsetFormat._immDiscardLsb = 12; + + rmRel = &o1; + goto EmitOp_Rel; + } + + break; + } + + // ------------------------------------------------------------------------ + // [Base - Arithmetic and Logical] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBaseAddSub: { + const InstDB::EncodingData::BaseAddSub& opData = InstDB::EncodingData::baseAddSub[encodingIndex]; + + uint32_t x; + if (!checkGpType(o0, o1, kWX, &x)) + goto InvalidInstruction; + + if (isign4 == ENC_OPS3(Reg, Reg, Imm) || isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { + opcode.reset(uint32_t(opData.immediateOp) << 24); + + // ADD | SUB (immediate) - ZR is not allowed. + // ADDS|SUBS (immediate) - ZR allowed in Rd, SP allowed in Rn. + uint32_t aHiId = opcode.get() & B(29) ? kZR : kSP; + uint32_t bHiId = kSP; + + if (!checkGpId(o0, aHiId) || !checkGpId(o1, bHiId)) + goto InvalidPhysId; + + // ADD|SUB (immediate) use 12-bit immediate optionally shifted by 'LSL #12'. + uint64_t imm = o2.as<Imm>().valueAs<uint64_t>(); + uint32_t shift = 0; + + if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { + if (o3.as<Imm>().predicate() != uint32_t(ShiftOp::kLSL)) + goto InvalidImmediate; + + if (o3.as<Imm>().value() != 0 && o3.as<Imm>().value() != 12) + goto InvalidImmediate; + + shift = uint32_t(o3.as<Imm>().value() != 0); + } + + // Accept immediate value of '0x00XXX000' by setting 'shift' to 12. + if (imm > 0xFFFu) { + if (shift || (imm & ~uint64_t(0xFFFu << 12)) != 0) + goto InvalidImmediate; + shift = 1; + imm >>= 12; + } + + opcode.addImm(x, 31); + opcode.addImm(shift, 22); + opcode.addImm(imm, 10); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { + if (!checkSignature(o1, o2)) + goto InvalidInstruction; + + uint32_t opSize = x ? 64 : 32; + uint64_t shift = 0; + uint32_t sType = uint32_t(ShiftOp::kLSL); + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { + sType = o3.as<Imm>().predicate(); + shift = o3.as<Imm>().valueAs<uint64_t>(); + } + + if (!checkGpId(o2, kZR)) + goto InvalidPhysId; + + // Shift operation - LSL, LSR, ASR. + if (sType <= uint32_t(ShiftOp::kASR)) { + bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP(); + if (!hasSP) { + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + if (shift >= opSize) + goto InvalidImmediate; + + opcode.reset(uint32_t(opData.shiftedOp) << 21); + opcode.addImm(x, 31); + opcode.addImm(sType, 22); + opcode.addReg(o2, 16); + opcode.addImm(shift, 10); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + // SP register can only be used with LSL or Extend. + if (sType != uint32_t(ShiftOp::kLSL)) + goto InvalidImmediate; + sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW); + } + + // Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX. + opcode.reset(uint32_t(opData.extendedOp) << 21); + sType -= uint32_t(ShiftOp::kUXTB); + + if (sType > 7 || shift > 4) + goto InvalidImmediate; + + if (!(opcode.get() & B(29))) { + // ADD|SUB (extend) - ZR is not allowed. + if (!checkGpId(o0, o1, kSP)) + goto InvalidPhysId; + } + else { + // ADDS|SUBS (extend) - ZR allowed in Rd, SP allowed in Rn. + if (!checkGpId(o0, kZR) || !checkGpId(o1, kSP)) + goto InvalidPhysId; + } + + opcode.addImm(x, 31); + opcode.addReg(o2, 16); + opcode.addImm(sType, 13); + opcode.addImm(shift, 10); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseLogical: { + const InstDB::EncodingData::BaseLogical& opData = InstDB::EncodingData::baseLogical[encodingIndex]; + + uint32_t x; + if (!checkGpType(o0, o1, kWX, &x)) + goto InvalidInstruction; + + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + uint32_t opSize = x ? 64 : 32; + + if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp != 0) { + opcode.reset(uint32_t(opData.immediateOp) << 23); + + // AND|ANDS|BIC|BICS|ORR|EOR (immediate) uses a LogicalImm format described by N:R:S values. + uint64_t immMask = Support::lsbMask<uint64_t>(opSize); + uint64_t immValue = o2.as<Imm>().valueAs<uint64_t>(); + + if (opData.negateImm) + immValue ^= immMask; + + // Logical instructions use 13-bit immediate pattern encoded as N:ImmS:ImmR. + LogicalImm logicalImm; + if (!Utils::encodeLogicalImm(immValue & immMask, opSize, &logicalImm)) + goto InvalidImmediate; + + // AND|BIC|ORR|EOR (immediate) can have SP on destination, but ANDS|BICS (immediate) cannot. + uint32_t kOpANDS = 0x3 << 29; + bool isANDS = (opcode.get() & kOpANDS) == kOpANDS; + + if (!checkGpId(o0, isANDS ? kZR : kSP) || !checkGpId(o1, kZR)) + goto InvalidPhysId; + + opcode.addImm(x, 31); + opcode.addLogicalImm(logicalImm); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + if (!checkSignature(o1, o2)) + goto InvalidInstruction; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + if (!checkGpId(o0, o1, o2, kZR)) + goto InvalidPhysId; + + opcode.reset(uint32_t(opData.shiftedOp) << 21); + opcode.addImm(x, 31); + opcode.addReg(o2, 16); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { + if (!checkGpId(o0, o1, o2, kZR)) + goto InvalidPhysId; + + uint32_t shiftType = o3.as<Imm>().predicate(); + uint64_t opShift = o3.as<Imm>().valueAs<uint64_t>(); + + if (shiftType > 0x3 || opShift >= opSize) + goto InvalidImmediate; + + opcode.reset(uint32_t(opData.shiftedOp) << 21); + opcode.addImm(x, 31); + opcode.addImm(shiftType, 22); + opcode.addReg(o2, 16); + opcode.addImm(opShift, 10); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseCmpCmn: { + const InstDB::EncodingData::BaseCmpCmn& opData = InstDB::EncodingData::baseCmpCmn[encodingIndex]; + + uint32_t x; + if (!checkGpType(o0, kWX, &x)) + goto InvalidInstruction; + + if (isign4 == ENC_OPS2(Reg, Imm)) { + // CMN|CMP (immediate) - ZR is not allowed. + if (!checkGpId(o0, kSP)) + goto InvalidPhysId; + + // CMN|CMP (immediate) use 12-bit immediate optionally shifted by 'LSL #12'. + const Imm& imm12 = o1.as<Imm>(); + uint32_t immShift = 0; + uint64_t immValue = imm12.valueAs<uint64_t>(); + + if (immValue > 0xFFFu) { + if ((immValue & ~uint64_t(0xFFFu << 12)) != 0) + goto InvalidImmediate; + immShift = 1; + immValue >>= 12; + } + + opcode.reset(uint32_t(opData.immediateOp) << 24); + opcode.addImm(x, 31); + opcode.addImm(immShift, 22); + opcode.addImm(immValue, 10); + opcode.addReg(o0, 5); + opcode.addReg(Gp::kIdZr, 0); + goto EmitOp; + } + + if (isign4 == ENC_OPS2(Reg, Reg) || isign4 == ENC_OPS3(Reg, Reg, Imm)) { + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + uint32_t opSize = x ? 64 : 32; + uint32_t sType = 0; + uint64_t shift = 0; + + if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { + sType = o2.as<Imm>().predicate(); + shift = o2.as<Imm>().valueAs<uint64_t>(); + } + + bool hasSP = o0.as<Gp>().isSP() || o1.as<Gp>().isSP(); + + // Shift operation - LSL, LSR, ASR. + if (sType <= uint32_t(ShiftOp::kASR)) { + if (!hasSP) { + if (shift >= opSize) + goto InvalidImmediate; + + opcode.reset(uint32_t(opData.shiftedOp) << 21); + opcode.addImm(x, 31); + opcode.addImm(sType, 22); + opcode.addReg(o1, 16); + opcode.addImm(shift, 10); + opcode.addReg(o0, 5); + opcode.addReg(Gp::kIdZr, 0); + goto EmitOp; + } + + // SP register can only be used with LSL or Extend. + if (sType != uint32_t(ShiftOp::kLSL)) + goto InvalidImmediate; + + sType = x ? uint32_t(ShiftOp::kUXTX) : uint32_t(ShiftOp::kUXTW); + } + + // Extend operation - UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX. + sType -= uint32_t(ShiftOp::kUXTB); + if (sType > 7 || shift > 4) + goto InvalidImmediate; + + opcode.reset(uint32_t(opData.extendedOp) << 21); + opcode.addImm(x, 31); + opcode.addReg(o1, 16); + opcode.addImm(sType, 13); + opcode.addImm(shift, 10); + opcode.addReg(o0, 5); + opcode.addReg(Gp::kIdZr, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseMvnNeg: { + const InstDB::EncodingData::BaseMvnNeg& opData = InstDB::EncodingData::baseMvnNeg[encodingIndex]; + + uint32_t x; + if (!checkGpType(o0, o1, kWX, &x)) + goto InvalidInstruction; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addReg(o1, 16); + opcode.addReg(o0, 0); + + if (isign4 == ENC_OPS2(Reg, Reg)) { + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + goto EmitOp; + } + + if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + uint32_t opSize = x ? 64 : 32; + uint32_t shiftType = o2.as<Imm>().predicate(); + uint64_t opShift = o2.as<Imm>().valueAs<uint64_t>(); + + if (shiftType > uint32_t(ShiftOp::kROR) || opShift >= opSize) + goto InvalidImmediate; + + opcode.addImm(shiftType, 22); + opcode.addImm(opShift, 10); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseTst: { + const InstDB::EncodingData::BaseTst& opData = InstDB::EncodingData::baseTst[encodingIndex]; + + uint32_t x; + if (!checkGpType(o0, kWX, &x)) + goto InvalidInstruction; + + uint32_t opSize = x ? 64 : 32; + + if (isign4 == ENC_OPS2(Reg, Imm) && opData.immediateOp != 0) { + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + // TST (immediate) uses a LogicalImm format described by N:R:S values. + uint64_t immMask = Support::lsbMask<uint64_t>(opSize); + uint64_t immValue = o1.as<Imm>().valueAs<uint64_t>(); + + // Logical instructions use 13-bit immediate pattern encoded as N:ImmS:ImmR. + LogicalImm logicalImm; + if (!Utils::encodeLogicalImm(immValue & immMask, opSize, &logicalImm)) + goto InvalidImmediate; + + opcode.reset(uint32_t(opData.immediateOp) << 22); + opcode.addLogicalImm(logicalImm); + opcode.addImm(x, 31); + opcode.addReg(o0, 5); + opcode.addReg(Gp::kIdZr, 0); + goto EmitOp; + } + + opcode.reset(uint32_t(opData.shiftedOp) << 21); + opcode.addImm(x, 31); + opcode.addReg(o1, 16); + opcode.addReg(o0, 5); + opcode.addReg(Gp::kIdZr, 0); + + if (isign4 == ENC_OPS2(Reg, Reg)) { + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + goto EmitOp; + } + + if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + uint32_t shiftType = o2.as<Imm>().predicate(); + uint64_t opShift = o2.as<Imm>().valueAs<uint64_t>(); + + if (shiftType > 0x3 || opShift >= opSize) + goto InvalidImmediate; + + opcode.addImm(shiftType, 22); + opcode.addImm(opShift, 10); + goto EmitOp; + } + + break; + } + + // ------------------------------------------------------------------------ + // [Base - Bit Manipulation] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBaseBfc: { + const InstDB::EncodingData::BaseBfc& opData = InstDB::EncodingData::baseBfc[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Imm, Imm)) { + uint32_t x; + if (!checkGpType(o0, InstDB::kWX, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0)) + goto InvalidPhysId; + + uint64_t lsb = o1.as<Imm>().valueAs<uint64_t>(); + uint64_t width = o2.as<Imm>().valueAs<uint64_t>(); + uint32_t opSize = x ? 64 : 32; + + if (lsb >= opSize || width == 0 || width > opSize) + goto InvalidImmediate; + + uint32_t lsb32 = Support::neg(uint32_t(lsb)) & (opSize - 1); + uint32_t width32 = uint32_t(width) - 1; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addImm(x, 22); + opcode.addImm(lsb32, 16); + opcode.addImm(width32, 10); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseBfi: { + const InstDB::EncodingData::BaseBfi& opData = InstDB::EncodingData::baseBfi[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { + uint32_t x; + if (!checkGpType(o0, InstDB::kWX, &x)) + goto InvalidInstruction; + + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1)) + goto InvalidPhysId; + + uint64_t lsb = o2.as<Imm>().valueAs<uint64_t>(); + uint64_t width = o3.as<Imm>().valueAs<uint64_t>(); + uint32_t opSize = x ? 64 : 32; + + if (lsb >= opSize || width == 0 || width > opSize) + goto InvalidImmediate; + + uint32_t lImm = Support::neg(uint32_t(lsb)) & (opSize - 1); + uint32_t wImm = uint32_t(width) - 1; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addImm(x, 22); + opcode.addImm(lImm, 16); + opcode.addImm(wImm, 10); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseBfm: { + const InstDB::EncodingData::BaseBfm& opData = InstDB::EncodingData::baseBfm[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { + uint32_t x; + if (!checkGpType(o0, InstDB::kWX, &x)) + goto InvalidInstruction; + + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1)) + goto InvalidPhysId; + + uint64_t immR = o2.as<Imm>().valueAs<uint64_t>(); + uint64_t immS = o3.as<Imm>().valueAs<uint64_t>(); + uint32_t opSize = x ? 64 : 32; + + if ((immR | immS) >= opSize) + goto InvalidImmediate; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addImm(x, 22); + opcode.addImm(immR, 16); + opcode.addImm(immS, 10); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseBfx: { + const InstDB::EncodingData::BaseBfx& opData = InstDB::EncodingData::baseBfx[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { + uint32_t x; + if (!checkGpType(o0, InstDB::kWX, &x)) + goto InvalidInstruction; + + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1)) + goto InvalidPhysId; + + uint64_t lsb = o2.as<Imm>().valueAs<uint64_t>(); + uint64_t width = o3.as<Imm>().valueAs<uint64_t>(); + uint32_t opSize = x ? 64 : 32; + + if (lsb >= opSize || width == 0 || width > opSize) + goto InvalidImmediate; + + uint32_t lsb32 = uint32_t(lsb); + uint32_t width32 = lsb32 + uint32_t(width) - 1u; + + if (width32 >= opSize) + goto InvalidImmediate; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addImm(x, 22); + opcode.addImm(lsb32, 16); + opcode.addImm(width32, 10); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseExtend: { + const InstDB::EncodingData::BaseExtend& opData = InstDB::EncodingData::baseExtend[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + uint32_t x; + if (!checkGpType(o0, opData.rType, &x)) + goto InvalidInstruction; + + if (!o1.as<Reg>().isGpW()) + goto InvalidInstruction; + + if (!checkGpId(o0, o1)) + goto InvalidPhysId; + + opcode.reset(opData.opcode()); + opcode.addImm(x, 31); + opcode.addImm(x, 22); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseExtract: { + const InstDB::EncodingData::BaseExtract& opData = InstDB::EncodingData::baseExtract[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { + uint32_t x; + if (!checkGpType(o0, kWX, &x)) + goto InvalidInstruction; + + if (!checkSignature(o0, o1, o2)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1, o2)) + goto InvalidPhysId; + + uint64_t lsb = o3.as<Imm>().valueAs<uint64_t>(); + uint32_t opSize = x ? 64 : 32; + + if (lsb >= opSize) + goto InvalidImmediate; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addImm(x, 22); + opcode.addReg(o2, 16); + opcode.addImm(lsb, 10); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseRev: { + if (isign4 == ENC_OPS2(Reg, Reg)) { + uint32_t x; + if (!checkGpType(o0, InstDB::kWX, &x)) + goto InvalidInstruction; + + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1)) + goto InvalidPhysId; + + opcode.reset(0b01011010110000000000100000000000); + opcode.addImm(x, 31); + opcode.addImm(x, 10); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseShift: { + const InstDB::EncodingData::BaseShift& opData = InstDB::EncodingData::baseShift[encodingIndex]; + + uint32_t x; + if (!checkGpType(o0, kWX, &x)) + goto InvalidInstruction; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + if (!checkSignature(o0, o1, o2)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1, o2, kZR)) + goto InvalidPhysId; + + opcode.reset(opData.registerOp()); + opcode.addImm(x, 31); + opcode.addReg(o2, 16); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp()) { + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + uint64_t immR = o2.as<Imm>().valueAs<uint64_t>(); + uint32_t opSize = x ? 64 : 32; + + if (immR >= opSize) + goto InvalidImmediate; + + opcode.reset(opData.immediateOp()); + opcode.addImm(x, 31); + opcode.addImm(x, 22); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + + if (opcode.get() & B(10)) { + // ASR and LSR (immediate) has the same logic. + opcode.addImm(x, 15); + opcode.addImm(immR, 16); + goto EmitOp; + } + + if (opData.ror == 0) { + // LSL (immediate) is an alias to UBFM + uint32_t ubfmImmR = Support::neg(uint32_t(immR)) & (opSize - 1); + uint32_t ubfmImmS = opSize - 1 - uint32_t(immR); + + opcode.addImm(ubfmImmR, 16); + opcode.addImm(ubfmImmS, 10); + goto EmitOp; + } + else { + // ROR (immediate) is an alias to EXTR. + opcode.addImm(immR, 10); + opcode.addReg(o1, 16); + goto EmitOp; + } + } + + break; + } + + // ------------------------------------------------------------------------ + // [Base - Conditionals] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBaseCCmp: { + const InstDB::EncodingData::BaseCCmp& opData = InstDB::EncodingData::baseCCmp[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm) || isign4 == ENC_OPS4(Reg, Imm, Imm, Imm)) { + uint32_t x; + if (!checkGpType(o0, InstDB::kWX, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + uint64_t nzcv = o2.as<Imm>().valueAs<uint64_t>(); + uint64_t cond = o3.as<Imm>().valueAs<uint64_t>(); + + if ((nzcv | cond) > 0xFu) + goto InvalidImmediate; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12); + opcode.addImm(nzcv, 0); + + if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { + // CCMN|CCMP (register) form. + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!checkGpId(o1, kZR)) + goto InvalidPhysId; + + opcode.addReg(o1, 16); + opcode.addReg(o0, 5); + goto EmitOp; + } + else { + // CCMN|CCMP (immediate) form. + uint64_t imm5 = o1.as<Imm>().valueAs<uint64_t>(); + if (imm5 > 0x1F) + goto InvalidImmediate; + + opcode.addImm(1, 11); + opcode.addImm(imm5, 16); + opcode.addReg(o0, 5); + goto EmitOp; + } + } + + break; + } + + case InstDB::kEncodingBaseCInc: { + const InstDB::EncodingData::BaseCInc& opData = InstDB::EncodingData::baseCInc[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { + uint32_t x; + if (!checkGpType(o0, o1, InstDB::kWX, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + uint64_t cond = o2.as<Imm>().valueAs<uint64_t>(); + if (cond - 2u > 0xEu) + goto InvalidImmediate; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addReg(o1, 16); + opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)) ^ 1u, 12); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseCSel: { + const InstDB::EncodingData::BaseCSel& opData = InstDB::EncodingData::baseCSel[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { + uint32_t x; + if (!checkGpType(o0, o1, o2, InstDB::kWX, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1, o2, kZR)) + goto InvalidPhysId; + + uint64_t cond = o3.as<Imm>().valueAs<uint64_t>(); + if (cond > 0xFu) + goto InvalidImmediate; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addReg(o2, 16); + opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12); + opcode.addReg(o1, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseCSet: { + const InstDB::EncodingData::BaseCSet& opData = InstDB::EncodingData::baseCSet[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Imm)) { + uint32_t x; + if (!checkGpType(o0, InstDB::kWX, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + uint64_t cond = o1.as<Imm>().valueAs<uint64_t>(); + if (cond - 2u >= 0xEu) + goto InvalidImmediate; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)) ^ 1u, 12); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + // ------------------------------------------------------------------------ + // [Base - Special] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBaseAtDcIcTlbi: { + const InstDB::EncodingData::BaseAtDcIcTlbi& opData = InstDB::EncodingData::baseAtDcIcTlbi[encodingIndex]; + + if (isign4 == ENC_OPS1(Imm) || isign4 == ENC_OPS2(Imm, Reg)) { + if (opData.mandatoryReg && isign4 != ENC_OPS2(Imm, Reg)) + goto InvalidInstruction; + + if (o0.as<Imm>().valueAs<uint64_t>() > 0x7FFFu) + goto InvalidImmediate; + + uint32_t imm = o0.as<Imm>().valueAs<uint32_t>(); + if ((imm & opData.immVerifyMask) != opData.immVerifyData) + goto InvalidImmediate; + + uint32_t rt = 31; + if (o1.isReg()) { + if (!o1.as<Reg>().isGpX()) + goto InvalidInstruction; + + if (!checkGpId(o1, kZR)) + goto InvalidPhysId; + + rt = o1.id() & 31; + } + + opcode.reset(0b11010101000010000000000000000000); + opcode.addImm(imm, 5); + opcode.addReg(rt, 0); + goto EmitOp; + } + break; + } + + case InstDB::kEncodingBaseMrs: { + if (isign4 == ENC_OPS2(Reg, Imm)) { + if (!o0.as<Reg>().isGpX()) + goto InvalidInstruction; + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + if (o1.as<Imm>().valueAs<uint64_t>() > 0xFFFFu) + goto InvalidImmediate; + + uint32_t imm = o1.as<Imm>().valueAs<uint32_t>(); + if (!(imm & B(15))) + goto InvalidImmediate; + + opcode.reset(0b11010101001100000000000000000000); + opcode.addImm(imm, 5); + opcode.addReg(o0, 0); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseMsr: { + if (isign4 == ENC_OPS2(Imm, Reg)) { + if (!o1.as<Reg>().isGpX()) + goto InvalidInstruction; + + if (o0.as<Imm>().valueAs<uint64_t>() > 0xFFFFu) + goto InvalidImmediate; + + uint32_t imm = o0.as<Imm>().valueAs<uint32_t>(); + if (!(imm & B(15))) + goto InvalidImmediate; + + if (!checkGpId(o1, kZR)) + goto InvalidPhysId; + + opcode.reset(0b11010101000100000000000000000000); + opcode.addImm(imm, 5); + opcode.addReg(o1, 0); + goto EmitOp; + } + + if (isign4 == ENC_OPS2(Imm, Imm)) { + if (o0.as<Imm>().valueAs<uint64_t>() > 0x1Fu) + goto InvalidImmediate; + + if (o1.as<Imm>().valueAs<uint64_t>() > 0xFu) + goto InvalidImmediate; + + uint32_t op = o0.as<Imm>().valueAs<uint32_t>(); + uint32_t cRm = o1.as<Imm>().valueAs<uint32_t>(); + + uint32_t op1 = uint32_t(op) >> 3; + uint32_t op2 = uint32_t(op) & 0x7u; + + opcode.reset(0b11010101000000000100000000011111); + opcode.addImm(op1, 16); + opcode.addImm(cRm, 8); + opcode.addImm(op2, 5); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseSys: { + if (isign4 == ENC_OPS4(Imm, Imm, Imm, Imm)) { + if (o0.as<Imm>().valueAs<uint64_t>() > 0x7u || + o1.as<Imm>().valueAs<uint64_t>() > 0xFu || + o2.as<Imm>().valueAs<uint64_t>() > 0xFu || + o3.as<Imm>().valueAs<uint64_t>() > 0x7u) + goto InvalidImmediate; + + uint32_t op1 = o0.as<Imm>().valueAs<uint32_t>(); + uint32_t cRn = o1.as<Imm>().valueAs<uint32_t>(); + uint32_t cRm = o2.as<Imm>().valueAs<uint32_t>(); + uint32_t op2 = o3.as<Imm>().valueAs<uint32_t>(); + uint32_t rt = 31; + + const Operand_& o4 = opExt[EmitterUtils::kOp4]; + if (o4.isReg()) { + if (!o4.as<Reg>().isGpX()) + goto InvalidInstruction; + + if (!checkGpId(o4, kZR)) + goto InvalidPhysId; + + rt = o4.id() & 31; + } + else if (!o4.isNone()) { + goto InvalidInstruction; + } + + opcode.reset(0b11010101000010000000000000000000); + opcode.addImm(op1, 16); + opcode.addImm(cRn, 12); + opcode.addImm(cRm, 8); + opcode.addImm(op2, 5); + opcode.addImm(rt, 0); + goto EmitOp; + } + + break; + } + + // ------------------------------------------------------------------------ + // [Base - Branch] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBaseBranchReg: { + const InstDB::EncodingData::BaseBranchReg& opData = InstDB::EncodingData::baseBranchReg[encodingIndex]; + + if (isign4 == ENC_OPS1(Reg)) { + if (!o0.as<Reg>().isGpX()) + goto InvalidInstruction; + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + opcode.reset(opData.opcode); + opcode.addReg(o0, 5); + goto EmitOp; + } + + break; + } + + case InstDB::kEncodingBaseBranchRel: { + const InstDB::EncodingData::BaseBranchRel& opData = InstDB::EncodingData::baseBranchRel[encodingIndex]; + + if (isign4 == ENC_OPS1(Label) || isign4 == ENC_OPS1(Imm)) { + opcode.reset(opData.opcode); + rmRel = &o0; + + if (instCC != CondCode::kAL) { + opcode |= B(30); + opcode.addImm(condCodeToOpcodeCond(uint32_t(instCC)), 0); + offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); + goto EmitOp_Rel; + } + + offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 0, 26, 2); + goto EmitOp_Rel; + } + + break; + } + + case InstDB::kEncodingBaseBranchCmp: { + const InstDB::EncodingData::BaseBranchCmp& opData = InstDB::EncodingData::baseBranchCmp[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Label) || isign4 == ENC_OPS2(Reg, Imm)) { + uint32_t x; + if (!checkGpType(o0, kWX, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + opcode.reset(opData.opcode); + opcode.addImm(x, 31); + opcode.addReg(o0, 0); + offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); + + rmRel = &o1; + goto EmitOp_Rel; + } + + break; + } + + case InstDB::kEncodingBaseBranchTst: { + const InstDB::EncodingData::BaseBranchTst& opData = InstDB::EncodingData::baseBranchTst[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Imm, Label) || isign4 == ENC_OPS3(Reg, Imm, Imm)) { + uint32_t x; + if (!checkGpType(o0, kWX, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + uint64_t imm = o1.as<Imm>().valueAs<uint64_t>(); + + opcode.reset(opData.opcode); + if (imm >= 32) { + if (!x) + goto InvalidImmediate; + opcode.addImm(x, 31); + imm &= 0x1F; + } + + opcode.addReg(o0, 0); + opcode.addImm(imm, 19); + offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 14, 2); + + rmRel = &o2; + goto EmitOp_Rel; + } + + break; + } + + // ------------------------------------------------------------------------ + // [Base - Load / Store] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingBaseLdSt: { + const InstDB::EncodingData::BaseLdSt& opData = InstDB::EncodingData::baseLdSt[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Mem)) { + const Mem& m = o1.as<Mem>(); + rmRel = &m; + + uint32_t x; + if (!checkGpType(o0, opData.rType, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + // Instructions that work with either word or dword have the unsigned + // offset shift set to 2 (word), so we set it to 3 (dword) if this is + // X version of the instruction. + uint32_t xShiftMask = uint32_t(opData.uOffsetShift == 2); + uint32_t immShift = uint32_t(opData.uOffsetShift) + (x & xShiftMask); + + if (!armCheckMemBaseIndexRel(m)) + goto InvalidAddress; + + int64_t offset = m.offset(); + if (m.hasBaseReg()) { + // [Base {Offset | Index}] + if (m.hasIndex()) { + uint32_t opt = armShiftOpToLdStOptMap[m.predicate()]; + if (opt == 0xFF) + goto InvalidAddress; + + uint32_t shift = m.shift(); + uint32_t s = shift != 0; + + if (s && shift != immShift) + goto InvalidAddressScale; + + opcode.reset(uint32_t(opData.registerOp) << 21); + opcode.xorImm(x, opData.xOffset); + opcode.addImm(opt, 13); + opcode.addImm(s, 12); + opcode |= B(11); + opcode.addReg(o0, 0); + goto EmitOp_MemBaseIndex_Rn5_Rm16; + } + + // Makes it easier to work with the offset especially on 32-bit arch. + if (!Support::isInt32(offset)) + goto InvalidDisplacement; + int32_t offset32 = int32_t(offset); + + if (m.isPreOrPost()) { + if (!Support::isInt9(offset32)) + goto InvalidDisplacement; + + opcode.reset(uint32_t(opData.prePostOp) << 21); + opcode.xorImm(x, opData.xOffset); + opcode.addImm(offset32 & 0x1FF, 12); + opcode.addImm(m.isPreIndex(), 11); + opcode |= B(10); + opcode.addReg(o0, 0); + goto EmitOp_MemBase_Rn5; + } + else { + uint32_t imm12 = uint32_t(offset32) >> immShift; + + // Alternative form of LDUR/STUR and related instructions as described by AArch64 reference manual: + // + // If this instruction is not encodable with scaled unsigned offset, try unscaled signed offset. + if (!Support::isUInt12(imm12) || (imm12 << immShift) != uint32_t(offset32)) { + instId = opData.uAltInstId; + instInfo = &InstDB::_instInfoTable[instId]; + encodingIndex = instInfo->_encodingDataIndex; + goto Case_BaseLdurStur; + } + + opcode.reset(uint32_t(opData.uOffsetOp) << 22); + opcode.xorImm(x, opData.xOffset); + opcode.addImm(imm12, 10); + opcode.addReg(o0, 0); + goto EmitOp_MemBase_Rn5; + } + } + else { + if (!opData.literalOp) + goto InvalidAddress; + + opcode.reset(uint32_t(opData.literalOp) << 24); + opcode.xorImm(x, opData.xOffset); + opcode.addReg(o0, 0); + offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); + goto EmitOp_Rel; + } + } + + break; + } + + case InstDB::kEncodingBaseLdpStp: { + const InstDB::EncodingData::BaseLdpStp& opData = InstDB::EncodingData::baseLdpStp[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { + const Mem& m = o2.as<Mem>(); + rmRel = &m; + + uint32_t x; + if (!checkGpType(o0, o1, opData.rType, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + if (m.baseType() != RegType::kARM_GpX || m.hasIndex()) + goto InvalidAddress; + + if (m.isOffset64Bit()) + goto InvalidDisplacement; + + uint32_t offsetShift = opData.offsetShift + x; + int32_t offset32 = m.offsetLo32() >> offsetShift; + + // Make sure we didn't lose bits by applying the mandatory offset shift. + if (uint32_t(offset32) << offsetShift != uint32_t(m.offsetLo32())) + goto InvalidDisplacement; + + // Offset is encoded as 7-bit immediate. + if (!Support::isInt7(offset32)) + goto InvalidDisplacement; + + if (m.isPreOrPost() && offset32 != 0) { + if (!opData.prePostOp) + goto InvalidAddress; + + opcode.reset(uint32_t(opData.prePostOp) << 22); + opcode.addImm(m.isPreIndex(), 24); + } + else { + opcode.reset(uint32_t(opData.offsetOp) << 22); + } + + opcode.addImm(x, opData.xOffset); + opcode.addImm(offset32 & 0x7F, 15); + opcode.addReg(o1, 10); + opcode.addReg(o0, 0); + goto EmitOp_MemBase_Rn5; + } + + break; + } + + case InstDB::kEncodingBaseStx: { + const InstDB::EncodingData::BaseStx& opData = InstDB::EncodingData::baseStx[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { + const Mem& m = o2.as<Mem>(); + uint32_t x; + + if (!o0.as<Reg>().isGpW() || !checkGpType(o1, opData.rType, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + opcode.reset(opData.opcode()); + opcode.addImm(x, opData.xOffset); + opcode.addReg(o0, 16); + opcode.addReg(o1, 0); + + rmRel = &m; + goto EmitOp_MemBaseNoImm_Rn5; + } + + break; + } + + case InstDB::kEncodingBaseLdxp: { + const InstDB::EncodingData::BaseLdxp& opData = InstDB::EncodingData::baseLdxp[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { + const Mem& m = o2.as<Mem>(); + uint32_t x; + + if (!checkGpType(o0, opData.rType, &x) || !checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1, kZR)) + goto InvalidPhysId; + + opcode.reset(opData.opcode()); + opcode.addImm(x, opData.xOffset); + opcode.addReg(o1, 10); + opcode.addReg(o0, 0); + + rmRel = &m; + goto EmitOp_MemBaseNoImm_Rn5; + } + + break; + } + + case InstDB::kEncodingBaseStxp: { + const InstDB::EncodingData::BaseStxp& opData = InstDB::EncodingData::baseStxp[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem)) { + const Mem& m = o3.as<Mem>(); + uint32_t x; + + if (!o0.as<Reg>().isGpW() || !checkGpType(o1, opData.rType, &x) || !checkSignature(o1, o2)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1, o2, kZR)) + goto InvalidPhysId; + + opcode.reset(opData.opcode()); + opcode.addImm(x, opData.xOffset); + opcode.addReg(o0, 16); + opcode.addReg(o2, 10); + opcode.addReg(o1, 0); + + rmRel = &m; + goto EmitOp_MemBaseNoImm_Rn5; + } + + break; + } + + case InstDB::kEncodingBaseRM_NoImm: { + const InstDB::EncodingData::BaseRM_NoImm& opData = InstDB::EncodingData::baseRM_NoImm[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Mem)) { + const Mem& m = o1.as<Mem>(); + rmRel = &m; + + uint32_t x; + if (!checkGpType(o0, opData.rType, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, opData.rHiId)) + goto InvalidPhysId; + + opcode.reset(opData.opcode()); + opcode.addImm(x, opData.xOffset); + opcode.addReg(o0, 0); + goto EmitOp_MemBaseNoImm_Rn5; + } + + break; + } + + case InstDB::kEncodingBaseRM_SImm9: { +Case_BaseLdurStur: + const InstDB::EncodingData::BaseRM_SImm9& opData = InstDB::EncodingData::baseRM_SImm9[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Mem)) { + const Mem& m = o1.as<Mem>(); + rmRel = &m; + + uint32_t x; + if (!checkGpType(o0, opData.rType, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, opData.rHiId)) + goto InvalidPhysId; + + if (m.hasBaseReg() && !m.hasIndex()) { + if (m.isOffset64Bit()) + goto InvalidDisplacement; + + int32_t offset32 = m.offsetLo32() >> opData.immShift; + if (Support::shl(offset32, opData.immShift) != m.offsetLo32()) + goto InvalidDisplacement; + + if (!Support::isInt9(offset32)) + goto InvalidDisplacement; + + if (m.isFixedOffset()) { + opcode.reset(opData.offsetOp()); + } + else { + if (!opData.prePostOp()) + goto InvalidInstruction; + + opcode.reset(opData.prePostOp()); + opcode.xorImm(m.isPreIndex(), 11); + } + + opcode.xorImm(x, opData.xOffset); + opcode.addImm(offset32 & 0x1FF, 12); + opcode.addReg(o0, 0); + goto EmitOp_MemBase_Rn5; + } + + goto InvalidAddress; + } + + break; + } + + case InstDB::kEncodingBaseRM_SImm10: { + const InstDB::EncodingData::BaseRM_SImm10& opData = InstDB::EncodingData::baseRM_SImm10[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Mem)) { + const Mem& m = o1.as<Mem>(); + rmRel = &m; + + uint32_t x; + if (!checkGpType(o0, opData.rType, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, opData.rHiId)) + goto InvalidPhysId; + + if (m.hasBaseReg() && !m.hasIndex()) { + if (m.isOffset64Bit()) + goto InvalidDisplacement; + + int32_t offset32 = m.offsetLo32() >> opData.immShift; + if (Support::shl(offset32, opData.immShift) != m.offsetLo32()) + goto InvalidDisplacement; + + if (!Support::isInt10(offset32)) + goto InvalidDisplacement; + + if (m.isPostIndex()) + goto InvalidAddress; + + // Offset has 10 bits, sign is stored in the 10th bit. + offset32 &= 0x3FF; + + opcode.reset(opData.opcode()); + opcode.xorImm(m.isPreIndex(), 11); + opcode.xorImm(x, opData.xOffset); + opcode.addImm(offset32 >> 9, 22); + opcode.addImm(offset32, 12); + opcode.addReg(o0, 0); + goto EmitOp_MemBase_Rn5; + } + + goto InvalidAddress; + } + + break; + } + + case InstDB::kEncodingBaseAtomicOp: { + const InstDB::EncodingData::BaseAtomicOp& opData = InstDB::EncodingData::baseAtomicOp[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { + const Mem& m = o2.as<Mem>(); + uint32_t x; + + if (!checkGpType(o0, opData.rType, &x) || !checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!checkGpId(o0, o1, kZR)) + goto InvalidInstruction; + + opcode.reset(opData.opcode()); + opcode.addImm(x, opData.xOffset); + opcode.addReg(o0, 16); + opcode.addReg(o1, 0); + + rmRel = &m; + goto EmitOp_MemBaseNoImm_Rn5; + } + + break; + } + + case InstDB::kEncodingBaseAtomicSt: { + const InstDB::EncodingData::BaseAtomicSt& opData = InstDB::EncodingData::baseAtomicSt[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Mem)) { + const Mem& m = o1.as<Mem>(); + uint32_t x; + + if (!checkGpType(o0, opData.rType, &x)) + goto InvalidInstruction; + + if (!checkGpId(o0, kZR)) + goto InvalidPhysId; + + opcode.reset(opData.opcode()); + opcode.addImm(x, opData.xOffset); + opcode.addReg(o0, 16); + opcode.addReg(Gp::kIdZr, 0); + + rmRel = &m; + goto EmitOp_MemBaseNoImm_Rn5; + } + + break; + } + + case InstDB::kEncodingBaseAtomicCasp: { + const InstDB::EncodingData::BaseAtomicCasp& opData = InstDB::EncodingData::baseAtomicCasp[encodingIndex]; + const Operand_& o4 = opExt[EmitterUtils::kOp4]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg) && o4.isMem()) { + const Mem& m = o4.as<Mem>(); + uint32_t x; + + if (!checkGpType(o0, opData.rType, &x)) + goto InvalidInstruction; + + if (!checkSignature(o0, o1, o2, o3)) + goto InvalidInstruction; + + if (!checkEven(o0, o2) || !checkGpId(o0, o2, kZR)) + goto InvalidPhysId; + + if (!checkConsecutive(o0, o1) || !checkConsecutive(o2, o3)) + goto InvalidPhysId; + + opcode.reset(opData.opcode()); + opcode.addImm(x, opData.xOffset); + opcode.addReg(o0, 16); + opcode.addReg(o2, 0); + + rmRel = &m; + goto EmitOp_MemBaseNoImm_Rn5; + } + + break; + } + + // ------------------------------------------------------------------------ + // [FSimd - Instructions] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingFSimdSV: { + const InstDB::EncodingData::FSimdSV& opData = InstDB::EncodingData::fSimdSV[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + uint32_t q = diff(o1.as<Reg>().type(), RegType::kARM_VecD); + if (q > 1) + goto InvalidInstruction; + + if (o0.as<Vec>().hasElementType()) + goto InvalidInstruction; + + // This operation is only defined for: + // hD, vS.{4|8}h (16-bit) + // sD, vS.4s (32-bit) + uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); + uint32_t elementSz = o1.as<Vec>().elementType() - Vec::kElementTypeH; + + // Size greater than 1 means 64-bit elements, not supported. + if ((sz | elementSz) > 1 || sz != elementSz) + goto InvalidInstruction; + + // Size 1 (32-bit float) requires at least 4 elements. + if (sz && !q) + goto InvalidInstruction; + + // Bit flipping according to sz. + static const uint32_t szBits[] = { B(29), 0 }; + + opcode.reset(opData.opcode << 10); + opcode ^= szBits[sz]; + opcode.addImm(q, 30); + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingFSimdVV: { + const InstDB::EncodingData::FSimdVV& opData = InstDB::EncodingData::fSimdVV[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + if (!matchSignature(o0, o1, instFlags)) + goto InvalidInstruction; + + if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode)) + goto InvalidInstruction; + + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingFSimdVVV: { + const InstDB::EncodingData::FSimdVVV& opData = InstDB::EncodingData::fSimdVVV[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + if (!matchSignature(o0, o1, o2, instFlags)) + goto InvalidInstruction; + + if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode)) + goto InvalidInstruction; + + goto EmitOp_Rd0_Rn5_Rm16; + } + + break; + } + + case InstDB::kEncodingFSimdVVVe: { + const InstDB::EncodingData::FSimdVVVe& opData = InstDB::EncodingData::fSimdVVVe[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + if (!o2.as<Vec>().hasElementIndex()) { + if (!matchSignature(o0, o1, o2, instFlags)) + goto InvalidInstruction; + + if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode)) + goto InvalidInstruction; + + goto EmitOp_Rd0_Rn5_Rm16; + } + else { + if (!matchSignature(o0, o1, instFlags)) + goto InvalidInstruction; + + uint32_t q = o1.as<Reg>().isVecQ(); + uint32_t sz; + + if (!pickFpOpcode(o0.as<Vec>(), opData.elementScalarOp(), InstDB::kHF_D, opData.elementVectorOp(), InstDB::kHF_D, &opcode, &sz)) + goto InvalidInstruction; + + if (sz == 0 && o2.as<Reg>().id() > 15) + goto InvalidPhysId; + + uint32_t elementIndex = o2.as<Vec>().elementIndex(); + if (elementIndex > (7u >> sz)) + goto InvalidElementIndex; + + uint32_t hlm = elementIndex << sz; + opcode.addImm(q, 30); + opcode.addImm(hlm & 3u, 20); + opcode.addImm(hlm >> 2, 11); + goto EmitOp_Rd0_Rn5_Rm16; + } + } + + break; + } + + case InstDB::kEncodingFSimdVVVV: { + const InstDB::EncodingData::FSimdVVVV& opData = InstDB::EncodingData::fSimdVVVV[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { + if (!matchSignature(o0, o1, o2, o3, instFlags)) + goto InvalidInstruction; + + if (!pickFpOpcode(o0.as<Vec>(), opData.scalarOp(), opData.scalarHf(), opData.vectorOp(), opData.vectorHf(), &opcode)) + goto InvalidInstruction; + + goto EmitOp_Rd0_Rn5_Rm16_Ra10; + } + + break; + } + + case InstDB::kEncodingSimdFcadd: { + const InstDB::EncodingData::SimdFcadd& opData = InstDB::EncodingData::simdFcadd[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { + if (!checkSignature(o0, o1, o2) || o0.as<Vec>().hasElementIndex()) + goto InvalidInstruction; + + uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD); + if (q > 1) + goto InvalidInstruction; + + uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeB; + if (sz == 0 || sz > 3) + goto InvalidInstruction; + + // 0 <- 90deg. + // 1 <- 270deg. + uint32_t rot = 0; + if (o3.as<Imm>().value() == 270) + rot = 1; + else if (o3.as<Imm>().value() != 90) + goto InvalidImmediate; + + opcode.reset(opData.opcode()); + opcode.addImm(q, 30); + opcode.addImm(sz, 22); + opcode.addImm(rot, 12); + goto EmitOp_Rd0_Rn5_Rm16; + } + + break; + } + + case InstDB::kEncodingSimdFccmpFccmpe: { + const InstDB::EncodingData::SimdFccmpFccmpe& opData = InstDB::EncodingData::simdFccmpFccmpe[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) { + uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); + if (sz > 2) + goto InvalidInstruction; + + if (!checkSignature(o0, o1) || o0.as<Vec>().hasElementType()) + goto InvalidInstruction; + + uint64_t nzcv = o2.as<Imm>().valueAs<uint64_t>(); + uint64_t cond = o3.as<Imm>().valueAs<uint64_t>(); + + if ((nzcv | cond) > 0xFu) + goto InvalidImmediate; + + uint32_t type = (sz - 1) & 0x3u; + + opcode.reset(opData.opcode()); + opcode.addImm(type, 22); + opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12); + opcode.addImm(nzcv, 0); + + goto EmitOp_Rn5_Rm16; + } + + break; + } + + case InstDB::kEncodingSimdFcm: { + const InstDB::EncodingData::SimdFcm& opData = InstDB::EncodingData::simdFcm[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.hasRegisterOp()) { + if (!matchSignature(o0, o1, o2, instFlags)) + goto InvalidInstruction; + + if (!pickFpOpcode(o0.as<Vec>(), opData.registerScalarOp(), opData.registerScalarHf(), opData.registerVectorOp(), opData.registerVectorHf(), &opcode)) + goto InvalidInstruction; + + goto EmitOp_Rd0_Rn5_Rm16; + } + + if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.hasZeroOp()) { + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + if (o2.as<Imm>().value() != 0 || o2.as<Imm>().predicate() != 0) + goto InvalidImmediate; + + if (!pickFpOpcode(o0.as<Vec>(), opData.zeroScalarOp(), InstDB::kHF_B, opData.zeroVectorOp(), InstDB::kHF_B, &opcode)) + goto InvalidInstruction; + + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingSimdFcmla: { + const InstDB::EncodingData::SimdFcmla& opData = InstDB::EncodingData::simdFcmla[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD); + if (q > 1) + goto InvalidInstruction; + + uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeB; + if (sz == 0 || sz > 3) + goto InvalidInstruction; + + uint32_t rot = 0; + switch (o3.as<Imm>().value()) { + case 0 : rot = 0; break; + case 90 : rot = 1; break; + case 180: rot = 2; break; + case 270: rot = 3; break; + default: + goto InvalidImmediate; + } + + if (!o2.as<Vec>().hasElementIndex()) { + if (!checkSignature(o1, o2)) + goto InvalidInstruction; + + opcode.reset(opData.regularOp()); + opcode.addImm(q, 30); + opcode.addImm(sz, 22); + opcode.addImm(rot, 11); + goto EmitOp_Rd0_Rn5_Rm16; + } + else { + if (o0.as<Vec>().elementType() != o2.as<Vec>().elementType()) + goto InvalidInstruction; + + // Only allowed vectors are: 4H, 8H, and 4S. + if (!(sz == 1 || (q == 1 && sz == 2))) + goto InvalidInstruction; + + // Element index ranges: + // 4H - ElementIndex[0..1] (index 2..3 is UNDEFINED). + // 8H - ElementIndex[0..3]. + // 4S - ElementIndex[0..1]. + uint32_t elementIndex = o2.as<Vec>().elementIndex(); + uint32_t hlFieldShift = sz == 1 ? 0u : 1u; + uint32_t maxElementIndex = q == 1 && sz == 1 ? 3u : 1u; + + if (elementIndex > maxElementIndex) + goto InvalidElementIndex; + + uint32_t hl = elementIndex << hlFieldShift; + + opcode.reset(opData.elementOp()); + opcode.addImm(q, 30); + opcode.addImm(sz, 22); + opcode.addImm(hl & 1u, 21); // L field. + opcode.addImm(hl >> 1, 11); // H field. + opcode.addImm(rot, 13); + goto EmitOp_Rd0_Rn5_Rm16; + } + } + + break; + } + + case InstDB::kEncodingSimdFcmpFcmpe: { + const InstDB::EncodingData::SimdFcmpFcmpe& opData = InstDB::EncodingData::simdFcmpFcmpe[encodingIndex]; + + uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); + uint32_t type = (sz - 1) & 0x3u; + + if (sz > 2) + goto InvalidInstruction; + + if (o0.as<Vec>().hasElementType()) + goto InvalidInstruction; + + opcode.reset(opData.opcode()); + opcode.addImm(type, 22); + + if (isign4 == ENC_OPS2(Reg, Reg)) { + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + goto EmitOp_Rn5_Rm16; + } + + if (isign4 == ENC_OPS2(Reg, Imm)) { + if (o1.as<Imm>().value() != 0 || o1.as<Imm>().predicate() != 0) + goto InvalidInstruction; + + opcode |= B(3); + goto EmitOp_Rn5; + } + + break; + } + + case InstDB::kEncodingSimdFcsel: { + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { + if (!checkSignature(o0, o1, o2)) + goto InvalidInstruction; + + uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); + uint32_t type = (sz - 1) & 0x3u; + + if (sz > 2 || o0.as<Vec>().hasElementType()) + goto InvalidInstruction; + + uint64_t cond = o3.as<Imm>().valueAs<uint64_t>(); + if (cond > 0xFu) + goto InvalidImmediate; + + opcode.reset(0b00011110001000000000110000000000); + opcode.addImm(type, 22); + opcode.addImm(condCodeToOpcodeCond(uint32_t(cond)), 12); + goto EmitOp_Rd0_Rn5_Rm16; + } + + break; + } + + case InstDB::kEncodingSimdFcvt: { + if (isign4 == ENC_OPS2(Reg, Reg)) { + uint32_t dstSz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); + uint32_t srcSz = diff(o1.as<Reg>().type(), RegType::kARM_VecH); + + if ((dstSz | srcSz) > 3) + goto InvalidInstruction; + + if (o0.as<Vec>().hasElementType() || o1.as<Vec>().hasElementType()) + goto InvalidInstruction; + + // Table that provides 'type' and 'opc' according to the dst/src combination. + static const uint8_t table[] = { + 0xFFu, // H <- H (Invalid). + 0x03u, // H <- S (type=00 opc=11). + 0x13u, // H <- D (type=01 opc=11). + 0xFFu, // H <- Q (Invalid). + 0x30u, // S <- H (type=11 opc=00). + 0xFFu, // S <- S (Invalid). + 0x10u, // S <- D (type=01 opc=00). + 0xFFu, // S <- Q (Invalid). + 0x31u, // D <- H (type=11 opc=01). + 0x01u, // D <- S (type=00 opc=01). + 0xFFu, // D <- D (Invalid). + 0xFFu, // D <- Q (Invalid). + 0xFFu, // Q <- H (Invalid). + 0xFFu, // Q <- S (Invalid). + 0xFFu, // Q <- D (Invalid). + 0xFFu // Q <- Q (Invalid). + }; + + uint32_t typeOpc = table[(dstSz << 2) | srcSz]; + opcode.reset(0b0001111000100010010000 << 10); + opcode.addImm(typeOpc >> 4, 22); + opcode.addImm(typeOpc & 15, 15); + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingSimdFcvtLN: { + const InstDB::EncodingData::SimdFcvtLN& opData = InstDB::EncodingData::simdFcvtLN[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + // Scalar form - only FCVTXN. + if (o0.as<Vec>().isVecS() && o1.as<Vec>().isVecD()) { + if (!opData.hasScalar()) + goto InvalidInstruction; + + if (o0.as<Vec>().hasElementType() || o1.as<Vec>().hasElementType()) + goto InvalidInstruction; + + opcode.reset(opData.scalarOp()); + opcode |= B(22); // sz bit must be 1, the only supported combination of FCVTXN. + goto EmitOp_Rd0_Rn5; + } + + opcode.reset(opData.vectorOp()); + + const Vec& rL = (instFlags & InstDB::kInstFlagLong) ? o0.as<Vec>() : o1.as<Vec>(); + const Vec& rN = (instFlags & InstDB::kInstFlagLong) ? o1.as<Vec>() : o0.as<Vec>(); + + uint32_t q = diff(rN.type(), RegType::kARM_VecD); + if (uint32_t(opcode.hasQ()) != q) + goto InvalidInstruction; + + if (rL.isVecS4() && rN.elementType() == Vec::kElementTypeH && !opData.isCvtxn()) { + goto EmitOp_Rd0_Rn5; + } + + if (rL.isVecD2() && rN.elementType() == Vec::kElementTypeS) { + opcode |= B(22); + goto EmitOp_Rd0_Rn5; + } + } + + break; + } + + case InstDB::kEncodingSimdFcvtSV: { + const InstDB::EncodingData::SimdFcvtSV& opData = InstDB::EncodingData::simdFcvtSV[encodingIndex]; + + // So we can support both IntToFloat and FloatToInt conversions. + const Operand_& oGp = opData.isFloatToInt() ? o0 : o1; + const Operand_& oVec = opData.isFloatToInt() ? o1 : o0; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + if (oGp.as<Reg>().isGp() && oVec.as<Reg>().isVec()) { + uint32_t x = oGp.as<Reg>().isGpX(); + uint32_t type = diff(oVec.as<Reg>().type(), RegType::kARM_VecH); + + if (type > 2u) + goto InvalidInstruction; + + type = (type - 1u) & 0x3; + opcode.reset(opData.generalOp()); + opcode.addImm(type, 22); + opcode.addImm(x, 31); + goto EmitOp_Rd0_Rn5; + } + + if (o0.as<Reg>().isVec() && o1.as<Reg>().isVec()) { + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!pickFpOpcode(o0.as<Vec>(), opData.scalarIntOp(), InstDB::kHF_B, opData.vectorIntOp(), InstDB::kHF_B, &opcode)) + goto InvalidInstruction; + + goto EmitOp_Rd0_Rn5; + } + } + + if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.isFixedPoint()) { + if (o2.as<Imm>().valueAs<uint64_t>() >= 64) + goto InvalidInstruction; + + uint32_t scale = o2.as<Imm>().valueAs<uint32_t>(); + if (scale == 0) + goto InvalidInstruction; + + if (oGp.as<Reg>().isGp() && oVec.as<Reg>().isVec()) { + uint32_t x = oGp.as<Reg>().isGpX(); + uint32_t type = diff(oVec.as<Reg>().type(), RegType::kARM_VecH); + + uint32_t scaleLimit = 32u << x; + if (scale > scaleLimit) + goto InvalidInstruction; + + type = (type - 1u) & 0x3; + opcode.reset(opData.generalOp() ^ B(21)); + opcode.addImm(type, 22); + opcode.addImm(x, 31); + opcode.addImm(64u - scale, 10); + goto EmitOp_Rd0_Rn5; + } + + if (o0.as<Reg>().isVec() && o1.as<Reg>().isVec()) { + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + uint32_t sz; + if (!pickFpOpcode(o0.as<Vec>(), opData.scalarFpOp(), InstDB::kHF_0, opData.vectorFpOp(), InstDB::kHF_0, &opcode, &sz)) + goto InvalidInstruction; + + uint32_t scaleLimit = 16u << sz; + if (scale > scaleLimit) + goto InvalidInstruction; + + uint32_t imm = Support::neg(scale) & Support::lsbMask<uint32_t>(sz + 4 + 1); + opcode.addImm(imm, 16); + goto EmitOp_Rd0_Rn5; + } + } + + break; + } + + case InstDB::kEncodingSimdFmlal: { + const InstDB::EncodingData::SimdFmlal& opData = InstDB::EncodingData::simdFmlal[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD); + uint32_t qIsOptional = opData.optionalQ(); + + if (qIsOptional) { + // This instruction works with either 64-bit or 128-bit registers, + // encoded by Q bit. + if (q > 1) + goto InvalidInstruction; + } + else { + // This instruction requires 128-bit vector registers. + if (q != 1) + goto InvalidInstruction; + + // The instruction is ehtier B (bottom) or T (top), which is part of + // the opcode, which uses Q bit, so we have to clear it explicitly. + q = 0; + } + + if (uint32_t(o0.as<Reg>().type()) != uint32_t(o1.as<Reg>().type()) + qIsOptional || + o0.as<Vec>().elementType() != opData.tA || + o1.as<Vec>().elementType() != opData.tB) + goto InvalidInstruction; + + if (!o2.as<Vec>().hasElementIndex()) { + if (!checkSignature(o1, o2)) + goto InvalidInstruction; + + opcode.reset(opData.vectorOp()); + opcode.addImm(q, 30); + goto EmitOp_Rd0_Rn5_Rm16; + } + else { + if (o2.as<Vec>().elementType() != opData.tElement) + goto InvalidInstruction; + + if (o2.as<Reg>().id() > 15) + goto InvalidPhysId; + + uint32_t elementIndex = o2.as<Vec>().elementIndex(); + if (elementIndex > 7u) + goto InvalidElementIndex; + + opcode.reset(opData.elementOp()); + opcode.addImm(q, 30); + opcode.addImm(elementIndex & 3u, 20); + opcode.addImm(elementIndex >> 2, 11); + goto EmitOp_Rd0_Rn5_Rm16; + } + } + + break; + } + + case InstDB::kEncodingSimdFmov: { + if (isign4 == ENC_OPS2(Reg, Reg)) { + // FMOV Gp <-> Vec opcode: + opcode.reset(0b00011110001001100000000000000000); + + if (o0.as<Reg>().isGp() && o1.as<Reg>().isVec()) { + // FMOV Wd, Hn (sf=0 type=11 rmode=00 op=110) + // FMOV Xd, Hn (sf=1 type=11 rmode=00 op=110) + // FMOV Wd, Sn (sf=0 type=00 rmode=00 op=110) + // FMOV Xd, Dn (sf=1 type=11 rmode=00 op=110) + // FMOV Xd, Vn.d[1] (sf=1 type=10 rmode=01 op=110) + uint32_t x = o0.as<Reg>().isGpX(); + uint32_t sz = diff(o1.as<Reg>().type(), RegType::kARM_VecH); + + uint32_t type = (sz - 1) & 0x3u; + uint32_t rModeOp = 0b00110; + + if (o1.as<Vec>().hasElementIndex()) { + // Special case. + if (!x || !o1.as<Vec>().isVecD2() || o1.as<Vec>().elementIndex() != 1) + goto InvalidInstruction; + type = 0b10; + rModeOp = 0b01110; + } + else { + // Must be scalar. + if (sz > 2) + goto InvalidInstruction; + + if (o1.as<Vec>().hasElementType()) + goto InvalidInstruction; + + if (o1.as<Vec>().isVecS() && x) + goto InvalidInstruction; + + if (o1.as<Vec>().isVecD() && !x) + goto InvalidInstruction; + } + + opcode.addImm(x, 31); + opcode.addImm(type, 22); + opcode.addImm(rModeOp, 16); + goto EmitOp_Rd0_Rn5; + } + + if (o0.as<Reg>().isVec() && o1.as<Reg>().isGp()) { + // FMOV Hd, Wn (sf=0 type=11 rmode=00 op=111) + // FMOV Hd, Xn (sf=1 type=11 rmode=00 op=111) + // FMOV Sd, Wn (sf=0 type=00 rmode=00 op=111) + // FMOV Dd, Xn (sf=1 type=11 rmode=00 op=111) + // FMOV Vd.d[1], Xn (sf=1 type=10 rmode=01 op=111) + uint32_t x = o1.as<Reg>().isGpX(); + uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); + + uint32_t type = (sz - 1) & 0x3u; + uint32_t rModeOp = 0b00111; + + if (o0.as<Vec>().hasElementIndex()) { + // Special case. + if (!x || !o0.as<Vec>().isVecD2() || o0.as<Vec>().elementIndex() != 1) + goto InvalidInstruction; + type = 0b10; + rModeOp = 0b01111; + } + else { + // Must be scalar. + if (sz > 2) + goto InvalidInstruction; + + if (o0.as<Vec>().hasElementType()) + goto InvalidInstruction; + + if (o0.as<Vec>().isVecS() && x) + goto InvalidInstruction; + + if (o0.as<Vec>().isVecD() && !x) + goto InvalidInstruction; + } + + opcode.addImm(x, 31); + opcode.addImm(type, 22); + opcode.addImm(rModeOp, 16); + goto EmitOp_Rd0_Rn5; + } + + if (checkSignature(o0, o1)) { + uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); + if (sz > 2) + goto InvalidInstruction; + + if (o0.as<Vec>().hasElementType()) + goto InvalidInstruction; + + uint32_t type = (sz - 1) & 0x3; + opcode.reset(0b00011110001000000100000000000000); + opcode.addImm(type, 22); + goto EmitOp_Rd0_Rn5; + } + } + + if (isign4 == ENC_OPS2(Reg, Imm)) { + if (o0.as<Reg>().isVec()) { + double fpValue; + if (o1.as<Imm>().isDouble()) + fpValue = o1.as<Imm>().valueAs<double>(); + else if (o1.as<Imm>().isInt32()) + fpValue = o1.as<Imm>().valueAs<int32_t>(); + else + goto InvalidImmediate; + + if (!Utils::isFP64Imm8(fpValue)) + goto InvalidImmediate; + + uint32_t imm8 = Utils::encodeFP64ToImm8(fpValue); + if (!o0.as<Vec>().hasElementType()) { + // FMOV (scalar, immediate). + uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); + uint32_t type = (sz - 1u) & 0x3u; + + if (sz > 2) + goto InvalidInstruction; + + opcode.reset(0b00011110001000000001000000000000); + opcode.addImm(type, 22); + opcode.addImm(imm8, 13); + goto EmitOp_Rd0; + } + else { + uint32_t q = diff(o0.as<Vec>().type(), RegType::kARM_VecD); + uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeH; + + if (q > 1 || sz > 2) + goto InvalidInstruction; + + static const uint32_t szBits[3] = { B(11), B(0), B(29) }; + opcode.reset(0b00001111000000001111010000000000); + opcode ^= szBits[sz]; + opcode.addImm(q, 30); + opcode.addImm(imm8 >> 5, 16); + opcode.addImm(imm8 & 31, 5); + goto EmitOp_Rd0; + } + } + } + + break; + } + + case InstDB::kEncodingFSimdPair: { + const InstDB::EncodingData::FSimdPair& opData = InstDB::EncodingData::fSimdPair[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + // This operation is only defined for: + // hD, vS.2h (16-bit) + // sD, vS.2s (32-bit) + // dD, vS.2d (64-bit) + uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecH); + if (sz > 2) + goto InvalidInstruction; + + static const uint32_t szSignatures[3] = { + VecS::kSignature | (Vec::kSignatureElementH), + VecD::kSignature | (Vec::kSignatureElementS), + VecV::kSignature | (Vec::kSignatureElementD) + }; + + if (o1.signature() != szSignatures[sz]) + goto InvalidInstruction; + + static const uint32_t szBits[] = { B(29), 0, B(22) }; + opcode.reset(opData.scalarOp()); + opcode ^= szBits[sz]; + goto EmitOp_Rd0_Rn5; + } + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + if (!checkSignature(o0, o1, o2)) + goto InvalidInstruction; + + uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD); + if (q > 1) + goto InvalidInstruction; + + uint32_t sz = o0.as<Vec>().elementType() - Vec::kElementTypeH; + if (sz > 2) + goto InvalidInstruction; + + static const uint32_t szBits[3] = { B(22) | B(21) | B(15) | B(14), 0, B(22) }; + opcode.reset(opData.vectorOp()); + opcode ^= szBits[sz]; + opcode.addImm(q, 30); + goto EmitOp_Rd0_Rn5_Rm16; + } + + break; + } + + // ------------------------------------------------------------------------ + // [ISimd - Instructions] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingISimdSV: { + const InstDB::EncodingData::ISimdSV& opData = InstDB::EncodingData::iSimdSV[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + // The first destination operand is scalar, which matches element-type of source vectors. + uint32_t L = (instFlags & InstDB::kInstFlagLong) != 0; + if (diff(o0.as<Vec>().type(), RegType::kARM_VecB) != o1.as<Vec>().elementType() - Vec::kElementTypeB + L) + goto InvalidInstruction; + + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + opcode.reset(opData.opcode()); + opcode.addImm(sizeOp.q(), 30); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingISimdVV: { + const InstDB::EncodingData::ISimdVV& opData = InstDB::EncodingData::iSimdVV[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + const Operand_& sop = significantSimdOp(o0, o1, instFlags); + if (!matchSignature(o0, o1, instFlags)) + goto InvalidInstruction; + + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + opcode.reset(opData.opcode()); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingISimdVVx: { + const InstDB::EncodingData::ISimdVVx& opData = InstDB::EncodingData::iSimdVVx[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + if (o0.signature() != opData.op0Signature || + o1.signature() != opData.op1Signature) + goto InvalidInstruction; + + opcode.reset(opData.opcode()); + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingISimdVVV: { + const InstDB::EncodingData::ISimdVVV& opData = InstDB::EncodingData::iSimdVVV[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + const Operand_& sop = significantSimdOp(o0, o1, instFlags); + if (!matchSignature(o0, o1, o2, instFlags)) + goto InvalidInstruction; + + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + opcode.reset(opData.opcode()); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5_Rm16; + } + + break; + } + + case InstDB::kEncodingISimdVVVx: { + const InstDB::EncodingData::ISimdVVVx& opData = InstDB::EncodingData::iSimdVVVx[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + if (o0.signature() != opData.op0Signature || + o1.signature() != opData.op1Signature || + o2.signature() != opData.op2Signature) + goto InvalidInstruction; + + opcode.reset(opData.opcode()); + goto EmitOp_Rd0_Rn5_Rm16; + } + + break; + } + + case InstDB::kEncodingISimdWWV: { + // Special case for wide add/sub [s|b][add|sub][w]{2}. + const InstDB::EncodingData::ISimdWWV& opData = InstDB::EncodingData::iSimdWWV[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o2.as<Reg>().type(), o2.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + if (!checkSignature(o0, o1) || !o0.as<Reg>().isVecV() || o0.as<Vec>().elementType() != o2.as<Vec>().elementType() + 1) + goto InvalidInstruction; + + opcode.reset(opData.opcode()); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5_Rm16; + } + + break; + } + + case InstDB::kEncodingISimdVVVe: { + const InstDB::EncodingData::ISimdVVVe& opData = InstDB::EncodingData::iSimdVVVe[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + const Operand_& sop = significantSimdOp(o0, o1, instFlags); + if (!matchSignature(o0, o1, instFlags)) + goto InvalidInstruction; + + if (!o2.as<Vec>().hasElementIndex()) { + SizeOp sizeOp = armElementTypeToSizeOp(opData.regularVecType, sop.as<Reg>().type(), sop.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + if (!checkSignature(o1, o2)) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.regularOp) << 10); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5_Rm16; + } + else { + SizeOp sizeOp = armElementTypeToSizeOp(opData.elementVecType, sop.as<Reg>().type(), sop.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + uint32_t elementIndex = o2.as<Vec>().elementIndex(); + LMHImm lmh; + + if (!encodeLMH(sizeOp.size(), elementIndex, &lmh)) + goto InvalidElementIndex; + + if (o2.as<Reg>().id() > lmh.maxRmId) + goto InvalidPhysId; + + opcode.reset(uint32_t(opData.elementOp) << 10); + opcode.addImm(sizeOp.q(), 30); + opcode.addImm(sizeOp.size(), 22); + opcode.addImm(lmh.lm, 20); + opcode.addImm(lmh.h, 11); + goto EmitOp_Rd0_Rn5_Rm16; + } + } + + break; + } + + case InstDB::kEncodingISimdVVVI: { + const InstDB::EncodingData::ISimdVVVI& opData = InstDB::EncodingData::iSimdVVVI[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Imm)) { + const Operand_& sop = significantSimdOp(o0, o1, instFlags); + if (!matchSignature(o0, o1, o2, instFlags)) + goto InvalidInstruction; + + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + uint64_t immValue = o3.as<Imm>().valueAs<uint64_t>(); + uint32_t immSize = opData.immSize; + + if (opData.imm64HasOneBitLess && !sizeOp.q()) + immSize--; + + uint32_t immMax = 1u << immSize; + if (immValue >= immMax) + goto InvalidImmediate; + + opcode.reset(opData.opcode()); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(sizeOp.size(), 22); + opcode.addImm(immValue, opData.immShift); + goto EmitOp_Rd0_Rn5_Rm16; + } + + break; + } + + case InstDB::kEncodingISimdVVVV: { + const InstDB::EncodingData::ISimdVVVV& opData = InstDB::EncodingData::iSimdVVVV[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { + const Operand_& sop = significantSimdOp(o0, o1, instFlags); + if (!matchSignature(o0, o1, o2, o3, instFlags)) + goto InvalidInstruction; + + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.opcode) << 10); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5_Rm16_Ra10; + } + + break; + } + + case InstDB::kEncodingISimdVVVVx: { + const InstDB::EncodingData::ISimdVVVVx& opData = InstDB::EncodingData::iSimdVVVVx[encodingIndex]; + + if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { + if (o0.signature() != opData.op0Signature || + o1.signature() != opData.op1Signature || + o2.signature() != opData.op2Signature || + o3.signature() != opData.op3Signature) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.opcode) << 10); + goto EmitOp_Rd0_Rn5_Rm16_Ra10; + } + + break; + } + + + case InstDB::kEncodingISimdPair: { + const InstDB::EncodingData::ISimdPair& opData = InstDB::EncodingData::iSimdPair[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg) && opData.opcode2) { + if (o0.as<Vec>().isVecD1() && o1.as<Vec>().isVecD2()) { + opcode.reset(uint32_t(opData.opcode2) << 10); + opcode.addImm(0x3, 22); // size. + goto EmitOp_Rd0_Rn5; + } + } + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + if (!matchSignature(o0, o1, o2, instFlags)) + goto InvalidInstruction; + + SizeOp sizeOp = armElementTypeToSizeOp(opData.opType3, o0.as<Reg>().type(), o0.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.opcode3) << 10); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5_Rm16; + } + + break; + } + + case InstDB::kEncodingSimdBicOrr: { + const InstDB::EncodingData::SimdBicOrr& opData = InstDB::EncodingData::simdBicOrr[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + if (!matchSignature(o0, o1, o2, instFlags)) + goto InvalidInstruction; + + SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_B, o0.as<Reg>().type(), o0.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.registerOp) << 10); + opcode.addImm(sizeOp.q(), 30); + goto EmitOp_Rd0_Rn5_Rm16; + } + + if (isign4 == ENC_OPS2(Reg, Imm) || isign4 == ENC_OPS3(Reg, Imm, Imm)) { + SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_HS, o0.as<Reg>().type(), o0.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + if (o1.as<Imm>().valueAs<uint64_t>() > 0xFFFFFFFFu) + goto InvalidImmediate; + + uint32_t imm = o1.as<Imm>().valueAs<uint32_t>(); + uint32_t shift = 0; + uint32_t maxShift = (8u << sizeOp.size()) - 8u; + + if (o2.isImm()) { + if (o2.as<Imm>().predicate() != uint32_t(ShiftOp::kLSL)) + goto InvalidImmediate; + + if (imm > 0xFFu || o2.as<Imm>().valueAs<uint64_t>() > maxShift) + goto InvalidImmediate; + + shift = o2.as<Imm>().valueAs<uint32_t>(); + if ((shift & 0x7u) != 0u) + goto InvalidImmediate; + } + else if (imm) { + shift = Support::ctz(imm) & 0x7u; + imm >>= shift; + + if (imm > 0xFFu || shift > maxShift) + goto InvalidImmediate; + } + + uint32_t cmode = 0x1u | ((shift / 8u) << 1); + if (sizeOp.size() == 1) + cmode |= B(3); + + // The immediate value is split into ABC and DEFGH parts. + uint32_t abc = (imm >> 5) & 0x7u; + uint32_t defgh = imm & 0x1Fu; + + opcode.reset(uint32_t(opData.immediateOp) << 10); + opcode.addImm(sizeOp.q(), 30); + opcode.addImm(abc, 16); + opcode.addImm(cmode, 12); + opcode.addImm(defgh, 5); + goto EmitOp_Rd0; + } + + break; + } + + case InstDB::kEncodingSimdCmp: { + const InstDB::EncodingData::SimdCmp& opData = InstDB::EncodingData::simdCmp[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.regOp) { + if (!matchSignature(o0, o1, o2, instFlags)) + goto InvalidInstruction; + + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o0.as<Reg>().type(), o0.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.regOp) << 10); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5_Rm16; + } + + if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.zeroOp) { + if (!matchSignature(o0, o1, instFlags)) + goto InvalidInstruction; + + if (o2.as<Imm>().value() != 0) + goto InvalidImmediate; + + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o0.as<Reg>().type(), o0.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.zeroOp) << 10); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingSimdDot: { + const InstDB::EncodingData::SimdDot& opData = InstDB::EncodingData::simdDot[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD); + uint32_t size = 2; + + if (q > 1u) + goto InvalidInstruction; + + if (!o2.as<Vec>().hasElementIndex()) { + if (!opData.vectorOp) + goto InvalidInstruction; + + if (o0.as<Reg>().type() != o1.as<Reg>().type() || o1.as<Reg>().type() != o2.as<Reg>().type()) + goto InvalidInstruction; + + if (o0.as<Vec>().elementType() != opData.tA || + o1.as<Vec>().elementType() != opData.tB || + o2.as<Vec>().elementType() != opData.tB) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.vectorOp) << 10); + opcode.addImm(q, 30); + goto EmitOp_Rd0_Rn5_Rm16; + } + else { + if (!opData.elementOp) + goto InvalidInstruction; + + if (o0.as<Reg>().type() != o1.as<Reg>().type() || !o2.as<Reg>().isVecV()) + goto InvalidInstruction; + + if (o0.as<Vec>().elementType() != opData.tA || + o1.as<Vec>().elementType() != opData.tB || + o2.as<Vec>().elementType() != opData.tElement) + goto InvalidInstruction; + + uint32_t elementIndex = o2.as<Vec>().elementIndex(); + LMHImm lmh; + + if (!encodeLMH(size, elementIndex, &lmh)) + goto InvalidElementIndex; + + if (o2.as<Reg>().id() > lmh.maxRmId) + goto InvalidPhysId; + + opcode.reset(uint32_t(opData.elementOp) << 10); + opcode.addImm(q, 30); + opcode.addImm(lmh.lm, 20); + opcode.addImm(lmh.h, 11); + goto EmitOp_Rd0_Rn5_Rm16; + } + } + + break; + } + + case InstDB::kEncodingSimdDup: SimdDup: { + if (isign4 == ENC_OPS2(Reg, Reg)) { + // Truth table of valid encodings of `Q:1|ElementType:3` + uint32_t kValidEncodings = B(Vec::kElementTypeB + 0) | + B(Vec::kElementTypeH + 0) | + B(Vec::kElementTypeS + 0) | + B(Vec::kElementTypeB + 8) | + B(Vec::kElementTypeH + 8) | + B(Vec::kElementTypeS + 8) | + B(Vec::kElementTypeD + 8) ; + + uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD); + + if (o1.as<Reg>().isGp()) { + // DUP - Vec (scalar|vector) <- GP register. + // + // NOTE: This is only scalar for `dup d, x` case, otherwise the value + // would be duplicated across all vector elements (1, 2, 4, 8, or 16). + uint32_t elementType = o0.as<Vec>().elementType(); + if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType)) + goto InvalidInstruction; + + uint32_t lsbIndex = elementType - 1u; + uint32_t imm5 = 1u << lsbIndex; + + opcode.reset(0b0000111000000000000011 << 10); + opcode.addImm(q, 30); + opcode.addImm(imm5, 16); + goto EmitOp_Rd0_Rn5; + } + + if (!o1.as<Reg>().isVec() || !o1.as<Vec>().hasElementIndex()) + goto InvalidInstruction; + + uint32_t dstIndex = o1.as<Vec>().elementIndex(); + if (!o0.as<Vec>().hasElementType()) { + // DUP - Vec (scalar) <- Vec[N]. + uint32_t lsbIndex = diff(o0.as<Reg>().type(), RegType::kARM_VecB); + + if (lsbIndex != o1.as<Vec>().elementType() - Vec::kElementTypeB || lsbIndex > 3) + goto InvalidInstruction; + + uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex; + if (imm5 > 31) + goto InvalidElementIndex; + + opcode.reset(0b0101111000000000000001 << 10); + opcode.addImm(imm5, 16); + goto EmitOp_Rd0_Rn5; + } + else { + // DUP - Vec (all) <- Vec[N]. + uint32_t elementType = o0.as<Vec>().elementType(); + if (q > 1 || !Support::bitTest(kValidEncodings, (q << 3) | elementType)) + goto InvalidInstruction; + + uint32_t lsbIndex = elementType - 1u; + uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex; + + if (imm5 > 31) + goto InvalidElementIndex; + + opcode.reset(0b0000111000000000000001 << 10); + opcode.addImm(q, 30); + opcode.addImm(imm5, 16); + goto EmitOp_Rd0_Rn5; + } + } + + break; + } + + case InstDB::kEncodingSimdIns: SimdIns: { + if (isign4 == ENC_OPS2(Reg, Reg) && o0.as<Reg>().isVecV()) { + if (!o0.as<Vec>().hasElementIndex()) + goto InvalidInstruction; + + uint32_t elementType = o0.as<Vec>().elementType(); + uint32_t dstIndex = o0.as<Vec>().elementIndex(); + uint32_t lsbIndex = elementType - 1u; + + uint32_t imm5 = ((dstIndex << 1) | 1u) << lsbIndex; + if (imm5 > 31) + goto InvalidElementIndex; + + if (o1.as<Reg>().isGp()) { + // INS - Vec[N] <- GP register. + opcode.reset(0b0100111000000000000111 << 10); + opcode.addImm(imm5, 16); + goto EmitOp_Rd0_Rn5; + } + else if (o1.as<Reg>().isVecV() && o1.as<Vec>().hasElementIndex()) { + // INS - Vec[N] <- Vec[M]. + if (o0.as<Vec>().elementType() != o1.as<Vec>().elementType()) + goto InvalidInstruction; + + uint32_t srcIndex = o1.as<Vec>().elementIndex(); + if (o0.as<Reg>().type() != o1.as<Reg>().type()) + goto InvalidInstruction; + + uint32_t imm4 = srcIndex << lsbIndex; + if (imm4 > 15) + goto InvalidElementIndex; + + opcode.reset(0b0110111000000000000001 << 10); + opcode.addImm(imm5, 16); + opcode.addImm(imm4, 11); + goto EmitOp_Rd0_Rn5; + } + } + + break; + } + + case InstDB::kEncodingSimdMov: { + if (isign4 == ENC_OPS2(Reg, Reg)) { + if (o0.as<Reg>().isVec() && o1.as<Reg>().isVec()) { + // INS v.x[index], v.x[index]. + if (o0.as<Vec>().hasElementIndex() && o1.as<Vec>().hasElementIndex()) + goto SimdIns; + + // DUP {b|h|s|d}, v.{b|h|s|d}[index]. + if (o1.as<Vec>().hasElementIndex()) + goto SimdDup; + + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + // ORR Vd, Vn, Vm + uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD); + if (q > 1) + goto InvalidInstruction; + + opcode.reset(0b0000111010100000000111 << 10); + opcode.addImm(q, 30); + opcode.addReg(o1, 16); // Vn == Vm. + goto EmitOp_Rd0_Rn5; + } + + if (o0.as<Reg>().isVec() && o1.as<Reg>().isGp()) { + // INS v.x[index], Rn. + if (o0.as<Vec>().hasElementIndex()) + goto SimdIns; + + goto InvalidInstruction; + } + + if (o0.as<Reg>().isGp() && o1.as<Reg>().isVec()) { + // UMOV Rd, V.{s|d}[index]. + encodingIndex = 1; + goto SimdUmov; + } + } + + break; + } + + case InstDB::kEncodingSimdMoviMvni: { + const InstDB::EncodingData::SimdMoviMvni& opData = InstDB::EncodingData::simdMoviMvni[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Imm) || isign4 == ENC_OPS3(Reg, Imm, Imm)) { + SizeOp sizeOp = armElementTypeToSizeOp(InstDB::kVO_V_Any, o0.as<Reg>().type(), o0.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + uint64_t imm64 = o1.as<Imm>().valueAs<uint64_t>(); + uint32_t imm8 = 0; + uint32_t cmode = 0; + uint32_t inverted = opData.inverted; + uint32_t op = 0; + uint32_t shift = 0; + uint32_t shiftOp = uint32_t(ShiftOp::kLSL); + + if (sizeOp.size() == 3u) { + // The second immediate should not be present, however, we accept + // an immediate value of zero as some user code may still pass it. + if (o2.isImm() && o0.as<Imm>().value() != 0) + goto InvalidImmediate; + + if (Utils::isByteMaskImm8(imm64)) { + imm8 = encodeImm64ByteMaskToImm8(imm64); + } + else { + // Change from D to S and from 64-bit imm to 32-bit imm if this + // is not a byte-mask pattern. + if ((imm64 >> 32) == (imm64 & 0xFFFFFFFFu)) { + imm64 &= 0xFFFFFFFFu; + sizeOp.decrementSize(); + } + else { + goto InvalidImmediate; + } + } + } + + if (sizeOp.size() < 3u) { + if (imm64 > 0xFFFFFFFFu) + goto InvalidImmediate; + imm8 = uint32_t(imm64); + + if (sizeOp.size() == 2) { + if ((imm8 >> 16) == (imm8 & 0xFFFFu)) { + imm8 >>= 16; + sizeOp.decrementSize(); + } + } + + if (sizeOp.size() == 1) { + if (imm8 > 0xFFFFu) + goto InvalidImmediate; + + if ((imm8 >> 8) == (imm8 & 0xFFu)) { + imm8 >>= 8; + sizeOp.decrementSize(); + } + } + + uint32_t maxShift = (8u << sizeOp.size()) - 8u; + if (o2.isImm()) { + if (imm8 > 0xFFu || o2.as<Imm>().valueAs<uint64_t>() > maxShift) + goto InvalidImmediate; + + shift = o2.as<Imm>().valueAs<uint32_t>(); + shiftOp = o2.as<Imm>().predicate(); + } + else if (imm8) { + shift = Support::ctz(imm8) & ~0x7u; + imm8 >>= shift; + + if (imm8 > 0xFFu || shift > maxShift) + goto InvalidImmediate; + } + + if ((shift & 0x7u) != 0u) + goto InvalidImmediate; + } + + shift /= 8u; + + switch (sizeOp.size()) { + case 0: + if (shiftOp != uint32_t(ShiftOp::kLSL)) + goto InvalidImmediate; + + if (inverted) { + imm8 = ~imm8 & 0xFFu; + inverted = 0; + } + + cmode = B(3) | B(2) | B(1); + break; + + case 1: + if (shiftOp != uint32_t(ShiftOp::kLSL)) + goto InvalidImmediate; + + cmode = B(3) | (shift << 1); + op = inverted; + break; + + case 2: + if (shiftOp == uint32_t(ShiftOp::kLSL)) { + cmode = shift << 1; + } + else if (shiftOp == uint32_t(ShiftOp::kMSL)) { + if (shift == 0 || shift > 2) + goto InvalidImmediate; + cmode = B(3) | B(2) | (shift - 1u); + } + else { + goto InvalidImmediate; + } + + op = inverted; + break; + + case 3: + if (inverted) { + imm8 = ~imm8 & 0xFFu; + inverted = 0; + } + + op = 1; + cmode = B(3) | B(2) | B(1); + break; + } + + // The immediate value is split into ABC and DEFGH parts. + uint32_t abc = (imm8 >> 5) & 0x7u; + uint32_t defgh = imm8 & 0x1Fu; + + opcode.reset(uint32_t(opData.opcode) << 10); + opcode.addImm(sizeOp.q(), 30); + opcode.addImm(op, 29); + opcode.addImm(abc, 16); + opcode.addImm(cmode, 12); + opcode.addImm(defgh, 5); + goto EmitOp_Rd0; + } + + break; + } + + case InstDB::kEncodingSimdShift: { + const InstDB::EncodingData::SimdShift& opData = InstDB::EncodingData::simdShift[encodingIndex]; + + const Operand_& sop = significantSimdOp(o0, o1, instFlags); + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, sop.as<Reg>().type(), sop.as<Vec>().elementType()); + + if (!sizeOp.isValid()) + goto InvalidInstruction; + + if (isign4 == ENC_OPS3(Reg, Reg, Imm) && opData.immediateOp) { + if (!matchSignature(o0, o1, instFlags)) + goto InvalidInstruction; + + if (o2.as<Imm>().valueAs<uint64_t>() > 63) + goto InvalidImmediate; + + uint32_t lsbShift = sizeOp.size() + 3u; + uint32_t lsbMask = (1u << lsbShift) - 1u; + uint32_t imm = o2.as<Imm>().valueAs<uint32_t>(); + + // Some instructions use IMM and some X - IMM, so negate if required. + if (opData.invertedImm) { + if (imm == 0 || imm > (1u << lsbShift)) + goto InvalidImmediate; + imm = Support::neg(imm) & lsbMask; + } + + if (imm > lsbMask) + goto InvalidImmediate; + imm |= (1u << lsbShift); + + opcode.reset(uint32_t(opData.immediateOp) << 10); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(imm, 16); + goto EmitOp_Rd0_Rn5; + } + + if (isign4 == ENC_OPS3(Reg, Reg, Reg) && opData.registerOp) { + if (!matchSignature(o0, o1, o2, instFlags)) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.registerOp) << 10); + opcode.addImm(sizeOp.qs(), 30); + opcode.addImm(sizeOp.scalar(), 28); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5_Rm16; + } + + break; + } + + case InstDB::kEncodingSimdShiftES: { + const InstDB::EncodingData::SimdShiftES& opData = InstDB::EncodingData::simdShiftES[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Imm)) { + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + if (!matchSignature(o0, o1, instFlags)) + goto InvalidInstruction; + + // The immediate value must match the element size. + uint64_t shift = o2.as<Imm>().valueAs<uint64_t>(); + uint32_t shiftOp = o2.as<Imm>().predicate(); + + if (shift != (8u << sizeOp.size()) || shiftOp != uint32_t(ShiftOp::kLSL)) + goto InvalidImmediate; + + opcode.reset(uint32_t(opData.opcode) << 10); + opcode.addImm(sizeOp.q(), 30); + opcode.addImm(sizeOp.size(), 22); + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingSimdSm3tt: { + const InstDB::EncodingData::SimdSm3tt& opData = InstDB::EncodingData::simdSm3tt[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg)) { + if (o0.as<Vec>().isVecS4() && o1.as<Vec>().isVecS4() && o2.as<Vec>().isVecS4() && o2.as<Vec>().hasElementIndex()) { + uint32_t imm2 = o2.as<Vec>().elementIndex(); + if (imm2 > 3) + goto InvalidElementIndex; + + opcode.reset(uint32_t(opData.opcode) << 10); + opcode.addImm(imm2, 12); + goto EmitOp_Rd0_Rn5_Rm16; + } + } + + break; + } + + + case InstDB::kEncodingSimdSmovUmov: SimdUmov: { + const InstDB::EncodingData::SimdSmovUmov& opData = InstDB::EncodingData::simdSmovUmov[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg) && o0.as<Reg>().isGp() && o1.as<Reg>().isVec()) { + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + if (!o1.as<Vec>().hasElementIndex()) + goto InvalidInstruction; + + uint32_t x = o0.as<Gp>().isGpX(); + uint32_t gpMustBeX = uint32_t(sizeOp.size() >= 3u - opData.isSigned); + + if (opData.isSigned) { + if (gpMustBeX && !x) + goto InvalidInstruction; + } + else { + if (x != gpMustBeX) + goto InvalidInstruction; + } + + uint32_t elementIndex = o1.as<Vec>().elementIndex(); + uint32_t maxElementIndex = 15u >> sizeOp.size(); + + if (elementIndex > maxElementIndex) + goto InvalidElementIndex; + + uint32_t imm5 = (1u | (elementIndex << 1)) << sizeOp.size(); + + opcode.reset(uint32_t(opData.opcode) << 10); + opcode.addImm(x, 30); + opcode.addImm(imm5, 16); + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingSimdSxtlUxtl: { + const InstDB::EncodingData::SimdSxtlUxtl& opData = InstDB::EncodingData::simdSxtlUxtl[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Reg)) { + SizeOp sizeOp = armElementTypeToSizeOp(opData.vecOpType, o1.as<Reg>().type(), o1.as<Vec>().elementType()); + if (!sizeOp.isValid()) + goto InvalidInstruction; + + if (!matchSignature(o0, o1, instFlags)) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.opcode) << 10); + opcode.addImm(sizeOp.q(), 30); + opcode.addImm(1u, sizeOp.size() + 19); + goto EmitOp_Rd0_Rn5; + } + + break; + } + + case InstDB::kEncodingSimdTblTbx: { + const InstDB::EncodingData::SimdTblTbx& opData = InstDB::EncodingData::simdTblTbx[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Reg) || isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) { + // TBL/TBX <Vd>.<Ta>, { <Vn>.16B }, <Vm>.<Ta> + // TBL/TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B }, <Vm>.<Ta> + // TBL/TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B }, <Vm>.<Ta> + // TBL/TBX <Vd>.<Ta>, { <Vn>.16B, <Vn+1>.16B, <Vn+2>.16B, <Vn+3>.16B }, <Vm>.<Ta> + opcode.reset(uint32_t(opData.opcode) << 10); + + const Operand_& o4 = opExt[EmitterUtils::kOp4]; + const Operand_& o5 = opExt[EmitterUtils::kOp5]; + + uint32_t q = diff(o0.as<Reg>().type(), RegType::kARM_VecD); + if (q > 1 || o0.as<Vec>().hasElementIndex()) + goto InvalidInstruction; + + if (!o1.as<Vec>().isVecB16() || o1.as<Vec>().hasElementIndex()) + goto InvalidInstruction; + + uint32_t len = uint32_t(!o3.isNone()) + uint32_t(!o4.isNone()) + uint32_t(!o5.isNone()); + opcode.addImm(q, 30); + opcode.addImm(len, 13); + + switch (len) { + case 0: + if (!checkSignature(o0, o2)) + goto InvalidInstruction; + + if (o2.id() > 31) + goto InvalidPhysId; + + opcode.addReg(o2, 16); + goto EmitOp_Rd0_Rn5; + + case 1: + if (!checkSignature(o0, o3)) + goto InvalidInstruction; + + if (o3.id() > 31) + goto InvalidPhysId; + + opcode.addReg(o3, 16); + goto EmitOp_Rd0_Rn5; + + case 2: + if (!checkSignature(o0, o4)) + goto InvalidInstruction; + + if (o4.id() > 31) + goto InvalidPhysId; + + opcode.addReg(o4, 16); + goto EmitOp_Rd0_Rn5; + + case 3: + if (!checkSignature(o0, o5)) + goto InvalidInstruction; + + if (o5.id() > 31) + goto InvalidPhysId; + + opcode.addReg(o5, 16); + goto EmitOp_Rd0_Rn5; + + default: + // Should never happen. + goto InvalidInstruction; + } + } + + break; + } + + // ------------------------------------------------------------------------ + // [Simd - Load / Store] + // ------------------------------------------------------------------------ + + case InstDB::kEncodingSimdLdSt: { + const InstDB::EncodingData::SimdLdSt& opData = InstDB::EncodingData::simdLdSt[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Mem)) { + const Mem& m = o1.as<Mem>(); + rmRel = &m; + + // Width | SZ | XY | XSZ + // -------+----------+-----------+----- + // 8-bit | size==00 | opc == 01 | 000 + // 16-bit | size==01 | opc == 01 | 001 + // 32-bit | size==10 | opc == 01 | 010 + // 64-bit | size==11 | opc == 01 | 011 + // 128-bit| size==00 | opc == 11 | 100 + uint32_t xsz = diff(o0.as<Reg>().type(), RegType::kARM_VecB); + if (xsz > 4u || o0.as<Vec>().hasElementIndex()) + goto InvalidRegType; + + if (!checkVecId(o0)) + goto InvalidPhysId; + + if (!armCheckMemBaseIndexRel(m)) + goto InvalidAddress; + + int64_t offset = m.offset(); + if (m.hasBaseReg()) { + // [Base {Offset | Index}] + if (m.hasIndex()) { + uint32_t opt = armShiftOpToLdStOptMap[m.predicate()]; + if (opt == 0xFFu) + goto InvalidAddress; + + uint32_t shift = m.shift(); + uint32_t s = (shift != 0); + + if (s && shift != xsz) + goto InvalidAddressScale; + + opcode.reset(uint32_t(opData.registerOp) << 21); + opcode.addImm(xsz & 3u, 30); + opcode.addImm(xsz >> 2, 23); + opcode.addImm(opt, 13); + opcode.addImm(s, 12); + opcode |= B(11); + opcode.addReg(o0, 0); + goto EmitOp_MemBaseIndex_Rn5_Rm16; + } + + // Makes it easier to work with the offset especially on 32-bit arch. + if (!Support::isInt32(offset)) + goto InvalidDisplacement; + int32_t offset32 = int32_t(offset); + + if (m.isPreOrPost()) { + if (!Support::isInt9(offset32)) + goto InvalidDisplacement; + + opcode.reset(uint32_t(opData.prePostOp) << 21); + opcode.addImm(xsz & 3u, 30); + opcode.addImm(xsz >> 2, 23); + opcode.addImm(offset32 & 0x1FF, 12); + opcode.addImm(m.isPreIndex(), 11); + opcode |= B(10); + opcode.addReg(o0, 0); + goto EmitOp_MemBase_Rn5; + } + else { + uint32_t imm12 = uint32_t(offset32) >> xsz; + + // If this instruction is not encodable with scaled unsigned offset, try unscaled signed offset. + if (!Support::isUInt12(imm12) || (imm12 << xsz) != uint32_t(offset32)) { + instId = opData.uAltInstId; + instInfo = &InstDB::_instInfoTable[instId]; + encodingIndex = instInfo->_encodingDataIndex; + goto Case_SimdLdurStur; + } + + opcode.reset(uint32_t(opData.uOffsetOp) << 22); + opcode.addImm(xsz & 3u, 30); + opcode.addImm(xsz >> 2, 23); + opcode.addImm(imm12, 10); + opcode.addReg(o0, 0); + goto EmitOp_MemBase_Rn5; + } + } + else { + if (!opData.literalOp) + goto InvalidAddress; + + if (xsz < 2u) + goto InvalidRegType; + + uint32_t opc = xsz - 2u; + opcode.reset(uint32_t(opData.literalOp) << 24); + opcode.addImm(opc, 30); + opcode.addReg(o0, 0); + offsetFormat.resetToImmValue(OffsetType::kSignedOffset, 4, 5, 19, 2); + goto EmitOp_Rel; + } + } + + break; + } + + case InstDB::kEncodingSimdLdpStp: { + const InstDB::EncodingData::SimdLdpStp& opData = InstDB::EncodingData::simdLdpStp[encodingIndex]; + + if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { + const Mem& m = o2.as<Mem>(); + rmRel = &m; + + uint32_t opc = diff(o0.as<Reg>().type(), RegType::kARM_VecS); + if (opc > 2u || o0.as<Vec>().hasElementTypeOrIndex()) + goto InvalidInstruction; + + if (!checkSignature(o0, o1)) + goto InvalidInstruction; + + if (!checkVecId(o0, o1)) + goto InvalidPhysId; + + if (m.baseType() != RegType::kARM_GpX || m.hasIndex()) + goto InvalidAddress; + + if (m.isOffset64Bit()) + goto InvalidDisplacement; + + uint32_t offsetShift = 2u + opc; + int32_t offset32 = m.offsetLo32() >> offsetShift; + + // Make sure we didn't lose bits by applying the mandatory offset shift. + if (Support::shl(offset32, offsetShift) != m.offsetLo32()) + goto InvalidDisplacement; + + // Offset is encoded as a 7-bit immediate. + if (!Support::isInt7(offset32)) + goto InvalidDisplacement; + + if (m.isPreOrPost() && offset32 != 0) { + if (!opData.prePostOp) + goto InvalidAddress; + + opcode.reset(uint32_t(opData.prePostOp) << 22); + opcode.addImm(m.isPreIndex(), 24); + } + else { + opcode.reset(uint32_t(opData.offsetOp) << 22); + } + + opcode.addImm(opc, 30); + opcode.addImm(offset32 & 0x7F, 15); + opcode.addReg(o1, 10); + opcode.addReg(o0, 0); + goto EmitOp_MemBase_Rn5; + } + + break; + } + + case InstDB::kEncodingSimdLdurStur: { +Case_SimdLdurStur: + const InstDB::EncodingData::SimdLdurStur& opData = InstDB::EncodingData::simdLdurStur[encodingIndex]; + + if (isign4 == ENC_OPS2(Reg, Mem)) { + const Mem& m = o1.as<Mem>(); + rmRel = &m; + + uint32_t sz = diff(o0.as<Reg>().type(), RegType::kARM_VecB); + if (sz > 4 || o0.as<Vec>().hasElementTypeOrIndex()) + goto InvalidInstruction; + + if (!checkVecId(o0)) + goto InvalidPhysId; + + if (!armCheckMemBaseIndexRel(m)) + goto InvalidAddress; + + if (m.hasBaseReg() && !m.hasIndex() && !m.isPreOrPost()) { + if (m.isOffset64Bit()) + goto InvalidDisplacement; + + int32_t offset32 = m.offsetLo32(); + if (!Support::isInt9(offset32)) + goto InvalidDisplacement; + + opcode.reset(uint32_t(opData.opcode) << 10); + opcode.addImm(sz & 3u, 30); + opcode.addImm(sz >> 2, 23); + opcode.addImm(offset32 & 0x1FF, 12); + opcode.addReg(o0, 0); + goto EmitOp_MemBase_Rn5; + } + + goto InvalidAddress; + } + + break; + } + + case InstDB::kEncodingSimdLdNStN: { + const InstDB::EncodingData::SimdLdNStN& opData = InstDB::EncodingData::simdLdNStN[encodingIndex]; + const Operand_& o4 = opExt[EmitterUtils::kOp4]; + + uint32_t n = 1; + + if (isign4 == ENC_OPS2(Reg, Mem)) { + if (opData.n != 1) + goto InvalidInstruction; + + rmRel = &o1; + } + else if (isign4 == ENC_OPS3(Reg, Reg, Mem)) { + if (opData.n != 1 && opData.n != 2) + goto InvalidInstruction; + + if (!checkSignature(o0, o1) || !checkConsecutive(o0, o1)) + goto InvalidInstruction; + + n = 2; + rmRel = &o2; + } + else if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem) && o4.isNone()) { + if (opData.n != 1 && opData.n != 3) + goto InvalidInstruction; + + if (!checkSignature(o0, o1, o2) || !checkConsecutive(o0, o1, o2)) + goto InvalidInstruction; + + n = 3; + rmRel = &o3; + } + else if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg) && o4.isMem()) { + if (opData.n != 1 && opData.n != 4) + goto InvalidInstruction; + + if (!checkSignature(o0, o1, o2, o3) || !checkConsecutive(o0, o1, o2, o3)) + goto InvalidInstruction; + + n = 4; + rmRel = &o4; + } + else { + goto InvalidInstruction; + } + + // We will use `v` and `m` from now as those are relevant for encoding. + const Vec& v = o0.as<Vec>(); + const Mem& m = rmRel->as<Mem>(); + + uint32_t q = 0; + uint32_t rm = 0; + uint32_t rn = m.baseId(); + uint32_t sz = v.elementType() - Vec::kElementTypeB; + uint32_t opcSsize = sz; + uint32_t offsetPossibility = 0; + + if (sz > 3) + goto InvalidInstruction; + + if (m.baseType() != RegType::kARM_GpX) + goto InvalidAddress; + + // Rn cannot be ZR, but can be SP. + if (rn > 30 && rn != Gp::kIdSp) + goto InvalidAddress; + + rn &= 31; + + if (opData.replicate) { + if (n != opData.n) + goto InvalidInstruction; + + // Replicates to the whole register, element index cannot be used. + if (v.hasElementIndex()) + goto InvalidInstruction; + + q = diff(v.type(), RegType::kARM_VecD); + if (q > 1) + goto InvalidInstruction; + + opcode.reset(uint32_t(opData.singleOp) << 10); + offsetPossibility = (1u << sz) * n; + } + else if (v.hasElementIndex()) { + if (n != opData.n) + goto InvalidInstruction; + + // LDx/STx (single structure). + static const uint8_t opcSsizeBySzS[] = { 0x0u << 3, 0x2u << 3, 0x4u << 3, (0x4u << 3) | 1u }; + + opcode.reset(uint32_t(opData.singleOp) << 10); + opcSsize = opcSsizeBySzS[sz]; + offsetPossibility = (1u << sz) * opData.n; + + uint32_t elementIndex = v.elementIndex(); + uint32_t maxElementIndex = 15 >> sz; + + if (elementIndex > maxElementIndex) + goto InvalidElementIndex; + + elementIndex <<= sz; + q = elementIndex >> 3; + opcSsize |= elementIndex & 0x7u; + } + else { + // LDx/STx (multiple structures). + static const uint8_t opcSsizeByN[] = { 0u, 0x7u << 2, 0xAu << 2, 0x6u << 2, 0x2u << 2 }; + + q = diff(v.type(), RegType::kARM_VecD); + if (q > 1) + goto InvalidInstruction; + + if (opData.n == 1) + opcSsize |= opcSsizeByN[n]; + + opcode.reset(uint32_t(opData.multipleOp) << 10); + offsetPossibility = (8u << q) * n; + } + + if (m.hasIndex()) { + if (m.hasOffset() || !m.isPostIndex()) + goto InvalidAddress; + + rm = m.indexId(); + if (rm > 30) + goto InvalidAddress; + + // Bit 23 - PostIndex. + opcode |= B(23); + } + else { + if (m.hasOffset()) { + if (m.offset() != int32_t(offsetPossibility) || !m.isPostIndex()) + goto InvalidAddress; + rm = 31; + + // Bit 23 - PostIndex. + opcode |= B(23); + } + } + + opcode.addImm(q, 30); + opcode.addImm(rm, 16); + opcode.addImm(opcSsize, 10); + opcode.addImm(rn, 5); + goto EmitOp_Rd0; + } + + default: + break; + } + + goto InvalidInstruction; + + // -------------------------------------------------------------------------- + // [EmitGp - Single] + // -------------------------------------------------------------------------- + +EmitOp_Rd0: + if (!checkValidRegs(o0)) + goto InvalidPhysId; + + opcode.addReg(o0, 0); + goto EmitOp; + +EmitOp_Rn5: + if (!checkValidRegs(o0)) + goto InvalidPhysId; + + opcode.addReg(o0, 5); + goto EmitOp; + +EmitOp_Rn5_Rm16: + if (!checkValidRegs(o0, o1)) + goto InvalidPhysId; + + opcode.addReg(o0, 5); + opcode.addReg(o1, 16); + goto EmitOp; + +EmitOp_Rd0_Rn5: + if (!checkValidRegs(o0, o1)) + goto InvalidPhysId; + + opcode.addReg(o0, 0); + opcode.addReg(o1, 5); + goto EmitOp; + +EmitOp_Rd0_Rn5_Rm16_Ra10: + if (!checkValidRegs(o0, o1, o2, o3)) + goto InvalidPhysId; + + opcode.addReg(o0, 0); + opcode.addReg(o1, 5); + opcode.addReg(o2, 16); + opcode.addReg(o3, 10); + goto EmitOp; + +EmitOp_Rd0_Rn5_Rm16: + if (!checkValidRegs(o0, o1, o3)) + goto InvalidPhysId; + + opcode.addReg(o0, 0); + opcode.addReg(o1, 5); + opcode.addReg(o2, 16); + goto EmitOp; + + // -------------------------------------------------------------------------- + // [EmitGp - Multiple] + // -------------------------------------------------------------------------- + +EmitOp_Multiple: + { + ASMJIT_ASSERT(multipleOpCount > 0); + err = writer.ensureSpace(this, multipleOpCount * 4u); + if (ASMJIT_UNLIKELY(err)) + goto Failed; + + for (uint32_t i = 0; i < multipleOpCount; i++) + writer.emit32uLE(multipleOpData[i]); + + goto EmitDone; + } + + // -------------------------------------------------------------------------- + // [EmitGp - Memory] + // -------------------------------------------------------------------------- + +EmitOp_MemBase_Rn5: + if (!checkMemBase(rmRel->as<Mem>())) + goto InvalidAddress; + + opcode.addReg(rmRel->as<Mem>().baseId(), 5); + goto EmitOp; + +EmitOp_MemBaseNoImm_Rn5: + if (!checkMemBase(rmRel->as<Mem>()) || rmRel->as<Mem>().hasIndex()) + goto InvalidAddress; + + if (rmRel->as<Mem>().hasOffset()) + goto InvalidDisplacement; + + opcode.addReg(rmRel->as<Mem>().baseId(), 5); + goto EmitOp; + +EmitOp_MemBaseIndex_Rn5_Rm16: + if (!rmRel->as<Mem>().hasBaseReg()) + goto InvalidAddress; + + if (rmRel->as<Mem>().indexId() > 30 && rmRel->as<Mem>().indexId() != Gp::kIdZr) + goto InvalidPhysId; + + opcode.addReg(rmRel->as<Mem>().indexId(), 16); + opcode.addReg(rmRel->as<Mem>().baseId(), 5); + goto EmitOp; + + // -------------------------------------------------------------------------- + // [EmitOp - PC Relative] + // -------------------------------------------------------------------------- + +EmitOp_Rel: + { + if (rmRel->isLabel() || rmRel->isMem()) { + uint32_t labelId; + int64_t labelOffset = 0; + + if (rmRel->isLabel()) { + labelId = rmRel->as<Label>().id(); + } + else { + labelId = rmRel->as<Mem>().baseId(); + labelOffset = rmRel->as<Mem>().offset(); + } + + LabelEntry* label = _code->labelEntry(labelId); + if (ASMJIT_UNLIKELY(!label)) + goto InvalidLabel; + + if (offsetFormat.type() == OffsetType::kAArch64_ADRP) { + // TODO: [ARM] Always create relocation entry. + } + + if (label->isBoundTo(_section)) { + // Label bound to the current section. + offsetValue = label->offset() - uint64_t(offset()) + uint64_t(labelOffset); + goto EmitOp_DispImm; + } + else { + // Record non-bound label. + size_t codeOffset = writer.offsetFrom(_bufferData); + LabelLink* link = _code->newLabelLink(label, _section->id(), codeOffset, intptr_t(labelOffset), offsetFormat); + + if (ASMJIT_UNLIKELY(!link)) + goto OutOfMemory; + + goto EmitOp; + } + } + } + + if (rmRel->isImm()) { + uint64_t baseAddress = _code->baseAddress(); + uint64_t targetOffset = rmRel->as<Imm>().valueAs<uint64_t>(); + + size_t codeOffset = writer.offsetFrom(_bufferData); + + if (baseAddress == Globals::kNoBaseAddress || _section->id() != 0) { + // Create a new RelocEntry as we cannot calculate the offset right now. + RelocEntry* re; + err = _code->newRelocEntry(&re, RelocType::kAbsToRel); + if (err) + goto Failed; + + re->_sourceSectionId = _section->id(); + re->_sourceOffset = codeOffset; + re->_format = offsetFormat; + re->_payload = rmRel->as<Imm>().valueAs<uint64_t>() + 4u; + goto EmitOp; + } + else { + uint64_t pc = baseAddress + codeOffset; + + if (offsetFormat.type() == OffsetType::kAArch64_ADRP) + pc &= ~uint64_t(4096 - 1); + + offsetValue = targetOffset - pc; + goto EmitOp_DispImm; + } + } + + goto InvalidInstruction; + +EmitOp_DispImm: + { + if ((offsetValue & Support::lsbMask<uint32_t>(offsetFormat.immDiscardLsb())) != 0) + goto InvalidDisplacement; + + int64_t dispImm64 = int64_t(offsetValue) >> offsetFormat.immDiscardLsb(); + if (!Support::isEncodableOffset64(dispImm64, offsetFormat.immBitCount())) + goto InvalidDisplacement; + + uint32_t dispImm32 = uint32_t(dispImm64 & Support::lsbMask<uint32_t>(offsetFormat.immBitCount())); + switch (offsetFormat.type()) { + case OffsetType::kSignedOffset: { + opcode.addImm(dispImm32, offsetFormat.immBitShift()); + goto EmitOp; + } + + case OffsetType::kAArch64_ADR: + case OffsetType::kAArch64_ADRP: { + uint32_t immLo = dispImm32 & 0x3u; + uint32_t immHi = dispImm32 >> 2; + opcode.addImm(immLo, 29); + opcode.addImm(immHi, 5); + goto EmitOp; + } + + default: + goto InvalidDisplacement; + } + } + + // -------------------------------------------------------------------------- + // [EmitOp - Opcode] + // -------------------------------------------------------------------------- + +EmitOp: + writer.emit32uLE(opcode.get()); + goto EmitDone; + + // -------------------------------------------------------------------------- + // [Done] + // -------------------------------------------------------------------------- + +EmitDone: + if (Support::test(options, InstOptions::kReserved)) { +#ifndef ASMJIT_NO_LOGGING + if (_logger) + EmitterUtils::logInstructionEmitted(this, instId, options, o0, o1, o2, opExt, 0, 0, writer.cursor()); +#endif + } + + resetExtraReg(); + resetInstOptions(); + resetInlineComment(); + + writer.done(this); + return kErrorOk; + + // -------------------------------------------------------------------------- + // [Error Handler] + // -------------------------------------------------------------------------- + +#define ERROR_HANDLER(ERR) ERR: err = DebugUtils::errored(kError##ERR); goto Failed; + ERROR_HANDLER(OutOfMemory) + ERROR_HANDLER(InvalidAddress) + ERROR_HANDLER(InvalidAddressScale) + ERROR_HANDLER(InvalidDisplacement) + ERROR_HANDLER(InvalidElementIndex) + ERROR_HANDLER(InvalidLabel) + ERROR_HANDLER(InvalidImmediate) + ERROR_HANDLER(InvalidInstruction) + ERROR_HANDLER(InvalidPhysId) + ERROR_HANDLER(InvalidRegType) +#undef ERROR_HANDLER + +Failed: +#ifndef ASMJIT_NO_LOGGING + return EmitterUtils::logInstructionFailed(this, err, instId, options, o0, o1, o2, opExt); +#else + resetExtraReg(); + resetInstOptions(); + resetInlineComment(); + return reportError(err); +#endif +} + +#undef ENC_OPS1 +#undef ENC_OPS2 +#undef ENC_OPS3 +#undef ENC_OPS4 + +// a64::Assembler - Align +// ====================== + +Error Assembler::align(AlignMode alignMode, uint32_t alignment) { + constexpr uint32_t kNopA64 = 0xD503201Fu; // [11010101|00000011|00100000|00011111]. + + if (ASMJIT_UNLIKELY(!_code)) + return reportError(DebugUtils::errored(kErrorNotInitialized)); + + if (ASMJIT_UNLIKELY(uint32_t(alignMode) > uint32_t(AlignMode::kMaxValue))) + return reportError(DebugUtils::errored(kErrorInvalidArgument)); + + if (alignment <= 1) + return kErrorOk; + + if (ASMJIT_UNLIKELY(alignment > Globals::kMaxAlignment || !Support::isPowerOf2(alignment))) + return reportError(DebugUtils::errored(kErrorInvalidArgument)); + + uint32_t i = uint32_t(Support::alignUpDiff<size_t>(offset(), alignment)); + if (i == 0) + return kErrorOk; + + CodeWriter writer(this); + ASMJIT_PROPAGATE(writer.ensureSpace(this, i)); + + switch (alignMode) { + case AlignMode::kCode: { + uint32_t pattern = kNopA64; + + if (ASMJIT_UNLIKELY(offset() & 0x3u)) + return DebugUtils::errored(kErrorInvalidState); + + while (i >= 4) { + writer.emit32uLE(pattern); + i -= 4; + } + + ASMJIT_ASSERT(i == 0); + break; + } + + case AlignMode::kData: + case AlignMode::kZero: + writer.emitZeros(i); + break; + } + + writer.done(this); + +#ifndef ASMJIT_NO_LOGGING + if (_logger) { + StringTmp<128> sb; + sb.appendChars(' ', _logger->indentation(FormatIndentationGroup::kCode)); + sb.appendFormat("align %u\n", alignment); + _logger->log(sb); + } +#endif + + return kErrorOk; +} + +// a64::Assembler - Events +// ======================= + +Error Assembler::onAttach(CodeHolder* code) noexcept { + ASMJIT_PROPAGATE(Base::onAttach(code)); + return kErrorOk; +} + +Error Assembler::onDetach(CodeHolder* code) noexcept { + return Base::onDetach(code); +} + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_AARCH64 diff --git a/src/asmjit/arm/a64assembler.h b/src/asmjit/arm/a64assembler.h new file mode 100644 index 0000000..f1ac72b --- /dev/null +++ b/src/asmjit/arm/a64assembler.h @@ -0,0 +1,72 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64ASSEMBLER_H_INCLUDED +#define ASMJIT_ARM_A64ASSEMBLER_H_INCLUDED + +#include "../core/assembler.h" +#include "../arm/a64emitter.h" +#include "../arm/a64operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \addtogroup asmjit_a64 +//! \{ + +//! AArch64 assembler implementation. +class ASMJIT_VIRTAPI Assembler + : public BaseAssembler, + public EmitterExplicitT<Assembler> { + +public: + typedef BaseAssembler Base; + + //! \name Construction / Destruction + //! \{ + + ASMJIT_API Assembler(CodeHolder* code = nullptr) noexcept; + ASMJIT_API virtual ~Assembler() noexcept; + + //! \} + + //! \name Accessors + //! \{ + + //! Gets whether the current ARM mode is THUMB (alternative to 32-bit ARM encoding). + inline bool isInThumbMode() const noexcept { return _environment.isArchThumb(); } + + //! Gets the current code alignment of the current mode (ARM vs THUMB). + inline uint32_t codeAlignment() const noexcept { return isInThumbMode() ? 2 : 4; } + + //! \} + + //! \name Emit + //! \{ + + ASMJIT_API Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) override; + + //! \} + + //! \name Align + //! \{ + + ASMJIT_API Error align(AlignMode alignMode, uint32_t alignment) override; + + //! \} + + //! \name Events + //! \{ + + ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; + ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; + + //! \} +}; + +//! \} + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_A64ASSEMBLER_H_INCLUDED diff --git a/src/asmjit/arm/a64builder.cpp b/src/asmjit/arm/a64builder.cpp new file mode 100644 index 0000000..3a52b2a --- /dev/null +++ b/src/asmjit/arm/a64builder.cpp @@ -0,0 +1,51 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#if !defined(ASMJIT_NO_AARCH64) && !defined(ASMJIT_NO_BUILDER) + +#include "../arm/a64assembler.h" +#include "../arm/a64builder.h" +#include "../arm/a64emithelper_p.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +// a64::Builder - Construction & Destruction +// ========================================= + +Builder::Builder(CodeHolder* code) noexcept : BaseBuilder() { + _archMask = uint64_t(1) << uint32_t(Arch::kAArch64); + assignEmitterFuncs(this); + + if (code) + code->attach(this); +} +Builder::~Builder() noexcept {} + +// a64::Builder - Events +// ===================== + +Error Builder::onAttach(CodeHolder* code) noexcept { + return Base::onAttach(code); +} + +Error Builder::onDetach(CodeHolder* code) noexcept { + return Base::onDetach(code); +} + +// a64::Builder - Finalize +// ======================= + +Error Builder::finalize() { + ASMJIT_PROPAGATE(runPasses()); + Assembler a(_code); + a.addEncodingOptions(encodingOptions()); + a.addDiagnosticOptions(diagnosticOptions()); + return serializeTo(&a); +} + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_AARCH64 && !ASMJIT_NO_BUILDER diff --git a/src/asmjit/arm/a64builder.h b/src/asmjit/arm/a64builder.h new file mode 100644 index 0000000..adc99aa --- /dev/null +++ b/src/asmjit/arm/a64builder.h @@ -0,0 +1,57 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64BUILDER_H_INCLUDED +#define ASMJIT_ARM_A64BUILDER_H_INCLUDED + +#include "../core/api-config.h" +#ifndef ASMJIT_NO_BUILDER + +#include "../core/builder.h" +#include "../arm/a64emitter.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \addtogroup asmjit_a64 +//! \{ + +//! AArch64 builder implementation. +class ASMJIT_VIRTAPI Builder + : public BaseBuilder, + public EmitterExplicitT<Builder> { +public: + ASMJIT_NONCOPYABLE(Builder) + typedef BaseBuilder Base; + + //! \name Construction & Destruction + //! \{ + + ASMJIT_API explicit Builder(CodeHolder* code = nullptr) noexcept; + ASMJIT_API virtual ~Builder() noexcept; + + //! \} + + //! \name Events + //! \{ + + ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; + ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; + + //! \} + + //! \name Finalize + //! \{ + + ASMJIT_API Error finalize() override; + + //! \} +}; + +//! \} + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_BUILDER +#endif // ASMJIT_ARM_A64BUILDER_H_INCLUDED diff --git a/src/asmjit/arm/a64compiler.cpp b/src/asmjit/arm/a64compiler.cpp new file mode 100644 index 0000000..d6c4ed2 --- /dev/null +++ b/src/asmjit/arm/a64compiler.cpp @@ -0,0 +1,60 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#if !defined(ASMJIT_NO_AARCH64) && !defined(ASMJIT_NO_COMPILER) + +#include "../arm/a64assembler.h" +#include "../arm/a64compiler.h" +#include "../arm/a64emithelper_p.h" +#include "../arm/a64rapass_p.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +// a64::Compiler - Construction & Destruction +// ========================================== + +Compiler::Compiler(CodeHolder* code) noexcept : BaseCompiler() { + _archMask = uint64_t(1) << uint32_t(Arch::kAArch64); + assignEmitterFuncs(this); + + if (code) + code->attach(this); +} +Compiler::~Compiler() noexcept {} + +// a64::Compiler - Events +// ====================== + +Error Compiler::onAttach(CodeHolder* code) noexcept { + ASMJIT_PROPAGATE(Base::onAttach(code)); + Error err = addPassT<ARMRAPass>(); + + if (ASMJIT_UNLIKELY(err)) { + onDetach(code); + return err; + } + + return kErrorOk; +} + +Error Compiler::onDetach(CodeHolder* code) noexcept { + return Base::onDetach(code); +} + +// a64::Compiler - Finalize +// ======================== + +Error Compiler::finalize() { + ASMJIT_PROPAGATE(runPasses()); + Assembler a(_code); + a.addEncodingOptions(encodingOptions()); + a.addDiagnosticOptions(diagnosticOptions()); + return serializeTo(&a); +} + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_AARCH64 && !ASMJIT_NO_COMPILER diff --git a/src/asmjit/arm/a64compiler.h b/src/asmjit/arm/a64compiler.h new file mode 100644 index 0000000..ebed549 --- /dev/null +++ b/src/asmjit/arm/a64compiler.h @@ -0,0 +1,235 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_ARMCOMPILER_H_INCLUDED +#define ASMJIT_ARM_ARMCOMPILER_H_INCLUDED + +#include "../core/api-config.h" +#ifndef ASMJIT_NO_COMPILER + +#include "../core/compiler.h" +#include "../core/type.h" +#include "../arm/a64emitter.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \addtogroup asmjit_a64 +//! \{ + +//! AArch64 compiler implementation. +class ASMJIT_VIRTAPI Compiler + : public BaseCompiler, + public EmitterExplicitT<Compiler> { +public: + ASMJIT_NONCOPYABLE(Compiler) + typedef BaseCompiler Base; + + //! \name Construction & Destruction + //! \{ + + ASMJIT_API explicit Compiler(CodeHolder* code = nullptr) noexcept; + ASMJIT_API virtual ~Compiler() noexcept; + + //! \} + + //! \name Virtual Registers + //! \{ + + //! \cond INTERNAL + template<typename RegT, typename Type> + inline RegT _newRegInternal(const Type& type) { + RegT reg(Globals::NoInit); + _newReg(®, type, nullptr); + return reg; + } + + template<typename RegT, typename Type, typename... Args> + inline RegT _newRegInternal(const Type& type, const char* s, Args&&... args) { +#ifndef ASMJIT_NO_LOGGING + RegT reg(Globals::NoInit); + if (sizeof...(Args) == 0) + _newReg(®, type, s); + else + _newRegFmt(®, type, s, std::forward<Args>(args)...); + return reg; +#else + DebugUtils::unused(std::forward<Args>(args)...); + RegT reg(Globals::NoInit); + _newReg(®, type, nullptr); + return reg; +#endif + } + //! \endcond + + template<typename RegT, typename... Args> + inline RegT newSimilarReg(const RegT& ref, Args&&... args) { + return _newRegInternal<RegT>(ref, std::forward<Args>(args)...); + } + + template<typename... Args> + inline Reg newReg(TypeId typeId, Args&&... args) { return _newRegInternal<Reg>(typeId, std::forward<Args>(args)...); } + + template<typename... Args> + inline Gp newGp(TypeId typeId, Args&&... args) { return _newRegInternal<Gp>(typeId, std::forward<Args>(args)...); } + + template<typename... Args> + inline Vec newVec(TypeId typeId, Args&&... args) { return _newRegInternal<Vec>(typeId, std::forward<Args>(args)...); } + + template<typename... Args> + inline Gp newInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt32, std::forward<Args>(args)...); } + template<typename... Args> + inline Gp newUInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); } + + template<typename... Args> + inline Gp newInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt64, std::forward<Args>(args)...); } + template<typename... Args> + inline Gp newUInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); } + + template<typename... Args> + inline Gp newIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kIntPtr, std::forward<Args>(args)...); } + template<typename... Args> + inline Gp newUIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); } + + template<typename... Args> + inline Gp newGpw(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); } + template<typename... Args> + inline Gp newGpx(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); } + template<typename... Args> + inline Gp newGpz(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); } + + template<typename... Args> + inline Vec newVecS(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat32, std::forward<Args>(args)...); } + + template<typename... Args> + inline Vec newVecD(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat64, std::forward<Args>(args)...); } + + template<typename... Args> + inline Vec newVecQ(Args&&... args) { return _newRegInternal<Vec>(TypeId::kUInt8x16, std::forward<Args>(args)...); } + + //! \} + + //! \name Stack + //! \{ + + //! Creates a new memory chunk allocated on the current function's stack. + inline Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) { + Mem m(Globals::NoInit); + _newStack(&m, size, alignment, name); + return m; + } + + //! \} + + //! \name Constants + //! \{ + + //! Put data to a constant-pool and get a memory reference to it. + inline Mem newConst(ConstPoolScope scope, const void* data, size_t size) { + Mem m(Globals::NoInit); + _newConst(&m, scope, data, size); + return m; + } + + //! Put a BYTE `val` to a constant-pool (8 bits). + inline Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); } + //! Put a HWORD `val` to a constant-pool (16 bits). + inline Mem newHWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } + //! Put a WORD `val` to a constant-pool (32 bits). + inline Mem newWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } + //! Put a DWORD `val` to a constant-pool (64 bits). + inline Mem newDWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } + + //! Put a WORD `val` to a constant-pool. + inline Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); } + //! Put a WORD `val` to a constant-pool. + inline Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); } + //! Put a DWORD `val` to a constant-pool. + inline Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); } + //! Put a DWORD `val` to a constant-pool. + inline Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); } + //! Put a QWORD `val` to a constant-pool. + inline Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); } + //! Put a QWORD `val` to a constant-pool. + inline Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); } + + //! Put a SP-FP `val` to a constant-pool. + inline Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); } + //! Put a DP-FP `val` to a constant-pool. + inline Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); } + + //! \} + + //! \name Instruction Options + //! \{ + + //! Force the compiler to not follow the conditional or unconditional jump. + inline Compiler& unfollow() noexcept { _instOptions |= InstOptions::kUnfollow; return *this; } + + //! \} + + //! \name Function Call & Ret Intrinsics + //! \{ + + //! Invoke a function call without `target` type enforcement. + inline Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) { + return addInvokeNode(out, Inst::kIdBlr, target, signature); + } + + //! Invoke a function call of the given `target` and `signature` and store the added node to `out`. + //! + //! Creates a new \ref InvokeNode, initializes all the necessary members to match the given function `signature`, + //! adds the node to the compiler, and stores its pointer to `out`. The operation is atomic, if anything fails + //! nullptr is stored in `out` and error code is returned. + inline Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + //! \overload + inline Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + //! \overload + inline Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + //! \overload + inline Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); } + //! \overload + inline Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); } + + //! Return. + inline Error ret() { return addRet(Operand(), Operand()); } + //! \overload + inline Error ret(const BaseReg& o0) { return addRet(o0, Operand()); } + //! \overload + inline Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); } + + //! \} + + //! \name Jump Tables Support + //! \{ + + using EmitterExplicitT<Compiler>::br; + + //! Adds a jump to the given `target` with the provided jump `annotation`. + inline Error br(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdBr, target, annotation); } + + //! \} + + //! \name Events + //! \{ + + ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; + ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; + + //! \} + + //! \name Finalize + //! \{ + + ASMJIT_API Error finalize() override; + + //! \} +}; + +//! \} + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_COMPILER +#endif // ASMJIT_ARM_ARMCOMPILER_H_INCLUDED diff --git a/src/asmjit/arm/a64emithelper.cpp b/src/asmjit/arm/a64emithelper.cpp new file mode 100644 index 0000000..2d8a578 --- /dev/null +++ b/src/asmjit/arm/a64emithelper.cpp @@ -0,0 +1,464 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#if !defined(ASMJIT_NO_AARCH64) + +#include "../core/formatter.h" +#include "../core/funcargscontext_p.h" +#include "../core/string.h" +#include "../core/support.h" +#include "../core/type.h" +#include "../arm/a64emithelper_p.h" +#include "../arm/a64formatter_p.h" +#include "../arm/a64instapi_p.h" +#include "../arm/a64operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +// a64::EmitHelper - Emit Operations +// ================================= + +ASMJIT_FAVOR_SIZE Error EmitHelper::emitRegMove( + const Operand_& dst_, + const Operand_& src_, TypeId typeId, const char* comment) { + + Emitter* emitter = _emitter->as<Emitter>(); + + // Invalid or abstract TypeIds are not allowed. + ASMJIT_ASSERT(TypeUtils::isValid(typeId) && !TypeUtils::isAbstract(typeId)); + + emitter->setInlineComment(comment); + + if (dst_.isReg() && src_.isMem()) { + Reg dst(dst_.as<Reg>()); + Mem src(src_.as<Mem>()); + + switch (typeId) { + case TypeId::kInt8: + case TypeId::kUInt8: + return emitter->ldrb(dst.as<Gp>(), src); + + case TypeId::kInt16: + case TypeId::kUInt16: + return emitter->ldrh(dst.as<Gp>(), src); + + case TypeId::kInt32: + case TypeId::kUInt32: + return emitter->ldr(dst.as<Gp>().w(), src); + + case TypeId::kInt64: + case TypeId::kUInt64: + return emitter->ldr(dst.as<Gp>().x(), src); + + default: { + if (TypeUtils::isFloat32(typeId) || TypeUtils::isVec32(typeId)) + return emitter->ldr(dst.as<Vec>().s(), src); + + if (TypeUtils::isFloat64(typeId) || TypeUtils::isVec64(typeId)) + return emitter->ldr(dst.as<Vec>().d(), src); + + if (TypeUtils::isVec128(typeId)) + return emitter->ldr(dst.as<Vec>().q(), src); + + break; + } + } + } + + if (dst_.isMem() && src_.isReg()) { + Mem dst(dst_.as<Mem>()); + Reg src(src_.as<Reg>()); + + switch (typeId) { + case TypeId::kInt8: + case TypeId::kUInt8: + return emitter->strb(src.as<Gp>(), dst); + + case TypeId::kInt16: + case TypeId::kUInt16: + return emitter->strh(src.as<Gp>(), dst); + + case TypeId::kInt32: + case TypeId::kUInt32: + return emitter->str(src.as<Gp>().w(), dst); + + case TypeId::kInt64: + case TypeId::kUInt64: + return emitter->str(src.as<Gp>().x(), dst); + + default: { + if (TypeUtils::isFloat32(typeId) || TypeUtils::isVec32(typeId)) + return emitter->str(src.as<Vec>().s(), dst); + + if (TypeUtils::isFloat64(typeId) || TypeUtils::isVec64(typeId)) + return emitter->str(src.as<Vec>().d(), dst); + + if (TypeUtils::isVec128(typeId)) + return emitter->str(src.as<Vec>().q(), dst); + + break; + } + } + } + + if (dst_.isReg() && src_.isReg()) { + Reg dst(dst_.as<Reg>()); + Reg src(src_.as<Reg>()); + + switch (typeId) { + case TypeId::kInt8: + case TypeId::kUInt8: + case TypeId::kInt16: + case TypeId::kUInt16: + case TypeId::kInt32: + case TypeId::kUInt32: + case TypeId::kInt64: + case TypeId::kUInt64: + return emitter->mov(src.as<Gp>().x(), dst.as<Gp>().x()); + + default: { + if (TypeUtils::isFloat32(typeId) || TypeUtils::isVec32(typeId)) + return emitter->fmov(dst.as<Vec>().s(), src.as<Vec>().s()); + + if (TypeUtils::isFloat64(typeId) || TypeUtils::isVec64(typeId)) + return emitter->mov(dst.as<Vec>().b8(), src.as<Vec>().b8()); + + if (TypeUtils::isVec128(typeId)) + return emitter->mov(dst.as<Vec>().b16(), src.as<Vec>().b16()); + + break; + } + } + } + + emitter->setInlineComment(nullptr); + return DebugUtils::errored(kErrorInvalidState); +} + +Error EmitHelper::emitRegSwap( + const BaseReg& a, + const BaseReg& b, const char* comment) { + + DebugUtils::unused(a, b, comment); + return DebugUtils::errored(kErrorInvalidState); +} + +// TODO: [ARM] EmitArgMove is unfinished. +Error EmitHelper::emitArgMove( + const BaseReg& dst_, TypeId dstTypeId, + const Operand_& src_, TypeId srcTypeId, const char* comment) { + + // Deduce optional `dstTypeId`, which may be `TypeId::kVoid` in some cases. + if (dstTypeId == TypeId::kVoid) { + const ArchTraits& archTraits = ArchTraits::byArch(_emitter->arch()); + dstTypeId = archTraits.regTypeToTypeId(dst_.type()); + } + + // Invalid or abstract TypeIds are not allowed. + ASMJIT_ASSERT(TypeUtils::isValid(dstTypeId) && !TypeUtils::isAbstract(dstTypeId)); + ASMJIT_ASSERT(TypeUtils::isValid(srcTypeId) && !TypeUtils::isAbstract(srcTypeId)); + + Reg dst(dst_.as<Reg>()); + Operand src(src_); + + uint32_t dstSize = TypeUtils::sizeOf(dstTypeId); + uint32_t srcSize = TypeUtils::sizeOf(srcTypeId); + + if (TypeUtils::isInt(dstTypeId)) { + if (TypeUtils::isInt(srcTypeId)) { + uint32_t x = dstSize == 8; + + dst.setSignature(OperandSignature{x ? uint32_t(GpX::kSignature) : uint32_t(GpW::kSignature)}); + _emitter->setInlineComment(comment); + + if (src.isReg()) { + src.setSignature(dst.signature()); + return _emitter->emit(Inst::kIdMov, dst, src); + } + else if (src.isMem()) { + InstId instId = Inst::kIdNone; + switch (srcTypeId) { + case TypeId::kInt8: instId = Inst::kIdLdrsb; break; + case TypeId::kUInt8: instId = Inst::kIdLdrb; break; + case TypeId::kInt16: instId = Inst::kIdLdrsh; break; + case TypeId::kUInt16: instId = Inst::kIdLdrh; break; + case TypeId::kInt32: instId = x ? Inst::kIdLdrsw : Inst::kIdLdr; break; + case TypeId::kUInt32: instId = Inst::kIdLdr; x = 0; break; + case TypeId::kInt64: instId = Inst::kIdLdr; break; + case TypeId::kUInt64: instId = Inst::kIdLdr; break; + default: + return DebugUtils::errored(kErrorInvalidState); + } + return _emitter->emit(instId, dst, src); + } + } + } + + if (TypeUtils::isFloat(dstTypeId) || TypeUtils::isVec(dstTypeId)) { + if (TypeUtils::isFloat(srcTypeId) || TypeUtils::isVec(srcTypeId)) { + switch (srcSize) { + case 2: dst.as<Vec>().setSignature(OperandSignature{VecH::kSignature}); break; + case 4: dst.as<Vec>().setSignature(OperandSignature{VecS::kSignature}); break; + case 8: dst.as<Vec>().setSignature(OperandSignature{VecD::kSignature}); break; + case 16: dst.as<Vec>().setSignature(OperandSignature{VecV::kSignature}); break; + default: + return DebugUtils::errored(kErrorInvalidState); + } + + _emitter->setInlineComment(comment); + + if (src.isReg()) { + InstId instId = srcSize <= 4 ? Inst::kIdFmov_v : Inst::kIdMov_v; + src.setSignature(dst.signature()); + return _emitter->emit(instId, dst, src); + } + else if (src.isMem()) { + return _emitter->emit(Inst::kIdLdr_v, dst, src); + } + } + } + + return DebugUtils::errored(kErrorInvalidState); +} + +// a64::EmitHelper - Emit Prolog & Epilog +// ====================================== + +struct LoadStoreInstructions { + InstId singleInstId; + InstId pairInstId; +}; + +struct PrologEpilogInfo { + struct RegPair { + uint8_t ids[2]; + uint16_t offset; + }; + + struct GroupData { + RegPair pairs[16]; + uint32_t pairCount; + }; + + Support::Array<GroupData, 2> groups; + uint32_t sizeTotal; + + Error init(const FuncFrame& frame) noexcept { + uint32_t offset = 0; + + for (RegGroup group : Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kVec>{}) { + GroupData& data = groups[group]; + + uint32_t n = 0; + uint32_t pairCount = 0; + RegPair* pairs = data.pairs; + + uint32_t slotSize = frame.saveRestoreRegSize(group); + uint32_t savedRegs = frame.savedRegs(group); + + if (group == RegGroup::kGp && frame.hasPreservedFP()) { + // Must be at the beginning of the push/pop sequence. + ASMJIT_ASSERT(pairCount == 0); + + pairs[0].offset = uint16_t(offset); + pairs[0].ids[0] = Gp::kIdFp; + pairs[0].ids[1] = Gp::kIdLr; + offset += slotSize * 2; + pairCount++; + + savedRegs &= ~Support::bitMask(Gp::kIdFp, Gp::kIdLr); + } + + Support::BitWordIterator<uint32_t> it(savedRegs); + while (it.hasNext()) { + pairs[pairCount].ids[n] = uint8_t(it.next()); + + if (++n == 2) { + pairs[pairCount].offset = uint16_t(offset); + offset += slotSize * 2; + + n = 0; + pairCount++; + } + } + + if (n == 1) { + pairs[pairCount].ids[1] = uint8_t(BaseReg::kIdBad); + pairs[pairCount].offset = uint16_t(offset); + offset += slotSize * 2; + pairCount++; + } + + data.pairCount = pairCount; + } + + sizeTotal = offset; + return kErrorOk; + } +}; + +ASMJIT_FAVOR_SIZE Error EmitHelper::emitProlog(const FuncFrame& frame) { + Emitter* emitter = _emitter->as<Emitter>(); + + PrologEpilogInfo pei; + ASMJIT_PROPAGATE(pei.init(frame)); + + static const Support::Array<Reg, 2> groupRegs = {{ x0, d0 }}; + static const Support::Array<LoadStoreInstructions, 2> groupInsts = {{ + { Inst::kIdStr , Inst::kIdStp }, + { Inst::kIdStr_v, Inst::kIdStp_v } + }}; + + uint32_t adjustInitialOffset = pei.sizeTotal; + + for (RegGroup group : Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kVec>{}) { + const PrologEpilogInfo::GroupData& data = pei.groups[group]; + uint32_t pairCount = data.pairCount; + + Reg regs[2] = { groupRegs[group], groupRegs[group] }; + Mem mem = ptr(sp); + + const LoadStoreInstructions& insts = groupInsts[group]; + for (uint32_t i = 0; i < pairCount; i++) { + const PrologEpilogInfo::RegPair& pair = data.pairs[i]; + + regs[0].setId(pair.ids[0]); + regs[1].setId(pair.ids[1]); + mem.setOffsetLo32(pair.offset); + + if (pair.offset == 0 && adjustInitialOffset) { + mem.setOffset(-int(adjustInitialOffset)); + mem.makePreIndex(); + } + + if (pair.ids[1] == BaseReg::kIdBad) + ASMJIT_PROPAGATE(emitter->emit(insts.singleInstId, regs[0], mem)); + else + ASMJIT_PROPAGATE(emitter->emit(insts.pairInstId, regs[0], regs[1], mem)); + + mem.resetToFixedOffset(); + + if (i == 0 && frame.hasPreservedFP()) { + ASMJIT_PROPAGATE(emitter->mov(x29, sp)); + } + } + } + + if (frame.hasStackAdjustment()) { + uint32_t adj = frame.stackAdjustment(); + if (adj <= 0xFFFu) { + ASMJIT_PROPAGATE(emitter->sub(sp, sp, adj)); + } + else if (adj <= 0xFFFFFFu) { + // TODO: [ARM] Prolog - we must touch the pages otherwise it's undefined. + ASMJIT_PROPAGATE(emitter->sub(sp, sp, adj & 0x000FFFu)); + ASMJIT_PROPAGATE(emitter->sub(sp, sp, adj & 0xFFF000u)); + } + else { + return DebugUtils::errored(kErrorInvalidState); + } + } + + return kErrorOk; +} + +// TODO: [ARM] Emit epilog. +ASMJIT_FAVOR_SIZE Error EmitHelper::emitEpilog(const FuncFrame& frame) { + Emitter* emitter = _emitter->as<Emitter>(); + + PrologEpilogInfo pei; + ASMJIT_PROPAGATE(pei.init(frame)); + + static const Support::Array<Reg, 2> groupRegs = {{ x0, d0 }}; + static const Support::Array<LoadStoreInstructions, 2> groupInsts = {{ + { Inst::kIdLdr , Inst::kIdLdp }, + { Inst::kIdLdr_v, Inst::kIdLdp_v } + }}; + + uint32_t adjustInitialOffset = pei.sizeTotal; + + if (frame.hasStackAdjustment()) { + uint32_t adj = frame.stackAdjustment(); + if (adj <= 0xFFFu) { + ASMJIT_PROPAGATE(emitter->add(sp, sp, adj)); + } + else if (adj <= 0xFFFFFFu) { + ASMJIT_PROPAGATE(emitter->add(sp, sp, adj & 0x000FFFu)); + ASMJIT_PROPAGATE(emitter->add(sp, sp, adj & 0xFFF000u)); + } + else { + return DebugUtils::errored(kErrorInvalidState); + } + } + + for (int g = 1; g >= 0; g--) { + RegGroup group = RegGroup(g); + const PrologEpilogInfo::GroupData& data = pei.groups[group]; + uint32_t pairCount = data.pairCount; + + Reg regs[2] = { groupRegs[group], groupRegs[group] }; + Mem mem = ptr(sp); + + const LoadStoreInstructions& insts = groupInsts[group]; + + for (int i = int(pairCount) - 1; i >= 0; i--) { + const PrologEpilogInfo::RegPair& pair = data.pairs[i]; + + regs[0].setId(pair.ids[0]); + regs[1].setId(pair.ids[1]); + mem.setOffsetLo32(pair.offset); + + if (pair.offset == 0 && adjustInitialOffset) { + mem.setOffset(int(adjustInitialOffset)); + mem.makePostIndex(); + } + + if (pair.ids[1] == BaseReg::kIdBad) + ASMJIT_PROPAGATE(emitter->emit(insts.singleInstId, regs[0], mem)); + else + ASMJIT_PROPAGATE(emitter->emit(insts.pairInstId, regs[0], regs[1], mem)); + + mem.resetToFixedOffset(); + } + } + + ASMJIT_PROPAGATE(emitter->ret(x30)); + + return kErrorOk; +} + +static Error ASMJIT_CDECL Emitter_emitProlog(BaseEmitter* emitter, const FuncFrame& frame) { + EmitHelper emitHelper(emitter); + return emitHelper.emitProlog(frame); +} + +static Error ASMJIT_CDECL Emitter_emitEpilog(BaseEmitter* emitter, const FuncFrame& frame) { + EmitHelper emitHelper(emitter); + return emitHelper.emitEpilog(frame); +} + +static Error ASMJIT_CDECL Emitter_emitArgsAssignment(BaseEmitter* emitter, const FuncFrame& frame, const FuncArgsAssignment& args) { + EmitHelper emitHelper(emitter); + return emitHelper.emitArgsAssignment(frame, args); +} + +void assignEmitterFuncs(BaseEmitter* emitter) { + emitter->_funcs.emitProlog = Emitter_emitProlog; + emitter->_funcs.emitEpilog = Emitter_emitEpilog; + emitter->_funcs.emitArgsAssignment = Emitter_emitArgsAssignment; + +#ifndef ASMJIT_NO_LOGGING + emitter->_funcs.formatInstruction = FormatterInternal::formatInstruction; +#endif + +#ifndef ASMJIT_NO_VALIDATION + emitter->_funcs.validate = InstInternal::validate; +#endif +} + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_AARCH64 diff --git a/src/asmjit/arm/a64emithelper_p.h b/src/asmjit/arm/a64emithelper_p.h new file mode 100644 index 0000000..b1ba1a9 --- /dev/null +++ b/src/asmjit/arm/a64emithelper_p.h @@ -0,0 +1,50 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_ARMEMITHELPER_P_H_INCLUDED +#define ASMJIT_ARM_ARMEMITHELPER_P_H_INCLUDED + +#include "../core/api-config.h" + +#include "../core/emithelper_p.h" +#include "../core/func.h" +#include "../arm/a64emitter.h" +#include "../arm/a64operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \cond INTERNAL +//! \addtogroup asmjit_a64 +//! \{ + +class EmitHelper : public BaseEmitHelper { +public: + inline explicit EmitHelper(BaseEmitter* emitter = nullptr) noexcept + : BaseEmitHelper(emitter) {} + + Error emitRegMove( + const Operand_& dst_, + const Operand_& src_, TypeId typeId, const char* comment = nullptr) override; + + Error emitRegSwap( + const BaseReg& a, + const BaseReg& b, const char* comment = nullptr) override; + + Error emitArgMove( + const BaseReg& dst_, TypeId dstTypeId, + const Operand_& src_, TypeId srcTypeId, const char* comment = nullptr) override; + + Error emitProlog(const FuncFrame& frame); + Error emitEpilog(const FuncFrame& frame); +}; + +void assignEmitterFuncs(BaseEmitter* emitter); + +//! \} +//! \endcond + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_ARMEMITHELPER_P_H_INCLUDED diff --git a/src/asmjit/arm/a64emitter.h b/src/asmjit/arm/a64emitter.h new file mode 100644 index 0000000..54354ea --- /dev/null +++ b/src/asmjit/arm/a64emitter.h @@ -0,0 +1,1228 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64EMITTER_H_INCLUDED +#define ASMJIT_ARM_A64EMITTER_H_INCLUDED + +#include "../core/emitter.h" +#include "../core/support.h" +#include "../arm/a64instdb.h" +#include "../arm/a64operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +#define ASMJIT_INST_0x(NAME, ID) \ + inline Error NAME() { return _emitter()->_emitI(Inst::kId##ID); } + +#define ASMJIT_INST_1x(NAME, ID, T0) \ + inline Error NAME(const T0& o0) { return _emitter()->_emitI(Inst::kId##ID, o0); } + +#define ASMJIT_INST_2x(NAME, ID, T0, T1) \ + inline Error NAME(const T0& o0, const T1& o1) { return _emitter()->_emitI(Inst::kId##ID, o0, o1); } + +#define ASMJIT_INST_3x(NAME, ID, T0, T1, T2) \ + inline Error NAME(const T0& o0, const T1& o1, const T2& o2) { return _emitter()->_emitI(Inst::kId##ID, o0, o1, o2); } + +#define ASMJIT_INST_4x(NAME, ID, T0, T1, T2, T3) \ + inline Error NAME(const T0& o0, const T1& o1, const T2& o2, const T3& o3) { return _emitter()->_emitI(Inst::kId##ID, o0, o1, o2, o3); } + +#define ASMJIT_INST_5x(NAME, ID, T0, T1, T2, T3, T4) \ + inline Error NAME(const T0& o0, const T1& o1, const T2& o2, const T3& o3, const T4& o4) { return _emitter()->_emitI(Inst::kId##ID, o0, o1, o2, o3, o4); } + +#define ASMJIT_INST_6x(NAME, ID, T0, T1, T2, T3, T4, T5) \ + inline Error NAME(const T0& o0, const T1& o1, const T2& o2, const T3& o3, const T4& o4, const T5& o5) { return _emitter()->_emitI(Inst::kId##ID, o0, o1, o2, o3, o4, o5); } + +#define ASMJIT_INST_1cc(NAME, ID, T0) \ + inline Error NAME(const T0& o0) { return _emitter()->_emitI(Inst::kId##ID, o0); } \ + \ + inline Error NAME(CondCode cc, const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, cc), o0); } \ + \ + inline Error NAME##_eq(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kEQ), o0); } \ + inline Error NAME##_ne(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kNE), o0); } \ + inline Error NAME##_cs(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kCS), o0); } \ + inline Error NAME##_hs(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kHS), o0); } \ + inline Error NAME##_cc(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kCC), o0); } \ + inline Error NAME##_lo(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kLO), o0); } \ + inline Error NAME##_mi(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kMI), o0); } \ + inline Error NAME##_pl(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kPL), o0); } \ + inline Error NAME##_vs(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kVS), o0); } \ + inline Error NAME##_vc(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kVC), o0); } \ + inline Error NAME##_hi(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kHI), o0); } \ + inline Error NAME##_ls(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kLS), o0); } \ + inline Error NAME##_ge(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kGE), o0); } \ + inline Error NAME##_lt(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kLT), o0); } \ + inline Error NAME##_gt(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kGT), o0); } \ + inline Error NAME##_le(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kLE), o0); } \ + inline Error NAME##_al(const T0& o0) { return _emitter()->_emitI(BaseInst::composeARMInstId(Inst::kId##ID, CondCode::kAL), o0); } + +//! \addtogroup asmjit_a64 +//! \{ + +//! ARM emitter. +//! +//! NOTE: This class cannot be instantiated, you can only cast to it and use it as emitter that emits to either +//! \ref Assembler, \ref Builder, or \ref Compiler (use withcaution with \ref Compiler as it expects virtual +//! registers to be used). +template<typename This> +struct EmitterExplicitT { + //! \cond + + // These two are unfortunately reported by the sanitizer. We know what we do, however, the sanitizer doesn't. + // I have tried to use reinterpret_cast instead, but that would generate bad code when compiled by MSC. + ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline This* _emitter() noexcept { return static_cast<This*>(this); } + ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF inline const This* _emitter() const noexcept { return static_cast<const This*>(this); } + + //! \endcond + + // -------------------------------------------------------------------------- + // [Options] + // -------------------------------------------------------------------------- + +protected: + inline This& _addInstOptions(InstOptions options) noexcept { + static_cast<This*>(this)->addInstOptions(options); + return *static_cast<This*>(this); + } + +public: + //! \name General Purpose Instructions + //! \{ + + ASMJIT_INST_3x(adc, Adc, Gp, Gp, Gp) + ASMJIT_INST_3x(adcs, Adcs, Gp, Gp, Gp) + + ASMJIT_INST_3x(add, Add, Gp, Gp, Gp) + ASMJIT_INST_4x(add, Add, Gp, Gp, Gp, Imm) + ASMJIT_INST_3x(add, Add, Gp, Gp, Imm) + ASMJIT_INST_4x(add, Add, Gp, Gp, Imm, Imm) + ASMJIT_INST_3x(adds, Adds, Gp, Gp, Gp) + ASMJIT_INST_3x(adds, Adds, Gp, Gp, Imm) + ASMJIT_INST_4x(adds, Adds, Gp, Gp, Gp, Imm) + ASMJIT_INST_4x(adds, Adds, Gp, Gp, Imm, Imm) + + ASMJIT_INST_2x(adr, Adr, Gp, Imm) + ASMJIT_INST_2x(adr, Adr, Gp, Label) + ASMJIT_INST_2x(adrp, Adrp, Gp, Imm) + ASMJIT_INST_2x(adrp, Adrp, Gp, Label) + + ASMJIT_INST_3x(and_, And, Gp, Gp, Imm) + ASMJIT_INST_3x(and_, And, Gp, Gp, Gp) + ASMJIT_INST_4x(and_, And, Gp, Gp, Gp, Imm) + ASMJIT_INST_3x(ands, Ands, Gp, Gp, Imm) + ASMJIT_INST_3x(ands, Ands, Gp, Gp, Gp) + ASMJIT_INST_4x(ands, Ands, Gp, Gp, Gp, Imm) + + ASMJIT_INST_3x(asr, Asr, Gp, Gp, Imm) + ASMJIT_INST_3x(asr, Asr, Gp, Gp, Gp) + ASMJIT_INST_3x(asrv, Asrv, Gp, Gp, Gp) + + ASMJIT_INST_2x(at, At, Imm, Gp) + + ASMJIT_INST_3x(bfc, Bfc, Gp, Imm, Imm) + ASMJIT_INST_4x(bfi, Bfi, Gp, Gp, Imm, Imm) + ASMJIT_INST_4x(bfm, Bfm, Gp, Gp, Imm, Imm) + ASMJIT_INST_4x(bfxil, Bfxil, Gp, Gp, Imm, Imm) + + ASMJIT_INST_3x(bic, Bic, Gp, Gp, Imm); + ASMJIT_INST_3x(bic, Bic, Gp, Gp, Gp); + ASMJIT_INST_4x(bic, Bic, Gp, Gp, Gp, Imm); + ASMJIT_INST_3x(bics, Bics, Gp, Gp, Imm); + ASMJIT_INST_3x(bics, Bics, Gp, Gp, Gp); + ASMJIT_INST_4x(bics, Bics, Gp, Gp, Gp, Imm); + + ASMJIT_INST_1x(brk, Brk, Imm) + + ASMJIT_INST_4x(ccmn, Ccmn, Gp, Gp, Imm, Imm); + ASMJIT_INST_4x(ccmn, Ccmn, Gp, Imm, Imm, Imm); + ASMJIT_INST_4x(ccmp, Ccmp, Gp, Gp, Imm, Imm); + ASMJIT_INST_4x(ccmp, Ccmp, Gp, Imm, Imm, Imm); + + ASMJIT_INST_3x(cinc, Cinc, Gp, Gp, Imm); + ASMJIT_INST_3x(cinv, Cinv, Gp, Gp, Imm); + + ASMJIT_INST_1x(clrex, Clrex, Imm) + + ASMJIT_INST_2x(cls, Cls, Gp, Gp) + ASMJIT_INST_2x(clz, Clz, Gp, Gp) + + ASMJIT_INST_2x(cmn, Cmn, Gp, Gp) + ASMJIT_INST_3x(cmn, Cmn, Gp, Gp, Imm) + ASMJIT_INST_2x(cmn, Cmn, Gp, Imm) + ASMJIT_INST_3x(cmn, Cmn, Gp, Imm, Imm) + ASMJIT_INST_2x(cmp, Cmp, Gp, Gp) + ASMJIT_INST_3x(cmp, Cmp, Gp, Gp, Imm) + ASMJIT_INST_2x(cmp, Cmp, Gp, Imm) + ASMJIT_INST_3x(cmp, Cmp, Gp, Imm, Imm) + + ASMJIT_INST_3x(cneg, Cneg, Gp, Gp, Imm); + + ASMJIT_INST_4x(csel, Csel, Gp, Gp, Gp, Imm); + ASMJIT_INST_2x(cset, Cset, Gp, Imm); + ASMJIT_INST_2x(csetm, Csetm, Gp, Imm); + + ASMJIT_INST_4x(csinc, Csinc, Gp, Gp, Gp, Imm); + ASMJIT_INST_4x(csinv, Csinv, Gp, Gp, Gp, Imm); + ASMJIT_INST_4x(csneg, Csneg, Gp, Gp, Gp, Imm); + + ASMJIT_INST_2x(dc, Dc, Imm, Gp) + ASMJIT_INST_1x(dmb, Dmb, Imm) + ASMJIT_INST_1x(dsb, Dsb, Imm) + ASMJIT_INST_0x(drps, Drps) + + ASMJIT_INST_3x(eon, Eon, Gp, Gp, Gp) + ASMJIT_INST_4x(eon, Eon, Gp, Gp, Gp, Imm) + + ASMJIT_INST_3x(eor, Eor, Gp, Gp, Imm) + ASMJIT_INST_3x(eor, Eor, Gp, Gp, Gp) + ASMJIT_INST_4x(eor, Eor, Gp, Gp, Gp, Imm) + + ASMJIT_INST_0x(eret, Eret) + ASMJIT_INST_0x(esb, Esb) + + ASMJIT_INST_4x(extr, Extr, Gp, Gp, Gp, Imm) + + ASMJIT_INST_1x(hlt, Hlt, Imm) + ASMJIT_INST_1x(hvc, Hvc, Imm) + ASMJIT_INST_2x(ic, Ic, Imm, Gp) + ASMJIT_INST_1x(isb, Isb, Imm) + + ASMJIT_INST_3x(lsl, Lsl, Gp, Gp, Imm) + ASMJIT_INST_3x(lsl, Lsl, Gp, Gp, Gp) + ASMJIT_INST_3x(lslv, Lslv, Gp, Gp, Gp) + + ASMJIT_INST_3x(lsr, Lsr, Gp, Gp, Imm) + ASMJIT_INST_3x(lsr, Lsr, Gp, Gp, Gp) + ASMJIT_INST_3x(lsrv, Lsrv, Gp, Gp, Gp) + + ASMJIT_INST_4x(madd, Madd, Gp, Gp, Gp, Gp) + ASMJIT_INST_3x(mneg, Mneg, Gp, Gp, Gp) + + ASMJIT_INST_2x(mov, Mov, Gp, Gp) + ASMJIT_INST_2x(mov, Mov, Gp, Imm) + ASMJIT_INST_2x(movk, Movk, Gp, Imm) + ASMJIT_INST_3x(movk, Movk, Gp, Imm, Imm) + ASMJIT_INST_2x(movn, Movn, Gp, Imm) + ASMJIT_INST_3x(movn, Movn, Gp, Imm, Imm) + ASMJIT_INST_2x(movz, Movz, Gp, Imm) + ASMJIT_INST_3x(movz, Movz, Gp, Imm, Imm) + + ASMJIT_INST_2x(mrs, Mrs, Gp, Imm) + ASMJIT_INST_2x(msr, Msr, Imm, Gp) + ASMJIT_INST_2x(msr, Msr, Imm, Imm) + + ASMJIT_INST_4x(msub, Msub, Gp, Gp, Gp, Gp) + ASMJIT_INST_3x(mul, Mul, Gp, Gp, Gp) + + ASMJIT_INST_2x(mvn, Mvn, Gp, Gp) + ASMJIT_INST_3x(mvn, Mvn, Gp, Gp, Imm) + + ASMJIT_INST_2x(neg, Neg, Gp, Gp) + ASMJIT_INST_3x(neg, Neg, Gp, Gp, Imm) + ASMJIT_INST_2x(negs, Negs, Gp, Gp) + ASMJIT_INST_3x(negs, Negs, Gp, Gp, Imm) + + ASMJIT_INST_2x(ngc, Ngc, Gp, Gp) + ASMJIT_INST_2x(ngcs, Ngcs, Gp, Gp) + + ASMJIT_INST_3x(orn, Orn, Gp, Gp, Gp) + ASMJIT_INST_4x(orn, Orn, Gp, Gp, Gp, Imm) + + ASMJIT_INST_3x(orr, Orr, Gp, Gp, Imm) + ASMJIT_INST_3x(orr, Orr, Gp, Gp, Gp) + ASMJIT_INST_4x(orr, Orr, Gp, Gp, Gp, Imm) + + ASMJIT_INST_2x(rbit, Rbit, Gp, Gp) + ASMJIT_INST_1x(ret, Ret, Gp) + + ASMJIT_INST_2x(rev, Rev, Gp, Gp) + ASMJIT_INST_2x(rev16, Rev16, Gp, Gp) + ASMJIT_INST_2x(rev32, Rev32, Gp, Gp) + ASMJIT_INST_2x(rev64, Rev64, Gp, Gp) + + ASMJIT_INST_3x(ror, Ror, Gp, Gp, Imm) + ASMJIT_INST_3x(ror, Ror, Gp, Gp, Gp) + ASMJIT_INST_3x(rorv, Rorv, Gp, Gp, Gp) + + ASMJIT_INST_3x(sbc, Sbc, Gp, Gp, Gp) + ASMJIT_INST_3x(sbcs, Sbcs, Gp, Gp, Gp) + + ASMJIT_INST_4x(sbfiz, Sbfiz, Gp, Gp, Imm, Imm) + ASMJIT_INST_4x(sbfm, Sbfm, Gp, Gp, Imm, Imm) + ASMJIT_INST_4x(sbfx, Sbfx, Gp, Gp, Imm, Imm) + + ASMJIT_INST_3x(sdiv, Sdiv, Gp, Gp, Gp) + + ASMJIT_INST_4x(smaddl, Smaddl, Gp, Gp, Gp, Gp) + ASMJIT_INST_1x(smc, Smc, Imm) + ASMJIT_INST_3x(smnegl, Smnegl, Gp, Gp, Gp) + ASMJIT_INST_4x(smsubl, Smsubl, Gp, Gp, Gp, Gp) + ASMJIT_INST_3x(smulh, Smulh, Gp, Gp, Gp) + ASMJIT_INST_3x(smull, Smull, Gp, Gp, Gp) + + ASMJIT_INST_3x(sub, Sub, Gp, Gp, Gp) + ASMJIT_INST_4x(sub, Sub, Gp, Gp, Gp, Imm) + ASMJIT_INST_3x(sub, Sub, Gp, Gp, Imm) + ASMJIT_INST_4x(sub, Sub, Gp, Gp, Imm, Imm) + ASMJIT_INST_3x(subs, Subs, Gp, Gp, Gp) + ASMJIT_INST_4x(subs, Subs, Gp, Gp, Gp, Imm) + ASMJIT_INST_3x(subs, Subs, Gp, Gp, Imm) + ASMJIT_INST_4x(subs, Subs, Gp, Gp, Imm, Imm) + + ASMJIT_INST_1x(svc, Svc, Imm) + + ASMJIT_INST_2x(sxtb, Sxtb, Gp, Gp) + ASMJIT_INST_2x(sxth, Sxth, Gp, Gp) + ASMJIT_INST_2x(sxtw, Sxtw, Gp, Gp) + + ASMJIT_INST_4x(sys, Sys, Imm, Imm, Imm, Imm) + ASMJIT_INST_5x(sys, Sys, Imm, Imm, Imm, Imm, Gp) + + ASMJIT_INST_2x(tlbi, Tlbi, Imm, Gp) + ASMJIT_INST_2x(tst, Tst, Gp, Imm) + ASMJIT_INST_2x(tst, Tst, Gp, Gp) + ASMJIT_INST_3x(tst, Tst, Gp, Gp, Imm) + + ASMJIT_INST_3x(udiv, Udiv, Gp, Gp, Gp) + + ASMJIT_INST_4x(ubfiz, Ubfiz, Gp, Gp, Imm, Imm) + ASMJIT_INST_4x(ubfm, Ubfm, Gp, Gp, Imm, Imm) + ASMJIT_INST_4x(ubfx, Ubfx, Gp, Gp, Imm, Imm) + + ASMJIT_INST_4x(umaddl, Umaddl, Gp, Gp, Gp, Gp) + ASMJIT_INST_3x(umnegl, Umnegl, Gp, Gp, Gp) + ASMJIT_INST_4x(umsubl, Umsubl, Gp, Gp, Gp, Gp) + ASMJIT_INST_3x(umull, Umull, Gp, Gp, Gp) + ASMJIT_INST_3x(umulh, Umulh, Gp, Gp, Gp) + + ASMJIT_INST_2x(uxtb, Uxtb, Gp, Gp) + ASMJIT_INST_2x(uxth, Uxth, Gp, Gp) + + ASMJIT_INST_0x(csdb, Csdb) + ASMJIT_INST_1x(dcps1, Dcps1, Imm) + ASMJIT_INST_1x(dcps2, Dcps2, Imm) + ASMJIT_INST_1x(dcps3, Dcps3, Imm) + ASMJIT_INST_0x(dgh, Dgh) + ASMJIT_INST_0x(pssbb, Pssbb) + ASMJIT_INST_0x(ssbb, Ssbb) + ASMJIT_INST_1x(udf, Udf, Imm) + ASMJIT_INST_1x(setf8, Setf8, Gp) + ASMJIT_INST_1x(setf16, Setf16, Gp) + + //! \} + + //! \name ARMv8.4 Instructions + //! \{ + + ASMJIT_INST_0x(cfinv, Cfinv) + + //! \} + + //! \name ARMv8.5 Instructions + //! \{ + + ASMJIT_INST_0x(axflag, Axflag) + ASMJIT_INST_0x(xaflag, Xaflag) + + //! \} + + //! \name Branch Instructions + //! \{ + + ASMJIT_INST_1cc(b, B, Imm) + ASMJIT_INST_1cc(b, B, Label) + ASMJIT_INST_1x(bl, Bl, Imm) + ASMJIT_INST_1x(bl, Bl, Label) + ASMJIT_INST_1x(blr, Blr, Gp) + ASMJIT_INST_1x(br, Br, Gp) + ASMJIT_INST_2x(cbz, Cbz, Gp, Imm) + ASMJIT_INST_2x(cbz, Cbz, Gp, Label) + ASMJIT_INST_2x(cbnz, Cbnz, Gp, Imm) + ASMJIT_INST_2x(cbnz, Cbnz, Gp, Label) + ASMJIT_INST_3x(tbnz, Tbnz, Gp, Imm, Imm) + ASMJIT_INST_3x(tbnz, Tbnz, Gp, Imm, Label) + ASMJIT_INST_3x(tbz, Tbz, Gp, Imm, Imm) + ASMJIT_INST_3x(tbz, Tbz, Gp, Imm, Label) + + //! \} + + //! \name Load & Store Instructions + //! \{ + + ASMJIT_INST_3x(cas, Cas, Gp, Gp, Mem) + ASMJIT_INST_3x(casa, Casa, Gp, Gp, Mem) + ASMJIT_INST_3x(casab, Casab, Gp, Gp, Mem) + ASMJIT_INST_3x(casah, Casah, Gp, Gp, Mem) + ASMJIT_INST_3x(casal, Casal, Gp, Gp, Mem) + ASMJIT_INST_3x(casalb, Casalb, Gp, Gp, Mem) + ASMJIT_INST_3x(casalh, Casalh, Gp, Gp, Mem) + ASMJIT_INST_3x(casb, Casb, Gp, Gp, Mem) + ASMJIT_INST_3x(cash, Cash, Gp, Gp, Mem) + ASMJIT_INST_3x(casl, Casl, Gp, Gp, Mem) + ASMJIT_INST_3x(caslb, Caslb, Gp, Gp, Mem) + ASMJIT_INST_3x(caslh, Caslh, Gp, Gp, Mem) + + ASMJIT_INST_5x(casp, Casp, Gp, Gp, Gp, Gp, Mem) + ASMJIT_INST_5x(caspa, Caspa, Gp, Gp, Gp, Gp, Mem) + ASMJIT_INST_5x(caspal, Caspal, Gp, Gp, Gp, Gp, Mem) + ASMJIT_INST_5x(caspl, Caspl, Gp, Gp, Gp, Gp, Mem) + + ASMJIT_INST_3x(ldadd, Ldadd, Gp, Gp, Mem) + ASMJIT_INST_3x(ldadda, Ldadda, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaddab, Ldaddab, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaddah, Ldaddah, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaddal, Ldaddal, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaddalb, Ldaddalb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaddalh, Ldaddalh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaddb, Ldaddb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaddh, Ldaddh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaddl, Ldaddl, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaddlb, Ldaddlb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaddlh, Ldaddlh, Gp, Gp, Mem) + + ASMJIT_INST_2x(ldar, Ldar, Gp, Mem) + ASMJIT_INST_2x(ldarb, Ldarb, Gp, Mem) + ASMJIT_INST_2x(ldarh, Ldarh, Gp, Mem) + + ASMJIT_INST_2x(ldaxr, Ldaxr, Gp, Mem) + ASMJIT_INST_2x(ldaxrb, Ldaxrb, Gp, Mem) + ASMJIT_INST_2x(ldaxrh, Ldaxrh, Gp, Mem) + + ASMJIT_INST_3x(ldclr, Ldclr, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclra, Ldclra, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclrab, Ldclrab, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclrah, Ldclrah, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclral, Ldclral, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclralb, Ldclralb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclralh, Ldclralh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclrb, Ldclrb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclrh, Ldclrh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclrl, Ldclrl, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclrlb, Ldclrlb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldclrlh, Ldclrlh, Gp, Gp, Mem) + + ASMJIT_INST_3x(ldeor, Ldeor, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeora, Ldeora, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeorab, Ldeorab, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeorah, Ldeorah, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeoral, Ldeoral, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeoralb, Ldeoralb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeoralh, Ldeoralh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeorb, Ldeorb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeorh, Ldeorh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeorl, Ldeorl, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeorlb, Ldeorlb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldeorlh, Ldeorlh, Gp, Gp, Mem) + + ASMJIT_INST_2x(ldlar, Ldlar, Gp, Mem) + ASMJIT_INST_2x(ldlarb, Ldlarb, Gp, Mem) + ASMJIT_INST_2x(ldlarh, Ldlarh, Gp, Mem) + + ASMJIT_INST_3x(ldnp, Ldnp, Gp, Gp, Mem) + + ASMJIT_INST_3x(ldp, Ldp, Gp, Gp, Mem) + ASMJIT_INST_3x(ldpsw, Ldpsw, Gp, Gp, Mem) + + ASMJIT_INST_2x(ldr, Ldr, Gp, Mem) + ASMJIT_INST_2x(ldrb, Ldrb, Gp, Mem) + ASMJIT_INST_2x(ldrh, Ldrh, Gp, Mem) + ASMJIT_INST_2x(ldrsb, Ldrsb, Gp, Mem) + ASMJIT_INST_2x(ldrsh, Ldrsh, Gp, Mem) + ASMJIT_INST_2x(ldrsw, Ldrsw, Gp, Mem) + + ASMJIT_INST_3x(ldset, Ldset, Gp, Gp, Mem) + ASMJIT_INST_3x(ldseta, Ldseta, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsetab, Ldsetab, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsetah, Ldsetah, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsetal, Ldsetal, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsetalb, Ldsetalb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsetalh, Ldsetalh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsetb, Ldsetb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldseth, Ldseth, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsetl, Ldsetl, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsetlb, Ldsetlb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsetlh, Ldsetlh, Gp, Gp, Mem) + + ASMJIT_INST_3x(ldsmax, Ldsmax, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxa, Ldsmaxa, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxab, Ldsmaxab, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxah, Ldsmaxah, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxal, Ldsmaxal, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxalb, Ldsmaxalb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxalh, Ldsmaxalh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxb, Ldsmaxb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxh, Ldsmaxh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxl, Ldsmaxl, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxlb, Ldsmaxlb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmaxlh, Ldsmaxlh, Gp, Gp, Mem) + + ASMJIT_INST_3x(ldsmin, Ldsmin, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsmina, Ldsmina, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsminab, Ldsminab, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsminah, Ldsminah, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsminal, Ldsminal, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsminalb, Ldsminalb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsminalh, Ldsminalh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsminb, Ldsminb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsminh, Ldsminh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsminl, Ldsminl, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsminlb, Ldsminlb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldsminlh, Ldsminlh, Gp, Gp, Mem) + + ASMJIT_INST_2x(ldtr, Ldtr, Gp, Mem) + ASMJIT_INST_2x(ldtrb, Ldtrb, Gp, Mem) + ASMJIT_INST_2x(ldtrh, Ldtrh, Gp, Mem) + ASMJIT_INST_2x(ldtrsb, Ldtrsb, Gp, Mem) + ASMJIT_INST_2x(ldtrsh, Ldtrsh, Gp, Mem) + ASMJIT_INST_2x(ldtrsw, Ldtrsw, Gp, Mem) + + ASMJIT_INST_3x(ldumax, Ldumax, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxa, Ldumaxa, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxab, Ldumaxab, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxah, Ldumaxah, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxal, Ldumaxal, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxalb, Ldumaxalb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxalh, Ldumaxalh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxb, Ldumaxb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxh, Ldumaxh, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxl, Ldumaxl, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxlb, Ldumaxlb, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumaxlh, Ldumaxlh, Gp, Gp, Mem) + + ASMJIT_INST_3x(ldumin, Ldumin, Gp, Gp, Mem) + ASMJIT_INST_3x(ldumina, Ldumina, Gp, Gp, Mem) + ASMJIT_INST_3x(lduminab, Lduminab, Gp, Gp, Mem) + ASMJIT_INST_3x(lduminah, Lduminah, Gp, Gp, Mem) + ASMJIT_INST_3x(lduminal, Lduminal, Gp, Gp, Mem) + ASMJIT_INST_3x(lduminalb, Lduminalb, Gp, Gp, Mem) + ASMJIT_INST_3x(lduminalh, Lduminalh, Gp, Gp, Mem) + ASMJIT_INST_3x(lduminb, Lduminb, Gp, Gp, Mem) + ASMJIT_INST_3x(lduminh, Lduminh, Gp, Gp, Mem) + ASMJIT_INST_3x(lduminl, Lduminl, Gp, Gp, Mem) + ASMJIT_INST_3x(lduminlb, Lduminlb, Gp, Gp, Mem) + ASMJIT_INST_3x(lduminlh, Lduminlh, Gp, Gp, Mem) + + ASMJIT_INST_2x(ldur, Ldur, Gp, Mem) + ASMJIT_INST_2x(ldurb, Ldurb, Gp, Mem) + ASMJIT_INST_2x(ldurh, Ldurh, Gp, Mem) + ASMJIT_INST_2x(ldursb, Ldursb, Gp, Mem) + ASMJIT_INST_2x(ldursh, Ldursh, Gp, Mem) + ASMJIT_INST_2x(ldursw, Ldursw, Gp, Mem) + + ASMJIT_INST_3x(ldxp, Ldxp, Gp, Gp, Mem) + ASMJIT_INST_3x(ldaxp, Ldaxp, Gp, Gp, Mem) + + ASMJIT_INST_2x(ldxr, Ldxr, Gp, Mem) + ASMJIT_INST_2x(ldxrb, Ldxrb, Gp, Mem) + ASMJIT_INST_2x(ldxrh, Ldxrh, Gp, Mem) + + ASMJIT_INST_2x(stadd, Stadd, Gp, Mem) + ASMJIT_INST_2x(staddb, Staddb, Gp, Mem) + ASMJIT_INST_2x(staddh, Staddh, Gp, Mem) + ASMJIT_INST_2x(staddl, Staddl, Gp, Mem) + ASMJIT_INST_2x(staddlb, Staddlb, Gp, Mem) + ASMJIT_INST_2x(staddlh, Staddlh, Gp, Mem) + + ASMJIT_INST_2x(stclr, Stclr, Gp, Mem) + ASMJIT_INST_2x(stclrb, Stclrb, Gp, Mem) + ASMJIT_INST_2x(stclrh, Stclrh, Gp, Mem) + ASMJIT_INST_2x(stclrl, Stclrl, Gp, Mem) + ASMJIT_INST_2x(stclrlb, Stclrlb, Gp, Mem) + ASMJIT_INST_2x(stclrlh, Stclrlh, Gp, Mem) + + ASMJIT_INST_2x(steor, Steor, Gp, Mem) + ASMJIT_INST_2x(steorb, Steorb, Gp, Mem) + ASMJIT_INST_2x(steorh, Steorh, Gp, Mem) + ASMJIT_INST_2x(steorl, Steorl, Gp, Mem) + ASMJIT_INST_2x(steorlb, Steorlb, Gp, Mem) + ASMJIT_INST_2x(steorlh, Steorlh, Gp, Mem) + + ASMJIT_INST_2x(stllr, Stllr, Gp, Mem) + ASMJIT_INST_2x(stllrb, Stllrb, Gp, Mem) + ASMJIT_INST_2x(stllrh, Stllrh, Gp, Mem) + + ASMJIT_INST_2x(stlr, Stllr, Gp, Mem) + ASMJIT_INST_2x(stlrb, Stllrb, Gp, Mem) + ASMJIT_INST_2x(stlrh, Stllrh, Gp, Mem) + + ASMJIT_INST_3x(stlxr, Stlxr, Gp, Gp, Mem) + ASMJIT_INST_3x(stlxrb, Stlxrb, Gp, Gp, Mem) + ASMJIT_INST_3x(stlxrh, Stlxrh, Gp, Gp, Mem) + + ASMJIT_INST_3x(stnp, Stnp, Gp, Gp, Mem) + ASMJIT_INST_3x(stp, Stp, Gp, Gp, Mem) + + ASMJIT_INST_2x(str, Str, Gp, Mem) + ASMJIT_INST_2x(strb, Strb, Gp, Mem) + ASMJIT_INST_2x(strh, Strh, Gp, Mem) + + ASMJIT_INST_2x(stset, Stset, Gp, Mem) + ASMJIT_INST_2x(stsetb, Stsetb, Gp, Mem) + ASMJIT_INST_2x(stseth, Stseth, Gp, Mem) + ASMJIT_INST_2x(stsetl, Stsetl, Gp, Mem) + ASMJIT_INST_2x(stsetlb, Stsetlb, Gp, Mem) + ASMJIT_INST_2x(stsetlh, Stsetlh, Gp, Mem) + + ASMJIT_INST_2x(stsmax, Stsmax, Gp, Mem) + ASMJIT_INST_2x(stsmaxb, Stsmaxb, Gp, Mem) + ASMJIT_INST_2x(stsmaxh, Stsmaxh, Gp, Mem) + ASMJIT_INST_2x(stsmaxl, Stsmaxl, Gp, Mem) + ASMJIT_INST_2x(stsmaxlb, Stsmaxlb, Gp, Mem) + ASMJIT_INST_2x(stsmaxlh, Stsmaxlh, Gp, Mem) + + ASMJIT_INST_2x(stsmin, Stsmin, Gp, Mem) + ASMJIT_INST_2x(stsminb, Stsminb, Gp, Mem) + ASMJIT_INST_2x(stsminh, Stsminh, Gp, Mem) + ASMJIT_INST_2x(stsminl, Stsminl, Gp, Mem) + ASMJIT_INST_2x(stsminlb, Stsminlb, Gp, Mem) + ASMJIT_INST_2x(stsminlh, Stsminlh, Gp, Mem) + + ASMJIT_INST_2x(sttr, Sttr, Gp, Mem) + ASMJIT_INST_2x(sttrb, Sttrb, Gp, Mem) + ASMJIT_INST_2x(sttrh, Sttrh, Gp, Mem) + + ASMJIT_INST_2x(stumax, Stumax, Gp, Mem) + ASMJIT_INST_2x(stumaxb, Stumaxb, Gp, Mem) + ASMJIT_INST_2x(stumaxh, Stumaxh, Gp, Mem) + ASMJIT_INST_2x(stumaxl, Stumaxl, Gp, Mem) + ASMJIT_INST_2x(stumaxlb, Stumaxlb, Gp, Mem) + ASMJIT_INST_2x(stumaxlh, Stumaxlh, Gp, Mem) + + ASMJIT_INST_2x(stumin, Stumin, Gp, Mem) + ASMJIT_INST_2x(stuminb, Stuminb, Gp, Mem) + ASMJIT_INST_2x(stuminh, Stuminh, Gp, Mem) + ASMJIT_INST_2x(stuminl, Stuminl, Gp, Mem) + ASMJIT_INST_2x(stuminlb, Stuminlb, Gp, Mem) + ASMJIT_INST_2x(stuminlh, Stuminlh, Gp, Mem) + + ASMJIT_INST_2x(stur, Stur, Gp, Mem) + ASMJIT_INST_2x(sturb, Sturb, Gp, Mem) + ASMJIT_INST_2x(sturh, Sturh, Gp, Mem) + + ASMJIT_INST_4x(stxp, Stxp, Gp, Gp, Gp, Mem) + ASMJIT_INST_4x(stlxp, Stlxp, Gp, Gp, Gp, Mem) + + ASMJIT_INST_3x(stxr, Stxr, Gp, Gp, Mem) + ASMJIT_INST_3x(stxrb, Stxrb, Gp, Gp, Mem) + ASMJIT_INST_3x(stxrh, Stxrh, Gp, Gp, Mem) + + ASMJIT_INST_3x(swp, Swp, Gp, Gp, Mem) + ASMJIT_INST_3x(swpa, Swpa, Gp, Gp, Mem) + ASMJIT_INST_3x(swpab, Swpab, Gp, Gp, Mem) + ASMJIT_INST_3x(swpah, Swpah, Gp, Gp, Mem) + ASMJIT_INST_3x(swpal, Swpal, Gp, Gp, Mem) + ASMJIT_INST_3x(swpalb, Swpalb, Gp, Gp, Mem) + ASMJIT_INST_3x(swpalh, Swpalh, Gp, Gp, Mem) + ASMJIT_INST_3x(swpb, Swpb, Gp, Gp, Mem) + ASMJIT_INST_3x(swph, Swph, Gp, Gp, Mem) + ASMJIT_INST_3x(swpl, Swpl, Gp, Gp, Mem) + ASMJIT_INST_3x(swplb, Swplb, Gp, Gp, Mem) + ASMJIT_INST_3x(swplh, Swplh, Gp, Gp, Mem) + //! \} + + //! \name CRC Instructions (ARMv8.1-A, optional in ARMv8.0-A) + //! \{ + + ASMJIT_INST_3x(crc32b, Crc32b, Gp, Gp, Gp); + ASMJIT_INST_3x(crc32h, Crc32h, Gp, Gp, Gp); + ASMJIT_INST_3x(crc32w, Crc32w, Gp, Gp, Gp); + ASMJIT_INST_3x(crc32x, Crc32x, Gp, Gp, Gp); + + ASMJIT_INST_3x(crc32cb, Crc32cb, Gp, Gp, Gp); + ASMJIT_INST_3x(crc32ch, Crc32ch, Gp, Gp, Gp); + ASMJIT_INST_3x(crc32cw, Crc32cw, Gp, Gp, Gp); + ASMJIT_INST_3x(crc32cx, Crc32cx, Gp, Gp, Gp); + + //! \} + + //! \name MTE Instructions + //! \{ + + ASMJIT_INST_2x(autda, Autda, Gp, Gp); + ASMJIT_INST_2x(autdb, Autdb, Gp, Gp); + ASMJIT_INST_1x(autdza, Autdza, Gp); + ASMJIT_INST_1x(autdzb, Autdzb, Gp); + ASMJIT_INST_2x(autia, Autia, Gp, Gp); + ASMJIT_INST_0x(autia1716, Autia1716); + ASMJIT_INST_0x(autiasp, Autiasp); + ASMJIT_INST_0x(autiaz, Autiaz); + ASMJIT_INST_2x(autib, Autib, Gp, Gp); + ASMJIT_INST_0x(autib1716, Autib1716); + ASMJIT_INST_0x(autibsp, Autibsp); + ASMJIT_INST_0x(autibz, Autibz); + ASMJIT_INST_1x(autiza, Autiza, Gp); + ASMJIT_INST_1x(autizb, Autizb, Gp); + + ASMJIT_INST_3x(gmi, Gmi, Gp, Gp, Gp); + + ASMJIT_INST_2x(cmpp, Cmpp, Gp, Gp); + ASMJIT_INST_4x(addg, Addg, Gp, Gp, Imm, Imm); + + ASMJIT_INST_2x(ldg, Ldg, Gp, Mem) + ASMJIT_INST_2x(ldgm, Ldgm, Gp, Mem) + ASMJIT_INST_2x(ldraa, Ldraa, Gp, Mem) + ASMJIT_INST_2x(ldrab, Ldrab, Gp, Mem) + + ASMJIT_INST_2x(pacda, Pacda, Gp, Gp); + ASMJIT_INST_2x(pacdb, Pacdb, Gp, Gp); + ASMJIT_INST_1x(pacdza, Pacdza, Gp); + ASMJIT_INST_1x(pacdzb, Pacdzb, Gp); + ASMJIT_INST_3x(pacga, Pacga, Gp, Gp, Gp); + + ASMJIT_INST_3x(subp, Subp, Gp, Gp, Gp); + ASMJIT_INST_3x(subps, Subps, Gp, Gp, Gp); + ASMJIT_INST_4x(subg, Subg, Gp, Gp, Imm, Imm); + + ASMJIT_INST_2x(st2g, St2g, Gp, Mem) + ASMJIT_INST_2x(stg, Stg, Gp, Mem) + ASMJIT_INST_3x(stgp, Stgp, Gp, Gp, Mem) + ASMJIT_INST_2x(stgm, Stgm, Gp, Mem) + ASMJIT_INST_2x(stzg, Stzg, Gp, Mem) + ASMJIT_INST_2x(stz2g, Stz2g, Gp, Mem) + ASMJIT_INST_2x(stzgm, Stzgm, Gp, Mem) + + ASMJIT_INST_1x(xpacd, Xpacd, Gp); + ASMJIT_INST_1x(xpaci, Xpaci, Gp); + ASMJIT_INST_0x(xpaclri, Xpaclri); + + //! \} + + //! \name Hint Instructions + //! \{ + + ASMJIT_INST_1x(hint, Hint, Imm) + ASMJIT_INST_0x(nop, Nop) + ASMJIT_INST_0x(sev, Sev) + ASMJIT_INST_0x(sevl, Sevl) + ASMJIT_INST_0x(wfe, Wfe) + ASMJIT_INST_0x(wfi, Wfi) + ASMJIT_INST_0x(yield, Yield) + + //! \} + + //! \name SIMD & FP Instructions + //! \{ + + ASMJIT_INST_2x(abs, Abs_v, Vec, Vec); + ASMJIT_INST_3x(add, Add_v, Vec, Vec, Vec); + ASMJIT_INST_3x(addhn, Addhn_v, Vec, Vec, Vec); + ASMJIT_INST_3x(addhn2, Addhn2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(addp, Addp_v, Vec, Vec); + ASMJIT_INST_3x(addp, Addp_v, Vec, Vec, Vec); + ASMJIT_INST_2x(addv, Addv_v, Vec, Vec); + ASMJIT_INST_3x(and_, And_v, Vec, Vec, Vec); + ASMJIT_INST_2x(bic, Bic_v, Vec, Imm); + ASMJIT_INST_3x(bic, Bic_v, Vec, Vec, Vec); + ASMJIT_INST_3x(bic, Bic_v, Vec, Imm, Imm); + ASMJIT_INST_3x(bif, Bif_v, Vec, Vec, Vec); + ASMJIT_INST_3x(bit, Bit_v, Vec, Vec, Vec); + ASMJIT_INST_3x(bsl, Bsl_v, Vec, Vec, Vec); + ASMJIT_INST_2x(cls, Cls_v, Vec, Vec); + ASMJIT_INST_2x(clz, Clz_v, Vec, Vec); + ASMJIT_INST_3x(cmeq, Cmeq_v, Vec, Vec, Vec); + ASMJIT_INST_3x(cmeq, Cmeq_v, Vec, Vec, Imm); + ASMJIT_INST_3x(cmge, Cmge_v, Vec, Vec, Vec); + ASMJIT_INST_3x(cmge, Cmge_v, Vec, Vec, Imm); + ASMJIT_INST_3x(cmgt, Cmgt_v, Vec, Vec, Vec); + ASMJIT_INST_3x(cmgt, Cmgt_v, Vec, Vec, Imm); + ASMJIT_INST_3x(cmhi, Cmhi_v, Vec, Vec, Vec); + ASMJIT_INST_3x(cmhs, Cmhs_v, Vec, Vec, Vec); + ASMJIT_INST_3x(cmle, Cmle_v, Vec, Vec, Imm); + ASMJIT_INST_3x(cmlt, Cmlt_v, Vec, Vec, Imm); + ASMJIT_INST_3x(cmtst, Cmtst_v, Vec, Vec, Vec); + ASMJIT_INST_2x(cnt, Cnt_v, Vec, Vec); + ASMJIT_INST_2x(dup, Dup_v, Vec, Gp); + ASMJIT_INST_2x(dup, Dup_v, Vec, Vec); + ASMJIT_INST_3x(eor, Eor_v, Vec, Vec, Vec); + ASMJIT_INST_4x(ext, Ext_v, Vec, Vec, Vec, Imm); + ASMJIT_INST_3x(fabd, Fabd_v, Vec, Vec, Vec); + ASMJIT_INST_2x(fabs, Fabs_v, Vec, Vec); + ASMJIT_INST_3x(facge, Facge_v, Vec, Vec, Vec); + ASMJIT_INST_3x(facgt, Facgt_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fadd, Fadd_v, Vec, Vec, Vec); + ASMJIT_INST_2x(faddp, Faddp_v, Vec, Vec); + ASMJIT_INST_3x(faddp, Faddp_v, Vec, Vec, Vec); + ASMJIT_INST_4x(fccmp, Fccmp_v, Vec, Vec, Imm, Imm); + ASMJIT_INST_4x(fccmpe, Fccmpe_v, Vec, Vec, Imm, Imm); + ASMJIT_INST_3x(fcmeq, Fcmeq_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fcmeq, Fcmeq_v, Vec, Vec, Imm); + ASMJIT_INST_3x(fcmge, Fcmge_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fcmge, Fcmge_v, Vec, Vec, Imm); + ASMJIT_INST_3x(fcmgt, Fcmgt_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fcmgt, Fcmgt_v, Vec, Vec, Imm); + ASMJIT_INST_3x(fcmle, Fcmle_v, Vec, Vec, Imm); + ASMJIT_INST_3x(fcmlt, Fcmlt_v, Vec, Vec, Imm); + ASMJIT_INST_2x(fcmp, Fcmp_v, Vec, Vec); + ASMJIT_INST_2x(fcmp, Fcmp_v, Vec, Imm); + ASMJIT_INST_2x(fcmpe, Fcmpe_v, Vec, Vec); + ASMJIT_INST_2x(fcmpe, Fcmpe_v, Vec, Imm); + ASMJIT_INST_4x(fcsel, Fcsel_v, Vec, Vec, Vec, Imm); + ASMJIT_INST_2x(fcvt, Fcvt_v, Vec, Vec); + ASMJIT_INST_2x(fcvtas, Fcvtas_v, Gp, Vec); + ASMJIT_INST_2x(fcvtas, Fcvtas_v, Vec, Vec); + ASMJIT_INST_2x(fcvtau, Fcvtau_v, Gp, Vec); + ASMJIT_INST_2x(fcvtau, Fcvtau_v, Vec, Vec); + ASMJIT_INST_2x(fcvtl, Fcvtl_v, Vec, Vec); + ASMJIT_INST_2x(fcvtl2, Fcvtl2_v, Vec, Vec); + ASMJIT_INST_2x(fcvtms, Fcvtms_v, Gp, Vec); + ASMJIT_INST_2x(fcvtms, Fcvtms_v, Vec, Vec); + ASMJIT_INST_2x(fcvtmu, Fcvtmu_v, Gp, Vec); + ASMJIT_INST_2x(fcvtmu, Fcvtmu_v, Vec, Vec); + ASMJIT_INST_2x(fcvtn, Fcvtn_v, Vec, Vec); + ASMJIT_INST_2x(fcvtn2, Fcvtn2_v, Vec, Vec); + ASMJIT_INST_2x(fcvtns, Fcvtns_v, Gp, Vec); + ASMJIT_INST_2x(fcvtns, Fcvtns_v, Vec, Vec); + ASMJIT_INST_2x(fcvtnu, Fcvtnu_v, Gp, Vec); + ASMJIT_INST_2x(fcvtnu, Fcvtnu_v, Vec, Vec); + ASMJIT_INST_2x(fcvtps, Fcvtps_v, Gp, Vec); + ASMJIT_INST_2x(fcvtps, Fcvtps_v, Vec, Vec); + ASMJIT_INST_2x(fcvtpu, Fcvtpu_v, Gp, Vec); + ASMJIT_INST_2x(fcvtpu, Fcvtpu_v, Vec, Vec); + ASMJIT_INST_2x(fcvtxn, Fcvtxn_v, Vec, Vec); + ASMJIT_INST_2x(fcvtxn2, Fcvtxn2_v, Vec, Vec); + ASMJIT_INST_2x(fcvtzs, Fcvtzs_v, Gp, Vec); + ASMJIT_INST_3x(fcvtzs, Fcvtzs_v, Gp, Vec, Imm); + ASMJIT_INST_2x(fcvtzs, Fcvtzs_v, Vec, Vec); + ASMJIT_INST_3x(fcvtzs, Fcvtzs_v, Vec, Vec, Imm); + ASMJIT_INST_2x(fcvtzu, Fcvtzu_v, Gp, Vec); + ASMJIT_INST_3x(fcvtzu, Fcvtzu_v, Gp, Vec, Imm); + ASMJIT_INST_2x(fcvtzu, Fcvtzu_v, Vec, Vec); + ASMJIT_INST_3x(fcvtzu, Fcvtzu_v, Vec, Vec, Imm); + ASMJIT_INST_3x(fdiv, Fdiv_v, Vec, Vec, Vec); + ASMJIT_INST_4x(fmadd, Fmadd_v, Vec, Vec, Vec, Vec); + ASMJIT_INST_3x(fmax, Fmax_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fmaxnm, Fmaxnm_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fmaxnmp, Fmaxnmp_v, Vec, Vec, Vec); + ASMJIT_INST_2x(fmaxnmp, Fmaxnmp_v, Vec, Vec); + ASMJIT_INST_2x(fmaxnmv, Fmaxnmv_v, Vec, Vec); + ASMJIT_INST_3x(fmaxp, Fmaxp_v, Vec, Vec, Vec); + ASMJIT_INST_2x(fmaxp, Fmaxp_v, Vec, Vec); + ASMJIT_INST_2x(fmaxv, Fmaxv_v, Vec, Vec); + ASMJIT_INST_3x(fmin, Fmin_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fminnm, Fminnm_v, Vec, Vec, Vec); + ASMJIT_INST_2x(fminnmv, Fminnmv_v, Vec, Vec); + ASMJIT_INST_3x(fminnmp, Fminnmp_v, Vec, Vec, Vec); + ASMJIT_INST_2x(fminnmp, Fminnmp_v, Vec, Vec); + ASMJIT_INST_2x(fminp, Fminp_v, Vec, Vec); + ASMJIT_INST_3x(fminp, Fminp_v, Vec, Vec, Vec); + ASMJIT_INST_2x(fminv, Fminv_v, Vec, Vec); + ASMJIT_INST_3x(fmla, Fmla_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fmls, Fmls_v, Vec, Vec, Vec); + ASMJIT_INST_2x(fmov, Fmov_v, Gp, Vec); + ASMJIT_INST_2x(fmov, Fmov_v, Vec, Gp); + ASMJIT_INST_2x(fmov, Fmov_v, Vec, Vec); + ASMJIT_INST_2x(fmov, Fmov_v, Vec, Imm); + ASMJIT_INST_4x(fmsub, Fmsub_v, Vec, Vec, Vec, Vec); + ASMJIT_INST_3x(fmul, Fmul_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fmulx, Fmulx_v, Vec, Vec, Vec); + ASMJIT_INST_2x(fneg, Fneg_v, Vec, Vec); + ASMJIT_INST_4x(fnmadd, Fnmadd_v, Vec, Vec, Vec, Vec); + ASMJIT_INST_4x(fnmsub, Fnmsub_v, Vec, Vec, Vec, Vec); + ASMJIT_INST_3x(fnmul, Fnmul_v, Vec, Vec, Vec); + ASMJIT_INST_2x(frecpe, Frecpe_v, Vec, Vec); + ASMJIT_INST_3x(frecps, Frecps_v, Vec, Vec, Vec); + ASMJIT_INST_2x(frecpx, Frecpx_v, Vec, Vec); + ASMJIT_INST_2x(frint32x, Frint32x_v, Vec, Vec); + ASMJIT_INST_2x(frint32z, Frint32z_v, Vec, Vec); + ASMJIT_INST_2x(frint64x, Frint64x_v, Vec, Vec); + ASMJIT_INST_2x(frint64z, Frint64z_v, Vec, Vec); + ASMJIT_INST_2x(frinta, Frinta_v, Vec, Vec); + ASMJIT_INST_2x(frinti, Frinti_v, Vec, Vec); + ASMJIT_INST_2x(frintm, Frintm_v, Vec, Vec); + ASMJIT_INST_2x(frintn, Frintn_v, Vec, Vec); + ASMJIT_INST_2x(frintp, Frintp_v, Vec, Vec); + ASMJIT_INST_2x(frintx, Frintx_v, Vec, Vec); + ASMJIT_INST_2x(frintz, Frintz_v, Vec, Vec); + ASMJIT_INST_2x(frsqrte, Frsqrte_v, Vec, Vec); + ASMJIT_INST_3x(frsqrts, Frsqrts_v, Vec, Vec, Vec); + ASMJIT_INST_2x(fsqrt, Fsqrt_v, Vec, Vec); + ASMJIT_INST_3x(fsub, Fsub_v, Vec, Vec, Vec); + ASMJIT_INST_2x(ins, Ins_v, Vec, Gp); + ASMJIT_INST_2x(ins, Ins_v, Vec, Vec); + ASMJIT_INST_2x(ld1, Ld1_v, Vec, Mem); + ASMJIT_INST_3x(ld1, Ld1_v, Vec, Vec, Mem); + ASMJIT_INST_4x(ld1, Ld1_v, Vec, Vec, Vec, Mem); + ASMJIT_INST_5x(ld1, Ld1_v, Vec, Vec, Vec, Vec, Mem); + ASMJIT_INST_2x(ld1r, Ld1r_v, Vec, Mem); + ASMJIT_INST_3x(ld2, Ld2_v, Vec, Vec, Mem); + ASMJIT_INST_3x(ld2r, Ld2r_v, Vec, Vec, Mem); + ASMJIT_INST_4x(ld3, Ld3_v, Vec, Vec, Vec, Mem); + ASMJIT_INST_4x(ld3r, Ld3r_v, Vec, Vec, Vec, Mem); + ASMJIT_INST_5x(ld4, Ld4_v, Vec, Vec, Vec, Vec, Mem); + ASMJIT_INST_5x(ld4r, Ld4r_v, Vec, Vec, Vec, Vec, Mem); + ASMJIT_INST_3x(ldnp, Ldnp_v, Vec, Vec, Mem); + ASMJIT_INST_3x(ldp, Ldp_v, Vec, Vec, Mem); + ASMJIT_INST_2x(ldr, Ldr_v, Vec, Mem); + ASMJIT_INST_2x(ldur, Ldur_v, Vec, Mem); + ASMJIT_INST_3x(mla, Mla_v, Vec, Vec, Vec); + ASMJIT_INST_3x(mls, Mls_v, Vec, Vec, Vec); + ASMJIT_INST_2x(mov, Mov_v, Vec, Vec); + ASMJIT_INST_2x(mov, Mov_v, Gp, Vec); + ASMJIT_INST_2x(mov, Mov_v, Vec, Gp); + ASMJIT_INST_2x(movi, Movi_v, Vec, Imm); + ASMJIT_INST_3x(movi, Movi_v, Vec, Imm, Imm); + ASMJIT_INST_3x(mul, Mul_v, Vec, Vec, Vec); + ASMJIT_INST_2x(mvn, Mvn_v, Vec, Vec); + ASMJIT_INST_2x(mvni, Mvni_v, Vec, Imm); + ASMJIT_INST_3x(mvni, Mvni_v, Vec, Imm, Imm); + ASMJIT_INST_2x(neg, Neg_v, Vec, Vec); + ASMJIT_INST_2x(not_, Not_v, Vec, Vec); + ASMJIT_INST_3x(orn, Orn_v, Vec, Vec, Vec); + ASMJIT_INST_2x(orr, Orr_v, Vec, Imm); + ASMJIT_INST_3x(orr, Orr_v, Vec, Vec, Vec); + ASMJIT_INST_3x(orr, Orr_v, Vec, Imm, Imm); + ASMJIT_INST_3x(pmul, Pmul_v, Vec, Vec, Vec); + ASMJIT_INST_3x(pmull, Pmull_v, Vec, Vec, Vec); + ASMJIT_INST_3x(pmull2, Pmull2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(raddhn, Raddhn_v, Vec, Vec, Vec); + ASMJIT_INST_3x(raddhn2, Raddhn2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(rbit, Rbit_v, Vec, Vec); + ASMJIT_INST_2x(rev16, Rev16_v, Vec, Vec); + ASMJIT_INST_2x(rev32, Rev32_v, Vec, Vec); + ASMJIT_INST_2x(rev64, Rev64_v, Vec, Vec); + ASMJIT_INST_3x(rshrn, Rshrn_v, Vec, Vec, Imm); + ASMJIT_INST_3x(rshrn2, Rshrn2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(rsubhn, Rsubhn_v, Vec, Vec, Vec); + ASMJIT_INST_3x(rsubhn2, Rsubhn2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(saba, Saba_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sabal, Sabal_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sabal2, Sabal2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sabd, Sabd_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sabdl, Sabdl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sabdl2, Sabdl2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(sadalp, Sadalp_v, Vec, Vec); + ASMJIT_INST_3x(saddl, Saddl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(saddl2, Saddl2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(saddlp, Saddlp_v, Vec, Vec); + ASMJIT_INST_2x(saddlv, Saddlv_v, Vec, Vec); + ASMJIT_INST_3x(saddw, Saddw_v, Vec, Vec, Vec); + ASMJIT_INST_3x(saddw2, Saddw2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(scvtf, Scvtf_v, Vec, Gp); + ASMJIT_INST_3x(scvtf, Scvtf_v, Vec, Gp, Imm); + ASMJIT_INST_2x(scvtf, Scvtf_v, Vec, Vec); + ASMJIT_INST_3x(scvtf, Scvtf_v, Vec, Vec, Imm); + ASMJIT_INST_3x(shadd, Shadd_v, Vec, Vec, Vec); + ASMJIT_INST_3x(shl, Shl_v, Vec, Vec, Imm); + ASMJIT_INST_3x(shll, Shll_v, Vec, Vec, Imm); + ASMJIT_INST_3x(shll2, Shll2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(shrn, Shrn_v, Vec, Vec, Imm); + ASMJIT_INST_3x(shrn2, Shrn2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(shsub, Shsub_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sli, Sli_v, Vec, Vec, Imm); + ASMJIT_INST_3x(smax, Smax_v, Vec, Vec, Vec); + ASMJIT_INST_3x(smaxp, Smaxp_v, Vec, Vec, Vec); + ASMJIT_INST_2x(smaxv, Smaxv_v, Vec, Vec); + ASMJIT_INST_3x(smin, Smin_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sminp, Sminp_v, Vec, Vec, Vec); + ASMJIT_INST_2x(sminv, Sminv_v, Vec, Vec); + ASMJIT_INST_3x(smlal, Smlal_v, Vec, Vec, Vec); + ASMJIT_INST_3x(smlal2, Smlal2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(smlsl, Smlsl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(smlsl2, Smlsl2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(smov, Smov_v, Gp, Vec); + ASMJIT_INST_3x(smull, Smull_v, Vec, Vec, Vec); + ASMJIT_INST_3x(smull2, Smull2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(sqabs, Sqabs_v, Vec, Vec); + ASMJIT_INST_3x(sqadd, Sqadd_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqdmlal, Sqdmlal_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqdmlal2, Sqdmlal2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqdmlsl, Sqdmlsl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqdmlsl2, Sqdmlsl2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqdmulh, Sqdmulh_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqdmull, Sqdmull_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqdmull2, Sqdmull2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(sqneg, Sqneg_v, Vec, Vec); + ASMJIT_INST_3x(sqrdmulh, Sqrdmulh_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqrshl, Sqrshl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqrshrn, Sqrshrn_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sqrshrn2, Sqrshrn2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sqrshrun, Sqrshrun_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sqrshrun2, Sqrshrun2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sqshl, Sqshl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqshl, Sqshl_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sqshlu, Sqshlu_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sqshrn, Sqshrn_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sqshrn2, Sqshrn2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sqshrun, Sqshrun_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sqshrun2, Sqshrun2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sqsub, Sqsub_v, Vec, Vec, Vec); + ASMJIT_INST_2x(sqxtn, Sqxtn_v, Vec, Vec); + ASMJIT_INST_2x(sqxtn2, Sqxtn2_v, Vec, Vec); + ASMJIT_INST_2x(sqxtun, Sqxtun_v, Vec, Vec); + ASMJIT_INST_2x(sqxtun2, Sqxtun2_v, Vec, Vec); + ASMJIT_INST_3x(srhadd, Srhadd_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sri, Sri_v, Vec, Vec, Imm); + ASMJIT_INST_3x(srshl, Srshl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(srshr, Srshr_v, Vec, Vec, Imm); + ASMJIT_INST_3x(srsra, Srsra_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sshl, Sshl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sshll, Sshll_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sshll2, Sshll2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(sshr, Sshr_v, Vec, Vec, Imm); + ASMJIT_INST_3x(ssra, Ssra_v, Vec, Vec, Imm); + ASMJIT_INST_3x(ssubl, Ssubl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(ssubl2, Ssubl2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(ssubw, Ssubw_v, Vec, Vec, Vec); + ASMJIT_INST_3x(ssubw2, Ssubw2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(st1, St1_v, Vec, Mem); + ASMJIT_INST_3x(st1, St1_v, Vec, Vec, Mem); + ASMJIT_INST_4x(st1, St1_v, Vec, Vec, Vec, Mem); + ASMJIT_INST_5x(st1, St1_v, Vec, Vec, Vec, Vec, Mem); + ASMJIT_INST_3x(st2, St2_v, Vec, Vec, Mem); + ASMJIT_INST_4x(st3, St3_v, Vec, Vec, Vec, Mem); + ASMJIT_INST_5x(st4, St4_v, Vec, Vec, Vec, Vec, Mem); + ASMJIT_INST_3x(stnp, Stnp_v, Vec, Vec, Mem); + ASMJIT_INST_3x(stp, Stp_v, Vec, Vec, Mem); + ASMJIT_INST_2x(str, Str_v, Vec, Mem); + ASMJIT_INST_2x(stur, Stur_v, Vec, Mem); + ASMJIT_INST_3x(sub, Sub_v, Vec, Vec, Vec); + ASMJIT_INST_3x(subhn, Subhn_v, Vec, Vec, Vec); + ASMJIT_INST_3x(subhn2, Subhn2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(suqadd, Suqadd_v, Vec, Vec); + ASMJIT_INST_2x(sxtl, Sxtl_v, Vec, Vec); + ASMJIT_INST_2x(sxtl2, Sxtl2_v, Vec, Vec); + ASMJIT_INST_3x(tbl, Tbl_v, Vec, Vec, Vec); + ASMJIT_INST_4x(tbl, Tbl_v, Vec, Vec, Vec, Vec); + ASMJIT_INST_5x(tbl, Tbl_v, Vec, Vec, Vec, Vec, Vec); + ASMJIT_INST_6x(tbl, Tbl_v, Vec, Vec, Vec, Vec, Vec, Vec); + ASMJIT_INST_3x(tbx, Tbx_v, Vec, Vec, Vec); + ASMJIT_INST_4x(tbx, Tbx_v, Vec, Vec, Vec, Vec); + ASMJIT_INST_5x(tbx, Tbx_v, Vec, Vec, Vec, Vec, Vec); + ASMJIT_INST_6x(tbx, Tbx_v, Vec, Vec, Vec, Vec, Vec, Vec); + ASMJIT_INST_3x(trn1, Trn1_v, Vec, Vec, Vec); + ASMJIT_INST_3x(trn2, Trn2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uaba, Uaba_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uabal, Uabal_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uabal2, Uabal2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uabd, Uabd_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uabdl, Uabdl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uabdl2, Uabdl2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(uadalp, Uadalp_v, Vec, Vec); + ASMJIT_INST_3x(uaddl, Uaddl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uaddl2, Uaddl2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(uaddlp, Uaddlp_v, Vec, Vec); + ASMJIT_INST_2x(uaddlv, Uaddlv_v, Vec, Vec); + ASMJIT_INST_3x(uaddw, Uaddw_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uaddw2, Uaddw2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(ucvtf, Ucvtf_v, Vec, Gp); + ASMJIT_INST_3x(ucvtf, Ucvtf_v, Vec, Gp, Imm); + ASMJIT_INST_2x(ucvtf, Ucvtf_v, Vec, Vec); + ASMJIT_INST_3x(ucvtf, Ucvtf_v, Vec, Vec, Imm); + ASMJIT_INST_3x(uhadd, Uhadd_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uhsub, Uhsub_v, Vec, Vec, Vec); + ASMJIT_INST_3x(umax, Umax_v, Vec, Vec, Vec); + ASMJIT_INST_3x(umaxp, Umaxp_v, Vec, Vec, Vec); + ASMJIT_INST_2x(umaxv, Umaxv_v, Vec, Vec); + ASMJIT_INST_3x(umin, Umin_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uminp, Uminp_v, Vec, Vec, Vec); + ASMJIT_INST_2x(uminv, Uminv_v, Vec, Vec); + ASMJIT_INST_3x(umlal, Umlal_v, Vec, Vec, Vec); + ASMJIT_INST_3x(umlal2, Umlal2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(umlsl, Umlsl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(umlsl2, Umlsl2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(umov, Umov_v, Gp, Vec); + ASMJIT_INST_3x(umull, Umull_v, Vec, Vec, Vec); + ASMJIT_INST_3x(umull2, Umull2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uqadd, Uqadd_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uqrshl, Uqrshl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uqrshl, Uqrshl_v, Vec, Vec, Imm); + ASMJIT_INST_3x(uqrshrn, Uqrshrn_v, Vec, Vec, Imm); + ASMJIT_INST_3x(uqrshrn2, Uqrshrn2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(uqshl, Uqshl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uqshl, Uqshl_v, Vec, Vec, Imm); + ASMJIT_INST_3x(uqshrn, Uqshrn_v, Vec, Vec, Imm); + ASMJIT_INST_3x(uqshrn2, Uqshrn2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(uqsub, Uqsub_v, Vec, Vec, Vec); + ASMJIT_INST_2x(uqxtn, Uqxtn_v, Vec, Vec); + ASMJIT_INST_2x(uqxtn2, Uqxtn2_v, Vec, Vec); + ASMJIT_INST_2x(urecpe, Urecpe_v, Vec, Vec); + ASMJIT_INST_3x(urhadd, Urhadd_v, Vec, Vec, Vec); + ASMJIT_INST_3x(urshl, Urshl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(urshr, Urshr_v, Vec, Vec, Imm); + ASMJIT_INST_2x(ursqrte, Ursqrte_v, Vec, Vec); + ASMJIT_INST_3x(ursra, Ursra_v, Vec, Vec, Imm); + ASMJIT_INST_3x(ushl, Ushl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(ushll, Ushll_v, Vec, Vec, Imm); + ASMJIT_INST_3x(ushll2, Ushll2_v, Vec, Vec, Imm); + ASMJIT_INST_3x(ushr, Ushr_v, Vec, Vec, Imm); + ASMJIT_INST_2x(usqadd, Usqadd_v, Vec, Vec); + ASMJIT_INST_3x(usra, Usra_v, Vec, Vec, Imm); + ASMJIT_INST_3x(usubl, Usubl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(usubl2, Usubl2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(usubw, Usubw_v, Vec, Vec, Vec); + ASMJIT_INST_3x(usubw2, Usubw2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(uxtl, Uxtl_v, Vec, Vec); + ASMJIT_INST_2x(uxtl2, Uxtl2_v, Vec, Vec); + ASMJIT_INST_3x(uzp1, Uzp1_v, Vec, Vec, Vec); + ASMJIT_INST_3x(uzp2, Uzp2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(xtn, Xtn_v, Vec, Vec); + ASMJIT_INST_2x(xtn2, Xtn2_v, Vec, Vec); + ASMJIT_INST_3x(zip1, Zip1_v, Vec, Vec, Vec); + ASMJIT_INST_3x(zip2, Zip2_v, Vec, Vec, Vec); + + //! \} + + //! \name AES Instructions + //! \{ + + ASMJIT_INST_2x(aesd, Aesd_v, Vec, Vec); + ASMJIT_INST_2x(aese, Aese_v, Vec, Vec); + ASMJIT_INST_2x(aesimc, Aesimc_v, Vec, Vec); + ASMJIT_INST_2x(aesmc, Aesmc_v, Vec, Vec); + + //! \} + + //! \name SHA1 Instructions + //! \{ + + ASMJIT_INST_3x(sha1c, Sha1c_v, Vec, Vec, Vec); + ASMJIT_INST_2x(sha1h, Sha1h_v, Vec, Vec); + ASMJIT_INST_3x(sha1m, Sha1m_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sha1p, Sha1p_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sha1su0, Sha1su0_v, Vec, Vec, Vec); + ASMJIT_INST_2x(sha1su1, Sha1su1_v, Vec, Vec); + + //! \} + + //! \name SHA2 Instructions + //! \{ + + ASMJIT_INST_3x(sha256h, Sha256h_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sha256h2, Sha256h2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(sha256su0, Sha256su0_v, Vec, Vec); + ASMJIT_INST_3x(sha256su1, Sha256su1_v, Vec, Vec, Vec); + + //! \} + + //! \name RDMA Instructions (ARMv8.1-A) + //! \{ + + ASMJIT_INST_3x(sqrdmlah, Sqrdmlah_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sqrdmlsh, Sqrdmlsh_v, Vec, Vec, Vec); + + //! \} + + //! \name FCMA Instruction (ARMv8.3-A) + //! \{ + + ASMJIT_INST_4x(fcadd, Fcadd_v, Vec, Vec, Vec, Imm); + ASMJIT_INST_4x(fcmla, Fcmla_v, Vec, Vec, Vec, Imm); + + //! \} + + //! \name FJCVTZS Instruction (ARMv8.3-A) + //! \{ + + ASMJIT_INST_2x(fjcvtzs, Fjcvtzs_v, Gp, Vec); + + //! \} + + //! \name FP16FML Instructions (ARMv8.4-A, optional in ARMv8.2-A) + //! \{ + + ASMJIT_INST_3x(fmlal, Fmlal_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fmlal2, Fmlal2_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fmlsl, Fmlsl_v, Vec, Vec, Vec); + ASMJIT_INST_3x(fmlsl2, Fmlsl2_v, Vec, Vec, Vec); + + + //! \} + + //! \name SHA3 Instructions (ARMv8.4-A, optional in ARMv8.2-A) + //! \{ + + ASMJIT_INST_4x(bcax, Bcax_v, Vec, Vec, Vec, Vec); + ASMJIT_INST_4x(eor3, Eor3_v, Vec, Vec, Vec, Vec); + ASMJIT_INST_3x(rax1, Rax1_v, Vec, Vec, Vec); + ASMJIT_INST_4x(xar, Xar_v, Vec, Vec, Vec, Imm); + + //! \} + + //! \name SHA512 Instructions (ARMv8.4-A) + //! \{ + + ASMJIT_INST_3x(sha512h, Sha512h_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sha512h2, Sha512h2_v, Vec, Vec, Vec); + ASMJIT_INST_2x(sha512su0, Sha512su0_v, Vec, Vec); + ASMJIT_INST_3x(sha512su1, Sha512su1_v, Vec, Vec, Vec); + + //! \} + + //! \name SM3 Instructions (ARMv8.4-A) + //! \{ + + ASMJIT_INST_3x(sm3partw1, Sm3partw1_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sm3partw2, Sm3partw2_v, Vec, Vec, Vec); + ASMJIT_INST_4x(sm3ss1, Sm3ss1_v, Vec, Vec, Vec, Vec); + ASMJIT_INST_3x(sm3tt1a, Sm3tt1a_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sm3tt1b, Sm3tt1b_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sm3tt2a, Sm3tt2a_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sm3tt2b, Sm3tt2b_v, Vec, Vec, Vec); + + //! \} + + //! \name SM4 Instructions (ARMv8.4-A) + //! \{ + + ASMJIT_INST_2x(sm4e, Sm4e_v, Vec, Vec); + ASMJIT_INST_3x(sm4ekey, Sm4ekey_v, Vec, Vec, Vec); + + //! \} + + //! \name DOTPROD Instructions (ARMv8.4-A, optional in ARMv8.2-A) + //! \{ + + ASMJIT_INST_3x(sdot, Sdot_v, Vec, Vec, Vec); + ASMJIT_INST_3x(udot, Udot_v, Vec, Vec, Vec); + + //! \} + + //! \name BF16 Instructions (ARMv8.6-A) + //! \{ + + ASMJIT_INST_2x(bfcvt, Bfcvt_v, Vec, Vec); + ASMJIT_INST_2x(bfcvtn, Bfcvtn_v, Vec, Vec); + ASMJIT_INST_2x(bfcvtn2, Bfcvtn2_v, Vec, Vec); + ASMJIT_INST_3x(bfmlalb, Bfmlalb_v, Vec, Vec, Vec); + ASMJIT_INST_3x(bfmlalt, Bfmlalt_v, Vec, Vec, Vec); + ASMJIT_INST_3x(bfmmla, Bfmmla_v, Vec, Vec, Vec); + ASMJIT_INST_3x(bfdot, Bfdot_v, Vec, Vec, Vec); + + //! \} + + //! \name I8MM Instructions (ARMv8.6-A) + //! \{ + + ASMJIT_INST_3x(smmla, Smmla_v, Vec, Vec, Vec); + ASMJIT_INST_3x(sudot, Sudot_v, Vec, Vec, Vec); + ASMJIT_INST_3x(ummla, Ummla_v, Vec, Vec, Vec); + ASMJIT_INST_3x(usdot, Usdot_v, Vec, Vec, Vec); + ASMJIT_INST_3x(usmmla, Usmmla_v, Vec, Vec, Vec); + + //! \} +}; + +//! Emitter (ARM). +//! +//! \note This class cannot be instantiated, you can only cast to it and use it as emitter that emits to either +//! `a64::Assembler`, `a64::Builder`, or `a64::Compiler` (use with caution with `a64::Compiler` as it requires +//! virtual registers). +class Emitter : public BaseEmitter, public EmitterExplicitT<Emitter> { + ASMJIT_NONCONSTRUCTIBLE(Emitter) +}; + +//! \} + +#undef ASMJIT_INST_0x +#undef ASMJIT_INST_1x +#undef ASMJIT_INST_2x +#undef ASMJIT_INST_3x +#undef ASMJIT_INST_4x +#undef ASMJIT_INST_5x +#undef ASMJIT_INST_6x +#undef ASMJIT_INST_1cc + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_A64EMITTER_H_INCLUDED diff --git a/src/asmjit/arm/a64formatter.cpp b/src/asmjit/arm/a64formatter.cpp new file mode 100644 index 0000000..bccb68b --- /dev/null +++ b/src/asmjit/arm/a64formatter.cpp @@ -0,0 +1,298 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#ifndef ASMJIT_NO_LOGGING + +#include "../core/misc_p.h" +#include "../core/support.h" +#include "../arm/a64formatter_p.h" +#include "../arm/a64instapi_p.h" +#include "../arm/a64instdb_p.h" +#include "../arm/a64operand.h" + +#ifndef ASMJIT_NO_COMPILER + #include "../core/compiler.h" +#endif + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +// a64::FormatterInternal - Format Register +// ======================================== + +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + RegType regType, + uint32_t rId, + uint32_t elementType, + uint32_t elementIndex) noexcept { + + DebugUtils::unused(flags); + DebugUtils::unused(arch); + + static const char bhsdq[] = "bhsdq"; + + bool virtRegFormatted = false; + +#ifndef ASMJIT_NO_COMPILER + if (Operand::isVirtId(rId)) { + if (emitter && emitter->isCompiler()) { + const BaseCompiler* cc = static_cast<const BaseCompiler*>(emitter); + if (cc->isVirtIdValid(rId)) { + VirtReg* vReg = cc->virtRegById(rId); + ASMJIT_ASSERT(vReg != nullptr); + + const char* name = vReg->name(); + if (name && name[0] != '\0') + ASMJIT_PROPAGATE(sb.append(name)); + else + ASMJIT_PROPAGATE(sb.appendFormat("%%%u", unsigned(Operand::virtIdToIndex(rId)))); + + virtRegFormatted = true; + } + } + } +#else + DebugUtils::unused(emitter, flags); +#endif + + if (!virtRegFormatted) { + char letter = '\0'; + switch (regType) { + case RegType::kARM_GpW: + if (rId == Gp::kIdZr) + return sb.append("wzr"); + if (rId == Gp::kIdSp) + return sb.append("wsp"); + + letter = 'w'; + break; + + case RegType::kARM_GpX: + if (rId == Gp::kIdZr) + return sb.append("xzr"); + if (rId == Gp::kIdSp) + return sb.append("sp"); + + letter = 'x'; + break; + + case RegType::kARM_VecB: + case RegType::kARM_VecH: + case RegType::kARM_VecS: + case RegType::kARM_VecD: + case RegType::kARM_VecV: + letter = bhsdq[uint32_t(regType) - uint32_t(RegType::kARM_VecB)]; + if (elementType) + letter = 'v'; + break; + + default: + ASMJIT_PROPAGATE(sb.appendFormat("<Reg-%u>?$u", uint32_t(regType), rId)); + break; + } + + if (letter) + ASMJIT_PROPAGATE(sb.appendFormat("%c%u", letter, rId)); + } + + if (elementType) { + char elementLetter = '\0'; + uint32_t elementCount = 0; + + switch (elementType) { + case Vec::kElementTypeB: + elementLetter = 'b'; + elementCount = 16; + break; + + case Vec::kElementTypeH: + elementLetter = 'h'; + elementCount = 8; + break; + + case Vec::kElementTypeS: + elementLetter = 's'; + elementCount = 4; + break; + + case Vec::kElementTypeD: + elementLetter = 'd'; + elementCount = 2; + break; + + default: + return sb.append(".<Unknown>"); + } + + if (elementLetter) { + if (elementIndex == 0xFFFFFFFFu) { + if (regType == RegType::kARM_VecD) + elementCount /= 2u; + ASMJIT_PROPAGATE(sb.appendFormat(".%u%c", elementCount, elementLetter)); + } + else { + ASMJIT_PROPAGATE(sb.appendFormat(".%c[%u]", elementLetter, elementIndex)); + } + } + } + + return kErrorOk; +} + +// a64::FormatterInternal - Format Operand +// ======================================= + +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + const Operand_& op) noexcept { + + if (op.isReg()) { + const BaseReg& reg = op.as<BaseReg>(); + + uint32_t elementType = op.as<Vec>().elementType(); + uint32_t elementIndex = op.as<Vec>().elementIndex(); + + if (!op.as<Vec>().hasElementIndex()) + elementIndex = 0xFFFFFFFFu; + + return formatRegister(sb, flags, emitter, arch, reg.type(), reg.id(), elementType, elementIndex); + } + + if (op.isMem()) { + const Mem& m = op.as<Mem>(); + ASMJIT_PROPAGATE(sb.append('[')); + + if (m.hasBase()) { + if (m.hasBaseLabel()) { + ASMJIT_PROPAGATE(Formatter::formatLabel(sb, flags, emitter, m.baseId())); + } + else { + FormatFlags modifiedFlags = flags; + if (m.isRegHome()) { + ASMJIT_PROPAGATE(sb.append('&')); + modifiedFlags &= ~FormatFlags::kRegCasts; + } + ASMJIT_PROPAGATE(formatRegister(sb, modifiedFlags, emitter, arch, m.baseType(), m.baseId())); + } + } + else { + // ARM really requires base. + if (m.hasIndex() || m.hasOffset()) { + ASMJIT_PROPAGATE(sb.append("<None>")); + } + } + + // The post index makes it look like there was another operand, but it's + // still the part of AsmJit's `arm::Mem` operand so it's consistent with + // other architectures. + if (m.isPostIndex()) + ASMJIT_PROPAGATE(sb.append(']')); + + if (m.hasIndex()) { + ASMJIT_PROPAGATE(sb.append(", ")); + ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, m.indexType(), m.indexId())); + } + + if (m.hasOffset()) { + ASMJIT_PROPAGATE(sb.append(", ")); + + int64_t off = int64_t(m.offset()); + uint32_t base = 10; + + if (Support::test(flags, FormatFlags::kHexOffsets) && uint64_t(off) > 9) + base = 16; + + if (base == 10) { + ASMJIT_PROPAGATE(sb.appendInt(off, base)); + } + else { + ASMJIT_PROPAGATE(sb.append("0x")); + ASMJIT_PROPAGATE(sb.appendUInt(uint64_t(off), base)); + } + } + + if (m.hasShift()) { + ASMJIT_PROPAGATE(sb.append(' ')); + if (!m.isPreOrPost()) + ASMJIT_PROPAGATE(formatShiftOp(sb, (ShiftOp)m.predicate())); + ASMJIT_PROPAGATE(sb.appendFormat(" %u", m.shift())); + } + + if (!m.isPostIndex()) + ASMJIT_PROPAGATE(sb.append(']')); + + if (m.isPreIndex()) + ASMJIT_PROPAGATE(sb.append('!')); + + return kErrorOk; + } + + if (op.isImm()) { + const Imm& i = op.as<Imm>(); + int64_t val = i.value(); + + if (Support::test(flags, FormatFlags::kHexImms) && uint64_t(val) > 9) { + ASMJIT_PROPAGATE(sb.append("0x")); + return sb.appendUInt(uint64_t(val), 16); + } + else { + return sb.appendInt(val, 10); + } + } + + if (op.isLabel()) { + return Formatter::formatLabel(sb, flags, emitter, op.id()); + } + + return sb.append("<None>"); +} + +// a64::FormatterInternal - Format Instruction +// =========================================== + +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept { + + DebugUtils::unused(arch); + + // Format instruction options and instruction mnemonic. + InstId instId = inst.realId(); + if (instId < Inst::_kIdCount) + ASMJIT_PROPAGATE(InstInternal::instIdToString(arch, instId, sb)); + else + ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId))); + + CondCode cc = inst.armCondCode(); + if (cc != CondCode::kAL) { + ASMJIT_PROPAGATE(sb.append('.')); + ASMJIT_PROPAGATE(formatCondCode(sb, cc)); + } + + for (uint32_t i = 0; i < opCount; i++) { + const Operand_& op = operands[i]; + if (op.isNone()) + break; + + ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", ")); + ASMJIT_PROPAGATE(formatOperand(sb, flags, emitter, arch, op)); + } + + return kErrorOk; +} + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_LOGGING diff --git a/src/asmjit/arm/a64formatter_p.h b/src/asmjit/arm/a64formatter_p.h new file mode 100644 index 0000000..bd7a144 --- /dev/null +++ b/src/asmjit/arm/a64formatter_p.h @@ -0,0 +1,59 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64FORMATTER_P_H_INCLUDED +#define ASMJIT_ARM_A64FORMATTER_P_H_INCLUDED + +#include "../core/api-config.h" +#ifndef ASMJIT_NO_LOGGING + +#include "../core/formatter.h" +#include "../core/string.h" +#include "../arm/armformatter_p.h" +#include "../arm/a64globals.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \cond INTERNAL +//! \addtogroup asmjit_a64 +//! \{ + +namespace FormatterInternal { + +using namespace arm::FormatterInternal; + +Error ASMJIT_CDECL formatRegister( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + RegType regType, + uint32_t regId, + uint32_t elementType = 0, + uint32_t elementIndex = 0xFFFFFFFFu) noexcept; + +Error ASMJIT_CDECL formatOperand( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + const Operand_& op) noexcept; + +Error ASMJIT_CDECL formatInstruction( + String& sb, + FormatFlags flags, + const BaseEmitter* emitter, + Arch arch, + const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept; + +} // {FormatterInternal} + +//! \} +//! \endcond + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_LOGGING +#endif // ASMJIT_ARM_A64FORMATTER_P_H_INCLUDED diff --git a/src/asmjit/arm/a64func.cpp b/src/asmjit/arm/a64func.cpp new file mode 100644 index 0000000..55e3f2e --- /dev/null +++ b/src/asmjit/arm/a64func.cpp @@ -0,0 +1,189 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#if !defined(ASMJIT_NO_AARCH64) + +#include "../arm/a64func_p.h" +#include "../arm/a64operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +namespace FuncInternal { + +static inline bool shouldThreatAsCDecl(CallConvId ccId) noexcept { + return ccId == CallConvId::kCDecl || + ccId == CallConvId::kStdCall || + ccId == CallConvId::kFastCall || + ccId == CallConvId::kVectorCall || + ccId == CallConvId::kThisCall || + ccId == CallConvId::kRegParm1 || + ccId == CallConvId::kRegParm2 || + ccId == CallConvId::kRegParm3; +} + +static RegType regTypeFromFpOrVecTypeId(TypeId typeId) noexcept { + if (typeId == TypeId::kFloat32) + return RegType::kARM_VecS; + else if (typeId == TypeId::kFloat64) + return RegType::kARM_VecD; + else if (TypeUtils::isVec32(typeId)) + return RegType::kARM_VecS; + else if (TypeUtils::isVec64(typeId)) + return RegType::kARM_VecD; + else if (TypeUtils::isVec128(typeId)) + return RegType::kARM_VecV; + else + return RegType::kNone; +} + +ASMJIT_FAVOR_SIZE Error initCallConv(CallConv& cc, CallConvId ccId, const Environment& environment) noexcept { + cc.setArch(environment.arch()); + + cc.setSaveRestoreRegSize(RegGroup::kGp, 8); + cc.setSaveRestoreRegSize(RegGroup::kVec, 8); + cc.setSaveRestoreAlignment(RegGroup::kGp, 16); + cc.setSaveRestoreAlignment(RegGroup::kVec, 16); + cc.setSaveRestoreAlignment(RegGroup::kExtraVirt2, 1); + cc.setSaveRestoreAlignment(RegGroup::kExtraVirt3, 1); + cc.setPassedOrder(RegGroup::kGp, 0, 1, 2, 3, 4, 5, 6, 7); + cc.setPassedOrder(RegGroup::kVec, 0, 1, 2, 3, 4, 5, 6, 7); + cc.setNaturalStackAlignment(16); + + if (shouldThreatAsCDecl(ccId)) { + // ARM doesn't have that many calling conventions as we can find in X86 world, treat most conventions as __cdecl. + cc.setId(CallConvId::kCDecl); + cc.setPreservedRegs(RegGroup::kGp, Support::bitMask(Gp::kIdOs, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30)); + cc.setPreservedRegs(RegGroup::kVec, Support::bitMask(8, 9, 10, 11, 12, 13, 14, 15)); + } + else { + cc.setId(ccId); + cc.setSaveRestoreRegSize(RegGroup::kVec, 16); + cc.setPreservedRegs(RegGroup::kGp, Support::bitMask(4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30)); + cc.setPreservedRegs(RegGroup::kVec, Support::bitMask(4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31)); + } + + return kErrorOk; +} + +ASMJIT_FAVOR_SIZE Error initFuncDetail(FuncDetail& func, const FuncSignature& signature, uint32_t registerSize) noexcept { + DebugUtils::unused(signature); + + const CallConv& cc = func.callConv(); + uint32_t stackOffset = 0; + + uint32_t i; + uint32_t argCount = func.argCount(); + + if (func.hasRet()) { + for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) { + TypeId typeId = func._rets[valueIndex].typeId(); + + // Terminate at the first void type (end of the pack). + if (typeId == TypeId::kVoid) + break; + + switch (typeId) { + case TypeId::kInt8: + case TypeId::kInt16: + case TypeId::kInt32: { + func._rets[valueIndex].initReg(RegType::kARM_GpW, valueIndex, TypeId::kInt32); + break; + } + + case TypeId::kUInt8: + case TypeId::kUInt16: + case TypeId::kUInt32: { + func._rets[valueIndex].initReg(RegType::kARM_GpW, valueIndex, TypeId::kUInt32); + break; + } + + case TypeId::kInt64: + case TypeId::kUInt64: { + func._rets[valueIndex].initReg(RegType::kARM_GpX, valueIndex, typeId); + break; + } + + default: { + RegType regType = regTypeFromFpOrVecTypeId(typeId); + if (regType == RegType::kNone) + return DebugUtils::errored(kErrorInvalidRegType); + + func._rets[valueIndex].initReg(regType, valueIndex, typeId); + break; + } + } + } + } + + switch (cc.strategy()) { + case CallConvStrategy::kDefault: { + uint32_t gpzPos = 0; + uint32_t vecPos = 0; + + for (i = 0; i < argCount; i++) { + FuncValue& arg = func._args[i][0]; + TypeId typeId = arg.typeId(); + + if (TypeUtils::isInt(typeId)) { + uint32_t regId = BaseReg::kIdBad; + + if (gpzPos < CallConv::kMaxRegArgsPerGroup) + regId = cc._passedOrder[RegGroup::kGp].id[gpzPos]; + + if (regId != BaseReg::kIdBad) { + RegType regType = typeId <= TypeId::kUInt32 ? RegType::kARM_GpW : RegType::kARM_GpX; + arg.assignRegData(regType, regId); + func.addUsedRegs(RegGroup::kGp, Support::bitMask(regId)); + gpzPos++; + } + else { + uint32_t size = Support::max<uint32_t>(TypeUtils::sizeOf(typeId), registerSize); + arg.assignStackOffset(int32_t(stackOffset)); + stackOffset += size; + } + continue; + } + + if (TypeUtils::isFloat(typeId) || TypeUtils::isVec(typeId)) { + uint32_t regId = BaseReg::kIdBad; + + if (vecPos < CallConv::kMaxRegArgsPerGroup) + regId = cc._passedOrder[RegGroup::kVec].id[vecPos]; + + if (regId != BaseReg::kIdBad) { + RegType regType = regTypeFromFpOrVecTypeId(typeId); + if (regType == RegType::kNone) + return DebugUtils::errored(kErrorInvalidRegType); + + arg.initTypeId(typeId); + arg.assignRegData(regType, regId); + func.addUsedRegs(RegGroup::kVec, Support::bitMask(regId)); + vecPos++; + } + else { + uint32_t size = TypeUtils::sizeOf(typeId); + arg.assignStackOffset(int32_t(stackOffset)); + stackOffset += size; + } + continue; + } + } + break; + } + + default: + return DebugUtils::errored(kErrorInvalidState); + } + + func._argStackSize = stackOffset; + return kErrorOk; +} + +} // {FuncInternal} + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_AARCH64 diff --git a/src/asmjit/arm/a64func_p.h b/src/asmjit/arm/a64func_p.h new file mode 100644 index 0000000..9f531fc --- /dev/null +++ b/src/asmjit/arm/a64func_p.h @@ -0,0 +1,33 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64FUNC_P_H_INCLUDED +#define ASMJIT_ARM_A64FUNC_P_H_INCLUDED + +#include "../core/func.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \cond INTERNAL +//! \addtogroup asmjit_a64 +//! \{ + +//! AArch64-specific function API (calling conventions and other utilities). +namespace FuncInternal { + +//! Initialize `CallConv` structure (AArch64 specific). +Error initCallConv(CallConv& cc, CallConvId ccId, const Environment& environment) noexcept; + +//! Initialize `FuncDetail` (AArch64 specific). +Error initFuncDetail(FuncDetail& func, const FuncSignature& signature, uint32_t registerSize) noexcept; + +} // {FuncInternal} + +//! \} +//! \endcond + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_A64FUNC_P_H_INCLUDED diff --git a/src/asmjit/arm/a64globals.h b/src/asmjit/arm/a64globals.h new file mode 100644 index 0000000..2b6b6f0 --- /dev/null +++ b/src/asmjit/arm/a64globals.h @@ -0,0 +1,1894 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64GLOBALS_H_INCLUDED +#define ASMJIT_ARM_A64GLOBALS_H_INCLUDED + +#include "../arm/armglobals.h" + +//! \namespace asmjit::a64 +//! \ingroup asmjit_a64 +//! +//! AArch64 backend. + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +// a64 uses everything from arm namespace and adds into it. +using namespace arm; + +//! \addtogroup asmjit_a64 +//! \{ + +//! AArch64 instruction. +//! +//! \note Only used to hold ARM-specific enumerations and static functions. +struct Inst { + //! Instruction id. + enum Id : uint32_t { + // ${InstId:Begin} + kIdNone = 0, //!< Instruction ''. + kIdAdc, //!< Instruction 'adc'. + kIdAdcs, //!< Instruction 'adcs'. + kIdAdd, //!< Instruction 'add'. + kIdAddg, //!< Instruction 'addg'. + kIdAdds, //!< Instruction 'adds'. + kIdAdr, //!< Instruction 'adr'. + kIdAdrp, //!< Instruction 'adrp'. + kIdAnd, //!< Instruction 'and'. + kIdAnds, //!< Instruction 'ands'. + kIdAsr, //!< Instruction 'asr'. + kIdAsrv, //!< Instruction 'asrv'. + kIdAt, //!< Instruction 'at'. + kIdAutda, //!< Instruction 'autda'. + kIdAutdza, //!< Instruction 'autdza'. + kIdAutdb, //!< Instruction 'autdb'. + kIdAutdzb, //!< Instruction 'autdzb'. + kIdAutia, //!< Instruction 'autia'. + kIdAutia1716, //!< Instruction 'autia1716'. + kIdAutiasp, //!< Instruction 'autiasp'. + kIdAutiaz, //!< Instruction 'autiaz'. + kIdAutib, //!< Instruction 'autib'. + kIdAutib1716, //!< Instruction 'autib1716'. + kIdAutibsp, //!< Instruction 'autibsp'. + kIdAutibz, //!< Instruction 'autibz'. + kIdAutiza, //!< Instruction 'autiza'. + kIdAutizb, //!< Instruction 'autizb'. + kIdAxflag, //!< Instruction 'axflag'. + kIdB, //!< Instruction 'b'. + kIdBfc, //!< Instruction 'bfc'. + kIdBfi, //!< Instruction 'bfi'. + kIdBfm, //!< Instruction 'bfm'. + kIdBfxil, //!< Instruction 'bfxil'. + kIdBic, //!< Instruction 'bic'. + kIdBics, //!< Instruction 'bics'. + kIdBl, //!< Instruction 'bl'. + kIdBlr, //!< Instruction 'blr'. + kIdBr, //!< Instruction 'br'. + kIdBrk, //!< Instruction 'brk'. + kIdCas, //!< Instruction 'cas'. + kIdCasa, //!< Instruction 'casa'. + kIdCasab, //!< Instruction 'casab'. + kIdCasah, //!< Instruction 'casah'. + kIdCasal, //!< Instruction 'casal'. + kIdCasalb, //!< Instruction 'casalb'. + kIdCasalh, //!< Instruction 'casalh'. + kIdCasb, //!< Instruction 'casb'. + kIdCash, //!< Instruction 'cash'. + kIdCasl, //!< Instruction 'casl'. + kIdCaslb, //!< Instruction 'caslb'. + kIdCaslh, //!< Instruction 'caslh'. + kIdCasp, //!< Instruction 'casp'. + kIdCaspa, //!< Instruction 'caspa'. + kIdCaspal, //!< Instruction 'caspal'. + kIdCaspl, //!< Instruction 'caspl'. + kIdCbnz, //!< Instruction 'cbnz'. + kIdCbz, //!< Instruction 'cbz'. + kIdCcmn, //!< Instruction 'ccmn'. + kIdCcmp, //!< Instruction 'ccmp'. + kIdCfinv, //!< Instruction 'cfinv'. + kIdCinc, //!< Instruction 'cinc'. + kIdCinv, //!< Instruction 'cinv'. + kIdClrex, //!< Instruction 'clrex'. + kIdCls, //!< Instruction 'cls'. + kIdClz, //!< Instruction 'clz'. + kIdCmn, //!< Instruction 'cmn'. + kIdCmp, //!< Instruction 'cmp'. + kIdCmpp, //!< Instruction 'cmpp'. + kIdCneg, //!< Instruction 'cneg'. + kIdCrc32b, //!< Instruction 'crc32b'. + kIdCrc32cb, //!< Instruction 'crc32cb'. + kIdCrc32ch, //!< Instruction 'crc32ch'. + kIdCrc32cw, //!< Instruction 'crc32cw'. + kIdCrc32cx, //!< Instruction 'crc32cx'. + kIdCrc32h, //!< Instruction 'crc32h'. + kIdCrc32w, //!< Instruction 'crc32w'. + kIdCrc32x, //!< Instruction 'crc32x'. + kIdCsdb, //!< Instruction 'csdb'. + kIdCsel, //!< Instruction 'csel'. + kIdCset, //!< Instruction 'cset'. + kIdCsetm, //!< Instruction 'csetm'. + kIdCsinc, //!< Instruction 'csinc'. + kIdCsinv, //!< Instruction 'csinv'. + kIdCsneg, //!< Instruction 'csneg'. + kIdDc, //!< Instruction 'dc'. + kIdDcps1, //!< Instruction 'dcps1'. + kIdDcps2, //!< Instruction 'dcps2'. + kIdDcps3, //!< Instruction 'dcps3'. + kIdDgh, //!< Instruction 'dgh'. + kIdDmb, //!< Instruction 'dmb'. + kIdDrps, //!< Instruction 'drps'. + kIdDsb, //!< Instruction 'dsb'. + kIdEon, //!< Instruction 'eon'. + kIdEor, //!< Instruction 'eor'. + kIdEsb, //!< Instruction 'esb'. + kIdExtr, //!< Instruction 'extr'. + kIdEret, //!< Instruction 'eret'. + kIdGmi, //!< Instruction 'gmi'. + kIdHint, //!< Instruction 'hint'. + kIdHlt, //!< Instruction 'hlt'. + kIdHvc, //!< Instruction 'hvc'. + kIdIc, //!< Instruction 'ic'. + kIdIsb, //!< Instruction 'isb'. + kIdLdadd, //!< Instruction 'ldadd'. + kIdLdadda, //!< Instruction 'ldadda'. + kIdLdaddab, //!< Instruction 'ldaddab'. + kIdLdaddah, //!< Instruction 'ldaddah'. + kIdLdaddal, //!< Instruction 'ldaddal'. + kIdLdaddalb, //!< Instruction 'ldaddalb'. + kIdLdaddalh, //!< Instruction 'ldaddalh'. + kIdLdaddb, //!< Instruction 'ldaddb'. + kIdLdaddh, //!< Instruction 'ldaddh'. + kIdLdaddl, //!< Instruction 'ldaddl'. + kIdLdaddlb, //!< Instruction 'ldaddlb'. + kIdLdaddlh, //!< Instruction 'ldaddlh'. + kIdLdar, //!< Instruction 'ldar'. + kIdLdarb, //!< Instruction 'ldarb'. + kIdLdarh, //!< Instruction 'ldarh'. + kIdLdaxp, //!< Instruction 'ldaxp'. + kIdLdaxr, //!< Instruction 'ldaxr'. + kIdLdaxrb, //!< Instruction 'ldaxrb'. + kIdLdaxrh, //!< Instruction 'ldaxrh'. + kIdLdclr, //!< Instruction 'ldclr'. + kIdLdclra, //!< Instruction 'ldclra'. + kIdLdclrab, //!< Instruction 'ldclrab'. + kIdLdclrah, //!< Instruction 'ldclrah'. + kIdLdclral, //!< Instruction 'ldclral'. + kIdLdclralb, //!< Instruction 'ldclralb'. + kIdLdclralh, //!< Instruction 'ldclralh'. + kIdLdclrb, //!< Instruction 'ldclrb'. + kIdLdclrh, //!< Instruction 'ldclrh'. + kIdLdclrl, //!< Instruction 'ldclrl'. + kIdLdclrlb, //!< Instruction 'ldclrlb'. + kIdLdclrlh, //!< Instruction 'ldclrlh'. + kIdLdeor, //!< Instruction 'ldeor'. + kIdLdeora, //!< Instruction 'ldeora'. + kIdLdeorab, //!< Instruction 'ldeorab'. + kIdLdeorah, //!< Instruction 'ldeorah'. + kIdLdeoral, //!< Instruction 'ldeoral'. + kIdLdeoralb, //!< Instruction 'ldeoralb'. + kIdLdeoralh, //!< Instruction 'ldeoralh'. + kIdLdeorb, //!< Instruction 'ldeorb'. + kIdLdeorh, //!< Instruction 'ldeorh'. + kIdLdeorl, //!< Instruction 'ldeorl'. + kIdLdeorlb, //!< Instruction 'ldeorlb'. + kIdLdeorlh, //!< Instruction 'ldeorlh'. + kIdLdg, //!< Instruction 'ldg'. + kIdLdgm, //!< Instruction 'ldgm'. + kIdLdlar, //!< Instruction 'ldlar'. + kIdLdlarb, //!< Instruction 'ldlarb'. + kIdLdlarh, //!< Instruction 'ldlarh'. + kIdLdnp, //!< Instruction 'ldnp'. + kIdLdp, //!< Instruction 'ldp'. + kIdLdpsw, //!< Instruction 'ldpsw'. + kIdLdr, //!< Instruction 'ldr'. + kIdLdraa, //!< Instruction 'ldraa'. + kIdLdrab, //!< Instruction 'ldrab'. + kIdLdrb, //!< Instruction 'ldrb'. + kIdLdrh, //!< Instruction 'ldrh'. + kIdLdrsb, //!< Instruction 'ldrsb'. + kIdLdrsh, //!< Instruction 'ldrsh'. + kIdLdrsw, //!< Instruction 'ldrsw'. + kIdLdset, //!< Instruction 'ldset'. + kIdLdseta, //!< Instruction 'ldseta'. + kIdLdsetab, //!< Instruction 'ldsetab'. + kIdLdsetah, //!< Instruction 'ldsetah'. + kIdLdsetal, //!< Instruction 'ldsetal'. + kIdLdsetalb, //!< Instruction 'ldsetalb'. + kIdLdsetalh, //!< Instruction 'ldsetalh'. + kIdLdsetb, //!< Instruction 'ldsetb'. + kIdLdseth, //!< Instruction 'ldseth'. + kIdLdsetl, //!< Instruction 'ldsetl'. + kIdLdsetlb, //!< Instruction 'ldsetlb'. + kIdLdsetlh, //!< Instruction 'ldsetlh'. + kIdLdsmax, //!< Instruction 'ldsmax'. + kIdLdsmaxa, //!< Instruction 'ldsmaxa'. + kIdLdsmaxab, //!< Instruction 'ldsmaxab'. + kIdLdsmaxah, //!< Instruction 'ldsmaxah'. + kIdLdsmaxal, //!< Instruction 'ldsmaxal'. + kIdLdsmaxalb, //!< Instruction 'ldsmaxalb'. + kIdLdsmaxalh, //!< Instruction 'ldsmaxalh'. + kIdLdsmaxb, //!< Instruction 'ldsmaxb'. + kIdLdsmaxh, //!< Instruction 'ldsmaxh'. + kIdLdsmaxl, //!< Instruction 'ldsmaxl'. + kIdLdsmaxlb, //!< Instruction 'ldsmaxlb'. + kIdLdsmaxlh, //!< Instruction 'ldsmaxlh'. + kIdLdsmin, //!< Instruction 'ldsmin'. + kIdLdsmina, //!< Instruction 'ldsmina'. + kIdLdsminab, //!< Instruction 'ldsminab'. + kIdLdsminah, //!< Instruction 'ldsminah'. + kIdLdsminal, //!< Instruction 'ldsminal'. + kIdLdsminalb, //!< Instruction 'ldsminalb'. + kIdLdsminalh, //!< Instruction 'ldsminalh'. + kIdLdsminb, //!< Instruction 'ldsminb'. + kIdLdsminh, //!< Instruction 'ldsminh'. + kIdLdsminl, //!< Instruction 'ldsminl'. + kIdLdsminlb, //!< Instruction 'ldsminlb'. + kIdLdsminlh, //!< Instruction 'ldsminlh'. + kIdLdtr, //!< Instruction 'ldtr'. + kIdLdtrb, //!< Instruction 'ldtrb'. + kIdLdtrh, //!< Instruction 'ldtrh'. + kIdLdtrsb, //!< Instruction 'ldtrsb'. + kIdLdtrsh, //!< Instruction 'ldtrsh'. + kIdLdtrsw, //!< Instruction 'ldtrsw'. + kIdLdumax, //!< Instruction 'ldumax'. + kIdLdumaxa, //!< Instruction 'ldumaxa'. + kIdLdumaxab, //!< Instruction 'ldumaxab'. + kIdLdumaxah, //!< Instruction 'ldumaxah'. + kIdLdumaxal, //!< Instruction 'ldumaxal'. + kIdLdumaxalb, //!< Instruction 'ldumaxalb'. + kIdLdumaxalh, //!< Instruction 'ldumaxalh'. + kIdLdumaxb, //!< Instruction 'ldumaxb'. + kIdLdumaxh, //!< Instruction 'ldumaxh'. + kIdLdumaxl, //!< Instruction 'ldumaxl'. + kIdLdumaxlb, //!< Instruction 'ldumaxlb'. + kIdLdumaxlh, //!< Instruction 'ldumaxlh'. + kIdLdumin, //!< Instruction 'ldumin'. + kIdLdumina, //!< Instruction 'ldumina'. + kIdLduminab, //!< Instruction 'lduminab'. + kIdLduminah, //!< Instruction 'lduminah'. + kIdLduminal, //!< Instruction 'lduminal'. + kIdLduminalb, //!< Instruction 'lduminalb'. + kIdLduminalh, //!< Instruction 'lduminalh'. + kIdLduminb, //!< Instruction 'lduminb'. + kIdLduminh, //!< Instruction 'lduminh'. + kIdLduminl, //!< Instruction 'lduminl'. + kIdLduminlb, //!< Instruction 'lduminlb'. + kIdLduminlh, //!< Instruction 'lduminlh'. + kIdLdur, //!< Instruction 'ldur'. + kIdLdurb, //!< Instruction 'ldurb'. + kIdLdurh, //!< Instruction 'ldurh'. + kIdLdursb, //!< Instruction 'ldursb'. + kIdLdursh, //!< Instruction 'ldursh'. + kIdLdursw, //!< Instruction 'ldursw'. + kIdLdxp, //!< Instruction 'ldxp'. + kIdLdxr, //!< Instruction 'ldxr'. + kIdLdxrb, //!< Instruction 'ldxrb'. + kIdLdxrh, //!< Instruction 'ldxrh'. + kIdLsl, //!< Instruction 'lsl'. + kIdLslv, //!< Instruction 'lslv'. + kIdLsr, //!< Instruction 'lsr'. + kIdLsrv, //!< Instruction 'lsrv'. + kIdMadd, //!< Instruction 'madd'. + kIdMneg, //!< Instruction 'mneg'. + kIdMov, //!< Instruction 'mov'. + kIdMovk, //!< Instruction 'movk'. + kIdMovn, //!< Instruction 'movn'. + kIdMovz, //!< Instruction 'movz'. + kIdMrs, //!< Instruction 'mrs'. + kIdMsr, //!< Instruction 'msr'. + kIdMsub, //!< Instruction 'msub'. + kIdMul, //!< Instruction 'mul'. + kIdMvn, //!< Instruction 'mvn'. + kIdNeg, //!< Instruction 'neg'. + kIdNegs, //!< Instruction 'negs'. + kIdNgc, //!< Instruction 'ngc'. + kIdNgcs, //!< Instruction 'ngcs'. + kIdNop, //!< Instruction 'nop'. + kIdOrn, //!< Instruction 'orn'. + kIdOrr, //!< Instruction 'orr'. + kIdPacda, //!< Instruction 'pacda'. + kIdPacdb, //!< Instruction 'pacdb'. + kIdPacdza, //!< Instruction 'pacdza'. + kIdPacdzb, //!< Instruction 'pacdzb'. + kIdPacga, //!< Instruction 'pacga'. + kIdPssbb, //!< Instruction 'pssbb'. + kIdRbit, //!< Instruction 'rbit'. + kIdRet, //!< Instruction 'ret'. + kIdRev, //!< Instruction 'rev'. + kIdRev16, //!< Instruction 'rev16'. + kIdRev32, //!< Instruction 'rev32'. + kIdRev64, //!< Instruction 'rev64'. + kIdRor, //!< Instruction 'ror'. + kIdRorv, //!< Instruction 'rorv'. + kIdSbc, //!< Instruction 'sbc'. + kIdSbcs, //!< Instruction 'sbcs'. + kIdSbfiz, //!< Instruction 'sbfiz'. + kIdSbfm, //!< Instruction 'sbfm'. + kIdSbfx, //!< Instruction 'sbfx'. + kIdSdiv, //!< Instruction 'sdiv'. + kIdSetf8, //!< Instruction 'setf8'. + kIdSetf16, //!< Instruction 'setf16'. + kIdSev, //!< Instruction 'sev'. + kIdSevl, //!< Instruction 'sevl'. + kIdSmaddl, //!< Instruction 'smaddl'. + kIdSmc, //!< Instruction 'smc'. + kIdSmnegl, //!< Instruction 'smnegl'. + kIdSmsubl, //!< Instruction 'smsubl'. + kIdSmulh, //!< Instruction 'smulh'. + kIdSmull, //!< Instruction 'smull'. + kIdSsbb, //!< Instruction 'ssbb'. + kIdSt2g, //!< Instruction 'st2g'. + kIdStadd, //!< Instruction 'stadd'. + kIdStaddl, //!< Instruction 'staddl'. + kIdStaddb, //!< Instruction 'staddb'. + kIdStaddlb, //!< Instruction 'staddlb'. + kIdStaddh, //!< Instruction 'staddh'. + kIdStaddlh, //!< Instruction 'staddlh'. + kIdStclr, //!< Instruction 'stclr'. + kIdStclrl, //!< Instruction 'stclrl'. + kIdStclrb, //!< Instruction 'stclrb'. + kIdStclrlb, //!< Instruction 'stclrlb'. + kIdStclrh, //!< Instruction 'stclrh'. + kIdStclrlh, //!< Instruction 'stclrlh'. + kIdSteor, //!< Instruction 'steor'. + kIdSteorl, //!< Instruction 'steorl'. + kIdSteorb, //!< Instruction 'steorb'. + kIdSteorlb, //!< Instruction 'steorlb'. + kIdSteorh, //!< Instruction 'steorh'. + kIdSteorlh, //!< Instruction 'steorlh'. + kIdStg, //!< Instruction 'stg'. + kIdStgm, //!< Instruction 'stgm'. + kIdStgp, //!< Instruction 'stgp'. + kIdStllr, //!< Instruction 'stllr'. + kIdStllrb, //!< Instruction 'stllrb'. + kIdStllrh, //!< Instruction 'stllrh'. + kIdStlr, //!< Instruction 'stlr'. + kIdStlrb, //!< Instruction 'stlrb'. + kIdStlrh, //!< Instruction 'stlrh'. + kIdStlxp, //!< Instruction 'stlxp'. + kIdStlxr, //!< Instruction 'stlxr'. + kIdStlxrb, //!< Instruction 'stlxrb'. + kIdStlxrh, //!< Instruction 'stlxrh'. + kIdStnp, //!< Instruction 'stnp'. + kIdStp, //!< Instruction 'stp'. + kIdStr, //!< Instruction 'str'. + kIdStrb, //!< Instruction 'strb'. + kIdStrh, //!< Instruction 'strh'. + kIdStset, //!< Instruction 'stset'. + kIdStsetl, //!< Instruction 'stsetl'. + kIdStsetb, //!< Instruction 'stsetb'. + kIdStsetlb, //!< Instruction 'stsetlb'. + kIdStseth, //!< Instruction 'stseth'. + kIdStsetlh, //!< Instruction 'stsetlh'. + kIdStsmax, //!< Instruction 'stsmax'. + kIdStsmaxl, //!< Instruction 'stsmaxl'. + kIdStsmaxb, //!< Instruction 'stsmaxb'. + kIdStsmaxlb, //!< Instruction 'stsmaxlb'. + kIdStsmaxh, //!< Instruction 'stsmaxh'. + kIdStsmaxlh, //!< Instruction 'stsmaxlh'. + kIdStsmin, //!< Instruction 'stsmin'. + kIdStsminl, //!< Instruction 'stsminl'. + kIdStsminb, //!< Instruction 'stsminb'. + kIdStsminlb, //!< Instruction 'stsminlb'. + kIdStsminh, //!< Instruction 'stsminh'. + kIdStsminlh, //!< Instruction 'stsminlh'. + kIdSttr, //!< Instruction 'sttr'. + kIdSttrb, //!< Instruction 'sttrb'. + kIdSttrh, //!< Instruction 'sttrh'. + kIdStumax, //!< Instruction 'stumax'. + kIdStumaxl, //!< Instruction 'stumaxl'. + kIdStumaxb, //!< Instruction 'stumaxb'. + kIdStumaxlb, //!< Instruction 'stumaxlb'. + kIdStumaxh, //!< Instruction 'stumaxh'. + kIdStumaxlh, //!< Instruction 'stumaxlh'. + kIdStumin, //!< Instruction 'stumin'. + kIdStuminl, //!< Instruction 'stuminl'. + kIdStuminb, //!< Instruction 'stuminb'. + kIdStuminlb, //!< Instruction 'stuminlb'. + kIdStuminh, //!< Instruction 'stuminh'. + kIdStuminlh, //!< Instruction 'stuminlh'. + kIdStur, //!< Instruction 'stur'. + kIdSturb, //!< Instruction 'sturb'. + kIdSturh, //!< Instruction 'sturh'. + kIdStxp, //!< Instruction 'stxp'. + kIdStxr, //!< Instruction 'stxr'. + kIdStxrb, //!< Instruction 'stxrb'. + kIdStxrh, //!< Instruction 'stxrh'. + kIdStz2g, //!< Instruction 'stz2g'. + kIdStzg, //!< Instruction 'stzg'. + kIdStzgm, //!< Instruction 'stzgm'. + kIdSub, //!< Instruction 'sub'. + kIdSubg, //!< Instruction 'subg'. + kIdSubp, //!< Instruction 'subp'. + kIdSubps, //!< Instruction 'subps'. + kIdSubs, //!< Instruction 'subs'. + kIdSvc, //!< Instruction 'svc'. + kIdSwp, //!< Instruction 'swp'. + kIdSwpa, //!< Instruction 'swpa'. + kIdSwpab, //!< Instruction 'swpab'. + kIdSwpah, //!< Instruction 'swpah'. + kIdSwpal, //!< Instruction 'swpal'. + kIdSwpalb, //!< Instruction 'swpalb'. + kIdSwpalh, //!< Instruction 'swpalh'. + kIdSwpb, //!< Instruction 'swpb'. + kIdSwph, //!< Instruction 'swph'. + kIdSwpl, //!< Instruction 'swpl'. + kIdSwplb, //!< Instruction 'swplb'. + kIdSwplh, //!< Instruction 'swplh'. + kIdSxtb, //!< Instruction 'sxtb'. + kIdSxth, //!< Instruction 'sxth'. + kIdSxtw, //!< Instruction 'sxtw'. + kIdSys, //!< Instruction 'sys'. + kIdTlbi, //!< Instruction 'tlbi'. + kIdTst, //!< Instruction 'tst'. + kIdTbnz, //!< Instruction 'tbnz'. + kIdTbz, //!< Instruction 'tbz'. + kIdUbfiz, //!< Instruction 'ubfiz'. + kIdUbfm, //!< Instruction 'ubfm'. + kIdUbfx, //!< Instruction 'ubfx'. + kIdUdf, //!< Instruction 'udf'. + kIdUdiv, //!< Instruction 'udiv'. + kIdUmaddl, //!< Instruction 'umaddl'. + kIdUmnegl, //!< Instruction 'umnegl'. + kIdUmull, //!< Instruction 'umull'. + kIdUmulh, //!< Instruction 'umulh'. + kIdUmsubl, //!< Instruction 'umsubl'. + kIdUxtb, //!< Instruction 'uxtb'. + kIdUxth, //!< Instruction 'uxth'. + kIdWfe, //!< Instruction 'wfe'. + kIdWfi, //!< Instruction 'wfi'. + kIdXaflag, //!< Instruction 'xaflag'. + kIdXpacd, //!< Instruction 'xpacd'. + kIdXpaci, //!< Instruction 'xpaci'. + kIdXpaclri, //!< Instruction 'xpaclri'. + kIdYield, //!< Instruction 'yield'. + kIdAbs_v, //!< Instruction 'abs' {ASIMD}. + kIdAdd_v, //!< Instruction 'add' {ASIMD}. + kIdAddhn_v, //!< Instruction 'addhn' {ASIMD}. + kIdAddhn2_v, //!< Instruction 'addhn2' {ASIMD}. + kIdAddp_v, //!< Instruction 'addp' {ASIMD}. + kIdAddv_v, //!< Instruction 'addv' {ASIMD}. + kIdAesd_v, //!< Instruction 'aesd' {ASIMD}. + kIdAese_v, //!< Instruction 'aese' {ASIMD}. + kIdAesimc_v, //!< Instruction 'aesimc' {ASIMD}. + kIdAesmc_v, //!< Instruction 'aesmc' {ASIMD}. + kIdAnd_v, //!< Instruction 'and' {ASIMD}. + kIdBcax_v, //!< Instruction 'bcax' {ASIMD}. + kIdBfcvt_v, //!< Instruction 'bfcvt' {ASIMD}. + kIdBfcvtn_v, //!< Instruction 'bfcvtn' {ASIMD}. + kIdBfcvtn2_v, //!< Instruction 'bfcvtn2' {ASIMD}. + kIdBfdot_v, //!< Instruction 'bfdot' {ASIMD}. + kIdBfmlalb_v, //!< Instruction 'bfmlalb' {ASIMD}. + kIdBfmlalt_v, //!< Instruction 'bfmlalt' {ASIMD}. + kIdBfmmla_v, //!< Instruction 'bfmmla' {ASIMD}. + kIdBic_v, //!< Instruction 'bic' {ASIMD}. + kIdBif_v, //!< Instruction 'bif' {ASIMD}. + kIdBit_v, //!< Instruction 'bit' {ASIMD}. + kIdBsl_v, //!< Instruction 'bsl' {ASIMD}. + kIdCls_v, //!< Instruction 'cls' {ASIMD}. + kIdClz_v, //!< Instruction 'clz' {ASIMD}. + kIdCmeq_v, //!< Instruction 'cmeq' {ASIMD}. + kIdCmge_v, //!< Instruction 'cmge' {ASIMD}. + kIdCmgt_v, //!< Instruction 'cmgt' {ASIMD}. + kIdCmhi_v, //!< Instruction 'cmhi' {ASIMD}. + kIdCmhs_v, //!< Instruction 'cmhs' {ASIMD}. + kIdCmle_v, //!< Instruction 'cmle' {ASIMD}. + kIdCmlt_v, //!< Instruction 'cmlt' {ASIMD}. + kIdCmtst_v, //!< Instruction 'cmtst' {ASIMD}. + kIdCnt_v, //!< Instruction 'cnt' {ASIMD}. + kIdDup_v, //!< Instruction 'dup' {ASIMD}. + kIdEor_v, //!< Instruction 'eor' {ASIMD}. + kIdEor3_v, //!< Instruction 'eor3' {ASIMD}. + kIdExt_v, //!< Instruction 'ext' {ASIMD}. + kIdFabd_v, //!< Instruction 'fabd' {ASIMD}. + kIdFabs_v, //!< Instruction 'fabs' {ASIMD}. + kIdFacge_v, //!< Instruction 'facge' {ASIMD}. + kIdFacgt_v, //!< Instruction 'facgt' {ASIMD}. + kIdFadd_v, //!< Instruction 'fadd' {ASIMD}. + kIdFaddp_v, //!< Instruction 'faddp' {ASIMD}. + kIdFcadd_v, //!< Instruction 'fcadd' {ASIMD}. + kIdFccmp_v, //!< Instruction 'fccmp' {ASIMD}. + kIdFccmpe_v, //!< Instruction 'fccmpe' {ASIMD}. + kIdFcmeq_v, //!< Instruction 'fcmeq' {ASIMD}. + kIdFcmge_v, //!< Instruction 'fcmge' {ASIMD}. + kIdFcmgt_v, //!< Instruction 'fcmgt' {ASIMD}. + kIdFcmla_v, //!< Instruction 'fcmla' {ASIMD}. + kIdFcmle_v, //!< Instruction 'fcmle' {ASIMD}. + kIdFcmlt_v, //!< Instruction 'fcmlt' {ASIMD}. + kIdFcmp_v, //!< Instruction 'fcmp' {ASIMD}. + kIdFcmpe_v, //!< Instruction 'fcmpe' {ASIMD}. + kIdFcsel_v, //!< Instruction 'fcsel' {ASIMD}. + kIdFcvt_v, //!< Instruction 'fcvt' {ASIMD}. + kIdFcvtas_v, //!< Instruction 'fcvtas' {ASIMD}. + kIdFcvtau_v, //!< Instruction 'fcvtau' {ASIMD}. + kIdFcvtl_v, //!< Instruction 'fcvtl' {ASIMD}. + kIdFcvtl2_v, //!< Instruction 'fcvtl2' {ASIMD}. + kIdFcvtms_v, //!< Instruction 'fcvtms' {ASIMD}. + kIdFcvtmu_v, //!< Instruction 'fcvtmu' {ASIMD}. + kIdFcvtn_v, //!< Instruction 'fcvtn' {ASIMD}. + kIdFcvtn2_v, //!< Instruction 'fcvtn2' {ASIMD}. + kIdFcvtns_v, //!< Instruction 'fcvtns' {ASIMD}. + kIdFcvtnu_v, //!< Instruction 'fcvtnu' {ASIMD}. + kIdFcvtps_v, //!< Instruction 'fcvtps' {ASIMD}. + kIdFcvtpu_v, //!< Instruction 'fcvtpu' {ASIMD}. + kIdFcvtxn_v, //!< Instruction 'fcvtxn' {ASIMD}. + kIdFcvtxn2_v, //!< Instruction 'fcvtxn2' {ASIMD}. + kIdFcvtzs_v, //!< Instruction 'fcvtzs' {ASIMD}. + kIdFcvtzu_v, //!< Instruction 'fcvtzu' {ASIMD}. + kIdFdiv_v, //!< Instruction 'fdiv' {ASIMD}. + kIdFjcvtzs_v, //!< Instruction 'fjcvtzs' {ASIMD}. + kIdFmadd_v, //!< Instruction 'fmadd' {ASIMD}. + kIdFmax_v, //!< Instruction 'fmax' {ASIMD}. + kIdFmaxnm_v, //!< Instruction 'fmaxnm' {ASIMD}. + kIdFmaxnmp_v, //!< Instruction 'fmaxnmp' {ASIMD}. + kIdFmaxnmv_v, //!< Instruction 'fmaxnmv' {ASIMD}. + kIdFmaxp_v, //!< Instruction 'fmaxp' {ASIMD}. + kIdFmaxv_v, //!< Instruction 'fmaxv' {ASIMD}. + kIdFmin_v, //!< Instruction 'fmin' {ASIMD}. + kIdFminnm_v, //!< Instruction 'fminnm' {ASIMD}. + kIdFminnmp_v, //!< Instruction 'fminnmp' {ASIMD}. + kIdFminnmv_v, //!< Instruction 'fminnmv' {ASIMD}. + kIdFminp_v, //!< Instruction 'fminp' {ASIMD}. + kIdFminv_v, //!< Instruction 'fminv' {ASIMD}. + kIdFmla_v, //!< Instruction 'fmla' {ASIMD}. + kIdFmlal_v, //!< Instruction 'fmlal' {ASIMD}. + kIdFmlal2_v, //!< Instruction 'fmlal2' {ASIMD}. + kIdFmls_v, //!< Instruction 'fmls' {ASIMD}. + kIdFmlsl_v, //!< Instruction 'fmlsl' {ASIMD}. + kIdFmlsl2_v, //!< Instruction 'fmlsl2' {ASIMD}. + kIdFmov_v, //!< Instruction 'fmov' {ASIMD}. + kIdFmsub_v, //!< Instruction 'fmsub' {ASIMD}. + kIdFmul_v, //!< Instruction 'fmul' {ASIMD}. + kIdFmulx_v, //!< Instruction 'fmulx' {ASIMD}. + kIdFneg_v, //!< Instruction 'fneg' {ASIMD}. + kIdFnmadd_v, //!< Instruction 'fnmadd' {ASIMD}. + kIdFnmsub_v, //!< Instruction 'fnmsub' {ASIMD}. + kIdFnmul_v, //!< Instruction 'fnmul' {ASIMD}. + kIdFrecpe_v, //!< Instruction 'frecpe' {ASIMD}. + kIdFrecps_v, //!< Instruction 'frecps' {ASIMD}. + kIdFrecpx_v, //!< Instruction 'frecpx' {ASIMD}. + kIdFrint32x_v, //!< Instruction 'frint32x' {ASIMD}. + kIdFrint32z_v, //!< Instruction 'frint32z' {ASIMD}. + kIdFrint64x_v, //!< Instruction 'frint64x' {ASIMD}. + kIdFrint64z_v, //!< Instruction 'frint64z' {ASIMD}. + kIdFrinta_v, //!< Instruction 'frinta' {ASIMD}. + kIdFrinti_v, //!< Instruction 'frinti' {ASIMD}. + kIdFrintm_v, //!< Instruction 'frintm' {ASIMD}. + kIdFrintn_v, //!< Instruction 'frintn' {ASIMD}. + kIdFrintp_v, //!< Instruction 'frintp' {ASIMD}. + kIdFrintx_v, //!< Instruction 'frintx' {ASIMD}. + kIdFrintz_v, //!< Instruction 'frintz' {ASIMD}. + kIdFrsqrte_v, //!< Instruction 'frsqrte' {ASIMD}. + kIdFrsqrts_v, //!< Instruction 'frsqrts' {ASIMD}. + kIdFsqrt_v, //!< Instruction 'fsqrt' {ASIMD}. + kIdFsub_v, //!< Instruction 'fsub' {ASIMD}. + kIdIns_v, //!< Instruction 'ins' {ASIMD}. + kIdLd1_v, //!< Instruction 'ld1' {ASIMD}. + kIdLd1r_v, //!< Instruction 'ld1r' {ASIMD}. + kIdLd2_v, //!< Instruction 'ld2' {ASIMD}. + kIdLd2r_v, //!< Instruction 'ld2r' {ASIMD}. + kIdLd3_v, //!< Instruction 'ld3' {ASIMD}. + kIdLd3r_v, //!< Instruction 'ld3r' {ASIMD}. + kIdLd4_v, //!< Instruction 'ld4' {ASIMD}. + kIdLd4r_v, //!< Instruction 'ld4r' {ASIMD}. + kIdLdnp_v, //!< Instruction 'ldnp' {ASIMD}. + kIdLdp_v, //!< Instruction 'ldp' {ASIMD}. + kIdLdr_v, //!< Instruction 'ldr' {ASIMD}. + kIdLdur_v, //!< Instruction 'ldur' {ASIMD}. + kIdMla_v, //!< Instruction 'mla' {ASIMD}. + kIdMls_v, //!< Instruction 'mls' {ASIMD}. + kIdMov_v, //!< Instruction 'mov' {ASIMD}. + kIdMovi_v, //!< Instruction 'movi' {ASIMD}. + kIdMul_v, //!< Instruction 'mul' {ASIMD}. + kIdMvn_v, //!< Instruction 'mvn' {ASIMD}. + kIdMvni_v, //!< Instruction 'mvni' {ASIMD}. + kIdNeg_v, //!< Instruction 'neg' {ASIMD}. + kIdNot_v, //!< Instruction 'not' {ASIMD}. + kIdOrn_v, //!< Instruction 'orn' {ASIMD}. + kIdOrr_v, //!< Instruction 'orr' {ASIMD}. + kIdPmul_v, //!< Instruction 'pmul' {ASIMD}. + kIdPmull_v, //!< Instruction 'pmull' {ASIMD}. + kIdPmull2_v, //!< Instruction 'pmull2' {ASIMD}. + kIdRaddhn_v, //!< Instruction 'raddhn' {ASIMD}. + kIdRaddhn2_v, //!< Instruction 'raddhn2' {ASIMD}. + kIdRax1_v, //!< Instruction 'rax1' {ASIMD}. + kIdRbit_v, //!< Instruction 'rbit' {ASIMD}. + kIdRev16_v, //!< Instruction 'rev16' {ASIMD}. + kIdRev32_v, //!< Instruction 'rev32' {ASIMD}. + kIdRev64_v, //!< Instruction 'rev64' {ASIMD}. + kIdRshrn_v, //!< Instruction 'rshrn' {ASIMD}. + kIdRshrn2_v, //!< Instruction 'rshrn2' {ASIMD}. + kIdRsubhn_v, //!< Instruction 'rsubhn' {ASIMD}. + kIdRsubhn2_v, //!< Instruction 'rsubhn2' {ASIMD}. + kIdSaba_v, //!< Instruction 'saba' {ASIMD}. + kIdSabal_v, //!< Instruction 'sabal' {ASIMD}. + kIdSabal2_v, //!< Instruction 'sabal2' {ASIMD}. + kIdSabd_v, //!< Instruction 'sabd' {ASIMD}. + kIdSabdl_v, //!< Instruction 'sabdl' {ASIMD}. + kIdSabdl2_v, //!< Instruction 'sabdl2' {ASIMD}. + kIdSadalp_v, //!< Instruction 'sadalp' {ASIMD}. + kIdSaddl_v, //!< Instruction 'saddl' {ASIMD}. + kIdSaddl2_v, //!< Instruction 'saddl2' {ASIMD}. + kIdSaddlp_v, //!< Instruction 'saddlp' {ASIMD}. + kIdSaddlv_v, //!< Instruction 'saddlv' {ASIMD}. + kIdSaddw_v, //!< Instruction 'saddw' {ASIMD}. + kIdSaddw2_v, //!< Instruction 'saddw2' {ASIMD}. + kIdScvtf_v, //!< Instruction 'scvtf' {ASIMD}. + kIdSdot_v, //!< Instruction 'sdot' {ASIMD}. + kIdSha1c_v, //!< Instruction 'sha1c' {ASIMD}. + kIdSha1h_v, //!< Instruction 'sha1h' {ASIMD}. + kIdSha1m_v, //!< Instruction 'sha1m' {ASIMD}. + kIdSha1p_v, //!< Instruction 'sha1p' {ASIMD}. + kIdSha1su0_v, //!< Instruction 'sha1su0' {ASIMD}. + kIdSha1su1_v, //!< Instruction 'sha1su1' {ASIMD}. + kIdSha256h_v, //!< Instruction 'sha256h' {ASIMD}. + kIdSha256h2_v, //!< Instruction 'sha256h2' {ASIMD}. + kIdSha256su0_v, //!< Instruction 'sha256su0' {ASIMD}. + kIdSha256su1_v, //!< Instruction 'sha256su1' {ASIMD}. + kIdSha512h_v, //!< Instruction 'sha512h' {ASIMD}. + kIdSha512h2_v, //!< Instruction 'sha512h2' {ASIMD}. + kIdSha512su0_v, //!< Instruction 'sha512su0' {ASIMD}. + kIdSha512su1_v, //!< Instruction 'sha512su1' {ASIMD}. + kIdShadd_v, //!< Instruction 'shadd' {ASIMD}. + kIdShl_v, //!< Instruction 'shl' {ASIMD}. + kIdShll_v, //!< Instruction 'shll' {ASIMD}. + kIdShll2_v, //!< Instruction 'shll2' {ASIMD}. + kIdShrn_v, //!< Instruction 'shrn' {ASIMD}. + kIdShrn2_v, //!< Instruction 'shrn2' {ASIMD}. + kIdShsub_v, //!< Instruction 'shsub' {ASIMD}. + kIdSli_v, //!< Instruction 'sli' {ASIMD}. + kIdSm3partw1_v, //!< Instruction 'sm3partw1' {ASIMD}. + kIdSm3partw2_v, //!< Instruction 'sm3partw2' {ASIMD}. + kIdSm3ss1_v, //!< Instruction 'sm3ss1' {ASIMD}. + kIdSm3tt1a_v, //!< Instruction 'sm3tt1a' {ASIMD}. + kIdSm3tt1b_v, //!< Instruction 'sm3tt1b' {ASIMD}. + kIdSm3tt2a_v, //!< Instruction 'sm3tt2a' {ASIMD}. + kIdSm3tt2b_v, //!< Instruction 'sm3tt2b' {ASIMD}. + kIdSm4e_v, //!< Instruction 'sm4e' {ASIMD}. + kIdSm4ekey_v, //!< Instruction 'sm4ekey' {ASIMD}. + kIdSmax_v, //!< Instruction 'smax' {ASIMD}. + kIdSmaxp_v, //!< Instruction 'smaxp' {ASIMD}. + kIdSmaxv_v, //!< Instruction 'smaxv' {ASIMD}. + kIdSmin_v, //!< Instruction 'smin' {ASIMD}. + kIdSminp_v, //!< Instruction 'sminp' {ASIMD}. + kIdSminv_v, //!< Instruction 'sminv' {ASIMD}. + kIdSmlal_v, //!< Instruction 'smlal' {ASIMD}. + kIdSmlal2_v, //!< Instruction 'smlal2' {ASIMD}. + kIdSmlsl_v, //!< Instruction 'smlsl' {ASIMD}. + kIdSmlsl2_v, //!< Instruction 'smlsl2' {ASIMD}. + kIdSmmla_v, //!< Instruction 'smmla' {ASIMD}. + kIdSmov_v, //!< Instruction 'smov' {ASIMD}. + kIdSmull_v, //!< Instruction 'smull' {ASIMD}. + kIdSmull2_v, //!< Instruction 'smull2' {ASIMD}. + kIdSqabs_v, //!< Instruction 'sqabs' {ASIMD}. + kIdSqadd_v, //!< Instruction 'sqadd' {ASIMD}. + kIdSqdmlal_v, //!< Instruction 'sqdmlal' {ASIMD}. + kIdSqdmlal2_v, //!< Instruction 'sqdmlal2' {ASIMD}. + kIdSqdmlsl_v, //!< Instruction 'sqdmlsl' {ASIMD}. + kIdSqdmlsl2_v, //!< Instruction 'sqdmlsl2' {ASIMD}. + kIdSqdmulh_v, //!< Instruction 'sqdmulh' {ASIMD}. + kIdSqdmull_v, //!< Instruction 'sqdmull' {ASIMD}. + kIdSqdmull2_v, //!< Instruction 'sqdmull2' {ASIMD}. + kIdSqneg_v, //!< Instruction 'sqneg' {ASIMD}. + kIdSqrdmlah_v, //!< Instruction 'sqrdmlah' {ASIMD}. + kIdSqrdmlsh_v, //!< Instruction 'sqrdmlsh' {ASIMD}. + kIdSqrdmulh_v, //!< Instruction 'sqrdmulh' {ASIMD}. + kIdSqrshl_v, //!< Instruction 'sqrshl' {ASIMD}. + kIdSqrshrn_v, //!< Instruction 'sqrshrn' {ASIMD}. + kIdSqrshrn2_v, //!< Instruction 'sqrshrn2' {ASIMD}. + kIdSqrshrun_v, //!< Instruction 'sqrshrun' {ASIMD}. + kIdSqrshrun2_v, //!< Instruction 'sqrshrun2' {ASIMD}. + kIdSqshl_v, //!< Instruction 'sqshl' {ASIMD}. + kIdSqshlu_v, //!< Instruction 'sqshlu' {ASIMD}. + kIdSqshrn_v, //!< Instruction 'sqshrn' {ASIMD}. + kIdSqshrn2_v, //!< Instruction 'sqshrn2' {ASIMD}. + kIdSqshrun_v, //!< Instruction 'sqshrun' {ASIMD}. + kIdSqshrun2_v, //!< Instruction 'sqshrun2' {ASIMD}. + kIdSqsub_v, //!< Instruction 'sqsub' {ASIMD}. + kIdSqxtn_v, //!< Instruction 'sqxtn' {ASIMD}. + kIdSqxtn2_v, //!< Instruction 'sqxtn2' {ASIMD}. + kIdSqxtun_v, //!< Instruction 'sqxtun' {ASIMD}. + kIdSqxtun2_v, //!< Instruction 'sqxtun2' {ASIMD}. + kIdSrhadd_v, //!< Instruction 'srhadd' {ASIMD}. + kIdSri_v, //!< Instruction 'sri' {ASIMD}. + kIdSrshl_v, //!< Instruction 'srshl' {ASIMD}. + kIdSrshr_v, //!< Instruction 'srshr' {ASIMD}. + kIdSrsra_v, //!< Instruction 'srsra' {ASIMD}. + kIdSshl_v, //!< Instruction 'sshl' {ASIMD}. + kIdSshll_v, //!< Instruction 'sshll' {ASIMD}. + kIdSshll2_v, //!< Instruction 'sshll2' {ASIMD}. + kIdSshr_v, //!< Instruction 'sshr' {ASIMD}. + kIdSsra_v, //!< Instruction 'ssra' {ASIMD}. + kIdSsubl_v, //!< Instruction 'ssubl' {ASIMD}. + kIdSsubl2_v, //!< Instruction 'ssubl2' {ASIMD}. + kIdSsubw_v, //!< Instruction 'ssubw' {ASIMD}. + kIdSsubw2_v, //!< Instruction 'ssubw2' {ASIMD}. + kIdSt1_v, //!< Instruction 'st1' {ASIMD}. + kIdSt2_v, //!< Instruction 'st2' {ASIMD}. + kIdSt3_v, //!< Instruction 'st3' {ASIMD}. + kIdSt4_v, //!< Instruction 'st4' {ASIMD}. + kIdStnp_v, //!< Instruction 'stnp' {ASIMD}. + kIdStp_v, //!< Instruction 'stp' {ASIMD}. + kIdStr_v, //!< Instruction 'str' {ASIMD}. + kIdStur_v, //!< Instruction 'stur' {ASIMD}. + kIdSub_v, //!< Instruction 'sub' {ASIMD}. + kIdSubhn_v, //!< Instruction 'subhn' {ASIMD}. + kIdSubhn2_v, //!< Instruction 'subhn2' {ASIMD}. + kIdSudot_v, //!< Instruction 'sudot' {ASIMD}. + kIdSuqadd_v, //!< Instruction 'suqadd' {ASIMD}. + kIdSxtl_v, //!< Instruction 'sxtl' {ASIMD}. + kIdSxtl2_v, //!< Instruction 'sxtl2' {ASIMD}. + kIdTbl_v, //!< Instruction 'tbl' {ASIMD}. + kIdTbx_v, //!< Instruction 'tbx' {ASIMD}. + kIdTrn1_v, //!< Instruction 'trn1' {ASIMD}. + kIdTrn2_v, //!< Instruction 'trn2' {ASIMD}. + kIdUaba_v, //!< Instruction 'uaba' {ASIMD}. + kIdUabal_v, //!< Instruction 'uabal' {ASIMD}. + kIdUabal2_v, //!< Instruction 'uabal2' {ASIMD}. + kIdUabd_v, //!< Instruction 'uabd' {ASIMD}. + kIdUabdl_v, //!< Instruction 'uabdl' {ASIMD}. + kIdUabdl2_v, //!< Instruction 'uabdl2' {ASIMD}. + kIdUadalp_v, //!< Instruction 'uadalp' {ASIMD}. + kIdUaddl_v, //!< Instruction 'uaddl' {ASIMD}. + kIdUaddl2_v, //!< Instruction 'uaddl2' {ASIMD}. + kIdUaddlp_v, //!< Instruction 'uaddlp' {ASIMD}. + kIdUaddlv_v, //!< Instruction 'uaddlv' {ASIMD}. + kIdUaddw_v, //!< Instruction 'uaddw' {ASIMD}. + kIdUaddw2_v, //!< Instruction 'uaddw2' {ASIMD}. + kIdUcvtf_v, //!< Instruction 'ucvtf' {ASIMD}. + kIdUdot_v, //!< Instruction 'udot' {ASIMD}. + kIdUhadd_v, //!< Instruction 'uhadd' {ASIMD}. + kIdUhsub_v, //!< Instruction 'uhsub' {ASIMD}. + kIdUmax_v, //!< Instruction 'umax' {ASIMD}. + kIdUmaxp_v, //!< Instruction 'umaxp' {ASIMD}. + kIdUmaxv_v, //!< Instruction 'umaxv' {ASIMD}. + kIdUmin_v, //!< Instruction 'umin' {ASIMD}. + kIdUminp_v, //!< Instruction 'uminp' {ASIMD}. + kIdUminv_v, //!< Instruction 'uminv' {ASIMD}. + kIdUmlal_v, //!< Instruction 'umlal' {ASIMD}. + kIdUmlal2_v, //!< Instruction 'umlal2' {ASIMD}. + kIdUmlsl_v, //!< Instruction 'umlsl' {ASIMD}. + kIdUmlsl2_v, //!< Instruction 'umlsl2' {ASIMD}. + kIdUmmla_v, //!< Instruction 'ummla' {ASIMD}. + kIdUmov_v, //!< Instruction 'umov' {ASIMD}. + kIdUmull_v, //!< Instruction 'umull' {ASIMD}. + kIdUmull2_v, //!< Instruction 'umull2' {ASIMD}. + kIdUqadd_v, //!< Instruction 'uqadd' {ASIMD}. + kIdUqrshl_v, //!< Instruction 'uqrshl' {ASIMD}. + kIdUqrshrn_v, //!< Instruction 'uqrshrn' {ASIMD}. + kIdUqrshrn2_v, //!< Instruction 'uqrshrn2' {ASIMD}. + kIdUqshl_v, //!< Instruction 'uqshl' {ASIMD}. + kIdUqshrn_v, //!< Instruction 'uqshrn' {ASIMD}. + kIdUqshrn2_v, //!< Instruction 'uqshrn2' {ASIMD}. + kIdUqsub_v, //!< Instruction 'uqsub' {ASIMD}. + kIdUqxtn_v, //!< Instruction 'uqxtn' {ASIMD}. + kIdUqxtn2_v, //!< Instruction 'uqxtn2' {ASIMD}. + kIdUrecpe_v, //!< Instruction 'urecpe' {ASIMD}. + kIdUrhadd_v, //!< Instruction 'urhadd' {ASIMD}. + kIdUrshl_v, //!< Instruction 'urshl' {ASIMD}. + kIdUrshr_v, //!< Instruction 'urshr' {ASIMD}. + kIdUrsqrte_v, //!< Instruction 'ursqrte' {ASIMD}. + kIdUrsra_v, //!< Instruction 'ursra' {ASIMD}. + kIdUsdot_v, //!< Instruction 'usdot' {ASIMD}. + kIdUshl_v, //!< Instruction 'ushl' {ASIMD}. + kIdUshll_v, //!< Instruction 'ushll' {ASIMD}. + kIdUshll2_v, //!< Instruction 'ushll2' {ASIMD}. + kIdUshr_v, //!< Instruction 'ushr' {ASIMD}. + kIdUsmmla_v, //!< Instruction 'usmmla' {ASIMD}. + kIdUsqadd_v, //!< Instruction 'usqadd' {ASIMD}. + kIdUsra_v, //!< Instruction 'usra' {ASIMD}. + kIdUsubl_v, //!< Instruction 'usubl' {ASIMD}. + kIdUsubl2_v, //!< Instruction 'usubl2' {ASIMD}. + kIdUsubw_v, //!< Instruction 'usubw' {ASIMD}. + kIdUsubw2_v, //!< Instruction 'usubw2' {ASIMD}. + kIdUxtl_v, //!< Instruction 'uxtl' {ASIMD}. + kIdUxtl2_v, //!< Instruction 'uxtl2' {ASIMD}. + kIdUzp1_v, //!< Instruction 'uzp1' {ASIMD}. + kIdUzp2_v, //!< Instruction 'uzp2' {ASIMD}. + kIdXar_v, //!< Instruction 'xar' {ASIMD}. + kIdXtn_v, //!< Instruction 'xtn' {ASIMD}. + kIdXtn2_v, //!< Instruction 'xtn2' {ASIMD}. + kIdZip1_v, //!< Instruction 'zip1' {ASIMD}. + kIdZip2_v, //!< Instruction 'zip2' {ASIMD}. + _kIdCount + // ${InstId:End} + }; + + //! Tests whether the `instId` is defined (counts also Inst::kIdNone, which must be zero). + static inline bool isDefinedId(InstId instId) noexcept { return (instId & uint32_t(InstIdParts::kRealId)) < _kIdCount; } +}; + +namespace Predicate { + +//! Address translate options (AT). +namespace AT { + static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { + return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0); + } + + enum Value : uint32_t { + kS1E1R = encode(0b000, 0b0111, 0b1000, 0b000), + kS1E2R = encode(0b100, 0b0111, 0b1000, 0b000), + kS1E3R = encode(0b110, 0b0111, 0b1000, 0b000), + kS1E1W = encode(0b000, 0b0111, 0b1000, 0b001), + kS1E2W = encode(0b100, 0b0111, 0b1000, 0b001), + kS1E3W = encode(0b110, 0b0111, 0b1000, 0b001), + kS1E0R = encode(0b000, 0b0111, 0b1000, 0b010), + kS1E0W = encode(0b000, 0b0111, 0b1000, 0b011), + kS12E1R = encode(0b100, 0b0111, 0b1000, 0b100), + kS12E1W = encode(0b100, 0b0111, 0b1000, 0b101), + kS12E0R = encode(0b100, 0b0111, 0b1000, 0b110), + kS12E0W = encode(0b100, 0b0111, 0b1000, 0b111), + kS1E1RP = encode(0b000, 0b0111, 0b1001, 0b000), + kS1E1WP = encode(0b000, 0b0111, 0b1001, 0b001) + }; +} + +//! Data barrier options (DMB/DSB). +namespace DB { + //! Data barrier immediate values. + enum Value : uint32_t { + //! Waits only for loads to complete, and only applies to the outer shareable domain. + kOSHLD = 0x01u, + //! Waits only for stores to complete, and only applies to the outer shareable domain. + kOSHST = 0x02u, + //! Only applies to the outer shareable domain. + kOSH = 0x03u, + + //! Waits only for loads to complete and only applies out to the point of unification. + kNSHLD = 0x05u, + //! Waits only for stores to complete and only applies out to the point of unification. + kNSHST = 0x06u, + //! Only applies out to the point of unification. + kNSH = 0x07u, + + //! Waits only for loads to complete, and only applies to the inner shareable domain. + kISHLD = 0x09u, + //! Waits only for stores to complete, and only applies to the inner shareable domain. + kISHST = 0x0Au, + //! Only applies to the inner shareable domain. + kISH = 0x0Bu, + + //! Waits only for loads to complete. + kLD = 0x0Du, + //! Waits only for stores to complete. + kST = 0x0Eu, + //! Full system memory barrier operation. + kSY = 0x0Fu + }; +} + +//! Data cache maintenance options. +namespace DC { + static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { + return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0); + } + + //! Data cache maintenance immediate values. + enum Value : uint32_t { + kZVA = encode(0b011, 0b0111, 0b0100, 0b001), + kIVAC = encode(0b000, 0b0111, 0b0110, 0b001), + kISW = encode(0b000, 0b0111, 0b0110, 0b010), + kCVAC = encode(0b011, 0b0111, 0b1010, 0b001), + kCSW = encode(0b000, 0b0111, 0b1010, 0b010), + kCVAU = encode(0b011, 0b0111, 0b1011, 0b001), + kCIVAC = encode(0b011, 0b0111, 0b1110, 0b001), + kCISW = encode(0b000, 0b0111, 0b1110, 0b010), + kCVAP = encode(0b011, 0b0111, 0b1100, 0b001), + kCVADP = encode(0b011, 0b0111, 0b1101, 0b001), + kIGVAC = encode(0b000, 0b0111, 0b0110, 0b011), + kIGSW = encode(0b000, 0b0111, 0b0110, 0b100), + kCGSW = encode(0b000, 0b0111, 0b1010, 0b100), + kCIGSW = encode(0b000, 0b0111, 0b1110, 0b100), + kCGVAC = encode(0b011, 0b0111, 0b1010, 0b011), + kCGVAP = encode(0b011, 0b0111, 0b1100, 0b011), + kCGVADP = encode(0b011, 0b0111, 0b1101, 0b011), + kCIGVAC = encode(0b011, 0b0111, 0b1110, 0b011), + kGVA = encode(0b011, 0b0111, 0b0100, 0b011), + kIGDVAC = encode(0b000, 0b0111, 0b0110, 0b101), + kIGDSW = encode(0b000, 0b0111, 0b0110, 0b110), + kCGDSW = encode(0b000, 0b0111, 0b1010, 0b110), + kCIGDSW = encode(0b000, 0b0111, 0b1110, 0b110), + kCGDVAC = encode(0b011, 0b0111, 0b1010, 0b101), + kCGDVAP = encode(0b011, 0b0111, 0b1100, 0b101), + kCGDVADP = encode(0b011, 0b0111, 0b1101, 0b101), + kCIGDVAC = encode(0b011, 0b0111, 0b1110, 0b101), + kGZVA = encode(0b011, 0b0111, 0b0100, 0b100) + }; +} + +//! Instruction cache maintenance options. +namespace IC { + static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { + return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0); + } + + //! Instruction cache maintenance immediate values. + enum Value : uint32_t { + kIALLUIS = encode(0b000, 0b0111, 0b0001, 0b000), + kIALLU = encode(0b000, 0b0111, 0b0101, 0b000), + kIVAU = encode(0b011, 0b0111, 0b0101, 0b001) + }; +} + +//! Instruction-fetch barrier options. +namespace ISB { + //! Instruction-fetch barrier immediate values. + enum Value : uint32_t { + kSY = 0xF + }; +} + +//! Prefetch options. +namespace PRFOp { + //! Prefetch immediate values. + enum Value : uint32_t { + kPLDL1KEEP = 0x00, + kPLDL1STRM = 0x01, + kPLDL2KEEP = 0x02, + kPLDL2STRM = 0x03, + kPLDL3KEEP = 0x04, + kPLDL3STRM = 0x05, + kPLIL1KEEP = 0x08, + kPLIL1STRM = 0x09, + kPLIL2KEEP = 0x0A, + kPLIL2STRM = 0x0B, + kPLIL3KEEP = 0x0C, + kPLIL3STRM = 0x0D, + kPSTL1KEEP = 0x10, + kPSTL1STRM = 0x11, + kPSTL2KEEP = 0x12, + kPSTL2STRM = 0x13, + kPSTL3KEEP = 0x14, + kPSTL3STRM = 0x15 + }; +} + +//! PSB instruction options. +namespace PSB { + //! PSB immediate values. + enum Value : uint32_t { + kCSYNC = 0x11u + }; +} + +namespace TLBI { + static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { + return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0); + } + + enum Value : uint32_t { + kIPAS2E1IS = encode(0b100, 0b1000, 0b0000, 0b001), + kIPAS2LE1IS = encode(0b100, 0b1000, 0b0000, 0b101), + kVMALLE1IS = encode(0b000, 0b1000, 0b0011, 0b000), + kALLE2IS = encode(0b100, 0b1000, 0b0011, 0b000), + kALLE3IS = encode(0b110, 0b1000, 0b0011, 0b000), + kVAE1IS = encode(0b000, 0b1000, 0b0011, 0b001), + kVAE2IS = encode(0b100, 0b1000, 0b0011, 0b001), + kVAE3IS = encode(0b110, 0b1000, 0b0011, 0b001), + kASIDE1IS = encode(0b000, 0b1000, 0b0011, 0b010), + kVAAE1IS = encode(0b000, 0b1000, 0b0011, 0b011), + kALLE1IS = encode(0b100, 0b1000, 0b0011, 0b100), + kVALE1IS = encode(0b000, 0b1000, 0b0011, 0b101), + kVALE2IS = encode(0b100, 0b1000, 0b0011, 0b101), + kVALE3IS = encode(0b110, 0b1000, 0b0011, 0b101), + kVMALLS12E1IS = encode(0b100, 0b1000, 0b0011, 0b110), + kVAALE1IS = encode(0b000, 0b1000, 0b0011, 0b111), + kIPAS2E1 = encode(0b100, 0b1000, 0b0100, 0b001), + kIPAS2LE1 = encode(0b100, 0b1000, 0b0100, 0b101), + kVMALLE1 = encode(0b000, 0b1000, 0b0111, 0b000), + kALLE2 = encode(0b100, 0b1000, 0b0111, 0b000), + kALLE3 = encode(0b110, 0b1000, 0b0111, 0b000), + kVAE1 = encode(0b000, 0b1000, 0b0111, 0b001), + kVAE2 = encode(0b100, 0b1000, 0b0111, 0b001), + kVAE3 = encode(0b110, 0b1000, 0b0111, 0b001), + kASIDE1 = encode(0b000, 0b1000, 0b0111, 0b010), + kVAAE1 = encode(0b000, 0b1000, 0b0111, 0b011), + kALLE1 = encode(0b100, 0b1000, 0b0111, 0b100), + kVALE1 = encode(0b000, 0b1000, 0b0111, 0b101), + kVALE2 = encode(0b100, 0b1000, 0b0111, 0b101), + kVALE3 = encode(0b110, 0b1000, 0b0111, 0b101), + kVMALLS12E1 = encode(0b100, 0b1000, 0b0111, 0b110), + kVAALE1 = encode(0b000, 0b1000, 0b0111, 0b111), + + kVMALLE1OS = encode(0b000, 0b1000, 0b0001, 0b000), + kVAE1OS = encode(0b000, 0b1000, 0b0001, 0b001), + kASIDE1OS = encode(0b000, 0b1000, 0b0001, 0b010), + kVAAE1OS = encode(0b000, 0b1000, 0b0001, 0b011), + kVALE1OS = encode(0b000, 0b1000, 0b0001, 0b101), + kVAALE1OS = encode(0b000, 0b1000, 0b0001, 0b111), + kIPAS2E1OS = encode(0b100, 0b1000, 0b0100, 0b000), + kIPAS2LE1OS = encode(0b100, 0b1000, 0b0100, 0b100), + kVAE2OS = encode(0b100, 0b1000, 0b0001, 0b001), + kVALE2OS = encode(0b100, 0b1000, 0b0001, 0b101), + kVMALLS12E1OS = encode(0b100, 0b1000, 0b0001, 0b110), + kVAE3OS = encode(0b110, 0b1000, 0b0001, 0b001), + kVALE3OS = encode(0b110, 0b1000, 0b0001, 0b101), + kALLE2OS = encode(0b100, 0b1000, 0b0001, 0b000), + kALLE1OS = encode(0b100, 0b1000, 0b0001, 0b100), + kALLE3OS = encode(0b110, 0b1000, 0b0001, 0b000), + + kRVAE1 = encode(0b000, 0b1000, 0b0110, 0b001), + kRVAAE1 = encode(0b000, 0b1000, 0b0110, 0b011), + kRVALE1 = encode(0b000, 0b1000, 0b0110, 0b101), + kRVAALE1 = encode(0b000, 0b1000, 0b0110, 0b111), + kRVAE1IS = encode(0b000, 0b1000, 0b0010, 0b001), + kRVAAE1IS = encode(0b000, 0b1000, 0b0010, 0b011), + kRVALE1IS = encode(0b000, 0b1000, 0b0010, 0b101), + kRVAALE1IS = encode(0b000, 0b1000, 0b0010, 0b111), + kRVAE1OS = encode(0b000, 0b1000, 0b0101, 0b001), + kRVAAE1OS = encode(0b000, 0b1000, 0b0101, 0b011), + kRVALE1OS = encode(0b000, 0b1000, 0b0101, 0b101), + kRVAALE1OS = encode(0b000, 0b1000, 0b0101, 0b111), + kRIPAS2E1IS = encode(0b100, 0b1000, 0b0000, 0b010), + kRIPAS2LE1IS = encode(0b100, 0b1000, 0b0000, 0b110), + kRIPAS2E1 = encode(0b100, 0b1000, 0b0100, 0b010), + kRIPAS2LE1 = encode(0b100, 0b1000, 0b0100, 0b110), + kRIPAS2E1OS = encode(0b100, 0b1000, 0b0100, 0b011), + kRIPAS2LE1OS = encode(0b100, 0b1000, 0b0100, 0b111), + kRVAE2 = encode(0b100, 0b1000, 0b0110, 0b001), + kRVALE2 = encode(0b100, 0b1000, 0b0110, 0b101), + kRVAE2IS = encode(0b100, 0b1000, 0b0010, 0b001), + kRVALE2IS = encode(0b100, 0b1000, 0b0010, 0b101), + kRVAE2OS = encode(0b100, 0b1000, 0b0101, 0b001), + kRVALE2OS = encode(0b100, 0b1000, 0b0101, 0b101), + kRVAE3 = encode(0b110, 0b1000, 0b0110, 0b001), + kRVALE3 = encode(0b110, 0b1000, 0b0110, 0b101), + kRVAE3IS = encode(0b110, 0b1000, 0b0010, 0b001), + kRVALE3IS = encode(0b110, 0b1000, 0b0010, 0b101), + kRVAE3OS = encode(0b110, 0b1000, 0b0101, 0b001), + kRVALE3OS = encode(0b110, 0b1000, 0b0101, 0b101), + }; +} + +//! Trace synchronization barrier options. +namespace TSB { + //! Trace synchronization immediate values. + enum Value : uint32_t { + kCSYNC = 0 + }; +} + +//! Processor state access through MSR. +namespace PState { + //! Encodes a pstate from `op0` and `op1`. + static inline constexpr uint32_t encode(uint32_t op0, uint32_t op1) noexcept { + return (op0 << 3) | (op1 << 0); + } + + //! Processor state access immediates. + enum Value : uint32_t { + kSPSel = encode(0b000, 0b101), + kDAIFSet = encode(0b011, 0b110), + kDAIFClr = encode(0b011, 0b111), + kPAN = encode(0b000, 0b100), + kUAO = encode(0b000, 0b011), + kDIT = encode(0b011, 0b010), + kSSBS = encode(0b011, 0b001), + kTCO = encode(0b011, 0b100) + }; +}; + +//! System register identifiers and utilities (MSR/MRS). +namespace SysReg { + //! System register fields. + struct Fields { + uint8_t op0; + uint8_t op1; + uint8_t cRn; + uint8_t cRm; + uint8_t op2; + }; + + //! Encodes a system register from `op0`, `op1`, `cRn`, `cRm`, and `op2` fields. + static inline constexpr uint32_t encode(uint32_t op0, uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept { + return (op0 << 14) | (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0); + } + + //! Encodes a system register from `fields`. + static inline constexpr uint32_t encode(const Fields& fields) noexcept { + return encode(fields.op0, fields.op1, fields.cRn, fields.cRm, fields.op2); + } + + //! Decodes a system register to \ref Fields. + static inline constexpr Fields decode(uint32_t id) noexcept { + return Fields { + uint8_t((id >> 14) & 0x3u), + uint8_t((id >> 11) & 0x7u), + uint8_t((id >> 7) & 0xFu), + uint8_t((id >> 3) & 0xFu), + uint8_t((id >> 0) & 0x7u) + }; + } + + //! System register identifiers. + enum Id : uint32_t { + kACTLR_EL1 = encode(0b11, 0b000, 0b0001, 0b0000, 0b001), // RW + kACTLR_EL2 = encode(0b11, 0b100, 0b0001, 0b0000, 0b001), // RW + kACTLR_EL3 = encode(0b11, 0b110, 0b0001, 0b0000, 0b001), // RW + kAFSR0_EL1 = encode(0b11, 0b000, 0b0101, 0b0001, 0b000), // RW + kAFSR0_EL12 = encode(0b11, 0b101, 0b0101, 0b0001, 0b000), // RW + kAFSR0_EL2 = encode(0b11, 0b100, 0b0101, 0b0001, 0b000), // RW + kAFSR0_EL3 = encode(0b11, 0b110, 0b0101, 0b0001, 0b000), // RW + kAFSR1_EL1 = encode(0b11, 0b000, 0b0101, 0b0001, 0b001), // RW + kAFSR1_EL12 = encode(0b11, 0b101, 0b0101, 0b0001, 0b001), // RW + kAFSR1_EL2 = encode(0b11, 0b100, 0b0101, 0b0001, 0b001), // RW + kAFSR1_EL3 = encode(0b11, 0b110, 0b0101, 0b0001, 0b001), // RW + kAIDR_EL1 = encode(0b11, 0b001, 0b0000, 0b0000, 0b111), // RO + kAMAIR_EL1 = encode(0b11, 0b000, 0b1010, 0b0011, 0b000), // RW + kAMAIR_EL12 = encode(0b11, 0b101, 0b1010, 0b0011, 0b000), // RW + kAMAIR_EL2 = encode(0b11, 0b100, 0b1010, 0b0011, 0b000), // RW + kAMAIR_EL3 = encode(0b11, 0b110, 0b1010, 0b0011, 0b000), // RW + kAMCFGR_EL0 = encode(0b11, 0b011, 0b1101, 0b0010, 0b001), // RO + kAMCGCR_EL0 = encode(0b11, 0b011, 0b1101, 0b0010, 0b010), // RO + kAMCNTENCLR0_EL0 = encode(0b11, 0b011, 0b1101, 0b0010, 0b100), // RW + kAMCNTENCLR1_EL0 = encode(0b11, 0b011, 0b1101, 0b0011, 0b000), // RW + kAMCNTENSET0_EL0 = encode(0b11, 0b011, 0b1101, 0b0010, 0b101), // RW + kAMCNTENSET1_EL0 = encode(0b11, 0b011, 0b1101, 0b0011, 0b001), // RW + kAMCR_EL0 = encode(0b11, 0b011, 0b1101, 0b0010, 0b000), // RW + kAMEVCNTR00_EL0 = encode(0b11, 0b011, 0b1101, 0b0100, 0b000), // RW + kAMEVCNTR01_EL0 = encode(0b11, 0b011, 0b1101, 0b0100, 0b001), // RW + kAMEVCNTR02_EL0 = encode(0b11, 0b011, 0b1101, 0b0100, 0b010), // RW + kAMEVCNTR03_EL0 = encode(0b11, 0b011, 0b1101, 0b0100, 0b011), // RW + kAMEVCNTR10_EL0 = encode(0b11, 0b011, 0b1101, 0b1100, 0b000), // RW + kAMEVCNTR110_EL0 = encode(0b11, 0b011, 0b1101, 0b1101, 0b010), // RW + kAMEVCNTR111_EL0 = encode(0b11, 0b011, 0b1101, 0b1101, 0b011), // RW + kAMEVCNTR112_EL0 = encode(0b11, 0b011, 0b1101, 0b1101, 0b100), // RW + kAMEVCNTR113_EL0 = encode(0b11, 0b011, 0b1101, 0b1101, 0b101), // RW + kAMEVCNTR114_EL0 = encode(0b11, 0b011, 0b1101, 0b1101, 0b110), // RW + kAMEVCNTR115_EL0 = encode(0b11, 0b011, 0b1101, 0b1101, 0b111), // RW + kAMEVCNTR11_EL0 = encode(0b11, 0b011, 0b1101, 0b1100, 0b001), // RW + kAMEVCNTR12_EL0 = encode(0b11, 0b011, 0b1101, 0b1100, 0b010), // RW + kAMEVCNTR13_EL0 = encode(0b11, 0b011, 0b1101, 0b1100, 0b011), // RW + kAMEVCNTR14_EL0 = encode(0b11, 0b011, 0b1101, 0b1100, 0b100), // RW + kAMEVCNTR15_EL0 = encode(0b11, 0b011, 0b1101, 0b1100, 0b101), // RW + kAMEVCNTR16_EL0 = encode(0b11, 0b011, 0b1101, 0b1100, 0b110), // RW + kAMEVCNTR17_EL0 = encode(0b11, 0b011, 0b1101, 0b1100, 0b111), // RW + kAMEVCNTR18_EL0 = encode(0b11, 0b011, 0b1101, 0b1101, 0b000), // RW + kAMEVCNTR19_EL0 = encode(0b11, 0b011, 0b1101, 0b1101, 0b001), // RW + kAMEVTYPER00_EL0 = encode(0b11, 0b011, 0b1101, 0b0110, 0b000), // RO + kAMEVTYPER01_EL0 = encode(0b11, 0b011, 0b1101, 0b0110, 0b001), // RO + kAMEVTYPER02_EL0 = encode(0b11, 0b011, 0b1101, 0b0110, 0b010), // RO + kAMEVTYPER03_EL0 = encode(0b11, 0b011, 0b1101, 0b0110, 0b011), // RO + kAMEVTYPER10_EL0 = encode(0b11, 0b011, 0b1101, 0b1110, 0b000), // RW + kAMEVTYPER110_EL0 = encode(0b11, 0b011, 0b1101, 0b1111, 0b010), // RW + kAMEVTYPER111_EL0 = encode(0b11, 0b011, 0b1101, 0b1111, 0b011), // RW + kAMEVTYPER112_EL0 = encode(0b11, 0b011, 0b1101, 0b1111, 0b100), // RW + kAMEVTYPER113_EL0 = encode(0b11, 0b011, 0b1101, 0b1111, 0b101), // RW + kAMEVTYPER114_EL0 = encode(0b11, 0b011, 0b1101, 0b1111, 0b110), // RW + kAMEVTYPER115_EL0 = encode(0b11, 0b011, 0b1101, 0b1111, 0b111), // RW + kAMEVTYPER11_EL0 = encode(0b11, 0b011, 0b1101, 0b1110, 0b001), // RW + kAMEVTYPER12_EL0 = encode(0b11, 0b011, 0b1101, 0b1110, 0b010), // RW + kAMEVTYPER13_EL0 = encode(0b11, 0b011, 0b1101, 0b1110, 0b011), // RW + kAMEVTYPER14_EL0 = encode(0b11, 0b011, 0b1101, 0b1110, 0b100), // RW + kAMEVTYPER15_EL0 = encode(0b11, 0b011, 0b1101, 0b1110, 0b101), // RW + kAMEVTYPER16_EL0 = encode(0b11, 0b011, 0b1101, 0b1110, 0b110), // RW + kAMEVTYPER17_EL0 = encode(0b11, 0b011, 0b1101, 0b1110, 0b111), // RW + kAMEVTYPER18_EL0 = encode(0b11, 0b011, 0b1101, 0b1111, 0b000), // RW + kAMEVTYPER19_EL0 = encode(0b11, 0b011, 0b1101, 0b1111, 0b001), // RW + kAMUSERENR_EL0 = encode(0b11, 0b011, 0b1101, 0b0010, 0b011), // RW + kAPDAKeyHi_EL1 = encode(0b11, 0b000, 0b0010, 0b0010, 0b001), // RW + kAPDAKeyLo_EL1 = encode(0b11, 0b000, 0b0010, 0b0010, 0b000), // RW + kAPDBKeyHi_EL1 = encode(0b11, 0b000, 0b0010, 0b0010, 0b011), // RW + kAPDBKeyLo_EL1 = encode(0b11, 0b000, 0b0010, 0b0010, 0b010), // RW + kAPGAKeyHi_EL1 = encode(0b11, 0b000, 0b0010, 0b0011, 0b001), // RW + kAPGAKeyLo_EL1 = encode(0b11, 0b000, 0b0010, 0b0011, 0b000), // RW + kAPIAKeyHi_EL1 = encode(0b11, 0b000, 0b0010, 0b0001, 0b001), // RW + kAPIAKeyLo_EL1 = encode(0b11, 0b000, 0b0010, 0b0001, 0b000), // RW + kAPIBKeyHi_EL1 = encode(0b11, 0b000, 0b0010, 0b0001, 0b011), // RW + kAPIBKeyLo_EL1 = encode(0b11, 0b000, 0b0010, 0b0001, 0b010), // RW + kCCSIDR2_EL1 = encode(0b11, 0b001, 0b0000, 0b0000, 0b010), // RO + kCCSIDR_EL1 = encode(0b11, 0b001, 0b0000, 0b0000, 0b000), // RO + kCLIDR_EL1 = encode(0b11, 0b001, 0b0000, 0b0000, 0b001), // RO + kCNTFRQ_EL0 = encode(0b11, 0b011, 0b1110, 0b0000, 0b000), // RW + kCNTHCTL_EL2 = encode(0b11, 0b100, 0b1110, 0b0001, 0b000), // RW + kCNTHPS_CTL_EL2 = encode(0b11, 0b100, 0b1110, 0b0101, 0b001), // RW + kCNTHPS_CVAL_EL2 = encode(0b11, 0b100, 0b1110, 0b0101, 0b010), // RW + kCNTHPS_TVAL_EL2 = encode(0b11, 0b100, 0b1110, 0b0101, 0b000), // RW + kCNTHP_CTL_EL2 = encode(0b11, 0b100, 0b1110, 0b0010, 0b001), // RW + kCNTHP_CVAL_EL2 = encode(0b11, 0b100, 0b1110, 0b0010, 0b010), // RW + kCNTHP_TVAL_EL2 = encode(0b11, 0b100, 0b1110, 0b0010, 0b000), // RW + kCNTHVS_CTL_EL2 = encode(0b11, 0b100, 0b1110, 0b0100, 0b001), // RW + kCNTHVS_CVAL_EL2 = encode(0b11, 0b100, 0b1110, 0b0100, 0b010), // RW + kCNTHVS_TVAL_EL2 = encode(0b11, 0b100, 0b1110, 0b0100, 0b000), // RW + kCNTHV_CTL_EL2 = encode(0b11, 0b100, 0b1110, 0b0011, 0b001), // RW + kCNTHV_CVAL_EL2 = encode(0b11, 0b100, 0b1110, 0b0011, 0b010), // RW + kCNTHV_TVAL_EL2 = encode(0b11, 0b100, 0b1110, 0b0011, 0b000), // RW + kCNTISCALE_EL2 = encode(0b11, 0b100, 0b1110, 0b0000, 0b101), // RW + kCNTKCTL_EL1 = encode(0b11, 0b000, 0b1110, 0b0001, 0b000), // RW + kCNTKCTL_EL12 = encode(0b11, 0b101, 0b1110, 0b0001, 0b000), // RW + kCNTPCTSS_EL0 = encode(0b11, 0b011, 0b1110, 0b0000, 0b101), // RW + kCNTPCT_EL0 = encode(0b11, 0b011, 0b1110, 0b0000, 0b001), // RO + kCNTPOFF_EL2 = encode(0b11, 0b100, 0b1110, 0b0000, 0b110), // RW + kCNTPS_CTL_EL1 = encode(0b11, 0b111, 0b1110, 0b0010, 0b001), // RW + kCNTPS_CVAL_EL1 = encode(0b11, 0b111, 0b1110, 0b0010, 0b010), // RW + kCNTPS_TVAL_EL1 = encode(0b11, 0b111, 0b1110, 0b0010, 0b000), // RW + kCNTP_CTL_EL0 = encode(0b11, 0b011, 0b1110, 0b0010, 0b001), // RW + kCNTP_CTL_EL02 = encode(0b11, 0b101, 0b1110, 0b0010, 0b001), // RW + kCNTP_CVAL_EL0 = encode(0b11, 0b011, 0b1110, 0b0010, 0b010), // RW + kCNTP_CVAL_EL02 = encode(0b11, 0b101, 0b1110, 0b0010, 0b010), // RW + kCNTP_TVAL_EL0 = encode(0b11, 0b011, 0b1110, 0b0010, 0b000), // RW + kCNTP_TVAL_EL02 = encode(0b11, 0b101, 0b1110, 0b0010, 0b000), // RW + kCNTSCALE_EL2 = encode(0b11, 0b100, 0b1110, 0b0000, 0b100), // RW + kCNTVCTSS_EL0 = encode(0b11, 0b011, 0b1110, 0b0000, 0b110), // RW + kCNTVCT_EL0 = encode(0b11, 0b011, 0b1110, 0b0000, 0b010), // RO + kCNTVFRQ_EL2 = encode(0b11, 0b100, 0b1110, 0b0000, 0b111), // RW + kCNTVOFF_EL2 = encode(0b11, 0b100, 0b1110, 0b0000, 0b011), // RW + kCNTV_CTL_EL0 = encode(0b11, 0b011, 0b1110, 0b0011, 0b001), // RW + kCNTV_CTL_EL02 = encode(0b11, 0b101, 0b1110, 0b0011, 0b001), // RW + kCNTV_CVAL_EL0 = encode(0b11, 0b011, 0b1110, 0b0011, 0b010), // RW + kCNTV_CVAL_EL02 = encode(0b11, 0b101, 0b1110, 0b0011, 0b010), // RW + kCNTV_TVAL_EL0 = encode(0b11, 0b011, 0b1110, 0b0011, 0b000), // RW + kCNTV_TVAL_EL02 = encode(0b11, 0b101, 0b1110, 0b0011, 0b000), // RW + kCONTEXTIDR_EL1 = encode(0b11, 0b000, 0b1101, 0b0000, 0b001), // RW + kCONTEXTIDR_EL12 = encode(0b11, 0b101, 0b1101, 0b0000, 0b001), // RW + kCONTEXTIDR_EL2 = encode(0b11, 0b100, 0b1101, 0b0000, 0b001), // RW + kCPACR_EL1 = encode(0b11, 0b000, 0b0001, 0b0000, 0b010), // RW + kCPACR_EL12 = encode(0b11, 0b101, 0b0001, 0b0000, 0b010), // RW + kCPM_IOACC_CTL_EL3 = encode(0b11, 0b111, 0b1111, 0b0010, 0b000), // RW + kCPTR_EL2 = encode(0b11, 0b100, 0b0001, 0b0001, 0b010), // RW + kCPTR_EL3 = encode(0b11, 0b110, 0b0001, 0b0001, 0b010), // RW + kCSSELR_EL1 = encode(0b11, 0b010, 0b0000, 0b0000, 0b000), // RW + kCTR_EL0 = encode(0b11, 0b011, 0b0000, 0b0000, 0b001), // RO + kCurrentEL = encode(0b11, 0b000, 0b0100, 0b0010, 0b010), // RO + kDACR32_EL2 = encode(0b11, 0b100, 0b0011, 0b0000, 0b000), // RW + kDAIF = encode(0b11, 0b011, 0b0100, 0b0010, 0b001), // RW + kDBGAUTHSTATUS_EL1 = encode(0b10, 0b000, 0b0111, 0b1110, 0b110), // RO + kDBGBCR0_EL1 = encode(0b10, 0b000, 0b0000, 0b0000, 0b101), // RW + kDBGBCR10_EL1 = encode(0b10, 0b000, 0b0000, 0b1010, 0b101), // RW + kDBGBCR11_EL1 = encode(0b10, 0b000, 0b0000, 0b1011, 0b101), // RW + kDBGBCR12_EL1 = encode(0b10, 0b000, 0b0000, 0b1100, 0b101), // RW + kDBGBCR13_EL1 = encode(0b10, 0b000, 0b0000, 0b1101, 0b101), // RW + kDBGBCR14_EL1 = encode(0b10, 0b000, 0b0000, 0b1110, 0b101), // RW + kDBGBCR15_EL1 = encode(0b10, 0b000, 0b0000, 0b1111, 0b101), // RW + kDBGBCR1_EL1 = encode(0b10, 0b000, 0b0000, 0b0001, 0b101), // RW + kDBGBCR2_EL1 = encode(0b10, 0b000, 0b0000, 0b0010, 0b101), // RW + kDBGBCR3_EL1 = encode(0b10, 0b000, 0b0000, 0b0011, 0b101), // RW + kDBGBCR4_EL1 = encode(0b10, 0b000, 0b0000, 0b0100, 0b101), // RW + kDBGBCR5_EL1 = encode(0b10, 0b000, 0b0000, 0b0101, 0b101), // RW + kDBGBCR6_EL1 = encode(0b10, 0b000, 0b0000, 0b0110, 0b101), // RW + kDBGBCR7_EL1 = encode(0b10, 0b000, 0b0000, 0b0111, 0b101), // RW + kDBGBCR8_EL1 = encode(0b10, 0b000, 0b0000, 0b1000, 0b101), // RW + kDBGBCR9_EL1 = encode(0b10, 0b000, 0b0000, 0b1001, 0b101), // RW + kDBGBVR0_EL1 = encode(0b10, 0b000, 0b0000, 0b0000, 0b100), // RW + kDBGBVR10_EL1 = encode(0b10, 0b000, 0b0000, 0b1010, 0b100), // RW + kDBGBVR11_EL1 = encode(0b10, 0b000, 0b0000, 0b1011, 0b100), // RW + kDBGBVR12_EL1 = encode(0b10, 0b000, 0b0000, 0b1100, 0b100), // RW + kDBGBVR13_EL1 = encode(0b10, 0b000, 0b0000, 0b1101, 0b100), // RW + kDBGBVR14_EL1 = encode(0b10, 0b000, 0b0000, 0b1110, 0b100), // RW + kDBGBVR15_EL1 = encode(0b10, 0b000, 0b0000, 0b1111, 0b100), // RW + kDBGBVR1_EL1 = encode(0b10, 0b000, 0b0000, 0b0001, 0b100), // RW + kDBGBVR2_EL1 = encode(0b10, 0b000, 0b0000, 0b0010, 0b100), // RW + kDBGBVR3_EL1 = encode(0b10, 0b000, 0b0000, 0b0011, 0b100), // RW + kDBGBVR4_EL1 = encode(0b10, 0b000, 0b0000, 0b0100, 0b100), // RW + kDBGBVR5_EL1 = encode(0b10, 0b000, 0b0000, 0b0101, 0b100), // RW + kDBGBVR6_EL1 = encode(0b10, 0b000, 0b0000, 0b0110, 0b100), // RW + kDBGBVR7_EL1 = encode(0b10, 0b000, 0b0000, 0b0111, 0b100), // RW + kDBGBVR8_EL1 = encode(0b10, 0b000, 0b0000, 0b1000, 0b100), // RW + kDBGBVR9_EL1 = encode(0b10, 0b000, 0b0000, 0b1001, 0b100), // RW + kDBGCLAIMCLR_EL1 = encode(0b10, 0b000, 0b0111, 0b1001, 0b110), // RW + kDBGCLAIMSET_EL1 = encode(0b10, 0b000, 0b0111, 0b1000, 0b110), // RW + kDBGDTRRX_EL0 = encode(0b10, 0b011, 0b0000, 0b0101, 0b000), // RO + kDBGDTRTX_EL0 = encode(0b10, 0b011, 0b0000, 0b0101, 0b000), // WO + kDBGDTR_EL0 = encode(0b10, 0b011, 0b0000, 0b0100, 0b000), // RW + kDBGPRCR_EL1 = encode(0b10, 0b000, 0b0001, 0b0100, 0b100), // RW + kDBGVCR32_EL2 = encode(0b10, 0b100, 0b0000, 0b0111, 0b000), // RW + kDBGWCR0_EL1 = encode(0b10, 0b000, 0b0000, 0b0000, 0b111), // RW + kDBGWCR10_EL1 = encode(0b10, 0b000, 0b0000, 0b1010, 0b111), // RW + kDBGWCR11_EL1 = encode(0b10, 0b000, 0b0000, 0b1011, 0b111), // RW + kDBGWCR12_EL1 = encode(0b10, 0b000, 0b0000, 0b1100, 0b111), // RW + kDBGWCR13_EL1 = encode(0b10, 0b000, 0b0000, 0b1101, 0b111), // RW + kDBGWCR14_EL1 = encode(0b10, 0b000, 0b0000, 0b1110, 0b111), // RW + kDBGWCR15_EL1 = encode(0b10, 0b000, 0b0000, 0b1111, 0b111), // RW + kDBGWCR1_EL1 = encode(0b10, 0b000, 0b0000, 0b0001, 0b111), // RW + kDBGWCR2_EL1 = encode(0b10, 0b000, 0b0000, 0b0010, 0b111), // RW + kDBGWCR3_EL1 = encode(0b10, 0b000, 0b0000, 0b0011, 0b111), // RW + kDBGWCR4_EL1 = encode(0b10, 0b000, 0b0000, 0b0100, 0b111), // RW + kDBGWCR5_EL1 = encode(0b10, 0b000, 0b0000, 0b0101, 0b111), // RW + kDBGWCR6_EL1 = encode(0b10, 0b000, 0b0000, 0b0110, 0b111), // RW + kDBGWCR7_EL1 = encode(0b10, 0b000, 0b0000, 0b0111, 0b111), // RW + kDBGWCR8_EL1 = encode(0b10, 0b000, 0b0000, 0b1000, 0b111), // RW + kDBGWCR9_EL1 = encode(0b10, 0b000, 0b0000, 0b1001, 0b111), // RW + kDBGWVR0_EL1 = encode(0b10, 0b000, 0b0000, 0b0000, 0b110), // RW + kDBGWVR10_EL1 = encode(0b10, 0b000, 0b0000, 0b1010, 0b110), // RW + kDBGWVR11_EL1 = encode(0b10, 0b000, 0b0000, 0b1011, 0b110), // RW + kDBGWVR12_EL1 = encode(0b10, 0b000, 0b0000, 0b1100, 0b110), // RW + kDBGWVR13_EL1 = encode(0b10, 0b000, 0b0000, 0b1101, 0b110), // RW + kDBGWVR14_EL1 = encode(0b10, 0b000, 0b0000, 0b1110, 0b110), // RW + kDBGWVR15_EL1 = encode(0b10, 0b000, 0b0000, 0b1111, 0b110), // RW + kDBGWVR1_EL1 = encode(0b10, 0b000, 0b0000, 0b0001, 0b110), // RW + kDBGWVR2_EL1 = encode(0b10, 0b000, 0b0000, 0b0010, 0b110), // RW + kDBGWVR3_EL1 = encode(0b10, 0b000, 0b0000, 0b0011, 0b110), // RW + kDBGWVR4_EL1 = encode(0b10, 0b000, 0b0000, 0b0100, 0b110), // RW + kDBGWVR5_EL1 = encode(0b10, 0b000, 0b0000, 0b0101, 0b110), // RW + kDBGWVR6_EL1 = encode(0b10, 0b000, 0b0000, 0b0110, 0b110), // RW + kDBGWVR7_EL1 = encode(0b10, 0b000, 0b0000, 0b0111, 0b110), // RW + kDBGWVR8_EL1 = encode(0b10, 0b000, 0b0000, 0b1000, 0b110), // RW + kDBGWVR9_EL1 = encode(0b10, 0b000, 0b0000, 0b1001, 0b110), // RW + kDCZID_EL0 = encode(0b11, 0b011, 0b0000, 0b0000, 0b111), // RO + kDISR_EL1 = encode(0b11, 0b000, 0b1100, 0b0001, 0b001), // RW + kDIT = encode(0b11, 0b011, 0b0100, 0b0010, 0b101), // RW + kDLR_EL0 = encode(0b11, 0b011, 0b0100, 0b0101, 0b001), // RW + kDSPSR_EL0 = encode(0b11, 0b011, 0b0100, 0b0101, 0b000), // RW + kELR_EL1 = encode(0b11, 0b000, 0b0100, 0b0000, 0b001), // RW + kELR_EL12 = encode(0b11, 0b101, 0b0100, 0b0000, 0b001), // RW + kELR_EL2 = encode(0b11, 0b100, 0b0100, 0b0000, 0b001), // RW + kELR_EL3 = encode(0b11, 0b110, 0b0100, 0b0000, 0b001), // RW + kERRIDR_EL1 = encode(0b11, 0b000, 0b0101, 0b0011, 0b000), // RO + kERRSELR_EL1 = encode(0b11, 0b000, 0b0101, 0b0011, 0b001), // RW + kERXADDR_EL1 = encode(0b11, 0b000, 0b0101, 0b0100, 0b011), // RW + kERXCTLR_EL1 = encode(0b11, 0b000, 0b0101, 0b0100, 0b001), // RW + kERXFR_EL1 = encode(0b11, 0b000, 0b0101, 0b0100, 0b000), // RO + kERXMISC0_EL1 = encode(0b11, 0b000, 0b0101, 0b0101, 0b000), // RW + kERXMISC1_EL1 = encode(0b11, 0b000, 0b0101, 0b0101, 0b001), // RW + kERXMISC2_EL1 = encode(0b11, 0b000, 0b0101, 0b0101, 0b010), // RW + kERXMISC3_EL1 = encode(0b11, 0b000, 0b0101, 0b0101, 0b011), // RW + kERXPFGCDN_EL1 = encode(0b11, 0b000, 0b0101, 0b0100, 0b110), // RW + kERXPFGCTL_EL1 = encode(0b11, 0b000, 0b0101, 0b0100, 0b101), // RW + kERXPFGF_EL1 = encode(0b11, 0b000, 0b0101, 0b0100, 0b100), // RO + kERXSTATUS_EL1 = encode(0b11, 0b000, 0b0101, 0b0100, 0b010), // RW + kESR_EL1 = encode(0b11, 0b000, 0b0101, 0b0010, 0b000), // RW + kESR_EL12 = encode(0b11, 0b101, 0b0101, 0b0010, 0b000), // RW + kESR_EL2 = encode(0b11, 0b100, 0b0101, 0b0010, 0b000), // RW + kESR_EL3 = encode(0b11, 0b110, 0b0101, 0b0010, 0b000), // RW + kFAR_EL1 = encode(0b11, 0b000, 0b0110, 0b0000, 0b000), // RW + kFAR_EL12 = encode(0b11, 0b101, 0b0110, 0b0000, 0b000), // RW + kFAR_EL2 = encode(0b11, 0b100, 0b0110, 0b0000, 0b000), // RW + kFAR_EL3 = encode(0b11, 0b110, 0b0110, 0b0000, 0b000), // RW + kFPCR = encode(0b11, 0b011, 0b0100, 0b0100, 0b000), // RW + kFPEXC32_EL2 = encode(0b11, 0b100, 0b0101, 0b0011, 0b000), // RW + kFPSR = encode(0b11, 0b011, 0b0100, 0b0100, 0b001), // RW + kGCR_EL1 = encode(0b11, 0b000, 0b0001, 0b0000, 0b110), // RW + kGMID_EL1 = encode(0b11, 0b001, 0b0000, 0b0000, 0b100), // RO + kHACR_EL2 = encode(0b11, 0b100, 0b0001, 0b0001, 0b111), // RW + kHCR_EL2 = encode(0b11, 0b100, 0b0001, 0b0001, 0b000), // RW + kHDFGRTR_EL2 = encode(0b11, 0b100, 0b0011, 0b0001, 0b100), // RW + kHDFGWTR_EL2 = encode(0b11, 0b100, 0b0011, 0b0001, 0b101), // RW + kHFGITR_EL2 = encode(0b11, 0b100, 0b0001, 0b0001, 0b110), // RW + kHFGRTR_EL2 = encode(0b11, 0b100, 0b0001, 0b0001, 0b100), // RW + kHFGWTR_EL2 = encode(0b11, 0b100, 0b0001, 0b0001, 0b101), // RW + kHPFAR_EL2 = encode(0b11, 0b100, 0b0110, 0b0000, 0b100), // RW + kHSTR_EL2 = encode(0b11, 0b100, 0b0001, 0b0001, 0b011), // RW + kICC_AP0R0_EL1 = encode(0b11, 0b000, 0b1100, 0b1000, 0b100), // RW + kICC_AP0R1_EL1 = encode(0b11, 0b000, 0b1100, 0b1000, 0b101), // RW + kICC_AP0R2_EL1 = encode(0b11, 0b000, 0b1100, 0b1000, 0b110), // RW + kICC_AP0R3_EL1 = encode(0b11, 0b000, 0b1100, 0b1000, 0b111), // RW + kICC_AP1R0_EL1 = encode(0b11, 0b000, 0b1100, 0b1001, 0b000), // RW + kICC_AP1R1_EL1 = encode(0b11, 0b000, 0b1100, 0b1001, 0b001), // RW + kICC_AP1R2_EL1 = encode(0b11, 0b000, 0b1100, 0b1001, 0b010), // RW + kICC_AP1R3_EL1 = encode(0b11, 0b000, 0b1100, 0b1001, 0b011), // RW + kICC_ASGI1R_EL1 = encode(0b11, 0b000, 0b1100, 0b1011, 0b110), // WO + kICC_BPR0_EL1 = encode(0b11, 0b000, 0b1100, 0b1000, 0b011), // RW + kICC_BPR1_EL1 = encode(0b11, 0b000, 0b1100, 0b1100, 0b011), // RW + kICC_CTLR_EL1 = encode(0b11, 0b000, 0b1100, 0b1100, 0b100), // RW + kICC_CTLR_EL3 = encode(0b11, 0b110, 0b1100, 0b1100, 0b100), // RW + kICC_DIR_EL1 = encode(0b11, 0b000, 0b1100, 0b1011, 0b001), // WO + kICC_EOIR0_EL1 = encode(0b11, 0b000, 0b1100, 0b1000, 0b001), // WO + kICC_EOIR1_EL1 = encode(0b11, 0b000, 0b1100, 0b1100, 0b001), // WO + kICC_HPPIR0_EL1 = encode(0b11, 0b000, 0b1100, 0b1000, 0b010), // RO + kICC_HPPIR1_EL1 = encode(0b11, 0b000, 0b1100, 0b1100, 0b010), // RO + kICC_IAR0_EL1 = encode(0b11, 0b000, 0b1100, 0b1000, 0b000), // RO + kICC_IAR1_EL1 = encode(0b11, 0b000, 0b1100, 0b1100, 0b000), // RO + kICC_IGRPEN0_EL1 = encode(0b11, 0b000, 0b1100, 0b1100, 0b110), // RW + kICC_IGRPEN1_EL1 = encode(0b11, 0b000, 0b1100, 0b1100, 0b111), // RW + kICC_IGRPEN1_EL3 = encode(0b11, 0b110, 0b1100, 0b1100, 0b111), // RW + kICC_PMR_EL1 = encode(0b11, 0b000, 0b0100, 0b0110, 0b000), // RW + kICC_RPR_EL1 = encode(0b11, 0b000, 0b1100, 0b1011, 0b011), // RO + kICC_SGI0R_EL1 = encode(0b11, 0b000, 0b1100, 0b1011, 0b111), // WO + kICC_SGI1R_EL1 = encode(0b11, 0b000, 0b1100, 0b1011, 0b101), // WO + kICC_SRE_EL1 = encode(0b11, 0b000, 0b1100, 0b1100, 0b101), // RW + kICC_SRE_EL2 = encode(0b11, 0b100, 0b1100, 0b1001, 0b101), // RW + kICC_SRE_EL3 = encode(0b11, 0b110, 0b1100, 0b1100, 0b101), // RW + kICH_AP0R0_EL2 = encode(0b11, 0b100, 0b1100, 0b1000, 0b000), // RW + kICH_AP0R1_EL2 = encode(0b11, 0b100, 0b1100, 0b1000, 0b001), // RW + kICH_AP0R2_EL2 = encode(0b11, 0b100, 0b1100, 0b1000, 0b010), // RW + kICH_AP0R3_EL2 = encode(0b11, 0b100, 0b1100, 0b1000, 0b011), // RW + kICH_AP1R0_EL2 = encode(0b11, 0b100, 0b1100, 0b1001, 0b000), // RW + kICH_AP1R1_EL2 = encode(0b11, 0b100, 0b1100, 0b1001, 0b001), // RW + kICH_AP1R2_EL2 = encode(0b11, 0b100, 0b1100, 0b1001, 0b010), // RW + kICH_AP1R3_EL2 = encode(0b11, 0b100, 0b1100, 0b1001, 0b011), // RW + kICH_EISR_EL2 = encode(0b11, 0b100, 0b1100, 0b1011, 0b011), // RO + kICH_ELRSR_EL2 = encode(0b11, 0b100, 0b1100, 0b1011, 0b101), // RO + kICH_HCR_EL2 = encode(0b11, 0b100, 0b1100, 0b1011, 0b000), // RW + kICH_LR0_EL2 = encode(0b11, 0b100, 0b1100, 0b1100, 0b000), // RW + kICH_LR10_EL2 = encode(0b11, 0b100, 0b1100, 0b1101, 0b010), // RW + kICH_LR11_EL2 = encode(0b11, 0b100, 0b1100, 0b1101, 0b011), // RW + kICH_LR12_EL2 = encode(0b11, 0b100, 0b1100, 0b1101, 0b100), // RW + kICH_LR13_EL2 = encode(0b11, 0b100, 0b1100, 0b1101, 0b101), // RW + kICH_LR14_EL2 = encode(0b11, 0b100, 0b1100, 0b1101, 0b110), // RW + kICH_LR15_EL2 = encode(0b11, 0b100, 0b1100, 0b1101, 0b111), // RW + kICH_LR1_EL2 = encode(0b11, 0b100, 0b1100, 0b1100, 0b001), // RW + kICH_LR2_EL2 = encode(0b11, 0b100, 0b1100, 0b1100, 0b010), // RW + kICH_LR3_EL2 = encode(0b11, 0b100, 0b1100, 0b1100, 0b011), // RW + kICH_LR4_EL2 = encode(0b11, 0b100, 0b1100, 0b1100, 0b100), // RW + kICH_LR5_EL2 = encode(0b11, 0b100, 0b1100, 0b1100, 0b101), // RW + kICH_LR6_EL2 = encode(0b11, 0b100, 0b1100, 0b1100, 0b110), // RW + kICH_LR7_EL2 = encode(0b11, 0b100, 0b1100, 0b1100, 0b111), // RW + kICH_LR8_EL2 = encode(0b11, 0b100, 0b1100, 0b1101, 0b000), // RW + kICH_LR9_EL2 = encode(0b11, 0b100, 0b1100, 0b1101, 0b001), // RW + kICH_MISR_EL2 = encode(0b11, 0b100, 0b1100, 0b1011, 0b010), // RO + kICH_VMCR_EL2 = encode(0b11, 0b100, 0b1100, 0b1011, 0b111), // RW + kICH_VTR_EL2 = encode(0b11, 0b100, 0b1100, 0b1011, 0b001), // RO + kID_AA64AFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0101, 0b100), // RO + kID_AA64AFR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0101, 0b101), // RO + kID_AA64DFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0101, 0b000), // RO + kID_AA64DFR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0101, 0b001), // RO + kID_AA64ISAR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0110, 0b000), // RO + kID_AA64ISAR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0110, 0b001), // RO + kID_AA64MMFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0111, 0b000), // RO + kID_AA64MMFR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0111, 0b001), // RO + kID_AA64MMFR2_EL1 = encode(0b11, 0b000, 0b0000, 0b0111, 0b010), // RO + kID_AA64PFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0100, 0b000), // RO + kID_AA64PFR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0100, 0b001), // RO + kID_AA64ZFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0100, 0b100), // RO + kID_AFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0001, 0b011), // RO + kID_DFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0001, 0b010), // RO + kID_ISAR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0010, 0b000), // RO + kID_ISAR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0010, 0b001), // RO + kID_ISAR2_EL1 = encode(0b11, 0b000, 0b0000, 0b0010, 0b010), // RO + kID_ISAR3_EL1 = encode(0b11, 0b000, 0b0000, 0b0010, 0b011), // RO + kID_ISAR4_EL1 = encode(0b11, 0b000, 0b0000, 0b0010, 0b100), // RO + kID_ISAR5_EL1 = encode(0b11, 0b000, 0b0000, 0b0010, 0b101), // RO + kID_ISAR6_EL1 = encode(0b11, 0b000, 0b0000, 0b0010, 0b111), // RO + kID_MMFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0001, 0b100), // RO + kID_MMFR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0001, 0b101), // RO + kID_MMFR2_EL1 = encode(0b11, 0b000, 0b0000, 0b0001, 0b110), // RO + kID_MMFR3_EL1 = encode(0b11, 0b000, 0b0000, 0b0001, 0b111), // RO + kID_MMFR4_EL1 = encode(0b11, 0b000, 0b0000, 0b0010, 0b110), // RO + kID_MMFR5_EL1 = encode(0b11, 0b000, 0b0000, 0b0011, 0b110), // RO + kID_PFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0001, 0b000), // RO + kID_PFR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0001, 0b001), // RO + kID_PFR2_EL1 = encode(0b11, 0b000, 0b0000, 0b0011, 0b100), // RO + kIFSR32_EL2 = encode(0b11, 0b100, 0b0101, 0b0000, 0b001), // RW + kISR_EL1 = encode(0b11, 0b000, 0b1100, 0b0001, 0b000), // RO + kLORC_EL1 = encode(0b11, 0b000, 0b1010, 0b0100, 0b011), // RW + kLOREA_EL1 = encode(0b11, 0b000, 0b1010, 0b0100, 0b001), // RW + kLORID_EL1 = encode(0b11, 0b000, 0b1010, 0b0100, 0b111), // RO + kLORN_EL1 = encode(0b11, 0b000, 0b1010, 0b0100, 0b010), // RW + kLORSA_EL1 = encode(0b11, 0b000, 0b1010, 0b0100, 0b000), // RW + kMAIR_EL1 = encode(0b11, 0b000, 0b1010, 0b0010, 0b000), // RW + kMAIR_EL12 = encode(0b11, 0b101, 0b1010, 0b0010, 0b000), // RW + kMAIR_EL2 = encode(0b11, 0b100, 0b1010, 0b0010, 0b000), // RW + kMAIR_EL3 = encode(0b11, 0b110, 0b1010, 0b0010, 0b000), // RW + kMDCCINT_EL1 = encode(0b10, 0b000, 0b0000, 0b0010, 0b000), // RW + kMDCCSR_EL0 = encode(0b10, 0b011, 0b0000, 0b0001, 0b000), // RO + kMDCR_EL2 = encode(0b11, 0b100, 0b0001, 0b0001, 0b001), // RW + kMDCR_EL3 = encode(0b11, 0b110, 0b0001, 0b0011, 0b001), // RW + kMDRAR_EL1 = encode(0b10, 0b000, 0b0001, 0b0000, 0b000), // RO + kMDSCR_EL1 = encode(0b10, 0b000, 0b0000, 0b0010, 0b010), // RW + kMIDR_EL1 = encode(0b11, 0b000, 0b0000, 0b0000, 0b000), // RO + kMPAM0_EL1 = encode(0b11, 0b000, 0b1010, 0b0101, 0b001), // RW + kMPAM1_EL1 = encode(0b11, 0b000, 0b1010, 0b0101, 0b000), // RW + kMPAM1_EL12 = encode(0b11, 0b101, 0b1010, 0b0101, 0b000), // RW + kMPAM2_EL2 = encode(0b11, 0b100, 0b1010, 0b0101, 0b000), // RW + kMPAM3_EL3 = encode(0b11, 0b110, 0b1010, 0b0101, 0b000), // RW + kMPAMHCR_EL2 = encode(0b11, 0b100, 0b1010, 0b0100, 0b000), // RW + kMPAMIDR_EL1 = encode(0b11, 0b000, 0b1010, 0b0100, 0b100), // RO + kMPAMVPM0_EL2 = encode(0b11, 0b100, 0b1010, 0b0110, 0b000), // RW + kMPAMVPM1_EL2 = encode(0b11, 0b100, 0b1010, 0b0110, 0b001), // RW + kMPAMVPM2_EL2 = encode(0b11, 0b100, 0b1010, 0b0110, 0b010), // RW + kMPAMVPM3_EL2 = encode(0b11, 0b100, 0b1010, 0b0110, 0b011), // RW + kMPAMVPM4_EL2 = encode(0b11, 0b100, 0b1010, 0b0110, 0b100), // RW + kMPAMVPM5_EL2 = encode(0b11, 0b100, 0b1010, 0b0110, 0b101), // RW + kMPAMVPM6_EL2 = encode(0b11, 0b100, 0b1010, 0b0110, 0b110), // RW + kMPAMVPM7_EL2 = encode(0b11, 0b100, 0b1010, 0b0110, 0b111), // RW + kMPAMVPMV_EL2 = encode(0b11, 0b100, 0b1010, 0b0100, 0b001), // RW + kMPIDR_EL1 = encode(0b11, 0b000, 0b0000, 0b0000, 0b101), // RO + kMVFR0_EL1 = encode(0b11, 0b000, 0b0000, 0b0011, 0b000), // RO + kMVFR1_EL1 = encode(0b11, 0b000, 0b0000, 0b0011, 0b001), // RO + kMVFR2_EL1 = encode(0b11, 0b000, 0b0000, 0b0011, 0b010), // RO + kNZCV = encode(0b11, 0b011, 0b0100, 0b0010, 0b000), // RW + kOSDLR_EL1 = encode(0b10, 0b000, 0b0001, 0b0011, 0b100), // RW + kOSDTRRX_EL1 = encode(0b10, 0b000, 0b0000, 0b0000, 0b010), // RW + kOSDTRTX_EL1 = encode(0b10, 0b000, 0b0000, 0b0011, 0b010), // RW + kOSECCR_EL1 = encode(0b10, 0b000, 0b0000, 0b0110, 0b010), // RW + kOSLAR_EL1 = encode(0b10, 0b000, 0b0001, 0b0000, 0b100), // WO + kOSLSR_EL1 = encode(0b10, 0b000, 0b0001, 0b0001, 0b100), // RO + kPAN = encode(0b11, 0b000, 0b0100, 0b0010, 0b011), // RW + kPAR_EL1 = encode(0b11, 0b000, 0b0111, 0b0100, 0b000), // RW + kPMBIDR_EL1 = encode(0b11, 0b000, 0b1001, 0b1010, 0b111), // RO + kPMBLIMITR_EL1 = encode(0b11, 0b000, 0b1001, 0b1010, 0b000), // RW + kPMBPTR_EL1 = encode(0b11, 0b000, 0b1001, 0b1010, 0b001), // RW + kPMBSR_EL1 = encode(0b11, 0b000, 0b1001, 0b1010, 0b011), // RW + kPMCCFILTR_EL0 = encode(0b11, 0b011, 0b1110, 0b1111, 0b111), // RW + kPMCCNTR_EL0 = encode(0b11, 0b011, 0b1001, 0b1101, 0b000), // RW + kPMCEID0_EL0 = encode(0b11, 0b011, 0b1001, 0b1100, 0b110), // RO + kPMCEID1_EL0 = encode(0b11, 0b011, 0b1001, 0b1100, 0b111), // RO + kPMCNTENCLR_EL0 = encode(0b11, 0b011, 0b1001, 0b1100, 0b010), // RW + kPMCNTENSET_EL0 = encode(0b11, 0b011, 0b1001, 0b1100, 0b001), // RW + kPMCR_EL0 = encode(0b11, 0b011, 0b1001, 0b1100, 0b000), // RW + kPMEVCNTR0_EL0 = encode(0b11, 0b011, 0b1110, 0b1000, 0b000), // RW + kPMEVCNTR10_EL0 = encode(0b11, 0b011, 0b1110, 0b1001, 0b010), // RW + kPMEVCNTR11_EL0 = encode(0b11, 0b011, 0b1110, 0b1001, 0b011), // RW + kPMEVCNTR12_EL0 = encode(0b11, 0b011, 0b1110, 0b1001, 0b100), // RW + kPMEVCNTR13_EL0 = encode(0b11, 0b011, 0b1110, 0b1001, 0b101), // RW + kPMEVCNTR14_EL0 = encode(0b11, 0b011, 0b1110, 0b1001, 0b110), // RW + kPMEVCNTR15_EL0 = encode(0b11, 0b011, 0b1110, 0b1001, 0b111), // RW + kPMEVCNTR16_EL0 = encode(0b11, 0b011, 0b1110, 0b1010, 0b000), // RW + kPMEVCNTR17_EL0 = encode(0b11, 0b011, 0b1110, 0b1010, 0b001), // RW + kPMEVCNTR18_EL0 = encode(0b11, 0b011, 0b1110, 0b1010, 0b010), // RW + kPMEVCNTR19_EL0 = encode(0b11, 0b011, 0b1110, 0b1010, 0b011), // RW + kPMEVCNTR1_EL0 = encode(0b11, 0b011, 0b1110, 0b1000, 0b001), // RW + kPMEVCNTR20_EL0 = encode(0b11, 0b011, 0b1110, 0b1010, 0b100), // RW + kPMEVCNTR21_EL0 = encode(0b11, 0b011, 0b1110, 0b1010, 0b101), // RW + kPMEVCNTR22_EL0 = encode(0b11, 0b011, 0b1110, 0b1010, 0b110), // RW + kPMEVCNTR23_EL0 = encode(0b11, 0b011, 0b1110, 0b1010, 0b111), // RW + kPMEVCNTR24_EL0 = encode(0b11, 0b011, 0b1110, 0b1011, 0b000), // RW + kPMEVCNTR25_EL0 = encode(0b11, 0b011, 0b1110, 0b1011, 0b001), // RW + kPMEVCNTR26_EL0 = encode(0b11, 0b011, 0b1110, 0b1011, 0b010), // RW + kPMEVCNTR27_EL0 = encode(0b11, 0b011, 0b1110, 0b1011, 0b011), // RW + kPMEVCNTR28_EL0 = encode(0b11, 0b011, 0b1110, 0b1011, 0b100), // RW + kPMEVCNTR29_EL0 = encode(0b11, 0b011, 0b1110, 0b1011, 0b101), // RW + kPMEVCNTR2_EL0 = encode(0b11, 0b011, 0b1110, 0b1000, 0b010), // RW + kPMEVCNTR30_EL0 = encode(0b11, 0b011, 0b1110, 0b1011, 0b110), // RW + kPMEVCNTR3_EL0 = encode(0b11, 0b011, 0b1110, 0b1000, 0b011), // RW + kPMEVCNTR4_EL0 = encode(0b11, 0b011, 0b1110, 0b1000, 0b100), // RW + kPMEVCNTR5_EL0 = encode(0b11, 0b011, 0b1110, 0b1000, 0b101), // RW + kPMEVCNTR6_EL0 = encode(0b11, 0b011, 0b1110, 0b1000, 0b110), // RW + kPMEVCNTR7_EL0 = encode(0b11, 0b011, 0b1110, 0b1000, 0b111), // RW + kPMEVCNTR8_EL0 = encode(0b11, 0b011, 0b1110, 0b1001, 0b000), // RW + kPMEVCNTR9_EL0 = encode(0b11, 0b011, 0b1110, 0b1001, 0b001), // RW + kPMEVTYPER0_EL0 = encode(0b11, 0b011, 0b1110, 0b1100, 0b000), // RW + kPMEVTYPER10_EL0 = encode(0b11, 0b011, 0b1110, 0b1101, 0b010), // RW + kPMEVTYPER11_EL0 = encode(0b11, 0b011, 0b1110, 0b1101, 0b011), // RW + kPMEVTYPER12_EL0 = encode(0b11, 0b011, 0b1110, 0b1101, 0b100), // RW + kPMEVTYPER13_EL0 = encode(0b11, 0b011, 0b1110, 0b1101, 0b101), // RW + kPMEVTYPER14_EL0 = encode(0b11, 0b011, 0b1110, 0b1101, 0b110), // RW + kPMEVTYPER15_EL0 = encode(0b11, 0b011, 0b1110, 0b1101, 0b111), // RW + kPMEVTYPER16_EL0 = encode(0b11, 0b011, 0b1110, 0b1110, 0b000), // RW + kPMEVTYPER17_EL0 = encode(0b11, 0b011, 0b1110, 0b1110, 0b001), // RW + kPMEVTYPER18_EL0 = encode(0b11, 0b011, 0b1110, 0b1110, 0b010), // RW + kPMEVTYPER19_EL0 = encode(0b11, 0b011, 0b1110, 0b1110, 0b011), // RW + kPMEVTYPER1_EL0 = encode(0b11, 0b011, 0b1110, 0b1100, 0b001), // RW + kPMEVTYPER20_EL0 = encode(0b11, 0b011, 0b1110, 0b1110, 0b100), // RW + kPMEVTYPER21_EL0 = encode(0b11, 0b011, 0b1110, 0b1110, 0b101), // RW + kPMEVTYPER22_EL0 = encode(0b11, 0b011, 0b1110, 0b1110, 0b110), // RW + kPMEVTYPER23_EL0 = encode(0b11, 0b011, 0b1110, 0b1110, 0b111), // RW + kPMEVTYPER24_EL0 = encode(0b11, 0b011, 0b1110, 0b1111, 0b000), // RW + kPMEVTYPER25_EL0 = encode(0b11, 0b011, 0b1110, 0b1111, 0b001), // RW + kPMEVTYPER26_EL0 = encode(0b11, 0b011, 0b1110, 0b1111, 0b010), // RW + kPMEVTYPER27_EL0 = encode(0b11, 0b011, 0b1110, 0b1111, 0b011), // RW + kPMEVTYPER28_EL0 = encode(0b11, 0b011, 0b1110, 0b1111, 0b100), // RW + kPMEVTYPER29_EL0 = encode(0b11, 0b011, 0b1110, 0b1111, 0b101), // RW + kPMEVTYPER2_EL0 = encode(0b11, 0b011, 0b1110, 0b1100, 0b010), // RW + kPMEVTYPER30_EL0 = encode(0b11, 0b011, 0b1110, 0b1111, 0b110), // RW + kPMEVTYPER3_EL0 = encode(0b11, 0b011, 0b1110, 0b1100, 0b011), // RW + kPMEVTYPER4_EL0 = encode(0b11, 0b011, 0b1110, 0b1100, 0b100), // RW + kPMEVTYPER5_EL0 = encode(0b11, 0b011, 0b1110, 0b1100, 0b101), // RW + kPMEVTYPER6_EL0 = encode(0b11, 0b011, 0b1110, 0b1100, 0b110), // RW + kPMEVTYPER7_EL0 = encode(0b11, 0b011, 0b1110, 0b1100, 0b111), // RW + kPMEVTYPER8_EL0 = encode(0b11, 0b011, 0b1110, 0b1101, 0b000), // RW + kPMEVTYPER9_EL0 = encode(0b11, 0b011, 0b1110, 0b1101, 0b001), // RW + kPMINTENCLR_EL1 = encode(0b11, 0b000, 0b1001, 0b1110, 0b010), // RW + kPMINTENSET_EL1 = encode(0b11, 0b000, 0b1001, 0b1110, 0b001), // RW + kPMMIR_EL1 = encode(0b11, 0b000, 0b1001, 0b1110, 0b110), // RW + kPMOVSCLR_EL0 = encode(0b11, 0b011, 0b1001, 0b1100, 0b011), // RW + kPMOVSSET_EL0 = encode(0b11, 0b011, 0b1001, 0b1110, 0b011), // RW + kPMSCR_EL1 = encode(0b11, 0b000, 0b1001, 0b1001, 0b000), // RW + kPMSCR_EL12 = encode(0b11, 0b101, 0b1001, 0b1001, 0b000), // RW + kPMSCR_EL2 = encode(0b11, 0b100, 0b1001, 0b1001, 0b000), // RW + kPMSELR_EL0 = encode(0b11, 0b011, 0b1001, 0b1100, 0b101), // RW + kPMSEVFR_EL1 = encode(0b11, 0b000, 0b1001, 0b1001, 0b101), // RW + kPMSFCR_EL1 = encode(0b11, 0b000, 0b1001, 0b1001, 0b100), // RW + kPMSICR_EL1 = encode(0b11, 0b000, 0b1001, 0b1001, 0b010), // RW + kPMSIDR_EL1 = encode(0b11, 0b000, 0b1001, 0b1001, 0b111), // RO + kPMSIRR_EL1 = encode(0b11, 0b000, 0b1001, 0b1001, 0b011), // RW + kPMSLATFR_EL1 = encode(0b11, 0b000, 0b1001, 0b1001, 0b110), // RW + kPMSWINC_EL0 = encode(0b11, 0b011, 0b1001, 0b1100, 0b100), // WO + kPMUSERENR_EL0 = encode(0b11, 0b011, 0b1001, 0b1110, 0b000), // RW + kPMXEVCNTR_EL0 = encode(0b11, 0b011, 0b1001, 0b1101, 0b010), // RW + kPMXEVTYPER_EL0 = encode(0b11, 0b011, 0b1001, 0b1101, 0b001), // RW + kREVIDR_EL1 = encode(0b11, 0b000, 0b0000, 0b0000, 0b110), // RO + kRGSR_EL1 = encode(0b11, 0b000, 0b0001, 0b0000, 0b101), // RW + kRMR_EL1 = encode(0b11, 0b000, 0b1100, 0b0000, 0b010), // RW + kRMR_EL2 = encode(0b11, 0b100, 0b1100, 0b0000, 0b010), // RW + kRMR_EL3 = encode(0b11, 0b110, 0b1100, 0b0000, 0b010), // RW + kRNDR = encode(0b11, 0b011, 0b0010, 0b0100, 0b000), // RO + kRNDRRS = encode(0b11, 0b011, 0b0010, 0b0100, 0b001), // RO + kRVBAR_EL1 = encode(0b11, 0b000, 0b1100, 0b0000, 0b001), // RO + kRVBAR_EL2 = encode(0b11, 0b100, 0b1100, 0b0000, 0b001), // RO + kRVBAR_EL3 = encode(0b11, 0b110, 0b1100, 0b0000, 0b001), // RO + kSCR_EL3 = encode(0b11, 0b110, 0b0001, 0b0001, 0b000), // RW + kSCTLR_EL1 = encode(0b11, 0b000, 0b0001, 0b0000, 0b000), // RW + kSCTLR_EL12 = encode(0b11, 0b101, 0b0001, 0b0000, 0b000), // RW + kSCTLR_EL2 = encode(0b11, 0b100, 0b0001, 0b0000, 0b000), // RW + kSCTLR_EL3 = encode(0b11, 0b110, 0b0001, 0b0000, 0b000), // RW + kSCXTNUM_EL0 = encode(0b11, 0b011, 0b1101, 0b0000, 0b111), // RW + kSCXTNUM_EL1 = encode(0b11, 0b000, 0b1101, 0b0000, 0b111), // RW + kSCXTNUM_EL12 = encode(0b11, 0b101, 0b1101, 0b0000, 0b111), // RW + kSCXTNUM_EL2 = encode(0b11, 0b100, 0b1101, 0b0000, 0b111), // RW + kSCXTNUM_EL3 = encode(0b11, 0b110, 0b1101, 0b0000, 0b111), // RW + kSDER32_EL2 = encode(0b11, 0b100, 0b0001, 0b0011, 0b001), // RW + kSDER32_EL3 = encode(0b11, 0b110, 0b0001, 0b0001, 0b001), // RW + kSPSR_EL1 = encode(0b11, 0b000, 0b0100, 0b0000, 0b000), // RW + kSPSR_EL12 = encode(0b11, 0b101, 0b0100, 0b0000, 0b000), // RW + kSPSR_EL2 = encode(0b11, 0b100, 0b0100, 0b0000, 0b000), // RW + kSPSR_EL3 = encode(0b11, 0b110, 0b0100, 0b0000, 0b000), // RW + kSPSR_abt = encode(0b11, 0b100, 0b0100, 0b0011, 0b001), // RW + kSPSR_fiq = encode(0b11, 0b100, 0b0100, 0b0011, 0b011), // RW + kSPSR_irq = encode(0b11, 0b100, 0b0100, 0b0011, 0b000), // RW + kSPSR_und = encode(0b11, 0b100, 0b0100, 0b0011, 0b010), // RW + kSPSel = encode(0b11, 0b000, 0b0100, 0b0010, 0b000), // RW + kSP_EL0 = encode(0b11, 0b000, 0b0100, 0b0001, 0b000), // RW + kSP_EL1 = encode(0b11, 0b100, 0b0100, 0b0001, 0b000), // RW + kSP_EL2 = encode(0b11, 0b110, 0b0100, 0b0001, 0b000), // RW + kSSBS = encode(0b11, 0b011, 0b0100, 0b0010, 0b110), // RW + kTCO = encode(0b11, 0b011, 0b0100, 0b0010, 0b111), // RW + kTCR_EL1 = encode(0b11, 0b000, 0b0010, 0b0000, 0b010), // RW + kTCR_EL12 = encode(0b11, 0b101, 0b0010, 0b0000, 0b010), // RW + kTCR_EL2 = encode(0b11, 0b100, 0b0010, 0b0000, 0b010), // RW + kTCR_EL3 = encode(0b11, 0b110, 0b0010, 0b0000, 0b010), // RW + kTEECR32_EL1 = encode(0b10, 0b010, 0b0000, 0b0000, 0b000), // RW + kTEEHBR32_EL1 = encode(0b10, 0b010, 0b0001, 0b0000, 0b000), // RW + kTFSRE0_EL1 = encode(0b11, 0b000, 0b0101, 0b0110, 0b001), // RW + kTFSR_EL1 = encode(0b11, 0b000, 0b0101, 0b0110, 0b000), // RW + kTFSR_EL12 = encode(0b11, 0b101, 0b0101, 0b0110, 0b000), // RW + kTFSR_EL2 = encode(0b11, 0b100, 0b0101, 0b0110, 0b000), // RW + kTFSR_EL3 = encode(0b11, 0b110, 0b0101, 0b0110, 0b000), // RW + kTPIDRRO_EL0 = encode(0b11, 0b011, 0b1101, 0b0000, 0b011), // RW + kTPIDR_EL0 = encode(0b11, 0b011, 0b1101, 0b0000, 0b010), // RW + kTPIDR_EL1 = encode(0b11, 0b000, 0b1101, 0b0000, 0b100), // RW + kTPIDR_EL2 = encode(0b11, 0b100, 0b1101, 0b0000, 0b010), // RW + kTPIDR_EL3 = encode(0b11, 0b110, 0b1101, 0b0000, 0b010), // RW + kTRBBASER_EL1 = encode(0b11, 0b000, 0b1001, 0b1011, 0b010), // RW + kTRBIDR_EL1 = encode(0b11, 0b000, 0b1001, 0b1011, 0b111), // RO + kTRBLIMITR_EL1 = encode(0b11, 0b000, 0b1001, 0b1011, 0b000), // RW + kTRBMAR_EL1 = encode(0b11, 0b000, 0b1001, 0b1011, 0b100), // RW + kTRBPTR_EL1 = encode(0b11, 0b000, 0b1001, 0b1011, 0b001), // RW + kTRBSR_EL1 = encode(0b11, 0b000, 0b1001, 0b1011, 0b011), // RW + kTRBTRG_EL1 = encode(0b11, 0b000, 0b1001, 0b1011, 0b110), // RW + kTRCACATR0 = encode(0b10, 0b001, 0b0010, 0b0000, 0b010), // RW + kTRCACATR1 = encode(0b10, 0b001, 0b0010, 0b0010, 0b010), // RW + kTRCACATR10 = encode(0b10, 0b001, 0b0010, 0b0100, 0b011), // RW + kTRCACATR11 = encode(0b10, 0b001, 0b0010, 0b0110, 0b011), // RW + kTRCACATR12 = encode(0b10, 0b001, 0b0010, 0b1000, 0b011), // RW + kTRCACATR13 = encode(0b10, 0b001, 0b0010, 0b1010, 0b011), // RW + kTRCACATR14 = encode(0b10, 0b001, 0b0010, 0b1100, 0b011), // RW + kTRCACATR15 = encode(0b10, 0b001, 0b0010, 0b1110, 0b011), // RW + kTRCACATR2 = encode(0b10, 0b001, 0b0010, 0b0100, 0b010), // RW + kTRCACATR3 = encode(0b10, 0b001, 0b0010, 0b0110, 0b010), // RW + kTRCACATR4 = encode(0b10, 0b001, 0b0010, 0b1000, 0b010), // RW + kTRCACATR5 = encode(0b10, 0b001, 0b0010, 0b1010, 0b010), // RW + kTRCACATR6 = encode(0b10, 0b001, 0b0010, 0b1100, 0b010), // RW + kTRCACATR7 = encode(0b10, 0b001, 0b0010, 0b1110, 0b010), // RW + kTRCACATR8 = encode(0b10, 0b001, 0b0010, 0b0000, 0b011), // RW + kTRCACATR9 = encode(0b10, 0b001, 0b0010, 0b0010, 0b011), // RW + kTRCACVR0 = encode(0b10, 0b001, 0b0010, 0b0000, 0b000), // RW + kTRCACVR1 = encode(0b10, 0b001, 0b0010, 0b0010, 0b000), // RW + kTRCACVR10 = encode(0b10, 0b001, 0b0010, 0b0100, 0b001), // RW + kTRCACVR11 = encode(0b10, 0b001, 0b0010, 0b0110, 0b001), // RW + kTRCACVR12 = encode(0b10, 0b001, 0b0010, 0b1000, 0b001), // RW + kTRCACVR13 = encode(0b10, 0b001, 0b0010, 0b1010, 0b001), // RW + kTRCACVR14 = encode(0b10, 0b001, 0b0010, 0b1100, 0b001), // RW + kTRCACVR15 = encode(0b10, 0b001, 0b0010, 0b1110, 0b001), // RW + kTRCACVR2 = encode(0b10, 0b001, 0b0010, 0b0100, 0b000), // RW + kTRCACVR3 = encode(0b10, 0b001, 0b0010, 0b0110, 0b000), // RW + kTRCACVR4 = encode(0b10, 0b001, 0b0010, 0b1000, 0b000), // RW + kTRCACVR5 = encode(0b10, 0b001, 0b0010, 0b1010, 0b000), // RW + kTRCACVR6 = encode(0b10, 0b001, 0b0010, 0b1100, 0b000), // RW + kTRCACVR7 = encode(0b10, 0b001, 0b0010, 0b1110, 0b000), // RW + kTRCACVR8 = encode(0b10, 0b001, 0b0010, 0b0000, 0b001), // RW + kTRCACVR9 = encode(0b10, 0b001, 0b0010, 0b0010, 0b001), // RW + kTRCAUTHSTATUS = encode(0b10, 0b001, 0b0111, 0b1110, 0b110), // RO + kTRCAUXCTLR = encode(0b10, 0b001, 0b0000, 0b0110, 0b000), // RW + kTRCBBCTLR = encode(0b10, 0b001, 0b0000, 0b1111, 0b000), // RW + kTRCCCCTLR = encode(0b10, 0b001, 0b0000, 0b1110, 0b000), // RW + kTRCCIDCCTLR0 = encode(0b10, 0b001, 0b0011, 0b0000, 0b010), // RW + kTRCCIDCCTLR1 = encode(0b10, 0b001, 0b0011, 0b0001, 0b010), // RW + kTRCCIDCVR0 = encode(0b10, 0b001, 0b0011, 0b0000, 0b000), // RW + kTRCCIDCVR1 = encode(0b10, 0b001, 0b0011, 0b0010, 0b000), // RW + kTRCCIDCVR2 = encode(0b10, 0b001, 0b0011, 0b0100, 0b000), // RW + kTRCCIDCVR3 = encode(0b10, 0b001, 0b0011, 0b0110, 0b000), // RW + kTRCCIDCVR4 = encode(0b10, 0b001, 0b0011, 0b1000, 0b000), // RW + kTRCCIDCVR5 = encode(0b10, 0b001, 0b0011, 0b1010, 0b000), // RW + kTRCCIDCVR6 = encode(0b10, 0b001, 0b0011, 0b1100, 0b000), // RW + kTRCCIDCVR7 = encode(0b10, 0b001, 0b0011, 0b1110, 0b000), // RW + kTRCCIDR0 = encode(0b10, 0b001, 0b0111, 0b1100, 0b111), // RO + kTRCCIDR1 = encode(0b10, 0b001, 0b0111, 0b1101, 0b111), // RO + kTRCCIDR2 = encode(0b10, 0b001, 0b0111, 0b1110, 0b111), // RO + kTRCCIDR3 = encode(0b10, 0b001, 0b0111, 0b1111, 0b111), // RO + kTRCCLAIMCLR = encode(0b10, 0b001, 0b0111, 0b1001, 0b110), // RW + kTRCCLAIMSET = encode(0b10, 0b001, 0b0111, 0b1000, 0b110), // RW + kTRCCNTCTLR0 = encode(0b10, 0b001, 0b0000, 0b0100, 0b101), // RW + kTRCCNTCTLR1 = encode(0b10, 0b001, 0b0000, 0b0101, 0b101), // RW + kTRCCNTCTLR2 = encode(0b10, 0b001, 0b0000, 0b0110, 0b101), // RW + kTRCCNTCTLR3 = encode(0b10, 0b001, 0b0000, 0b0111, 0b101), // RW + kTRCCNTRLDVR0 = encode(0b10, 0b001, 0b0000, 0b0000, 0b101), // RW + kTRCCNTRLDVR1 = encode(0b10, 0b001, 0b0000, 0b0001, 0b101), // RW + kTRCCNTRLDVR2 = encode(0b10, 0b001, 0b0000, 0b0010, 0b101), // RW + kTRCCNTRLDVR3 = encode(0b10, 0b001, 0b0000, 0b0011, 0b101), // RW + kTRCCNTVR0 = encode(0b10, 0b001, 0b0000, 0b1000, 0b101), // RW + kTRCCNTVR1 = encode(0b10, 0b001, 0b0000, 0b1001, 0b101), // RW + kTRCCNTVR2 = encode(0b10, 0b001, 0b0000, 0b1010, 0b101), // RW + kTRCCNTVR3 = encode(0b10, 0b001, 0b0000, 0b1011, 0b101), // RW + kTRCCONFIGR = encode(0b10, 0b001, 0b0000, 0b0100, 0b000), // RW + kTRCDEVAFF0 = encode(0b10, 0b001, 0b0111, 0b1010, 0b110), // RO + kTRCDEVAFF1 = encode(0b10, 0b001, 0b0111, 0b1011, 0b110), // RO + kTRCDEVARCH = encode(0b10, 0b001, 0b0111, 0b1111, 0b110), // RO + kTRCDEVID = encode(0b10, 0b001, 0b0111, 0b0010, 0b111), // RO + kTRCDEVTYPE = encode(0b10, 0b001, 0b0111, 0b0011, 0b111), // RO + kTRCDVCMR0 = encode(0b10, 0b001, 0b0010, 0b0000, 0b110), // RW + kTRCDVCMR1 = encode(0b10, 0b001, 0b0010, 0b0100, 0b110), // RW + kTRCDVCMR2 = encode(0b10, 0b001, 0b0010, 0b1000, 0b110), // RW + kTRCDVCMR3 = encode(0b10, 0b001, 0b0010, 0b1100, 0b110), // RW + kTRCDVCMR4 = encode(0b10, 0b001, 0b0010, 0b0000, 0b111), // RW + kTRCDVCMR5 = encode(0b10, 0b001, 0b0010, 0b0100, 0b111), // RW + kTRCDVCMR6 = encode(0b10, 0b001, 0b0010, 0b1000, 0b111), // RW + kTRCDVCMR7 = encode(0b10, 0b001, 0b0010, 0b1100, 0b111), // RW + kTRCDVCVR0 = encode(0b10, 0b001, 0b0010, 0b0000, 0b100), // RW + kTRCDVCVR1 = encode(0b10, 0b001, 0b0010, 0b0100, 0b100), // RW + kTRCDVCVR2 = encode(0b10, 0b001, 0b0010, 0b1000, 0b100), // RW + kTRCDVCVR3 = encode(0b10, 0b001, 0b0010, 0b1100, 0b100), // RW + kTRCDVCVR4 = encode(0b10, 0b001, 0b0010, 0b0000, 0b101), // RW + kTRCDVCVR5 = encode(0b10, 0b001, 0b0010, 0b0100, 0b101), // RW + kTRCDVCVR6 = encode(0b10, 0b001, 0b0010, 0b1000, 0b101), // RW + kTRCDVCVR7 = encode(0b10, 0b001, 0b0010, 0b1100, 0b101), // RW + kTRCEVENTCTL0R = encode(0b10, 0b001, 0b0000, 0b1000, 0b000), // RW + kTRCEVENTCTL1R = encode(0b10, 0b001, 0b0000, 0b1001, 0b000), // RW + kTRCEXTINSELR = encode(0b10, 0b001, 0b0000, 0b1000, 0b100), // RW + kTRCEXTINSELR0 = encode(0b10, 0b001, 0b0000, 0b1000, 0b100), // RW + kTRCEXTINSELR1 = encode(0b10, 0b001, 0b0000, 0b1001, 0b100), // RW + kTRCEXTINSELR2 = encode(0b10, 0b001, 0b0000, 0b1010, 0b100), // RW + kTRCEXTINSELR3 = encode(0b10, 0b001, 0b0000, 0b1011, 0b100), // RW + kTRCIDR0 = encode(0b10, 0b001, 0b0000, 0b1000, 0b111), // RO + kTRCIDR1 = encode(0b10, 0b001, 0b0000, 0b1001, 0b111), // RO + kTRCIDR10 = encode(0b10, 0b001, 0b0000, 0b0010, 0b110), // RO + kTRCIDR11 = encode(0b10, 0b001, 0b0000, 0b0011, 0b110), // RO + kTRCIDR12 = encode(0b10, 0b001, 0b0000, 0b0100, 0b110), // RO + kTRCIDR13 = encode(0b10, 0b001, 0b0000, 0b0101, 0b110), // RO + kTRCIDR2 = encode(0b10, 0b001, 0b0000, 0b1010, 0b111), // RO + kTRCIDR3 = encode(0b10, 0b001, 0b0000, 0b1011, 0b111), // RO + kTRCIDR4 = encode(0b10, 0b001, 0b0000, 0b1100, 0b111), // RO + kTRCIDR5 = encode(0b10, 0b001, 0b0000, 0b1101, 0b111), // RO + kTRCIDR6 = encode(0b10, 0b001, 0b0000, 0b1110, 0b111), // RO + kTRCIDR7 = encode(0b10, 0b001, 0b0000, 0b1111, 0b111), // RO + kTRCIDR8 = encode(0b10, 0b001, 0b0000, 0b0000, 0b110), // RO + kTRCIDR9 = encode(0b10, 0b001, 0b0000, 0b0001, 0b110), // RO + kTRCIMSPEC0 = encode(0b10, 0b001, 0b0000, 0b0000, 0b111), // RW + kTRCIMSPEC1 = encode(0b10, 0b001, 0b0000, 0b0001, 0b111), // RW + kTRCIMSPEC2 = encode(0b10, 0b001, 0b0000, 0b0010, 0b111), // RW + kTRCIMSPEC3 = encode(0b10, 0b001, 0b0000, 0b0011, 0b111), // RW + kTRCIMSPEC4 = encode(0b10, 0b001, 0b0000, 0b0100, 0b111), // RW + kTRCIMSPEC5 = encode(0b10, 0b001, 0b0000, 0b0101, 0b111), // RW + kTRCIMSPEC6 = encode(0b10, 0b001, 0b0000, 0b0110, 0b111), // RW + kTRCIMSPEC7 = encode(0b10, 0b001, 0b0000, 0b0111, 0b111), // RW + kTRCITCTRL = encode(0b10, 0b001, 0b0111, 0b0000, 0b100), // RW + kTRCLAR = encode(0b10, 0b001, 0b0111, 0b1100, 0b110), // WO + kTRCLSR = encode(0b10, 0b001, 0b0111, 0b1101, 0b110), // RO + kTRCOSLAR = encode(0b10, 0b001, 0b0001, 0b0000, 0b100), // WO + kTRCOSLSR = encode(0b10, 0b001, 0b0001, 0b0001, 0b100), // RO + kTRCPDCR = encode(0b10, 0b001, 0b0001, 0b0100, 0b100), // RW + kTRCPDSR = encode(0b10, 0b001, 0b0001, 0b0101, 0b100), // RO + kTRCPIDR0 = encode(0b10, 0b001, 0b0111, 0b1000, 0b111), // RO + kTRCPIDR1 = encode(0b10, 0b001, 0b0111, 0b1001, 0b111), // RO + kTRCPIDR2 = encode(0b10, 0b001, 0b0111, 0b1010, 0b111), // RO + kTRCPIDR3 = encode(0b10, 0b001, 0b0111, 0b1011, 0b111), // RO + kTRCPIDR4 = encode(0b10, 0b001, 0b0111, 0b0100, 0b111), // RO + kTRCPIDR5 = encode(0b10, 0b001, 0b0111, 0b0101, 0b111), // RO + kTRCPIDR6 = encode(0b10, 0b001, 0b0111, 0b0110, 0b111), // RO + kTRCPIDR7 = encode(0b10, 0b001, 0b0111, 0b0111, 0b111), // RO + kTRCPRGCTLR = encode(0b10, 0b001, 0b0000, 0b0001, 0b000), // RW + kTRCPROCSELR = encode(0b10, 0b001, 0b0000, 0b0010, 0b000), // RW + kTRCQCTLR = encode(0b10, 0b001, 0b0000, 0b0001, 0b001), // RW + kTRCRSCTLR10 = encode(0b10, 0b001, 0b0001, 0b1010, 0b000), // RW + kTRCRSCTLR11 = encode(0b10, 0b001, 0b0001, 0b1011, 0b000), // RW + kTRCRSCTLR12 = encode(0b10, 0b001, 0b0001, 0b1100, 0b000), // RW + kTRCRSCTLR13 = encode(0b10, 0b001, 0b0001, 0b1101, 0b000), // RW + kTRCRSCTLR14 = encode(0b10, 0b001, 0b0001, 0b1110, 0b000), // RW + kTRCRSCTLR15 = encode(0b10, 0b001, 0b0001, 0b1111, 0b000), // RW + kTRCRSCTLR16 = encode(0b10, 0b001, 0b0001, 0b0000, 0b001), // RW + kTRCRSCTLR17 = encode(0b10, 0b001, 0b0001, 0b0001, 0b001), // RW + kTRCRSCTLR18 = encode(0b10, 0b001, 0b0001, 0b0010, 0b001), // RW + kTRCRSCTLR19 = encode(0b10, 0b001, 0b0001, 0b0011, 0b001), // RW + kTRCRSCTLR2 = encode(0b10, 0b001, 0b0001, 0b0010, 0b000), // RW + kTRCRSCTLR20 = encode(0b10, 0b001, 0b0001, 0b0100, 0b001), // RW + kTRCRSCTLR21 = encode(0b10, 0b001, 0b0001, 0b0101, 0b001), // RW + kTRCRSCTLR22 = encode(0b10, 0b001, 0b0001, 0b0110, 0b001), // RW + kTRCRSCTLR23 = encode(0b10, 0b001, 0b0001, 0b0111, 0b001), // RW + kTRCRSCTLR24 = encode(0b10, 0b001, 0b0001, 0b1000, 0b001), // RW + kTRCRSCTLR25 = encode(0b10, 0b001, 0b0001, 0b1001, 0b001), // RW + kTRCRSCTLR26 = encode(0b10, 0b001, 0b0001, 0b1010, 0b001), // RW + kTRCRSCTLR27 = encode(0b10, 0b001, 0b0001, 0b1011, 0b001), // RW + kTRCRSCTLR28 = encode(0b10, 0b001, 0b0001, 0b1100, 0b001), // RW + kTRCRSCTLR29 = encode(0b10, 0b001, 0b0001, 0b1101, 0b001), // RW + kTRCRSCTLR3 = encode(0b10, 0b001, 0b0001, 0b0011, 0b000), // RW + kTRCRSCTLR30 = encode(0b10, 0b001, 0b0001, 0b1110, 0b001), // RW + kTRCRSCTLR31 = encode(0b10, 0b001, 0b0001, 0b1111, 0b001), // RW + kTRCRSCTLR4 = encode(0b10, 0b001, 0b0001, 0b0100, 0b000), // RW + kTRCRSCTLR5 = encode(0b10, 0b001, 0b0001, 0b0101, 0b000), // RW + kTRCRSCTLR6 = encode(0b10, 0b001, 0b0001, 0b0110, 0b000), // RW + kTRCRSCTLR7 = encode(0b10, 0b001, 0b0001, 0b0111, 0b000), // RW + kTRCRSCTLR8 = encode(0b10, 0b001, 0b0001, 0b1000, 0b000), // RW + kTRCRSCTLR9 = encode(0b10, 0b001, 0b0001, 0b1001, 0b000), // RW + kTRCRSR = encode(0b10, 0b001, 0b0000, 0b1010, 0b000), // RW + kTRCSEQEVR0 = encode(0b10, 0b001, 0b0000, 0b0000, 0b100), // RW + kTRCSEQEVR1 = encode(0b10, 0b001, 0b0000, 0b0001, 0b100), // RW + kTRCSEQEVR2 = encode(0b10, 0b001, 0b0000, 0b0010, 0b100), // RW + kTRCSEQRSTEVR = encode(0b10, 0b001, 0b0000, 0b0110, 0b100), // RW + kTRCSEQSTR = encode(0b10, 0b001, 0b0000, 0b0111, 0b100), // RW + kTRCSSCCR0 = encode(0b10, 0b001, 0b0001, 0b0000, 0b010), // RW + kTRCSSCCR1 = encode(0b10, 0b001, 0b0001, 0b0001, 0b010), // RW + kTRCSSCCR2 = encode(0b10, 0b001, 0b0001, 0b0010, 0b010), // RW + kTRCSSCCR3 = encode(0b10, 0b001, 0b0001, 0b0011, 0b010), // RW + kTRCSSCCR4 = encode(0b10, 0b001, 0b0001, 0b0100, 0b010), // RW + kTRCSSCCR5 = encode(0b10, 0b001, 0b0001, 0b0101, 0b010), // RW + kTRCSSCCR6 = encode(0b10, 0b001, 0b0001, 0b0110, 0b010), // RW + kTRCSSCCR7 = encode(0b10, 0b001, 0b0001, 0b0111, 0b010), // RW + kTRCSSCSR0 = encode(0b10, 0b001, 0b0001, 0b1000, 0b010), // RW + kTRCSSCSR1 = encode(0b10, 0b001, 0b0001, 0b1001, 0b010), // RW + kTRCSSCSR2 = encode(0b10, 0b001, 0b0001, 0b1010, 0b010), // RW + kTRCSSCSR3 = encode(0b10, 0b001, 0b0001, 0b1011, 0b010), // RW + kTRCSSCSR4 = encode(0b10, 0b001, 0b0001, 0b1100, 0b010), // RW + kTRCSSCSR5 = encode(0b10, 0b001, 0b0001, 0b1101, 0b010), // RW + kTRCSSCSR6 = encode(0b10, 0b001, 0b0001, 0b1110, 0b010), // RW + kTRCSSCSR7 = encode(0b10, 0b001, 0b0001, 0b1111, 0b010), // RW + kTRCSSPCICR0 = encode(0b10, 0b001, 0b0001, 0b0000, 0b011), // RW + kTRCSSPCICR1 = encode(0b10, 0b001, 0b0001, 0b0001, 0b011), // RW + kTRCSSPCICR2 = encode(0b10, 0b001, 0b0001, 0b0010, 0b011), // RW + kTRCSSPCICR3 = encode(0b10, 0b001, 0b0001, 0b0011, 0b011), // RW + kTRCSSPCICR4 = encode(0b10, 0b001, 0b0001, 0b0100, 0b011), // RW + kTRCSSPCICR5 = encode(0b10, 0b001, 0b0001, 0b0101, 0b011), // RW + kTRCSSPCICR6 = encode(0b10, 0b001, 0b0001, 0b0110, 0b011), // RW + kTRCSSPCICR7 = encode(0b10, 0b001, 0b0001, 0b0111, 0b011), // RW + kTRCSTALLCTLR = encode(0b10, 0b001, 0b0000, 0b1011, 0b000), // RW + kTRCSTATR = encode(0b10, 0b001, 0b0000, 0b0011, 0b000), // RO + kTRCSYNCPR = encode(0b10, 0b001, 0b0000, 0b1101, 0b000), // RW + kTRCTRACEIDR = encode(0b10, 0b001, 0b0000, 0b0000, 0b001), // RW + kTRCTSCTLR = encode(0b10, 0b001, 0b0000, 0b1100, 0b000), // RW + kTRCVDARCCTLR = encode(0b10, 0b001, 0b0000, 0b1010, 0b010), // RW + kTRCVDCTLR = encode(0b10, 0b001, 0b0000, 0b1000, 0b010), // RW + kTRCVDSACCTLR = encode(0b10, 0b001, 0b0000, 0b1001, 0b010), // RW + kTRCVICTLR = encode(0b10, 0b001, 0b0000, 0b0000, 0b010), // RW + kTRCVIIECTLR = encode(0b10, 0b001, 0b0000, 0b0001, 0b010), // RW + kTRCVIPCSSCTLR = encode(0b10, 0b001, 0b0000, 0b0011, 0b010), // RW + kTRCVISSCTLR = encode(0b10, 0b001, 0b0000, 0b0010, 0b010), // RW + kTRCVMIDCCTLR0 = encode(0b10, 0b001, 0b0011, 0b0010, 0b010), // RW + kTRCVMIDCCTLR1 = encode(0b10, 0b001, 0b0011, 0b0011, 0b010), // RW + kTRCVMIDCVR0 = encode(0b10, 0b001, 0b0011, 0b0000, 0b001), // RW + kTRCVMIDCVR1 = encode(0b10, 0b001, 0b0011, 0b0010, 0b001), // RW + kTRCVMIDCVR2 = encode(0b10, 0b001, 0b0011, 0b0100, 0b001), // RW + kTRCVMIDCVR3 = encode(0b10, 0b001, 0b0011, 0b0110, 0b001), // RW + kTRCVMIDCVR4 = encode(0b10, 0b001, 0b0011, 0b1000, 0b001), // RW + kTRCVMIDCVR5 = encode(0b10, 0b001, 0b0011, 0b1010, 0b001), // RW + kTRCVMIDCVR6 = encode(0b10, 0b001, 0b0011, 0b1100, 0b001), // RW + kTRCVMIDCVR7 = encode(0b10, 0b001, 0b0011, 0b1110, 0b001), // RW + kTRFCR_EL1 = encode(0b11, 0b000, 0b0001, 0b0010, 0b001), // RW + kTRFCR_EL12 = encode(0b11, 0b101, 0b0001, 0b0010, 0b001), // RW + kTRFCR_EL2 = encode(0b11, 0b100, 0b0001, 0b0010, 0b001), // RW + kTTBR0_EL1 = encode(0b11, 0b000, 0b0010, 0b0000, 0b000), // RW + kTTBR0_EL12 = encode(0b11, 0b101, 0b0010, 0b0000, 0b000), // RW + kTTBR0_EL2 = encode(0b11, 0b100, 0b0010, 0b0000, 0b000), // RW + kTTBR0_EL3 = encode(0b11, 0b110, 0b0010, 0b0000, 0b000), // RW + kTTBR1_EL1 = encode(0b11, 0b000, 0b0010, 0b0000, 0b001), // RW + kTTBR1_EL12 = encode(0b11, 0b101, 0b0010, 0b0000, 0b001), // RW + kTTBR1_EL2 = encode(0b11, 0b100, 0b0010, 0b0000, 0b001), // RW + kUAO = encode(0b11, 0b000, 0b0100, 0b0010, 0b100), // RW + kVBAR_EL1 = encode(0b11, 0b000, 0b1100, 0b0000, 0b000), // RW + kVBAR_EL12 = encode(0b11, 0b101, 0b1100, 0b0000, 0b000), // RW + kVBAR_EL2 = encode(0b11, 0b100, 0b1100, 0b0000, 0b000), // RW + kVBAR_EL3 = encode(0b11, 0b110, 0b1100, 0b0000, 0b000), // RW + kVDISR_EL2 = encode(0b11, 0b100, 0b1100, 0b0001, 0b001), // RW + kVMPIDR_EL2 = encode(0b11, 0b100, 0b0000, 0b0000, 0b101), // RW + kVNCR_EL2 = encode(0b11, 0b100, 0b0010, 0b0010, 0b000), // RW + kVPIDR_EL2 = encode(0b11, 0b100, 0b0000, 0b0000, 0b000), // RW + kVSESR_EL2 = encode(0b11, 0b100, 0b0101, 0b0010, 0b011), // RW + kVSTCR_EL2 = encode(0b11, 0b100, 0b0010, 0b0110, 0b010), // RW + kVSTTBR_EL2 = encode(0b11, 0b100, 0b0010, 0b0110, 0b000), // RW + kVTCR_EL2 = encode(0b11, 0b100, 0b0010, 0b0001, 0b010), // RW + kVTTBR_EL2 = encode(0b11, 0b100, 0b0010, 0b0001, 0b000), // RW + kZCR_EL1 = encode(0b11, 0b000, 0b0001, 0b0010, 0b000), // RW + kZCR_EL12 = encode(0b11, 0b101, 0b0001, 0b0010, 0b000), // RW + kZCR_EL2 = encode(0b11, 0b100, 0b0001, 0b0010, 0b000), // RW + kZCR_EL3 = encode(0b11, 0b110, 0b0001, 0b0010, 0b000) // RW + }; +}; + +} // {Predicate} + +//! \} + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_A64GLOBALS_H_INCLUDED diff --git a/src/asmjit/arm/a64instapi.cpp b/src/asmjit/arm/a64instapi.cpp new file mode 100644 index 0000000..dc98bc8 --- /dev/null +++ b/src/asmjit/arm/a64instapi.cpp @@ -0,0 +1,278 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#if !defined(ASMJIT_NO_AARCH64) + +#include "../core/cpuinfo.h" +#include "../core/misc_p.h" +#include "../core/support.h" +#include "../arm/a64instapi_p.h" +#include "../arm/a64instdb_p.h" +#include "../arm/a64operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +// a64::InstInternal - Text +// ======================== + +#ifndef ASMJIT_NO_TEXT +Error InstInternal::instIdToString(Arch arch, InstId instId, String& output) noexcept { + uint32_t realId = instId & uint32_t(InstIdParts::kRealId); + DebugUtils::unused(arch); + + if (ASMJIT_UNLIKELY(!Inst::isDefinedId(realId))) + return DebugUtils::errored(kErrorInvalidInstruction); + + const InstDB::InstInfo& info = InstDB::infoById(realId); + return output.append(InstDB::_nameData + info._nameDataIndex); +} + +InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept { + DebugUtils::unused(arch); + + if (ASMJIT_UNLIKELY(!s)) + return Inst::kIdNone; + + if (len == SIZE_MAX) + len = strlen(s); + + if (ASMJIT_UNLIKELY(len == 0 || len > InstDB::kMaxNameSize)) + return Inst::kIdNone; + + uint32_t prefix = uint32_t(s[0]) - 'a'; + if (ASMJIT_UNLIKELY(prefix > 'z' - 'a')) + return Inst::kIdNone; + + uint32_t index = InstDB::instNameIndex[prefix].start; + if (ASMJIT_UNLIKELY(!index)) + return Inst::kIdNone; + + const char* nameData = InstDB::_nameData; + const InstDB::InstInfo* table = InstDB::_instInfoTable; + + const InstDB::InstInfo* base = table + index; + const InstDB::InstInfo* end = table + InstDB::instNameIndex[prefix].end; + + for (size_t lim = (size_t)(end - base); lim != 0; lim >>= 1) { + const InstDB::InstInfo* cur = base + (lim >> 1); + int result = Support::cmpInstName(nameData + cur[0]._nameDataIndex, s, len); + + if (result < 0) { + base = cur + 1; + lim--; + continue; + } + + if (result > 0) + continue; + + return uint32_t((size_t)(cur - table)); + } + + return Inst::kIdNone; +} +#endif // !ASMJIT_NO_TEXT + +// a64::InstInternal - Validate +// ============================ + +#ifndef ASMJIT_NO_VALIDATION +ASMJIT_FAVOR_SIZE Error InstInternal::validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept { + // TODO: + DebugUtils::unused(arch, inst, operands, opCount, validationFlags); + return kErrorOk; +} +#endif // !ASMJIT_NO_VALIDATION + +// a64::InstInternal - QueryRWInfo +// =============================== + +#ifndef ASMJIT_NO_INTROSPECTION +struct InstRWInfoData { + uint8_t rwx[Globals::kMaxOpCount]; +}; + +static const InstRWInfoData instRWInfoData[] = { + #define R uint8_t(OpRWFlags::kRead) + #define W uint8_t(OpRWFlags::kWrite) + #define X uint8_t(OpRWFlags::kRW) + + {{ R, R, R, R, R, R }}, // kRWI_R + {{ R, W, R, R, R, R }}, // kRWI_RW + {{ R, X, R, R, R, R }}, // kRWI_RX + {{ R, R, W, R, R, R }}, // kRWI_RRW + {{ R, W, X, R, R, R }}, // kRWI_RWX + {{ W, R, R, R, R, R }}, // kRWI_W + {{ W, R, W, R, R, R }}, // kRWI_WRW + {{ W, R, X, R, R, R }}, // kRWI_WRX + {{ W, R, R, W, R, R }}, // kRWI_WRRW + {{ W, R, R, X, R, R }}, // kRWI_WRRX + {{ W, W, R, R, R, R }}, // kRWI_WW + {{ X, R, R, R, R, R }}, // kRWI_X + {{ X, R, X, R, R, R }}, // kRWI_XRX + {{ X, X, R, R, X, R }}, // kRWI_XXRRX + + {{ W, R, R, R, R, R }}, // kRWI_LDn + {{ R, W, R, R, R, R }}, // kRWI_STn + {{ R, R, R, R, R, R }} // kRWI_TODO + + #undef R + #undef W + #undef X +}; + +static const uint8_t elementTypeSize[8] = { 0, 1, 2, 4, 8, 4, 4, 0 }; + +Error InstInternal::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { + // Unused in Release configuration as the assert is not compiled in. + DebugUtils::unused(arch); + + // Only called when `arch` matches X86 family. + ASMJIT_ASSERT(Environment::isFamilyARM(arch)); + + // Get the instruction data. + uint32_t realId = inst.id() & uint32_t(InstIdParts::kRealId); + + if (ASMJIT_UNLIKELY(!Inst::isDefinedId(realId))) + return DebugUtils::errored(kErrorInvalidInstruction); + + out->_instFlags = 0; + out->_opCount = uint8_t(opCount); + out->_rmFeature = 0; + out->_extraReg.reset(); + out->_readFlags = CpuRWFlags::kNone; // TODO: [ARM] Read PSTATUS. + out->_writeFlags = CpuRWFlags::kNone; // TODO: [ARM] Write PSTATUS + + const InstDB::InstInfo& instInfo = InstDB::_instInfoTable[realId]; + const InstRWInfoData& rwInfo = instRWInfoData[instInfo.rwInfoIndex()]; + + if (instInfo.hasFlag(InstDB::kInstFlagConsecutive) && opCount > 2) { + for (uint32_t i = 0; i < opCount; i++) { + OpRWInfo& op = out->_operands[i]; + const Operand_& srcOp = operands[i]; + + if (!srcOp.isRegOrMem()) { + op.reset(); + continue; + } + + OpRWFlags rwFlags = i < opCount - 1 ? (OpRWFlags)rwInfo.rwx[0] : (OpRWFlags)rwInfo.rwx[1]; + + op._opFlags = rwFlags & ~(OpRWFlags::kZExt); + op._physId = BaseReg::kIdBad; + op._rmSize = 0; + op._resetReserved(); + + uint64_t rByteMask = op.isRead() ? 0xFFFFFFFFFFFFFFFFu : 0x0000000000000000u; + uint64_t wByteMask = op.isWrite() ? 0xFFFFFFFFFFFFFFFFu : 0x0000000000000000u; + + op._readByteMask = rByteMask; + op._writeByteMask = wByteMask; + op._extendByteMask = 0; + op._consecutiveLeadCount = 0; + + if (srcOp.isReg()) { + if (i == 0) + op._consecutiveLeadCount = uint8_t(opCount - 1); + else + op.addOpFlags(OpRWFlags::kConsecutive); + } + else { + const Mem& memOp = srcOp.as<Mem>(); + + if (memOp.hasBase()) { + op.addOpFlags(OpRWFlags::kMemBaseRead); + } + + if (memOp.hasIndex()) { + op.addOpFlags(OpRWFlags::kMemIndexRead); + op.addOpFlags(memOp.isPreOrPost() ? OpRWFlags::kMemIndexWrite : OpRWFlags::kNone); + } + } + } + } + else { + for (uint32_t i = 0; i < opCount; i++) { + OpRWInfo& op = out->_operands[i]; + const Operand_& srcOp = operands[i]; + + if (!srcOp.isRegOrMem()) { + op.reset(); + continue; + } + + OpRWFlags rwFlags = (OpRWFlags)rwInfo.rwx[i]; + + op._opFlags = rwFlags & ~(OpRWFlags::kZExt); + op._physId = BaseReg::kIdBad; + op._rmSize = 0; + op._resetReserved(); + + uint64_t rByteMask = op.isRead() ? 0xFFFFFFFFFFFFFFFFu : 0x0000000000000000u; + uint64_t wByteMask = op.isWrite() ? 0xFFFFFFFFFFFFFFFFu : 0x0000000000000000u; + + op._readByteMask = rByteMask; + op._writeByteMask = wByteMask; + op._extendByteMask = 0; + op._consecutiveLeadCount = 0; + + if (srcOp.isReg()) { + if (srcOp.as<Vec>().hasElementIndex()) { + // Only part of the vector is accessed if element index [] is used. + uint32_t elementType = srcOp.as<Vec>().elementType(); + uint32_t elementIndex = srcOp.as<Vec>().elementIndex(); + + uint32_t elementSize = elementTypeSize[elementType]; + uint64_t accessMask = uint64_t(Support::lsbMask<uint32_t>(elementSize)) << (elementIndex * elementSize); + + op._readByteMask &= accessMask; + op._writeByteMask &= accessMask; + } + + // TODO: [ARM] RW info is not finished. + } + else { + const Mem& memOp = srcOp.as<Mem>(); + + if (memOp.hasBase()) { + op.addOpFlags(OpRWFlags::kMemBaseRead); + } + + if (memOp.hasIndex()) { + op.addOpFlags(OpRWFlags::kMemIndexRead); + op.addOpFlags(memOp.isPreOrPost() ? OpRWFlags::kMemIndexWrite : OpRWFlags::kNone); + } + } + } + } + + return kErrorOk; +} +#endif // !ASMJIT_NO_INTROSPECTION + +// a64::InstInternal - QueryFeatures +// ================================= + +#ifndef ASMJIT_NO_INTROSPECTION +Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept { + // TODO: [ARM] QueryFeatures not implemented yet. + DebugUtils::unused(arch, inst, operands, opCount, out); + return kErrorOk; +} +#endif // !ASMJIT_NO_INTROSPECTION + +// a64::InstInternal - Unit +// ======================== + +#if defined(ASMJIT_TEST) +UNIT(arm_inst_api_text) { + // TODO: +} +#endif + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_AARCH64 diff --git a/src/asmjit/arm/a64instapi_p.h b/src/asmjit/arm/a64instapi_p.h new file mode 100644 index 0000000..320a3e8 --- /dev/null +++ b/src/asmjit/arm/a64instapi_p.h @@ -0,0 +1,41 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64INSTAPI_P_H_INCLUDED +#define ASMJIT_ARM_A64INSTAPI_P_H_INCLUDED + +#include "../core/inst.h" +#include "../core/operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \cond INTERNAL +//! \addtogroup asmjit_a64 +//! \{ + +namespace InstInternal { + +#ifndef ASMJIT_NO_TEXT +Error ASMJIT_CDECL instIdToString(Arch arch, InstId instId, String& output) noexcept; +InstId ASMJIT_CDECL stringToInstId(Arch arch, const char* s, size_t len) noexcept; +#endif // !ASMJIT_NO_TEXT + +#ifndef ASMJIT_NO_VALIDATION +Error ASMJIT_CDECL validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; +#endif // !ASMJIT_NO_VALIDATION + +#ifndef ASMJIT_NO_INTROSPECTION +Error ASMJIT_CDECL queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; +Error ASMJIT_CDECL queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept; +#endif // !ASMJIT_NO_INTROSPECTION + +} // {InstInternal} + +//! \} +//! \endcond + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_A64INSTAPI_P_H_INCLUDED diff --git a/src/asmjit/arm/a64instdb.cpp b/src/asmjit/arm/a64instdb.cpp new file mode 100644 index 0000000..64709b5 --- /dev/null +++ b/src/asmjit/arm/a64instdb.cpp @@ -0,0 +1,1957 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#if !defined(ASMJIT_NO_AARCH64) + +#include "../core/codeholder.h" +#include "../core/support.h" +#include "../arm/a64instdb_p.h" +#include "../arm/a64operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +namespace InstDB { + +// a64::InstDB - InstInfoTable +// =========================== + +// Don't store `_nameDataIndex` if instruction names are disabled. Since some +// APIs can use `_nameDataIndex` it's much safer if it's zero if it's not used. +#if defined(ASMJIT_NO_TEXT) + #define NAME_DATA_INDEX(x) 0 +#else + #define NAME_DATA_INDEX(x) x +#endif + +// Defines an ARM/AArch64 instruction. +#define INST(id, opcodeEncoding, opcodeData, rwInfoIndex, flags, opcodeDataIndex, nameDataIndex) { \ + uint32_t(kEncoding##opcodeEncoding), \ + uint32_t(opcodeDataIndex), \ + 0, \ + uint32_t(NAME_DATA_INDEX(nameDataIndex)), \ + uint16_t(rwInfoIndex), \ + uint16_t(flags) \ +} + +#define F(flag) kInstFlag##flag + +// TODO: [ARM] Missing Instructions: +/* +BLRAA, BLRAAZ, BLRAB, BLRABZ: Branch with Link to Register, with pointer authentication. +BRAA, BRAAZ, BRAB, BRABZ: Branch to Register, with pointer authentication. + +CFP: Control Flow Prediction Restriction by Context: an alias of SYS. +CPP: Cache Prefetch Prediction Restriction by Context: an alias of SYS. +DVP: Data Value Prediction Restriction by Context: an alias of SYS. +PSB CSYNC: Profiling Synchronization Barrier. + +ERETAA, ERETAB: Exception Return, with pointer authentication. +LDAPxxx +PACIA, PACIA1716, PACIASP, PACIAZ, PACIZA: Pointer Authentication Code for Instruction address, using key A. +PACIB, PACIB1716, PACIBSP, PACIBZ, PACIZB: Pointer Authentication Code for Instruction address, using key B. +PRFM (immediate): Prefetch Memory (immediate). +PRFM (literal): Prefetch Memory (literal). +PRFM (register): Prefetch Memory (register). +PRFUM: Prefetch Memory (unscaled offset). +RETAA, RETAB: Return from subroutine, with pointer authentication. +RMIF: Rotate, Mask Insert Flags. +SYSL +IRG: Insert Random Tag. +INST_(Irg , BaseRRR , (0b1001101011000000000100, kX , kSP, kX , kSP, kX , kZR, true) , kRWI_W , 0 , 0 , 1 ), // #1 +*/ +const InstInfo _instInfoTable[] = { + // +------------------+---------------------+--------------------------------------------------------------------------------------+-----------+---------------------------+----+-----+ + // | Instruction Id | Encoding | Opcode Data | RW Info | Instruction Flags |DatX|NameX| + // +------------------+---------------------+--------------------------------------------------------------------------------------+-----------+---------------------------+----+-----+ + // ${InstInfo:Begin} + INST(None , None , (_) , 0 , 0 , 0 , 0 ), // #0 + INST(Adc , BaseRRR , (0b0001101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 0 , 1 ), // #1 + INST(Adcs , BaseRRR , (0b0011101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 1 , 5 ), // #2 + INST(Add , BaseAddSub , (0b0001011000, 0b0001011001, 0b0010001) , kRWI_W , 0 , 0 , 978 ), // #3 + INST(Addg , BaseRRII , (0b1001000110000000000000, kX, kSP, kX, kSP, 6, 4, 16, 4, 0, 10) , kRWI_W , 0 , 0 , 10 ), // #4 + INST(Adds , BaseAddSub , (0b0101011000, 0b0101011001, 0b0110001) , kRWI_W , 0 , 1 , 15 ), // #5 + INST(Adr , BaseAdr , (0b0001000000000000000000, OffsetType::kAArch64_ADR) , kRWI_W , 0 , 0 , 25 ), // #6 + INST(Adrp , BaseAdr , (0b1001000000000000000000, OffsetType::kAArch64_ADRP) , kRWI_W , 0 , 1 , 29 ), // #7 + INST(And , BaseLogical , (0b0001010000, 0b00100100, 0) , kRWI_W , 0 , 0 , 57 ), // #8 + INST(Ands , BaseLogical , (0b1101010000, 0b11100100, 0) , kRWI_W , 0 , 1 , 61 ), // #9 + INST(Asr , BaseShift , (0b0001101011000000001010, 0b0001001100000000011111, 0) , kRWI_W , 0 , 0 , 66 ), // #10 + INST(Asrv , BaseShift , (0b0001101011000000001010, 0b0000000000000000000000, 0) , kRWI_W , 0 , 1 , 70 ), // #11 + INST(At , BaseAtDcIcTlbi , (0b00011111110000, 0b00001111000000, true) , kRWI_RX , 0 , 0 , 75 ), // #12 + INST(Autda , BaseRR , (0b11011010110000010001100000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 0 , 78 ), // #13 + INST(Autdza , BaseR , (0b11011010110000010011101111100000, kX, kZR, 0) , kRWI_X , 0 , 0 , 90 ), // #14 + INST(Autdb , BaseRR , (0b11011010110000010001110000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 1 , 84 ), // #15 + INST(Autdzb , BaseR , (0b11011010110000010011111111100000, kX, kZR, 0) , kRWI_X , 0 , 1 , 97 ), // #16 + INST(Autia , BaseRR , (0b11011010110000010001000000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 2 , 104 ), // #17 + INST(Autia1716 , BaseOp , (0b11010101000000110010000110011111) , 0 , 0 , 0 , 110 ), // #18 + INST(Autiasp , BaseOp , (0b11010101000000110010001110111111) , 0 , 0 , 1 , 120 ), // #19 + INST(Autiaz , BaseOp , (0b11010101000000110010001110011111) , 0 , 0 , 2 , 128 ), // #20 + INST(Autib , BaseRR , (0b11011010110000010001010000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 3 , 135 ), // #21 + INST(Autib1716 , BaseOp , (0b11010101000000110010000111011111) , 0 , 0 , 3 , 141 ), // #22 + INST(Autibsp , BaseOp , (0b11010101000000110010001111111111) , 0 , 0 , 4 , 151 ), // #23 + INST(Autibz , BaseOp , (0b11010101000000110010001111011111) , 0 , 0 , 5 , 159 ), // #24 + INST(Autiza , BaseR , (0b11011010110000010011001111100000, kX, kZR, 0) , kRWI_X , 0 , 2 , 166 ), // #25 + INST(Autizb , BaseR , (0b11011010110000010011011111100000, kX, kZR, 0) , kRWI_X , 0 , 3 , 173 ), // #26 + INST(Axflag , BaseOp , (0b11010101000000000100000001011111) , 0 , 0 , 6 , 180 ), // #27 + INST(B , BaseBranchRel , (0b00010100000000000000000000000000) , 0 , F(Cond) , 0 , 1738), // #28 + INST(Bfc , BaseBfc , (0b00110011000000000000001111100000) , kRWI_X , 0 , 0 , 192 ), // #29 + INST(Bfi , BaseBfi , (0b00110011000000000000000000000000) , kRWI_X , 0 , 0 , 223 ), // #30 + INST(Bfm , BaseBfm , (0b00110011000000000000000000000000) , kRWI_X , 0 , 0 , 2514), // #31 + INST(Bfxil , BaseBfx , (0b00110011000000000000000000000000) , kRWI_X , 0 , 0 , 250 ), // #32 + INST(Bic , BaseLogical , (0b0001010001, 0b00100100, 1) , kRWI_W , 0 , 2 , 256 ), // #33 + INST(Bics , BaseLogical , (0b1101010001, 0b11100100, 1) , kRWI_W , 0 , 3 , 260 ), // #34 + INST(Bl , BaseBranchRel , (0b10010100000000000000000000000000) , 0 , 0 , 1 , 2831), // #35 + INST(Blr , BaseBranchReg , (0b11010110001111110000000000000000) , kRWI_R , 0 , 0 , 269 ), // #36 + INST(Br , BaseBranchReg , (0b11010110000111110000000000000000) , kRWI_R , 0 , 1 , 273 ), // #37 + INST(Brk , BaseOpImm , (0b11010100001000000000000000000000, 16, 5) , 0 , 0 , 0 , 276 ), // #38 + INST(Cas , BaseAtomicOp , (0b1000100010100000011111, kWX, 30, 0) , kRWI_XRX , 0 , 0 , 284 ), // #39 + INST(Casa , BaseAtomicOp , (0b1000100011100000011111, kWX, 30, 1) , kRWI_XRX , 0 , 1 , 288 ), // #40 + INST(Casab , BaseAtomicOp , (0b0000100011100000011111, kW , 0 , 1) , kRWI_XRX , 0 , 2 , 293 ), // #41 + INST(Casah , BaseAtomicOp , (0b0100100011100000011111, kW , 0 , 1) , kRWI_XRX , 0 , 3 , 299 ), // #42 + INST(Casal , BaseAtomicOp , (0b1000100011100000111111, kWX, 30, 1) , kRWI_XRX , 0 , 4 , 305 ), // #43 + INST(Casalb , BaseAtomicOp , (0b0000100011100000111111, kW , 0 , 1) , kRWI_XRX , 0 , 5 , 311 ), // #44 + INST(Casalh , BaseAtomicOp , (0b0100100011100000111111, kW , 0 , 1) , kRWI_XRX , 0 , 6 , 318 ), // #45 + INST(Casb , BaseAtomicOp , (0b0000100010100000011111, kW , 0 , 0) , kRWI_XRX , 0 , 7 , 325 ), // #46 + INST(Cash , BaseAtomicOp , (0b0100100010100000011111, kW , 0 , 0) , kRWI_XRX , 0 , 8 , 330 ), // #47 + INST(Casl , BaseAtomicOp , (0b1000100010100000111111, kWX, 30, 0) , kRWI_XRX , 0 , 9 , 335 ), // #48 + INST(Caslb , BaseAtomicOp , (0b0000100010100000111111, kW , 0 , 0) , kRWI_XRX , 0 , 10 , 340 ), // #49 + INST(Caslh , BaseAtomicOp , (0b0100100010100000111111, kW , 0 , 0) , kRWI_XRX , 0 , 11 , 346 ), // #50 + INST(Casp , BaseAtomicCasp , (0b0000100000100000011111, kWX, 30) , kRWI_XXRRX, 0 , 0 , 352 ), // #51 + INST(Caspa , BaseAtomicCasp , (0b0000100001100000011111, kWX, 30) , kRWI_XXRRX, 0 , 1 , 357 ), // #52 + INST(Caspal , BaseAtomicCasp , (0b0000100001100000111111, kWX, 30) , kRWI_XXRRX, 0 , 2 , 363 ), // #53 + INST(Caspl , BaseAtomicCasp , (0b0000100000100000111111, kWX, 30) , kRWI_XXRRX, 0 , 3 , 370 ), // #54 + INST(Cbnz , BaseBranchCmp , (0b00110101000000000000000000000000) , kRWI_R , 0 , 0 , 376 ), // #55 + INST(Cbz , BaseBranchCmp , (0b00110100000000000000000000000000) , kRWI_R , 0 , 1 , 381 ), // #56 + INST(Ccmn , BaseCCmp , (0b00111010010000000000000000000000) , kRWI_R , 0 , 0 , 385 ), // #57 + INST(Ccmp , BaseCCmp , (0b01111010010000000000000000000000) , kRWI_R , 0 , 1 , 650 ), // #58 + INST(Cfinv , BaseOp , (0b11010101000000000100000000011111) , 0 , 0 , 7 , 390 ), // #59 + INST(Cinc , BaseCInc , (0b00011010100000000000010000000000) , kRWI_W , 0 , 0 , 396 ), // #60 + INST(Cinv , BaseCInc , (0b01011010100000000000000000000000) , kRWI_W , 0 , 1 , 401 ), // #61 + INST(Clrex , BaseOpImm , (0b11010101000000110011000001011111, 4, 8) , 0 , 0 , 1 , 406 ), // #62 + INST(Cls , BaseRR , (0b01011010110000000001010000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 4 , 412 ), // #63 + INST(Clz , BaseRR , (0b01011010110000000001000000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 5 , 416 ), // #64 + INST(Cmn , BaseCmpCmn , (0b0101011000, 0b0101011001, 0b0110001) , kRWI_R , 0 , 0 , 386 ), // #65 + INST(Cmp , BaseCmpCmn , (0b1101011000, 0b1101011001, 0b1110001) , kRWI_R , 0 , 1 , 651 ), // #66 + INST(Cmpp , BaseRR , (0b10111010110000000000000000011111, kX, kSP, 5, kX, kSP, 16, true) , kRWI_R , 0 , 6 , 430 ), // #67 + INST(Cneg , BaseCInc , (0b01011010100000000000010000000000) , kRWI_W , 0 , 2 , 441 ), // #68 + INST(Crc32b , BaseRRR , (0b0001101011000000010000, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 2 , 450 ), // #69 + INST(Crc32cb , BaseRRR , (0b0001101011000000010100, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 3 , 457 ), // #70 + INST(Crc32ch , BaseRRR , (0b0001101011000000010101, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 4 , 465 ), // #71 + INST(Crc32cw , BaseRRR , (0b0001101011000000010110, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 5 , 473 ), // #72 + INST(Crc32cx , BaseRRR , (0b1001101011000000010111, kW, kZR, kW, kZR, kX, kZR, false) , kRWI_W , 0 , 6 , 481 ), // #73 + INST(Crc32h , BaseRRR , (0b0001101011000000010001, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 7 , 489 ), // #74 + INST(Crc32w , BaseRRR , (0b0001101011000000010010, kW, kZR, kW, kZR, kW, kZR, false) , kRWI_W , 0 , 8 , 496 ), // #75 + INST(Crc32x , BaseRRR , (0b1001101011000000010011, kW, kZR, kW, kZR, kX, kZR, false) , kRWI_W , 0 , 9 , 503 ), // #76 + INST(Csdb , BaseOp , (0b11010101000000110010001010011111) , 0 , 0 , 8 , 510 ), // #77 + INST(Csel , BaseCSel , (0b00011010100000000000000000000000) , kRWI_W , 0 , 0 , 710 ), // #78 + INST(Cset , BaseCSet , (0b00011010100111110000011111100000) , kRWI_W , 0 , 0 , 515 ), // #79 + INST(Csetm , BaseCSet , (0b01011010100111110000001111100000) , kRWI_W , 0 , 1 , 520 ), // #80 + INST(Csinc , BaseCSel , (0b00011010100000000000010000000000) , kRWI_W , 0 , 1 , 526 ), // #81 + INST(Csinv , BaseCSel , (0b01011010100000000000000000000000) , kRWI_W , 0 , 2 , 532 ), // #82 + INST(Csneg , BaseCSel , (0b01011010100000000000010000000000) , kRWI_W , 0 , 3 , 538 ), // #83 + INST(Dc , BaseAtDcIcTlbi , (0b00011110000000, 0b00001110000000, true) , kRWI_RX , 0 , 1 , 2 ), // #84 + INST(Dcps1 , BaseOpImm , (0b11010100101000000000000000000001, 16, 5) , 0 , 0 , 2 , 544 ), // #85 + INST(Dcps2 , BaseOpImm , (0b11010100101000000000000000000010, 16, 5) , 0 , 0 , 3 , 550 ), // #86 + INST(Dcps3 , BaseOpImm , (0b11010100101000000000000000000011, 16, 5) , 0 , 0 , 4 , 556 ), // #87 + INST(Dgh , BaseOp , (0b11010101000000110010000011011111) , 0 , 0 , 9 , 562 ), // #88 + INST(Dmb , BaseOpImm , (0b11010101000000110011000010111111, 4, 8) , 0 , 0 , 5 , 566 ), // #89 + INST(Drps , BaseOp , (0b11010110101111110000001111100000) , 0 , 0 , 10 , 570 ), // #90 + INST(Dsb , BaseOpImm , (0b11010101000000110011000010011111, 4, 8) , 0 , 0 , 6 , 575 ), // #91 + INST(Eon , BaseLogical , (0b1001010001, 0b10100100, 1) , kRWI_W , 0 , 4 , 583 ), // #92 + INST(Eor , BaseLogical , (0b1001010000, 0b10100100, 0) , kRWI_W , 0 , 5 , 1418), // #93 + INST(Esb , BaseOp , (0b11010101000000110010001000011111) , 0 , 0 , 11 , 597 ), // #94 + INST(Extr , BaseExtract , (0b00010011100000000000000000000000) , kRWI_W , 0 , 0 , 605 ), // #95 + INST(Eret , BaseOp , (0b11010110100111110000001111100000) , 0 , 0 , 12 , 592 ), // #96 + INST(Gmi , BaseRRR , (0b1001101011000000000101, kX , kZR, kX , kSP, kX , kZR, true) , kRWI_W , 0 , 10 , 1128), // #97 + INST(Hint , BaseOpImm , (0b11010101000000110010000000011111, 7, 5) , 0 , 0 , 7 , 1132), // #98 + INST(Hlt , BaseOpImm , (0b11010100010000000000000000000000, 16, 5) , 0 , 0 , 8 , 1137), // #99 + INST(Hvc , BaseOpImm , (0b11010100000000000000000000000010, 16, 5) , 0 , 0 , 9 , 1141), // #100 + INST(Ic , BaseAtDcIcTlbi , (0b00011110000000, 0b00001110000000, false) , kRWI_RX , 0 , 2 , 257 ), // #101 + INST(Isb , BaseOpImm , (0b11010101000000110011000011011111, 4, 8) , 0 , 0 , 10 , 1149), // #102 + INST(Ldadd , BaseAtomicOp , (0b1011100000100000000000, kWX, 30, 0) , kRWI_WRX , 0 , 12 , 1189), // #103 + INST(Ldadda , BaseAtomicOp , (0b1011100010100000000000, kWX, 30, 1) , kRWI_WRX , 0 , 13 , 1195), // #104 + INST(Ldaddab , BaseAtomicOp , (0b0011100010100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 14 , 1202), // #105 + INST(Ldaddah , BaseAtomicOp , (0b0111100010100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 15 , 1210), // #106 + INST(Ldaddal , BaseAtomicOp , (0b1011100011100000000000, kWX, 30, 1) , kRWI_WRX , 0 , 16 , 1218), // #107 + INST(Ldaddalb , BaseAtomicOp , (0b0011100011100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 17 , 1226), // #108 + INST(Ldaddalh , BaseAtomicOp , (0b0111100011100000000000, kW , 0 , 1) , kRWI_WRX , 0 , 18 , 1235), // #109 + INST(Ldaddb , BaseAtomicOp , (0b0011100000100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 19 , 1244), // #110 + INST(Ldaddh , BaseAtomicOp , (0b0111100000100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 20 , 1251), // #111 + INST(Ldaddl , BaseAtomicOp , (0b1011100001100000000000, kWX, 30, 0) , kRWI_WRX , 0 , 21 , 1258), // #112 + INST(Ldaddlb , BaseAtomicOp , (0b0011100001100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 22 , 1265), // #113 + INST(Ldaddlh , BaseAtomicOp , (0b0111100001100000000000, kW , 0 , 0) , kRWI_WRX , 0 , 23 , 1273), // #114 + INST(Ldar , BaseRM_NoImm , (0b1000100011011111111111, kWX, kZR, 30) , kRWI_W , 0 , 0 , 1281), // #115 + INST(Ldarb , BaseRM_NoImm , (0b0000100011011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 1 , 1286), // #116 + INST(Ldarh , BaseRM_NoImm , (0b0100100011011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 2 , 1292), // #117 + INST(Ldaxp , BaseLdxp , (0b1000100001111111100000, kWX, 30) , kRWI_WW , 0 , 0 , 1298), // #118 + INST(Ldaxr , BaseRM_NoImm , (0b1000100001011111111111, kWX, kZR, 30) , kRWI_W , 0 , 3 , 1304), // #119 + INST(Ldaxrb , BaseRM_NoImm , (0b0000100001011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 4 , 1310), // #120 + INST(Ldaxrh , BaseRM_NoImm , (0b0100100001011111111111, kW , kZR, 0 ) , kRWI_W , 0 , 5 , 1317), // #121 + INST(Ldclr , BaseAtomicOp , (0b1011100000100000000100, kWX, 30, 0) , kRWI_WRX , 0 , 24 , 1324), // #122 + INST(Ldclra , BaseAtomicOp , (0b1011100010100000000100, kWX, 30, 1) , kRWI_WRX , 0 , 25 , 1330), // #123 + INST(Ldclrab , BaseAtomicOp , (0b0011100010100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 26 , 1337), // #124 + INST(Ldclrah , BaseAtomicOp , (0b0111100010100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 27 , 1345), // #125 + INST(Ldclral , BaseAtomicOp , (0b1011100011100000000100, kWX, 30, 1) , kRWI_WRX , 0 , 28 , 1353), // #126 + INST(Ldclralb , BaseAtomicOp , (0b0011100011100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 29 , 1361), // #127 + INST(Ldclralh , BaseAtomicOp , (0b0111100011100000000100, kW , 0 , 1) , kRWI_WRX , 0 , 30 , 1370), // #128 + INST(Ldclrb , BaseAtomicOp , (0b0011100000100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 31 , 1379), // #129 + INST(Ldclrh , BaseAtomicOp , (0b0111100000100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 32 , 1386), // #130 + INST(Ldclrl , BaseAtomicOp , (0b1011100001100000000100, kWX, 30, 0) , kRWI_WRX , 0 , 33 , 1393), // #131 + INST(Ldclrlb , BaseAtomicOp , (0b0011100001100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 34 , 1400), // #132 + INST(Ldclrlh , BaseAtomicOp , (0b0111100001100000000100, kW , 0 , 0) , kRWI_WRX , 0 , 35 , 1408), // #133 + INST(Ldeor , BaseAtomicOp , (0b1011100000100000001000, kWX, 30, 0) , kRWI_WRX , 0 , 36 , 1416), // #134 + INST(Ldeora , BaseAtomicOp , (0b1011100010100000001000, kWX, 30, 1) , kRWI_WRX , 0 , 37 , 1422), // #135 + INST(Ldeorab , BaseAtomicOp , (0b0011100010100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 38 , 1429), // #136 + INST(Ldeorah , BaseAtomicOp , (0b0111100010100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 39 , 1437), // #137 + INST(Ldeoral , BaseAtomicOp , (0b1011100011100000001000, kWX, 30, 1) , kRWI_WRX , 0 , 40 , 1445), // #138 + INST(Ldeoralb , BaseAtomicOp , (0b0011100011100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 41 , 1453), // #139 + INST(Ldeoralh , BaseAtomicOp , (0b0111100011100000001000, kW , 0 , 1) , kRWI_WRX , 0 , 42 , 1462), // #140 + INST(Ldeorb , BaseAtomicOp , (0b0011100000100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 43 , 1471), // #141 + INST(Ldeorh , BaseAtomicOp , (0b0111100000100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 44 , 1478), // #142 + INST(Ldeorl , BaseAtomicOp , (0b1011100001100000001000, kWX, 30, 0) , kRWI_WRX , 0 , 45 , 1485), // #143 + INST(Ldeorlb , BaseAtomicOp , (0b0011100001100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 46 , 1492), // #144 + INST(Ldeorlh , BaseAtomicOp , (0b0111100001100000001000, kW , 0 , 0) , kRWI_WRX , 0 , 47 , 1500), // #145 + INST(Ldg , BaseRM_SImm9 , (0b1101100101100000000000, 0b0000000000000000000000, kX , kZR, 0, 4) , kRWI_W , 0 , 0 , 1508), // #146 + INST(Ldgm , BaseRM_NoImm , (0b1101100111100000000000, kX , kZR, 0 ) , kRWI_W , 0 , 6 , 1512), // #147 + INST(Ldlar , BaseRM_NoImm , (0b1000100011011111011111, kWX, kZR, 30) , kRWI_W , 0 , 7 , 1517), // #148 + INST(Ldlarb , BaseRM_NoImm , (0b0000100011011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 8 , 1523), // #149 + INST(Ldlarh , BaseRM_NoImm , (0b0100100011011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 9 , 1530), // #150 + INST(Ldnp , BaseLdpStp , (0b0010100001, 0 , kWX, 31, 2) , kRWI_WW , 0 , 0 , 1537), // #151 + INST(Ldp , BaseLdpStp , (0b0010100101, 0b0010100011, kWX, 31, 2) , kRWI_W , 0 , 1 , 1542), // #152 + INST(Ldpsw , BaseLdpStp , (0b0110100101, 0b0110100011, kX , 0 , 2) , kRWI_WW , 0 , 2 , 1546), // #153 + INST(Ldr , BaseLdSt , (0b1011100101, 0b10111000010, 0b10111000011, 0b00011000, kWX, 30, 2, Inst::kIdLdur) , kRWI_W , 0 , 0 , 1552), // #154 + INST(Ldraa , BaseRM_SImm10 , (0b1111100000100000000001, kX , kZR, 0, 3) , kRWI_W , 0 , 0 , 1556), // #155 + INST(Ldrab , BaseRM_SImm10 , (0b1111100010100000000001, kX , kZR, 0, 3) , kRWI_W , 0 , 1 , 1562), // #156 + INST(Ldrb , BaseLdSt , (0b0011100101, 0b00111000010, 0b00111000011, 0 , kW , 0 , 0, Inst::kIdLdurb) , kRWI_W , 0 , 1 , 1568), // #157 + INST(Ldrh , BaseLdSt , (0b0111100101, 0b01111000010, 0b01111000011, 0 , kW , 0 , 1, Inst::kIdLdurh) , kRWI_W , 0 , 2 , 1573), // #158 + INST(Ldrsb , BaseLdSt , (0b0011100111, 0b00111000100, 0b00111000101, 0 , kWX, 22, 0, Inst::kIdLdursb) , kRWI_W , 0 , 3 , 1578), // #159 + INST(Ldrsh , BaseLdSt , (0b0111100110, 0b01111000100, 0b01111000101, 0 , kWX, 22, 1, Inst::kIdLdursh) , kRWI_W , 0 , 4 , 1584), // #160 + INST(Ldrsw , BaseLdSt , (0b1011100110, 0b10111000100, 0b10111000101, 0b10011000, kX , 0 , 2, Inst::kIdLdursw) , kRWI_W , 0 , 5 , 1590), // #161 + INST(Ldset , BaseAtomicOp , (0b1011100000100000001100, kWX, 30, 0) , kRWI_WRX , 0 , 48 , 1596), // #162 + INST(Ldseta , BaseAtomicOp , (0b1011100010100000001100, kWX, 30, 1) , kRWI_WRX , 0 , 49 , 1602), // #163 + INST(Ldsetab , BaseAtomicOp , (0b0011100010100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 50 , 1609), // #164 + INST(Ldsetah , BaseAtomicOp , (0b0111100010100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 51 , 1617), // #165 + INST(Ldsetal , BaseAtomicOp , (0b1011100011100000001100, kWX, 30, 1) , kRWI_WRX , 0 , 52 , 1625), // #166 + INST(Ldsetalb , BaseAtomicOp , (0b0011100011100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 53 , 1633), // #167 + INST(Ldsetalh , BaseAtomicOp , (0b0111100011100000001100, kW , 0 , 1) , kRWI_WRX , 0 , 54 , 1642), // #168 + INST(Ldsetb , BaseAtomicOp , (0b0011100000100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 55 , 1651), // #169 + INST(Ldseth , BaseAtomicOp , (0b0111100000100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 56 , 1658), // #170 + INST(Ldsetl , BaseAtomicOp , (0b1011100001100000001100, kWX, 30, 0) , kRWI_WRX , 0 , 57 , 1665), // #171 + INST(Ldsetlb , BaseAtomicOp , (0b0011100001100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 58 , 1672), // #172 + INST(Ldsetlh , BaseAtomicOp , (0b0111100001100000001100, kW , 0 , 0) , kRWI_WRX , 0 , 59 , 1680), // #173 + INST(Ldsmax , BaseAtomicOp , (0b1011100000100000010000, kWX, 30, 0) , kRWI_WRX , 0 , 60 , 1688), // #174 + INST(Ldsmaxa , BaseAtomicOp , (0b1011100010100000010000, kWX, 30, 1) , kRWI_WRX , 0 , 61 , 1695), // #175 + INST(Ldsmaxab , BaseAtomicOp , (0b0011100010100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 62 , 1703), // #176 + INST(Ldsmaxah , BaseAtomicOp , (0b0111100010100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 63 , 1712), // #177 + INST(Ldsmaxal , BaseAtomicOp , (0b1011100011100000010000, kWX, 30, 1) , kRWI_WRX , 0 , 64 , 1721), // #178 + INST(Ldsmaxalb , BaseAtomicOp , (0b0011100011100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 65 , 1730), // #179 + INST(Ldsmaxalh , BaseAtomicOp , (0b0111100011100000010000, kW , 0 , 1) , kRWI_WRX , 0 , 66 , 1740), // #180 + INST(Ldsmaxb , BaseAtomicOp , (0b0011100000100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 67 , 1750), // #181 + INST(Ldsmaxh , BaseAtomicOp , (0b0111100000100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 68 , 1758), // #182 + INST(Ldsmaxl , BaseAtomicOp , (0b1011100001100000010000, kWX, 30, 0) , kRWI_WRX , 0 , 69 , 1766), // #183 + INST(Ldsmaxlb , BaseAtomicOp , (0b0011100001100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 70 , 1774), // #184 + INST(Ldsmaxlh , BaseAtomicOp , (0b0111100001100000010000, kW , 0 , 0) , kRWI_WRX , 0 , 71 , 1783), // #185 + INST(Ldsmin , BaseAtomicOp , (0b1011100000100000010100, kWX, 30, 0) , kRWI_WRX , 0 , 72 , 1792), // #186 + INST(Ldsmina , BaseAtomicOp , (0b1011100010100000010100, kWX, 30, 1) , kRWI_WRX , 0 , 73 , 1799), // #187 + INST(Ldsminab , BaseAtomicOp , (0b0011100010100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 74 , 1807), // #188 + INST(Ldsminah , BaseAtomicOp , (0b0111100010100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 75 , 1816), // #189 + INST(Ldsminal , BaseAtomicOp , (0b1011100011100000010100, kWX, 30, 1) , kRWI_WRX , 0 , 76 , 1825), // #190 + INST(Ldsminalb , BaseAtomicOp , (0b0011100011100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 77 , 1834), // #191 + INST(Ldsminalh , BaseAtomicOp , (0b0111100011100000010100, kW , 0 , 1) , kRWI_WRX , 0 , 78 , 1844), // #192 + INST(Ldsminb , BaseAtomicOp , (0b0011100000100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 79 , 1854), // #193 + INST(Ldsminh , BaseAtomicOp , (0b0111100000100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 80 , 1862), // #194 + INST(Ldsminl , BaseAtomicOp , (0b1011100001100000010100, kWX, 30, 0) , kRWI_WRX , 0 , 81 , 1870), // #195 + INST(Ldsminlb , BaseAtomicOp , (0b0011100001100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 82 , 1878), // #196 + INST(Ldsminlh , BaseAtomicOp , (0b0111100001100000010100, kW , 0 , 0) , kRWI_WRX , 0 , 83 , 1887), // #197 + INST(Ldtr , BaseRM_SImm9 , (0b1011100001000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_W , 0 , 1 , 1896), // #198 + INST(Ldtrb , BaseRM_SImm9 , (0b0011100001000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 2 , 1901), // #199 + INST(Ldtrh , BaseRM_SImm9 , (0b0111100001000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 3 , 1907), // #200 + INST(Ldtrsb , BaseRM_SImm9 , (0b0011100011000000000010, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 4 , 1913), // #201 + INST(Ldtrsh , BaseRM_SImm9 , (0b0111100011000000000010, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 5 , 1920), // #202 + INST(Ldtrsw , BaseRM_SImm9 , (0b1011100010000000000010, 0b0000000000000000000000, kX , kZR, 0 , 0) , kRWI_W , 0 , 6 , 1927), // #203 + INST(Ldumax , BaseAtomicOp , (0b1011100000100000011000, kWX, 30, 0) , kRWI_WRX , 0 , 84 , 1934), // #204 + INST(Ldumaxa , BaseAtomicOp , (0b1011100010100000011000, kWX, 30, 1) , kRWI_WRX , 0 , 85 , 1941), // #205 + INST(Ldumaxab , BaseAtomicOp , (0b0011100010100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 86 , 1949), // #206 + INST(Ldumaxah , BaseAtomicOp , (0b0111100010100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 87 , 1958), // #207 + INST(Ldumaxal , BaseAtomicOp , (0b1011100011100000011000, kWX, 30, 1) , kRWI_WRX , 0 , 88 , 1967), // #208 + INST(Ldumaxalb , BaseAtomicOp , (0b0011100011100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 89 , 1976), // #209 + INST(Ldumaxalh , BaseAtomicOp , (0b0111100011100000011000, kW , 0 , 1) , kRWI_WRX , 0 , 90 , 1986), // #210 + INST(Ldumaxb , BaseAtomicOp , (0b0011100000100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 91 , 1996), // #211 + INST(Ldumaxh , BaseAtomicOp , (0b0111100000100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 92 , 2004), // #212 + INST(Ldumaxl , BaseAtomicOp , (0b1011100001100000011000, kWX, 30, 0) , kRWI_WRX , 0 , 93 , 2012), // #213 + INST(Ldumaxlb , BaseAtomicOp , (0b0011100001100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 94 , 2020), // #214 + INST(Ldumaxlh , BaseAtomicOp , (0b0111100001100000011000, kW , 0 , 0) , kRWI_WRX , 0 , 95 , 2029), // #215 + INST(Ldumin , BaseAtomicOp , (0b1011100000100000011100, kWX, 30, 0) , kRWI_WRX , 0 , 96 , 2038), // #216 + INST(Ldumina , BaseAtomicOp , (0b1011100010100000011100, kWX, 30, 1) , kRWI_WRX , 0 , 97 , 2045), // #217 + INST(Lduminab , BaseAtomicOp , (0b0011100010100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 98 , 2053), // #218 + INST(Lduminah , BaseAtomicOp , (0b0111100010100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 99 , 2062), // #219 + INST(Lduminal , BaseAtomicOp , (0b1011100011100000011100, kWX, 30, 1) , kRWI_WRX , 0 , 100, 2071), // #220 + INST(Lduminalb , BaseAtomicOp , (0b0011100011100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 101, 2080), // #221 + INST(Lduminalh , BaseAtomicOp , (0b0111100011100000011100, kW , 0 , 1) , kRWI_WRX , 0 , 102, 2090), // #222 + INST(Lduminb , BaseAtomicOp , (0b0011100000100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 103, 2100), // #223 + INST(Lduminh , BaseAtomicOp , (0b0111100000100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 104, 2108), // #224 + INST(Lduminl , BaseAtomicOp , (0b1011100001100000011100, kWX, 30, 0) , kRWI_WRX , 0 , 105, 2116), // #225 + INST(Lduminlb , BaseAtomicOp , (0b0011100001100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 106, 2124), // #226 + INST(Lduminlh , BaseAtomicOp , (0b0111100001100000011100, kW , 0 , 0) , kRWI_WRX , 0 , 107, 2133), // #227 + INST(Ldur , BaseRM_SImm9 , (0b1011100001000000000000, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_W , 0 , 7 , 2142), // #228 + INST(Ldurb , BaseRM_SImm9 , (0b0011100001000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 8 , 2147), // #229 + INST(Ldurh , BaseRM_SImm9 , (0b0111100001000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_W , 0 , 9 , 2153), // #230 + INST(Ldursb , BaseRM_SImm9 , (0b0011100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 10 , 2159), // #231 + INST(Ldursh , BaseRM_SImm9 , (0b0111100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0) , kRWI_W , 0 , 11 , 2166), // #232 + INST(Ldursw , BaseRM_SImm9 , (0b1011100010000000000000, 0b0000000000000000000000, kWX, kZR, 0 , 0) , kRWI_W , 0 , 12 , 2173), // #233 + INST(Ldxp , BaseLdxp , (0b1000100001111111000000, kWX, 30) , kRWI_WW , 0 , 1 , 2180), // #234 + INST(Ldxr , BaseRM_NoImm , (0b1000100001011111011111, kWX, kZR, 30) , kRWI_W , 0 , 10 , 2185), // #235 + INST(Ldxrb , BaseRM_NoImm , (0b0000100001011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 11 , 2190), // #236 + INST(Ldxrh , BaseRM_NoImm , (0b0100100001011111011111, kW , kZR, 0 ) , kRWI_W , 0 , 12 , 2196), // #237 + INST(Lsl , BaseShift , (0b0001101011000000001000, 0b0101001100000000000000, 0) , kRWI_W , 0 , 2 , 2880), // #238 + INST(Lslv , BaseShift , (0b0001101011000000001000, 0b0000000000000000000000, 0) , kRWI_W , 0 , 3 , 2202), // #239 + INST(Lsr , BaseShift , (0b0001101011000000001001, 0b0101001100000000011111, 0) , kRWI_W , 0 , 4 , 2207), // #240 + INST(Lsrv , BaseShift , (0b0001101011000000001001, 0b0000000000000000000000, 0) , kRWI_W , 0 , 5 , 2211), // #241 + INST(Madd , BaseRRRR , (0b0001101100000000000000, kWX, kZR, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 0 , 977 ), // #242 + INST(Mneg , BaseRRR , (0b0001101100000000111111, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 11 , 2216), // #243 + INST(Mov , BaseMov , (_) , kRWI_W , 0 , 0 , 949 ), // #244 + INST(Movk , BaseMovKNZ , (0b01110010100000000000000000000000) , kRWI_X , 0 , 0 , 2226), // #245 + INST(Movn , BaseMovKNZ , (0b00010010100000000000000000000000) , kRWI_W , 0 , 1 , 2231), // #246 + INST(Movz , BaseMovKNZ , (0b01010010100000000000000000000000) , kRWI_W , 0 , 2 , 2236), // #247 + INST(Mrs , BaseMrs , (_) , kRWI_W , 0 , 0 , 2241), // #248 + INST(Msr , BaseMsr , (_) , kRWI_W , 0 , 0 , 2245), // #249 + INST(Msub , BaseRRRR , (0b0001101100000000100000, kWX, kZR, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 1 , 984 ), // #250 + INST(Mul , BaseRRR , (0b0001101100000000011111, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 12 , 991 ), // #251 + INST(Mvn , BaseMvnNeg , (0b00101010001000000000001111100000) , kRWI_W , 0 , 0 , 2249), // #252 + INST(Neg , BaseMvnNeg , (0b01001011000000000000001111100000) , kRWI_W , 0 , 1 , 540 ), // #253 + INST(Negs , BaseMvnNeg , (0b01101011000000000000001111100000) , kRWI_W , 0 , 2 , 2258), // #254 + INST(Ngc , BaseRR , (0b01011010000000000000001111100000, kWX, kZR, 0, kWX, kZR, 16, true) , kRWI_W , 0 , 7 , 2263), // #255 + INST(Ngcs , BaseRR , (0b01111010000000000000001111100000, kWX, kZR, 0, kWX, kZR, 16, true) , kRWI_W , 0 , 8 , 2267), // #256 + INST(Nop , BaseOp , (0b11010101000000110010000000011111) , 0 , 0 , 13 , 2272), // #257 + INST(Orn , BaseLogical , (0b0101010001, 0b01100100, 1) , kRWI_W , 0 , 6 , 2280), // #258 + INST(Orr , BaseLogical , (0b0101010000, 0b01100100, 0) , kRWI_W , 0 , 7 , 2284), // #259 + INST(Pacda , BaseRR , (0b11011010110000010000100000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 9 , 2288), // #260 + INST(Pacdb , BaseRR , (0b11011010110000010000110000000000, kX, kZR, 0, kX, kSP, 5, true) , kRWI_X , 0 , 10 , 2294), // #261 + INST(Pacdza , BaseR , (0b11011010110000010010101111100000, kX, kZR, 0) , kRWI_X , 0 , 4 , 2300), // #262 + INST(Pacdzb , BaseR , (0b11011010110000010010111111100000, kX, kZR, 0) , kRWI_X , 0 , 5 , 2307), // #263 + INST(Pacga , BaseRRR , (0b1001101011000000001100, kX, kZR, kX, kZR, kX, kSP, false) , kRWI_W , 0 , 13 , 2314), // #264 + INST(Pssbb , BaseOp , (0b11010101000000110011010010011111) , 0 , 0 , 14 , 2338), // #265 + INST(Rbit , BaseRR , (0b01011010110000000000000000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 11 , 2364), // #266 + INST(Ret , BaseBranchReg , (0b11010110010111110000000000000000) , kRWI_R , 0 , 2 , 593 ), // #267 + INST(Rev , BaseRev , (_) , kRWI_W , 0 , 0 , 2369), // #268 + INST(Rev16 , BaseRR , (0b01011010110000000000010000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 12 , 2373), // #269 + INST(Rev32 , BaseRR , (0b11011010110000000000100000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 13 , 2379), // #270 + INST(Rev64 , BaseRR , (0b11011010110000000000110000000000, kWX, kZR, 0, kWX, kZR, 5, true) , kRWI_W , 0 , 14 , 2385), // #271 + INST(Ror , BaseShift , (0b0001101011000000001011, 0b0001001110000000000000, 1) , kRWI_W , 0 , 6 , 2391), // #272 + INST(Rorv , BaseShift , (0b0001101011000000001011, 0b0000000000000000000000, 1) , kRWI_W , 0 , 7 , 2395), // #273 + INST(Sbc , BaseRRR , (0b0101101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 14 , 2498), // #274 + INST(Sbcs , BaseRRR , (0b0111101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 15 , 2502), // #275 + INST(Sbfiz , BaseBfi , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 , 2507), // #276 + INST(Sbfm , BaseBfm , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 , 2513), // #277 + INST(Sbfx , BaseBfx , (0b00010011000000000000000000000000) , kRWI_W , 0 , 1 , 2518), // #278 + INST(Sdiv , BaseRRR , (0b0001101011000000000011, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 16 , 2529), // #279 + INST(Setf8 , BaseR , (0b00111010000000000000100000001101, kW, kZR, 5) , 0 , 0 , 6 , 2541), // #280 + INST(Setf16 , BaseR , (0b00111010000000000100100000001101, kW, kZR, 5) , 0 , 0 , 7 , 2534), // #281 + INST(Sev , BaseOp , (0b11010101000000110010000010011111) , 0 , 0 , 15 , 2547), // #282 + INST(Sevl , BaseOp , (0b11010101000000110010000010111111) , 0 , 0 , 16 , 2551), // #283 + INST(Smaddl , BaseRRRR , (0b1001101100100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 2 , 2758), // #284 + INST(Smc , BaseOpImm , (0b11010100000000000000000000000011, 16, 5) , 0 , 0 , 11 , 53 ), // #285 + INST(Smnegl , BaseRRR , (0b1001101100100000111111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 17 , 2815), // #286 + INST(Smsubl , BaseRRRR , (0b1001101100100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 3 , 2827), // #287 + INST(Smulh , BaseRRR , (0b1001101101000000011111, kX , kZR, kX , kZR, kX , kZR, true) , kRWI_W , 0 , 18 , 2834), // #288 + INST(Smull , BaseRRR , (0b1001101100100000011111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 19 , 2840), // #289 + INST(Ssbb , BaseOp , (0b11010101000000110011000010011111) , 0 , 0 , 17 , 2339), // #290 + INST(St2g , BaseRM_SImm9 , (0b1101100110100000000010, 0b1101100110100000000001, kX, kSP, 0, 4) , kRWI_RW , 0 , 13 , 3164), // #291 + INST(Stadd , BaseAtomicSt , (0b1011100000100000000000, kWX, 30) , kRWI_RX , 0 , 0 , 3177), // #292 + INST(Staddl , BaseAtomicSt , (0b1011100001100000000000, kWX, 30) , kRWI_RX , 0 , 1 , 3197), // #293 + INST(Staddb , BaseAtomicSt , (0b0011100000100000000000, kW , 0 ) , kRWI_RX , 0 , 2 , 3183), // #294 + INST(Staddlb , BaseAtomicSt , (0b0011100001100000000000, kW , 0 ) , kRWI_RX , 0 , 3 , 3204), // #295 + INST(Staddh , BaseAtomicSt , (0b0111100000100000000000, kW , 0 ) , kRWI_RX , 0 , 4 , 3190), // #296 + INST(Staddlh , BaseAtomicSt , (0b0111100001100000000000, kW , 0 ) , kRWI_RX , 0 , 5 , 3212), // #297 + INST(Stclr , BaseAtomicSt , (0b1011100000100000000100, kWX, 30) , kRWI_RX , 0 , 6 , 3220), // #298 + INST(Stclrl , BaseAtomicSt , (0b1011100001100000000100, kWX, 30) , kRWI_RX , 0 , 7 , 3240), // #299 + INST(Stclrb , BaseAtomicSt , (0b0011100000100000000100, kW , 0 ) , kRWI_RX , 0 , 8 , 3226), // #300 + INST(Stclrlb , BaseAtomicSt , (0b0011100001100000000100, kW , 0 ) , kRWI_RX , 0 , 9 , 3247), // #301 + INST(Stclrh , BaseAtomicSt , (0b0111100000100000000100, kW , 0 ) , kRWI_RX , 0 , 10 , 3233), // #302 + INST(Stclrlh , BaseAtomicSt , (0b0111100001100000000100, kW , 0 ) , kRWI_RX , 0 , 11 , 3255), // #303 + INST(Steor , BaseAtomicSt , (0b1011100000100000001000, kWX, 30) , kRWI_RX , 0 , 12 , 3263), // #304 + INST(Steorl , BaseAtomicSt , (0b1011100001100000001000, kWX, 30) , kRWI_RX , 0 , 13 , 3283), // #305 + INST(Steorb , BaseAtomicSt , (0b0011100000100000001000, kW , 0 ) , kRWI_RX , 0 , 14 , 3269), // #306 + INST(Steorlb , BaseAtomicSt , (0b0011100001100000001000, kW , 0 ) , kRWI_RX , 0 , 15 , 3290), // #307 + INST(Steorh , BaseAtomicSt , (0b0111100000100000001000, kW , 0 ) , kRWI_RX , 0 , 16 , 3276), // #308 + INST(Steorlh , BaseAtomicSt , (0b0111100001100000001000, kW , 0 ) , kRWI_RX , 0 , 17 , 3298), // #309 + INST(Stg , BaseRM_SImm9 , (0b1101100100100000000010, 0b1101100100100000000001, kX, kSP, 0, 4) , kRWI_RW , 0 , 14 , 3306), // #310 + INST(Stgm , BaseRM_NoImm , (0b1101100110100000000000, kX , kZR, 0 ) , kRWI_RW , 0 , 13 , 3310), // #311 + INST(Stgp , BaseLdpStp , (0b0110100100, 0b0110100010, kX, 0, 4) , kRWI_RRW , 0 , 3 , 3315), // #312 + INST(Stllr , BaseRM_NoImm , (0b1000100010011111011111, kWX, kZR, 30) , kRWI_RW , 0 , 14 , 3320), // #313 + INST(Stllrb , BaseRM_NoImm , (0b0000100010011111011111, kW , kZR, 0 ) , kRWI_RW , 0 , 15 , 3326), // #314 + INST(Stllrh , BaseRM_NoImm , (0b0100100010011111011111, kW , kZR, 0 ) , kRWI_RW , 0 , 16 , 3333), // #315 + INST(Stlr , BaseRM_NoImm , (0b1000100010011111111111, kWX, kZR, 30) , kRWI_RW , 0 , 17 , 3340), // #316 + INST(Stlrb , BaseRM_NoImm , (0b0000100010011111111111, kW , kZR, 0 ) , kRWI_RW , 0 , 18 , 3345), // #317 + INST(Stlrh , BaseRM_NoImm , (0b0100100010011111111111, kW , kZR, 0 ) , kRWI_RW , 0 , 19 , 3351), // #318 + INST(Stlxp , BaseStxp , (0b1000100000100000100000, kWX, 30) , kRWI_WRRX , 0 , 0 , 3357), // #319 + INST(Stlxr , BaseAtomicOp , (0b1000100000000000111111, kWX, 30, 1) , kRWI_WRX , 0 , 108, 3363), // #320 + INST(Stlxrb , BaseAtomicOp , (0b0000100000000000111111, kW , 0 , 1) , kRWI_WRX , 0 , 109, 3369), // #321 + INST(Stlxrh , BaseAtomicOp , (0b0100100000000000111111, kW , 0 , 1) , kRWI_WRX , 0 , 110, 3376), // #322 + INST(Stnp , BaseLdpStp , (0b0010100000, 0 , kWX, 31, 2) , kRWI_RRW , 0 , 4 , 3383), // #323 + INST(Stp , BaseLdpStp , (0b0010100100, 0b0010100010, kWX, 31, 2) , kRWI_RRW , 0 , 5 , 3388), // #324 + INST(Str , BaseLdSt , (0b1011100100, 0b10111000000, 0b10111000001, 0 , kWX, 30, 2, Inst::kIdStur) , kRWI_RW , 0 , 6 , 3392), // #325 + INST(Strb , BaseLdSt , (0b0011100100, 0b00111000000, 0b00111000001, 0 , kW , 30, 0, Inst::kIdSturb) , kRWI_RW , 0 , 7 , 3396), // #326 + INST(Strh , BaseLdSt , (0b0111100100, 0b01111000000, 0b01111000001, 0 , kWX, 30, 1, Inst::kIdSturh) , kRWI_RW , 0 , 8 , 3401), // #327 + INST(Stset , BaseAtomicSt , (0b1011100000100000001100, kWX, 30) , kRWI_RX , 0 , 18 , 3406), // #328 + INST(Stsetl , BaseAtomicSt , (0b1011100001100000001100, kWX, 30) , kRWI_RX , 0 , 19 , 3426), // #329 + INST(Stsetb , BaseAtomicSt , (0b0011100000100000001100, kW , 0 ) , kRWI_RX , 0 , 20 , 3412), // #330 + INST(Stsetlb , BaseAtomicSt , (0b0011100001100000001100, kW , 0 ) , kRWI_RX , 0 , 21 , 3433), // #331 + INST(Stseth , BaseAtomicSt , (0b0111100000100000001100, kW , 0 ) , kRWI_RX , 0 , 22 , 3419), // #332 + INST(Stsetlh , BaseAtomicSt , (0b0111100001100000001100, kW , 0 ) , kRWI_RX , 0 , 23 , 3441), // #333 + INST(Stsmax , BaseAtomicSt , (0b1011100000100000010000, kWX, 30) , kRWI_RX , 0 , 24 , 3449), // #334 + INST(Stsmaxl , BaseAtomicSt , (0b1011100001100000010000, kWX, 30) , kRWI_RX , 0 , 25 , 3472), // #335 + INST(Stsmaxb , BaseAtomicSt , (0b0011100000100000010000, kW , 0 ) , kRWI_RX , 0 , 26 , 3456), // #336 + INST(Stsmaxlb , BaseAtomicSt , (0b0011100001100000010000, kW , 0 ) , kRWI_RX , 0 , 27 , 3480), // #337 + INST(Stsmaxh , BaseAtomicSt , (0b0111100000100000010000, kW , 0 ) , kRWI_RX , 0 , 28 , 3464), // #338 + INST(Stsmaxlh , BaseAtomicSt , (0b0111100001100000010000, kW , 0 ) , kRWI_RX , 0 , 29 , 3489), // #339 + INST(Stsmin , BaseAtomicSt , (0b1011100000100000010100, kWX, 30) , kRWI_RX , 0 , 30 , 3498), // #340 + INST(Stsminl , BaseAtomicSt , (0b1011100001100000010100, kWX, 30) , kRWI_RX , 0 , 31 , 3521), // #341 + INST(Stsminb , BaseAtomicSt , (0b0011100000100000010100, kW , 0 ) , kRWI_RX , 0 , 32 , 3505), // #342 + INST(Stsminlb , BaseAtomicSt , (0b0011100001100000010100, kW , 0 ) , kRWI_RX , 0 , 33 , 3529), // #343 + INST(Stsminh , BaseAtomicSt , (0b0111100000100000010100, kW , 0 ) , kRWI_RX , 0 , 34 , 3513), // #344 + INST(Stsminlh , BaseAtomicSt , (0b0111100001100000010100, kW , 0 ) , kRWI_RX , 0 , 35 , 3538), // #345 + INST(Sttr , BaseRM_SImm9 , (0b1011100000000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_RW , 0 , 15 , 3547), // #346 + INST(Sttrb , BaseRM_SImm9 , (0b0011100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 16 , 3552), // #347 + INST(Sttrh , BaseRM_SImm9 , (0b0111100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 17 , 3558), // #348 + INST(Stumax , BaseAtomicSt , (0b1011100000100000011000, kWX, 30) , kRWI_RX , 0 , 36 , 3564), // #349 + INST(Stumaxl , BaseAtomicSt , (0b1011100001100000011000, kWX, 30) , kRWI_RX , 0 , 37 , 3587), // #350 + INST(Stumaxb , BaseAtomicSt , (0b0011100000100000011000, kW , 0 ) , kRWI_RX , 0 , 38 , 3571), // #351 + INST(Stumaxlb , BaseAtomicSt , (0b0011100001100000011000, kW , 0 ) , kRWI_RX , 0 , 39 , 3595), // #352 + INST(Stumaxh , BaseAtomicSt , (0b0111100000100000011000, kW , 0 ) , kRWI_RX , 0 , 40 , 3579), // #353 + INST(Stumaxlh , BaseAtomicSt , (0b0111100001100000011000, kW , 0 ) , kRWI_RX , 0 , 41 , 3604), // #354 + INST(Stumin , BaseAtomicSt , (0b1011100000100000011100, kWX, 30) , kRWI_RX , 0 , 42 , 3613), // #355 + INST(Stuminl , BaseAtomicSt , (0b1011100001100000011100, kWX, 30) , kRWI_RX , 0 , 43 , 3636), // #356 + INST(Stuminb , BaseAtomicSt , (0b0011100000100000011100, kW , 0 ) , kRWI_RX , 0 , 44 , 3620), // #357 + INST(Stuminlb , BaseAtomicSt , (0b0011100001100000011100, kW , 0 ) , kRWI_RX , 0 , 45 , 3644), // #358 + INST(Stuminh , BaseAtomicSt , (0b0111100000100000011100, kW , 0 ) , kRWI_RX , 0 , 46 , 3628), // #359 + INST(Stuminlh , BaseAtomicSt , (0b0111100001100000011100, kW , 0 ) , kRWI_RX , 0 , 47 , 3653), // #360 + INST(Stur , BaseRM_SImm9 , (0b1011100000000000000000, 0b0000000000000000000000, kWX, kZR, 30, 0) , kRWI_RW , 0 , 18 , 3662), // #361 + INST(Sturb , BaseRM_SImm9 , (0b0011100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 19 , 3667), // #362 + INST(Sturh , BaseRM_SImm9 , (0b0111100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0) , kRWI_RW , 0 , 20 , 3673), // #363 + INST(Stxp , BaseStxp , (0b1000100000100000000000, kWX, 30) , kRWI_WRRW , 0 , 1 , 3679), // #364 + INST(Stxr , BaseStx , (0b1000100000000000011111, kWX, 30) , kRWI_WRW , 0 , 0 , 3684), // #365 + INST(Stxrb , BaseStx , (0b0000100000000000011111, kW , 0 ) , kRWI_WRW , 0 , 1 , 3689), // #366 + INST(Stxrh , BaseStx , (0b0100100000000000011111, kW , 0 ) , kRWI_WRW , 0 , 2 , 3695), // #367 + INST(Stz2g , BaseRM_SImm9 , (0b1101100111100000000010, 0b1101100111100000000001, kX , kSP, 0, 4) , kRWI_RW , 0 , 21 , 3701), // #368 + INST(Stzg , BaseRM_SImm9 , (0b1101100101100000000010, 0b1101100101100000000001, kX , kSP, 0, 4) , kRWI_RW , 0 , 22 , 3707), // #369 + INST(Stzgm , BaseRM_NoImm , (0b1101100100100000000000, kX , kZR, 0) , kRWI_RW , 0 , 20 , 3712), // #370 + INST(Sub , BaseAddSub , (0b1001011000, 0b1001011001, 0b1010001) , kRWI_X , 0 , 2 , 985 ), // #371 + INST(Subg , BaseRRII , (0b1101000110000000000000, kX, kSP, kX, kSP, 6, 4, 16, 4, 0, 10) , kRWI_W , 0 , 1 , 3718), // #372 + INST(Subp , BaseRRR , (0b1001101011000000000000, kX, kZR, kX, kSP, kX, kSP, false) , kRWI_W , 0 , 20 , 3723), // #373 + INST(Subps , BaseRRR , (0b1011101011000000000000, kX, kZR, kX, kSP, kX, kSP, false) , kRWI_W , 0 , 21 , 3728), // #374 + INST(Subs , BaseAddSub , (0b1101011000, 0b1101011001, 0b1110001) , kRWI_X , 0 , 3 , 3734), // #375 + INST(Svc , BaseOpImm , (0b11010100000000000000000000000001, 16, 5) , 0 , 0 , 12 , 3752), // #376 + INST(Swp , BaseAtomicOp , (0b1011100000100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 111, 3756), // #377 + INST(Swpa , BaseAtomicOp , (0b1011100010100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 112, 3760), // #378 + INST(Swpab , BaseAtomicOp , (0b0011100010100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 113, 3765), // #379 + INST(Swpah , BaseAtomicOp , (0b0111100010100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 114, 3771), // #380 + INST(Swpal , BaseAtomicOp , (0b1011100011100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 115, 3777), // #381 + INST(Swpalb , BaseAtomicOp , (0b0011100011100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 116, 3783), // #382 + INST(Swpalh , BaseAtomicOp , (0b0111100011100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 117, 3790), // #383 + INST(Swpb , BaseAtomicOp , (0b0011100000100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 118, 3797), // #384 + INST(Swph , BaseAtomicOp , (0b0111100000100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 119, 3802), // #385 + INST(Swpl , BaseAtomicOp , (0b1011100001100000100000, kWX, 30, 1) , kRWI_RWX , 0 , 120, 3807), // #386 + INST(Swplb , BaseAtomicOp , (0b0011100001100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 121, 3812), // #387 + INST(Swplh , BaseAtomicOp , (0b0111100001100000100000, kW , 0 , 1) , kRWI_RWX , 0 , 122, 3818), // #388 + INST(Sxtb , BaseExtend , (0b0001001100000000000111, kWX, 0) , kRWI_W , 0 , 0 , 3824), // #389 + INST(Sxth , BaseExtend , (0b0001001100000000001111, kWX, 0) , kRWI_W , 0 , 1 , 3829), // #390 + INST(Sxtw , BaseExtend , (0b1001001101000000011111, kX , 0) , kRWI_W , 0 , 2 , 3845), // #391 + INST(Sys , BaseSys , (_) , kRWI_W , 0 , 0 , 3850), // #392 + INST(Tlbi , BaseAtDcIcTlbi , (0b00011110000000, 0b00010000000000, false) , kRWI_RX , 0 , 3 , 3871), // #393 + INST(Tst , BaseTst , (0b1101010000, 0b111001000) , kRWI_R , 0 , 0 , 437 ), // #394 + INST(Tbnz , BaseBranchTst , (0b00110111000000000000000000000000) , kRWI_R , 0 , 0 , 3858), // #395 + INST(Tbz , BaseBranchTst , (0b00110110000000000000000000000000) , kRWI_R , 0 , 1 , 3867), // #396 + INST(Ubfiz , BaseBfi , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 , 3969), // #397 + INST(Ubfm , BaseBfm , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 , 3975), // #398 + INST(Ubfx , BaseBfx , (0b01010011000000000000000000000000) , kRWI_W , 0 , 2 , 3980), // #399 + INST(Udf , BaseOpImm , (0b00000000000000000000000000000000, 16, 0) , 0 , 0 , 13 , 3991), // #400 + INST(Udiv , BaseRRR , (0b0001101011000000000010, kWX, kZR, kWX, kZR, kWX, kZR, true) , kRWI_W , 0 , 22 , 3995), // #401 + INST(Umaddl , BaseRRRR , (0b1001101110100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 4 , 4012), // #402 + INST(Umnegl , BaseRRR , (0b1001101110100000111111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 23 , 4075), // #403 + INST(Umull , BaseRRR , (0b1001101110100000011111, kX , kZR, kW , kZR, kW , kZR, false) , kRWI_W , 0 , 24 , 4100), // #404 + INST(Umulh , BaseRRR , (0b1001101111000000011111, kX , kZR, kX , kZR, kX , kZR, false) , kRWI_W , 0 , 25 , 4094), // #405 + INST(Umsubl , BaseRRRR , (0b1001101110100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false) , kRWI_W , 0 , 5 , 4087), // #406 + INST(Uxtb , BaseExtend , (0b0101001100000000000111, kW, 1) , kRWI_W , 0 , 3 , 4291), // #407 + INST(Uxth , BaseExtend , (0b0101001100000000001111, kW, 1) , kRWI_W , 0 , 4 , 4296), // #408 + INST(Wfe , BaseOp , (0b11010101000000110010000001011111) , 0 , 0 , 18 , 4322), // #409 + INST(Wfi , BaseOp , (0b11010101000000110010000001111111) , 0 , 0 , 19 , 4326), // #410 + INST(Xaflag , BaseOp , (0b11010101000000000100000000111111) , 0 , 0 , 20 , 4330), // #411 + INST(Xpacd , BaseR , (0b11011010110000010100011111100000, kX, kZR, 0) , kRWI_X , 0 , 8 , 4341), // #412 + INST(Xpaci , BaseR , (0b11011010110000010100001111100000, kX, kZR, 0) , kRWI_X , 0 , 9 , 4347), // #413 + INST(Xpaclri , BaseOp , (0b11010101000000110010000011111111) , kRWI_X , 0 , 21 , 4353), // #414 + INST(Yield , BaseOp , (0b11010101000000110010000000111111) , 0 , 0 , 22 , 4361), // #415 + INST(Abs_v , ISimdVV , (0b0000111000100000101110, kVO_V_Any) , kRWI_W , 0 , 0 , 2855), // #416 + INST(Add_v , ISimdVVV , (0b0000111000100000100001, kVO_V_Any) , kRWI_W , 0 , 0 , 978 ), // #417 + INST(Addhn_v , ISimdVVV , (0b0000111000100000010000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 1 , 2345), // #418 + INST(Addhn2_v , ISimdVVV , (0b0100111000100000010000, kVO_V_B16H8S4) , kRWI_W , F(Narrow) , 2 , 2352), // #419 + INST(Addp_v , ISimdPair , (0b0101111000110001101110, 0b0000111000100000101111, kVO_V_Any) , kRWI_W , F(Pair) , 0 , 638 ), // #420 + INST(Addv_v , ISimdSV , (0b0000111000110001101110, kVO_V_BH_4S) , kRWI_W , 0 , 0 , 20 ), // #421 + INST(Aesd_v , ISimdVVx , (0b0100111000101000010110, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 0 , 34 ), // #422 + INST(Aese_v , ISimdVVx , (0b0100111000101000010010, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 1 , 39 ), // #423 + INST(Aesimc_v , ISimdVVx , (0b0100111000101000011110, kOp_V16B, kOp_V16B) , kRWI_W , 0 , 2 , 44 ), // #424 + INST(Aesmc_v , ISimdVVx , (0b0100111000101000011010, kOp_V16B, kOp_V16B) , kRWI_W , 0 , 3 , 51 ), // #425 + INST(And_v , ISimdVVV , (0b0000111000100000000111, kVO_V_B) , kRWI_W , 0 , 3 , 57 ), // #426 + INST(Bcax_v , ISimdVVVV , (0b1100111000100000000000, kVO_V_B16) , kRWI_W , 0 , 0 , 187 ), // #427 + INST(Bfcvt_v , ISimdVVx , (0b0001111001100011010000, kOp_H, kOp_S) , kRWI_W , 0 , 4 , 196 ), // #428 + INST(Bfcvtn_v , ISimdVVx , (0b0000111010100001011010, kOp_V4H, kOp_V4S) , kRWI_W , F(Narrow) , 5 , 202 ), // #429 + INST(Bfcvtn2_v , ISimdVVx , (0b0100111010100001011010, kOp_V8H, kOp_V4S) , kRWI_W , F(Narrow) , 6 , 209 ), // #430 + INST(Bfdot_v , SimdDot , (0b0010111001000000111111, 0b0000111101000000111100, kET_S, kET_H, kET_2H) , kRWI_X , 0 , 0 , 217 ), // #431 + INST(Bfmlalb_v , SimdFmlal , (0b0010111011000000111111, 0b0000111111000000111100, 0, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 0 , 227 ), // #432 + INST(Bfmlalt_v , SimdFmlal , (0b0110111011000000111111, 0b0100111111000000111100, 0, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 1 , 235 ), // #433 + INST(Bfmmla_v , ISimdVVVx , (0b0110111001000000111011, kOp_V4S, kOp_V8H, kOp_V8H) , kRWI_X , F(Long) , 0 , 243 ), // #434 + INST(Bic_v , SimdBicOrr , (0b0000111001100000000111, 0b0010111100000000000001) , kRWI_W , 0 , 0 , 256 ), // #435 + INST(Bif_v , ISimdVVV , (0b0010111011100000000111, kVO_V_B) , kRWI_X , 0 , 4 , 265 ), // #436 + INST(Bit_v , ISimdVVV , (0b0010111010100000000111, kVO_V_B) , kRWI_X , 0 , 5 , 2365), // #437 + INST(Bsl_v , ISimdVVV , (0b0010111001100000000111, kVO_V_B) , kRWI_X , 0 , 6 , 280 ), // #438 + INST(Cls_v , ISimdVV , (0b0000111000100000010010, kVO_V_BHS) , kRWI_W , 0 , 1 , 412 ), // #439 + INST(Clz_v , ISimdVV , (0b0010111000100000010010, kVO_V_BHS) , kRWI_W , 0 , 2 , 416 ), // #440 + INST(Cmeq_v , SimdCmp , (0b0010111000100000100011, 0b0000111000100000100110, kVO_V_Any) , kRWI_W , 0 , 0 , 663 ), // #441 + INST(Cmge_v , SimdCmp , (0b0000111000100000001111, 0b0010111000100000100010, kVO_V_Any) , kRWI_W , 0 , 1 , 669 ), // #442 + INST(Cmgt_v , SimdCmp , (0b0000111000100000001101, 0b0000111000100000100010, kVO_V_Any) , kRWI_W , 0 , 2 , 675 ), // #443 + INST(Cmhi_v , SimdCmp , (0b0010111000100000001101, 0b0000000000000000000000, kVO_V_Any) , kRWI_W , 0 , 3 , 420 ), // #444 + INST(Cmhs_v , SimdCmp , (0b0010111000100000001111, 0b0000000000000000000000, kVO_V_Any) , kRWI_W , 0 , 4 , 425 ), // #445 + INST(Cmle_v , SimdCmp , (0b0000000000000000000000, 0b0010111000100000100110, kVO_V_Any) , kRWI_W , 0 , 5 , 687 ), // #446 + INST(Cmlt_v , SimdCmp , (0b0000000000000000000000, 0b0000111000100000101010, kVO_V_Any) , kRWI_W , 0 , 6 , 693 ), // #447 + INST(Cmtst_v , ISimdVVV , (0b0000111000100000100011, kVO_V_Any) , kRWI_W , 0 , 7 , 435 ), // #448 + INST(Cnt_v , ISimdVV , (0b0000111000100000010110, kVO_V_B) , kRWI_W , 0 , 3 , 446 ), // #449 + INST(Dup_v , SimdDup , (_) , kRWI_W , 0 , 0 , 579 ), // #450 + INST(Eor_v , ISimdVVV , (0b0010111000100000000111, kVO_V_B) , kRWI_W , 0 , 8 , 1418), // #451 + INST(Eor3_v , ISimdVVVV , (0b1100111000000000000000, kVO_V_B16) , kRWI_W , 0 , 1 , 587 ), // #452 + INST(Ext_v , ISimdVVVI , (0b0010111000000000000000, kVO_V_B, 4, 11, 1) , kRWI_W , 0 , 0 , 601 ), // #453 + INST(Fabd_v , FSimdVVV , (0b0111111010100000110101, kHF_C, 0b0010111010100000110101, kHF_C) , kRWI_W , 0 , 0 , 610 ), // #454 + INST(Fabs_v , FSimdVV , (0b0001111000100000110000, kHF_A, 0b0000111010100000111110, kHF_B) , kRWI_W , 0 , 0 , 615 ), // #455 + INST(Facge_v , FSimdVVV , (0b0111111000100000111011, kHF_C, 0b0010111000100000111011, kHF_C) , kRWI_W , 0 , 1 , 620 ), // #456 + INST(Facgt_v , FSimdVVV , (0b0111111010100000111011, kHF_C, 0b0010111010100000111011, kHF_C) , kRWI_W , 0 , 2 , 626 ), // #457 + INST(Fadd_v , FSimdVVV , (0b0001111000100000001010, kHF_A, 0b0000111000100000110101, kHF_C) , kRWI_W , 0 , 3 , 632 ), // #458 + INST(Faddp_v , FSimdPair , (0b0111111000110000110110, 0b0010111000100000110101) , kRWI_W , 0 , 0 , 637 ), // #459 + INST(Fcadd_v , SimdFcadd , (0b0010111000000000111001) , kRWI_W , 0 , 0 , 643 ), // #460 + INST(Fccmp_v , SimdFccmpFccmpe , (0b00011110001000000000010000000000) , kRWI_R , 0 , 0 , 649 ), // #461 + INST(Fccmpe_v , SimdFccmpFccmpe , (0b00011110001000000000010000010000) , kRWI_R , 0 , 1 , 655 ), // #462 + INST(Fcmeq_v , SimdFcm , (0b0000111000100000111001, kHF_C, 0b0000111010100000110110) , kRWI_W , 0 , 0 , 662 ), // #463 + INST(Fcmge_v , SimdFcm , (0b0010111000100000111001, kHF_C, 0b0010111010100000110010) , kRWI_W , 0 , 1 , 668 ), // #464 + INST(Fcmgt_v , SimdFcm , (0b0010111010100000111001, kHF_C, 0b0000111010100000110010) , kRWI_W , 0 , 2 , 674 ), // #465 + INST(Fcmla_v , SimdFcmla , (0b0010111000000000110001, 0b0010111100000000000100) , kRWI_X , 0 , 0 , 680 ), // #466 + INST(Fcmle_v , SimdFcm , (0b0000000000000000000000, kHF_C, 0b0010111010100000110110) , kRWI_W , 0 , 3 , 686 ), // #467 + INST(Fcmlt_v , SimdFcm , (0b0000000000000000000000, kHF_C, 0b0000111010100000111010) , kRWI_W , 0 , 4 , 692 ), // #468 + INST(Fcmp_v , SimdFcmpFcmpe , (0b00011110001000000010000000000000) , kRWI_R , 0 , 0 , 698 ), // #469 + INST(Fcmpe_v , SimdFcmpFcmpe , (0b00011110001000000010000000010000) , kRWI_R , 0 , 1 , 703 ), // #470 + INST(Fcsel_v , SimdFcsel , (_) , kRWI_W , 0 , 0 , 709 ), // #471 + INST(Fcvt_v , SimdFcvt , (_) , kRWI_W , 0 , 0 , 197 ), // #472 + INST(Fcvtas_v , SimdFcvtSV , (0b0000111000100001110010, 0b0000000000000000000000, 0b0001111000100100000000, 1) , kRWI_W , 0 , 0 , 715 ), // #473 + INST(Fcvtau_v , SimdFcvtSV , (0b0010111000100001110010, 0b0000000000000000000000, 0b0001111000100101000000, 1) , kRWI_W , 0 , 1 , 722 ), // #474 + INST(Fcvtl_v , SimdFcvtLN , (0b0000111000100001011110, 0, 0) , kRWI_W , F(Long) , 0 , 729 ), // #475 + INST(Fcvtl2_v , SimdFcvtLN , (0b0100111000100001011110, 0, 0) , kRWI_W , F(Long) , 1 , 735 ), // #476 + INST(Fcvtms_v , SimdFcvtSV , (0b0000111000100001101110, 0b0000000000000000000000, 0b0001111000110000000000, 1) , kRWI_W , 0 , 2 , 742 ), // #477 + INST(Fcvtmu_v , SimdFcvtSV , (0b0010111000100001101110, 0b0000000000000000000000, 0b0001111000110001000000, 1) , kRWI_W , 0 , 3 , 749 ), // #478 + INST(Fcvtn_v , SimdFcvtLN , (0b0000111000100001011010, 0, 0) , kRWI_W , F(Narrow) , 2 , 203 ), // #479 + INST(Fcvtn2_v , SimdFcvtLN , (0b0100111000100001011010, 0, 0) , kRWI_X , F(Narrow) , 3 , 210 ), // #480 + INST(Fcvtns_v , SimdFcvtSV , (0b0000111000100001101010, 0b0000000000000000000000, 0b0001111000100000000000, 1) , kRWI_W , 0 , 4 , 756 ), // #481 + INST(Fcvtnu_v , SimdFcvtSV , (0b0010111000100001101010, 0b0000000000000000000000, 0b0001111000100001000000, 1) , kRWI_W , 0 , 5 , 763 ), // #482 + INST(Fcvtps_v , SimdFcvtSV , (0b0000111010100001101010, 0b0000000000000000000000, 0b0001111000101000000000, 1) , kRWI_W , 0 , 6 , 770 ), // #483 + INST(Fcvtpu_v , SimdFcvtSV , (0b0010111010100001101010, 0b0000000000000000000000, 0b0001111000101001000000, 1) , kRWI_W , 0 , 7 , 777 ), // #484 + INST(Fcvtxn_v , SimdFcvtLN , (0b0010111000100001011010, 1, 1) , kRWI_W , F(Narrow) , 4 , 784 ), // #485 + INST(Fcvtxn2_v , SimdFcvtLN , (0b0110111000100001011010, 1, 0) , kRWI_X , F(Narrow) , 5 , 791 ), // #486 + INST(Fcvtzs_v , SimdFcvtSV , (0b0000111010100001101110, 0b0000111100000000111111, 0b0001111000111000000000, 1) , kRWI_W , 0 , 8 , 799 ), // #487 + INST(Fcvtzu_v , SimdFcvtSV , (0b0010111010100001101110, 0b0010111100000000111111, 0b0001111000111001000000, 1) , kRWI_W , 0 , 9 , 806 ), // #488 + INST(Fdiv_v , FSimdVVV , (0b0001111000100000000110, kHF_A, 0b0010111000100000111111, kHF_C) , kRWI_W , 0 , 4 , 813 ), // #489 + INST(Fjcvtzs_v , ISimdVVx , (0b0001111001111110000000, kOp_GpW, kOp_D) , kRWI_W , 0 , 7 , 818 ), // #490 + INST(Fmadd_v , FSimdVVVV , (0b0001111100000000000000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 0 , 826 ), // #491 + INST(Fmax_v , FSimdVVV , (0b0001111000100000010010, kHF_A, 0b0000111000100000111101, kHF_C) , kRWI_W , 0 , 5 , 832 ), // #492 + INST(Fmaxnm_v , FSimdVVV , (0b0001111000100000011010, kHF_A, 0b0000111000100000110001, kHF_C) , kRWI_W , 0 , 6 , 837 ), // #493 + INST(Fmaxnmp_v , FSimdPair , (0b0111111000110000110010, 0b0010111000100000110001) , kRWI_W , 0 , 1 , 844 ), // #494 + INST(Fmaxnmv_v , FSimdSV , (0b0010111000110000110010) , kRWI_W , 0 , 0 , 852 ), // #495 + INST(Fmaxp_v , FSimdPair , (0b0111111000110000111110, 0b0010111000100000111101) , kRWI_W , 0 , 2 , 860 ), // #496 + INST(Fmaxv_v , FSimdSV , (0b0010111000110000111110) , kRWI_W , 0 , 1 , 866 ), // #497 + INST(Fmin_v , FSimdVVV , (0b0001111000100000010110, kHF_A, 0b0000111010100000111101, kHF_C) , kRWI_W , 0 , 7 , 872 ), // #498 + INST(Fminnm_v , FSimdVVV , (0b0001111000100000011110, kHF_A, 0b0000111010100000110001, kHF_C) , kRWI_W , 0 , 8 , 877 ), // #499 + INST(Fminnmp_v , FSimdPair , (0b0111111010110000110010, 0b0010111010100000110001) , kRWI_W , 0 , 3 , 884 ), // #500 + INST(Fminnmv_v , FSimdSV , (0b0010111010110000110010) , kRWI_W , 0 , 2 , 892 ), // #501 + INST(Fminp_v , FSimdPair , (0b0111111010110000111110, 0b0010111010100000111101) , kRWI_W , 0 , 4 , 900 ), // #502 + INST(Fminv_v , FSimdSV , (0b0010111010110000111110) , kRWI_W , 0 , 3 , 906 ), // #503 + INST(Fmla_v , FSimdVVVe , (0b0000000000000000000000, kHF_N, 0b0000111000100000110011, 0b0000111110000000000100) , kRWI_X , F(VH0_15) , 0 , 912 ), // #504 + INST(Fmlal_v , SimdFmlal , (0b0000111000100000111011, 0b0000111110000000000000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 2 , 917 ), // #505 + INST(Fmlal2_v , SimdFmlal , (0b0010111000100000110011, 0b0010111110000000100000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 3 , 923 ), // #506 + INST(Fmls_v , FSimdVVVe , (0b0000000000000000000000, kHF_N, 0b0000111010100000110011, 0b0000111110000000010100) , kRWI_X , F(VH0_15) , 1 , 930 ), // #507 + INST(Fmlsl_v , SimdFmlal , (0b0000111010100000111011, 0b0000111110000000010000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 4 , 935 ), // #508 + INST(Fmlsl2_v , SimdFmlal , (0b0010111010100000110011, 0b0010111110000000110000, 1, kET_S, kET_H, kET_H) , kRWI_X , F(VH0_15) , 5 , 941 ), // #509 + INST(Fmov_v , SimdFmov , (_) , kRWI_W , 0 , 0 , 948 ), // #510 + INST(Fmsub_v , FSimdVVVV , (0b0001111100000000100000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 1 , 953 ), // #511 + INST(Fmul_v , FSimdVVVe , (0b0001111000100000000010, kHF_A, 0b0010111000100000110111, 0b0000111110000000100100) , kRWI_W , F(VH0_15) , 2 , 959 ), // #512 + INST(Fmulx_v , FSimdVVVe , (0b0101111000100000110111, kHF_C, 0b0000111000100000110111, 0b0010111110000000100100) , kRWI_W , F(VH0_15) , 3 , 964 ), // #513 + INST(Fneg_v , FSimdVV , (0b0001111000100001010000, kHF_A, 0b0010111010100000111110, kHF_B) , kRWI_W , 0 , 1 , 970 ), // #514 + INST(Fnmadd_v , FSimdVVVV , (0b0001111100100000000000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 2 , 975 ), // #515 + INST(Fnmsub_v , FSimdVVVV , (0b0001111100100000100000, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 3 , 982 ), // #516 + INST(Fnmul_v , FSimdVVV , (0b0001111000100000100010, kHF_A, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 9 , 989 ), // #517 + INST(Frecpe_v , FSimdVV , (0b0101111010100001110110, kHF_B, 0b0000111010100001110110, kHF_B) , kRWI_W , 0 , 2 , 995 ), // #518 + INST(Frecps_v , FSimdVVV , (0b0101111000100000111111, kHF_C, 0b0000111000100000111111, kHF_C) , kRWI_W , 0 , 10 , 1002), // #519 + INST(Frecpx_v , FSimdVV , (0b0101111010100001111110, kHF_B, 0b0000000000000000000000, kHF_N) , kRWI_W , 0 , 3 , 1009), // #520 + INST(Frint32x_v , FSimdVV , (0b0001111000101000110000, kHF_N, 0b0010111000100001111010, kHF_N) , kRWI_W , 0 , 4 , 1016), // #521 + INST(Frint32z_v , FSimdVV , (0b0001111000101000010000, kHF_N, 0b0000111000100001111010, kHF_N) , kRWI_W , 0 , 5 , 1025), // #522 + INST(Frint64x_v , FSimdVV , (0b0001111000101001110000, kHF_N, 0b0010111000100001111110, kHF_N) , kRWI_W , 0 , 6 , 1034), // #523 + INST(Frint64z_v , FSimdVV , (0b0001111000101001010000, kHF_N, 0b0000111000100001111110, kHF_N) , kRWI_W , 0 , 7 , 1043), // #524 + INST(Frinta_v , FSimdVV , (0b0001111000100110010000, kHF_A, 0b0010111000100001100010, kHF_B) , kRWI_W , 0 , 8 , 1052), // #525 + INST(Frinti_v , FSimdVV , (0b0001111000100111110000, kHF_A, 0b0010111010100001100110, kHF_B) , kRWI_W , 0 , 9 , 1059), // #526 + INST(Frintm_v , FSimdVV , (0b0001111000100101010000, kHF_A, 0b0000111000100001100110, kHF_B) , kRWI_W , 0 , 10 , 1066), // #527 + INST(Frintn_v , FSimdVV , (0b0001111000100100010000, kHF_A, 0b0000111000100001100010, kHF_B) , kRWI_W , 0 , 11 , 1073), // #528 + INST(Frintp_v , FSimdVV , (0b0001111000100100110000, kHF_A, 0b0000111010100001100010, kHF_B) , kRWI_W , 0 , 12 , 1080), // #529 + INST(Frintx_v , FSimdVV , (0b0001111000100111010000, kHF_A, 0b0010111000100001100110, kHF_B) , kRWI_W , 0 , 13 , 1087), // #530 + INST(Frintz_v , FSimdVV , (0b0001111000100101110000, kHF_A, 0b0000111010100001100110, kHF_B) , kRWI_W , 0 , 14 , 1094), // #531 + INST(Frsqrte_v , FSimdVV , (0b0111111010100001110110, kHF_B, 0b0010111010100001110110, kHF_B) , kRWI_W , 0 , 15 , 1101), // #532 + INST(Frsqrts_v , FSimdVVV , (0b0101111010100000111111, kHF_C, 0b0000111010100000111111, kHF_C) , kRWI_W , 0 , 11 , 1109), // #533 + INST(Fsqrt_v , FSimdVV , (0b0001111000100001110000, kHF_A, 0b0010111010100001111110, kHF_B) , kRWI_W , 0 , 16 , 1117), // #534 + INST(Fsub_v , FSimdVVV , (0b0001111000100000001110, kHF_A, 0b0000111010100000110101, kHF_C) , kRWI_W , 0 , 12 , 1123), // #535 + INST(Ins_v , SimdIns , (_) , kRWI_X , 0 , 0 , 1145), // #536 + INST(Ld1_v , SimdLdNStN , (0b0000110101000000000000, 0b0000110001000000001000, 1, 0) , kRWI_LDn , F(Consecutive) , 0 , 1153), // #537 + INST(Ld1r_v , SimdLdNStN , (0b0000110101000000110000, 0b0000000000000000000000, 1, 1) , kRWI_LDn , F(Consecutive) , 1 , 1157), // #538 + INST(Ld2_v , SimdLdNStN , (0b0000110101100000000000, 0b0000110001000000100000, 2, 0) , kRWI_LDn , F(Consecutive) , 2 , 1162), // #539 + INST(Ld2r_v , SimdLdNStN , (0b0000110101100000110000, 0b0000000000000000000000, 2, 1) , kRWI_LDn , F(Consecutive) , 3 , 1166), // #540 + INST(Ld3_v , SimdLdNStN , (0b0000110101000000001000, 0b0000110001000000010000, 3, 0) , kRWI_LDn , F(Consecutive) , 4 , 1171), // #541 + INST(Ld3r_v , SimdLdNStN , (0b0000110101000000111000, 0b0000000000000000000000, 3, 1) , kRWI_LDn , F(Consecutive) , 5 , 1175), // #542 + INST(Ld4_v , SimdLdNStN , (0b0000110101100000001000, 0b0000110001000000000000, 4, 0) , kRWI_LDn , F(Consecutive) , 6 , 1180), // #543 + INST(Ld4r_v , SimdLdNStN , (0b0000110101100000111000, 0b0000000000000000000000, 4, 1) , kRWI_LDn , F(Consecutive) , 7 , 1184), // #544 + INST(Ldnp_v , SimdLdpStp , (0b0010110001, 0b0000000000) , kRWI_WW , 0 , 0 , 1537), // #545 + INST(Ldp_v , SimdLdpStp , (0b0010110101, 0b0010110011) , kRWI_WW , 0 , 1 , 1542), // #546 + INST(Ldr_v , SimdLdSt , (0b0011110101, 0b00111100010, 0b00111100011, 0b00011100, Inst::kIdLdur_v) , kRWI_W , 0 , 0 , 1552), // #547 + INST(Ldur_v , SimdLdurStur , (0b0011110001000000000000) , kRWI_W , 0 , 0 , 2142), // #548 + INST(Mla_v , ISimdVVVe , (0b0000111000100000100101, kVO_V_BHS, 0b0010111100000000000000, kVO_V_HS) , kRWI_X , F(VH0_15) , 0 , 246 ), // #549 + INST(Mls_v , ISimdVVVe , (0b0010111000100000100101, kVO_V_BHS, 0b0010111100000000010000, kVO_V_HS) , kRWI_X , F(VH0_15) , 1 , 931 ), // #550 + INST(Mov_v , SimdMov , (_) , kRWI_W , 0 , 0 , 949 ), // #551 + INST(Movi_v , SimdMoviMvni , (0b0000111100000000000001, 0) , kRWI_W , 0 , 0 , 2221), // #552 + INST(Mul_v , ISimdVVVe , (0b0000111000100000100111, kVO_V_BHS, 0b0000111100000000100000, kVO_V_HS) , kRWI_W , F(VH0_15) , 2 , 991 ), // #553 + INST(Mvn_v , ISimdVV , (0b0010111000100000010110, kVO_V_B) , kRWI_W , 0 , 4 , 2249), // #554 + INST(Mvni_v , SimdMoviMvni , (0b0000111100000000000001, 1) , kRWI_W , 0 , 1 , 2253), // #555 + INST(Neg_v , ISimdVV , (0b0010111000100000101110, kVO_V_Any) , kRWI_W , 0 , 5 , 540 ), // #556 + INST(Not_v , ISimdVV , (0b0010111000100000010110, kVO_V_B) , kRWI_W , 0 , 6 , 2276), // #557 + INST(Orn_v , ISimdVVV , (0b0000111011100000000111, kVO_V_B) , kRWI_W , 0 , 9 , 2280), // #558 + INST(Orr_v , SimdBicOrr , (0b0000111010100000000111, 0b0000111100000000000001) , kRWI_W , 0 , 1 , 2284), // #559 + INST(Pmul_v , ISimdVVV , (0b0010111000100000100111, kVO_V_B) , kRWI_W , 0 , 10 , 2320), // #560 + INST(Pmull_v , ISimdVVV , (0b0000111000100000111000, kVO_V_B8D1) , kRWI_W , F(Long) , 11 , 2325), // #561 + INST(Pmull2_v , ISimdVVV , (0b0100111000100000111000, kVO_V_B16D2) , kRWI_W , F(Long) , 12 , 2331), // #562 + INST(Raddhn_v , ISimdVVV , (0b0010111000100000010000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 13 , 2344), // #563 + INST(Raddhn2_v , ISimdVVV , (0b0110111000100000010000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 14 , 2351), // #564 + INST(Rax1_v , ISimdVVV , (0b1100111001100000100011, kVO_V_D2) , kRWI_W , 0 , 15 , 2359), // #565 + INST(Rbit_v , ISimdVV , (0b0010111001100000010110, kVO_V_B) , kRWI_W , 0 , 7 , 2364), // #566 + INST(Rev16_v , ISimdVV , (0b0000111000100000000110, kVO_V_B) , kRWI_W , 0 , 8 , 2373), // #567 + INST(Rev32_v , ISimdVV , (0b0010111000100000000010, kVO_V_BH) , kRWI_W , 0 , 9 , 2379), // #568 + INST(Rev64_v , ISimdVV , (0b0000111000100000000010, kVO_V_BHS) , kRWI_W , 0 , 10 , 2385), // #569 + INST(Rshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100011, 1, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 0 , 2960), // #570 + INST(Rshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100011, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 1 , 2968), // #571 + INST(Rsubhn_v , ISimdVVV , (0b0010111000100000011000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 16 , 2400), // #572 + INST(Rsubhn2_v , ISimdVVV , (0b0110111000100000011000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 17 , 2407), // #573 + INST(Saba_v , ISimdVVV , (0b0000111000100000011111, kVO_V_BHS) , kRWI_X , 0 , 18 , 2415), // #574 + INST(Sabal_v , ISimdVVV , (0b0000111000100000010100, kVO_V_B8H4S2) , kRWI_X , F(Long) , 19 , 2420), // #575 + INST(Sabal2_v , ISimdVVV , (0b0100111000100000010100, kVO_V_B16H8S4) , kRWI_X , F(Long) , 20 , 2426), // #576 + INST(Sabd_v , ISimdVVV , (0b0000111000100000011101, kVO_V_BHS) , kRWI_W , 0 , 21 , 2433), // #577 + INST(Sabdl_v , ISimdVVV , (0b0000111000100000011100, kVO_V_B8H4S2) , kRWI_W , F(Long) , 22 , 2438), // #578 + INST(Sabdl2_v , ISimdVVV , (0b0100111000100000011100, kVO_V_B16H8S4) , kRWI_W , F(Long) , 23 , 2444), // #579 + INST(Sadalp_v , ISimdVV , (0b0000111000100000011010, kVO_V_BHS) , kRWI_X , F(Long) | F(Pair) , 11 , 2451), // #580 + INST(Saddl_v , ISimdVVV , (0b0000111000100000000000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 24 , 2458), // #581 + INST(Saddl2_v , ISimdVVV , (0b0100111000100000000000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 25 , 2464), // #582 + INST(Saddlp_v , ISimdVV , (0b0000111000100000001010, kVO_V_BHS) , kRWI_W , F(Long) | F(Pair) , 12 , 2471), // #583 + INST(Saddlv_v , ISimdSV , (0b0000111000110000001110, kVO_V_BH_4S) , kRWI_W , F(Long) , 1 , 2478), // #584 + INST(Saddw_v , ISimdWWV , (0b0000111000100000000100, kVO_V_B8H4S2) , kRWI_W , 0 , 0 , 2485), // #585 + INST(Saddw2_v , ISimdWWV , (0b0000111000100000000100, kVO_V_B16H8S4) , kRWI_W , 0 , 1 , 2491), // #586 + INST(Scvtf_v , SimdFcvtSV , (0b0000111000100001110110, 0b0000111100000000111001, 0b0001111000100010000000, 0) , kRWI_W , 0 , 10 , 2523), // #587 + INST(Sdot_v , SimdDot , (0b0000111010000000100101, 0b0000111110000000111000, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 1 , 4218), // #588 + INST(Sha1c_v , ISimdVVVx , (0b0101111000000000000000, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 1 , 2556), // #589 + INST(Sha1h_v , ISimdVVx , (0b0101111000101000000010, kOp_S, kOp_S) , kRWI_W , 0 , 8 , 2562), // #590 + INST(Sha1m_v , ISimdVVVx , (0b0101111000000000001000, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 2 , 2568), // #591 + INST(Sha1p_v , ISimdVVVx , (0b0101111000000000000100, kOp_Q, kOp_S, kOp_V4S) , kRWI_X , 0 , 3 , 2574), // #592 + INST(Sha1su0_v , ISimdVVVx , (0b0101111000000000001100, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 4 , 2580), // #593 + INST(Sha1su1_v , ISimdVVx , (0b0101111000101000000110, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 9 , 2588), // #594 + INST(Sha256h_v , ISimdVVVx , (0b0101111000000000010000, kOp_Q, kOp_Q, kOp_V4S) , kRWI_X , 0 , 5 , 2596), // #595 + INST(Sha256h2_v , ISimdVVVx , (0b0101111000000000010100, kOp_Q, kOp_Q, kOp_V4S) , kRWI_X , 0 , 6 , 2604), // #596 + INST(Sha256su0_v , ISimdVVx , (0b0101111000101000001010, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 10 , 2613), // #597 + INST(Sha256su1_v , ISimdVVVx , (0b0101111000000000011000, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 7 , 2623), // #598 + INST(Sha512h_v , ISimdVVVx , (0b1100111001100000100000, kOp_Q, kOp_Q, kOp_V2D) , kRWI_X , 0 , 8 , 2633), // #599 + INST(Sha512h2_v , ISimdVVVx , (0b1100111001100000100001, kOp_Q, kOp_Q, kOp_V2D) , kRWI_X , 0 , 9 , 2641), // #600 + INST(Sha512su0_v , ISimdVVx , (0b1100111011000000100000, kOp_V2D, kOp_V2D) , kRWI_X , 0 , 11 , 2650), // #601 + INST(Sha512su1_v , ISimdVVVx , (0b1100111001100000100010, kOp_V2D, kOp_V2D, kOp_V2D) , kRWI_X , 0 , 10 , 2660), // #602 + INST(Shadd_v , ISimdVVV , (0b0000111000100000000001, kVO_V_BHS) , kRWI_W , 0 , 26 , 2670), // #603 + INST(Shl_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000010101, 0, kVO_V_Any) , kRWI_W , 0 , 2 , 2954), // #604 + INST(Shll_v , SimdShiftES , (0b0010111000100001001110, kVO_V_B8H4S2) , kRWI_W , F(Long) , 0 , 3108), // #605 + INST(Shll2_v , SimdShiftES , (0b0110111000100001001110, kVO_V_B16H8S4) , kRWI_W , F(Long) , 1 , 3114), // #606 + INST(Shrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100001, 1, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 3 , 2961), // #607 + INST(Shrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100001, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 4 , 2969), // #608 + INST(Shsub_v , ISimdVVV , (0b0000111000100000001001, kVO_V_BHS) , kRWI_W , 0 , 27 , 2676), // #609 + INST(Sli_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000010101, 0, kVO_V_Any) , kRWI_X , 0 , 5 , 2682), // #610 + INST(Sm3partw1_v , ISimdVVVx , (0b1100111001100000110000, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 11 , 2686), // #611 + INST(Sm3partw2_v , ISimdVVVx , (0b1100111001100000110001, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 12 , 2696), // #612 + INST(Sm3ss1_v , ISimdVVVVx , (0b1100111001000000000000, kOp_V4S, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_W , 0 , 0 , 2706), // #613 + INST(Sm3tt1a_v , SimdSm3tt , (0b1100111001000000100000) , kRWI_X , 0 , 0 , 2713), // #614 + INST(Sm3tt1b_v , SimdSm3tt , (0b1100111001000000100001) , kRWI_X , 0 , 1 , 2721), // #615 + INST(Sm3tt2a_v , SimdSm3tt , (0b1100111001000000100010) , kRWI_X , 0 , 2 , 2729), // #616 + INST(Sm3tt2b_v , SimdSm3tt , (0b1100111001000000100011) , kRWI_X , 0 , 3 , 2737), // #617 + INST(Sm4e_v , ISimdVVx , (0b1100111011000000100001, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 12 , 2745), // #618 + INST(Sm4ekey_v , ISimdVVVx , (0b1100111001100000110010, kOp_V4S, kOp_V4S, kOp_V4S) , kRWI_X , 0 , 13 , 2750), // #619 + INST(Smax_v , ISimdVVV , (0b0000111000100000011001, kVO_V_BHS) , kRWI_W , 0 , 28 , 1690), // #620 + INST(Smaxp_v , ISimdVVV , (0b0000111000100000101001, kVO_V_BHS) , kRWI_W , 0 , 29 , 2765), // #621 + INST(Smaxv_v , ISimdSV , (0b0000111000110000101010, kVO_V_BH_4S) , kRWI_W , 0 , 2 , 2771), // #622 + INST(Smin_v , ISimdVVV , (0b0000111000100000011011, kVO_V_BHS) , kRWI_W , 0 , 30 , 1794), // #623 + INST(Sminp_v , ISimdVVV , (0b0000111000100000101011, kVO_V_BHS) , kRWI_W , 0 , 31 , 2777), // #624 + INST(Sminv_v , ISimdSV , (0b0000111000110001101010, kVO_V_BH_4S) , kRWI_W , 0 , 3 , 2783), // #625 + INST(Smlal_v , ISimdVVVe , (0b0000111000100000100000, kVO_V_B8H4S2, 0b0000111100000000001000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 3 , 2789), // #626 + INST(Smlal2_v , ISimdVVVe , (0b0100111000100000100000, kVO_V_B16H8S4, 0b0100111100000000001000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 4 , 2795), // #627 + INST(Smlsl_v , ISimdVVVe , (0b0000111000100000101000, kVO_V_B8H4S2, 0b0000111100000000011000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 5 , 2802), // #628 + INST(Smlsl2_v , ISimdVVVe , (0b0100111000100000101000, kVO_V_B16H8S4, 0b0100111100000000011000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 6 , 2808), // #629 + INST(Smmla_v , ISimdVVVx , (0b0100111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 14 , 4247), // #630 + INST(Smov_v , SimdSmovUmov , (0b0000111000000000001011, kVO_V_BHS, 1) , kRWI_W , 0 , 0 , 2822), // #631 + INST(Smull_v , ISimdVVVe , (0b0000111000100000110000, kVO_V_B8H4S2, 0b0000111100000000101000, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 7 , 2840), // #632 + INST(Smull2_v , ISimdVVVe , (0b0100111000100000110000, kVO_V_B16H8S4, 0b0100111100000000101000, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 8 , 2846), // #633 + INST(Sqabs_v , ISimdVV , (0b0000111000100000011110, kVO_SV_Any) , kRWI_W , 0 , 13 , 2853), // #634 + INST(Sqadd_v , ISimdVVV , (0b0000111000100000000011, kVO_SV_Any) , kRWI_W , 0 , 32 , 4254), // #635 + INST(Sqdmlal_v , ISimdVVVe , (0b0000111000100000100100, kVO_SV_BHS, 0b0000111100000000001100, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 9 , 2859), // #636 + INST(Sqdmlal2_v , ISimdVVVe , (0b0100111000100000100100, kVO_V_B16H8S4, 0b0100111100000000001100, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 10 , 2867), // #637 + INST(Sqdmlsl_v , ISimdVVVe , (0b0000111000100000101100, kVO_SV_BHS, 0b0000111100000000011100, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 11 , 2876), // #638 + INST(Sqdmlsl2_v , ISimdVVVe , (0b0100111000100000101100, kVO_V_B16H8S4, 0b0100111100000000011100, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 12 , 2884), // #639 + INST(Sqdmulh_v , ISimdVVVe , (0b0000111000100000101101, kVO_SV_HS, 0b0000111100000000110000, kVO_SV_HS) , kRWI_W , F(VH0_15) , 13 , 2893), // #640 + INST(Sqdmull_v , ISimdVVVe , (0b0000111000100000110100, kVO_SV_BHS, 0b0000111100000000101100, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 14 , 2901), // #641 + INST(Sqdmull2_v , ISimdVVVe , (0b0100111000100000110100, kVO_V_B16H8S4, 0b0100111100000000101100, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 15 , 2909), // #642 + INST(Sqneg_v , ISimdVV , (0b0010111000100000011110, kVO_SV_Any) , kRWI_W , 0 , 14 , 2918), // #643 + INST(Sqrdmlah_v , ISimdVVVe , (0b0010111000000000100001, kVO_SV_HS, 0b0010111100000000110100, kVO_SV_HS) , kRWI_X , F(VH0_15) , 16 , 2924), // #644 + INST(Sqrdmlsh_v , ISimdVVVe , (0b0010111000000000100011, kVO_SV_HS, 0b0010111100000000111100, kVO_SV_HS) , kRWI_X , F(VH0_15) , 17 , 2933), // #645 + INST(Sqrdmulh_v , ISimdVVVe , (0b0010111000100000101101, kVO_SV_HS, 0b0000111100000000110100, kVO_SV_HS) , kRWI_W , F(VH0_15) , 18 , 2942), // #646 + INST(Sqrshl_v , SimdShift , (0b0000111000100000010111, 0b0000000000000000000000, 1, kVO_SV_Any) , kRWI_W , 0 , 6 , 2951), // #647 + INST(Sqrshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100111, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 7 , 2958), // #648 + INST(Sqrshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100111, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 8 , 2966), // #649 + INST(Sqrshrun_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100011, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 9 , 2975), // #650 + INST(Sqrshrun2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100011, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 10 , 2984), // #651 + INST(Sqshl_v , SimdShift , (0b0000111000100000010011, 0b0000111100000000011101, 0, kVO_SV_Any) , kRWI_W , 0 , 11 , 2994), // #652 + INST(Sqshlu_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000011001, 0, kVO_SV_Any) , kRWI_W , 0 , 12 , 3000), // #653 + INST(Sqshrn_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000100101, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 13 , 3007), // #654 + INST(Sqshrn2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000100101, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 14 , 3014), // #655 + INST(Sqshrun_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100001, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 15 , 3022), // #656 + INST(Sqshrun2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100001, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 16 , 3030), // #657 + INST(Sqsub_v , ISimdVVV , (0b0000111000100000001011, kVO_SV_Any) , kRWI_W , 0 , 33 , 3039), // #658 + INST(Sqxtn_v , ISimdVV , (0b0000111000100001010010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 15 , 3045), // #659 + INST(Sqxtn2_v , ISimdVV , (0b0100111000100001010010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 16 , 3051), // #660 + INST(Sqxtun_v , ISimdVV , (0b0010111000100001001010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 17 , 3058), // #661 + INST(Sqxtun2_v , ISimdVV , (0b0110111000100001001010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 18 , 3065), // #662 + INST(Srhadd_v , ISimdVVV , (0b0000111000100000000101, kVO_V_BHS) , kRWI_W , 0 , 34 , 3073), // #663 + INST(Sri_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000010001, 1, kVO_V_Any) , kRWI_W , 0 , 17 , 3080), // #664 + INST(Srshl_v , SimdShift , (0b0000111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 18 , 3084), // #665 + INST(Srshr_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000001001, 1, kVO_V_Any) , kRWI_W , 0 , 19 , 3090), // #666 + INST(Srsra_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000001101, 1, kVO_V_Any) , kRWI_X , 0 , 20 , 3096), // #667 + INST(Sshl_v , SimdShift , (0b0000111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 21 , 3102), // #668 + INST(Sshll_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000101001, 0, kVO_V_B8H4S2) , kRWI_W , F(Long) , 22 , 3107), // #669 + INST(Sshll2_v , SimdShift , (0b0000000000000000000000, 0b0100111100000000101001, 0, kVO_V_B16H8S4) , kRWI_W , F(Long) , 23 , 3113), // #670 + INST(Sshr_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000000001, 1, kVO_V_Any) , kRWI_W , 0 , 24 , 3120), // #671 + INST(Ssra_v , SimdShift , (0b0000000000000000000000, 0b0000111100000000000101, 1, kVO_V_Any) , kRWI_X , 0 , 25 , 3125), // #672 + INST(Ssubl_v , ISimdVVV , (0b0000111000100000001000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 35 , 3130), // #673 + INST(Ssubl2_v , ISimdVVV , (0b0100111000100000001000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 36 , 3136), // #674 + INST(Ssubw_v , ISimdWWV , (0b0000111000100000001100, kVO_V_B8H4S2) , kRWI_W , 0 , 2 , 3143), // #675 + INST(Ssubw2_v , ISimdWWV , (0b0000111000100000001100, kVO_V_B16H8S4) , kRWI_X , 0 , 3 , 3149), // #676 + INST(St1_v , SimdLdNStN , (0b0000110100000000000000, 0b0000110000000000001000, 1, 0) , kRWI_STn , F(Consecutive) , 8 , 3156), // #677 + INST(St2_v , SimdLdNStN , (0b0000110100100000000000, 0b0000110000000000100000, 2, 0) , kRWI_STn , F(Consecutive) , 9 , 3160), // #678 + INST(St3_v , SimdLdNStN , (0b0000110100000000001000, 0b0000110000000000010000, 3, 0) , kRWI_STn , F(Consecutive) , 10 , 3169), // #679 + INST(St4_v , SimdLdNStN , (0b0000110100100000001000, 0b0000110000000000000000, 4, 0) , kRWI_STn , F(Consecutive) , 11 , 3173), // #680 + INST(Stnp_v , SimdLdpStp , (0b0010110000, 0b0000000000) , kRWI_RRW , 0 , 2 , 3383), // #681 + INST(Stp_v , SimdLdpStp , (0b0010110100, 0b0010110010) , kRWI_RRW , 0 , 3 , 3388), // #682 + INST(Str_v , SimdLdSt , (0b0011110100, 0b00111100000, 0b00111100001, 0b00000000, Inst::kIdStur_v) , kRWI_RW , 0 , 1 , 3392), // #683 + INST(Stur_v , SimdLdurStur , (0b0011110000000000000000) , kRWI_RW , 0 , 1 , 3662), // #684 + INST(Sub_v , ISimdVVV , (0b0010111000100000100001, kVO_V_Any) , kRWI_W , 0 , 37 , 985 ), // #685 + INST(Subhn_v , ISimdVVV , (0b0000111000100000011000, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 38 , 2401), // #686 + INST(Subhn2_v , ISimdVVV , (0b0000111000100000011000, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 39 , 2408), // #687 + INST(Sudot_v , SimdDot , (0b0000000000000000000000, 0b0000111100000000111100, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 2 , 3739), // #688 + INST(Suqadd_v , ISimdVV , (0b0000111000100000001110, kVO_SV_Any) , kRWI_X , 0 , 19 , 3745), // #689 + INST(Sxtl_v , SimdSxtlUxtl , (0b0000111100000000101001, kVO_V_B8H4S2) , kRWI_W , F(Long) , 0 , 3834), // #690 + INST(Sxtl2_v , SimdSxtlUxtl , (0b0100111100000000101001, kVO_V_B16H8S4) , kRWI_W , F(Long) , 1 , 3839), // #691 + INST(Tbl_v , SimdTblTbx , (0b0000111000000000000000) , kRWI_W , 0 , 0 , 3854), // #692 + INST(Tbx_v , SimdTblTbx , (0b0000111000000000000100) , kRWI_W , 0 , 1 , 3863), // #693 + INST(Trn1_v , ISimdVVV , (0b0000111000000000001010, kVO_V_BHS_D2) , kRWI_W , 0 , 40 , 3876), // #694 + INST(Trn2_v , ISimdVVV , (0b0000111000000000011010, kVO_V_BHS_D2) , kRWI_W , 0 , 41 , 3881), // #695 + INST(Uaba_v , ISimdVVV , (0b0010111000100000011111, kVO_V_BHS) , kRWI_X , 0 , 42 , 3886), // #696 + INST(Uabal_v , ISimdVVV , (0b0010111000100000010100, kVO_V_B8H4S2) , kRWI_X , F(Long) , 43 , 3891), // #697 + INST(Uabal2_v , ISimdVVV , (0b0110111000100000010100, kVO_V_B16H8S4) , kRWI_X , F(Long) , 44 , 3897), // #698 + INST(Uabd_v , ISimdVVV , (0b0010111000100000011101, kVO_V_BHS) , kRWI_W , 0 , 45 , 3904), // #699 + INST(Uabdl_v , ISimdVVV , (0b0010111000100000011100, kVO_V_B8H4S2) , kRWI_W , F(Long) , 46 , 3909), // #700 + INST(Uabdl2_v , ISimdVVV , (0b0110111000100000011100, kVO_V_B16H8S4) , kRWI_W , F(Long) , 47 , 3915), // #701 + INST(Uadalp_v , ISimdVV , (0b0010111000100000011010, kVO_V_BHS) , kRWI_X , F(Long) | F(Pair) , 20 , 3922), // #702 + INST(Uaddl_v , ISimdVVV , (0b0010111000100000000000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 48 , 3929), // #703 + INST(Uaddl2_v , ISimdVVV , (0b0110111000100000000000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 49 , 3935), // #704 + INST(Uaddlp_v , ISimdVV , (0b0010111000100000001010, kVO_V_BHS) , kRWI_W , F(Long) | F(Pair) , 21 , 3942), // #705 + INST(Uaddlv_v , ISimdSV , (0b0010111000110000001110, kVO_V_BH_4S) , kRWI_W , F(Long) , 4 , 3949), // #706 + INST(Uaddw_v , ISimdWWV , (0b0010111000100000000100, kVO_V_B8H4S2) , kRWI_W , 0 , 4 , 3956), // #707 + INST(Uaddw2_v , ISimdWWV , (0b0010111000100000000100, kVO_V_B16H8S4) , kRWI_W , 0 , 5 , 3962), // #708 + INST(Ucvtf_v , SimdFcvtSV , (0b0010111000100001110110, 0b0010111100000000111001, 0b0001111000100011000000, 0) , kRWI_W , 0 , 11 , 3985), // #709 + INST(Udot_v , SimdDot , (0b0010111010000000100101, 0b0010111110000000111000, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 3 , 3740), // #710 + INST(Uhadd_v , ISimdVVV , (0b0010111000100000000001, kVO_V_BHS) , kRWI_W , 0 , 50 , 4000), // #711 + INST(Uhsub_v , ISimdVVV , (0b0010111000100000001001, kVO_V_BHS) , kRWI_W , 0 , 51 , 4006), // #712 + INST(Umax_v , ISimdVVV , (0b0010111000100000011001, kVO_V_BHS) , kRWI_W , 0 , 52 , 1936), // #713 + INST(Umaxp_v , ISimdVVV , (0b0010111000100000101001, kVO_V_BHS) , kRWI_W , 0 , 53 , 4019), // #714 + INST(Umaxv_v , ISimdSV , (0b0010111000110000101010, kVO_V_BH_4S) , kRWI_W , 0 , 5 , 4025), // #715 + INST(Umin_v , ISimdVVV , (0b0010111000100000011011, kVO_V_BHS) , kRWI_W , 0 , 54 , 2040), // #716 + INST(Uminp_v , ISimdVVV , (0b0010111000100000101011, kVO_V_BHS) , kRWI_W , 0 , 55 , 4031), // #717 + INST(Uminv_v , ISimdSV , (0b0010111000110001101010, kVO_V_BH_4S) , kRWI_W , 0 , 6 , 4037), // #718 + INST(Umlal_v , ISimdVVVe , (0b0010111000100000100000, kVO_V_B8H4S2, 0b0010111100000000001000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 19 , 4043), // #719 + INST(Umlal2_v , ISimdVVVe , (0b0110111000100000100000, kVO_V_B16H8S4, 0b0010111100000000001000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 20 , 4049), // #720 + INST(Umlsl_v , ISimdVVVe , (0b0010111000100000101000, kVO_V_B8H4S2, 0b0010111100000000011000, kVO_V_H4S2) , kRWI_X , F(Long) | F(VH0_15) , 21 , 4056), // #721 + INST(Umlsl2_v , ISimdVVVe , (0b0110111000100000101000, kVO_V_B16H8S4, 0b0110111100000000011000, kVO_V_H8S4) , kRWI_X , F(Long) | F(VH0_15) , 22 , 4062), // #722 + INST(Ummla_v , ISimdVVVx , (0b0110111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 15 , 4069), // #723 + INST(Umov_v , SimdSmovUmov , (0b0000111000000000001111, kVO_V_Any, 0) , kRWI_W , 0 , 1 , 4082), // #724 + INST(Umull_v , ISimdVVVe , (0b0010111000100000110000, kVO_V_B8H4S2, 0b0010111100000000101000, kVO_V_H4S2) , kRWI_W , F(Long) | F(VH0_15) , 23 , 4100), // #725 + INST(Umull2_v , ISimdVVVe , (0b0110111000100000110000, kVO_V_B16H8S4, 0b0110111100000000101000, kVO_V_H8S4) , kRWI_W , F(Long) | F(VH0_15) , 24 , 4106), // #726 + INST(Uqadd_v , ISimdVVV , (0b0010111000100000000011, kVO_SV_Any) , kRWI_W , 0 , 56 , 3746), // #727 + INST(Uqrshl_v , SimdShift , (0b0010111000100000010111, 0b0000000000000000000000, 0, kVO_SV_Any) , kRWI_W , 0 , 26 , 4113), // #728 + INST(Uqrshrn_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100111, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 27 , 4120), // #729 + INST(Uqrshrn2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100111, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 28 , 4128), // #730 + INST(Uqshl_v , SimdShift , (0b0010111000100000010011, 0b0010111100000000011101, 0, kVO_SV_Any) , kRWI_W , 0 , 29 , 4137), // #731 + INST(Uqshrn_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000100101, 1, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 30 , 4143), // #732 + INST(Uqshrn2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000100101, 1, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 31 , 4150), // #733 + INST(Uqsub_v , ISimdVVV , (0b0010111000100000001011, kVO_SV_Any) , kRWI_W , 0 , 57 , 4158), // #734 + INST(Uqxtn_v , ISimdVV , (0b0010111000100001010010, kVO_SV_B8H4S2) , kRWI_W , F(Narrow) , 22 , 4164), // #735 + INST(Uqxtn2_v , ISimdVV , (0b0110111000100001010010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 23 , 4170), // #736 + INST(Urecpe_v , ISimdVV , (0b0000111010100001110010, kVO_V_S) , kRWI_W , 0 , 24 , 4177), // #737 + INST(Urhadd_v , ISimdVVV , (0b0010111000100000000101, kVO_V_BHS) , kRWI_W , 0 , 58 , 4184), // #738 + INST(Urshl_v , SimdShift , (0b0010111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 32 , 4191), // #739 + INST(Urshr_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000001001, 1, kVO_V_Any) , kRWI_W , 0 , 33 , 4197), // #740 + INST(Ursqrte_v , ISimdVV , (0b0010111010100001110010, kVO_V_S) , kRWI_W , 0 , 25 , 4203), // #741 + INST(Ursra_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000001101, 1, kVO_V_Any) , kRWI_X , 0 , 34 , 4211), // #742 + INST(Usdot_v , SimdDot , (0b0000111010000000100111, 0b0000111110000000111100, kET_S, kET_B, kET_4B) , kRWI_X , 0 , 4 , 4217), // #743 + INST(Ushl_v , SimdShift , (0b0010111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any) , kRWI_W , 0 , 35 , 4223), // #744 + INST(Ushll_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000101001, 0, kVO_V_B8H4S2) , kRWI_W , F(Long) , 36 , 4228), // #745 + INST(Ushll2_v , SimdShift , (0b0000000000000000000000, 0b0110111100000000101001, 0, kVO_V_B16H8S4) , kRWI_W , F(Long) , 37 , 4234), // #746 + INST(Ushr_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000000001, 1, kVO_V_Any) , kRWI_W , 0 , 38 , 4241), // #747 + INST(Usmmla_v , ISimdVVVx , (0b0100111010000000101011, kOp_V4S, kOp_V16B, kOp_V16B) , kRWI_X , 0 , 16 , 4246), // #748 + INST(Usqadd_v , ISimdVV , (0b0010111000100000001110, kVO_SV_Any) , kRWI_X , 0 , 26 , 4253), // #749 + INST(Usra_v , SimdShift , (0b0000000000000000000000, 0b0010111100000000000101, 1, kVO_V_Any) , kRWI_X , 0 , 39 , 4260), // #750 + INST(Usubl_v , ISimdVVV , (0b0010111000100000001000, kVO_V_B8H4S2) , kRWI_W , F(Long) , 59 , 4265), // #751 + INST(Usubl2_v , ISimdVVV , (0b0110111000100000001000, kVO_V_B16H8S4) , kRWI_W , F(Long) , 60 , 4271), // #752 + INST(Usubw_v , ISimdWWV , (0b0010111000100000001100, kVO_V_B8H4S2) , kRWI_W , 0 , 6 , 4278), // #753 + INST(Usubw2_v , ISimdWWV , (0b0010111000100000001100, kVO_V_B16H8S4) , kRWI_W , 0 , 7 , 4284), // #754 + INST(Uxtl_v , SimdSxtlUxtl , (0b0010111100000000101001, kVO_V_B8H4S2) , kRWI_W , F(Long) , 2 , 4301), // #755 + INST(Uxtl2_v , SimdSxtlUxtl , (0b0110111100000000101001, kVO_V_B16H8S4) , kRWI_W , F(Long) , 3 , 4306), // #756 + INST(Uzp1_v , ISimdVVV , (0b0000111000000000000110, kVO_V_BHS_D2) , kRWI_W , 0 , 61 , 4312), // #757 + INST(Uzp2_v , ISimdVVV , (0b0000111000000000010110, kVO_V_BHS_D2) , kRWI_W , 0 , 62 , 4317), // #758 + INST(Xar_v , ISimdVVVI , (0b1100111001100000100011, kVO_V_D2, 6, 10, 0) , kRWI_W , 0 , 1 , 4337), // #759 + INST(Xtn_v , ISimdVV , (0b0000111000100001001010, kVO_V_B8H4S2) , kRWI_W , F(Narrow) , 27 , 3047), // #760 + INST(Xtn2_v , ISimdVV , (0b0100111000100001001010, kVO_V_B16H8S4) , kRWI_X , F(Narrow) , 28 , 3053), // #761 + INST(Zip1_v , ISimdVVV , (0b0000111000000000001110, kVO_V_BHS_D2) , kRWI_W , 0 , 63 , 4367), // #762 + INST(Zip2_v , ISimdVVV , (0b0000111000000000011110, kVO_V_BHS_D2) , kRWI_W , 0 , 64 , 4372) // #763 + // ${InstInfo:End} +}; + +#undef F +#undef INST +#undef NAME_DATA_INDEX + +namespace EncodingData { + +// ${EncodingData:Begin} +// ------------------- Automatically generated, do not edit ------------------- +const BaseAddSub baseAddSub[4] = { + { 0b0001011000, 0b0001011001, 0b0010001 }, // add + { 0b0101011000, 0b0101011001, 0b0110001 }, // adds + { 0b1001011000, 0b1001011001, 0b1010001 }, // sub + { 0b1101011000, 0b1101011001, 0b1110001 } // subs +}; + +const BaseAdr baseAdr[2] = { + { 0b0001000000000000000000, OffsetType::kAArch64_ADR }, // adr + { 0b1001000000000000000000, OffsetType::kAArch64_ADRP } // adrp +}; + +const BaseAtDcIcTlbi baseAtDcIcTlbi[4] = { + { 0b00011111110000, 0b00001111000000, true }, // at + { 0b00011110000000, 0b00001110000000, true }, // dc + { 0b00011110000000, 0b00001110000000, false }, // ic + { 0b00011110000000, 0b00010000000000, false } // tlbi +}; + +const BaseAtomicCasp baseAtomicCasp[4] = { + { 0b0000100000100000011111, kWX, 30 }, // casp + { 0b0000100001100000011111, kWX, 30 }, // caspa + { 0b0000100001100000111111, kWX, 30 }, // caspal + { 0b0000100000100000111111, kWX, 30 } // caspl +}; + +const BaseAtomicOp baseAtomicOp[123] = { + { 0b1000100010100000011111, kWX, 30, 0 }, // cas + { 0b1000100011100000011111, kWX, 30, 1 }, // casa + { 0b0000100011100000011111, kW , 0 , 1 }, // casab + { 0b0100100011100000011111, kW , 0 , 1 }, // casah + { 0b1000100011100000111111, kWX, 30, 1 }, // casal + { 0b0000100011100000111111, kW , 0 , 1 }, // casalb + { 0b0100100011100000111111, kW , 0 , 1 }, // casalh + { 0b0000100010100000011111, kW , 0 , 0 }, // casb + { 0b0100100010100000011111, kW , 0 , 0 }, // cash + { 0b1000100010100000111111, kWX, 30, 0 }, // casl + { 0b0000100010100000111111, kW , 0 , 0 }, // caslb + { 0b0100100010100000111111, kW , 0 , 0 }, // caslh + { 0b1011100000100000000000, kWX, 30, 0 }, // ldadd + { 0b1011100010100000000000, kWX, 30, 1 }, // ldadda + { 0b0011100010100000000000, kW , 0 , 1 }, // ldaddab + { 0b0111100010100000000000, kW , 0 , 1 }, // ldaddah + { 0b1011100011100000000000, kWX, 30, 1 }, // ldaddal + { 0b0011100011100000000000, kW , 0 , 1 }, // ldaddalb + { 0b0111100011100000000000, kW , 0 , 1 }, // ldaddalh + { 0b0011100000100000000000, kW , 0 , 0 }, // ldaddb + { 0b0111100000100000000000, kW , 0 , 0 }, // ldaddh + { 0b1011100001100000000000, kWX, 30, 0 }, // ldaddl + { 0b0011100001100000000000, kW , 0 , 0 }, // ldaddlb + { 0b0111100001100000000000, kW , 0 , 0 }, // ldaddlh + { 0b1011100000100000000100, kWX, 30, 0 }, // ldclr + { 0b1011100010100000000100, kWX, 30, 1 }, // ldclra + { 0b0011100010100000000100, kW , 0 , 1 }, // ldclrab + { 0b0111100010100000000100, kW , 0 , 1 }, // ldclrah + { 0b1011100011100000000100, kWX, 30, 1 }, // ldclral + { 0b0011100011100000000100, kW , 0 , 1 }, // ldclralb + { 0b0111100011100000000100, kW , 0 , 1 }, // ldclralh + { 0b0011100000100000000100, kW , 0 , 0 }, // ldclrb + { 0b0111100000100000000100, kW , 0 , 0 }, // ldclrh + { 0b1011100001100000000100, kWX, 30, 0 }, // ldclrl + { 0b0011100001100000000100, kW , 0 , 0 }, // ldclrlb + { 0b0111100001100000000100, kW , 0 , 0 }, // ldclrlh + { 0b1011100000100000001000, kWX, 30, 0 }, // ldeor + { 0b1011100010100000001000, kWX, 30, 1 }, // ldeora + { 0b0011100010100000001000, kW , 0 , 1 }, // ldeorab + { 0b0111100010100000001000, kW , 0 , 1 }, // ldeorah + { 0b1011100011100000001000, kWX, 30, 1 }, // ldeoral + { 0b0011100011100000001000, kW , 0 , 1 }, // ldeoralb + { 0b0111100011100000001000, kW , 0 , 1 }, // ldeoralh + { 0b0011100000100000001000, kW , 0 , 0 }, // ldeorb + { 0b0111100000100000001000, kW , 0 , 0 }, // ldeorh + { 0b1011100001100000001000, kWX, 30, 0 }, // ldeorl + { 0b0011100001100000001000, kW , 0 , 0 }, // ldeorlb + { 0b0111100001100000001000, kW , 0 , 0 }, // ldeorlh + { 0b1011100000100000001100, kWX, 30, 0 }, // ldset + { 0b1011100010100000001100, kWX, 30, 1 }, // ldseta + { 0b0011100010100000001100, kW , 0 , 1 }, // ldsetab + { 0b0111100010100000001100, kW , 0 , 1 }, // ldsetah + { 0b1011100011100000001100, kWX, 30, 1 }, // ldsetal + { 0b0011100011100000001100, kW , 0 , 1 }, // ldsetalb + { 0b0111100011100000001100, kW , 0 , 1 }, // ldsetalh + { 0b0011100000100000001100, kW , 0 , 0 }, // ldsetb + { 0b0111100000100000001100, kW , 0 , 0 }, // ldseth + { 0b1011100001100000001100, kWX, 30, 0 }, // ldsetl + { 0b0011100001100000001100, kW , 0 , 0 }, // ldsetlb + { 0b0111100001100000001100, kW , 0 , 0 }, // ldsetlh + { 0b1011100000100000010000, kWX, 30, 0 }, // ldsmax + { 0b1011100010100000010000, kWX, 30, 1 }, // ldsmaxa + { 0b0011100010100000010000, kW , 0 , 1 }, // ldsmaxab + { 0b0111100010100000010000, kW , 0 , 1 }, // ldsmaxah + { 0b1011100011100000010000, kWX, 30, 1 }, // ldsmaxal + { 0b0011100011100000010000, kW , 0 , 1 }, // ldsmaxalb + { 0b0111100011100000010000, kW , 0 , 1 }, // ldsmaxalh + { 0b0011100000100000010000, kW , 0 , 0 }, // ldsmaxb + { 0b0111100000100000010000, kW , 0 , 0 }, // ldsmaxh + { 0b1011100001100000010000, kWX, 30, 0 }, // ldsmaxl + { 0b0011100001100000010000, kW , 0 , 0 }, // ldsmaxlb + { 0b0111100001100000010000, kW , 0 , 0 }, // ldsmaxlh + { 0b1011100000100000010100, kWX, 30, 0 }, // ldsmin + { 0b1011100010100000010100, kWX, 30, 1 }, // ldsmina + { 0b0011100010100000010100, kW , 0 , 1 }, // ldsminab + { 0b0111100010100000010100, kW , 0 , 1 }, // ldsminah + { 0b1011100011100000010100, kWX, 30, 1 }, // ldsminal + { 0b0011100011100000010100, kW , 0 , 1 }, // ldsminalb + { 0b0111100011100000010100, kW , 0 , 1 }, // ldsminalh + { 0b0011100000100000010100, kW , 0 , 0 }, // ldsminb + { 0b0111100000100000010100, kW , 0 , 0 }, // ldsminh + { 0b1011100001100000010100, kWX, 30, 0 }, // ldsminl + { 0b0011100001100000010100, kW , 0 , 0 }, // ldsminlb + { 0b0111100001100000010100, kW , 0 , 0 }, // ldsminlh + { 0b1011100000100000011000, kWX, 30, 0 }, // ldumax + { 0b1011100010100000011000, kWX, 30, 1 }, // ldumaxa + { 0b0011100010100000011000, kW , 0 , 1 }, // ldumaxab + { 0b0111100010100000011000, kW , 0 , 1 }, // ldumaxah + { 0b1011100011100000011000, kWX, 30, 1 }, // ldumaxal + { 0b0011100011100000011000, kW , 0 , 1 }, // ldumaxalb + { 0b0111100011100000011000, kW , 0 , 1 }, // ldumaxalh + { 0b0011100000100000011000, kW , 0 , 0 }, // ldumaxb + { 0b0111100000100000011000, kW , 0 , 0 }, // ldumaxh + { 0b1011100001100000011000, kWX, 30, 0 }, // ldumaxl + { 0b0011100001100000011000, kW , 0 , 0 }, // ldumaxlb + { 0b0111100001100000011000, kW , 0 , 0 }, // ldumaxlh + { 0b1011100000100000011100, kWX, 30, 0 }, // ldumin + { 0b1011100010100000011100, kWX, 30, 1 }, // ldumina + { 0b0011100010100000011100, kW , 0 , 1 }, // lduminab + { 0b0111100010100000011100, kW , 0 , 1 }, // lduminah + { 0b1011100011100000011100, kWX, 30, 1 }, // lduminal + { 0b0011100011100000011100, kW , 0 , 1 }, // lduminalb + { 0b0111100011100000011100, kW , 0 , 1 }, // lduminalh + { 0b0011100000100000011100, kW , 0 , 0 }, // lduminb + { 0b0111100000100000011100, kW , 0 , 0 }, // lduminh + { 0b1011100001100000011100, kWX, 30, 0 }, // lduminl + { 0b0011100001100000011100, kW , 0 , 0 }, // lduminlb + { 0b0111100001100000011100, kW , 0 , 0 }, // lduminlh + { 0b1000100000000000111111, kWX, 30, 1 }, // stlxr + { 0b0000100000000000111111, kW , 0 , 1 }, // stlxrb + { 0b0100100000000000111111, kW , 0 , 1 }, // stlxrh + { 0b1011100000100000100000, kWX, 30, 1 }, // swp + { 0b1011100010100000100000, kWX, 30, 1 }, // swpa + { 0b0011100010100000100000, kW , 0 , 1 }, // swpab + { 0b0111100010100000100000, kW , 0 , 1 }, // swpah + { 0b1011100011100000100000, kWX, 30, 1 }, // swpal + { 0b0011100011100000100000, kW , 0 , 1 }, // swpalb + { 0b0111100011100000100000, kW , 0 , 1 }, // swpalh + { 0b0011100000100000100000, kW , 0 , 1 }, // swpb + { 0b0111100000100000100000, kW , 0 , 1 }, // swph + { 0b1011100001100000100000, kWX, 30, 1 }, // swpl + { 0b0011100001100000100000, kW , 0 , 1 }, // swplb + { 0b0111100001100000100000, kW , 0 , 1 } // swplh +}; + +const BaseAtomicSt baseAtomicSt[48] = { + { 0b1011100000100000000000, kWX, 30 }, // stadd + { 0b1011100001100000000000, kWX, 30 }, // staddl + { 0b0011100000100000000000, kW , 0 }, // staddb + { 0b0011100001100000000000, kW , 0 }, // staddlb + { 0b0111100000100000000000, kW , 0 }, // staddh + { 0b0111100001100000000000, kW , 0 }, // staddlh + { 0b1011100000100000000100, kWX, 30 }, // stclr + { 0b1011100001100000000100, kWX, 30 }, // stclrl + { 0b0011100000100000000100, kW , 0 }, // stclrb + { 0b0011100001100000000100, kW , 0 }, // stclrlb + { 0b0111100000100000000100, kW , 0 }, // stclrh + { 0b0111100001100000000100, kW , 0 }, // stclrlh + { 0b1011100000100000001000, kWX, 30 }, // steor + { 0b1011100001100000001000, kWX, 30 }, // steorl + { 0b0011100000100000001000, kW , 0 }, // steorb + { 0b0011100001100000001000, kW , 0 }, // steorlb + { 0b0111100000100000001000, kW , 0 }, // steorh + { 0b0111100001100000001000, kW , 0 }, // steorlh + { 0b1011100000100000001100, kWX, 30 }, // stset + { 0b1011100001100000001100, kWX, 30 }, // stsetl + { 0b0011100000100000001100, kW , 0 }, // stsetb + { 0b0011100001100000001100, kW , 0 }, // stsetlb + { 0b0111100000100000001100, kW , 0 }, // stseth + { 0b0111100001100000001100, kW , 0 }, // stsetlh + { 0b1011100000100000010000, kWX, 30 }, // stsmax + { 0b1011100001100000010000, kWX, 30 }, // stsmaxl + { 0b0011100000100000010000, kW , 0 }, // stsmaxb + { 0b0011100001100000010000, kW , 0 }, // stsmaxlb + { 0b0111100000100000010000, kW , 0 }, // stsmaxh + { 0b0111100001100000010000, kW , 0 }, // stsmaxlh + { 0b1011100000100000010100, kWX, 30 }, // stsmin + { 0b1011100001100000010100, kWX, 30 }, // stsminl + { 0b0011100000100000010100, kW , 0 }, // stsminb + { 0b0011100001100000010100, kW , 0 }, // stsminlb + { 0b0111100000100000010100, kW , 0 }, // stsminh + { 0b0111100001100000010100, kW , 0 }, // stsminlh + { 0b1011100000100000011000, kWX, 30 }, // stumax + { 0b1011100001100000011000, kWX, 30 }, // stumaxl + { 0b0011100000100000011000, kW , 0 }, // stumaxb + { 0b0011100001100000011000, kW , 0 }, // stumaxlb + { 0b0111100000100000011000, kW , 0 }, // stumaxh + { 0b0111100001100000011000, kW , 0 }, // stumaxlh + { 0b1011100000100000011100, kWX, 30 }, // stumin + { 0b1011100001100000011100, kWX, 30 }, // stuminl + { 0b0011100000100000011100, kW , 0 }, // stuminb + { 0b0011100001100000011100, kW , 0 }, // stuminlb + { 0b0111100000100000011100, kW , 0 }, // stuminh + { 0b0111100001100000011100, kW , 0 } // stuminlh +}; + +const BaseBfc baseBfc[1] = { + { 0b00110011000000000000001111100000 } // bfc +}; + +const BaseBfi baseBfi[3] = { + { 0b00110011000000000000000000000000 }, // bfi + { 0b00010011000000000000000000000000 }, // sbfiz + { 0b01010011000000000000000000000000 } // ubfiz +}; + +const BaseBfm baseBfm[3] = { + { 0b00110011000000000000000000000000 }, // bfm + { 0b00010011000000000000000000000000 }, // sbfm + { 0b01010011000000000000000000000000 } // ubfm +}; + +const BaseBfx baseBfx[3] = { + { 0b00110011000000000000000000000000 }, // bfxil + { 0b00010011000000000000000000000000 }, // sbfx + { 0b01010011000000000000000000000000 } // ubfx +}; + +const BaseBranchCmp baseBranchCmp[2] = { + { 0b00110101000000000000000000000000 }, // cbnz + { 0b00110100000000000000000000000000 } // cbz +}; + +const BaseBranchReg baseBranchReg[3] = { + { 0b11010110001111110000000000000000 }, // blr + { 0b11010110000111110000000000000000 }, // br + { 0b11010110010111110000000000000000 } // ret +}; + +const BaseBranchRel baseBranchRel[2] = { + { 0b00010100000000000000000000000000 }, // b + { 0b10010100000000000000000000000000 } // bl +}; + +const BaseBranchTst baseBranchTst[2] = { + { 0b00110111000000000000000000000000 }, // tbnz + { 0b00110110000000000000000000000000 } // tbz +}; + +const BaseCCmp baseCCmp[2] = { + { 0b00111010010000000000000000000000 }, // ccmn + { 0b01111010010000000000000000000000 } // ccmp +}; + +const BaseCInc baseCInc[3] = { + { 0b00011010100000000000010000000000 }, // cinc + { 0b01011010100000000000000000000000 }, // cinv + { 0b01011010100000000000010000000000 } // cneg +}; + +const BaseCSel baseCSel[4] = { + { 0b00011010100000000000000000000000 }, // csel + { 0b00011010100000000000010000000000 }, // csinc + { 0b01011010100000000000000000000000 }, // csinv + { 0b01011010100000000000010000000000 } // csneg +}; + +const BaseCSet baseCSet[2] = { + { 0b00011010100111110000011111100000 }, // cset + { 0b01011010100111110000001111100000 } // csetm +}; + +const BaseCmpCmn baseCmpCmn[2] = { + { 0b0101011000, 0b0101011001, 0b0110001 }, // cmn + { 0b1101011000, 0b1101011001, 0b1110001 } // cmp +}; + +const BaseExtend baseExtend[5] = { + { 0b0001001100000000000111, kWX, 0 }, // sxtb + { 0b0001001100000000001111, kWX, 0 }, // sxth + { 0b1001001101000000011111, kX , 0 }, // sxtw + { 0b0101001100000000000111, kW, 1 }, // uxtb + { 0b0101001100000000001111, kW, 1 } // uxth +}; + +const BaseExtract baseExtract[1] = { + { 0b00010011100000000000000000000000 } // extr +}; + +const BaseLdSt baseLdSt[9] = { + { 0b1011100101, 0b10111000010, 0b10111000011, 0b00011000, kWX, 30, 2, Inst::kIdLdur }, // ldr + { 0b0011100101, 0b00111000010, 0b00111000011, 0 , kW , 0 , 0, Inst::kIdLdurb }, // ldrb + { 0b0111100101, 0b01111000010, 0b01111000011, 0 , kW , 0 , 1, Inst::kIdLdurh }, // ldrh + { 0b0011100111, 0b00111000100, 0b00111000101, 0 , kWX, 22, 0, Inst::kIdLdursb }, // ldrsb + { 0b0111100110, 0b01111000100, 0b01111000101, 0 , kWX, 22, 1, Inst::kIdLdursh }, // ldrsh + { 0b1011100110, 0b10111000100, 0b10111000101, 0b10011000, kX , 0 , 2, Inst::kIdLdursw }, // ldrsw + { 0b1011100100, 0b10111000000, 0b10111000001, 0 , kWX, 30, 2, Inst::kIdStur }, // str + { 0b0011100100, 0b00111000000, 0b00111000001, 0 , kW , 30, 0, Inst::kIdSturb }, // strb + { 0b0111100100, 0b01111000000, 0b01111000001, 0 , kWX, 30, 1, Inst::kIdSturh } // strh +}; + +const BaseLdpStp baseLdpStp[6] = { + { 0b0010100001, 0 , kWX, 31, 2 }, // ldnp + { 0b0010100101, 0b0010100011, kWX, 31, 2 }, // ldp + { 0b0110100101, 0b0110100011, kX , 0 , 2 }, // ldpsw + { 0b0110100100, 0b0110100010, kX, 0, 4 }, // stgp + { 0b0010100000, 0 , kWX, 31, 2 }, // stnp + { 0b0010100100, 0b0010100010, kWX, 31, 2 } // stp +}; + +const BaseLdxp baseLdxp[2] = { + { 0b1000100001111111100000, kWX, 30 }, // ldaxp + { 0b1000100001111111000000, kWX, 30 } // ldxp +}; + +const BaseLogical baseLogical[8] = { + { 0b0001010000, 0b00100100, 0 }, // and + { 0b1101010000, 0b11100100, 0 }, // ands + { 0b0001010001, 0b00100100, 1 }, // bic + { 0b1101010001, 0b11100100, 1 }, // bics + { 0b1001010001, 0b10100100, 1 }, // eon + { 0b1001010000, 0b10100100, 0 }, // eor + { 0b0101010001, 0b01100100, 1 }, // orn + { 0b0101010000, 0b01100100, 0 } // orr +}; + +const BaseMovKNZ baseMovKNZ[3] = { + { 0b01110010100000000000000000000000 }, // movk + { 0b00010010100000000000000000000000 }, // movn + { 0b01010010100000000000000000000000 } // movz +}; + +const BaseMvnNeg baseMvnNeg[3] = { + { 0b00101010001000000000001111100000 }, // mvn + { 0b01001011000000000000001111100000 }, // neg + { 0b01101011000000000000001111100000 } // negs +}; + +const BaseOp baseOp[23] = { + { 0b11010101000000110010000110011111 }, // autia1716 + { 0b11010101000000110010001110111111 }, // autiasp + { 0b11010101000000110010001110011111 }, // autiaz + { 0b11010101000000110010000111011111 }, // autib1716 + { 0b11010101000000110010001111111111 }, // autibsp + { 0b11010101000000110010001111011111 }, // autibz + { 0b11010101000000000100000001011111 }, // axflag + { 0b11010101000000000100000000011111 }, // cfinv + { 0b11010101000000110010001010011111 }, // csdb + { 0b11010101000000110010000011011111 }, // dgh + { 0b11010110101111110000001111100000 }, // drps + { 0b11010101000000110010001000011111 }, // esb + { 0b11010110100111110000001111100000 }, // eret + { 0b11010101000000110010000000011111 }, // nop + { 0b11010101000000110011010010011111 }, // pssbb + { 0b11010101000000110010000010011111 }, // sev + { 0b11010101000000110010000010111111 }, // sevl + { 0b11010101000000110011000010011111 }, // ssbb + { 0b11010101000000110010000001011111 }, // wfe + { 0b11010101000000110010000001111111 }, // wfi + { 0b11010101000000000100000000111111 }, // xaflag + { 0b11010101000000110010000011111111 }, // xpaclri + { 0b11010101000000110010000000111111 } // yield +}; + +const BaseOpImm baseOpImm[14] = { + { 0b11010100001000000000000000000000, 16, 5 }, // brk + { 0b11010101000000110011000001011111, 4, 8 }, // clrex + { 0b11010100101000000000000000000001, 16, 5 }, // dcps1 + { 0b11010100101000000000000000000010, 16, 5 }, // dcps2 + { 0b11010100101000000000000000000011, 16, 5 }, // dcps3 + { 0b11010101000000110011000010111111, 4, 8 }, // dmb + { 0b11010101000000110011000010011111, 4, 8 }, // dsb + { 0b11010101000000110010000000011111, 7, 5 }, // hint + { 0b11010100010000000000000000000000, 16, 5 }, // hlt + { 0b11010100000000000000000000000010, 16, 5 }, // hvc + { 0b11010101000000110011000011011111, 4, 8 }, // isb + { 0b11010100000000000000000000000011, 16, 5 }, // smc + { 0b11010100000000000000000000000001, 16, 5 }, // svc + { 0b00000000000000000000000000000000, 16, 0 } // udf +}; + +const BaseR baseR[10] = { + { 0b11011010110000010011101111100000, kX, kZR, 0 }, // autdza + { 0b11011010110000010011111111100000, kX, kZR, 0 }, // autdzb + { 0b11011010110000010011001111100000, kX, kZR, 0 }, // autiza + { 0b11011010110000010011011111100000, kX, kZR, 0 }, // autizb + { 0b11011010110000010010101111100000, kX, kZR, 0 }, // pacdza + { 0b11011010110000010010111111100000, kX, kZR, 0 }, // pacdzb + { 0b00111010000000000000100000001101, kW, kZR, 5 }, // setf8 + { 0b00111010000000000100100000001101, kW, kZR, 5 }, // setf16 + { 0b11011010110000010100011111100000, kX, kZR, 0 }, // xpacd + { 0b11011010110000010100001111100000, kX, kZR, 0 } // xpaci +}; + +const BaseRM_NoImm baseRM_NoImm[21] = { + { 0b1000100011011111111111, kWX, kZR, 30 }, // ldar + { 0b0000100011011111111111, kW , kZR, 0 }, // ldarb + { 0b0100100011011111111111, kW , kZR, 0 }, // ldarh + { 0b1000100001011111111111, kWX, kZR, 30 }, // ldaxr + { 0b0000100001011111111111, kW , kZR, 0 }, // ldaxrb + { 0b0100100001011111111111, kW , kZR, 0 }, // ldaxrh + { 0b1101100111100000000000, kX , kZR, 0 }, // ldgm + { 0b1000100011011111011111, kWX, kZR, 30 }, // ldlar + { 0b0000100011011111011111, kW , kZR, 0 }, // ldlarb + { 0b0100100011011111011111, kW , kZR, 0 }, // ldlarh + { 0b1000100001011111011111, kWX, kZR, 30 }, // ldxr + { 0b0000100001011111011111, kW , kZR, 0 }, // ldxrb + { 0b0100100001011111011111, kW , kZR, 0 }, // ldxrh + { 0b1101100110100000000000, kX , kZR, 0 }, // stgm + { 0b1000100010011111011111, kWX, kZR, 30 }, // stllr + { 0b0000100010011111011111, kW , kZR, 0 }, // stllrb + { 0b0100100010011111011111, kW , kZR, 0 }, // stllrh + { 0b1000100010011111111111, kWX, kZR, 30 }, // stlr + { 0b0000100010011111111111, kW , kZR, 0 }, // stlrb + { 0b0100100010011111111111, kW , kZR, 0 }, // stlrh + { 0b1101100100100000000000, kX , kZR, 0 } // stzgm +}; + +const BaseRM_SImm10 baseRM_SImm10[2] = { + { 0b1111100000100000000001, kX , kZR, 0, 3 }, // ldraa + { 0b1111100010100000000001, kX , kZR, 0, 3 } // ldrab +}; + +const BaseRM_SImm9 baseRM_SImm9[23] = { + { 0b1101100101100000000000, 0b0000000000000000000000, kX , kZR, 0, 4 }, // ldg + { 0b1011100001000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0 }, // ldtr + { 0b0011100001000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0 }, // ldtrb + { 0b0111100001000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0 }, // ldtrh + { 0b0011100011000000000010, 0b0000000000000000000000, kWX, kZR, 22, 0 }, // ldtrsb + { 0b0111100011000000000010, 0b0000000000000000000000, kWX, kZR, 22, 0 }, // ldtrsh + { 0b1011100010000000000010, 0b0000000000000000000000, kX , kZR, 0 , 0 }, // ldtrsw + { 0b1011100001000000000000, 0b0000000000000000000000, kWX, kZR, 30, 0 }, // ldur + { 0b0011100001000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0 }, // ldurb + { 0b0111100001000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0 }, // ldurh + { 0b0011100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0 }, // ldursb + { 0b0111100011000000000000, 0b0000000000000000000000, kWX, kZR, 22, 0 }, // ldursh + { 0b1011100010000000000000, 0b0000000000000000000000, kWX, kZR, 0 , 0 }, // ldursw + { 0b1101100110100000000010, 0b1101100110100000000001, kX, kSP, 0, 4 }, // st2g + { 0b1101100100100000000010, 0b1101100100100000000001, kX, kSP, 0, 4 }, // stg + { 0b1011100000000000000010, 0b0000000000000000000000, kWX, kZR, 30, 0 }, // sttr + { 0b0011100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0 }, // sttrb + { 0b0111100000000000000010, 0b0000000000000000000000, kW , kZR, 0 , 0 }, // sttrh + { 0b1011100000000000000000, 0b0000000000000000000000, kWX, kZR, 30, 0 }, // stur + { 0b0011100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0 }, // sturb + { 0b0111100000000000000000, 0b0000000000000000000000, kW , kZR, 0 , 0 }, // sturh + { 0b1101100111100000000010, 0b1101100111100000000001, kX , kSP, 0, 4 }, // stz2g + { 0b1101100101100000000010, 0b1101100101100000000001, kX , kSP, 0, 4 } // stzg +}; + +const BaseRR baseRR[15] = { + { 0b11011010110000010001100000000000, kX, kZR, 0, kX, kSP, 5, true }, // autda + { 0b11011010110000010001110000000000, kX, kZR, 0, kX, kSP, 5, true }, // autdb + { 0b11011010110000010001000000000000, kX, kZR, 0, kX, kSP, 5, true }, // autia + { 0b11011010110000010001010000000000, kX, kZR, 0, kX, kSP, 5, true }, // autib + { 0b01011010110000000001010000000000, kWX, kZR, 0, kWX, kZR, 5, true }, // cls + { 0b01011010110000000001000000000000, kWX, kZR, 0, kWX, kZR, 5, true }, // clz + { 0b10111010110000000000000000011111, kX, kSP, 5, kX, kSP, 16, true }, // cmpp + { 0b01011010000000000000001111100000, kWX, kZR, 0, kWX, kZR, 16, true }, // ngc + { 0b01111010000000000000001111100000, kWX, kZR, 0, kWX, kZR, 16, true }, // ngcs + { 0b11011010110000010000100000000000, kX, kZR, 0, kX, kSP, 5, true }, // pacda + { 0b11011010110000010000110000000000, kX, kZR, 0, kX, kSP, 5, true }, // pacdb + { 0b01011010110000000000000000000000, kWX, kZR, 0, kWX, kZR, 5, true }, // rbit + { 0b01011010110000000000010000000000, kWX, kZR, 0, kWX, kZR, 5, true }, // rev16 + { 0b11011010110000000000100000000000, kWX, kZR, 0, kWX, kZR, 5, true }, // rev32 + { 0b11011010110000000000110000000000, kWX, kZR, 0, kWX, kZR, 5, true } // rev64 +}; + +const BaseRRII baseRRII[2] = { + { 0b1001000110000000000000, kX, kSP, kX, kSP, 6, 4, 16, 4, 0, 10 }, // addg + { 0b1101000110000000000000, kX, kSP, kX, kSP, 6, 4, 16, 4, 0, 10 } // subg +}; + +const BaseRRR baseRRR[26] = { + { 0b0001101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true }, // adc + { 0b0011101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true }, // adcs + { 0b0001101011000000010000, kW, kZR, kW, kZR, kW, kZR, false }, // crc32b + { 0b0001101011000000010100, kW, kZR, kW, kZR, kW, kZR, false }, // crc32cb + { 0b0001101011000000010101, kW, kZR, kW, kZR, kW, kZR, false }, // crc32ch + { 0b0001101011000000010110, kW, kZR, kW, kZR, kW, kZR, false }, // crc32cw + { 0b1001101011000000010111, kW, kZR, kW, kZR, kX, kZR, false }, // crc32cx + { 0b0001101011000000010001, kW, kZR, kW, kZR, kW, kZR, false }, // crc32h + { 0b0001101011000000010010, kW, kZR, kW, kZR, kW, kZR, false }, // crc32w + { 0b1001101011000000010011, kW, kZR, kW, kZR, kX, kZR, false }, // crc32x + { 0b1001101011000000000101, kX , kZR, kX , kSP, kX , kZR, true }, // gmi + { 0b0001101100000000111111, kWX, kZR, kWX, kZR, kWX, kZR, true }, // mneg + { 0b0001101100000000011111, kWX, kZR, kWX, kZR, kWX, kZR, true }, // mul + { 0b1001101011000000001100, kX, kZR, kX, kZR, kX, kSP, false }, // pacga + { 0b0101101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true }, // sbc + { 0b0111101000000000000000, kWX, kZR, kWX, kZR, kWX, kZR, true }, // sbcs + { 0b0001101011000000000011, kWX, kZR, kWX, kZR, kWX, kZR, true }, // sdiv + { 0b1001101100100000111111, kX , kZR, kW , kZR, kW , kZR, false }, // smnegl + { 0b1001101101000000011111, kX , kZR, kX , kZR, kX , kZR, true }, // smulh + { 0b1001101100100000011111, kX , kZR, kW , kZR, kW , kZR, false }, // smull + { 0b1001101011000000000000, kX, kZR, kX, kSP, kX, kSP, false }, // subp + { 0b1011101011000000000000, kX, kZR, kX, kSP, kX, kSP, false }, // subps + { 0b0001101011000000000010, kWX, kZR, kWX, kZR, kWX, kZR, true }, // udiv + { 0b1001101110100000111111, kX , kZR, kW , kZR, kW , kZR, false }, // umnegl + { 0b1001101110100000011111, kX , kZR, kW , kZR, kW , kZR, false }, // umull + { 0b1001101111000000011111, kX , kZR, kX , kZR, kX , kZR, false } // umulh +}; + +const BaseRRRR baseRRRR[6] = { + { 0b0001101100000000000000, kWX, kZR, kWX, kZR, kWX, kZR, kWX, kZR, true }, // madd + { 0b0001101100000000100000, kWX, kZR, kWX, kZR, kWX, kZR, kWX, kZR, true }, // msub + { 0b1001101100100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false }, // smaddl + { 0b1001101100100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false }, // smsubl + { 0b1001101110100000000000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false }, // umaddl + { 0b1001101110100000100000, kX , kZR, kW , kZR, kW , kZR, kX , kZR, false } // umsubl +}; + +const BaseShift baseShift[8] = { + { 0b0001101011000000001010, 0b0001001100000000011111, 0 }, // asr + { 0b0001101011000000001010, 0b0000000000000000000000, 0 }, // asrv + { 0b0001101011000000001000, 0b0101001100000000000000, 0 }, // lsl + { 0b0001101011000000001000, 0b0000000000000000000000, 0 }, // lslv + { 0b0001101011000000001001, 0b0101001100000000011111, 0 }, // lsr + { 0b0001101011000000001001, 0b0000000000000000000000, 0 }, // lsrv + { 0b0001101011000000001011, 0b0001001110000000000000, 1 }, // ror + { 0b0001101011000000001011, 0b0000000000000000000000, 1 } // rorv +}; + +const BaseStx baseStx[3] = { + { 0b1000100000000000011111, kWX, 30 }, // stxr + { 0b0000100000000000011111, kW , 0 }, // stxrb + { 0b0100100000000000011111, kW , 0 } // stxrh +}; + +const BaseStxp baseStxp[2] = { + { 0b1000100000100000100000, kWX, 30 }, // stlxp + { 0b1000100000100000000000, kWX, 30 } // stxp +}; + +const BaseTst baseTst[1] = { + { 0b1101010000, 0b111001000 } // tst +}; + +const FSimdPair fSimdPair[5] = { + { 0b0111111000110000110110, 0b0010111000100000110101 }, // faddp_v + { 0b0111111000110000110010, 0b0010111000100000110001 }, // fmaxnmp_v + { 0b0111111000110000111110, 0b0010111000100000111101 }, // fmaxp_v + { 0b0111111010110000110010, 0b0010111010100000110001 }, // fminnmp_v + { 0b0111111010110000111110, 0b0010111010100000111101 } // fminp_v +}; + +const FSimdSV fSimdSV[4] = { + { 0b0010111000110000110010 }, // fmaxnmv_v + { 0b0010111000110000111110 }, // fmaxv_v + { 0b0010111010110000110010 }, // fminnmv_v + { 0b0010111010110000111110 } // fminv_v +}; + +const FSimdVV fSimdVV[17] = { + { 0b0001111000100000110000, kHF_A, 0b0000111010100000111110, kHF_B }, // fabs_v + { 0b0001111000100001010000, kHF_A, 0b0010111010100000111110, kHF_B }, // fneg_v + { 0b0101111010100001110110, kHF_B, 0b0000111010100001110110, kHF_B }, // frecpe_v + { 0b0101111010100001111110, kHF_B, 0b0000000000000000000000, kHF_N }, // frecpx_v + { 0b0001111000101000110000, kHF_N, 0b0010111000100001111010, kHF_N }, // frint32x_v + { 0b0001111000101000010000, kHF_N, 0b0000111000100001111010, kHF_N }, // frint32z_v + { 0b0001111000101001110000, kHF_N, 0b0010111000100001111110, kHF_N }, // frint64x_v + { 0b0001111000101001010000, kHF_N, 0b0000111000100001111110, kHF_N }, // frint64z_v + { 0b0001111000100110010000, kHF_A, 0b0010111000100001100010, kHF_B }, // frinta_v + { 0b0001111000100111110000, kHF_A, 0b0010111010100001100110, kHF_B }, // frinti_v + { 0b0001111000100101010000, kHF_A, 0b0000111000100001100110, kHF_B }, // frintm_v + { 0b0001111000100100010000, kHF_A, 0b0000111000100001100010, kHF_B }, // frintn_v + { 0b0001111000100100110000, kHF_A, 0b0000111010100001100010, kHF_B }, // frintp_v + { 0b0001111000100111010000, kHF_A, 0b0010111000100001100110, kHF_B }, // frintx_v + { 0b0001111000100101110000, kHF_A, 0b0000111010100001100110, kHF_B }, // frintz_v + { 0b0111111010100001110110, kHF_B, 0b0010111010100001110110, kHF_B }, // frsqrte_v + { 0b0001111000100001110000, kHF_A, 0b0010111010100001111110, kHF_B } // fsqrt_v +}; + +const FSimdVVV fSimdVVV[13] = { + { 0b0111111010100000110101, kHF_C, 0b0010111010100000110101, kHF_C }, // fabd_v + { 0b0111111000100000111011, kHF_C, 0b0010111000100000111011, kHF_C }, // facge_v + { 0b0111111010100000111011, kHF_C, 0b0010111010100000111011, kHF_C }, // facgt_v + { 0b0001111000100000001010, kHF_A, 0b0000111000100000110101, kHF_C }, // fadd_v + { 0b0001111000100000000110, kHF_A, 0b0010111000100000111111, kHF_C }, // fdiv_v + { 0b0001111000100000010010, kHF_A, 0b0000111000100000111101, kHF_C }, // fmax_v + { 0b0001111000100000011010, kHF_A, 0b0000111000100000110001, kHF_C }, // fmaxnm_v + { 0b0001111000100000010110, kHF_A, 0b0000111010100000111101, kHF_C }, // fmin_v + { 0b0001111000100000011110, kHF_A, 0b0000111010100000110001, kHF_C }, // fminnm_v + { 0b0001111000100000100010, kHF_A, 0b0000000000000000000000, kHF_N }, // fnmul_v + { 0b0101111000100000111111, kHF_C, 0b0000111000100000111111, kHF_C }, // frecps_v + { 0b0101111010100000111111, kHF_C, 0b0000111010100000111111, kHF_C }, // frsqrts_v + { 0b0001111000100000001110, kHF_A, 0b0000111010100000110101, kHF_C } // fsub_v +}; + +const FSimdVVVV fSimdVVVV[4] = { + { 0b0001111100000000000000, kHF_A, 0b0000000000000000000000, kHF_N }, // fmadd_v + { 0b0001111100000000100000, kHF_A, 0b0000000000000000000000, kHF_N }, // fmsub_v + { 0b0001111100100000000000, kHF_A, 0b0000000000000000000000, kHF_N }, // fnmadd_v + { 0b0001111100100000100000, kHF_A, 0b0000000000000000000000, kHF_N } // fnmsub_v +}; + +const FSimdVVVe fSimdVVVe[4] = { + { 0b0000000000000000000000, kHF_N, 0b0000111000100000110011, 0b0000111110000000000100 }, // fmla_v + { 0b0000000000000000000000, kHF_N, 0b0000111010100000110011, 0b0000111110000000010100 }, // fmls_v + { 0b0001111000100000000010, kHF_A, 0b0010111000100000110111, 0b0000111110000000100100 }, // fmul_v + { 0b0101111000100000110111, kHF_C, 0b0000111000100000110111, 0b0010111110000000100100 } // fmulx_v +}; + +const ISimdPair iSimdPair[1] = { + { 0b0101111000110001101110, 0b0000111000100000101111, kVO_V_Any } // addp_v +}; + +const ISimdSV iSimdSV[7] = { + { 0b0000111000110001101110, kVO_V_BH_4S }, // addv_v + { 0b0000111000110000001110, kVO_V_BH_4S }, // saddlv_v + { 0b0000111000110000101010, kVO_V_BH_4S }, // smaxv_v + { 0b0000111000110001101010, kVO_V_BH_4S }, // sminv_v + { 0b0010111000110000001110, kVO_V_BH_4S }, // uaddlv_v + { 0b0010111000110000101010, kVO_V_BH_4S }, // umaxv_v + { 0b0010111000110001101010, kVO_V_BH_4S } // uminv_v +}; + +const ISimdVV iSimdVV[29] = { + { 0b0000111000100000101110, kVO_V_Any }, // abs_v + { 0b0000111000100000010010, kVO_V_BHS }, // cls_v + { 0b0010111000100000010010, kVO_V_BHS }, // clz_v + { 0b0000111000100000010110, kVO_V_B }, // cnt_v + { 0b0010111000100000010110, kVO_V_B }, // mvn_v + { 0b0010111000100000101110, kVO_V_Any }, // neg_v + { 0b0010111000100000010110, kVO_V_B }, // not_v + { 0b0010111001100000010110, kVO_V_B }, // rbit_v + { 0b0000111000100000000110, kVO_V_B }, // rev16_v + { 0b0010111000100000000010, kVO_V_BH }, // rev32_v + { 0b0000111000100000000010, kVO_V_BHS }, // rev64_v + { 0b0000111000100000011010, kVO_V_BHS }, // sadalp_v + { 0b0000111000100000001010, kVO_V_BHS }, // saddlp_v + { 0b0000111000100000011110, kVO_SV_Any }, // sqabs_v + { 0b0010111000100000011110, kVO_SV_Any }, // sqneg_v + { 0b0000111000100001010010, kVO_SV_B8H4S2 }, // sqxtn_v + { 0b0100111000100001010010, kVO_V_B16H8S4 }, // sqxtn2_v + { 0b0010111000100001001010, kVO_SV_B8H4S2 }, // sqxtun_v + { 0b0110111000100001001010, kVO_V_B16H8S4 }, // sqxtun2_v + { 0b0000111000100000001110, kVO_SV_Any }, // suqadd_v + { 0b0010111000100000011010, kVO_V_BHS }, // uadalp_v + { 0b0010111000100000001010, kVO_V_BHS }, // uaddlp_v + { 0b0010111000100001010010, kVO_SV_B8H4S2 }, // uqxtn_v + { 0b0110111000100001010010, kVO_V_B16H8S4 }, // uqxtn2_v + { 0b0000111010100001110010, kVO_V_S }, // urecpe_v + { 0b0010111010100001110010, kVO_V_S }, // ursqrte_v + { 0b0010111000100000001110, kVO_SV_Any }, // usqadd_v + { 0b0000111000100001001010, kVO_V_B8H4S2 }, // xtn_v + { 0b0100111000100001001010, kVO_V_B16H8S4 } // xtn2_v +}; + +const ISimdVVV iSimdVVV[65] = { + { 0b0000111000100000100001, kVO_V_Any }, // add_v + { 0b0000111000100000010000, kVO_V_B8H4S2 }, // addhn_v + { 0b0100111000100000010000, kVO_V_B16H8S4 }, // addhn2_v + { 0b0000111000100000000111, kVO_V_B }, // and_v + { 0b0010111011100000000111, kVO_V_B }, // bif_v + { 0b0010111010100000000111, kVO_V_B }, // bit_v + { 0b0010111001100000000111, kVO_V_B }, // bsl_v + { 0b0000111000100000100011, kVO_V_Any }, // cmtst_v + { 0b0010111000100000000111, kVO_V_B }, // eor_v + { 0b0000111011100000000111, kVO_V_B }, // orn_v + { 0b0010111000100000100111, kVO_V_B }, // pmul_v + { 0b0000111000100000111000, kVO_V_B8D1 }, // pmull_v + { 0b0100111000100000111000, kVO_V_B16D2 }, // pmull2_v + { 0b0010111000100000010000, kVO_V_B8H4S2 }, // raddhn_v + { 0b0110111000100000010000, kVO_V_B16H8S4 }, // raddhn2_v + { 0b1100111001100000100011, kVO_V_D2 }, // rax1_v + { 0b0010111000100000011000, kVO_V_B8H4S2 }, // rsubhn_v + { 0b0110111000100000011000, kVO_V_B16H8S4 }, // rsubhn2_v + { 0b0000111000100000011111, kVO_V_BHS }, // saba_v + { 0b0000111000100000010100, kVO_V_B8H4S2 }, // sabal_v + { 0b0100111000100000010100, kVO_V_B16H8S4 }, // sabal2_v + { 0b0000111000100000011101, kVO_V_BHS }, // sabd_v + { 0b0000111000100000011100, kVO_V_B8H4S2 }, // sabdl_v + { 0b0100111000100000011100, kVO_V_B16H8S4 }, // sabdl2_v + { 0b0000111000100000000000, kVO_V_B8H4S2 }, // saddl_v + { 0b0100111000100000000000, kVO_V_B16H8S4 }, // saddl2_v + { 0b0000111000100000000001, kVO_V_BHS }, // shadd_v + { 0b0000111000100000001001, kVO_V_BHS }, // shsub_v + { 0b0000111000100000011001, kVO_V_BHS }, // smax_v + { 0b0000111000100000101001, kVO_V_BHS }, // smaxp_v + { 0b0000111000100000011011, kVO_V_BHS }, // smin_v + { 0b0000111000100000101011, kVO_V_BHS }, // sminp_v + { 0b0000111000100000000011, kVO_SV_Any }, // sqadd_v + { 0b0000111000100000001011, kVO_SV_Any }, // sqsub_v + { 0b0000111000100000000101, kVO_V_BHS }, // srhadd_v + { 0b0000111000100000001000, kVO_V_B8H4S2 }, // ssubl_v + { 0b0100111000100000001000, kVO_V_B16H8S4 }, // ssubl2_v + { 0b0010111000100000100001, kVO_V_Any }, // sub_v + { 0b0000111000100000011000, kVO_V_B8H4S2 }, // subhn_v + { 0b0000111000100000011000, kVO_V_B16H8S4 }, // subhn2_v + { 0b0000111000000000001010, kVO_V_BHS_D2 }, // trn1_v + { 0b0000111000000000011010, kVO_V_BHS_D2 }, // trn2_v + { 0b0010111000100000011111, kVO_V_BHS }, // uaba_v + { 0b0010111000100000010100, kVO_V_B8H4S2 }, // uabal_v + { 0b0110111000100000010100, kVO_V_B16H8S4 }, // uabal2_v + { 0b0010111000100000011101, kVO_V_BHS }, // uabd_v + { 0b0010111000100000011100, kVO_V_B8H4S2 }, // uabdl_v + { 0b0110111000100000011100, kVO_V_B16H8S4 }, // uabdl2_v + { 0b0010111000100000000000, kVO_V_B8H4S2 }, // uaddl_v + { 0b0110111000100000000000, kVO_V_B16H8S4 }, // uaddl2_v + { 0b0010111000100000000001, kVO_V_BHS }, // uhadd_v + { 0b0010111000100000001001, kVO_V_BHS }, // uhsub_v + { 0b0010111000100000011001, kVO_V_BHS }, // umax_v + { 0b0010111000100000101001, kVO_V_BHS }, // umaxp_v + { 0b0010111000100000011011, kVO_V_BHS }, // umin_v + { 0b0010111000100000101011, kVO_V_BHS }, // uminp_v + { 0b0010111000100000000011, kVO_SV_Any }, // uqadd_v + { 0b0010111000100000001011, kVO_SV_Any }, // uqsub_v + { 0b0010111000100000000101, kVO_V_BHS }, // urhadd_v + { 0b0010111000100000001000, kVO_V_B8H4S2 }, // usubl_v + { 0b0110111000100000001000, kVO_V_B16H8S4 }, // usubl2_v + { 0b0000111000000000000110, kVO_V_BHS_D2 }, // uzp1_v + { 0b0000111000000000010110, kVO_V_BHS_D2 }, // uzp2_v + { 0b0000111000000000001110, kVO_V_BHS_D2 }, // zip1_v + { 0b0000111000000000011110, kVO_V_BHS_D2 } // zip2_v +}; + +const ISimdVVVI iSimdVVVI[2] = { + { 0b0010111000000000000000, kVO_V_B, 4, 11, 1 }, // ext_v + { 0b1100111001100000100011, kVO_V_D2, 6, 10, 0 } // xar_v +}; + +const ISimdVVVV iSimdVVVV[2] = { + { 0b1100111000100000000000, kVO_V_B16 }, // bcax_v + { 0b1100111000000000000000, kVO_V_B16 } // eor3_v +}; + +const ISimdVVVVx iSimdVVVVx[1] = { + { 0b1100111001000000000000, kOp_V4S, kOp_V4S, kOp_V4S, kOp_V4S } // sm3ss1_v +}; + +const ISimdVVVe iSimdVVVe[25] = { + { 0b0000111000100000100101, kVO_V_BHS, 0b0010111100000000000000, kVO_V_HS }, // mla_v + { 0b0010111000100000100101, kVO_V_BHS, 0b0010111100000000010000, kVO_V_HS }, // mls_v + { 0b0000111000100000100111, kVO_V_BHS, 0b0000111100000000100000, kVO_V_HS }, // mul_v + { 0b0000111000100000100000, kVO_V_B8H4S2, 0b0000111100000000001000, kVO_V_H4S2 }, // smlal_v + { 0b0100111000100000100000, kVO_V_B16H8S4, 0b0100111100000000001000, kVO_V_H8S4 }, // smlal2_v + { 0b0000111000100000101000, kVO_V_B8H4S2, 0b0000111100000000011000, kVO_V_H4S2 }, // smlsl_v + { 0b0100111000100000101000, kVO_V_B16H8S4, 0b0100111100000000011000, kVO_V_H8S4 }, // smlsl2_v + { 0b0000111000100000110000, kVO_V_B8H4S2, 0b0000111100000000101000, kVO_V_H4S2 }, // smull_v + { 0b0100111000100000110000, kVO_V_B16H8S4, 0b0100111100000000101000, kVO_V_H8S4 }, // smull2_v + { 0b0000111000100000100100, kVO_SV_BHS, 0b0000111100000000001100, kVO_V_H4S2 }, // sqdmlal_v + { 0b0100111000100000100100, kVO_V_B16H8S4, 0b0100111100000000001100, kVO_V_H8S4 }, // sqdmlal2_v + { 0b0000111000100000101100, kVO_SV_BHS, 0b0000111100000000011100, kVO_V_H4S2 }, // sqdmlsl_v + { 0b0100111000100000101100, kVO_V_B16H8S4, 0b0100111100000000011100, kVO_V_H8S4 }, // sqdmlsl2_v + { 0b0000111000100000101101, kVO_SV_HS, 0b0000111100000000110000, kVO_SV_HS }, // sqdmulh_v + { 0b0000111000100000110100, kVO_SV_BHS, 0b0000111100000000101100, kVO_V_H4S2 }, // sqdmull_v + { 0b0100111000100000110100, kVO_V_B16H8S4, 0b0100111100000000101100, kVO_V_H8S4 }, // sqdmull2_v + { 0b0010111000000000100001, kVO_SV_HS, 0b0010111100000000110100, kVO_SV_HS }, // sqrdmlah_v + { 0b0010111000000000100011, kVO_SV_HS, 0b0010111100000000111100, kVO_SV_HS }, // sqrdmlsh_v + { 0b0010111000100000101101, kVO_SV_HS, 0b0000111100000000110100, kVO_SV_HS }, // sqrdmulh_v + { 0b0010111000100000100000, kVO_V_B8H4S2, 0b0010111100000000001000, kVO_V_H4S2 }, // umlal_v + { 0b0110111000100000100000, kVO_V_B16H8S4, 0b0010111100000000001000, kVO_V_H8S4 }, // umlal2_v + { 0b0010111000100000101000, kVO_V_B8H4S2, 0b0010111100000000011000, kVO_V_H4S2 }, // umlsl_v + { 0b0110111000100000101000, kVO_V_B16H8S4, 0b0110111100000000011000, kVO_V_H8S4 }, // umlsl2_v + { 0b0010111000100000110000, kVO_V_B8H4S2, 0b0010111100000000101000, kVO_V_H4S2 }, // umull_v + { 0b0110111000100000110000, kVO_V_B16H8S4, 0b0110111100000000101000, kVO_V_H8S4 } // umull2_v +}; + +const ISimdVVVx iSimdVVVx[17] = { + { 0b0110111001000000111011, kOp_V4S, kOp_V8H, kOp_V8H }, // bfmmla_v + { 0b0101111000000000000000, kOp_Q, kOp_S, kOp_V4S }, // sha1c_v + { 0b0101111000000000001000, kOp_Q, kOp_S, kOp_V4S }, // sha1m_v + { 0b0101111000000000000100, kOp_Q, kOp_S, kOp_V4S }, // sha1p_v + { 0b0101111000000000001100, kOp_V4S, kOp_V4S, kOp_V4S }, // sha1su0_v + { 0b0101111000000000010000, kOp_Q, kOp_Q, kOp_V4S }, // sha256h_v + { 0b0101111000000000010100, kOp_Q, kOp_Q, kOp_V4S }, // sha256h2_v + { 0b0101111000000000011000, kOp_V4S, kOp_V4S, kOp_V4S }, // sha256su1_v + { 0b1100111001100000100000, kOp_Q, kOp_Q, kOp_V2D }, // sha512h_v + { 0b1100111001100000100001, kOp_Q, kOp_Q, kOp_V2D }, // sha512h2_v + { 0b1100111001100000100010, kOp_V2D, kOp_V2D, kOp_V2D }, // sha512su1_v + { 0b1100111001100000110000, kOp_V4S, kOp_V4S, kOp_V4S }, // sm3partw1_v + { 0b1100111001100000110001, kOp_V4S, kOp_V4S, kOp_V4S }, // sm3partw2_v + { 0b1100111001100000110010, kOp_V4S, kOp_V4S, kOp_V4S }, // sm4ekey_v + { 0b0100111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B }, // smmla_v + { 0b0110111010000000101001, kOp_V4S, kOp_V16B, kOp_V16B }, // ummla_v + { 0b0100111010000000101011, kOp_V4S, kOp_V16B, kOp_V16B } // usmmla_v +}; + +const ISimdVVx iSimdVVx[13] = { + { 0b0100111000101000010110, kOp_V16B, kOp_V16B }, // aesd_v + { 0b0100111000101000010010, kOp_V16B, kOp_V16B }, // aese_v + { 0b0100111000101000011110, kOp_V16B, kOp_V16B }, // aesimc_v + { 0b0100111000101000011010, kOp_V16B, kOp_V16B }, // aesmc_v + { 0b0001111001100011010000, kOp_H, kOp_S }, // bfcvt_v + { 0b0000111010100001011010, kOp_V4H, kOp_V4S }, // bfcvtn_v + { 0b0100111010100001011010, kOp_V8H, kOp_V4S }, // bfcvtn2_v + { 0b0001111001111110000000, kOp_GpW, kOp_D }, // fjcvtzs_v + { 0b0101111000101000000010, kOp_S, kOp_S }, // sha1h_v + { 0b0101111000101000000110, kOp_V4S, kOp_V4S }, // sha1su1_v + { 0b0101111000101000001010, kOp_V4S, kOp_V4S }, // sha256su0_v + { 0b1100111011000000100000, kOp_V2D, kOp_V2D }, // sha512su0_v + { 0b1100111011000000100001, kOp_V4S, kOp_V4S } // sm4e_v +}; + +const ISimdWWV iSimdWWV[8] = { + { 0b0000111000100000000100, kVO_V_B8H4S2 }, // saddw_v + { 0b0000111000100000000100, kVO_V_B16H8S4 }, // saddw2_v + { 0b0000111000100000001100, kVO_V_B8H4S2 }, // ssubw_v + { 0b0000111000100000001100, kVO_V_B16H8S4 }, // ssubw2_v + { 0b0010111000100000000100, kVO_V_B8H4S2 }, // uaddw_v + { 0b0010111000100000000100, kVO_V_B16H8S4 }, // uaddw2_v + { 0b0010111000100000001100, kVO_V_B8H4S2 }, // usubw_v + { 0b0010111000100000001100, kVO_V_B16H8S4 } // usubw2_v +}; + +const SimdBicOrr simdBicOrr[2] = { + { 0b0000111001100000000111, 0b0010111100000000000001 }, // bic_v + { 0b0000111010100000000111, 0b0000111100000000000001 } // orr_v +}; + +const SimdCmp simdCmp[7] = { + { 0b0010111000100000100011, 0b0000111000100000100110, kVO_V_Any }, // cmeq_v + { 0b0000111000100000001111, 0b0010111000100000100010, kVO_V_Any }, // cmge_v + { 0b0000111000100000001101, 0b0000111000100000100010, kVO_V_Any }, // cmgt_v + { 0b0010111000100000001101, 0b0000000000000000000000, kVO_V_Any }, // cmhi_v + { 0b0010111000100000001111, 0b0000000000000000000000, kVO_V_Any }, // cmhs_v + { 0b0000000000000000000000, 0b0010111000100000100110, kVO_V_Any }, // cmle_v + { 0b0000000000000000000000, 0b0000111000100000101010, kVO_V_Any } // cmlt_v +}; + +const SimdDot simdDot[5] = { + { 0b0010111001000000111111, 0b0000111101000000111100, kET_S, kET_H, kET_2H }, // bfdot_v + { 0b0000111010000000100101, 0b0000111110000000111000, kET_S, kET_B, kET_4B }, // sdot_v + { 0b0000000000000000000000, 0b0000111100000000111100, kET_S, kET_B, kET_4B }, // sudot_v + { 0b0010111010000000100101, 0b0010111110000000111000, kET_S, kET_B, kET_4B }, // udot_v + { 0b0000111010000000100111, 0b0000111110000000111100, kET_S, kET_B, kET_4B } // usdot_v +}; + +const SimdFcadd simdFcadd[1] = { + { 0b0010111000000000111001 } // fcadd_v +}; + +const SimdFccmpFccmpe simdFccmpFccmpe[2] = { + { 0b00011110001000000000010000000000 }, // fccmp_v + { 0b00011110001000000000010000010000 } // fccmpe_v +}; + +const SimdFcm simdFcm[5] = { + { 0b0000111000100000111001, kHF_C, 0b0000111010100000110110 }, // fcmeq_v + { 0b0010111000100000111001, kHF_C, 0b0010111010100000110010 }, // fcmge_v + { 0b0010111010100000111001, kHF_C, 0b0000111010100000110010 }, // fcmgt_v + { 0b0000000000000000000000, kHF_C, 0b0010111010100000110110 }, // fcmle_v + { 0b0000000000000000000000, kHF_C, 0b0000111010100000111010 } // fcmlt_v +}; + +const SimdFcmla simdFcmla[1] = { + { 0b0010111000000000110001, 0b0010111100000000000100 } // fcmla_v +}; + +const SimdFcmpFcmpe simdFcmpFcmpe[2] = { + { 0b00011110001000000010000000000000 }, // fcmp_v + { 0b00011110001000000010000000010000 } // fcmpe_v +}; + +const SimdFcvtLN simdFcvtLN[6] = { + { 0b0000111000100001011110, 0, 0 }, // fcvtl_v + { 0b0100111000100001011110, 0, 0 }, // fcvtl2_v + { 0b0000111000100001011010, 0, 0 }, // fcvtn_v + { 0b0100111000100001011010, 0, 0 }, // fcvtn2_v + { 0b0010111000100001011010, 1, 1 }, // fcvtxn_v + { 0b0110111000100001011010, 1, 0 } // fcvtxn2_v +}; + +const SimdFcvtSV simdFcvtSV[12] = { + { 0b0000111000100001110010, 0b0000000000000000000000, 0b0001111000100100000000, 1 }, // fcvtas_v + { 0b0010111000100001110010, 0b0000000000000000000000, 0b0001111000100101000000, 1 }, // fcvtau_v + { 0b0000111000100001101110, 0b0000000000000000000000, 0b0001111000110000000000, 1 }, // fcvtms_v + { 0b0010111000100001101110, 0b0000000000000000000000, 0b0001111000110001000000, 1 }, // fcvtmu_v + { 0b0000111000100001101010, 0b0000000000000000000000, 0b0001111000100000000000, 1 }, // fcvtns_v + { 0b0010111000100001101010, 0b0000000000000000000000, 0b0001111000100001000000, 1 }, // fcvtnu_v + { 0b0000111010100001101010, 0b0000000000000000000000, 0b0001111000101000000000, 1 }, // fcvtps_v + { 0b0010111010100001101010, 0b0000000000000000000000, 0b0001111000101001000000, 1 }, // fcvtpu_v + { 0b0000111010100001101110, 0b0000111100000000111111, 0b0001111000111000000000, 1 }, // fcvtzs_v + { 0b0010111010100001101110, 0b0010111100000000111111, 0b0001111000111001000000, 1 }, // fcvtzu_v + { 0b0000111000100001110110, 0b0000111100000000111001, 0b0001111000100010000000, 0 }, // scvtf_v + { 0b0010111000100001110110, 0b0010111100000000111001, 0b0001111000100011000000, 0 } // ucvtf_v +}; + +const SimdFmlal simdFmlal[6] = { + { 0b0010111011000000111111, 0b0000111111000000111100, 0, kET_S, kET_H, kET_H }, // bfmlalb_v + { 0b0110111011000000111111, 0b0100111111000000111100, 0, kET_S, kET_H, kET_H }, // bfmlalt_v + { 0b0000111000100000111011, 0b0000111110000000000000, 1, kET_S, kET_H, kET_H }, // fmlal_v + { 0b0010111000100000110011, 0b0010111110000000100000, 1, kET_S, kET_H, kET_H }, // fmlal2_v + { 0b0000111010100000111011, 0b0000111110000000010000, 1, kET_S, kET_H, kET_H }, // fmlsl_v + { 0b0010111010100000110011, 0b0010111110000000110000, 1, kET_S, kET_H, kET_H } // fmlsl2_v +}; + +const SimdLdNStN simdLdNStN[12] = { + { 0b0000110101000000000000, 0b0000110001000000001000, 1, 0 }, // ld1_v + { 0b0000110101000000110000, 0b0000000000000000000000, 1, 1 }, // ld1r_v + { 0b0000110101100000000000, 0b0000110001000000100000, 2, 0 }, // ld2_v + { 0b0000110101100000110000, 0b0000000000000000000000, 2, 1 }, // ld2r_v + { 0b0000110101000000001000, 0b0000110001000000010000, 3, 0 }, // ld3_v + { 0b0000110101000000111000, 0b0000000000000000000000, 3, 1 }, // ld3r_v + { 0b0000110101100000001000, 0b0000110001000000000000, 4, 0 }, // ld4_v + { 0b0000110101100000111000, 0b0000000000000000000000, 4, 1 }, // ld4r_v + { 0b0000110100000000000000, 0b0000110000000000001000, 1, 0 }, // st1_v + { 0b0000110100100000000000, 0b0000110000000000100000, 2, 0 }, // st2_v + { 0b0000110100000000001000, 0b0000110000000000010000, 3, 0 }, // st3_v + { 0b0000110100100000001000, 0b0000110000000000000000, 4, 0 } // st4_v +}; + +const SimdLdSt simdLdSt[2] = { + { 0b0011110101, 0b00111100010, 0b00111100011, 0b00011100, Inst::kIdLdur_v }, // ldr_v + { 0b0011110100, 0b00111100000, 0b00111100001, 0b00000000, Inst::kIdStur_v } // str_v +}; + +const SimdLdpStp simdLdpStp[4] = { + { 0b0010110001, 0b0000000000 }, // ldnp_v + { 0b0010110101, 0b0010110011 }, // ldp_v + { 0b0010110000, 0b0000000000 }, // stnp_v + { 0b0010110100, 0b0010110010 } // stp_v +}; + +const SimdLdurStur simdLdurStur[2] = { + { 0b0011110001000000000000 }, // ldur_v + { 0b0011110000000000000000 } // stur_v +}; + +const SimdMoviMvni simdMoviMvni[2] = { + { 0b0000111100000000000001, 0 }, // movi_v + { 0b0000111100000000000001, 1 } // mvni_v +}; + +const SimdShift simdShift[40] = { + { 0b0000000000000000000000, 0b0000111100000000100011, 1, kVO_V_B8H4S2 }, // rshrn_v + { 0b0000000000000000000000, 0b0100111100000000100011, 1, kVO_V_B16H8S4 }, // rshrn2_v + { 0b0000000000000000000000, 0b0000111100000000010101, 0, kVO_V_Any }, // shl_v + { 0b0000000000000000000000, 0b0000111100000000100001, 1, kVO_V_B8H4S2 }, // shrn_v + { 0b0000000000000000000000, 0b0100111100000000100001, 1, kVO_V_B16H8S4 }, // shrn2_v + { 0b0000000000000000000000, 0b0010111100000000010101, 0, kVO_V_Any }, // sli_v + { 0b0000111000100000010111, 0b0000000000000000000000, 1, kVO_SV_Any }, // sqrshl_v + { 0b0000000000000000000000, 0b0000111100000000100111, 1, kVO_SV_B8H4S2 }, // sqrshrn_v + { 0b0000000000000000000000, 0b0100111100000000100111, 1, kVO_V_B16H8S4 }, // sqrshrn2_v + { 0b0000000000000000000000, 0b0010111100000000100011, 1, kVO_SV_B8H4S2 }, // sqrshrun_v + { 0b0000000000000000000000, 0b0110111100000000100011, 1, kVO_V_B16H8S4 }, // sqrshrun2_v + { 0b0000111000100000010011, 0b0000111100000000011101, 0, kVO_SV_Any }, // sqshl_v + { 0b0000000000000000000000, 0b0010111100000000011001, 0, kVO_SV_Any }, // sqshlu_v + { 0b0000000000000000000000, 0b0000111100000000100101, 1, kVO_SV_B8H4S2 }, // sqshrn_v + { 0b0000000000000000000000, 0b0100111100000000100101, 1, kVO_V_B16H8S4 }, // sqshrn2_v + { 0b0000000000000000000000, 0b0010111100000000100001, 1, kVO_SV_B8H4S2 }, // sqshrun_v + { 0b0000000000000000000000, 0b0110111100000000100001, 1, kVO_V_B16H8S4 }, // sqshrun2_v + { 0b0000000000000000000000, 0b0010111100000000010001, 1, kVO_V_Any }, // sri_v + { 0b0000111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any }, // srshl_v + { 0b0000000000000000000000, 0b0000111100000000001001, 1, kVO_V_Any }, // srshr_v + { 0b0000000000000000000000, 0b0000111100000000001101, 1, kVO_V_Any }, // srsra_v + { 0b0000111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any }, // sshl_v + { 0b0000000000000000000000, 0b0000111100000000101001, 0, kVO_V_B8H4S2 }, // sshll_v + { 0b0000000000000000000000, 0b0100111100000000101001, 0, kVO_V_B16H8S4 }, // sshll2_v + { 0b0000000000000000000000, 0b0000111100000000000001, 1, kVO_V_Any }, // sshr_v + { 0b0000000000000000000000, 0b0000111100000000000101, 1, kVO_V_Any }, // ssra_v + { 0b0010111000100000010111, 0b0000000000000000000000, 0, kVO_SV_Any }, // uqrshl_v + { 0b0000000000000000000000, 0b0010111100000000100111, 1, kVO_SV_B8H4S2 }, // uqrshrn_v + { 0b0000000000000000000000, 0b0110111100000000100111, 1, kVO_V_B16H8S4 }, // uqrshrn2_v + { 0b0010111000100000010011, 0b0010111100000000011101, 0, kVO_SV_Any }, // uqshl_v + { 0b0000000000000000000000, 0b0010111100000000100101, 1, kVO_SV_B8H4S2 }, // uqshrn_v + { 0b0000000000000000000000, 0b0110111100000000100101, 1, kVO_V_B16H8S4 }, // uqshrn2_v + { 0b0010111000100000010101, 0b0000000000000000000000, 0, kVO_V_Any }, // urshl_v + { 0b0000000000000000000000, 0b0010111100000000001001, 1, kVO_V_Any }, // urshr_v + { 0b0000000000000000000000, 0b0010111100000000001101, 1, kVO_V_Any }, // ursra_v + { 0b0010111000100000010001, 0b0000000000000000000000, 0, kVO_V_Any }, // ushl_v + { 0b0000000000000000000000, 0b0010111100000000101001, 0, kVO_V_B8H4S2 }, // ushll_v + { 0b0000000000000000000000, 0b0110111100000000101001, 0, kVO_V_B16H8S4 }, // ushll2_v + { 0b0000000000000000000000, 0b0010111100000000000001, 1, kVO_V_Any }, // ushr_v + { 0b0000000000000000000000, 0b0010111100000000000101, 1, kVO_V_Any } // usra_v +}; + +const SimdShiftES simdShiftES[2] = { + { 0b0010111000100001001110, kVO_V_B8H4S2 }, // shll_v + { 0b0110111000100001001110, kVO_V_B16H8S4 } // shll2_v +}; + +const SimdSm3tt simdSm3tt[4] = { + { 0b1100111001000000100000 }, // sm3tt1a_v + { 0b1100111001000000100001 }, // sm3tt1b_v + { 0b1100111001000000100010 }, // sm3tt2a_v + { 0b1100111001000000100011 } // sm3tt2b_v +}; + +const SimdSmovUmov simdSmovUmov[2] = { + { 0b0000111000000000001011, kVO_V_BHS, 1 }, // smov_v + { 0b0000111000000000001111, kVO_V_Any, 0 } // umov_v +}; + +const SimdSxtlUxtl simdSxtlUxtl[4] = { + { 0b0000111100000000101001, kVO_V_B8H4S2 }, // sxtl_v + { 0b0100111100000000101001, kVO_V_B16H8S4 }, // sxtl2_v + { 0b0010111100000000101001, kVO_V_B8H4S2 }, // uxtl_v + { 0b0110111100000000101001, kVO_V_B16H8S4 } // uxtl2_v +}; + +const SimdTblTbx simdTblTbx[2] = { + { 0b0000111000000000000000 }, // tbl_v + { 0b0000111000000000000100 } // tbx_v +}; +// ---------------------------------------------------------------------------- +// ${EncodingData:End} + +} // {EncodingData} +} // {InstDB} + +/* +// ${CommonData:Begin} +// ------------------- Automatically generated, do not edit ------------------- +const InstDB::CommonInfo InstDB::commonData[] = { + { 0} // #0 [ref=440x] +}; +// ---------------------------------------------------------------------------- +// ${CommonData:End} +*/ + +// ArmUtil - Id <-> Name +// ===================== + +#ifndef ASMJIT_DISABLE_TEXT +// ${NameData:Begin} +// ------------------- Automatically generated, do not edit ------------------- +const char InstDB::_nameData[] = + "\0" "adc\0" "adcs\0" "addg\0" "adds\0" "addv\0" "adr\0" "adrp\0" "aesd\0" "aese\0" "aesimc\0" "aesmc\0" "and\0" + "ands\0" "asr\0" "asrv\0" "at\0" "autda\0" "autdb\0" "autdza\0" "autdzb\0" "autia\0" "autia1716\0" "autiasp\0" + "autiaz\0" "autib\0" "autib1716\0" "autibsp\0" "autibz\0" "autiza\0" "autizb\0" "axflag\0" "bcax\0" "bfc\0" "bfcvt\0" + "bfcvtn\0" "bfcvtn2\0" "bfdot\0" "bfi\0" "bfmlalb\0" "bfmlalt\0" "bfmmla\0" "bfxil\0" "bic\0" "bics\0" "bif\0" + "blr\0" "br\0" "brk\0" "bsl\0" "cas\0" "casa\0" "casab\0" "casah\0" "casal\0" "casalb\0" "casalh\0" "casb\0" "cash\0" + "casl\0" "caslb\0" "caslh\0" "casp\0" "caspa\0" "caspal\0" "caspl\0" "cbnz\0" "cbz\0" "ccmn\0" "cfinv\0" "cinc\0" + "cinv\0" "clrex\0" "cls\0" "clz\0" "cmhi\0" "cmhs\0" "cmpp\0" "cmtst\0" "cneg\0" "cnt\0" "crc32b\0" "crc32cb\0" + "crc32ch\0" "crc32cw\0" "crc32cx\0" "crc32h\0" "crc32w\0" "crc32x\0" "csdb\0" "cset\0" "csetm\0" "csinc\0" "csinv\0" + "csneg\0" "dcps1\0" "dcps2\0" "dcps3\0" "dgh\0" "dmb\0" "drps\0" "dsb\0" "dup\0" "eon\0" "eor3\0" "eret\0" "esb\0" + "ext\0" "extr\0" "fabd\0" "fabs\0" "facge\0" "facgt\0" "fadd\0" "faddp\0" "fcadd\0" "fccmp\0" "fccmpe\0" "fcmeq\0" + "fcmge\0" "fcmgt\0" "fcmla\0" "fcmle\0" "fcmlt\0" "fcmp\0" "fcmpe\0" "fcsel\0" "fcvtas\0" "fcvtau\0" "fcvtl\0" + "fcvtl2\0" "fcvtms\0" "fcvtmu\0" "fcvtns\0" "fcvtnu\0" "fcvtps\0" "fcvtpu\0" "fcvtxn\0" "fcvtxn2\0" "fcvtzs\0" + "fcvtzu\0" "fdiv\0" "fjcvtzs\0" "fmadd\0" "fmax\0" "fmaxnm\0" "fmaxnmp\0" "fmaxnmv\0" "fmaxp\0" "fmaxv\0" "fmin\0" + "fminnm\0" "fminnmp\0" "fminnmv\0" "fminp\0" "fminv\0" "fmla\0" "fmlal\0" "fmlal2\0" "fmls\0" "fmlsl\0" "fmlsl2\0" + "fmov\0" "fmsub\0" "fmul\0" "fmulx\0" "fneg\0" "fnmadd\0" "fnmsub\0" "fnmul\0" "frecpe\0" "frecps\0" "frecpx\0" + "frint32x\0" "frint32z\0" "frint64x\0" "frint64z\0" "frinta\0" "frinti\0" "frintm\0" "frintn\0" "frintp\0" "frintx\0" + "frintz\0" "frsqrte\0" "frsqrts\0" "fsqrt\0" "fsub\0" "gmi\0" "hint\0" "hlt\0" "hvc\0" "ins\0" "isb\0" "ld1\0" + "ld1r\0" "ld2\0" "ld2r\0" "ld3\0" "ld3r\0" "ld4\0" "ld4r\0" "ldadd\0" "ldadda\0" "ldaddab\0" "ldaddah\0" "ldaddal\0" + "ldaddalb\0" "ldaddalh\0" "ldaddb\0" "ldaddh\0" "ldaddl\0" "ldaddlb\0" "ldaddlh\0" "ldar\0" "ldarb\0" "ldarh\0" + "ldaxp\0" "ldaxr\0" "ldaxrb\0" "ldaxrh\0" "ldclr\0" "ldclra\0" "ldclrab\0" "ldclrah\0" "ldclral\0" "ldclralb\0" + "ldclralh\0" "ldclrb\0" "ldclrh\0" "ldclrl\0" "ldclrlb\0" "ldclrlh\0" "ldeor\0" "ldeora\0" "ldeorab\0" "ldeorah\0" + "ldeoral\0" "ldeoralb\0" "ldeoralh\0" "ldeorb\0" "ldeorh\0" "ldeorl\0" "ldeorlb\0" "ldeorlh\0" "ldg\0" "ldgm\0" + "ldlar\0" "ldlarb\0" "ldlarh\0" "ldnp\0" "ldp\0" "ldpsw\0" "ldr\0" "ldraa\0" "ldrab\0" "ldrb\0" "ldrh\0" "ldrsb\0" + "ldrsh\0" "ldrsw\0" "ldset\0" "ldseta\0" "ldsetab\0" "ldsetah\0" "ldsetal\0" "ldsetalb\0" "ldsetalh\0" "ldsetb\0" + "ldseth\0" "ldsetl\0" "ldsetlb\0" "ldsetlh\0" "ldsmax\0" "ldsmaxa\0" "ldsmaxab\0" "ldsmaxah\0" "ldsmaxal\0" + "ldsmaxalb\0" "ldsmaxalh\0" "ldsmaxb\0" "ldsmaxh\0" "ldsmaxl\0" "ldsmaxlb\0" "ldsmaxlh\0" "ldsmin\0" "ldsmina\0" + "ldsminab\0" "ldsminah\0" "ldsminal\0" "ldsminalb\0" "ldsminalh\0" "ldsminb\0" "ldsminh\0" "ldsminl\0" "ldsminlb\0" + "ldsminlh\0" "ldtr\0" "ldtrb\0" "ldtrh\0" "ldtrsb\0" "ldtrsh\0" "ldtrsw\0" "ldumax\0" "ldumaxa\0" "ldumaxab\0" + "ldumaxah\0" "ldumaxal\0" "ldumaxalb\0" "ldumaxalh\0" "ldumaxb\0" "ldumaxh\0" "ldumaxl\0" "ldumaxlb\0" "ldumaxlh\0" + "ldumin\0" "ldumina\0" "lduminab\0" "lduminah\0" "lduminal\0" "lduminalb\0" "lduminalh\0" "lduminb\0" "lduminh\0" + "lduminl\0" "lduminlb\0" "lduminlh\0" "ldur\0" "ldurb\0" "ldurh\0" "ldursb\0" "ldursh\0" "ldursw\0" "ldxp\0" "ldxr\0" + "ldxrb\0" "ldxrh\0" "lslv\0" "lsr\0" "lsrv\0" "mneg\0" "movi\0" "movk\0" "movn\0" "movz\0" "mrs\0" "msr\0" "mvn\0" + "mvni\0" "negs\0" "ngc\0" "ngcs\0" "nop\0" "not\0" "orn\0" "orr\0" "pacda\0" "pacdb\0" "pacdza\0" "pacdzb\0" + "pacga\0" "pmul\0" "pmull\0" "pmull2\0" "pssbb\0" "raddhn\0" "raddhn2\0" "rax1\0" "rbit\0" "rev\0" "rev16\0" + "rev32\0" "rev64\0" "ror\0" "rorv\0" "rsubhn\0" "rsubhn2\0" "saba\0" "sabal\0" "sabal2\0" "sabd\0" "sabdl\0" + "sabdl2\0" "sadalp\0" "saddl\0" "saddl2\0" "saddlp\0" "saddlv\0" "saddw\0" "saddw2\0" "sbc\0" "sbcs\0" "sbfiz\0" + "sbfm\0" "sbfx\0" "scvtf\0" "sdiv\0" "setf16\0" "setf8\0" "sev\0" "sevl\0" "sha1c\0" "sha1h\0" "sha1m\0" "sha1p\0" + "sha1su0\0" "sha1su1\0" "sha256h\0" "sha256h2\0" "sha256su0\0" "sha256su1\0" "sha512h\0" "sha512h2\0" "sha512su0\0" + "sha512su1\0" "shadd\0" "shsub\0" "sli\0" "sm3partw1\0" "sm3partw2\0" "sm3ss1\0" "sm3tt1a\0" "sm3tt1b\0" "sm3tt2a\0" + "sm3tt2b\0" "sm4e\0" "sm4ekey\0" "smaddl\0" "smaxp\0" "smaxv\0" "sminp\0" "sminv\0" "smlal\0" "smlal2\0" "smlsl\0" + "smlsl2\0" "smnegl\0" "smov\0" "smsubl\0" "smulh\0" "smull\0" "smull2\0" "sqabs\0" "sqdmlal\0" "sqdmlal2\0" + "sqdmlsl\0" "sqdmlsl2\0" "sqdmulh\0" "sqdmull\0" "sqdmull2\0" "sqneg\0" "sqrdmlah\0" "sqrdmlsh\0" "sqrdmulh\0" + "sqrshl\0" "sqrshrn\0" "sqrshrn2\0" "sqrshrun\0" "sqrshrun2\0" "sqshl\0" "sqshlu\0" "sqshrn\0" "sqshrn2\0" + "sqshrun\0" "sqshrun2\0" "sqsub\0" "sqxtn\0" "sqxtn2\0" "sqxtun\0" "sqxtun2\0" "srhadd\0" "sri\0" "srshl\0" "srshr\0" + "srsra\0" "sshl\0" "sshll\0" "sshll2\0" "sshr\0" "ssra\0" "ssubl\0" "ssubl2\0" "ssubw\0" "ssubw2\0" "st1\0" "st2\0" + "st2g\0" "st3\0" "st4\0" "stadd\0" "staddb\0" "staddh\0" "staddl\0" "staddlb\0" "staddlh\0" "stclr\0" "stclrb\0" + "stclrh\0" "stclrl\0" "stclrlb\0" "stclrlh\0" "steor\0" "steorb\0" "steorh\0" "steorl\0" "steorlb\0" "steorlh\0" + "stg\0" "stgm\0" "stgp\0" "stllr\0" "stllrb\0" "stllrh\0" "stlr\0" "stlrb\0" "stlrh\0" "stlxp\0" "stlxr\0" "stlxrb\0" + "stlxrh\0" "stnp\0" "stp\0" "str\0" "strb\0" "strh\0" "stset\0" "stsetb\0" "stseth\0" "stsetl\0" "stsetlb\0" + "stsetlh\0" "stsmax\0" "stsmaxb\0" "stsmaxh\0" "stsmaxl\0" "stsmaxlb\0" "stsmaxlh\0" "stsmin\0" "stsminb\0" + "stsminh\0" "stsminl\0" "stsminlb\0" "stsminlh\0" "sttr\0" "sttrb\0" "sttrh\0" "stumax\0" "stumaxb\0" "stumaxh\0" + "stumaxl\0" "stumaxlb\0" "stumaxlh\0" "stumin\0" "stuminb\0" "stuminh\0" "stuminl\0" "stuminlb\0" "stuminlh\0" + "stur\0" "sturb\0" "sturh\0" "stxp\0" "stxr\0" "stxrb\0" "stxrh\0" "stz2g\0" "stzg\0" "stzgm\0" "subg\0" "subp\0" + "subps\0" "subs\0" "sudot\0" "suqadd\0" "svc\0" "swp\0" "swpa\0" "swpab\0" "swpah\0" "swpal\0" "swpalb\0" "swpalh\0" + "swpb\0" "swph\0" "swpl\0" "swplb\0" "swplh\0" "sxtb\0" "sxth\0" "sxtl\0" "sxtl2\0" "sxtw\0" "sys\0" "tbl\0" "tbnz\0" + "tbx\0" "tbz\0" "tlbi\0" "trn1\0" "trn2\0" "uaba\0" "uabal\0" "uabal2\0" "uabd\0" "uabdl\0" "uabdl2\0" "uadalp\0" + "uaddl\0" "uaddl2\0" "uaddlp\0" "uaddlv\0" "uaddw\0" "uaddw2\0" "ubfiz\0" "ubfm\0" "ubfx\0" "ucvtf\0" "udf\0" + "udiv\0" "uhadd\0" "uhsub\0" "umaddl\0" "umaxp\0" "umaxv\0" "uminp\0" "uminv\0" "umlal\0" "umlal2\0" "umlsl\0" + "umlsl2\0" "ummla\0" "umnegl\0" "umov\0" "umsubl\0" "umulh\0" "umull\0" "umull2\0" "uqrshl\0" "uqrshrn\0" + "uqrshrn2\0" "uqshl\0" "uqshrn\0" "uqshrn2\0" "uqsub\0" "uqxtn\0" "uqxtn2\0" "urecpe\0" "urhadd\0" "urshl\0" + "urshr\0" "ursqrte\0" "ursra\0" "usdot\0" "ushl\0" "ushll\0" "ushll2\0" "ushr\0" "usmmla\0" "usqadd\0" "usra\0" + "usubl\0" "usubl2\0" "usubw\0" "usubw2\0" "uxtb\0" "uxth\0" "uxtl\0" "uxtl2\0" "uzp1\0" "uzp2\0" "wfe\0" "wfi\0" + "xaflag\0" "xar\0" "xpacd\0" "xpaci\0" "xpaclri\0" "yield\0" "zip1\0" "zip2"; + +const InstDB::InstNameIndex InstDB::instNameIndex[26] = { + { Inst::kIdAdc , Inst::kIdAnd_v + 1 }, + { Inst::kIdB , Inst::kIdBsl_v + 1 }, + { Inst::kIdCas , Inst::kIdCnt_v + 1 }, + { Inst::kIdDc , Inst::kIdDup_v + 1 }, + { Inst::kIdEon , Inst::kIdExt_v + 1 }, + { Inst::kIdFabd_v , Inst::kIdFsub_v + 1 }, + { Inst::kIdGmi , Inst::kIdGmi + 1 }, + { Inst::kIdHint , Inst::kIdHvc + 1 }, + { Inst::kIdIc , Inst::kIdIns_v + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 }, + { Inst::kIdLdadd , Inst::kIdLdur_v + 1 }, + { Inst::kIdMadd , Inst::kIdMvni_v + 1 }, + { Inst::kIdNeg , Inst::kIdNot_v + 1 }, + { Inst::kIdOrn , Inst::kIdOrr_v + 1 }, + { Inst::kIdPacda , Inst::kIdPmull2_v + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 }, + { Inst::kIdRbit , Inst::kIdRsubhn2_v + 1 }, + { Inst::kIdSbc , Inst::kIdSxtl2_v + 1 }, + { Inst::kIdTlbi , Inst::kIdTrn2_v + 1 }, + { Inst::kIdUbfiz , Inst::kIdUzp2_v + 1 }, + { Inst::kIdNone , Inst::kIdNone + 1 }, + { Inst::kIdWfe , Inst::kIdWfi + 1 }, + { Inst::kIdXaflag , Inst::kIdXtn2_v + 1 }, + { Inst::kIdYield , Inst::kIdYield + 1 }, + { Inst::kIdZip1_v , Inst::kIdZip2_v + 1 } +}; +// ---------------------------------------------------------------------------- +// ${NameData:End} +#endif + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_AARCH64 diff --git a/src/asmjit/arm/a64instdb.h b/src/asmjit/arm/a64instdb.h new file mode 100644 index 0000000..0575d1a --- /dev/null +++ b/src/asmjit/arm/a64instdb.h @@ -0,0 +1,74 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64INSTDB_H_INCLUDED +#define ASMJIT_ARM_A64INSTDB_H_INCLUDED + +#include "../arm/a64globals.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \addtogroup asmjit_a64 +//! \{ + +//! Instruction database (AArch64). +namespace InstDB { + +//! Instruction flags. +enum InstFlags : uint32_t { + //! The instruction provides conditional execution. + kInstFlagCond = 0x00000001u, + //! SIMD instruction that processes elements in pairs. + kInstFlagPair = 0x00000002u, + //! SIMD instruction that does widening (Long). + kInstFlagLong = 0x00000004u, + //! SIMD instruction that does narrowing (Narrow). + kInstFlagNarrow = 0x00000008u, + //! SIMD element access of half-words can only be used with v0..15. + kInstFlagVH0_15 = 0x00000010u, + + //! Instruction may consecutive registers if the number of operands is greater than 2. + kInstFlagConsecutive = 0x00000080u +}; + +//! Instruction information (AArch64). +struct InstInfo { + //! Instruction encoding type. + uint32_t _encoding : 8; + //! Index to data specific to each encoding type. + uint32_t _encodingDataIndex : 8; + uint32_t _reserved : 2; + //! Index to \ref _nameData. + uint32_t _nameDataIndex : 14; + + uint16_t _rwInfoIndex; + uint16_t _flags; + + //! \name Accessors + //! \{ + + inline uint32_t rwInfoIndex() const noexcept { return _rwInfoIndex; } + inline uint32_t flags() const noexcept { return _flags; } + + inline bool hasFlag(uint32_t flag) const { return (_flags & flag) != 0; } + + //! \} +}; + +ASMJIT_VARAPI const InstInfo _instInfoTable[]; + +static inline const InstInfo& infoById(InstId instId) noexcept { + instId &= uint32_t(InstIdParts::kRealId); + ASMJIT_ASSERT(Inst::isDefinedId(instId)); + return _instInfoTable[instId]; +} + +} // {InstDB} + +//! \} + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_A64INSTDB_H_INCLUDED diff --git a/src/asmjit/arm/a64instdb_p.h b/src/asmjit/arm/a64instdb_p.h new file mode 100644 index 0000000..eb4f3f8 --- /dev/null +++ b/src/asmjit/arm/a64instdb_p.h @@ -0,0 +1,876 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64INSTDB_H_P_INCLUDED +#define ASMJIT_ARM_A64INSTDB_H_P_INCLUDED + +#include "../core/codeholder.h" +#include "../arm/a64instdb.h" +#include "../arm/a64operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \cond INTERNAL +//! \addtogroup asmjit_a64 +//! \{ + +namespace InstDB { + +// a64::InstDB - Constants Used by Instructions +// ============================================ + +// GP register types supported by base instructions. +static constexpr uint32_t kW = 0x1; +static constexpr uint32_t kX = 0x2; +static constexpr uint32_t kWX = 0x3; + +// GP high register IDs supported by the instruction. +static constexpr uint32_t kZR = Gp::kIdZr; +static constexpr uint32_t kSP = Gp::kIdSp; + +// a64::InstDB - RWInfo +// ==================== + +enum RWInfoType : uint32_t { + kRWI_R, + kRWI_RW, + kRWI_RX, + kRWI_RRW, + kRWI_RWX, + kRWI_W, + kRWI_WRW, + kRWI_WRX, + kRWI_WRRW, + kRWI_WRRX, + kRWI_WW, + kRWI_X, + kRWI_XRX, + kRWI_XXRRX, + + kRWI_LDn, + kRWI_STn, + + kRWI_SpecialStart = kRWI_LDn +}; + +// a64::InstDB - ElementType +// ========================= + +enum ElementType : uint8_t { + kET_None = Vec::kElementTypeNone, + kET_B = Vec::kElementTypeB, + kET_H = Vec::kElementTypeH, + kET_S = Vec::kElementTypeS, + kET_D = Vec::kElementTypeD, + kET_2H = Vec::kElementTypeH2, + kET_4B = Vec::kElementTypeB4 +}; + +// a64::InstDB - GpType +// ==================== + +enum GpType : uint8_t { + kGp_W, + kGp_X, + kGp_X_SP +}; + +// a64::InstDB - OPSig +// =================== + +enum kOpSignature : uint32_t { + kOp_GpW = GpW::kSignature, + kOp_GpX = GpX::kSignature, + + kOp_B = VecB::kSignature, + kOp_H = VecH::kSignature, + kOp_S = VecS::kSignature, + kOp_D = VecD::kSignature, + kOp_Q = VecV::kSignature, + + kOp_V8B = VecD::kSignature | Vec::kSignatureElementB, + kOp_V4H = VecD::kSignature | Vec::kSignatureElementH, + kOp_V2S = VecD::kSignature | Vec::kSignatureElementS, + + kOp_V16B = VecV::kSignature | Vec::kSignatureElementB, + kOp_V8H = VecV::kSignature | Vec::kSignatureElementH, + kOp_V4S = VecV::kSignature | Vec::kSignatureElementS, + kOp_V2D = VecV::kSignature | Vec::kSignatureElementD +}; + +// a64::InstDB - HFConv +// ==================== + +enum kHFConv : uint32_t { + //! FP16 version of the instruction is not available. + kHF_N, + + //! Doesn't do any change to the opcode. + kHF_0, + + kHF_A, + kHF_B, + kHF_C, + kHF_D, + + kHF_Count +}; + +// a64::InstDB - VOType +// ==================== + +//! Vector operand type combinations used by FP&SIMD instructions. +enum VOType : uint32_t { + kVO_V_B, + kVO_V_BH, + kVO_V_BH_4S, + kVO_V_BHS, + kVO_V_BHS_D2, + kVO_V_HS, + kVO_V_S, + + kVO_V_B8H4, + kVO_V_B8H4S2, + kVO_V_B8D1, + kVO_V_H4S2, + + kVO_V_B16, + kVO_V_B16H8, + kVO_V_B16H8S4, + kVO_V_B16D2, + kVO_V_H8S4, + kVO_V_S4, + kVO_V_D2, + + kVO_SV_BHS, + kVO_SV_B8H4S2, + kVO_SV_HS, + kVO_V_Any, + kVO_SV_Any, + + kVO_Count +}; + +// a64::InstDB - EncodingId +// ======================== + +// ${EncodingId:Begin} +// ------------------- Automatically generated, do not edit ------------------- +enum EncodingId : uint32_t { + kEncodingNone = 0, + kEncodingBaseAddSub, + kEncodingBaseAdr, + kEncodingBaseAtDcIcTlbi, + kEncodingBaseAtomicCasp, + kEncodingBaseAtomicOp, + kEncodingBaseAtomicSt, + kEncodingBaseBfc, + kEncodingBaseBfi, + kEncodingBaseBfm, + kEncodingBaseBfx, + kEncodingBaseBranchCmp, + kEncodingBaseBranchReg, + kEncodingBaseBranchRel, + kEncodingBaseBranchTst, + kEncodingBaseCCmp, + kEncodingBaseCInc, + kEncodingBaseCSel, + kEncodingBaseCSet, + kEncodingBaseCmpCmn, + kEncodingBaseExtend, + kEncodingBaseExtract, + kEncodingBaseLdSt, + kEncodingBaseLdpStp, + kEncodingBaseLdxp, + kEncodingBaseLogical, + kEncodingBaseMov, + kEncodingBaseMovKNZ, + kEncodingBaseMrs, + kEncodingBaseMsr, + kEncodingBaseMvnNeg, + kEncodingBaseOp, + kEncodingBaseOpImm, + kEncodingBaseR, + kEncodingBaseRM_NoImm, + kEncodingBaseRM_SImm10, + kEncodingBaseRM_SImm9, + kEncodingBaseRR, + kEncodingBaseRRII, + kEncodingBaseRRR, + kEncodingBaseRRRR, + kEncodingBaseRev, + kEncodingBaseShift, + kEncodingBaseStx, + kEncodingBaseStxp, + kEncodingBaseSys, + kEncodingBaseTst, + kEncodingFSimdPair, + kEncodingFSimdSV, + kEncodingFSimdVV, + kEncodingFSimdVVV, + kEncodingFSimdVVVV, + kEncodingFSimdVVVe, + kEncodingISimdPair, + kEncodingISimdSV, + kEncodingISimdVV, + kEncodingISimdVVV, + kEncodingISimdVVVI, + kEncodingISimdVVVV, + kEncodingISimdVVVVx, + kEncodingISimdVVVe, + kEncodingISimdVVVx, + kEncodingISimdVVx, + kEncodingISimdWWV, + kEncodingSimdBicOrr, + kEncodingSimdCmp, + kEncodingSimdDot, + kEncodingSimdDup, + kEncodingSimdFcadd, + kEncodingSimdFccmpFccmpe, + kEncodingSimdFcm, + kEncodingSimdFcmla, + kEncodingSimdFcmpFcmpe, + kEncodingSimdFcsel, + kEncodingSimdFcvt, + kEncodingSimdFcvtLN, + kEncodingSimdFcvtSV, + kEncodingSimdFmlal, + kEncodingSimdFmov, + kEncodingSimdIns, + kEncodingSimdLdNStN, + kEncodingSimdLdSt, + kEncodingSimdLdpStp, + kEncodingSimdLdurStur, + kEncodingSimdMov, + kEncodingSimdMoviMvni, + kEncodingSimdShift, + kEncodingSimdShiftES, + kEncodingSimdSm3tt, + kEncodingSimdSmovUmov, + kEncodingSimdSxtlUxtl, + kEncodingSimdTblTbx +}; +// ---------------------------------------------------------------------------- +// ${EncodingId:End} + +// a64::InstDB::EncodingData +// ========================= + +namespace EncodingData { + +#define M_OPCODE(field, bits) \ + uint32_t _##field : bits; \ + inline constexpr uint32_t field() const noexcept { return uint32_t(_##field) << (32 - bits); } + +struct BaseOp { + uint32_t opcode; +}; + +struct BaseOpImm { + uint32_t opcode; + uint16_t immBits; + uint16_t immOffset; +}; + +struct BaseR { + uint32_t opcode; + uint32_t rType : 8; + uint32_t rHiId : 8; + uint32_t rShift : 8; +}; + +struct BaseRR { + uint32_t opcode; + uint32_t aType : 2; + uint32_t aHiId : 6; + uint32_t aShift : 5; + uint32_t bType : 2; + uint32_t bHiId : 6; + uint32_t bShift : 5; + uint32_t uniform : 1; +}; + +struct BaseRRR { + M_OPCODE(opcode, 22) + uint32_t aType : 2; + uint32_t aHiId : 6; + uint32_t bType : 2; + uint32_t bHiId : 6; + uint32_t cType : 2; + uint32_t cHiId : 6; + uint32_t uniform : 1; +}; + +struct BaseRRRR { + M_OPCODE(opcode, 22) + uint32_t aType : 2; + uint32_t aHiId : 6; + uint32_t bType : 2; + uint32_t bHiId : 6; + uint32_t cType : 2; + uint32_t cHiId : 6; + uint32_t dType : 2; + uint32_t dHiId : 6; + uint32_t uniform : 1; +}; + +struct BaseRRII { + M_OPCODE(opcode, 22) + uint32_t aType : 2; + uint32_t aHiId : 6; + uint32_t bType : 2; + uint32_t bHiId : 6; + uint32_t aImmSize : 6; + uint32_t aImmDiscardLsb : 5; + uint32_t aImmOffset : 5; + uint32_t bImmSize : 6; + uint32_t bImmDiscardLsb : 5; + uint32_t bImmOffset : 5; +}; + +struct BaseAtDcIcTlbi { + uint32_t immVerifyMask : 14; + uint32_t immVerifyData : 14; + uint32_t mandatoryReg : 1; +}; + +struct BaseAdcSbc { + uint32_t opcode; +}; + +struct BaseAddSub { + uint32_t shiftedOp : 10; // sf|.......|Sh|.|Rm| Imm:6 |Rn|Rd| + uint32_t extendedOp : 10; // sf|.......|..|.|Rm|Opt|Imm3|Rn|Rd| + uint32_t immediateOp: 10; // sf|.......|Sh| Imm:12 |Rn|Rd| +}; + +struct BaseAdr { + M_OPCODE(opcode, 22) + OffsetType offsetType : 8; +}; + +struct BaseBfm { + uint32_t opcode; // sf|........|N|ImmR:6|ImmS:6|Rn|Rd| +}; + +struct BaseCmpCmn { + uint32_t shiftedOp : 10; // sf|.......|Sh|.|Rm| Imm:6 |Rn|11111| + uint32_t extendedOp : 10; // sf|.......|..|.|Rm|Opt|Imm3|Rn|11111| + uint32_t immediateOp: 10; // sf|.......|Sh| Imm:12 |Rn|11111| +}; + +struct BaseExtend { + M_OPCODE(opcode, 22) // sf|........|N|......|......|Rn|Rd| + uint32_t rType : 2; + uint32_t u : 1; +}; + +struct BaseLogical { + uint32_t shiftedOp : 10; // sf|.......|Sh|.|Rm| Imm:6 |Rn|Rd| + uint32_t immediateOp: 10; // sf|........|N|ImmR:6|ImmS:6|Rn|Rd| + uint32_t negateImm : 1 ; // True if this is an operation that must negate IMM. +}; + +struct BaseMvnNeg { + uint32_t opcode; +}; + +struct BaseShift { + M_OPCODE(registerOp, 22) + M_OPCODE(immediateOp, 22) + uint32_t ror : 2; +}; + +struct BaseTst { + uint32_t shiftedOp : 10; // sf|.......|Sh|.|Rm| Imm:6 |Rn|11111| + uint32_t immediateOp: 10; // sf|........|N|ImmR:6|ImmS:6|Rn|11111| +}; + +struct BaseRM_NoImm { + M_OPCODE(opcode, 22) + uint32_t rType : 2; + uint32_t rHiId : 6; + uint32_t xOffset : 5; +}; + +struct BaseRM_SImm9 { + M_OPCODE(offsetOp, 22) + M_OPCODE(prePostOp, 22) + uint32_t rType : 2; + uint32_t rHiId : 6; + uint32_t xOffset : 5; + uint32_t immShift : 4; +}; + +struct BaseRM_SImm10 { + M_OPCODE(opcode, 22) + uint32_t rType : 2; + uint32_t rHiId : 6; + uint32_t xOffset : 5; + uint32_t immShift : 4; +}; + +struct BaseLdSt { + uint32_t uOffsetOp : 10; + uint32_t prePostOp : 11; + uint32_t registerOp : 11; + uint32_t literalOp : 8; + uint32_t rType : 2; + uint32_t xOffset : 5; + uint32_t uOffsetShift : 3; + uint32_t uAltInstId : 14; +}; + +struct BaseLdpStp { + uint32_t offsetOp : 10; + uint32_t prePostOp : 10; + uint32_t rType : 2; + uint32_t xOffset : 5; + uint32_t offsetShift : 3; +}; + +struct BaseStx { + M_OPCODE(opcode, 22) + uint32_t rType : 2; + uint32_t xOffset : 5; +}; + +struct BaseLdxp { + M_OPCODE(opcode, 22) + uint32_t rType : 2; + uint32_t xOffset : 5; +}; + +struct BaseStxp { + M_OPCODE(opcode, 22) + uint32_t rType : 2; + uint32_t xOffset : 5; +}; + +struct BaseAtomicOp { + M_OPCODE(opcode, 22) + uint32_t rType : 2; + uint32_t xOffset : 5; + uint32_t zr : 1; +}; + +struct BaseAtomicSt { + M_OPCODE(opcode, 22) + uint32_t rType : 2; + uint32_t xOffset : 5; +}; + +struct BaseAtomicCasp { + M_OPCODE(opcode, 22) + uint32_t rType : 2; + uint32_t xOffset : 5; +}; + +typedef BaseOp BaseBranchReg; +typedef BaseOp BaseBranchRel; +typedef BaseOp BaseBranchCmp; +typedef BaseOp BaseBranchTst; +typedef BaseOp BaseExtract; +typedef BaseOp BaseBfc; +typedef BaseOp BaseBfi; +typedef BaseOp BaseBfx; +typedef BaseOp BaseCCmp; +typedef BaseOp BaseCInc; +typedef BaseOp BaseCSet; +typedef BaseOp BaseCSel; +typedef BaseOp BaseMovKNZ; +typedef BaseOp BaseMull; + +struct FSimdGeneric { + uint32_t _scalarOp : 28; + uint32_t _scalarHf : 4; + uint32_t _vectorOp : 28; + uint32_t _vectorHf : 4; + + constexpr uint32_t scalarOp() const noexcept { return uint32_t(_scalarOp) << 10; } + constexpr uint32_t vectorOp() const noexcept { return uint32_t(_vectorOp) << 10; } + constexpr uint32_t scalarHf() const noexcept { return uint32_t(_scalarHf); } + constexpr uint32_t vectorHf() const noexcept { return uint32_t(_vectorHf); } +}; + +typedef FSimdGeneric FSimdVV; +typedef FSimdGeneric FSimdVVV; +typedef FSimdGeneric FSimdVVVV; + +struct FSimdSV { + uint32_t opcode; +}; + +struct FSimdVVVe { + uint32_t _scalarOp : 28; + uint32_t _scalarHf : 4; + uint32_t _vectorOp; + uint32_t _elementOp; + + constexpr uint32_t scalarOp() const noexcept { return uint32_t(_scalarOp) << 10; } + constexpr uint32_t scalarHf() const noexcept { return uint32_t(_scalarHf); }; + constexpr uint32_t vectorOp() const noexcept { return uint32_t(_vectorOp) << 10; } + constexpr uint32_t vectorHf() const noexcept { return kHF_C; } + constexpr uint32_t elementScalarOp() const noexcept { return (uint32_t(_elementOp) << 10) | (0x5u << 28); } + constexpr uint32_t elementVectorOp() const noexcept { return (uint32_t(_elementOp) << 10); } +}; + +struct SimdFcadd { + uint32_t _opcode; + + constexpr uint32_t opcode() const noexcept { return _opcode << 10; } +}; + +struct SimdFcmla { + uint32_t _regularOp; + uint32_t _elementOp; + + constexpr uint32_t regularOp() const noexcept { return uint32_t(_regularOp) << 10; } + constexpr uint32_t elementOp() const noexcept { return (uint32_t(_elementOp) << 10); } +}; + +struct SimdFccmpFccmpe { + uint32_t _opcode; + constexpr uint32_t opcode() const noexcept { return _opcode; } +}; + +struct SimdFcm { + uint32_t _registerOp : 28; + uint32_t _registerHf : 4; + + uint32_t _zeroOp : 28; + + constexpr bool hasRegisterOp() const noexcept { return _registerOp != 0; } + constexpr bool hasZeroOp() const noexcept { return _zeroOp != 0; } + + constexpr uint32_t registerScalarOp() const noexcept { return (uint32_t(_registerOp) << 10) | (0x5u << 28); } + constexpr uint32_t registerVectorOp() const noexcept { return uint32_t(_registerOp) << 10; } + constexpr uint32_t registerScalarHf() const noexcept { return uint32_t(_registerHf); } + constexpr uint32_t registerVectorHf() const noexcept { return uint32_t(_registerHf); } + + constexpr uint32_t zeroScalarOp() const noexcept { return (uint32_t(_zeroOp) << 10) | (0x5u << 28); } + constexpr uint32_t zeroVectorOp() const noexcept { return (uint32_t(_zeroOp) << 10); } +}; + +struct SimdFcmpFcmpe { + uint32_t _opcode; + constexpr uint32_t opcode() const noexcept { return _opcode; } +}; + +struct SimdFcvtLN { + uint32_t _opcode : 22; + uint32_t _isCvtxn : 1; + uint32_t _hasScalar : 1; + + constexpr uint32_t scalarOp() const noexcept { return (uint32_t(_opcode) << 10) | (0x5u << 28); } + constexpr uint32_t vectorOp() const noexcept { return (uint32_t(_opcode) << 10); } + + constexpr uint32_t isCvtxn() const noexcept { return _isCvtxn; } + constexpr uint32_t hasScalar() const noexcept { return _hasScalar; } +}; + +struct SimdFcvtSV { + uint32_t _vectorIntOp; + uint32_t _vectorFpOp; + uint32_t _generalOp : 31; + uint32_t _isFloatToInt : 1; + + constexpr uint32_t scalarIntOp() const noexcept { return (uint32_t(_vectorIntOp) << 10) | (0x5u << 28); } + constexpr uint32_t vectorIntOp() const noexcept { return uint32_t(_vectorIntOp) << 10; } + constexpr uint32_t scalarFpOp() const noexcept { return (uint32_t(_vectorFpOp) << 10) | (0x5u << 28); } + constexpr uint32_t vectorFpOp() const noexcept { return uint32_t(_vectorFpOp) << 10; } + constexpr uint32_t generalOp() const noexcept { return (uint32_t(_generalOp) << 10); } + + constexpr uint32_t isFloatToInt() const noexcept { return _isFloatToInt; } + constexpr uint32_t isFixedPoint() const noexcept { return _vectorFpOp != 0; } +}; + +struct SimdFmlal { + uint32_t _vectorOp; + uint32_t _elementOp; + uint8_t _optionalQ; + uint8_t tA; + uint8_t tB; + uint8_t tElement; + + constexpr uint32_t vectorOp() const noexcept { return uint32_t(_vectorOp) << 10; } + constexpr uint32_t elementOp() const noexcept { return uint32_t(_elementOp) << 10; } + constexpr uint32_t optionalQ() const noexcept { return _optionalQ; } +}; + +struct FSimdPair { + uint32_t _scalarOp; + uint32_t _vectorOp; + + constexpr uint32_t scalarOp() const noexcept { return uint32_t(_scalarOp) << 10; } + constexpr uint32_t vectorOp() const noexcept { return uint32_t(_vectorOp) << 10; } +}; + +struct ISimdVV { + M_OPCODE(opcode, 22) + uint32_t vecOpType : 6; +}; + +struct ISimdVVx { + M_OPCODE(opcode, 22) + uint32_t op0Signature; + uint32_t op1Signature; +}; + +struct ISimdSV { + M_OPCODE(opcode, 22) + uint32_t vecOpType : 6; +}; + +struct ISimdVVV { + M_OPCODE(opcode, 22) + uint32_t vecOpType : 6; +}; + +struct ISimdVVVx { + M_OPCODE(opcode, 22) + uint32_t op0Signature; + uint32_t op1Signature; + uint32_t op2Signature; +}; + +struct ISimdWWV { + M_OPCODE(opcode, 22) + uint32_t vecOpType : 6; +}; + +struct ISimdVVVe { + uint32_t regularOp : 26; // 22 bits used. + uint32_t regularVecType : 6; + uint32_t elementOp : 26; // 22 bits used. + uint32_t elementVecType : 6; +}; + +struct ISimdVVVI { + M_OPCODE(opcode, 22) + uint32_t vecOpType : 6; + uint32_t immSize : 4; + uint32_t immShift : 4; + uint32_t imm64HasOneBitLess : 1; +}; + +struct ISimdVVVV { + uint32_t opcode : 22; + uint32_t vecOpType : 6; +}; + +struct ISimdVVVVx { + uint32_t opcode; + uint32_t op0Signature; + uint32_t op1Signature; + uint32_t op2Signature; + uint32_t op3Signature; +}; + +struct SimdBicOrr { + uint32_t registerOp; // 22 bits used. + uint32_t immediateOp; // 22 bits used. +}; + +struct SimdCmp { + uint32_t regOp; + uint32_t zeroOp : 22; + uint32_t vecOpType : 6; +}; + +struct SimdDot { + uint32_t vectorOp; // 22 bits used. + uint32_t elementOp; // 22 bits used. + uint8_t tA; // Element-type of the first operand. + uint8_t tB; // Element-type of the second and third operands. + uint8_t tElement; // Element-type of the element index[] operand. +}; + +struct SimdMoviMvni { + uint32_t opcode : 31; + uint32_t inverted : 1; +}; + +struct SimdLdSt { + uint32_t uOffsetOp : 10; + uint32_t prePostOp : 11; + uint32_t registerOp : 11; + uint32_t literalOp : 8; + uint32_t uAltInstId : 16; +}; + +struct SimdLdNStN { + uint32_t singleOp; + uint32_t multipleOp : 22; + uint32_t n : 3; + uint32_t replicate : 1; +}; + +struct SimdLdpStp { + uint32_t offsetOp : 10; + uint32_t prePostOp : 10; +}; + +struct SimdLdurStur { + uint32_t opcode; +}; + +struct ISimdPair { + uint32_t opcode2; // 22 bits used. + uint32_t opcode3 : 26; // 22 bits used. + uint32_t opType3 : 6; +}; + +struct SimdShift { + uint32_t registerOp; // 22 bits used. + uint32_t immediateOp : 22; // 22 bits used. + uint32_t invertedImm : 1; + uint32_t vecOpType : 6; +}; + +struct SimdShiftES { + uint32_t opcode : 22; + uint32_t vecOpType : 6; +}; + +struct SimdSm3tt { + uint32_t opcode; +}; + +struct SimdSmovUmov { + uint32_t opcode : 22; + uint32_t vecOpType : 6; + uint32_t isSigned : 1; +}; + +struct SimdSxtlUxtl { + uint32_t opcode : 22; + uint32_t vecOpType : 6; +}; + +struct SimdTblTbx { + uint32_t opcode; +}; + +#undef M_OPCODE + +// ${EncodingDataForward:Begin} +// ------------------- Automatically generated, do not edit ------------------- +extern const BaseAddSub baseAddSub[4]; +extern const BaseAdr baseAdr[2]; +extern const BaseAtDcIcTlbi baseAtDcIcTlbi[4]; +extern const BaseAtomicCasp baseAtomicCasp[4]; +extern const BaseAtomicOp baseAtomicOp[123]; +extern const BaseAtomicSt baseAtomicSt[48]; +extern const BaseBfc baseBfc[1]; +extern const BaseBfi baseBfi[3]; +extern const BaseBfm baseBfm[3]; +extern const BaseBfx baseBfx[3]; +extern const BaseBranchCmp baseBranchCmp[2]; +extern const BaseBranchReg baseBranchReg[3]; +extern const BaseBranchRel baseBranchRel[2]; +extern const BaseBranchTst baseBranchTst[2]; +extern const BaseCCmp baseCCmp[2]; +extern const BaseCInc baseCInc[3]; +extern const BaseCSel baseCSel[4]; +extern const BaseCSet baseCSet[2]; +extern const BaseCmpCmn baseCmpCmn[2]; +extern const BaseExtend baseExtend[5]; +extern const BaseExtract baseExtract[1]; +extern const BaseLdSt baseLdSt[9]; +extern const BaseLdpStp baseLdpStp[6]; +extern const BaseLdxp baseLdxp[2]; +extern const BaseLogical baseLogical[8]; +extern const BaseMovKNZ baseMovKNZ[3]; +extern const BaseMvnNeg baseMvnNeg[3]; +extern const BaseOp baseOp[23]; +extern const BaseOpImm baseOpImm[14]; +extern const BaseR baseR[10]; +extern const BaseRM_NoImm baseRM_NoImm[21]; +extern const BaseRM_SImm10 baseRM_SImm10[2]; +extern const BaseRM_SImm9 baseRM_SImm9[23]; +extern const BaseRR baseRR[15]; +extern const BaseRRII baseRRII[2]; +extern const BaseRRR baseRRR[26]; +extern const BaseRRRR baseRRRR[6]; +extern const BaseShift baseShift[8]; +extern const BaseStx baseStx[3]; +extern const BaseStxp baseStxp[2]; +extern const BaseTst baseTst[1]; +extern const FSimdPair fSimdPair[5]; +extern const FSimdSV fSimdSV[4]; +extern const FSimdVV fSimdVV[17]; +extern const FSimdVVV fSimdVVV[13]; +extern const FSimdVVVV fSimdVVVV[4]; +extern const FSimdVVVe fSimdVVVe[4]; +extern const ISimdPair iSimdPair[1]; +extern const ISimdSV iSimdSV[7]; +extern const ISimdVV iSimdVV[29]; +extern const ISimdVVV iSimdVVV[65]; +extern const ISimdVVVI iSimdVVVI[2]; +extern const ISimdVVVV iSimdVVVV[2]; +extern const ISimdVVVVx iSimdVVVVx[1]; +extern const ISimdVVVe iSimdVVVe[25]; +extern const ISimdVVVx iSimdVVVx[17]; +extern const ISimdVVx iSimdVVx[13]; +extern const ISimdWWV iSimdWWV[8]; +extern const SimdBicOrr simdBicOrr[2]; +extern const SimdCmp simdCmp[7]; +extern const SimdDot simdDot[5]; +extern const SimdFcadd simdFcadd[1]; +extern const SimdFccmpFccmpe simdFccmpFccmpe[2]; +extern const SimdFcm simdFcm[5]; +extern const SimdFcmla simdFcmla[1]; +extern const SimdFcmpFcmpe simdFcmpFcmpe[2]; +extern const SimdFcvtLN simdFcvtLN[6]; +extern const SimdFcvtSV simdFcvtSV[12]; +extern const SimdFmlal simdFmlal[6]; +extern const SimdLdNStN simdLdNStN[12]; +extern const SimdLdSt simdLdSt[2]; +extern const SimdLdpStp simdLdpStp[4]; +extern const SimdLdurStur simdLdurStur[2]; +extern const SimdMoviMvni simdMoviMvni[2]; +extern const SimdShift simdShift[40]; +extern const SimdShiftES simdShiftES[2]; +extern const SimdSm3tt simdSm3tt[4]; +extern const SimdSmovUmov simdSmovUmov[2]; +extern const SimdSxtlUxtl simdSxtlUxtl[4]; +extern const SimdTblTbx simdTblTbx[2]; +// ---------------------------------------------------------------------------- +// ${EncodingDataForward:End} + +} // {EncodingData} + +// a64::InstDB - InstNameIndex +// =========================== + +// ${NameLimits:Begin} +// ------------------- Automatically generated, do not edit ------------------- +enum : uint32_t { kMaxNameSize = 9 }; +// ---------------------------------------------------------------------------- +// ${NameLimits:End} + +struct InstNameIndex { + uint16_t start; + uint16_t end; +}; + +// a64::InstDB - Tables +// ==================== + +#ifndef ASMJIT_NO_TEXT +extern const char _nameData[]; +extern const InstNameIndex instNameIndex[26]; +#endif // !ASMJIT_NO_TEXT + +} // {InstDB} + +//! \} +//! \endcond + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_A64_ARMINSTDB_H_P_INCLUDED + diff --git a/src/asmjit/arm/a64operand.cpp b/src/asmjit/arm/a64operand.cpp new file mode 100644 index 0000000..40a4a79 --- /dev/null +++ b/src/asmjit/arm/a64operand.cpp @@ -0,0 +1,85 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#if !defined(ASMJIT_NO_AARCH64) + +#include "../core/misc_p.h" +#include "../arm/a64operand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +// a64::Operand - Tests +// ==================== + +#if defined(ASMJIT_TEST) +UNIT(a64_operand) { + INFO("Checking if a64::reg(...) matches built-in IDs"); + EXPECT(w(5) == w5); + EXPECT(x(5) == x5); + + INFO("Checking Gp register properties"); + EXPECT(Gp().isReg() == true); + EXPECT(w0.isReg() == true); + EXPECT(x0.isReg() == true); + EXPECT(w0.id() == 0); + EXPECT(x0.id() == 0); + EXPECT(wzr.id() == Gp::kIdZr); + EXPECT(xzr.id() == Gp::kIdZr); + EXPECT(wsp.id() == Gp::kIdSp); + EXPECT(sp.id() == Gp::kIdSp); + EXPECT(w0.size() == 4); + EXPECT(x0.size() == 8); + EXPECT(w0.type() == RegType::kARM_GpW); + EXPECT(x0.type() == RegType::kARM_GpX); + EXPECT(w0.group() == RegGroup::kGp); + EXPECT(x0.group() == RegGroup::kGp); + + INFO("Checking Vec register properties"); + EXPECT(v0.type() == RegType::kARM_VecV); + EXPECT(d0.type() == RegType::kARM_VecD); + EXPECT(s0.type() == RegType::kARM_VecS); + EXPECT(h0.type() == RegType::kARM_VecH); + EXPECT(b0.type() == RegType::kARM_VecB); + + EXPECT(v0.group() == RegGroup::kVec); + EXPECT(d0.group() == RegGroup::kVec); + EXPECT(s0.group() == RegGroup::kVec); + EXPECT(h0.group() == RegGroup::kVec); + EXPECT(b0.group() == RegGroup::kVec); + + INFO("Checking Vec register element[] access"); + Vec vd_1 = v15.d(1); + EXPECT(vd_1.type() == RegType::kARM_VecV); + EXPECT(vd_1.group() == RegGroup::kVec); + EXPECT(vd_1.id() == 15); + EXPECT(vd_1.isVecD2()); + EXPECT(vd_1.elementType() == Vec::kElementTypeD); + EXPECT(vd_1.hasElementIndex()); + EXPECT(vd_1.elementIndex() == 1); + + Vec vs_3 = v15.s(3); + EXPECT(vs_3.type() == RegType::kARM_VecV); + EXPECT(vs_3.group() == RegGroup::kVec); + EXPECT(vs_3.id() == 15); + EXPECT(vs_3.isVecS4()); + EXPECT(vs_3.elementType() == Vec::kElementTypeS); + EXPECT(vs_3.hasElementIndex()); + EXPECT(vs_3.elementIndex() == 3); + + Vec vb_4 = v15.b4(3); + EXPECT(vb_4.type() == RegType::kARM_VecV); + EXPECT(vb_4.group() == RegGroup::kVec); + EXPECT(vb_4.id() == 15); + EXPECT(vb_4.isVecB4x4()); + EXPECT(vb_4.elementType() == Vec::kElementTypeB4); + EXPECT(vb_4.hasElementIndex()); + EXPECT(vb_4.elementIndex() == 3); +} +#endif + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_AARCH64 diff --git a/src/asmjit/arm/a64operand.h b/src/asmjit/arm/a64operand.h new file mode 100644 index 0000000..c2d3c17 --- /dev/null +++ b/src/asmjit/arm/a64operand.h @@ -0,0 +1,312 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64OPERAND_H_INCLUDED +#define ASMJIT_ARM_A64OPERAND_H_INCLUDED + +#include "../arm/armoperand.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \addtogroup asmjit_a64 +//! \{ + +using arm::Reg; +using arm::Mem; +using arm::Gp; +using arm::GpW; +using arm::GpX; + +using arm::Vec; +using arm::VecB; +using arm::VecH; +using arm::VecS; +using arm::VecD; +using arm::VecV; + +#ifndef _DOXYGEN +namespace regs { +#endif + +using namespace ::asmjit::arm::regs; + +static constexpr GpW w0 = GpW(0); +static constexpr GpW w1 = GpW(1); +static constexpr GpW w2 = GpW(2); +static constexpr GpW w3 = GpW(3); +static constexpr GpW w4 = GpW(4); +static constexpr GpW w5 = GpW(5); +static constexpr GpW w6 = GpW(6); +static constexpr GpW w7 = GpW(7); +static constexpr GpW w8 = GpW(8); +static constexpr GpW w9 = GpW(9); +static constexpr GpW w10 = GpW(10); +static constexpr GpW w11 = GpW(11); +static constexpr GpW w12 = GpW(12); +static constexpr GpW w13 = GpW(13); +static constexpr GpW w14 = GpW(14); +static constexpr GpW w15 = GpW(15); +static constexpr GpW w16 = GpW(16); +static constexpr GpW w17 = GpW(17); +static constexpr GpW w18 = GpW(18); +static constexpr GpW w19 = GpW(19); +static constexpr GpW w20 = GpW(20); +static constexpr GpW w21 = GpW(21); +static constexpr GpW w22 = GpW(22); +static constexpr GpW w23 = GpW(23); +static constexpr GpW w24 = GpW(24); +static constexpr GpW w25 = GpW(25); +static constexpr GpW w26 = GpW(26); +static constexpr GpW w27 = GpW(27); +static constexpr GpW w28 = GpW(28); +static constexpr GpW w29 = GpW(29); +static constexpr GpW w30 = GpW(30); +static constexpr GpW wzr = GpW(Gp::kIdZr); +static constexpr GpW wsp = GpW(Gp::kIdSp); + +static constexpr GpX x0 = GpX(0); +static constexpr GpX x1 = GpX(1); +static constexpr GpX x2 = GpX(2); +static constexpr GpX x3 = GpX(3); +static constexpr GpX x4 = GpX(4); +static constexpr GpX x5 = GpX(5); +static constexpr GpX x6 = GpX(6); +static constexpr GpX x7 = GpX(7); +static constexpr GpX x8 = GpX(8); +static constexpr GpX x9 = GpX(9); +static constexpr GpX x10 = GpX(10); +static constexpr GpX x11 = GpX(11); +static constexpr GpX x12 = GpX(12); +static constexpr GpX x13 = GpX(13); +static constexpr GpX x14 = GpX(14); +static constexpr GpX x15 = GpX(15); +static constexpr GpX x16 = GpX(16); +static constexpr GpX x17 = GpX(17); +static constexpr GpX x18 = GpX(18); +static constexpr GpX x19 = GpX(19); +static constexpr GpX x20 = GpX(20); +static constexpr GpX x21 = GpX(21); +static constexpr GpX x22 = GpX(22); +static constexpr GpX x23 = GpX(23); +static constexpr GpX x24 = GpX(24); +static constexpr GpX x25 = GpX(25); +static constexpr GpX x26 = GpX(26); +static constexpr GpX x27 = GpX(27); +static constexpr GpX x28 = GpX(28); +static constexpr GpX x29 = GpX(29); +static constexpr GpX x30 = GpX(30); +static constexpr GpX xzr = GpX(Gp::kIdZr); +static constexpr GpX sp = GpX(Gp::kIdSp); + +static constexpr VecB b0 = VecB(0); +static constexpr VecB b1 = VecB(1); +static constexpr VecB b2 = VecB(2); +static constexpr VecB b3 = VecB(3); +static constexpr VecB b4 = VecB(4); +static constexpr VecB b5 = VecB(5); +static constexpr VecB b6 = VecB(6); +static constexpr VecB b7 = VecB(7); +static constexpr VecB b8 = VecB(8); +static constexpr VecB b9 = VecB(9); +static constexpr VecB b10 = VecB(10); +static constexpr VecB b11 = VecB(11); +static constexpr VecB b12 = VecB(12); +static constexpr VecB b13 = VecB(13); +static constexpr VecB b14 = VecB(14); +static constexpr VecB b15 = VecB(15); +static constexpr VecB b16 = VecB(16); +static constexpr VecB b17 = VecB(17); +static constexpr VecB b18 = VecB(18); +static constexpr VecB b19 = VecB(19); +static constexpr VecB b20 = VecB(20); +static constexpr VecB b21 = VecB(21); +static constexpr VecB b22 = VecB(22); +static constexpr VecB b23 = VecB(23); +static constexpr VecB b24 = VecB(24); +static constexpr VecB b25 = VecB(25); +static constexpr VecB b26 = VecB(26); +static constexpr VecB b27 = VecB(27); +static constexpr VecB b28 = VecB(28); +static constexpr VecB b29 = VecB(29); +static constexpr VecB b30 = VecB(30); +static constexpr VecB b31 = VecB(31); + +static constexpr VecH h0 = VecH(0); +static constexpr VecH h1 = VecH(1); +static constexpr VecH h2 = VecH(2); +static constexpr VecH h3 = VecH(3); +static constexpr VecH h4 = VecH(4); +static constexpr VecH h5 = VecH(5); +static constexpr VecH h6 = VecH(6); +static constexpr VecH h7 = VecH(7); +static constexpr VecH h8 = VecH(8); +static constexpr VecH h9 = VecH(9); +static constexpr VecH h10 = VecH(10); +static constexpr VecH h11 = VecH(11); +static constexpr VecH h12 = VecH(12); +static constexpr VecH h13 = VecH(13); +static constexpr VecH h14 = VecH(14); +static constexpr VecH h15 = VecH(15); +static constexpr VecH h16 = VecH(16); +static constexpr VecH h17 = VecH(17); +static constexpr VecH h18 = VecH(18); +static constexpr VecH h19 = VecH(19); +static constexpr VecH h20 = VecH(20); +static constexpr VecH h21 = VecH(21); +static constexpr VecH h22 = VecH(22); +static constexpr VecH h23 = VecH(23); +static constexpr VecH h24 = VecH(24); +static constexpr VecH h25 = VecH(25); +static constexpr VecH h26 = VecH(26); +static constexpr VecH h27 = VecH(27); +static constexpr VecH h28 = VecH(28); +static constexpr VecH h29 = VecH(29); +static constexpr VecH h30 = VecH(30); +static constexpr VecH h31 = VecH(31); + +static constexpr VecS s0 = VecS(0); +static constexpr VecS s1 = VecS(1); +static constexpr VecS s2 = VecS(2); +static constexpr VecS s3 = VecS(3); +static constexpr VecS s4 = VecS(4); +static constexpr VecS s5 = VecS(5); +static constexpr VecS s6 = VecS(6); +static constexpr VecS s7 = VecS(7); +static constexpr VecS s8 = VecS(8); +static constexpr VecS s9 = VecS(9); +static constexpr VecS s10 = VecS(10); +static constexpr VecS s11 = VecS(11); +static constexpr VecS s12 = VecS(12); +static constexpr VecS s13 = VecS(13); +static constexpr VecS s14 = VecS(14); +static constexpr VecS s15 = VecS(15); +static constexpr VecS s16 = VecS(16); +static constexpr VecS s17 = VecS(17); +static constexpr VecS s18 = VecS(18); +static constexpr VecS s19 = VecS(19); +static constexpr VecS s20 = VecS(20); +static constexpr VecS s21 = VecS(21); +static constexpr VecS s22 = VecS(22); +static constexpr VecS s23 = VecS(23); +static constexpr VecS s24 = VecS(24); +static constexpr VecS s25 = VecS(25); +static constexpr VecS s26 = VecS(26); +static constexpr VecS s27 = VecS(27); +static constexpr VecS s28 = VecS(28); +static constexpr VecS s29 = VecS(29); +static constexpr VecS s30 = VecS(30); +static constexpr VecS s31 = VecS(31); + +static constexpr VecD d0 = VecD(0); +static constexpr VecD d1 = VecD(1); +static constexpr VecD d2 = VecD(2); +static constexpr VecD d3 = VecD(3); +static constexpr VecD d4 = VecD(4); +static constexpr VecD d5 = VecD(5); +static constexpr VecD d6 = VecD(6); +static constexpr VecD d7 = VecD(7); +static constexpr VecD d8 = VecD(8); +static constexpr VecD d9 = VecD(9); +static constexpr VecD d10 = VecD(10); +static constexpr VecD d11 = VecD(11); +static constexpr VecD d12 = VecD(12); +static constexpr VecD d13 = VecD(13); +static constexpr VecD d14 = VecD(14); +static constexpr VecD d15 = VecD(15); +static constexpr VecD d16 = VecD(16); +static constexpr VecD d17 = VecD(17); +static constexpr VecD d18 = VecD(18); +static constexpr VecD d19 = VecD(19); +static constexpr VecD d20 = VecD(20); +static constexpr VecD d21 = VecD(21); +static constexpr VecD d22 = VecD(22); +static constexpr VecD d23 = VecD(23); +static constexpr VecD d24 = VecD(24); +static constexpr VecD d25 = VecD(25); +static constexpr VecD d26 = VecD(26); +static constexpr VecD d27 = VecD(27); +static constexpr VecD d28 = VecD(28); +static constexpr VecD d29 = VecD(29); +static constexpr VecD d30 = VecD(30); +static constexpr VecD d31 = VecD(31); + +static constexpr VecV q0 = VecV(0); +static constexpr VecV q1 = VecV(1); +static constexpr VecV q2 = VecV(2); +static constexpr VecV q3 = VecV(3); +static constexpr VecV q4 = VecV(4); +static constexpr VecV q5 = VecV(5); +static constexpr VecV q6 = VecV(6); +static constexpr VecV q7 = VecV(7); +static constexpr VecV q8 = VecV(8); +static constexpr VecV q9 = VecV(9); +static constexpr VecV q10 = VecV(10); +static constexpr VecV q11 = VecV(11); +static constexpr VecV q12 = VecV(12); +static constexpr VecV q13 = VecV(13); +static constexpr VecV q14 = VecV(14); +static constexpr VecV q15 = VecV(15); +static constexpr VecV q16 = VecV(16); +static constexpr VecV q17 = VecV(17); +static constexpr VecV q18 = VecV(18); +static constexpr VecV q19 = VecV(19); +static constexpr VecV q20 = VecV(20); +static constexpr VecV q21 = VecV(21); +static constexpr VecV q22 = VecV(22); +static constexpr VecV q23 = VecV(23); +static constexpr VecV q24 = VecV(24); +static constexpr VecV q25 = VecV(25); +static constexpr VecV q26 = VecV(26); +static constexpr VecV q27 = VecV(27); +static constexpr VecV q28 = VecV(28); +static constexpr VecV q29 = VecV(29); +static constexpr VecV q30 = VecV(30); +static constexpr VecV q31 = VecV(31); + +static constexpr VecV v0 = VecV(0); +static constexpr VecV v1 = VecV(1); +static constexpr VecV v2 = VecV(2); +static constexpr VecV v3 = VecV(3); +static constexpr VecV v4 = VecV(4); +static constexpr VecV v5 = VecV(5); +static constexpr VecV v6 = VecV(6); +static constexpr VecV v7 = VecV(7); +static constexpr VecV v8 = VecV(8); +static constexpr VecV v9 = VecV(9); +static constexpr VecV v10 = VecV(10); +static constexpr VecV v11 = VecV(11); +static constexpr VecV v12 = VecV(12); +static constexpr VecV v13 = VecV(13); +static constexpr VecV v14 = VecV(14); +static constexpr VecV v15 = VecV(15); +static constexpr VecV v16 = VecV(16); +static constexpr VecV v17 = VecV(17); +static constexpr VecV v18 = VecV(18); +static constexpr VecV v19 = VecV(19); +static constexpr VecV v20 = VecV(20); +static constexpr VecV v21 = VecV(21); +static constexpr VecV v22 = VecV(22); +static constexpr VecV v23 = VecV(23); +static constexpr VecV v24 = VecV(24); +static constexpr VecV v25 = VecV(25); +static constexpr VecV v26 = VecV(26); +static constexpr VecV v27 = VecV(27); +static constexpr VecV v28 = VecV(28); +static constexpr VecV v29 = VecV(29); +static constexpr VecV v30 = VecV(30); +static constexpr VecV v31 = VecV(31); + +#ifndef _DOXYGEN +} // {regs} + +// Make `a64::regs` accessible through `a64` namespace as well. +using namespace regs; +#endif + +//! \} + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_A64OPERAND_H_INCLUDED diff --git a/src/asmjit/arm/a64rapass.cpp b/src/asmjit/arm/a64rapass.cpp new file mode 100644 index 0000000..ad78369 --- /dev/null +++ b/src/asmjit/arm/a64rapass.cpp @@ -0,0 +1,806 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#if !defined(ASMJIT_NO_AARCH64) && !defined(ASMJIT_NO_COMPILER) + +#include "../core/cpuinfo.h" +#include "../core/support.h" +#include "../core/type.h" +#include "../arm/a64assembler.h" +#include "../arm/a64compiler.h" +#include "../arm/a64emithelper_p.h" +#include "../arm/a64instapi_p.h" +#include "../arm/a64instdb_p.h" +#include "../arm/a64rapass_p.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +// a64::ARMRAPass - Helpers +// ======================== + +// TODO: [ARM] These should be shared with all backends. +ASMJIT_MAYBE_UNUSED +static inline uint64_t raImmMaskFromSize(uint32_t size) noexcept { + ASMJIT_ASSERT(size > 0 && size < 256); + static const uint64_t masks[] = { + 0x00000000000000FFu, // 1 + 0x000000000000FFFFu, // 2 + 0x00000000FFFFFFFFu, // 4 + 0xFFFFFFFFFFFFFFFFu, // 8 + 0x0000000000000000u, // 16 + 0x0000000000000000u, // 32 + 0x0000000000000000u, // 64 + 0x0000000000000000u, // 128 + 0x0000000000000000u // 256 + }; + return masks[Support::ctz(size)]; +} + +static const RegMask raConsecutiveLeadCountToRegMaskFilter[5] = { + 0xFFFFFFFFu, // [0] No consecutive. + 0x00000000u, // [1] Invalid, never used. + 0x7FFFFFFFu, // [2] 2 consecutive registers. + 0x3FFFFFFFu, // [3] 3 consecutive registers. + 0x1FFFFFFFu // [4] 4 consecutive registers. +}; + +static inline RATiedFlags raUseOutFlagsFromRWFlags(OpRWFlags rwFlags) noexcept { + static constexpr RATiedFlags map[] = { + RATiedFlags::kNone, + RATiedFlags::kRead | RATiedFlags::kUse, // kRead + RATiedFlags::kWrite | RATiedFlags::kOut, // kWrite + RATiedFlags::kRW | RATiedFlags::kUse, // kRW + }; + + return map[uint32_t(rwFlags & OpRWFlags::kRW)]; +} + +static inline RATiedFlags raRegRwFlags(OpRWFlags flags) noexcept { + return raUseOutFlagsFromRWFlags(flags); +} + +static inline RATiedFlags raMemBaseRwFlags(OpRWFlags flags) noexcept { + constexpr uint32_t shift = Support::ConstCTZ<uint32_t(OpRWFlags::kMemBaseRW)>::value; + return raUseOutFlagsFromRWFlags(OpRWFlags(uint32_t(flags) >> shift) & OpRWFlags::kRW); +} + +static inline RATiedFlags raMemIndexRwFlags(OpRWFlags flags) noexcept { + constexpr uint32_t shift = Support::ConstCTZ<uint32_t(OpRWFlags::kMemIndexRW)>::value; + return raUseOutFlagsFromRWFlags(OpRWFlags(uint32_t(flags) >> shift) & OpRWFlags::kRW); +} +// a64::RACFGBuilder +// ================= + +class RACFGBuilder : public RACFGBuilderT<RACFGBuilder> { +public: + Arch _arch; + + inline RACFGBuilder(ARMRAPass* pass) noexcept + : RACFGBuilderT<RACFGBuilder>(pass), + _arch(pass->cc()->arch()) {} + + inline Compiler* cc() const noexcept { return static_cast<Compiler*>(_cc); } + + Error onInst(InstNode* inst, InstControlFlow& controlType, RAInstBuilder& ib) noexcept; + + Error onBeforeInvoke(InvokeNode* invokeNode) noexcept; + Error onInvoke(InvokeNode* invokeNode, RAInstBuilder& ib) noexcept; + + Error moveImmToRegArg(InvokeNode* invokeNode, const FuncValue& arg, const Imm& imm_, BaseReg* out) noexcept; + Error moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const Imm& imm_) noexcept; + Error moveRegToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const BaseReg& reg) noexcept; + + Error onBeforeRet(FuncRetNode* funcRet) noexcept; + Error onRet(FuncRetNode* funcRet, RAInstBuilder& ib) noexcept; +}; + +// a64::RACFGBuilder - OnInst +// ========================== + +// TODO: [ARM] This is just a workaround... +static InstControlFlow getControlFlowType(InstId instId) noexcept { + switch (instId) { + case Inst::kIdB: + case Inst::kIdBr: + if (BaseInst::extractARMCondCode(instId) == CondCode::kAL) + return InstControlFlow::kJump; + else + return InstControlFlow::kBranch; + case Inst::kIdBl: + case Inst::kIdBlr: + return InstControlFlow::kCall; + case Inst::kIdCbz: + case Inst::kIdCbnz: + case Inst::kIdTbz: + case Inst::kIdTbnz: + return InstControlFlow::kBranch; + case Inst::kIdRet: + return InstControlFlow::kReturn; + default: + return InstControlFlow::kRegular; + } +} + +Error RACFGBuilder::onInst(InstNode* inst, InstControlFlow& controlType, RAInstBuilder& ib) noexcept { + InstRWInfo rwInfo; + + InstId instId = inst->id(); + if (Inst::isDefinedId(instId)) { + uint32_t opCount = inst->opCount(); + const Operand* opArray = inst->operands(); + ASMJIT_PROPAGATE(InstInternal::queryRWInfo(_arch, inst->baseInst(), opArray, opCount, &rwInfo)); + + const InstDB::InstInfo& instInfo = InstDB::infoById(instId); + uint32_t singleRegOps = 0; + + if (opCount) { + uint32_t consecutiveOffset = 0xFFFFFFFFu; + uint32_t consecutiveParent = Globals::kInvalidId; + + for (uint32_t i = 0; i < opCount; i++) { + const Operand& op = opArray[i]; + const OpRWInfo& opRwInfo = rwInfo.operand(i); + + if (op.isReg()) { + // Register Operand + // ---------------- + const Reg& reg = op.as<Reg>(); + + RATiedFlags flags = raRegRwFlags(opRwInfo.opFlags()); + uint32_t vIndex = Operand::virtIdToIndex(reg.id()); + + if (vIndex < Operand::kVirtIdCount) { + RAWorkReg* workReg; + ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg)); + + // Use RW instead of Write in case that not the whole register is overwritten. This is important for + // liveness as we cannot kill a register that will be used. + if ((flags & RATiedFlags::kRW) == RATiedFlags::kWrite) { + if (workReg->regByteMask() & ~(opRwInfo.writeByteMask() | opRwInfo.extendByteMask())) { + // Not write-only operation. + flags = (flags & ~RATiedFlags::kOut) | (RATiedFlags::kRead | RATiedFlags::kUse); + } + } + + RegGroup group = workReg->group(); + + RegMask useRegs = _pass->_availableRegs[group]; + RegMask outRegs = useRegs; + + uint32_t useId = BaseReg::kIdBad; + uint32_t outId = BaseReg::kIdBad; + + uint32_t useRewriteMask = 0; + uint32_t outRewriteMask = 0; + + if (opRwInfo.consecutiveLeadCount()) { + // There must be a single consecutive register lead, otherwise the RW data is invalid. + if (consecutiveOffset != 0xFFFFFFFFu) + return DebugUtils::errored(kErrorInvalidState); + + // A consecutive lead register cannot be used as a consecutive +1/+2/+3 register, the registers must be distinct. + if (RATiedReg::consecutiveDataFromFlags(flags) != 0) + return DebugUtils::errored(kErrorNotConsecutiveRegs); + + flags |= RATiedFlags::kLeadConsecutive | RATiedReg::consecutiveDataToFlags(opRwInfo.consecutiveLeadCount() - 1); + consecutiveOffset = 0; + + RegMask filter = raConsecutiveLeadCountToRegMaskFilter[opRwInfo.consecutiveLeadCount()]; + if (Support::test(flags, RATiedFlags::kUse)) { + flags |= RATiedFlags::kUseConsecutive; + useRegs &= filter; + } + else { + flags |= RATiedFlags::kOutConsecutive; + outRegs &= filter; + } + } + + if (Support::test(flags, RATiedFlags::kUse)) { + useRewriteMask = Support::bitMask(inst->getRewriteIndex(®._baseId)); + if (opRwInfo.hasOpFlag(OpRWFlags::kRegPhysId)) { + useId = opRwInfo.physId(); + flags |= RATiedFlags::kUseFixed; + } + else if (opRwInfo.hasOpFlag(OpRWFlags::kConsecutive)) { + if (consecutiveOffset == 0xFFFFFFFFu) + return DebugUtils::errored(kErrorInvalidState); + flags |= RATiedFlags::kUseConsecutive | RATiedReg::consecutiveDataToFlags(++consecutiveOffset); + } + } + else { + outRewriteMask = Support::bitMask(inst->getRewriteIndex(®._baseId)); + if (opRwInfo.hasOpFlag(OpRWFlags::kRegPhysId)) { + outId = opRwInfo.physId(); + flags |= RATiedFlags::kOutFixed; + } + else if (opRwInfo.hasOpFlag(OpRWFlags::kConsecutive)) { + if (consecutiveOffset == 0xFFFFFFFFu) + return DebugUtils::errored(kErrorInvalidState); + flags |= RATiedFlags::kOutConsecutive | RATiedReg::consecutiveDataToFlags(++consecutiveOffset); + } + } + + // Special cases regarding element access. + if (reg.as<Vec>().hasElementIndex()) { + // Only the first 0..15 registers can be used if the register uses + // element accessor that accesses half-words (h[0..7] elements). + if (instInfo.hasFlag(InstDB::kInstFlagVH0_15) && reg.as<Vec>().elementType() == Vec::kElementTypeH) { + if (Support::test(flags, RATiedFlags::kUse)) + useId &= 0x0000FFFFu; + else + outId &= 0x0000FFFFu; + } + } + + ASMJIT_PROPAGATE(ib.add(workReg, flags, useRegs, useId, useRewriteMask, outRegs, outId, outRewriteMask, opRwInfo.rmSize(), consecutiveParent)); + if (singleRegOps == i) + singleRegOps++; + + if (Support::test(flags, RATiedFlags::kLeadConsecutive | RATiedFlags::kUseConsecutive | RATiedFlags::kOutConsecutive)) + consecutiveParent = workReg->workId(); + } + } + else if (op.isMem()) { + // Memory Operand + // -------------- + const Mem& mem = op.as<Mem>(); + + if (mem.isRegHome()) { + RAWorkReg* workReg; + ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(mem.baseId()), &workReg)); + _pass->getOrCreateStackSlot(workReg); + } + else if (mem.hasBaseReg()) { + uint32_t vIndex = Operand::virtIdToIndex(mem.baseId()); + if (vIndex < Operand::kVirtIdCount) { + RAWorkReg* workReg; + ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg)); + + RATiedFlags flags = raMemBaseRwFlags(opRwInfo.opFlags()); + RegGroup group = workReg->group(); + RegMask allocable = _pass->_availableRegs[group]; + + // Base registers have never fixed id on ARM. + const uint32_t useId = BaseReg::kIdBad; + const uint32_t outId = BaseReg::kIdBad; + + uint32_t useRewriteMask = 0; + uint32_t outRewriteMask = 0; + + if (Support::test(flags, RATiedFlags::kUse)) + useRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._baseId)); + else + outRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._baseId)); + + ASMJIT_PROPAGATE(ib.add(workReg, flags, allocable, useId, useRewriteMask, allocable, outId, outRewriteMask)); + } + } + + if (mem.hasIndexReg()) { + uint32_t vIndex = Operand::virtIdToIndex(mem.indexId()); + if (vIndex < Operand::kVirtIdCount) { + RAWorkReg* workReg; + ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg)); + + RATiedFlags flags = raMemIndexRwFlags(opRwInfo.opFlags()); + RegGroup group = workReg->group(); + RegMask allocable = _pass->_availableRegs[group]; + + // Index registers have never fixed id on ARM. + const uint32_t useId = BaseReg::kIdBad; + const uint32_t outId = BaseReg::kIdBad; + + uint32_t useRewriteMask = 0; + uint32_t outRewriteMask = 0; + + if (Support::test(flags, RATiedFlags::kUse)) + useRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._data[Operand::kDataMemIndexId])); + else + outRewriteMask = Support::bitMask(inst->getRewriteIndex(&mem._data[Operand::kDataMemIndexId])); + + ASMJIT_PROPAGATE(ib.add(workReg, RATiedFlags::kUse | RATiedFlags::kRead, allocable, useId, useRewriteMask, allocable, outId, outRewriteMask)); + } + } + } + } + } + + controlType = getControlFlowType(instId); + } + + return kErrorOk; +} + +// a64::RACFGBuilder - OnInvoke +// ============================ + +Error RACFGBuilder::onBeforeInvoke(InvokeNode* invokeNode) noexcept { + const FuncDetail& fd = invokeNode->detail(); + uint32_t argCount = invokeNode->argCount(); + + cc()->_setCursor(invokeNode->prev()); + + for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { + const FuncValuePack& argPack = fd.argPack(argIndex); + for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) { + if (!argPack[valueIndex]) + break; + + const FuncValue& arg = argPack[valueIndex]; + const Operand& op = invokeNode->arg(argIndex, valueIndex); + + if (op.isNone()) + continue; + + if (op.isReg()) { + const Reg& reg = op.as<Reg>(); + RAWorkReg* workReg; + ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg)); + + if (arg.isReg()) { + RegGroup regGroup = workReg->group(); + RegGroup argGroup = Reg::groupOf(arg.regType()); + + if (regGroup != argGroup) { + // TODO: [ARM] Conversion is not supported. + return DebugUtils::errored(kErrorInvalidAssignment); + } + } + else { + ASMJIT_PROPAGATE(moveRegToStackArg(invokeNode, arg, reg)); + } + } + else if (op.isImm()) { + if (arg.isReg()) { + BaseReg reg; + ASMJIT_PROPAGATE(moveImmToRegArg(invokeNode, arg, op.as<Imm>(), ®)); + invokeNode->_args[argIndex][valueIndex] = reg; + } + else { + ASMJIT_PROPAGATE(moveImmToStackArg(invokeNode, arg, op.as<Imm>())); + } + } + } + } + + cc()->_setCursor(invokeNode); + + if (fd.hasRet()) { + for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) { + const FuncValue& ret = fd.ret(valueIndex); + if (!ret) + break; + + const Operand& op = invokeNode->ret(valueIndex); + if (op.isReg()) { + const Reg& reg = op.as<Reg>(); + RAWorkReg* workReg; + ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg)); + + if (ret.isReg()) { + RegGroup regGroup = workReg->group(); + RegGroup retGroup = Reg::groupOf(ret.regType()); + + if (regGroup != retGroup) { + // TODO: [ARM] Conversion is not supported. + return DebugUtils::errored(kErrorInvalidAssignment); + } + } + } + } + } + + // This block has function call(s). + _curBlock->addFlags(RABlockFlags::kHasFuncCalls); + _pass->func()->frame().addAttributes(FuncAttributes::kHasFuncCalls); + _pass->func()->frame().updateCallStackSize(fd.argStackSize()); + + return kErrorOk; +} + +Error RACFGBuilder::onInvoke(InvokeNode* invokeNode, RAInstBuilder& ib) noexcept { + uint32_t argCount = invokeNode->argCount(); + const FuncDetail& fd = invokeNode->detail(); + + for (uint32_t argIndex = 0; argIndex < argCount; argIndex++) { + const FuncValuePack& argPack = fd.argPack(argIndex); + for (uint32_t valueIndex = 0; valueIndex < Globals::kMaxValuePack; valueIndex++) { + if (!argPack[valueIndex]) + continue; + + const FuncValue& arg = argPack[valueIndex]; + const Operand& op = invokeNode->arg(argIndex, valueIndex); + + if (op.isNone()) + continue; + + if (op.isReg()) { + const Reg& reg = op.as<Reg>(); + RAWorkReg* workReg; + ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg)); + + if (arg.isIndirect()) { + RegGroup regGroup = workReg->group(); + if (regGroup != RegGroup::kGp) + return DebugUtils::errored(kErrorInvalidState); + ASMJIT_PROPAGATE(ib.addCallArg(workReg, arg.regId())); + } + else if (arg.isReg()) { + RegGroup regGroup = workReg->group(); + RegGroup argGroup = Reg::groupOf(arg.regType()); + + if (regGroup == argGroup) { + ASMJIT_PROPAGATE(ib.addCallArg(workReg, arg.regId())); + } + } + } + } + } + + for (uint32_t retIndex = 0; retIndex < Globals::kMaxValuePack; retIndex++) { + const FuncValue& ret = fd.ret(retIndex); + if (!ret) + break; + + const Operand& op = invokeNode->ret(retIndex); + if (op.isReg()) { + const Reg& reg = op.as<Reg>(); + RAWorkReg* workReg; + ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(Operand::virtIdToIndex(reg.id()), &workReg)); + + if (ret.isReg()) { + RegGroup regGroup = workReg->group(); + RegGroup retGroup = Reg::groupOf(ret.regType()); + + if (regGroup == retGroup) { + ASMJIT_PROPAGATE(ib.addCallRet(workReg, ret.regId())); + } + } + else { + return DebugUtils::errored(kErrorInvalidAssignment); + } + } + } + + // Setup clobbered registers. + ib._clobbered[0] = Support::lsbMask<RegMask>(_pass->_physRegCount[RegGroup(0)]) & ~fd.preservedRegs(RegGroup(0)); + ib._clobbered[1] = Support::lsbMask<RegMask>(_pass->_physRegCount[RegGroup(1)]) & ~fd.preservedRegs(RegGroup(1)); + ib._clobbered[2] = Support::lsbMask<RegMask>(_pass->_physRegCount[RegGroup(2)]) & ~fd.preservedRegs(RegGroup(2)); + ib._clobbered[3] = Support::lsbMask<RegMask>(_pass->_physRegCount[RegGroup(3)]) & ~fd.preservedRegs(RegGroup(3)); + + return kErrorOk; +} + +// a64::RACFGBuilder - MoveImmToRegArg +// =================================== + +Error RACFGBuilder::moveImmToRegArg(InvokeNode* invokeNode, const FuncValue& arg, const Imm& imm_, BaseReg* out) noexcept { + DebugUtils::unused(invokeNode); + ASMJIT_ASSERT(arg.isReg()); + + Imm imm(imm_); + TypeId typeId = TypeId::kVoid; + + switch (arg.typeId()) { + case TypeId::kInt8 : typeId = TypeId::kUInt64; imm.signExtend8Bits(); break; + case TypeId::kUInt8 : typeId = TypeId::kUInt64; imm.zeroExtend8Bits(); break; + case TypeId::kInt16 : typeId = TypeId::kUInt64; imm.signExtend16Bits(); break; + case TypeId::kUInt16: typeId = TypeId::kUInt64; imm.zeroExtend16Bits(); break; + case TypeId::kInt32 : typeId = TypeId::kUInt64; imm.signExtend32Bits(); break; + case TypeId::kUInt32: typeId = TypeId::kUInt64; imm.zeroExtend32Bits(); break; + case TypeId::kInt64 : typeId = TypeId::kUInt64; break; + case TypeId::kUInt64: typeId = TypeId::kUInt64; break; + + default: + return DebugUtils::errored(kErrorInvalidAssignment); + } + + ASMJIT_PROPAGATE(cc()->_newReg(out, typeId, nullptr)); + cc()->virtRegById(out->id())->setWeight(BaseRAPass::kCallArgWeight); + return cc()->mov(out->as<Gp>(), imm); +} + +// a64::RACFGBuilder - MoveImmToStackArg +// ===================================== + +Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const Imm& imm_) noexcept { + BaseReg reg; + + ASMJIT_PROPAGATE(moveImmToRegArg(invokeNode, arg, imm_, ®)); + ASMJIT_PROPAGATE(moveRegToStackArg(invokeNode, arg, reg)); + + return kErrorOk; +} + +// a64::RACFGBuilder - MoveRegToStackArg +// ===================================== + +Error RACFGBuilder::moveRegToStackArg(InvokeNode* invokeNode, const FuncValue& arg, const BaseReg& reg) noexcept { + DebugUtils::unused(invokeNode); + Mem stackPtr = ptr(_pass->_sp.as<Gp>(), arg.stackOffset()); + + if (reg.isGp()) + return cc()->str(reg.as<Gp>(), stackPtr); + + if (reg.isVec()) + return cc()->str(reg.as<Vec>(), stackPtr); + + return DebugUtils::errored(kErrorInvalidState); +} + +// a64::RACFGBuilder - OnReg +// ========================= + +Error RACFGBuilder::onBeforeRet(FuncRetNode* funcRet) noexcept { + DebugUtils::unused(funcRet); + return kErrorOk; +} + +Error RACFGBuilder::onRet(FuncRetNode* funcRet, RAInstBuilder& ib) noexcept { + const FuncDetail& funcDetail = _pass->func()->detail(); + const Operand* opArray = funcRet->operands(); + uint32_t opCount = funcRet->opCount(); + + for (uint32_t i = 0; i < opCount; i++) { + const Operand& op = opArray[i]; + if (op.isNone()) continue; + + const FuncValue& ret = funcDetail.ret(i); + if (ASMJIT_UNLIKELY(!ret.isReg())) + return DebugUtils::errored(kErrorInvalidAssignment); + + if (op.isReg()) { + // Register return value. + const Reg& reg = op.as<Reg>(); + uint32_t vIndex = Operand::virtIdToIndex(reg.id()); + + if (vIndex < Operand::kVirtIdCount) { + RAWorkReg* workReg; + ASMJIT_PROPAGATE(_pass->virtIndexAsWorkReg(vIndex, &workReg)); + + RegGroup group = workReg->group(); + RegMask allocable = _pass->_availableRegs[group]; + ASMJIT_PROPAGATE(ib.add(workReg, RATiedFlags::kUse | RATiedFlags::kRead, allocable, ret.regId(), 0, 0, BaseReg::kIdBad, 0)); + } + } + else { + return DebugUtils::errored(kErrorInvalidAssignment); + } + } + + return kErrorOk; +} + +// a64::ARMRAPass - Construction & Destruction +// =========================================== + +ARMRAPass::ARMRAPass() noexcept + : BaseRAPass() { _iEmitHelper = &_emitHelper; } +ARMRAPass::~ARMRAPass() noexcept {} + +// a64::ARMRAPass - OnInit / OnDone +// ================================ + +void ARMRAPass::onInit() noexcept { + Arch arch = cc()->arch(); + + _emitHelper._emitter = _cb; + + _archTraits = &ArchTraits::byArch(arch); + _physRegCount.set(RegGroup::kGp, 32); + _physRegCount.set(RegGroup::kVec, 32); + _physRegCount.set(RegGroup::kExtraVirt2, 0); + _physRegCount.set(RegGroup::kExtraVirt3, 0); + _buildPhysIndex(); + + _availableRegCount = _physRegCount; + _availableRegs[RegGroup::kGp] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kGp)); + _availableRegs[RegGroup::kVec] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kVec)); + _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kExtraVirt2)); + _availableRegs[RegGroup::kExtraVirt3] = Support::lsbMask<uint32_t>(_physRegCount.get(RegGroup::kExtraVirt3)); + + _scratchRegIndexes[0] = uint8_t(27); + _scratchRegIndexes[1] = uint8_t(28); + + // The architecture specific setup makes implicitly all registers available. So + // make unavailable all registers that are special and cannot be used in general. + bool hasFP = _func->frame().hasPreservedFP(); + + if (hasFP) + makeUnavailable(RegGroup::kGp, Gp::kIdFp); + + makeUnavailable(RegGroup::kGp, Gp::kIdSp); + makeUnavailable(RegGroup::kGp, Gp::kIdOs); // OS-specific use, usually TLS. + + _sp = sp; + _fp = x29; +} + +void ARMRAPass::onDone() noexcept {} + +// a64::ARMRAPass - BuildCFG +// ========================= + +Error ARMRAPass::buildCFG() noexcept { + return RACFGBuilder(this).run(); +} + +// a64::ARMRAPass - Rewrite +// ======================== + +ASMJIT_FAVOR_SPEED Error ARMRAPass::_rewrite(BaseNode* first, BaseNode* stop) noexcept { + uint32_t virtCount = cc()->_vRegArray.size(); + + BaseNode* node = first; + while (node != stop) { + BaseNode* next = node->next(); + if (node->isInst()) { + InstNode* inst = node->as<InstNode>(); + RAInst* raInst = node->passData<RAInst>(); + + Operand* operands = inst->operands(); + uint32_t opCount = inst->opCount(); + + uint32_t i; + + // Rewrite virtual registers into physical registers. + if (raInst) { + // If the instruction contains pass data (raInst) then it was a subject + // for register allocation and must be rewritten to use physical regs. + RATiedReg* tiedRegs = raInst->tiedRegs(); + uint32_t tiedCount = raInst->tiedCount(); + + for (i = 0; i < tiedCount; i++) { + RATiedReg* tiedReg = &tiedRegs[i]; + + Support::BitWordIterator<uint32_t> useIt(tiedReg->useRewriteMask()); + uint32_t useId = tiedReg->useId(); + while (useIt.hasNext()) + inst->rewriteIdAtIndex(useIt.next(), useId); + + Support::BitWordIterator<uint32_t> outIt(tiedReg->outRewriteMask()); + uint32_t outId = tiedReg->outId(); + while (outIt.hasNext()) + inst->rewriteIdAtIndex(outIt.next(), outId); + } + + // This data is allocated by Zone passed to `runOnFunction()`, which + // will be reset after the RA pass finishes. So reset this data to + // prevent having a dead pointer after the RA pass is complete. + node->resetPassData(); + + if (ASMJIT_UNLIKELY(node->type() != NodeType::kInst)) { + // FuncRet terminates the flow, it must either be removed if the exit + // label is next to it (optimization) or patched to an architecture + // dependent jump instruction that jumps to the function's exit before + // the epilog. + if (node->type() == NodeType::kFuncRet) { + RABlock* block = raInst->block(); + if (!isNextTo(node, _func->exitNode())) { + cc()->_setCursor(node->prev()); + ASMJIT_PROPAGATE(emitJump(_func->exitNode()->label())); + } + + BaseNode* prev = node->prev(); + cc()->removeNode(node); + block->setLast(prev); + } + } + } + + // Rewrite stack slot addresses. + for (i = 0; i < opCount; i++) { + Operand& op = operands[i]; + if (op.isMem()) { + BaseMem& mem = op.as<BaseMem>(); + if (mem.isRegHome()) { + uint32_t virtIndex = Operand::virtIdToIndex(mem.baseId()); + if (ASMJIT_UNLIKELY(virtIndex >= virtCount)) + return DebugUtils::errored(kErrorInvalidVirtId); + + VirtReg* virtReg = cc()->virtRegByIndex(virtIndex); + RAWorkReg* workReg = virtReg->workReg(); + ASMJIT_ASSERT(workReg != nullptr); + + RAStackSlot* slot = workReg->stackSlot(); + int32_t offset = slot->offset(); + + mem._setBase(_sp.type(), slot->baseRegId()); + mem.clearRegHome(); + mem.addOffsetLo32(offset); + } + } + } + } + + node = next; + } + + return kErrorOk; +} + +// a64::ARMRAPass - Prolog & Epilog +// ================================ + +Error ARMRAPass::updateStackFrame() noexcept { + if (_func->frame().hasFuncCalls()) + _func->frame().addDirtyRegs(RegGroup::kGp, Support::bitMask(Gp::kIdLr)); + + return BaseRAPass::updateStackFrame(); +} + +// a64::ARMRAPass - OnEmit +// ======================= + +Error ARMRAPass::emitMove(uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { + RAWorkReg* wReg = workRegById(workId); + BaseReg dst(wReg->signature(), dstPhysId); + BaseReg src(wReg->signature(), srcPhysId); + + const char* comment = nullptr; + +#ifndef ASMJIT_NO_LOGGING + if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) { + _tmpString.assignFormat("<MOVE> %s", workRegById(workId)->name()); + comment = _tmpString.data(); + } +#endif + + return _emitHelper.emitRegMove(dst, src, wReg->typeId(), comment); +} + +Error ARMRAPass::emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept { + DebugUtils::unused(aWorkId, aPhysId, bWorkId, bPhysId); + return DebugUtils::errored(kErrorInvalidState); +} + +Error ARMRAPass::emitLoad(uint32_t workId, uint32_t dstPhysId) noexcept { + RAWorkReg* wReg = workRegById(workId); + BaseReg dstReg(wReg->signature(), dstPhysId); + BaseMem srcMem(workRegAsMem(wReg)); + + const char* comment = nullptr; + +#ifndef ASMJIT_NO_LOGGING + if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) { + _tmpString.assignFormat("<LOAD> %s", workRegById(workId)->name()); + comment = _tmpString.data(); + } +#endif + + return _emitHelper.emitRegMove(dstReg, srcMem, wReg->typeId(), comment); +} + +Error ARMRAPass::emitSave(uint32_t workId, uint32_t srcPhysId) noexcept { + RAWorkReg* wReg = workRegById(workId); + BaseMem dstMem(workRegAsMem(wReg)); + BaseReg srcReg(wReg->signature(), srcPhysId); + + const char* comment = nullptr; + +#ifndef ASMJIT_NO_LOGGING + if (hasDiagnosticOption(DiagnosticOptions::kRAAnnotate)) { + _tmpString.assignFormat("<SAVE> %s", workRegById(workId)->name()); + comment = _tmpString.data(); + } +#endif + + return _emitHelper.emitRegMove(dstMem, srcReg, wReg->typeId(), comment); +} + +Error ARMRAPass::emitJump(const Label& label) noexcept { + return cc()->b(label); +} + +Error ARMRAPass::emitPreCall(InvokeNode* invokeNode) noexcept { + DebugUtils::unused(invokeNode); + return kErrorOk; +} + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_AARCH64 && !ASMJIT_NO_COMPILER diff --git a/src/asmjit/arm/a64rapass_p.h b/src/asmjit/arm/a64rapass_p.h new file mode 100644 index 0000000..e1a90ab --- /dev/null +++ b/src/asmjit/arm/a64rapass_p.h @@ -0,0 +1,105 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64RAPASS_P_H_INCLUDED +#define ASMJIT_ARM_A64RAPASS_P_H_INCLUDED + +#include "../core/api-config.h" +#ifndef ASMJIT_NO_COMPILER + +#include "../core/compiler.h" +#include "../core/rabuilders_p.h" +#include "../core/rapass_p.h" +#include "../arm/a64assembler.h" +#include "../arm/a64compiler.h" +#include "../arm/a64emithelper_p.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \cond INTERNAL +//! \addtogroup asmjit_a64 +//! \{ + +//! ARM register allocation pass. +//! +//! Takes care of generating function prologs and epilogs, and also performs +//! register allocation. +class ARMRAPass : public BaseRAPass { +public: + ASMJIT_NONCOPYABLE(ARMRAPass) + typedef BaseRAPass Base; + + EmitHelper _emitHelper; + + //! \name Construction & Destruction + //! \{ + + ARMRAPass() noexcept; + virtual ~ARMRAPass() noexcept; + + //! \} + + //! \name Accessors + //! \{ + + //! Returns the compiler casted to `arm::Compiler`. + inline Compiler* cc() const noexcept { return static_cast<Compiler*>(_cb); } + + //! Returns emit helper. + inline EmitHelper* emitHelper() noexcept { return &_emitHelper; } + + //! \} + + //! \name Events + //! \{ + + void onInit() noexcept override; + void onDone() noexcept override; + + //! \} + + //! \name CFG + //! \{ + + Error buildCFG() noexcept override; + + //! \} + + //! \name Rewrite + //! \{ + + Error _rewrite(BaseNode* first, BaseNode* stop) noexcept override; + + //! \} + + //! \name Prolog & Epilog + //! \{ + + Error updateStackFrame() noexcept override; + + //! \} + + //! \name Emit Helpers + //! \{ + + Error emitMove(uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept override; + Error emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept override; + + Error emitLoad(uint32_t workId, uint32_t dstPhysId) noexcept override; + Error emitSave(uint32_t workId, uint32_t srcPhysId) noexcept override; + + Error emitJump(const Label& label) noexcept override; + Error emitPreCall(InvokeNode* invokeNode) noexcept override; + + //! \} +}; + +//! \} +//! \endcond + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_COMPILER +#endif // ASMJIT_ARM_A64RAPASS_P_H_INCLUDED diff --git a/src/asmjit/arm/a64utils.h b/src/asmjit/arm/a64utils.h new file mode 100644 index 0000000..4a88ca5 --- /dev/null +++ b/src/asmjit/arm/a64utils.h @@ -0,0 +1,179 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_A64UTILS_H_INCLUDED +#define ASMJIT_ARM_A64UTILS_H_INCLUDED + +#include "../arm/a64globals.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(a64) + +//! \addtogroup asmjit_a64 +//! \{ + +//! Public utilities and helpers for targeting AArch64 architecture. +namespace Utils { + +//! Decomposed fields of a logical immediate value (AArch64). +struct LogicalImm { + uint32_t n; + uint32_t s; + uint32_t r; +}; + +//! Encodes the given `imm` value of the given `width` to a logical immediate value represented as N, S, and R fields +//! and writes these fields to `out`. +//! +//! Encoding Table: +//! +//! ``` +//! +---+--------+--------+------+ +//! | N | ImmS | ImmR | Size | +//! +---+--------+--------+------+ +//! | 1 | ssssss | rrrrrr | 64 | +//! | 0 | 0sssss | .rrrrr | 32 | +//! | 0 | 10ssss | ..rrrr | 16 | +//! | 0 | 110sss | ...rrr | 8 | +//! | 0 | 1110ss | ....rr | 4 | +//! | 0 | 11110s | .....r | 2 | +//! +---+--------+--------+------+ +//! ``` +ASMJIT_MAYBE_UNUSED +static bool encodeLogicalImm(uint64_t imm, uint32_t width, a64::Utils::LogicalImm* out) noexcept { + // Determine the element width, which must be 2, 4, 8, 16, 32, or 64 bits. + do { + width /= 2; + uint64_t mask = (uint64_t(1) << width) - 1u; + if ((imm & mask) != ((imm >> width) & mask)) { + width *= 2; + break; + } + } while (width > 2); + + // Patterns of all zeros and all ones are not encodable. + uint64_t lsbMask = Support::lsbMask<uint64_t>(width); + imm &= lsbMask; + + if (imm == 0 || imm == lsbMask) + return false; + + // Inspect the pattern and get the most important bit indexes. + // + // oIndex <-+ +-> zIndex + // | | + // |..zeros..|oCount|zCount|..ones..| + // |000000000|111111|000000|11111111| + + uint32_t zIndex = Support::ctz(~imm); + uint64_t zImm = imm ^ ((uint64_t(1) << zIndex) - 1); + uint32_t zCount = (zImm ? Support::ctz(zImm) : width) - zIndex; + + uint32_t oIndex = zIndex + zCount; + uint64_t oImm = ~(zImm ^ Support::lsbMask<uint64_t>(oIndex)); + uint32_t oCount = (oImm ? Support::ctz(oImm) : width) - (oIndex); + + // Verify whether the bit-pattern is encodable. + uint64_t mustBeZero = oImm ^ ~Support::lsbMask<uint64_t>(oIndex + oCount); + if (mustBeZero != 0 || (zIndex > 0 && width - (oIndex + oCount) != 0)) + return false; + + out->n = width == 64; + out->s = (oCount + zIndex - 1) | (Support::neg(width * 2) & 0x3F); + out->r = width - oIndex; + return true; +} + +//! Returns true if the given `imm` value is encodable as a logical immediate. The `width` argument describes the +//! width of the operation, and must be either 32 or 64. This function can be used to test whether an immediate +//! value can be used with AND, ANDS, BIC, BICS, EON, EOR, ORN, and ORR instruction. +ASMJIT_MAYBE_UNUSED +static inline bool isLogicalImm(uint64_t imm, uint32_t width) noexcept { + LogicalImm dummy; + return encodeLogicalImm(imm, width, &dummy); +} + +//! Returns true if the given `imm` value is a byte mask. Byte mask has each byte part of the value set to either +//! 0x00 or 0xFF. Some ARM instructions accept immediates that form a byte-mask and this function can be used to +//! verify that the immediate is encodable before using the value. +template<typename T> +static inline bool isByteMaskImm8(const T& imm) noexcept { + constexpr T kMask = T(0x0101010101010101 & Support::allOnes<T>()); + return imm == (imm & kMask) * T(255); +} + +//! \cond +//! A generic implementation that checjs whether a floating point value can be converted to ARM Imm8. +template<typename T, uint32_t kNumBBits, uint32_t kNumCDEFGHBits, uint32_t kNumZeroBits> +static inline bool isFPImm8Generic(T val) noexcept { + constexpr uint32_t kAllBsMask = Support::lsbMask<uint32_t>(kNumBBits); + constexpr uint32_t kB0Pattern = Support::bitMask(kNumBBits - 1); + constexpr uint32_t kB1Pattern = kAllBsMask ^ kB0Pattern; + + T immZ = val & Support::lsbMask<T>(kNumZeroBits); + uint32_t immB = uint32_t(val >> (kNumZeroBits + kNumCDEFGHBits)) & kAllBsMask; + + // ImmZ must be all zeros and ImmB must either be B0 or B1 pattern. + return immZ == 0 && (immB == kB0Pattern || immB == kB1Pattern); +} +//! \endcond + +//! Returns true if the given half precision floating point `val` can be encoded as ARM IMM8 value, which represents +//! a limited set of floating point immediate values, which can be used with FMOV instruction. +//! +//! The floating point must have bits distributed in the following way: +//! +//! ``` +//! [aBbbcdef|gh000000] +//! ``` +static inline bool isFP16Imm8(uint32_t val) noexcept { return isFPImm8Generic<uint32_t, 3, 6, 6>(val); } + +//! Returns true if the given single precision floating point `val` can be encoded as ARM IMM8 value, which represents +//! a limited set of floating point immediate values, which can be used with FMOV instruction. +//! +//! The floating point must have bits distributed in the following way: +//! +//! ``` +//! [aBbbbbbc|defgh000|00000000|00000000] +//! ``` +static inline bool isFP32Imm8(uint32_t val) noexcept { return isFPImm8Generic<uint32_t, 6, 6, 19>(val); } +//! \overload +static inline bool isFP32Imm8(float val) noexcept { return isFP32Imm8(Support::bitCast<uint32_t>(val)); } + +//! Returns true if the given double precision floating point `val` can be encoded as ARM IMM8 value, which represents +//! a limited set of floating point immediate values, which can be used with FMOV instruction. +//! +//! The floating point must have bits distributed in the following way: +//! +//! ``` +//! [aBbbbbbb|bbcdefgh|00000000|00000000|00000000|00000000|00000000|00000000] +//! ``` +static inline bool isFP64Imm8(uint64_t val) noexcept { return isFPImm8Generic<uint64_t, 9, 6, 48>(val); } +//! \overload +static inline bool isFP64Imm8(double val) noexcept { return isFP64Imm8(Support::bitCast<uint64_t>(val)); } + +//! \cond +template<typename T, uint32_t kNumBBits, uint32_t kNumCDEFGHBits, uint32_t kNumZeroBits> +static inline uint32_t encodeFPToImm8Generic(T val) noexcept { + uint32_t bits = uint32_t(val >> kNumZeroBits); + return ((bits >> (kNumBBits + kNumCDEFGHBits - 7)) & 0x80u) | (bits & 0x7F); +} +//! \endcond + +//! Encodes a double precision floating point value into IMM8 format. +//! +//! \note This function expects that `isFP64Imm8(val) == true` so it doesn't perform any checks of the value and just +//! rearranges some bits into Imm8 order. +static inline uint32_t encodeFP64ToImm8(uint64_t val) noexcept { return encodeFPToImm8Generic<uint64_t, 9, 6, 48>(val); } +//! \overload +static inline uint32_t encodeFP64ToImm8(double val) noexcept { return encodeFP64ToImm8(Support::bitCast<uint64_t>(val)); } + +} // {Utils} + +//! \} + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_A64UTILS_H_INCLUDED + diff --git a/src/asmjit/arm/armformatter.cpp b/src/asmjit/arm/armformatter.cpp new file mode 100644 index 0000000..0432043 --- /dev/null +++ b/src/asmjit/arm/armformatter.cpp @@ -0,0 +1,143 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include "../core/api-build_p.h" +#ifndef ASMJIT_NO_LOGGING + +#include "../core/misc_p.h" +#include "../core/support.h" +#include "../arm/armformatter_p.h" +#include "../arm/armoperand.h" +#include "../arm/a64instapi_p.h" +#include "../arm/a64instdb_p.h" + +#ifndef ASMJIT_NO_COMPILER + #include "../core/compiler.h" +#endif + +ASMJIT_BEGIN_SUB_NAMESPACE(arm) + +// arm::FormatterInternal - Format Feature +// ======================================= + +Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept { + // @EnumStringBegin{"enum": "CpuFeatures::ARM", "output": "sFeature", "strip": "k"}@ + static const char sFeatureString[] = + "None\0" + "THUMB\0" + "THUMBv2\0" + "ARMv6\0" + "ARMv7\0" + "ARMv8a\0" + "ARMv8_1a\0" + "ARMv8_2a\0" + "ARMv8_3a\0" + "ARMv8_4a\0" + "ARMv8_5a\0" + "ARMv8_6a\0" + "ARMv8_7a\0" + "VFPv2\0" + "VFPv3\0" + "VFPv4\0" + "VFP_D32\0" + "AES\0" + "ALTNZCV\0" + "ASIMD\0" + "BF16\0" + "BTI\0" + "CPUID\0" + "CRC32\0" + "DGH\0" + "DIT\0" + "DOTPROD\0" + "EDSP\0" + "FCMA\0" + "FJCVTZS\0" + "FLAGM\0" + "FP16CONV\0" + "FP16FML\0" + "FP16FULL\0" + "FRINT\0" + "I8MM\0" + "IDIVA\0" + "IDIVT\0" + "LSE\0" + "MTE\0" + "RCPC_IMMO\0" + "RDM\0" + "PMU\0" + "PMULL\0" + "RNG\0" + "SB\0" + "SHA1\0" + "SHA2\0" + "SHA3\0" + "SHA512\0" + "SM3\0" + "SM4\0" + "SSBS\0" + "SVE\0" + "SVE_BF16\0" + "SVE_F32MM\0" + "SVE_F64MM\0" + "SVE_I8MM\0" + "SVE_PMULL\0" + "SVE2\0" + "SVE2_AES\0" + "SVE2_BITPERM\0" + "SVE2_SHA3\0" + "SVE2_SM4\0" + "TME\0" + "<Unknown>\0"; + + static const uint16_t sFeatureIndex[] = { + 0, 5, 11, 19, 25, 31, 38, 47, 56, 65, 74, 83, 92, 101, 107, 113, 119, 127, + 131, 139, 145, 150, 154, 160, 166, 170, 174, 182, 187, 192, 200, 206, 215, + 223, 232, 238, 243, 249, 255, 259, 263, 273, 277, 281, 287, 291, 294, 299, + 304, 309, 316, 320, 324, 329, 333, 342, 352, 362, 371, 381, 386, 395, 408, + 418, 427, 431 + }; + // @EnumStringEnd@ + + return sb.append(sFeatureString + sFeatureIndex[Support::min<uint32_t>(featureId, uint32_t(CpuFeatures::ARM::kMaxValue) + 1)]); +} + +// arm::FormatterInternal - Format Constants +// ========================================= + +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatCondCode(String& sb, CondCode cc) noexcept { + static const char condCodeData[] = + "al\0" "na\0" + "eq\0" "ne\0" + "cs\0" "cc\0" "mi\0" "pl\0" "vs\0" "vc\0" + "hi\0" "ls\0" "ge\0" "lt\0" "gt\0" "le\0" + "<Unknown>"; + return sb.append(condCodeData + Support::min<uint32_t>(uint32_t(cc), 16u) * 3); +} + +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatShiftOp(String& sb, ShiftOp shiftOp) noexcept { + const char* str = "<Unknown>"; + switch (shiftOp) { + case ShiftOp::kLSL: str = "lsl"; break; + case ShiftOp::kLSR: str = "lsr"; break; + case ShiftOp::kASR: str = "asr"; break; + case ShiftOp::kROR: str = "ror"; break; + case ShiftOp::kRRX: str = "rrx"; break; + case ShiftOp::kMSL: str = "msl"; break; + case ShiftOp::kUXTB: str = "uxtb"; break; + case ShiftOp::kUXTH: str = "uxth"; break; + case ShiftOp::kUXTW: str = "uxtw"; break; + case ShiftOp::kUXTX: str = "uxtx"; break; + case ShiftOp::kSXTB: str = "sxtb"; break; + case ShiftOp::kSXTH: str = "sxth"; break; + case ShiftOp::kSXTW: str = "sxtw"; break; + case ShiftOp::kSXTX: str = "sxtx"; break; + } + return sb.append(str); +} + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_LOGGING diff --git a/src/asmjit/arm/armformatter_p.h b/src/asmjit/arm/armformatter_p.h new file mode 100644 index 0000000..5821730 --- /dev/null +++ b/src/asmjit/arm/armformatter_p.h @@ -0,0 +1,44 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_ARMFORMATTER_P_H_INCLUDED +#define ASMJIT_ARM_ARMFORMATTER_P_H_INCLUDED + +#include "../core/api-config.h" +#ifndef ASMJIT_NO_LOGGING + +#include "../core/formatter.h" +#include "../core/string.h" +#include "../arm/armglobals.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(arm) + +//! \cond INTERNAL +//! \addtogroup asmjit_arm +//! \{ + +namespace FormatterInternal { + +Error ASMJIT_CDECL formatFeature( + String& sb, + uint32_t featureId) noexcept; + +Error ASMJIT_CDECL formatCondCode( + String& sb, + CondCode cc) noexcept; + +Error ASMJIT_CDECL formatShiftOp( + String& sb, + ShiftOp shiftOp) noexcept; + +} // {FormatterInternal} + +//! \} +//! \endcond + +ASMJIT_END_SUB_NAMESPACE + +#endif // !ASMJIT_NO_LOGGING +#endif // ASMJIT_ARM_ARMFORMATTER_P_H_INCLUDED diff --git a/src/asmjit/arm/armglobals.h b/src/asmjit/arm/armglobals.h new file mode 100644 index 0000000..506646f --- /dev/null +++ b/src/asmjit/arm/armglobals.h @@ -0,0 +1,21 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_ARMGLOBALS_H_INCLUDED +#define ASMJIT_ARM_ARMGLOBALS_H_INCLUDED + +#include "../core/archcommons.h" +#include "../core/inst.h" + +//! \namespace asmjit::arm +//! \ingroup asmjit_arm +//! +//! API shared between AArch32 & AArch64 backends. + +ASMJIT_BEGIN_SUB_NAMESPACE(arm) + +ASMJIT_END_SUB_NAMESPACE + +#endif // ASMJIT_ARM_ARMGLOBALS_H_INCLUDED diff --git a/src/asmjit/arm/armoperand.h b/src/asmjit/arm/armoperand.h new file mode 100644 index 0000000..e7803e9 --- /dev/null +++ b/src/asmjit/arm/armoperand.h @@ -0,0 +1,596 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#ifndef ASMJIT_ARM_ARMOPERAND_H_INCLUDED +#define ASMJIT_ARM_ARMOPERAND_H_INCLUDED + +#include "../core/archtraits.h" +#include "../core/operand.h" +#include "../core/type.h" +#include "../arm/armglobals.h" + +ASMJIT_BEGIN_SUB_NAMESPACE(arm) + +//! \addtogroup asmjit_arm +//! \{ + +class Reg; +class Mem; + +class Gp; +class GpW; +class GpX; + +class Vec; +class VecB; +class VecH; +class VecS; +class VecD; +class VecV; + +//! Register traits (ARM/AArch64). +//! +//! Register traits contains information about a particular register type. It's used by asmjit to setup register +//! information on-the-fly and to populate tables that contain register information (this way it's possible to +//! change register types and groups without having to reorder these tables). +template<RegType kRegType> +struct RegTraits : public BaseRegTraits {}; + +//! \cond +// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ +// | Reg | Reg-Type | Reg-Group |Sz |Cnt| TypeId | +// <--------------------+-----+-------------------------+------------------------+---+---+------------------+ +ASMJIT_DEFINE_REG_TRAITS(GpW , RegType::kARM_GpW , RegGroup::kGp , 4 , 32, TypeId::kInt32 ); +ASMJIT_DEFINE_REG_TRAITS(GpX , RegType::kARM_GpX , RegGroup::kGp , 8 , 32, TypeId::kInt64 ); +ASMJIT_DEFINE_REG_TRAITS(VecB , RegType::kARM_VecB , RegGroup::kVec , 1 , 32, TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(VecH , RegType::kARM_VecH , RegGroup::kVec , 2 , 32, TypeId::kVoid ); +ASMJIT_DEFINE_REG_TRAITS(VecS , RegType::kARM_VecS , RegGroup::kVec , 4 , 32, TypeId::kInt32x1 ); +ASMJIT_DEFINE_REG_TRAITS(VecD , RegType::kARM_VecD , RegGroup::kVec , 8 , 32, TypeId::kInt32x2 ); +ASMJIT_DEFINE_REG_TRAITS(VecV , RegType::kARM_VecV , RegGroup::kVec , 16, 32, TypeId::kInt32x4 ); +//! \endcond + +//! Register (ARM). +class Reg : public BaseReg { +public: + ASMJIT_DEFINE_ABSTRACT_REG(Reg, BaseReg) + + //! Gets whether the register is a `R|W` register (32-bit). + inline constexpr bool isGpW() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpW>::kSignature; } + //! Gets whether the register is an `X` register (64-bit). + inline constexpr bool isGpX() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpX>::kSignature; } + //! Gets whether the register is a VEC-B register (8-bit). + inline constexpr bool isVecB() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecB>::kSignature; } + //! Gets whether the register is a VEC-H register (16-bit). + inline constexpr bool isVecH() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecH>::kSignature; } + //! Gets whether the register is a VEC-S register (32-bit). + inline constexpr bool isVecS() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecS>::kSignature; } + //! Gets whether the register is a VEC-D register (64-bit). + inline constexpr bool isVecD() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecD>::kSignature; } + //! Gets whether the register is a VEC-Q register (128-bit). + inline constexpr bool isVecQ() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; } + + //! Gets whether the register is either VEC-D (64-bit) or VEC-Q (128-bit). + inline constexpr bool isVecDOrQ() const noexcept { return uint32_t(type()) - uint32_t(RegType::kARM_VecD) <= 1u; } + + //! Gets whether the register is a VEC-V register (128-bit). + inline constexpr bool isVecV() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; } + + template<RegType kRegType> + inline void setRegT(uint32_t id) noexcept { + setSignature(RegTraits<kRegType>::kSignature); + setId(id); + } + + inline void setTypeAndId(RegType type, uint32_t id) noexcept { + setSignature(signatureOf(type)); + setId(id); + } + + static inline RegGroup groupOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToGroup(type); } + static inline TypeId typeIdOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToTypeId(type); } + static inline OperandSignature signatureOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToSignature(type); } + + template<RegType kRegType> + static inline RegGroup groupOfT() noexcept { return RegTraits<kRegType>::kGroup; } + + template<RegType kRegType> + static inline TypeId typeIdOfT() noexcept { return RegTraits<kRegType>::kTypeId; } + + template<RegType kRegType> + static inline OperandSignature signatureOfT() noexcept { return RegTraits<kRegType>::kSignature; } + + static inline bool isGpW(const Operand_& op) noexcept { return op.as<Reg>().isGpW(); } + static inline bool isGpX(const Operand_& op) noexcept { return op.as<Reg>().isGpX(); } + static inline bool isVecB(const Operand_& op) noexcept { return op.as<Reg>().isVecB(); } + static inline bool isVecH(const Operand_& op) noexcept { return op.as<Reg>().isVecH(); } + static inline bool isVecS(const Operand_& op) noexcept { return op.as<Reg>().isVecS(); } + static inline bool isVecD(const Operand_& op) noexcept { return op.as<Reg>().isVecD(); } + static inline bool isVecQ(const Operand_& op) noexcept { return op.as<Reg>().isVecQ(); } + static inline bool isVecV(const Operand_& op) noexcept { return op.as<Reg>().isVecV(); } + + static inline bool isGpW(const Operand_& op, uint32_t id) noexcept { return isGpW(op) & (op.id() == id); } + static inline bool isGpX(const Operand_& op, uint32_t id) noexcept { return isGpX(op) & (op.id() == id); } + static inline bool isVecB(const Operand_& op, uint32_t id) noexcept { return isVecB(op) & (op.id() == id); } + static inline bool isVecH(const Operand_& op, uint32_t id) noexcept { return isVecH(op) & (op.id() == id); } + static inline bool isVecS(const Operand_& op, uint32_t id) noexcept { return isVecS(op) & (op.id() == id); } + static inline bool isVecD(const Operand_& op, uint32_t id) noexcept { return isVecD(op) & (op.id() == id); } + static inline bool isVecQ(const Operand_& op, uint32_t id) noexcept { return isVecQ(op) & (op.id() == id); } + static inline bool isVecV(const Operand_& op, uint32_t id) noexcept { return isVecV(op) & (op.id() == id); } +}; + +//! General purpose register (ARM). +class Gp : public Reg { +public: + ASMJIT_DEFINE_ABSTRACT_REG(Gp, Reg) + + //! Special register id. + enum Id : uint32_t { + //! Register that depends on OS, could be used as TLS offset. + kIdOs = 18, + //! Frame pointer. + kIdFp = 29, + //! Link register. + kIdLr = 30, + //! Stack register id. + kIdSp = 31, + //! Zero register id. + //! + //! Although zero register has the same id as stack register it has a special treatment, because we need to be + //! able to distinguish between these two at API level. Some intructions were designed to be used with SP and + //! some other with ZR - so we need a way to distinguish these two to make sure we emit the right thing. + //! + //! The number 63 is not random, when you perform `id & 31` you would always get 31 for both SP and ZR inputs, + //! which is the identifier used by AArch64 ISA to encode either SP or ZR depending on the instruction. + kIdZr = 63 + }; + + inline constexpr bool isZR() const noexcept { return id() == kIdZr; } + inline constexpr bool isSP() const noexcept { return id() == kIdSp; } + + //! Cast this register to a 32-bit R|W. + inline GpW w() const noexcept; + //! Cast this register to a 64-bit X. + inline GpX x() const noexcept; +}; + +//! Vector register (ARM). +class Vec : public Reg { +public: + ASMJIT_DEFINE_ABSTRACT_REG(Vec, Reg) + + //! Additional signature bits used by arm::Vec. + enum AdditionalBits : uint32_t { + // Register element type (3 bits). + // |........|........|.XXX....|........| + kSignatureRegElementTypeShift = 12, + kSignatureRegElementTypeMask = 0x07 << kSignatureRegElementTypeShift, + + // Register has element index (1 bit). + // |........|........|X.......|........| + kSignatureRegElementFlagShift = 15, + kSignatureRegElementFlagMask = 0x01 << kSignatureRegElementFlagShift, + + // Register element index (4 bits). + // |........|....XXXX|........|........| + kSignatureRegElementIndexShift = 16, + kSignatureRegElementIndexMask = 0x0F << kSignatureRegElementIndexShift + }; + + //! Element type. + enum ElementType : uint32_t { + //! No element type specified. + kElementTypeNone = 0, + //! Byte elements (B8 or B16). + kElementTypeB, + //! Halfword elements (H4 or H8). + kElementTypeH, + //! Singleword elements (S2 or S4). + kElementTypeS, + //! Doubleword elements (D2). + kElementTypeD, + //! Byte elements grouped by 4 bytes (B4). + //! + //! \note This element-type is only used by few instructions. + kElementTypeB4, + //! Halfword elements grouped by 2 halfwords (H2). + //! + //! \note This element-type is only used by few instructions. + kElementTypeH2, + + //! Count of element types. + kElementTypeCount + }; + + //! \cond + //! Shortcuts. + enum SignatureReg : uint32_t { + kSignatureElementB = kElementTypeB << kSignatureRegElementTypeShift, + kSignatureElementH = kElementTypeH << kSignatureRegElementTypeShift, + kSignatureElementS = kElementTypeS << kSignatureRegElementTypeShift, + kSignatureElementD = kElementTypeD << kSignatureRegElementTypeShift, + kSignatureElementB4 = kElementTypeB4 << kSignatureRegElementTypeShift, + kSignatureElementH2 = kElementTypeH2 << kSignatureRegElementTypeShift + }; + //! \endcond + + //! Returns whether the register has associated an element type. + inline constexpr bool hasElementType() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask>(); } + //! Returns whether the register has element index (it's an element index access). + inline constexpr bool hasElementIndex() const noexcept { return _signature.hasField<kSignatureRegElementFlagMask>(); } + //! Returns whether the reggister has element type or element index (or both). + inline constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask | kSignatureRegElementFlagMask>(); } + + //! Returns element type of the register. + inline constexpr uint32_t elementType() const noexcept { return _signature.getField<kSignatureRegElementTypeMask>(); } + //! Sets element type of the register to `elementType`. + inline void setElementType(uint32_t elementType) noexcept { _signature.setField<kSignatureRegElementTypeMask>(elementType); } + //! Resets element type to none. + inline void resetElementType() noexcept { _signature.setField<kSignatureRegElementTypeMask>(0); } + + //! Returns element index of the register. + inline constexpr uint32_t elementIndex() const noexcept { return _signature.getField<kSignatureRegElementIndexMask>(); } + //! Sets element index of the register to `elementType`. + inline void setElementIndex(uint32_t elementIndex) noexcept { + _signature |= kSignatureRegElementFlagMask; + _signature.setField<kSignatureRegElementIndexMask>(elementIndex); + } + //! Resets element index of the register. + inline void resetElementIndex() noexcept { + _signature &= ~(kSignatureRegElementFlagMask | kSignatureRegElementIndexMask); + } + + inline constexpr bool isVecB8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementB); } + inline constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementH); } + inline constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementS); } + inline constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature); } + + inline constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB); } + inline constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH); } + inline constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementS); } + inline constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementD); } + inline constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB4); } + inline constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH2); } + + //! Creates a cloned register with element access. + inline Vec at(uint32_t elementIndex) const noexcept { + return Vec((signature() & ~kSignatureRegElementIndexMask) | (elementIndex << kSignatureRegElementIndexShift) | kSignatureRegElementFlagMask, id()); + } + + //! Cast this register to an 8-bit B register (scalar). + inline VecB b() const noexcept; + //! Cast this register to a 16-bit H register (scalar). + inline VecH h() const noexcept; + //! Cast this register to a 32-bit S register (scalar). + inline VecS s() const noexcept; + //! Cast this register to a 64-bit D register (scalar). + inline VecD d() const noexcept; + //! Cast this register to a 128-bit Q register (scalar). + inline VecV q() const noexcept; + //! Cast this register to a 128-bit V register. + inline VecV v() const noexcept; + + //! Cast this register to a 128-bit V.B[elementIndex] register. + inline VecV b(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.H[elementIndex] register. + inline VecV h(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.S[elementIndex] register. + inline VecV s(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.D[elementIndex] register. + inline VecV d(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.H2[elementIndex] register. + inline VecV h2(uint32_t elementIndex) const noexcept; + //! Cast this register to a 128-bit V.B4[elementIndex] register. + inline VecV b4(uint32_t elementIndex) const noexcept; + + //! Cast this register to V.8B. + inline VecD b8() const noexcept; + //! Cast this register to V.16B. + inline VecV b16() const noexcept; + //! Cast this register to V.2H. + inline VecS h2() const noexcept; + //! Cast this register to V.4H. + inline VecD h4() const noexcept; + //! Cast this register to V.8H. + inline VecV h8() const noexcept; + //! Cast this register to V.2S. + inline VecD s2() const noexcept; + //! Cast this register to V.4S. + inline VecV s4() const noexcept; + //! Cast this register to V.2D. + inline VecV d2() const noexcept; + + static inline constexpr OperandSignature _makeElementAccessSignature(uint32_t elementType, uint32_t elementIndex) noexcept { + return OperandSignature{ + uint32_t(RegTraits<RegType::kARM_VecV>::kSignature) | + uint32_t(kSignatureRegElementFlagMask) | + uint32_t(elementType << kSignatureRegElementTypeShift) | + uint32_t(elementIndex << kSignatureRegElementIndexShift)}; + } +}; + +//! 32-bit GPW (AArch64) and/or GPR (ARM/AArch32) register. +class GpW : public Gp { ASMJIT_DEFINE_FINAL_REG(GpW, Gp, RegTraits<RegType::kARM_GpW>) }; +//! 64-bit GPX (AArch64) register. +class GpX : public Gp { ASMJIT_DEFINE_FINAL_REG(GpX, Gp, RegTraits<RegType::kARM_GpX>) }; + +//! 8-bit view (S) of VFP/SIMD register. +class VecB : public Vec { ASMJIT_DEFINE_FINAL_REG(VecB, Vec, RegTraits<RegType::kARM_VecB>) }; +//! 16-bit view (S) of VFP/SIMD register. +class VecH : public Vec { ASMJIT_DEFINE_FINAL_REG(VecH, Vec, RegTraits<RegType::kARM_VecH>) }; +//! 32-bit view (S) of VFP/SIMD register. +class VecS : public Vec { ASMJIT_DEFINE_FINAL_REG(VecS, Vec, RegTraits<RegType::kARM_VecS>) }; +//! 64-bit view (D) of VFP/SIMD register. +class VecD : public Vec { ASMJIT_DEFINE_FINAL_REG(VecD, Vec, RegTraits<RegType::kARM_VecD>) }; +//! 128-bit vector register (Q or V). +class VecV : public Vec { ASMJIT_DEFINE_FINAL_REG(VecV, Vec, RegTraits<RegType::kARM_VecV>) }; + +inline GpW Gp::w() const noexcept { return GpW(id()); } +inline GpX Gp::x() const noexcept { return GpX(id()); } + +inline VecB Vec::b() const noexcept { return VecB(id()); } +inline VecH Vec::h() const noexcept { return VecH(id()); } +inline VecS Vec::s() const noexcept { return VecS(id()); } +inline VecD Vec::d() const noexcept { return VecD(id()); } +inline VecV Vec::q() const noexcept { return VecV(id()); } +inline VecV Vec::v() const noexcept { return VecV(id()); } + +inline VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB, elementIndex), id()); } +inline VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH, elementIndex), id()); } +inline VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeS, elementIndex), id()); } +inline VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeD, elementIndex), id()); } +inline VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH2, elementIndex), id()); } +inline VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB4, elementIndex), id()); } + +inline VecD Vec::b8() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementB}, id()); } +inline VecS Vec::h2() const noexcept { return VecS(OperandSignature{VecS::kSignature | kSignatureElementH}, id()); } +inline VecD Vec::h4() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementH}, id()); } +inline VecD Vec::s2() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementS}, id()); } +inline VecV Vec::b16() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementB}, id()); } +inline VecV Vec::h8() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementH}, id()); } +inline VecV Vec::s4() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementS}, id()); } +inline VecV Vec::d2() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementD}, id()); } + +#ifndef _DOXYGEN +namespace regs { +#endif + +//! Creates a 32-bit W register operand (ARM/AArch64). +static inline constexpr GpW w(uint32_t id) noexcept { return GpW(id); } +//! Creates a 64-bit X register operand (AArch64). +static inline constexpr GpX x(uint32_t id) noexcept { return GpX(id); } +//! Creates a 32-bit S register operand (ARM/AArch64). +static inline constexpr VecS s(uint32_t id) noexcept { return VecS(id); } +//! Creates a 64-bit D register operand (ARM/AArch64). +static inline constexpr VecD d(uint32_t id) noexcept { return VecD(id); } +//! Creates a 1282-bit V register operand (ARM/AArch64). +static inline constexpr VecV v(uint32_t id) noexcept { return VecV(id); } + +#ifndef _DOXYGEN +} // {regs} + +// Make `arm::regs` accessible through `arm` namespace as well. +using namespace regs; +#endif + +//! Memory operand (ARM). +class Mem : public BaseMem { +public: + //! \cond INTERNAL + //! Additional bits of operand's signature used by `arm::Mem`. + enum AdditionalBits : uint32_t { + // Index shift value (5 bits). + // |........|.....XXX|XX......|........| + kSignatureMemShiftValueShift = 14, + kSignatureMemShiftValueMask = 0x1Fu << kSignatureMemShiftValueShift, + + // Shift operation type (4 bits). + // |........|XXXX....|........|........| + kSignatureMemPredicateShift = 20, + kSignatureMemPredicateMask = 0x0Fu << kSignatureMemPredicateShift + }; + //! \endcond + + //! Memory offset mode. + //! + //! Additional constants that can be used with the `predicate`. + enum OffsetMode : uint32_t { + //! Pre-index "[BASE, #Offset {, <shift>}]!" with write-back. + kOffsetPreIndex = 0xE, + //! Post-index "[BASE], #Offset {, <shift>}" with write-back. + kOffsetPostIndex = 0xF + }; + + //! \name Construction & Destruction + //! \{ + + //! Construct a default `Mem` operand, that points to [0]. + inline constexpr Mem() noexcept + : BaseMem() {} + + inline constexpr Mem(const Mem& other) noexcept + : BaseMem(other) {} + + inline explicit Mem(Globals::NoInit_) noexcept + : BaseMem(Globals::NoInit) {} + + inline constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept + : BaseMem(signature, baseId, indexId, offset) {} + + inline constexpr explicit Mem(const Label& base, int32_t off = 0, Signature signature = Signature{0}) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + Signature::fromMemBaseType(RegType::kLabelTag) | + signature, base.id(), 0, off) {} + + inline constexpr explicit Mem(const BaseReg& base, int32_t off = 0, Signature signature = Signature{0}) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + Signature::fromMemBaseType(base.type()) | + signature, base.id(), 0, off) {} + + inline constexpr Mem(const BaseReg& base, const BaseReg& index, Signature signature = Signature{0}) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + Signature::fromMemBaseType(base.type()) | + Signature::fromMemIndexType(index.type()) | + signature, base.id(), index.id(), 0) {} + + inline constexpr Mem(const BaseReg& base, const BaseReg& index, const Shift& shift, Signature signature = Signature{0}) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + Signature::fromMemBaseType(base.type()) | + Signature::fromMemIndexType(index.type()) | + Signature::fromValue<kSignatureMemPredicateMask>(uint32_t(shift.op())) | + Signature::fromValue<kSignatureMemShiftValueMask>(shift.value()) | + signature, base.id(), index.id(), 0) {} + + inline constexpr Mem(uint64_t base, Signature signature = Signature{0}) noexcept + : BaseMem(Signature::fromOpType(OperandType::kMem) | + signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {} + + //! \} + + //! \name Overloaded Operators + //! \{ + + inline Mem& operator=(const Mem& other) noexcept = default; + + //! \} + + //! \name ARM Specific Features + //! \{ + + //! Clones the memory operand. + inline constexpr Mem clone() const noexcept { return Mem(*this); } + //! Gets new memory operand adjusted by `off`. + inline Mem cloneAdjusted(int64_t off) const noexcept { + Mem result(*this); + result.addOffset(off); + return result; + } + + using BaseMem::setIndex; + + inline void setIndex(const BaseReg& index, uint32_t shift) noexcept { + setIndex(index); + setShift(shift); + } + + //! Gets whether the memory operand has shift (aka scale) constant. + inline constexpr bool hasShift() const noexcept { return _signature.hasField<kSignatureMemShiftValueMask>(); } + //! Gets the memory operand's shift (aka scale) constant. + inline constexpr uint32_t shift() const noexcept { return _signature.getField<kSignatureMemShiftValueMask>(); } + //! Sets the memory operand's shift (aka scale) constant. + inline void setShift(uint32_t shift) noexcept { _signature.setField<kSignatureMemShiftValueMask>(shift); } + //! Resets the memory operand's shift (aka scale) constant to zero. + inline void resetShift() noexcept { _signature.setField<kSignatureMemShiftValueMask>(0); } + + //! Gets memory predicate (shift mode or offset mode), see \ref ShiftOp and \ref OffsetMode. + inline constexpr uint32_t predicate() const noexcept { return _signature.getField<kSignatureMemPredicateMask>(); } + //! Sets memory predicate to `predicate`, see `Mem::ShiftOp`. + inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<kSignatureMemPredicateMask>(predicate); } + //! Resets shift mode to LSL (default). + inline void resetPredicate() noexcept { _signature.setField<kSignatureMemPredicateMask>(0); } + + inline constexpr bool isFixedOffset() const noexcept { return predicate() < kOffsetPreIndex; } + inline constexpr bool isPreOrPost() const noexcept { return predicate() >= kOffsetPreIndex; } + inline constexpr bool isPreIndex() const noexcept { return predicate() == kOffsetPreIndex; } + inline constexpr bool isPostIndex() const noexcept { return predicate() == kOffsetPostIndex; } + + inline void resetToFixedOffset() noexcept { resetPredicate(); } + inline void makePreIndex() noexcept { setPredicate(kOffsetPreIndex); } + inline void makePostIndex() noexcept { setPredicate(kOffsetPostIndex); } + + inline Mem pre() const noexcept { + Mem result(*this); + result.setPredicate(kOffsetPreIndex); + return result; + } + + inline Mem pre(int64_t off) const noexcept { + Mem result(*this); + result.setPredicate(kOffsetPreIndex); + result.addOffset(off); + return result; + } + + inline Mem post() const noexcept { + Mem result(*this); + result.setPredicate(kOffsetPreIndex); + return result; + } + + inline Mem post(int64_t off) const noexcept { + Mem result(*this); + result.setPredicate(kOffsetPostIndex); + result.addOffset(off); + return result; + } + + //! \} +}; + +//! Creates `[base.reg, offset]` memory operand (offset mode). +static inline constexpr Mem ptr(const Gp& base, int32_t offset = 0) noexcept { + return Mem(base, offset); +} + +//! Creates `[base.reg, offset]!` memory operand (pre-index mode). +static inline constexpr Mem ptr_pre(const Gp& base, int32_t offset = 0) noexcept { + return Mem(base, offset, OperandSignature::fromValue<Mem::kSignatureMemPredicateMask>(Mem::kOffsetPreIndex)); +} + +//! Creates `[base.reg], offset` memory operand (post-index mode). +static inline constexpr Mem ptr_post(const Gp& base, int32_t offset = 0) noexcept { + return Mem(base, offset, OperandSignature::fromValue<Mem::kSignatureMemPredicateMask>(Mem::kOffsetPostIndex)); +} + +//! Creates `[base.reg, index]` memory operand. +static inline constexpr Mem ptr(const Gp& base, const Gp& index) noexcept { + return Mem(base, index); +} + +//! Creates `[base.reg], index` memory operand (post-index mode). +static inline constexpr Mem ptr_post(const Gp& base, const Gp& index) noexcept { + return Mem(base, index, OperandSignature::fromValue<Mem::kSignatureMemPredicateMask>(Mem::kOffsetPostIndex)); +} + +//! Creates `[base.reg, index, SHIFT_OP #shift]` memory operand. +static inline constexpr Mem ptr(const Gp& base, const Gp& index, const Shift& shift) noexcept { + return Mem(base, index, shift); +} + +//! Creates `[base + offset]` memory operand. +static inline constexpr Mem ptr(const Label& base, int32_t offset = 0) noexcept { + return Mem(base, offset); +} + +// TODO: [ARM] PC + offset address. +#if 0 +//! Creates `[PC + offset]` (relative) memory operand. +static inline constexpr Mem ptr(const PC& pc, int32_t offset = 0) noexcept { + return Mem(pc, offset); +} +#endif + +//! Creates `[base]` absolute memory operand. +//! +//! \note The concept of absolute memory operands doesn't exist on ARM, the ISA only provides PC relative addressing. +//! Absolute memory operands can only be used if it's known that the PC relative offset is encodable and that it +//! would be within the limits. Absolute address is also often output from disassemblers, so AsmJit support it so it +//! can assemble it back. +static inline constexpr Mem ptr(uint64_t base) noexcept { return Mem(base); } + +//! \} + +ASMJIT_END_SUB_NAMESPACE + +//! \cond INTERNAL +ASMJIT_BEGIN_NAMESPACE +ASMJIT_DEFINE_TYPE_ID(arm::GpW, TypeId::kInt32); +ASMJIT_DEFINE_TYPE_ID(arm::GpX, TypeId::kInt64); +ASMJIT_DEFINE_TYPE_ID(arm::VecS, TypeId::kFloat32x1); +ASMJIT_DEFINE_TYPE_ID(arm::VecD, TypeId::kFloat64x1); +ASMJIT_DEFINE_TYPE_ID(arm::VecV, TypeId::kInt32x4); +ASMJIT_END_NAMESPACE +//! \endcond + +#endif // ASMJIT_ARM_ARMOPERAND_H_INCLUDED diff --git a/src/asmjit/core.h b/src/asmjit/core.h index 32f208f..4406ed8 100644 --- a/src/asmjit/core.h +++ b/src/asmjit/core.h @@ -26,9 +26,9 @@ namespace asmjit { //! //! \note It's important to understand that in order to learn AsmJit all groups are important. Some groups can be //! omitted if a particular tool is out of interest - for example \ref asmjit_assembler users don't need to know -//! about \ref asmjit_builder, but it's not the opposite. \ref asmjit_builder users must know about \ref +//! about \ref asmjit_builder, but it's not the opposite. \ref asmjit_builder users should know about \ref //! asmjit_assembler as it also uses operands, labels, and other concepts. Similarly \ref asmjit_compiler users -//! must know how both \ref asmjit_assembler and \ref asmjit_builder tools work. +//! should know how both \ref asmjit_assembler and \ref asmjit_builder tools work. //! //! \section where_to_start Where To Start //! @@ -70,13 +70,13 @@ namespace asmjit { //! //! - Make sure you put a breakpoint into \ref DebugUtils::errored() function if you have a problem with AsmJit //! returning errors during instruction encoding or register allocation. Having an active breakpoint there can -//! help to reveal the origin of the error, to inspect variables and other conditions that caused to it. +//! help to reveal the origin of the error, to inspect variables and other conditions that caused it. //! //! The reason for using \ref Logger and \ref ErrorHandler is that they provide a very useful information about what's -//! happening inside emitters. In many cases the information provided by these two is crucial to quickly fix issues -//! that happen during development (for example wrong instruction, address, or register used). In addition, output from -//! \ref Logger is always necessary when filling bug reports. In other words, using logging and proper error handling -//! can save a lot of time during the development. +//! happening inside emitters. In many cases the information provided by these two is crucial to quickly identify and +//! fix issues that happen during development (for example wrong instruction, address, or register used). In addition, +//! output from \ref Logger is always necessary when filling bug reports. In other words, using logging and proper error +//! handling can save a lot of time during the development and can also save users from submitting issues. //! //! \section main_other Other Pages //! @@ -147,7 +147,9 @@ namespace asmjit { //! //! ### Supported Backends / Architectures //! -//! - **X86** - Both 32-bit and 64-bit backends tested on our CI. +//! - **X86** and **X86_64** - Both 32-bit and 64-bit backends tested on CI. +//! - **AArch64** - AArch64 backend is currently only partially tested (there is no native AArch64 runner to test +//! AsmJit Builder/Compiler) //! //! ### Static Builds and Embedding //! @@ -1807,6 +1809,14 @@ namespace asmjit { //! \brief X86/X64 backend. +//! \defgroup asmjit_arm ARM Commons +//! \brief ARM commons shared between AArch32 and AArch64. + + +//! \defgroup asmjit_a64 AArch64 Backend +//! \brief AArch64 backend. + + //! \cond INTERNAL //! \defgroup asmjit_ra RA //! \brief Register allocator internals. diff --git a/src/asmjit/core/api-config.h b/src/asmjit/core/api-config.h index 3c4f8b2..a0fb979 100644 --- a/src/asmjit/core/api-config.h +++ b/src/asmjit/core/api-config.h @@ -13,7 +13,7 @@ //! \{ //! AsmJit library version in `(Major << 16) | (Minor << 8) | (Patch)` format. -#define ASMJIT_LIBRARY_VERSION 0x010800 /* 1.8.0 */ +#define ASMJIT_LIBRARY_VERSION 0x010900 /* 1.9.0 */ //! \def ASMJIT_ABI_NAMESPACE //! @@ -24,7 +24,7 @@ //! default, which makes it possible to use use multiple AsmJit libraries within a single project, totally controlled //! by the users. This is useful especially in cases in which some of such library comes from a third party. #ifndef ASMJIT_ABI_NAMESPACE - #define ASMJIT_ABI_NAMESPACE _abi_1_8 + #define ASMJIT_ABI_NAMESPACE _abi_1_9 #endif //! \} @@ -79,6 +79,12 @@ namespace asmjit { //! Disables X86/X64 backends. #define ASMJIT_NO_X86 +//! Disables AArch32 backends (both ARM and Thumb). +#define ASMJIT_NO_AARCH32 + +//! Disables AArch64 backend. +#define ASMJIT_NO_AARCH64 + //! Disables non-host backends entirely (useful for JIT compilers to minimize the library size). #define ASMJIT_NO_FOREIGN @@ -206,6 +212,10 @@ namespace asmjit { #if !ASMJIT_ARCH_X86 && !defined(ASMJIT_NO_X86) #define ASMJIT_NO_X86 #endif + + #if !ASMJIT_ARCH_ARM && !defined(ASMJIT_NO_AARCH64) + #define ASMJIT_NO_AARCH64 + #endif #endif @@ -344,7 +354,6 @@ namespace asmjit { #define ASMJIT_VECTORCALL #endif - // Type alignment (not allowed by C++11 'alignas' keyword). #if defined(__GNUC__) #define ASMJIT_ALIGN_TYPE(TYPE, N) __attribute__((__aligned__(N))) TYPE @@ -383,6 +392,15 @@ namespace asmjit { #define ASMJIT_NONNULL(FUNCTION_ARGUMENT) FUNCTION_ARGUMENT #endif +//! \def ASMJIT_NOEXCEPT_TYPE +//! +//! Defined to `noexcept` in C++17 mode or nothing otherwise. Used by function typedefs. +#if __cplusplus >= 201703L + #define ASMJIT_NOEXCEPT_TYPE noexcept +#else + #define ASMJIT_NOEXCEPT_TYPE +#endif + //! \def ASMJIT_ASSUME(...) //! //! Macro that tells the C/C++ compiler that the expression `...` evaluates to true. diff --git a/src/asmjit/core/archcommons.h b/src/asmjit/core/archcommons.h index 88b6069..e9d2c84 100644 --- a/src/asmjit/core/archcommons.h +++ b/src/asmjit/core/archcommons.h @@ -17,12 +17,105 @@ ASMJIT_BEGIN_SUB_NAMESPACE(arm) //! \addtogroup asmjit_arm //! \{ +//! Condition code (both AArch32 & AArch64). +//! +//! \note This enumeration doesn't match condition code that is used in AArch32/AArch64 opcodes. In general this +//! condition code is encoded as `(cc - 2) & 0xF` so that `kAL` condition code is zero and encoded as 0xE in opcode. +//! This makes it easier to use a condition code as an instruction modifier that defaults to 'al'. +enum class CondCode : uint8_t { + kAL = 0x00u, //!< (no condition code) (always) + kNA = 0x01u, //!< (not available) (special) + kEQ = 0x02u, //!< Z==1 (any_sign ==) + kNE = 0x03u, //!< Z==0 (any_sign !=) + kCS = 0x04u, //!< C==1 (unsigned >=) + kHS = 0x04u, //!< C==1 (unsigned >=) + kCC = 0x05u, //!< C==0 (unsigned < ) + kLO = 0x05u, //!< C==0 (unsigned < ) + kMI = 0x06u, //!< N==1 (is negative) + kPL = 0x07u, //!< N==0 (is positive or zero) + kVS = 0x08u, //!< V==1 (is overflow) + kVC = 0x09u, //!< V==0 (no overflow) + kHI = 0x0Au, //!< C==1 & Z==0 (unsigned > ) + kLS = 0x0Bu, //!< C==0 | Z==1 (unsigned <=) + kGE = 0x0Cu, //!< N==V (signed >=) + kLT = 0x0Du, //!< N!=V (signed < ) + kGT = 0x0Eu, //!< Z==0 & N==V (signed > ) + kLE = 0x0Fu, //!< Z==1 | N!=V (signed <=) + + kSign = kMI, //!< Sign. + kNotSign = kPL, //!< Not sign. + + kOverflow = kVS, //!< Signed overflow. + kNotOverflow = kVC, //!< Not signed overflow. + + kEqual = kEQ, //!< Equal `a == b`. + kNotEqual = kNE, //!< Not Equal `a != b`. + + kZero = kEQ, //!< Zero (alias to equal). + kNotZero = kNE, //!< Not Zero (alias to Not Equal). + + kNegative = kMI, //!< Negative. + kPositive = kPL, //!< Positive or zero. + + kSignedLT = kLT, //!< Signed `a < b`. + kSignedLE = kLE, //!< Signed `a <= b`. + kSignedGT = kGT, //!< Signed `a > b`. + kSignedGE = kGE, //!< Signed `a >= b`. + + kUnsignedLT = kLO, //!< Unsigned `a < b`. + kUnsignedLE = kLS, //!< Unsigned `a <= b`. + kUnsignedGT = kHI, //!< Unsigned `a > b`. + kUnsignedGE = kHS, //!< Unsigned `a >= b`. + + kAlways = kAL, //!< No condition code (always). + + kMaxValue = 0x0Fu //!< Maximum value of `CondCode`. +}; + +//! Negates a condition code. +static inline constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ uint8_t(1)); } + +//! Data type that can be encoded with the instruction (AArch32 only). +enum class DataType : uint32_t { + //! No data type specified (default for all general purpose instructions). + kNone = 0, + //! 8-bit signed integer, specified as `.s8` in assembly. + kS8 = 1, + //! 16-bit signed integer, specified as `.s16` in assembly. + kS16 = 2, + //! 32-bit signed integer, specified as `.s32` in assembly. + kS32 = 3, + //! 64-bit signed integer, specified as `.s64` in assembly. + kS64 = 4, + //! 8-bit unsigned integer, specified as `.u8` in assembly. + kU8 = 5, + //! 16-bit unsigned integer, specified as `.u16` in assembly. + kU16 = 6, + //! 32-bit unsigned integer, specified as `.u32` in assembly. + kU32 = 7, + //! 64-bit unsigned integer, specified as `.u64` in assembly. + kU64 = 8, + //! 16-bit floating point (half precision), specified as `.f16` in assembly. + kF16 = 10, + //! 32-bit floating point (single precision), specified as `.f32` in assembly. + kF32 = 11, + //! 64-bit floating point (double precision), specified as `.f64` in assembly. + kF64 = 12, + //! 8-bit polynomial. + kP8 = 13, + //! 64-bit polynomial. + kP64 = 15, + + //! Maximum value of `DataType`. + kMaxValue = 15 +}; + //! Shift operation predicate (ARM) describes either SHIFT or EXTEND operation. //! //! \note The constants are AsmJit specific. The first 5 values describe real constants on ARM32 and AArch64 hardware, //! however, the addition constants that describe extend modes are specific to AsmJit and would be translated to the //! AArch64 specific constants by the assembler. -enum class ShiftOp { +enum class ShiftOp : uint32_t { //! Shift left logical operation (default). //! //! Available to all ARM architectures. @@ -38,14 +131,10 @@ enum class ShiftOp { //! Available to all ARM architectures. kASR = 0x02u, - //! Rotate right operation. - //! - //! \note Not available in AArch64 mode. + //! Rotate right operation (AArch32 only). kROR = 0x03u, - //! Rotate right with carry operation (encoded as `kShiftROR` with zero). - //! - //! \note Not available in AArch64 mode. + //! Rotate right with carry operation (encoded as `ShiftOp::kROR` with zero) (AArch32 only). kRRX = 0x04u, //! Shift left by filling low order bits with ones. diff --git a/src/asmjit/core/archtraits.cpp b/src/asmjit/core/archtraits.cpp index b83d930..fc825df 100644 --- a/src/asmjit/core/archtraits.cpp +++ b/src/asmjit/core/archtraits.cpp @@ -11,8 +11,8 @@ #include "../x86/x86archtraits_p.h" #endif -#ifdef ASMJIT_BUILD_ARM - #include "../arm/armarchtraits_p.h" +#if !defined(ASMJIT_NO_AARCH64) + #include "../arm/a64archtraits_p.h" #endif ASMJIT_BEGIN_NAMESPACE @@ -83,8 +83,8 @@ ASMJIT_VARAPI const ArchTraits _archTraits[uint32_t(Arch::kMaxValue) + 1] = { noArchTraits, // AArch64 architecture. -#ifdef ASMJIT_BUILD_ARM - arm::a64ArchTraits, +#if !defined(ASMJIT_NO_AARCH64) + a64::a64ArchTraits, #else noArchTraits, #endif diff --git a/src/asmjit/core/assembler.cpp b/src/asmjit/core/assembler.cpp index ea223a3..d6c8762 100644 --- a/src/asmjit/core/assembler.cpp +++ b/src/asmjit/core/assembler.cpp @@ -271,7 +271,7 @@ Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) { re->_sourceSectionId = _section->id(); re->_sourceOffset = offset(); - re->_format.resetToDataValue(uint32_t(dataSize)); + re->_format.resetToSimpleValue(OffsetType::kUnsignedOffset, dataSize); if (le->isBound()) { re->_targetSectionId = le->section()->id(); @@ -279,7 +279,7 @@ Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) { } else { OffsetFormat of; - of.resetToDataValue(uint32_t(dataSize)); + of.resetToSimpleValue(OffsetType::kUnsignedOffset, dataSize); LabelLink* link = _code->newLabelLink(le, _section->id(), offset(), 0, of); if (ASMJIT_UNLIKELY(!link)) @@ -348,7 +348,7 @@ Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size exp->setValueAsLabel(0, labelEntry); exp->setValueAsLabel(1, baseEntry); - re->_format.resetToDataValue(dataSize); + re->_format.resetToSimpleValue(OffsetType::kSignedOffset, dataSize); re->_sourceSectionId = _section->id(); re->_sourceOffset = offset(); re->_payload = (uint64_t)(uintptr_t)exp; diff --git a/src/asmjit/core/builder.cpp b/src/asmjit/core/builder.cpp index e3767a1..5df243e 100644 --- a/src/asmjit/core/builder.cpp +++ b/src/asmjit/core/builder.cpp @@ -590,7 +590,9 @@ Error BaseBuilder::_emit(InstId instId, const Operand_& o0, const Operand_& o1, Operand_ opArray[Globals::kMaxOpCount]; EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - Error err = InstAPI::validate(arch(), BaseInst(instId, options, _extraReg), opArray, opCount); + ValidationFlags validationFlags = isCompiler() ? ValidationFlags::kEnableVirtRegs : ValidationFlags::kNone; + Error err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, opCount, validationFlags); + if (ASMJIT_UNLIKELY(err)) { resetInstOptions(); resetExtraReg(); diff --git a/src/asmjit/core/builder.h b/src/asmjit/core/builder.h index 8376986..3575de2 100644 --- a/src/asmjit/core/builder.h +++ b/src/asmjit/core/builder.h @@ -746,6 +746,9 @@ public: //! Returns the instruction id, see `BaseInst::Id`. inline InstId id() const noexcept { return _baseInst.id(); } + //! Returns the instruction real id, see `BaseInst::Id`. + inline InstId realId() const noexcept { return _baseInst.realId(); } + //! Sets the instruction id to `id`, see `BaseInst::Id`. inline void setId(InstId id) noexcept { _baseInst.setId(id); } diff --git a/src/asmjit/core/codeholder.cpp b/src/asmjit/core/codeholder.cpp index 25d8f90..cf763cf 100644 --- a/src/asmjit/core/codeholder.cpp +++ b/src/asmjit/core/codeholder.cpp @@ -194,6 +194,10 @@ Error CodeHolder::attach(BaseEmitter* emitter) noexcept { if (ASMJIT_UNLIKELY(type == EmitterType::kNone || uint32_t(type) > uint32_t(EmitterType::kMaxValue))) return DebugUtils::errored(kErrorInvalidState); + uint64_t archMask = emitter->_archMask; + if (ASMJIT_UNLIKELY(!(archMask & (uint64_t(1) << uint32_t(arch()))))) + return DebugUtils::errored(kErrorInvalidArch); + // This is suspicious, but don't fail if `emitter` is already attached // to this code holder. This is not error, but it's not recommended. if (emitter->_code != nullptr) { @@ -944,7 +948,6 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept { return DebugUtils::errored(kErrorInvalidRelocEntry); uint8_t* buffer = sourceSection->data(); - size_t valueOffset = size_t(re->sourceOffset()) + re->format().valueOffset(); switch (re->relocType()) { case RelocType::kExpression: { @@ -970,12 +973,18 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept { case RelocType::kAbsToRel: { value -= baseAddress + sectionOffset + sourceOffset + regionSize; - if (addressSize > 4 && !Support::isInt32(int64_t(value))) + + // Sign extend as we are not interested in the high 32-bit word in a 32-bit address space. + if (addressSize <= 4) + value = uint64_t(int64_t(int32_t(value & 0xFFFFFFFFu))); + else if (!Support::isInt32(int64_t(value))) return DebugUtils::errored(kErrorRelocOffsetOutOfRange); + break; } case RelocType::kX64AddressEntry: { + size_t valueOffset = size_t(re->sourceOffset()) + re->format().valueOffset(); if (re->format().valueSize() != 4 || valueOffset < 2) return DebugUtils::errored(kErrorInvalidRelocEntry); @@ -1030,25 +1039,8 @@ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept { return DebugUtils::errored(kErrorInvalidRelocEntry); } - switch (re->format().valueSize()) { - case 1: - Support::writeU8(buffer + valueOffset, uint8_t(value & 0xFFu)); - break; - - case 2: - Support::writeU16uLE(buffer + valueOffset, uint16_t(value & 0xFFFFu)); - break; - - case 4: - Support::writeU32uLE(buffer + valueOffset, uint32_t(value & 0xFFFFFFFFu)); - break; - - case 8: - Support::writeU64uLE(buffer + valueOffset, value); - break; - - default: - return DebugUtils::errored(kErrorInvalidRelocEntry); + if (!CodeWriterUtils::writeOffset(buffer + re->sourceOffset(), int64_t(value), re->format())) { + return DebugUtils::errored(kErrorInvalidRelocEntry); } } diff --git a/src/asmjit/core/codeholder.h b/src/asmjit/core/codeholder.h index b6257f2..e3bd0d5 100644 --- a/src/asmjit/core/codeholder.h +++ b/src/asmjit/core/codeholder.h @@ -276,7 +276,10 @@ enum class OffsetType : uint8_t { //! //! This offset type is sufficient for many targets that store offset as a continuous set bits within an //! instruction word / sequence of bytes. - kCommon = 0, + kSignedOffset, + + //! An unsigned value having `_immBitCount` bits and shifted by `_immBitShift`. + kUnsignedOffset, // AArch64 Specific Offset Formats // ------------------------------- @@ -370,15 +373,15 @@ struct OffsetFormat { //! //! The region will be the same size as data and immediate bits would correspond to `dataSize * 8`. There will be //! no immediate bit shift or discarded bits. - inline void resetToDataValue(size_t dataSize) noexcept { - ASMJIT_ASSERT(dataSize <= 8u); + inline void resetToSimpleValue(OffsetType type, size_t valueSize) noexcept { + ASMJIT_ASSERT(valueSize <= 8u); - _type = OffsetType::kCommon; + _type = type; _flags = uint8_t(0); - _regionSize = uint8_t(dataSize); - _valueSize = uint8_t(dataSize); + _regionSize = uint8_t(valueSize); + _valueSize = uint8_t(valueSize); _valueOffset = uint8_t(0); - _immBitCount = uint8_t(dataSize * 8u); + _immBitCount = uint8_t(valueSize * 8u); _immBitShift = uint8_t(0); _immDiscardLsb = uint8_t(0); } diff --git a/src/asmjit/core/codewriter.cpp b/src/asmjit/core/codewriter.cpp index b416dec..1babc5f 100644 --- a/src/asmjit/core/codewriter.cpp +++ b/src/asmjit/core/codewriter.cpp @@ -14,26 +14,46 @@ bool CodeWriterUtils::encodeOffset32(uint32_t* dst, int64_t offset64, const Offs uint32_t bitShift = format.immBitShift(); uint32_t discardLsb = format.immDiscardLsb(); + // Invalid offset (should not happen). if (!bitCount || bitCount > format.valueSize() * 8u) return false; - if (discardLsb) { - ASMJIT_ASSERT(discardLsb <= 32); - if ((offset64 & Support::lsbMask<uint32_t>(discardLsb)) != 0) + uint32_t value; + + // First handle all unsigned offset types. + if (format.type() == OffsetType::kUnsignedOffset) { + if (discardLsb) { + ASMJIT_ASSERT(discardLsb <= 32); + if ((offset64 & Support::lsbMask<uint32_t>(discardLsb)) != 0) + return false; + offset64 = int64_t(uint64_t(offset64) >> discardLsb); + } + + value = uint32_t(offset64 & Support::lsbMask<uint32_t>(bitCount)); + if (value != offset64) return false; - offset64 >>= discardLsb; } + else { + // The rest of OffsetType options are all signed. + if (discardLsb) { + ASMJIT_ASSERT(discardLsb <= 32); + if ((offset64 & Support::lsbMask<uint32_t>(discardLsb)) != 0) + return false; + offset64 >>= discardLsb; + } - if (!Support::isInt32(offset64)) - return false; + if (!Support::isInt32(offset64)) + return false; - int32_t offset32 = int32_t(offset64); - if (!Support::isEncodableOffset32(offset32, bitCount)) - return false; + value = uint32_t(int32_t(offset64)); + if (!Support::isEncodableOffset32(int32_t(value), bitCount)) + return false; + } switch (format.type()) { - case OffsetType::kCommon: { - *dst = (uint32_t(offset32) & Support::lsbMask<uint32_t>(bitCount)) << bitShift; + case OffsetType::kSignedOffset: + case OffsetType::kUnsignedOffset: { + *dst = (value & Support::lsbMask<uint32_t>(bitCount)) << bitShift; return true; } @@ -43,8 +63,8 @@ bool CodeWriterUtils::encodeOffset32(uint32_t* dst, int64_t offset64, const Offs if (format.valueSize() != 4 || bitCount != 21 || bitShift != 5) return false; - uint32_t immLo = uint32_t(offset32) & 0x3u; - uint32_t immHi = uint32_t(offset32 >> 2) & Support::lsbMask<uint32_t>(19); + uint32_t immLo = value & 0x3u; + uint32_t immHi = (value >> 2) & Support::lsbMask<uint32_t>(19); *dst = (immLo << 29) | (immHi << 5); return true; @@ -62,19 +82,40 @@ bool CodeWriterUtils::encodeOffset64(uint64_t* dst, int64_t offset64, const Offs if (!bitCount || bitCount > format.valueSize() * 8u) return false; - if (discardLsb) { - ASMJIT_ASSERT(discardLsb <= 32); - if ((offset64 & Support::lsbMask<uint32_t>(discardLsb)) != 0) + uint64_t value; + + // First handle all unsigned offset types. + if (format.type() == OffsetType::kUnsignedOffset) { + if (discardLsb) { + ASMJIT_ASSERT(discardLsb <= 32); + if ((offset64 & Support::lsbMask<uint32_t>(discardLsb)) != 0) + return false; + offset64 = int64_t(uint64_t(offset64) >> discardLsb); + } + + value = uint64_t(offset64) & Support::lsbMask<uint64_t>(bitCount); + if (value != uint64_t(offset64)) return false; - offset64 >>= discardLsb; } + else { + // The rest of OffsetType options are all signed. + if (discardLsb) { + ASMJIT_ASSERT(discardLsb <= 32); + if ((offset64 & Support::lsbMask<uint32_t>(discardLsb)) != 0) + return false; + offset64 >>= discardLsb; + } - if (!Support::isEncodableOffset64(offset64, bitCount)) - return false; + if (!Support::isEncodableOffset64(offset64, bitCount)) + return false; + + value = uint64_t(offset64); + } switch (format.type()) { - case OffsetType::kCommon: { - *dst = (uint64_t(offset64) & Support::lsbMask<uint64_t>(bitCount)) << format.immBitShift(); + case OffsetType::kSignedOffset: + case OffsetType::kUnsignedOffset: { + *dst = (value & Support::lsbMask<uint64_t>(bitCount)) << format.immBitShift(); return true; } @@ -109,8 +150,9 @@ bool CodeWriterUtils::writeOffset(void* dst, int64_t offset64, const OffsetForma case 4: { uint32_t mask; - if (!encodeOffset32(&mask, offset64, format)) + if (!encodeOffset32(&mask, offset64, format)) { return false; + } Support::writeU32uLE(dst, Support::readU32uLE(dst) | mask); return true; diff --git a/src/asmjit/core/cpuinfo.cpp b/src/asmjit/core/cpuinfo.cpp index ef152cd..7bf7407 100644 --- a/src/asmjit/core/cpuinfo.cpp +++ b/src/asmjit/core/cpuinfo.cpp @@ -980,7 +980,7 @@ namespace AppleHWId { static ASMJIT_FAVOR_SIZE uint32_t queryARMCpuFamilyId() noexcept { uint32_t result = 0; - size_t size = sizeof(cpuFamily); + size_t size = sizeof(result); int res = sysctlbyname("hw.cpufamily", &result, &size, nullptr, 0); if (res != 0) diff --git a/src/asmjit/core/cpuinfo.h b/src/asmjit/core/cpuinfo.h index 974fb3e..4af5c3a 100644 --- a/src/asmjit/core/cpuinfo.h +++ b/src/asmjit/core/cpuinfo.h @@ -429,7 +429,7 @@ public: kARMv8_4a, //!< ARMv8.4-A ISA. kARMv8_5a, //!< ARMv8.5-A ISA. kARMv8_6a, //!< ARMv8.6-A ISA. - kARMv8_7a, //!< ARMv8.6-A ISA. + kARMv8_7a, //!< ARMv8.7-A ISA. kVFPv2, //!< CPU has VFPv2 instruction set. kVFPv3, //!< CPU has VFPv3 instruction set. diff --git a/src/asmjit/core/emitter.cpp b/src/asmjit/core/emitter.cpp index 38061b5..92d67a7 100644 --- a/src/asmjit/core/emitter.cpp +++ b/src/asmjit/core/emitter.cpp @@ -9,16 +9,6 @@ #include "../core/logger.h" #include "../core/support.h" -#if !defined(ASMJIT_NO_X86) - #include "../x86/x86emithelper_p.h" - #include "../x86/x86instdb_p.h" -#endif // !ASMJIT_NO_X86 - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/a64emithelper_p.h" - #include "../arm/a64instdb.h" -#endif // ASMJIT_BUILD_ARM - ASMJIT_BEGIN_NAMESPACE // BaseEmitter - Construction & Destruction @@ -219,70 +209,28 @@ Error BaseEmitter::_emitOpArray(InstId instId, const Operand_* operands, size_t } } -// BaseEmitter - Emit (High-Level) -// =============================== +// BaseEmitter - Emit Utilities +// ============================ -ASMJIT_FAVOR_SIZE Error BaseEmitter::emitProlog(const FuncFrame& frame) { +Error BaseEmitter::emitProlog(const FuncFrame& frame) { if (ASMJIT_UNLIKELY(!_code)) return DebugUtils::errored(kErrorNotInitialized); -#if !defined(ASMJIT_NO_X86) - if (environment().isFamilyX86()) { - x86::EmitHelper emitHelper(this, frame.isAvxEnabled(), frame.isAvx512Enabled()); - return emitHelper.emitProlog(frame); - } -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment().isArchAArch64()) { - a64::EmitHelper emitHelper(this); - return emitHelper.emitProlog(frame); - } -#endif - - return DebugUtils::errored(kErrorInvalidArch); + return _funcs.emitProlog(this, frame); } -ASMJIT_FAVOR_SIZE Error BaseEmitter::emitEpilog(const FuncFrame& frame) { +Error BaseEmitter::emitEpilog(const FuncFrame& frame) { if (ASMJIT_UNLIKELY(!_code)) return DebugUtils::errored(kErrorNotInitialized); -#if !defined(ASMJIT_NO_X86) - if (environment().isFamilyX86()) { - x86::EmitHelper emitHelper(this, frame.isAvxEnabled(), frame.isAvx512Enabled()); - return emitHelper.emitEpilog(frame); - } -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment().isArchAArch64()) { - a64::EmitHelper emitHelper(this); - return emitHelper.emitEpilog(frame); - } -#endif - - return DebugUtils::errored(kErrorInvalidArch); + return _funcs.emitEpilog(this, frame); } -ASMJIT_FAVOR_SIZE Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) { +Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) { if (ASMJIT_UNLIKELY(!_code)) return DebugUtils::errored(kErrorNotInitialized); -#if !defined(ASMJIT_NO_X86) - if (environment().isFamilyX86()) { - x86::EmitHelper emitHelper(this, frame.isAvxEnabled(), frame.isAvx512Enabled()); - return emitHelper.emitArgsAssignment(frame, args); - } -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment().isArchAArch64()) { - a64::EmitHelper emitHelper(this); - return emitHelper.emitArgsAssignment(frame, args); - } -#endif - - return DebugUtils::errored(kErrorInvalidArch); + return _funcs.emitArgsAssignment(this, frame, args); } // BaseEmitter - Comment diff --git a/src/asmjit/core/emitter.h b/src/asmjit/core/emitter.h index 2aca695..b8afd6b 100644 --- a/src/asmjit/core/emitter.h +++ b/src/asmjit/core/emitter.h @@ -8,6 +8,7 @@ #include "../core/archtraits.h" #include "../core/codeholder.h" +#include "../core/formatter.h" #include "../core/inst.h" #include "../core/operand.h" #include "../core/type.h" @@ -209,6 +210,9 @@ public: //! Validation options. DiagnosticOptions _diagnosticOptions = DiagnosticOptions::kNone; + //! All supported architectures in a bit-mask, where LSB is the bit with a zero index. + uint64_t _archMask = 0; + //! Encoding options. EncodingOptions _encodingOptions = EncodingOptions::kNone; @@ -236,6 +240,45 @@ public: //! Inline comment of the next instruction (affects the next instruction). const char* _inlineComment = nullptr; + //! Function callbacks used by emitter implementation. + //! + //! These are typically shared between Assembler/Builder/Compiler of a single backend. + struct Funcs { + typedef Error (ASMJIT_CDECL* EmitProlog)(BaseEmitter* emitter, const FuncFrame& frame); + typedef Error (ASMJIT_CDECL* EmitEpilog)(BaseEmitter* emitter, const FuncFrame& frame); + typedef Error (ASMJIT_CDECL* EmitArgsAssignment)(BaseEmitter* emitter, const FuncFrame& frame, const FuncArgsAssignment& args); + + typedef Error (ASMJIT_CDECL* FormatInstruction)( + String& sb, + FormatFlags formatFlags, + const BaseEmitter* emitter, + Arch arch, + const BaseInst& inst, const Operand_* operands, size_t opCount) ASMJIT_NOEXCEPT_TYPE; + + typedef Error (ASMJIT_CDECL* ValidateFunc)(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) ASMJIT_NOEXCEPT_TYPE; + + //! Emit prolog implementation. + EmitProlog emitProlog; + //! Emit epilog implementation. + EmitEpilog emitEpilog; + //! Emit arguments assignment implementation. + EmitArgsAssignment emitArgsAssignment; + //! Instruction formatter implementation. + FormatInstruction formatInstruction; + //! Instruction validation implementation. + ValidateFunc validate; + + //! Resets all functions to nullptr. + inline void reset() noexcept { + emitProlog = nullptr; + emitEpilog = nullptr; + emitArgsAssignment = nullptr; + validate = nullptr; + } + }; + + Funcs _funcs {}; + //! \} //! \name Construction & Destruction diff --git a/src/asmjit/core/emitterutils.cpp b/src/asmjit/core/emitterutils.cpp index ba79787..f36a1b3 100644 --- a/src/asmjit/core/emitterutils.cpp +++ b/src/asmjit/core/emitterutils.cpp @@ -86,7 +86,7 @@ void logInstructionEmitted( opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); sb.appendChars(' ', logger->indentation(FormatIndentationGroup::kCode)); - Formatter::formatInstruction(sb, formatFlags, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); + self->_funcs.formatInstruction(sb, formatFlags, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); if (Support::test(formatFlags, FormatFlags::kMachineCode)) finishFormattedLine(sb, logger->options(), self->bufferPtr(), size_t(emittedSize), relSize, immSize, self->inlineComment()); @@ -109,7 +109,7 @@ Error logInstructionFailed( Operand_ opArray[Globals::kMaxOpCount]; opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - Formatter::formatInstruction(sb, FormatFlags::kNone, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); + self->_funcs.formatInstruction(sb, FormatFlags::kNone, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); if (self->inlineComment()) { sb.append(" ; "); diff --git a/src/asmjit/core/environment.h b/src/asmjit/core/environment.h index 8225ef2..7e328a9 100644 --- a/src/asmjit/core/environment.h +++ b/src/asmjit/core/environment.h @@ -339,8 +339,12 @@ public: //! Tests whether this architecture is of X86 family. inline bool isFamilyX86() const noexcept { return isFamilyX86(_arch); } - //! Tests whether this architecture family is ARM, Thumb, or AArch64. + //! Tests whether this architecture family is ARM, THUMB, or AArch64. inline bool isFamilyARM() const noexcept { return isFamilyARM(_arch); } + //! Tests whether this architecture family is AArch32 (ARM or THUMB). + inline bool isFamilyAArch32() const noexcept { return isFamilyAArch32(_arch); } + //! Tests whether this architecture family is AArch64. + inline bool isFamilyAArch64() const noexcept { return isFamilyAArch64(_arch); } //! Tests whether this architecture family is MISP or MIPS64. inline bool isFamilyMIPS() const noexcept { return isFamilyMIPS(_arch); } //! Tests whether this architecture family is RISC-V (both 32-bit and 64-bit). @@ -431,16 +435,16 @@ public: return uint32_t(arch) >= uint32_t(Arch::kBigEndian); } - //! Tests whether the given architecture is ARM or ARM_BE. - static inline bool isArchARM(Arch arch) noexcept { - return arch == Arch::kARM || arch == Arch::kARM_BE; - } - //! Tests whether the given architecture is Thumb or Thumb_BE. static inline bool isArchThumb(Arch arch) noexcept { return arch == Arch::kThumb || arch == Arch::kThumb_BE; } + //! Tests whether the given architecture is ARM or ARM_BE. + static inline bool isArchARM(Arch arch) noexcept { + return arch == Arch::kARM || arch == Arch::kARM_BE; + } + //! Tests whether the given architecture is AArch64 or AArch64_BE. static inline bool isArchAArch64(Arch arch) noexcept { return arch == Arch::kAArch64 || arch == Arch::kAArch64_BE; @@ -461,11 +465,21 @@ public: return arch == Arch::kX86 || arch == Arch::kX64; } - //! Tests whether the given architecture family is ARM, Thumb, or AArch64. + //! Tests whether the given architecture family is ARM, THUMB, or AArch64. static inline bool isFamilyARM(Arch arch) noexcept { return isArchARM(arch) || isArchAArch64(arch) || isArchThumb(arch); } + //! Tests whether the given architecture family is AArch32 (ARM or THUMB). + static inline bool isFamilyAArch32(Arch arch) noexcept { + return isArchARM(arch) || isArchThumb(arch); + } + + //! Tests whether the given architecture family is AArch64. + static inline bool isFamilyAArch64(Arch arch) noexcept { + return isArchAArch64(arch); + } + //! Tests whether the given architecture family is MISP or MIPS64. static inline bool isFamilyMIPS(Arch arch) noexcept { return isArchMIPS32(arch) || isArchMIPS64(arch); diff --git a/src/asmjit/core/formatter.cpp b/src/asmjit/core/formatter.cpp index efa0c47..1c4b7b6 100644 --- a/src/asmjit/core/formatter.cpp +++ b/src/asmjit/core/formatter.cpp @@ -20,8 +20,8 @@ #include "../x86/x86formatter_p.h" #endif -#ifdef ASMJIT_BUILD_ARM - #include "../arm/armformatter_p.h" +#if !defined(ASMJIT_NO_AARCH64) + #include "../arm/a64formatter_p.h" #endif ASMJIT_BEGIN_NAMESPACE @@ -107,7 +107,7 @@ Error formatFeature( return x86::FormatterInternal::formatFeature(sb, featureId); #endif -#ifdef ASMJIT_BUILD_ARM +#if !defined(ASMJIT_NO_AARCH32) && !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyARM(arch)) return arm::FormatterInternal::formatFeature(sb, featureId); #endif @@ -164,9 +164,9 @@ Error formatRegister( return x86::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); #endif -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); +#if !defined(ASMJIT_NO_AARCH64) + if (Environment::isFamilyAArch64(arch)) + return a64::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); #endif return kErrorInvalidArch; @@ -184,9 +184,9 @@ Error formatOperand( return x86::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); #endif -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); +#if !defined(ASMJIT_NO_AARCH64) + if (Environment::isFamilyAArch64(arch)) + return a64::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); #endif return kErrorInvalidArch; @@ -282,9 +282,9 @@ Error formatInstruction( return x86::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount); #endif -#ifdef ASMJIT_BUILD_ARM +#if !defined(ASMJIT_NO_AARCH64) if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount); + return a64::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount); #endif return kErrorInvalidArch; @@ -408,7 +408,7 @@ Error formatNode( case NodeType::kInst: case NodeType::kJump: { const InstNode* instNode = node->as<InstNode>(); - ASMJIT_PROPAGATE(formatInstruction(sb, formatOptions.flags(), builder, + ASMJIT_PROPAGATE(builder->_funcs.formatInstruction(sb, formatOptions.flags(), builder, builder->arch(), instNode->baseInst(), instNode->operands(), instNode->opCount())); break; @@ -525,7 +525,7 @@ Error formatNode( case NodeType::kInvoke: { const InvokeNode* invokeNode = node->as<InvokeNode>(); - ASMJIT_PROPAGATE(formatInstruction(sb, formatOptions.flags(), builder, + ASMJIT_PROPAGATE(builder->_funcs.formatInstruction(sb, formatOptions.flags(), builder, builder->arch(), invokeNode->baseInst(), invokeNode->operands(), invokeNode->opCount())); break; diff --git a/src/asmjit/core/func.cpp b/src/asmjit/core/func.cpp index fcc962c..04dc2aa 100644 --- a/src/asmjit/core/func.cpp +++ b/src/asmjit/core/func.cpp @@ -14,8 +14,8 @@ #include "../x86/x86func_p.h" #endif -#ifdef ASMJIT_BUILD_ARM - #include "../arm/armfunc_p.h" +#if !defined(ASMJIT_NO_AARCH64) + #include "../arm/a64func_p.h" #endif ASMJIT_BEGIN_NAMESPACE @@ -31,9 +31,9 @@ ASMJIT_FAVOR_SIZE Error CallConv::init(CallConvId ccId, const Environment& envir return x86::FuncInternal::initCallConv(*this, ccId, environment); #endif -#ifdef ASMJIT_BUILD_ARM - if (environment.isFamilyARM()) - return arm::FuncInternal::initCallConv(*this, ccId, environment); +#if !defined(ASMJIT_NO_AARCH64) + if (environment.isFamilyAArch64()) + return a64::FuncInternal::initCallConv(*this, ccId, environment); #endif return DebugUtils::errored(kErrorInvalidArgument); @@ -73,9 +73,9 @@ ASMJIT_FAVOR_SIZE Error FuncDetail::init(const FuncSignature& signature, const E return x86::FuncInternal::initFuncDetail(*this, signature, registerSize); #endif -#ifdef ASMJIT_BUILD_ARM - if (environment.isFamilyARM()) - return arm::FuncInternal::initFuncDetail(*this, signature, registerSize); +#if !defined(ASMJIT_NO_AARCH64) + if (environment.isFamilyAArch64()) + return a64::FuncInternal::initFuncDetail(*this, signature, registerSize); #endif // We should never bubble here as if `cc.init()` succeeded then there has to be an implementation for the current diff --git a/src/asmjit/core/inst.cpp b/src/asmjit/core/inst.cpp index 26f1df9..8f29d8b 100644 --- a/src/asmjit/core/inst.cpp +++ b/src/asmjit/core/inst.cpp @@ -11,7 +11,7 @@ #include "../x86/x86instapi_p.h" #endif -#ifdef ASMJIT_BUILD_ARM +#if !defined(ASMJIT_NO_AARCH64) #include "../arm/a64instapi_p.h" #endif @@ -27,8 +27,8 @@ Error InstAPI::instIdToString(Arch arch, InstId instId, String& output) noexcept return x86::InstInternal::instIdToString(arch, instId, output); #endif -#ifdef ASMJIT_BUILD_ARM - if (Environment::isArchAArch64(arch)) +#if !defined(ASMJIT_NO_AARCH64) + if (Environment::isFamilyAArch64(arch)) return a64::InstInternal::instIdToString(arch, instId, output); #endif @@ -41,8 +41,8 @@ InstId InstAPI::stringToInstId(Arch arch, const char* s, size_t len) noexcept { return x86::InstInternal::stringToInstId(arch, s, len); #endif -#ifdef ASMJIT_BUILD_ARM - if (Environment::isArchAArch64(arch)) +#if !defined(ASMJIT_NO_AARCH64) + if (Environment::isFamilyAArch64(arch)) return a64::InstInternal::stringToInstId(arch, s, len); #endif @@ -60,8 +60,8 @@ Error InstAPI::validate(Arch arch, const BaseInst& inst, const Operand_* operand return x86::InstInternal::validate(arch, inst, operands, opCount, validationFlags); #endif -#ifdef ASMJIT_BUILD_ARM - if (Environment::isArchAArch64(arch)) +#if !defined(ASMJIT_NO_AARCH64) + if (Environment::isFamilyAArch64(arch)) return a64::InstInternal::validate(arch, inst, operands, opCount, validationFlags); #endif @@ -82,8 +82,8 @@ Error InstAPI::queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* oper return x86::InstInternal::queryRWInfo(arch, inst, operands, opCount, out); #endif -#ifdef ASMJIT_BUILD_ARM - if (Environment::isArchAArch64(arch)) +#if !defined(ASMJIT_NO_AARCH64) + if (Environment::isFamilyAArch64(arch)) return a64::InstInternal::queryRWInfo(arch, inst, operands, opCount, out); #endif @@ -101,8 +101,8 @@ Error InstAPI::queryFeatures(Arch arch, const BaseInst& inst, const Operand_* op return x86::InstInternal::queryFeatures(arch, inst, operands, opCount, out); #endif -#ifdef ASMJIT_BUILD_ARM - if (Environment::isArchAArch64(arch)) +#if !defined(ASMJIT_NO_AARCH64) + if (Environment::isFamilyAArch64(arch)) return a64::InstInternal::queryFeatures(arch, inst, operands, opCount, out); #endif diff --git a/src/asmjit/core/inst.h b/src/asmjit/core/inst.h index 0b890d8..2310631 100644 --- a/src/asmjit/core/inst.h +++ b/src/asmjit/core/inst.h @@ -16,17 +16,41 @@ ASMJIT_BEGIN_NAMESPACE //! \addtogroup asmjit_instruction_db //! \{ -//! Describes an instruction. +//! Describes an instruction id and modifiers used together with the id. //! //! Each architecture has a set of valid instructions indexed from 0. Instruction with 0 id is, however, a special -//! instruction that describes an invalid instruction. Different architectures can share the same instruction id, -//! which would describe a different instruction per architecture. +//! instruction that describes a "no instruction" or "invalid instruction". Different architectures can assign a. +//! different instruction to the same id, each architecture typicall has its own instructions indexed from 1. //! //! Instruction identifiers listed by architecture: //! //! - \ref x86::Inst (X86 and X86_64) +//! - \ref a64::Inst (AArch64) typedef uint32_t InstId; +//! Instruction id parts. +//! +//! A mask that specifies a bit-layout of \ref InstId. +enum class InstIdParts : uint32_t { + // Common Masks + // ------------ + + //! Real id without any modifiers (always 16 least significant bits). + kRealId = 0x0000FFFFu, + //! Instruction is abstract (or virtual, IR, etc...). + kAbstract = 0x80000000u, + + // ARM Specific + // ------------ + + //! AArch32 first data type, used by ASIMD instructions (`inst.dt.dt2`). + kA32_DT = 0x000F0000u, + //! AArch32 second data type, used by ASIMD instructions (`inst.dt.dt2`). + kA32_DT2 = 0x00F00000u, + //! AArch32/AArch64 condition code. + kARM_Cond = 0x78000000u +}; + //! Instruction options. //! //! Instruction options complement instruction identifier and attributes. @@ -184,7 +208,7 @@ public: //! \name Members //! \{ - //! Instruction id. + //! Instruction id with modifiers. InstId _id; //! Instruction options. InstOptions _options; @@ -224,16 +248,29 @@ public: //! \} - //! \name Instruction Id + //! \name Instruction id and modifiers //! \{ - //! Returns the instruction id. + //! Returns the instruction id with modifiers. inline InstId id() const noexcept { return _id; } - //! Sets the instruction id to the given `id`. + //! Sets the instruction id and modiiers from `id`. inline void setId(InstId id) noexcept { _id = id; } - //! Resets the instruction id to zero, see \ref kIdNone. + //! Resets the instruction id and modifiers to zero, see \ref kIdNone. inline void resetId() noexcept { _id = 0; } + //! Returns a real instruction id that doesn't contain any modifiers. + inline InstId realId() const noexcept { return _id & uint32_t(InstIdParts::kRealId); } + + template<InstIdParts kPart> + inline uint32_t getInstIdPart() const noexcept { + return (uint32_t(_id) & uint32_t(kPart)) >> Support::ConstCTZ<uint32_t(kPart)>::value; + } + + template<InstIdParts kPart> + inline void setInstIdPart(uint32_t value) noexcept { + _id = (_id & ~uint32_t(kPart)) | (value << Support::ConstCTZ<uint32_t(kPart)>::value); + } + //! \} //! \name Instruction Options @@ -259,6 +296,27 @@ public: inline void resetExtraReg() noexcept { _extraReg.reset(); } //! \} + + //! \name ARM Specific + //! \{ + + inline arm::CondCode armCondCode() const noexcept { return (arm::CondCode)getInstIdPart<InstIdParts::kARM_Cond>(); } + inline void setArmCondCode(arm::CondCode cc) noexcept { setInstIdPart<InstIdParts::kARM_Cond>(uint32_t(cc)); } + + //! \} + + //! \name Statics + //! \{ + + static inline constexpr InstId composeARMInstId(uint32_t id, arm::CondCode cc) noexcept { + return id | (uint32_t(cc) << Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value); + } + + static inline constexpr arm::CondCode extractARMCondCode(uint32_t id) noexcept { + return (arm::CondCode)((uint32_t(id) & uint32_t(InstIdParts::kARM_Cond)) >> Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value); + } + + //! \} }; //! CPU read/write flags used by \ref InstRWInfo. diff --git a/src/asmjit/core/jitruntime.cpp b/src/asmjit/core/jitruntime.cpp index 85fbdc4..491c204 100644 --- a/src/asmjit/core/jitruntime.cpp +++ b/src/asmjit/core/jitruntime.cpp @@ -43,6 +43,8 @@ Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept { // Recalculate the final code size and shrink the memory we allocated for it // in case that some relocations didn't require records in an address table. size_t codeSize = code->codeSize(); + if (codeSize < estimatedCodeSize) + _allocator.shrink(rx, codeSize); if (codeSize < estimatedCodeSize) _allocator.shrink(rx, codeSize); diff --git a/src/asmjit/core/operand.h b/src/asmjit/core/operand.h index 0bf098a..2f81a21 100644 --- a/src/asmjit/core/operand.h +++ b/src/asmjit/core/operand.h @@ -98,6 +98,9 @@ enum class RegType : uint8_t { // X86 Specific Register Types // --------------------------- + // X86 Specific Register Types + // =========================== + //! Instruction pointer (RIP), only addressable in \ref x86::Mem in 64-bit targets. kX86_Rip = kPC, //! Low GPB register (AL, BL, CL, DL, ...). @@ -133,6 +136,26 @@ enum class RegType : uint8_t { //! TMM register (AMX_TILE) kX86_Tmm = kExtra + 6, + // ARM Specific Register Types + // =========================== + + //! Program pointer (PC) register (AArch64). + kARM_PC = kPC, + //! 32-bit general purpose register (R or W). + kARM_GpW = kGp32, + //! 64-bit general purpose register (X). + kARM_GpX = kGp64, + //! 8-bit view of VFP/ASIMD register (B). + kARM_VecB = kVec8, + //! 16-bit view of VFP/ASIMD register (H). + kARM_VecH = kVec16, + //! 32-bit view of VFP/ASIMD register (S). + kARM_VecS = kVec32, + //! 64-bit view of VFP/ASIMD register (D). + kARM_VecD = kVec64, + //! 128-bit view of VFP/ASIMD register (Q|V). + kARM_VecV = kVec128, + //! Maximum value of `RegType`. kMaxValue = 31 }; diff --git a/src/asmjit/core/support.h b/src/asmjit/core/support.h index a9091c3..e55b808 100644 --- a/src/asmjit/core/support.h +++ b/src/asmjit/core/support.h @@ -176,6 +176,12 @@ static constexpr X sar(const X& x, const Y& y) noexcept { return X(S(x) >> y); } +template<typename X, typename Y> +static constexpr X ror(const X& x, const Y& y) noexcept { + typedef typename std::make_unsigned<X>::type U; + return X((U(x) >> y) | (U(x) << (bitSizeOf<U>() - y))); +} + //! Returns `x | (x >> y)` - helper used by some bit manipulation helpers. template<typename X, typename Y> static constexpr X or_shr(const X& x, const Y& y) noexcept { return X(x | shr(x, y)); } @@ -187,7 +193,33 @@ static constexpr T blsi(T x) noexcept { return T(U(x) & neg(U(x))); } -//! Generate a trailing bit-mask that has `n` least significant (trailing) bits set. +//! Tests whether the given value `x` has `n`th bit set. +template<typename T, typename IndexT> +static constexpr bool bitTest(T x, IndexT n) noexcept { + typedef typename std::make_unsigned<T>::type U; + return (U(x) & (U(1) << asStdInt(n))) != 0; +} + +// Tests whether the given `value` is a consecutive mask of bits that starts at +// the least significant bit. +template<typename T> +static inline constexpr bool isLsbMask(const T& value) { + typedef typename std::make_unsigned<T>::type U; + return value && ((U(value) + 1u) & U(value)) == 0; +} + +// Tests whether the given value contains at least one bit or whether it's a +// bit-mask of consecutive bits. +// +// This function is similar to \ref isLsbMask(), but the mask doesn't have to +// start at a least significant bit. +template<typename T> +static inline constexpr bool isConsecutiveMask(const T& value) { + typedef typename std::make_unsigned<T>::type U; + return value && isLsbMask((U(value) - 1u) | U(value)); +} + +//! Generates a trailing bit-mask that has `n` least significant (trailing) bits set. template<typename T, typename CountT> static constexpr T lsbMask(const CountT& n) noexcept { typedef typename std::make_unsigned<T>::type U; @@ -198,11 +230,15 @@ static constexpr T lsbMask(const CountT& n) noexcept { : n ? T(shr(allOnes<T>(), bitSizeOf<T>() - size_t(n))) : T(0); } -//! Tests whether the given value `x` has `n`th bit set. -template<typename T, typename IndexT> -static constexpr bool bitTest(T x, IndexT n) noexcept { +//! Generats a leading bit-mask that has `n` most significant (leading) bits set. +template<typename T, typename CountT> +static constexpr T msbMask(const CountT& n) noexcept { typedef typename std::make_unsigned<T>::type U; - return (U(x) & (U(1) << asUInt(n))) != 0; + return (sizeof(U) < sizeof(uintptr_t)) + // Prevent undefined behavior by using a larger type than T. + ? T(allOnes<uintptr_t>() >> (bitSizeOf<uintptr_t>() - n)) + // Prevent undefined behavior by performing `n & (nBits - 1)` so it's always within the range. + : T(sar(U(n != 0) << (bitSizeOf<U>() - 1), n ? uint32_t(n - 1) : uint32_t(0))); } //! Returns a bit-mask that has `x` bit set. diff --git a/src/asmjit/core/virtmem.cpp b/src/asmjit/core/virtmem.cpp index 8259f9c..43766ef 100644 --- a/src/asmjit/core/virtmem.cpp +++ b/src/asmjit/core/virtmem.cpp @@ -211,6 +211,7 @@ Error releaseDualMapping(DualMapping* dm, size_t size) noexcept { dm->rw = nullptr; return kErrorOk; } + #endif // Virtual Memory [Posix] diff --git a/src/asmjit/core/zonetree.h b/src/asmjit/core/zonetree.h index e1bfdc5..c5dbc78 100644 --- a/src/asmjit/core/zonetree.h +++ b/src/asmjit/core/zonetree.h @@ -364,6 +364,7 @@ public: static inline ZoneTreeNode* _doubleRotate(ZoneTreeNode* ASMJIT_NONNULL(root), size_t dir) noexcept { ZoneTreeNode* child = root->_getChild(!dir); ASMJIT_ASSUME(child != nullptr); + root->_setChild(!dir, _singleRotate(child, !dir)); return _singleRotate(root, dir); } diff --git a/src/asmjit/x86/x86assembler.cpp b/src/asmjit/x86/x86assembler.cpp index 4da28f1..f11fea0 100644 --- a/src/asmjit/x86/x86assembler.cpp +++ b/src/asmjit/x86/x86assembler.cpp @@ -15,6 +15,8 @@ #include "../core/misc_p.h" #include "../core/support.h" #include "../x86/x86assembler.h" +#include "../x86/x86emithelper_p.h" +#include "../x86/x86instapi_p.h" #include "../x86/x86instdb_p.h" #include "../x86/x86formatter_p.h" #include "../x86/x86opcode_p.h" @@ -525,6 +527,10 @@ static ASMJIT_FORCE_INLINE bool x86ShouldUseMovabs(Assembler* self, X86BufferWri // =========================================== Assembler::Assembler(CodeHolder* code) noexcept : BaseAssembler() { + _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) | + (uint64_t(1) << uint32_t(Arch::kX64)) ; + assignEmitterFuncs(this); + if (code) code->attach(this); } @@ -604,7 +610,7 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, con Operand_ opArray[Globals::kMaxOpCount]; EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - err = InstAPI::validate(arch(), BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount); + err = _funcs.validate(arch(), BaseInst(instId, options, _extraReg), opArray, Globals::kMaxOpCount, ValidationFlags::kNone); if (ASMJIT_UNLIKELY(err)) goto Failed; } @@ -4159,7 +4165,7 @@ EmitModSib: re->_sourceSectionId = _section->id(); re->_sourceOffset = offset(); - re->_format.resetToDataValue(4); + re->_format.resetToSimpleValue(OffsetType::kSignedOffset, 4); re->_format.setLeadingAndTrailingSize(writer.offsetFrom(_bufferPtr), immSize); re->_payload = uint64_t(rmRel->as<Mem>().offset()); @@ -4256,7 +4262,7 @@ EmitModSib_LabelRip_X86: re->_sourceSectionId = _section->id(); re->_sourceOffset = offset(); - re->_format.resetToDataValue(4); + re->_format.resetToSimpleValue(OffsetType::kUnsignedOffset, 4); re->_format.setLeadingAndTrailingSize(writer.offsetFrom(_bufferPtr), immSize); re->_payload = uint64_t(int64_t(relOffset)); @@ -4281,7 +4287,7 @@ EmitModSib_LabelRip_X86: re->_sourceSectionId = _section->id(); re->_targetSectionId = _section->id(); - re->_format.resetToDataValue(4); + re->_format.resetToSimpleValue(OffsetType::kUnsignedOffset, 4); re->_format.setLeadingAndTrailingSize(writer.offsetFrom(_bufferPtr), immSize); re->_sourceOffset = offset(); re->_payload = re->_sourceOffset + re->_format.regionSize() + uint64_t(int64_t(relOffset)); @@ -4871,13 +4877,13 @@ EmitJmpCall: writer.emit8If(0x0F, (opcode & Opcode::kMM_Mask) != 0); // Emit 0F prefix. writer.emit8(opcode.v); // Emit opcode. writer.emit8If(x86EncodeMod(3, opReg, 0), opReg != 0); // Emit MOD. - re->_format.resetToDataValue(4); + re->_format.resetToSimpleValue(OffsetType::kSignedOffset, 4); re->_format.setLeadingAndTrailingSize(writer.offsetFrom(_bufferPtr), immSize); writer.emit32uLE(0); // Emit DISP32. } else { writer.emit8(opCode8); // Emit opcode. - re->_format.resetToDataValue(4); + re->_format.resetToSimpleValue(OffsetType::kSignedOffset, 1); re->_format.setLeadingAndTrailingSize(writer.offsetFrom(_bufferPtr), immSize); writer.emit8(0); // Emit DISP8 (zero). } @@ -4919,7 +4925,7 @@ EmitRel: // Chain with label. size_t offset = size_t(writer.offsetFrom(_bufferData)); OffsetFormat of; - of.resetToDataValue(relSize); + of.resetToSimpleValue(OffsetType::kSignedOffset, relSize); LabelLink* link = _code->newLabelLink(label, _section->id(), offset, relOffset, of); if (ASMJIT_UNLIKELY(!link)) @@ -5077,9 +5083,6 @@ Error Assembler::align(AlignMode alignMode, uint32_t alignment) { Error Assembler::onAttach(CodeHolder* code) noexcept { Arch arch = code->arch(); - if (!Environment::isFamilyX86(arch)) - return DebugUtils::errored(kErrorInvalidArch); - ASMJIT_PROPAGATE(Base::onAttach(code)); if (Environment::is32Bit(arch)) { @@ -5099,7 +5102,6 @@ Error Assembler::onAttach(CodeHolder* code) noexcept { Error Assembler::onDetach(CodeHolder* code) noexcept { _forcedInstOptions &= ~InstOptions::kX86_InvalidRex; _setAddressOverrideMask(0); - return Base::onDetach(code); } diff --git a/src/asmjit/x86/x86builder.cpp b/src/asmjit/x86/x86builder.cpp index a1b848d..a27948b 100644 --- a/src/asmjit/x86/x86builder.cpp +++ b/src/asmjit/x86/x86builder.cpp @@ -8,15 +8,37 @@ #include "../x86/x86assembler.h" #include "../x86/x86builder.h" +#include "../x86/x86emithelper_p.h" ASMJIT_BEGIN_SUB_NAMESPACE(x86) +// x86::Builder - Construction & Destruction +// ========================================= + Builder::Builder(CodeHolder* code) noexcept : BaseBuilder() { + _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) | + (uint64_t(1) << uint32_t(Arch::kX64)) ; + assignEmitterFuncs(this); + if (code) code->attach(this); } Builder::~Builder() noexcept {} +// x86::Builder - Events +// ===================== + +Error Builder::onAttach(CodeHolder* code) noexcept { + return Base::onAttach(code); +} + +Error Builder::onDetach(CodeHolder* code) noexcept { + return Base::onDetach(code); +} + +// x86::Builder - Finalize +// ======================= + Error Builder::finalize() { ASMJIT_PROPAGATE(runPasses()); Assembler a(_code); @@ -25,14 +47,6 @@ Error Builder::finalize() { return serializeTo(&a); } -Error Builder::onAttach(CodeHolder* code) noexcept { - Arch arch = code->arch(); - if (!Environment::isFamilyX86(arch)) - return DebugUtils::errored(kErrorInvalidArch); - - return Base::onAttach(code); -} - ASMJIT_END_SUB_NAMESPACE #endif // !ASMJIT_NO_X86 && !ASMJIT_NO_BUILDER diff --git a/src/asmjit/x86/x86builder.h b/src/asmjit/x86/x86builder.h index 31c9783..f3bb11a 100644 --- a/src/asmjit/x86/x86builder.h +++ b/src/asmjit/x86/x86builder.h @@ -327,17 +327,18 @@ public: //! \} - //! \name Finalize + //! \name Events //! \{ - ASMJIT_API Error finalize() override; + ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; + ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; //! \} - //! \name Events + //! \name Finalize //! \{ - ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; + ASMJIT_API Error finalize() override; //! \} }; diff --git a/src/asmjit/x86/x86compiler.cpp b/src/asmjit/x86/x86compiler.cpp index 014ba19..04d0980 100644 --- a/src/asmjit/x86/x86compiler.cpp +++ b/src/asmjit/x86/x86compiler.cpp @@ -8,29 +8,28 @@ #include "../x86/x86assembler.h" #include "../x86/x86compiler.h" +#include "../x86/x86instapi_p.h" #include "../x86/x86rapass_p.h" ASMJIT_BEGIN_SUB_NAMESPACE(x86) +// x86::Compiler - Construction & Destruction +// ========================================== + Compiler::Compiler(CodeHolder* code) noexcept : BaseCompiler() { + _archMask = (uint64_t(1) << uint32_t(Arch::kX86)) | + (uint64_t(1) << uint32_t(Arch::kX64)) ; + assignEmitterFuncs(this); + if (code) code->attach(this); } Compiler::~Compiler() noexcept {} -Error Compiler::finalize() { - ASMJIT_PROPAGATE(runPasses()); - Assembler a(_code); - a.addEncodingOptions(encodingOptions()); - a.addDiagnosticOptions(diagnosticOptions()); - return serializeTo(&a); -} +// x86::Compiler - Events +// ====================== Error Compiler::onAttach(CodeHolder* code) noexcept { - Arch arch = code->arch(); - if (!Environment::isFamilyX86(arch)) - return DebugUtils::errored(kErrorInvalidArch); - ASMJIT_PROPAGATE(Base::onAttach(code)); Error err = addPassT<X86RAPass>(); @@ -42,6 +41,21 @@ Error Compiler::onAttach(CodeHolder* code) noexcept { return kErrorOk; } +Error Compiler::onDetach(CodeHolder* code) noexcept { + return Base::onDetach(code); +} + +// x86::Compiler - Finalize +// ======================== + +Error Compiler::finalize() { + ASMJIT_PROPAGATE(runPasses()); + Assembler a(_code); + a.addEncodingOptions(encodingOptions()); + a.addDiagnosticOptions(diagnosticOptions()); + return serializeTo(&a); +} + ASMJIT_END_SUB_NAMESPACE #endif // !ASMJIT_NO_X86 && !ASMJIT_NO_COMPILER diff --git a/src/asmjit/x86/x86compiler.h b/src/asmjit/x86/x86compiler.h index 466ffa2..d89aea0 100644 --- a/src/asmjit/x86/x86compiler.h +++ b/src/asmjit/x86/x86compiler.h @@ -697,17 +697,18 @@ public: //! \} - //! \name Finalize + //! \name Events //! \{ - ASMJIT_API Error finalize() override; + ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; + ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; //! \} - //! \name Events + //! \name Finalize //! \{ - ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; + ASMJIT_API Error finalize() override; //! \} }; diff --git a/src/asmjit/x86/x86emithelper.cpp b/src/asmjit/x86/x86emithelper.cpp index d2d90c7..cc558e0 100644 --- a/src/asmjit/x86/x86emithelper.cpp +++ b/src/asmjit/x86/x86emithelper.cpp @@ -14,6 +14,8 @@ #include "../core/radefs_p.h" #include "../x86/x86emithelper_p.h" #include "../x86/x86emitter.h" +#include "../x86/x86formatter_p.h" +#include "../x86/x86instapi_p.h" ASMJIT_BEGIN_SUB_NAMESPACE(x86) @@ -583,6 +585,35 @@ ASMJIT_FAVOR_SIZE Error EmitHelper::emitEpilog(const FuncFrame& frame) { return kErrorOk; } +static Error ASMJIT_CDECL Emitter_emitProlog(BaseEmitter* emitter, const FuncFrame& frame) { + EmitHelper emitHelper(emitter, frame.isAvxEnabled(), frame.isAvx512Enabled()); + return emitHelper.emitProlog(frame); +} + +static Error ASMJIT_CDECL Emitter_emitEpilog(BaseEmitter* emitter, const FuncFrame& frame) { + EmitHelper emitHelper(emitter, frame.isAvxEnabled(), frame.isAvx512Enabled()); + return emitHelper.emitEpilog(frame); +} + +static Error ASMJIT_CDECL Emitter_emitArgsAssignment(BaseEmitter* emitter, const FuncFrame& frame, const FuncArgsAssignment& args) { + EmitHelper emitHelper(emitter, frame.isAvxEnabled(), frame.isAvx512Enabled()); + return emitHelper.emitArgsAssignment(frame, args); +} + +void assignEmitterFuncs(BaseEmitter* emitter) { + emitter->_funcs.emitProlog = Emitter_emitProlog; + emitter->_funcs.emitEpilog = Emitter_emitEpilog; + emitter->_funcs.emitArgsAssignment = Emitter_emitArgsAssignment; + +#ifndef ASMJIT_NO_LOGGING + emitter->_funcs.formatInstruction = FormatterInternal::formatInstruction; +#endif + +#ifndef ASMJIT_NO_VALIDATION + emitter->_funcs.validate = InstInternal::validate; +#endif +} + ASMJIT_END_SUB_NAMESPACE #endif // !ASMJIT_NO_X86 diff --git a/src/asmjit/x86/x86emithelper_p.h b/src/asmjit/x86/x86emithelper_p.h index 98d16da..e71d9af 100644 --- a/src/asmjit/x86/x86emithelper_p.h +++ b/src/asmjit/x86/x86emithelper_p.h @@ -50,6 +50,8 @@ public: Error emitEpilog(const FuncFrame& frame); }; +void assignEmitterFuncs(BaseEmitter* emitter); + //! \} //! \endcond diff --git a/src/asmjit/x86/x86formatter.cpp b/src/asmjit/x86/x86formatter.cpp index b667019..d62dd18 100644 --- a/src/asmjit/x86/x86formatter.cpp +++ b/src/asmjit/x86/x86formatter.cpp @@ -10,6 +10,7 @@ #include "../core/misc_p.h" #include "../core/support.h" #include "../x86/x86formatter_p.h" +#include "../x86/x86instapi_p.h" #include "../x86/x86instdb_p.h" #include "../x86/x86operand.h" @@ -880,7 +881,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( } } - ASMJIT_PROPAGATE(InstAPI::instIdToString(arch, instId, sb)); + ASMJIT_PROPAGATE(InstInternal::instIdToString(arch, instId, sb)); } else { ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId))); diff --git a/src/asmjit/x86/x86formatter_p.h b/src/asmjit/x86/x86formatter_p.h index 1dbdb68..f37a8f6 100644 --- a/src/asmjit/x86/x86formatter_p.h +++ b/src/asmjit/x86/x86formatter_p.h @@ -21,11 +21,11 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) namespace FormatterInternal { -Error formatFeature( +Error ASMJIT_CDECL formatFeature( String& sb, uint32_t featureId) noexcept; -Error formatRegister( +Error ASMJIT_CDECL formatRegister( String& sb, FormatFlags flags, const BaseEmitter* emitter, @@ -33,14 +33,14 @@ Error formatRegister( RegType regType, uint32_t regId) noexcept; -Error formatOperand( +Error ASMJIT_CDECL formatOperand( String& sb, FormatFlags flags, const BaseEmitter* emitter, Arch arch, const Operand_& op) noexcept; -Error formatInstruction( +Error ASMJIT_CDECL formatInstruction( String& sb, FormatFlags flags, const BaseEmitter* emitter, diff --git a/src/asmjit/x86/x86instapi_p.h b/src/asmjit/x86/x86instapi_p.h index 0a4b10a..56f7fb9 100644 --- a/src/asmjit/x86/x86instapi_p.h +++ b/src/asmjit/x86/x86instapi_p.h @@ -18,17 +18,17 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) namespace InstInternal { #ifndef ASMJIT_NO_TEXT -Error instIdToString(Arch arch, InstId instId, String& output) noexcept; -InstId stringToInstId(Arch arch, const char* s, size_t len) noexcept; +Error ASMJIT_CDECL instIdToString(Arch arch, InstId instId, String& output) noexcept; +InstId ASMJIT_CDECL stringToInstId(Arch arch, const char* s, size_t len) noexcept; #endif // !ASMJIT_NO_TEXT #ifndef ASMJIT_NO_VALIDATION -Error validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; +Error ASMJIT_CDECL validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags) noexcept; #endif // !ASMJIT_NO_VALIDATION #ifndef ASMJIT_NO_INTROSPECTION -Error queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; -Error queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept; +Error ASMJIT_CDECL queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; +Error ASMJIT_CDECL queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept; #endif // !ASMJIT_NO_INTROSPECTION } // {InstInternal} diff --git a/test/asmjit_test_assembler.cpp b/test/asmjit_test_assembler.cpp index bcb16ad..4b40a75 100644 --- a/test/asmjit_test_assembler.cpp +++ b/test/asmjit_test_assembler.cpp @@ -18,6 +18,10 @@ bool testX86Assembler(const TestSettings& settings) noexcept; bool testX64Assembler(const TestSettings& settings) noexcept; #endif +#if !defined(ASMJIT_NO_AARCH64) +bool testA64Assembler(const TestSettings& settings) noexcept; +#endif + int main(int argc, char* argv[]) { CmdLine cmdLine(argc, argv); @@ -43,6 +47,7 @@ int main(int argc, char* argv[]) { const char* arch = cmdLine.valueOf("--arch", "all"); bool x86Failed = false; bool x64Failed = false; + bool aarch64Failed = false; #if !defined(ASMJIT_NO_X86) if ((strcmp(arch, "all") == 0 || strcmp(arch, "x86") == 0)) @@ -52,11 +57,23 @@ int main(int argc, char* argv[]) { x64Failed = !testX64Assembler(settings); #endif - bool failed = x86Failed || x64Failed; +#if !defined(ASMJIT_NO_AARCH64) + if ((strcmp(arch, "all") == 0 || strcmp(arch, "aarch64") == 0)) + aarch64Failed = !testA64Assembler(settings); +#endif + + bool failed = x86Failed || x64Failed || aarch64Failed; if (failed) { - if (x86Failed) printf("** X86 test suite failed **\n"); - if (x64Failed) printf("** X64 test suite failed **\n"); + if (x86Failed) + printf("** X86 test suite failed **\n"); + + if (x64Failed) + printf("** X64 test suite failed **\n"); + + if (aarch64Failed) + printf("** AArch64 test suite failed **\n"); + printf("** FAILURE **\n"); } else { diff --git a/test/asmjit_test_assembler.h b/test/asmjit_test_assembler.h index 0e98c26..61d774b 100644 --- a/test/asmjit_test_assembler.h +++ b/test/asmjit_test_assembler.h @@ -20,6 +20,7 @@ public: asmjit::Environment env {}; asmjit::CodeHolder code {}; AssemblerType assembler {}; + asmjit::Label L0 {}; const TestSettings& settings; size_t passed {}; @@ -45,6 +46,7 @@ public: code.reset(); code.init(env, 0); code.attach(&assembler); + L0 = assembler.newLabel(); if (settings.validate) assembler.addDiagnosticOptions(asmjit::DiagnosticOptions::kValidateAssembler); diff --git a/test/asmjit_test_assembler_a64.cpp b/test/asmjit_test_assembler_a64.cpp new file mode 100644 index 0000000..a1d1178 --- /dev/null +++ b/test/asmjit_test_assembler_a64.cpp @@ -0,0 +1,4006 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include <asmjit/core.h> +#if !defined(ASMJIT_NO_AARCH64) + +#include <asmjit/a64.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "asmjit_test_assembler.h" +#include "cmdline.h" + +using namespace asmjit; + +#define TEST_INSTRUCTION(OPCODE, ...) \ + tester.testInstruction(OPCODE, #__VA_ARGS__, tester.assembler.__VA_ARGS__) + +static void ASMJIT_NOINLINE testA64AssemblerBase(AssemblerTester<a64::Assembler>& tester) noexcept { + using namespace a64; + + TEST_INSTRUCTION("4100031A", adc(w1, w2, w3)); + TEST_INSTRUCTION("4100039A", adc(x1, x2, x3)); + TEST_INSTRUCTION("E103031A", adc(w1, wzr, w3)); + TEST_INSTRUCTION("E103039A", adc(x1, xzr, x3)); + TEST_INSTRUCTION("5F00031A", adc(wzr, w2, w3)); + TEST_INSTRUCTION("5F00039A", adc(xzr, x2, x3)); + TEST_INSTRUCTION("4100033A", adcs(w1, w2, w3)); + TEST_INSTRUCTION("410003BA", adcs(x1, x2, x3)); + TEST_INSTRUCTION("4100030B", add(w1, w2, w3)); + TEST_INSTRUCTION("4100038B", add(x1, x2, x3)); + TEST_INSTRUCTION("410C030B", add(w1, w2, w3, lsl(3))); + TEST_INSTRUCTION("410C038B", add(x1, x2, x3, lsl(3))); + TEST_INSTRUCTION("FF030411", add(wsp, wsp, 256)); + TEST_INSTRUCTION("FFFF3F11", add(wsp, wsp, 0xFFF)); + TEST_INSTRUCTION("FF030491", add(sp, sp, 256)); + TEST_INSTRUCTION("FFFF3F91", add(sp, sp, 0xFFF)); + TEST_INSTRUCTION("E103030B", add(w1, wzr, w3)); + TEST_INSTRUCTION("E103038B", add(x1, xzr, x3)); + TEST_INSTRUCTION("5F00030B", add(wzr, w2, w3)); + TEST_INSTRUCTION("5F00038B", add(xzr, x2, x3)); + TEST_INSTRUCTION("83004011", add(w3, w4, 0, lsl(12))); + TEST_INSTRUCTION("83004091", add(x3, x4, 0, lsl(12))); + TEST_INSTRUCTION("83005011", add(w3, w4, 1024, lsl(12))); + TEST_INSTRUCTION("83005091", add(x3, x4, 1024, lsl(12))); + TEST_INSTRUCTION("83005011", add(w3, w4, 1024, lsl(12))); + TEST_INSTRUCTION("83005091", add(x3, x4, 1024, lsl(12))); + TEST_INSTRUCTION("FF830091", add(sp, sp, 32)); + TEST_INSTRUCTION("412C8291", addg(x1, x2, 32, 11)); + TEST_INSTRUCTION("5F2C8291", addg(sp, x2, 32, 11)); + TEST_INSTRUCTION("E12F8291", addg(x1, sp, 32, 11)); + TEST_INSTRUCTION("4100032B", adds(w1, w2, w3)); + TEST_INSTRUCTION("410003AB", adds(x1, x2, x3)); + TEST_INSTRUCTION("01000010", adr(x1, 0)); + TEST_INSTRUCTION("01080010", adr(x1, 256)); + TEST_INSTRUCTION("010000B0", adrp(x1, 4096)); + TEST_INSTRUCTION("4100030A", and_(w1, w2, w3)); + TEST_INSTRUCTION("4100038A", and_(x1, x2, x3)); + TEST_INSTRUCTION("41000012", and_(w1, w2, 1)); + TEST_INSTRUCTION("41004092", and_(x1, x2, 1)); + TEST_INSTRUCTION("410C0012", and_(w1, w2, 15)); + TEST_INSTRUCTION("410C4092", and_(x1, x2, 15)); + TEST_INSTRUCTION("3F1C0012", and_(wsp, w1, 0xFF)); + TEST_INSTRUCTION("3F1C4092", and_(sp, x1, 0xFF)); + TEST_INSTRUCTION("E103030A", and_(w1, wzr, w3)); + TEST_INSTRUCTION("E103038A", and_(x1, xzr, x3)); + TEST_INSTRUCTION("5F00030A", and_(wzr, w2, w3)); + TEST_INSTRUCTION("5F00038A", and_(xzr, x2, x3)); + TEST_INSTRUCTION("00000012", and_(w0, w0, 0x1)); + TEST_INSTRUCTION("00004092", and_(x0, x0, 0x1)); + TEST_INSTRUCTION("410C0012", and_(w1, w2, 0xf)); + TEST_INSTRUCTION("410C4092", and_(x1, x2, 0xf)); + TEST_INSTRUCTION("BFEC7C92", and_(sp, x5, 0xfffffffffffffff0)); + TEST_INSTRUCTION("4100036A", ands(w1, w2, w3)); + TEST_INSTRUCTION("410003EA", ands(x1, x2, x3)); + TEST_INSTRUCTION("E103036A", ands(w1, wzr, w3)); + TEST_INSTRUCTION("E10303EA", ands(x1, xzr, x3)); + TEST_INSTRUCTION("5F00036A", ands(wzr, w2, w3)); + TEST_INSTRUCTION("5F0003EA", ands(xzr, x2, x3)); + TEST_INSTRUCTION("00000072", ands(w0, w0, 0x1)); + TEST_INSTRUCTION("000040F2", ands(x0, x0, 0x1)); + TEST_INSTRUCTION("410C0072", ands(w1, w2, 0xf)); + TEST_INSTRUCTION("410C40F2", ands(x1, x2, 0xf)); + TEST_INSTRUCTION("417C0F13", asr(w1, w2, 15)); + TEST_INSTRUCTION("41FC4F93", asr(x1, x2, 15)); + TEST_INSTRUCTION("4128C31A", asrv(w1, w2, w3)); + TEST_INSTRUCTION("4128C39A", asrv(x1, x2, x3)); + TEST_INSTRUCTION("4F7808D5", at(Predicate::AT::kS1E0R, x15)); + TEST_INSTRUCTION("4118C1DA", autda(x1, x2)); + TEST_INSTRUCTION("E11BC1DA", autda(x1, sp)); + TEST_INSTRUCTION("411CC1DA", autdb(x1, x2)); + TEST_INSTRUCTION("E11FC1DA", autdb(x1, sp)); + TEST_INSTRUCTION("E13BC1DA", autdza(x1)); + TEST_INSTRUCTION("F43BC1DA", autdza(x20)); + TEST_INSTRUCTION("E13FC1DA", autdzb(x1)); + TEST_INSTRUCTION("F43FC1DA", autdzb(x20)); + TEST_INSTRUCTION("4110C1DA", autia(x1, x2)); + TEST_INSTRUCTION("E113C1DA", autia(x1, sp)); + TEST_INSTRUCTION("9F2103D5", autia1716()); + TEST_INSTRUCTION("BF2303D5", autiasp()); + TEST_INSTRUCTION("9F2303D5", autiaz()); + TEST_INSTRUCTION("4114C1DA", autib(x1, x2)); + TEST_INSTRUCTION("E117C1DA", autib(x1, sp)); + TEST_INSTRUCTION("DF2103D5", autib1716()); + TEST_INSTRUCTION("FF2303D5", autibsp()); + TEST_INSTRUCTION("DF2303D5", autibz()); + TEST_INSTRUCTION("E133C1DA", autiza(x1)); + TEST_INSTRUCTION("F433C1DA", autiza(x20)); + TEST_INSTRUCTION("E137C1DA", autizb(x1)); + TEST_INSTRUCTION("F437C1DA", autizb(x20)); + TEST_INSTRUCTION("5F4000D5", axflag()); + TEST_INSTRUCTION("E13F1833", bfc(w1, 8, 16)); + TEST_INSTRUCTION("E13F78B3", bfc(x1, 8, 16)); + TEST_INSTRUCTION("413C1833", bfi(w1, w2, 8, 16)); + TEST_INSTRUCTION("413C78B3", bfi(x1, x2, 8, 16)); + TEST_INSTRUCTION("41400833", bfm(w1, w2, 8, 16)); + TEST_INSTRUCTION("414048B3", bfm(x1, x2, 8, 16)); + TEST_INSTRUCTION("415C0833", bfxil(w1, w2, 8, 16)); + TEST_INSTRUCTION("415C48B3", bfxil(x1, x2, 8, 16)); + TEST_INSTRUCTION("41781F12", bic(w1, w2, 1)); + TEST_INSTRUCTION("41F87F92", bic(x1, x2, 1)); + TEST_INSTRUCTION("416C1C12", bic(w1, w2, 15)); + TEST_INSTRUCTION("41EC7C92", bic(x1, x2, 15)); + TEST_INSTRUCTION("4110230A", bic(w1, w2, w3, lsl(4))); + TEST_INSTRUCTION("4110238A", bic(x1, x2, x3, lsl(4))); + TEST_INSTRUCTION("E103230A", bic(w1, wzr, w3)); + TEST_INSTRUCTION("E103238A", bic(x1, xzr, x3)); + TEST_INSTRUCTION("41781F72", bics(w1, w2, 1)); + TEST_INSTRUCTION("41F87FF2", bics(x1, x2, 1)); + TEST_INSTRUCTION("416C1C72", bics(w1, w2, 15)); + TEST_INSTRUCTION("41EC7CF2", bics(x1, x2, 15)); + TEST_INSTRUCTION("4110236A", bics(w1, w2, w3, lsl(4))); + TEST_INSTRUCTION("411023EA", bics(x1, x2, x3, lsl(4))); + TEST_INSTRUCTION("E103236A", bics(w1, wzr, w3)); + TEST_INSTRUCTION("E10323EA", bics(x1, xzr, x3)); + TEST_INSTRUCTION("60031FD6", br(x27)); + TEST_INSTRUCTION("E0031FD6", br(xzr)); + TEST_INSTRUCTION("200020D4", brk(1)); + TEST_INSTRUCTION("627CA188", cas(w1, w2, ptr(x3))); + TEST_INSTRUCTION("627CA1C8", cas(x1, x2, ptr(x3))); + TEST_INSTRUCTION("627CE188", casa(w1, w2, ptr(x3))); + TEST_INSTRUCTION("627CE1C8", casa(x1, x2, ptr(x3))); + TEST_INSTRUCTION("627CE108", casab(w1, w2, ptr(x3))); + TEST_INSTRUCTION("627CE148", casah(w1, w2, ptr(x3))); + TEST_INSTRUCTION("62FCE188", casal(w1, w2, ptr(x3))); + TEST_INSTRUCTION("62FCE1C8", casal(x1, x2, ptr(x3))); + TEST_INSTRUCTION("62FCE108", casalb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("62FCE148", casalh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("627CA108", casb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("627CA148", cash(w1, w2, ptr(x3))); + TEST_INSTRUCTION("62FCA188", casl(w1, w2, ptr(x3))); + TEST_INSTRUCTION("62FCA1C8", casl(x1, x2, ptr(x3))); + TEST_INSTRUCTION("62FCA108", caslb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("62FCA148", caslh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("687C2208", casp(w2, w3, w8, w9, ptr(x3))); + TEST_INSTRUCTION("687C2248", casp(x2, x3, x8, x9, ptr(x3))); + TEST_INSTRUCTION("687C6208", caspa(w2, w3, w8, w9, ptr(x3))); + TEST_INSTRUCTION("687C6248", caspa(x2, x3, x8, x9, ptr(x3))); + TEST_INSTRUCTION("68FC6208", caspal(w2, w3, w8, w9, ptr(x3))); + TEST_INSTRUCTION("68FC6248", caspal(x2, x3, x8, x9, ptr(x3))); + TEST_INSTRUCTION("68FC2208", caspl(w2, w3, w8, w9, ptr(x3))); + TEST_INSTRUCTION("68FC2248", caspl(x2, x3, x8, x9, ptr(x3))); + TEST_INSTRUCTION("2300423A", ccmn(w1, w2, 3, CondCode::kEQ)); + TEST_INSTRUCTION("230042BA", ccmn(x1, x2, 3, CondCode::kEQ)); + TEST_INSTRUCTION("2308423A", ccmn(w1, 2, 3, CondCode::kEQ)); + TEST_INSTRUCTION("230842BA", ccmn(x1, 2, 3, CondCode::kEQ)); + TEST_INSTRUCTION("23005F3A", ccmn(w1, wzr, 3, CondCode::kEQ)); + TEST_INSTRUCTION("23005FBA", ccmn(x1, xzr, 3, CondCode::kEQ)); + TEST_INSTRUCTION("2300427A", ccmp(w1, w2, 3, CondCode::kEQ)); + TEST_INSTRUCTION("230042FA", ccmp(x1, x2, 3, CondCode::kEQ)); + TEST_INSTRUCTION("2308427A", ccmp(w1, 2, 3, CondCode::kEQ)); + TEST_INSTRUCTION("230842FA", ccmp(x1, 2, 3, CondCode::kEQ)); + TEST_INSTRUCTION("23005F7A", ccmp(w1, wzr, 3, CondCode::kEQ)); + TEST_INSTRUCTION("23005FFA", ccmp(x1, xzr, 3, CondCode::kEQ)); + TEST_INSTRUCTION("1F4000D5", cfinv()); + TEST_INSTRUCTION("4114821A", cinc(w1, w2, CondCode::kEQ)); + TEST_INSTRUCTION("4114829A", cinc(x1, x2, CondCode::kEQ)); + TEST_INSTRUCTION("5F14821A", cinc(wzr, w2, CondCode::kEQ)); + TEST_INSTRUCTION("E1179F1A", cinc(w1, wzr, CondCode::kEQ)); + TEST_INSTRUCTION("5F14829A", cinc(xzr, x2, CondCode::kEQ)); + TEST_INSTRUCTION("E1179F9A", cinc(x1, xzr, CondCode::kEQ)); + TEST_INSTRUCTION("4110825A", cinv(w1, w2, CondCode::kEQ)); + TEST_INSTRUCTION("411082DA", cinv(x1, x2, CondCode::kEQ)); + TEST_INSTRUCTION("5F10825A", cinv(wzr, w2, CondCode::kEQ)); + TEST_INSTRUCTION("E1139F5A", cinv(w1, wzr, CondCode::kEQ)); + TEST_INSTRUCTION("5F1082DA", cinv(xzr, x2, CondCode::kEQ)); + TEST_INSTRUCTION("E1139FDA", cinv(x1, xzr, CondCode::kEQ)); + TEST_INSTRUCTION("5F3B03D5", clrex(11)); + TEST_INSTRUCTION("4114C05A", cls(w1, w2)); + TEST_INSTRUCTION("4114C0DA", cls(x1, x2)); + TEST_INSTRUCTION("E117C05A", cls(w1, wzr)); + TEST_INSTRUCTION("E117C0DA", cls(x1, xzr)); + TEST_INSTRUCTION("5F14C05A", cls(wzr, w2)); + TEST_INSTRUCTION("5F14C0DA", cls(xzr, x2)); + TEST_INSTRUCTION("4110C05A", clz(w1, w2)); + TEST_INSTRUCTION("4110C0DA", clz(x1, x2)); + TEST_INSTRUCTION("E113C05A", clz(w1, wzr)); + TEST_INSTRUCTION("E113C0DA", clz(x1, xzr)); + TEST_INSTRUCTION("5F10C05A", clz(wzr, w2)); + TEST_INSTRUCTION("5F10C0DA", clz(xzr, x2)); + TEST_INSTRUCTION("3F840031", cmn(w1, 33)); + TEST_INSTRUCTION("3FFC4331", cmn(w1, 0xFF000)); + TEST_INSTRUCTION("FF030231", cmn(wsp, 128)); + TEST_INSTRUCTION("3F8400B1", cmn(x1, 33)); + TEST_INSTRUCTION("3FFC43B1", cmn(x1, 0xFF000)); + TEST_INSTRUCTION("FF0302B1", cmn(sp, 128)); + TEST_INSTRUCTION("3F00022B", cmn(w1, w2)); + TEST_INSTRUCTION("3F0002AB", cmn(x1, x2)); + TEST_INSTRUCTION("3F08222B", cmn(w1, w2, uxtb(2))); + TEST_INSTRUCTION("3F0822AB", cmn(x1, x2, uxtb(2))); + TEST_INSTRUCTION("FF43212B", cmn(wsp, w1)); + TEST_INSTRUCTION("FF07212B", cmn(wsp, w1, uxtb(1))); + TEST_INSTRUCTION("FF6321AB", cmn(sp, x1)); + TEST_INSTRUCTION("FF6721AB", cmn(sp, x1, uxtx(1))); + TEST_INSTRUCTION("3F840071", cmp(w1, 33)); + TEST_INSTRUCTION("3FFC4371", cmp(w1, 0xFF000)); + TEST_INSTRUCTION("FF030271", cmp(wsp, 128)); + TEST_INSTRUCTION("3F8400F1", cmp(x1, 33)); + TEST_INSTRUCTION("3FFC43F1", cmp(x1, 0xFF000)); + TEST_INSTRUCTION("FF0302F1", cmp(sp, 128)); + TEST_INSTRUCTION("3F00026B", cmp(w1, w2)); + TEST_INSTRUCTION("3F0002EB", cmp(x1, x2)); + TEST_INSTRUCTION("3F08226B", cmp(w1, w2, uxtb(2))); + TEST_INSTRUCTION("3F0822EB", cmp(x1, x2, uxtb(2))); + TEST_INSTRUCTION("FF43216B", cmp(wsp, w1)); + TEST_INSTRUCTION("FF07216B", cmp(wsp, w1, uxtb(1))); + TEST_INSTRUCTION("FF6321EB", cmp(sp, x1)); + TEST_INSTRUCTION("FF6721EB", cmp(sp, x1, uxtx(1))); + TEST_INSTRUCTION("3F00C2BA", cmpp(x1, x2)); + TEST_INSTRUCTION("3F00DFBA", cmpp(x1, sp)); + TEST_INSTRUCTION("FF03C2BA", cmpp(sp, x2)); + TEST_INSTRUCTION("FF03DFBA", cmpp(sp, sp)); + TEST_INSTRUCTION("4140C31A", crc32b(w1, w2, w3)); + TEST_INSTRUCTION("5F40C31A", crc32b(wzr, w2, w3)); + TEST_INSTRUCTION("E143C31A", crc32b(w1, wzr, w3)); + TEST_INSTRUCTION("4140DF1A", crc32b(w1, w2, wzr)); + TEST_INSTRUCTION("4150C31A", crc32cb(w1, w2, w3)); + TEST_INSTRUCTION("5F50C31A", crc32cb(wzr, w2, w3)); + TEST_INSTRUCTION("E153C31A", crc32cb(w1, wzr, w3)); + TEST_INSTRUCTION("4150DF1A", crc32cb(w1, w2, wzr)); + TEST_INSTRUCTION("4154C31A", crc32ch(w1, w2, w3)); + TEST_INSTRUCTION("5F54C31A", crc32ch(wzr, w2, w3)); + TEST_INSTRUCTION("E157C31A", crc32ch(w1, wzr, w3)); + TEST_INSTRUCTION("4154DF1A", crc32ch(w1, w2, wzr)); + TEST_INSTRUCTION("4158C31A", crc32cw(w1, w2, w3)); + TEST_INSTRUCTION("5F58C31A", crc32cw(wzr, w2, w3)); + TEST_INSTRUCTION("E15BC31A", crc32cw(w1, wzr, w3)); + TEST_INSTRUCTION("4158DF1A", crc32cw(w1, w2, wzr)); + TEST_INSTRUCTION("415CC39A", crc32cx(w1, w2, x3)); + TEST_INSTRUCTION("5F5CC39A", crc32cx(wzr, w2, x3)); + TEST_INSTRUCTION("E15FC39A", crc32cx(w1, wzr, x3)); + TEST_INSTRUCTION("415CDF9A", crc32cx(w1, w2, xzr)); + TEST_INSTRUCTION("4144C31A", crc32h(w1, w2, w3)); + TEST_INSTRUCTION("5F44C31A", crc32h(wzr, w2, w3)); + TEST_INSTRUCTION("E147C31A", crc32h(w1, wzr, w3)); + TEST_INSTRUCTION("4144DF1A", crc32h(w1, w2, wzr)); + TEST_INSTRUCTION("4148C31A", crc32w(w1, w2, w3)); + TEST_INSTRUCTION("5F48C31A", crc32w(wzr, w2, w3)); + TEST_INSTRUCTION("E14BC31A", crc32w(w1, wzr, w3)); + TEST_INSTRUCTION("4148DF1A", crc32w(w1, w2, wzr)); + TEST_INSTRUCTION("414CC39A", crc32x(w1, w2, x3)); + TEST_INSTRUCTION("5F4CC39A", crc32x(wzr, w2, x3)); + TEST_INSTRUCTION("E14FC39A", crc32x(w1, wzr, x3)); + TEST_INSTRUCTION("414CDF9A", crc32x(w1, w2, xzr)); + TEST_INSTRUCTION("9F2203D5", csdb()); + TEST_INSTRUCTION("4100831A", csel(w1, w2, w3, CondCode::kEQ)); + TEST_INSTRUCTION("4100839A", csel(x1, x2, x3, CondCode::kEQ)); + TEST_INSTRUCTION("E1179F1A", cset(w1, CondCode::kEQ)); + TEST_INSTRUCTION("E1179F9A", cset(x1, CondCode::kEQ)); + TEST_INSTRUCTION("E1179F1A", cset(w1, CondCode::kEQ)); + TEST_INSTRUCTION("E1179F9A", cset(x1, CondCode::kEQ)); + TEST_INSTRUCTION("E1139F5A", csetm(w1, CondCode::kEQ)); + TEST_INSTRUCTION("E1139FDA", csetm(x1, CondCode::kEQ)); + TEST_INSTRUCTION("4104831A", csinc(w1, w2, w3, CondCode::kEQ)); + TEST_INSTRUCTION("4104839A", csinc(x1, x2, x3, CondCode::kEQ)); + TEST_INSTRUCTION("4100835A", csinv(w1, w2, w3, CondCode::kEQ)); + TEST_INSTRUCTION("410083DA", csinv(x1, x2, x3, CondCode::kEQ)); + TEST_INSTRUCTION("4104835A", csneg(w1, w2, w3, CondCode::kEQ)); + TEST_INSTRUCTION("410483DA", csneg(x1, x2, x3, CondCode::kEQ)); + TEST_INSTRUCTION("2F740BD5", dc(Predicate::DC::kZVA, x15)); + TEST_INSTRUCTION("2100B0D4", dcps1(0x8001)); + TEST_INSTRUCTION("2200B0D4", dcps2(0x8001)); + TEST_INSTRUCTION("2300B0D4", dcps3(0x8001)); + TEST_INSTRUCTION("DF2003D5", dgh()); + TEST_INSTRUCTION("BF3103D5", dmb(1)); + TEST_INSTRUCTION("E003BFD6", drps()); + TEST_INSTRUCTION("9F3103D5", dsb(1)); + TEST_INSTRUCTION("4100234A", eon(w1, w2, w3)); + TEST_INSTRUCTION("5F00234A", eon(wzr, w2, w3)); + TEST_INSTRUCTION("E103234A", eon(w1, wzr, w3)); + TEST_INSTRUCTION("41003F4A", eon(w1, w2, wzr)); + TEST_INSTRUCTION("4110234A", eon(w1, w2, w3, lsl(4))); + TEST_INSTRUCTION("410023CA", eon(x1, x2, x3)); + TEST_INSTRUCTION("5F0023CA", eon(xzr, x2, x3)); + TEST_INSTRUCTION("E10323CA", eon(x1, xzr, x3)); + TEST_INSTRUCTION("41003FCA", eon(x1, x2, xzr)); + TEST_INSTRUCTION("411023CA", eon(x1, x2, x3, lsl(4))); + TEST_INSTRUCTION("4100034A", eor(w1, w2, w3)); + TEST_INSTRUCTION("5F00034A", eor(wzr, w2, w3)); + TEST_INSTRUCTION("E103034A", eor(w1, wzr, w3)); + TEST_INSTRUCTION("41001F4A", eor(w1, w2, wzr)); + TEST_INSTRUCTION("410003CA", eor(x1, x2, x3)); + TEST_INSTRUCTION("5F0003CA", eor(xzr, x2, x3)); + TEST_INSTRUCTION("E10303CA", eor(x1, xzr, x3)); + TEST_INSTRUCTION("41001FCA", eor(x1, x2, xzr)); + TEST_INSTRUCTION("4110034A", eor(w1, w2, w3, lsl(4))); + TEST_INSTRUCTION("411003CA", eor(x1, x2, x3, lsl(4))); + TEST_INSTRUCTION("3F1C0052", eor(wsp, w1, 0xFF)); + TEST_INSTRUCTION("FF1F0052", eor(wsp, wzr, 0xFF)); + TEST_INSTRUCTION("3F1C40D2", eor(sp, x1, 0xFF)); + TEST_INSTRUCTION("FF1F40D2", eor(sp, xzr, 0xFF)); + TEST_INSTRUCTION("41001252", eor(w1, w2, 0x4000)); + TEST_INSTRUCTION("410071D2", eor(x1, x2, 0x8000)); + TEST_INSTRUCTION("E0039FD6", eret()); + TEST_INSTRUCTION("1F2203D5", esb()); + TEST_INSTRUCTION("413C8313", extr(w1, w2, w3, 15)); + TEST_INSTRUCTION("5F3C8313", extr(wzr, w2, w3, 15)); + TEST_INSTRUCTION("E13F8313", extr(w1, wzr, w3, 15)); + TEST_INSTRUCTION("413C9F13", extr(w1, w2, wzr, 15)); + TEST_INSTRUCTION("413CC393", extr(x1, x2, x3, 15)); + TEST_INSTRUCTION("5F3CC393", extr(xzr, x2, x3, 15)); + TEST_INSTRUCTION("E13FC393", extr(x1, xzr, x3, 15)); + TEST_INSTRUCTION("413CDF93", extr(x1, x2, xzr, 15)); + TEST_INSTRUCTION("4114C39A", gmi(x1, x2, x3)); + TEST_INSTRUCTION("E117C39A", gmi(x1, sp, x3)); + TEST_INSTRUCTION("200040D4", hlt(1)); + TEST_INSTRUCTION("220000D4", hvc(1)); + TEST_INSTRUCTION("2F750BD5", ic(Predicate::IC::kIVAU, x15)); + TEST_INSTRUCTION("DF3103D5", isb(1)); + TEST_INSTRUCTION("620021B8", ldadd(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E20321B8", ldadd(w1, w2, ptr(sp))); + TEST_INSTRUCTION("620021F8", ldadd(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E20321F8", ldadd(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6200A1B8", ldadda(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E203A1B8", ldadda(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6200A1F8", ldadda(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E203A1F8", ldadda(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6200A138", ldaddab(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E203A138", ldaddab(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6200A178", ldaddah(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E203A178", ldaddah(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6200E1B8", ldaddal(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E203E1B8", ldaddal(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6200E1F8", ldaddal(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E203E1F8", ldaddal(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6200E138", ldaddalb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E203E138", ldaddalb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6200E178", ldaddalh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E203E178", ldaddalh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62002138", ldaddb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2032138", ldaddb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62002178", ldaddh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2032178", ldaddh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("620061B8", ldaddl(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E20361B8", ldaddl(w1, w2, ptr(sp))); + TEST_INSTRUCTION("620061F8", ldaddl(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E20361F8", ldaddl(x1, x2, ptr(sp))); + TEST_INSTRUCTION("62006138", ldaddlb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2036138", ldaddlb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62006178", ldaddlh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2036178", ldaddlh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("621021B8", ldclr(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E21321B8", ldclr(w1, w2, ptr(sp))); + TEST_INSTRUCTION("621021F8", ldclr(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E21321F8", ldclr(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6210A1B8", ldclra(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E213A1B8", ldclra(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6210A1F8", ldclra(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E213A1F8", ldclra(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6210A138", ldclrab(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E213A138", ldclrab(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6210A178", ldclrah(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E213A178", ldclrah(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6210E1B8", ldclral(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E213E1B8", ldclral(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6210E1F8", ldclral(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E213E1F8", ldclral(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6210E138", ldclralb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E213E138", ldclralb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6210E178", ldclralh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E213E178", ldclralh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62102138", ldclrb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2132138", ldclrb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62102178", ldclrh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2132178", ldclrh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("621061B8", ldclrl(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E21361B8", ldclrl(w1, w2, ptr(sp))); + TEST_INSTRUCTION("621061F8", ldclrl(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E21361F8", ldclrl(x1, x2, ptr(sp))); + TEST_INSTRUCTION("62106138", ldclrlb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2136138", ldclrlb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62106178", ldclrlh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2136178", ldclrlh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("622021B8", ldeor(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E22321B8", ldeor(w1, w2, ptr(sp))); + TEST_INSTRUCTION("622021F8", ldeor(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E22321F8", ldeor(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6220A1B8", ldeora(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E223A1B8", ldeora(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6220A1F8", ldeora(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E223A1F8", ldeora(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6220A138", ldeorab(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E223A138", ldeorab(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6220A178", ldeorah(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E223A178", ldeorah(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6220E1B8", ldeoral(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E223E1B8", ldeoral(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6220E1F8", ldeoral(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E223E1F8", ldeoral(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6220E138", ldeoralb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E223E138", ldeoralb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6220E178", ldeoralh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E223E178", ldeoralh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62202138", ldeorb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2232138", ldeorb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62202178", ldeorh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2232178", ldeorh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("622061B8", ldeorl(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E22361B8", ldeorl(w1, w2, ptr(sp))); + TEST_INSTRUCTION("622061F8", ldeorl(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E22361F8", ldeorl(x1, x2, ptr(sp))); + TEST_INSTRUCTION("62206138", ldeorlb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2236138", ldeorlb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62206178", ldeorlh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2236178", ldeorlh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("410060D9", ldg(x1, ptr(x2))); + TEST_INSTRUCTION("418060D9", ldg(x1, ptr(x2, 128))); + TEST_INSTRUCTION("E10360D9", ldg(x1, ptr(sp))); + TEST_INSTRUCTION("E18360D9", ldg(x1, ptr(sp, 128))); + TEST_INSTRUCTION("4100E0D9", ldgm(x1, ptr(x2))); + TEST_INSTRUCTION("E103E0D9", ldgm(x1, ptr(sp))); + TEST_INSTRUCTION("417CDF88", ldlar(w1, ptr(x2))); + TEST_INSTRUCTION("E17FDF88", ldlar(w1, ptr(sp))); + TEST_INSTRUCTION("417CDFC8", ldlar(x1, ptr(x2))); + TEST_INSTRUCTION("E17FDFC8", ldlar(x1, ptr(sp))); + TEST_INSTRUCTION("417CDF08", ldlarb(w1, ptr(x2))); + TEST_INSTRUCTION("E17FDF08", ldlarb(w1, ptr(sp))); + TEST_INSTRUCTION("417CDF48", ldlarh(w1, ptr(x2))); + TEST_INSTRUCTION("E17FDF48", ldlarh(w1, ptr(sp))); + TEST_INSTRUCTION("41084028", ldnp(w1, w2, ptr(x2))); + TEST_INSTRUCTION("41086028", ldnp(w1, w2, ptr(x2, -256))); + TEST_INSTRUCTION("41885F28", ldnp(w1, w2, ptr(x2, 252))); + TEST_INSTRUCTION("410840A8", ldnp(x1, x2, ptr(x2))); + TEST_INSTRUCTION("410860A8", ldnp(x1, x2, ptr(x2, -512))); + TEST_INSTRUCTION("41885FA8", ldnp(x1, x2, ptr(x2, 504))); + TEST_INSTRUCTION("41084029", ldp(w1, w2, ptr(x2))); + TEST_INSTRUCTION("41086029", ldp(w1, w2, ptr(x2, -256))); + TEST_INSTRUCTION("41885F29", ldp(w1, w2, ptr(x2, 252))); + TEST_INSTRUCTION("410840A9", ldp(x1, x2, ptr(x2))); + TEST_INSTRUCTION("410860A9", ldp(x1, x2, ptr(x2, -512))); + TEST_INSTRUCTION("41885FA9", ldp(x1, x2, ptr(x2, 504))); + TEST_INSTRUCTION("41084069", ldpsw(x1, x2, ptr(x2))); + TEST_INSTRUCTION("41086069", ldpsw(x1, x2, ptr(x2, -256))); + TEST_INSTRUCTION("41885F69", ldpsw(x1, x2, ptr(x2, 252))); + TEST_INSTRUCTION("410040B9", ldr(w1, ptr(x2))); + TEST_INSTRUCTION("413040B9", ldr(w1, ptr(x2, 48))); + TEST_INSTRUCTION("410C43B8", ldr(w1, ptr_pre(x2, 48))); + TEST_INSTRUCTION("416863B8", ldr(w1, ptr(x2, x3))); + TEST_INSTRUCTION("410040F9", ldr(x1, ptr(x2))); + TEST_INSTRUCTION("411840F9", ldr(x1, ptr(x2, 48))); + TEST_INSTRUCTION("410C43F8", ldr(x1, ptr_pre(x2, 48))); + TEST_INSTRUCTION("416863F8", ldr(x1, ptr(x2, x3))); + TEST_INSTRUCTION("FB0F5FF8", ldr(x27, ptr_pre(sp, -16))); + TEST_INSTRUCTION("FB0741F8", ldr(x27, ptr_post(sp, 16))); + TEST_INSTRUCTION("411040B8", ldr(w1, ptr(x2, 1))); // LDUR + TEST_INSTRUCTION("41D05FB8", ldr(w1, ptr(x2, -3))); // LDUR + TEST_INSTRUCTION("41705FB8", ldr(w1, ptr(x2, -9))); // LDUR + TEST_INSTRUCTION("411040F8", ldr(x1, ptr(x2, 1))); // LDUR + TEST_INSTRUCTION("413040F8", ldr(x1, ptr(x2, 3))); // LDUR + TEST_INSTRUCTION("41705FF8", ldr(x1, ptr(x2, -9))); // LDUR + TEST_INSTRUCTION("41004039", ldrb(w1, ptr(x2))); + TEST_INSTRUCTION("41C04039", ldrb(w1, ptr(x2, 48))); + TEST_INSTRUCTION("410C4338", ldrb(w1, ptr_pre(x2, 48))); + TEST_INSTRUCTION("41686338", ldrb(w1, ptr(x2, x3))); + TEST_INSTRUCTION("41044039", ldrb(w1, ptr(x2, 1))); + TEST_INSTRUCTION("41D05F38", ldrb(w1, ptr(x2, -3))); // LDURB + TEST_INSTRUCTION("41705F38", ldrb(w1, ptr(x2, -9))); // LDURB + TEST_INSTRUCTION("41004079", ldrh(w1, ptr(x2))); + TEST_INSTRUCTION("41604079", ldrh(w1, ptr(x2, 48))); + TEST_INSTRUCTION("410C4378", ldrh(w1, ptr_pre(x2, 48))); + TEST_INSTRUCTION("41686378", ldrh(w1, ptr(x2, x3))); + TEST_INSTRUCTION("41104078", ldrh(w1, ptr(x2, 1))); // LDURH + TEST_INSTRUCTION("41D05F78", ldrh(w1, ptr(x2, -3))); // LDURH + TEST_INSTRUCTION("41705F78", ldrh(w1, ptr(x2, -9))); // LDURH + TEST_INSTRUCTION("4104C039", ldrsb(w1, ptr(x2, 1))); + TEST_INSTRUCTION("41D0DF38", ldrsb(w1, ptr(x2, -3))); // LDURSB + TEST_INSTRUCTION("4170DF38", ldrsb(w1, ptr(x2, -9))); // LDURSB + TEST_INSTRUCTION("41048039", ldrsb(x1, ptr(x2, 1))); + TEST_INSTRUCTION("41D09F38", ldrsb(x1, ptr(x2, -3))); // LDURSB + TEST_INSTRUCTION("41709F38", ldrsb(x1, ptr(x2, -9))); // LDURSB + TEST_INSTRUCTION("4110C078", ldrsh(w1, ptr(x2, 1))); // LDURSH + TEST_INSTRUCTION("41D0DF78", ldrsh(w1, ptr(x2, -3))); // LDURSH + TEST_INSTRUCTION("4170DF78", ldrsh(w1, ptr(x2, -9))); // LDURSH + TEST_INSTRUCTION("41108078", ldrsh(x1, ptr(x2, 1))); // LDURSH + TEST_INSTRUCTION("41D09F78", ldrsh(x1, ptr(x2, -3))); // LDURSH + TEST_INSTRUCTION("41709F78", ldrsh(x1, ptr(x2, -9))); // LDURSH + TEST_INSTRUCTION("410080B9", ldrsw(x1, ptr(x2))); + TEST_INSTRUCTION("413080B9", ldrsw(x1, ptr(x2, 48))); + TEST_INSTRUCTION("410C83B8", ldrsw(x1, ptr_pre(x2, 48))); + TEST_INSTRUCTION("410483B8", ldrsw(x1, ptr_post(x2, 48))); + TEST_INSTRUCTION("4168A3B8", ldrsw(x1, ptr(x2, x3))); + TEST_INSTRUCTION("411080B8", ldrsw(x1, ptr(x2, 1))); // LDURSW + TEST_INSTRUCTION("413080B8", ldrsw(x1, ptr(x2, 3))); // LDURSW + TEST_INSTRUCTION("41709FB8", ldrsw(x1, ptr(x2, -9))); // LDURSW + TEST_INSTRUCTION("410420F8", ldraa(x1, ptr(x2))); + TEST_INSTRUCTION("410460F8", ldraa(x1, ptr(x2, -4096))); + TEST_INSTRUCTION("410C60F8", ldraa(x1, ptr_pre(x2, -4096))); + TEST_INSTRUCTION("41FC3FF8", ldraa(x1, ptr_pre(x2, 4088))); + TEST_INSTRUCTION("E10720F8", ldraa(x1, ptr(sp))); + TEST_INSTRUCTION("E10760F8", ldraa(x1, ptr(sp, -4096))); + TEST_INSTRUCTION("E10F60F8", ldraa(x1, ptr_pre(sp, -4096))); + TEST_INSTRUCTION("E1FF3FF8", ldraa(x1, ptr_pre(sp, 4088))); + TEST_INSTRUCTION("4104A0F8", ldrab(x1, ptr(x2))); + TEST_INSTRUCTION("4104E0F8", ldrab(x1, ptr(x2, -4096))); + TEST_INSTRUCTION("410CE0F8", ldrab(x1, ptr_pre(x2, -4096))); + TEST_INSTRUCTION("41FCBFF8", ldrab(x1, ptr_pre(x2, 4088))); + TEST_INSTRUCTION("E107A0F8", ldrab(x1, ptr(sp))); + TEST_INSTRUCTION("E107E0F8", ldrab(x1, ptr(sp, -4096))); + TEST_INSTRUCTION("E10FE0F8", ldrab(x1, ptr_pre(sp, -4096))); + TEST_INSTRUCTION("E1FFBFF8", ldrab(x1, ptr_pre(sp, 4088))); + TEST_INSTRUCTION("60DBA0B8", ldrsw(x0, ptr(x27, w0, sxtw(2)))); + TEST_INSTRUCTION("623021B8", ldset(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E23321B8", ldset(w1, w2, ptr(sp))); + TEST_INSTRUCTION("623021F8", ldset(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E23321F8", ldset(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6230A1B8", ldseta(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E233A1B8", ldseta(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6230A1F8", ldseta(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E233A1F8", ldseta(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6230A138", ldsetab(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E233A138", ldsetab(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6230A178", ldsetah(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E233A178", ldsetah(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6230E1B8", ldsetal(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E233E1B8", ldsetal(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6230E1F8", ldsetal(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E233E1F8", ldsetal(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6230E178", ldsetalh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E233E178", ldsetalh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6230E138", ldsetalb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E233E138", ldsetalb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62302138", ldsetb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2332138", ldsetb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62302178", ldseth(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2332178", ldseth(w1, w2, ptr(sp))); + TEST_INSTRUCTION("623061B8", ldsetl(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E23361B8", ldsetl(w1, w2, ptr(sp))); + TEST_INSTRUCTION("623061F8", ldsetl(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E23361F8", ldsetl(x1, x2, ptr(sp))); + TEST_INSTRUCTION("62306138", ldsetlb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2336138", ldsetlb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62306178", ldsetlh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2336178", ldsetlh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("624021B8", ldsmax(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E24321B8", ldsmax(w1, w2, ptr(sp))); + TEST_INSTRUCTION("624021F8", ldsmax(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E24321F8", ldsmax(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6240A1B8", ldsmaxa(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E243A1B8", ldsmaxa(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6240A1F8", ldsmaxa(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E243A1F8", ldsmaxa(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6240A138", ldsmaxab(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E243A138", ldsmaxab(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6240A178", ldsmaxah(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E243A178", ldsmaxah(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6240E1B8", ldsmaxal(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E243E1B8", ldsmaxal(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6240E1F8", ldsmaxal(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E243E1F8", ldsmaxal(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6240E138", ldsmaxalb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E243E138", ldsmaxalb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6240E178", ldsmaxalh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E243E178", ldsmaxalh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62402138", ldsmaxb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2432138", ldsmaxb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62402178", ldsmaxh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2432178", ldsmaxh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("624061B8", ldsmaxl(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E24361B8", ldsmaxl(w1, w2, ptr(sp))); + TEST_INSTRUCTION("624061F8", ldsmaxl(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E24361F8", ldsmaxl(x1, x2, ptr(sp))); + TEST_INSTRUCTION("62406138", ldsmaxlb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2436138", ldsmaxlb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62406178", ldsmaxlh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2436178", ldsmaxlh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("625021B8", ldsmin(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E25321B8", ldsmin(w1, w2, ptr(sp))); + TEST_INSTRUCTION("625021F8", ldsmin(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E25321F8", ldsmin(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6250A1B8", ldsmina(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E253A1B8", ldsmina(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6250A1F8", ldsmina(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E253A1F8", ldsmina(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6250A138", ldsminab(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E253A138", ldsminab(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6250A178", ldsminah(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E253A178", ldsminah(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6250E1B8", ldsminal(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E253E1B8", ldsminal(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6250E1F8", ldsminal(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E253E1F8", ldsminal(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6250E138", ldsminalb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E253E138", ldsminalb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6250E178", ldsminalh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E253E178", ldsminalh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62502138", ldsminb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2532138", ldsminb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62502178", ldsminh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2532178", ldsminh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("625061B8", ldsminl(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E25361B8", ldsminl(w1, w2, ptr(sp))); + TEST_INSTRUCTION("625061F8", ldsminl(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E25361F8", ldsminl(x1, x2, ptr(sp))); + TEST_INSTRUCTION("62506138", ldsminlb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2536138", ldsminlb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62506178", ldsminlh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2536178", ldsminlh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("410840B8", ldtr(w1, ptr(x2))); + TEST_INSTRUCTION("411848B8", ldtr(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E10B40B8", ldtr(w1, ptr(sp))); + TEST_INSTRUCTION("E11B48B8", ldtr(w1, ptr(sp, 129))); + TEST_INSTRUCTION("410840F8", ldtr(x1, ptr(x2))); + TEST_INSTRUCTION("411848F8", ldtr(x1, ptr(x2, 129))); + TEST_INSTRUCTION("E10B40F8", ldtr(x1, ptr(sp))); + TEST_INSTRUCTION("E11B48F8", ldtr(x1, ptr(sp, 129))); + TEST_INSTRUCTION("41084038", ldtrb(w1, ptr(x2))); + TEST_INSTRUCTION("41184838", ldtrb(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E10B4038", ldtrb(w1, ptr(sp))); + TEST_INSTRUCTION("E11B4838", ldtrb(w1, ptr(sp, 129))); + TEST_INSTRUCTION("41084078", ldtrh(w1, ptr(x2))); + TEST_INSTRUCTION("41184878", ldtrh(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E10B4078", ldtrh(w1, ptr(sp))); + TEST_INSTRUCTION("E11B4878", ldtrh(w1, ptr(sp, 129))); + TEST_INSTRUCTION("4108C038", ldtrsb(w1, ptr(x2))); + TEST_INSTRUCTION("4118C838", ldtrsb(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E10BC038", ldtrsb(w1, ptr(sp))); + TEST_INSTRUCTION("E11BC838", ldtrsb(w1, ptr(sp, 129))); + TEST_INSTRUCTION("4108C078", ldtrsh(w1, ptr(x2))); + TEST_INSTRUCTION("4118C878", ldtrsh(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E10BC078", ldtrsh(w1, ptr(sp))); + TEST_INSTRUCTION("E11BC878", ldtrsh(w1, ptr(sp, 129))); + TEST_INSTRUCTION("410880B8", ldtrsw(x1, ptr(x2))); + TEST_INSTRUCTION("411888B8", ldtrsw(x1, ptr(x2, 129))); + TEST_INSTRUCTION("E10B80B8", ldtrsw(x1, ptr(sp))); + TEST_INSTRUCTION("E11B88B8", ldtrsw(x1, ptr(sp, 129))); + TEST_INSTRUCTION("626021B8", ldumax(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E26321B8", ldumax(w1, w2, ptr(sp))); + TEST_INSTRUCTION("626021F8", ldumax(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E26321F8", ldumax(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6260A1B8", ldumaxa(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E263A1B8", ldumaxa(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6260A1F8", ldumaxa(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E263A1F8", ldumaxa(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6260A138", ldumaxab(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E263A138", ldumaxab(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6260A178", ldumaxah(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E263A178", ldumaxah(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6260E1B8", ldumaxal(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E263E1B8", ldumaxal(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6260E1F8", ldumaxal(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E263E1F8", ldumaxal(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6260E138", ldumaxalb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E263E138", ldumaxalb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6260E178", ldumaxalh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E263E178", ldumaxalh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62602138", ldumaxb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2632138", ldumaxb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62602178", ldumaxh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2632178", ldumaxh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("626061B8", ldumaxl(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E26361B8", ldumaxl(w1, w2, ptr(sp))); + TEST_INSTRUCTION("626061F8", ldumaxl(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E26361F8", ldumaxl(x1, x2, ptr(sp))); + TEST_INSTRUCTION("62606138", ldumaxlb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2636138", ldumaxlb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62606178", ldumaxlh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2636178", ldumaxlh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("627021B8", ldumin(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E27321B8", ldumin(w1, w2, ptr(sp))); + TEST_INSTRUCTION("627021F8", ldumin(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E27321F8", ldumin(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6270A1B8", ldumina(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E273A1B8", ldumina(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6270A1F8", ldumina(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E273A1F8", ldumina(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6270A138", lduminab(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E273A138", lduminab(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6270A178", lduminah(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E273A178", lduminah(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6270E1B8", lduminal(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E273E1B8", lduminal(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6270E1F8", lduminal(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E273E1F8", lduminal(x1, x2, ptr(sp))); + TEST_INSTRUCTION("6270E138", lduminalb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E273E138", lduminalb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("6270E178", lduminalh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E273E178", lduminalh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62702138", lduminb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2732138", lduminb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62702178", lduminh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2732178", lduminh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("627061B8", lduminl(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E27361B8", lduminl(w1, w2, ptr(sp))); + TEST_INSTRUCTION("627061F8", lduminl(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E27361F8", lduminl(x1, x2, ptr(sp))); + TEST_INSTRUCTION("62706138", lduminlb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2736138", lduminlb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("62706178", lduminlh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E2736178", lduminlh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("410040B8", ldur(w1, ptr(x2))); + TEST_INSTRUCTION("411048B8", ldur(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E10340B8", ldur(w1, ptr(sp))); + TEST_INSTRUCTION("E11348B8", ldur(w1, ptr(sp, 129))); + TEST_INSTRUCTION("410040F8", ldur(x1, ptr(x2))); + TEST_INSTRUCTION("411048F8", ldur(x1, ptr(x2, 129))); + TEST_INSTRUCTION("E10340F8", ldur(x1, ptr(sp))); + TEST_INSTRUCTION("E11348F8", ldur(x1, ptr(sp, 129))); + TEST_INSTRUCTION("41004038", ldurb(w1, ptr(x2))); + TEST_INSTRUCTION("41104838", ldurb(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E1034038", ldurb(w1, ptr(sp))); + TEST_INSTRUCTION("E1134838", ldurb(w1, ptr(sp, 129))); + TEST_INSTRUCTION("41004078", ldurh(w1, ptr(x2))); + TEST_INSTRUCTION("41104878", ldurh(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E1034078", ldurh(w1, ptr(sp))); + TEST_INSTRUCTION("E1134878", ldurh(w1, ptr(sp, 129))); + TEST_INSTRUCTION("4100C038", ldursb(w1, ptr(x2))); + TEST_INSTRUCTION("4110C838", ldursb(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E103C038", ldursb(w1, ptr(sp))); + TEST_INSTRUCTION("E113C838", ldursb(w1, ptr(sp, 129))); + TEST_INSTRUCTION("4100C078", ldursh(w1, ptr(x2))); + TEST_INSTRUCTION("4110C878", ldursh(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E103C078", ldursh(w1, ptr(sp))); + TEST_INSTRUCTION("E113C878", ldursh(w1, ptr(sp, 129))); + TEST_INSTRUCTION("410080B8", ldursw(x1, ptr(x2))); + TEST_INSTRUCTION("411088B8", ldursw(x1, ptr(x2, 129))); + TEST_INSTRUCTION("E10380B8", ldursw(x1, ptr(sp))); + TEST_INSTRUCTION("E11388B8", ldursw(x1, ptr(sp, 129))); + TEST_INSTRUCTION("61087F88", ldxp(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E10B7F88", ldxp(w1, w2, ptr(sp))); + TEST_INSTRUCTION("61087FC8", ldxp(x1, x2, ptr(x3))); + TEST_INSTRUCTION("E10B7FC8", ldxp(x1, x2, ptr(sp))); + TEST_INSTRUCTION("417C5F88", ldxr(w1, ptr(x2))); + TEST_INSTRUCTION("E17F5F88", ldxr(w1, ptr(sp))); + TEST_INSTRUCTION("417C5FC8", ldxr(x1, ptr(x2))); + TEST_INSTRUCTION("E17F5FC8", ldxr(x1, ptr(sp))); + TEST_INSTRUCTION("417C5F08", ldxrb(w1, ptr(x2))); + TEST_INSTRUCTION("E17F5F08", ldxrb(w1, ptr(sp))); + TEST_INSTRUCTION("417C5F48", ldxrh(w1, ptr(x2))); + TEST_INSTRUCTION("E17F5F48", ldxrh(w1, ptr(sp))); + TEST_INSTRUCTION("4120C31A", lsl(w1, w2, w3)); + TEST_INSTRUCTION("4120C39A", lsl(x1, x2, x3)); + TEST_INSTRUCTION("41401153", lsl(w1, w2, 15)); + TEST_INSTRUCTION("41C071D3", lsl(x1, x2, 15)); + TEST_INSTRUCTION("4120C31A", lslv(w1, w2, w3)); + TEST_INSTRUCTION("4120C39A", lslv(x1, x2, x3)); + TEST_INSTRUCTION("4124C31A", lsr(w1, w2, w3)); + TEST_INSTRUCTION("4124C39A", lsr(x1, x2, x3)); + TEST_INSTRUCTION("417C0F53", lsr(w1, w2, 15)); + TEST_INSTRUCTION("41FC4FD3", lsr(x1, x2, 15)); + TEST_INSTRUCTION("4124C31A", lsrv(w1, w2, w3)); + TEST_INSTRUCTION("4124C39A", lsrv(x1, x2, x3)); + TEST_INSTRUCTION("4110031B", madd(w1, w2, w3, w4)); + TEST_INSTRUCTION("4110039B", madd(x1, x2, x3, x4)); + TEST_INSTRUCTION("41FC031B", mneg(w1, w2, w3)); + TEST_INSTRUCTION("41FC039B", mneg(x1, x2, x3)); + TEST_INSTRUCTION("E103022A", mov(w1, w2)); + TEST_INSTRUCTION("E10302AA", mov(x1, x2)); + TEST_INSTRUCTION("01008052", mov(w1, 0)); + TEST_INSTRUCTION("01008012", mov(w1, -1)); + TEST_INSTRUCTION("21008052", mov(w1, 1)); + TEST_INSTRUCTION("41008052", mov(w1, 2)); + TEST_INSTRUCTION("61008052", mov(w1, 3)); + TEST_INSTRUCTION("81008052", mov(w1, 4)); + TEST_INSTRUCTION("A1008052", mov(w1, 5)); + TEST_INSTRUCTION("C1008052", mov(w1, 6)); + TEST_INSTRUCTION("E1008052", mov(w1, 7)); + TEST_INSTRUCTION("01018052", mov(w1, 8)); + TEST_INSTRUCTION("21018052", mov(w1, 9)); + TEST_INSTRUCTION("41018052", mov(w1, 10)); + TEST_INSTRUCTION("8146A252", mov(w1, 0x12340000)); + TEST_INSTRUCTION("81468252", mov(w1, 0x00001234)); + TEST_INSTRUCTION("61B9BD12", mov(w1, 0x1234FFFF)); + TEST_INSTRUCTION("61B99D12", mov(w1, 0xFFFF1234)); + TEST_INSTRUCTION("010080D2", mov(x1, 0)); + TEST_INSTRUCTION("01008092", mov(x1, -1)); + TEST_INSTRUCTION("8146E2D2", mov(x1, 0x1234000000000000)); + TEST_INSTRUCTION("8146C2D2", mov(x1, 0x0000123400000000)); + TEST_INSTRUCTION("8146A2D2", mov(x1, 0x0000000012340000)); + TEST_INSTRUCTION("814682D2", mov(x1, 0x0000000000001234)); + TEST_INSTRUCTION("61B9FD92", mov(x1, 0x1234FFFFFFFFFFFF)); + TEST_INSTRUCTION("61B9DD92", mov(x1, 0xFFFF1234FFFFFFFF)); + TEST_INSTRUCTION("61B9BD92", mov(x1, 0xFFFFFFFF1234FFFF)); + TEST_INSTRUCTION("61B99D92", mov(x1, 0xFFFFFFFFFFFF1234)); + TEST_INSTRUCTION("E1030011", mov(w1, wsp)); + TEST_INSTRUCTION("E1030091", mov(x1, sp)); + TEST_INSTRUCTION("3F000011", mov(wsp, w1)); + TEST_INSTRUCTION("FF3F0032", mov(wsp, 0xFFFF)); + TEST_INSTRUCTION("3F000091", mov(sp, x1)); + TEST_INSTRUCTION("FF3F40B2", mov(sp, 0xFFFF)); + TEST_INSTRUCTION("FF030011", mov(wsp, wsp)); + TEST_INSTRUCTION("FF030091", mov(sp, sp)); + TEST_INSTRUCTION("015138D5", mrs(x1, Predicate::SysReg::kAFSR0_EL1)); + TEST_INSTRUCTION("01423BD5", mrs(x1, Predicate::SysReg::kNZCV)); + TEST_INSTRUCTION("015118D5", msr(Predicate::SysReg::kAFSR0_EL1, x1)); + TEST_INSTRUCTION("01421BD5", msr(Predicate::SysReg::kNZCV, x1)); + TEST_INSTRUCTION("4190031B", msub(w1, w2, w3, w4)); + TEST_INSTRUCTION("4190039B", msub(x1, x2, x3, x4)); + TEST_INSTRUCTION("417C031B", mul(w1, w2, w3)); + TEST_INSTRUCTION("417C039B", mul(x1, x2, x3)); + TEST_INSTRUCTION("E103222A", mvn(w1, w2)); + TEST_INSTRUCTION("E10322AA", mvn(x1, x2)); + TEST_INSTRUCTION("E113222A", mvn(w1, w2, lsl(4))); + TEST_INSTRUCTION("E11322AA", mvn(x1, x2, lsl(4))); + TEST_INSTRUCTION("E103024B", neg(w1, w2)); + TEST_INSTRUCTION("E10302CB", neg(x1, x2)); + TEST_INSTRUCTION("E113024B", neg(w1, w2, lsl(4))); + TEST_INSTRUCTION("E11302CB", neg(x1, x2, lsl(4))); + TEST_INSTRUCTION("E103026B", negs(w1, w2)); + TEST_INSTRUCTION("E10302EB", negs(x1, x2)); + TEST_INSTRUCTION("E113026B", negs(w1, w2, lsl(4))); + TEST_INSTRUCTION("E11302EB", negs(x1, x2, lsl(4))); + TEST_INSTRUCTION("E103025A", ngc(w1, w2)); + TEST_INSTRUCTION("E10302DA", ngc(x1, x2)); + TEST_INSTRUCTION("E103027A", ngcs(w1, w2)); + TEST_INSTRUCTION("E10302FA", ngcs(x1, x2)); + TEST_INSTRUCTION("4100232A", orn(w1, w2, w3)); + TEST_INSTRUCTION("410023AA", orn(x1, x2, x3)); + TEST_INSTRUCTION("4110232A", orn(w1, w2, w3, lsl(4))); + TEST_INSTRUCTION("411023AA", orn(x1, x2, x3, lsl(4))); + TEST_INSTRUCTION("4100032A", orr(w1, w2, w3)); + TEST_INSTRUCTION("410003AA", orr(x1, x2, x3)); + TEST_INSTRUCTION("4110032A", orr(w1, w2, w3, lsl(4))); + TEST_INSTRUCTION("411003AA", orr(x1, x2, x3, lsl(4))); + TEST_INSTRUCTION("3F1C0032", orr(wsp, w1, 0xFF)); + TEST_INSTRUCTION("3F1C40B2", orr(sp, x1, 0xFF)); + TEST_INSTRUCTION("41001232", orr(w1, w2, 0x4000)); + TEST_INSTRUCTION("410071B2", orr(x1, x2, 0x8000)); + TEST_INSTRUCTION("E8030032", orr(w8, wzr, 0x1)); + TEST_INSTRUCTION("E80340B2", orr(x8, xzr, 0x1)); + TEST_INSTRUCTION("4108C1DA", pacda(x1, x2)); + TEST_INSTRUCTION("E10BC1DA", pacda(x1, sp)); + TEST_INSTRUCTION("410CC1DA", pacdb(x1, x2)); + TEST_INSTRUCTION("E10FC1DA", pacdb(x1, sp)); + TEST_INSTRUCTION("E12BC1DA", pacdza(x1)); + TEST_INSTRUCTION("F42BC1DA", pacdza(x20)); + TEST_INSTRUCTION("E12FC1DA", pacdzb(x1)); + TEST_INSTRUCTION("F42FC1DA", pacdzb(x20)); + TEST_INSTRUCTION("4130C39A", pacga(x1, x2, x3)); + TEST_INSTRUCTION("4130DF9A", pacga(x1, x2, sp)); + TEST_INSTRUCTION("9F3403D5", pssbb()); + TEST_INSTRUCTION("4100C05A", rbit(w1, w2)); + TEST_INSTRUCTION("4100C0DA", rbit(x1, x2)); + TEST_INSTRUCTION("4108C05A", rev(w1, w2)); + TEST_INSTRUCTION("410CC0DA", rev(x1, x2)); + TEST_INSTRUCTION("4104C05A", rev16(w1, w2)); + TEST_INSTRUCTION("4104C0DA", rev16(x1, x2)); + TEST_INSTRUCTION("4108C0DA", rev32(x1, x2)); + TEST_INSTRUCTION("410CC0DA", rev64(x1, x2)); + TEST_INSTRUCTION("412CC31A", ror(w1, w2, w3)); + TEST_INSTRUCTION("412CC39A", ror(x1, x2, x3)); + TEST_INSTRUCTION("413C8213", ror(w1, w2, 15)); + TEST_INSTRUCTION("413CC293", ror(x1, x2, 15)); + TEST_INSTRUCTION("412CC31A", rorv(w1, w2, w3)); + TEST_INSTRUCTION("412CC39A", rorv(x1, x2, x3)); + TEST_INSTRUCTION("4100035A", sbc(w1, w2, w3)); + TEST_INSTRUCTION("410003DA", sbc(x1, x2, x3)); + TEST_INSTRUCTION("4100037A", sbcs(w1, w2, w3)); + TEST_INSTRUCTION("410003FA", sbcs(x1, x2, x3)); + TEST_INSTRUCTION("41241B13", sbfiz(w1, w2, 5, 10)); + TEST_INSTRUCTION("41247B93", sbfiz(x1, x2, 5, 10)); + TEST_INSTRUCTION("41280513", sbfm(w1, w2, 5, 10)); + TEST_INSTRUCTION("41284593", sbfm(x1, x2, 5, 10)); + TEST_INSTRUCTION("41380513", sbfx(w1, w2, 5, 10)); + TEST_INSTRUCTION("41384593", sbfx(x1, x2, 5, 10)); + TEST_INSTRUCTION("410CC31A", sdiv(w1, w2, w3)); + TEST_INSTRUCTION("410CC39A", sdiv(x1, x2, x3)); + TEST_INSTRUCTION("2D08003A", setf8(w1)); + TEST_INSTRUCTION("2D48003A", setf16(w1)); + TEST_INSTRUCTION("4110239B", smaddl(x1, w2, w3, x4)); + TEST_INSTRUCTION("230000D4", smc(1)); + TEST_INSTRUCTION("41FC239B", smnegl(x1, w2, w3)); + TEST_INSTRUCTION("4190239B", smsubl(x1, w2, w3, x4)); + TEST_INSTRUCTION("417C439B", smulh(x1, x2, x3)); + TEST_INSTRUCTION("417C239B", smull(x1, w2, w3)); + TEST_INSTRUCTION("9F3003D5", ssbb()); + TEST_INSTRUCTION("4108A0D9", st2g(x1, ptr(x2))); + TEST_INSTRUCTION("4188A0D9", st2g(x1, ptr(x2, 128))); + TEST_INSTRUCTION("418CA0D9", st2g(x1, ptr_pre(x2, 128))); + TEST_INSTRUCTION("4184A0D9", st2g(x1, ptr_post(x2, 128))); + TEST_INSTRUCTION("E10BA0D9", st2g(x1, ptr(sp))); + TEST_INSTRUCTION("E18BA0D9", st2g(x1, ptr(sp, 128))); + TEST_INSTRUCTION("E18FA0D9", st2g(x1, ptr_pre(sp, 128))); + TEST_INSTRUCTION("E187A0D9", st2g(x1, ptr_post(sp, 128))); + TEST_INSTRUCTION("5F08A0D9", st2g(sp, ptr(x2))); + TEST_INSTRUCTION("5F88A0D9", st2g(sp, ptr(x2, 128))); + TEST_INSTRUCTION("5F8CA0D9", st2g(sp, ptr_pre(x2, 128))); + TEST_INSTRUCTION("5F84A0D9", st2g(sp, ptr_post(x2, 128))); + TEST_INSTRUCTION("FF0BA0D9", st2g(sp, ptr(sp))); + TEST_INSTRUCTION("FF8BA0D9", st2g(sp, ptr(sp, 128))); + TEST_INSTRUCTION("FF8FA0D9", st2g(sp, ptr_pre(sp, 128))); + TEST_INSTRUCTION("FF87A0D9", st2g(sp, ptr_post(sp, 128))); + TEST_INSTRUCTION("410820D9", stg(x1, ptr(x2))); + TEST_INSTRUCTION("418820D9", stg(x1, ptr(x2, 128))); + TEST_INSTRUCTION("418C20D9", stg(x1, ptr_pre(x2, 128))); + TEST_INSTRUCTION("418420D9", stg(x1, ptr_post(x2, 128))); + TEST_INSTRUCTION("E10B20D9", stg(x1, ptr(sp))); + TEST_INSTRUCTION("E18B20D9", stg(x1, ptr(sp, 128))); + TEST_INSTRUCTION("E18F20D9", stg(x1, ptr_pre(sp, 128))); + TEST_INSTRUCTION("E18720D9", stg(x1, ptr_post(sp, 128))); + TEST_INSTRUCTION("5F0820D9", stg(sp, ptr(x2))); + TEST_INSTRUCTION("5F8820D9", stg(sp, ptr(x2, 128))); + TEST_INSTRUCTION("5F8C20D9", stg(sp, ptr_pre(x2, 128))); + TEST_INSTRUCTION("5F8420D9", stg(sp, ptr_post(x2, 128))); + TEST_INSTRUCTION("FF0B20D9", stg(sp, ptr(sp))); + TEST_INSTRUCTION("FF8B20D9", stg(sp, ptr(sp, 128))); + TEST_INSTRUCTION("FF8F20D9", stg(sp, ptr_pre(sp, 128))); + TEST_INSTRUCTION("FF8720D9", stg(sp, ptr_post(sp, 128))); + TEST_INSTRUCTION("4100A0D9", stgm(x1, ptr(x2))); + TEST_INSTRUCTION("E103A0D9", stgm(x1, ptr(sp))); + TEST_INSTRUCTION("FF03A0D9", stgm(xzr, ptr(sp))); + TEST_INSTRUCTION("61080069", stgp(x1, x2, ptr(x3))); + TEST_INSTRUCTION("61082069", stgp(x1, x2, ptr(x3, -1024))); + TEST_INSTRUCTION("6108A069", stgp(x1, x2, ptr_pre(x3, -1024))); + TEST_INSTRUCTION("6108A068", stgp(x1, x2, ptr_post(x3, -1024))); + TEST_INSTRUCTION("61881F69", stgp(x1, x2, ptr(x3, 1008))); + TEST_INSTRUCTION("61889F69", stgp(x1, x2, ptr_pre(x3, 1008))); + TEST_INSTRUCTION("61889F68", stgp(x1, x2, ptr_post(x3, 1008))); + TEST_INSTRUCTION("E10B0069", stgp(x1, x2, ptr(sp))); + TEST_INSTRUCTION("E10B2069", stgp(x1, x2, ptr(sp, -1024))); + TEST_INSTRUCTION("E10BA069", stgp(x1, x2, ptr_pre(sp, -1024))); + TEST_INSTRUCTION("E10BA068", stgp(x1, x2, ptr_post(sp, -1024))); + TEST_INSTRUCTION("E18B1F69", stgp(x1, x2, ptr(sp, 1008))); + TEST_INSTRUCTION("E18B9F69", stgp(x1, x2, ptr_pre(sp, 1008))); + TEST_INSTRUCTION("E18B9F68", stgp(x1, x2, ptr_post(sp, 1008))); + TEST_INSTRUCTION("41080029", stp(w1, w2, ptr(x2))); + TEST_INSTRUCTION("41082029", stp(w1, w2, ptr(x2, -256))); + TEST_INSTRUCTION("41881F29", stp(w1, w2, ptr(x2, 252))); + TEST_INSTRUCTION("410800A9", stp(x1, x2, ptr(x2))); + TEST_INSTRUCTION("410820A9", stp(x1, x2, ptr(x2, -512))); + TEST_INSTRUCTION("41881FA9", stp(x1, x2, ptr(x2, 504))); + TEST_INSTRUCTION("FB0F1FF8", str(x27, ptr_pre(sp, -16))); + TEST_INSTRUCTION("411000B8", str(w1, ptr(x2, 1))); // STUR + TEST_INSTRUCTION("41D01FB8", str(w1, ptr(x2, -3))); // STUR + TEST_INSTRUCTION("41701FB8", str(w1, ptr(x2, -9))); // STUR + TEST_INSTRUCTION("411000F8", str(x1, ptr(x2, 1))); // STUR + TEST_INSTRUCTION("413000F8", str(x1, ptr(x2, 3))); // STUR + TEST_INSTRUCTION("41701FF8", str(x1, ptr(x2, -9))); // STUR + TEST_INSTRUCTION("41040039", strb(w1, ptr(x2, 1))); + TEST_INSTRUCTION("41D01F38", strb(w1, ptr(x2, -3))); // STURB + TEST_INSTRUCTION("41701F38", strb(w1, ptr(x2, -9))); // STURB + TEST_INSTRUCTION("41100078", strh(w1, ptr(x2, 1))); // STURH + TEST_INSTRUCTION("41D01F78", strh(w1, ptr(x2, -3))); // STURH + TEST_INSTRUCTION("41701F78", strh(w1, ptr(x2, -9))); // STURH + TEST_INSTRUCTION("410800B8", sttr(w1, ptr(x2))); + TEST_INSTRUCTION("411808B8", sttr(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E10B00B8", sttr(w1, ptr(sp))); + TEST_INSTRUCTION("E11B08B8", sttr(w1, ptr(sp, 129))); + TEST_INSTRUCTION("410800F8", sttr(x1, ptr(x2))); + TEST_INSTRUCTION("411808F8", sttr(x1, ptr(x2, 129))); + TEST_INSTRUCTION("E10B00F8", sttr(x1, ptr(sp))); + TEST_INSTRUCTION("E11B08F8", sttr(x1, ptr(sp, 129))); + TEST_INSTRUCTION("41080038", sttrb(w1, ptr(x2))); + TEST_INSTRUCTION("41180838", sttrb(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E10B0038", sttrb(w1, ptr(sp))); + TEST_INSTRUCTION("E11B0838", sttrb(w1, ptr(sp, 129))); + TEST_INSTRUCTION("41080078", sttrh(w1, ptr(x2))); + TEST_INSTRUCTION("41180878", sttrh(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E10B0078", sttrh(w1, ptr(sp))); + TEST_INSTRUCTION("E11B0878", sttrh(w1, ptr(sp, 129))); + TEST_INSTRUCTION("410000B8", stur(w1, ptr(x2))); + TEST_INSTRUCTION("411008B8", stur(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E10300B8", stur(w1, ptr(sp))); + TEST_INSTRUCTION("E11308B8", stur(w1, ptr(sp, 129))); + TEST_INSTRUCTION("410000F8", stur(x1, ptr(x2))); + TEST_INSTRUCTION("411008F8", stur(x1, ptr(x2, 129))); + TEST_INSTRUCTION("E10300F8", stur(x1, ptr(sp))); + TEST_INSTRUCTION("E11308F8", stur(x1, ptr(sp, 129))); + TEST_INSTRUCTION("41000038", sturb(w1, ptr(x2))); + TEST_INSTRUCTION("41100838", sturb(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E1030038", sturb(w1, ptr(sp))); + TEST_INSTRUCTION("E1130838", sturb(w1, ptr(sp, 129))); + TEST_INSTRUCTION("41000078", sturh(w1, ptr(x2))); + TEST_INSTRUCTION("41100878", sturh(w1, ptr(x2, 129))); + TEST_INSTRUCTION("E1030078", sturh(w1, ptr(sp))); + TEST_INSTRUCTION("E1130878", sturh(w1, ptr(sp, 129))); + TEST_INSTRUCTION("820C2188", stxp(w1, w2, w3, ptr(x4))); + TEST_INSTRUCTION("E20F2188", stxp(w1, w2, w3, ptr(sp))); + TEST_INSTRUCTION("820C21C8", stxp(w1, x2, x3, ptr(x4))); + TEST_INSTRUCTION("E20F21C8", stxp(w1, x2, x3, ptr(sp))); + TEST_INSTRUCTION("627C0188", stxr(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E27F0188", stxr(w1, w2, ptr(sp))); + TEST_INSTRUCTION("627C01C8", stxr(w1, x2, ptr(x3))); + TEST_INSTRUCTION("E27F01C8", stxr(w1, x2, ptr(sp))); + TEST_INSTRUCTION("627C0108", stxrb(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E27F0108", stxrb(w1, w2, ptr(sp))); + TEST_INSTRUCTION("627C0148", stxrh(w1, w2, ptr(x3))); + TEST_INSTRUCTION("E27F0148", stxrh(w1, w2, ptr(sp))); + TEST_INSTRUCTION("4108E0D9", stz2g(x1, ptr(x2))); + TEST_INSTRUCTION("4108F0D9", stz2g(x1, ptr(x2, -4096))); + TEST_INSTRUCTION("410CF0D9", stz2g(x1, ptr_pre(x2, -4096))); + TEST_INSTRUCTION("4104F0D9", stz2g(x1, ptr_post(x2, -4096))); + TEST_INSTRUCTION("41F8EFD9", stz2g(x1, ptr(x2, 4080))); + TEST_INSTRUCTION("41FCEFD9", stz2g(x1, ptr_pre(x2, 4080))); + TEST_INSTRUCTION("41F4EFD9", stz2g(x1, ptr_post(x2, 4080))); + TEST_INSTRUCTION("E10BE0D9", stz2g(x1, ptr(sp))); + TEST_INSTRUCTION("E10BF0D9", stz2g(x1, ptr(sp, -4096))); + TEST_INSTRUCTION("E10FF0D9", stz2g(x1, ptr_pre(sp, -4096))); + TEST_INSTRUCTION("E107F0D9", stz2g(x1, ptr_post(sp, -4096))); + TEST_INSTRUCTION("E1FBEFD9", stz2g(x1, ptr(sp, 4080))); + TEST_INSTRUCTION("E1FFEFD9", stz2g(x1, ptr_pre(sp, 4080))); + TEST_INSTRUCTION("E1F7EFD9", stz2g(x1, ptr_post(sp, 4080))); + TEST_INSTRUCTION("410860D9", stzg(x1, ptr(x2))); + TEST_INSTRUCTION("418860D9", stzg(x1, ptr(x2, 128))); + TEST_INSTRUCTION("418C60D9", stzg(x1, ptr_pre(x2, 128))); + TEST_INSTRUCTION("418460D9", stzg(x1, ptr_post(x2, 128))); + TEST_INSTRUCTION("E10B60D9", stzg(x1, ptr(sp))); + TEST_INSTRUCTION("E18B60D9", stzg(x1, ptr(sp, 128))); + TEST_INSTRUCTION("E18F60D9", stzg(x1, ptr_pre(sp, 128))); + TEST_INSTRUCTION("E18760D9", stzg(x1, ptr_post(sp, 128))); + TEST_INSTRUCTION("5F0860D9", stzg(sp, ptr(x2))); + TEST_INSTRUCTION("5F8860D9", stzg(sp, ptr(x2, 128))); + TEST_INSTRUCTION("5F8C60D9", stzg(sp, ptr_pre(x2, 128))); + TEST_INSTRUCTION("5F8460D9", stzg(sp, ptr_post(x2, 128))); + TEST_INSTRUCTION("FF0B60D9", stzg(sp, ptr(sp))); + TEST_INSTRUCTION("FF8B60D9", stzg(sp, ptr(sp, 128))); + TEST_INSTRUCTION("FF8F60D9", stzg(sp, ptr_pre(sp, 128))); + TEST_INSTRUCTION("FF8760D9", stzg(sp, ptr_post(sp, 128))); + TEST_INSTRUCTION("410020D9", stzgm(x1, ptr(x2))); + TEST_INSTRUCTION("E10320D9", stzgm(x1, ptr(sp))); + TEST_INSTRUCTION("4100034B", sub(w1, w2, w3)); + TEST_INSTRUCTION("410003CB", sub(x1, x2, x3)); + TEST_INSTRUCTION("410C034B", sub(w1, w2, w3, lsl(3))); + TEST_INSTRUCTION("410C03CB", sub(x1, x2, x3, lsl(3))); + TEST_INSTRUCTION("FF030451", sub(wsp, wsp, 256)); + TEST_INSTRUCTION("FFFF3F51", sub(wsp, wsp, 0xFFF)); + TEST_INSTRUCTION("FF0304D1", sub(sp, sp, 256)); + TEST_INSTRUCTION("FFFF3FD1", sub(sp, sp, 0xFFF)); + TEST_INSTRUCTION("412C82D1", subg(x1, x2, 32, 11)); + TEST_INSTRUCTION("5F2C82D1", subg(sp, x2, 32, 11)); + TEST_INSTRUCTION("E12F82D1", subg(x1, sp, 32, 11)); + TEST_INSTRUCTION("4100C39A", subp(x1, x2, x3)); + TEST_INSTRUCTION("E103C39A", subp(x1, sp, x3)); + TEST_INSTRUCTION("4100DF9A", subp(x1, x2, sp)); + TEST_INSTRUCTION("4100C3BA", subps(x1, x2, x3)); + TEST_INSTRUCTION("E103C3BA", subps(x1, sp, x3)); + TEST_INSTRUCTION("4100DFBA", subps(x1, x2, sp)); + TEST_INSTRUCTION("4100036B", subs(w1, w2, w3)); + TEST_INSTRUCTION("410003EB", subs(x1, x2, x3)); + TEST_INSTRUCTION("410C036B", subs(w1, w2, w3, lsl(3))); + TEST_INSTRUCTION("410C03EB", subs(x1, x2, x3, lsl(3))); + TEST_INSTRUCTION("210000D4", svc(1)); + TEST_INSTRUCTION("411C0013", sxtb(w1, w2)); + TEST_INSTRUCTION("411C4093", sxtb(x1, w2)); + TEST_INSTRUCTION("413C0013", sxth(w1, w2)); + TEST_INSTRUCTION("413C4093", sxth(x1, w2)); + TEST_INSTRUCTION("417C4093", sxtw(x1, w2)); + TEST_INSTRUCTION("932309D5", sys(1, 2, 3, 4, x19)); + TEST_INSTRUCTION("AF8708D5", tlbi(Predicate::TLBI::kVALE1, x15)); + TEST_INSTRUCTION("3F000072", tst(w1, 1)); + TEST_INSTRUCTION("3F0040F2", tst(x1, 1)); + TEST_INSTRUCTION("3F00026A", tst(w1, w2)); + TEST_INSTRUCTION("3F0002EA", tst(x1, x2)); + TEST_INSTRUCTION("3F10026A", tst(w1, w2, lsl(4))); + TEST_INSTRUCTION("3F1002EA", tst(x1, x2, lsl(4))); + TEST_INSTRUCTION("00000000", udf(0)); + TEST_INSTRUCTION("01800000", udf(0x8001)); + TEST_INSTRUCTION("4108C31A", udiv(w1, w2, w3)); + TEST_INSTRUCTION("4108C39A", udiv(x1, x2, x3)); + TEST_INSTRUCTION("41241B53", ubfiz(w1, w2, 5, 10)); + TEST_INSTRUCTION("41247BD3", ubfiz(x1, x2, 5, 10)); + TEST_INSTRUCTION("41280553", ubfm(w1, w2, 5, 10)); + TEST_INSTRUCTION("412845D3", ubfm(x1, x2, 5, 10)); + TEST_INSTRUCTION("41380553", ubfx(w1, w2, 5, 10)); + TEST_INSTRUCTION("413845D3", ubfx(x1, x2, 5, 10)); + TEST_INSTRUCTION("4110A39B", umaddl(x1, w2, w3, x4)); + TEST_INSTRUCTION("41FCA39B", umnegl(x1, w2, w3)); + TEST_INSTRUCTION("4190A39B", umsubl(x1, w2, w3, x4)); + TEST_INSTRUCTION("417CC39B", umulh(x1, x2, x3)); + TEST_INSTRUCTION("417CA39B", umull(x1, w2, w3)); + TEST_INSTRUCTION("411C0053", uxtb(w1, w2)); + TEST_INSTRUCTION("413C0053", uxth(w1, w2)); + TEST_INSTRUCTION("3F4000D5", xaflag()); + TEST_INSTRUCTION("E147C1DA", xpacd(x1)); + TEST_INSTRUCTION("E143C1DA", xpaci(x1)); + TEST_INSTRUCTION("FF2003D5", xpaclri()); +} + +static void ASMJIT_NOINLINE testA64AssemblerRel(AssemblerTester<a64::Assembler>& tester) noexcept { + using namespace a64; + + // Must be a reference, because it's recreated after every `TEST_INSTRUCTION()`. + const Label& L0 = tester.L0; + + TEST_INSTRUCTION("01000010", adr(x1, L0)); + TEST_INSTRUCTION("00000014", b(L0)); + TEST_INSTRUCTION("00000014", b_al(L0)); + TEST_INSTRUCTION("00000054", b_eq(L0)); + TEST_INSTRUCTION("01000054", b_ne(L0)); + TEST_INSTRUCTION("02000054", b_hs(L0)); + TEST_INSTRUCTION("03000054", b_lo(L0)); + TEST_INSTRUCTION("04000054", b_mi(L0)); + TEST_INSTRUCTION("05000054", b_pl(L0)); + TEST_INSTRUCTION("06000054", b_vs(L0)); + TEST_INSTRUCTION("07000054", b_vc(L0)); + TEST_INSTRUCTION("08000054", b_hi(L0)); + TEST_INSTRUCTION("09000054", b_ls(L0)); + TEST_INSTRUCTION("0A000054", b_ge(L0)); + TEST_INSTRUCTION("0B000054", b_lt(L0)); + TEST_INSTRUCTION("0C000054", b_gt(L0)); + TEST_INSTRUCTION("0D000054", b_le(L0)); + TEST_INSTRUCTION("00000014", b(CondCode::kAL, L0)); + TEST_INSTRUCTION("00000054", b(CondCode::kEQ, L0)); + TEST_INSTRUCTION("01000054", b(CondCode::kNE, L0)); + TEST_INSTRUCTION("02000054", b(CondCode::kHS, L0)); + TEST_INSTRUCTION("03000054", b(CondCode::kLO, L0)); + TEST_INSTRUCTION("04000054", b(CondCode::kMI, L0)); + TEST_INSTRUCTION("05000054", b(CondCode::kPL, L0)); + TEST_INSTRUCTION("06000054", b(CondCode::kVS, L0)); + TEST_INSTRUCTION("07000054", b(CondCode::kVC, L0)); + TEST_INSTRUCTION("08000054", b(CondCode::kHI, L0)); + TEST_INSTRUCTION("09000054", b(CondCode::kLS, L0)); + TEST_INSTRUCTION("0A000054", b(CondCode::kGE, L0)); + TEST_INSTRUCTION("0B000054", b(CondCode::kLT, L0)); + TEST_INSTRUCTION("0C000054", b(CondCode::kGT, L0)); + TEST_INSTRUCTION("0D000054", b(CondCode::kLE, L0)); + + TEST_INSTRUCTION("00000094", bl(L0)); + TEST_INSTRUCTION("01000034", cbz(w1, L0)); + TEST_INSTRUCTION("010000B4", cbz(x1, L0)); + TEST_INSTRUCTION("01000035", cbnz(w1, L0)); + TEST_INSTRUCTION("010000B5", cbnz(x1, L0)); + TEST_INSTRUCTION("01001837", tbnz(w1, 3, L0)); + TEST_INSTRUCTION("010008B7", tbnz(x1, 33, L0)); + TEST_INSTRUCTION("01001836", tbz(w1, 3, L0)); + TEST_INSTRUCTION("010008B6", tbz(x1, 33, L0)); +} + +static void ASMJIT_NOINLINE testA64AssemblerSIMD(AssemblerTester<a64::Assembler>& tester) noexcept { + using namespace a64; + + TEST_INSTRUCTION("41B8200E", abs(v1.b8(), v2.b8())); + TEST_INSTRUCTION("41B8600E", abs(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41B8A00E", abs(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41B8E05E", abs(d1, d2)); + TEST_INSTRUCTION("41B8204E", abs(v1.b16(), v2.b16())); + TEST_INSTRUCTION("41B8604E", abs(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41B8A04E", abs(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41B8E04E", abs(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4184230E", add(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4184630E", add(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4184A30E", add(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4184E35E", add(d1, d2, d3)); + TEST_INSTRUCTION("4184234E", add(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4184634E", add(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4184A34E", add(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4184E34E", add(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4140230E", addhn(v1.b8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4140630E", addhn(v1.h4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4140A30E", addhn(v1.s2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4140234E", addhn2(v1.b16(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4140634E", addhn2(v1.h8(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4140A34E", addhn2(v1.s4(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41BC230E", addp(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("41BC630E", addp(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41BCA30E", addp(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41B8F15E", addp(d1, v2.d2())); + TEST_INSTRUCTION("41BC234E", addp(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41BC634E", addp(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41BCA34E", addp(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41BCE34E", addp(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41B8310E", addv(b1, v2.b8())); + TEST_INSTRUCTION("41B8314E", addv(b1, v2.b16())); + TEST_INSTRUCTION("41B8710E", addv(h1, v2.h4())); + TEST_INSTRUCTION("41B8714E", addv(h1, v2.h8())); + TEST_INSTRUCTION("41B8B14E", addv(s1, v2.s4())); + TEST_INSTRUCTION("4158284E", aesd(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4148284E", aese(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4178284E", aesimc(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4168284E", aesmc(v1.b16(), v2.b16())); + TEST_INSTRUCTION("411C230E", and_(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("411C234E", and_(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("411023CE", bcax(v1.b16(), v2.b16(), v3.b16(), v4.b16())); + TEST_INSTRUCTION("4140631E", bfcvt(h1, s2)); + TEST_INSTRUCTION("4168A10E", bfcvtn(v1.h4(), v2.s4())); + TEST_INSTRUCTION("4168A14E", bfcvtn2(v1.h8(), v2.s4())); + TEST_INSTRUCTION("41FC432E", bfdot(v1.s2(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41FC436E", bfdot(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41F0430F", bfdot(v1.s2(), v2.h4(), v3.h2(0))); + TEST_INSTRUCTION("41F8634F", bfdot(v1.s4(), v2.h8(), v3.h2(3))); + TEST_INSTRUCTION("41FCC32E", bfmlalb(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41F0C30F", bfmlalb(v1.s4(), v2.h8(), v3.h(0))); + TEST_INSTRUCTION("41F8F30F", bfmlalb(v1.s4(), v2.h8(), v3.h(7))); + TEST_INSTRUCTION("41FCC36E", bfmlalt(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41F0C34F", bfmlalt(v1.s4(), v2.h8(), v3.h(0))); + TEST_INSTRUCTION("41F8F34F", bfmlalt(v1.s4(), v2.h8(), v3.h(7))); + TEST_INSTRUCTION("41EC436E", bfmmla(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("411C630E", bic(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("411C634E", bic(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("E197072F", bic(v1.h4(), 255)); + TEST_INSTRUCTION("E1B7072F", bic(v1.h4(), 255, lsl(8))); + TEST_INSTRUCTION("E197076F", bic(v1.h8(), 255)); + TEST_INSTRUCTION("E1B7076F", bic(v1.h8(), 255, lsl(8))); + TEST_INSTRUCTION("E117072F", bic(v1.s2(), 255)); + TEST_INSTRUCTION("E137072F", bic(v1.s2(), 255, lsl(8))); + TEST_INSTRUCTION("E117076F", bic(v1.s4(), 255)); + TEST_INSTRUCTION("E177076F", bic(v1.s4(), 255, lsl(24))); + TEST_INSTRUCTION("411CE32E", bif(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("411CE36E", bif(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("411CA32E", bit(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("411CA36E", bit(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("411C632E", bsl(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("411C636E", bsl(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4148200E", cls(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4148600E", cls(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4148A00E", cls(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4148204E", cls(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4148604E", cls(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4148A04E", cls(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4148202E", clz(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4148602E", clz(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4148A02E", clz(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4148206E", clz(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4148606E", clz(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4148A06E", clz(v1.s4(), v2.s4())); + TEST_INSTRUCTION("418C232E", cmeq(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("418C632E", cmeq(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("418CA32E", cmeq(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("418CE37E", cmeq(d1, d2, d3)); + TEST_INSTRUCTION("418C236E", cmeq(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("418C636E", cmeq(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("418CA36E", cmeq(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("418CE36E", cmeq(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4198200E", cmeq(v1.b8(), v2.b8(), 0)); + TEST_INSTRUCTION("4198600E", cmeq(v1.h4(), v2.h4(), 0)); + TEST_INSTRUCTION("4198A00E", cmeq(v1.s2(), v2.s2(), 0)); + TEST_INSTRUCTION("4198E05E", cmeq(d1, d2, 0)); + TEST_INSTRUCTION("4198204E", cmeq(v1.b16(), v2.b16(), 0)); + TEST_INSTRUCTION("4198604E", cmeq(v1.h8(), v2.h8(), 0)); + TEST_INSTRUCTION("4198A04E", cmeq(v1.s4(), v2.s4(), 0)); + TEST_INSTRUCTION("4198E04E", cmeq(v1.d2(), v2.d2(), 0)); + TEST_INSTRUCTION("413C230E", cmge(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("413C630E", cmge(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("413CA30E", cmge(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("413CE35E", cmge(d1, d2, d3)); + TEST_INSTRUCTION("413C234E", cmge(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("413C634E", cmge(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("413CA34E", cmge(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("413CE34E", cmge(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4188202E", cmge(v1.b8(), v2.b8(), 0)); + TEST_INSTRUCTION("4188602E", cmge(v1.h4(), v2.h4(), 0)); + TEST_INSTRUCTION("4188A02E", cmge(v1.s2(), v2.s2(), 0)); + TEST_INSTRUCTION("4188E07E", cmge(d1, d2, 0)); + TEST_INSTRUCTION("4188206E", cmge(v1.b16(), v2.b16(), 0)); + TEST_INSTRUCTION("4188606E", cmge(v1.h8(), v2.h8(), 0)); + TEST_INSTRUCTION("4188A06E", cmge(v1.s4(), v2.s4(), 0)); + TEST_INSTRUCTION("4188E06E", cmge(v1.d2(), v2.d2(), 0)); + TEST_INSTRUCTION("4134230E", cmgt(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4134630E", cmgt(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4134A30E", cmgt(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4134E35E", cmgt(d1, d2, d3)); + TEST_INSTRUCTION("4134234E", cmgt(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4134634E", cmgt(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4134A34E", cmgt(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4134E34E", cmgt(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4188200E", cmgt(v1.b8(), v2.b8(), 0)); + TEST_INSTRUCTION("4188600E", cmgt(v1.h4(), v2.h4(), 0)); + TEST_INSTRUCTION("4188A00E", cmgt(v1.s2(), v2.s2(), 0)); + TEST_INSTRUCTION("4188E05E", cmgt(d1, d2, 0)); + TEST_INSTRUCTION("4188204E", cmgt(v1.b16(), v2.b16(), 0)); + TEST_INSTRUCTION("4188604E", cmgt(v1.h8(), v2.h8(), 0)); + TEST_INSTRUCTION("4188A04E", cmgt(v1.s4(), v2.s4(), 0)); + TEST_INSTRUCTION("4188E04E", cmgt(v1.d2(), v2.d2(), 0)); + TEST_INSTRUCTION("4134232E", cmhi(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4134632E", cmhi(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4134A32E", cmhi(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4134E37E", cmhi(d1, d2, d3)); + TEST_INSTRUCTION("4134236E", cmhi(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4134636E", cmhi(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4134A36E", cmhi(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4134E36E", cmhi(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("413C232E", cmhs(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("413C632E", cmhs(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("413CA32E", cmhs(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("413CE37E", cmhs(d1, d2, d3)); + TEST_INSTRUCTION("413C236E", cmhs(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("413C636E", cmhs(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("413CA36E", cmhs(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("413CE36E", cmhs(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4198202E", cmle(v1.b8(), v2.b8(), 0)); + TEST_INSTRUCTION("4198602E", cmle(v1.h4(), v2.h4(), 0)); + TEST_INSTRUCTION("4198A02E", cmle(v1.s2(), v2.s2(), 0)); + TEST_INSTRUCTION("4198E07E", cmle(d1, d2, 0)); + TEST_INSTRUCTION("4198206E", cmle(v1.b16(), v2.b16(), 0)); + TEST_INSTRUCTION("4198606E", cmle(v1.h8(), v2.h8(), 0)); + TEST_INSTRUCTION("4198A06E", cmle(v1.s4(), v2.s4(), 0)); + TEST_INSTRUCTION("4198E06E", cmle(v1.d2(), v2.d2(), 0)); + TEST_INSTRUCTION("41A8200E", cmlt(v1.b8(), v2.b8(), 0)); + TEST_INSTRUCTION("41A8600E", cmlt(v1.h4(), v2.h4(), 0)); + TEST_INSTRUCTION("41A8A00E", cmlt(v1.s2(), v2.s2(), 0)); + TEST_INSTRUCTION("41A8E05E", cmlt(d1, d2, 0)); + TEST_INSTRUCTION("41A8204E", cmlt(v1.b16(), v2.b16(), 0)); + TEST_INSTRUCTION("41A8604E", cmlt(v1.h8(), v2.h8(), 0)); + TEST_INSTRUCTION("41A8A04E", cmlt(v1.s4(), v2.s4(), 0)); + TEST_INSTRUCTION("41A8E04E", cmlt(v1.d2(), v2.d2(), 0)); + TEST_INSTRUCTION("418C230E", cmtst(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("418C630E", cmtst(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("418CA30E", cmtst(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("418CE35E", cmtst(d1, d2, d3)); + TEST_INSTRUCTION("418C234E", cmtst(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("418C634E", cmtst(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("418CA34E", cmtst(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("418CE34E", cmtst(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4158200E", cnt(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4158204E", cnt(v1.b16(), v2.b16())); + TEST_INSTRUCTION("410C010E", dup(v1.b8(), w2)); + TEST_INSTRUCTION("410C020E", dup(v1.h4(), w2)); + TEST_INSTRUCTION("410C040E", dup(v1.s2(), w2)); + TEST_INSTRUCTION("410C014E", dup(v1.b16(), w2)); + TEST_INSTRUCTION("410C024E", dup(v1.h8(), w2)); + TEST_INSTRUCTION("410C044E", dup(v1.s4(), w2)); + TEST_INSTRUCTION("410C084E", dup(v1.d2(), x2)); + TEST_INSTRUCTION("4F04035E", dup(b15, v2.b(1))); + TEST_INSTRUCTION("4F04065E", dup(h15, v2.h(1))); + TEST_INSTRUCTION("4F040C5E", dup(s15, v2.s(1))); + TEST_INSTRUCTION("4F04185E", dup(d15, v2.d(1))); + TEST_INSTRUCTION("4F04030E", dup(v15.b8(), v2.b(1))); + TEST_INSTRUCTION("4F04060E", dup(v15.h4(), v2.h(1))); + TEST_INSTRUCTION("4F040C0E", dup(v15.s2(), v2.s(1))); + TEST_INSTRUCTION("4F04034E", dup(v15.b16(), v2.b(1))); + TEST_INSTRUCTION("4F04064E", dup(v15.h8(), v2.h(1))); + TEST_INSTRUCTION("4F040C4E", dup(v15.s4(), v2.s(1))); + TEST_INSTRUCTION("4F04184E", dup(v15.d2(), v2.d(1))); + TEST_INSTRUCTION("411C232E", eor(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("411C236E", eor(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("411003CE", eor3(v1.b16(), v2.b16(), v3.b16(), v4.b16())); + TEST_INSTRUCTION("4128032E", ext(v1.b8(), v2.b8(), v3.b8(), 5)); + TEST_INSTRUCTION("4128036E", ext(v1.b16(), v2.b16(), v3.b16(), 5)); + TEST_INSTRUCTION("4114C37E", fabd(h1, h2, h3)); + TEST_INSTRUCTION("41D4A37E", fabd(s1, s2, s3)); + TEST_INSTRUCTION("41D4E37E", fabd(d1, d2, d3)); + TEST_INSTRUCTION("4114C32E", fabd(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41D4A32E", fabd(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4114C36E", fabd(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41D4A36E", fabd(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41D4E36E", fabd(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41C0E01E", fabs(h1, h2)); + TEST_INSTRUCTION("41C0201E", fabs(s1, s2)); + TEST_INSTRUCTION("41C0601E", fabs(d1, d2)); + TEST_INSTRUCTION("41F8F80E", fabs(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41F8A00E", fabs(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41F8F84E", fabs(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41F8A04E", fabs(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41F8E04E", fabs(v1.d2(), v2.d2())); + TEST_INSTRUCTION("412C437E", facge(h1, h2, h3)); + TEST_INSTRUCTION("41EC237E", facge(s1, s2, s3)); + TEST_INSTRUCTION("41EC637E", facge(d1, d2, d3)); + TEST_INSTRUCTION("412C432E", facge(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41EC232E", facge(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("412C436E", facge(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41EC236E", facge(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41EC636E", facge(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("412CC37E", facgt(h1, h2, h3)); + TEST_INSTRUCTION("41ECA37E", facgt(s1, s2, s3)); + TEST_INSTRUCTION("41ECE37E", facgt(d1, d2, d3)); + TEST_INSTRUCTION("412CC32E", facgt(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41ECA32E", facgt(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("412CC36E", facgt(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41ECA36E", facgt(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41ECE36E", facgt(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4128E31E", fadd(h1, h2, h3)); + TEST_INSTRUCTION("4128231E", fadd(s1, s2, s3)); + TEST_INSTRUCTION("4128631E", fadd(d1, d2, d3)); + TEST_INSTRUCTION("4114430E", fadd(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41D4230E", fadd(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4114434E", fadd(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41D4234E", fadd(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41D4634E", fadd(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41D8305E", faddp(h1, v2.h2())); + TEST_INSTRUCTION("41D8307E", faddp(s1, v2.s2())); + TEST_INSTRUCTION("41D8707E", faddp(d1, v2.d2())); + TEST_INSTRUCTION("4114432E", faddp(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41D4232E", faddp(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4114436E", faddp(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41D4236E", faddp(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41D4636E", faddp(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41E4432E", fcadd(v1.h4(), v2.h4(), v3.h4(), 90)); + TEST_INSTRUCTION("41E4832E", fcadd(v1.s2(), v2.s2(), v3.s2(), 90)); + TEST_INSTRUCTION("41E4436E", fcadd(v1.h8(), v2.h8(), v3.h8(), 90)); + TEST_INSTRUCTION("41E4836E", fcadd(v1.s4(), v2.s4(), v3.s4(), 90)); + TEST_INSTRUCTION("41E4C36E", fcadd(v1.d2(), v2.d2(), v3.d2(), 90)); + TEST_INSTRUCTION("41F4432E", fcadd(v1.h4(), v2.h4(), v3.h4(), 270)); + TEST_INSTRUCTION("41F4832E", fcadd(v1.s2(), v2.s2(), v3.s2(), 270)); + TEST_INSTRUCTION("41F4436E", fcadd(v1.h8(), v2.h8(), v3.h8(), 270)); + TEST_INSTRUCTION("41F4836E", fcadd(v1.s4(), v2.s4(), v3.s4(), 270)); + TEST_INSTRUCTION("41F4C36E", fcadd(v1.d2(), v2.d2(), v3.d2(), 270)); + TEST_INSTRUCTION("2404E21E", fccmp(h1, h2, 4, CondCode::kEQ)); + TEST_INSTRUCTION("2404221E", fccmp(s1, s2, 4, CondCode::kEQ)); + TEST_INSTRUCTION("2404621E", fccmp(d1, d2, 4, CondCode::kEQ)); + TEST_INSTRUCTION("3404E21E", fccmpe(h1, h2, 4, CondCode::kEQ)); + TEST_INSTRUCTION("3404221E", fccmpe(s1, s2, 4, CondCode::kEQ)); + TEST_INSTRUCTION("3404621E", fccmpe(d1, d2, 4, CondCode::kEQ)); + TEST_INSTRUCTION("4124435E", fcmeq(h1, h2, h3)); + TEST_INSTRUCTION("41E4235E", fcmeq(s1, s2, s3)); + TEST_INSTRUCTION("41E4635E", fcmeq(d1, d2, d3)); + TEST_INSTRUCTION("4124430E", fcmeq(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41E4230E", fcmeq(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4124434E", fcmeq(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41E4234E", fcmeq(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41E4634E", fcmeq(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41D8F85E", fcmeq(h1, h2, 0)); + TEST_INSTRUCTION("41D8A05E", fcmeq(s1, s2, 0)); + TEST_INSTRUCTION("41D8E05E", fcmeq(d1, d2, 0)); + TEST_INSTRUCTION("41D8F80E", fcmeq(v1.h4(), v2.h4(), 0)); + TEST_INSTRUCTION("41D8A00E", fcmeq(v1.s2(), v2.s2(), 0)); + TEST_INSTRUCTION("41D8F84E", fcmeq(v1.h8(), v2.h8(), 0)); + TEST_INSTRUCTION("41D8A04E", fcmeq(v1.s4(), v2.s4(), 0)); + TEST_INSTRUCTION("41D8E04E", fcmeq(v1.d2(), v2.d2(), 0)); + TEST_INSTRUCTION("4124437E", fcmge(h1, h2, h3)); + TEST_INSTRUCTION("41E4237E", fcmge(s1, s2, s3)); + TEST_INSTRUCTION("41E4637E", fcmge(d1, d2, d3)); + TEST_INSTRUCTION("4124432E", fcmge(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41E4232E", fcmge(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4124436E", fcmge(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41E4236E", fcmge(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41E4636E", fcmge(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41C8F87E", fcmge(h1, h2, 0)); + TEST_INSTRUCTION("41C8A07E", fcmge(s1, s2, 0)); + TEST_INSTRUCTION("41C8E07E", fcmge(d1, d2, 0)); + TEST_INSTRUCTION("41C8F82E", fcmge(v1.h4(), v2.h4(), 0)); + TEST_INSTRUCTION("41C8A02E", fcmge(v1.s2(), v2.s2(), 0)); + TEST_INSTRUCTION("41C8F86E", fcmge(v1.h8(), v2.h8(), 0)); + TEST_INSTRUCTION("41C8A06E", fcmge(v1.s4(), v2.s4(), 0)); + TEST_INSTRUCTION("41C8E06E", fcmge(v1.d2(), v2.d2(), 0)); + TEST_INSTRUCTION("4124C37E", fcmgt(h1, h2, h3)); + TEST_INSTRUCTION("41E4A37E", fcmgt(s1, s2, s3)); + TEST_INSTRUCTION("41E4E37E", fcmgt(d1, d2, d3)); + TEST_INSTRUCTION("4124C32E", fcmgt(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41E4A32E", fcmgt(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4124C36E", fcmgt(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41E4A36E", fcmgt(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41E4E36E", fcmgt(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41C8F85E", fcmgt(h1, h2, 0)); + TEST_INSTRUCTION("41C8A05E", fcmgt(s1, s2, 0)); + TEST_INSTRUCTION("41C8E05E", fcmgt(d1, d2, 0)); + TEST_INSTRUCTION("41C8F80E", fcmgt(v1.h4(), v2.h4(), 0)); + TEST_INSTRUCTION("41C8A00E", fcmgt(v1.s2(), v2.s2(), 0)); + TEST_INSTRUCTION("41C8F84E", fcmgt(v1.h8(), v2.h8(), 0)); + TEST_INSTRUCTION("41C8A04E", fcmgt(v1.s4(), v2.s4(), 0)); + TEST_INSTRUCTION("41C8E04E", fcmgt(v1.d2(), v2.d2(), 0)); + TEST_INSTRUCTION("41CC432E", fcmla(v1.h4(), v2.h4(), v3.h4(), 90)); + TEST_INSTRUCTION("41CC832E", fcmla(v1.s2(), v2.s2(), v3.s2(), 90)); + TEST_INSTRUCTION("41CC436E", fcmla(v1.h8(), v2.h8(), v3.h8(), 90)); + TEST_INSTRUCTION("41CC836E", fcmla(v1.s4(), v2.s4(), v3.s4(), 90)); + TEST_INSTRUCTION("41CCC36E", fcmla(v1.d2(), v2.d2(), v3.d2(), 90)); + TEST_INSTRUCTION("41DC432E", fcmla(v1.h4(), v2.h4(), v3.h4(), 270)); + TEST_INSTRUCTION("41DC832E", fcmla(v1.s2(), v2.s2(), v3.s2(), 270)); + TEST_INSTRUCTION("41DC436E", fcmla(v1.h8(), v2.h8(), v3.h8(), 270)); + TEST_INSTRUCTION("41DC836E", fcmla(v1.s4(), v2.s4(), v3.s4(), 270)); + TEST_INSTRUCTION("41DCC36E", fcmla(v1.d2(), v2.d2(), v3.d2(), 270)); + TEST_INSTRUCTION("4130432F", fcmla(v1.h4(), v2.h4(), v3.h(0), 90)); + TEST_INSTRUCTION("4130632F", fcmla(v1.h4(), v2.h4(), v3.h(1), 90)); + TEST_INSTRUCTION("4130436F", fcmla(v1.h8(), v2.h8(), v3.h(0), 90)); + TEST_INSTRUCTION("4138636F", fcmla(v1.h8(), v2.h8(), v3.h(3), 90)); + TEST_INSTRUCTION("4130836F", fcmla(v1.s4(), v2.s4(), v3.s(0), 90)); + TEST_INSTRUCTION("4138836F", fcmla(v1.s4(), v2.s4(), v3.s(1), 90)); + TEST_INSTRUCTION("4170432F", fcmla(v1.h4(), v2.h4(), v3.h(0), 270)); + TEST_INSTRUCTION("4170632F", fcmla(v1.h4(), v2.h4(), v3.h(1), 270)); + TEST_INSTRUCTION("4170436F", fcmla(v1.h8(), v2.h8(), v3.h(0), 270)); + TEST_INSTRUCTION("4178636F", fcmla(v1.h8(), v2.h8(), v3.h(3), 270)); + TEST_INSTRUCTION("4170836F", fcmla(v1.s4(), v2.s4(), v3.s(0), 270)); + TEST_INSTRUCTION("4178836F", fcmla(v1.s4(), v2.s4(), v3.s(1), 270)); + TEST_INSTRUCTION("41D8F87E", fcmle(h1, h2, 0)); + TEST_INSTRUCTION("41D8A07E", fcmle(s1, s2, 0)); + TEST_INSTRUCTION("41D8E07E", fcmle(d1, d2, 0)); + TEST_INSTRUCTION("41D8F82E", fcmle(v1.h4(), v2.h4(), 0)); + TEST_INSTRUCTION("41D8A02E", fcmle(v1.s2(), v2.s2(), 0)); + TEST_INSTRUCTION("41D8F86E", fcmle(v1.h8(), v2.h8(), 0)); + TEST_INSTRUCTION("41D8A06E", fcmle(v1.s4(), v2.s4(), 0)); + TEST_INSTRUCTION("41D8E06E", fcmle(v1.d2(), v2.d2(), 0)); + TEST_INSTRUCTION("41E8F85E", fcmlt(h1, h2, 0)); + TEST_INSTRUCTION("41E8A05E", fcmlt(s1, s2, 0)); + TEST_INSTRUCTION("41E8E05E", fcmlt(d1, d2, 0)); + TEST_INSTRUCTION("41E8F80E", fcmlt(v1.h4(), v2.h4(), 0)); + TEST_INSTRUCTION("41E8A00E", fcmlt(v1.s2(), v2.s2(), 0)); + TEST_INSTRUCTION("41E8F84E", fcmlt(v1.h8(), v2.h8(), 0)); + TEST_INSTRUCTION("41E8A04E", fcmlt(v1.s4(), v2.s4(), 0)); + TEST_INSTRUCTION("41E8E04E", fcmlt(v1.d2(), v2.d2(), 0)); + TEST_INSTRUCTION("2020E21E", fcmp(h1, h2)); + TEST_INSTRUCTION("2020221E", fcmp(s1, s2)); + TEST_INSTRUCTION("2020621E", fcmp(d1, d2)); + TEST_INSTRUCTION("2820E01E", fcmp(h1, 0)); + TEST_INSTRUCTION("2820201E", fcmp(s1, 0)); + TEST_INSTRUCTION("2820601E", fcmp(d1, 0)); + TEST_INSTRUCTION("3020E21E", fcmpe(h1, h2)); + TEST_INSTRUCTION("3020221E", fcmpe(s1, s2)); + TEST_INSTRUCTION("3020621E", fcmpe(d1, d2)); + TEST_INSTRUCTION("3820E01E", fcmpe(h1, 0)); + TEST_INSTRUCTION("3820201E", fcmpe(s1, 0)); + TEST_INSTRUCTION("3820601E", fcmpe(d1, 0)); + TEST_INSTRUCTION("410CE31E", fcsel(h1, h2, h3, CondCode::kEQ)); + TEST_INSTRUCTION("410C231E", fcsel(s1, s2, s3, CondCode::kEQ)); + TEST_INSTRUCTION("410C631E", fcsel(d1, d2, d3, CondCode::kEQ)); + TEST_INSTRUCTION("41C0231E", fcvt(h1, s2)); + TEST_INSTRUCTION("41C0631E", fcvt(h1, d2)); + TEST_INSTRUCTION("4140E21E", fcvt(s1, h2)); + TEST_INSTRUCTION("4140621E", fcvt(s1, d2)); + TEST_INSTRUCTION("41C0E21E", fcvt(d1, h2)); + TEST_INSTRUCTION("41C0221E", fcvt(d1, s2)); + TEST_INSTRUCTION("4100E41E", fcvtas(w1, h2)); + TEST_INSTRUCTION("4100241E", fcvtas(w1, s2)); + TEST_INSTRUCTION("4100641E", fcvtas(w1, d2)); + TEST_INSTRUCTION("4100E49E", fcvtas(x1, h2)); + TEST_INSTRUCTION("4100249E", fcvtas(x1, s2)); + TEST_INSTRUCTION("4100649E", fcvtas(x1, d2)); + TEST_INSTRUCTION("41C8795E", fcvtas(h1, h2)); + TEST_INSTRUCTION("41C8215E", fcvtas(s1, s2)); + TEST_INSTRUCTION("41C8615E", fcvtas(d1, d2)); + TEST_INSTRUCTION("41C8790E", fcvtas(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41C8210E", fcvtas(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41C8794E", fcvtas(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41C8214E", fcvtas(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41C8614E", fcvtas(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4100E51E", fcvtau(w1, h2)); + TEST_INSTRUCTION("4100251E", fcvtau(w1, s2)); + TEST_INSTRUCTION("4100651E", fcvtau(w1, d2)); + TEST_INSTRUCTION("4100E59E", fcvtau(x1, h2)); + TEST_INSTRUCTION("4100259E", fcvtau(x1, s2)); + TEST_INSTRUCTION("4100659E", fcvtau(x1, d2)); + TEST_INSTRUCTION("41C8797E", fcvtau(h1, h2)); + TEST_INSTRUCTION("41C8217E", fcvtau(s1, s2)); + TEST_INSTRUCTION("41C8617E", fcvtau(d1, d2)); + TEST_INSTRUCTION("41C8792E", fcvtau(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41C8212E", fcvtau(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41C8796E", fcvtau(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41C8216E", fcvtau(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41C8616E", fcvtau(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4178210E", fcvtl(v1.s4(), v2.h4())); + TEST_INSTRUCTION("4178214E", fcvtl2(v1.s4(), v2.h8())); + TEST_INSTRUCTION("4178610E", fcvtl(v1.d2(), v2.s2())); + TEST_INSTRUCTION("4178614E", fcvtl2(v1.d2(), v2.s4())); + TEST_INSTRUCTION("4100F01E", fcvtms(w1, h2)); + TEST_INSTRUCTION("4100301E", fcvtms(w1, s2)); + TEST_INSTRUCTION("4100701E", fcvtms(w1, d2)); + TEST_INSTRUCTION("4100F09E", fcvtms(x1, h2)); + TEST_INSTRUCTION("4100309E", fcvtms(x1, s2)); + TEST_INSTRUCTION("4100709E", fcvtms(x1, d2)); + TEST_INSTRUCTION("41B8795E", fcvtms(h1, h2)); + TEST_INSTRUCTION("41B8215E", fcvtms(s1, s2)); + TEST_INSTRUCTION("41B8615E", fcvtms(d1, d2)); + TEST_INSTRUCTION("41B8790E", fcvtms(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41B8210E", fcvtms(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41B8794E", fcvtms(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41B8214E", fcvtms(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41B8614E", fcvtms(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4100F11E", fcvtmu(w1, h2)); + TEST_INSTRUCTION("4100311E", fcvtmu(w1, s2)); + TEST_INSTRUCTION("4100711E", fcvtmu(w1, d2)); + TEST_INSTRUCTION("4100F19E", fcvtmu(x1, h2)); + TEST_INSTRUCTION("4100319E", fcvtmu(x1, s2)); + TEST_INSTRUCTION("4100719E", fcvtmu(x1, d2)); + TEST_INSTRUCTION("41B8797E", fcvtmu(h1, h2)); + TEST_INSTRUCTION("41B8217E", fcvtmu(s1, s2)); + TEST_INSTRUCTION("41B8617E", fcvtmu(d1, d2)); + TEST_INSTRUCTION("41B8792E", fcvtmu(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41B8212E", fcvtmu(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41B8796E", fcvtmu(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41B8216E", fcvtmu(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41B8616E", fcvtmu(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4168210E", fcvtn(v1.h4(), v2.s4())); + TEST_INSTRUCTION("4168214E", fcvtn2(v1.h8(), v2.s4())); + TEST_INSTRUCTION("4168610E", fcvtn(v1.s2(), v2.d2())); + TEST_INSTRUCTION("4168614E", fcvtn2(v1.s4(), v2.d2())); + TEST_INSTRUCTION("4100E01E", fcvtns(w1, h2)); + TEST_INSTRUCTION("4100201E", fcvtns(w1, s2)); + TEST_INSTRUCTION("4100601E", fcvtns(w1, d2)); + TEST_INSTRUCTION("4100E09E", fcvtns(x1, h2)); + TEST_INSTRUCTION("4100209E", fcvtns(x1, s2)); + TEST_INSTRUCTION("4100609E", fcvtns(x1, d2)); + TEST_INSTRUCTION("41A8795E", fcvtns(h1, h2)); + TEST_INSTRUCTION("41A8215E", fcvtns(s1, s2)); + TEST_INSTRUCTION("41A8615E", fcvtns(d1, d2)); + TEST_INSTRUCTION("41A8790E", fcvtns(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41A8210E", fcvtns(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41A8794E", fcvtns(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41A8214E", fcvtns(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41A8614E", fcvtns(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4100E11E", fcvtnu(w1, h2)); + TEST_INSTRUCTION("4100211E", fcvtnu(w1, s2)); + TEST_INSTRUCTION("4100611E", fcvtnu(w1, d2)); + TEST_INSTRUCTION("4100E19E", fcvtnu(x1, h2)); + TEST_INSTRUCTION("4100219E", fcvtnu(x1, s2)); + TEST_INSTRUCTION("4100619E", fcvtnu(x1, d2)); + TEST_INSTRUCTION("41A8797E", fcvtnu(h1, h2)); + TEST_INSTRUCTION("41A8217E", fcvtnu(s1, s2)); + TEST_INSTRUCTION("41A8617E", fcvtnu(d1, d2)); + TEST_INSTRUCTION("41A8792E", fcvtnu(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41A8212E", fcvtnu(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41A8796E", fcvtnu(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41A8216E", fcvtnu(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41A8616E", fcvtnu(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4100E81E", fcvtps(w1, h2)); + TEST_INSTRUCTION("4100281E", fcvtps(w1, s2)); + TEST_INSTRUCTION("4100681E", fcvtps(w1, d2)); + TEST_INSTRUCTION("4100E89E", fcvtps(x1, h2)); + TEST_INSTRUCTION("4100289E", fcvtps(x1, s2)); + TEST_INSTRUCTION("4100689E", fcvtps(x1, d2)); + TEST_INSTRUCTION("41A8F95E", fcvtps(h1, h2)); + TEST_INSTRUCTION("41A8A15E", fcvtps(s1, s2)); + TEST_INSTRUCTION("41A8E15E", fcvtps(d1, d2)); + TEST_INSTRUCTION("41A8F90E", fcvtps(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41A8A10E", fcvtps(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41A8F94E", fcvtps(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41A8A14E", fcvtps(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41A8E14E", fcvtps(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4100E91E", fcvtpu(w1, h2)); + TEST_INSTRUCTION("4100291E", fcvtpu(w1, s2)); + TEST_INSTRUCTION("4100691E", fcvtpu(w1, d2)); + TEST_INSTRUCTION("4100E99E", fcvtpu(x1, h2)); + TEST_INSTRUCTION("4100299E", fcvtpu(x1, s2)); + TEST_INSTRUCTION("4100699E", fcvtpu(x1, d2)); + TEST_INSTRUCTION("41A8F97E", fcvtpu(h1, h2)); + TEST_INSTRUCTION("41A8A17E", fcvtpu(s1, s2)); + TEST_INSTRUCTION("41A8E17E", fcvtpu(d1, d2)); + TEST_INSTRUCTION("41A8F92E", fcvtpu(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41A8A12E", fcvtpu(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41A8F96E", fcvtpu(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41A8A16E", fcvtpu(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41A8E16E", fcvtpu(v1.d2(), v2.d2())); + TEST_INSTRUCTION("2168617E", fcvtxn(s1, d1)); + TEST_INSTRUCTION("4168612E", fcvtxn(v1.s2(), v2.d2())); + TEST_INSTRUCTION("4168616E", fcvtxn2(v1.s4(), v2.d2())); + TEST_INSTRUCTION("4100F81E", fcvtzs(w1, h2)); + TEST_INSTRUCTION("4100381E", fcvtzs(w1, s2)); + TEST_INSTRUCTION("4100781E", fcvtzs(w1, d2)); + TEST_INSTRUCTION("4100F89E", fcvtzs(x1, h2)); + TEST_INSTRUCTION("4100389E", fcvtzs(x1, s2)); + TEST_INSTRUCTION("4100789E", fcvtzs(x1, d2)); + TEST_INSTRUCTION("41B8F95E", fcvtzs(h1, h2)); + TEST_INSTRUCTION("41B8A15E", fcvtzs(s1, s2)); + TEST_INSTRUCTION("41B8E15E", fcvtzs(d1, d2)); + TEST_INSTRUCTION("41B8F90E", fcvtzs(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41B8A10E", fcvtzs(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41B8F94E", fcvtzs(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41B8A14E", fcvtzs(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41B8E14E", fcvtzs(v1.d2(), v2.d2())); + TEST_INSTRUCTION("41E0D81E", fcvtzs(w1, h2, 8)); + TEST_INSTRUCTION("41E0181E", fcvtzs(w1, s2, 8)); + TEST_INSTRUCTION("41E0581E", fcvtzs(w1, d2, 8)); + TEST_INSTRUCTION("41E0D89E", fcvtzs(x1, h2, 8)); + TEST_INSTRUCTION("41E0189E", fcvtzs(x1, s2, 8)); + TEST_INSTRUCTION("41E0589E", fcvtzs(x1, d2, 8)); + TEST_INSTRUCTION("41FC185F", fcvtzs(h1, h2, 8)); + TEST_INSTRUCTION("41FC385F", fcvtzs(s1, s2, 8)); + TEST_INSTRUCTION("41FC785F", fcvtzs(d1, d2, 8)); + TEST_INSTRUCTION("41FC180F", fcvtzs(v1.h4(), v2.h4(), 8)); + TEST_INSTRUCTION("41FC380F", fcvtzs(v1.s2(), v2.s2(), 8)); + TEST_INSTRUCTION("41FC184F", fcvtzs(v1.h8(), v2.h8(), 8)); + TEST_INSTRUCTION("41FC384F", fcvtzs(v1.s4(), v2.s4(), 8)); + TEST_INSTRUCTION("41FC784F", fcvtzs(v1.d2(), v2.d2(), 8)); + TEST_INSTRUCTION("4100F91E", fcvtzu(w1, h2)); + TEST_INSTRUCTION("4100391E", fcvtzu(w1, s2)); + TEST_INSTRUCTION("4100791E", fcvtzu(w1, d2)); + TEST_INSTRUCTION("4100F99E", fcvtzu(x1, h2)); + TEST_INSTRUCTION("4100399E", fcvtzu(x1, s2)); + TEST_INSTRUCTION("4100799E", fcvtzu(x1, d2)); + TEST_INSTRUCTION("41B8F97E", fcvtzu(h1, h2)); + TEST_INSTRUCTION("41B8A17E", fcvtzu(s1, s2)); + TEST_INSTRUCTION("41B8E17E", fcvtzu(d1, d2)); + TEST_INSTRUCTION("41B8F92E", fcvtzu(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41B8A12E", fcvtzu(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41B8F96E", fcvtzu(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41B8A16E", fcvtzu(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41B8E16E", fcvtzu(v1.d2(), v2.d2())); + TEST_INSTRUCTION("41E0D91E", fcvtzu(w1, h2, 8)); + TEST_INSTRUCTION("41E0191E", fcvtzu(w1, s2, 8)); + TEST_INSTRUCTION("41E0591E", fcvtzu(w1, d2, 8)); + TEST_INSTRUCTION("41E0D99E", fcvtzu(x1, h2, 8)); + TEST_INSTRUCTION("41E0199E", fcvtzu(x1, s2, 8)); + TEST_INSTRUCTION("41E0599E", fcvtzu(x1, d2, 8)); + TEST_INSTRUCTION("41FC187F", fcvtzu(h1, h2, 8)); + TEST_INSTRUCTION("41FC387F", fcvtzu(s1, s2, 8)); + TEST_INSTRUCTION("41FC787F", fcvtzu(d1, d2, 8)); + TEST_INSTRUCTION("41FC182F", fcvtzu(v1.h4(), v2.h4(), 8)); + TEST_INSTRUCTION("41FC382F", fcvtzu(v1.s2(), v2.s2(), 8)); + TEST_INSTRUCTION("41FC186F", fcvtzu(v1.h8(), v2.h8(), 8)); + TEST_INSTRUCTION("41FC386F", fcvtzu(v1.s4(), v2.s4(), 8)); + TEST_INSTRUCTION("41FC786F", fcvtzu(v1.d2(), v2.d2(), 8)); + TEST_INSTRUCTION("4118E31E", fdiv(h1, h2, h3)); + TEST_INSTRUCTION("4118231E", fdiv(s1, s2, s3)); + TEST_INSTRUCTION("4118631E", fdiv(d1, d2, d3)); + TEST_INSTRUCTION("413C432E", fdiv(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41FC232E", fdiv(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("413C436E", fdiv(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41FC236E", fdiv(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41FC636E", fdiv(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41007E1E", fjcvtzs(w1, d2)); + TEST_INSTRUCTION("4110C31F", fmadd(h1, h2, h3, h4)); + TEST_INSTRUCTION("4110031F", fmadd(s1, s2, s3, s4)); + TEST_INSTRUCTION("4110431F", fmadd(d1, d2, d3, d4)); + TEST_INSTRUCTION("4148E31E", fmax(h1, h2, h3)); + TEST_INSTRUCTION("4148231E", fmax(s1, s2, s3)); + TEST_INSTRUCTION("4148631E", fmax(d1, d2, d3)); + TEST_INSTRUCTION("4134430E", fmax(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41F4230E", fmax(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4134434E", fmax(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41F4234E", fmax(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41F4634E", fmax(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4168E31E", fmaxnm(h1, h2, h3)); + TEST_INSTRUCTION("4168231E", fmaxnm(s1, s2, s3)); + TEST_INSTRUCTION("4168631E", fmaxnm(d1, d2, d3)); + TEST_INSTRUCTION("4104430E", fmaxnm(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41C4230E", fmaxnm(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4104434E", fmaxnm(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41C4234E", fmaxnm(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41C4634E", fmaxnm(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41C8305E", fmaxnmp(h1, v2.h2())); + TEST_INSTRUCTION("41C8307E", fmaxnmp(s1, v2.s2())); + TEST_INSTRUCTION("41C8707E", fmaxnmp(d1, v2.d2())); + TEST_INSTRUCTION("4104432E", fmaxnmp(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41C4232E", fmaxnmp(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4104436E", fmaxnmp(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41C4236E", fmaxnmp(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41C4636E", fmaxnmp(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41C8300E", fmaxnmv(h1, v2.h4())); + TEST_INSTRUCTION("41C8304E", fmaxnmv(h1, v2.h8())); + TEST_INSTRUCTION("41C8306E", fmaxnmv(s1, v2.s4())); + TEST_INSTRUCTION("41F8305E", fmaxp(h1, v2.h2())); + TEST_INSTRUCTION("41F8307E", fmaxp(s1, v2.s2())); + TEST_INSTRUCTION("41F8707E", fmaxp(d1, v2.d2())); + TEST_INSTRUCTION("4134432E", fmaxp(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41F4232E", fmaxp(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4134436E", fmaxp(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41F4236E", fmaxp(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41F4636E", fmaxp(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41F8300E", fmaxv(h1, v2.h4())); + TEST_INSTRUCTION("41F8304E", fmaxv(h1, v2.h8())); + TEST_INSTRUCTION("41F8306E", fmaxv(s1, v2.s4())); + TEST_INSTRUCTION("4158E31E", fmin(h1, h2, h3)); + TEST_INSTRUCTION("4158231E", fmin(s1, s2, s3)); + TEST_INSTRUCTION("4158631E", fmin(d1, d2, d3)); + TEST_INSTRUCTION("4134C30E", fmin(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41F4A30E", fmin(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4134C34E", fmin(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41F4A34E", fmin(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41F4E34E", fmin(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4178E31E", fminnm(h1, h2, h3)); + TEST_INSTRUCTION("4178231E", fminnm(s1, s2, s3)); + TEST_INSTRUCTION("4178631E", fminnm(d1, d2, d3)); + TEST_INSTRUCTION("4104C30E", fminnm(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41C4A30E", fminnm(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4104C34E", fminnm(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41C4A34E", fminnm(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41C4E34E", fminnm(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41C8B05E", fminnmp(h1, v2.h2())); + TEST_INSTRUCTION("41C8B07E", fminnmp(s1, v2.s2())); + TEST_INSTRUCTION("41C8F07E", fminnmp(d1, v2.d2())); + TEST_INSTRUCTION("4104C32E", fminnmp(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41C4A32E", fminnmp(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4104C36E", fminnmp(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41C4A36E", fminnmp(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41C4E36E", fminnmp(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41C8B00E", fminnmv(h1, v2.h4())); + TEST_INSTRUCTION("41C8B04E", fminnmv(h1, v2.h8())); + TEST_INSTRUCTION("41C8B06E", fminnmv(s1, v2.s4())); + TEST_INSTRUCTION("41F8B05E", fminp(h1, v2.h2())); + TEST_INSTRUCTION("41F8B07E", fminp(s1, v2.s2())); + TEST_INSTRUCTION("41F8F07E", fminp(d1, v2.d2())); + TEST_INSTRUCTION("4134C32E", fminp(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41F4A32E", fminp(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4134C36E", fminp(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41F4A36E", fminp(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41F4E36E", fminp(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41F8B00E", fminv(h1, v2.h4())); + TEST_INSTRUCTION("41F8B04E", fminv(h1, v2.h8())); + TEST_INSTRUCTION("41F8B06E", fminv(s1, v2.s4())); + TEST_INSTRUCTION("410C430E", fmla(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41CC230E", fmla(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("410C434E", fmla(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41CC234E", fmla(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41CC634E", fmla(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4118335F", fmla(h1, h2, v3.h(7))); + TEST_INSTRUCTION("4118A35F", fmla(s1, s2, v3.s(3))); + TEST_INSTRUCTION("4118C35F", fmla(d1, d2, v3.d(1))); + TEST_INSTRUCTION("4118330F", fmla(v1.h4(), v2.h4(), v3.h(7))); + TEST_INSTRUCTION("4118A30F", fmla(v1.s2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("4118334F", fmla(v1.h8(), v2.h8(), v3.h(7))); + TEST_INSTRUCTION("4118A34F", fmla(v1.s4(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("4118C34F", fmla(v1.d2(), v2.d2(), v3.d(1))); + TEST_INSTRUCTION("41EC230E", fmlal(v1.s2(), v2.h2(), v3.h2())); + TEST_INSTRUCTION("41EC234E", fmlal(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4100830F", fmlal(v1.s2(), v2.h2(), v3.h(0))); + TEST_INSTRUCTION("4108B30F", fmlal(v1.s2(), v2.h2(), v3.h(7))); + TEST_INSTRUCTION("4100834F", fmlal(v1.s4(), v2.h4(), v3.h(0))); + TEST_INSTRUCTION("4108B34F", fmlal(v1.s4(), v2.h4(), v3.h(7))); + TEST_INSTRUCTION("41CC232E", fmlal2(v1.s2(), v2.h2(), v3.h2())); + TEST_INSTRUCTION("41CC236E", fmlal2(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4180832F", fmlal2(v1.s2(), v2.h2(), v3.h(0))); + TEST_INSTRUCTION("4188B32F", fmlal2(v1.s2(), v2.h2(), v3.h(7))); + TEST_INSTRUCTION("4180836F", fmlal2(v1.s4(), v2.h4(), v3.h(0))); + TEST_INSTRUCTION("4188B36F", fmlal2(v1.s4(), v2.h4(), v3.h(7))); + TEST_INSTRUCTION("410CC30E", fmls(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41CCA30E", fmls(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("410CC34E", fmls(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41CCA34E", fmls(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41CCE34E", fmls(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4158335F", fmls(h1, h2, v3.h(7))); + TEST_INSTRUCTION("4158A35F", fmls(s1, s2, v3.s(3))); + TEST_INSTRUCTION("4158C35F", fmls(d1, d2, v3.d(1))); + TEST_INSTRUCTION("4158330F", fmls(v1.h4(), v2.h4(), v3.h(7))); + TEST_INSTRUCTION("4158A30F", fmls(v1.s2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("4158334F", fmls(v1.h8(), v2.h8(), v3.h(7))); + TEST_INSTRUCTION("4158A34F", fmls(v1.s4(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("4158C34F", fmls(v1.d2(), v2.d2(), v3.d(1))); + TEST_INSTRUCTION("41ECA30E", fmlsl(v1.s2(), v2.h2(), v3.h2())); + TEST_INSTRUCTION("41ECA34E", fmlsl(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4140830F", fmlsl(v1.s2(), v2.h2(), v3.h(0))); + TEST_INSTRUCTION("4148B30F", fmlsl(v1.s2(), v2.h2(), v3.h(7))); + TEST_INSTRUCTION("4140834F", fmlsl(v1.s4(), v2.h4(), v3.h(0))); + TEST_INSTRUCTION("4148B34F", fmlsl(v1.s4(), v2.h4(), v3.h(7))); + TEST_INSTRUCTION("41CCA32E", fmlsl2(v1.s2(), v2.h2(), v3.h2())); + TEST_INSTRUCTION("41CCA36E", fmlsl2(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41C0832F", fmlsl2(v1.s2(), v2.h2(), v3.h(0))); + TEST_INSTRUCTION("41C8B32F", fmlsl2(v1.s2(), v2.h2(), v3.h(7))); + TEST_INSTRUCTION("41C0836F", fmlsl2(v1.s4(), v2.h4(), v3.h(0))); + TEST_INSTRUCTION("41C8B36F", fmlsl2(v1.s4(), v2.h4(), v3.h(7))); + TEST_INSTRUCTION("4100E71E", fmov(h1, w2)); + TEST_INSTRUCTION("4100E79E", fmov(h1, x2)); + TEST_INSTRUCTION("4100271E", fmov(s1, w2)); + TEST_INSTRUCTION("4100679E", fmov(d1, x2)); + TEST_INSTRUCTION("4100AF9E", fmov(v1.d(1), x2)); + TEST_INSTRUCTION("4100E61E", fmov(w1, h2)); + TEST_INSTRUCTION("4100E69E", fmov(x1, h2)); + TEST_INSTRUCTION("4100261E", fmov(w1, s2)); + TEST_INSTRUCTION("4100669E", fmov(x1, d2)); + TEST_INSTRUCTION("4100AE9E", fmov(x1, v2.d(1))); + TEST_INSTRUCTION("0110EA1E", fmov(h1, 0.25)); + TEST_INSTRUCTION("0110EC1E", fmov(h1, 0.5)); + TEST_INSTRUCTION("0110EF1E", fmov(h1, 1.5)); + TEST_INSTRUCTION("0110E01E", fmov(h1, 2.0)); + TEST_INSTRUCTION("01D0E51E", fmov(h1, 15.0)); + TEST_INSTRUCTION("01102A1E", fmov(s1, 0.25)); + TEST_INSTRUCTION("01102C1E", fmov(s1, 0.5)); + TEST_INSTRUCTION("01102F1E", fmov(s1, 1.5)); + TEST_INSTRUCTION("0110201E", fmov(s1, 2.0)); + TEST_INSTRUCTION("01D0251E", fmov(s1, 15.0)); + TEST_INSTRUCTION("01106A1E", fmov(d1, 0.25)); + TEST_INSTRUCTION("01106C1E", fmov(d1, 0.5)); + TEST_INSTRUCTION("01106F1E", fmov(d1, 1.5)); + TEST_INSTRUCTION("0110601E", fmov(d1, 2.0)); + TEST_INSTRUCTION("01D0651E", fmov(d1, 15.0)); + TEST_INSTRUCTION("01FC030F", fmov(v1.h4(), 0.5)); + TEST_INSTRUCTION("01FC000F", fmov(v1.h4(), 2.0)); + TEST_INSTRUCTION("01FC034F", fmov(v1.h8(), 0.5)); + TEST_INSTRUCTION("01FC004F", fmov(v1.h8(), 2.0)); + TEST_INSTRUCTION("01F4030F", fmov(v1.s2(), 0.5)); + TEST_INSTRUCTION("01F4000F", fmov(v1.s2(), 2.0)); + TEST_INSTRUCTION("01F4034F", fmov(v1.s4(), 0.5)); + TEST_INSTRUCTION("01F4004F", fmov(v1.s4(), 2.0)); + TEST_INSTRUCTION("01F4036F", fmov(v1.d2(), 0.5)); + TEST_INSTRUCTION("01F4006F", fmov(v1.d2(), 2.0)); + TEST_INSTRUCTION("4190C31F", fmsub(h1, h2, h3, h4)); + TEST_INSTRUCTION("4190031F", fmsub(s1, s2, s3, s4)); + TEST_INSTRUCTION("4190431F", fmsub(d1, d2, d3, d4)); + TEST_INSTRUCTION("4108E31E", fmul(h1, h2, h3)); + TEST_INSTRUCTION("4108231E", fmul(s1, s2, s3)); + TEST_INSTRUCTION("4108631E", fmul(d1, d2, d3)); + TEST_INSTRUCTION("411C432E", fmul(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41DC232E", fmul(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("411C436E", fmul(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41DC236E", fmul(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41DC636E", fmul(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4198335F", fmul(h1, h2, v3.h(7))); + TEST_INSTRUCTION("4198A35F", fmul(s1, s2, v3.s(3))); + TEST_INSTRUCTION("4198C35F", fmul(d1, d2, v3.d(1))); + TEST_INSTRUCTION("4198330F", fmul(v1.h4(), v2.h4(), v3.h(7))); + TEST_INSTRUCTION("4198A30F", fmul(v1.s2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("4198334F", fmul(v1.h8(), v2.h8(), v3.h(7))); + TEST_INSTRUCTION("4198A34F", fmul(v1.s4(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("4198C34F", fmul(v1.d2(), v2.d2(), v3.d(1))); + TEST_INSTRUCTION("411C435E", fmulx(h1, h2, h3)); + TEST_INSTRUCTION("41DC235E", fmulx(s1, s2, s3)); + TEST_INSTRUCTION("41DC635E", fmulx(d1, d2, d3)); + TEST_INSTRUCTION("411C430E", fmulx(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41DC230E", fmulx(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("411C434E", fmulx(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41DC234E", fmulx(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41DC634E", fmulx(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4198337F", fmulx(h1, h2, v3.h(7))); + TEST_INSTRUCTION("4198A37F", fmulx(s1, s2, v3.s(3))); + TEST_INSTRUCTION("4198C37F", fmulx(d1, d2, v3.d(1))); + TEST_INSTRUCTION("4198332F", fmulx(v1.h4(), v2.h4(), v3.h(7))); + TEST_INSTRUCTION("4198A32F", fmulx(v1.s2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("4198336F", fmulx(v1.h8(), v2.h8(), v3.h(7))); + TEST_INSTRUCTION("4198A36F", fmulx(v1.s4(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("4198C36F", fmulx(v1.d2(), v2.d2(), v3.d(1))); + TEST_INSTRUCTION("4140E11E", fneg(h1, h2)); + TEST_INSTRUCTION("4140211E", fneg(s1, s2)); + TEST_INSTRUCTION("4140611E", fneg(d1, d2)); + TEST_INSTRUCTION("41F8F82E", fneg(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41F8A02E", fneg(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41F8F86E", fneg(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41F8A06E", fneg(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41F8E06E", fneg(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4110E31F", fnmadd(h1, h2, h3, h4)); + TEST_INSTRUCTION("4110231F", fnmadd(s1, s2, s3, s4)); + TEST_INSTRUCTION("4110631F", fnmadd(d1, d2, d3, d4)); + TEST_INSTRUCTION("4190E31F", fnmsub(h1, h2, h3, h4)); + TEST_INSTRUCTION("4190231F", fnmsub(s1, s2, s3, s4)); + TEST_INSTRUCTION("4190631F", fnmsub(d1, d2, d3, d4)); + TEST_INSTRUCTION("4188E31E", fnmul(h1, h2, h3)); + TEST_INSTRUCTION("4188231E", fnmul(s1, s2, s3)); + TEST_INSTRUCTION("4188631E", fnmul(d1, d2, d3)); + TEST_INSTRUCTION("41D8F95E", frecpe(h1, h2)); + TEST_INSTRUCTION("41D8A15E", frecpe(s1, s2)); + TEST_INSTRUCTION("41D8E15E", frecpe(d1, d2)); + TEST_INSTRUCTION("41D8F90E", frecpe(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41D8A10E", frecpe(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41D8F94E", frecpe(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41D8A14E", frecpe(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41D8E14E", frecpe(v1.d2(), v2.d2())); + TEST_INSTRUCTION("413C435E", frecps(h1, h2, h3)); + TEST_INSTRUCTION("41FC235E", frecps(s1, s2, s3)); + TEST_INSTRUCTION("41FC635E", frecps(d1, d2, d3)); + TEST_INSTRUCTION("413C430E", frecps(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41FC230E", frecps(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("413C434E", frecps(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41FC234E", frecps(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41FC634E", frecps(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41F8F95E", frecpx(h1, h2)); + TEST_INSTRUCTION("41F8A15E", frecpx(s1, s2)); + TEST_INSTRUCTION("41F8E15E", frecpx(d1, d2)); + TEST_INSTRUCTION("41C0281E", frint32x(s1, s2)); + TEST_INSTRUCTION("41C0681E", frint32x(d1, d2)); + TEST_INSTRUCTION("41E8212E", frint32x(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41E8216E", frint32x(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41E8616E", frint32x(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4140281E", frint32z(s1, s2)); + TEST_INSTRUCTION("4140681E", frint32z(d1, d2)); + TEST_INSTRUCTION("41E8210E", frint32z(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41E8214E", frint32z(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41E8614E", frint32z(v1.d2(), v2.d2())); + TEST_INSTRUCTION("41C0291E", frint64x(s1, s2)); + TEST_INSTRUCTION("41C0691E", frint64x(d1, d2)); + TEST_INSTRUCTION("41F8212E", frint64x(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41F8216E", frint64x(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41F8616E", frint64x(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4140291E", frint64z(s1, s2)); + TEST_INSTRUCTION("4140691E", frint64z(d1, d2)); + TEST_INSTRUCTION("41F8210E", frint64z(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41F8214E", frint64z(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41F8614E", frint64z(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4140E61E", frinta(h1, h2)); + TEST_INSTRUCTION("4140261E", frinta(s1, s2)); + TEST_INSTRUCTION("4140661E", frinta(d1, d2)); + TEST_INSTRUCTION("4188792E", frinta(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4188212E", frinta(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4188796E", frinta(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4188216E", frinta(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4188616E", frinta(v1.d2(), v2.d2())); + TEST_INSTRUCTION("41C0E71E", frinti(h1, h2)); + TEST_INSTRUCTION("41C0271E", frinti(s1, s2)); + TEST_INSTRUCTION("41C0671E", frinti(d1, d2)); + TEST_INSTRUCTION("4198F92E", frinti(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4198A12E", frinti(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4198F96E", frinti(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4198A16E", frinti(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4198E16E", frinti(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4140E51E", frintm(h1, h2)); + TEST_INSTRUCTION("4140251E", frintm(s1, s2)); + TEST_INSTRUCTION("4140651E", frintm(d1, d2)); + TEST_INSTRUCTION("4198790E", frintm(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4198210E", frintm(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4198794E", frintm(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4198214E", frintm(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4198614E", frintm(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4140E41E", frintn(h1, h2)); + TEST_INSTRUCTION("4140241E", frintn(s1, s2)); + TEST_INSTRUCTION("4140641E", frintn(d1, d2)); + TEST_INSTRUCTION("4188790E", frintn(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4188210E", frintn(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4188794E", frintn(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4188214E", frintn(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4188614E", frintn(v1.d2(), v2.d2())); + TEST_INSTRUCTION("41C0E41E", frintp(h1, h2)); + TEST_INSTRUCTION("41C0241E", frintp(s1, s2)); + TEST_INSTRUCTION("41C0641E", frintp(d1, d2)); + TEST_INSTRUCTION("4188F90E", frintp(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4188A10E", frintp(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4188F94E", frintp(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4188A14E", frintp(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4188E14E", frintp(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4140E71E", frintx(h1, h2)); + TEST_INSTRUCTION("4140271E", frintx(s1, s2)); + TEST_INSTRUCTION("4140671E", frintx(d1, d2)); + TEST_INSTRUCTION("4198792E", frintx(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4198212E", frintx(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4198796E", frintx(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4198216E", frintx(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4198616E", frintx(v1.d2(), v2.d2())); + TEST_INSTRUCTION("41C0E51E", frintz(h1, h2)); + TEST_INSTRUCTION("41C0251E", frintz(s1, s2)); + TEST_INSTRUCTION("41C0651E", frintz(d1, d2)); + TEST_INSTRUCTION("4198F90E", frintz(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4198A10E", frintz(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4198F94E", frintz(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4198A14E", frintz(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4198E14E", frintz(v1.d2(), v2.d2())); + TEST_INSTRUCTION("41D8F97E", frsqrte(h1, h2)); + TEST_INSTRUCTION("41D8A17E", frsqrte(s1, s2)); + TEST_INSTRUCTION("41D8E17E", frsqrte(d1, d2)); + TEST_INSTRUCTION("41D8F92E", frsqrte(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41D8A12E", frsqrte(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41D8F96E", frsqrte(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41D8A16E", frsqrte(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41D8E16E", frsqrte(v1.d2(), v2.d2())); + TEST_INSTRUCTION("413CC35E", frsqrts(h1, h2, h3)); + TEST_INSTRUCTION("41FCA35E", frsqrts(s1, s2, s3)); + TEST_INSTRUCTION("41FCE35E", frsqrts(d1, d2, d3)); + TEST_INSTRUCTION("413CC30E", frsqrts(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41FCA30E", frsqrts(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("413CC34E", frsqrts(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41FCA34E", frsqrts(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41FCE34E", frsqrts(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41C0E11E", fsqrt(h1, h2)); + TEST_INSTRUCTION("41C0211E", fsqrt(s1, s2)); + TEST_INSTRUCTION("41C0611E", fsqrt(d1, d2)); + TEST_INSTRUCTION("41F8F92E", fsqrt(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41F8A12E", fsqrt(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41F8F96E", fsqrt(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41F8A16E", fsqrt(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41F8E16E", fsqrt(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4138E31E", fsub(h1, h2, h3)); + TEST_INSTRUCTION("4138231E", fsub(s1, s2, s3)); + TEST_INSTRUCTION("4138631E", fsub(d1, d2, d3)); + TEST_INSTRUCTION("4114C30E", fsub(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41D4A30E", fsub(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4114C34E", fsub(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41D4A34E", fsub(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41D4E34E", fsub(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("411C014E", ins(v1.b(0), w2)); + TEST_INSTRUCTION("411C074E", ins(v1.b(3), w2)); + TEST_INSTRUCTION("411C0D4E", ins(v1.b(6), w2)); + TEST_INSTRUCTION("411C134E", ins(v1.b(9), w2)); + TEST_INSTRUCTION("411C1F4E", ins(v1.b(15), w2)); + TEST_INSTRUCTION("411C024E", ins(v1.h(0), w2)); + TEST_INSTRUCTION("411C0E4E", ins(v1.h(3), w2)); + TEST_INSTRUCTION("411C1E4E", ins(v1.h(7), w2)); + TEST_INSTRUCTION("411C044E", ins(v1.s(0), w2)); + TEST_INSTRUCTION("411C0C4E", ins(v1.s(1), w2)); + TEST_INSTRUCTION("411C144E", ins(v1.s(2), w2)); + TEST_INSTRUCTION("411C1C4E", ins(v1.s(3), w2)); + TEST_INSTRUCTION("411C084E", ins(v1.d(0), x2)); + TEST_INSTRUCTION("411C184E", ins(v1.d(1), x2)); + TEST_INSTRUCTION("417C016E", ins(v1.b(0), v2.b(15))); + TEST_INSTRUCTION("4174036E", ins(v1.b(1), v2.b(14))); + TEST_INSTRUCTION("4174026E", ins(v1.h(0), v2.h(7))); + TEST_INSTRUCTION("4164066E", ins(v1.h(1), v2.h(6))); + TEST_INSTRUCTION("4164046E", ins(v1.s(0), v2.s(3))); + TEST_INSTRUCTION("41440C6E", ins(v1.s(1), v2.s(2))); + TEST_INSTRUCTION("4144086E", ins(v1.d(0), v2.d(1))); + TEST_INSTRUCTION("4104186E", ins(v1.d(1), v2.d(0))); + TEST_INSTRUCTION("4100400D", ld1(v1.b(0), ptr(x2))); + TEST_INSTRUCTION("4100DF0D", ld1(v1.b(0), ptr_post(x2, 1))); + TEST_INSTRUCTION("4100CB0D", ld1(v1.b(0), ptr_post(x2, x11))); + TEST_INSTRUCTION("4140400D", ld1(v1.h(0), ptr(x2))); + TEST_INSTRUCTION("4140DF0D", ld1(v1.h(0), ptr_post(x2, 2))); + TEST_INSTRUCTION("4140CB0D", ld1(v1.h(0), ptr_post(x2, x11))); + TEST_INSTRUCTION("4180400D", ld1(v1.s(0), ptr(x2))); + TEST_INSTRUCTION("4180DF0D", ld1(v1.s(0), ptr_post(x2, 4))); + TEST_INSTRUCTION("4180CB0D", ld1(v1.s(0), ptr_post(x2, x11))); + TEST_INSTRUCTION("4184400D", ld1(v1.d(0), ptr(x2))); + TEST_INSTRUCTION("4184DF0D", ld1(v1.d(0), ptr_post(x2, 8))); + TEST_INSTRUCTION("4184CB0D", ld1(v1.d(0), ptr_post(x2, x11))); + TEST_INSTRUCTION("411C404D", ld1(v1.b(15), ptr(x2))); + TEST_INSTRUCTION("411CDF4D", ld1(v1.b(15), ptr_post(x2, 1))); + TEST_INSTRUCTION("411CCB4D", ld1(v1.b(15), ptr_post(x2, x11))); + TEST_INSTRUCTION("4158404D", ld1(v1.h(7), ptr(x2))); + TEST_INSTRUCTION("4158DF4D", ld1(v1.h(7), ptr_post(x2, 2))); + TEST_INSTRUCTION("4158CB4D", ld1(v1.h(7), ptr_post(x2, x11))); + TEST_INSTRUCTION("4190404D", ld1(v1.s(3), ptr(x2))); + TEST_INSTRUCTION("4190DF4D", ld1(v1.s(3), ptr_post(x2, 4))); + TEST_INSTRUCTION("4190CB4D", ld1(v1.s(3), ptr_post(x2, x11))); + TEST_INSTRUCTION("4184404D", ld1(v1.d(1), ptr(x2))); + TEST_INSTRUCTION("4184DF4D", ld1(v1.d(1), ptr_post(x2, 8))); + TEST_INSTRUCTION("4184CB4D", ld1(v1.d(1), ptr_post(x2, x11))); + TEST_INSTRUCTION("4170400C", ld1(v1.b8(), ptr(x2))); + TEST_INSTRUCTION("4170DF0C", ld1(v1.b8(), ptr_post(x2, 8))); + TEST_INSTRUCTION("4170404C", ld1(v1.b16(), ptr(x2))); + TEST_INSTRUCTION("4170DF4C", ld1(v1.b16(), ptr_post(x2, 16))); + TEST_INSTRUCTION("61A0400C", ld1(v1.b8(), v2.b8(), ptr(x3))); + TEST_INSTRUCTION("61A0DF0C", ld1(v1.b8(), v2.b8(), ptr_post(x3, 16))); + TEST_INSTRUCTION("61A0404C", ld1(v1.b16(), v2.b16(), ptr(x3))); + TEST_INSTRUCTION("61A0DF4C", ld1(v1.b16(), v2.b16(), ptr_post(x3, 32))); + TEST_INSTRUCTION("8160400C", ld1(v1.b8(), v2.b8(), v3.b8(), ptr(x4))); + TEST_INSTRUCTION("8160DF0C", ld1(v1.b8(), v2.b8(), v3.b8(), ptr_post(x4, 24))); + TEST_INSTRUCTION("8160404C", ld1(v1.b16(), v2.b16(), v3.b16(), ptr(x4))); + TEST_INSTRUCTION("8160DF4C", ld1(v1.b16(), v2.b16(), v3.b16(), ptr_post(x4, 48))); + TEST_INSTRUCTION("A120400C", ld1(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr(x5))); + TEST_INSTRUCTION("A120DF0C", ld1(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A120404C", ld1(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr(x5))); + TEST_INSTRUCTION("A120DF4C", ld1(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr_post(x5, 64))); + TEST_INSTRUCTION("4174400C", ld1(v1.h4(), ptr(x2))); + TEST_INSTRUCTION("4174DF0C", ld1(v1.h4(), ptr_post(x2, 8))); + TEST_INSTRUCTION("4174404C", ld1(v1.h8(), ptr(x2))); + TEST_INSTRUCTION("4174DF4C", ld1(v1.h8(), ptr_post(x2, 16))); + TEST_INSTRUCTION("61A4400C", ld1(v1.h4(), v2.h4(), ptr(x3))); + TEST_INSTRUCTION("61A4DF0C", ld1(v1.h4(), v2.h4(), ptr_post(x3, 16))); + TEST_INSTRUCTION("61A4404C", ld1(v1.h8(), v2.h8(), ptr(x3))); + TEST_INSTRUCTION("61A4DF4C", ld1(v1.h8(), v2.h8(), ptr_post(x3, 32))); + TEST_INSTRUCTION("8164400C", ld1(v1.h4(), v2.h4(), v3.h4(), ptr(x4))); + TEST_INSTRUCTION("8164DF0C", ld1(v1.h4(), v2.h4(), v3.h4(), ptr_post(x4, 24))); + TEST_INSTRUCTION("8164404C", ld1(v1.h8(), v2.h8(), v3.h8(), ptr(x4))); + TEST_INSTRUCTION("8164DF4C", ld1(v1.h8(), v2.h8(), v3.h8(), ptr_post(x4, 48))); + TEST_INSTRUCTION("A124400C", ld1(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr(x5))); + TEST_INSTRUCTION("A124DF0C", ld1(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A124404C", ld1(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr(x5))); + TEST_INSTRUCTION("A124DF4C", ld1(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr_post(x5, 64))); + TEST_INSTRUCTION("4178400C", ld1(v1.s2(), ptr(x2))); + TEST_INSTRUCTION("4178DF0C", ld1(v1.s2(), ptr_post(x2, 8))); + TEST_INSTRUCTION("4178404C", ld1(v1.s4(), ptr(x2))); + TEST_INSTRUCTION("4178DF4C", ld1(v1.s4(), ptr_post(x2, 16))); + TEST_INSTRUCTION("61A8400C", ld1(v1.s2(), v2.s2(), ptr(x3))); + TEST_INSTRUCTION("61A8DF0C", ld1(v1.s2(), v2.s2(), ptr_post(x3, 16))); + TEST_INSTRUCTION("61A8404C", ld1(v1.s4(), v2.s4(), ptr(x3))); + TEST_INSTRUCTION("61A8DF4C", ld1(v1.s4(), v2.s4(), ptr_post(x3, 32))); + TEST_INSTRUCTION("8168400C", ld1(v1.s2(), v2.s2(), v3.s2(), ptr(x4))); + TEST_INSTRUCTION("8168DF0C", ld1(v1.s2(), v2.s2(), v3.s2(), ptr_post(x4, 24))); + TEST_INSTRUCTION("8168404C", ld1(v1.s4(), v2.s4(), v3.s4(), ptr(x4))); + TEST_INSTRUCTION("8168DF4C", ld1(v1.s4(), v2.s4(), v3.s4(), ptr_post(x4, 48))); + TEST_INSTRUCTION("A128400C", ld1(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr(x5))); + TEST_INSTRUCTION("A128DF0C", ld1(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A128404C", ld1(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr(x5))); + TEST_INSTRUCTION("A128DF4C", ld1(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr_post(x5, 64))); + TEST_INSTRUCTION("417C404C", ld1(v1.d2(), ptr(x2))); + TEST_INSTRUCTION("417CDF4C", ld1(v1.d2(), ptr_post(x2, 16))); + TEST_INSTRUCTION("61AC404C", ld1(v1.d2(), v2.d2(), ptr(x3))); + TEST_INSTRUCTION("61ACDF4C", ld1(v1.d2(), v2.d2(), ptr_post(x3, 32))); + TEST_INSTRUCTION("816C404C", ld1(v1.d2(), v2.d2(), v3.d2(), ptr(x4))); + TEST_INSTRUCTION("816CDF4C", ld1(v1.d2(), v2.d2(), v3.d2(), ptr_post(x4, 48))); + TEST_INSTRUCTION("A12C404C", ld1(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr(x5))); + TEST_INSTRUCTION("A12CDF4C", ld1(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr_post(x5, 64))); + TEST_INSTRUCTION("41C0400D", ld1r(v1.b8(), ptr(x2))); + TEST_INSTRUCTION("41C0DF0D", ld1r(v1.b8(), ptr_post(x2, 1))); + TEST_INSTRUCTION("41C0CB0D", ld1r(v1.b8(), ptr_post(x2, x11))); + TEST_INSTRUCTION("41C0404D", ld1r(v1.b16(), ptr(x2))); + TEST_INSTRUCTION("41C0DF4D", ld1r(v1.b16(), ptr_post(x2, 1))); + TEST_INSTRUCTION("41C0CB4D", ld1r(v1.b16(), ptr_post(x2, x11))); + TEST_INSTRUCTION("41C4400D", ld1r(v1.h4(), ptr(x2))); + TEST_INSTRUCTION("41C4DF0D", ld1r(v1.h4(), ptr_post(x2, 2))); + TEST_INSTRUCTION("41C4CB0D", ld1r(v1.h4(), ptr_post(x2, x11))); + TEST_INSTRUCTION("41C4404D", ld1r(v1.h8(), ptr(x2))); + TEST_INSTRUCTION("41C4DF4D", ld1r(v1.h8(), ptr_post(x2, 2))); + TEST_INSTRUCTION("41C4CB4D", ld1r(v1.h8(), ptr_post(x2, x11))); + TEST_INSTRUCTION("41C8400D", ld1r(v1.s2(), ptr(x2))); + TEST_INSTRUCTION("41C8DF0D", ld1r(v1.s2(), ptr_post(x2, 4))); + TEST_INSTRUCTION("41C8CB0D", ld1r(v1.s2(), ptr_post(x2, x11))); + TEST_INSTRUCTION("41C8404D", ld1r(v1.s4(), ptr(x2))); + TEST_INSTRUCTION("41C8DF4D", ld1r(v1.s4(), ptr_post(x2, 4))); + TEST_INSTRUCTION("41C8CB4D", ld1r(v1.s4(), ptr_post(x2, x11))); + TEST_INSTRUCTION("41CC404D", ld1r(v1.d2(), ptr(x2))); + TEST_INSTRUCTION("41CCDF4D", ld1r(v1.d2(), ptr_post(x2, 8))); + TEST_INSTRUCTION("41CCCB4D", ld1r(v1.d2(), ptr_post(x2, x11))); + TEST_INSTRUCTION("6100600D", ld2(v1.b(0), v2.b(0), ptr(x3))); + TEST_INSTRUCTION("6100FF0D", ld2(v1.b(0), v2.b(0), ptr_post(x3, 2))); + TEST_INSTRUCTION("6100EB0D", ld2(v1.b(0), v2.b(0), ptr_post(x3, x11))); + TEST_INSTRUCTION("6140600D", ld2(v1.h(0), v2.h(0), ptr(x3))); + TEST_INSTRUCTION("6140FF0D", ld2(v1.h(0), v2.h(0), ptr_post(x3, 4))); + TEST_INSTRUCTION("6140EB0D", ld2(v1.h(0), v2.h(0), ptr_post(x3, x11))); + TEST_INSTRUCTION("6180600D", ld2(v1.s(0), v2.s(0), ptr(x3))); + TEST_INSTRUCTION("6180FF0D", ld2(v1.s(0), v2.s(0), ptr_post(x3, 8))); + TEST_INSTRUCTION("6180EB0D", ld2(v1.s(0), v2.s(0), ptr_post(x3, x11))); + TEST_INSTRUCTION("6184600D", ld2(v1.d(0), v2.d(0), ptr(x3))); + TEST_INSTRUCTION("6184FF0D", ld2(v1.d(0), v2.d(0), ptr_post(x3, 16))); + TEST_INSTRUCTION("6184EB0D", ld2(v1.d(0), v2.d(0), ptr_post(x3, x11))); + TEST_INSTRUCTION("611C604D", ld2(v1.b(15), v2.b(15), ptr(x3))); + TEST_INSTRUCTION("611CFF4D", ld2(v1.b(15), v2.b(15), ptr_post(x3, 2))); + TEST_INSTRUCTION("611CEB4D", ld2(v1.b(15), v2.b(15), ptr_post(x3, x11))); + TEST_INSTRUCTION("6158604D", ld2(v1.h(7), v2.h(7), ptr(x3))); + TEST_INSTRUCTION("6158FF4D", ld2(v1.h(7), v2.h(7), ptr_post(x3, 4))); + TEST_INSTRUCTION("6158EB4D", ld2(v1.h(7), v2.h(7), ptr_post(x3, x11))); + TEST_INSTRUCTION("6190604D", ld2(v1.s(3), v2.s(3), ptr(x3))); + TEST_INSTRUCTION("6190FF4D", ld2(v1.s(3), v2.s(3), ptr_post(x3, 8))); + TEST_INSTRUCTION("6190EB4D", ld2(v1.s(3), v2.s(3), ptr_post(x3, x11))); + TEST_INSTRUCTION("6184604D", ld2(v1.d(1), v2.d(1), ptr(x3))); + TEST_INSTRUCTION("6184FF4D", ld2(v1.d(1), v2.d(1), ptr_post(x3, 16))); + TEST_INSTRUCTION("6184EB4D", ld2(v1.d(1), v2.d(1), ptr_post(x3, x11))); + TEST_INSTRUCTION("6180400C", ld2(v1.b8(), v2.b8(), ptr(x3))); + TEST_INSTRUCTION("6180DF0C", ld2(v1.b8(), v2.b8(), ptr_post(x3, 16))); + TEST_INSTRUCTION("6180CB0C", ld2(v1.b8(), v2.b8(), ptr_post(x3, x11))); + TEST_INSTRUCTION("6180404C", ld2(v1.b16(), v2.b16(), ptr(x3))); + TEST_INSTRUCTION("6180DF4C", ld2(v1.b16(), v2.b16(), ptr_post(x3, 32))); + TEST_INSTRUCTION("6180CB4C", ld2(v1.b16(), v2.b16(), ptr_post(x3, x11))); + TEST_INSTRUCTION("6184400C", ld2(v1.h4(), v2.h4(), ptr(x3))); + TEST_INSTRUCTION("6184DF0C", ld2(v1.h4(), v2.h4(), ptr_post(x3, 16))); + TEST_INSTRUCTION("6184CB0C", ld2(v1.h4(), v2.h4(), ptr_post(x3, x11))); + TEST_INSTRUCTION("6184404C", ld2(v1.h8(), v2.h8(), ptr(x3))); + TEST_INSTRUCTION("6184DF4C", ld2(v1.h8(), v2.h8(), ptr_post(x3, 32))); + TEST_INSTRUCTION("6184CB4C", ld2(v1.h8(), v2.h8(), ptr_post(x3, x11))); + TEST_INSTRUCTION("6188400C", ld2(v1.s2(), v2.s2(), ptr(x3))); + TEST_INSTRUCTION("6188DF0C", ld2(v1.s2(), v2.s2(), ptr_post(x3, 16))); + TEST_INSTRUCTION("6188CB0C", ld2(v1.s2(), v2.s2(), ptr_post(x3, x11))); + TEST_INSTRUCTION("6188404C", ld2(v1.s4(), v2.s4(), ptr(x3))); + TEST_INSTRUCTION("6188DF4C", ld2(v1.s4(), v2.s4(), ptr_post(x3, 32))); + TEST_INSTRUCTION("6188CB4C", ld2(v1.s4(), v2.s4(), ptr_post(x3, x11))); + TEST_INSTRUCTION("618C404C", ld2(v1.d2(), v2.d2(), ptr(x3))); + TEST_INSTRUCTION("618CDF4C", ld2(v1.d2(), v2.d2(), ptr_post(x3, 32))); + TEST_INSTRUCTION("618CCB4C", ld2(v1.d2(), v2.d2(), ptr_post(x3, x11))); + TEST_INSTRUCTION("61C0600D", ld2r(v1.b8(), v2.b8(), ptr(x3))); + TEST_INSTRUCTION("61C0FF0D", ld2r(v1.b8(), v2.b8(), ptr_post(x3, 2))); + TEST_INSTRUCTION("61C0EB0D", ld2r(v1.b8(), v2.b8(), ptr_post(x3, x11))); + TEST_INSTRUCTION("61C0604D", ld2r(v1.b16(), v2.b16(), ptr(x3))); + TEST_INSTRUCTION("61C0FF4D", ld2r(v1.b16(), v2.b16(), ptr_post(x3, 2))); + TEST_INSTRUCTION("61C0EB4D", ld2r(v1.b16(), v2.b16(), ptr_post(x3, x11))); + TEST_INSTRUCTION("61C4600D", ld2r(v1.h4(), v2.h4(), ptr(x3))); + TEST_INSTRUCTION("61C4FF0D", ld2r(v1.h4(), v2.h4(), ptr_post(x3, 4))); + TEST_INSTRUCTION("61C4EB0D", ld2r(v1.h4(), v2.h4(), ptr_post(x3, x11))); + TEST_INSTRUCTION("61C4604D", ld2r(v1.h8(), v2.h8(), ptr(x3))); + TEST_INSTRUCTION("61C4FF4D", ld2r(v1.h8(), v2.h8(), ptr_post(x3, 4))); + TEST_INSTRUCTION("61C4EB4D", ld2r(v1.h8(), v2.h8(), ptr_post(x3, x11))); + TEST_INSTRUCTION("61C8600D", ld2r(v1.s2(), v2.s2(), ptr(x3))); + TEST_INSTRUCTION("61C8FF0D", ld2r(v1.s2(), v2.s2(), ptr_post(x3, 8))); + TEST_INSTRUCTION("61C8EB0D", ld2r(v1.s2(), v2.s2(), ptr_post(x3, x11))); + TEST_INSTRUCTION("61C8604D", ld2r(v1.s4(), v2.s4(), ptr(x3))); + TEST_INSTRUCTION("61C8FF4D", ld2r(v1.s4(), v2.s4(), ptr_post(x3, 8))); + TEST_INSTRUCTION("61C8EB4D", ld2r(v1.s4(), v2.s4(), ptr_post(x3, x11))); + TEST_INSTRUCTION("61CC604D", ld2r(v1.d2(), v2.d2(), ptr(x3))); + TEST_INSTRUCTION("61CCFF4D", ld2r(v1.d2(), v2.d2(), ptr_post(x3, 16))); + TEST_INSTRUCTION("61CCEB4D", ld2r(v1.d2(), v2.d2(), ptr_post(x3, x11))); + TEST_INSTRUCTION("8120400D", ld3(v1.b(0), v2.b(0), v3.b(0), ptr(x4))); + TEST_INSTRUCTION("8120DF0D", ld3(v1.b(0), v2.b(0), v3.b(0), ptr_post(x4, 3))); + TEST_INSTRUCTION("8120CB0D", ld3(v1.b(0), v2.b(0), v3.b(0), ptr_post(x4, x11))); + TEST_INSTRUCTION("8160400D", ld3(v1.h(0), v2.h(0), v3.h(0), ptr(x4))); + TEST_INSTRUCTION("8160DF0D", ld3(v1.h(0), v2.h(0), v3.h(0), ptr_post(x4, 6))); + TEST_INSTRUCTION("8160CB0D", ld3(v1.h(0), v2.h(0), v3.h(0), ptr_post(x4, x11))); + TEST_INSTRUCTION("81A0400D", ld3(v1.s(0), v2.s(0), v3.s(0), ptr(x4))); + TEST_INSTRUCTION("81A0DF0D", ld3(v1.s(0), v2.s(0), v3.s(0), ptr_post(x4, 12))); + TEST_INSTRUCTION("81A0CB0D", ld3(v1.s(0), v2.s(0), v3.s(0), ptr_post(x4, x11))); + TEST_INSTRUCTION("81A4400D", ld3(v1.d(0), v2.d(0), v3.d(0), ptr(x4))); + TEST_INSTRUCTION("81A4DF0D", ld3(v1.d(0), v2.d(0), v3.d(0), ptr_post(x4, 24))); + TEST_INSTRUCTION("81A4CB0D", ld3(v1.d(0), v2.d(0), v3.d(0), ptr_post(x4, x11))); + TEST_INSTRUCTION("813C404D", ld3(v1.b(15), v2.b(15), v3.b(15), ptr(x4))); + TEST_INSTRUCTION("813CDF4D", ld3(v1.b(15), v2.b(15), v3.b(15), ptr_post(x4, 3))); + TEST_INSTRUCTION("813CCB4D", ld3(v1.b(15), v2.b(15), v3.b(15), ptr_post(x4, x11))); + TEST_INSTRUCTION("8178404D", ld3(v1.h(7), v2.h(7), v3.h(7), ptr(x4))); + TEST_INSTRUCTION("8178DF4D", ld3(v1.h(7), v2.h(7), v3.h(7), ptr_post(x4, 6))); + TEST_INSTRUCTION("8178CB4D", ld3(v1.h(7), v2.h(7), v3.h(7), ptr_post(x4, x11))); + TEST_INSTRUCTION("81B0404D", ld3(v1.s(3), v2.s(3), v3.s(3), ptr(x4))); + TEST_INSTRUCTION("81B0DF4D", ld3(v1.s(3), v2.s(3), v3.s(3), ptr_post(x4, 12))); + TEST_INSTRUCTION("81B0CB4D", ld3(v1.s(3), v2.s(3), v3.s(3), ptr_post(x4, x11))); + TEST_INSTRUCTION("81A4404D", ld3(v1.d(1), v2.d(1), v3.d(1), ptr(x4))); + TEST_INSTRUCTION("81A4DF4D", ld3(v1.d(1), v2.d(1), v3.d(1), ptr_post(x4, 24))); + TEST_INSTRUCTION("81A4CB4D", ld3(v1.d(1), v2.d(1), v3.d(1), ptr_post(x4, x11))); + TEST_INSTRUCTION("8140400C", ld3(v1.b8(), v2.b8(), v3.b8(), ptr(x4))); + TEST_INSTRUCTION("8140DF0C", ld3(v1.b8(), v2.b8(), v3.b8(), ptr_post(x4, 24))); + TEST_INSTRUCTION("8140CB0C", ld3(v1.b8(), v2.b8(), v3.b8(), ptr_post(x4, x11))); + TEST_INSTRUCTION("8140404C", ld3(v1.b16(), v2.b16(), v3.b16(), ptr(x4))); + TEST_INSTRUCTION("8140DF4C", ld3(v1.b16(), v2.b16(), v3.b16(), ptr_post(x4, 48))); + TEST_INSTRUCTION("8140CB4C", ld3(v1.b16(), v2.b16(), v3.b16(), ptr_post(x4, x11))); + TEST_INSTRUCTION("8144400C", ld3(v1.h4(), v2.h4(), v3.h4(), ptr(x4))); + TEST_INSTRUCTION("8144DF0C", ld3(v1.h4(), v2.h4(), v3.h4(), ptr_post(x4, 24))); + TEST_INSTRUCTION("8144CB0C", ld3(v1.h4(), v2.h4(), v3.h4(), ptr_post(x4, x11))); + TEST_INSTRUCTION("8144404C", ld3(v1.h8(), v2.h8(), v3.h8(), ptr(x4))); + TEST_INSTRUCTION("8144DF4C", ld3(v1.h8(), v2.h8(), v3.h8(), ptr_post(x4, 48))); + TEST_INSTRUCTION("8144CB4C", ld3(v1.h8(), v2.h8(), v3.h8(), ptr_post(x4, x11))); + TEST_INSTRUCTION("8148400C", ld3(v1.s2(), v2.s2(), v3.s2(), ptr(x4))); + TEST_INSTRUCTION("8148DF0C", ld3(v1.s2(), v2.s2(), v3.s2(), ptr_post(x4, 24))); + TEST_INSTRUCTION("8148CB0C", ld3(v1.s2(), v2.s2(), v3.s2(), ptr_post(x4, x11))); + TEST_INSTRUCTION("8148404C", ld3(v1.s4(), v2.s4(), v3.s4(), ptr(x4))); + TEST_INSTRUCTION("8148DF4C", ld3(v1.s4(), v2.s4(), v3.s4(), ptr_post(x4, 48))); + TEST_INSTRUCTION("8148CB4C", ld3(v1.s4(), v2.s4(), v3.s4(), ptr_post(x4, x11))); + TEST_INSTRUCTION("814C404C", ld3(v1.d2(), v2.d2(), v3.d2(), ptr(x4))); + TEST_INSTRUCTION("814CDF4C", ld3(v1.d2(), v2.d2(), v3.d2(), ptr_post(x4, 48))); + TEST_INSTRUCTION("814CCB4C", ld3(v1.d2(), v2.d2(), v3.d2(), ptr_post(x4, x11))); + TEST_INSTRUCTION("81E0400D", ld3r(v1.b8(), v2.b8(), v3.b8(), ptr(x4))); + TEST_INSTRUCTION("81E0DF0D", ld3r(v1.b8(), v2.b8(), v3.b8(), ptr_post(x4, 3))); + TEST_INSTRUCTION("81E0CB0D", ld3r(v1.b8(), v2.b8(), v3.b8(), ptr_post(x4, x11))); + TEST_INSTRUCTION("81E0404D", ld3r(v1.b16(), v2.b16(), v3.b16(), ptr(x4))); + TEST_INSTRUCTION("81E0DF4D", ld3r(v1.b16(), v2.b16(), v3.b16(), ptr_post(x4, 3))); + TEST_INSTRUCTION("81E0CB4D", ld3r(v1.b16(), v2.b16(), v3.b16(), ptr_post(x4, x11))); + TEST_INSTRUCTION("81E4400D", ld3r(v1.h4(), v2.h4(), v3.h4(), ptr(x4))); + TEST_INSTRUCTION("81E4DF0D", ld3r(v1.h4(), v2.h4(), v3.h4(), ptr_post(x4, 6))); + TEST_INSTRUCTION("81E4CB0D", ld3r(v1.h4(), v2.h4(), v3.h4(), ptr_post(x4, x11))); + TEST_INSTRUCTION("81E4404D", ld3r(v1.h8(), v2.h8(), v3.h8(), ptr(x4))); + TEST_INSTRUCTION("81E4DF4D", ld3r(v1.h8(), v2.h8(), v3.h8(), ptr_post(x4, 6))); + TEST_INSTRUCTION("81E4CB4D", ld3r(v1.h8(), v2.h8(), v3.h8(), ptr_post(x4, x11))); + TEST_INSTRUCTION("81E8400D", ld3r(v1.s2(), v2.s2(), v3.s2(), ptr(x4))); + TEST_INSTRUCTION("81E8DF0D", ld3r(v1.s2(), v2.s2(), v3.s2(), ptr_post(x4, 12))); + TEST_INSTRUCTION("81E8CB0D", ld3r(v1.s2(), v2.s2(), v3.s2(), ptr_post(x4, x11))); + TEST_INSTRUCTION("81E8404D", ld3r(v1.s4(), v2.s4(), v3.s4(), ptr(x4))); + TEST_INSTRUCTION("81E8DF4D", ld3r(v1.s4(), v2.s4(), v3.s4(), ptr_post(x4, 12))); + TEST_INSTRUCTION("81E8CB4D", ld3r(v1.s4(), v2.s4(), v3.s4(), ptr_post(x4, x11))); + TEST_INSTRUCTION("81EC404D", ld3r(v1.d2(), v2.d2(), v3.d2(), ptr(x4))); + TEST_INSTRUCTION("81ECDF4D", ld3r(v1.d2(), v2.d2(), v3.d2(), ptr_post(x4, 24))); + TEST_INSTRUCTION("81ECCB4D", ld3r(v1.d2(), v2.d2(), v3.d2(), ptr_post(x4, x11))); + TEST_INSTRUCTION("A120600D", ld4(v1.b(0), v2.b(0), v3.b(0), v4.b(0), ptr(x5))); + TEST_INSTRUCTION("A120FF0D", ld4(v1.b(0), v2.b(0), v3.b(0), v4.b(0), ptr_post(x5, 4))); + TEST_INSTRUCTION("A120EB0D", ld4(v1.b(0), v2.b(0), v3.b(0), v4.b(0), ptr_post(x5, x11))); + TEST_INSTRUCTION("A160600D", ld4(v1.h(0), v2.h(0), v3.h(0), v4.h(0), ptr(x5))); + TEST_INSTRUCTION("A160FF0D", ld4(v1.h(0), v2.h(0), v3.h(0), v4.h(0), ptr_post(x5, 8))); + TEST_INSTRUCTION("A160EB0D", ld4(v1.h(0), v2.h(0), v3.h(0), v4.h(0), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1A0600D", ld4(v1.s(0), v2.s(0), v3.s(0), v4.s(0), ptr(x5))); + TEST_INSTRUCTION("A1A0FF0D", ld4(v1.s(0), v2.s(0), v3.s(0), v4.s(0), ptr_post(x5, 16))); + TEST_INSTRUCTION("A1A0EB0D", ld4(v1.s(0), v2.s(0), v3.s(0), v4.s(0), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1A4600D", ld4(v1.d(0), v2.d(0), v3.d(0), v4.d(0), ptr(x5))); + TEST_INSTRUCTION("A1A4FF0D", ld4(v1.d(0), v2.d(0), v3.d(0), v4.d(0), ptr_post(x5, 32))); + TEST_INSTRUCTION("A1A4EB0D", ld4(v1.d(0), v2.d(0), v3.d(0), v4.d(0), ptr_post(x5, x11))); + TEST_INSTRUCTION("A13C604D", ld4(v1.b(15), v2.b(15), v3.b(15), v4.b(15), ptr(x5))); + TEST_INSTRUCTION("A13CFF4D", ld4(v1.b(15), v2.b(15), v3.b(15), v4.b(15), ptr_post(x5, 4))); + TEST_INSTRUCTION("A13CEB4D", ld4(v1.b(15), v2.b(15), v3.b(15), v4.b(15), ptr_post(x5, x11))); + TEST_INSTRUCTION("A178604D", ld4(v1.h(7), v2.h(7), v3.h(7), v4.h(7), ptr(x5))); + TEST_INSTRUCTION("A178FF4D", ld4(v1.h(7), v2.h(7), v3.h(7), v4.h(7), ptr_post(x5, 8))); + TEST_INSTRUCTION("A178EB4D", ld4(v1.h(7), v2.h(7), v3.h(7), v4.h(7), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1B0604D", ld4(v1.s(3), v2.s(3), v3.s(3), v4.s(3), ptr(x5))); + TEST_INSTRUCTION("A1B0FF4D", ld4(v1.s(3), v2.s(3), v3.s(3), v4.s(3), ptr_post(x5, 16))); + TEST_INSTRUCTION("A1B0EB4D", ld4(v1.s(3), v2.s(3), v3.s(3), v4.s(3), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1A4604D", ld4(v1.d(1), v2.d(1), v3.d(1), v4.d(1), ptr(x5))); + TEST_INSTRUCTION("A1A4FF4D", ld4(v1.d(1), v2.d(1), v3.d(1), v4.d(1), ptr_post(x5, 32))); + TEST_INSTRUCTION("A1A4EB4D", ld4(v1.d(1), v2.d(1), v3.d(1), v4.d(1), ptr_post(x5, x11))); + TEST_INSTRUCTION("A100400C", ld4(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr(x5))); + TEST_INSTRUCTION("A100DF0C", ld4(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A100CB0C", ld4(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A100404C", ld4(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr(x5))); + TEST_INSTRUCTION("A100DF4C", ld4(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr_post(x5, 64))); + TEST_INSTRUCTION("A100CB4C", ld4(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A104400C", ld4(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr(x5))); + TEST_INSTRUCTION("A104DF0C", ld4(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A104CB0C", ld4(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A104404C", ld4(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr(x5))); + TEST_INSTRUCTION("A104DF4C", ld4(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr_post(x5, 64))); + TEST_INSTRUCTION("A104CB4C", ld4(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A108400C", ld4(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr(x5))); + TEST_INSTRUCTION("A108DF0C", ld4(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A108CB0C", ld4(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A108404C", ld4(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr(x5))); + TEST_INSTRUCTION("A108DF4C", ld4(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr_post(x5, 64))); + TEST_INSTRUCTION("A108CB4C", ld4(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A10C404C", ld4(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr(x5))); + TEST_INSTRUCTION("A10CDF4C", ld4(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr_post(x5, 64))); + TEST_INSTRUCTION("A10CCB4C", ld4(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1E0600D", ld4r(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr(x5))); + TEST_INSTRUCTION("A1E0FF0D", ld4r(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr_post(x5, 4))); + TEST_INSTRUCTION("A1E0EB0D", ld4r(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1E0604D", ld4r(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr(x5))); + TEST_INSTRUCTION("A1E0FF4D", ld4r(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr_post(x5, 4))); + TEST_INSTRUCTION("A1E0EB4D", ld4r(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1E4600D", ld4r(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr(x5))); + TEST_INSTRUCTION("A1E4FF0D", ld4r(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr_post(x5, 8))); + TEST_INSTRUCTION("A1E4EB0D", ld4r(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1E4604D", ld4r(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr(x5))); + TEST_INSTRUCTION("A1E4FF4D", ld4r(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr_post(x5, 8))); + TEST_INSTRUCTION("A1E4EB4D", ld4r(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1E8600D", ld4r(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr(x5))); + TEST_INSTRUCTION("A1E8FF0D", ld4r(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr_post(x5, 16))); + TEST_INSTRUCTION("A1E8EB0D", ld4r(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1E8604D", ld4r(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr(x5))); + TEST_INSTRUCTION("A1E8FF4D", ld4r(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr_post(x5, 16))); + TEST_INSTRUCTION("A1E8EB4D", ld4r(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1EC604D", ld4r(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr(x5))); + TEST_INSTRUCTION("A1ECFF4D", ld4r(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A1ECEB4D", ld4r(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr_post(x5, x11))); + TEST_INSTRUCTION("8109402C", ldnp(s1, s2, ptr(x12))); + TEST_INSTRUCTION("8189402C", ldnp(s1, s2, ptr(x12, 4))); + TEST_INSTRUCTION("8109702C", ldnp(s1, s2, ptr(x12, -128))); + TEST_INSTRUCTION("E10B402C", ldnp(s1, s2, ptr(sp))); + TEST_INSTRUCTION("E18B402C", ldnp(s1, s2, ptr(sp, 4))); + TEST_INSTRUCTION("E10B502C", ldnp(s1, s2, ptr(sp, 128))); + TEST_INSTRUCTION("8109406C", ldnp(d1, d2, ptr(x12))); + TEST_INSTRUCTION("8189406C", ldnp(d1, d2, ptr(x12, 8))); + TEST_INSTRUCTION("8109786C", ldnp(d1, d2, ptr(x12, -128))); + TEST_INSTRUCTION("E10B406C", ldnp(d1, d2, ptr(sp))); + TEST_INSTRUCTION("E18B406C", ldnp(d1, d2, ptr(sp, 8))); + TEST_INSTRUCTION("E10B486C", ldnp(d1, d2, ptr(sp, 128))); + TEST_INSTRUCTION("810940AC", ldnp(q1, q2, ptr(x12))); + TEST_INSTRUCTION("818940AC", ldnp(q1, q2, ptr(x12, 16))); + TEST_INSTRUCTION("81097CAC", ldnp(q1, q2, ptr(x12, -128))); + TEST_INSTRUCTION("E10B40AC", ldnp(q1, q2, ptr(sp))); + TEST_INSTRUCTION("E18B40AC", ldnp(q1, q2, ptr(sp, 16))); + TEST_INSTRUCTION("E10B44AC", ldnp(q1, q2, ptr(sp, 128))); + TEST_INSTRUCTION("8109402D", ldp(s1, s2, ptr(x12))); + TEST_INSTRUCTION("8189402D", ldp(s1, s2, ptr(x12, 4))); + TEST_INSTRUCTION("8109702D", ldp(s1, s2, ptr(x12, -128))); + TEST_INSTRUCTION("8189C02D", ldp(s1, s2, ptr_pre(x12, 4))); + TEST_INSTRUCTION("8189C02C", ldp(s1, s2, ptr_post(x12, 4))); + TEST_INSTRUCTION("E10B402D", ldp(s1, s2, ptr(sp))); + TEST_INSTRUCTION("E18B402D", ldp(s1, s2, ptr(sp, 4))); + TEST_INSTRUCTION("E10B502D", ldp(s1, s2, ptr(sp, 128))); + TEST_INSTRUCTION("E18BC02C", ldp(s1, s2, ptr_post(sp, 4))); + TEST_INSTRUCTION("E18BC02D", ldp(s1, s2, ptr_pre(sp, 4))); + TEST_INSTRUCTION("8109406D", ldp(d1, d2, ptr(x12))); + TEST_INSTRUCTION("8189406D", ldp(d1, d2, ptr(x12, 8))); + TEST_INSTRUCTION("8109786D", ldp(d1, d2, ptr(x12, -128))); + TEST_INSTRUCTION("8189C06D", ldp(d1, d2, ptr_pre(x12, 8))); + TEST_INSTRUCTION("8189C06C", ldp(d1, d2, ptr_post(x12, 8))); + TEST_INSTRUCTION("E10B406D", ldp(d1, d2, ptr(sp))); + TEST_INSTRUCTION("E18B406D", ldp(d1, d2, ptr(sp, 8))); + TEST_INSTRUCTION("E10B486D", ldp(d1, d2, ptr(sp, 128))); + TEST_INSTRUCTION("E18BC06D", ldp(d1, d2, ptr_pre(sp, 8))); + TEST_INSTRUCTION("E18BC06C", ldp(d1, d2, ptr_post(sp, 8))); + TEST_INSTRUCTION("810940AD", ldp(q1, q2, ptr(x12))); + TEST_INSTRUCTION("818940AD", ldp(q1, q2, ptr(x12, 16))); + TEST_INSTRUCTION("81097CAD", ldp(q1, q2, ptr(x12, -128))); + TEST_INSTRUCTION("8189C0AD", ldp(q1, q2, ptr_pre(x12, 16))); + TEST_INSTRUCTION("8189C0AC", ldp(q1, q2, ptr_post(x12, 16))); + TEST_INSTRUCTION("E10B40AD", ldp(q1, q2, ptr(sp))); + TEST_INSTRUCTION("E18B40AD", ldp(q1, q2, ptr(sp, 16))); + TEST_INSTRUCTION("E10B44AD", ldp(q1, q2, ptr(sp, 128))); + TEST_INSTRUCTION("E18BC0AD", ldp(q1, q2, ptr_pre(sp, 16))); + TEST_INSTRUCTION("E18BC0AC", ldp(q1, q2, ptr_post(sp, 16))); + TEST_INSTRUCTION("4100403D", ldr(b1, ptr(x2))); + TEST_INSTRUCTION("4114403C", ldr(b1, ptr_post(x2, 1))); + TEST_INSTRUCTION("4104403D", ldr(b1, ptr(x2, 1))); + TEST_INSTRUCTION("411C403C", ldr(b1, ptr_pre(x2, 1))); + TEST_INSTRUCTION("4114483C", ldr(b1, ptr_post(x2, 129))); + TEST_INSTRUCTION("4100407D", ldr(h1, ptr(x2))); + TEST_INSTRUCTION("4124407C", ldr(h1, ptr_post(x2, 2))); + TEST_INSTRUCTION("4104407D", ldr(h1, ptr(x2, 2))); + TEST_INSTRUCTION("412C407C", ldr(h1, ptr_pre(x2, 2))); + TEST_INSTRUCTION("4124487C", ldr(h1, ptr_post(x2, 130))); + TEST_INSTRUCTION("410040BD", ldr(s1, ptr(x2))); + TEST_INSTRUCTION("414440BC", ldr(s1, ptr_post(x2, 4))); + TEST_INSTRUCTION("410440BD", ldr(s1, ptr(x2, 4))); + TEST_INSTRUCTION("414C40BC", ldr(s1, ptr_pre(x2, 4))); + TEST_INSTRUCTION("414448BC", ldr(s1, ptr_post(x2, 132))); + TEST_INSTRUCTION("410040FD", ldr(d1, ptr(x2))); + TEST_INSTRUCTION("418440FC", ldr(d1, ptr_post(x2, 8))); + TEST_INSTRUCTION("410440FD", ldr(d1, ptr(x2, 8))); + TEST_INSTRUCTION("418C40FC", ldr(d1, ptr_pre(x2, 8))); + TEST_INSTRUCTION("414448FC", ldr(d1, ptr_post(x2, 132))); + TEST_INSTRUCTION("4168633C", ldr(b1, ptr(x2, x3))); + TEST_INSTRUCTION("4148633C", ldr(b1, ptr(x2, w3, uxtw(0)))); + TEST_INSTRUCTION("41C8633C", ldr(b1, ptr(x2, w3, sxtw(0)))); + TEST_INSTRUCTION("4168637C", ldr(h1, ptr(x2, x3))); + TEST_INSTRUCTION("4178637C", ldr(h1, ptr(x2, x3, lsl(1)))); + TEST_INSTRUCTION("4148637C", ldr(h1, ptr(x2, w3, uxtw(0)))); + TEST_INSTRUCTION("4158637C", ldr(h1, ptr(x2, w3, uxtw(1)))); + TEST_INSTRUCTION("41C8637C", ldr(h1, ptr(x2, w3, sxtw(0)))); + TEST_INSTRUCTION("41D8637C", ldr(h1, ptr(x2, w3, sxtw(1)))); + TEST_INSTRUCTION("416863BC", ldr(s1, ptr(x2, x3))); + TEST_INSTRUCTION("417863BC", ldr(s1, ptr(x2, x3, lsl(2)))); + TEST_INSTRUCTION("414863BC", ldr(s1, ptr(x2, w3, uxtw(0)))); + TEST_INSTRUCTION("415863BC", ldr(s1, ptr(x2, w3, uxtw(2)))); + TEST_INSTRUCTION("41C863BC", ldr(s1, ptr(x2, w3, sxtw(0)))); + TEST_INSTRUCTION("41D863BC", ldr(s1, ptr(x2, w3, sxtw(2)))); + TEST_INSTRUCTION("416863FC", ldr(d1, ptr(x2, x3))); + TEST_INSTRUCTION("417863FC", ldr(d1, ptr(x2, x3, lsl(3)))); + TEST_INSTRUCTION("414863FC", ldr(d1, ptr(x2, w3, uxtw(0)))); + TEST_INSTRUCTION("415863FC", ldr(d1, ptr(x2, w3, uxtw(3)))); + TEST_INSTRUCTION("41C863FC", ldr(d1, ptr(x2, w3, sxtw(0)))); + TEST_INSTRUCTION("41D863FC", ldr(d1, ptr(x2, w3, sxtw(3)))); + TEST_INSTRUCTION("4104403D", ldr(b1, ptr(x2, 1))); + TEST_INSTRUCTION("41F05F3C", ldr(b1, ptr(x2, -1))); // LDUR + TEST_INSTRUCTION("4110407C", ldr(h1, ptr(x2, 1))); // LDUR + TEST_INSTRUCTION("41F05F7C", ldr(h1, ptr(x2, -1))); // LDUR + TEST_INSTRUCTION("411040BC", ldr(s1, ptr(x2, 1))); // LDUR + TEST_INSTRUCTION("41F05FBC", ldr(s1, ptr(x2, -1))); // LDUR + TEST_INSTRUCTION("411040FC", ldr(d1, ptr(x2, 1))); // LDUR + TEST_INSTRUCTION("41F05FFC", ldr(d1, ptr(x2, -1))); // LDUR + TEST_INSTRUCTION("8101403C", ldur(b1, ptr(x12))); + TEST_INSTRUCTION("8131403C", ldur(b1, ptr(x12, 3))); + TEST_INSTRUCTION("8131463C", ldur(b1, ptr(x12, 99))); + TEST_INSTRUCTION("81F14F3C", ldur(b1, ptr(x12, 255))); + TEST_INSTRUCTION("8101503C", ldur(b1, ptr(x12, -256))); + TEST_INSTRUCTION("E103403C", ldur(b1, ptr(sp))); + TEST_INSTRUCTION("E153483C", ldur(b1, ptr(sp, 133))); + TEST_INSTRUCTION("8101407C", ldur(h1, ptr(x12))); + TEST_INSTRUCTION("8131407C", ldur(h1, ptr(x12, 3))); + TEST_INSTRUCTION("8131467C", ldur(h1, ptr(x12, 99))); + TEST_INSTRUCTION("81F14F7C", ldur(h1, ptr(x12, 255))); + TEST_INSTRUCTION("8101507C", ldur(h1, ptr(x12, -256))); + TEST_INSTRUCTION("E103407C", ldur(h1, ptr(sp))); + TEST_INSTRUCTION("E153487C", ldur(h1, ptr(sp, 133))); + TEST_INSTRUCTION("810140BC", ldur(s1, ptr(x12))); + TEST_INSTRUCTION("813140BC", ldur(s1, ptr(x12, 3))); + TEST_INSTRUCTION("813146BC", ldur(s1, ptr(x12, 99))); + TEST_INSTRUCTION("81F14FBC", ldur(s1, ptr(x12, 255))); + TEST_INSTRUCTION("810150BC", ldur(s1, ptr(x12, -256))); + TEST_INSTRUCTION("E10340BC", ldur(s1, ptr(sp))); + TEST_INSTRUCTION("E15348BC", ldur(s1, ptr(sp, 133))); + TEST_INSTRUCTION("810140FC", ldur(d1, ptr(x12))); + TEST_INSTRUCTION("813140FC", ldur(d1, ptr(x12, 3))); + TEST_INSTRUCTION("813146FC", ldur(d1, ptr(x12, 99))); + TEST_INSTRUCTION("81F14FFC", ldur(d1, ptr(x12, 255))); + TEST_INSTRUCTION("810150FC", ldur(d1, ptr(x12, -256))); + TEST_INSTRUCTION("E10340FC", ldur(d1, ptr(sp))); + TEST_INSTRUCTION("E15348FC", ldur(d1, ptr(sp, 133))); + TEST_INSTRUCTION("8101C03C", ldur(q1, ptr(x12))); + TEST_INSTRUCTION("8131C03C", ldur(q1, ptr(x12, 3))); + TEST_INSTRUCTION("8131C63C", ldur(q1, ptr(x12, 99))); + TEST_INSTRUCTION("81F1CF3C", ldur(q1, ptr(x12, 255))); + TEST_INSTRUCTION("8101D03C", ldur(q1, ptr(x12, -256))); + TEST_INSTRUCTION("E103C03C", ldur(q1, ptr(sp))); + TEST_INSTRUCTION("E153C83C", ldur(q1, ptr(sp, 133))); + TEST_INSTRUCTION("4194230E", mla(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4194630E", mla(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4194A30E", mla(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4194234E", mla(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4194634E", mla(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4194A34E", mla(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4100432F", mla(v1.h4(), v2.h4(), v3.h(0))); + TEST_INSTRUCTION("4100532F", mla(v1.h4(), v2.h4(), v3.h(1))); + TEST_INSTRUCTION("4100632F", mla(v1.h4(), v2.h4(), v3.h(2))); + TEST_INSTRUCTION("4100732F", mla(v1.h4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("4108436F", mla(v1.h8(), v2.h8(), v3.h(4))); + TEST_INSTRUCTION("4108536F", mla(v1.h8(), v2.h8(), v3.h(5))); + TEST_INSTRUCTION("4108636F", mla(v1.h8(), v2.h8(), v3.h(6))); + TEST_INSTRUCTION("4108736F", mla(v1.h8(), v2.h8(), v3.h(7))); + TEST_INSTRUCTION("4100832F", mla(v1.s2(), v2.s2(), v3.s(0))); + TEST_INSTRUCTION("4100A32F", mla(v1.s2(), v2.s2(), v3.s(1))); + TEST_INSTRUCTION("4108836F", mla(v1.s4(), v2.s4(), v3.s(2))); + TEST_INSTRUCTION("4108A36F", mla(v1.s4(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("4194232E", mls(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4194632E", mls(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4194A32E", mls(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4194236E", mls(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4194636E", mls(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4194A36E", mls(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4140432F", mls(v1.h4(), v2.h4(), v3.h(0))); + TEST_INSTRUCTION("4140532F", mls(v1.h4(), v2.h4(), v3.h(1))); + TEST_INSTRUCTION("4140632F", mls(v1.h4(), v2.h4(), v3.h(2))); + TEST_INSTRUCTION("4140732F", mls(v1.h4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("4148436F", mls(v1.h8(), v2.h8(), v3.h(4))); + TEST_INSTRUCTION("4148536F", mls(v1.h8(), v2.h8(), v3.h(5))); + TEST_INSTRUCTION("4148636F", mls(v1.h8(), v2.h8(), v3.h(6))); + TEST_INSTRUCTION("4148736F", mls(v1.h8(), v2.h8(), v3.h(7))); + TEST_INSTRUCTION("4140832F", mls(v1.s2(), v2.s2(), v3.s(0))); + TEST_INSTRUCTION("4140A32F", mls(v1.s2(), v2.s2(), v3.s(1))); + TEST_INSTRUCTION("4148836F", mls(v1.s4(), v2.s4(), v3.s(2))); + TEST_INSTRUCTION("4148A36F", mls(v1.s4(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("4F04035E", mov(b15, v2.b(1))); + TEST_INSTRUCTION("4F04065E", mov(h15, v2.h(1))); + TEST_INSTRUCTION("4F040C5E", mov(s15, v2.s(1))); + TEST_INSTRUCTION("4F04185E", mov(d15, v2.d(1))); + TEST_INSTRUCTION("411C014E", mov(v1.b(0), w2)); + TEST_INSTRUCTION("411C074E", mov(v1.b(3), w2)); + TEST_INSTRUCTION("411C0D4E", mov(v1.b(6), w2)); + TEST_INSTRUCTION("411C134E", mov(v1.b(9), w2)); + TEST_INSTRUCTION("411C1F4E", mov(v1.b(15), w2)); + TEST_INSTRUCTION("411C024E", mov(v1.h(0), w2)); + TEST_INSTRUCTION("411C0E4E", mov(v1.h(3), w2)); + TEST_INSTRUCTION("411C1E4E", mov(v1.h(7), w2)); + TEST_INSTRUCTION("411C044E", mov(v1.s(0), w2)); + TEST_INSTRUCTION("411C0C4E", mov(v1.s(1), w2)); + TEST_INSTRUCTION("411C144E", mov(v1.s(2), w2)); + TEST_INSTRUCTION("411C1C4E", mov(v1.s(3), w2)); + TEST_INSTRUCTION("411C084E", mov(v1.d(0), x2)); + TEST_INSTRUCTION("411C184E", mov(v1.d(1), x2)); + TEST_INSTRUCTION("417C016E", mov(v1.b(0), v2.b(15))); + TEST_INSTRUCTION("4174036E", mov(v1.b(1), v2.b(14))); + TEST_INSTRUCTION("4174026E", mov(v1.h(0), v2.h(7))); + TEST_INSTRUCTION("4164066E", mov(v1.h(1), v2.h(6))); + TEST_INSTRUCTION("4164046E", mov(v1.s(0), v2.s(3))); + TEST_INSTRUCTION("41440C6E", mov(v1.s(1), v2.s(2))); + TEST_INSTRUCTION("4144086E", mov(v1.d(0), v2.d(1))); + TEST_INSTRUCTION("4104186E", mov(v1.d(1), v2.d(0))); + TEST_INSTRUCTION("41E5010F", movi(v1.b8(), 42)); + TEST_INSTRUCTION("4185010F", movi(v1.h4(), 42)); + TEST_INSTRUCTION("4105010F", movi(v1.s2(), 42)); + TEST_INSTRUCTION("C1E5022F", movi(d1, 0x00FF0000FFFFFF00u)); + TEST_INSTRUCTION("41E5014F", movi(v1.b16(), 42)); + TEST_INSTRUCTION("4185014F", movi(v1.h8(), 42)); + TEST_INSTRUCTION("4105014F", movi(v1.s4(), 42)); + TEST_INSTRUCTION("E167074F", movi(v1.s4(), 0xFF, lsl(24))); + TEST_INSTRUCTION("E1D7074F", movi(v1.s4(), 0xFF, msl(16))); + TEST_INSTRUCTION("C1E5026F", movi(v1.d2(), 0x00FF0000FFFFFF00u)); + TEST_INSTRUCTION("419C230E", mul(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("419C630E", mul(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("419CA30E", mul(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("419C234E", mul(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("419C634E", mul(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("419CA34E", mul(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4158202E", mvn(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4158206E", mvn(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4185012F", mvni(v1.h4(), 42)); + TEST_INSTRUCTION("4105012F", mvni(v1.s2(), 42)); + TEST_INSTRUCTION("4185016F", mvni(v1.h8(), 42)); + TEST_INSTRUCTION("4105016F", mvni(v1.s4(), 42)); + TEST_INSTRUCTION("41B8202E", neg(v1.b8(), v2.b8())); + TEST_INSTRUCTION("41B8602E", neg(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41B8A02E", neg(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41B8E07E", neg(d1, d2)); + TEST_INSTRUCTION("41B8206E", neg(v1.b16(), v2.b16())); + TEST_INSTRUCTION("41B8606E", neg(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41B8A06E", neg(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41B8E06E", neg(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4158202E", not_(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4158206E", not_(v1.b16(), v2.b16())); + TEST_INSTRUCTION("411CE30E", orn(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("411CE34E", orn(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("411CA30E", orr(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("411CA34E", orr(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("E197070F", orr(v1.h4(), 255)); + TEST_INSTRUCTION("E1B7070F", orr(v1.h4(), 255, lsl(8))); + TEST_INSTRUCTION("E197074F", orr(v1.h8(), 255)); + TEST_INSTRUCTION("E1B7074F", orr(v1.h8(), 255, lsl(8))); + TEST_INSTRUCTION("E117070F", orr(v1.s2(), 255)); + TEST_INSTRUCTION("E137070F", orr(v1.s2(), 255, lsl(8))); + TEST_INSTRUCTION("E117074F", orr(v1.s4(), 255)); + TEST_INSTRUCTION("E177074F", orr(v1.s4(), 255, lsl(24))); + TEST_INSTRUCTION("419C232E", pmul(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("419C236E", pmul(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41E0230E", pmull(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("41E0E30E", pmull(q1, d2, d3)); + TEST_INSTRUCTION("41E0234E", pmull2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41E0E34E", pmull2(q1, v2.d2(), v3.d2())); + TEST_INSTRUCTION("4140232E", raddhn(v1.b8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4140632E", raddhn(v1.h4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4140A32E", raddhn(v1.s2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4140236E", raddhn2(v1.b16(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4140636E", raddhn2(v1.h8(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4140A36E", raddhn2(v1.s4(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("418C63CE", rax1(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4158602E", rbit(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4158606E", rbit(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4118200E", rev16(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4118204E", rev16(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4108202E", rev32(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4108206E", rev32(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4108602E", rev32(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4108606E", rev32(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4108200E", rev64(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4108204E", rev64(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4108600E", rev64(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4108604E", rev64(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4108A00E", rev64(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4108A04E", rev64(v1.s4(), v2.s4())); + TEST_INSTRUCTION("418C090F", rshrn(v1.b8(), v2.h8(), 7)); + TEST_INSTRUCTION("418C110F", rshrn(v1.h4(), v2.s4(), 15)); + TEST_INSTRUCTION("418C210F", rshrn(v1.s2(), v2.d2(), 31)); + TEST_INSTRUCTION("418C094F", rshrn2(v1.b16(), v2.h8(), 7)); + TEST_INSTRUCTION("418C114F", rshrn2(v1.h8(), v2.s4(), 15)); + TEST_INSTRUCTION("418C214F", rshrn2(v1.s4(), v2.d2(), 31)); + TEST_INSTRUCTION("4160232E", rsubhn(v1.b8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4160632E", rsubhn(v1.h4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4160A32E", rsubhn(v1.s2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4160236E", rsubhn2(v1.b16(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4160636E", rsubhn2(v1.h8(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4160A36E", rsubhn2(v1.s4(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("417C230E", saba(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("417C630E", saba(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("417CA30E", saba(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("417C234E", saba(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("417C634E", saba(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("417CA34E", saba(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4150230E", sabal(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4150630E", sabal(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4150A30E", sabal(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4150234E", sabal2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4150634E", sabal2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4150A34E", sabal2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4174230E", sabd(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4174630E", sabd(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4174A30E", sabd(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4174234E", sabd(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4174634E", sabd(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4174A34E", sabd(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4170230E", sabdl(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4170630E", sabdl(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4170A30E", sabdl(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4170234E", sabdl2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4170634E", sabdl2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4170A34E", sabdl2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4168200E", sadalp(v1.h4(), v2.b8())); + TEST_INSTRUCTION("4168600E", sadalp(v1.s2(), v2.h4())); + TEST_INSTRUCTION("4168A00E", sadalp(d1, v2.s2())); + TEST_INSTRUCTION("4168204E", sadalp(v1.h8(), v2.b16())); + TEST_INSTRUCTION("4168604E", sadalp(v1.s4(), v2.h8())); + TEST_INSTRUCTION("4168A04E", sadalp(v1.d2(), v2.s4())); + TEST_INSTRUCTION("4100230E", saddl(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4100630E", saddl(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4100A30E", saddl(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4100234E", saddl2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4100634E", saddl2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4100A34E", saddl2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4128200E", saddlp(v1.h4(), v2.b8())); + TEST_INSTRUCTION("4128600E", saddlp(v1.s2(), v2.h4())); + TEST_INSTRUCTION("4128A00E", saddlp(d1, v2.s2())); + TEST_INSTRUCTION("4128204E", saddlp(v1.h8(), v2.b16())); + TEST_INSTRUCTION("4128604E", saddlp(v1.s4(), v2.h8())); + TEST_INSTRUCTION("4128A04E", saddlp(v1.d2(), v2.s4())); + TEST_INSTRUCTION("4138300E", saddlv(h1, v2.b8())); + TEST_INSTRUCTION("4138304E", saddlv(h1, v2.b16())); + TEST_INSTRUCTION("4138700E", saddlv(s1, v2.h4())); + TEST_INSTRUCTION("4138704E", saddlv(s1, v2.h8())); + TEST_INSTRUCTION("4138B04E", saddlv(d1, v2.s4())); + TEST_INSTRUCTION("4110230E", saddw(v1.h8(), v2.h8(), v3.b8())); + TEST_INSTRUCTION("4110630E", saddw(v1.s4(), v2.s4(), v3.h4())); + TEST_INSTRUCTION("4110A30E", saddw(v1.d2(), v2.d2(), v3.s2())); + TEST_INSTRUCTION("4110234E", saddw2(v1.h8(), v2.h8(), v3.b16())); + TEST_INSTRUCTION("4110634E", saddw2(v1.s4(), v2.s4(), v3.h8())); + TEST_INSTRUCTION("4110A34E", saddw2(v1.d2(), v2.d2(), v3.s4())); + TEST_INSTRUCTION("4100E21E", scvtf(h1, w2)); + TEST_INSTRUCTION("4100221E", scvtf(s1, w2)); + TEST_INSTRUCTION("4100621E", scvtf(d1, w2)); + TEST_INSTRUCTION("4100E29E", scvtf(h1, x2)); + TEST_INSTRUCTION("4100229E", scvtf(s1, x2)); + TEST_INSTRUCTION("4100629E", scvtf(d1, x2)); + TEST_INSTRUCTION("41D8795E", scvtf(h1, h2)); + TEST_INSTRUCTION("41D8215E", scvtf(s1, s2)); + TEST_INSTRUCTION("41D8615E", scvtf(d1, d2)); + TEST_INSTRUCTION("41D8790E", scvtf(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41D8210E", scvtf(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41D8794E", scvtf(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41D8214E", scvtf(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41D8614E", scvtf(v1.d2(), v2.d2())); + TEST_INSTRUCTION("41E0C21E", scvtf(h1, w2, 8)); + TEST_INSTRUCTION("41E0021E", scvtf(s1, w2, 8)); + TEST_INSTRUCTION("41E0421E", scvtf(d1, w2, 8)); + TEST_INSTRUCTION("41E0C29E", scvtf(h1, x2, 8)); + TEST_INSTRUCTION("41E0029E", scvtf(s1, x2, 8)); + TEST_INSTRUCTION("41E0429E", scvtf(d1, x2, 8)); + TEST_INSTRUCTION("41E4185F", scvtf(h1, h2, 8)); + TEST_INSTRUCTION("41E4385F", scvtf(s1, s2, 8)); + TEST_INSTRUCTION("41E4785F", scvtf(d1, d2, 8)); + TEST_INSTRUCTION("41E4180F", scvtf(v1.h4(), v2.h4(), 8)); + TEST_INSTRUCTION("41E4380F", scvtf(v1.s2(), v2.s2(), 8)); + TEST_INSTRUCTION("41E4184F", scvtf(v1.h8(), v2.h8(), 8)); + TEST_INSTRUCTION("41E4384F", scvtf(v1.s4(), v2.s4(), 8)); + TEST_INSTRUCTION("41E4784F", scvtf(v1.d2(), v2.d2(), 8)); + TEST_INSTRUCTION("4194830E", sdot(v1.s2(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4194834E", sdot(v1.s4(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41E0830F", sdot(v1.s2(), v2.b8(), v3.b4(0))); + TEST_INSTRUCTION("41E0A30F", sdot(v1.s2(), v2.b8(), v3.b4(1))); + TEST_INSTRUCTION("41E8830F", sdot(v1.s2(), v2.b8(), v3.b4(2))); + TEST_INSTRUCTION("41E8A30F", sdot(v1.s2(), v2.b8(), v3.b4(3))); + TEST_INSTRUCTION("41E0834F", sdot(v1.s4(), v2.b16(), v3.b4(0))); + TEST_INSTRUCTION("41E0A34F", sdot(v1.s4(), v2.b16(), v3.b4(1))); + TEST_INSTRUCTION("41E8834F", sdot(v1.s4(), v2.b16(), v3.b4(2))); + TEST_INSTRUCTION("41E8A34F", sdot(v1.s4(), v2.b16(), v3.b4(3))); + TEST_INSTRUCTION("4100035E", sha1c(q1, s2, v3.s4())); + TEST_INSTRUCTION("4108285E", sha1h(s1, s2)); + TEST_INSTRUCTION("4120035E", sha1m(q1, s2, v3.s4())); + TEST_INSTRUCTION("4110035E", sha1p(q1, s2, v3.s4())); + TEST_INSTRUCTION("4130035E", sha1su0(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4118285E", sha1su1(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4140035E", sha256h(q1, q2, v3.s4())); + TEST_INSTRUCTION("4150035E", sha256h2(q1, q2, v3.s4())); + TEST_INSTRUCTION("4128285E", sha256su0(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4160035E", sha256su1(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4104230E", shadd(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4104630E", shadd(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4104A30E", shadd(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4104234E", shadd(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4104634E", shadd(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4104A34E", shadd(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41540F0F", shl(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("41541F0F", shl(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("41543F0F", shl(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("41547F5F", shl(d1, d2, 63)); + TEST_INSTRUCTION("41540F4F", shl(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("41541F4F", shl(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("41543F4F", shl(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("41547F4F", shl(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("4138212E", shll(v1.h8(), v2.b8(), 8)); + TEST_INSTRUCTION("4138612E", shll(v1.s4(), v2.h4(), 16)); + TEST_INSTRUCTION("4138A12E", shll(v1.d2(), v2.s2(), 32)); + TEST_INSTRUCTION("4138216E", shll2(v1.h8(), v2.b16(), 8)); + TEST_INSTRUCTION("4138616E", shll2(v1.s4(), v2.h8(), 16)); + TEST_INSTRUCTION("4138A16E", shll2(v1.d2(), v2.s4(), 32)); + TEST_INSTRUCTION("4184090F", shrn(v1.b8(), v2.h8(), 7)); + TEST_INSTRUCTION("4184110F", shrn(v1.h4(), v2.s4(), 15)); + TEST_INSTRUCTION("4184210F", shrn(v1.s2(), v2.d2(), 31)); + TEST_INSTRUCTION("4184094F", shrn2(v1.b16(), v2.h8(), 7)); + TEST_INSTRUCTION("4184114F", shrn2(v1.h8(), v2.s4(), 15)); + TEST_INSTRUCTION("4184214F", shrn2(v1.s4(), v2.d2(), 31)); + TEST_INSTRUCTION("4124230E", shsub(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4124630E", shsub(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4124A30E", shsub(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4124234E", shsub(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4124634E", shsub(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4124A34E", shsub(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41540F2F", sli(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("41541F2F", sli(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("41543F2F", sli(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("41547F7F", sli(d1, d2, 63)); + TEST_INSTRUCTION("41540F6F", sli(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("41541F6F", sli(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("41543F6F", sli(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("41547F6F", sli(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("41C063CE", sm3partw1(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41C463CE", sm3partw2(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("411043CE", sm3ss1(v1.s4(), v2.s4(), v3.s4(), v4.s4())); + TEST_INSTRUCTION("418044CE", sm3tt1a(v1.s4(), v2.s4(), v4.s(0))); + TEST_INSTRUCTION("41B044CE", sm3tt1a(v1.s4(), v2.s4(), v4.s(3))); + TEST_INSTRUCTION("418444CE", sm3tt1b(v1.s4(), v2.s4(), v4.s(0))); + TEST_INSTRUCTION("41B444CE", sm3tt1b(v1.s4(), v2.s4(), v4.s(3))); + TEST_INSTRUCTION("418844CE", sm3tt2a(v1.s4(), v2.s4(), v4.s(0))); + TEST_INSTRUCTION("41B844CE", sm3tt2a(v1.s4(), v2.s4(), v4.s(3))); + TEST_INSTRUCTION("418C44CE", sm3tt2b(v1.s4(), v2.s4(), v4.s(0))); + TEST_INSTRUCTION("41BC44CE", sm3tt2b(v1.s4(), v2.s4(), v4.s(3))); + TEST_INSTRUCTION("4184C0CE", sm4e(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41C863CE", sm4ekey(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4164230E", smax(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4164630E", smax(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4164A30E", smax(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4164234E", smax(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4164634E", smax(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4164A34E", smax(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41A4230E", smaxp(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("41A4630E", smaxp(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41A4A30E", smaxp(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41A4234E", smaxp(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41A4634E", smaxp(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41A4A34E", smaxp(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41A8300E", smaxv(b1, v2.b8())); + TEST_INSTRUCTION("41A8304E", smaxv(b1, v2.b16())); + TEST_INSTRUCTION("41A8700E", smaxv(h1, v2.h4())); + TEST_INSTRUCTION("41A8704E", smaxv(h1, v2.h8())); + TEST_INSTRUCTION("41A8B04E", smaxv(s1, v2.s4())); + TEST_INSTRUCTION("416C230E", smin(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("416C630E", smin(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("416CA30E", smin(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("416C234E", smin(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("416C634E", smin(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("416CA34E", smin(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41AC230E", sminp(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("41AC630E", sminp(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41ACA30E", sminp(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41AC234E", sminp(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41AC634E", sminp(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41ACA34E", sminp(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41A8310E", sminv(b1, v2.b8())); + TEST_INSTRUCTION("41A8314E", sminv(b1, v2.b16())); + TEST_INSTRUCTION("41A8710E", sminv(h1, v2.h4())); + TEST_INSTRUCTION("41A8714E", sminv(h1, v2.h8())); + TEST_INSTRUCTION("41A8B14E", sminv(s1, v2.s4())); + TEST_INSTRUCTION("4180230E", smlal(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4180630E", smlal(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4180A30E", smlal(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4120730F", smlal(v1.s4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("4128A30F", smlal(v1.d2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("4180234E", smlal2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4180634E", smlal2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4180A34E", smlal2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4120734F", smlal2(v1.s4(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("4128A34F", smlal2(v1.d2(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("41A0230E", smlsl(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("41A0630E", smlsl(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41A0A30E", smlsl(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4160730F", smlsl(v1.s4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("4168A30F", smlsl(v1.d2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("41A0234E", smlsl2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41A0634E", smlsl2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41A0A34E", smlsl2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4160734F", smlsl2(v1.s4(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("4168A34F", smlsl2(v1.d2(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("41A4834E", smmla(v1.s4(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("412C010E", smov(w1, v2.b(0))); + TEST_INSTRUCTION("412C1F0E", smov(w1, v2.b(15))); + TEST_INSTRUCTION("412C020E", smov(w1, v2.h(0))); + TEST_INSTRUCTION("412C1E0E", smov(w1, v2.h(7))); + TEST_INSTRUCTION("412C014E", smov(x1, v2.b(0))); + TEST_INSTRUCTION("412C1F4E", smov(x1, v2.b(15))); + TEST_INSTRUCTION("412C024E", smov(x1, v2.h(0))); + TEST_INSTRUCTION("412C1E4E", smov(x1, v2.h(7))); + TEST_INSTRUCTION("412C044E", smov(x1, v2.s(0))); + TEST_INSTRUCTION("412C1C4E", smov(x1, v2.s(3))); + TEST_INSTRUCTION("41C0230E", smull(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("41C0630E", smull(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41C0A30E", smull(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41A0730F", smull(v1.s4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("41A8A30F", smull(v1.d2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("41C0234E", smull2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41C0634E", smull2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41C0A34E", smull2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41A0734F", smull2(v1.s4(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("41A8A34F", smull2(v1.d2(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("4178205E", sqabs(b1, b2)); + TEST_INSTRUCTION("4178605E", sqabs(h1, h2)); + TEST_INSTRUCTION("4178A05E", sqabs(s1, s2)); + TEST_INSTRUCTION("4178E05E", sqabs(d1, d2)); + TEST_INSTRUCTION("4178200E", sqabs(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4178600E", sqabs(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4178A00E", sqabs(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4178204E", sqabs(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4178604E", sqabs(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4178A04E", sqabs(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4178E04E", sqabs(v1.d2(), v2.d2())); + TEST_INSTRUCTION("410C235E", sqadd(b1, b2, b3)); + TEST_INSTRUCTION("410C635E", sqadd(h1, h2, h3)); + TEST_INSTRUCTION("410CA35E", sqadd(s1, s2, s3)); + TEST_INSTRUCTION("410CE35E", sqadd(d1, d2, d3)); + TEST_INSTRUCTION("410C230E", sqadd(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("410C630E", sqadd(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("410CA30E", sqadd(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("410C234E", sqadd(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("410C634E", sqadd(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("410CA34E", sqadd(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("410CE34E", sqadd(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4190635E", sqdmlal(s1, h2, h3)); + TEST_INSTRUCTION("4190A35E", sqdmlal(d1, s2, s3)); + TEST_INSTRUCTION("4190630E", sqdmlal(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4190A30E", sqdmlal(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4130730F", sqdmlal(v1.s4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("4138A30F", sqdmlal(v1.d2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("4190634E", sqdmlal2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4190A34E", sqdmlal2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4130734F", sqdmlal2(v1.s4(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("4138A34F", sqdmlal2(v1.d2(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("41B0635E", sqdmlsl(s1, h2, h3)); + TEST_INSTRUCTION("41B0A35E", sqdmlsl(d1, s2, s3)); + TEST_INSTRUCTION("41B0630E", sqdmlsl(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41B0A30E", sqdmlsl(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4170730F", sqdmlsl(v1.s4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("4178A30F", sqdmlsl(v1.d2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("41B0634E", sqdmlsl2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41B0A34E", sqdmlsl2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4170734F", sqdmlsl2(v1.s4(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("4178A34F", sqdmlsl2(v1.d2(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("41B4635E", sqdmulh(h1, h2, h3)); + TEST_INSTRUCTION("41B4A35E", sqdmulh(s1, s2, s3)); + TEST_INSTRUCTION("41B4630E", sqdmulh(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41B4A30E", sqdmulh(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41B4634E", sqdmulh(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41B4A34E", sqdmulh(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41C0730F", sqdmulh(v1.h4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("41C8A30F", sqdmulh(v1.s2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("41C0734F", sqdmulh(v1.h8(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("41C8A34F", sqdmulh(v1.s4(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("41D0635E", sqdmull(s1, h2, h3)); + TEST_INSTRUCTION("41D0A35E", sqdmull(d1, s2, s3)); + TEST_INSTRUCTION("41D0630E", sqdmull(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41D0A30E", sqdmull(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41B0730F", sqdmull(v1.s4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("41B8A30F", sqdmull(v1.d2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("41D0634E", sqdmull2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41D0A34E", sqdmull2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41B0734F", sqdmull2(v1.s4(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("41B8A34F", sqdmull2(v1.d2(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("4178207E", sqneg(b1, b2)); + TEST_INSTRUCTION("4178607E", sqneg(h1, h2)); + TEST_INSTRUCTION("4178A07E", sqneg(s1, s2)); + TEST_INSTRUCTION("4178E07E", sqneg(d1, d2)); + TEST_INSTRUCTION("4178202E", sqneg(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4178602E", sqneg(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4178A02E", sqneg(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4178206E", sqneg(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4178606E", sqneg(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4178A06E", sqneg(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4178E06E", sqneg(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4184437E", sqrdmlah(h1, h2, h3)); + TEST_INSTRUCTION("4184837E", sqrdmlah(s1, s2, s3)); + TEST_INSTRUCTION("4184432E", sqrdmlah(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4184832E", sqrdmlah(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41D0732F", sqrdmlah(v1.h4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("41D8A32F", sqrdmlah(v1.s2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("4184436E", sqrdmlah(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4184836E", sqrdmlah(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41D0736F", sqrdmlah(v1.h8(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("41D8A36F", sqrdmlah(v1.s4(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("418C437E", sqrdmlsh(h1, h2, h3)); + TEST_INSTRUCTION("418C837E", sqrdmlsh(s1, s2, s3)); + TEST_INSTRUCTION("418C432E", sqrdmlsh(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("418C832E", sqrdmlsh(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41F0732F", sqrdmlsh(v1.h4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("41F8A32F", sqrdmlsh(v1.s2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("418C436E", sqrdmlsh(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("418C836E", sqrdmlsh(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41F0736F", sqrdmlsh(v1.h8(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("41F8A36F", sqrdmlsh(v1.s4(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("41B4637E", sqrdmulh(h1, h2, h3)); + TEST_INSTRUCTION("41B4A37E", sqrdmulh(s1, s2, s3)); + TEST_INSTRUCTION("41B4632E", sqrdmulh(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41B4A32E", sqrdmulh(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41D0730F", sqrdmulh(v1.h4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("41D8A30F", sqrdmulh(v1.s2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("41B4636E", sqrdmulh(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41B4A36E", sqrdmulh(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41D0734F", sqrdmulh(v1.h8(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("41D8A34F", sqrdmulh(v1.s4(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("415C235E", sqrshl(b1, b2, b3)); + TEST_INSTRUCTION("415C635E", sqrshl(h1, h2, h3)); + TEST_INSTRUCTION("415CA35E", sqrshl(s1, s2, s3)); + TEST_INSTRUCTION("415C230E", sqrshl(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("415C630E", sqrshl(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("415CA30E", sqrshl(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("415CE35E", sqrshl(d1, d2, d3)); + TEST_INSTRUCTION("415C234E", sqrshl(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("415C634E", sqrshl(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("415CA34E", sqrshl(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("415CE34E", sqrshl(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("419C085F", sqrshrn(b1, h2, 8)); + TEST_INSTRUCTION("419C105F", sqrshrn(h1, s2, 16)); + TEST_INSTRUCTION("419C205F", sqrshrn(s1, d2, 32)); + TEST_INSTRUCTION("419C080F", sqrshrn(v1.b8(), v2.h8(), 8)); + TEST_INSTRUCTION("419C100F", sqrshrn(v1.h4(), v2.s4(), 16)); + TEST_INSTRUCTION("419C200F", sqrshrn(v1.s2(), v2.d2(), 32)); + TEST_INSTRUCTION("419C084F", sqrshrn2(v1.b16(), v2.h8(), 8)); + TEST_INSTRUCTION("419C104F", sqrshrn2(v1.h8(), v2.s4(), 16)); + TEST_INSTRUCTION("419C204F", sqrshrn2(v1.s4(), v2.d2(), 32)); + TEST_INSTRUCTION("418C087F", sqrshrun(b1, h2, 8)); + TEST_INSTRUCTION("418C107F", sqrshrun(h1, s2, 16)); + TEST_INSTRUCTION("418C207F", sqrshrun(s1, d2, 32)); + TEST_INSTRUCTION("418C082F", sqrshrun(v1.b8(), v2.h8(), 8)); + TEST_INSTRUCTION("418C102F", sqrshrun(v1.h4(), v2.s4(), 16)); + TEST_INSTRUCTION("418C202F", sqrshrun(v1.s2(), v2.d2(), 32)); + TEST_INSTRUCTION("418C086F", sqrshrun2(v1.b16(), v2.h8(), 8)); + TEST_INSTRUCTION("418C106F", sqrshrun2(v1.h8(), v2.s4(), 16)); + TEST_INSTRUCTION("418C206F", sqrshrun2(v1.s4(), v2.d2(), 32)); + TEST_INSTRUCTION("4174095F", sqshl(b1, b2, 1)); + TEST_INSTRUCTION("4174125F", sqshl(h1, h2, 2)); + TEST_INSTRUCTION("4174235F", sqshl(s1, s2, 3)); + TEST_INSTRUCTION("41740F0F", sqshl(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("41741F0F", sqshl(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("41743F0F", sqshl(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("41747F5F", sqshl(d1, d2, 63)); + TEST_INSTRUCTION("41740F4F", sqshl(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("41741F4F", sqshl(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("41743F4F", sqshl(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("41747F4F", sqshl(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("414C235E", sqshl(b1, b2, b3)); + TEST_INSTRUCTION("414C635E", sqshl(h1, h2, h3)); + TEST_INSTRUCTION("414CA35E", sqshl(s1, s2, s3)); + TEST_INSTRUCTION("414C230E", sqshl(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("414C630E", sqshl(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("414CA30E", sqshl(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("414CE35E", sqshl(d1, d2, d3)); + TEST_INSTRUCTION("414C234E", sqshl(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("414C634E", sqshl(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("414CA34E", sqshl(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("414CE34E", sqshl(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4164097F", sqshlu(b1, b2, 1)); + TEST_INSTRUCTION("4164127F", sqshlu(h1, h2, 2)); + TEST_INSTRUCTION("4164237F", sqshlu(s1, s2, 3)); + TEST_INSTRUCTION("41640F2F", sqshlu(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("41641F2F", sqshlu(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("41643F2F", sqshlu(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("41647F7F", sqshlu(d1, d2, 63)); + TEST_INSTRUCTION("41640F6F", sqshlu(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("41641F6F", sqshlu(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("41643F6F", sqshlu(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("41647F6F", sqshlu(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("4194085F", sqshrn(b1, h2, 8)); + TEST_INSTRUCTION("4194105F", sqshrn(h1, s2, 16)); + TEST_INSTRUCTION("4194205F", sqshrn(s1, d2, 32)); + TEST_INSTRUCTION("4194080F", sqshrn(v1.b8(), v2.h8(), 8)); + TEST_INSTRUCTION("4194100F", sqshrn(v1.h4(), v2.s4(), 16)); + TEST_INSTRUCTION("4194200F", sqshrn(v1.s2(), v2.d2(), 32)); + TEST_INSTRUCTION("4194084F", sqshrn2(v1.b16(), v2.h8(), 8)); + TEST_INSTRUCTION("4194104F", sqshrn2(v1.h8(), v2.s4(), 16)); + TEST_INSTRUCTION("4194204F", sqshrn2(v1.s4(), v2.d2(), 32)); + TEST_INSTRUCTION("4184087F", sqshrun(b1, h2, 8)); + TEST_INSTRUCTION("4184107F", sqshrun(h1, s2, 16)); + TEST_INSTRUCTION("4184207F", sqshrun(s1, d2, 32)); + TEST_INSTRUCTION("4184082F", sqshrun(v1.b8(), v2.h8(), 8)); + TEST_INSTRUCTION("4184102F", sqshrun(v1.h4(), v2.s4(), 16)); + TEST_INSTRUCTION("4184202F", sqshrun(v1.s2(), v2.d2(), 32)); + TEST_INSTRUCTION("4184086F", sqshrun2(v1.b16(), v2.h8(), 8)); + TEST_INSTRUCTION("4184106F", sqshrun2(v1.h8(), v2.s4(), 16)); + TEST_INSTRUCTION("4184206F", sqshrun2(v1.s4(), v2.d2(), 32)); + TEST_INSTRUCTION("412C235E", sqsub(b1, b2, b3)); + TEST_INSTRUCTION("412C635E", sqsub(h1, h2, h3)); + TEST_INSTRUCTION("412CA35E", sqsub(s1, s2, s3)); + TEST_INSTRUCTION("412CE35E", sqsub(d1, d2, d3)); + TEST_INSTRUCTION("412C230E", sqsub(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("412C630E", sqsub(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("412CA30E", sqsub(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("412C234E", sqsub(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("412C634E", sqsub(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("412CA34E", sqsub(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("412CE34E", sqsub(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4148215E", sqxtn(b1, h2)); + TEST_INSTRUCTION("4148615E", sqxtn(h1, s2)); + TEST_INSTRUCTION("4148A15E", sqxtn(s1, d2)); + TEST_INSTRUCTION("4148210E", sqxtn(v1.b8(), v2.h8())); + TEST_INSTRUCTION("4148610E", sqxtn(v1.h4(), v2.s4())); + TEST_INSTRUCTION("4148A10E", sqxtn(v1.s2(), v2.d2())); + TEST_INSTRUCTION("4148214E", sqxtn2(v1.b16(), v2.h8())); + TEST_INSTRUCTION("4148614E", sqxtn2(v1.h8(), v2.s4())); + TEST_INSTRUCTION("4148A14E", sqxtn2(v1.s4(), v2.d2())); + TEST_INSTRUCTION("4128217E", sqxtun(b1, h2)); + TEST_INSTRUCTION("4128617E", sqxtun(h1, s2)); + TEST_INSTRUCTION("4128A17E", sqxtun(s1, d2)); + TEST_INSTRUCTION("4128212E", sqxtun(v1.b8(), v2.h8())); + TEST_INSTRUCTION("4128612E", sqxtun(v1.h4(), v2.s4())); + TEST_INSTRUCTION("4128A12E", sqxtun(v1.s2(), v2.d2())); + TEST_INSTRUCTION("4128216E", sqxtun2(v1.b16(), v2.h8())); + TEST_INSTRUCTION("4128616E", sqxtun2(v1.h8(), v2.s4())); + TEST_INSTRUCTION("4128A16E", sqxtun2(v1.s4(), v2.d2())); + TEST_INSTRUCTION("4114230E", srhadd(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4114630E", srhadd(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4114A30E", srhadd(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4114234E", srhadd(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4114634E", srhadd(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4114A34E", srhadd(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4144092F", sri(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("4144112F", sri(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("4144212F", sri(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("4144417F", sri(d1, d2, 63)); + TEST_INSTRUCTION("4144096F", sri(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("4144116F", sri(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("4144216F", sri(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("4144416F", sri(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("4154230E", srshl(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4154630E", srshl(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4154A30E", srshl(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4154E35E", srshl(d1, d2, d3)); + TEST_INSTRUCTION("4154234E", srshl(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4154634E", srshl(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4154A34E", srshl(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4154E34E", srshl(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4124090F", srshr(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("4124110F", srshr(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("4124210F", srshr(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("4124415F", srshr(d1, d2, 63)); + TEST_INSTRUCTION("4124094F", srshr(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("4124114F", srshr(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("4124214F", srshr(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("4124414F", srshr(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("4134090F", srsra(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("4134110F", srsra(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("4134210F", srsra(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("4134415F", srsra(d1, d2, 63)); + TEST_INSTRUCTION("4134094F", srsra(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("4134114F", srsra(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("4134214F", srsra(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("4134414F", srsra(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("4144230E", sshl(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4144630E", sshl(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4144A30E", sshl(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4144E35E", sshl(d1, d2, d3)); + TEST_INSTRUCTION("4144234E", sshl(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4144634E", sshl(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4144A34E", sshl(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4144E34E", sshl(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41A40F0F", sshll(v1.h8(), v2.b8(), 7)); + TEST_INSTRUCTION("41A41F0F", sshll(v1.s4(), v2.h4(), 15)); + TEST_INSTRUCTION("41A43F0F", sshll(v1.d2(), v2.s2(), 31)); + TEST_INSTRUCTION("41A40F4F", sshll2(v1.h8(), v2.b16(), 7)); + TEST_INSTRUCTION("41A41F4F", sshll2(v1.s4(), v2.h8(), 15)); + TEST_INSTRUCTION("41A43F4F", sshll2(v1.s2(), v2.s4(), 31)); + TEST_INSTRUCTION("4104090F", sshr(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("4104110F", sshr(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("4104210F", sshr(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("4104415F", sshr(d1, d2, 63)); + TEST_INSTRUCTION("4104094F", sshr(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("4104114F", sshr(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("4104214F", sshr(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("4104414F", sshr(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("4114090F", ssra(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("4114110F", ssra(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("4114210F", ssra(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("4114415F", ssra(d1, d2, 63)); + TEST_INSTRUCTION("4114094F", ssra(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("4114114F", ssra(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("4114214F", ssra(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("4114414F", ssra(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("4120230E", ssubl(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4120630E", ssubl(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4120A30E", ssubl(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4120234E", ssubl2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4120634E", ssubl2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4120A34E", ssubl2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4130230E", ssubw(v1.h8(), v2.h8(), v3.b8())); + TEST_INSTRUCTION("4130630E", ssubw(v1.s4(), v2.s4(), v3.h4())); + TEST_INSTRUCTION("4130A30E", ssubw(v1.d2(), v2.d2(), v3.s2())); + TEST_INSTRUCTION("4130234E", ssubw2(v1.h8(), v2.h8(), v3.b16())); + TEST_INSTRUCTION("4130634E", ssubw2(v1.s4(), v2.s4(), v3.h8())); + TEST_INSTRUCTION("4130A34E", ssubw2(v1.d2(), v2.d2(), v3.s4())); + TEST_INSTRUCTION("4100000D", st1(v1.b(0), ptr(x2))); + TEST_INSTRUCTION("41009F0D", st1(v1.b(0), ptr_post(x2, 1))); + TEST_INSTRUCTION("4140000D", st1(v1.h(0), ptr(x2))); + TEST_INSTRUCTION("41409F0D", st1(v1.h(0), ptr_post(x2, 2))); + TEST_INSTRUCTION("4180000D", st1(v1.s(0), ptr(x2))); + TEST_INSTRUCTION("41809F0D", st1(v1.s(0), ptr_post(x2, 4))); + TEST_INSTRUCTION("4184000D", st1(v1.d(0), ptr(x2))); + TEST_INSTRUCTION("41849F0D", st1(v1.d(0), ptr_post(x2, 8))); + TEST_INSTRUCTION("411C004D", st1(v1.b(15), ptr(x2))); + TEST_INSTRUCTION("411C9F4D", st1(v1.b(15), ptr_post(x2, 1))); + TEST_INSTRUCTION("4158004D", st1(v1.h(7), ptr(x2))); + TEST_INSTRUCTION("41589F4D", st1(v1.h(7), ptr_post(x2, 2))); + TEST_INSTRUCTION("4190004D", st1(v1.s(3), ptr(x2))); + TEST_INSTRUCTION("41909F4D", st1(v1.s(3), ptr_post(x2, 4))); + TEST_INSTRUCTION("4184004D", st1(v1.d(1), ptr(x2))); + TEST_INSTRUCTION("41849F4D", st1(v1.d(1), ptr_post(x2, 8))); + TEST_INSTRUCTION("4170000C", st1(v1.b8(), ptr(x2))); + TEST_INSTRUCTION("41709F0C", st1(v1.b8(), ptr_post(x2, 8))); + TEST_INSTRUCTION("4170004C", st1(v1.b16(), ptr(x2))); + TEST_INSTRUCTION("41709F4C", st1(v1.b16(), ptr_post(x2, 16))); + TEST_INSTRUCTION("61A0000C", st1(v1.b8(), v2.b8(), ptr(x3))); + TEST_INSTRUCTION("61A09F0C", st1(v1.b8(), v2.b8(), ptr_post(x3, 16))); + TEST_INSTRUCTION("61A0004C", st1(v1.b16(), v2.b16(), ptr(x3))); + TEST_INSTRUCTION("61A09F4C", st1(v1.b16(), v2.b16(), ptr_post(x3, 32))); + TEST_INSTRUCTION("8160000C", st1(v1.b8(), v2.b8(), v3.b8(), ptr(x4))); + TEST_INSTRUCTION("81609F0C", st1(v1.b8(), v2.b8(), v3.b8(), ptr_post(x4, 24))); + TEST_INSTRUCTION("8160004C", st1(v1.b16(), v2.b16(), v3.b16(), ptr(x4))); + TEST_INSTRUCTION("81609F4C", st1(v1.b16(), v2.b16(), v3.b16(), ptr_post(x4, 48))); + TEST_INSTRUCTION("A120000C", st1(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr(x5))); + TEST_INSTRUCTION("A1209F0C", st1(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A120004C", st1(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr(x5))); + TEST_INSTRUCTION("A1209F4C", st1(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr_post(x5, 64))); + TEST_INSTRUCTION("4174000C", st1(v1.h4(), ptr(x2))); + TEST_INSTRUCTION("41749F0C", st1(v1.h4(), ptr_post(x2, 8))); + TEST_INSTRUCTION("4174004C", st1(v1.h8(), ptr(x2))); + TEST_INSTRUCTION("41749F4C", st1(v1.h8(), ptr_post(x2, 16))); + TEST_INSTRUCTION("61A4000C", st1(v1.h4(), v2.h4(), ptr(x3))); + TEST_INSTRUCTION("61A49F0C", st1(v1.h4(), v2.h4(), ptr_post(x3, 16))); + TEST_INSTRUCTION("61A4004C", st1(v1.h8(), v2.h8(), ptr(x3))); + TEST_INSTRUCTION("61A49F4C", st1(v1.h8(), v2.h8(), ptr_post(x3, 32))); + TEST_INSTRUCTION("8164000C", st1(v1.h4(), v2.h4(), v3.h4(), ptr(x4))); + TEST_INSTRUCTION("81649F0C", st1(v1.h4(), v2.h4(), v3.h4(), ptr_post(x4, 24))); + TEST_INSTRUCTION("8164004C", st1(v1.h8(), v2.h8(), v3.h8(), ptr(x4))); + TEST_INSTRUCTION("81649F4C", st1(v1.h8(), v2.h8(), v3.h8(), ptr_post(x4, 48))); + TEST_INSTRUCTION("A124000C", st1(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr(x5))); + TEST_INSTRUCTION("A1249F0C", st1(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A124004C", st1(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr(x5))); + TEST_INSTRUCTION("A1249F4C", st1(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr_post(x5, 64))); + TEST_INSTRUCTION("4178000C", st1(v1.s2(), ptr(x2))); + TEST_INSTRUCTION("41789F0C", st1(v1.s2(), ptr_post(x2, 8))); + TEST_INSTRUCTION("4178004C", st1(v1.s4(), ptr(x2))); + TEST_INSTRUCTION("41789F4C", st1(v1.s4(), ptr_post(x2, 16))); + TEST_INSTRUCTION("61A8000C", st1(v1.s2(), v2.s2(), ptr(x3))); + TEST_INSTRUCTION("61A89F0C", st1(v1.s2(), v2.s2(), ptr_post(x3, 16))); + TEST_INSTRUCTION("61A8004C", st1(v1.s4(), v2.s4(), ptr(x3))); + TEST_INSTRUCTION("61A89F4C", st1(v1.s4(), v2.s4(), ptr_post(x3, 32))); + TEST_INSTRUCTION("8168000C", st1(v1.s2(), v2.s2(), v3.s2(), ptr(x4))); + TEST_INSTRUCTION("81689F0C", st1(v1.s2(), v2.s2(), v3.s2(), ptr_post(x4, 24))); + TEST_INSTRUCTION("8168004C", st1(v1.s4(), v2.s4(), v3.s4(), ptr(x4))); + TEST_INSTRUCTION("81689F4C", st1(v1.s4(), v2.s4(), v3.s4(), ptr_post(x4, 48))); + TEST_INSTRUCTION("A128000C", st1(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr(x5))); + TEST_INSTRUCTION("A1289F0C", st1(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A128004C", st1(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr(x5))); + TEST_INSTRUCTION("A1289F4C", st1(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr_post(x5, 64))); + TEST_INSTRUCTION("417C004C", st1(v1.d2(), ptr(x2))); + TEST_INSTRUCTION("417C9F4C", st1(v1.d2(), ptr_post(x2, 16))); + TEST_INSTRUCTION("61AC004C", st1(v1.d2(), v2.d2(), ptr(x3))); + TEST_INSTRUCTION("61AC9F4C", st1(v1.d2(), v2.d2(), ptr_post(x3, 32))); + TEST_INSTRUCTION("816C004C", st1(v1.d2(), v2.d2(), v3.d2(), ptr(x4))); + TEST_INSTRUCTION("816C9F4C", st1(v1.d2(), v2.d2(), v3.d2(), ptr_post(x4, 48))); + TEST_INSTRUCTION("A12C004C", st1(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr(x5))); + TEST_INSTRUCTION("A12C9F4C", st1(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr_post(x5, 64))); + TEST_INSTRUCTION("6100200D", st2(v1.b(0), v2.b(0), ptr(x3))); + TEST_INSTRUCTION("6100BF0D", st2(v1.b(0), v2.b(0), ptr_post(x3, 2))); + TEST_INSTRUCTION("6100AB0D", st2(v1.b(0), v2.b(0), ptr_post(x3, x11))); + TEST_INSTRUCTION("6140200D", st2(v1.h(0), v2.h(0), ptr(x3))); + TEST_INSTRUCTION("6140BF0D", st2(v1.h(0), v2.h(0), ptr_post(x3, 4))); + TEST_INSTRUCTION("6140AB0D", st2(v1.h(0), v2.h(0), ptr_post(x3, x11))); + TEST_INSTRUCTION("6180200D", st2(v1.s(0), v2.s(0), ptr(x3))); + TEST_INSTRUCTION("6180BF0D", st2(v1.s(0), v2.s(0), ptr_post(x3, 8))); + TEST_INSTRUCTION("6180AB0D", st2(v1.s(0), v2.s(0), ptr_post(x3, x11))); + TEST_INSTRUCTION("6184200D", st2(v1.d(0), v2.d(0), ptr(x3))); + TEST_INSTRUCTION("6184BF0D", st2(v1.d(0), v2.d(0), ptr_post(x3, 16))); + TEST_INSTRUCTION("6184AB0D", st2(v1.d(0), v2.d(0), ptr_post(x3, x11))); + TEST_INSTRUCTION("611C204D", st2(v1.b(15), v2.b(15), ptr(x3))); + TEST_INSTRUCTION("611CBF4D", st2(v1.b(15), v2.b(15), ptr_post(x3, 2))); + TEST_INSTRUCTION("611CAB4D", st2(v1.b(15), v2.b(15), ptr_post(x3, x11))); + TEST_INSTRUCTION("6158204D", st2(v1.h(7), v2.h(7), ptr(x3))); + TEST_INSTRUCTION("6158BF4D", st2(v1.h(7), v2.h(7), ptr_post(x3, 4))); + TEST_INSTRUCTION("6158AB4D", st2(v1.h(7), v2.h(7), ptr_post(x3, x11))); + TEST_INSTRUCTION("6190204D", st2(v1.s(3), v2.s(3), ptr(x3))); + TEST_INSTRUCTION("6190BF4D", st2(v1.s(3), v2.s(3), ptr_post(x3, 8))); + TEST_INSTRUCTION("6190AB4D", st2(v1.s(3), v2.s(3), ptr_post(x3, x11))); + TEST_INSTRUCTION("6184204D", st2(v1.d(1), v2.d(1), ptr(x3))); + TEST_INSTRUCTION("6184BF4D", st2(v1.d(1), v2.d(1), ptr_post(x3, 16))); + TEST_INSTRUCTION("6184AB4D", st2(v1.d(1), v2.d(1), ptr_post(x3, x11))); + TEST_INSTRUCTION("6180000C", st2(v1.b8(), v2.b8(), ptr(x3))); + TEST_INSTRUCTION("61809F0C", st2(v1.b8(), v2.b8(), ptr_post(x3, 16))); + TEST_INSTRUCTION("61808B0C", st2(v1.b8(), v2.b8(), ptr_post(x3, x11))); + TEST_INSTRUCTION("6180004C", st2(v1.b16(), v2.b16(), ptr(x3))); + TEST_INSTRUCTION("61809F4C", st2(v1.b16(), v2.b16(), ptr_post(x3, 32))); + TEST_INSTRUCTION("61808B4C", st2(v1.b16(), v2.b16(), ptr_post(x3, x11))); + TEST_INSTRUCTION("6184000C", st2(v1.h4(), v2.h4(), ptr(x3))); + TEST_INSTRUCTION("61849F0C", st2(v1.h4(), v2.h4(), ptr_post(x3, 16))); + TEST_INSTRUCTION("61848B0C", st2(v1.h4(), v2.h4(), ptr_post(x3, x11))); + TEST_INSTRUCTION("6184004C", st2(v1.h8(), v2.h8(), ptr(x3))); + TEST_INSTRUCTION("61849F4C", st2(v1.h8(), v2.h8(), ptr_post(x3, 32))); + TEST_INSTRUCTION("61848B4C", st2(v1.h8(), v2.h8(), ptr_post(x3, x11))); + TEST_INSTRUCTION("6188000C", st2(v1.s2(), v2.s2(), ptr(x3))); + TEST_INSTRUCTION("61889F0C", st2(v1.s2(), v2.s2(), ptr_post(x3, 16))); + TEST_INSTRUCTION("61888B0C", st2(v1.s2(), v2.s2(), ptr_post(x3, x11))); + TEST_INSTRUCTION("6188004C", st2(v1.s4(), v2.s4(), ptr(x3))); + TEST_INSTRUCTION("61889F4C", st2(v1.s4(), v2.s4(), ptr_post(x3, 32))); + TEST_INSTRUCTION("61888B4C", st2(v1.s4(), v2.s4(), ptr_post(x3, x11))); + TEST_INSTRUCTION("618C004C", st2(v1.d2(), v2.d2(), ptr(x3))); + TEST_INSTRUCTION("618C9F4C", st2(v1.d2(), v2.d2(), ptr_post(x3, 32))); + TEST_INSTRUCTION("618C8B4C", st2(v1.d2(), v2.d2(), ptr_post(x3, x11))); + TEST_INSTRUCTION("8120000D", st3(v1.b(0), v2.b(0), v3.b(0), ptr(x4))); + TEST_INSTRUCTION("81209F0D", st3(v1.b(0), v2.b(0), v3.b(0), ptr_post(x4, 3))); + TEST_INSTRUCTION("81208B0D", st3(v1.b(0), v2.b(0), v3.b(0), ptr_post(x4, x11))); + TEST_INSTRUCTION("8160000D", st3(v1.h(0), v2.h(0), v3.h(0), ptr(x4))); + TEST_INSTRUCTION("81609F0D", st3(v1.h(0), v2.h(0), v3.h(0), ptr_post(x4, 6))); + TEST_INSTRUCTION("81608B0D", st3(v1.h(0), v2.h(0), v3.h(0), ptr_post(x4, x11))); + TEST_INSTRUCTION("81A0000D", st3(v1.s(0), v2.s(0), v3.s(0), ptr(x4))); + TEST_INSTRUCTION("81A09F0D", st3(v1.s(0), v2.s(0), v3.s(0), ptr_post(x4, 12))); + TEST_INSTRUCTION("81A08B0D", st3(v1.s(0), v2.s(0), v3.s(0), ptr_post(x4, x11))); + TEST_INSTRUCTION("81A4000D", st3(v1.d(0), v2.d(0), v3.d(0), ptr(x4))); + TEST_INSTRUCTION("81A49F0D", st3(v1.d(0), v2.d(0), v3.d(0), ptr_post(x4, 24))); + TEST_INSTRUCTION("81A48B0D", st3(v1.d(0), v2.d(0), v3.d(0), ptr_post(x4, x11))); + TEST_INSTRUCTION("813C004D", st3(v1.b(15), v2.b(15), v3.b(15), ptr(x4))); + TEST_INSTRUCTION("813C9F4D", st3(v1.b(15), v2.b(15), v3.b(15), ptr_post(x4, 3))); + TEST_INSTRUCTION("813C8B4D", st3(v1.b(15), v2.b(15), v3.b(15), ptr_post(x4, x11))); + TEST_INSTRUCTION("8178004D", st3(v1.h(7), v2.h(7), v3.h(7), ptr(x4))); + TEST_INSTRUCTION("81789F4D", st3(v1.h(7), v2.h(7), v3.h(7), ptr_post(x4, 6))); + TEST_INSTRUCTION("81788B4D", st3(v1.h(7), v2.h(7), v3.h(7), ptr_post(x4, x11))); + TEST_INSTRUCTION("81B0004D", st3(v1.s(3), v2.s(3), v3.s(3), ptr(x4))); + TEST_INSTRUCTION("81B09F4D", st3(v1.s(3), v2.s(3), v3.s(3), ptr_post(x4, 12))); + TEST_INSTRUCTION("81B08B4D", st3(v1.s(3), v2.s(3), v3.s(3), ptr_post(x4, x11))); + TEST_INSTRUCTION("81A4004D", st3(v1.d(1), v2.d(1), v3.d(1), ptr(x4))); + TEST_INSTRUCTION("81A49F4D", st3(v1.d(1), v2.d(1), v3.d(1), ptr_post(x4, 24))); + TEST_INSTRUCTION("81A48B4D", st3(v1.d(1), v2.d(1), v3.d(1), ptr_post(x4, x11))); + TEST_INSTRUCTION("8140000C", st3(v1.b8(), v2.b8(), v3.b8(), ptr(x4))); + TEST_INSTRUCTION("81409F0C", st3(v1.b8(), v2.b8(), v3.b8(), ptr_post(x4, 24))); + TEST_INSTRUCTION("81408B0C", st3(v1.b8(), v2.b8(), v3.b8(), ptr_post(x4, x11))); + TEST_INSTRUCTION("8140004C", st3(v1.b16(), v2.b16(), v3.b16(), ptr(x4))); + TEST_INSTRUCTION("81409F4C", st3(v1.b16(), v2.b16(), v3.b16(), ptr_post(x4, 48))); + TEST_INSTRUCTION("81408B4C", st3(v1.b16(), v2.b16(), v3.b16(), ptr_post(x4, x11))); + TEST_INSTRUCTION("8144000C", st3(v1.h4(), v2.h4(), v3.h4(), ptr(x4))); + TEST_INSTRUCTION("81449F0C", st3(v1.h4(), v2.h4(), v3.h4(), ptr_post(x4, 24))); + TEST_INSTRUCTION("81448B0C", st3(v1.h4(), v2.h4(), v3.h4(), ptr_post(x4, x11))); + TEST_INSTRUCTION("8144004C", st3(v1.h8(), v2.h8(), v3.h8(), ptr(x4))); + TEST_INSTRUCTION("81449F4C", st3(v1.h8(), v2.h8(), v3.h8(), ptr_post(x4, 48))); + TEST_INSTRUCTION("81448B4C", st3(v1.h8(), v2.h8(), v3.h8(), ptr_post(x4, x11))); + TEST_INSTRUCTION("8148000C", st3(v1.s2(), v2.s2(), v3.s2(), ptr(x4))); + TEST_INSTRUCTION("81489F0C", st3(v1.s2(), v2.s2(), v3.s2(), ptr_post(x4, 24))); + TEST_INSTRUCTION("81488B0C", st3(v1.s2(), v2.s2(), v3.s2(), ptr_post(x4, x11))); + TEST_INSTRUCTION("8148004C", st3(v1.s4(), v2.s4(), v3.s4(), ptr(x4))); + TEST_INSTRUCTION("81489F4C", st3(v1.s4(), v2.s4(), v3.s4(), ptr_post(x4, 48))); + TEST_INSTRUCTION("81488B4C", st3(v1.s4(), v2.s4(), v3.s4(), ptr_post(x4, x11))); + TEST_INSTRUCTION("814C004C", st3(v1.d2(), v2.d2(), v3.d2(), ptr(x4))); + TEST_INSTRUCTION("814C9F4C", st3(v1.d2(), v2.d2(), v3.d2(), ptr_post(x4, 48))); + TEST_INSTRUCTION("814C8B4C", st3(v1.d2(), v2.d2(), v3.d2(), ptr_post(x4, x11))); + TEST_INSTRUCTION("A120200D", st4(v1.b(0), v2.b(0), v3.b(0), v4.b(0), ptr(x5))); + TEST_INSTRUCTION("A120BF0D", st4(v1.b(0), v2.b(0), v3.b(0), v4.b(0), ptr_post(x5, 4))); + TEST_INSTRUCTION("A120AB0D", st4(v1.b(0), v2.b(0), v3.b(0), v4.b(0), ptr_post(x5, x11))); + TEST_INSTRUCTION("A160200D", st4(v1.h(0), v2.h(0), v3.h(0), v4.h(0), ptr(x5))); + TEST_INSTRUCTION("A160BF0D", st4(v1.h(0), v2.h(0), v3.h(0), v4.h(0), ptr_post(x5, 8))); + TEST_INSTRUCTION("A160AB0D", st4(v1.h(0), v2.h(0), v3.h(0), v4.h(0), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1A0200D", st4(v1.s(0), v2.s(0), v3.s(0), v4.s(0), ptr(x5))); + TEST_INSTRUCTION("A1A0BF0D", st4(v1.s(0), v2.s(0), v3.s(0), v4.s(0), ptr_post(x5, 16))); + TEST_INSTRUCTION("A1A0AB0D", st4(v1.s(0), v2.s(0), v3.s(0), v4.s(0), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1A4200D", st4(v1.d(0), v2.d(0), v3.d(0), v4.d(0), ptr(x5))); + TEST_INSTRUCTION("A1A4BF0D", st4(v1.d(0), v2.d(0), v3.d(0), v4.d(0), ptr_post(x5, 32))); + TEST_INSTRUCTION("A1A4AB0D", st4(v1.d(0), v2.d(0), v3.d(0), v4.d(0), ptr_post(x5, x11))); + TEST_INSTRUCTION("A13C204D", st4(v1.b(15), v2.b(15), v3.b(15), v4.b(15), ptr(x5))); + TEST_INSTRUCTION("A13CBF4D", st4(v1.b(15), v2.b(15), v3.b(15), v4.b(15), ptr_post(x5, 4))); + TEST_INSTRUCTION("A13CAB4D", st4(v1.b(15), v2.b(15), v3.b(15), v4.b(15), ptr_post(x5, x11))); + TEST_INSTRUCTION("A178204D", st4(v1.h(7), v2.h(7), v3.h(7), v4.h(7), ptr(x5))); + TEST_INSTRUCTION("A178BF4D", st4(v1.h(7), v2.h(7), v3.h(7), v4.h(7), ptr_post(x5, 8))); + TEST_INSTRUCTION("A178AB4D", st4(v1.h(7), v2.h(7), v3.h(7), v4.h(7), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1B0204D", st4(v1.s(3), v2.s(3), v3.s(3), v4.s(3), ptr(x5))); + TEST_INSTRUCTION("A1B0BF4D", st4(v1.s(3), v2.s(3), v3.s(3), v4.s(3), ptr_post(x5, 16))); + TEST_INSTRUCTION("A1B0AB4D", st4(v1.s(3), v2.s(3), v3.s(3), v4.s(3), ptr_post(x5, x11))); + TEST_INSTRUCTION("A1A4204D", st4(v1.d(1), v2.d(1), v3.d(1), v4.d(1), ptr(x5))); + TEST_INSTRUCTION("A1A4BF4D", st4(v1.d(1), v2.d(1), v3.d(1), v4.d(1), ptr_post(x5, 32))); + TEST_INSTRUCTION("A1A4AB4D", st4(v1.d(1), v2.d(1), v3.d(1), v4.d(1), ptr_post(x5, x11))); + TEST_INSTRUCTION("A100000C", st4(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr(x5))); + TEST_INSTRUCTION("A1009F0C", st4(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A1008B0C", st4(v1.b8(), v2.b8(), v3.b8(), v4.b8(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A100004C", st4(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr(x5))); + TEST_INSTRUCTION("A1009F4C", st4(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr_post(x5, 64))); + TEST_INSTRUCTION("A1008B4C", st4(v1.b16(), v2.b16(), v3.b16(), v4.b16(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A104000C", st4(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr(x5))); + TEST_INSTRUCTION("A1049F0C", st4(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A1048B0C", st4(v1.h4(), v2.h4(), v3.h4(), v4.h4(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A104004C", st4(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr(x5))); + TEST_INSTRUCTION("A1049F4C", st4(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr_post(x5, 64))); + TEST_INSTRUCTION("A1048B4C", st4(v1.h8(), v2.h8(), v3.h8(), v4.h8(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A108000C", st4(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr(x5))); + TEST_INSTRUCTION("A1089F0C", st4(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr_post(x5, 32))); + TEST_INSTRUCTION("A1088B0C", st4(v1.s2(), v2.s2(), v3.s2(), v4.s2(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A108004C", st4(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr(x5))); + TEST_INSTRUCTION("A1089F4C", st4(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr_post(x5, 64))); + TEST_INSTRUCTION("A1088B4C", st4(v1.s4(), v2.s4(), v3.s4(), v4.s4(), ptr_post(x5, x11))); + TEST_INSTRUCTION("A10C004C", st4(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr(x5))); + TEST_INSTRUCTION("A10C9F4C", st4(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr_post(x5, 64))); + TEST_INSTRUCTION("A10C8B4C", st4(v1.d2(), v2.d2(), v3.d2(), v4.d2(), ptr_post(x5, x11))); + TEST_INSTRUCTION("8109002C", stnp(s1, s2, ptr(x12))); + TEST_INSTRUCTION("8189002C", stnp(s1, s2, ptr(x12, 4))); + TEST_INSTRUCTION("8109302C", stnp(s1, s2, ptr(x12, -128))); + TEST_INSTRUCTION("E10B002C", stnp(s1, s2, ptr(sp))); + TEST_INSTRUCTION("E18B002C", stnp(s1, s2, ptr(sp, 4))); + TEST_INSTRUCTION("E10B102C", stnp(s1, s2, ptr(sp, 128))); + TEST_INSTRUCTION("8109006C", stnp(d1, d2, ptr(x12))); + TEST_INSTRUCTION("8189006C", stnp(d1, d2, ptr(x12, 8))); + TEST_INSTRUCTION("8109386C", stnp(d1, d2, ptr(x12, -128))); + TEST_INSTRUCTION("E10B006C", stnp(d1, d2, ptr(sp))); + TEST_INSTRUCTION("E18B006C", stnp(d1, d2, ptr(sp, 8))); + TEST_INSTRUCTION("E10B086C", stnp(d1, d2, ptr(sp, 128))); + TEST_INSTRUCTION("810900AC", stnp(q1, q2, ptr(x12))); + TEST_INSTRUCTION("818900AC", stnp(q1, q2, ptr(x12, 16))); + TEST_INSTRUCTION("81093CAC", stnp(q1, q2, ptr(x12, -128))); + TEST_INSTRUCTION("E10B00AC", stnp(q1, q2, ptr(sp))); + TEST_INSTRUCTION("E18B00AC", stnp(q1, q2, ptr(sp, 16))); + TEST_INSTRUCTION("E10B04AC", stnp(q1, q2, ptr(sp, 128))); + TEST_INSTRUCTION("8109002D", stp(s1, s2, ptr(x12))); + TEST_INSTRUCTION("8189002D", stp(s1, s2, ptr(x12, 4))); + TEST_INSTRUCTION("8109302D", stp(s1, s2, ptr(x12, -128))); + TEST_INSTRUCTION("8189802D", stp(s1, s2, ptr_pre(x12, 4))); + TEST_INSTRUCTION("8189802C", stp(s1, s2, ptr_post(x12, 4))); + TEST_INSTRUCTION("E10B002D", stp(s1, s2, ptr(sp))); + TEST_INSTRUCTION("E18B002D", stp(s1, s2, ptr(sp, 4))); + TEST_INSTRUCTION("E10B102D", stp(s1, s2, ptr(sp, 128))); + TEST_INSTRUCTION("E18B802D", stp(s1, s2, ptr_pre(sp, 4))); + TEST_INSTRUCTION("E18B802C", stp(s1, s2, ptr_post(sp, 4))); + TEST_INSTRUCTION("8109006D", stp(d1, d2, ptr(x12))); + TEST_INSTRUCTION("8189006D", stp(d1, d2, ptr(x12, 8))); + TEST_INSTRUCTION("8109386D", stp(d1, d2, ptr(x12, -128))); + TEST_INSTRUCTION("8189806D", stp(d1, d2, ptr_pre(x12, 8))); + TEST_INSTRUCTION("8189806C", stp(d1, d2, ptr_post(x12, 8))); + TEST_INSTRUCTION("E10B006D", stp(d1, d2, ptr(sp))); + TEST_INSTRUCTION("E18B006D", stp(d1, d2, ptr(sp, 8))); + TEST_INSTRUCTION("E10B086D", stp(d1, d2, ptr(sp, 128))); + TEST_INSTRUCTION("E18B806D", stp(d1, d2, ptr_pre(sp, 8))); + TEST_INSTRUCTION("E18B806C", stp(d1, d2, ptr_post(sp, 8))); + TEST_INSTRUCTION("810900AD", stp(q1, q2, ptr(x12))); + TEST_INSTRUCTION("818900AD", stp(q1, q2, ptr(x12, 16))); + TEST_INSTRUCTION("81093CAD", stp(q1, q2, ptr(x12, -128))); + TEST_INSTRUCTION("818980AD", stp(q1, q2, ptr_pre(x12, 16))); + TEST_INSTRUCTION("818980AC", stp(q1, q2, ptr_post(x12, 16))); + TEST_INSTRUCTION("E10B00AD", stp(q1, q2, ptr(sp))); + TEST_INSTRUCTION("E18B00AD", stp(q1, q2, ptr(sp, 16))); + TEST_INSTRUCTION("E10B04AD", stp(q1, q2, ptr(sp, 128))); + TEST_INSTRUCTION("E18B80AD", stp(q1, q2, ptr_pre(sp, 16))); + TEST_INSTRUCTION("E18B80AC", stp(q1, q2, ptr_post(sp, 16))); + TEST_INSTRUCTION("4100003D", str(b1, ptr(x2))); + TEST_INSTRUCTION("4114003C", str(b1, ptr_post(x2, 1))); + TEST_INSTRUCTION("4104003D", str(b1, ptr(x2, 1))); + TEST_INSTRUCTION("411C003C", str(b1, ptr_pre(x2, 1))); + TEST_INSTRUCTION("4114083C", str(b1, ptr_post(x2, 129))); + TEST_INSTRUCTION("4100007D", str(h1, ptr(x2))); + TEST_INSTRUCTION("4124007C", str(h1, ptr_post(x2, 2))); + TEST_INSTRUCTION("4104007D", str(h1, ptr(x2, 2))); + TEST_INSTRUCTION("412C007C", str(h1, ptr_pre(x2, 2))); + TEST_INSTRUCTION("4124087C", str(h1, ptr_post(x2, 130))); + TEST_INSTRUCTION("410000BD", str(s1, ptr(x2))); + TEST_INSTRUCTION("414400BC", str(s1, ptr_post(x2, 4))); + TEST_INSTRUCTION("410400BD", str(s1, ptr(x2, 4))); + TEST_INSTRUCTION("414C00BC", str(s1, ptr_pre(x2, 4))); + TEST_INSTRUCTION("414408BC", str(s1, ptr_post(x2, 132))); + TEST_INSTRUCTION("410000FD", str(d1, ptr(x2))); + TEST_INSTRUCTION("418400FC", str(d1, ptr_post(x2, 8))); + TEST_INSTRUCTION("410400FD", str(d1, ptr(x2, 8))); + TEST_INSTRUCTION("418C00FC", str(d1, ptr_pre(x2, 8))); + TEST_INSTRUCTION("414408FC", str(d1, ptr_post(x2, 132))); + TEST_INSTRUCTION("4168233C", str(b1, ptr(x2, x3))); + TEST_INSTRUCTION("4148233C", str(b1, ptr(x2, w3, uxtw(0)))); + TEST_INSTRUCTION("41C8233C", str(b1, ptr(x2, w3, sxtw(0)))); + TEST_INSTRUCTION("4168237C", str(h1, ptr(x2, x3))); + TEST_INSTRUCTION("4178237C", str(h1, ptr(x2, x3, lsl(1)))); + TEST_INSTRUCTION("4148237C", str(h1, ptr(x2, w3, uxtw(0)))); + TEST_INSTRUCTION("4158237C", str(h1, ptr(x2, w3, uxtw(1)))); + TEST_INSTRUCTION("41C8237C", str(h1, ptr(x2, w3, sxtw(0)))); + TEST_INSTRUCTION("41D8237C", str(h1, ptr(x2, w3, sxtw(1)))); + TEST_INSTRUCTION("416823BC", str(s1, ptr(x2, x3))); + TEST_INSTRUCTION("417823BC", str(s1, ptr(x2, x3, lsl(2)))); + TEST_INSTRUCTION("414823BC", str(s1, ptr(x2, w3, uxtw(0)))); + TEST_INSTRUCTION("415823BC", str(s1, ptr(x2, w3, uxtw(2)))); + TEST_INSTRUCTION("41C823BC", str(s1, ptr(x2, w3, sxtw(0)))); + TEST_INSTRUCTION("41D823BC", str(s1, ptr(x2, w3, sxtw(2)))); + TEST_INSTRUCTION("416823FC", str(d1, ptr(x2, x3))); + TEST_INSTRUCTION("417823FC", str(d1, ptr(x2, x3, lsl(3)))); + TEST_INSTRUCTION("414823FC", str(d1, ptr(x2, w3, uxtw(0)))); + TEST_INSTRUCTION("415823FC", str(d1, ptr(x2, w3, uxtw(3)))); + TEST_INSTRUCTION("41C823FC", str(d1, ptr(x2, w3, sxtw(0)))); + TEST_INSTRUCTION("41D823FC", str(d1, ptr(x2, w3, sxtw(3)))); + TEST_INSTRUCTION("4104003D", str(b1, ptr(x2, 1))); + TEST_INSTRUCTION("41F01F3C", str(b1, ptr(x2, -1))); // STUR + TEST_INSTRUCTION("4110007C", str(h1, ptr(x2, 1))); // STUR + TEST_INSTRUCTION("41F01F7C", str(h1, ptr(x2, -1))); // STUR + TEST_INSTRUCTION("411000BC", str(s1, ptr(x2, 1))); // STUR + TEST_INSTRUCTION("41F01FBC", str(s1, ptr(x2, -1))); // STUR + TEST_INSTRUCTION("411000FC", str(d1, ptr(x2, 1))); // STUR + TEST_INSTRUCTION("41F01FFC", str(d1, ptr(x2, -1))); // STUR + TEST_INSTRUCTION("8101003C", stur(b1, ptr(x12))); + TEST_INSTRUCTION("8131003C", stur(b1, ptr(x12, 3))); + TEST_INSTRUCTION("8131063C", stur(b1, ptr(x12, 99))); + TEST_INSTRUCTION("81F10F3C", stur(b1, ptr(x12, 255))); + TEST_INSTRUCTION("8101103C", stur(b1, ptr(x12, -256))); + TEST_INSTRUCTION("E103003C", stur(b1, ptr(sp))); + TEST_INSTRUCTION("E153083C", stur(b1, ptr(sp, 133))); + TEST_INSTRUCTION("8101007C", stur(h1, ptr(x12))); + TEST_INSTRUCTION("8131007C", stur(h1, ptr(x12, 3))); + TEST_INSTRUCTION("8131067C", stur(h1, ptr(x12, 99))); + TEST_INSTRUCTION("81F10F7C", stur(h1, ptr(x12, 255))); + TEST_INSTRUCTION("8101107C", stur(h1, ptr(x12, -256))); + TEST_INSTRUCTION("E103007C", stur(h1, ptr(sp))); + TEST_INSTRUCTION("E153087C", stur(h1, ptr(sp, 133))); + TEST_INSTRUCTION("810100BC", stur(s1, ptr(x12))); + TEST_INSTRUCTION("813100BC", stur(s1, ptr(x12, 3))); + TEST_INSTRUCTION("813106BC", stur(s1, ptr(x12, 99))); + TEST_INSTRUCTION("81F10FBC", stur(s1, ptr(x12, 255))); + TEST_INSTRUCTION("810110BC", stur(s1, ptr(x12, -256))); + TEST_INSTRUCTION("E10300BC", stur(s1, ptr(sp))); + TEST_INSTRUCTION("E15308BC", stur(s1, ptr(sp, 133))); + TEST_INSTRUCTION("810100FC", stur(d1, ptr(x12))); + TEST_INSTRUCTION("813100FC", stur(d1, ptr(x12, 3))); + TEST_INSTRUCTION("813106FC", stur(d1, ptr(x12, 99))); + TEST_INSTRUCTION("81F10FFC", stur(d1, ptr(x12, 255))); + TEST_INSTRUCTION("810110FC", stur(d1, ptr(x12, -256))); + TEST_INSTRUCTION("E10300FC", stur(d1, ptr(sp))); + TEST_INSTRUCTION("E15308FC", stur(d1, ptr(sp, 133))); + TEST_INSTRUCTION("8101803C", stur(q1, ptr(x12))); + TEST_INSTRUCTION("8131803C", stur(q1, ptr(x12, 3))); + TEST_INSTRUCTION("8131863C", stur(q1, ptr(x12, 99))); + TEST_INSTRUCTION("81F18F3C", stur(q1, ptr(x12, 255))); + TEST_INSTRUCTION("8101903C", stur(q1, ptr(x12, -256))); + TEST_INSTRUCTION("E103803C", stur(q1, ptr(sp))); + TEST_INSTRUCTION("E153883C", stur(q1, ptr(sp, 133))); + TEST_INSTRUCTION("4184232E", sub(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4184632E", sub(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4184A32E", sub(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4184E37E", sub(d1, d2, d3)); + TEST_INSTRUCTION("4184236E", sub(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4184636E", sub(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4184A36E", sub(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4184E36E", sub(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4160230E", subhn(v1.b8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4160630E", subhn(v1.h4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4160A30E", subhn(v1.s2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4160234E", subhn2(v1.b16(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4160634E", subhn2(v1.h8(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4160A34E", subhn2(v1.s4(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41F0030F", sudot(v1.s2(), v2.b8(), v3.b4(0))); + TEST_INSTRUCTION("41F0230F", sudot(v1.s2(), v2.b8(), v3.b4(1))); + TEST_INSTRUCTION("41F8030F", sudot(v1.s2(), v2.b8(), v3.b4(2))); + TEST_INSTRUCTION("41F8230F", sudot(v1.s2(), v2.b8(), v3.b4(3))); + TEST_INSTRUCTION("41F0034F", sudot(v1.s4(), v2.b16(), v3.b4(0))); + TEST_INSTRUCTION("41F0234F", sudot(v1.s4(), v2.b16(), v3.b4(1))); + TEST_INSTRUCTION("41F8034F", sudot(v1.s4(), v2.b16(), v3.b4(2))); + TEST_INSTRUCTION("41F8234F", sudot(v1.s4(), v2.b16(), v3.b4(3))); + TEST_INSTRUCTION("4138205E", suqadd(b1, b2)); + TEST_INSTRUCTION("4138605E", suqadd(h1, h2)); + TEST_INSTRUCTION("4138A05E", suqadd(s1, s2)); + TEST_INSTRUCTION("4138E05E", suqadd(d1, d2)); + TEST_INSTRUCTION("4138200E", suqadd(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4138600E", suqadd(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4138A00E", suqadd(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4138204E", suqadd(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4138604E", suqadd(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4138A04E", suqadd(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4138E04E", suqadd(v1.d2(), v2.d2())); + TEST_INSTRUCTION("41A4080F", sxtl(v1.h8(), v2.b8())); + TEST_INSTRUCTION("41A4100F", sxtl(v1.s4(), v2.h4())); + TEST_INSTRUCTION("41A4200F", sxtl(v1.d2(), v2.s2())); + TEST_INSTRUCTION("41A4084F", sxtl2(v1.h8(), v2.b16())); + TEST_INSTRUCTION("41A4104F", sxtl2(v1.s4(), v2.h8())); + TEST_INSTRUCTION("41A4204F", sxtl2(v1.d2(), v2.s4())); + TEST_INSTRUCTION("4100030E", tbl(v1.b8(), v2.b16(), v3.b8())); + TEST_INSTRUCTION("4120040E", tbl(v1.b8(), v2.b16(), v3.b16(), v4.b8())); + TEST_INSTRUCTION("4140050E", tbl(v1.b8(), v2.b16(), v3.b16(), v4.b16(), v5.b8())); + TEST_INSTRUCTION("4160060E", tbl(v1.b8(), v2.b16(), v3.b16(), v4.b16(), v5.b16(), v6.b8())); + TEST_INSTRUCTION("4100034E", tbl(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4120044E", tbl(v1.b16(), v2.b16(), v3.b16(), v4.b16())); + TEST_INSTRUCTION("4140054E", tbl(v1.b16(), v2.b16(), v3.b16(), v4.b16(), v5.b16())); + TEST_INSTRUCTION("4160064E", tbl(v1.b16(), v2.b16(), v3.b16(), v4.b16(), v5.b16(), v6.b16())); + TEST_INSTRUCTION("4110030E", tbx(v1.b8(), v2.b16(), v3.b8())); + TEST_INSTRUCTION("4130040E", tbx(v1.b8(), v2.b16(), v3.b16(), v4.b8())); + TEST_INSTRUCTION("4150050E", tbx(v1.b8(), v2.b16(), v3.b16(), v4.b16(), v5.b8())); + TEST_INSTRUCTION("4170060E", tbx(v1.b8(), v2.b16(), v3.b16(), v4.b16(), v5.b16(), v6.b8())); + TEST_INSTRUCTION("4110034E", tbx(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4130044E", tbx(v1.b16(), v2.b16(), v3.b16(), v4.b16())); + TEST_INSTRUCTION("4150054E", tbx(v1.b16(), v2.b16(), v3.b16(), v4.b16(), v5.b16())); + TEST_INSTRUCTION("4170064E", tbx(v1.b16(), v2.b16(), v3.b16(), v4.b16(), v5.b16(), v6.b16())); + TEST_INSTRUCTION("4128030E", trn1(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4128430E", trn1(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4128830E", trn1(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4128034E", trn1(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4128434E", trn1(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4128834E", trn1(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4128C34E", trn1(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4168030E", trn2(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4168430E", trn2(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4168830E", trn2(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4168034E", trn2(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4168434E", trn2(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4168834E", trn2(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4168C34E", trn2(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("417C232E", uaba(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("417C632E", uaba(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("417CA32E", uaba(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("417C236E", uaba(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("417C636E", uaba(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("417CA36E", uaba(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4150232E", uabal(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4150632E", uabal(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4150A32E", uabal(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4150236E", uabal2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4150636E", uabal2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4150A36E", uabal2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4174232E", uabd(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4174632E", uabd(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4174A32E", uabd(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4174236E", uabd(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4174636E", uabd(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4174A36E", uabd(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4170232E", uabdl(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4170632E", uabdl(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4170A32E", uabdl(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4170236E", uabdl2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4170636E", uabdl2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4170A36E", uabdl2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4168202E", uadalp(v1.h4(), v2.b8())); + TEST_INSTRUCTION("4168602E", uadalp(v1.s2(), v2.h4())); + TEST_INSTRUCTION("4168A02E", uadalp(d1, v2.s2())); + TEST_INSTRUCTION("4168206E", uadalp(v1.h8(), v2.b16())); + TEST_INSTRUCTION("4168606E", uadalp(v1.s4(), v2.h8())); + TEST_INSTRUCTION("4168A06E", uadalp(v1.d2(), v2.s4())); + TEST_INSTRUCTION("4100232E", uaddl(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4100632E", uaddl(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4100A32E", uaddl(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4100236E", uaddl2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4100636E", uaddl2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4100A36E", uaddl2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4128202E", uaddlp(v1.h4(), v2.b8())); + TEST_INSTRUCTION("4128602E", uaddlp(v1.s2(), v2.h4())); + TEST_INSTRUCTION("4128A02E", uaddlp(d1, v2.s2())); + TEST_INSTRUCTION("4128206E", uaddlp(v1.h8(), v2.b16())); + TEST_INSTRUCTION("4128606E", uaddlp(v1.s4(), v2.h8())); + TEST_INSTRUCTION("4128A06E", uaddlp(v1.d2(), v2.s4())); + TEST_INSTRUCTION("4138302E", uaddlv(h1, v2.b8())); + TEST_INSTRUCTION("4138306E", uaddlv(h1, v2.b16())); + TEST_INSTRUCTION("4138702E", uaddlv(s1, v2.h4())); + TEST_INSTRUCTION("4138706E", uaddlv(s1, v2.h8())); + TEST_INSTRUCTION("4138B06E", uaddlv(d1, v2.s4())); + TEST_INSTRUCTION("4110232E", uaddw(v1.h8(), v2.h8(), v3.b8())); + TEST_INSTRUCTION("4110632E", uaddw(v1.s4(), v2.s4(), v3.h4())); + TEST_INSTRUCTION("4110A32E", uaddw(v1.d2(), v2.d2(), v3.s2())); + TEST_INSTRUCTION("4110236E", uaddw2(v1.h8(), v2.h8(), v3.b16())); + TEST_INSTRUCTION("4110636E", uaddw2(v1.s4(), v2.s4(), v3.h8())); + TEST_INSTRUCTION("4110A36E", uaddw2(v1.d2(), v2.d2(), v3.s4())); + TEST_INSTRUCTION("4100E31E", ucvtf(h1, w2)); + TEST_INSTRUCTION("4100231E", ucvtf(s1, w2)); + TEST_INSTRUCTION("4100631E", ucvtf(d1, w2)); + TEST_INSTRUCTION("4100E39E", ucvtf(h1, x2)); + TEST_INSTRUCTION("4100239E", ucvtf(s1, x2)); + TEST_INSTRUCTION("4100639E", ucvtf(d1, x2)); + TEST_INSTRUCTION("41D8797E", ucvtf(h1, h2)); + TEST_INSTRUCTION("41D8217E", ucvtf(s1, s2)); + TEST_INSTRUCTION("41D8617E", ucvtf(d1, d2)); + TEST_INSTRUCTION("41D8792E", ucvtf(v1.h4(), v2.h4())); + TEST_INSTRUCTION("41D8212E", ucvtf(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41D8796E", ucvtf(v1.h8(), v2.h8())); + TEST_INSTRUCTION("41D8216E", ucvtf(v1.s4(), v2.s4())); + TEST_INSTRUCTION("41D8616E", ucvtf(v1.d2(), v2.d2())); + TEST_INSTRUCTION("41E0C31E", ucvtf(h1, w2, 8)); + TEST_INSTRUCTION("41E0031E", ucvtf(s1, w2, 8)); + TEST_INSTRUCTION("41E0431E", ucvtf(d1, w2, 8)); + TEST_INSTRUCTION("41E0C39E", ucvtf(h1, x2, 8)); + TEST_INSTRUCTION("41E0039E", ucvtf(s1, x2, 8)); + TEST_INSTRUCTION("41E0439E", ucvtf(d1, x2, 8)); + TEST_INSTRUCTION("41E4187F", ucvtf(h1, h2, 8)); + TEST_INSTRUCTION("41E4387F", ucvtf(s1, s2, 8)); + TEST_INSTRUCTION("41E4787F", ucvtf(d1, d2, 8)); + TEST_INSTRUCTION("41E4182F", ucvtf(v1.h4(), v2.h4(), 8)); + TEST_INSTRUCTION("41E4382F", ucvtf(v1.s2(), v2.s2(), 8)); + TEST_INSTRUCTION("41E4186F", ucvtf(v1.h8(), v2.h8(), 8)); + TEST_INSTRUCTION("41E4386F", ucvtf(v1.s4(), v2.s4(), 8)); + TEST_INSTRUCTION("41E4786F", ucvtf(v1.d2(), v2.d2(), 8)); + TEST_INSTRUCTION("4194832E", udot(v1.s2(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4194836E", udot(v1.s4(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41E0832F", udot(v1.s2(), v2.b8(), v3.b4(0))); + TEST_INSTRUCTION("41E0A32F", udot(v1.s2(), v2.b8(), v3.b4(1))); + TEST_INSTRUCTION("41E8832F", udot(v1.s2(), v2.b8(), v3.b4(2))); + TEST_INSTRUCTION("41E8A32F", udot(v1.s2(), v2.b8(), v3.b4(3))); + TEST_INSTRUCTION("41E0836F", udot(v1.s4(), v2.b16(), v3.b4(0))); + TEST_INSTRUCTION("41E0A36F", udot(v1.s4(), v2.b16(), v3.b4(1))); + TEST_INSTRUCTION("41E8836F", udot(v1.s4(), v2.b16(), v3.b4(2))); + TEST_INSTRUCTION("41E8A36F", udot(v1.s4(), v2.b16(), v3.b4(3))); + TEST_INSTRUCTION("4104232E", uhadd(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4104632E", uhadd(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4104A32E", uhadd(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4104236E", uhadd(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4104636E", uhadd(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4104A36E", uhadd(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4124232E", uhsub(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4124632E", uhsub(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4124A32E", uhsub(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4124236E", uhsub(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4124636E", uhsub(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4124A36E", uhsub(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4164232E", umax(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4164632E", umax(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4164A32E", umax(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4164236E", umax(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4164636E", umax(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4164A36E", umax(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41A4232E", umaxp(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("41A4632E", umaxp(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41A4A32E", umaxp(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41A4236E", umaxp(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41A4636E", umaxp(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41A4A36E", umaxp(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41A8302E", umaxv(b1, v2.b8())); + TEST_INSTRUCTION("41A8306E", umaxv(b1, v2.b16())); + TEST_INSTRUCTION("41A8702E", umaxv(h1, v2.h4())); + TEST_INSTRUCTION("41A8706E", umaxv(h1, v2.h8())); + TEST_INSTRUCTION("41A8B06E", umaxv(s1, v2.s4())); + TEST_INSTRUCTION("416C232E", umin(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("416C632E", umin(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("416CA32E", umin(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("416C236E", umin(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("416C636E", umin(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("416CA36E", umin(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41AC232E", uminp(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("41AC632E", uminp(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41ACA32E", uminp(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41AC236E", uminp(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41AC636E", uminp(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41ACA36E", uminp(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41A8312E", uminv(b1, v2.b8())); + TEST_INSTRUCTION("41A8316E", uminv(b1, v2.b16())); + TEST_INSTRUCTION("41A8712E", uminv(h1, v2.h4())); + TEST_INSTRUCTION("41A8716E", uminv(h1, v2.h8())); + TEST_INSTRUCTION("41A8B16E", uminv(s1, v2.s4())); + TEST_INSTRUCTION("4180232E", umlal(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4180632E", umlal(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4180A32E", umlal(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4120732F", umlal(v1.s4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("4128A32F", umlal(v1.d2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("4180236E", umlal2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4180636E", umlal2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4180A36E", umlal2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4120736F", umlal2(v1.s4(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("4128A36F", umlal2(v1.d2(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("41A0232E", umlsl(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("41A0632E", umlsl(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41A0A32E", umlsl(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4160732F", umlsl(v1.s4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("4168A32F", umlsl(v1.d2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("41A0236E", umlsl2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41A0636E", umlsl2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41A0A36E", umlsl2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4160736F", umlsl2(v1.s4(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("4168A36F", umlsl2(v1.d2(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("41A4836E", ummla(v1.s4(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("413C010E", umov(w1, v2.b(0))); + TEST_INSTRUCTION("413C1F0E", umov(w1, v2.b(15))); + TEST_INSTRUCTION("413C020E", umov(w1, v2.h(0))); + TEST_INSTRUCTION("413C1E0E", umov(w1, v2.h(7))); + TEST_INSTRUCTION("413C040E", umov(w1, v2.s(0))); + TEST_INSTRUCTION("413C1C0E", umov(w1, v2.s(3))); + TEST_INSTRUCTION("413C084E", umov(x1, v2.d(0))); + TEST_INSTRUCTION("413C184E", umov(x1, v2.d(1))); + TEST_INSTRUCTION("41C0232E", umull(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("41C0632E", umull(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("41C0A32E", umull(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("41A0732F", umull(v1.s4(), v2.h4(), v3.h(3))); + TEST_INSTRUCTION("41A8A32F", umull(v1.d2(), v2.s2(), v3.s(3))); + TEST_INSTRUCTION("41C0236E", umull2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41C0636E", umull2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("41C0A36E", umull2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("41A0736F", umull2(v1.s4(), v2.h8(), v3.h(3))); + TEST_INSTRUCTION("41A8A36F", umull2(v1.d2(), v2.s4(), v3.s(3))); + TEST_INSTRUCTION("410C237E", uqadd(b1, b2, b3)); + TEST_INSTRUCTION("410C637E", uqadd(h1, h2, h3)); + TEST_INSTRUCTION("410CA37E", uqadd(s1, s2, s3)); + TEST_INSTRUCTION("410CE37E", uqadd(d1, d2, d3)); + TEST_INSTRUCTION("410C232E", uqadd(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("410C632E", uqadd(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("410CA32E", uqadd(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("410C236E", uqadd(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("410C636E", uqadd(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("410CA36E", uqadd(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("410CE36E", uqadd(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("415C237E", uqrshl(b1, b2, b3)); + TEST_INSTRUCTION("415C637E", uqrshl(h1, h2, h3)); + TEST_INSTRUCTION("415CA37E", uqrshl(s1, s2, s3)); + TEST_INSTRUCTION("415C232E", uqrshl(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("415C632E", uqrshl(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("415CA32E", uqrshl(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("415CE37E", uqrshl(d1, d2, d3)); + TEST_INSTRUCTION("415C236E", uqrshl(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("415C636E", uqrshl(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("415CA36E", uqrshl(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("415CE36E", uqrshl(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("419C087F", uqrshrn(b1, h2, 8)); + TEST_INSTRUCTION("419C107F", uqrshrn(h1, s2, 16)); + TEST_INSTRUCTION("419C207F", uqrshrn(s1, d2, 32)); + TEST_INSTRUCTION("419C082F", uqrshrn(v1.b8(), v2.h8(), 8)); + TEST_INSTRUCTION("419C102F", uqrshrn(v1.h4(), v2.s4(), 16)); + TEST_INSTRUCTION("419C202F", uqrshrn(v1.s2(), v2.d2(), 32)); + TEST_INSTRUCTION("419C086F", uqrshrn2(v1.b16(), v2.h8(), 8)); + TEST_INSTRUCTION("419C106F", uqrshrn2(v1.h8(), v2.s4(), 16)); + TEST_INSTRUCTION("419C206F", uqrshrn2(v1.s4(), v2.d2(), 32)); + TEST_INSTRUCTION("4174097F", uqshl(b1, b2, 1)); + TEST_INSTRUCTION("4174127F", uqshl(h1, h2, 2)); + TEST_INSTRUCTION("4174237F", uqshl(s1, s2, 3)); + TEST_INSTRUCTION("41740F2F", uqshl(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("41741F2F", uqshl(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("41743F2F", uqshl(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("41747F7F", uqshl(d1, d2, 63)); + TEST_INSTRUCTION("41740F6F", uqshl(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("41741F6F", uqshl(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("41743F6F", uqshl(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("41747F6F", uqshl(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("414C237E", uqshl(b1, b2, b3)); + TEST_INSTRUCTION("414C637E", uqshl(h1, h2, h3)); + TEST_INSTRUCTION("414CA37E", uqshl(s1, s2, s3)); + TEST_INSTRUCTION("414C232E", uqshl(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("414C632E", uqshl(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("414CA32E", uqshl(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("414CE37E", uqshl(d1, d2, d3)); + TEST_INSTRUCTION("414C236E", uqshl(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("414C636E", uqshl(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("414CA36E", uqshl(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("414CE36E", uqshl(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4194087F", uqshrn(b1, h2, 8)); + TEST_INSTRUCTION("4194107F", uqshrn(h1, s2, 16)); + TEST_INSTRUCTION("4194207F", uqshrn(s1, d2, 32)); + TEST_INSTRUCTION("4194082F", uqshrn(v1.b8(), v2.h8(), 8)); + TEST_INSTRUCTION("4194102F", uqshrn(v1.h4(), v2.s4(), 16)); + TEST_INSTRUCTION("4194202F", uqshrn(v1.s2(), v2.d2(), 32)); + TEST_INSTRUCTION("4194086F", uqshrn2(v1.b16(), v2.h8(), 8)); + TEST_INSTRUCTION("4194106F", uqshrn2(v1.h8(), v2.s4(), 16)); + TEST_INSTRUCTION("4194206F", uqshrn2(v1.s4(), v2.d2(), 32)); + TEST_INSTRUCTION("412C237E", uqsub(b1, b2, b3)); + TEST_INSTRUCTION("412C637E", uqsub(h1, h2, h3)); + TEST_INSTRUCTION("412CA37E", uqsub(s1, s2, s3)); + TEST_INSTRUCTION("412CE37E", uqsub(d1, d2, d3)); + TEST_INSTRUCTION("412C232E", uqsub(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("412C632E", uqsub(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("412CA32E", uqsub(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("412C236E", uqsub(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("412C636E", uqsub(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("412CA36E", uqsub(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("412CE36E", uqsub(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4148217E", uqxtn(b1, h2)); + TEST_INSTRUCTION("4148617E", uqxtn(h1, s2)); + TEST_INSTRUCTION("4148A17E", uqxtn(s1, d2)); + TEST_INSTRUCTION("4148212E", uqxtn(v1.b8(), v2.h8())); + TEST_INSTRUCTION("4148612E", uqxtn(v1.h4(), v2.s4())); + TEST_INSTRUCTION("4148A12E", uqxtn(v1.s2(), v2.d2())); + TEST_INSTRUCTION("4148216E", uqxtn2(v1.b16(), v2.h8())); + TEST_INSTRUCTION("4148616E", uqxtn2(v1.h8(), v2.s4())); + TEST_INSTRUCTION("4148A16E", uqxtn2(v1.s4(), v2.d2())); + TEST_INSTRUCTION("41C8A10E", urecpe(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41C8A14E", urecpe(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4114232E", urhadd(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4114632E", urhadd(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4114A32E", urhadd(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4114236E", urhadd(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4114636E", urhadd(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4114A36E", urhadd(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4154232E", urshl(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4154632E", urshl(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4154A32E", urshl(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4154E37E", urshl(d1, d2, d3)); + TEST_INSTRUCTION("4154236E", urshl(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4154636E", urshl(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4154A36E", urshl(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4154E36E", urshl(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4124092F", urshr(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("4124112F", urshr(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("4124212F", urshr(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("4124417F", urshr(d1, d2, 63)); + TEST_INSTRUCTION("4124096F", urshr(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("4124116F", urshr(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("4124216F", urshr(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("4124416F", urshr(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("41C8A12E", ursqrte(v1.s2(), v2.s2())); + TEST_INSTRUCTION("41C8A16E", ursqrte(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4134092F", ursra(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("4134112F", ursra(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("4134212F", ursra(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("4134417F", ursra(d1, d2, 63)); + TEST_INSTRUCTION("4134096F", ursra(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("4134116F", ursra(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("4134216F", ursra(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("4134416F", ursra(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("419C830E", usdot(v1.s2(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("419C834E", usdot(v1.s4(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("41F0830F", usdot(v1.s2(), v2.b8(), v3.b4(0))); + TEST_INSTRUCTION("41F0A30F", usdot(v1.s2(), v2.b8(), v3.b4(1))); + TEST_INSTRUCTION("41F8830F", usdot(v1.s2(), v2.b8(), v3.b4(2))); + TEST_INSTRUCTION("41F8A30F", usdot(v1.s2(), v2.b8(), v3.b4(3))); + TEST_INSTRUCTION("41F0834F", usdot(v1.s4(), v2.b16(), v3.b4(0))); + TEST_INSTRUCTION("41F0A34F", usdot(v1.s4(), v2.b16(), v3.b4(1))); + TEST_INSTRUCTION("41F8834F", usdot(v1.s4(), v2.b16(), v3.b4(2))); + TEST_INSTRUCTION("41F8A34F", usdot(v1.s4(), v2.b16(), v3.b4(3))); + TEST_INSTRUCTION("4144232E", ushl(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4144632E", ushl(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4144A32E", ushl(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4144E37E", ushl(d1, d2, d3)); + TEST_INSTRUCTION("4144236E", ushl(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4144636E", ushl(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4144A36E", ushl(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4144E36E", ushl(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("41A40F2F", ushll(v1.h8(), v2.b8(), 7)); + TEST_INSTRUCTION("41A41F2F", ushll(v1.s4(), v2.h4(), 15)); + TEST_INSTRUCTION("41A43F2F", ushll(v1.d2(), v2.s2(), 31)); + TEST_INSTRUCTION("41A40F6F", ushll2(v1.h8(), v2.b16(), 7)); + TEST_INSTRUCTION("41A41F6F", ushll2(v1.s4(), v2.h8(), 15)); + TEST_INSTRUCTION("41A43F6F", ushll2(v1.s2(), v2.s4(), 31)); + TEST_INSTRUCTION("4104092F", ushr(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("4104112F", ushr(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("4104212F", ushr(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("4104417F", ushr(d1, d2, 63)); + TEST_INSTRUCTION("4104096F", ushr(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("4104116F", ushr(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("4104216F", ushr(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("4104416F", ushr(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("41AC834E", usmmla(v1.s4(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4138207E", usqadd(b1, b2)); + TEST_INSTRUCTION("4138607E", usqadd(h1, h2)); + TEST_INSTRUCTION("4138A07E", usqadd(s1, s2)); + TEST_INSTRUCTION("4138E07E", usqadd(d1, d2)); + TEST_INSTRUCTION("4138202E", usqadd(v1.b8(), v2.b8())); + TEST_INSTRUCTION("4138602E", usqadd(v1.h4(), v2.h4())); + TEST_INSTRUCTION("4138A02E", usqadd(v1.s2(), v2.s2())); + TEST_INSTRUCTION("4138206E", usqadd(v1.b16(), v2.b16())); + TEST_INSTRUCTION("4138606E", usqadd(v1.h8(), v2.h8())); + TEST_INSTRUCTION("4138A06E", usqadd(v1.s4(), v2.s4())); + TEST_INSTRUCTION("4138E06E", usqadd(v1.d2(), v2.d2())); + TEST_INSTRUCTION("4114092F", usra(v1.b8(), v2.b8(), 7)); + TEST_INSTRUCTION("4114112F", usra(v1.h4(), v2.h4(), 15)); + TEST_INSTRUCTION("4114212F", usra(v1.s2(), v2.s2(), 31)); + TEST_INSTRUCTION("4114417F", usra(d1, d2, 63)); + TEST_INSTRUCTION("4114096F", usra(v1.b16(), v2.b16(), 7)); + TEST_INSTRUCTION("4114116F", usra(v1.h8(), v2.h8(), 15)); + TEST_INSTRUCTION("4114216F", usra(v1.s4(), v2.s4(), 31)); + TEST_INSTRUCTION("4114416F", usra(v1.d2(), v2.d2(), 63)); + TEST_INSTRUCTION("4120232E", usubl(v1.h8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4120632E", usubl(v1.s4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4120A32E", usubl(v1.d2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4120236E", usubl2(v1.h8(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4120636E", usubl2(v1.s4(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4120A36E", usubl2(v1.d2(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4130232E", usubw(v1.h8(), v2.h8(), v3.b8())); + TEST_INSTRUCTION("4130632E", usubw(v1.s4(), v2.s4(), v3.h4())); + TEST_INSTRUCTION("4130A32E", usubw(v1.d2(), v2.d2(), v3.s2())); + TEST_INSTRUCTION("4130236E", usubw2(v1.h8(), v2.h8(), v3.b16())); + TEST_INSTRUCTION("4130636E", usubw2(v1.s4(), v2.s4(), v3.h8())); + TEST_INSTRUCTION("4130A36E", usubw2(v1.d2(), v2.d2(), v3.s4())); + TEST_INSTRUCTION("41A4082F", uxtl(v1.h8(), v2.b8())); + TEST_INSTRUCTION("41A4102F", uxtl(v1.s4(), v2.h4())); + TEST_INSTRUCTION("41A4202F", uxtl(v1.d2(), v2.s2())); + TEST_INSTRUCTION("41A4086F", uxtl2(v1.h8(), v2.b16())); + TEST_INSTRUCTION("41A4106F", uxtl2(v1.s4(), v2.h8())); + TEST_INSTRUCTION("41A4206F", uxtl2(v1.d2(), v2.s4())); + TEST_INSTRUCTION("4118030E", uzp1(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4118430E", uzp1(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4118830E", uzp1(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4118034E", uzp1(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4118434E", uzp1(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4118834E", uzp1(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4118C34E", uzp1(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4158030E", uzp2(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4158430E", uzp2(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4158830E", uzp2(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4158034E", uzp2(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4158434E", uzp2(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4158834E", uzp2(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4158C34E", uzp2(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4128210E", xtn(v1.b8(), v2.h8())); + TEST_INSTRUCTION("4128610E", xtn(v1.h4(), v2.s4())); + TEST_INSTRUCTION("4128A10E", xtn(v1.s2(), v2.d2())); + TEST_INSTRUCTION("4128214E", xtn2(v1.b16(), v2.h8())); + TEST_INSTRUCTION("4128614E", xtn2(v1.h8(), v2.s4())); + TEST_INSTRUCTION("4128A14E", xtn2(v1.s4(), v2.d2())); + TEST_INSTRUCTION("4138030E", zip1(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4138430E", zip1(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4138830E", zip1(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4138034E", zip1(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4138434E", zip1(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4138834E", zip1(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4138C34E", zip1(v1.d2(), v2.d2(), v3.d2())); + TEST_INSTRUCTION("4178030E", zip2(v1.b8(), v2.b8(), v3.b8())); + TEST_INSTRUCTION("4178430E", zip2(v1.h4(), v2.h4(), v3.h4())); + TEST_INSTRUCTION("4178830E", zip2(v1.s2(), v2.s2(), v3.s2())); + TEST_INSTRUCTION("4178034E", zip2(v1.b16(), v2.b16(), v3.b16())); + TEST_INSTRUCTION("4178434E", zip2(v1.h8(), v2.h8(), v3.h8())); + TEST_INSTRUCTION("4178834E", zip2(v1.s4(), v2.s4(), v3.s4())); + TEST_INSTRUCTION("4178C34E", zip2(v1.d2(), v2.d2(), v3.d2())); +} + +static void ASMJIT_NOINLINE testA64AssemblerExtras(AssemblerTester<a64::Assembler>& tester) noexcept { + using namespace a64; + + // AsmJit additions - AArch64 assembler accepts variety of immediates in + // MOVI instruction that it encodes by changing the size of its operands. + TEST_INSTRUCTION("C1E7074F", movi(v1.b16(), 0xFE)); + TEST_INSTRUCTION("C1E7074F", movi(v1.h8(), 0xFEFE)); + TEST_INSTRUCTION("C1E7074F", movi(v1.s4(), 0xFEFEFEFE)); + TEST_INSTRUCTION("C1E7074F", movi(v1.d2(), 0xFEFEFEFEFEFEFEFE)); + TEST_INSTRUCTION("C1A7074F", movi(v1.h8(), 0xFE, lsl(8))); + TEST_INSTRUCTION("C1A7074F", movi(v1.h8(), 0xFE00)); + TEST_INSTRUCTION("C1A7074F", movi(v1.s4(), 0xFE00FE00)); + TEST_INSTRUCTION("C1A7074F", movi(v1.d2(), 0xFE00FE00FE00FE00)); + TEST_INSTRUCTION("C147074F", movi(v1.s4(), 0xFE, lsl(16))); + TEST_INSTRUCTION("C147074F", movi(v1.s4(), 0x00FE0000)); + TEST_INSTRUCTION("C147074F", movi(v1.d2(), 0x00FE000000FE0000)); + TEST_INSTRUCTION("C167074F", movi(v1.s4(), 0xFE, lsl(24))); + TEST_INSTRUCTION("C167074F", movi(v1.s4(), 0xFE000000)); + TEST_INSTRUCTION("C167074F", movi(v1.d2(), 0xFE000000FE000000)); +} + +bool testA64Assembler(const TestSettings& settings) noexcept { + using namespace a64; + + AssemblerTester<Assembler> tester(Arch::kAArch64, settings); + tester.printHeader("AArch64"); + + testA64AssemblerBase(tester); + testA64AssemblerRel(tester); + testA64AssemblerSIMD(tester); + testA64AssemblerExtras(tester); + + tester.printSummary(); + return tester.didPass(); +} + +#undef TEST_INSTRUCTION + +#endif // !ASMJIT_NO_AARCH64 diff --git a/test/asmjit_test_compiler.cpp b/test/asmjit_test_compiler.cpp index 70a24a9..f2bc306 100644 --- a/test/asmjit_test_compiler.cpp +++ b/test/asmjit_test_compiler.cpp @@ -24,7 +24,7 @@ void compiler_add_x86_tests(TestApp& app); #endif -#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM == 64 +#if !defined(ASMJIT_NO_AARCH64) && ASMJIT_ARCH_ARM == 64 #include <asmjit/a64.h> void compiler_add_a64_tests(TestApp& app); #endif @@ -33,7 +33,7 @@ void compiler_add_a64_tests(TestApp& app); #define ASMJIT_HAVE_WORKING_JIT #endif -#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM == 64 +#if !defined(ASMJIT_NO_AARCH64) && ASMJIT_ARCH_ARM == 64 #define ASMJIT_HAVE_WORKING_JIT #endif @@ -118,8 +118,8 @@ int TestApp::run() { x86::Compiler cc(&code); #endif -#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM == 64 - arm::Compiler cc(&code); +#if !defined(ASMJIT_NO_AARCH64) && ASMJIT_ARCH_ARM == 64 + a64::Compiler cc(&code); #endif #ifndef ASMJIT_NO_LOGGING @@ -245,7 +245,7 @@ int main(int argc, char* argv[]) { compiler_add_x86_tests(app); #endif -#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM == 64 +#if !defined(ASMJIT_NO_AARCH64) && ASMJIT_ARCH_ARM == 64 compiler_add_a64_tests(app); #endif diff --git a/test/asmjit_test_compiler_a64.cpp b/test/asmjit_test_compiler_a64.cpp new file mode 100644 index 0000000..4fc362e --- /dev/null +++ b/test/asmjit_test_compiler_a64.cpp @@ -0,0 +1,690 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include <asmjit/core.h> +#if !defined(ASMJIT_NO_AARCH64) && ASMJIT_ARCH_ARM == 64 + +#include <asmjit/a64.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "./asmjit_test_compiler.h" + +using namespace asmjit; + +// a64::Compiler - A64TestCase +// =========================== + +class A64TestCase : public TestCase { +public: + A64TestCase(const char* name = nullptr) + : TestCase(name) {} + + virtual void compile(BaseCompiler& cc) override { + compile(static_cast<a64::Compiler&>(cc)); + } + + virtual void compile(a64::Compiler& cc) = 0; +}; + +// a64::Compiler - A64Test_GpArgs +// ============================== + +class A64Test_GpArgs : public A64TestCase { +public: + uint32_t _argCount; + bool _preserveFP; + + A64Test_GpArgs(uint32_t argCount, bool preserveFP) + : _argCount(argCount), + _preserveFP(preserveFP) { + _name.assignFormat("GpArgs {NumArgs=%u PreserveFP=%c}", argCount, preserveFP ? 'Y' : 'N'); + } + + static void add(TestApp& app) { + for (uint32_t i = 0; i <= 16; i++) { + app.add(new A64Test_GpArgs(i, true)); + app.add(new A64Test_GpArgs(i, false)); + } + } + + virtual void compile(a64::Compiler& cc) { + uint32_t i; + uint32_t argCount = _argCount; + + FuncSignatureBuilder signature; + signature.setRetT<int>(); + for (i = 0; i < argCount; i++) + signature.addArgT<int>(); + + FuncNode* funcNode = cc.addFunc(signature); + if (_preserveFP) + funcNode->frame().setPreservedFP(); + + arm::Gp sum; + + if (argCount) { + for (i = 0; i < argCount; i++) { + arm::Gp iReg = cc.newInt32("i%u", i); + funcNode->setArg(i, iReg); + + if (i == 0) + sum = iReg; + else + cc.add(sum, sum, iReg); + } + } + else { + sum = cc.newInt32("i"); + cc.mov(sum, 0); + } + + cc.ret(sum); + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef unsigned int U; + + typedef U (*Func0)(); + typedef U (*Func1)(U); + typedef U (*Func2)(U, U); + typedef U (*Func3)(U, U, U); + typedef U (*Func4)(U, U, U, U); + typedef U (*Func5)(U, U, U, U, U); + typedef U (*Func6)(U, U, U, U, U, U); + typedef U (*Func7)(U, U, U, U, U, U, U); + typedef U (*Func8)(U, U, U, U, U, U, U, U); + typedef U (*Func9)(U, U, U, U, U, U, U, U, U); + typedef U (*Func10)(U, U, U, U, U, U, U, U, U, U); + typedef U (*Func11)(U, U, U, U, U, U, U, U, U, U, U); + typedef U (*Func12)(U, U, U, U, U, U, U, U, U, U, U, U); + typedef U (*Func13)(U, U, U, U, U, U, U, U, U, U, U, U, U); + typedef U (*Func14)(U, U, U, U, U, U, U, U, U, U, U, U, U, U); + typedef U (*Func15)(U, U, U, U, U, U, U, U, U, U, U, U, U, U, U); + typedef U (*Func16)(U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U); + + unsigned int resultRet = 0; + unsigned int expectRet = 0; + + switch (_argCount) { + case 0: + resultRet = ptr_as_func<Func0>(_func)(); + expectRet = 0; + break; + case 1: + resultRet = ptr_as_func<Func1>(_func)(1); + expectRet = 1; + break; + case 2: + resultRet = ptr_as_func<Func2>(_func)(1, 2); + expectRet = 1 + 2; + break; + case 3: + resultRet = ptr_as_func<Func3>(_func)(1, 2, 3); + expectRet = 1 + 2 + 3; + break; + case 4: + resultRet = ptr_as_func<Func4>(_func)(1, 2, 3, 4); + expectRet = 1 + 2 + 3 + 4; + break; + case 5: + resultRet = ptr_as_func<Func5>(_func)(1, 2, 3, 4, 5); + expectRet = 1 + 2 + 3 + 4 + 5; + break; + case 6: + resultRet = ptr_as_func<Func6>(_func)(1, 2, 3, 4, 5, 6); + expectRet = 1 + 2 + 3 + 4 + 5 + 6; + break; + case 7: + resultRet = ptr_as_func<Func7>(_func)(1, 2, 3, 4, 5, 6, 7); + expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7; + break; + case 8: + resultRet = ptr_as_func<Func8>(_func)(1, 2, 3, 4, 5, 6, 7, 8); + expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8; + break; + case 9: + resultRet = ptr_as_func<Func9>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9); + expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9; + break; + case 10: + resultRet = ptr_as_func<Func10>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10; + break; + case 11: + resultRet = ptr_as_func<Func11>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11; + break; + case 12: + resultRet = ptr_as_func<Func12>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); + expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12; + break; + case 13: + resultRet = ptr_as_func<Func13>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13); + expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13; + break; + case 14: + resultRet = ptr_as_func<Func14>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); + expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14; + break; + case 15: + resultRet = ptr_as_func<Func15>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15; + break; + case 16: + resultRet = ptr_as_func<Func16>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16; + break; + } + + result.assignFormat("ret={%u, %u}", resultRet >> 28, resultRet & 0x0FFFFFFFu); + expect.assignFormat("ret={%u, %u}", expectRet >> 28, expectRet & 0x0FFFFFFFu); + + return resultRet == expectRet; + } +}; + +// a64::Compiler - A64Test_Simd1 +// ============================= + +class A64Test_Simd1 : public A64TestCase { +public: + A64Test_Simd1() + : A64TestCase("Simd1") {} + + static void add(TestApp& app) { + app.add(new A64Test_Simd1()); + } + + virtual void compile(a64::Compiler& cc) { + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*, const void*, const void*>()); + + arm::Gp dst = cc.newUIntPtr("dst"); + arm::Gp src1 = cc.newUIntPtr("src1"); + arm::Gp src2 = cc.newUIntPtr("src2"); + + funcNode->setArg(0, dst); + funcNode->setArg(1, src1); + funcNode->setArg(2, src2); + + arm::Vec v1 = cc.newVecQ("vec1"); + arm::Vec v2 = cc.newVecQ("vec2"); + arm::Vec v3 = cc.newVecQ("vec3"); + + cc.ldr(v2, arm::ptr(src1)); + cc.ldr(v3, arm::ptr(src2)); + cc.add(v1.b16(), v2.b16(), v3.b16()); + cc.str(v1, arm::ptr(dst)); + + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef void (*Func)(void*, const void*, const void*); + + uint32_t dst[4]; + uint32_t aSrc[4] = { 0 , 1 , 2 , 255 }; + uint32_t bSrc[4] = { 99, 17, 33, 1 }; + + // NOTE: It's a byte-add, so uint8_t(255+1) == 0. + uint32_t ref[4] = { 99, 18, 35, 0 }; + + ptr_as_func<Func>(_func)(dst, aSrc, bSrc); + + unsigned int resultRet = 0; + unsigned int expectRet = 0; + + result.assignFormat("ret={%u, %u, %u, %u}", dst[0], dst[1], dst[2], dst[3]); + expect.assignFormat("ret={%u, %u, %u, %u}", ref[0], ref[1], ref[2], ref[3]); + + return resultRet == expectRet; + } +}; + +// a64::Compiler - A64Test_ManyRegs +// ================================ + +class A64Test_ManyRegs : public A64TestCase { +public: + uint32_t _regCount; + + A64Test_ManyRegs(uint32_t n) + : A64TestCase(), + _regCount(n) { + _name.assignFormat("GpRegs {NumRegs=%u}", n); + } + + static void add(TestApp& app) { + for (uint32_t i = 2; i < 64; i++) + app.add(new A64Test_ManyRegs(i)); + } + + virtual void compile(a64::Compiler& cc) { + cc.addFunc(FuncSignatureT<int>()); + + arm::Gp* regs = static_cast<arm::Gp*>(malloc(_regCount * sizeof(arm::Gp))); + + for (uint32_t i = 0; i < _regCount; i++) { + regs[i] = cc.newUInt32("reg%u", i); + cc.mov(regs[i], i + 1); + } + + arm::Gp sum = cc.newUInt32("sum"); + cc.mov(sum, 0); + + for (uint32_t i = 0; i < _regCount; i++) { + cc.add(sum, sum, regs[i]); + } + + cc.ret(sum); + cc.endFunc(); + + free(regs); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef int (*Func)(void); + Func func = ptr_as_func<Func>(_func); + + result.assignFormat("ret={%d}", func()); + expect.assignFormat("ret={%d}", calcSum()); + + return result == expect; + } + + uint32_t calcSum() const { + return (_regCount | 1) * ((_regCount + 1) / 2); + } +}; + +// a64::Compiler - A64Test_Adr +// =========================== + +class A64Test_Adr : public A64TestCase { +public: + A64Test_Adr() + : A64TestCase("Adr") {} + + static void add(TestApp& app) { + app.add(new A64Test_Adr()); + } + + virtual void compile(a64::Compiler& cc) { + cc.addFunc(FuncSignatureT<int>()); + + arm::Gp addr = cc.newIntPtr("addr"); + arm::Gp val = cc.newIntPtr("val"); + + Label L_Table = cc.newLabel(); + + cc.adr(addr, L_Table); + cc.ldrsw(val, arm::ptr(addr, 8)); + cc.ret(val); + cc.endFunc(); + + cc.bind(L_Table); + cc.embedInt32(1); + cc.embedInt32(2); + cc.embedInt32(3); + cc.embedInt32(4); + cc.embedInt32(5); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef int (*Func)(void); + Func func = ptr_as_func<Func>(_func); + + result.assignFormat("ret={%d}", func()); + expect.assignFormat("ret={%d}", 3); + + return result == expect; + } +}; + +// a64::Compiler - A64Test_Branch1 +// =============================== + +class A64Test_Branch1 : public A64TestCase { +public: + A64Test_Branch1() + : A64TestCase("Branch1") {} + + static void add(TestApp& app) { + app.add(new A64Test_Branch1()); + } + + virtual void compile(a64::Compiler& cc) { + FuncNode* funcNode = cc.addFunc(FuncSignatureT<void, void*, size_t>()); + + arm::Gp p = cc.newIntPtr("p"); + arm::Gp count = cc.newIntPtr("count"); + arm::Gp i = cc.newIntPtr("i"); + Label L = cc.newLabel(); + + funcNode->setArg(0, p); + funcNode->setArg(1, count); + + cc.mov(i, 0); + + cc.bind(L); + cc.strb(i.w(), a64::ptr(p, i)); + cc.add(i, i, 1); + cc.cmp(i, count); + cc.b_ne(L); + + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef void (*Func)(void* p, size_t n); + Func func = ptr_as_func<Func>(_func); + + uint8_t array[16]; + func(array, 16); + + expect.assign("ret={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}"); + + result.assign("ret={"); + for (size_t i = 0; i < 16; i++) { + if (i) + result.append(", "); + result.appendFormat("%d", int(array[i])); + } + result.append("}"); + + return result == expect; + } +}; + +// a64::Compiler - A64Test_Invoke1 +// =============================== + +class A64Test_Invoke1 : public A64TestCase { +public: + A64Test_Invoke1() + : A64TestCase("Invoke1") {} + + static void add(TestApp& app) { + app.add(new A64Test_Invoke1()); + } + + virtual void compile(a64::Compiler& cc) { + FuncNode* funcNode = cc.addFunc(FuncSignatureT<uint32_t, uint32_t, uint32_t>()); + + arm::Gp x = cc.newUInt32("x"); + arm::Gp y = cc.newUInt32("y"); + arm::Gp r = cc.newUInt32("r"); + arm::Gp fn = cc.newUIntPtr("fn"); + + funcNode->setArg(0, x); + funcNode->setArg(1, y); + + cc.mov(fn, (uint64_t)calledFunc); + + InvokeNode* invokeNode; + cc.invoke(&invokeNode, fn, FuncSignatureT<uint32_t, uint32_t, uint32_t>(CallConvId::kHost)); + invokeNode->setArg(0, x); + invokeNode->setArg(1, y); + invokeNode->setRet(0, r); + + cc.ret(r); + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef uint32_t (*Func)(uint32_t, uint32_t); + Func func = ptr_as_func<Func>(_func); + + uint32_t x = 49; + uint32_t y = 7; + + result.assignFormat("ret={%u}", func(x, y)); + expect.assignFormat("ret={%u}", x - y); + + return result == expect; + } + + static uint32_t calledFunc(uint32_t x, uint32_t y) { + return x - y; + } +}; + +// a64::Compiler - A64Test_Invoke2 +// =============================== + +class A64Test_Invoke2 : public A64TestCase { +public: + A64Test_Invoke2() + : A64TestCase("Invoke2") {} + + static void add(TestApp& app) { + app.add(new A64Test_Invoke2()); + } + + virtual void compile(a64::Compiler& cc) { + FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double>()); + + arm::Vec x = cc.newVecD("x"); + arm::Vec y = cc.newVecD("y"); + arm::Vec r = cc.newVecD("r"); + arm::Gp fn = cc.newUIntPtr("fn"); + + funcNode->setArg(0, x); + funcNode->setArg(1, y); + cc.mov(fn, (uint64_t)calledFunc); + + InvokeNode* invokeNode; + cc.invoke(&invokeNode, fn, FuncSignatureT<double, double, double>(CallConvId::kHost)); + invokeNode->setArg(0, x); + invokeNode->setArg(1, y); + invokeNode->setRet(0, r); + + cc.ret(r); + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef double (*Func)(double, double); + Func func = ptr_as_func<Func>(_func); + + double x = 49; + double y = 7; + + result.assignFormat("ret={%f}", func(x, y)); + expect.assignFormat("ret={%f}", calledFunc(x, y)); + + return result == expect; + } + + static double calledFunc(double x, double y) { + return x - y; + } +}; + +// a64::Compiler - A64Test_Invoke3 +// =============================== + +class A64Test_Invoke3 : public A64TestCase { +public: + A64Test_Invoke3() + : A64TestCase("Invoke3") {} + + static void add(TestApp& app) { + app.add(new A64Test_Invoke3()); + } + + virtual void compile(a64::Compiler& cc) { + FuncNode* funcNode = cc.addFunc(FuncSignatureT<double, double, double>()); + + arm::Vec x = cc.newVecD("x"); + arm::Vec y = cc.newVecD("y"); + arm::Vec r = cc.newVecD("r"); + arm::Gp fn = cc.newUIntPtr("fn"); + + funcNode->setArg(0, x); + funcNode->setArg(1, y); + cc.mov(fn, (uint64_t)calledFunc); + + InvokeNode* invokeNode; + cc.invoke(&invokeNode, fn, FuncSignatureT<double, double, double>(CallConvId::kHost)); + invokeNode->setArg(0, y); + invokeNode->setArg(1, x); + invokeNode->setRet(0, r); + + cc.ret(r); + cc.endFunc(); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef double (*Func)(double, double); + Func func = ptr_as_func<Func>(_func); + + double x = 49; + double y = 7; + + result.assignFormat("ret={%f}", func(x, y)); + expect.assignFormat("ret={%f}", calledFunc(y, x)); + + return result == expect; + } + + static double calledFunc(double x, double y) { + return x - y; + } +}; + +// a64::Compiler - A64Test_JumpTable +// ================================= + +class A64Test_JumpTable : public A64TestCase { +public: + bool _annotated; + + A64Test_JumpTable(bool annotated) + : A64TestCase("A64Test_JumpTable"), + _annotated(annotated) { + _name.assignFormat("JumpTable {%s}", annotated ? "Annotated" : "Unknown Target"); + } + + enum Operator { + kOperatorAdd = 0, + kOperatorSub = 1, + kOperatorMul = 2, + kOperatorDiv = 3 + }; + + static void add(TestApp& app) { + app.add(new A64Test_JumpTable(false)); + app.add(new A64Test_JumpTable(true)); + } + + virtual void compile(a64::Compiler& cc) { + FuncNode* funcNode = cc.addFunc(FuncSignatureT<float, float, float, uint32_t>()); + + arm::Vec a = cc.newVecS("a"); + arm::Vec b = cc.newVecS("b"); + arm::Gp op = cc.newUInt32("op"); + + arm::Gp target = cc.newIntPtr("target"); + arm::Gp offset = cc.newIntPtr("offset"); + + Label L_End = cc.newLabel(); + + Label L_Table = cc.newLabel(); + Label L_Add = cc.newLabel(); + Label L_Sub = cc.newLabel(); + Label L_Mul = cc.newLabel(); + Label L_Div = cc.newLabel(); + + funcNode->setArg(0, a); + funcNode->setArg(1, b); + funcNode->setArg(2, op); + + cc.adr(target, L_Table); + cc.ldrsw(offset, arm::ptr(target, op, arm::sxtw(2))); + cc.add(target, target, offset); + + // JumpAnnotation allows to annotate all possible jump targets of + // instructions where it cannot be deduced from operands. + if (_annotated) { + JumpAnnotation* annotation = cc.newJumpAnnotation(); + annotation->addLabel(L_Add); + annotation->addLabel(L_Sub); + annotation->addLabel(L_Mul); + annotation->addLabel(L_Div); + cc.br(target, annotation); + } + else { + cc.br(target); + } + + cc.bind(L_Add); + cc.fadd(a, a, b); + cc.b(L_End); + + cc.bind(L_Sub); + cc.fsub(a, a, b); + cc.b(L_End); + + cc.bind(L_Mul); + cc.fmul(a, a, b); + cc.b(L_End); + + cc.bind(L_Div); + cc.fdiv(a, a, b); + + cc.bind(L_End); + cc.ret(a); + cc.endFunc(); + + cc.bind(L_Table); + cc.embedLabelDelta(L_Add, L_Table, 4); + cc.embedLabelDelta(L_Sub, L_Table, 4); + cc.embedLabelDelta(L_Mul, L_Table, 4); + cc.embedLabelDelta(L_Div, L_Table, 4); + } + + virtual bool run(void* _func, String& result, String& expect) { + typedef float (*Func)(float, float, uint32_t); + Func func = ptr_as_func<Func>(_func); + + float dst[4]; + float ref[4]; + + dst[0] = func(33.0f, 14.0f, kOperatorAdd); + dst[1] = func(33.0f, 14.0f, kOperatorSub); + dst[2] = func(10.0f, 6.0f, kOperatorMul); + dst[3] = func(80.0f, 8.0f, kOperatorDiv); + + ref[0] = 47.0f; + ref[1] = 19.0f; + ref[2] = 60.0f; + ref[3] = 10.0f; + + result.assignFormat("ret={%f, %f, %f, %f}", dst[0], dst[1], dst[2], dst[3]); + expect.assignFormat("ret={%f, %f, %f, %f}", ref[0], ref[1], ref[2], ref[3]); + + return result == expect; + } +}; + +// a64::Compiler - Export +// ====================== + +void compiler_add_a64_tests(TestApp& app) { + app.addT<A64Test_GpArgs>(); + app.addT<A64Test_ManyRegs>(); + app.addT<A64Test_Simd1>(); + app.addT<A64Test_Adr>(); + app.addT<A64Test_Branch1>(); + app.addT<A64Test_Invoke1>(); + app.addT<A64Test_Invoke2>(); + app.addT<A64Test_Invoke3>(); + app.addT<A64Test_JumpTable>(); +} + +#endif // !ASMJIT_NO_AARCH64 && ASMJIT_ARCH_ARM == 64 diff --git a/test/asmjit_test_perf.cpp b/test/asmjit_test_perf.cpp index 2ade96c..ab96594 100644 --- a/test/asmjit_test_perf.cpp +++ b/test/asmjit_test_perf.cpp @@ -16,6 +16,10 @@ using namespace asmjit; void benchmarkX86Emitters(uint32_t numIterations, bool testX86, bool testX64) noexcept; #endif +#if !defined(ASMJIT_NO_AARCH64) +void benchmarkA64Emitters(uint32_t numIterations); +#endif + int main(int argc, char* argv[]) { CmdLine cmdLine(argc, argv); uint32_t numIterations = 20000; @@ -47,5 +51,12 @@ int main(int argc, char* argv[]) { benchmarkX86Emitters(numIterations, testX86, testX64); #endif +#if !defined(ASMJIT_NO_AARCH64) + bool testAArch64 = strcmp(arch, "all") == 0 || strcmp(arch, "aarch64") == 0; + + if (testAArch64) + benchmarkA64Emitters(numIterations); +#endif + return 0; } diff --git a/test/asmjit_test_perf_a64.cpp b/test/asmjit_test_perf_a64.cpp new file mode 100644 index 0000000..4f4aebb --- /dev/null +++ b/test/asmjit_test_perf_a64.cpp @@ -0,0 +1,699 @@ +// This file is part of AsmJit project <https://asmjit.com> +// +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib + +#include <asmjit/core.h> + +#if !defined(ASMJIT_NO_AARCH64) +#include <asmjit/a64.h> + +#include <limits> +#include <stdio.h> +#include <string.h> + +#include "asmjit_test_perf.h" + +using namespace asmjit; + +// Generates a long sequence of GP instructions. +template<typename Emitter> +static void generateGpSequenceInternal( + Emitter& cc, + const a64::Gp& a, const a64::Gp& b, const a64::Gp& c, const a64::Gp& d) { + + using namespace asmjit::a64; + + Gp wA = a.w(); + Gp wB = b.w(); + Gp wC = c.w(); + Gp wD = d.w(); + + Gp xA = a.x(); + Gp xB = b.x(); + Gp xC = c.x(); + Gp xD = d.x(); + + Mem m = ptr(xD); + + cc.mov(wA, 0); + cc.mov(wB, 1); + cc.mov(wC, 2); + cc.mov(wD, 3); + + cc.adc(wA, wB, wC); + cc.adc(xA, xB, xC); + cc.adc(wA, wzr, wC); + cc.adc(xA, xzr, xC); + cc.adc(wzr, wB, wC); + cc.adc(xzr, xB, xC); + cc.adcs(wA, wB, wC); + cc.adcs(xA, xB, xC); + cc.add(wA, wB, wC); + cc.add(xA, xB, xC); + cc.add(wA, wB, wC, lsl(3)); + cc.add(xA, xB, xC, lsl(3)); + cc.add(wA, wzr, wC); + cc.add(xA, xzr, xC); + cc.add(wzr, wB, wC); + cc.add(xzr, xB, xC); + cc.add(wC, wD, 0, lsl(12)); + cc.add(xC, xD, 0, lsl(12)); + cc.add(wC, wD, 1024, lsl(12)); + cc.add(xC, xD, 1024, lsl(12)); + cc.add(wC, wD, 1024, lsl(12)); + cc.add(xC, xD, 1024, lsl(12)); + cc.adds(wA, wB, wC); + cc.adds(xA, xB, xC); + cc.adr(xA, 0); + cc.adr(xA, 256); + cc.adrp(xA, 4096); + cc.and_(wA, wB, wC); + cc.and_(xA, xB, xC); + cc.and_(wA, wB, 1); + cc.and_(xA, xB, 1); + cc.and_(wA, wB, 15); + cc.and_(xA, xB, 15); + cc.and_(wA, wzr, wC); + cc.and_(xA, xzr, xC); + cc.and_(wzr, wB, wC); + cc.and_(xzr, xB, xC); + cc.and_(wA, wB, 0x1); + cc.and_(xA, xB, 0x1); + cc.and_(wA, wB, 0xf); + cc.and_(xA, xB, 0xf); + cc.ands(wA, wB, wC); + cc.ands(xA, xB, xC); + cc.ands(wA, wzr, wC); + cc.ands(xA, xzr, xC); + cc.ands(wzr, wB, wC); + cc.ands(xzr, xB, xC); + cc.ands(wA, wB, 0x1); + cc.ands(xA, xB, 0x1); + cc.ands(wA, wB, 0xf); + cc.ands(xA, xB, 0xf); + cc.asr(wA, wB, 15); + cc.asr(xA, xB, 15); + cc.asrv(wA, wB, wC); + cc.asrv(xA, xB, xC); + cc.bfc(wA, 8, 16); + cc.bfc(xA, 8, 16); + cc.bfi(wA, wB, 8, 16); + cc.bfi(xA, xB, 8, 16); + cc.bfm(wA, wB, 8, 16); + cc.bfm(xA, xB, 8, 16); + cc.bfxil(wA, wB, 8, 16); + cc.bfxil(xA, xB, 8, 16); + cc.bic(wA, wB, wC, lsl(4)); + cc.bic(xA, xB, xC, lsl(4)); + cc.bic(wA, wzr, wC); + cc.bic(xA, xzr, xC); + cc.bics(wA, wB, wC, lsl(4)); + cc.bics(xA, xB, xC, lsl(4)); + cc.bics(wA, wzr, wC); + cc.bics(xA, xzr, xC); + cc.cas(wA, wB, m); + cc.cas(xA, xB, m); + cc.casa(wA, wB, m); + cc.casa(xA, xB, m); + cc.casab(wA, wB, m); + cc.casah(wA, wB, m); + cc.casal(wA, wB, m); + cc.casal(xA, xB, m); + cc.casalb(wA, wB, m); + cc.casalh(wA, wB, m); + cc.casb(wA, wB, m); + cc.cash(wA, wB, m); + cc.casl(wA, wB, m); + cc.casl(xA, xB, m); + cc.caslb(wA, wB, m); + cc.caslh(wA, wB, m); + cc.casp(wA, wB, wC, wD, m); + cc.casp(xA, xB, xC, xD, m); + cc.caspa(wA, wB, wC, wD, m); + cc.caspa(xA, xB, xC, xD, m); + cc.caspal(wA, wB, wC, wD, m); + cc.caspal(xA, xB, xC, xD, m); + cc.caspl(wA, wB, wC, wD, m); + cc.caspl(xA, xB, xC, xD, m); + cc.ccmn(wA, wB, 3, CondCode::kEQ); + cc.ccmn(xA, xB, 3, CondCode::kEQ); + cc.ccmn(wA, 2, 3, CondCode::kEQ); + cc.ccmn(xA, 2, 3, CondCode::kEQ); + cc.ccmn(wA, wzr, 3, CondCode::kEQ); + cc.ccmn(xA, xzr, 3, CondCode::kEQ); + cc.ccmp(wA, wB, 3, CondCode::kEQ); + cc.ccmp(xA, xB, 3, CondCode::kEQ); + cc.ccmp(wA, 2, 3, CondCode::kEQ); + cc.ccmp(xA, 2, 3, CondCode::kEQ); + cc.ccmp(wA, wzr, 3, CondCode::kEQ); + cc.ccmp(xA, xzr, 3, CondCode::kEQ); + cc.cinc(wA, wB, CondCode::kEQ); + cc.cinc(xA, xB, CondCode::kEQ); + cc.cinc(wzr, wB, CondCode::kEQ); + cc.cinc(wA, wzr, CondCode::kEQ); + cc.cinc(xzr, xB, CondCode::kEQ); + cc.cinc(xA, xzr, CondCode::kEQ); + cc.cinv(wA, wB, CondCode::kEQ); + cc.cinv(xA, xB, CondCode::kEQ); + cc.cinv(wzr, wB, CondCode::kEQ); + cc.cinv(wA, wzr, CondCode::kEQ); + cc.cinv(xzr, xB, CondCode::kEQ); + cc.cinv(xA, xzr, CondCode::kEQ); + cc.cls(wA, wB); + cc.cls(xA, xB); + cc.cls(wA, wzr); + cc.cls(xA, xzr); + cc.cls(wzr, wB); + cc.cls(xzr, xB); + cc.clz(wA, wB); + cc.clz(xA, xB); + cc.clz(wA, wzr); + cc.clz(xA, xzr); + cc.clz(wzr, wB); + cc.clz(xzr, xB); + cc.cmn(wA, 33); + cc.cmn(xA, 33); + cc.cmn(wA, wB); + cc.cmn(xA, xB); + cc.cmn(wA, wB, uxtb(2)); + cc.cmn(xA, xB, uxtb(2)); + cc.cmp(wA, 33); + cc.cmp(xA, 33); + cc.cmp(wA, wB); + cc.cmp(xA, xB); + cc.cmp(wA, wB, uxtb(2)); + cc.cmp(xA, xB, uxtb(2)); + cc.crc32b(wA, wB, wC); + cc.crc32b(wzr, wB, wC); + cc.crc32b(wA, wzr, wC); + cc.crc32b(wA, wB, wzr); + cc.crc32cb(wA, wB, wC); + cc.crc32cb(wzr, wB, wC); + cc.crc32cb(wA, wzr, wC); + cc.crc32cb(wA, wB, wzr); + cc.crc32ch(wA, wB, wC); + cc.crc32ch(wzr, wB, wC); + cc.crc32ch(wA, wzr, wC); + cc.crc32ch(wA, wB, wzr); + cc.crc32cw(wA, wB, wC); + cc.crc32cw(wzr, wB, wC); + cc.crc32cw(wA, wzr, wC); + cc.crc32cw(wA, wB, wzr); + cc.crc32cx(wA, wB, xC); + cc.crc32cx(wzr, wB, xC); + cc.crc32cx(wA, wzr, xC); + cc.crc32cx(wA, wB, xzr); + cc.crc32h(wA, wB, wC); + cc.crc32h(wzr, wB, wC); + cc.crc32h(wA, wzr, wC); + cc.crc32h(wA, wB, wzr); + cc.crc32w(wA, wB, wC); + cc.crc32w(wzr, wB, wC); + cc.crc32w(wA, wzr, wC); + cc.crc32w(wA, wB, wzr); + cc.crc32x(wA, wB, xC); + cc.crc32x(wzr, wB, xC); + cc.crc32x(wA, wzr, xC); + cc.crc32x(wA, wB, xzr); + cc.csel(wA, wB, wC, CondCode::kEQ); + cc.csel(xA, xB, xC, CondCode::kEQ); + cc.cset(wA, CondCode::kEQ); + cc.cset(xA, CondCode::kEQ); + cc.cset(wA, CondCode::kEQ); + cc.cset(xA, CondCode::kEQ); + cc.csetm(wA, CondCode::kEQ); + cc.csetm(xA, CondCode::kEQ); + cc.csinc(wA, wB, wC, CondCode::kEQ); + cc.csinc(xA, xB, xC, CondCode::kEQ); + cc.csinv(wA, wB, wC, CondCode::kEQ); + cc.csinv(xA, xB, xC, CondCode::kEQ); + cc.csneg(wA, wB, wC, CondCode::kEQ); + cc.csneg(xA, xB, xC, CondCode::kEQ); + cc.eon(wA, wB, wC); + cc.eon(wzr, wB, wC); + cc.eon(wA, wzr, wC); + cc.eon(wA, wB, wzr); + cc.eon(wA, wB, wC, lsl(4)); + cc.eon(xA, xB, xC); + cc.eon(xzr, xB, xC); + cc.eon(xA, xzr, xC); + cc.eon(xA, xB, xzr); + cc.eon(xA, xB, xC, lsl(4)); + cc.eor(wA, wB, wC); + cc.eor(wzr, wB, wC); + cc.eor(wA, wzr, wC); + cc.eor(wA, wB, wzr); + cc.eor(xA, xB, xC); + cc.eor(xzr, xB, xC); + cc.eor(xA, xzr, xC); + cc.eor(xA, xB, xzr); + cc.eor(wA, wB, wC, lsl(4)); + cc.eor(xA, xB, xC, lsl(4)); + cc.eor(wA, wB, 0x4000); + cc.eor(xA, xB, 0x8000); + cc.extr(wA, wB, wC, 15); + cc.extr(wzr, wB, wC, 15); + cc.extr(wA, wzr, wC, 15); + cc.extr(wA, wB, wzr, 15); + cc.extr(xA, xB, xC, 15); + cc.extr(xzr, xB, xC, 15); + cc.extr(xA, xzr, xC, 15); + cc.extr(xA, xB, xzr, 15); + cc.ldadd(wA, wB, m); + cc.ldadd(xA, xB, m); + cc.ldadda(wA, wB, m); + cc.ldadda(xA, xB, m); + cc.ldaddab(wA, wB, m); + cc.ldaddah(wA, wB, m); + cc.ldaddal(wA, wB, m); + cc.ldaddal(xA, xB, m); + cc.ldaddalb(wA, wB, m); + cc.ldaddalh(wA, wB, m); + cc.ldaddb(wA, wB, m); + cc.ldaddh(wA, wB, m); + cc.ldaddl(wA, wB, m); + cc.ldaddl(xA, xB, m); + cc.ldaddlb(wA, wB, m); + cc.ldaddlh(wA, wB, m); + cc.ldclr(wA, wB, m); + cc.ldclr(xA, xB, m); + cc.ldclra(wA, wB, m); + cc.ldclra(xA, xB, m); + cc.ldclrab(wA, wB, m); + cc.ldclrah(wA, wB, m); + cc.ldclral(wA, wB, m); + cc.ldclral(xA, xB, m); + cc.ldclralb(wA, wB, m); + cc.ldclralh(wA, wB, m); + cc.ldclrb(wA, wB, m); + cc.ldclrh(wA, wB, m); + cc.ldclrl(wA, wB, m); + cc.ldclrl(xA, xB, m); + cc.ldclrlb(wA, wB, m); + cc.ldclrlh(wA, wB, m); + cc.ldeor(wA, wB, m); + cc.ldeor(xA, xB, m); + cc.ldeora(wA, wB, m); + cc.ldeora(xA, xB, m); + cc.ldeorab(wA, wB, m); + cc.ldeorah(wA, wB, m); + cc.ldeoral(wA, wB, m); + cc.ldeoral(xA, xB, m); + cc.ldeoralb(wA, wB, m); + cc.ldeoralh(wA, wB, m); + cc.ldeorb(wA, wB, m); + cc.ldeorh(wA, wB, m); + cc.ldeorl(wA, wB, m); + cc.ldeorl(xA, xB, m); + cc.ldeorlb(wA, wB, m); + cc.ldeorlh(wA, wB, m); + cc.ldlar(wA, m); + cc.ldlar(xA, m); + cc.ldlarb(wA, m); + cc.ldlarh(wA, m); + cc.ldnp(wA, wB, m); + cc.ldnp(xA, xB, m); + cc.ldp(wA, wB, m); + cc.ldp(xA, xB, m); + cc.ldpsw(xA, xB, m); + cc.ldr(wA, m); + cc.ldr(xA, m); + cc.ldrb(wA, m); + cc.ldrh(wA, m); + cc.ldrsw(xA, m); + cc.ldraa(xA, m); + cc.ldrab(xA, m); + cc.ldset(wA, wB, m); + cc.ldset(xA, xB, m); + cc.ldseta(wA, wB, m); + cc.ldseta(xA, xB, m); + cc.ldsetab(wA, wB, m); + cc.ldsetah(wA, wB, m); + cc.ldsetal(wA, wB, m); + cc.ldsetal(xA, xB, m); + cc.ldsetalh(wA, wB, m); + cc.ldsetalb(wA, wB, m); + cc.ldsetb(wA, wB, m); + cc.ldseth(wA, wB, m); + cc.ldsetl(wA, wB, m); + cc.ldsetl(xA, xB, m); + cc.ldsetlb(wA, wB, m); + cc.ldsetlh(wA, wB, m); + cc.ldsmax(wA, wB, m); + cc.ldsmax(xA, xB, m); + cc.ldsmaxa(wA, wB, m); + cc.ldsmaxa(xA, xB, m); + cc.ldsmaxab(wA, wB, m); + cc.ldsmaxah(wA, wB, m); + cc.ldsmaxal(wA, wB, m); + cc.ldsmaxal(xA, xB, m); + cc.ldsmaxalb(wA, wB, m); + cc.ldsmaxalh(wA, wB, m); + cc.ldsmaxb(wA, wB, m); + cc.ldsmaxh(wA, wB, m); + cc.ldsmaxl(wA, wB, m); + cc.ldsmaxl(xA, xB, m); + cc.ldsmaxlb(wA, wB, m); + cc.ldsmaxlh(wA, wB, m); + cc.ldsmin(wA, wB, m); + cc.ldsmin(xA, xB, m); + cc.ldsmina(wA, wB, m); + cc.ldsmina(xA, xB, m); + cc.ldsminab(wA, wB, m); + cc.ldsminah(wA, wB, m); + cc.ldsminal(wA, wB, m); + cc.ldsminal(xA, xB, m); + cc.ldsminalb(wA, wB, m); + cc.ldsminalh(wA, wB, m); + cc.ldsminb(wA, wB, m); + cc.ldsminh(wA, wB, m); + cc.ldsminl(wA, wB, m); + cc.ldsminl(xA, xB, m); + cc.ldsminlb(wA, wB, m); + cc.ldsminlh(wA, wB, m); + cc.ldtr(wA, m); + cc.ldtr(xA, m); + cc.ldtrb(wA, m); + cc.ldtrh(wA, m); + cc.ldtrsb(wA, m); + cc.ldtrsh(wA, m); + cc.ldtrsw(xA, m); + cc.ldumax(wA, wB, m); + cc.ldumax(xA, xB, m); + cc.ldumaxa(wA, wB, m); + cc.ldumaxa(xA, xB, m); + cc.ldumaxab(wA, wB, m); + cc.ldumaxah(wA, wB, m); + cc.ldumaxal(wA, wB, m); + cc.ldumaxal(xA, xB, m); + cc.ldumaxalb(wA, wB, m); + cc.ldumaxalh(wA, wB, m); + cc.ldumaxb(wA, wB, m); + cc.ldumaxh(wA, wB, m); + cc.ldumaxl(wA, wB, m); + cc.ldumaxl(xA, xB, m); + cc.ldumaxlb(wA, wB, m); + cc.ldumaxlh(wA, wB, m); + cc.ldumin(wA, wB, m); + cc.ldumin(xA, xB, m); + cc.ldumina(wA, wB, m); + cc.ldumina(xA, xB, m); + cc.lduminab(wA, wB, m); + cc.lduminah(wA, wB, m); + cc.lduminal(wA, wB, m); + cc.lduminal(xA, xB, m); + cc.lduminalb(wA, wB, m); + cc.lduminalh(wA, wB, m); + cc.lduminb(wA, wB, m); + cc.lduminh(wA, wB, m); + cc.lduminl(wA, wB, m); + cc.lduminl(xA, xB, m); + cc.lduminlb(wA, wB, m); + cc.lduminlh(wA, wB, m); + cc.ldur(wA, m); + cc.ldur(xA, m); + cc.ldurb(wA, m); + cc.ldurh(wA, m); + cc.ldursb(wA, m); + cc.ldursh(wA, m); + cc.ldursw(xA, m); + cc.ldxp(wA, wB, m); + cc.ldxp(xA, xB, m); + cc.ldxr(wA, m); + cc.ldxr(xA, m); + cc.ldxrb(wA, m); + cc.ldxrh(wA, m); + cc.lsl(wA, wB, wC); + cc.lsl(xA, xB, xC); + cc.lsl(wA, wB, 15); + cc.lsl(xA, xB, 15); + cc.lslv(wA, wB, wC); + cc.lslv(xA, xB, xC); + cc.lsr(wA, wB, wC); + cc.lsr(xA, xB, xC); + cc.lsr(wA, wB, 15); + cc.lsr(xA, xB, 15); + cc.lsrv(wA, wB, wC); + cc.lsrv(xA, xB, xC); + cc.madd(wA, wB, wC, wD); + cc.madd(xA, xB, xC, xD); + cc.mneg(wA, wB, wC); + cc.mneg(xA, xB, xC); + cc.mov(wA, wB); + cc.mov(xA, xB); + cc.mov(wA, 0); + cc.mov(wA, 1); + cc.mov(wA, 2); + cc.mov(wA, 3); + cc.mov(wA, 4); + cc.mov(wA, 5); + cc.mov(wA, 6); + cc.mov(wA, 7); + cc.mov(wA, 8); + cc.mov(wA, 9); + cc.mov(wA, 10); + cc.mov(wA, 0xA234); + cc.mov(xA, 0xA23400000000); + cc.msub(wA, wB, wC, wD); + cc.msub(xA, xB, xC, xD); + cc.mul(wA, wB, wC); + cc.mul(xA, xB, xC); + cc.mvn(wA, wB); + cc.mvn(xA, xB); + cc.mvn(wA, wB, lsl(4)); + cc.mvn(xA, xB, lsl(4)); + cc.neg(wA, wB); + cc.neg(xA, xB); + cc.neg(wA, wB, lsl(4)); + cc.neg(xA, xB, lsl(4)); + cc.negs(wA, wB); + cc.negs(xA, xB); + cc.negs(wA, wB, lsl(4)); + cc.negs(xA, xB, lsl(4)); + cc.ngc(wA, wB); + cc.ngc(xA, xB); + cc.ngcs(wA, wB); + cc.ngcs(xA, xB); + cc.orn(wA, wB, wC); + cc.orn(xA, xB, xC); + cc.orn(wA, wB, wC, lsl(4)); + cc.orn(xA, xB, xC, lsl(4)); + cc.orr(wA, wB, wC); + cc.orr(xA, xB, xC); + cc.orr(wA, wB, wC, lsl(4)); + cc.orr(xA, xB, xC, lsl(4)); + cc.orr(wA, wB, 0x4000); + cc.orr(xA, xB, 0x8000); + cc.rbit(wA, wB); + cc.rbit(xA, xB); + cc.rev(wA, wB); + cc.rev(xA, xB); + cc.rev16(wA, wB); + cc.rev16(xA, xB); + cc.rev32(xA, xB); + cc.rev64(xA, xB); + cc.ror(wA, wB, wC); + cc.ror(xA, xB, xC); + cc.ror(wA, wB, 15); + cc.ror(xA, xB, 15); + cc.rorv(wA, wB, wC); + cc.rorv(xA, xB, xC); + cc.sbc(wA, wB, wC); + cc.sbc(xA, xB, xC); + cc.sbcs(wA, wB, wC); + cc.sbcs(xA, xB, xC); + cc.sbfiz(wA, wB, 5, 10); + cc.sbfiz(xA, xB, 5, 10); + cc.sbfm(wA, wB, 5, 10); + cc.sbfm(xA, xB, 5, 10); + cc.sbfx(wA, wB, 5, 10); + cc.sbfx(xA, xB, 5, 10); + cc.sdiv(wA, wB, wC); + cc.sdiv(xA, xB, xC); + cc.smaddl(xA, wB, wC, xD); + cc.smnegl(xA, wB, wC); + cc.smsubl(xA, wB, wC, xD); + cc.smulh(xA, xB, xC); + cc.smull(xA, wB, wC); + cc.stp(wA, wB, m); + cc.stp(xA, xB, m); + cc.sttr(wA, m); + cc.sttr(xA, m); + cc.sttrb(wA, m); + cc.sttrh(wA, m); + cc.stur(wA, m); + cc.stur(xA, m); + cc.sturb(wA, m); + cc.sturh(wA, m); + cc.stxp(wA, wB, wC, m); + cc.stxp(wA, xB, xC, m); + cc.stxr(wA, wB, m); + cc.stxr(wA, xB, m); + cc.stxrb(wA, wB, m); + cc.stxrh(wA, wB, m); + cc.sub(wA, wB, wC); + cc.sub(xA, xB, xC); + cc.sub(wA, wB, wC, lsl(3)); + cc.sub(xA, xB, xC, lsl(3)); + cc.subg(xA, xB, 32, 11); + cc.subp(xA, xB, xC); + cc.subps(xA, xB, xC); + cc.subs(wA, wB, wC); + cc.subs(xA, xB, xC); + cc.subs(wA, wB, wC, lsl(3)); + cc.subs(xA, xB, xC, lsl(3)); + cc.sxtb(wA, wB); + cc.sxtb(xA, wB); + cc.sxth(wA, wB); + cc.sxth(xA, wB); + cc.sxtw(xA, wB); + cc.tst(wA, 1); + cc.tst(xA, 1); + cc.tst(wA, wB); + cc.tst(xA, xB); + cc.tst(wA, wB, lsl(4)); + cc.tst(xA, xB, lsl(4)); + cc.udiv(wA, wB, wC); + cc.udiv(xA, xB, xC); + cc.ubfiz(wA, wB, 5, 10); + cc.ubfiz(xA, xB, 5, 10); + cc.ubfm(wA, wB, 5, 10); + cc.ubfm(xA, xB, 5, 10); + cc.ubfx(wA, wB, 5, 10); + cc.ubfx(xA, xB, 5, 10); + cc.umaddl(xA, wB, wC, xD); + cc.umnegl(xA, wB, wC); + cc.umsubl(xA, wB, wC, xD); + cc.umulh(xA, xB, xC); + cc.umull(xA, wB, wC); + cc.uxtb(wA, wB); + cc.uxth(wA, wB); +} + +static void generateGpSequence(BaseEmitter& emitter, bool emitPrologEpilog) { + if (emitter.isAssembler()) { + a64::Assembler& cc = *emitter.as<a64::Assembler>(); + + a64::Gp a = a64::x0; + a64::Gp b = a64::x1; + a64::Gp c = a64::x2; + a64::Gp d = a64::x3; + + if (emitPrologEpilog) { + FuncDetail func; + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); + + FuncFrame frame; + frame.init(func); + frame.addDirtyRegs(a, b, c, d); + frame.finalize(); + + cc.emitProlog(frame); + generateGpSequenceInternal(cc, a, b, c, d); + cc.emitEpilog(frame); + } + else { + generateGpSequenceInternal(cc, a, b, c, d); + } + } +#ifndef ASMJIT_NO_BUILDER + else if (emitter.isBuilder()) { + a64::Builder& cc = *emitter.as<a64::Builder>(); + + a64::Gp a = a64::x0; + a64::Gp b = a64::x1; + a64::Gp c = a64::x2; + a64::Gp d = a64::x3; + + if (emitPrologEpilog) { + FuncDetail func; + func.init(FuncSignatureT<void, void*, const void*, size_t>(CallConvId::kHost), cc.environment()); + + FuncFrame frame; + frame.init(func); + frame.addDirtyRegs(a, b, c, d); + frame.finalize(); + + cc.emitProlog(frame); + generateGpSequenceInternal(cc, a, b, c, d); + cc.emitEpilog(frame); + } + else { + generateGpSequenceInternal(cc, a, b, c, d); + } + } +#endif +#ifndef ASMJIT_NO_COMPILER + else if (emitter.isCompiler()) { + a64::Compiler& cc = *emitter.as<a64::Compiler>(); + + a64::Gp a = cc.newIntPtr("a"); + a64::Gp b = cc.newIntPtr("b"); + a64::Gp c = cc.newIntPtr("c"); + a64::Gp d = cc.newIntPtr("d"); + + cc.addFunc(FuncSignatureT<void>(CallConvId::kHost)); + generateGpSequenceInternal(cc, a, b, c, d); + cc.endFunc(); + } +#endif +} + +template<typename EmitterFn> +static void benchmarkA64Function(Arch arch, uint32_t numIterations, const char* description, const EmitterFn& emitterFn) noexcept { + CodeHolder code; + printf("%s:\n", description); + + bench<a64::Assembler>(code, arch, numIterations, "[raw]", [&](a64::Assembler& cc) { + emitterFn(cc, false); + }); + + bench<a64::Assembler>(code, arch, numIterations, "[validated]", [&](a64::Assembler& cc) { + cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler); + emitterFn(cc, false); + }); + + bench<a64::Assembler>(code, arch, numIterations, "[prolog/epilog]", [&](a64::Assembler& cc) { + cc.addDiagnosticOptions(DiagnosticOptions::kValidateAssembler); + emitterFn(cc, true); + }); + +#ifndef ASMJIT_NO_BUILDER + bench<a64::Builder>(code, arch, numIterations, "[no-asm]", [&](a64::Builder& cc) { + emitterFn(cc, false); + }); + + bench<a64::Builder>(code, arch, numIterations, "[finalized]", [&](a64::Builder& cc) { + emitterFn(cc, false); + cc.finalize(); + }); + + bench<a64::Builder>(code, arch, numIterations, "[prolog/epilog]", [&](a64::Builder& cc) { + emitterFn(cc, true); + cc.finalize(); + }); +#endif + +#ifndef ASMJIT_NO_COMPILER + bench<a64::Compiler>(code, arch, numIterations, "[no-asm]", [&](a64::Compiler& cc) { + emitterFn(cc, true); + }); + + bench<a64::Compiler>(code, arch, numIterations, "[finalized]", [&](a64::Compiler& cc) { + emitterFn(cc, true); + cc.finalize(); + }); +#endif + + printf("\n"); +} + +void benchmarkA64Emitters(uint32_t numIterations) { + static const char description[] = "GpSequence (Sequence of GP instructions - reg/mem)"; + benchmarkA64Function(Arch::kAArch64, numIterations, description, [](BaseEmitter& emitter, bool emitPrologEpilog) { + generateGpSequence(emitter, emitPrologEpilog); + }); +} + +#endif // !ASMJIT_NO_AARCH64 diff --git a/test/asmjit_test_x86_sections.cpp b/test/asmjit_test_x86_sections.cpp index afd5807..353b5e4 100644 --- a/test/asmjit_test_x86_sections.cpp +++ b/test/asmjit_test_x86_sections.cpp @@ -136,12 +136,17 @@ int main() { // Relocate to the base-address of the allocated memory. code.relocateToBase(uint64_t(uintptr_t(rxPtr))); + VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadWrite); + // Copy the flattened code into `mem.rw`. There are two ways. You can either copy // everything manually by iterating over all sections or use `copyFlattenedData`. // This code is similar to what `copyFlattenedData(p, codeSize, 0)` would do: for (Section* section : code.sectionsByOrder()) memcpy(static_cast<uint8_t*>(rwPtr) + size_t(section->offset()), section->data(), section->bufferSize()); + VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadExecute); + VirtMem::flushInstructionCache(rwPtr, code.codeSize()); + // Execute the function and test whether it works. typedef size_t (*Func)(size_t idx); Func fn = (Func)rxPtr; diff --git a/tools/tablegen-arm.js b/tools/tablegen-arm.js new file mode 100644 index 0000000..e1c8293 --- /dev/null +++ b/tools/tablegen-arm.js @@ -0,0 +1,365 @@ +// [AsmJit] +// Machine Code Generation for C++. +// +// [License] +// ZLIB - See LICENSE.md file in the package. + +// ============================================================================ +// tablegen-arm.js +// ============================================================================ + +"use strict"; + +const { executionAsyncResource } = require("async_hooks"); +const core = require("./tablegen.js"); +const hasOwn = Object.prototype.hasOwnProperty; + +const asmdb = core.asmdb; +const kIndent = core.kIndent; +const IndexedArray = core.IndexedArray; +const StringUtils = core.StringUtils; + +const FAIL = core.FAIL; + +// ============================================================================ +// [ArmDB] +// ============================================================================ + +// Create ARM ISA. +const isa = new asmdb.arm.ISA(); + +// ============================================================================ +// [tablegen.arm.GenUtils] +// ============================================================================ + +class GenUtils { + // Get a list of instructions based on `name` and optional `mode`. + static query(name, mode) { + const insts = isa.query(name); + return !mode ? insts : insts.filter(function(inst) { return inst.arch === mode; }); + } + + static archOf(records) { + var t16Arch = false; + var t32Arch = false; + var a32Arch = false; + var a64Arch = false; + + for (var i = 0; i < records.length; i++) { + const record = records[i]; + if (record.encoding === "T16") t16Arch = true; + if (record.encoding === "T32") t32Arch = true; + if (record.encoding === "A32") a32Arch = true; + if (record.encoding === "A64") a64Arch = true; + } + + var s = (t16Arch && !t32Arch) ? "T16" : + (t32Arch && !t16Arch) ? "T32" : + (t16Arch && t32Arch) ? "Txx" : "---"; + s += " "; + s += (a32Arch) ? "A32" : "---"; + s += " "; + s += (a64Arch) ? "A64" : "---"; + + return `[${s}]`; + } + + static featuresOf(records) { + const exts = Object.create(null); + for (var i = 0; i < records.length; i++) { + const record = records[i]; + for (var k in record.extensions) + exts[k] = true; + } + const arr = Object.keys(exts); + arr.sort(); + return arr; + } +} + +// ============================================================================ +// [tablegen.arm.ArmTableGen] +// ============================================================================ + +class ArmTableGen extends core.TableGen { + constructor() { + super("A64"); + } + + // -------------------------------------------------------------------------- + // [Parse / Merge] + // -------------------------------------------------------------------------- + + parse() { + const rawData = this.dataOfFile("src/asmjit/arm/a64instdb.cpp"); + const stringData = StringUtils.extract(rawData, "// ${InstInfo:Begin}", "// ${InstInfo:End"); + + const re = new RegExp( + "INST\\(\\s*" + + // [01] Instruction. + "(" + + "[A-Za-z0-9_]+" + + ")\\s*,\\s*" + + + // [02] Encoding. + "(" + + "[^,]+" + + ")\\s*,\\s*" + + + // [03] OpcodeData. + "(" + + "\\([^\\)]+\\)" + + ")\\s*,\\s*" + + + // [04] RWInfo. + "(" + + "[^,]+" + + ")\\s*,\\s*" + + + // [05] InstructionFlags. + "(\\s*" + + "(?:" + + "(?:" + + "[\\d]+" + + "|" + + "F\\([^\\)]*\\)" + + ")" + + "\\s*" + + "[|]?\\s*" + + ")+" + + ")\\s*,\\s*" + + + // --- autogenerated fields --- + + // [06] OpcodeDataIndex. + "([^\\)]+)" + + "\\s*,\\s*" + + + // [07] NameDataIndex. + "([^\\)]+)" + + "\\s*\\)" + , "g"); + + var m; + while ((m = re.exec(stringData)) !== null) { + var enum_ = m[1]; + var name = enum_ === "None" ? "" : enum_.toLowerCase(); + var encoding = m[2].trim(); + var opcodeData = m[3].trim(); + var rwInfo = m[4].trim(); + var instFlags = m[5].trim(); + + var displayName = name; + if (name.endsWith("_v")) + displayName = name.substring(0, name.length - 2); + + // We have just matched #define INST() + if (name == "id" && + encoding === "encoding" && + encodingDataIndex === "encodingDataIndex") + continue; + + this.addInst({ + id : 0, // Instruction id (numeric value). + name : name, // Instruction name. + displayName : displayName, // Instruction name to display. + enum : enum_, // Instruction enum without `kId` prefix. + encoding : encoding, // Opcode encoding. + opcodeData : opcodeData, // Opcode data. + opcodeDataIndex : -1, // Opcode data index. + rwInfo : rwInfo, // RW info. + flags : instFlags, // Instruction flags. + + nameIndex : -1 // Index to InstDB::_nameData. + }); + } + + if (this.insts.length === 0 || this.insts.length !== StringUtils.countOf(stringData, "INST(")) + FAIL("ARMTableGen.parse(): Invalid parsing regexp (no data parsed)"); + + console.log("Number of Instructions: " + this.insts.length); + } + + merge() { + var s = StringUtils.format(this.insts, "", true, function(inst) { + return "INST(" + + String(inst.enum ).padEnd(17) + ", " + + String(inst.encoding ).padEnd(19) + ", " + + String(inst.opcodeData ).padEnd(86) + ", " + + String(inst.rwInfo ).padEnd(10) + ", " + + String(inst.flags ).padEnd(26) + ", " + + String(inst.opcodeDataIndex ).padEnd( 3) + ", " + + String(inst.nameIndex ).padEnd( 4) + ")"; + }) + "\n"; + return this.inject("InstInfo", s, this.insts.length * 4); + } + + // -------------------------------------------------------------------------- + // [Hooks] + // -------------------------------------------------------------------------- + + onBeforeRun() { + this.load([ + "src/asmjit/arm/a64emitter.h", + "src/asmjit/arm/a64globals.h", + "src/asmjit/arm/a64instdb.cpp", + "src/asmjit/arm/a64instdb.h", + "src/asmjit/arm/a64instdb_p.h" + ]); + this.parse(); + } + + onAfterRun() { + this.merge(); + this.save(); + this.dumpTableSizes(); + } +} + +// ============================================================================ +// [tablegen.arm.IdEnum] +// ============================================================================ + +class IdEnum extends core.IdEnum { + constructor() { + super("IdEnum"); + } + + comment(inst) { + let name = inst.name; + let ext = []; + + if (name.endsWith("_v")) { + name = name.substr(0, name.length - 2); + ext.push("ASIMD"); + } + + let exts = ""; + if (ext.length) + exts = " {" + ext.join("&") + "}"; + + return `Instruction '${name}'${exts}.`; + } +} + +// ============================================================================ +// [tablegen.arm.NameTable] +// ============================================================================ + +class NameTable extends core.NameTable { + constructor() { + super("NameTable"); + } +} + +// ============================================================================ +// [tablegen.arm.EncodingTable] +// ============================================================================ + +class EncodingTable extends core.Task { + constructor() { + super("EncodingTable"); + } + + run() { + const insts = this.ctx.insts; + const map = {}; + + for (var i = 0; i < insts.length; i++) { + const inst = insts[i]; + + const encoding = inst.encoding; + const opcodeData = inst.opcodeData.replace(/\(/g, "{ ").replace(/\)/g, " }"); + + if (!hasOwn.call(map, encoding)) + map[encoding] = []; + + if (inst.opcodeData === "(_)") { + inst.opcodeDataIndex = 0; + continue; + } + + const opcodeTable = map[encoding]; + const opcodeDataIndex = opcodeTable.length; + + opcodeTable.push({ name: inst.name, data: opcodeData }); + inst.opcodeDataIndex = opcodeDataIndex; + } + + const keys = Object.keys(map); + keys.sort(); + + var tableSource = ""; + var tableHeader = ""; + var encodingIds = ""; + + encodingIds += "enum EncodingId : uint32_t {\n" + encodingIds += " kEncodingNone = 0"; + + keys.forEach((dataClass) => { + const dataName = dataClass[0].toLowerCase() + dataClass.substr(1); + const opcodeTable = map[dataClass]; + const count = opcodeTable.length; + + if (dataClass !== "None") { + encodingIds += ",\n" + encodingIds += " kEncoding" + dataClass; + } + + if (count) { + tableHeader += `extern const ${dataClass} ${dataName}[${count}];\n`; + + if (tableSource) + tableSource += "\n"; + + tableSource += `const ${dataClass} ${dataName}[${count}] = {\n`; + for (var i = 0; i < count; i++) { + tableSource += ` ${opcodeTable[i].data}` + (i == count - 1 ? " " : ",") + " // " + opcodeTable[i].name + "\n"; + } + tableSource += `};\n`; + } + }); + + encodingIds += "\n};\n"; + + return this.ctx.inject("EncodingId" , StringUtils.disclaimer(encodingIds), 0) + + this.ctx.inject("EncodingDataForward", StringUtils.disclaimer(tableHeader), 0) + + this.ctx.inject("EncodingData" , StringUtils.disclaimer(tableSource), 0); + } +} +// ============================================================================ +// [tablegen.arm.CommonTable] +// ============================================================================ + +class CommonTable extends core.Task { + constructor() { + super("CommonTable", [ + "IdEnum", + "NameTable" + ]); + } + + run() { + //const table = new IndexedArray(); + + //for (var i = 0; i < insts.length; i++) { + // const inst = insts[i]; + // const item = "{ " + "0" + "}"; + // inst.commonIndex = table.addIndexed(item); + //} + + // return this.ctx.inject("InstInfo", StringUtils.disclaimer(s), 0); + return 0; + } +} + +// ============================================================================ +// [Main] +// ============================================================================ + +new ArmTableGen() + .addTask(new IdEnum()) + .addTask(new NameTable()) + .addTask(new EncodingTable()) + .addTask(new CommonTable()) + .run(); diff --git a/tools/tablegen-arm.sh b/tools/tablegen-arm.sh new file mode 100755 index 0000000..8545c1e --- /dev/null +++ b/tools/tablegen-arm.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +node ./tablegen-arm.js diff --git a/tools/tablegen-x86.js b/tools/tablegen-x86.js index 6b2110b..61fc734 100644 --- a/tools/tablegen-x86.js +++ b/tools/tablegen-x86.js @@ -524,6 +524,7 @@ class X86TableGen extends core.TableGen { this.addInst({ id : 0, // Instruction id (numeric value). name : name, // Instruction name. + displayName : name, // Instruction name to display. enum : enum_, // Instruction enum without `kId` prefix. dbInsts : dbInsts, // All dbInsts returned from asmdb query. encoding : encoding, // Instruction encoding. diff --git a/tools/tablegen-x86.sh b/tools/tablegen-x86.sh new file mode 100755 index 0000000..40facf3 --- /dev/null +++ b/tools/tablegen-x86.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env sh +set -e +node ./tablegen-x86.js $@ diff --git a/tools/tablegen.js b/tools/tablegen.js index 75d81b1..fdc65fd 100644 --- a/tools/tablegen.js +++ b/tools/tablegen.js @@ -160,6 +160,21 @@ exports.Lang = Lang; class StringUtils { static asString(x) { return String(x); } + static countOf(s, pattern) { + if (!pattern) + FAIL(`Pattern cannot be empty`); + + var n = 0; + var pos = 0; + + while ((pos = s.indexOf(pattern, pos)) >= 0) { + n++; + pos += pattern.length; + } + + return n; + } + static capitalize(s) { s = String(s); return !s ? s : s[0].toUpperCase() + s.substr(1); @@ -258,15 +273,28 @@ class StringUtils { return lines.join("\n"); } + static extract(s, start, end) { + var iStart = s.indexOf(start); + var iEnd = s.indexOf(end); + + if (iStart === -1) + FAIL(`StringUtils.extract(): Couldn't locate start mark '${start}'`); + + if (iEnd === -1) + FAIL(`StringUtils.extract(): Couldn't locate end mark '${end}'`); + + return s.substring(iStart + start.length, iEnd).trim(); + } + static inject(s, start, end, code) { var iStart = s.indexOf(start); var iEnd = s.indexOf(end); if (iStart === -1) - FAIL(`Utils.inject(): Couldn't locate start mark '${start}'`); + FAIL(`StringUtils.inject(): Couldn't locate start mark '${start}'`); if (iEnd === -1) - FAIL(`Utils.inject(): Couldn't locate end mark '${end}'`); + FAIL(`StringUtils.inject(): Couldn't locate end mark '${end}'`); var nIndent = 0; while (iStart > 0 && s[iStart-1] === " ") { @@ -875,14 +903,14 @@ class NameTable extends Task { var maxLength = 0; for (var i = 0; i < insts.length; i++) { const inst = insts[i]; - instNames.add(inst.name); - maxLength = Math.max(maxLength, inst.name.length); + instNames.add(inst.displayName); + maxLength = Math.max(maxLength, inst.displayName.length); } instNames.index(); for (var i = 0; i < insts.length; i++) { const inst = insts[i]; - const name = inst.name; + const name = inst.displayName; const nameIndex = instNames.getIndex(name); const index = name.charCodeAt(0) - 'a'.charCodeAt(0); diff --git a/tools/tablegen.sh b/tools/tablegen.sh index 40facf3..b2c9cac 100755 --- a/tools/tablegen.sh +++ b/tools/tablegen.sh @@ -1,3 +1,4 @@ #!/usr/bin/env sh set -e +node ./tablegen-arm.js $@ node ./tablegen-x86.js $@ |