From a55fe366c721e9e5abe6e308fd85439a5abee5e2 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 29 Aug 2024 20:37:41 +0100 Subject: [PATCH 01/34] Temp change of UoB-HPC captone branch to next-update. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 542049f2f8..d2fd31cc01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,7 @@ FetchContent_Declare( FetchContent_Declare( capstone-lib GIT_REPOSITORY https://github.com/UoB-HPC/capstone.git - GIT_TAG next + GIT_TAG next-update GIT_PROGRESS TRUE # Old Git tag pre-Armv9.2 From d57b227c5c0bb93b0252fa547f172ace551f075e Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Fri, 30 Aug 2024 11:16:26 +0100 Subject: [PATCH 02/34] Began migrating to new Capstone structure. --- src/include/simeng/arch/aarch64/ArchInfo.hh | 16 +- .../simeng/arch/aarch64/Instruction.hh | 145 +++++---- .../simeng/arch/aarch64/MicroDecoder.hh | 34 +- .../aarch64/helpers/auxiliaryFunctions.hh | 2 +- src/lib/arch/aarch64/InstructionMetadata.cc | 294 +++++++++--------- src/lib/arch/aarch64/InstructionMetadata.hh | 4 +- src/lib/arch/aarch64/Instruction_decode.cc | 164 +++++----- src/lib/arch/aarch64/Instruction_execute.cc | 72 +++-- src/lib/arch/aarch64/MicroDecoder.cc | 268 +++++++++------- 9 files changed, 529 insertions(+), 470 deletions(-) diff --git a/src/include/simeng/arch/aarch64/ArchInfo.hh b/src/include/simeng/arch/aarch64/ArchInfo.hh index bbd764c757..971c958eda 100644 --- a/src/include/simeng/arch/aarch64/ArchInfo.hh +++ b/src/include/simeng/arch/aarch64/ArchInfo.hh @@ -11,14 +11,14 @@ namespace aarch64 { class ArchInfo : public simeng::arch::ArchInfo { public: ArchInfo(ryml::ConstNodeRef config) - : sysRegisterEnums_({arm64_sysreg::ARM64_SYSREG_DCZID_EL0, - arm64_sysreg::ARM64_SYSREG_FPCR, - arm64_sysreg::ARM64_SYSREG_FPSR, - arm64_sysreg::ARM64_SYSREG_TPIDR_EL0, - arm64_sysreg::ARM64_SYSREG_MIDR_EL1, - arm64_sysreg::ARM64_SYSREG_CNTVCT_EL0, - arm64_sysreg::ARM64_SYSREG_PMCCNTR_EL0, - arm64_sysreg::ARM64_SYSREG_SVCR}), + : sysRegisterEnums_({aarch64_sysreg::AARCH64_SYSREG_DCZID_EL0, + aarch64_sysreg::AARCH64_SYSREG_FPCR, + aarch64_sysreg::AARCH64_SYSREG_FPSR, + aarch64_sysreg::AARCH64_SYSREG_TPIDR_EL0, + aarch64_sysreg::AARCH64_SYSREG_MIDR_EL1, + aarch64_sysreg::AARCH64_SYSREG_CNTVCT_EL0, + aarch64_sysreg::AARCH64_SYSREG_PMCCNTR_EL0, + aarch64_sysreg::AARCH64_SYSREG_SVCR}), zaSize_(config["Core"]["Streaming-Vector-Length"].as() / 8) { // Generate the architecture-defined architectural register structure archRegStruct_ = { diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index 76e74d7eb7..a4f8fa3c43 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -8,7 +8,7 @@ #include "simeng/arch/aarch64/operandContainer.hh" #include "simeng/branchpredictors/BranchPredictor.hh" -struct cs_arm64_op; +struct cs_aarch64_op; namespace simeng { namespace arch { @@ -83,39 +83,39 @@ struct MicroOpInfo { int microOpIndex = 0; }; +// TODO: Handle multi-register aarch64_reg operands /** Get the size of the data to be accessed from/to memory. */ -inline uint8_t getDataSize(cs_arm64_op op) { - // Check from top of the range downwards - - // ARM64_REG_V0 -> {end} are vector registers - if (op.reg >= ARM64_REG_V0) { - // Data size for vector registers relies on opcode, get vector access - // specifier - arm64_vas vas = op.vas; - assert(vas != ARM64_VAS_INVALID && "Invalid VAS type"); +inline uint8_t getDataSize(cs_aarch64_op op) { + // No V-register enum identifiers exist. Instead, depending on whether a full + // or half vector is accessed, a Q or D register is used instead. + // A `is_vreg` bool in `op` defines if we are using v-vecotr registers. + if (op.is_vreg && ((AARCH64_REG_D0 <= op.reg && op.reg <= AARCH64_REG_D31) || + (AARCH64_REG_Q0 <= op.reg && op.reg <= AARCH64_REG_Q31))) { + AArch64Layout_VectorLayout vas = op.vas; + assert(vas != AARCH64LAYOUT_INVALID && "Invalid VAS type"); switch (vas) { - case ARM64_VAS_16B: - case ARM64_VAS_8H: - case ARM64_VAS_4S: - case ARM64_VAS_2D: - case ARM64_VAS_1Q: { + case AARCH64LAYOUT_VL_16B: + case AARCH64LAYOUT_VL_8H: + case AARCH64LAYOUT_VL_4S: + case AARCH64LAYOUT_VL_2D: + case AARCH64LAYOUT_VL_1Q: { return 16; } - case ARM64_VAS_8B: - case ARM64_VAS_4H: - case ARM64_VAS_2S: - case ARM64_VAS_1D: { + case AARCH64LAYOUT_VL_8B: + case AARCH64LAYOUT_VL_4H: + case AARCH64LAYOUT_VL_2S: + case AARCH64LAYOUT_VL_1D: { return 8; } - case ARM64_VAS_4B: - case ARM64_VAS_2H: - case ARM64_VAS_1S: { + case AARCH64LAYOUT_VL_4B: + case AARCH64LAYOUT_VL_2H: + case AARCH64LAYOUT_VL_1S: { return 4; } - case ARM64_VAS_1H: { + case AARCH64LAYOUT_VL_H: { return 2; } - case ARM64_VAS_1B: { + case AARCH64LAYOUT_VL_B: { return 1; } default: { @@ -124,100 +124,121 @@ inline uint8_t getDataSize(cs_arm64_op op) { } } - // ARM64_REG_ZAB0 -> +31 are tiles of the matrix register (ZA) - if (op.reg >= ARM64_REG_ZAB0 || op.reg == ARM64_REG_ZA) { + // SME ZA Tiles, SVE Z registers, and SVE P predicates also have Vector + // Arrangement Specifier set + /** TODO: When SME, SVE instruction splitting is supported / implemented, + * update the data size returned based on VAS. */ + + // Work top down through register enums (highest value -> lowest value) + if (op.reg >= AARCH64_REG_D0_D1) { + // Multi-register currently not supported. Return 0. + return 0; + } + + // AARCH64_REG_ZAB0 -> +31 are tiles of the matrix register (ZA) + // AARCH64_REG_ZT0 is new 512-bit register from SME2 + if (op.reg >= AARCH64_REG_ZAB0 || op.reg == AARCH64_REG_ZA || + op.reg == AARCH64_REG_ZT0) { // Data size for tile registers relies on opcode thus return 0 return 0; } - // ARM64_REG_Z0 -> +31 are scalable vector registers (Z) - if (op.reg >= ARM64_REG_Z0) { + // AARCH64_REG_Z0 -> +31 are scalable vector registers (Z) + if (op.reg >= AARCH64_REG_Z0) { // Data size for vector registers relies on opcode thus return 0 return 0; } - // ARM64_REG_X0 -> +28 are 64-bit (X) registers - if (op.reg >= ARM64_REG_X0) { + // AARCH64_REG_X0 -> +28 are 64-bit (X) registers + if (op.reg >= AARCH64_REG_X0) { return 8; } - // ARM64_REG_W0 -> +30 are 32-bit (W) registers - if (op.reg >= ARM64_REG_W0) { + // AARCH64_REG_W0 -> +30 are 32-bit (W) registers + if (op.reg >= AARCH64_REG_W0) { return 4; } - // ARM64_REG_S0 -> +31 are 32-bit arranged (S) neon registers - if (op.reg >= ARM64_REG_S0) { + // AARCH64_REG_S0 -> +31 are 32-bit arranged (S) neon registers + if (op.reg >= AARCH64_REG_S0) { return 4; } - // ARM64_REG_Q0 -> +31 are 128-bit arranged (Q) neon registers - if (op.reg >= ARM64_REG_Q0) { + // AARCH64_REG_Q0 -> +31 are 128-bit arranged (Q) neon registers + if (op.reg >= AARCH64_REG_Q0) { return 16; } - // ARM64_REG_P0 -> +15 are 256-bit (P) registers - if (op.reg >= ARM64_REG_P0) { + // ARCH64_REG_PN0 -> +15 are scalable predicate registers + if (op.reg >= AARCH64_REG_PN0) { + /** TODO: Check functionality is correct when multi-vector operands + SME2 + * has been supported. */ + return 1; + } + + // AARCH64_REG_P0 -> +15 are 256-bit (P) registers + if (op.reg >= AARCH64_REG_P0) { return 1; } - // ARM64_REG_H0 -> +31 are 16-bit arranged (H) neon registers - if (op.reg >= ARM64_REG_H0) { + // AARCH64_REG_H0 -> +31 are 16-bit arranged (H) neon registers + if (op.reg >= AARCH64_REG_H0) { return 2; } - // ARM64_REG_D0 -> +31 are 64-bit arranged (D) neon registers - if (op.reg >= ARM64_REG_D0) { + // AARCH64_REG_D0 -> +31 are 64-bit arranged (D) neon registers + if (op.reg >= AARCH64_REG_D0) { return 8; } - // ARM64_REG_B0 -> +31 are 8-bit arranged (B) neon registers - if (op.reg >= ARM64_REG_B0) { + // AARCH64_REG_B0 -> +31 are 8-bit arranged (B) neon registers + if (op.reg >= AARCH64_REG_B0) { return 1; } - // ARM64_REG_XZR is the 64-bit zero register - if (op.reg == ARM64_REG_XZR) { + // AARCH64_REG_XZR is the 64-bit zero register + if (op.reg == AARCH64_REG_XZR) { return 8; } - // ARM64_REG_WZR is the 32-bit zero register - if (op.reg == ARM64_REG_WZR) { + // AARCH64_REG_WZR is the 32-bit zero register + if (op.reg == AARCH64_REG_WZR) { return 4; } - // ARM64_REG_WSP (w31) is the 32-bit stack pointer register - if (op.reg == ARM64_REG_WSP) { + // AARCH64_REG_WSP (w31) is the 32-bit stack pointer register + if (op.reg == AARCH64_REG_WSP) { return 4; } - // ARM64_REG_SP (x31) is the 64-bit stack pointer register - if (op.reg == ARM64_REG_SP) { + // AARCH64_REG_SP (x31) is the 64-bit stack pointer register + if (op.reg == AARCH64_REG_SP) { return 8; } - // ARM64_REG_NZCV is the NZCV flag register - if (op.reg == ARM64_REG_NZCV) { + // AARCH64_REG_NZCV is the NZCV flag register + if (op.reg == AARCH64_REG_NZCV) { return 1; } - // ARM64_REG_X30 is the 64-bit link register - if (op.reg == ARM64_REG_X30) { + // AARCH64_REG_X30 is the 64-bit link register + if (op.reg == AARCH64_REG_X30) { return 8; } - // ARM64_REG_X29 is the 64-bit frame pointer - if (op.reg == ARM64_REG_X29) { + // AARCH64_REG_X29 is the 64-bit frame pointer + if (op.reg == AARCH64_REG_X29) { return 8; } - // ARM64_REG_FFR (p15) is a special purpose predicate register - if (op.reg == ARM64_REG_FFR) { + // AARCH64_REG_FFR (p15) is a special purpose predicate register + if (op.reg == AARCH64_REG_FFR) { return 1; } - // ARM64_REG_INVALID is an invalid capstone register so return 0 bytes as size - if (op.reg == ARM64_REG_INVALID) { + // AARCH64_REG_INVALID is an invalid capstone register so return 0 bytes as + // size + if (op.reg == AARCH64_REG_INVALID) { return 0; } diff --git a/src/include/simeng/arch/aarch64/MicroDecoder.hh b/src/include/simeng/arch/aarch64/MicroDecoder.hh index d4524c8abc..f7e72097fd 100644 --- a/src/include/simeng/arch/aarch64/MicroDecoder.hh +++ b/src/include/simeng/arch/aarch64/MicroDecoder.hh @@ -9,9 +9,9 @@ namespace simeng { namespace arch { namespace aarch64 { -/** A struct to hold information to construct a default cs_arm64_op from. */ +/** A struct to hold information to construct a default cs_aarch64_op from. */ struct OpType { - arm64_op_type type; + aarch64_op_type type; bool isDestination = false; }; @@ -33,38 +33,38 @@ class MicroDecoder { private: /** Detect if there's an overlap between the underlying hardware registers * (e.g. z5, v5, q5, d5, s5, h5, and b5). */ - bool detectOverlap(arm64_reg registerA, arm64_reg registerB); + bool detectOverlap(aarch64_reg registerA, aarch64_reg registerB); /** Create a default cs_detail object from a vector of operand types. */ cs_detail createDefaultDetail(std::vector opTypes); /** Create an address offset uop from a base register and an immediate. */ Instruction createImmOffsetUop(const Architecture& architecture, - arm64_reg base, int64_t offset, + aarch64_reg base, int64_t offset, csh capstoneHandle, bool lastMicroOp = false, int microOpIndex = 0); /** Create an address offset uop from a base register and a register. */ Instruction createRegOffsetUop(const Architecture& architecture, - arm64_reg base, arm64_reg offset, + aarch64_reg base, aarch64_reg offset, csh capstoneHandle, bool lastMicroOp = false, int microOpIndex = 0); /** Create a load uop from a destination register and a capstone memory * operand. */ - Instruction createLdrUop(const Architecture& architecture, arm64_reg dest, - arm64_op_mem mem, csh capstoneHandle, + Instruction createLdrUop(const Architecture& architecture, aarch64_reg dest, + aarch64_op_mem mem, csh capstoneHandle, bool lastMicroOp = false, int microOpIndex = 0, uint8_t dataSize = 0); /** Create a store data uop from a source register. */ - Instruction createSDUop(const Architecture& architecture, arm64_reg src, + Instruction createSDUop(const Architecture& architecture, aarch64_reg src, csh capstoneHandle, bool lastMicroOp = false, int microOpIndex = 0); /** Create a store address uop from a capstone memory * operand. */ - Instruction createStrUop(const Architecture& architecture, arm64_op_mem mem, + Instruction createStrUop(const Architecture& architecture, aarch64_op_mem mem, csh capstoneHandle, bool lastMicroOp = false, int microOpIndex = 0, uint8_t dataSize = 0); @@ -87,14 +87,14 @@ class MicroDecoder { cs_arm64 default_info = {ARM64_CC_INVALID, false, false, 0, {}}; /** Default register. */ - cs_arm64_op default_op = {0, - ARM64_VAS_INVALID, - {ARM64_SFT_INVALID, 0}, - ARM64_EXT_INVALID, - ARM64_OP_INVALID, - ARM64_SVCR_INVALID, - {}, - CS_AC_READ}; + cs_aarch64_op default_op = {0, + ARM64_VAS_INVALID, + {ARM64_SFT_INVALID, 0}, + ARM64_EXT_INVALID, + AARCH64_OP_INVALID, + ARM64_SVCR_INVALID, + {}, + CS_AC_READ}; /** Default capstone instruction detail. */ cs_detail default_detail = {{}, 0, {}, 0, {}, 0, {}}; diff --git a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh index a16029bf5c..f4f8b94d0f 100644 --- a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh +++ b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh @@ -205,7 +205,7 @@ inline uint64_t extendValue(uint64_t value, uint8_t extendType, uint8_t shift) { } /** Extend `value` using extension/shifting rules defined in `op`. */ -inline uint64_t extendOffset(uint64_t value, const cs_arm64_op& op) { +inline uint64_t extendOffset(uint64_t value, const cs_aarch64_op& op) { if (op.ext == 0) { if (op.shift.value == 0) { return value; diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index e0106f97f8..350c4be592 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -29,7 +29,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) sizeof(uint16_t) * implicitDestinationCount); std::memcpy(groups, insn.detail->groups, sizeof(uint8_t) * groupCount); std::memcpy(operands, insn.detail->arm64.operands, - sizeof(cs_arm64_op) * operandCount); + sizeof(cs_aarch64_op) * operandCount); // Fix some inaccuracies in the decoded metadata switch (opcode) { @@ -53,7 +53,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ; - operands[2].type = ARM64_OP_REG; + operands[2].type = AARCH64_OP_REG; break; } case Opcode::AArch64_SMIN_ZPmZ_S: @@ -167,7 +167,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[3].access = CS_AC_READ; // Doesn't identify implicit NZCV destination implicitDestinationCount = 1; - implicitDestinations[0] = ARM64_REG_NZCV; + implicitDestinations[0] = AARCH64_REG_NZCV; break; case Opcode::AArch64_CNTB_XPiI: [[fallthrough]]; @@ -180,7 +180,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_WRITE; if (operandStr.length() < 4) { operandCount = 2; - operands[1].type = ARM64_OP_IMM; + operands[1].type = AARCH64_OP_IMM; operands[1].imm = 1; operands[1].access = CS_AC_READ; operands[1].shift = {ARM64_SFT_INVALID, 0}; @@ -199,7 +199,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operandCount = 3; // Extract immediate in SVE add with immediate instruction @@ -237,7 +237,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operandCount = 3; char specifier = operandStr[operandStr.find(".") + 1]; @@ -289,7 +289,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) std::string str(operandStr); if (str.length() < 4) { operandCount = 2; - operands[1].type = ARM64_OP_IMM; + operands[1].type = AARCH64_OP_IMM; operands[1].imm = 1; operands[1].access = CS_AC_READ; operands[1].shift = {ARM64_SFT_INVALID, 0}; @@ -492,7 +492,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ; - operands[3].type = ARM64_OP_FP; + operands[3].type = AARCH64_OP_FP; operands[3].access = CS_AC_READ; // Doesn't recognise immediate operands // Extract two possible values, 0.5 or 2.0 @@ -511,7 +511,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].access = CS_AC_READ; operands[3].access = CS_AC_READ; operands[4].access = CS_AC_READ; - operands[4].type = ARM64_OP_IMM; + operands[4].type = AARCH64_OP_IMM; break; } case Opcode::AArch64_FCADD_ZPmZ_D: { @@ -521,7 +521,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].access = CS_AC_READ; operands[3].access = CS_AC_READ; operands[4].access = CS_AC_READ; - operands[4].type = ARM64_OP_IMM; + operands[4].type = AARCH64_OP_IMM; break; } case Opcode::AArch64_FSUB_ZPmI_D: @@ -536,7 +536,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ; - operands[3].type = ARM64_OP_FP; + operands[3].type = AARCH64_OP_FP; operands[3].access = CS_AC_READ; // Doesn't recognise immediate operands // Extract two possible values, 0.5 or 1.0 @@ -669,7 +669,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_READ | CS_AC_WRITE; if (operandStr.length() < 4) { operandCount = 2; - operands[1].type = ARM64_OP_IMM; + operands[1].type = AARCH64_OP_IMM; operands[1].imm = 1; operands[1].access = CS_AC_READ; operands[1].shift = {ARM64_SFT_INVALID, 0}; @@ -687,7 +687,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_READ | CS_AC_WRITE; if (operandStr.length() < 6) { operandCount = 2; - operands[1].type = ARM64_OP_IMM; + operands[1].type = AARCH64_OP_IMM; operands[1].imm = 1; operands[1].access = CS_AC_READ; operands[1].shift = {ARM64_SFT_INVALID, 0}; @@ -725,24 +725,24 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) case Opcode::AArch64_GLD1D_REAL: { // LD1D gather instruction doesn't correctly identify destination // register - uint16_t reg_enum = ARM64_REG_Z0; + uint16_t reg_enum = AARCH64_REG_Z0; // Single or double digit Z register identifier if (operandStr[3] == '.') { reg_enum += std::stoi(operandStr.substr(2, 1)); } else { reg_enum += std::stoi(operandStr.substr(2, 2)); } - operands[0].reg = static_cast(reg_enum); + operands[0].reg = static_cast(reg_enum); // No defined access types operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; // LD1D gather instruction doesn't correctly identify memory operands - operands[2].type = ARM64_OP_MEM; + operands[2].type = AARCH64_OP_MEM; operands[2].access = CS_AC_READ; // LD1D doesn't correctly identify vector memory register correctly - uint16_t vec_enum = ARM64_REG_Z0; + uint16_t vec_enum = AARCH64_REG_Z0; std::string tmp_str(operandStr.substr(operandStr.find("["))); // Single or double digit Z register identifier if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { @@ -750,7 +750,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) } else { vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); } - operands[2].mem.index = static_cast(vec_enum); + operands[2].mem.index = static_cast(vec_enum); break; } case Opcode::AArch64_LD1RQ_W: @@ -764,20 +764,20 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) case Opcode::AArch64_LD1RQ_D_IMM: { // LD1RQ gather instruction doesn't correctly identify destination // register - uint16_t reg_enum = ARM64_REG_Z0; + uint16_t reg_enum = AARCH64_REG_Z0; // Single or double digit Z register identifier if (operandStr[3] == '.') { reg_enum += std::stoi(operandStr.substr(2, 1)); } else { reg_enum += std::stoi(operandStr.substr(2, 2)); } - operands[0].reg = static_cast(reg_enum); + operands[0].reg = static_cast(reg_enum); // No defined access types operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; // LD1RQ gather instruction doesn't correctly identify memory operands - operands[2].type = ARM64_OP_MEM; + operands[2].type = AARCH64_OP_MEM; operands[2].access = CS_AC_READ; break; } @@ -786,7 +786,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) case Opcode::AArch64_GLD1D_IMM_REAL: { // LD1D gather instruction doesn't correctly identify destination // register - uint16_t reg_enum = ARM64_REG_Z0; + uint16_t reg_enum = AARCH64_REG_Z0; // Single or double digit Z register identifier if (operandStr[3] == '.') { reg_enum += std::stoi(operandStr.substr(2, 1)); @@ -794,13 +794,13 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) reg_enum += std::stoi(operandStr.substr(2, 2)); } - operands[0].reg = static_cast(reg_enum); + operands[0].reg = static_cast(reg_enum); // No defined access types operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; // LD1D gather instruction doesn't correctly identify second Z reg as // memory operand - operands[2].type = ARM64_OP_MEM; + operands[2].type = AARCH64_OP_MEM; operands[2].access = CS_AC_READ; // LD1D gather instruction doesn't recognise memory-offset immediate // correctly @@ -837,7 +837,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) [[fallthrough]]; case Opcode::AArch64_LD1W_IMM_REAL: { // LD1RW doesn't correctly identify destination register - uint16_t reg_enum = ARM64_REG_Z0; + uint16_t reg_enum = AARCH64_REG_Z0; // Single or double digit Z register identifier if (operandStr[3] == '.') { reg_enum += std::stoi(operandStr.substr(2, 1)); @@ -845,7 +845,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) reg_enum += std::stoi(operandStr.substr(2, 2)); } - operands[0].reg = static_cast(reg_enum); + operands[0].reg = static_cast(reg_enum); // No defined access types operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; @@ -877,7 +877,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[1].access = CS_AC_READ | CS_AC_WRITE; // Fix for exclusion of post_index immediate in disassembly operandCount = 3; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operands[2].access = CS_AC_READ; // For vector arrangement of 16-bit, post_index immediate is 2 operands[2].imm = 2; @@ -889,7 +889,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[1].access = CS_AC_READ | CS_AC_WRITE; // Fix for exclusion of post_index immediate in disassembly operandCount = 3; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operands[2].access = CS_AC_READ; // For vector arrangement of 64-bit, post_index immediate is 8 operands[2].imm = 8; @@ -902,7 +902,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // Fix for exclusion of post_index immediate in disassembly operandCount = 3; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operands[2].access = CS_AC_READ; // For vector arrangement of 8-bit, post_index immediate is 1 operands[2].imm = 1; @@ -915,7 +915,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // Fix for exclusion of post_index immediate in disassembly operandCount = 3; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operands[2].access = CS_AC_READ; // For vector arrangement of 32-bit, post_index immediate is 4 operands[2].imm = 4; @@ -1003,8 +1003,8 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) case Opcode::AArch64_LD2D: case Opcode::AArch64_LD2D_IMM: { // LD2D doesn't correctly identify destination registers - uint16_t reg_enum0 = ARM64_REG_Z0; - uint16_t reg_enum1 = ARM64_REG_Z0; + uint16_t reg_enum0 = AARCH64_REG_Z0; + uint16_t reg_enum1 = AARCH64_REG_Z0; // tmpOpStr = "zxx.d, zyy.d" std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); @@ -1025,9 +1025,9 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); } - operands[0].reg = static_cast(reg_enum0); + operands[0].reg = static_cast(reg_enum0); operands[0].access = CS_AC_WRITE; - operands[1].reg = static_cast(reg_enum1); + operands[1].reg = static_cast(reg_enum1); operands[1].access = CS_AC_WRITE; operands[2].access = CS_AC_READ; @@ -1036,9 +1036,9 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) } case Opcode::AArch64_LD3D_IMM: { // LD3D doesn't correctly identify destination registers - uint16_t reg_enum0 = ARM64_REG_Z0; - uint16_t reg_enum1 = ARM64_REG_Z0; - uint16_t reg_enum2 = ARM64_REG_Z0; + uint16_t reg_enum0 = AARCH64_REG_Z0; + uint16_t reg_enum1 = AARCH64_REG_Z0; + uint16_t reg_enum2 = AARCH64_REG_Z0; // tmpOpStr = "zxx.d, zyy.d, znn.d" std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); @@ -1068,11 +1068,11 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); } - operands[0].reg = static_cast(reg_enum0); + operands[0].reg = static_cast(reg_enum0); operands[0].access = CS_AC_WRITE; - operands[1].reg = static_cast(reg_enum1); + operands[1].reg = static_cast(reg_enum1); operands[1].access = CS_AC_WRITE; - operands[2].reg = static_cast(reg_enum2); + operands[2].reg = static_cast(reg_enum2); operands[2].access = CS_AC_WRITE; operands[3].access = CS_AC_READ; @@ -1081,10 +1081,10 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) } case Opcode::AArch64_LD4D_IMM: { // LD4D doesn't correctly identify destination registers - uint16_t reg_enum0 = ARM64_REG_Z0; - uint16_t reg_enum1 = ARM64_REG_Z0; - uint16_t reg_enum2 = ARM64_REG_Z0; - uint16_t reg_enum3 = ARM64_REG_Z0; + uint16_t reg_enum0 = AARCH64_REG_Z0; + uint16_t reg_enum1 = AARCH64_REG_Z0; + uint16_t reg_enum2 = AARCH64_REG_Z0; + uint16_t reg_enum3 = AARCH64_REG_Z0; // tmpOpStr = "zxx.d, zyy.d, znn.d, zmm.d" std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); @@ -1123,13 +1123,13 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) reg_enum3 += std::stoi(tmpOpStr.substr(1, 2)); } - operands[0].reg = static_cast(reg_enum0); + operands[0].reg = static_cast(reg_enum0); operands[0].access = CS_AC_WRITE; - operands[1].reg = static_cast(reg_enum1); + operands[1].reg = static_cast(reg_enum1); operands[1].access = CS_AC_WRITE; - operands[2].reg = static_cast(reg_enum2); + operands[2].reg = static_cast(reg_enum2); operands[2].access = CS_AC_WRITE; - operands[3].reg = static_cast(reg_enum3); + operands[3].reg = static_cast(reg_enum3); operands[3].access = CS_AC_WRITE; operands[4].access = CS_AC_READ; @@ -1155,15 +1155,15 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // MRS incorrectly flags source/destination as READ | WRITE operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; - // MRS incorrectly tags ARM64_OP_REG_MRS as ARM64_OP_SYS - operands[1].type = ARM64_OP_REG_MRS; + // MRS incorrectly tags AARCH64_OP_REG_MRS as AARCH64_OP_SYS + operands[1].type = AARCH64_OP_REG_MRS; break; case Opcode::AArch64_MSR: // MSR incorrectly flags source/destination as READ | WRITE operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; - // MSR incorrectly tags ARM64_OP_REG_MSR as ARM64_OP_SYS - operands[0].type = ARM64_OP_REG_MSR; + // MSR incorrectly tags AARCH64_OP_REG_MSR as AARCH64_OP_SYS + operands[0].type = AARCH64_OP_REG_MSR; break; case Opcode::AArch64_PTEST_PP: { // PTEST doesn't label access types for operands @@ -1171,7 +1171,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[1].access = CS_AC_READ; // Doesn't identify implicit NZCV destination implicitDestinationCount = 1; - implicitDestinations[0] = ARM64_REG_NZCV; + implicitDestinations[0] = AARCH64_REG_NZCV; break; } case Opcode::AArch64_PTRUE_B: @@ -1188,8 +1188,8 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // If no register supplied to RET, default to x30 (LR) if (operandCount == 0) { operandCount = 1; - operands[0].type = ARM64_OP_REG; - operands[0].reg = ARM64_REG_LR; + operands[0].type = AARCH64_OP_REG; + operands[0].reg = AARCH64_REG_LR; operands[0].access = CS_AC_READ; } groupCount = 1; @@ -1220,7 +1220,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) [[fallthrough]]; case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { // ST1W doesn't correctly identify first source register - uint16_t reg_enum = ARM64_REG_Z0; + uint16_t reg_enum = AARCH64_REG_Z0; // Single or double digit Z register identifier if (operandStr[3] == '.') { reg_enum += std::stoi(operandStr.substr(2, 1)); @@ -1228,17 +1228,17 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) reg_enum += std::stoi(operandStr.substr(2, 2)); } - operands[0].reg = static_cast(reg_enum); + operands[0].reg = static_cast(reg_enum); // No defined access types operands[0].access = CS_AC_READ; operands[1].access = CS_AC_READ; // SST1D{_SCALED} gather instruction doesn't correctly identify memory // operands - operands[2].type = ARM64_OP_MEM; + operands[2].type = AARCH64_OP_MEM; operands[2].access = CS_AC_READ; // ST1D doesn't correctly identify vector memory register correctly - uint16_t vec_enum = ARM64_REG_Z0; + uint16_t vec_enum = AARCH64_REG_Z0; std::string tmp_str(operandStr.substr(operandStr.find("["))); // Single or double digit Z register identifier if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { @@ -1246,13 +1246,13 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) } else { vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); } - operands[2].mem.index = static_cast(vec_enum); + operands[2].mem.index = static_cast(vec_enum); break; } case Opcode::AArch64_ST2D_IMM: { // ST2D doesn't correctly identify destination registers - uint16_t reg_enum0 = ARM64_REG_Z0; - uint16_t reg_enum1 = ARM64_REG_Z0; + uint16_t reg_enum0 = AARCH64_REG_Z0; + uint16_t reg_enum1 = AARCH64_REG_Z0; // tmpOpStr = "zxx.d, zyy.d" std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); @@ -1275,9 +1275,9 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) tmpOpStr.erase(0, 7); } - operands[0].reg = static_cast(reg_enum0); + operands[0].reg = static_cast(reg_enum0); operands[0].access = CS_AC_READ; - operands[1].reg = static_cast(reg_enum1); + operands[1].reg = static_cast(reg_enum1); operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ; @@ -1294,7 +1294,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) [[fallthrough]]; case Opcode::AArch64_ST1W_IMM: { // ST1W doesn't correctly identify first source register - uint16_t reg_enum = ARM64_REG_Z0; + uint16_t reg_enum = AARCH64_REG_Z0; // Single or double digit Z register identifier if (operandStr[3] == '.') { reg_enum += std::stoi(operandStr.substr(2, 1)); @@ -1302,7 +1302,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) reg_enum += std::stoi(operandStr.substr(2, 2)); } - operands[0].reg = static_cast(reg_enum); + operands[0].reg = static_cast(reg_enum); // No defined access types operands[0].access = CS_AC_READ; operands[1].access = CS_AC_READ; @@ -1313,7 +1313,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) [[fallthrough]]; case Opcode::AArch64_ST1W_D: { // ST1W doesn't correctly identify first source register - uint16_t reg_enum = ARM64_REG_Z0; + uint16_t reg_enum = AARCH64_REG_Z0; // Single or double digit Z register identifier if (operandStr[3] == '.') { reg_enum += std::stoi(operandStr.substr(2, 1)); @@ -1321,7 +1321,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) reg_enum += std::stoi(operandStr.substr(2, 2)); } - operands[0].reg = static_cast(reg_enum); + operands[0].reg = static_cast(reg_enum); // No defined access types operands[0].access = CS_AC_READ; operands[1].access = CS_AC_READ; @@ -1336,7 +1336,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) case Opcode::AArch64_SST1W_IMM: { // ST1W scatter instruction doesn't correctly identify first source // register - uint16_t reg_enum = ARM64_REG_Z0; + uint16_t reg_enum = AARCH64_REG_Z0; // Single or double digit Z register identifier if (operandStr[3] == '.') { reg_enum += std::stoi(operandStr.substr(2, 1)); @@ -1344,13 +1344,13 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) reg_enum += std::stoi(operandStr.substr(2, 2)); } - operands[0].reg = static_cast(reg_enum); + operands[0].reg = static_cast(reg_enum); // No defined access types operands[0].access = CS_AC_READ; operands[1].access = CS_AC_READ; // ST1W scatter instruction doesn't correctly identify second Z reg as // memory operand - operands[2].type = ARM64_OP_MEM; + operands[2].type = AARCH64_OP_MEM; operands[2].access = CS_AC_READ; // ST1W scatter instruction doesn't recognise memory-offset immediate // correctly @@ -1409,9 +1409,9 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[5].access = CS_AC_READ; // determine correct type for operand 5 if (operandStr.find("#") != std::string::npos) { - operands[5].type = ARM64_OP_IMM; + operands[5].type = AARCH64_OP_IMM; } else { - operands[5].type = ARM64_OP_REG; + operands[5].type = AARCH64_OP_REG; } break; case Opcode::AArch64_ST1Twov16b: @@ -1435,9 +1435,9 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[3].access = CS_AC_READ; // determine correct type for operand 3 if (operandStr.find("#") != std::string::npos) { - operands[3].type = ARM64_OP_IMM; + operands[3].type = AARCH64_OP_IMM; } else { - operands[3].type = ARM64_OP_REG; + operands[3].type = AARCH64_OP_REG; } break; case Opcode::AArch64_ST2Twov4s_POST: @@ -1524,7 +1524,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_READ | CS_AC_WRITE; if (operandCount == 1) { operandCount = 2; - operands[1].type = ARM64_OP_IMM; + operands[1].type = AARCH64_OP_IMM; operands[1].imm = 1; } operands[1].access = CS_AC_READ; @@ -1572,7 +1572,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].access = CS_AC_READ; // Doesn't identify implicit NZCV destination implicitDestinationCount = 1; - implicitDestinations[0] = ARM64_REG_NZCV; + implicitDestinations[0] = AARCH64_REG_NZCV; break; case Opcode::AArch64_XTNv16i8: case Opcode::AArch64_XTNv4i32: @@ -1720,29 +1720,29 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) uint8_t tileNum = std::stoi(operandStr.substr((pos + 2), 1)); switch (type) { case 'b': - operands[operandCount].reg = ARM64_REG_ZAB0; + operands[operandCount].reg = AARCH64_REG_ZAB0; break; case 'h': operands[operandCount].reg = - static_cast(ARM64_REG_ZAH0 + tileNum); + static_cast(AARCH64_REG_ZAH0 + tileNum); break; case 's': operands[operandCount].reg = - static_cast(ARM64_REG_ZAS0 + tileNum); + static_cast(AARCH64_REG_ZAS0 + tileNum); break; case 'd': operands[operandCount].reg = - static_cast(ARM64_REG_ZAD0 + tileNum); + static_cast(AARCH64_REG_ZAD0 + tileNum); break; case 'q': operands[operandCount].reg = - static_cast(ARM64_REG_ZAQ0 + tileNum); + static_cast(AARCH64_REG_ZAQ0 + tileNum); break; } } else { - operands[operandCount].reg = ARM64_REG_ZA; + operands[operandCount].reg = AARCH64_REG_ZA; } - operands[operandCount].type = ARM64_OP_REG; + operands[operandCount].type = AARCH64_OP_REG; operands[operandCount].access = CS_AC_WRITE; operandCount++; pos = operandStr.find("za", pos + 1); @@ -1784,7 +1784,7 @@ void InstructionMetadata::revertAliasing() { opcode == Opcode::AArch64_SBFMXri) { operandCount = 4; - operands[3].type = ARM64_OP_IMM; + operands[3].type = AARCH64_OP_IMM; operands[3].access = CS_AC_READ; if (opcode == Opcode::AArch64_SBFMWri) { // 32-bit @@ -1830,7 +1830,7 @@ void InstructionMetadata::revertAliasing() { // cinc rd, rn, cc; alias for: csinc rd, rn, rn, invert(cc) operandCount = 3; - operands[2].type = ARM64_OP_REG; + operands[2].type = AARCH64_OP_REG; operands[2].access = CS_AC_READ; operands[2].reg = operands[1].reg; @@ -1847,17 +1847,17 @@ void InstructionMetadata::revertAliasing() { operands[1] = operands[0]; operands[1].access = CS_AC_READ; - operands[0].type = ARM64_OP_REG; + operands[0].type = AARCH64_OP_REG; operands[0].access = CS_AC_WRITE; if (opcode == Opcode::AArch64_ADDSXri || opcode == Opcode::AArch64_ADDSXrr || opcode == Opcode::AArch64_ADDSXrs) { // 64-bit version - operands[0].reg = ARM64_REG_XZR; + operands[0].reg = AARCH64_REG_XZR; } else { // 32-bit version - operands[0].reg = ARM64_REG_WZR; + operands[0].reg = AARCH64_REG_WZR; } return; case ARM64_INS_CMP: @@ -1874,15 +1874,15 @@ void InstructionMetadata::revertAliasing() { operands[1] = operands[0]; operands[1].access = CS_AC_READ; - operands[0].type = ARM64_OP_REG; + operands[0].type = AARCH64_OP_REG; operands[0].access = CS_AC_WRITE; if (opcode == Opcode::AArch64_SUBSWri || opcode == Opcode::AArch64_SUBSWrs || opcode == Opcode::AArch64_SUBSWrx) { - operands[0].reg = ARM64_REG_WZR; + operands[0].reg = AARCH64_REG_WZR; } else { - operands[0].reg = ARM64_REG_XZR; + operands[0].reg = AARCH64_REG_XZR; } return; } @@ -1904,20 +1904,20 @@ void InstructionMetadata::revertAliasing() { // cset rd, cc; alias for: csinc rd, zr, zr, invert(cc) operandCount = 3; - operands[1].type = ARM64_OP_REG; + operands[1].type = AARCH64_OP_REG; operands[1].access = CS_AC_READ; operands[1].shift = {ARM64_SFT_INVALID, 0}; - operands[2].type = ARM64_OP_REG; + operands[2].type = AARCH64_OP_REG; operands[2].access = CS_AC_READ; operands[2].shift = {ARM64_SFT_INVALID, 0}; if (opcode == Opcode::AArch64_CSINCWr) { - operands[1].reg = ARM64_REG_WZR; - operands[2].reg = ARM64_REG_WZR; + operands[1].reg = AARCH64_REG_WZR; + operands[2].reg = AARCH64_REG_WZR; } else { - operands[1].reg = ARM64_REG_XZR; - operands[2].reg = ARM64_REG_XZR; + operands[1].reg = AARCH64_REG_XZR; + operands[2].reg = AARCH64_REG_XZR; } cc ^= 1; // invert lowest bit to negate cc @@ -1931,18 +1931,18 @@ void InstructionMetadata::revertAliasing() { // csetm rd, cc; alias for: csinv rd, zr, zr, invert(cc) operandCount = 3; - operands[1].type = ARM64_OP_REG; + operands[1].type = AARCH64_OP_REG; operands[1].access = CS_AC_READ; - operands[2].type = ARM64_OP_REG; + operands[2].type = AARCH64_OP_REG; operands[2].access = CS_AC_READ; if (opcode == Opcode::AArch64_CSINVWr) { - operands[1].reg = ARM64_REG_WZR; - operands[2].reg = ARM64_REG_WZR; + operands[1].reg = AARCH64_REG_WZR; + operands[2].reg = AARCH64_REG_WZR; } else { - operands[1].reg = ARM64_REG_XZR; - operands[2].reg = ARM64_REG_XZR; + operands[1].reg = AARCH64_REG_XZR; + operands[2].reg = AARCH64_REG_XZR; } cc ^= 1; // invert lowest bit to negate cc @@ -1968,7 +1968,7 @@ void InstructionMetadata::revertAliasing() { auto shift = operands[2].imm; operands[2].imm = (-shift) & highestBit; - operands[3].type = ARM64_OP_IMM; + operands[3].type = AARCH64_OP_IMM; operands[3].imm = highestBit - shift; operands[3].access = CS_AC_READ; return; @@ -1990,7 +1990,7 @@ void InstructionMetadata::revertAliasing() { // lsr rd, rn, #amount; alias for ubfm rd, rn, #amount, #<31|63> operandCount = 4; - operands[3].type = ARM64_OP_IMM; + operands[3].type = AARCH64_OP_IMM; operands[3].access = CS_AC_READ; if (opcode == Opcode::AArch64_UBFMWri) { @@ -2006,17 +2006,17 @@ void InstructionMetadata::revertAliasing() { if (opcode == Opcode::AArch64_MSUBXrrr) { // mneg xd, xn, xm; alias for msub xd, xn, xm, xzr operandCount = 4; - operands[3].type = ARM64_OP_REG; + operands[3].type = AARCH64_OP_REG; operands[3].access = CS_AC_READ; - operands[3].reg = ARM64_REG_XZR; + operands[3].reg = AARCH64_REG_XZR; return; } if (opcode == Opcode::AArch64_MSUBWrrr) { // mneg wd, wn, wm; alias for msub wd, wn, wm, wzr operandCount = 4; - operands[3].type = ARM64_OP_REG; + operands[3].type = AARCH64_OP_REG; operands[3].access = CS_AC_READ; - operands[3].reg = ARM64_REG_WZR; + operands[3].reg = AARCH64_REG_WZR; return; } return aliasNYI(); @@ -2032,7 +2032,7 @@ void InstructionMetadata::revertAliasing() { opcode == Opcode::AArch64_ADDWri) { // mov to/from sp; alias for: add , , #0 operandCount = 3; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operands[2].imm = 0; operands[2].access = CS_AC_READ; operands[2].shift.type = ARM64_SFT_INVALID; @@ -2055,7 +2055,7 @@ void InstructionMetadata::revertAliasing() { operandCount = 3; operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operands[2].access = CS_AC_READ; // get imm value @@ -2075,7 +2075,7 @@ void InstructionMetadata::revertAliasing() { // mov Zd.T, #imm{, shift}; alias for dup Zd.T, #imm{, shift} operandCount = 2; operands[0].access = CS_AC_WRITE; - operands[1].type = ARM64_OP_IMM; + operands[1].type = AARCH64_OP_IMM; operands[1].access = CS_AC_READ; uint8_t start = operandStr[6] == '#' ? 7 : 8; @@ -2162,8 +2162,8 @@ void InstructionMetadata::revertAliasing() { uint8_t start = operandStr[2] == '.' ? 7 : 8; uint8_t end = operandStr.length() - start; - operands[1].reg = static_cast( - ARM64_REG_Z0 + stoi(operandStr.substr(start, end))); + operands[1].reg = static_cast( + AARCH64_REG_Z0 + stoi(operandStr.substr(start, end))); operands[1].vector_index = 0; return; } @@ -2194,14 +2194,14 @@ void InstructionMetadata::revertAliasing() { operandCount = 3; operands[2] = operands[1]; - operands[1].type = ARM64_OP_REG; + operands[1].type = AARCH64_OP_REG; operands[1].access = CS_AC_READ; operands[1].shift = {ARM64_SFT_INVALID, 0}; if (opcode == Opcode::AArch64_ORRWri || opcode == Opcode::AArch64_ORRWrs) { - operands[1].reg = ARM64_REG_WZR; + operands[1].reg = AARCH64_REG_WZR; } else { - operands[1].reg = ARM64_REG_XZR; + operands[1].reg = AARCH64_REG_XZR; } return; } @@ -2282,12 +2282,12 @@ void InstructionMetadata::revertAliasing() { if (opcode == Opcode::AArch64_MADDXrrr || opcode == Opcode::AArch64_MADDWrrr) { operandCount = 4; - operands[3].type = ARM64_OP_REG; + operands[3].type = AARCH64_OP_REG; operands[3].access = CS_AC_READ; if (opcode == Opcode::AArch64_MADDWrrr) { - operands[3].reg = ARM64_REG_WZR; + operands[3].reg = AARCH64_REG_WZR; } else { - operands[3].reg = ARM64_REG_XZR; + operands[3].reg = AARCH64_REG_XZR; } return; } @@ -2305,13 +2305,13 @@ void InstructionMetadata::revertAliasing() { operandCount = 3; operands[2] = operands[1]; - operands[1].type = ARM64_OP_REG; + operands[1].type = AARCH64_OP_REG; operands[1].access = CS_AC_READ; operands[1].shift = {ARM64_SFT_INVALID, 0}; if (opcode == Opcode::AArch64_ORNWrs) { - operands[1].reg = ARM64_REG_WZR; + operands[1].reg = AARCH64_REG_WZR; } else { - operands[1].reg = ARM64_REG_XZR; + operands[1].reg = AARCH64_REG_XZR; } return; } @@ -2333,13 +2333,13 @@ void InstructionMetadata::revertAliasing() { operandCount = 3; operands[2] = operands[1]; - operands[1].type = ARM64_OP_REG; + operands[1].type = AARCH64_OP_REG; operands[1].access = CS_AC_READ; if (opcode == Opcode::AArch64_SUBWrs) { - operands[1].reg = ARM64_REG_WZR; + operands[1].reg = AARCH64_REG_WZR; } else { - operands[1].reg = ARM64_REG_XZR; + operands[1].reg = AARCH64_REG_XZR; } return; } @@ -2356,13 +2356,13 @@ void InstructionMetadata::revertAliasing() { operandCount = 3; operands[2] = operands[1]; - operands[1].type = ARM64_OP_REG; + operands[1].type = AARCH64_OP_REG; operands[1].access = CS_AC_READ; if (opcode == Opcode::AArch64_SUBWrs) { - operands[1].reg = ARM64_REG_WZR; + operands[1].reg = AARCH64_REG_WZR; } else { - operands[1].reg = ARM64_REG_XZR; + operands[1].reg = AARCH64_REG_XZR; } return; } @@ -2437,9 +2437,9 @@ void InstructionMetadata::revertAliasing() { case ARM64_INS_SMULL: if (opcode == Opcode::AArch64_SMADDLrrr) { operandCount = 4; - operands[3].type = ARM64_OP_REG; + operands[3].type = AARCH64_OP_REG; operands[3].access = CS_AC_READ; - operands[3].reg = ARM64_REG_XZR; + operands[3].reg = AARCH64_REG_XZR; return; } return aliasNYI(); @@ -2449,11 +2449,11 @@ void InstructionMetadata::revertAliasing() { opcode == Opcode::AArch64_SBFMXri) { operandCount = 4; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operands[2].access = CS_AC_READ; operands[2].imm = 0; - operands[3].type = ARM64_OP_IMM; + operands[3].type = AARCH64_OP_IMM; operands[3].access = CS_AC_READ; operands[3].imm = 7; return; @@ -2465,11 +2465,11 @@ void InstructionMetadata::revertAliasing() { opcode == Opcode::AArch64_SBFMXri) { operandCount = 4; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operands[2].access = CS_AC_READ; operands[2].imm = 0; - operands[3].type = ARM64_OP_IMM; + operands[3].type = AARCH64_OP_IMM; operands[3].access = CS_AC_READ; operands[3].imm = 15; return; @@ -2480,11 +2480,11 @@ void InstructionMetadata::revertAliasing() { if (opcode == Opcode::AArch64_SBFMXri) { operandCount = 4; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operands[2].access = CS_AC_READ; operands[2].imm = 0; - operands[3].type = ARM64_OP_IMM; + operands[3].type = AARCH64_OP_IMM; operands[3].access = CS_AC_READ; operands[3].imm = 31; return; @@ -2502,9 +2502,9 @@ void InstructionMetadata::revertAliasing() { operandCount = 3; operands[1] = operands[0]; operands[1].access = CS_AC_READ; - operands[0].type = ARM64_OP_SYS; + operands[0].type = AARCH64_OP_SYS; operands[0].sys = ARM64_DC_ZVA; - operands[2].type = ARM64_OP_REG_MRS; + operands[2].type = AARCH64_OP_REG_MRS; operands[2].access = CS_AC_READ; operands[2].imm = ARM64_SYSREG_DCZID_EL0; return; @@ -2527,13 +2527,13 @@ void InstructionMetadata::revertAliasing() { operands[1] = operands[0]; operands[1].access = CS_AC_READ; - operands[0].type = ARM64_OP_REG; + operands[0].type = AARCH64_OP_REG; operands[0].access = CS_AC_WRITE; if (opcode == Opcode::AArch64_ANDSWrs || opcode == Opcode::AArch64_ANDSWri) { - operands[0].reg = ARM64_REG_WZR; + operands[0].reg = AARCH64_REG_WZR; } else { - operands[0].reg = ARM64_REG_XZR; + operands[0].reg = AARCH64_REG_XZR; } return; } @@ -2569,9 +2569,9 @@ void InstructionMetadata::revertAliasing() { // umull xd, wn, wm; alias for: umaddl xd, wn, wm, xzr if (opcode == Opcode::AArch64_UMADDLrrr) { operandCount = 4; - operands[3].type = ARM64_OP_REG; + operands[3].type = AARCH64_OP_REG; operands[3].access = CS_AC_READ; - operands[3].reg = ARM64_REG_XZR; + operands[3].reg = AARCH64_REG_XZR; return; } return aliasNYI(); @@ -2580,10 +2580,10 @@ void InstructionMetadata::revertAliasing() { // uxtb wd, wn; alias for: ubfm wd, wn, #0, #7 if (opcode == Opcode::AArch64_UBFMWri) { operandCount = 4; - operands[2].type = ARM64_OP_IMM; + operands[2].type = AARCH64_OP_IMM; operands[2].access = CS_AC_READ; operands[2].imm = 0; - operands[3].type = ARM64_OP_IMM; + operands[3].type = AARCH64_OP_IMM; operands[3].access = CS_AC_READ; operands[3].imm = 7; return; diff --git a/src/lib/arch/aarch64/InstructionMetadata.hh b/src/lib/arch/aarch64/InstructionMetadata.hh index 90eba4a5d0..dfd38cd8d0 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.hh +++ b/src/lib/arch/aarch64/InstructionMetadata.hh @@ -53,7 +53,7 @@ struct InstructionMetadata { static const size_t MAX_GROUPS = sizeof(cs_detail::groups) / sizeof(uint8_t); /** The maximum number of operands as defined in Capstone */ static const size_t MAX_OPERANDS = - sizeof(cs_arm64::operands) / sizeof(cs_arm64_op); + sizeof(cs_arm64::operands) / sizeof(cs_aarch64_op); /** The instruction's mnemonic ID. */ unsigned int id; @@ -93,7 +93,7 @@ struct InstructionMetadata { bool writeback; /** The explicit operands. */ - cs_arm64_op operands[MAX_OPERANDS]; + cs_aarch64_op operands[MAX_OPERANDS]; /** The number of explicit operands. */ uint8_t operandCount; diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 165c51b9ac..f6aec59456 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -36,98 +36,99 @@ constexpr int32_t signExtend(uint32_t value, int currentLength) { return static_cast(value) | (negative ? mask : 0); } -/** Parses the Capstone `arm64_reg` value to generate an architectural register - * representation. +/** Parses the Capstone `aarch64_reg` value to generate an architectural + * register representation. * * WARNING: this conversion is FRAGILE, and relies on the structure of the - * `arm64_reg` enum. Updates to the Capstone library version may cause this to + * `aarch64_reg` enum. Updates to the Capstone library version may cause this to * break. */ -Register csRegToRegister(arm64_reg reg) { +Register csRegToRegister(aarch64_reg reg) { // Check from top of the range downwards - // ARM64_REG_V0 -> {end} are vector registers, reading from the vector file - if (reg >= ARM64_REG_V0) { - return {RegisterType::VECTOR, static_cast(reg - ARM64_REG_V0)}; + // AARCH64_REG_V0 -> {end} are vector registers, reading from the vector file + if (reg >= AARCH64_REG_V0) { + return {RegisterType::VECTOR, static_cast(reg - AARCH64_REG_V0)}; } - // ARM64_REG_ZAB0 -> +31 are tiles of the matrix register (ZA), reading from + // AARCH64_REG_ZAB0 -> +31 are tiles of the matrix register (ZA), reading from // the matrix file. - if (reg >= ARM64_REG_ZAB0) { + if (reg >= AARCH64_REG_ZAB0) { // Placeholder value returned as each tile (what the enum represents) // consists of multiple vectors (rows) return {RegisterType::MATRIX, 0}; } - // ARM64_REG_Z0 -> +31 are scalable vector registers (Z) registers, reading + // AARCH64_REG_Z0 -> +31 are scalable vector registers (Z) registers, reading // from the vector file - if (reg >= ARM64_REG_Z0) { - return {RegisterType::VECTOR, static_cast(reg - ARM64_REG_Z0)}; + if (reg >= AARCH64_REG_Z0) { + return {RegisterType::VECTOR, static_cast(reg - AARCH64_REG_Z0)}; } - // ARM64_REG_X0 -> +28 are 64-bit (X) registers, reading from the general + // AARCH64_REG_X0 -> +28 are 64-bit (X) registers, reading from the general // file. Excludes #29 (FP) and #30 (LR) - if (reg >= ARM64_REG_X0) { - return {RegisterType::GENERAL, static_cast(reg - ARM64_REG_X0)}; + if (reg >= AARCH64_REG_X0) { + return {RegisterType::GENERAL, static_cast(reg - AARCH64_REG_X0)}; } - // ARM64_REG_W0 -> +30 are 32-bit (W) registers, reading from the general + // AARCH64_REG_W0 -> +30 are 32-bit (W) registers, reading from the general // file. Excludes #31 (WZR/WSP). - if (reg >= ARM64_REG_W0) { - return {RegisterType::GENERAL, static_cast(reg - ARM64_REG_W0)}; + if (reg >= AARCH64_REG_W0) { + return {RegisterType::GENERAL, static_cast(reg - AARCH64_REG_W0)}; } - // ARM64_REG_Q0 and above are repeated ranges representing scalar access + // AARCH64_REG_Q0 and above are repeated ranges representing scalar access // specifiers on the vector registers with arrangements Q and S, each // covering 32 registers - if (reg >= ARM64_REG_Q0) { + if (reg >= AARCH64_REG_Q0) { return {RegisterType::VECTOR, - static_cast((reg - ARM64_REG_Q0) % 32)}; + static_cast((reg - AARCH64_REG_Q0) % 32)}; } - // ARM64_REG_P0 -> +15 are 256-bit (P) registers. Excludes #16 (FFR). - if (reg >= ARM64_REG_P0) { - return {RegisterType::PREDICATE, static_cast(reg - ARM64_REG_P0)}; + // AARCH64_REG_P0 -> +15 are 256-bit (P) registers. Excludes #16 (FFR). + if (reg >= AARCH64_REG_P0) { + return {RegisterType::PREDICATE, + static_cast(reg - AARCH64_REG_P0)}; } - // ARM64_REG_Q0 and above are repeated ranges representing scalar access + // AARCH64_REG_Q0 and above are repeated ranges representing scalar access // specifiers on the vector registers with arrangements B, D and H, each // covering 32 registers - if (reg >= ARM64_REG_B0) { + if (reg >= AARCH64_REG_B0) { return {RegisterType::VECTOR, - static_cast((reg - ARM64_REG_B0) % 32)}; + static_cast((reg - AARCH64_REG_B0) % 32)}; } - // ARM64_REG_WZR and _XZR are zero registers, and don't read - if (reg == ARM64_REG_WZR || reg == ARM64_REG_XZR) { + // AARCH64_REG_WZR and _XZR are zero registers, and don't read + if (reg == AARCH64_REG_WZR || reg == AARCH64_REG_XZR) { return RegisterType::ZERO_REGISTER; } - // ARM64_REG_SP and _WSP are stack pointer registers, stored in r31 of the + // AARCH64_REG_SP and _WSP are stack pointer registers, stored in r31 of the // general file - if (reg == ARM64_REG_SP || reg == ARM64_REG_WSP) { + if (reg == AARCH64_REG_SP || reg == AARCH64_REG_WSP) { return {RegisterType::GENERAL, 31}; } - // ARM64_REG_NZCV is the condition flags register - if (reg == ARM64_REG_NZCV) { + // AARCH64_REG_NZCV is the condition flags register + if (reg == AARCH64_REG_NZCV) { return {RegisterType::NZCV, 0}; } - // ARM64_REG_X29 is the frame pointer, stored in r29 of the general file - if (reg == ARM64_REG_X29) { + // AARCH64_REG_X29 is the frame pointer, stored in r29 of the general file + if (reg == AARCH64_REG_X29) { return {RegisterType::GENERAL, 29}; } - // ARM64_REG_X30 is the link register, stored in r30 of the general file - if (reg == ARM64_REG_X30) { + // AARCH64_REG_X30 is the link register, stored in r30 of the general file + if (reg == AARCH64_REG_X30) { return {RegisterType::GENERAL, 30}; } - if (reg == ARM64_REG_FFR) { + if (reg == AARCH64_REG_FFR) { return {RegisterType::PREDICATE, 16}; } // The matrix register (ZA) can also be referenced as a whole in some // instructions. - if (reg == ARM64_REG_ZA) { + if (reg == AARCH64_REG_ZA) { // Placeholder value returned as each tile (what the enum represents) // consists of multiple vectors (rows) return {RegisterType::MATRIX, 0}; @@ -140,29 +141,30 @@ Register csRegToRegister(arm64_reg reg) { /** Returns a full set of rows from the ZA matrix register that make up the * supplied SME tile register. */ -std::vector getZARowVectors(arm64_reg reg, const uint64_t SVL_bits) { +std::vector getZARowVectors(aarch64_reg reg, + const uint64_t SVL_bits) { std::vector outRegs; // Get SVL in bytes (will equal total number of implemented ZA rows) uint64_t SVL = SVL_bits / 8; uint8_t base = 0; uint8_t tileTypeCount = 0; - if (reg == ARM64_REG_ZA || reg == ARM64_REG_ZAB0) { + if (reg == AARCH64_REG_ZA || reg == AARCH64_REG_ZAB0) { // Treat ZA as byte tile : ZAB0 represents whole matrix, only 1 tile // Add all rows for this SVL // Don't need to set base as will always be 0 tileTypeCount = 1; - } else if (reg >= ARM64_REG_ZAH0 && reg <= ARM64_REG_ZAH1) { - base = reg - ARM64_REG_ZAH0; + } else if (reg >= AARCH64_REG_ZAH0 && reg <= AARCH64_REG_ZAH1) { + base = reg - AARCH64_REG_ZAH0; tileTypeCount = 2; - } else if (reg >= ARM64_REG_ZAS0 && reg <= ARM64_REG_ZAS3) { - base = reg - ARM64_REG_ZAS0; + } else if (reg >= AARCH64_REG_ZAS0 && reg <= AARCH64_REG_ZAS3) { + base = reg - AARCH64_REG_ZAS0; tileTypeCount = 4; - } else if (reg >= ARM64_REG_ZAD0 && reg <= ARM64_REG_ZAD7) { - base = reg - ARM64_REG_ZAD0; + } else if (reg >= AARCH64_REG_ZAD0 && reg <= AARCH64_REG_ZAD7) { + base = reg - AARCH64_REG_ZAD0; tileTypeCount = 8; - } else if (reg >= ARM64_REG_ZAQ0 && reg <= ARM64_REG_ZAQ15) { - base = reg - ARM64_REG_ZAQ0; + } else if (reg >= AARCH64_REG_ZAQ0 && reg <= AARCH64_REG_ZAQ15) { + base = reg - AARCH64_REG_ZAQ0; tileTypeCount = 16; } @@ -191,13 +193,13 @@ void Instruction::decode() { // Extract implicit writes for (size_t i = 0; i < metadata_.implicitDestinationCount; i++) { destinationRegisters_[destinationRegisterCount_] = csRegToRegister( - static_cast(metadata_.implicitDestinations[i])); + static_cast(metadata_.implicitDestinations[i])); destinationRegisterCount_++; } // Extract implicit reads for (size_t i = 0; i < metadata_.implicitSourceCount; i++) { sourceRegisters_[sourceOperandsPending_] = - csRegToRegister(static_cast(metadata_.implicitSources[i])); + csRegToRegister(static_cast(metadata_.implicitSources[i])); sourceRegisterCount_++; sourceOperandsPending_++; } @@ -208,29 +210,29 @@ void Instruction::decode() { for (size_t i = 0; i < metadata_.operandCount; i++) { const auto& op = metadata_.operands[i]; - if (op.type == ARM64_OP_REG) { // Register operand + if (op.type == AARCH64_OP_REG) { // Register operand if ((op.access & cs_ac_type::CS_AC_WRITE)) { - if (op.reg != ARM64_REG_WZR && op.reg != ARM64_REG_XZR) { + if (op.reg != AARCH64_REG_WZR && op.reg != AARCH64_REG_XZR) { // Determine the data type the instruction operates on based on the // register operand used // Belongs to the predicate group if the destination register is a // predicate - if (op.reg >= ARM64_REG_V0) { + if (op.reg >= AARCH64_REG_V0) { setInstructionType(InsnType::isVectorData); - } else if (op.reg >= ARM64_REG_ZAB0 || op.reg == ARM64_REG_ZA) { + } else if (op.reg >= AARCH64_REG_ZAB0 || op.reg == AARCH64_REG_ZA) { setInstructionType(InsnType::isSMEData); - } else if (op.reg >= ARM64_REG_Z0) { + } else if (op.reg >= AARCH64_REG_Z0) { setInstructionType(InsnType::isSVEData); - } else if (op.reg <= ARM64_REG_S31 && op.reg >= ARM64_REG_Q0) { + } else if (op.reg <= AARCH64_REG_S31 && op.reg >= AARCH64_REG_Q0) { setInstructionType(InsnType::isScalarData); - } else if (op.reg <= ARM64_REG_P15 && op.reg >= ARM64_REG_P0) { + } else if (op.reg <= AARCH64_REG_P15 && op.reg >= AARCH64_REG_P0) { setInstructionType(InsnType::isPredicate); - } else if (op.reg <= ARM64_REG_H31 && op.reg >= ARM64_REG_B0) { + } else if (op.reg <= AARCH64_REG_H31 && op.reg >= AARCH64_REG_B0) { setInstructionType(InsnType::isScalarData); } - if ((op.reg >= ARM64_REG_ZAB0 && op.reg < ARM64_REG_V0) || - (op.reg == ARM64_REG_ZA)) { + if ((op.reg >= AARCH64_REG_ZAB0 && op.reg < AARCH64_REG_V0) || + (op.reg == AARCH64_REG_ZA)) { // Add all Matrix register rows as destination operands std::vector regs = getZARowVectors( op.reg, architecture_.getStreamingVectorLength()); @@ -258,8 +260,8 @@ void Instruction::decode() { } } if (op.access & cs_ac_type::CS_AC_READ) { - if ((op.reg >= ARM64_REG_ZAB0 && op.reg < ARM64_REG_V0) || - (op.reg == ARM64_REG_ZA)) { + if ((op.reg >= AARCH64_REG_ZAB0 && op.reg < AARCH64_REG_V0) || + (op.reg == AARCH64_REG_ZA)) { // Add all Matrix register rows as source operands std::vector regs = getZARowVectors(op.reg, architecture_.getStreamingVectorLength()); @@ -288,7 +290,7 @@ void Instruction::decode() { setInstructionType(InsnType::isShift); // Identify shift operands } } - } else if (op.type == ARM64_OP_MEM) { // Memory operand + } else if (op.type == AARCH64_OP_MEM) { // Memory operand accessesMemory = true; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.mem.base); sourceRegisterCount_++; @@ -306,11 +308,11 @@ void Instruction::decode() { sourceRegisterCount_++; sourceOperandsPending_++; } - } else if (op.type == ARM64_OP_SME_INDEX) { // SME instruction with index + } else if (op.type == AARCH64_OP_SME_INDEX) { // SME instruction with index std::vector regs; - if ((op.sme_index.reg >= ARM64_REG_ZAB0 && - op.sme_index.reg < ARM64_REG_V0) || - (op.sme_index.reg == ARM64_REG_ZA)) { + if ((op.sme_index.reg >= AARCH64_REG_ZAB0 && + op.sme_index.reg < AARCH64_REG_V0) || + (op.sme_index.reg == AARCH64_REG_ZA)) { // Set instruction group setInstructionType(InsnType::isSMEData); regs = getZARowVectors(op.sme_index.reg, @@ -354,7 +356,7 @@ void Instruction::decode() { csRegToRegister(op.sme_index.base); sourceRegisterCount_++; sourceOperandsPending_++; - } else if (op.type == ARM64_OP_REG_MRS) { + } else if (op.type == AARCH64_OP_REG_MRS) { int32_t sysRegTag = architecture_.getSystemRegisterTag(op.imm); if (sysRegTag == -1) { exceptionEncountered_ = true; @@ -366,7 +368,7 @@ void Instruction::decode() { sourceRegisterCount_++; sourceOperandsPending_++; } - } else if (op.type == ARM64_OP_REG_MSR) { + } else if (op.type == AARCH64_OP_REG_MSR) { int32_t sysRegTag = architecture_.getSystemRegisterTag(op.imm); if (sysRegTag == -1) { exceptionEncountered_ = true; @@ -377,7 +379,7 @@ void Instruction::decode() { RegisterType::SYSTEM, static_cast(sysRegTag)}; destinationRegisterCount_++; } - } else if (op.type == ARM64_OP_SVCR) { + } else if (op.type == AARCH64_OP_SVCR) { // Updating of SVCR is done via an exception and not via the sysreg file. // No operands are required for this operation. // Any access to SVCR other than SMSTART and SMSTOP (i.e. this OP_TYPE) @@ -499,19 +501,19 @@ void Instruction::decode() { if (isInstruction(InsnType::isStoreData)) { // Identify store instruction group - if (ARM64_REG_Z0 <= metadata_.operands[0].reg && - metadata_.operands[0].reg <= ARM64_REG_Z31) { + if (AARCH64_REG_Z0 <= metadata_.operands[0].reg && + metadata_.operands[0].reg <= AARCH64_REG_Z31) { setInstructionType(InsnType::isSVEData); - } else if ((metadata_.operands[0].reg <= ARM64_REG_S31 && - metadata_.operands[0].reg >= ARM64_REG_Q0) || - (metadata_.operands[0].reg <= ARM64_REG_H31 && - metadata_.operands[0].reg >= ARM64_REG_B0)) { + } else if ((metadata_.operands[0].reg <= AARCH64_REG_S31 && + metadata_.operands[0].reg >= AARCH64_REG_Q0) || + (metadata_.operands[0].reg <= AARCH64_REG_H31 && + metadata_.operands[0].reg >= AARCH64_REG_B0)) { setInstructionType(InsnType::isScalarData); - } else if (metadata_.operands[0].reg >= ARM64_REG_V0) { + } else if (metadata_.operands[0].reg >= AARCH64_REG_V0) { setInstructionType(InsnType::isVectorData); - } else if ((metadata_.operands[0].reg >= ARM64_REG_ZAB0 && - metadata_.operands[0].reg < ARM64_REG_V0) || - metadata_.operands[0].reg == ARM64_REG_ZA) { + } else if ((metadata_.operands[0].reg >= AARCH64_REG_ZAB0 && + metadata_.operands[0].reg < AARCH64_REG_V0) || + metadata_.operands[0].reg == AARCH64_REG_ZA) { setInstructionType(InsnType::isSMEData); } } diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index 6da1864eaf..7fb9bc1974 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -2788,9 +2788,10 @@ void Instruction::execute() { results_[0] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); // if #imm post-index, value can only be 16 - const uint64_t postIndex = (metadata_.operands[2].type == ARM64_OP_REG) - ? sourceValues_[1].get() - : 16; + const uint64_t postIndex = + (metadata_.operands[2].type == AARCH64_OP_REG) + ? sourceValues_[1].get() + : 16; results_[1] = sourceValues_[0].get() + postIndex; break; } @@ -3082,9 +3083,10 @@ void Instruction::execute() { results_[2] = memoryData_[2].zeroExtend(memoryData_[2].size(), 256); results_[3] = memoryData_[3].zeroExtend(memoryData_[3].size(), 256); // if #imm post-index, value can only be 64 - const uint64_t postIndex = (metadata_.operands[5].type == ARM64_OP_REG) - ? sourceValues_[1].get() - : 64; + const uint64_t postIndex = + (metadata_.operands[5].type == AARCH64_OP_REG) + ? sourceValues_[1].get() + : 64; results_[4] = sourceValues_[0].get() + postIndex; break; } @@ -3111,9 +3113,10 @@ void Instruction::execute() { results_[1] = memoryData_[1].zeroExtend(memoryData_[1].size(), 256); // if #imm post-index, value can only be 32 - const uint64_t postIndex = (metadata_.operands[3].type == ARM64_OP_REG) - ? sourceValues_[1].get() - : 32; + const uint64_t postIndex = + (metadata_.operands[3].type == AARCH64_OP_REG) + ? sourceValues_[1].get() + : 32; results_[2] = sourceValues_[0].get() + postIndex; break; } @@ -3848,7 +3851,7 @@ void Instruction::execute() { // Handle case where SVCR is being updated as this invokes additional // functionality if (metadata_.operands[0].reg == - static_cast(ARM64_SYSREG_SVCR)) { + static_cast(ARM64_SYSREG_SVCR)) { return SMZAupdated(); } else { results_[0] = sourceValues_[0]; @@ -4634,9 +4637,10 @@ void Instruction::execute() { 16 * sizeof(uint8_t)); } // if #imm post-index, value can only be 64 - const uint64_t postIndex = (metadata_.operands[5].type == ARM64_OP_REG) - ? sourceValues_[5].get() - : 64; + const uint64_t postIndex = + (metadata_.operands[5].type == AARCH64_OP_REG) + ? sourceValues_[5].get() + : 64; results_[0] = sourceValues_[4].get() + postIndex; break; } @@ -4659,9 +4663,10 @@ void Instruction::execute() { 2 * sizeof(uint64_t)); } // if #imm post-index, value can only be 64 - const uint64_t postIndex = (metadata_.operands[5].type == ARM64_OP_REG) - ? sourceValues_[5].get() - : 64; + const uint64_t postIndex = + (metadata_.operands[5].type == AARCH64_OP_REG) + ? sourceValues_[5].get() + : 64; results_[0] = sourceValues_[4].get() + postIndex; break; } @@ -4674,9 +4679,10 @@ void Instruction::execute() { 2 * sizeof(uint32_t)); } // if #imm post-index, value can only be 32 - const uint64_t postIndex = (metadata_.operands[5].type == ARM64_OP_REG) - ? sourceValues_[5].get() - : 32; + const uint64_t postIndex = + (metadata_.operands[5].type == AARCH64_OP_REG) + ? sourceValues_[5].get() + : 32; results_[0] = sourceValues_[4].get() + postIndex; break; } @@ -4699,9 +4705,10 @@ void Instruction::execute() { 4 * sizeof(uint32_t)); } // if #imm post-index, value can only be 64 - const uint64_t postIndex = (metadata_.operands[5].type == ARM64_OP_REG) - ? sourceValues_[5].get() - : 64; + const uint64_t postIndex = + (metadata_.operands[5].type == AARCH64_OP_REG) + ? sourceValues_[5].get() + : 64; results_[0] = sourceValues_[4].get() + postIndex; break; } @@ -4722,9 +4729,10 @@ void Instruction::execute() { memoryData_[1] = RegisterValue((char*)t2, 16 * sizeof(uint8_t)); // if #imm post-index, value can only be 32 - const uint64_t postIndex = (metadata_.operands[3].type == ARM64_OP_REG) - ? sourceValues_[3].get() - : 32; + const uint64_t postIndex = + (metadata_.operands[3].type == AARCH64_OP_REG) + ? sourceValues_[3].get() + : 32; results_[0] = sourceValues_[2].get() + postIndex; break; } @@ -4745,9 +4753,10 @@ void Instruction::execute() { memoryData_[1] = RegisterValue((char*)t2, 2 * sizeof(uint64_t)); // if #imm post-index, value can only be 32 - const uint64_t postIndex = (metadata_.operands[3].type == ARM64_OP_REG) - ? sourceValues_[3].get() - : 32; + const uint64_t postIndex = + (metadata_.operands[3].type == AARCH64_OP_REG) + ? sourceValues_[3].get() + : 32; results_[0] = sourceValues_[2].get() + postIndex; break; } @@ -4768,9 +4777,10 @@ void Instruction::execute() { memoryData_[1] = RegisterValue((char*)t2, 4 * sizeof(uint32_t)); // if #imm post-index, value can only be 32 - const uint64_t postIndex = (metadata_.operands[3].type == ARM64_OP_REG) - ? sourceValues_[3].get() - : 32; + const uint64_t postIndex = + (metadata_.operands[3].type == AARCH64_OP_REG) + ? sourceValues_[3].get() + : 32; results_[0] = sourceValues_[2].get() + postIndex; break; } diff --git a/src/lib/arch/aarch64/MicroDecoder.cc b/src/lib/arch/aarch64/MicroDecoder.cc index edb4a9a1c2..3981489b9c 100644 --- a/src/lib/arch/aarch64/MicroDecoder.cc +++ b/src/lib/arch/aarch64/MicroDecoder.cc @@ -18,52 +18,52 @@ MicroDecoder::~MicroDecoder() { microMetadataCache_.clear(); } -bool MicroDecoder::detectOverlap(arm64_reg registerA, arm64_reg registerB) { +bool MicroDecoder::detectOverlap(aarch64_reg registerA, aarch64_reg registerB) { // Early checks on equivalent register ISA names if (registerA == registerB) return true; - if ((registerA == ARM64_REG_WZR || registerA == ARM64_REG_XZR) && - (registerB == ARM64_REG_WZR || registerB == ARM64_REG_XZR)) + if ((registerA == AARCH64_REG_WZR || registerA == AARCH64_REG_XZR) && + (registerB == AARCH64_REG_WZR || registerB == AARCH64_REG_XZR)) return true; - if ((registerA == ARM64_REG_WSP || registerA == ARM64_REG_SP) && - (registerB == ARM64_REG_WSP || registerB == ARM64_REG_SP)) + if ((registerA == AARCH64_REG_WSP || registerA == AARCH64_REG_SP) && + (registerB == AARCH64_REG_WSP || registerB == AARCH64_REG_SP)) return true; // Arrays to hold register identifiers - std::array registers = {registerA, registerB}; + std::array registers = {registerA, registerB}; std::array isGP = {false, false}; std::array indexes = {0, 0}; // Get index of each register and whether they are general purpose for (int i = 0; i < 2; i++) { - if (registers[i] == ARM64_REG_FP) { + if (registers[i] == AARCH64_REG_FP) { isGP[i] = true; indexes[i] = 29; - } else if (registers[i] == ARM64_REG_LR) { + } else if (registers[i] == AARCH64_REG_LR) { isGP[i] = true; indexes[i] = 30; } else { - arm64_reg base = (arm64_reg)0; - if (registers[i] >= ARM64_REG_V0) { - base = ARM64_REG_V0; - } else if (registers[i] >= ARM64_REG_Z0) { - base = ARM64_REG_Z0; - } else if (registers[i] >= ARM64_REG_X0) { - base = ARM64_REG_X0; + aarch64_reg base = (aarch64_reg)0; + if (registers[i] >= AARCH64_REG_V0) { + base = AARCH64_REG_V0; + } else if (registers[i] >= AARCH64_REG_Z0) { + base = AARCH64_REG_Z0; + } else if (registers[i] >= AARCH64_REG_X0) { + base = AARCH64_REG_X0; isGP[i] = true; - } else if (registers[i] >= ARM64_REG_W0) { - base = ARM64_REG_W0; + } else if (registers[i] >= AARCH64_REG_W0) { + base = AARCH64_REG_W0; isGP[i] = true; - } else if (registers[i] >= ARM64_REG_S0) { - base = ARM64_REG_S0; - } else if (registers[i] >= ARM64_REG_Q0) { - base = ARM64_REG_Q0; - } else if (registers[i] >= ARM64_REG_P0) { - base = ARM64_REG_P0; - } else if (registers[i] >= ARM64_REG_H0) { - base = ARM64_REG_H0; - } else if (registers[i] >= ARM64_REG_D0) { - base = ARM64_REG_D0; - } else if (registers[i] >= ARM64_REG_B0) { - base = ARM64_REG_B0; + } else if (registers[i] >= AARCH64_REG_S0) { + base = AARCH64_REG_S0; + } else if (registers[i] >= AARCH64_REG_Q0) { + base = AARCH64_REG_Q0; + } else if (registers[i] >= AARCH64_REG_P0) { + base = AARCH64_REG_P0; + } else if (registers[i] >= AARCH64_REG_H0) { + base = AARCH64_REG_H0; + } else if (registers[i] >= AARCH64_REG_D0) { + base = AARCH64_REG_D0; + } else if (registers[i] >= AARCH64_REG_B0) { + base = AARCH64_REG_B0; } indexes[i] = registers[i] - base; } @@ -105,23 +105,25 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop 0 cacheVector.push_back(createLdrUop( architecture, metadata.operands[0].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // ldr uop 1 cacheVector.push_back(createLdrUop( architecture, metadata.operands[1].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, dataSize}, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, dataSize}, capstoneHandle, true, 2, dataSize)); // ldr uop 2 - cacheVector.push_back(createLdrUop( - architecture, metadata.operands[2].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, 2 * dataSize}, - capstoneHandle, true, 2, dataSize)); + cacheVector.push_back( + createLdrUop(architecture, metadata.operands[2].reg, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, + 2 * dataSize}, + capstoneHandle, true, 2, dataSize)); // ldr uop 3 - cacheVector.push_back(createLdrUop( - architecture, metadata.operands[3].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, 3 * dataSize}, - capstoneHandle, true, 2, dataSize)); + cacheVector.push_back( + createLdrUop(architecture, metadata.operands[3].reg, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, + 3 * dataSize}, + capstoneHandle, true, 2, dataSize)); iter = microDecodeCache_.try_emplace(word, cacheVector).first; break; @@ -134,25 +136,27 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop 0 cacheVector.push_back(createLdrUop( architecture, metadata.operands[0].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // ldr uop 1 cacheVector.push_back(createLdrUop( architecture, metadata.operands[1].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, dataSize}, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, dataSize}, capstoneHandle, true, 2, dataSize)); // ldr uop 2 - cacheVector.push_back(createLdrUop( - architecture, metadata.operands[2].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, 2 * dataSize}, - capstoneHandle, true, 2, dataSize)); + cacheVector.push_back( + createLdrUop(architecture, metadata.operands[2].reg, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, + 2 * dataSize}, + capstoneHandle, true, 2, dataSize)); // ldr uop 3 - cacheVector.push_back(createLdrUop( - architecture, metadata.operands[3].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, 3 * dataSize}, - capstoneHandle, true, 2, dataSize)); + cacheVector.push_back( + createLdrUop(architecture, metadata.operands[3].reg, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, + 3 * dataSize}, + capstoneHandle, true, 2, dataSize)); // offset generation uop - if (metadata.operands[5].type == ARM64_OP_REG) { + if (metadata.operands[5].type == AARCH64_OP_REG) { cacheVector.push_back(createRegOffsetUop( architecture, metadata.operands[4].mem.base, metadata.operands[5].reg, capstoneHandle, true)); @@ -173,25 +177,27 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop 0 cacheVector.push_back(createLdrUop( architecture, metadata.operands[0].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // ldr uop 1 cacheVector.push_back(createLdrUop( architecture, metadata.operands[1].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, dataSize}, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, dataSize}, capstoneHandle, true, 2, dataSize)); // ldr uop 2 - cacheVector.push_back(createLdrUop( - architecture, metadata.operands[2].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, 2 * dataSize}, - capstoneHandle, true, 2, dataSize)); + cacheVector.push_back( + createLdrUop(architecture, metadata.operands[2].reg, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, + 2 * dataSize}, + capstoneHandle, true, 2, dataSize)); // ldr uop 3 - cacheVector.push_back(createLdrUop( - architecture, metadata.operands[3].reg, - {metadata.operands[4].mem.base, ARM64_REG_INVALID, 3 * dataSize}, - capstoneHandle, true, 2, dataSize)); + cacheVector.push_back( + createLdrUop(architecture, metadata.operands[3].reg, + {metadata.operands[4].mem.base, AARCH64_REG_INVALID, + 3 * dataSize}, + capstoneHandle, true, 2, dataSize)); // offset generation uop - if (metadata.operands[5].type == ARM64_OP_REG) { + if (metadata.operands[5].type == AARCH64_OP_REG) { cacheVector.push_back(createRegOffsetUop( architecture, metadata.operands[4].mem.base, metadata.operands[5].reg, capstoneHandle, true)); @@ -216,12 +222,12 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop 0 cacheVector.push_back(createLdrUop( architecture, metadata.operands[0].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // ldr uop 1 cacheVector.push_back(createLdrUop( architecture, metadata.operands[1].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, dataSize}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, dataSize}, capstoneHandle, true, 2, dataSize)); iter = microDecodeCache_.try_emplace(word, cacheVector).first; @@ -235,15 +241,15 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop 0 cacheVector.push_back(createLdrUop( architecture, metadata.operands[0].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // ldr uop 1 cacheVector.push_back(createLdrUop( architecture, metadata.operands[1].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, dataSize}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, dataSize}, capstoneHandle, true, 2, dataSize)); // offset generation uop - if (metadata.operands[3].type == ARM64_OP_REG) { + if (metadata.operands[3].type == AARCH64_OP_REG) { cacheVector.push_back(createRegOffsetUop( architecture, metadata.operands[2].mem.base, metadata.operands[3].reg, capstoneHandle, true)); @@ -264,15 +270,15 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop 0 cacheVector.push_back(createLdrUop( architecture, metadata.operands[0].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // ldr uop 1 cacheVector.push_back(createLdrUop( architecture, metadata.operands[1].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, dataSize}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, dataSize}, capstoneHandle, true, 2, dataSize)); // offset generation uop - if (metadata.operands[3].type == ARM64_OP_REG) { + if (metadata.operands[3].type == AARCH64_OP_REG) { cacheVector.push_back(createRegOffsetUop( architecture, metadata.operands[2].mem.base, metadata.operands[3].reg, capstoneHandle, true)); @@ -305,13 +311,13 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop 0 cacheVector.push_back(createLdrUop( architecture, metadata.operands[orderA].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, metadata.operands[2].mem.disp + (orderA * dataSize)}, capstoneHandle, false, 1, dataSize)); // ldr uop 1 cacheVector.push_back(createLdrUop( architecture, metadata.operands[orderB].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, metadata.operands[2].mem.disp + (orderB * dataSize)}, capstoneHandle, true, 2, dataSize)); @@ -329,12 +335,12 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop 0 cacheVector.push_back(createLdrUop( architecture, metadata.operands[0].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // ldr uop 1 cacheVector.push_back(createLdrUop( architecture, metadata.operands[1].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, dataSize}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, dataSize}, capstoneHandle, false, 2, dataSize)); // offset generation uop cacheVector.push_back(createImmOffsetUop( @@ -358,12 +364,12 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop 0 cacheVector.push_back(createLdrUop( architecture, metadata.operands[0].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // ldr uop 1 cacheVector.push_back(createLdrUop( architecture, metadata.operands[1].reg, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, dataSize}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, dataSize}, capstoneHandle, true, 2, dataSize)); iter = microDecodeCache_.try_emplace(word, cacheVector).first; @@ -382,7 +388,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop cacheVector.push_back(createLdrUop( architecture, metadata.operands[0].reg, - {metadata.operands[1].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[1].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // offset generation uop cacheVector.push_back(createImmOffsetUop( @@ -409,7 +415,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // ldr uop cacheVector.push_back(createLdrUop( architecture, metadata.operands[0].reg, - {metadata.operands[1].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[1].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, true, 1, dataSize)); iter = microDecodeCache_.try_emplace(word, cacheVector).first; @@ -428,7 +434,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // store0 address uop cacheVector.push_back( createStrUop(architecture, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, metadata.operands[2].mem.disp}, capstoneHandle, false, 1, dataSize)); // store0 data uop @@ -438,7 +444,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // store1 address uop cacheVector.push_back( createStrUop(architecture, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, metadata.operands[2].mem.disp + dataSize}, capstoneHandle, false, 2, dataSize)); // store1 data uop @@ -461,7 +467,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // store0 address uop cacheVector.push_back(createStrUop( architecture, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // store0 data uop cacheVector.push_back(createSDUop(architecture, @@ -470,7 +476,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // store1 address uop cacheVector.push_back(createStrUop( architecture, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, dataSize}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, dataSize}, capstoneHandle, false, 2, dataSize)); // store1 data uop cacheVector.push_back(createSDUop(architecture, @@ -501,7 +507,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // store0 address uop cacheVector.push_back(createStrUop( architecture, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // store0 data uop cacheVector.push_back(createSDUop(architecture, @@ -510,7 +516,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // store1 address uop cacheVector.push_back(createStrUop( architecture, - {metadata.operands[2].mem.base, ARM64_REG_INVALID, dataSize}, + {metadata.operands[2].mem.base, AARCH64_REG_INVALID, dataSize}, capstoneHandle, false, 2, dataSize)); // store1 data uop cacheVector.push_back(createSDUop( @@ -534,7 +540,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // store address uop cacheVector.push_back(createStrUop( architecture, - {metadata.operands[1].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[1].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // store data uop cacheVector.push_back(createSDUop(architecture, @@ -567,7 +573,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // store address uop cacheVector.push_back(createStrUop( architecture, - {metadata.operands[1].mem.base, ARM64_REG_INVALID, 0}, + {metadata.operands[1].mem.base, AARCH64_REG_INVALID, 0}, capstoneHandle, false, 1, dataSize)); // store data uop cacheVector.push_back(createSDUop( @@ -591,7 +597,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, // store address uop cacheVector.push_back( createStrUop(architecture, - {metadata.operands[1].mem.base, ARM64_REG_INVALID, + {metadata.operands[1].mem.base, AARCH64_REG_INVALID, metadata.operands[1].mem.disp}, capstoneHandle, false, 1, dataSize)); // store data uop @@ -629,35 +635,57 @@ cs_detail MicroDecoder::createDefaultDetail(std::vector opTypes) { for (size_t op = 0; op < opTypes.size(); op++) { info.operands[op] = default_op; switch (opTypes[op].type) { - case arm64_op_type::ARM64_OP_REG: { - info.operands[op].type = ARM64_OP_REG; - info.operands[op].reg = ARM64_REG_INVALID; + case aarch64_op_type::AARCH64_OP_REG: { + info.operands[op].type = AARCH64_OP_REG; + info.operands[op].reg = AARCH64_REG_INVALID; if (opTypes[op].isDestination) { info.operands[op].access = CS_AC_WRITE; } break; } - case arm64_op_type::ARM64_OP_IMM: { - info.operands[op].type = ARM64_OP_IMM; + case aarch64_op_type::AARCH64_OP_IMM: { + info.operands[op].type = AARCH64_OP_IMM; info.operands[op].imm = 0; break; } - case arm64_op_type::ARM64_OP_MEM: { - info.operands[op].type = ARM64_OP_MEM; - info.operands[op].mem = {ARM64_REG_INVALID, ARM64_REG_INVALID, 0}; + case aarch64_op_type::AARCH64_OP_MEM: { + info.operands[op].type = AARCH64_OP_MEM; + info.operands[op].mem = {AARCH64_REG_INVALID, AARCH64_REG_INVALID, 0}; break; } - case arm64_op_type::ARM64_OP_INVALID: - case arm64_op_type::ARM64_OP_FP: - case arm64_op_type::ARM64_OP_CIMM: - case arm64_op_type::ARM64_OP_REG_MRS: - case arm64_op_type::ARM64_OP_REG_MSR: - case arm64_op_type::ARM64_OP_PSTATE: - case arm64_op_type::ARM64_OP_SYS: - case arm64_op_type::ARM64_OP_SVCR: - case arm64_op_type::ARM64_OP_PREFETCH: - case arm64_op_type::ARM64_OP_BARRIER: - case arm64_op_type::ARM64_OP_SME_INDEX: + case aarch64_op_type::AARCH64_OP_INVALID: + case aarch64_op_type::AARCH64_OP_MEM_REG: + case aarch64_op_type::AARCH64_OP_MEM_IMM: + case aarch64_op_type::AARCH64_OP_FP: + case aarch64_op_type::AARCH64_OP_CIMM: + case aarch64_op_type::AARCH64_OP_REG_MRS: + case aarch64_op_type::AARCH64_OP_REG_MSR: + case aarch64_op_type::AARCH64_OP_IMPLICIT_IMM_0: + case aarch64_op_type::AARCH64_OP_SVCR: + case aarch64_op_type::AARCH64_OP_AT: + case aarch64_op_type::AARCH64_OP_DB: + case aarch64_op_type::AARCH64_OP_DC: + case aarch64_op_type::AARCH64_OP_ISB: + case aarch64_op_type::AARCH64_OP_TSB: + case aarch64_op_type::AARCH64_OP_PRFM: + case aarch64_op_type::AARCH64_OP_SVEPRFM: + case aarch64_op_type::AARCH64_OP_RPRFM: + case aarch64_op_type::AARCH64_OP_PSTATEIMM0_15: + case aarch64_op_type::AARCH64_OP_PSTATEIMM0_1: + case aarch64_op_type::AARCH64_OP_PSB: + case aarch64_op_type::AARCH64_OP_BTI: + case aarch64_op_type::AARCH64_OP_SVEPREDPAT: + case aarch64_op_type::AARCH64_OP_SVEVECLENSPECIFIER: + case aarch64_op_type::AARCH64_OP_SME: + case aarch64_op_type::AARCH64_OP_IMM_RANGE: + case aarch64_op_type::AARCH64_OP_TLBI: + case aarch64_op_type::AARCH64_OP_IC: + case aarch64_op_type::AARCH64_OP_DBNXS: + case aarch64_op_type::AARCH64_OP_EXACTFPIMM: + case aarch64_op_type::AARCH64_OP_SYSREG: + case aarch64_op_type::AARCH64_OP_SYSIMM: + case aarch64_op_type::AARCH64_OP_SYSALIAS: + case aarch64_op_type::AARCH64_OP_PRED: break; } } @@ -666,12 +694,12 @@ cs_detail MicroDecoder::createDefaultDetail(std::vector opTypes) { } Instruction MicroDecoder::createImmOffsetUop(const Architecture& architecture, - arm64_reg base, int64_t offset, + aarch64_reg base, int64_t offset, csh capstoneHandle, bool lastMicroOp, int microOpIndex) { - cs_detail off_imm_detail = - createDefaultDetail({{ARM64_OP_REG, 1}, {ARM64_OP_REG}, {ARM64_OP_IMM}}); + cs_detail off_imm_detail = createDefaultDetail( + {{AARCH64_OP_REG, 1}, {AARCH64_OP_REG}, {AARCH64_OP_IMM}}); off_imm_detail.arm64.operands[0].reg = base; off_imm_detail.arm64.operands[1].reg = base; off_imm_detail.arm64.operands[2].imm = offset; @@ -694,13 +722,11 @@ Instruction MicroDecoder::createImmOffsetUop(const Architecture& architecture, return off_imm; } -Instruction MicroDecoder::createRegOffsetUop(const Architecture& architecture, - arm64_reg base, arm64_reg offset, - csh capstoneHandle, - bool lastMicroOp, - int microOpIndex) { - cs_detail off_reg_detail = - createDefaultDetail({{ARM64_OP_REG, 1}, {ARM64_OP_REG}, {ARM64_OP_REG}}); +Instruction MicroDecoder::createRegOffsetUop( + const Architecture& architecture, aarch64_reg base, aarch64_reg offset, + csh capstoneHandle, bool lastMicroOp, int microOpIndex) { + cs_detail off_reg_detail = createDefaultDetail( + {{AARCH64_OP_REG, 1}, {AARCH64_OP_REG}, {AARCH64_OP_REG}}); off_reg_detail.arm64.operands[0].reg = base; off_reg_detail.arm64.operands[1].reg = base; off_reg_detail.arm64.operands[2].reg = offset; @@ -724,11 +750,11 @@ Instruction MicroDecoder::createRegOffsetUop(const Architecture& architecture, } Instruction MicroDecoder::createLdrUop(const Architecture& architecture, - arm64_reg dest, arm64_op_mem mem, + aarch64_reg dest, aarch64_op_mem mem, csh capstoneHandle, bool lastMicroOp, int microOpIndex, uint8_t dataSize) { cs_detail ldr_detail = - createDefaultDetail({{ARM64_OP_REG, 1}, {ARM64_OP_MEM}}); + createDefaultDetail({{AARCH64_OP_REG, 1}, {AARCH64_OP_MEM}}); ldr_detail.arm64.operands[0].reg = dest; ldr_detail.arm64.operands[1].mem = mem; cs_insn ldr_cs = { @@ -744,9 +770,9 @@ Instruction MicroDecoder::createLdrUop(const Architecture& architecture, } Instruction MicroDecoder::createSDUop(const Architecture& architecture, - arm64_reg src, csh capstoneHandle, + aarch64_reg src, csh capstoneHandle, bool lastMicroOp, int microOpIndex) { - cs_detail sd_detail = createDefaultDetail({{ARM64_OP_REG}}); + cs_detail sd_detail = createDefaultDetail({{AARCH64_OP_REG}}); sd_detail.arm64.operands[0].reg = src; cs_insn sd_cs = { arm64_insn::ARM64_INS_STR, 0x0, 4, "", "micro_sd", "", &sd_detail, @@ -761,10 +787,10 @@ Instruction MicroDecoder::createSDUop(const Architecture& architecture, } Instruction MicroDecoder::createStrUop(const Architecture& architecture, - arm64_op_mem mem, csh capstoneHandle, + aarch64_op_mem mem, csh capstoneHandle, bool lastMicroOp, int microOpIndex, uint8_t dataSize) { - cs_detail str_detail = createDefaultDetail({{ARM64_OP_MEM}}); + cs_detail str_detail = createDefaultDetail({{AARCH64_OP_MEM}}); str_detail.arm64.operands[0].mem = mem; cs_insn str_cs = { arm64_insn::ARM64_INS_STR, 0x0, 4, "", "micro_str", "", &str_detail, From e0fe83a2a5582d5a3eb79eb00836bb638abd1e89 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Tue, 3 Sep 2024 11:14:57 +0200 Subject: [PATCH 03/34] Continued with Capstone update in SimEng. --- src/include/simeng/arch/aarch64/ArchInfo.hh | 3 +- .../simeng/arch/aarch64/Instruction.hh | 2 + .../simeng/arch/aarch64/MicroDecoder.hh | 13 +- .../aarch64/helpers/auxiliaryFunctions.hh | 32 +- .../simeng/arch/aarch64/helpers/sve.hh | 3 +- .../simeng/arch/aarch64/operandContainer.hh | 2 +- src/lib/arch/aarch64/Architecture.cc | 9 +- src/lib/arch/aarch64/ExceptionHandler.cc | 24 +- src/lib/arch/aarch64/InstructionMetadata.cc | 5105 +++++++++-------- src/lib/arch/aarch64/InstructionMetadata.hh | 2 +- src/lib/arch/aarch64/Instruction_address.cc | 42 +- src/lib/arch/aarch64/Instruction_decode.cc | 324 +- src/lib/arch/aarch64/Instruction_execute.cc | 176 +- src/lib/arch/aarch64/MicroDecoder.cc | 81 +- src/lib/config/ModelConfig.cc | 2 +- 15 files changed, 2929 insertions(+), 2891 deletions(-) diff --git a/src/include/simeng/arch/aarch64/ArchInfo.hh b/src/include/simeng/arch/aarch64/ArchInfo.hh index 971c958eda..40743f3ea2 100644 --- a/src/include/simeng/arch/aarch64/ArchInfo.hh +++ b/src/include/simeng/arch/aarch64/ArchInfo.hh @@ -27,7 +27,8 @@ class ArchInfo : public simeng::arch::ArchInfo { {32, 17}, // Predicate {1, 1}, // NZCV {8, static_cast(sysRegisterEnums_.size())}, // System - {256, zaSize_} // Matrix (Each row is a register) + {256, zaSize_}, // Matrix (Each row is a register) + {64, 1} // SME ZT0 table register (fixed width of 512-bit) }; // Generate the config-defined physical register structure and quantities diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index a4f8fa3c43..c926efe20e 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -38,6 +38,8 @@ const uint8_t NZCV = 3; const uint8_t SYSTEM = 4; /** The [256-byte x (SVL / 8)] SME matrix register za. */ const uint8_t MATRIX = 5; +/** The fixed width (512-bit) SME ZT0 table register. */ +const uint8_t TABLE = 6; /** A special register value representing the zero register. */ const Register ZERO_REGISTER = {GENERAL, (uint16_t)-1}; diff --git a/src/include/simeng/arch/aarch64/MicroDecoder.hh b/src/include/simeng/arch/aarch64/MicroDecoder.hh index f7e72097fd..18865167f1 100644 --- a/src/include/simeng/arch/aarch64/MicroDecoder.hh +++ b/src/include/simeng/arch/aarch64/MicroDecoder.hh @@ -84,17 +84,18 @@ class MicroDecoder { // Default objects /** Default capstone instruction structure. */ - cs_arm64 default_info = {ARM64_CC_INVALID, false, false, 0, {}}; + cs_aarch64 default_info = {AArch64CC_Invalid, false, false, 0, {}}; /** Default register. */ cs_aarch64_op default_op = {0, - ARM64_VAS_INVALID, - {ARM64_SFT_INVALID, 0}, - ARM64_EXT_INVALID, + AARCH64LAYOUT_INVALID, + {AARCH64_SFT_INVALID, 0}, + AARCH64_EXT_INVALID, AARCH64_OP_INVALID, - ARM64_SVCR_INVALID, + false, {}, - CS_AC_READ}; + CS_AC_READ, + false}; /** Default capstone instruction detail. */ cs_detail default_detail = {{}, 0, {}, 0, {}, 0, {}}; diff --git a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh index f4f8b94d0f..459ad4dc93 100644 --- a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh +++ b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh @@ -164,7 +164,7 @@ inline bool conditionHolds(uint8_t cond, uint8_t nzcv) { /** Extend `value` according to `extendType`, and left-shift the result by * `shift`. Replicated from Instruction.cc */ inline uint64_t extendValue(uint64_t value, uint8_t extendType, uint8_t shift) { - if (extendType == ARM64_EXT_INVALID && shift == 0) { + if (extendType == AARCH64_EXT_INVALID && shift == 0) { // Special case: an invalid shift type with a shift amount of 0 implies an // identity operation return value; @@ -172,28 +172,28 @@ inline uint64_t extendValue(uint64_t value, uint8_t extendType, uint8_t shift) { uint64_t extended; switch (extendType) { - case ARM64_EXT_UXTB: + case AARCH64_EXT_UXTB: extended = static_cast(value); break; - case ARM64_EXT_UXTH: + case AARCH64_EXT_UXTH: extended = static_cast(value); break; - case ARM64_EXT_UXTW: + case AARCH64_EXT_UXTW: extended = static_cast(value); break; - case ARM64_EXT_UXTX: + case AARCH64_EXT_UXTX: extended = value; break; - case ARM64_EXT_SXTB: + case AARCH64_EXT_SXTB: extended = static_cast(value); break; - case ARM64_EXT_SXTH: + case AARCH64_EXT_SXTH: extended = static_cast(value); break; - case ARM64_EXT_SXTW: + case AARCH64_EXT_SXTW: extended = static_cast(value); break; - case ARM64_EXT_SXTX: + case AARCH64_EXT_SXTX: extended = value; break; default: @@ -211,7 +211,7 @@ inline uint64_t extendOffset(uint64_t value, const cs_aarch64_op& op) { return value; } if (op.shift.type == 1) { - return extendValue(value, ARM64_EXT_UXTX, op.shift.value); + return extendValue(value, AARCH64_EXT_UXTX, op.shift.value); } } return extendValue(value, op.ext, op.shift.value); @@ -327,25 +327,25 @@ template inline std::enable_if_t && std::is_unsigned_v, T> shiftValue(T value, uint8_t shiftType, uint8_t amount) { switch (shiftType) { - case ARM64_SFT_LSL: + case AARCH64_SFT_LSL: return value << amount; - case ARM64_SFT_LSR: + case AARCH64_SFT_LSR: return value >> amount; - case ARM64_SFT_ASR: + case AARCH64_SFT_ASR: return static_cast>(value) >> amount; - case ARM64_SFT_ROR: { + case AARCH64_SFT_ROR: { // Assuming sizeof(T) is a power of 2. const T mask = sizeof(T) * 8 - 1; assert((amount <= mask) && "Rotate amount exceeds type width"); amount &= mask; return (value >> amount) | (value << ((-amount) & mask)); } - case ARM64_SFT_MSL: { + case AARCH64_SFT_MSL: { // pad in with ones instead of zeros const T mask = (static_cast(1) << static_cast(amount)) - 1; return (value << amount) | mask; } - case ARM64_SFT_INVALID: + case AARCH64_SFT_INVALID: return value; default: assert(false && "Unknown shift type"); diff --git a/src/include/simeng/arch/aarch64/helpers/sve.hh b/src/include/simeng/arch/aarch64/helpers/sve.hh index 076a2f29c1..dc3b2dca21 100644 --- a/src/include/simeng/arch/aarch64/helpers/sve.hh +++ b/src/include/simeng/arch/aarch64/helpers/sve.hh @@ -1276,7 +1276,8 @@ std::array svePsel( const uint64_t* pn = sourceValues[0].getAsVector(); const uint64_t* pm = sourceValues[1].getAsVector(); const uint32_t wa = sourceValues[2].get(); - const uint32_t imm = metadata.operands[2].sme_index.disp; + const uint32_t imm = + static_cast(metadata.operands[2].pred.imm_index); const uint16_t partition_num = VL_bits / (sizeof(T) * 8); diff --git a/src/include/simeng/arch/aarch64/operandContainer.hh b/src/include/simeng/arch/aarch64/operandContainer.hh index 802c5466d4..c73b8881da 100644 --- a/src/include/simeng/arch/aarch64/operandContainer.hh +++ b/src/include/simeng/arch/aarch64/operandContainer.hh @@ -18,7 +18,7 @@ const uint8_t MAX_DESTINATION_REGISTERS = 5; /** The maximum number of source/destination operands an SME instruction can * have in addition to any ZA operands. */ -const uint8_t ADDITIONAL_SME_REGISTERS = 8; +const uint8_t ADDITIONAL_SME_REGISTERS = 11; /** Simple class to allow AArch64 instructions to use std::array for operands in * most cases, but for SME instructions a std::vector can be utilised to allow diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index e27ea8f0f9..0515c91eef 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -14,13 +14,14 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) SVL_(config["Core"]["Streaming-Vector-Length"].as()), vctModulo_((config["Core"]["Clock-Frequency-GHz"].as() * 1e9) / (config["Core"]["Timer-Frequency-MHz"].as() * 1e6)) { - if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &capstoneHandle_) != CS_ERR_OK) { + if (cs_open(CS_ARCH_AARCH64, CS_MODE_ARM, &capstoneHandle_) != CS_ERR_OK) { std::cerr << "[SimEng:Architecture] Could not create capstone handle" << std::endl; exit(1); } cs_option(capstoneHandle_, CS_OPT_DETAIL, CS_OPT_ON); + cs_option(capstoneHandle_, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL); // Generate zero-indexed system register map std::vector sysRegs = config::SimInfo::getSysRegVec(); @@ -31,10 +32,10 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) // Get Virtual Counter Timer and Processor Cycle Counter system registers. VCTreg_ = { RegisterType::SYSTEM, - static_cast(getSystemRegisterTag(ARM64_SYSREG_CNTVCT_EL0))}; + static_cast(getSystemRegisterTag(AARCH64_SYSREG_CNTVCT_EL0))}; PCCreg_ = { RegisterType::SYSTEM, - static_cast(getSystemRegisterTag(ARM64_SYSREG_PMCCNTR_EL0))}; + static_cast(getSystemRegisterTag(AARCH64_SYSREG_PMCCNTR_EL0))}; // Instantiate an ExecutionInfo entry for each group in the // InstructionGroup namespace. @@ -231,7 +232,7 @@ ProcessStateChange Architecture::getInitialState() const { // but is disabled due to bit 4 being set changes.modifiedRegisters.push_back( {RegisterType::SYSTEM, - static_cast(getSystemRegisterTag(ARM64_SYSREG_DCZID_EL0))}); + static_cast(getSystemRegisterTag(AARCH64_SYSREG_DCZID_EL0))}); changes.modifiedRegisterValues.push_back(static_cast(0b10100)); return changes; diff --git a/src/lib/arch/aarch64/ExceptionHandler.cc b/src/lib/arch/aarch64/ExceptionHandler.cc index 36aff03781..983e8accb7 100644 --- a/src/lib/arch/aarch64/ExceptionHandler.cc +++ b/src/lib/arch/aarch64/ExceptionHandler.cc @@ -656,10 +656,22 @@ bool ExceptionHandler::init() { // Check if exception was called by AArch64_MSR (msr systemreg, xt) or // AArch64_MSRpstatesvcrImm1 (msr svcr, #imm) if (metadata.opcode == Opcode::AArch64_MSR) { + // Enusre operand metadata is as expected + assert(metadata.operands[0].type == AARCH64_OP_SYSALIAS); + assert(metadata.operands[0].sysop.sub_type == AARCH64_OP_SVCR); newSVCR = instruction_.getSourceOperands()[0].get(); } else if (metadata.opcode == Opcode::AArch64_MSRpstatesvcrImm1) { + // Enusre operand metadata is as expected + assert(metadata.operands[0].type == AARCH64_OP_SYSALIAS); + assert(metadata.operands[0].sysop.sub_type == AARCH64_OP_SVCR); + // extract SVCR bits const uint64_t svcrBits = - static_cast(metadata.operands[0].svcr); + static_cast(metadata.operands[0].sysop.alias.svcr); + // Ensure SVCR Bits are valid + assert(svcrBits == AARCH64_SVCR_SVCRSM || + svcrBits == AARCH64_SVCR_SVCRZA || + svcrBits == AARCH64_SVCR_SVCRSMZA); + const uint64_t imm = metadata.operands[1].imm; assert((imm == 0 || imm == 1) && "[SimEng:ExceptionHandler] SVCR Instruction invalid - Imm value " @@ -682,7 +694,7 @@ bool ExceptionHandler::init() { // If SVCR.ZA has changed state then zero out ZA register, else don't if (exception != InstructionException::StreamingModeUpdate) { - if ((newSVCR & ARM64_SVCR_SVCRZA) != (currSVCR & ARM64_SVCR_SVCRZA)) { + if ((newSVCR & AARCH64_SVCR_SVCRZA) != (currSVCR & AARCH64_SVCR_SVCRZA)) { for (uint16_t i = 0; i < regFileStruct[RegisterType::MATRIX].quantity; i++) { regs.push_back({RegisterType::MATRIX, i}); @@ -693,7 +705,7 @@ bool ExceptionHandler::init() { // If SVCR.SM has changed state then zero out SVE, NEON, Predicate // registers, else don't if (exception != InstructionException::ZAregisterStatusUpdate) { - if ((newSVCR & ARM64_SVCR_SVCRSM) != (currSVCR & ARM64_SVCR_SVCRSM)) { + if ((newSVCR & AARCH64_SVCR_SVCRSM) != (currSVCR & AARCH64_SVCR_SVCRSM)) { for (uint16_t i = 0; i < regFileStruct[RegisterType::VECTOR].quantity; i++) { regs.push_back({RegisterType::VECTOR, i}); @@ -707,9 +719,9 @@ bool ExceptionHandler::init() { } // Update SVCR system register in regFile - regs.push_back( - {RegisterType::SYSTEM, - static_cast(arch.getSystemRegisterTag(ARM64_SYSREG_SVCR))}); + regs.push_back({RegisterType::SYSTEM, + static_cast( + arch.getSystemRegisterTag(AARCH64_SYSREG_SVCR))}); regValues.push_back(RegisterValue(newSVCR, 8)); ProcessStateChange stateChange = {ChangeType::REPLACEMENT, regs, regValues}; diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index 350c4be592..7b7594ff73 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -13,10 +13,10 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) implicitSourceCount(insn.detail->regs_read_count), implicitDestinationCount(insn.detail->regs_write_count), groupCount(insn.detail->groups_count), - cc(insn.detail->arm64.cc - 1), - setsFlags(insn.detail->arm64.update_flags), - writeback(insn.detail->arm64.writeback), - operandCount(insn.detail->arm64.op_count) { + cc(insn.detail->aarch64.cc - 1), + setsFlags(insn.detail->aarch64.update_flags), + writeback(insn.detail->writeback), + operandCount(insn.detail->aarch64.op_count) { std::memcpy(encoding, insn.bytes, sizeof(encoding)); // Copy printed output std::strncpy(mnemonic, insn.mnemonic, CS_MNEMONIC_SIZE); @@ -28,1736 +28,1741 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) std::memcpy(implicitDestinations, insn.detail->regs_write, sizeof(uint16_t) * implicitDestinationCount); std::memcpy(groups, insn.detail->groups, sizeof(uint8_t) * groupCount); - std::memcpy(operands, insn.detail->arm64.operands, + std::memcpy(operands, insn.detail->aarch64.operands, sizeof(cs_aarch64_op) * operandCount); - // Fix some inaccuracies in the decoded metadata - switch (opcode) { - case Opcode::AArch64_ADR_LSL_ZZZ_D_0: - [[fallthrough]]; - case Opcode::AArch64_ADR_LSL_ZZZ_D_1: - [[fallthrough]]; - case Opcode::AArch64_ADR_LSL_ZZZ_D_2: - [[fallthrough]]; - case Opcode::AArch64_ADR_LSL_ZZZ_D_3: - [[fallthrough]]; - case Opcode::AArch64_ADR_LSL_ZZZ_S_0: - [[fallthrough]]; - case Opcode::AArch64_ADR_LSL_ZZZ_S_1: - [[fallthrough]]; - case Opcode::AArch64_ADR_LSL_ZZZ_S_2: - [[fallthrough]]; - case Opcode::AArch64_ADR_LSL_ZZZ_S_3: { - // No defined access types - operandCount = 3; - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[2].type = AARCH64_OP_REG; - break; - } - case Opcode::AArch64_SMIN_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_EOR_ZPmZ_B: - [[fallthrough]]; - case Opcode::AArch64_EOR_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_EOR_ZPmZ_H: - [[fallthrough]]; - case Opcode::AArch64_EOR_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_AND_ZPmZ_B: - [[fallthrough]]; - case Opcode::AArch64_AND_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_AND_ZPmZ_H: - [[fallthrough]]; - case Opcode::AArch64_AND_ZPmZ_S: - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - break; - case Opcode::AArch64_BICv4i32: - // BIC incorrectly flags destination as WRITE only - operands[0].access = CS_AC_WRITE | CS_AC_READ; - break; - case Opcode::AArch64_ADDSWri: - // adds incorrectly flags destination as READ - operands[0].access = CS_AC_WRITE; - break; - case Opcode::AArch64_BICv8i16: - operands[0].access = CS_AC_WRITE | CS_AC_READ; - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_BICv8i8: - // access specifier for last operand was missing - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_CASALW: - [[fallthrough]]; - case Opcode::AArch64_CASALX: - operandCount = 3; - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_CBNZW: - [[fallthrough]]; - case Opcode::AArch64_CBNZX: - [[fallthrough]]; - case Opcode::AArch64_CBZW: - [[fallthrough]]; - case Opcode::AArch64_CBZX: - // incorrectly adds implicit nzcv dependency - implicitSourceCount = 0; - break; - case Opcode::AArch64_CMPHI_PPzZZ_B: - [[fallthrough]]; - case Opcode::AArch64_CMPHI_PPzZZ_D: - [[fallthrough]]; - case Opcode::AArch64_CMPHI_PPzZZ_H: - [[fallthrough]]; - case Opcode::AArch64_CMPHI_PPzZZ_S: - [[fallthrough]]; - case Opcode::AArch64_CMPGT_PPzZZ_B: - [[fallthrough]]; - case Opcode::AArch64_CMPGT_PPzZZ_D: - [[fallthrough]]; - case Opcode::AArch64_CMPGT_PPzZZ_H: - [[fallthrough]]; - case Opcode::AArch64_CMPGT_PPzZZ_S: - [[fallthrough]]; - case Opcode::AArch64_CMPEQ_PPzZI_B: - [[fallthrough]]; - case Opcode::AArch64_CMPEQ_PPzZI_D: - [[fallthrough]]; - case Opcode::AArch64_CMPEQ_PPzZI_H: - [[fallthrough]]; - case Opcode::AArch64_CMPEQ_PPzZI_S: - [[fallthrough]]; - case Opcode::AArch64_CMPEQ_PPzZZ_B: - [[fallthrough]]; - case Opcode::AArch64_CMPEQ_PPzZZ_D: - [[fallthrough]]; - case Opcode::AArch64_CMPEQ_PPzZZ_H: - [[fallthrough]]; - case Opcode::AArch64_CMPEQ_PPzZZ_S: - [[fallthrough]]; - case Opcode::AArch64_CMPNE_PPzZZ_B: - [[fallthrough]]; - case Opcode::AArch64_CMPNE_PPzZZ_D: - [[fallthrough]]; - case Opcode::AArch64_CMPNE_PPzZZ_H: - [[fallthrough]]; - case Opcode::AArch64_CMPNE_PPzZZ_S: - [[fallthrough]]; - case Opcode::AArch64_CMPNE_PPzZI_B: - [[fallthrough]]; - case Opcode::AArch64_CMPNE_PPzZI_D: - [[fallthrough]]; - case Opcode::AArch64_CMPNE_PPzZI_H: - [[fallthrough]]; - case Opcode::AArch64_CMPNE_PPzZI_S: - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - // Doesn't identify implicit NZCV destination - implicitDestinationCount = 1; - implicitDestinations[0] = AARCH64_REG_NZCV; - break; - case Opcode::AArch64_CNTB_XPiI: - [[fallthrough]]; - case Opcode::AArch64_CNTH_XPiI: - [[fallthrough]]; - case Opcode::AArch64_CNTD_XPiI: - [[fallthrough]]; - case Opcode::AArch64_CNTW_XPiI: { - // lacking access specifiers for destination - operands[0].access = CS_AC_WRITE; - if (operandStr.length() < 4) { - operandCount = 2; - operands[1].type = AARCH64_OP_IMM; - operands[1].imm = 1; - operands[1].access = CS_AC_READ; - operands[1].shift = {ARM64_SFT_INVALID, 0}; - operands[1].ext = ARM64_EXT_INVALID; - operands[1].vector_index = -1; - } - break; - } - case Opcode::AArch64_ADD_ZI_B: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZI_D: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZI_H: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZI_S: { - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[2].type = AARCH64_OP_IMM; - operandCount = 3; - - // Extract immediate in SVE add with immediate instruction - size_t start = operandStr.find("#"); - // Identify whether the immediate value is in base-10 or base-16 - if (start != std::string::npos) { - start++; - bool hex = false; - if (operandStr[start + 1] == 'x') { - hex = true; - start += 2; - } - - uint8_t end = operandStr.size(); - size_t shifted = operandStr.find("LSL"); - if (shifted != std::string::npos) { - std::cerr << "[SimEng:arch] SVE add with immediate has shift value " - "in operandStr which is unsupported." - << std::endl; - exit(1); - } - // Convert extracted immediate from string to int64_t - std::string sub = operandStr.substr(start, end); - if (hex) { - operands[2].imm = std::stoul(sub, 0, 16); - } else { - operands[2].imm = stoi(sub); - } - } else { - operands[2].imm = 0; - } - break; - } - case Opcode::AArch64_AND_ZI: { - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[2].type = AARCH64_OP_IMM; - operandCount = 3; - - char specifier = operandStr[operandStr.find(".") + 1]; - switch (specifier) { - case 'b': { - uint8_t mask = static_cast(operands[2].imm); - operands[2].imm = static_cast(0); - for (int i = 0; i < 8; i++) - operands[2].imm |= (static_cast(mask) << (i * 8)); - break; - } - case 'h': { - uint16_t mask = static_cast(operands[2].imm); - operands[2].imm = static_cast(0); - for (int i = 0; i < 4; i++) - operands[2].imm |= (static_cast(mask) << (i * 16)); - break; - } - case 's': { - uint32_t mask = static_cast(operands[2].imm); - operands[2].imm = static_cast(0); - for (int i = 0; i < 2; i++) - operands[2].imm |= (static_cast(mask) << (i * 32)); - break; - } - default: - break; - } - break; - } - case Opcode::AArch64_CNTP_XPP_B: - [[fallthrough]]; - case Opcode::AArch64_CNTP_XPP_D: - [[fallthrough]]; - case Opcode::AArch64_CNTP_XPP_H: - [[fallthrough]]; - case Opcode::AArch64_CNTP_XPP_S: - [[fallthrough]]; - case Opcode::AArch64_EOR_ZZZ: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_DECD_XPiI: - [[fallthrough]]; - case Opcode::AArch64_DECB_XPiI: { - // lacking access specifiers for destination - operands[0].access = CS_AC_READ | CS_AC_WRITE; - std::string str(operandStr); - if (str.length() < 4) { - operandCount = 2; - operands[1].type = AARCH64_OP_IMM; - operands[1].imm = 1; - operands[1].access = CS_AC_READ; - operands[1].shift = {ARM64_SFT_INVALID, 0}; - operands[1].ext = ARM64_EXT_INVALID; - operands[1].vector_index = -1; - } - break; - } - case Opcode::AArch64_EOR_PPzPP: { - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - break; - } - case Opcode::AArch64_FMOVXDHighr: - // FMOVXDHighr incorrectly flags destination as only WRITE - operands[0].access = CS_AC_READ | CS_AC_WRITE; - break; - case Opcode::AArch64_FNMSB_ZPmZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FNMSB_ZPmZZ_S: - [[fallthrough]]; - case Opcode::AArch64_FNMLS_ZPmZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FNMLS_ZPmZZ_S: - [[fallthrough]]; - case Opcode::AArch64_FMAD_ZPmZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FMAD_ZPmZZ_S: - [[fallthrough]]; - case Opcode::AArch64_FMLA_ZPmZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FMLA_ZPmZZ_S: - [[fallthrough]]; - case Opcode::AArch64_FMLS_ZPmZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FMLS_ZPmZZ_S: - [[fallthrough]]; - case Opcode::AArch64_FMSB_ZPmZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FMSB_ZPmZZ_S: - [[fallthrough]]; - case Opcode::AArch64_MLA_ZPmZZ_B: - [[fallthrough]]; - case Opcode::AArch64_MLA_ZPmZZ_D: - [[fallthrough]]; - case Opcode::AArch64_MLA_ZPmZZ_H: - [[fallthrough]]; - case Opcode::AArch64_MLA_ZPmZZ_S: - [[fallthrough]]; - case Opcode::AArch64_SMAX_ZPmZ_S: - // No defined access types - operands[0].access = CS_AC_READ | CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - break; - case Opcode::AArch64_ADDPL_XXI: - [[fallthrough]]; - case Opcode::AArch64_ADDVL_XXI: - [[fallthrough]]; - case Opcode::AArch64_UADDV_VPZ_B: - [[fallthrough]]; - case Opcode::AArch64_UADDV_VPZ_D: - [[fallthrough]]; - case Opcode::AArch64_UADDV_VPZ_H: - [[fallthrough]]; - case Opcode::AArch64_UADDV_VPZ_S: - [[fallthrough]]; - case Opcode::AArch64_MOVPRFX_ZPzZ_D: - [[fallthrough]]; - case Opcode::AArch64_MOVPRFX_ZPzZ_S: - [[fallthrough]]; - case Opcode::AArch64_SUB_ZZZ_B: - [[fallthrough]]; - case Opcode::AArch64_SUB_ZZZ_H: - [[fallthrough]]; - case Opcode::AArch64_SUB_ZZZ_S: - [[fallthrough]]; - case Opcode::AArch64_SUB_ZZZ_D: - [[fallthrough]]; - case Opcode::AArch64_INDEX_II_B: - [[fallthrough]]; - case Opcode::AArch64_INDEX_II_H: - [[fallthrough]]; - case Opcode::AArch64_INDEX_II_S: - [[fallthrough]]; - case Opcode::AArch64_INDEX_II_D: - [[fallthrough]]; - case Opcode::AArch64_INDEX_IR_B: - [[fallthrough]]; - case Opcode::AArch64_INDEX_IR_D: - [[fallthrough]]; - case Opcode::AArch64_INDEX_IR_H: - [[fallthrough]]; - case Opcode::AArch64_INDEX_IR_S: - [[fallthrough]]; - case Opcode::AArch64_INDEX_RI_B: - [[fallthrough]]; - case Opcode::AArch64_INDEX_RI_D: - [[fallthrough]]; - case Opcode::AArch64_INDEX_RI_H: - [[fallthrough]]; - case Opcode::AArch64_INDEX_RI_S: - [[fallthrough]]; - case Opcode::AArch64_INDEX_RR_B: - [[fallthrough]]; - case Opcode::AArch64_INDEX_RR_D: - [[fallthrough]]; - case Opcode::AArch64_INDEX_RR_H: - [[fallthrough]]; - case Opcode::AArch64_INDEX_RR_S: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZZZ_B: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZZZ_D: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZZZ_H: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZZZ_S: - [[fallthrough]]; - case Opcode::AArch64_FADD_ZZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FADD_ZZZ_S: - [[fallthrough]]; - case Opcode::AArch64_FSUB_ZZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FSUB_ZZZ_S: - [[fallthrough]]; - case Opcode::AArch64_FMUL_ZZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FMUL_ZZZ_S: - [[fallthrough]]; - case Opcode::AArch64_SMAX_ZI_S: - [[fallthrough]]; - case Opcode::AArch64_SMINV_VPZ_S: - [[fallthrough]]; - case Opcode::AArch64_TRN1_ZZZ_B: - [[fallthrough]]; - case Opcode::AArch64_TRN1_ZZZ_D: - [[fallthrough]]; - case Opcode::AArch64_TRN1_ZZZ_H: - [[fallthrough]]; - case Opcode::AArch64_TRN1_ZZZ_S: - [[fallthrough]]; - case Opcode::AArch64_TRN2_ZZZ_B: - [[fallthrough]]; - case Opcode::AArch64_TRN2_ZZZ_D: - [[fallthrough]]; - case Opcode::AArch64_TRN2_ZZZ_H: - [[fallthrough]]; - case Opcode::AArch64_TRN2_ZZZ_S: - [[fallthrough]]; - case Opcode::AArch64_UZP1_ZZZ_S: - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_MOVPRFX_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FCPY_ZPmI_D: - [[fallthrough]]; - case Opcode::AArch64_FCPY_ZPmI_S: - [[fallthrough]]; - case Opcode::AArch64_FNEG_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FNEG_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_FRINTN_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FRINTN_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_FABS_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FABS_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_FSQRT_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_FSQRT_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FCVTZS_ZPmZ_DtoD: - [[fallthrough]]; - case Opcode::AArch64_FCVTZS_ZPmZ_StoD: - [[fallthrough]]; - case Opcode::AArch64_FCVTZS_ZPmZ_StoS: - [[fallthrough]]; - case Opcode::AArch64_FCVTZS_ZPmZ_DtoS: - // No defined access types - operands[0].access = CS_AC_READ | CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_FMUL_ZPmI_D: - [[fallthrough]]; - case Opcode::AArch64_FMUL_ZPmI_S: { - // No defined access types - operandCount = 4; - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].type = AARCH64_OP_FP; - operands[3].access = CS_AC_READ; - // Doesn't recognise immediate operands - // Extract two possible values, 0.5 or 2.0 - if (operandStr.substr(operandStr.length() - 1, 1) == "5") { - operands[3].fp = 0.5f; - } else { - operands[3].fp = 2.0f; - } - - break; - } - case Opcode::AArch64_FCMLA_ZPmZZ_D: { - // No defined access types - operands[0].access = CS_AC_READ | CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - operands[4].access = CS_AC_READ; - operands[4].type = AARCH64_OP_IMM; - break; - } - case Opcode::AArch64_FCADD_ZPmZ_D: { - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - operands[4].access = CS_AC_READ; - operands[4].type = AARCH64_OP_IMM; - break; - } - case Opcode::AArch64_FSUB_ZPmI_D: - [[fallthrough]]; - case Opcode::AArch64_FSUB_ZPmI_S: - [[fallthrough]]; - case Opcode::AArch64_FADD_ZPmI_D: - [[fallthrough]]; - case Opcode::AArch64_FADD_ZPmI_S: - // No defined access types - operandCount = 4; - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].type = AARCH64_OP_FP; - operands[3].access = CS_AC_READ; - // Doesn't recognise immediate operands - // Extract two possible values, 0.5 or 1.0 - if (operandStr.substr(operandStr.length() - 1, 1) == "5") { - operands[3].fp = 0.5f; - } else { - operands[3].fp = 1.0f; - } - break; - case Opcode::AArch64_FCMGT_PPzZ0_D: - [[fallthrough]]; - case Opcode::AArch64_FCMGT_PPzZ0_S: { - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - } - case Opcode::AArch64_FMLA_ZZZI_D: - [[fallthrough]]; - case Opcode::AArch64_FMLA_ZZZI_S: { - // Need to define missing access types - operands[0].access = CS_AC_READ | CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - } - case Opcode::AArch64_FDIVR_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FDIVR_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_FDIV_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_AND_PPzPP: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZPmZ_B: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZPmZ_H: - [[fallthrough]]; - case Opcode::AArch64_ADD_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_FADD_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FADD_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_FCMGE_PPzZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FCMGE_PPzZZ_S: - [[fallthrough]]; - case Opcode::AArch64_FCMGE_PPzZ0_D: - [[fallthrough]]; - case Opcode::AArch64_FCMGE_PPzZ0_S: - [[fallthrough]]; - case Opcode::AArch64_FCMGT_PPzZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FCMGT_PPzZZ_S: - [[fallthrough]]; - case Opcode::AArch64_FCMLE_PPzZ0_D: - [[fallthrough]]; - case Opcode::AArch64_FCMLE_PPzZ0_S: - [[fallthrough]]; - case Opcode::AArch64_FCMLT_PPzZ0_S: - [[fallthrough]]; - case Opcode::AArch64_FMUL_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FMUL_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_FSUBR_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FSUBR_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_FSUB_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FSUB_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_FADDA_VPZ_S: - [[fallthrough]]; - case Opcode::AArch64_MUL_ZPmZ_B: - [[fallthrough]]; - case Opcode::AArch64_MUL_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_MUL_ZPmZ_H: - [[fallthrough]]; - case Opcode::AArch64_MUL_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_ORR_PPzPP: - [[fallthrough]]; - case Opcode::AArch64_SMULH_ZPmZ_B: - [[fallthrough]]; - case Opcode::AArch64_SMULH_ZPmZ_H: - [[fallthrough]]; - case Opcode::AArch64_SMULH_ZPmZ_S: - [[fallthrough]]; - case Opcode::AArch64_SEL_ZPZZ_D: - [[fallthrough]]; - case Opcode::AArch64_SEL_ZPZZ_S: - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - break; - case Opcode::AArch64_FRINTPDr: - [[fallthrough]]; - case Opcode::AArch64_FRINTPSr: - [[fallthrough]]; - case Opcode::AArch64_FDUP_ZI_D: - [[fallthrough]]; - case Opcode::AArch64_FDUP_ZI_S: - [[fallthrough]]; - case Opcode::AArch64_PUNPKHI_PP: - [[fallthrough]]; - case Opcode::AArch64_PUNPKLO_PP: - [[fallthrough]]; - case Opcode::AArch64_RDVLI_XI: - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_INCB_XPiI: - [[fallthrough]]; - case Opcode::AArch64_INCD_XPiI: - [[fallthrough]]; - case Opcode::AArch64_INCH_XPiI: - [[fallthrough]]; - case Opcode::AArch64_INCW_XPiI: { - // lacking access specifiers for destination - operands[0].access = CS_AC_READ | CS_AC_WRITE; - if (operandStr.length() < 4) { - operandCount = 2; - operands[1].type = AARCH64_OP_IMM; - operands[1].imm = 1; - operands[1].access = CS_AC_READ; - operands[1].shift = {ARM64_SFT_INVALID, 0}; - operands[1].ext = ARM64_EXT_INVALID; - operands[1].vector_index = -1; - } - break; - } - case Opcode::AArch64_INCD_ZPiI: - [[fallthrough]]; - case Opcode::AArch64_INCH_ZPiI: - [[fallthrough]]; - case Opcode::AArch64_INCW_ZPiI: { - // lacking access specifiers for destination - operands[0].access = CS_AC_READ | CS_AC_WRITE; - if (operandStr.length() < 6) { - operandCount = 2; - operands[1].type = AARCH64_OP_IMM; - operands[1].imm = 1; - operands[1].access = CS_AC_READ; - operands[1].shift = {ARM64_SFT_INVALID, 0}; - operands[1].ext = ARM64_EXT_INVALID; - operands[1].vector_index = -1; - } - break; - } - case Opcode::AArch64_INCP_XP_B: - [[fallthrough]]; - case Opcode::AArch64_INCP_XP_D: - [[fallthrough]]; - case Opcode::AArch64_INCP_XP_H: - [[fallthrough]]; - case Opcode::AArch64_INCP_XP_S: - operands[0].access = CS_AC_READ | CS_AC_WRITE; - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_LD1i32: - [[fallthrough]]; - case Opcode::AArch64_LD1i64: - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_GLD1W_D_SCALED_REAL: - [[fallthrough]]; - case Opcode::AArch64_GLD1W_SXTW_REAL: { - // Access types are not set correctly - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - } - case Opcode::AArch64_GLD1D_SCALED_REAL: - [[fallthrough]]; - case Opcode::AArch64_GLD1D_REAL: { - // LD1D gather instruction doesn't correctly identify destination - // register - uint16_t reg_enum = AARCH64_REG_Z0; - // Single or double digit Z register identifier - if (operandStr[3] == '.') { - reg_enum += std::stoi(operandStr.substr(2, 1)); - } else { - reg_enum += std::stoi(operandStr.substr(2, 2)); - } - operands[0].reg = static_cast(reg_enum); - - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - // LD1D gather instruction doesn't correctly identify memory operands - operands[2].type = AARCH64_OP_MEM; - operands[2].access = CS_AC_READ; - - // LD1D doesn't correctly identify vector memory register correctly - uint16_t vec_enum = AARCH64_REG_Z0; - std::string tmp_str(operandStr.substr(operandStr.find("["))); - // Single or double digit Z register identifier - if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { - vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); - } else { - vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); - } - operands[2].mem.index = static_cast(vec_enum); - break; - } - case Opcode::AArch64_LD1RQ_W: - [[fallthrough]]; - case Opcode::AArch64_LD1RQ_W_IMM: { - // LD1RQW doesn't identify correct access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - break; - } - case Opcode::AArch64_LD1RQ_D_IMM: { - // LD1RQ gather instruction doesn't correctly identify destination - // register - uint16_t reg_enum = AARCH64_REG_Z0; - // Single or double digit Z register identifier - if (operandStr[3] == '.') { - reg_enum += std::stoi(operandStr.substr(2, 1)); - } else { - reg_enum += std::stoi(operandStr.substr(2, 2)); - } - operands[0].reg = static_cast(reg_enum); - - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - // LD1RQ gather instruction doesn't correctly identify memory operands - operands[2].type = AARCH64_OP_MEM; - operands[2].access = CS_AC_READ; - break; - } - case Opcode::AArch64_GLD1SW_D_IMM_REAL: - [[fallthrough]]; - case Opcode::AArch64_GLD1D_IMM_REAL: { - // LD1D gather instruction doesn't correctly identify destination - // register - uint16_t reg_enum = AARCH64_REG_Z0; - // Single or double digit Z register identifier - if (operandStr[3] == '.') { - reg_enum += std::stoi(operandStr.substr(2, 1)); - } else { - reg_enum += std::stoi(operandStr.substr(2, 2)); - } - - operands[0].reg = static_cast(reg_enum); - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - // LD1D gather instruction doesn't correctly identify second Z reg as - // memory operand - operands[2].type = AARCH64_OP_MEM; - operands[2].access = CS_AC_READ; - // LD1D gather instruction doesn't recognise memory-offset immediate - // correctly - if (operandStr[operandStr.length() - 3] != '.') { - int64_t startPos = operandStr.find('#') + 1; - int64_t immSize = (operandStr.length() - 1) - startPos; - if (immSize == 1) { - operands[2].mem.disp = - std::stoi(operandStr.substr(startPos, immSize)); - } else { - // double or triple digit immediates are converted to hex, and so - // require a different conversion to uint - operands[2].mem.disp = - std::stoul(operandStr.substr(startPos, immSize), nullptr, 16); - } - } - break; - } - case Opcode::AArch64_LD1B: - [[fallthrough]]; - case Opcode::AArch64_LD1D: - [[fallthrough]]; - case Opcode::AArch64_LD1B_IMM_REAL: - [[fallthrough]]; - case Opcode::AArch64_LD1D_IMM_REAL: - [[fallthrough]]; - case Opcode::AArch64_LD1RD_IMM: - [[fallthrough]]; - case Opcode::AArch64_LD1RW_IMM: - [[fallthrough]]; - case Opcode::AArch64_LD1H: - [[fallthrough]]; - case Opcode::AArch64_LD1W: - [[fallthrough]]; - case Opcode::AArch64_LD1W_IMM_REAL: { - // LD1RW doesn't correctly identify destination register - uint16_t reg_enum = AARCH64_REG_Z0; - // Single or double digit Z register identifier - if (operandStr[3] == '.') { - reg_enum += std::stoi(operandStr.substr(2, 1)); - } else { - reg_enum += std::stoi(operandStr.substr(2, 2)); - } - - operands[0].reg = static_cast(reg_enum); - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - } - case Opcode::AArch64_LD1Rv4s: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv1d: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv2d: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv2s: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv8b: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv16b: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv8h: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv4h: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_LD1Rv4h_POST: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv8h_POST: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ | CS_AC_WRITE; - // Fix for exclusion of post_index immediate in disassembly - operandCount = 3; - operands[2].type = AARCH64_OP_IMM; - operands[2].access = CS_AC_READ; - // For vector arrangement of 16-bit, post_index immediate is 2 - operands[2].imm = 2; - break; - case Opcode::AArch64_LD1Rv1d_POST: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv2d_POST: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ | CS_AC_WRITE; - // Fix for exclusion of post_index immediate in disassembly - operandCount = 3; - operands[2].type = AARCH64_OP_IMM; - operands[2].access = CS_AC_READ; - // For vector arrangement of 64-bit, post_index immediate is 8 - operands[2].imm = 8; - break; - case Opcode::AArch64_LD1Rv16b_POST: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv8b_POST: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ | CS_AC_WRITE; - - // Fix for exclusion of post_index immediate in disassembly - operandCount = 3; - operands[2].type = AARCH64_OP_IMM; - operands[2].access = CS_AC_READ; - // For vector arrangement of 8-bit, post_index immediate is 1 - operands[2].imm = 1; - break; - case Opcode::AArch64_LD1Rv2s_POST: - [[fallthrough]]; - case Opcode::AArch64_LD1Rv4s_POST: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ | CS_AC_WRITE; - - // Fix for exclusion of post_index immediate in disassembly - operandCount = 3; - operands[2].type = AARCH64_OP_IMM; - operands[2].access = CS_AC_READ; - // For vector arrangement of 32-bit, post_index immediate is 4 - operands[2].imm = 4; - break; - case Opcode::AArch64_LD1Fourv16b: - [[fallthrough]]; - case Opcode::AArch64_LD1Fourv4s: - [[fallthrough]]; - case Opcode::AArch64_LD1Fourv2d: - // Fix incorrect access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_WRITE; - operands[2].access = CS_AC_WRITE; - operands[3].access = CS_AC_WRITE; - operands[4].access = CS_AC_READ; - break; - case Opcode::AArch64_LD1Fourv16b_POST: - [[fallthrough]]; - case Opcode::AArch64_LD1Fourv2d_POST: - [[fallthrough]]; - case Opcode::AArch64_LD1Fourv4s_POST: - // Fix incorrect access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_WRITE; - operands[2].access = CS_AC_WRITE; - operands[3].access = CS_AC_WRITE; - operands[4].access = CS_AC_READ | CS_AC_WRITE; - operands[5].access = CS_AC_READ; - break; - case Opcode::AArch64_LD1Onev16b: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_LD1Onev16b_POST: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ | CS_AC_WRITE; - break; - case Opcode::AArch64_LD1Twov16b: - [[fallthrough]]; - case Opcode::AArch64_LD1Twov4s: - [[fallthrough]]; - case Opcode::AArch64_LD1Twov2d: - // Fix incorrect access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_WRITE; - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_LD1Twov16b_POST: - [[fallthrough]]; - case Opcode::AArch64_LD1Twov2d_POST: - [[fallthrough]]; - case Opcode::AArch64_LD1Twov4s_POST: - // Fix incorrect access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_WRITE; - operands[2].access = CS_AC_READ | CS_AC_WRITE; - operands[3].access = CS_AC_READ; - break; - case Opcode::AArch64_LDADDLW: - [[fallthrough]]; - case Opcode::AArch64_LDADDW: - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_WRITE; - break; - case Opcode::AArch64_LD2Twov4s_POST: - // Fixing wrong access flag for offset register operand - if (operandCount == 4) { - operands[3].access = CS_AC_READ; - } - break; - case Opcode::AArch64_LDR_PXI: - [[fallthrough]]; - case Opcode::AArch64_LDR_ZXI: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_LSL_ZZI_S: - // No defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - // No instruction id assigned - id = ARM64_INS_LSL; - break; - case Opcode::AArch64_LD2D: - case Opcode::AArch64_LD2D_IMM: { - // LD2D doesn't correctly identify destination registers - uint16_t reg_enum0 = AARCH64_REG_Z0; - uint16_t reg_enum1 = AARCH64_REG_Z0; - - // tmpOpStr = "zxx.d, zyy.d" - std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); - // get dest0, then remove from string - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - tmpOpStr.erase(0, 6); - } else { - reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - tmpOpStr.erase(0, 7); - } - // get dest1, then remove from string - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - } else { - reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - } - - operands[0].reg = static_cast(reg_enum0); - operands[0].access = CS_AC_WRITE; - operands[1].reg = static_cast(reg_enum1); - operands[1].access = CS_AC_WRITE; - - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - break; - } - case Opcode::AArch64_LD3D_IMM: { - // LD3D doesn't correctly identify destination registers - uint16_t reg_enum0 = AARCH64_REG_Z0; - uint16_t reg_enum1 = AARCH64_REG_Z0; - uint16_t reg_enum2 = AARCH64_REG_Z0; - - // tmpOpStr = "zxx.d, zyy.d, znn.d" - std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); - // get dest0, then remove from string - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - tmpOpStr.erase(0, 6); - } else { - reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - tmpOpStr.erase(0, 7); - } - // get dest1, then remove from string - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - tmpOpStr.erase(0, 6); - } else { - reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - tmpOpStr.erase(0, 7); - } - // get dest2 - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); - } else { - reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); - } - - operands[0].reg = static_cast(reg_enum0); - operands[0].access = CS_AC_WRITE; - operands[1].reg = static_cast(reg_enum1); - operands[1].access = CS_AC_WRITE; - operands[2].reg = static_cast(reg_enum2); - operands[2].access = CS_AC_WRITE; - - operands[3].access = CS_AC_READ; - operands[4].access = CS_AC_READ; - break; - } - case Opcode::AArch64_LD4D_IMM: { - // LD4D doesn't correctly identify destination registers - uint16_t reg_enum0 = AARCH64_REG_Z0; - uint16_t reg_enum1 = AARCH64_REG_Z0; - uint16_t reg_enum2 = AARCH64_REG_Z0; - uint16_t reg_enum3 = AARCH64_REG_Z0; - - // tmpOpStr = "zxx.d, zyy.d, znn.d, zmm.d" - std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); - // get dest0, then remove from string - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - tmpOpStr.erase(0, 6); - } else { - reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - tmpOpStr.erase(0, 7); - } - // get dest1, then remove from string - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - tmpOpStr.erase(0, 6); - } else { - reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - tmpOpStr.erase(0, 7); - } - // get dest2 - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); - tmpOpStr.erase(0, 6); - } else { - reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); - tmpOpStr.erase(0, 7); - } - // get dest3 - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum3 += std::stoi(tmpOpStr.substr(1, 1)); - } else { - reg_enum3 += std::stoi(tmpOpStr.substr(1, 2)); - } - - operands[0].reg = static_cast(reg_enum0); - operands[0].access = CS_AC_WRITE; - operands[1].reg = static_cast(reg_enum1); - operands[1].access = CS_AC_WRITE; - operands[2].reg = static_cast(reg_enum2); - operands[2].access = CS_AC_WRITE; - operands[3].reg = static_cast(reg_enum3); - operands[3].access = CS_AC_WRITE; - - operands[4].access = CS_AC_READ; - operands[5].access = CS_AC_READ; - break; - } - case Opcode::AArch64_MOVNWi: - [[fallthrough]]; - case Opcode::AArch64_MOVNXi: - [[fallthrough]]; - case Opcode::AArch64_MOVZWi: - [[fallthrough]]; - case Opcode::AArch64_MOVZXi: - // MOVZ incorrectly flags destination as READ | WRITE - operands[0].access = CS_AC_WRITE; - break; - case Opcode::AArch64_MOVPRFX_ZZ: - // Assign operand access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_MRS: - // MRS incorrectly flags source/destination as READ | WRITE - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - // MRS incorrectly tags AARCH64_OP_REG_MRS as AARCH64_OP_SYS - operands[1].type = AARCH64_OP_REG_MRS; - break; - case Opcode::AArch64_MSR: - // MSR incorrectly flags source/destination as READ | WRITE - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - // MSR incorrectly tags AARCH64_OP_REG_MSR as AARCH64_OP_SYS - operands[0].type = AARCH64_OP_REG_MSR; - break; - case Opcode::AArch64_PTEST_PP: { - // PTEST doesn't label access types for operands - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - // Doesn't identify implicit NZCV destination - implicitDestinationCount = 1; - implicitDestinations[0] = AARCH64_REG_NZCV; - break; - } - case Opcode::AArch64_PTRUE_B: - [[fallthrough]]; - case Opcode::AArch64_PTRUE_H: - [[fallthrough]]; - case Opcode::AArch64_PTRUE_D: - [[fallthrough]]; - case Opcode::AArch64_PTRUE_S: - // PTRUE doesn't label access - operands[0].access = CS_AC_WRITE; - break; - case Opcode::AArch64_RET: - // If no register supplied to RET, default to x30 (LR) - if (operandCount == 0) { - operandCount = 1; - operands[0].type = AARCH64_OP_REG; - operands[0].reg = AARCH64_REG_LR; - operands[0].access = CS_AC_READ; - } - groupCount = 1; - groups[0] = CS_GRP_JUMP; - break; - case Opcode::AArch64_REV_ZZ_B: - [[fallthrough]]; - case Opcode::AArch64_REV_ZZ_D: - [[fallthrough]]; - case Opcode::AArch64_REV_ZZ_H: - [[fallthrough]]; - case Opcode::AArch64_REV_ZZ_S: - [[fallthrough]]; - case Opcode::AArch64_REV_PP_B: - [[fallthrough]]; - case Opcode::AArch64_REV_PP_D: - [[fallthrough]]; - case Opcode::AArch64_REV_PP_H: - [[fallthrough]]; - case Opcode::AArch64_REV_PP_S: { - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - break; - } - case Opcode::AArch64_SST1B_D_REAL: - [[fallthrough]]; - case Opcode::AArch64_SST1D_REAL: - [[fallthrough]]; - case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { - // ST1W doesn't correctly identify first source register - uint16_t reg_enum = AARCH64_REG_Z0; - // Single or double digit Z register identifier - if (operandStr[3] == '.') { - reg_enum += std::stoi(operandStr.substr(2, 1)); - } else { - reg_enum += std::stoi(operandStr.substr(2, 2)); - } - - operands[0].reg = static_cast(reg_enum); - // No defined access types - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - // SST1D{_SCALED} gather instruction doesn't correctly identify memory - // operands - operands[2].type = AARCH64_OP_MEM; - operands[2].access = CS_AC_READ; - - // ST1D doesn't correctly identify vector memory register correctly - uint16_t vec_enum = AARCH64_REG_Z0; - std::string tmp_str(operandStr.substr(operandStr.find("["))); - // Single or double digit Z register identifier - if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { - vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); - } else { - vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); - } - operands[2].mem.index = static_cast(vec_enum); - break; - } - case Opcode::AArch64_ST2D_IMM: { - // ST2D doesn't correctly identify destination registers - uint16_t reg_enum0 = AARCH64_REG_Z0; - uint16_t reg_enum1 = AARCH64_REG_Z0; - - // tmpOpStr = "zxx.d, zyy.d" - std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); - // get dest0, then remove from string - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - tmpOpStr.erase(0, 6); - } else { - reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - tmpOpStr.erase(0, 7); - } - // get dest1, then remove from string - // Single or double digit Z register identifier - if (tmpOpStr[2] == '.') { - reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - tmpOpStr.erase(0, 6); - } else { - reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - tmpOpStr.erase(0, 7); - } - - operands[0].reg = static_cast(reg_enum0); - operands[0].access = CS_AC_READ; - operands[1].reg = static_cast(reg_enum1); - operands[1].access = CS_AC_READ; - - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - break; - } - case Opcode::AArch64_ST1B: - [[fallthrough]]; - case Opcode::AArch64_ST1D: - [[fallthrough]]; - case Opcode::AArch64_ST1B_IMM: - [[fallthrough]]; - case Opcode::AArch64_ST1D_IMM: - [[fallthrough]]; - case Opcode::AArch64_ST1W_IMM: { - // ST1W doesn't correctly identify first source register - uint16_t reg_enum = AARCH64_REG_Z0; - // Single or double digit Z register identifier - if (operandStr[3] == '.') { - reg_enum += std::stoi(operandStr.substr(2, 1)); - } else { - reg_enum += std::stoi(operandStr.substr(2, 2)); - } - - operands[0].reg = static_cast(reg_enum); - // No defined access types - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - } - case Opcode::AArch64_ST1W: - [[fallthrough]]; - case Opcode::AArch64_ST1W_D: { - // ST1W doesn't correctly identify first source register - uint16_t reg_enum = AARCH64_REG_Z0; - // Single or double digit Z register identifier - if (operandStr[3] == '.') { - reg_enum += std::stoi(operandStr.substr(2, 1)); - } else { - reg_enum += std::stoi(operandStr.substr(2, 2)); - } - - operands[0].reg = static_cast(reg_enum); - // No defined access types - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - break; - } - case Opcode::AArch64_SST1D_IMM: - [[fallthrough]]; - case Opcode::AArch64_SST1W_D_IMM: - [[fallthrough]]; - case Opcode::AArch64_SST1W_IMM: { - // ST1W scatter instruction doesn't correctly identify first source - // register - uint16_t reg_enum = AARCH64_REG_Z0; - // Single or double digit Z register identifier - if (operandStr[3] == '.') { - reg_enum += std::stoi(operandStr.substr(2, 1)); - } else { - reg_enum += std::stoi(operandStr.substr(2, 2)); - } - - operands[0].reg = static_cast(reg_enum); - // No defined access types - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - // ST1W scatter instruction doesn't correctly identify second Z reg as - // memory operand - operands[2].type = AARCH64_OP_MEM; - operands[2].access = CS_AC_READ; - // ST1W scatter instruction doesn't recognise memory-offset immediate - // correctly - if (operandStr[operandStr.length() - 3] != '.') { - int64_t startPos = operandStr.find('#') + 1; - int64_t immSize = (operandStr.length() - 1) - startPos; - if (immSize == 1) { - operands[2].mem.disp = - std::stoi(operandStr.substr(startPos, immSize)); - } else { - // double or triple digit immediates are converted to hex, and so - // require a different conversion to uint - operands[2].mem.disp = - std::stoul(operandStr.substr(startPos, immSize), nullptr, 16); - } - } - break; - } - case Opcode::AArch64_ST1i8_POST: - [[fallthrough]]; - case Opcode::AArch64_ST1i16_POST: - [[fallthrough]]; - case Opcode::AArch64_ST1i32_POST: - [[fallthrough]]; - case Opcode::AArch64_ST1i64_POST: - // fixing incorrect access type for register offset - if (operandCount == 3) { - operands[2].access = CS_AC_READ; - } - break; - case Opcode::AArch64_ST1Fourv16b: - [[fallthrough]]; - case Opcode::AArch64_ST1Fourv2d: - [[fallthrough]]; - case Opcode::AArch64_ST1Fourv4s: - // ST1 incorrectly flags read and write - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - operands[4].access = CS_AC_READ; - break; - case Opcode::AArch64_ST1Fourv16b_POST: - [[fallthrough]]; - case Opcode::AArch64_ST1Fourv2d_POST: - [[fallthrough]]; - case Opcode::AArch64_ST1Fourv2s_POST: - [[fallthrough]]; - case Opcode::AArch64_ST1Fourv4s_POST: - // ST1 incorrectly flags read and write - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - operands[4].access = CS_AC_READ | CS_AC_WRITE; - operands[5].access = CS_AC_READ; - // determine correct type for operand 5 - if (operandStr.find("#") != std::string::npos) { - operands[5].type = AARCH64_OP_IMM; - } else { - operands[5].type = AARCH64_OP_REG; - } - break; - case Opcode::AArch64_ST1Twov16b: - [[fallthrough]]; - case Opcode::AArch64_ST1Twov2d: - [[fallthrough]]; - case Opcode::AArch64_ST1Twov4s: - // ST1 incorrectly flags read and write - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_ST1Twov16b_POST: - [[fallthrough]]; - case Opcode::AArch64_ST1Twov2d_POST: - [[fallthrough]]; - case Opcode::AArch64_ST1Twov4s_POST: - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ | CS_AC_WRITE; - operands[3].access = CS_AC_READ; - // determine correct type for operand 3 - if (operandStr.find("#") != std::string::npos) { - operands[3].type = AARCH64_OP_IMM; - } else { - operands[3].type = AARCH64_OP_REG; - } - break; - case Opcode::AArch64_ST2Twov4s_POST: - // ST2 post incorrectly flags read and write - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ | CS_AC_WRITE; - // Another incorrect access flag for register offset operand - if (operandCount == 4) { - operands[3].access = CS_AC_READ; - } - break; - case Opcode::AArch64_STRBui: - [[fallthrough]]; - case Opcode::AArch64_STRDui: - [[fallthrough]]; - case Opcode::AArch64_STRHui: - [[fallthrough]]; - case Opcode::AArch64_STRQui: - [[fallthrough]]; - case Opcode::AArch64_STRSui: - [[fallthrough]]; - case Opcode::AArch64_STRWui: - [[fallthrough]]; - case Opcode::AArch64_STRXui: - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_PFALSE: - operands[0].access = CS_AC_WRITE; - break; - case Opcode::AArch64_STR_PXI: - [[fallthrough]]; - case Opcode::AArch64_STR_ZXI: - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_SBFMWri: - [[fallthrough]]; - case Opcode::AArch64_SBFMXri: - // SBFM incorrectly flags destination as READ | WRITE - operands[0].access = CS_AC_WRITE; - break; - case Opcode::AArch64_SVC: - // SVC is incorrectly marked as setting x30 - implicitDestinationCount = 0; - break; - case Opcode::AArch64_SYSxt: - // No defined metadata.id for SYS instructions - id = ARM64_INS_SYS; - break; - case Opcode::AArch64_PSEL_PPPRI_B: - [[fallthrough]]; - case Opcode::AArch64_PSEL_PPPRI_D: - [[fallthrough]]; - case Opcode::AArch64_PSEL_PPPRI_H: - [[fallthrough]]; - case Opcode::AArch64_PSEL_PPPRI_S: - // Add correct access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_UBFMWri: - [[fallthrough]]; - case Opcode::AArch64_UBFMXri: - // UBFM incorrectly flags destination as READ | WRITE - operands[0].access = CS_AC_WRITE; - break; - case Opcode::AArch64_UQDECB_WPiI: - [[fallthrough]]; - case Opcode::AArch64_UQDECB_XPiI: - [[fallthrough]]; - case Opcode::AArch64_UQDECD_WPiI: - [[fallthrough]]; - case Opcode::AArch64_UQDECD_XPiI: - [[fallthrough]]; - case Opcode::AArch64_UQDECH_WPiI: - [[fallthrough]]; - case Opcode::AArch64_UQDECH_XPiI: - [[fallthrough]]; - case Opcode::AArch64_UQDECW_WPiI: - [[fallthrough]]; - case Opcode::AArch64_UQDECW_XPiI: - // UQDEC lacks access types - operands[0].access = CS_AC_READ | CS_AC_WRITE; - if (operandCount == 1) { - operandCount = 2; - operands[1].type = AARCH64_OP_IMM; - operands[1].imm = 1; - } - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_UUNPKHI_ZZ_D: - [[fallthrough]]; - case Opcode::AArch64_UUNPKHI_ZZ_H: - [[fallthrough]]; - case Opcode::AArch64_UUNPKHI_ZZ_S: - [[fallthrough]]; - case Opcode::AArch64_UUNPKLO_ZZ_D: - [[fallthrough]]; - case Opcode::AArch64_UUNPKLO_ZZ_H: - [[fallthrough]]; - case Opcode::AArch64_UUNPKLO_ZZ_S: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_WHILELT_PXX_B: - [[fallthrough]]; - case Opcode::AArch64_WHILELT_PXX_D: - [[fallthrough]]; - case Opcode::AArch64_WHILELT_PXX_H: - [[fallthrough]]; - case Opcode::AArch64_WHILELT_PXX_S: - [[fallthrough]]; - case Opcode::AArch64_WHILELO_PWW_B: - [[fallthrough]]; - case Opcode::AArch64_WHILELO_PWW_D: - [[fallthrough]]; - case Opcode::AArch64_WHILELO_PWW_H: - [[fallthrough]]; - case Opcode::AArch64_WHILELO_PWW_S: - [[fallthrough]]; - case Opcode::AArch64_WHILELO_PXX_B: - [[fallthrough]]; - case Opcode::AArch64_WHILELO_PXX_D: - [[fallthrough]]; - case Opcode::AArch64_WHILELO_PXX_H: - [[fallthrough]]; - case Opcode::AArch64_WHILELO_PXX_S: - // WHILELO doesn't label access or vector specifiers - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - // Doesn't identify implicit NZCV destination - implicitDestinationCount = 1; - implicitDestinations[0] = AARCH64_REG_NZCV; - break; - case Opcode::AArch64_XTNv16i8: - case Opcode::AArch64_XTNv4i32: - case Opcode::AArch64_XTNv8i16: - // XTN2 incorrectly flags destination as only WRITE - operands[0].access = CS_AC_READ | CS_AC_WRITE; - break; - case Opcode::AArch64_ZIP1_PPP_B: - [[fallthrough]]; - case Opcode::AArch64_ZIP1_PPP_D: - [[fallthrough]]; - case Opcode::AArch64_ZIP1_PPP_H: - [[fallthrough]]; - case Opcode::AArch64_ZIP1_PPP_S: - [[fallthrough]]; - case Opcode::AArch64_ZIP1_ZZZ_S: - [[fallthrough]]; - case Opcode::AArch64_ZIP1_ZZZ_D: - [[fallthrough]]; - case Opcode::AArch64_ZIP2_PPP_B: - [[fallthrough]]; - case Opcode::AArch64_ZIP2_PPP_D: - [[fallthrough]]; - case Opcode::AArch64_ZIP2_PPP_H: - [[fallthrough]]; - case Opcode::AArch64_ZIP2_PPP_S: - [[fallthrough]]; - case Opcode::AArch64_ZIP2_ZZZ_S: - [[fallthrough]]; - case Opcode::AArch64_ZIP2_ZZZ_D: - // ZIP lacks access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_SXTW_ZPmZ_D: - [[fallthrough]]; - case Opcode::AArch64_FCVT_ZPmZ_DtoS: - [[fallthrough]]; - case Opcode::AArch64_FCVT_ZPmZ_StoD: - [[fallthrough]]; - case Opcode::AArch64_SCVTF_ZPmZ_DtoS: - [[fallthrough]]; - case Opcode::AArch64_SCVTF_ZPmZ_StoD: - [[fallthrough]]; - case Opcode::AArch64_SCVTF_ZPmZ_StoS: - [[fallthrough]]; - case Opcode::AArch64_SCVTF_ZPmZ_DtoD: - // Need to see if Destination vector elements are active - operands[0].access = CS_AC_READ | CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_TBLv8i8One: - [[fallthrough]]; - case Opcode::AArch64_TBLv16i8One: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - break; - case Opcode::AArch64_TBLv8i8Two: - [[fallthrough]]; - case Opcode::AArch64_TBLv16i8Two: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - break; - case Opcode::AArch64_TBLv8i8Three: - [[fallthrough]]; - case Opcode::AArch64_TBLv16i8Three: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - operands[4].access = CS_AC_READ; - break; - case Opcode::AArch64_TBLv8i8Four: - [[fallthrough]]; - case Opcode::AArch64_TBLv16i8Four: - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - operands[4].access = CS_AC_READ; - operands[5].access = CS_AC_READ; - break; - case Opcode::AArch64_LD1_MXIPXX_H_D: - [[fallthrough]]; - case Opcode::AArch64_LD1_MXIPXX_V_D: - [[fallthrough]]; - case Opcode::AArch64_LD1_MXIPXX_V_S: - [[fallthrough]]; - case Opcode::AArch64_LD1_MXIPXX_H_S: { - // Lacking access specifiers - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - break; - } - case Opcode::AArch64_ST1_MXIPXX_H_D: - [[fallthrough]]; - case Opcode::AArch64_ST1_MXIPXX_V_D: - [[fallthrough]]; - case Opcode::AArch64_ST1_MXIPXX_H_S: - [[fallthrough]]; - case Opcode::AArch64_ST1_MXIPXX_V_S: - // Access types are not defined - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - break; - case Opcode::AArch64_FMOPA_MPPZZ_D: - [[fallthrough]]; - case Opcode::AArch64_FMOPA_MPPZZ_S: { - // Need to add access specifiers - // although operands[0] should be READ | WRITE, due to the implemented - // decode logic for SME tile destinations, the register will be added as - // both source and destination with just WRITE access. - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - operands[4].access = CS_AC_READ; - operands[5].access = CS_AC_READ; - break; - } - case Opcode::AArch64_EXTRACT_ZPMXI_H_B: { - operandCount = 4; - operands[0].access = CS_AC_READ | CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].reg = operands[2].sme_index.base; - operands[3].access = CS_AC_READ; - break; - } - case Opcode::AArch64_ZERO_M: { - // Operands often mangled from ZA tile overlap aliasing in decode. Need to - // re-extract relevant tiles from operandStr - operandCount = 0; - size_t pos = operandStr.find("za", 0); - while (pos != std::string::npos) { - size_t pos_2 = operandStr.find(".", pos); - if (pos_2 != std::string::npos) { - char type = operandStr[pos_2 + 1]; - // Tile Number can only ever be 1 digit - uint8_t tileNum = std::stoi(operandStr.substr((pos + 2), 1)); - switch (type) { - case 'b': - operands[operandCount].reg = AARCH64_REG_ZAB0; - break; - case 'h': - operands[operandCount].reg = - static_cast(AARCH64_REG_ZAH0 + tileNum); - break; - case 's': - operands[operandCount].reg = - static_cast(AARCH64_REG_ZAS0 + tileNum); - break; - case 'd': - operands[operandCount].reg = - static_cast(AARCH64_REG_ZAD0 + tileNum); - break; - case 'q': - operands[operandCount].reg = - static_cast(AARCH64_REG_ZAQ0 + tileNum); - break; - } - } else { - operands[operandCount].reg = AARCH64_REG_ZA; - } - operands[operandCount].type = AARCH64_OP_REG; - operands[operandCount].access = CS_AC_WRITE; - operandCount++; - pos = operandStr.find("za", pos + 1); - } - break; - } + // // Fix some inaccuracies in the decoded metadata + // switch (opcode) { + // case Opcode::AArch64_ADR_LSL_ZZZ_D_0: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_D_1: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_D_2: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_D_3: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_S_0: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_S_1: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_S_2: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_S_3: { + // // No defined access types + // operandCount = 3; + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[2].type = AARCH64_OP_REG; + // break; + // } + // case Opcode::AArch64_SMIN_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_EOR_ZPmZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_EOR_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_EOR_ZPmZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_EOR_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_AND_ZPmZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_AND_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_AND_ZPmZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_AND_ZPmZ_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_BICv4i32: + // // BIC incorrectly flags destination as WRITE only + // operands[0].access = CS_AC_WRITE | CS_AC_READ; + // break; + // case Opcode::AArch64_ADDSWri: + // // adds incorrectly flags destination as READ + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_BICv8i16: + // operands[0].access = CS_AC_WRITE | CS_AC_READ; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_BICv8i8: + // // access specifier for last operand was missing + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_CASALW: + // [[fallthrough]]; + // case Opcode::AArch64_CASALX: + // operandCount = 3; + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_CBNZW: + // [[fallthrough]]; + // case Opcode::AArch64_CBNZX: + // [[fallthrough]]; + // case Opcode::AArch64_CBZW: + // [[fallthrough]]; + // case Opcode::AArch64_CBZX: + // // incorrectly adds implicit nzcv dependency + // implicitSourceCount = 0; + // break; + // case Opcode::AArch64_CMPHI_PPzZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPHI_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPHI_PPzZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPHI_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_CMPGT_PPzZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPGT_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPGT_PPzZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPGT_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZI_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZI_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZI_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZI_S: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZI_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZI_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZI_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZI_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // // Doesn't identify implicit NZCV destination + // implicitDestinationCount = 1; + // implicitDestinations[0] = AARCH64_REG_NZCV; + // break; + // case Opcode::AArch64_CNTB_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_CNTH_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_CNTD_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_CNTW_XPiI: { + // // lacking access specifiers for destination + // operands[0].access = CS_AC_WRITE; + // if (operandStr.length() < 4) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + // operands[1].ext = AARCH64_EXT_INVALID; + // operands[1].vector_index = -1; + // } + // break; + // } + // case Opcode::AArch64_ADD_ZI_B: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZI_D: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZI_H: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZI_S: { + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[2].type = AARCH64_OP_IMM; + // operandCount = 3; + + // // Extract immediate in SVE add with immediate instruction + // size_t start = operandStr.find("#"); + // // Identify whether the immediate value is in base-10 or base-16 + // if (start != std::string::npos) { + // start++; + // bool hex = false; + // if (operandStr[start + 1] == 'x') { + // hex = true; + // start += 2; + // } + + // uint8_t end = operandStr.size(); + // size_t shifted = operandStr.find("LSL"); + // if (shifted != std::string::npos) { + // std::cerr << "[SimEng:arch] SVE add with immediate has shift value + // " + // "in operandStr which is unsupported." + // << std::endl; + // exit(1); + // } + // // Convert extracted immediate from string to int64_t + // std::string sub = operandStr.substr(start, end); + // if (hex) { + // operands[2].imm = std::stoul(sub, 0, 16); + // } else { + // operands[2].imm = stoi(sub); + // } + // } else { + // operands[2].imm = 0; + // } + // break; + // } + // case Opcode::AArch64_AND_ZI: { + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[2].type = AARCH64_OP_IMM; + // operandCount = 3; + + // char specifier = operandStr[operandStr.find(".") + 1]; + // switch (specifier) { + // case 'b': { + // uint8_t mask = static_cast(operands[2].imm); + // operands[2].imm = static_cast(0); + // for (int i = 0; i < 8; i++) + // operands[2].imm |= (static_cast(mask) << (i * 8)); + // break; + // } + // case 'h': { + // uint16_t mask = static_cast(operands[2].imm); + // operands[2].imm = static_cast(0); + // for (int i = 0; i < 4; i++) + // operands[2].imm |= (static_cast(mask) << (i * 16)); + // break; + // } + // case 's': { + // uint32_t mask = static_cast(operands[2].imm); + // operands[2].imm = static_cast(0); + // for (int i = 0; i < 2; i++) + // operands[2].imm |= (static_cast(mask) << (i * 32)); + // break; + // } + // default: + // break; + // } + // break; + // } + // case Opcode::AArch64_CNTP_XPP_B: + // [[fallthrough]]; + // case Opcode::AArch64_CNTP_XPP_D: + // [[fallthrough]]; + // case Opcode::AArch64_CNTP_XPP_H: + // [[fallthrough]]; + // case Opcode::AArch64_CNTP_XPP_S: + // [[fallthrough]]; + // case Opcode::AArch64_EOR_ZZZ: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_DECD_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_DECB_XPiI: { + // // lacking access specifiers for destination + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // std::string str(operandStr); + // if (str.length() < 4) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + // operands[1].ext = AARCH64_EXT_INVALID; + // operands[1].vector_index = -1; + // } + // break; + // } + // case Opcode::AArch64_EOR_PPzPP: { + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_FMOVXDHighr: + // // FMOVXDHighr incorrectly flags destination as only WRITE + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // break; + // case Opcode::AArch64_FNMSB_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FNMSB_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FNMLS_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FNMLS_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMAD_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMAD_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMLA_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMLA_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMLS_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMLS_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMSB_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMSB_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_MLA_ZPmZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_MLA_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_MLA_ZPmZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_MLA_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_SMAX_ZPmZ_S: + // // No defined access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_ADDPL_XXI: + // [[fallthrough]]; + // case Opcode::AArch64_ADDVL_XXI: + // [[fallthrough]]; + // case Opcode::AArch64_UADDV_VPZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_UADDV_VPZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_UADDV_VPZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_UADDV_VPZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_MOVPRFX_ZPzZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_MOVPRFX_ZPzZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_SUB_ZZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_SUB_ZZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_SUB_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_SUB_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_II_B: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_II_H: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_II_S: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_II_D: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_IR_B: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_IR_D: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_IR_H: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_IR_S: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RI_B: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RI_D: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RI_H: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RI_S: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RR_B: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RR_D: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RR_H: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RR_S: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FSUB_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FSUB_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMUL_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMUL_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_SMAX_ZI_S: + // [[fallthrough]]; + // case Opcode::AArch64_SMINV_VPZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_TRN1_ZZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_TRN1_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_TRN1_ZZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_TRN1_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_TRN2_ZZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_TRN2_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_TRN2_ZZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_TRN2_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_UZP1_ZZZ_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_MOVPRFX_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCPY_ZPmI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCPY_ZPmI_S: + // [[fallthrough]]; + // case Opcode::AArch64_FNEG_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FNEG_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FRINTN_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FRINTN_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FABS_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FABS_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FSQRT_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FSQRT_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCVTZS_ZPmZ_DtoD: + // [[fallthrough]]; + // case Opcode::AArch64_FCVTZS_ZPmZ_StoD: + // [[fallthrough]]; + // case Opcode::AArch64_FCVTZS_ZPmZ_StoS: + // [[fallthrough]]; + // case Opcode::AArch64_FCVTZS_ZPmZ_DtoS: + // // No defined access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_FMUL_ZPmI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMUL_ZPmI_S: { + // // No defined access types + // operandCount = 4; + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].type = AARCH64_OP_FP; + // operands[3].access = CS_AC_READ; + // // Doesn't recognise immediate operands + // // Extract two possible values, 0.5 or 2.0 + // if (operandStr.substr(operandStr.length() - 1, 1) == "5") { + // operands[3].fp = 0.5f; + // } else { + // operands[3].fp = 2.0f; + // } + + // break; + // } + // case Opcode::AArch64_FCMLA_ZPmZZ_D: { + // // No defined access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // operands[4].type = AARCH64_OP_IMM; + // break; + // } + // case Opcode::AArch64_FCADD_ZPmZ_D: { + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // operands[4].type = AARCH64_OP_IMM; + // break; + // } + // case Opcode::AArch64_FSUB_ZPmI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FSUB_ZPmI_S: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZPmI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZPmI_S: + // // No defined access types + // operandCount = 4; + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].type = AARCH64_OP_FP; + // operands[3].access = CS_AC_READ; + // // Doesn't recognise immediate operands + // // Extract two possible values, 0.5 or 1.0 + // if (operandStr.substr(operandStr.length() - 1, 1) == "5") { + // operands[3].fp = 0.5f; + // } else { + // operands[3].fp = 1.0f; + // } + // break; + // case Opcode::AArch64_FCMGT_PPzZ0_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGT_PPzZ0_S: { + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_FMLA_ZZZI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMLA_ZZZI_S: { + // // Need to define missing access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_FDIVR_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FDIVR_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FDIV_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_AND_PPzPP: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZPmZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZPmZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGE_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGE_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGE_PPzZ0_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGE_PPzZ0_S: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGT_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGT_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FCMLE_PPzZ0_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCMLE_PPzZ0_S: + // [[fallthrough]]; + // case Opcode::AArch64_FCMLT_PPzZ0_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMUL_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMUL_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FSUBR_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FSUBR_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FSUB_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FSUB_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FADDA_VPZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_MUL_ZPmZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_MUL_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_MUL_ZPmZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_MUL_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_ORR_PPzPP: + // [[fallthrough]]; + // case Opcode::AArch64_SMULH_ZPmZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_SMULH_ZPmZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_SMULH_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_SEL_ZPZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_SEL_ZPZZ_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_FRINTPDr: + // [[fallthrough]]; + // case Opcode::AArch64_FRINTPSr: + // [[fallthrough]]; + // case Opcode::AArch64_FDUP_ZI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FDUP_ZI_S: + // [[fallthrough]]; + // case Opcode::AArch64_PUNPKHI_PP: + // [[fallthrough]]; + // case Opcode::AArch64_PUNPKLO_PP: + // [[fallthrough]]; + // case Opcode::AArch64_RDVLI_XI: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_INCB_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_INCD_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_INCH_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_INCW_XPiI: { + // // lacking access specifiers for destination + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // if (operandStr.length() < 4) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + // operands[1].ext = AARCH64_EXT_INVALID; + // operands[1].vector_index = -1; + // } + // break; + // } + // case Opcode::AArch64_INCD_ZPiI: + // [[fallthrough]]; + // case Opcode::AArch64_INCH_ZPiI: + // [[fallthrough]]; + // case Opcode::AArch64_INCW_ZPiI: { + // // lacking access specifiers for destination + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // if (operandStr.length() < 6) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + // operands[1].ext = AARCH64_EXT_INVALID; + // operands[1].vector_index = -1; + // } + // break; + // } + // case Opcode::AArch64_INCP_XP_B: + // [[fallthrough]]; + // case Opcode::AArch64_INCP_XP_D: + // [[fallthrough]]; + // case Opcode::AArch64_INCP_XP_H: + // [[fallthrough]]; + // case Opcode::AArch64_INCP_XP_S: + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1i32: + // [[fallthrough]]; + // case Opcode::AArch64_LD1i64: + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_GLD1W_D_SCALED_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_GLD1W_SXTW_REAL: { + // // Access types are not set correctly + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_GLD1D_SCALED_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_GLD1D_REAL: { + // // LD1D gather instruction doesn't correctly identify destination + // // register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + // operands[0].reg = static_cast(reg_enum); + + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // LD1D gather instruction doesn't correctly identify memory operands + // operands[2].type = AARCH64_OP_MEM; + // operands[2].access = CS_AC_READ; + + // // LD1D doesn't correctly identify vector memory register correctly + // uint16_t vec_enum = AARCH64_REG_Z0; + // std::string tmp_str(operandStr.substr(operandStr.find("["))); + // // Single or double digit Z register identifier + // if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { + // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); + // } else { + // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); + // } + // operands[2].mem.index = static_cast(vec_enum); + // break; + // } + // case Opcode::AArch64_LD1RQ_W: + // [[fallthrough]]; + // case Opcode::AArch64_LD1RQ_W_IMM: { + // // LD1RQW doesn't identify correct access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_LD1RQ_D_IMM: { + // // LD1RQ gather instruction doesn't correctly identify destination + // // register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + // operands[0].reg = static_cast(reg_enum); + + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // LD1RQ gather instruction doesn't correctly identify memory operands + // operands[2].type = AARCH64_OP_MEM; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_GLD1SW_D_IMM_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_GLD1D_IMM_REAL: { + // // LD1D gather instruction doesn't correctly identify destination + // // register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // LD1D gather instruction doesn't correctly identify second Z reg as + // // memory operand + // operands[2].type = AARCH64_OP_MEM; + // operands[2].access = CS_AC_READ; + // // LD1D gather instruction doesn't recognise memory-offset immediate + // // correctly + // if (operandStr[operandStr.length() - 3] != '.') { + // int64_t startPos = operandStr.find('#') + 1; + // int64_t immSize = (operandStr.length() - 1) - startPos; + // if (immSize == 1) { + // operands[2].mem.disp = + // std::stoi(operandStr.substr(startPos, immSize)); + // } else { + // // double or triple digit immediates are converted to hex, and so + // // require a different conversion to uint + // operands[2].mem.disp = + // std::stoul(operandStr.substr(startPos, immSize), nullptr, 16); + // } + // } + // break; + // } + // case Opcode::AArch64_LD1B: + // [[fallthrough]]; + // case Opcode::AArch64_LD1D: + // [[fallthrough]]; + // case Opcode::AArch64_LD1B_IMM_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_LD1D_IMM_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_LD1RD_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_LD1RW_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_LD1H: + // [[fallthrough]]; + // case Opcode::AArch64_LD1W: + // [[fallthrough]]; + // case Opcode::AArch64_LD1W_IMM_REAL: { + // // LD1RW doesn't correctly identify destination register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_LD1Rv4s: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv1d: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv2d: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv2s: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv8b: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv16b: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv8h: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv4h: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1Rv4h_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv8h_POST: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ | CS_AC_WRITE; + // // Fix for exclusion of post_index immediate in disassembly + // operandCount = 3; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // // For vector arrangement of 16-bit, post_index immediate is 2 + // operands[2].imm = 2; + // break; + // case Opcode::AArch64_LD1Rv1d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv2d_POST: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ | CS_AC_WRITE; + // // Fix for exclusion of post_index immediate in disassembly + // operandCount = 3; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // // For vector arrangement of 64-bit, post_index immediate is 8 + // operands[2].imm = 8; + // break; + // case Opcode::AArch64_LD1Rv16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv8b_POST: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ | CS_AC_WRITE; + + // // Fix for exclusion of post_index immediate in disassembly + // operandCount = 3; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // // For vector arrangement of 8-bit, post_index immediate is 1 + // operands[2].imm = 1; + // break; + // case Opcode::AArch64_LD1Rv2s_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv4s_POST: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ | CS_AC_WRITE; + + // // Fix for exclusion of post_index immediate in disassembly + // operandCount = 3; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // // For vector arrangement of 32-bit, post_index immediate is 4 + // operands[2].imm = 4; + // break; + // case Opcode::AArch64_LD1Fourv16b: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Fourv4s: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Fourv2d: + // // Fix incorrect access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_WRITE; + // operands[2].access = CS_AC_WRITE; + // operands[3].access = CS_AC_WRITE; + // operands[4].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1Fourv16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Fourv2d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Fourv4s_POST: + // // Fix incorrect access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_WRITE; + // operands[2].access = CS_AC_WRITE; + // operands[3].access = CS_AC_WRITE; + // operands[4].access = CS_AC_READ | CS_AC_WRITE; + // operands[5].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1Onev16b: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1Onev16b_POST: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ | CS_AC_WRITE; + // break; + // case Opcode::AArch64_LD1Twov16b: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Twov4s: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Twov2d: + // // Fix incorrect access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_WRITE; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1Twov16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Twov2d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Twov4s_POST: + // // Fix incorrect access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_WRITE; + // operands[2].access = CS_AC_READ | CS_AC_WRITE; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LDADDLW: + // [[fallthrough]]; + // case Opcode::AArch64_LDADDW: + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_LD2Twov4s_POST: + // // Fixing wrong access flag for offset register operand + // if (operandCount == 4) { + // operands[3].access = CS_AC_READ; + // } + // break; + // case Opcode::AArch64_LDR_PXI: + // [[fallthrough]]; + // case Opcode::AArch64_LDR_ZXI: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LSL_ZZI_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // // No instruction id assigned + // id = AARCH64_INS_LSL; + // break; + // case Opcode::AArch64_LD2D: + // case Opcode::AArch64_LD2D_IMM: { + // // LD2D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_WRITE; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_WRITE; + + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_LD3D_IMM: { + // // LD3D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + // uint16_t reg_enum2 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d, znn.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest2 + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); + // } else { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_WRITE; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_WRITE; + // operands[2].reg = static_cast(reg_enum2); + // operands[2].access = CS_AC_WRITE; + + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_LD4D_IMM: { + // // LD4D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + // uint16_t reg_enum2 = AARCH64_REG_Z0; + // uint16_t reg_enum3 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d, znn.d, zmm.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest2 + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest3 + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum3 += std::stoi(tmpOpStr.substr(1, 1)); + // } else { + // reg_enum3 += std::stoi(tmpOpStr.substr(1, 2)); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_WRITE; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_WRITE; + // operands[2].reg = static_cast(reg_enum2); + // operands[2].access = CS_AC_WRITE; + // operands[3].reg = static_cast(reg_enum3); + // operands[3].access = CS_AC_WRITE; + + // operands[4].access = CS_AC_READ; + // operands[5].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_MOVNWi: + // [[fallthrough]]; + // case Opcode::AArch64_MOVNXi: + // [[fallthrough]]; + // case Opcode::AArch64_MOVZWi: + // [[fallthrough]]; + // case Opcode::AArch64_MOVZXi: + // // MOVZ incorrectly flags destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_MOVPRFX_ZZ: + // // Assign operand access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_MRS: + // // MRS incorrectly flags source/destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // MRS incorrectly tags AARCH64_OP_REG_MRS as AARCH64_OP_SYS + // operands[1].type = AARCH64_OP_REG_MRS; + // break; + // case Opcode::AArch64_MSR: + // // MSR incorrectly flags source/destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // MSR incorrectly tags AARCH64_OP_REG_MSR as AARCH64_OP_SYS + // operands[0].type = AARCH64_OP_REG_MSR; + // break; + // case Opcode::AArch64_PTEST_PP: { + // // PTEST doesn't label access types for operands + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // // Doesn't identify implicit NZCV destination + // implicitDestinationCount = 1; + // implicitDestinations[0] = AARCH64_REG_NZCV; + // break; + // } + // case Opcode::AArch64_PTRUE_B: + // [[fallthrough]]; + // case Opcode::AArch64_PTRUE_H: + // [[fallthrough]]; + // case Opcode::AArch64_PTRUE_D: + // [[fallthrough]]; + // case Opcode::AArch64_PTRUE_S: + // // PTRUE doesn't label access + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_RET: + // // If no register supplied to RET, default to x30 (LR) + // if (operandCount == 0) { + // operandCount = 1; + // operands[0].type = AARCH64_OP_REG; + // operands[0].reg = AARCH64_REG_LR; + // operands[0].access = CS_AC_READ; + // } + // groupCount = 1; + // groups[0] = CS_GRP_JUMP; + // break; + // case Opcode::AArch64_REV_ZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_REV_ZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_REV_ZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_REV_ZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_B: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_D: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_H: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_S: { + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_SST1B_D_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_SST1D_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { + // // ST1W doesn't correctly identify first source register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // // SST1D{_SCALED} gather instruction doesn't correctly identify memory + // // operands + // operands[2].type = AARCH64_OP_MEM; + // operands[2].access = CS_AC_READ; + + // // ST1D doesn't correctly identify vector memory register correctly + // uint16_t vec_enum = AARCH64_REG_Z0; + // std::string tmp_str(operandStr.substr(operandStr.find("["))); + // // Single or double digit Z register identifier + // if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { + // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); + // } else { + // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); + // } + // operands[2].mem.index = static_cast(vec_enum); + // break; + // } + // case Opcode::AArch64_ST2D_IMM: { + // // ST2D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_READ; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_READ; + + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_ST1B: + // [[fallthrough]]; + // case Opcode::AArch64_ST1D: + // [[fallthrough]]; + // case Opcode::AArch64_ST1B_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_ST1D_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_ST1W_IMM: { + // // ST1W doesn't correctly identify first source register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_ST1W: + // [[fallthrough]]; + // case Opcode::AArch64_ST1W_D: { + // // ST1W doesn't correctly identify first source register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_SST1D_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_SST1W_D_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_SST1W_IMM: { + // // ST1W scatter instruction doesn't correctly identify first source + // // register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // // ST1W scatter instruction doesn't correctly identify second Z reg as + // // memory operand + // operands[2].type = AARCH64_OP_MEM; + // operands[2].access = CS_AC_READ; + // // ST1W scatter instruction doesn't recognise memory-offset immediate + // // correctly + // if (operandStr[operandStr.length() - 3] != '.') { + // int64_t startPos = operandStr.find('#') + 1; + // int64_t immSize = (operandStr.length() - 1) - startPos; + // if (immSize == 1) { + // operands[2].mem.disp = + // std::stoi(operandStr.substr(startPos, immSize)); + // } else { + // // double or triple digit immediates are converted to hex, and so + // // require a different conversion to uint + // operands[2].mem.disp = + // std::stoul(operandStr.substr(startPos, immSize), nullptr, 16); + // } + // } + // break; + // } + // case Opcode::AArch64_ST1i8_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1i16_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1i32_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1i64_POST: + // // fixing incorrect access type for register offset + // if (operandCount == 3) { + // operands[2].access = CS_AC_READ; + // } + // break; + // case Opcode::AArch64_ST1Fourv16b: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv2d: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv4s: + // // ST1 incorrectly flags read and write + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // break; + // case Opcode::AArch64_ST1Fourv16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv2d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv2s_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv4s_POST: + // // ST1 incorrectly flags read and write + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ | CS_AC_WRITE; + // operands[5].access = CS_AC_READ; + // // determine correct type for operand 5 + // if (operandStr.find("#") != std::string::npos) { + // operands[5].type = AARCH64_OP_IMM; + // } else { + // operands[5].type = AARCH64_OP_REG; + // } + // break; + // case Opcode::AArch64_ST1Twov16b: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov2d: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov4s: + // // ST1 incorrectly flags read and write + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_ST1Twov16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov2d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov4s_POST: + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ | CS_AC_WRITE; + // operands[3].access = CS_AC_READ; + // // determine correct type for operand 3 + // if (operandStr.find("#") != std::string::npos) { + // operands[3].type = AARCH64_OP_IMM; + // } else { + // operands[3].type = AARCH64_OP_REG; + // } + // break; + // case Opcode::AArch64_ST2Twov4s_POST: + // // ST2 post incorrectly flags read and write + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ | CS_AC_WRITE; + // // Another incorrect access flag for register offset operand + // if (operandCount == 4) { + // operands[3].access = CS_AC_READ; + // } + // break; + // case Opcode::AArch64_STRBui: + // [[fallthrough]]; + // case Opcode::AArch64_STRDui: + // [[fallthrough]]; + // case Opcode::AArch64_STRHui: + // [[fallthrough]]; + // case Opcode::AArch64_STRQui: + // [[fallthrough]]; + // case Opcode::AArch64_STRSui: + // [[fallthrough]]; + // case Opcode::AArch64_STRWui: + // [[fallthrough]]; + // case Opcode::AArch64_STRXui: + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_PFALSE: + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_STR_PXI: + // [[fallthrough]]; + // case Opcode::AArch64_STR_ZXI: + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_SBFMWri: + // [[fallthrough]]; + // case Opcode::AArch64_SBFMXri: + // // SBFM incorrectly flags destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_SVC: + // // SVC is incorrectly marked as setting x30 + // implicitDestinationCount = 0; + // break; + // case Opcode::AArch64_SYSxt: + // // No defined metadata.id for SYS instructions + // id = AARCH64_INS_SYS; + // break; + // case Opcode::AArch64_PSEL_PPPRI_B: + // [[fallthrough]]; + // case Opcode::AArch64_PSEL_PPPRI_D: + // [[fallthrough]]; + // case Opcode::AArch64_PSEL_PPPRI_H: + // [[fallthrough]]; + // case Opcode::AArch64_PSEL_PPPRI_S: + // // Add correct access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_UBFMWri: + // [[fallthrough]]; + // case Opcode::AArch64_UBFMXri: + // // UBFM incorrectly flags destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_UQDECB_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECB_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECD_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECD_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECH_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECH_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECW_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECW_XPiI: + // // UQDEC lacks access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // if (operandCount == 1) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // } + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_UUNPKHI_ZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKHI_ZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKHI_ZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKLO_ZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKLO_ZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKLO_ZZ_S: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_WHILELT_PXX_B: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELT_PXX_D: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELT_PXX_H: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELT_PXX_S: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_B: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_D: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_H: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_S: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_B: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_D: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_H: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_S: + // // WHILELO doesn't label access or vector specifiers + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // // Doesn't identify implicit NZCV destination + // implicitDestinationCount = 1; + // implicitDestinations[0] = AARCH64_REG_NZCV; + // break; + // case Opcode::AArch64_XTNv16i8: + // case Opcode::AArch64_XTNv4i32: + // case Opcode::AArch64_XTNv8i16: + // // XTN2 incorrectly flags destination as only WRITE + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // break; + // case Opcode::AArch64_ZIP1_PPP_B: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_PPP_D: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_PPP_H: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_PPP_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_B: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_D: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_H: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_ZZZ_D: + // // ZIP lacks access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_SXTW_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCVT_ZPmZ_DtoS: + // [[fallthrough]]; + // case Opcode::AArch64_FCVT_ZPmZ_StoD: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_DtoS: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_StoD: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_StoS: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_DtoD: + // // Need to see if Destination vector elements are active + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8One: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8One: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8Two: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8Two: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8Three: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8Three: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8Four: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8Four: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // operands[5].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1_MXIPXX_H_D: + // [[fallthrough]]; + // case Opcode::AArch64_LD1_MXIPXX_V_D: + // [[fallthrough]]; + // case Opcode::AArch64_LD1_MXIPXX_V_S: + // [[fallthrough]]; + // case Opcode::AArch64_LD1_MXIPXX_H_S: { + // // Lacking access specifiers + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_ST1_MXIPXX_H_D: + // [[fallthrough]]; + // case Opcode::AArch64_ST1_MXIPXX_V_D: + // [[fallthrough]]; + // case Opcode::AArch64_ST1_MXIPXX_H_S: + // [[fallthrough]]; + // case Opcode::AArch64_ST1_MXIPXX_V_S: + // // Access types are not defined + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_FMOPA_MPPZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMOPA_MPPZZ_S: { + // // Need to add access specifiers + // // although operands[0] should be READ | WRITE, due to the implemented + // // decode logic for SME tile destinations, the register will be added + // as + // // both source and destination with just WRITE access. + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // operands[5].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_EXTRACT_ZPMXI_H_B: { + // operandCount = 4; + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].reg = operands[2].sme_index.base; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_ZERO_M: { + // // Operands often mangled from ZA tile overlap aliasing in decode. Need + // to + // // re-extract relevant tiles from operandStr + // operandCount = 0; + // size_t pos = operandStr.find("za", 0); + // while (pos != std::string::npos) { + // size_t pos_2 = operandStr.find(".", pos); + // if (pos_2 != std::string::npos) { + // char type = operandStr[pos_2 + 1]; + // // Tile Number can only ever be 1 digit + // uint8_t tileNum = std::stoi(operandStr.substr((pos + 2), 1)); + // switch (type) { + // case 'b': + // operands[operandCount].reg = AARCH64_REG_ZAB0; + // break; + // case 'h': + // operands[operandCount].reg = + // static_cast(AARCH64_REG_ZAH0 + tileNum); + // break; + // case 's': + // operands[operandCount].reg = + // static_cast(AARCH64_REG_ZAS0 + tileNum); + // break; + // case 'd': + // operands[operandCount].reg = + // static_cast(AARCH64_REG_ZAD0 + tileNum); + // break; + // case 'q': + // operands[operandCount].reg = + // static_cast(AARCH64_REG_ZAQ0 + tileNum); + // break; + // } + // } else { + // operands[operandCount].reg = AARCH64_REG_ZA; + // } + // operands[operandCount].type = AARCH64_OP_REG; + // operands[operandCount].access = CS_AC_WRITE; + // operandCount++; + // pos = operandStr.find("za", pos + 1); + // } + // break; + // } + // } + + if (insn.is_alias) { + // revertAliasing(); } - - revertAliasing(); } InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, uint8_t bytes) - : id(ARM64_INS_INVALID), - opcode(Opcode::AArch64_INSTRUCTION_LIST_END), + : id(AARCH64_INS_INVALID), + opcode(Opcode::INSTRUCTION_LIST_END), implicitSourceCount(0), implicitDestinationCount(0), groupCount(0), @@ -1771,827 +1776,831 @@ InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, } void InstructionMetadata::revertAliasing() { - // Check mnemonics known to be aliases and see if their opcode matches - // something else - switch (id) { - case ARM64_INS_ASR: - if (opcode == Opcode::AArch64_ASRVWr || - opcode == Opcode::AArch64_ASRVXr) { - // asr rd, rn, rm; alias for: asrv rd, rn, rm - return; - } - if (opcode == Opcode::AArch64_SBFMWri || - opcode == Opcode::AArch64_SBFMXri) { - operandCount = 4; - - operands[3].type = AARCH64_OP_IMM; - operands[3].access = CS_AC_READ; - if (opcode == Opcode::AArch64_SBFMWri) { - // 32-bit - operands[3].imm = 31; - } else { - operands[3].imm = 63; - } - return; - } - return aliasNYI(); - case ARM64_INS_AT: - return aliasNYI(); - case ARM64_INS_BFI: - // TODO no tests of alias - if (opcode == Opcode::AArch64_BFMWri) { - // bfi wd, wn, #lsb, #width; alias for - // bfm wd, wn, #(-lsb MOD 32), #(width - 1) - operands[2].imm = static_cast(-operands[2].imm) % 32; - operands[3].imm = operands[3].imm - 1; - return; - } - if (opcode == Opcode::AArch64_BFMXri) { - // bfi xd, xn, #lsb, #width; alias for - // bfm xd, xn, #(-lsb MOD 64), #(width - 1) - operands[2].imm = static_cast(-operands[2].imm) % 64; - operands[3].imm = operands[3].imm - 1; - return; - } - return aliasNYI(); - case ARM64_INS_BFXIL: - // TODO no tests for alias - if (opcode == Opcode::AArch64_BFMWri || - opcode == Opcode::AArch64_BFMXri) { - // bfxil rd, rn, #lsb, #width; alias for - // bfm rd, rn, #lsb, #(lsb + width - 1) - operands[3].imm = operands[2].imm + operands[3].imm - 1; - return; - } - return aliasNYI(); - case ARM64_INS_CINC: - if (opcode == Opcode::AArch64_CSINCWr || - opcode == Opcode::AArch64_CSINCXr) { - // cinc rd, rn, cc; alias for: csinc rd, rn, rn, invert(cc) - operandCount = 3; - - operands[2].type = AARCH64_OP_REG; - operands[2].access = CS_AC_READ; - operands[2].reg = operands[1].reg; - - cc ^= 1; // invert lowest bit to negate cc - return; - } - return aliasNYI(); - case ARM64_INS_CINV: - return aliasNYI(); - case ARM64_INS_CMN: - // cmn , alias for adds - operandCount = 3; - operands[2] = operands[1]; - operands[1] = operands[0]; - operands[1].access = CS_AC_READ; - - operands[0].type = AARCH64_OP_REG; - operands[0].access = CS_AC_WRITE; - - if (opcode == Opcode::AArch64_ADDSXri || - opcode == Opcode::AArch64_ADDSXrr || - opcode == Opcode::AArch64_ADDSXrs) { - // 64-bit version - operands[0].reg = AARCH64_REG_XZR; - } else { - // 32-bit version - operands[0].reg = AARCH64_REG_WZR; - } - return; - case ARM64_INS_CMP: - if (opcode == Opcode::AArch64_SUBSWri || - opcode == Opcode::AArch64_SUBSWrs || - opcode == Opcode::AArch64_SUBSWrx || - opcode == Opcode::AArch64_SUBSXri || - opcode == Opcode::AArch64_SUBSXrs || - opcode == Opcode::AArch64_SUBSXrx || - opcode == Opcode::AArch64_SUBSXrx64) { - operandCount = 3; - operands[2] = operands[1]; - - operands[1] = operands[0]; - operands[1].access = CS_AC_READ; - - operands[0].type = AARCH64_OP_REG; - operands[0].access = CS_AC_WRITE; - - if (opcode == Opcode::AArch64_SUBSWri || - opcode == Opcode::AArch64_SUBSWrs || - opcode == Opcode::AArch64_SUBSWrx) { - operands[0].reg = AARCH64_REG_WZR; - } else { - operands[0].reg = AARCH64_REG_XZR; - } - return; - } - return aliasNYI(); - case ARM64_INS_CNEG: - if (opcode == Opcode::AArch64_CSNEGWr || - opcode == Opcode::AArch64_CSNEGXr) { - // cneg rd, rn, cc; alias for: csneg rd, rn, rn, invert(cc) - operandCount = 3; - operands[2] = operands[1]; - cc ^= 1; // invert lowest bit to negate cc - return; - } - return aliasNYI(); - case ARM64_INS_CSET: - // TODO no usage in regression tests - if (opcode == Opcode::AArch64_CSINCWr || - opcode == Opcode::AArch64_CSINCXr) { - // cset rd, cc; alias for: csinc rd, zr, zr, invert(cc) - operandCount = 3; - - operands[1].type = AARCH64_OP_REG; - operands[1].access = CS_AC_READ; - operands[1].shift = {ARM64_SFT_INVALID, 0}; - - operands[2].type = AARCH64_OP_REG; - operands[2].access = CS_AC_READ; - operands[2].shift = {ARM64_SFT_INVALID, 0}; - - if (opcode == Opcode::AArch64_CSINCWr) { - operands[1].reg = AARCH64_REG_WZR; - operands[2].reg = AARCH64_REG_WZR; - } else { - operands[1].reg = AARCH64_REG_XZR; - operands[2].reg = AARCH64_REG_XZR; - } - - cc ^= 1; // invert lowest bit to negate cc - - return; - } - return aliasNYI(); - case ARM64_INS_CSETM: - if (opcode == Opcode::AArch64_CSINVWr || - opcode == Opcode::AArch64_CSINVXr) { - // csetm rd, cc; alias for: csinv rd, zr, zr, invert(cc) - operandCount = 3; - - operands[1].type = AARCH64_OP_REG; - operands[1].access = CS_AC_READ; - - operands[2].type = AARCH64_OP_REG; - operands[2].access = CS_AC_READ; - - if (opcode == Opcode::AArch64_CSINVWr) { - operands[1].reg = AARCH64_REG_WZR; - operands[2].reg = AARCH64_REG_WZR; - } else { - operands[1].reg = AARCH64_REG_XZR; - operands[2].reg = AARCH64_REG_XZR; - } - - cc ^= 1; // invert lowest bit to negate cc - - return; - } - return aliasNYI(); - case ARM64_INS_DC: - return aliasNYI(); - case ARM64_INS_IC: - return aliasNYI(); - case ARM64_INS_LSL: - // TODO no usage in regression tests - if (opcode == Opcode::AArch64_UBFMWri || - opcode == Opcode::AArch64_UBFMXri) { - // lsl rd, rn, #shift; alias for: - // ubfm rd, rn, #(-shift MOD <32|64>), #(<31|63> - shift) - operandCount = 4; - uint8_t highestBit = 63; - if (opcode == Opcode::AArch64_UBFMWri) { - highestBit = 31; - } - - auto shift = operands[2].imm; - operands[2].imm = (-shift) & highestBit; - operands[3].type = AARCH64_OP_IMM; - operands[3].imm = highestBit - shift; - operands[3].access = CS_AC_READ; - return; - } - if (opcode == Opcode::AArch64_LSLVWr || - opcode == Opcode::AArch64_LSLVXr || - opcode == Opcode::AArch64_LSL_ZZI_S) { - return; - } - return aliasNYI(); - case ARM64_INS_LSR: - if (opcode == Opcode::AArch64_LSRVWr || - opcode == Opcode::AArch64_LSRVXr) { - // lsr rd, rn, rm; alias for lsrv rd, rn, rm - return; - } - if (opcode == Opcode::AArch64_UBFMWri || - opcode == Opcode::AArch64_UBFMXri) { - // lsr rd, rn, #amount; alias for ubfm rd, rn, #amount, #<31|63> - operandCount = 4; - - operands[3].type = AARCH64_OP_IMM; - operands[3].access = CS_AC_READ; - - if (opcode == Opcode::AArch64_UBFMWri) { - operands[3].imm = 31; - } else { - operands[3].imm = 63; - } - return; - } - return aliasNYI(); - case ARM64_INS_MNEG: - // TODO no test - if (opcode == Opcode::AArch64_MSUBXrrr) { - // mneg xd, xn, xm; alias for msub xd, xn, xm, xzr - operandCount = 4; - operands[3].type = AARCH64_OP_REG; - operands[3].access = CS_AC_READ; - operands[3].reg = AARCH64_REG_XZR; - return; - } - if (opcode == Opcode::AArch64_MSUBWrrr) { - // mneg wd, wn, wm; alias for msub wd, wn, wm, wzr - operandCount = 4; - operands[3].type = AARCH64_OP_REG; - operands[3].access = CS_AC_READ; - operands[3].reg = AARCH64_REG_WZR; - return; - } - return aliasNYI(); - case ARM64_INS_MOV: - // TODO no specific tests - if (opcode == Opcode::AArch64_AND_PPzPP) { - // mov pd.b, pg/z, pn.b; alias for: and pd.b, pg/z, pn.b, pn.b - operandCount = 4; - operands[3] = operands[2]; - return; - } - if (opcode == Opcode::AArch64_ADDXri || - opcode == Opcode::AArch64_ADDWri) { - // mov to/from sp; alias for: add , , #0 - operandCount = 3; - operands[2].type = AARCH64_OP_IMM; - operands[2].imm = 0; - operands[2].access = CS_AC_READ; - operands[2].shift.type = ARM64_SFT_INVALID; - operands[2].vas = ARM64_VAS_INVALID; - operands[2].vector_index = -1; - return; - } - if (opcode == Opcode::AArch64_DUPi8 || opcode == Opcode::AArch64_DUPi16 || - opcode == Opcode::AArch64_DUPi32 || - opcode == Opcode::AArch64_DUPi64) { - // mov vd, Vn.T[index]; alias of dup vd, Vn.T[index] - return; - } - if (opcode == Opcode ::AArch64_CPY_ZPzI_B || - opcode == Opcode ::AArch64_CPY_ZPzI_D || - opcode == Opcode ::AArch64_CPY_ZPzI_H || - opcode == Opcode ::AArch64_CPY_ZPzI_S) { - // mov zd.T, pg/z, #imm{, shift}; alias of cpy zd.T, pg/z, #imm{, - // shift} - operandCount = 3; - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].type = AARCH64_OP_IMM; - operands[2].access = CS_AC_READ; - - // get imm value - std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); - auto value = std::stoi(tmpOpStr, 0, 16); - operands[2].imm = tmpOpStr.length() == 4 ? static_cast(value) - : static_cast(value); - return; - } - if (opcode == Opcode::AArch64_DUPM_ZI || - opcode == Opcode::AArch64_DUP_ZI_B || - opcode == Opcode::AArch64_DUP_ZI_D || - opcode == Opcode::AArch64_DUP_ZI_H || - opcode == Opcode::AArch64_DUP_ZI_S) { - // mov Zd.T, #imm; alias for dupm Zd.T, #imm - // or - // mov Zd.T, #imm{, shift}; alias for dup Zd.T, #imm{, shift} - operandCount = 2; - operands[0].access = CS_AC_WRITE; - operands[1].type = AARCH64_OP_IMM; - operands[1].access = CS_AC_READ; - - uint8_t start = operandStr[6] == '#' ? 7 : 8; - - if (opcode == Opcode::AArch64_DUPM_ZI) { - char specifier = operandStr[start - 4]; - switch (specifier) { - case 'b': - operands[0].vas = ARM64_VAS_1B; - break; - case 'h': - operands[0].vas = ARM64_VAS_1H; - break; - case 's': - operands[0].vas = ARM64_VAS_1S; - break; - case 'd': - operands[0].vas = ARM64_VAS_1D; - break; - - default: - break; - } - } - - bool hex = false; - if (operandStr[start + 1] == 'x') { - hex = true; - start += 2; - } - - uint8_t end = start + 1; - while (true) { - if (operandStr[end] < '0') { - break; - } - end++; - } - - std::string sub = operandStr.substr(start, end); - if (hex) { - operands[1].imm = std::stoul(sub, 0, 16); - } else { - operands[1].imm = stoi(sub); - } - - return; - } - if (opcode == Opcode::AArch64_DUP_ZR_S || - opcode == Opcode::AArch64_DUP_ZR_D || - opcode == Opcode::AArch64_DUP_ZR_B || - opcode == Opcode::AArch64_DUP_ZR_H) { - // mov Zd.T, ; alias for dup Zd.T, - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - - char specifier = operandStr[operandStr.find(".") + 1]; - switch (specifier) { - case 'b': - operands[0].vas = ARM64_VAS_1B; - break; - case 'h': - operands[0].vas = ARM64_VAS_1H; - break; - case 's': - operands[0].vas = ARM64_VAS_1S; - break; - case 'd': - operands[0].vas = ARM64_VAS_1D; - break; - - default: - break; - } - return; - } - if (opcode == Opcode::AArch64_DUP_ZZI_S || - opcode == Opcode::AArch64_DUP_ZZI_D || - opcode == Opcode::AArch64_DUP_ZZI_Q) { - // mov Zd.T, Vn; alias for dup Zd.T, Zn.T[0] - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - - uint8_t start = operandStr[2] == '.' ? 7 : 8; - uint8_t end = operandStr.length() - start; - - operands[1].reg = static_cast( - AARCH64_REG_Z0 + stoi(operandStr.substr(start, end))); - operands[1].vector_index = 0; - return; - } - if (opcode == Opcode::AArch64_INSvi32lane || - opcode == Opcode::AArch64_INSvi64lane) { - // mov vd.T[index1], vn.T[index2]; alias for ins vd.T[index1], - // vn.T[index2] - return; - } - if (opcode == Opcode::AArch64_ORRv8i8) { - // mov vd, vn; alias for orr vd.t, vn.t, vn.t - operandCount = 3; - - operands[2] = operands[1]; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - return; - } - if (opcode >= Opcode::AArch64_EXTRACT_ZPMXI_H_B && - opcode <= Opcode::AArch64_EXTRACT_ZPMXI_V_S) { - return; - } - if (opcode == Opcode::AArch64_ORRWri || - opcode == Opcode::AArch64_ORRWrs || - opcode == Opcode::AArch64_ORRXri || - opcode == Opcode::AArch64_ORRXrs) { - // mov rd, rn; alias for: orr rd, zr, rn - operandCount = 3; - operands[2] = operands[1]; - - operands[1].type = AARCH64_OP_REG; - operands[1].access = CS_AC_READ; - operands[1].shift = {ARM64_SFT_INVALID, 0}; - if (opcode == Opcode::AArch64_ORRWri || - opcode == Opcode::AArch64_ORRWrs) { - operands[1].reg = AARCH64_REG_WZR; - } else { - operands[1].reg = AARCH64_REG_XZR; - } - return; - } - if (opcode == Opcode::AArch64_ORR_PPzPP) { - // mov Pd.b, Pn.b; alias for: orr Pd.b, Pn/z, Pn.b, Pn.b - operandCount = 4; - operands[0].access = CS_AC_WRITE; - operands[0].vas = ARM64_VAS_1B; - operands[1].access = CS_AC_READ; - operands[1].vas = ARM64_VAS_1B; - operands[2] = operands[1]; - operands[3] = operands[1]; - return; - } - if (opcode == Opcode::AArch64_ORR_ZZZ) { - // mov Zd.d, Zn.d; alias for: orr Zd.d, Zn.d, Zn.d - operandCount = 3; - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2] = operands[1]; - return; - } - if (opcode == Opcode::AArch64_ORRv16i8) { - // mov Vd.16b, Vn.16b; alias for: orr Vd.16b, Vn.16b, Vn.16b - operandCount = 3; - operands[2] = operands[1]; - return; - } - if (opcode == Opcode::AArch64_SEL_ZPZZ_S || - opcode == Opcode::AArch64_SEL_ZPZZ_D) { - // mov Zd.T, Pg/M, Zn.T; alias for: sel Zd.T, Pg, Zn.T, Zd.T - if (mnemonic[0] == 'm') { - // SEL instructions id sometimes set as ARM64_INS_MOV even if - // aliasing hasn't occurred so double check mnemonic is MOV alias - operandCount = 4; - operands[3] = operands[0]; - operands[3].access = CS_AC_READ; - } - return; - } - if (opcode == Opcode::AArch64_UMOVvi8 || - opcode == Opcode::AArch64_UMOVvi16 || - opcode == Opcode::AArch64_UMOVvi32 || - opcode == Opcode::AArch64_UMOVvi64) { - // mov rd, Vn.T[index]; alias for umov rd, Vn.T[index] - return; - } - if (opcode == Opcode::AArch64_MOVZWi || - opcode == Opcode::AArch64_MOVZXi) { - // mov rd, #0; alias for: movz rd, #0{, shift #0} - operands[1].access = CS_AC_READ; - operands[1].shift = {ARM64_SFT_LSL, 0}; - return; - } - if (opcode == Opcode::AArch64_MOVNWi || - opcode == Opcode::AArch64_MOVNXi) { - // mov rd, #amount; alias for: movn rd, #amount{, shift #0} - operands[1].access = CS_AC_READ; - operands[1].shift = {ARM64_SFT_LSL, 0}; - operands[1].imm = ~(operands[1].imm); - return; - } - if (opcode == Opcode::AArch64_INSvi8gpr || - opcode == Opcode::AArch64_INSvi16gpr || - opcode == Opcode::AArch64_INSvi32gpr || - opcode == Opcode::AArch64_INSvi64gpr) { - // mov vd.ts[index], rn; alias for: ins vd.ts[index], rn - return; - } - if (opcode == Opcode::AArch64_UMOVvi32_idx0 || - opcode == Opcode::AArch64_UMOVvi64_idx0) { - // mov wd, vn.t[0]; alias for: umov wd, vn.t[0] - return; - } - return aliasNYI(); - case ARM64_INS_MUL: - // TODO add comment - if (opcode == Opcode::AArch64_MADDXrrr || - opcode == Opcode::AArch64_MADDWrrr) { - operandCount = 4; - operands[3].type = AARCH64_OP_REG; - operands[3].access = CS_AC_READ; - if (opcode == Opcode::AArch64_MADDWrrr) { - operands[3].reg = AARCH64_REG_WZR; - } else { - operands[3].reg = AARCH64_REG_XZR; - } - return; - } - if (opcode == Opcode::AArch64_MUL_ZPmZ_B || - opcode == Opcode::AArch64_MUL_ZPmZ_D || - opcode == Opcode::AArch64_MUL_ZPmZ_H || - opcode == Opcode::AArch64_MUL_ZPmZ_S) { - return; - } - return aliasNYI(); - case ARM64_INS_MVN: - if (opcode == Opcode::AArch64_ORNWrs || - opcode == Opcode::AArch64_ORNXrs) { - // mvn rd, rn; alias for: orn rd, zr, rn - operandCount = 3; - operands[2] = operands[1]; - - operands[1].type = AARCH64_OP_REG; - operands[1].access = CS_AC_READ; - operands[1].shift = {ARM64_SFT_INVALID, 0}; - if (opcode == Opcode::AArch64_ORNWrs) { - operands[1].reg = AARCH64_REG_WZR; - } else { - operands[1].reg = AARCH64_REG_XZR; - } - return; - } - if (opcode == Opcode::AArch64_NOTv16i8 || - opcode == Opcode::AArch64_NOTv8i8) { - // TODO needs tests - // mvn vd.t, vn.t; alias for : not vd.t, vn.t - // Blank entry was for a legitimate alias, however operands were - // identical so nothing to alter between the instructions. - return; - } - return aliasNYI(); - case ARM64_INS_NEG: - // TODO needs tests - if (opcode == Opcode::AArch64_SUBWrs || - opcode == Opcode::AArch64_SUBXrs) { - // neg rd, rm{, shift #amount}; alias for: - // sub rd, zr, rm{, shift #amount} - operandCount = 3; - operands[2] = operands[1]; - - operands[1].type = AARCH64_OP_REG; - operands[1].access = CS_AC_READ; - - if (opcode == Opcode::AArch64_SUBWrs) { - operands[1].reg = AARCH64_REG_WZR; - } else { - operands[1].reg = AARCH64_REG_XZR; - } - return; - } - if (opcode == Opcode::AArch64_NEGv2i64) { - // No alias present, trying to alias self. - return; - } - return aliasNYI(); - case ARM64_INS_NEGS: - if (opcode == Opcode::AArch64_SUBSWrs || - opcode == Opcode::AArch64_SUBSXrs) { - // negs rd, rm{, shift #amount}; alias for: - // subs rd, zr, rm{, shift #amount} - operandCount = 3; - operands[2] = operands[1]; - - operands[1].type = AARCH64_OP_REG; - operands[1].access = CS_AC_READ; - - if (opcode == Opcode::AArch64_SUBWrs) { - operands[1].reg = AARCH64_REG_WZR; - } else { - operands[1].reg = AARCH64_REG_XZR; - } - return; - } - return aliasNYI(); - case ARM64_INS_NGC: - return aliasNYI(); - case ARM64_INS_NGCS: - return aliasNYI(); - case ARM64_INS_NOT: - if (opcode == Opcode::AArch64_EOR_PPzPP) { - // not pd.b, pg/z, pn.b; alias for: eor pd.b, pg/z, pn.b, pg.b - operandCount = 4; - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3] = operands[1]; - return; - } - return aliasNYI(); - case ARM64_INS_REV64: - // rev64 vd.t, vn.t - if (opcode == Opcode::AArch64_REV64v16i8 || - opcode == Opcode::AArch64_REV64v2i32 || - opcode == Opcode::AArch64_REV64v4i16 || - opcode == Opcode::AArch64_REV64v4i32 || - opcode == Opcode::AArch64_REV64v8i16 || - opcode == Opcode::AArch64_REV64v8i8) { - operandCount = 2; - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - return; - } - return aliasNYI(); - case ARM64_INS_ROR: - // TODO needs test - if (opcode == Opcode::AArch64_RORVWr || - opcode == Opcode::AArch64_RORVXr) { - // ror wd, wn, wm; alias for : rorv wd, wn, wm - // ror xd, xn, xm; alias for : rorv xd, xn, xm - // Blank entry was for a legitimate alias, however operands were - // identical so nothing to alter between the instructions. - return; - } - return aliasNYI(); - case ARM64_INS_SBFIZ: - // TODO needs test - if (opcode == Opcode::AArch64_SBFMWri || - opcode == Opcode::AArch64_SBFMXri) { - operands[3].imm -= 1; - - uint8_t highestBit = 63; - if (opcode == Opcode::AArch64_SBFMWri) { - highestBit = 31; - } - - operands[2].imm = (-operands[2].imm) & highestBit; - return; - } - return aliasNYI(); - case ARM64_INS_SBFX: - // TODO needs test - if (opcode == Opcode::AArch64_SBFMWri || - opcode == Opcode::AArch64_SBFMXri) { - // sbfx rd, rn, #lsb, #width; alias for - // sbfm rd, rn, #lsb, #(lsb + width - 1) - operands[3].imm = operands[2].imm + operands[3].imm - 1; - return; - } - return aliasNYI(); - case ARM64_INS_SMNEGL: - return aliasNYI(); - case ARM64_INS_SMULL: - if (opcode == Opcode::AArch64_SMADDLrrr) { - operandCount = 4; - operands[3].type = AARCH64_OP_REG; - operands[3].access = CS_AC_READ; - operands[3].reg = AARCH64_REG_XZR; - return; - } - return aliasNYI(); - case ARM64_INS_SXTB: - // sxtb rd, rn; alias for: sbfm rd, rn, #0, #7 - if (opcode == Opcode::AArch64_SBFMWri || - opcode == Opcode::AArch64_SBFMXri) { - operandCount = 4; - - operands[2].type = AARCH64_OP_IMM; - operands[2].access = CS_AC_READ; - operands[2].imm = 0; - - operands[3].type = AARCH64_OP_IMM; - operands[3].access = CS_AC_READ; - operands[3].imm = 7; - return; - } - return aliasNYI(); - case ARM64_INS_SXTH: - // sxth rd, rn; alias for: sbfm rd, rn, #0, #15 - if (opcode == Opcode::AArch64_SBFMWri || - opcode == Opcode::AArch64_SBFMXri) { - operandCount = 4; - - operands[2].type = AARCH64_OP_IMM; - operands[2].access = CS_AC_READ; - operands[2].imm = 0; - - operands[3].type = AARCH64_OP_IMM; - operands[3].access = CS_AC_READ; - operands[3].imm = 15; - return; - } - return aliasNYI(); - case ARM64_INS_SXTW: - // sxtw rd, rn; alias for: sbfm rd, rn, #0, #31 - if (opcode == Opcode::AArch64_SBFMXri) { - operandCount = 4; - - operands[2].type = AARCH64_OP_IMM; - operands[2].access = CS_AC_READ; - operands[2].imm = 0; - - operands[3].type = AARCH64_OP_IMM; - operands[3].access = CS_AC_READ; - operands[3].imm = 31; - return; - } - if (opcode == Opcode::AArch64_SXTW_ZPmZ_D) { - return; - } - return aliasNYI(); - case ARM64_INS_SYS: { - // TODO no test - // Extract IC/DC/AT/TLBI operation - if (std::string(mnemonic) == "dc") { - if (operandStr.substr(0, 3) == "zva") { - id = ARM64_INS_DC; - operandCount = 3; - operands[1] = operands[0]; - operands[1].access = CS_AC_READ; - operands[0].type = AARCH64_OP_SYS; - operands[0].sys = ARM64_DC_ZVA; - operands[2].type = AARCH64_OP_REG_MRS; - operands[2].access = CS_AC_READ; - operands[2].imm = ARM64_SYSREG_DCZID_EL0; - return; - } - } - return aliasNYI(); - } - case ARM64_INS_TLBI: - return aliasNYI(); - case ARM64_INS_TST: - // TODO needs test for register case - if (opcode == Opcode::AArch64_ANDSWrs || - opcode == Opcode::AArch64_ANDSXrs || - opcode == Opcode::AArch64_ANDSWri || - opcode == Opcode::AArch64_ANDSXri) { - // tst rn, rm; alias for: ands zr, rn, rm - // tst rn, #imm; alias for: ands zr, rn, #imm - operandCount = 3; - operands[2] = operands[1]; - operands[1] = operands[0]; - operands[1].access = CS_AC_READ; - - operands[0].type = AARCH64_OP_REG; - operands[0].access = CS_AC_WRITE; - if (opcode == Opcode::AArch64_ANDSWrs || - opcode == Opcode::AArch64_ANDSWri) { - operands[0].reg = AARCH64_REG_WZR; - } else { - operands[0].reg = AARCH64_REG_XZR; - } - return; - } - return aliasNYI(); - case ARM64_INS_UBFIZ: - // TODO needs test and comment - if (opcode == Opcode::AArch64_UBFMWri || - opcode == Opcode::AArch64_UBFMXri) { - operands[3].imm -= 1; - - uint8_t highestBit = 63; - if (opcode == Opcode::AArch64_UBFMWri) { - highestBit = 31; - } - - operands[2].imm = (-operands[2].imm) & highestBit; - return; - } - return aliasNYI(); - case ARM64_INS_UBFX: - // TODO needs test - if (opcode == Opcode::AArch64_UBFMWri || - opcode == Opcode::AArch64_UBFMXri) { - // ubfx rd, rn, #lsb, #width; alias for - // ubfm rd, rn, #lsb, #(lsb + width - 1) - operands[3].imm = operands[2].imm + operands[3].imm - 1; - return; - } - return aliasNYI(); - case ARM64_INS_UMNEGL: - return aliasNYI(); - case ARM64_INS_UMULL: - // umull xd, wn, wm; alias for: umaddl xd, wn, wm, xzr - if (opcode == Opcode::AArch64_UMADDLrrr) { - operandCount = 4; - operands[3].type = AARCH64_OP_REG; - operands[3].access = CS_AC_READ; - operands[3].reg = AARCH64_REG_XZR; - return; - } - return aliasNYI(); - case ARM64_INS_UXTB: - // TODO needs test - // uxtb wd, wn; alias for: ubfm wd, wn, #0, #7 - if (opcode == Opcode::AArch64_UBFMWri) { - operandCount = 4; - operands[2].type = AARCH64_OP_IMM; - operands[2].access = CS_AC_READ; - operands[2].imm = 0; - operands[3].type = AARCH64_OP_IMM; - operands[3].access = CS_AC_READ; - operands[3].imm = 7; - return; - } - return aliasNYI(); - case ARM64_INS_UXTH: - return aliasNYI(); - } + // // Check mnemonics known to be aliases and see if their opcode matches + // // something else + // switch (id) { + // case AARCH64_INS_ASR: + // if (opcode == Opcode::AArch64_ASRVWr || + // opcode == Opcode::AArch64_ASRVXr) { + // // asr rd, rn, rm; alias for: asrv rd, rn, rm + // return; + // } + // if (opcode == Opcode::AArch64_SBFMWri || + // opcode == Opcode::AArch64_SBFMXri) { + // operandCount = 4; + + // operands[3].type = AARCH64_OP_IMM; + // operands[3].access = CS_AC_READ; + // if (opcode == Opcode::AArch64_SBFMWri) { + // // 32-bit + // operands[3].imm = 31; + // } else { + // operands[3].imm = 63; + // } + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_AT: + // return aliasNYI(); + // case AARCH64_INS_BFI: + // // TODO no tests of alias + // if (opcode == Opcode::AArch64_BFMWri) { + // // bfi wd, wn, #lsb, #width; alias for + // // bfm wd, wn, #(-lsb MOD 32), #(width - 1) + // operands[2].imm = static_cast(-operands[2].imm) % 32; + // operands[3].imm = operands[3].imm - 1; + // return; + // } + // if (opcode == Opcode::AArch64_BFMXri) { + // // bfi xd, xn, #lsb, #width; alias for + // // bfm xd, xn, #(-lsb MOD 64), #(width - 1) + // operands[2].imm = static_cast(-operands[2].imm) % 64; + // operands[3].imm = operands[3].imm - 1; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_BFXIL: + // // TODO no tests for alias + // if (opcode == Opcode::AArch64_BFMWri || + // opcode == Opcode::AArch64_BFMXri) { + // // bfxil rd, rn, #lsb, #width; alias for + // // bfm rd, rn, #lsb, #(lsb + width - 1) + // operands[3].imm = operands[2].imm + operands[3].imm - 1; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_CINC: + // if (opcode == Opcode::AArch64_CSINCWr || + // opcode == Opcode::AArch64_CSINCXr) { + // // cinc rd, rn, cc; alias for: csinc rd, rn, rn, invert(cc) + // operandCount = 3; + + // operands[2].type = AARCH64_OP_REG; + // operands[2].access = CS_AC_READ; + // operands[2].reg = operands[1].reg; + + // cc ^= 1; // invert lowest bit to negate cc + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_CINV: + // return aliasNYI(); + // case AARCH64_INS_CMN: + // // cmn , alias for adds + // operandCount = 3; + // operands[2] = operands[1]; + // operands[1] = operands[0]; + // operands[1].access = CS_AC_READ; + + // operands[0].type = AARCH64_OP_REG; + // operands[0].access = CS_AC_WRITE; + + // if (opcode == Opcode::AArch64_ADDSXri || + // opcode == Opcode::AArch64_ADDSXrr || + // opcode == Opcode::AArch64_ADDSXrs) { + // // 64-bit version + // operands[0].reg = AARCH64_REG_XZR; + // } else { + // // 32-bit version + // operands[0].reg = AARCH64_REG_WZR; + // } + // return; + // case AARCH64_INS_CMP: + // if (opcode == Opcode::AArch64_SUBSWri || + // opcode == Opcode::AArch64_SUBSWrs || + // opcode == Opcode::AArch64_SUBSWrx || + // opcode == Opcode::AArch64_SUBSXri || + // opcode == Opcode::AArch64_SUBSXrs || + // opcode == Opcode::AArch64_SUBSXrx || + // opcode == Opcode::AArch64_SUBSXrx64) { + // operandCount = 3; + // operands[2] = operands[1]; + + // operands[1] = operands[0]; + // operands[1].access = CS_AC_READ; + + // operands[0].type = AARCH64_OP_REG; + // operands[0].access = CS_AC_WRITE; + + // if (opcode == Opcode::AArch64_SUBSWri || + // opcode == Opcode::AArch64_SUBSWrs || + // opcode == Opcode::AArch64_SUBSWrx) { + // operands[0].reg = AARCH64_REG_WZR; + // } else { + // operands[0].reg = AARCH64_REG_XZR; + // } + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_CNEG: + // if (opcode == Opcode::AArch64_CSNEGWr || + // opcode == Opcode::AArch64_CSNEGXr) { + // // cneg rd, rn, cc; alias for: csneg rd, rn, rn, invert(cc) + // operandCount = 3; + // operands[2] = operands[1]; + // cc ^= 1; // invert lowest bit to negate cc + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_CSET: + // // TODO no usage in regression tests + // if (opcode == Opcode::AArch64_CSINCWr || + // opcode == Opcode::AArch64_CSINCXr) { + // // cset rd, cc; alias for: csinc rd, zr, zr, invert(cc) + // operandCount = 3; + + // operands[1].type = AARCH64_OP_REG; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + + // operands[2].type = AARCH64_OP_REG; + // operands[2].access = CS_AC_READ; + // operands[2].shift = {AARCH64_SFT_INVALID, 0}; + + // if (opcode == Opcode::AArch64_CSINCWr) { + // operands[1].reg = AARCH64_REG_WZR; + // operands[2].reg = AARCH64_REG_WZR; + // } else { + // operands[1].reg = AARCH64_REG_XZR; + // operands[2].reg = AARCH64_REG_XZR; + // } + + // cc ^= 1; // invert lowest bit to negate cc + + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_CSETM: + // if (opcode == Opcode::AArch64_CSINVWr || + // opcode == Opcode::AArch64_CSINVXr) { + // // csetm rd, cc; alias for: csinv rd, zr, zr, invert(cc) + // operandCount = 3; + + // operands[1].type = AARCH64_OP_REG; + // operands[1].access = CS_AC_READ; + + // operands[2].type = AARCH64_OP_REG; + // operands[2].access = CS_AC_READ; + + // if (opcode == Opcode::AArch64_CSINVWr) { + // operands[1].reg = AARCH64_REG_WZR; + // operands[2].reg = AARCH64_REG_WZR; + // } else { + // operands[1].reg = AARCH64_REG_XZR; + // operands[2].reg = AARCH64_REG_XZR; + // } + + // cc ^= 1; // invert lowest bit to negate cc + + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_DC: + // return aliasNYI(); + // case AARCH64_INS_IC: + // return aliasNYI(); + // case AARCH64_INS_LSL: + // // TODO no usage in regression tests + // if (opcode == Opcode::AArch64_UBFMWri || + // opcode == Opcode::AArch64_UBFMXri) { + // // lsl rd, rn, #shift; alias for: + // // ubfm rd, rn, #(-shift MOD <32|64>), #(<31|63> - shift) + // operandCount = 4; + // uint8_t highestBit = 63; + // if (opcode == Opcode::AArch64_UBFMWri) { + // highestBit = 31; + // } + + // auto shift = operands[2].imm; + // operands[2].imm = (-shift) & highestBit; + // operands[3].type = AARCH64_OP_IMM; + // operands[3].imm = highestBit - shift; + // operands[3].access = CS_AC_READ; + // return; + // } + // if (opcode == Opcode::AArch64_LSLVWr || + // opcode == Opcode::AArch64_LSLVXr || + // opcode == Opcode::AArch64_LSL_ZZI_S) { + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_LSR: + // if (opcode == Opcode::AArch64_LSRVWr || + // opcode == Opcode::AArch64_LSRVXr) { + // // lsr rd, rn, rm; alias for lsrv rd, rn, rm + // return; + // } + // if (opcode == Opcode::AArch64_UBFMWri || + // opcode == Opcode::AArch64_UBFMXri) { + // // lsr rd, rn, #amount; alias for ubfm rd, rn, #amount, #<31|63> + // operandCount = 4; + + // operands[3].type = AARCH64_OP_IMM; + // operands[3].access = CS_AC_READ; + + // if (opcode == Opcode::AArch64_UBFMWri) { + // operands[3].imm = 31; + // } else { + // operands[3].imm = 63; + // } + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_MNEG: + // // TODO no test + // if (opcode == Opcode::AArch64_MSUBXrrr) { + // // mneg xd, xn, xm; alias for msub xd, xn, xm, xzr + // operandCount = 4; + // operands[3].type = AARCH64_OP_REG; + // operands[3].access = CS_AC_READ; + // operands[3].reg = AARCH64_REG_XZR; + // return; + // } + // if (opcode == Opcode::AArch64_MSUBWrrr) { + // // mneg wd, wn, wm; alias for msub wd, wn, wm, wzr + // operandCount = 4; + // operands[3].type = AARCH64_OP_REG; + // operands[3].access = CS_AC_READ; + // operands[3].reg = AARCH64_REG_WZR; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_MOV: + // // TODO no specific tests + // if (opcode == Opcode::AArch64_AND_PPzPP) { + // // mov pd.b, pg/z, pn.b; alias for: and pd.b, pg/z, pn.b, pn.b + // operandCount = 4; + // operands[3] = operands[2]; + // return; + // } + // if (opcode == Opcode::AArch64_ADDXri || + // opcode == Opcode::AArch64_ADDWri) { + // // mov to/from sp; alias for: add , , #0 + // operandCount = 3; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].imm = 0; + // operands[2].access = CS_AC_READ; + // operands[2].shift.type = AARCH64_SFT_INVALID; + // operands[2].vas = AARCH64_VAS_INVALID; + // operands[2].vector_index = -1; + // return; + // } + // if (opcode == Opcode::AArch64_DUPi8 || opcode == + // Opcode::AArch64_DUPi16 + // || + // opcode == Opcode::AArch64_DUPi32 || + // opcode == Opcode::AArch64_DUPi64) { + // // mov vd, Vn.T[index]; alias of dup vd, Vn.T[index] + // return; + // } + // if (opcode == Opcode ::AArch64_CPY_ZPzI_B || + // opcode == Opcode ::AArch64_CPY_ZPzI_D || + // opcode == Opcode ::AArch64_CPY_ZPzI_H || + // opcode == Opcode ::AArch64_CPY_ZPzI_S) { + // // mov zd.T, pg/z, #imm{, shift}; alias of cpy zd.T, pg/z, #imm{, + // // shift} + // operandCount = 3; + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + + // // get imm value + // std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); + // auto value = std::stoi(tmpOpStr, 0, 16); + // operands[2].imm = tmpOpStr.length() == 4 ? + // static_cast(value) + // : + // static_cast(value); + // return; + // } + // if (opcode == Opcode::AArch64_DUPM_ZI || + // opcode == Opcode::AArch64_DUP_ZI_B || + // opcode == Opcode::AArch64_DUP_ZI_D || + // opcode == Opcode::AArch64_DUP_ZI_H || + // opcode == Opcode::AArch64_DUP_ZI_S) { + // // mov Zd.T, #imm; alias for dupm Zd.T, #imm + // // or + // // mov Zd.T, #imm{, shift}; alias for dup Zd.T, #imm{, shift} + // operandCount = 2; + // operands[0].access = CS_AC_WRITE; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].access = CS_AC_READ; + + // uint8_t start = operandStr[6] == '#' ? 7 : 8; + + // if (opcode == Opcode::AArch64_DUPM_ZI) { + // char specifier = operandStr[start - 4]; + // switch (specifier) { + // case 'b': + // operands[0].vas = AARCH64_VAS_1B; + // break; + // case 'h': + // operands[0].vas = AARCH64_VAS_1H; + // break; + // case 's': + // operands[0].vas = AARCH64_VAS_1S; + // break; + // case 'd': + // operands[0].vas = AARCH64_VAS_1D; + // break; + + // default: + // break; + // } + // } + + // bool hex = false; + // if (operandStr[start + 1] == 'x') { + // hex = true; + // start += 2; + // } + + // uint8_t end = start + 1; + // while (true) { + // if (operandStr[end] < '0') { + // break; + // } + // end++; + // } + + // std::string sub = operandStr.substr(start, end); + // if (hex) { + // operands[1].imm = std::stoul(sub, 0, 16); + // } else { + // operands[1].imm = stoi(sub); + // } + + // return; + // } + // if (opcode == Opcode::AArch64_DUP_ZR_S || + // opcode == Opcode::AArch64_DUP_ZR_D || + // opcode == Opcode::AArch64_DUP_ZR_B || + // opcode == Opcode::AArch64_DUP_ZR_H) { + // // mov Zd.T, ; alias for dup Zd.T, + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + + // char specifier = operandStr[operandStr.find(".") + 1]; + // switch (specifier) { + // case 'b': + // operands[0].vas = AARCH64_VAS_1B; + // break; + // case 'h': + // operands[0].vas = AARCH64_VAS_1H; + // break; + // case 's': + // operands[0].vas = AARCH64_VAS_1S; + // break; + // case 'd': + // operands[0].vas = AARCH64_VAS_1D; + // break; + + // default: + // break; + // } + // return; + // } + // if (opcode == Opcode::AArch64_DUP_ZZI_S || + // opcode == Opcode::AArch64_DUP_ZZI_D || + // opcode == Opcode::AArch64_DUP_ZZI_Q) { + // // mov Zd.T, Vn; alias for dup Zd.T, Zn.T[0] + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + + // uint8_t start = operandStr[2] == '.' ? 7 : 8; + // uint8_t end = operandStr.length() - start; + + // operands[1].reg = static_cast( + // AARCH64_REG_Z0 + stoi(operandStr.substr(start, end))); + // operands[1].vector_index = 0; + // return; + // } + // if (opcode == Opcode::AArch64_INSvi32lane || + // opcode == Opcode::AArch64_INSvi64lane) { + // // mov vd.T[index1], vn.T[index2]; alias for ins vd.T[index1], + // // vn.T[index2] + // return; + // } + // if (opcode == Opcode::AArch64_ORRv8i8) { + // // mov vd, vn; alias for orr vd.t, vn.t, vn.t + // operandCount = 3; + + // operands[2] = operands[1]; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // return; + // } + // if (opcode >= Opcode::AArch64_EXTRACT_ZPMXI_H_B && + // opcode <= Opcode::AArch64_EXTRACT_ZPMXI_V_S) { + // return; + // } + // if (opcode == Opcode::AArch64_ORRWri || + // opcode == Opcode::AArch64_ORRWrs || + // opcode == Opcode::AArch64_ORRXri || + // opcode == Opcode::AArch64_ORRXrs) { + // // mov rd, rn; alias for: orr rd, zr, rn + // operandCount = 3; + // operands[2] = operands[1]; + + // operands[1].type = AARCH64_OP_REG; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + // if (opcode == Opcode::AArch64_ORRWri || + // opcode == Opcode::AArch64_ORRWrs) { + // operands[1].reg = AARCH64_REG_WZR; + // } else { + // operands[1].reg = AARCH64_REG_XZR; + // } + // return; + // } + // if (opcode == Opcode::AArch64_ORR_PPzPP) { + // // mov Pd.b, Pn.b; alias for: orr Pd.b, Pn/z, Pn.b, Pn.b + // operandCount = 4; + // operands[0].access = CS_AC_WRITE; + // operands[0].vas = AARCH64_VAS_1B; + // operands[1].access = CS_AC_READ; + // operands[1].vas = AARCH64_VAS_1B; + // operands[2] = operands[1]; + // operands[3] = operands[1]; + // return; + // } + // if (opcode == Opcode::AArch64_ORR_ZZZ) { + // // mov Zd.d, Zn.d; alias for: orr Zd.d, Zn.d, Zn.d + // operandCount = 3; + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2] = operands[1]; + // return; + // } + // if (opcode == Opcode::AArch64_ORRv16i8) { + // // mov Vd.16b, Vn.16b; alias for: orr Vd.16b, Vn.16b, Vn.16b + // operandCount = 3; + // operands[2] = operands[1]; + // return; + // } + // if (opcode == Opcode::AArch64_SEL_ZPZZ_S || + // opcode == Opcode::AArch64_SEL_ZPZZ_D) { + // // mov Zd.T, Pg/M, Zn.T; alias for: sel Zd.T, Pg, Zn.T, Zd.T + // if (mnemonic[0] == 'm') { + // // SEL instructions id sometimes set as AARCH64_INS_MOV even if + // // aliasing hasn't occurred so double check mnemonic is MOV alias + // operandCount = 4; + // operands[3] = operands[0]; + // operands[3].access = CS_AC_READ; + // } + // return; + // } + // if (opcode == Opcode::AArch64_UMOVvi8 || + // opcode == Opcode::AArch64_UMOVvi16 || + // opcode == Opcode::AArch64_UMOVvi32 || + // opcode == Opcode::AArch64_UMOVvi64) { + // // mov rd, Vn.T[index]; alias for umov rd, Vn.T[index] + // return; + // } + // if (opcode == Opcode::AArch64_MOVZWi || + // opcode == Opcode::AArch64_MOVZXi) { + // // mov rd, #0; alias for: movz rd, #0{, shift #0} + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_LSL, 0}; + // return; + // } + // if (opcode == Opcode::AArch64_MOVNWi || + // opcode == Opcode::AArch64_MOVNXi) { + // // mov rd, #amount; alias for: movn rd, #amount{, shift #0} + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_LSL, 0}; + // operands[1].imm = ~(operands[1].imm); + // return; + // } + // if (opcode == Opcode::AArch64_INSvi8gpr || + // opcode == Opcode::AArch64_INSvi16gpr || + // opcode == Opcode::AArch64_INSvi32gpr || + // opcode == Opcode::AArch64_INSvi64gpr) { + // // mov vd.ts[index], rn; alias for: ins vd.ts[index], rn + // return; + // } + // if (opcode == Opcode::AArch64_UMOVvi32_idx0 || + // opcode == Opcode::AArch64_UMOVvi64_idx0) { + // // mov wd, vn.t[0]; alias for: umov wd, vn.t[0] + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_MUL: + // // TODO add comment + // if (opcode == Opcode::AArch64_MADDXrrr || + // opcode == Opcode::AArch64_MADDWrrr) { + // operandCount = 4; + // operands[3].type = AARCH64_OP_REG; + // operands[3].access = CS_AC_READ; + // if (opcode == Opcode::AArch64_MADDWrrr) { + // operands[3].reg = AARCH64_REG_WZR; + // } else { + // operands[3].reg = AARCH64_REG_XZR; + // } + // return; + // } + // if (opcode == Opcode::AArch64_MUL_ZPmZ_B || + // opcode == Opcode::AArch64_MUL_ZPmZ_D || + // opcode == Opcode::AArch64_MUL_ZPmZ_H || + // opcode == Opcode::AArch64_MUL_ZPmZ_S) { + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_MVN: + // if (opcode == Opcode::AArch64_ORNWrs || + // opcode == Opcode::AArch64_ORNXrs) { + // // mvn rd, rn; alias for: orn rd, zr, rn + // operandCount = 3; + // operands[2] = operands[1]; + + // operands[1].type = AARCH64_OP_REG; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + // if (opcode == Opcode::AArch64_ORNWrs) { + // operands[1].reg = AARCH64_REG_WZR; + // } else { + // operands[1].reg = AARCH64_REG_XZR; + // } + // return; + // } + // if (opcode == Opcode::AArch64_NOTv16i8 || + // opcode == Opcode::AArch64_NOTv8i8) { + // // TODO needs tests + // // mvn vd.t, vn.t; alias for : not vd.t, vn.t + // // Blank entry was for a legitimate alias, however operands were + // // identical so nothing to alter between the instructions. + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_NEG: + // // TODO needs tests + // if (opcode == Opcode::AArch64_SUBWrs || + // opcode == Opcode::AArch64_SUBXrs) { + // // neg rd, rm{, shift #amount}; alias for: + // // sub rd, zr, rm{, shift #amount} + // operandCount = 3; + // operands[2] = operands[1]; + + // operands[1].type = AARCH64_OP_REG; + // operands[1].access = CS_AC_READ; + + // if (opcode == Opcode::AArch64_SUBWrs) { + // operands[1].reg = AARCH64_REG_WZR; + // } else { + // operands[1].reg = AARCH64_REG_XZR; + // } + // return; + // } + // if (opcode == Opcode::AArch64_NEGv2i64) { + // // No alias present, trying to alias self. + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_NEGS: + // if (opcode == Opcode::AArch64_SUBSWrs || + // opcode == Opcode::AArch64_SUBSXrs) { + // // negs rd, rm{, shift #amount}; alias for: + // // subs rd, zr, rm{, shift #amount} + // operandCount = 3; + // operands[2] = operands[1]; + + // operands[1].type = AARCH64_OP_REG; + // operands[1].access = CS_AC_READ; + + // if (opcode == Opcode::AArch64_SUBWrs) { + // operands[1].reg = AARCH64_REG_WZR; + // } else { + // operands[1].reg = AARCH64_REG_XZR; + // } + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_NGC: + // return aliasNYI(); + // case AARCH64_INS_NGCS: + // return aliasNYI(); + // case AARCH64_INS_NOT: + // if (opcode == Opcode::AArch64_EOR_PPzPP) { + // // not pd.b, pg/z, pn.b; alias for: eor pd.b, pg/z, pn.b, pg.b + // operandCount = 4; + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3] = operands[1]; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_REV64: + // // rev64 vd.t, vn.t + // if (opcode == Opcode::AArch64_REV64v16i8 || + // opcode == Opcode::AArch64_REV64v2i32 || + // opcode == Opcode::AArch64_REV64v4i16 || + // opcode == Opcode::AArch64_REV64v4i32 || + // opcode == Opcode::AArch64_REV64v8i16 || + // opcode == Opcode::AArch64_REV64v8i8) { + // operandCount = 2; + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_ROR: + // // TODO needs test + // if (opcode == Opcode::AArch64_RORVWr || + // opcode == Opcode::AArch64_RORVXr) { + // // ror wd, wn, wm; alias for : rorv wd, wn, wm + // // ror xd, xn, xm; alias for : rorv xd, xn, xm + // // Blank entry was for a legitimate alias, however operands were + // // identical so nothing to alter between the instructions. + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_SBFIZ: + // // TODO needs test + // if (opcode == Opcode::AArch64_SBFMWri || + // opcode == Opcode::AArch64_SBFMXri) { + // operands[3].imm -= 1; + + // uint8_t highestBit = 63; + // if (opcode == Opcode::AArch64_SBFMWri) { + // highestBit = 31; + // } + + // operands[2].imm = (-operands[2].imm) & highestBit; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_SBFX: + // // TODO needs test + // if (opcode == Opcode::AArch64_SBFMWri || + // opcode == Opcode::AArch64_SBFMXri) { + // // sbfx rd, rn, #lsb, #width; alias for + // // sbfm rd, rn, #lsb, #(lsb + width - 1) + // operands[3].imm = operands[2].imm + operands[3].imm - 1; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_SMNEGL: + // return aliasNYI(); + // case AARCH64_INS_SMULL: + // if (opcode == Opcode::AArch64_SMADDLrrr) { + // operandCount = 4; + // operands[3].type = AARCH64_OP_REG; + // operands[3].access = CS_AC_READ; + // operands[3].reg = AARCH64_REG_XZR; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_SXTB: + // // sxtb rd, rn; alias for: sbfm rd, rn, #0, #7 + // if (opcode == Opcode::AArch64_SBFMWri || + // opcode == Opcode::AArch64_SBFMXri) { + // operandCount = 4; + + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // operands[2].imm = 0; + + // operands[3].type = AARCH64_OP_IMM; + // operands[3].access = CS_AC_READ; + // operands[3].imm = 7; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_SXTH: + // // sxth rd, rn; alias for: sbfm rd, rn, #0, #15 + // if (opcode == Opcode::AArch64_SBFMWri || + // opcode == Opcode::AArch64_SBFMXri) { + // operandCount = 4; + + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // operands[2].imm = 0; + + // operands[3].type = AARCH64_OP_IMM; + // operands[3].access = CS_AC_READ; + // operands[3].imm = 15; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_SXTW: + // // sxtw rd, rn; alias for: sbfm rd, rn, #0, #31 + // if (opcode == Opcode::AArch64_SBFMXri) { + // operandCount = 4; + + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // operands[2].imm = 0; + + // operands[3].type = AARCH64_OP_IMM; + // operands[3].access = CS_AC_READ; + // operands[3].imm = 31; + // return; + // } + // if (opcode == Opcode::AArch64_SXTW_ZPmZ_D) { + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_SYS: { + // // TODO no test + // // Extract IC/DC/AT/TLBI operation + // if (std::string(mnemonic) == "dc") { + // if (operandStr.substr(0, 3) == "zva") { + // id = AARCH64_INS_DC; + // operandCount = 3; + // operands[1] = operands[0]; + // operands[1].access = CS_AC_READ; + // operands[0].type = AARCH64_OP_SYS; + // operands[0].sys = AARCH64_DC_ZVA; + // operands[2].type = AARCH64_OP_REG_MRS; + // operands[2].access = CS_AC_READ; + // operands[2].imm = AARCH64_SYSREG_DCZID_EL0; + // return; + // } + // } + // return aliasNYI(); + // } + // case AARCH64_INS_TLBI: + // return aliasNYI(); + // case AARCH64_INS_TST: + // // TODO needs test for register case + // if (opcode == Opcode::AArch64_ANDSWrs || + // opcode == Opcode::AArch64_ANDSXrs || + // opcode == Opcode::AArch64_ANDSWri || + // opcode == Opcode::AArch64_ANDSXri) { + // // tst rn, rm; alias for: ands zr, rn, rm + // // tst rn, #imm; alias for: ands zr, rn, #imm + // operandCount = 3; + // operands[2] = operands[1]; + // operands[1] = operands[0]; + // operands[1].access = CS_AC_READ; + + // operands[0].type = AARCH64_OP_REG; + // operands[0].access = CS_AC_WRITE; + // if (opcode == Opcode::AArch64_ANDSWrs || + // opcode == Opcode::AArch64_ANDSWri) { + // operands[0].reg = AARCH64_REG_WZR; + // } else { + // operands[0].reg = AARCH64_REG_XZR; + // } + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_UBFIZ: + // // TODO needs test and comment + // if (opcode == Opcode::AArch64_UBFMWri || + // opcode == Opcode::AArch64_UBFMXri) { + // operands[3].imm -= 1; + + // uint8_t highestBit = 63; + // if (opcode == Opcode::AArch64_UBFMWri) { + // highestBit = 31; + // } + + // operands[2].imm = (-operands[2].imm) & highestBit; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_UBFX: + // // TODO needs test + // if (opcode == Opcode::AArch64_UBFMWri || + // opcode == Opcode::AArch64_UBFMXri) { + // // ubfx rd, rn, #lsb, #width; alias for + // // ubfm rd, rn, #lsb, #(lsb + width - 1) + // operands[3].imm = operands[2].imm + operands[3].imm - 1; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_UMNEGL: + // return aliasNYI(); + // case AARCH64_INS_UMULL: + // // umull xd, wn, wm; alias for: umaddl xd, wn, wm, xzr + // if (opcode == Opcode::AArch64_UMADDLrrr) { + // operandCount = 4; + // operands[3].type = AARCH64_OP_REG; + // operands[3].access = CS_AC_READ; + // operands[3].reg = AARCH64_REG_XZR; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_UXTB: + // // TODO needs test + // // uxtb wd, wn; alias for: ubfm wd, wn, #0, #7 + // if (opcode == Opcode::AArch64_UBFMWri) { + // operandCount = 4; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // operands[2].imm = 0; + // operands[3].type = AARCH64_OP_IMM; + // operands[3].access = CS_AC_READ; + // operands[3].imm = 7; + // return; + // } + // return aliasNYI(); + // case AARCH64_INS_UXTH: + // return aliasNYI(); + // } } void InstructionMetadata::aliasNYI() { diff --git a/src/lib/arch/aarch64/InstructionMetadata.hh b/src/lib/arch/aarch64/InstructionMetadata.hh index dfd38cd8d0..9e44b1980f 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.hh +++ b/src/lib/arch/aarch64/InstructionMetadata.hh @@ -53,7 +53,7 @@ struct InstructionMetadata { static const size_t MAX_GROUPS = sizeof(cs_detail::groups) / sizeof(uint8_t); /** The maximum number of operands as defined in Capstone */ static const size_t MAX_OPERANDS = - sizeof(cs_arm64::operands) / sizeof(cs_aarch64_op); + sizeof(cs_aarch64::operands) / sizeof(cs_aarch64_op); /** The instruction's mnemonic ID. */ unsigned int id; diff --git a/src/lib/arch/aarch64/Instruction_address.cc b/src/lib/arch/aarch64/Instruction_address.cc index 6ff4fd99a9..7462e0ab1b 100644 --- a/src/lib/arch/aarch64/Instruction_address.cc +++ b/src/lib/arch/aarch64/Instruction_address.cc @@ -290,8 +290,8 @@ span Instruction::generateAddresses() { setMemoryAddresses({base + offset, static_cast(VL_bits / 8)}); break; } - case Opcode::AArch64_LD1B_IMM_REAL: { // ld1b {zt.b}, pg/z, [xn{, #imm, - // mul vl}] + case Opcode::AArch64_LD1B_IMM: { // ld1b {zt.b}, pg/z, [xn{, #imm, + // mul vl}] const uint64_t base = sourceValues_[1].get(); const int64_t offset = static_cast(metadata_.operands[2].mem.disp); @@ -308,8 +308,8 @@ span Instruction::generateAddresses() { setMemoryAddresses({addr, static_cast(VL_bits / 8)}); break; } - case Opcode::AArch64_LD1D_IMM_REAL: { // ld1d {zt.d}, pg/z, [xn{, #imm, - // mul vl}] + case Opcode::AArch64_LD1D_IMM: { // ld1d {zt.d}, pg/z, [xn{, #imm, + // mul vl}] const uint16_t partition_num = VL_bits / 64; const uint64_t base = sourceValues_[1].get(); @@ -336,8 +336,8 @@ span Instruction::generateAddresses() { setMemoryAddresses({addr, static_cast(VL_bits / 8)}); break; } - case Opcode::AArch64_LD1W_IMM_REAL: { // ld1w {zt.s}, pg/z, [xn{, #imm, - // mul vl}] + case Opcode::AArch64_LD1W_IMM: { // ld1w {zt.s}, pg/z, [xn{, #imm, + // mul vl}] const uint16_t partition_num = VL_bits / 32; const uint64_t base = sourceValues_[1].get(); @@ -847,7 +847,7 @@ span Instruction::generateAddresses() { setMemoryAddresses(std::move(addresses)); break; } - case Opcode::AArch64_SST1B_D_REAL: { // st1b {zd.d}, pg, [xn, zm.d] + case Opcode::AArch64_SST1B_D: { // st1b {zd.d}, pg, [xn, zm.d] const uint64_t* p = sourceValues_[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -866,7 +866,7 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_SST1D_REAL: { // st1d {zt.d}, pg, [xn, zm.d] + case Opcode::AArch64_SST1D: { // st1d {zt.d}, pg, [xn, zm.d] const uint64_t* p = sourceValues_[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -886,8 +886,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { // st1d {zt.d}, pg, [xn, - // zm.d, lsl #3] + case Opcode::AArch64_SST1D_SCALED: { // st1d {zt.d}, pg, [xn, + // zm.d, lsl #3] const uint64_t* p = sourceValues_[1].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1090,7 +1090,7 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1D_REAL: { // ld1d {zt.d}, pg/z, [xn, zm.d] + case Opcode::AArch64_GLD1D: { // ld1d {zt.d}, pg/z, [xn, zm.d] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1110,8 +1110,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1D_SCALED_REAL: { // ld1d {zt.d}, pg/z, [xn, - // zm.d, LSL #3] + case Opcode::AArch64_GLD1D_SCALED: { // ld1d {zt.d}, pg/z, [xn, + // zm.d, LSL #3] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1131,8 +1131,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1D_IMM_REAL: { // ld1d {zd.d}, pg/z, [zn.d{, - // #imm}] + case Opcode::AArch64_GLD1D_IMM: { // ld1d {zd.d}, pg/z, [zn.d{, + // #imm}] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1153,8 +1153,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1SW_D_IMM_REAL: { // ld1sw {zd.d}, pg/z, - // [zn.d{, #imm}] + case Opcode::AArch64_GLD1SW_D_IMM: { // ld1sw {zd.d}, pg/z, + // [zn.d{, #imm}] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1175,8 +1175,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1W_D_SCALED_REAL: { // ld1w {zd.d}, pg/z, - // [, zm.d, lsl #2] + case Opcode::AArch64_GLD1W_D_SCALED: { // ld1w {zd.d}, pg/z, + // [, zm.d, lsl #2] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1196,8 +1196,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1W_SXTW_REAL: { // ld1w {zd.s}, pg/z, - // [, zm.s, sxtw] + case Opcode::AArch64_GLD1W_SXTW: { // ld1w {zd.s}, pg/z, + // [, zm.s, sxtw] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index f6aec59456..b03934d81b 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -23,9 +23,6 @@ constexpr uint32_t bits(uint32_t value, uint8_t start, uint8_t width) { return ((value >> start) & ((1 << width) - 1)); } -// Generate a general purpose register identifier with tag `tag` -constexpr Register genReg(uint16_t tag) { return {RegisterType::GENERAL, tag}; } - // Generate a NZCV register identifier constexpr Register nzcvReg() { return {RegisterType::NZCV, 0}; } @@ -43,59 +40,77 @@ constexpr int32_t signExtend(uint32_t value, int currentLength) { * `aarch64_reg` enum. Updates to the Capstone library version may cause this to * break. */ Register csRegToRegister(aarch64_reg reg) { - // Check from top of the range downwards + // Do not need check for AARCH64_REG_Vn as in Capstone, they are aliased as Qn + // (full vector) or Dn (half vector). + // As D and Q registers are also of type RegisterType::VECTOR, the outcome + // will be the same - // AARCH64_REG_V0 -> {end} are vector registers, reading from the vector file - if (reg >= AARCH64_REG_V0) { - return {RegisterType::VECTOR, static_cast(reg - AARCH64_REG_V0)}; - } + // Assert that reg is not a SME tile as these should be passed to + // `getZARowVectors()` + assert(reg != AARCH64_REG_ZA); + assert(!(AARCH64_REG_ZAB0 <= reg && reg <= AARCH64_REG_ZAS3)); - // AARCH64_REG_ZAB0 -> +31 are tiles of the matrix register (ZA), reading from - // the matrix file. - if (reg >= AARCH64_REG_ZAB0) { - // Placeholder value returned as each tile (what the enum represents) - // consists of multiple vectors (rows) - return {RegisterType::MATRIX, 0}; + // AARCH64_REG_ZT0 is a fixed with Table register, reading from the table + // register file. + if (reg == AARCH64_REG_ZT0) { + return {RegisterType::TABLE, 0}; } // AARCH64_REG_Z0 -> +31 are scalable vector registers (Z) registers, reading // from the vector file - if (reg >= AARCH64_REG_Z0) { + if (AARCH64_REG_Z0 <= reg && reg <= AARCH64_REG_Z31) { return {RegisterType::VECTOR, static_cast(reg - AARCH64_REG_Z0)}; } // AARCH64_REG_X0 -> +28 are 64-bit (X) registers, reading from the general // file. Excludes #29 (FP) and #30 (LR) - if (reg >= AARCH64_REG_X0) { + if (AARCH64_REG_X0 <= reg && reg <= AARCH64_REG_X28) { return {RegisterType::GENERAL, static_cast(reg - AARCH64_REG_X0)}; } // AARCH64_REG_W0 -> +30 are 32-bit (W) registers, reading from the general // file. Excludes #31 (WZR/WSP). - if (reg >= AARCH64_REG_W0) { + if (AARCH64_REG_W0 <= reg && reg <= AARCH64_REG_W30) { return {RegisterType::GENERAL, static_cast(reg - AARCH64_REG_W0)}; } - // AARCH64_REG_Q0 and above are repeated ranges representing scalar access - // specifiers on the vector registers with arrangements Q and S, each - // covering 32 registers - if (reg >= AARCH64_REG_Q0) { - return {RegisterType::VECTOR, - static_cast((reg - AARCH64_REG_Q0) % 32)}; + // AARCH64_REG_Q0 -> +31 are 128-bit registers representing scalar access + // specifiers on the vector registers + if (AARCH64_REG_Q0 <= reg && reg <= AARCH64_REG_Q31) { + return {RegisterType::VECTOR, static_cast(reg - AARCH64_REG_Q0)}; } - // AARCH64_REG_P0 -> +15 are 256-bit (P) registers. Excludes #16 (FFR). - if (reg >= AARCH64_REG_P0) { - return {RegisterType::PREDICATE, - static_cast(reg - AARCH64_REG_P0)}; + // AARCH64_REG_D0 -> +31 are 64-bit registers representing scalar access + // specifiers on the vector registers + if (AARCH64_REG_D0 <= reg && reg <= AARCH64_REG_D31) { + return {RegisterType::VECTOR, static_cast(reg - AARCH64_REG_D0)}; + } + + // AARCH64_REG_S0 -> +31 are 32-bit registers representing scalar access + // specifiers on the vector registers + if (AARCH64_REG_S0 <= reg && reg <= AARCH64_REG_S31) { + return {RegisterType::VECTOR, static_cast(reg - AARCH64_REG_S0)}; + } + + // AARCH64_REG_H0 -> +31 are 16-bit registers representing scalar access + // specifiers on the vector registers + if (AARCH64_REG_H0 <= reg && reg <= AARCH64_REG_H31) { + return {RegisterType::VECTOR, static_cast(reg - AARCH64_REG_H0)}; } - // AARCH64_REG_Q0 and above are repeated ranges representing scalar access - // specifiers on the vector registers with arrangements B, D and H, each - // covering 32 registers - if (reg >= AARCH64_REG_B0) { - return {RegisterType::VECTOR, - static_cast((reg - AARCH64_REG_B0) % 32)}; + // AARCH64_REG_B0 -> +31 are 8-bit registers representing scalar access + // specifiers on the vector registers + if (AARCH64_REG_B0 <= reg && reg <= AARCH64_REG_B31) { + return {RegisterType::VECTOR, static_cast(reg - AARCH64_REG_B0)}; + } + + // AARCH64_REG_P0 -> +15 are 256-bit (P) "predicate-as-mask" registers. + // Excludes #16 (FFR). + // AARCH64_REG_PN0 -> +15 are 256-bit (PN) "predicate-as-counter" registers. + if (AARCH64_REG_P0 <= reg && reg <= AARCH64_REG_PN15) { + return {RegisterType::PREDICATE, + static_cast(static_cast(reg - AARCH64_REG_P0) % + 16u)}; } // AARCH64_REG_WZR and _XZR are zero registers, and don't read @@ -126,14 +141,6 @@ Register csRegToRegister(aarch64_reg reg) { return {RegisterType::PREDICATE, 16}; } - // The matrix register (ZA) can also be referenced as a whole in some - // instructions. - if (reg == AARCH64_REG_ZA) { - // Placeholder value returned as each tile (what the enum represents) - // consists of multiple vectors (rows) - return {RegisterType::MATRIX, 0}; - } - assert(false && "Decoding failed due to unknown register identifier"); return {std::numeric_limits::max(), std::numeric_limits::max()}; @@ -184,18 +191,26 @@ std::vector getZARowVectors(aarch64_reg reg, * DECODING LOGIC *****************/ void Instruction::decode() { - if (metadata_.id == ARM64_INS_INVALID) { + if (metadata_.id == AARCH64_INS_INVALID) { exception_ = InstructionException::EncodingUnallocated; exceptionEncountered_ = true; return; } - // Extract implicit writes + // Extract implicit writes, including pre/post index writeback for (size_t i = 0; i < metadata_.implicitDestinationCount; i++) { + if (metadata_.implicitDestinations[i] == AARCH64_REG_NZCV && + (metadata_.opcode == Opcode::AArch64_MRS || + metadata_.opcode == Opcode::AArch64_MSR)) { + // MRS / MSR instructions mistakenly have NZCV added as an implicit + // destination. Ignore + continue; + } destinationRegisters_[destinationRegisterCount_] = csRegToRegister( static_cast(metadata_.implicitDestinations[i])); destinationRegisterCount_++; } + // Extract implicit reads for (size_t i = 0; i < metadata_.implicitSourceCount; i++) { sourceRegisters_[sourceOperandsPending_] = @@ -215,181 +230,146 @@ void Instruction::decode() { if (op.reg != AARCH64_REG_WZR && op.reg != AARCH64_REG_XZR) { // Determine the data type the instruction operates on based on the // register operand used - // Belongs to the predicate group if the destination register is a - // predicate - if (op.reg >= AARCH64_REG_V0) { + // SME and Predicate based operations use individual op.type + if (op.is_vreg) { setInstructionType(InsnType::isVectorData); - } else if (op.reg >= AARCH64_REG_ZAB0 || op.reg == AARCH64_REG_ZA) { - setInstructionType(InsnType::isSMEData); - } else if (op.reg >= AARCH64_REG_Z0) { + } else if ((AARCH64_REG_Z31 <= op.reg && op.reg >= AARCH64_REG_Z0) || + op.reg == AARCH64_REG_ZT0) { + // zT0 is an SME register, but we declare it as an SVE instruction + // due to its 1D format. setInstructionType(InsnType::isSVEData); } else if (op.reg <= AARCH64_REG_S31 && op.reg >= AARCH64_REG_Q0) { setInstructionType(InsnType::isScalarData); - } else if (op.reg <= AARCH64_REG_P15 && op.reg >= AARCH64_REG_P0) { - setInstructionType(InsnType::isPredicate); } else if (op.reg <= AARCH64_REG_H31 && op.reg >= AARCH64_REG_B0) { setInstructionType(InsnType::isScalarData); } - if ((op.reg >= AARCH64_REG_ZAB0 && op.reg < AARCH64_REG_V0) || - (op.reg == AARCH64_REG_ZA)) { - // Add all Matrix register rows as destination operands - std::vector regs = getZARowVectors( - op.reg, architecture_.getStreamingVectorLength()); - // Update operand structure sizes - sourceRegisters_.addSMEOperand(regs.size()); - destinationRegisters_.addSMEOperand(regs.size()); - sourceValues_.addSMEOperand(regs.size()); - results_.addSMEOperand(regs.size()); - for (size_t i = 0; i < regs.size(); i++) { - destinationRegisters_[destinationRegisterCount_] = regs[i]; - destinationRegisterCount_++; - // If WRITE, also need to add to source registers to maintain - // unaltered row values - sourceRegisters_[sourceRegisterCount_] = regs[i]; - sourceRegisterCount_++; - sourceOperandsPending_++; - } - } else { - // Add register writes to destinations, but skip zero-register - // destinations - destinationRegisters_[destinationRegisterCount_] = - csRegToRegister(op.reg); - destinationRegisterCount_++; - } + // Add register writes to destinations, but skip zero-register + // destinations + destinationRegisters_[destinationRegisterCount_] = + csRegToRegister(op.reg); + destinationRegisterCount_++; } } if (op.access & cs_ac_type::CS_AC_READ) { - if ((op.reg >= AARCH64_REG_ZAB0 && op.reg < AARCH64_REG_V0) || - (op.reg == AARCH64_REG_ZA)) { - // Add all Matrix register rows as source operands - std::vector regs = - getZARowVectors(op.reg, architecture_.getStreamingVectorLength()); - // Update source operand structure sizes - sourceRegisters_.addSMEOperand(regs.size()); - sourceValues_.addSMEOperand(regs.size()); - for (size_t i = 0; i < regs.size(); i++) { - sourceRegisters_[sourceRegisterCount_] = regs[i]; - sourceRegisterCount_++; - sourceOperandsPending_++; - } - } else { - // Add register reads to destinations - sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.reg); - sourceRegisterCount_++; - sourceOperandsPending_++; - } + // Add register reads to destinations + + sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.reg); + sourceRegisterCount_++; + sourceOperandsPending_++; + // TODO checking of the shift type is a temporary fix to help reduce the // chance of incorrectly reverted aliases from being mis-classified as // isShift when op.shift contains garbage data. This should be reviewed // on the next capstone update which should remove the need to revert // aliasing - if (op.shift.type > arm64_shifter::ARM64_SFT_INVALID && - op.shift.type <= arm64_shifter::ARM64_SFT_ROR && + if (op.shift.type > aarch64_shifter::AARCH64_SFT_INVALID && + op.shift.type <= aarch64_shifter::AARCH64_SFT_ROR && op.shift.value > 0) { setInstructionType(InsnType::isShift); // Identify shift operands } } } else if (op.type == AARCH64_OP_MEM) { // Memory operand - accessesMemory = true; - sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.mem.base); - sourceRegisterCount_++; - sourceOperandsPending_++; - - if (metadata_.writeback) { - // Writeback instructions modify the base address - destinationRegisters_[destinationRegisterCount_] = - csRegToRegister(op.mem.base); - destinationRegisterCount_++; + // Check base register exists + if (op.mem.base != AARCH64_REG_INVALID) { + accessesMemory = true; + sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.mem.base); + sourceRegisterCount_++; + sourceOperandsPending_++; } - if (op.mem.index) { + + // if (metadata_.writeback) { + // // Writeback instructions modify the base address + // destinationRegisters_[destinationRegisterCount_] = + // csRegToRegister(op.mem.base); + // destinationRegisterCount_++; + // } + if (op.mem.index != AARCH64_REG_INVALID) { // Register offset; add to sources sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.mem.index); sourceRegisterCount_++; sourceOperandsPending_++; } - } else if (op.type == AARCH64_OP_SME_INDEX) { // SME instruction with index - std::vector regs; - if ((op.sme_index.reg >= AARCH64_REG_ZAB0 && - op.sme_index.reg < AARCH64_REG_V0) || - (op.sme_index.reg == AARCH64_REG_ZA)) { - // Set instruction group - setInstructionType(InsnType::isSMEData); - regs = getZARowVectors(op.sme_index.reg, - architecture_.getStreamingVectorLength()); - // Update operands structure sizes - destinationRegisters_.addSMEOperand(regs.size()); - results_.addSMEOperand(regs.size()); - sourceRegisters_.addSMEOperand(regs.size()); - sourceValues_.addSMEOperand(regs.size()); - for (size_t i = 0; i < regs.size(); i++) { - // If READ access, we only need to add SME rows to source registers. - // If WRITE access, then we need to add SME rows to destination - // registers AND source registers. The latter is required to maintain - // any un-updated rows given that an SME_INDEX op will specify only - // one row (or column) to write to. - sourceRegisters_[sourceRegisterCount_] = regs[i]; - sourceRegisterCount_++; - sourceOperandsPending_++; - if (op.access & cs_ac_type::CS_AC_WRITE) { - destinationRegisters_[destinationRegisterCount_] = regs[i]; - destinationRegisterCount_++; - } - } - } else { - // SME_INDEX can also be for predicate - // Set instruction group - setInstructionType(InsnType::isPredicate); + + } else if (op.type == AARCH64_OP_SME) { + setInstructionType(InsnType::isSMEData); + std::vector regs = getZARowVectors( + op.sme.tile, architecture_.getStreamingVectorLength()); + // Update operands structure sizes + destinationRegisters_.addSMEOperand(regs.size()); + results_.addSMEOperand(regs.size()); + sourceRegisters_.addSMEOperand(regs.size()); + sourceValues_.addSMEOperand(regs.size()); + for (size_t i = 0; i < regs.size(); i++) { + // If READ access, we only need to add SME rows to source registers. + // If WRITE access, then we need to add SME rows to destination + // registers AND source registers. The latter is required to maintain + // any un-updated rows if an SME op will specifies + // one row (or column) to write to. + sourceRegisters_[sourceRegisterCount_] = regs[i]; + sourceRegisterCount_++; + sourceOperandsPending_++; if (op.access & cs_ac_type::CS_AC_WRITE) { - destinationRegisters_[destinationRegisterCount_] = - csRegToRegister(op.sme_index.reg); + destinationRegisters_[destinationRegisterCount_] = regs[i]; destinationRegisterCount_++; - } else if (op.access & cs_ac_type::CS_AC_READ) { - sourceRegisters_[sourceRegisterCount_] = - csRegToRegister(op.sme_index.reg); - sourceRegisterCount_++; - sourceOperandsPending_++; } } - // Register that is base of index will always be a source operand - sourceRegisters_[sourceRegisterCount_] = - csRegToRegister(op.sme_index.base); - sourceRegisterCount_++; - sourceOperandsPending_++; - } else if (op.type == AARCH64_OP_REG_MRS) { - int32_t sysRegTag = architecture_.getSystemRegisterTag(op.imm); + if (op.sme.type == AARCH64_SME_OP_TILE_VEC) { + // SME tile has slice determined by register and immidiate. + // Add base register to source operands + sourceRegisters_[sourceRegisterCount_] = + csRegToRegister(op.sme.slice_reg); + sourceRegisterCount_++; + sourceOperandsPending_++; + } + } else if (op.type == AARCH64_OP_PRED) { + if (op.access == CS_AC_READ) { + sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.pred.reg); + sourceRegisterCount_++; + sourceOperandsPending_++; + } + if (op.access == CS_AC_WRITE) { + destinationRegisters_[destinationRegisterCount_] = + csRegToRegister(op.pred.reg); + destinationRegisterCount_++; + } + if (op.pred.vec_select != AARCH64_REG_INVALID) { + sourceRegisters_[sourceRegisterCount_] = + csRegToRegister(op.pred.vec_select); + sourceRegisterCount_++; + sourceOperandsPending_++; + } + } else if (op.type == AARCH64_OP_SYSREG) { + int32_t sysRegTag = + architecture_.getSystemRegisterTag(op.sysop.reg.sysreg); + // Check SYSREG is supported if (sysRegTag == -1) { exceptionEncountered_ = true; exception_ = InstructionException::UnmappedSysReg; return; - } else { + } + if (op.sysop.sub_type == AARCH64_OP_REG_MRS) { sourceRegisters_[sourceRegisterCount_] = { RegisterType::SYSTEM, static_cast(sysRegTag)}; sourceRegisterCount_++; sourceOperandsPending_++; } - } else if (op.type == AARCH64_OP_REG_MSR) { - int32_t sysRegTag = architecture_.getSystemRegisterTag(op.imm); - if (sysRegTag == -1) { - exceptionEncountered_ = true; - exception_ = InstructionException::UnmappedSysReg; - return; - } else { + if (op.sysop.sub_type == AARCH64_OP_REG_MSR) { destinationRegisters_[destinationRegisterCount_] = { RegisterType::SYSTEM, static_cast(sysRegTag)}; destinationRegisterCount_++; } - } else if (op.type == AARCH64_OP_SVCR) { + } else if (metadata_.operands[0].type == AARCH64_OP_SYSALIAS && + metadata_.operands[0].sysop.sub_type == AARCH64_OP_SVCR) { // Updating of SVCR is done via an exception and not via the sysreg file. // No operands are required for this operation. - // Any access to SVCR other than SMSTART and SMSTOP (i.e. this OP_TYPE) - // will result in an `unmapped system register` exception. } } // Identify branches for (size_t i = 0; i < metadata_.groupCount; i++) { - if (metadata_.groups[i] == ARM64_GRP_JUMP) { + if (metadata_.groups[i] == AARCH64_GRP_JUMP || + metadata_.groups[i] == AARCH64_GRP_BRANCH_RELATIVE) { setInstructionType(InsnType::isBranch); } } @@ -465,7 +445,8 @@ void Instruction::decode() { // Check first operand access to determine if it's a load or store if (metadata_.operands[0].access & CS_AC_WRITE) { - if (metadata_.id == ARM64_INS_STXR || metadata_.id == ARM64_INS_STLXR) { + if (metadata_.id == AARCH64_INS_STXR || + metadata_.id == AARCH64_INS_STLXR) { // Exceptions to this is load condition are exclusive store with a // success flag as first operand if (microOpcode_ != MicroOpcode::STR_DATA) { @@ -487,7 +468,8 @@ void Instruction::decode() { } // LDADD* are considered to be both a load and a store - if (metadata_.id >= ARM64_INS_LDADD && metadata_.id <= ARM64_INS_LDADDLH) { + if (AARCH64_INS_LDADDAB <= metadata_.id && + metadata_.id <= AARCH64_INS_LDADD) { setInstructionType(InsnType::isLoad); setInstructionType(InsnType::isStoreData); } @@ -509,10 +491,10 @@ void Instruction::decode() { (metadata_.operands[0].reg <= AARCH64_REG_H31 && metadata_.operands[0].reg >= AARCH64_REG_B0)) { setInstructionType(InsnType::isScalarData); - } else if (metadata_.operands[0].reg >= AARCH64_REG_V0) { + } else if (metadata_.operands[0].is_vreg) { setInstructionType(InsnType::isVectorData); } else if ((metadata_.operands[0].reg >= AARCH64_REG_ZAB0 && - metadata_.operands[0].reg < AARCH64_REG_V0) || + metadata_.operands[0].reg <= AARCH64_REG_ZT0) || metadata_.operands[0].reg == AARCH64_REG_ZA) { setInstructionType(InsnType::isSMEData); } diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index 7fb9bc1974..206e222916 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -1239,7 +1239,8 @@ void Instruction::execute() { const uint64_t* pg = sourceValues_[1].getAsVector(); const uint64_t sliceNum = (sourceValues_[2 + rowCount].get() + - static_cast(metadata_.operands[2].sme_index.disp)) % + static_cast( + metadata_.operands[2].sme.slice_offset.imm)) % rowCount; const uint8_t* zanRow = sourceValues_[2 + sliceNum].getAsVector(); @@ -2305,8 +2306,8 @@ void Instruction::execute() { sourceValues_, [](float x, float y) -> float { return x - y; }); break; } - case Opcode::AArch64_GLD1D_IMM_REAL: { // ld1d {zd.d}, pg/z, [zn.d{, - // #imm}] + case Opcode::AArch64_GLD1D_IMM: { // ld1d {zd.d}, pg/z, [zn.d{, + // #imm}] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2323,11 +2324,11 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_GLD1D_REAL: // ld1d {zt.d}, pg/z, [xn, zm.d] + case Opcode::AArch64_GLD1D: // ld1d {zt.d}, pg/z, [xn, zm.d] // LOAD [[fallthrough]]; - case Opcode::AArch64_GLD1D_SCALED_REAL: { // ld1d {zt.d}, pg/z, [xn, - // zm.d, LSL #3] + case Opcode::AArch64_GLD1D_SCALED: { // ld1d {zt.d}, pg/z, [xn, + // zm.d, LSL #3] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2346,8 +2347,8 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_GLD1SW_D_IMM_REAL: { // ld1sw {zd.d}, pg/z, [zn.d{, - // #imm}] + case Opcode::AArch64_GLD1SW_D_IMM: { // ld1sw {zd.d}, pg/z, [zn.d{, + // #imm}] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2364,8 +2365,8 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_GLD1W_D_SCALED_REAL: { // ld1w {zd.d}, pg/z, - // [, zm.d, lsl #2] + case Opcode::AArch64_GLD1W_D_SCALED: { // ld1w {zd.d}, pg/z, + // [, zm.d, lsl #2] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2382,8 +2383,8 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_GLD1W_SXTW_REAL: { // ld1w {zd.s}, pg/z, - // [, zm.s, sxtw] + case Opcode::AArch64_GLD1W_SXTW: { // ld1w {zd.s}, pg/z, + // [, zm.s, sxtw] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2568,7 +2569,7 @@ void Instruction::execute() { sourceValues_[partition_num + 1].getAsVector(); const uint16_t sliceNum = - (ws + metadata_.operands[0].sme_index.disp) % partition_num; + (ws + metadata_.operands[0].sme.slice_offset.imm) % partition_num; const uint64_t* data = memoryData_[0].getAsVector(); uint64_t out[32] = {0}; @@ -2604,7 +2605,7 @@ void Instruction::execute() { sourceValues_[partition_num + 1].getAsVector(); const uint32_t sliceNum = - (ws + metadata_.operands[0].sme_index.disp) % partition_num; + (ws + metadata_.operands[0].sme.slice_offset.imm) % partition_num; const uint64_t* data = memoryData_[0].getAsVector(); for (int i = 0; i < partition_num; i++) { @@ -2632,7 +2633,7 @@ void Instruction::execute() { sourceValues_[partition_num + 1].getAsVector(); const uint32_t sliceNum = - (ws + metadata_.operands[0].sme_index.disp) % partition_num; + (ws + metadata_.operands[0].sme.slice_offset.imm) % partition_num; const uint32_t* data = memoryData_[0].getAsVector(); uint32_t out[64] = {0}; @@ -2668,7 +2669,7 @@ void Instruction::execute() { sourceValues_[partition_num + 1].getAsVector(); const uint32_t sliceNum = - (ws + metadata_.operands[0].sme_index.disp) % partition_num; + (ws + metadata_.operands[0].sme.slice_offset.imm) % partition_num; const uint32_t* data = memoryData_[0].getAsVector(); for (int i = 0; i < partition_num; i++) { @@ -2703,8 +2704,8 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_LD1B_IMM_REAL: { // ld1b {zt.b}, pg/z, [xn{, #imm, - // mul vl}] + case Opcode::AArch64_LD1B_IMM: { // ld1b {zt.b}, pg/z, [xn{, #imm, + // mul vl}] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2741,8 +2742,8 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_LD1D_IMM_REAL: { // ld1d {zt.d}, pg/z, [xn{, #imm, - // mul vl}] + case Opcode::AArch64_LD1D_IMM: { // ld1d {zt.d}, pg/z, [xn{, #imm, + // mul vl}] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2785,14 +2786,14 @@ void Instruction::execute() { break; } case Opcode::AArch64_LD1Onev16b_POST: { // ld1 {vt.16b}, [xn], <#imm|xm> - results_[0] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); + results_[1] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); // if #imm post-index, value can only be 16 const uint64_t postIndex = (metadata_.operands[2].type == AARCH64_OP_REG) ? sourceValues_[1].get() : 16; - results_[1] = sourceValues_[0].get() + postIndex; + results_[0] = sourceValues_[0].get() + postIndex; break; } case Opcode::AArch64_LD1RD_IMM: { // ld1rd {zt.d}, pg/z, [xn, #imm] @@ -2935,8 +2936,8 @@ void Instruction::execute() { uint8_t val = memoryData_[0].get(); uint8_t out[16] = {val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}; - results_[0] = {out, 256}; - results_[1] = + results_[1] = {out, 256}; + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } @@ -2951,8 +2952,8 @@ void Instruction::execute() { // LOAD uint64_t val = memoryData_[0].get(); uint64_t out[2] = {val, 0}; - results_[0] = {out, 256}; - results_[1] = + results_[1] = {out, 256}; + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } @@ -2967,8 +2968,8 @@ void Instruction::execute() { // LOAD uint64_t val = memoryData_[0].get(); uint64_t out[2] = {val, val}; - results_[0] = {out, 256}; - results_[1] = + results_[1] = {out, 256}; + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } @@ -2983,8 +2984,8 @@ void Instruction::execute() { // LOAD uint32_t val = memoryData_[0].get(); uint32_t out[4] = {val, val, 0, 0}; - results_[0] = {out, 256}; - results_[1] = + results_[1] = {out, 256}; + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } @@ -2999,8 +3000,8 @@ void Instruction::execute() { // LOAD uint16_t val = memoryData_[0].get(); uint16_t out[8] = {val, val, val, val, 0, 0, 0, 0}; - results_[0] = {out, 256}; - results_[1] = + results_[1] = {out, 256}; + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } @@ -3015,8 +3016,8 @@ void Instruction::execute() { // LOAD uint32_t val = memoryData_[0].get(); uint32_t out[4] = {val, val, val, val}; - results_[0] = {out, 256}; - results_[1] = + results_[1] = {out, 256}; + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } @@ -3033,8 +3034,8 @@ void Instruction::execute() { uint8_t val = memoryData_[0].get(); uint8_t out[16] = {val, val, val, val, val, val, val, val, 0, 0, 0, 0, 0, 0, 0, 0}; - results_[0] = {out, 256}; - results_[1] = + results_[1] = {out, 256}; + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } @@ -3049,8 +3050,8 @@ void Instruction::execute() { // LOAD uint16_t val = memoryData_[0].get(); uint16_t out[8] = {val, val, val, val, val, val, val, val}; - results_[0] = {out, 256}; - results_[1] = + results_[1] = {out, 256}; + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } @@ -3078,16 +3079,16 @@ void Instruction::execute() { case Opcode::AArch64_LD1Fourv4s_POST: { // ld1 {vt1.4s, vt2.4s, vt3.4s, // vt4.4s}, [xn], <#imm|xm> // LOAD - results_[0] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); - results_[1] = memoryData_[1].zeroExtend(memoryData_[1].size(), 256); - results_[2] = memoryData_[2].zeroExtend(memoryData_[2].size(), 256); - results_[3] = memoryData_[3].zeroExtend(memoryData_[3].size(), 256); + results_[1] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); + results_[2] = memoryData_[1].zeroExtend(memoryData_[1].size(), 256); + results_[3] = memoryData_[2].zeroExtend(memoryData_[2].size(), 256); + results_[4] = memoryData_[3].zeroExtend(memoryData_[3].size(), 256); // if #imm post-index, value can only be 64 const uint64_t postIndex = (metadata_.operands[5].type == AARCH64_OP_REG) ? sourceValues_[1].get() : 64; - results_[4] = sourceValues_[0].get() + postIndex; + results_[0] = sourceValues_[0].get() + postIndex; break; } case Opcode::AArch64_LD1Twov16b: // ld1 {vt1.16b, vt2.16b}, [xn] @@ -3109,15 +3110,15 @@ void Instruction::execute() { case Opcode::AArch64_LD1Twov4s_POST: { // ld1 {vt1.4s, vt2.4s}, [xn], // <#imm|xm> // LOAD - results_[0] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); - results_[1] = memoryData_[1].zeroExtend(memoryData_[1].size(), 256); + results_[1] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); + results_[2] = memoryData_[1].zeroExtend(memoryData_[1].size(), 256); // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata_.operands[3].type == AARCH64_OP_REG) ? sourceValues_[1].get() : 32; - results_[2] = sourceValues_[0].get() + postIndex; + results_[0] = sourceValues_[0].get() + postIndex; break; } case Opcode::AArch64_LD1W: { // ld1w {zt.s}, pg/z, [xn, xm, lsl #2] @@ -3139,8 +3140,8 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_LD1W_IMM_REAL: { // ld1w {zt.s}, pg/z, [xn{, #imm, - // mul vl}] + case Opcode::AArch64_LD1W_IMM: { // ld1w {zt.s}, pg/z, [xn{, #imm, + // mul vl}] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -3189,8 +3190,8 @@ void Instruction::execute() { for (int i = 0; i < 2; i++) { out[i] = (i == index) ? memoryData_[0].get() : vt[i]; } - results_[0] = {out, 256}; - results_[1] = + results_[1] = {out, 256}; + results_[0] = sourceValues_[1].get() + metadata_.operands[2].imm; break; } @@ -3239,13 +3240,13 @@ void Instruction::execute() { const float* region2 = memoryData_[1].getAsVector(); float t1[4] = {region1[0], region1[2], region2[0], region2[2]}; float t2[4] = {region1[1], region1[3], region2[1], region2[3]}; - results_[0] = {t1, 256}; - results_[1] = {t2, 256}; + results_[1] = {t1, 256}; + results_[2] = {t2, 256}; uint64_t offset = 32; if (metadata_.operandCount == 4) { offset = sourceValues_[3].get(); } - results_[2] = sourceValues_[2].get() + offset; + results_[0] = sourceValues_[2].get() + offset; break; } case Opcode::AArch64_LD3D_IMM: { // ld3d {zt1.d, zt2.d, zt3.d}, pg/z, @@ -3367,9 +3368,9 @@ void Instruction::execute() { isInstruction(InsnType::isSVEData)) ? 256 : 8; - results_[0] = memoryData_[0].zeroExtend(dataSize_, regSize); - results_[1] = memoryData_[1].zeroExtend(dataSize_, regSize); - results_[2] = + results_[1] = memoryData_[0].zeroExtend(dataSize_, regSize); + results_[2] = memoryData_[1].zeroExtend(dataSize_, regSize); + results_[0] = sourceValues_[0].get() + metadata_.operands[3].imm; break; } @@ -3383,9 +3384,9 @@ void Instruction::execute() { isInstruction(InsnType::isSVEData)) ? 256 : 8; - results_[0] = memoryData_[0].zeroExtend(dataSize_, regSize); - results_[1] = memoryData_[1].zeroExtend(dataSize_, regSize); - results_[2] = + results_[1] = memoryData_[0].zeroExtend(dataSize_, regSize); + results_[2] = memoryData_[1].zeroExtend(dataSize_, regSize); + results_[0] = sourceValues_[0].get() + metadata_.operands[2].mem.disp; break; } @@ -3397,15 +3398,15 @@ void Instruction::execute() { } case Opcode::AArch64_LDRBBpost: { // ldrb wt, [xn], #imm // LOAD - results_[0] = memoryData_[0].zeroExtend(1, 8); - results_[1] = + results_[1] = memoryData_[0].zeroExtend(1, 8); + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } case Opcode::AArch64_LDRBBpre: { // ldrb wt, [xn, #imm]! // LOAD - results_[0] = memoryData_[0].zeroExtend(1, 8); - results_[1] = + results_[1] = memoryData_[0].zeroExtend(1, 8); + results_[0] = sourceValues_[0].get() + metadata_.operands[1].mem.disp; break; } @@ -3453,8 +3454,8 @@ void Instruction::execute() { isInstruction(InsnType::isSVEData)) ? 256 : 8; - results_[0] = memoryData_[0].zeroExtend(dataSize_, regSize); - results_[1] = + results_[1] = memoryData_[0].zeroExtend(dataSize_, regSize); + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } @@ -3470,8 +3471,8 @@ void Instruction::execute() { isInstruction(InsnType::isSVEData)) ? 256 : 8; - results_[0] = memoryData_[0].zeroExtend(dataSize_, regSize); - results_[1] = + results_[1] = memoryData_[0].zeroExtend(dataSize_, regSize); + results_[0] = sourceValues_[0].get() + metadata_.operands[1].mem.disp; break; } @@ -3487,15 +3488,15 @@ void Instruction::execute() { } case Opcode::AArch64_LDRHHpost: { // ldrh wt, [xn], #imm // LOAD - results_[0] = memoryData_[0].zeroExtend(2, 8); - results_[1] = + results_[1] = memoryData_[0].zeroExtend(2, 8); + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } case Opcode::AArch64_LDRHHpre: { // ldrh wt, [xn, #imm]! // LOAD - results_[0] = memoryData_[0].zeroExtend(2, 8); - results_[1] = + results_[1] = memoryData_[0].zeroExtend(2, 8); + results_[0] = sourceValues_[0].get() + metadata_.operands[1].mem.disp; break; } @@ -3589,8 +3590,8 @@ void Instruction::execute() { } case Opcode::AArch64_LDRSWpost: { // ldrsw xt, [xn], #simm // LOAD - results_[0] = static_cast(memoryData_[0].get()); - results_[1] = + results_[1] = static_cast(memoryData_[0].get()); + results_[0] = sourceValues_[0].get() + metadata_.operands[2].imm; break; } @@ -3850,8 +3851,8 @@ void Instruction::execute() { case Opcode::AArch64_MSR: { // msr (systemreg|Sop0_op1_Cn_Cm_op2), xt // Handle case where SVCR is being updated as this invokes additional // functionality - if (metadata_.operands[0].reg == - static_cast(ARM64_SYSREG_SVCR)) { + if (metadata_.operands[0].type == AARCH64_OP_SYSALIAS && + metadata_.operands[0].sysop.sub_type == AARCH64_OP_SVCR) { return SMZAupdated(); } else { results_[0] = sourceValues_[0]; @@ -3869,16 +3870,16 @@ void Instruction::execute() { case Opcode::AArch64_MSRpstatesvcrImm1: { // msr svcr, #imm // This instruction is always used by SMSTART and SMSTOP aliases. const uint64_t svcrBits = - static_cast(metadata_.operands[0].svcr); + static_cast(metadata_.operands[0].sysop.alias.svcr); // Changing value of SM or ZA bits in SVCR zeros out vector, predicate, // and ZA registers. Raise an exception to do this. switch (svcrBits) { - case ARM64_SVCR_SVCRSM: + case AARCH64_SVCR_SVCRSM: return streamingModeUpdated(); - case ARM64_SVCR_SVCRZA: + case AARCH64_SVCR_SVCRZA: return zaRegisterStatusUpdated(); - case ARM64_SVCR_SVCRSMZA: + case AARCH64_SVCR_SVCRSMZA: return SMZAupdated(); default: // Invalid instruction @@ -4376,7 +4377,7 @@ void Instruction::execute() { results_[0] = vecSshrShift_imm(sourceValues_, metadata_); break; } - case Opcode::AArch64_SST1B_D_REAL: { // st1b {zd.d}, pg, [xn, zm.d] + case Opcode::AArch64_SST1B_D: { // st1b {zd.d}, pg, [xn, zm.d] // STORE const uint64_t* d = sourceValues_[0].getAsVector(); const uint64_t* p = sourceValues_[1].getAsVector(); @@ -4392,7 +4393,7 @@ void Instruction::execute() { } break; } - case Opcode::AArch64_SST1D_REAL: { // st1d {zt.d}, pg, [xn, zm.d] + case Opcode::AArch64_SST1D: { // st1d {zt.d}, pg, [xn, zm.d] // STORE const uint64_t* d = sourceValues_[0].getAsVector(); const uint64_t* p = sourceValues_[1].getAsVector(); @@ -4424,9 +4425,8 @@ void Instruction::execute() { } break; } - case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { // st1d {zt.d}, pg, [xn, - // zm.d, lsl # - // 3] + case Opcode::AArch64_SST1D_SCALED: { // st1d {zt.d}, pg, [xn, + // zm.d, lsl #3] // STORE const uint64_t* d = sourceValues_[0].getAsVector(); const uint64_t* p = sourceValues_[1].getAsVector(); @@ -4454,7 +4454,7 @@ void Instruction::execute() { sourceValues_[partition_num + 1].getAsVector(); const uint32_t sliceNum = - (ws + metadata_.operands[0].sme_index.disp) % partition_num; + (ws + metadata_.operands[0].sme.slice_offset.imm) % partition_num; const uint64_t* tileSlice = sourceValues_[sliceNum].getAsVector(); @@ -4474,7 +4474,7 @@ void Instruction::execute() { sourceValues_[partition_num + 1].getAsVector(); const uint32_t sliceNum = - (ws + metadata_.operands[0].sme_index.disp) % partition_num; + (ws + metadata_.operands[0].sme.slice_offset.imm) % partition_num; std::array mdata; uint16_t md_size = 0; @@ -4509,7 +4509,7 @@ void Instruction::execute() { sourceValues_[partition_num + 1].getAsVector(); const uint32_t sliceNum = - (ws + metadata_.operands[0].sme_index.disp) % partition_num; + (ws + metadata_.operands[0].sme.slice_offset.imm) % partition_num; const uint32_t* tileSlice = sourceValues_[sliceNum].getAsVector(); @@ -4529,7 +4529,7 @@ void Instruction::execute() { sourceValues_[partition_num + 1].getAsVector(); const uint32_t sliceNum = - (ws + metadata_.operands[0].sme_index.disp) % partition_num; + (ws + metadata_.operands[0].sme.slice_offset.imm) % partition_num; std::array mdata; uint16_t md_size = 0; diff --git a/src/lib/arch/aarch64/MicroDecoder.cc b/src/lib/arch/aarch64/MicroDecoder.cc index 3981489b9c..5b71fc3c8d 100644 --- a/src/lib/arch/aarch64/MicroDecoder.cc +++ b/src/lib/arch/aarch64/MicroDecoder.cc @@ -42,9 +42,8 @@ bool MicroDecoder::detectOverlap(aarch64_reg registerA, aarch64_reg registerB) { indexes[i] = 30; } else { aarch64_reg base = (aarch64_reg)0; - if (registers[i] >= AARCH64_REG_V0) { - base = AARCH64_REG_V0; - } else if (registers[i] >= AARCH64_REG_Z0) { + // No need to check V registers as they are encoded as Q or D registers + if (registers[i] >= AARCH64_REG_Z0) { base = AARCH64_REG_Z0; } else if (registers[i] >= AARCH64_REG_X0) { base = AARCH64_REG_X0; @@ -628,7 +627,7 @@ uint8_t MicroDecoder::decode(const Architecture& architecture, uint32_t word, } cs_detail MicroDecoder::createDefaultDetail(std::vector opTypes) { - cs_arm64 info = default_info; + cs_aarch64 info = default_info; cs_detail detail = default_detail; info.op_count = opTypes.size(); @@ -689,7 +688,7 @@ cs_detail MicroDecoder::createDefaultDetail(std::vector opTypes) { break; } } - detail.arm64 = info; + detail.aarch64 = info; return detail; } @@ -700,16 +699,19 @@ Instruction MicroDecoder::createImmOffsetUop(const Architecture& architecture, int microOpIndex) { cs_detail off_imm_detail = createDefaultDetail( {{AARCH64_OP_REG, 1}, {AARCH64_OP_REG}, {AARCH64_OP_IMM}}); - off_imm_detail.arm64.operands[0].reg = base; - off_imm_detail.arm64.operands[1].reg = base; - off_imm_detail.arm64.operands[2].imm = offset; + off_imm_detail.aarch64.operands[0].reg = base; + off_imm_detail.aarch64.operands[1].reg = base; + off_imm_detail.aarch64.operands[2].imm = offset; - cs_insn off_imm_cs = {arm64_insn::ARM64_INS_ADD, + cs_insn off_imm_cs = {aarch64_insn::AARCH64_INS_ADD, + aarch64_insn::AARCH64_INS_INVALID, 0x0, 4, "", "micro_offset_imm", "", + false, + false, &off_imm_detail, MicroOpcode::OFFSET_IMM}; @@ -727,16 +729,19 @@ Instruction MicroDecoder::createRegOffsetUop( csh capstoneHandle, bool lastMicroOp, int microOpIndex) { cs_detail off_reg_detail = createDefaultDetail( {{AARCH64_OP_REG, 1}, {AARCH64_OP_REG}, {AARCH64_OP_REG}}); - off_reg_detail.arm64.operands[0].reg = base; - off_reg_detail.arm64.operands[1].reg = base; - off_reg_detail.arm64.operands[2].reg = offset; + off_reg_detail.aarch64.operands[0].reg = base; + off_reg_detail.aarch64.operands[1].reg = base; + off_reg_detail.aarch64.operands[2].reg = offset; - cs_insn off_reg_cs = {arm64_insn::ARM64_INS_ADD, + cs_insn off_reg_cs = {aarch64_insn::AARCH64_INS_ADD, + aarch64_insn::AARCH64_INS_INVALID, 0x0, 4, "", "micro_offset_reg", "", + false, + false, &off_reg_detail, MicroOpcode::OFFSET_REG}; @@ -755,11 +760,19 @@ Instruction MicroDecoder::createLdrUop(const Architecture& architecture, int microOpIndex, uint8_t dataSize) { cs_detail ldr_detail = createDefaultDetail({{AARCH64_OP_REG, 1}, {AARCH64_OP_MEM}}); - ldr_detail.arm64.operands[0].reg = dest; - ldr_detail.arm64.operands[1].mem = mem; - cs_insn ldr_cs = { - arm64_insn::ARM64_INS_LDR, 0x0, 4, "", "micro_ldr", "", &ldr_detail, - MicroOpcode::LDR_ADDR}; + ldr_detail.aarch64.operands[0].reg = dest; + ldr_detail.aarch64.operands[1].mem = mem; + cs_insn ldr_cs = {aarch64_insn::AARCH64_INS_LDR, + aarch64_insn::AARCH64_INS_INVALID, + 0x0, + 4, + "", + "micro_ldr", + "", + false, + false, + &ldr_detail, + MicroOpcode::LDR_ADDR}; InstructionMetadata ldr_metadata(ldr_cs); microMetadataCache_.emplace_front(ldr_metadata); Instruction ldr(architecture, microMetadataCache_.front(), @@ -773,10 +786,18 @@ Instruction MicroDecoder::createSDUop(const Architecture& architecture, aarch64_reg src, csh capstoneHandle, bool lastMicroOp, int microOpIndex) { cs_detail sd_detail = createDefaultDetail({{AARCH64_OP_REG}}); - sd_detail.arm64.operands[0].reg = src; - cs_insn sd_cs = { - arm64_insn::ARM64_INS_STR, 0x0, 4, "", "micro_sd", "", &sd_detail, - MicroOpcode::STR_DATA}; + sd_detail.aarch64.operands[0].reg = src; + cs_insn sd_cs = {aarch64_insn::AARCH64_INS_STR, + aarch64_insn::AARCH64_INS_INVALID, + 0x0, + 4, + "", + "micro_sd", + "", + false, + false, + &sd_detail, + MicroOpcode::STR_DATA}; InstructionMetadata sd_metadata(sd_cs); microMetadataCache_.emplace_front(sd_metadata); Instruction sd( @@ -791,10 +812,18 @@ Instruction MicroDecoder::createStrUop(const Architecture& architecture, bool lastMicroOp, int microOpIndex, uint8_t dataSize) { cs_detail str_detail = createDefaultDetail({{AARCH64_OP_MEM}}); - str_detail.arm64.operands[0].mem = mem; - cs_insn str_cs = { - arm64_insn::ARM64_INS_STR, 0x0, 4, "", "micro_str", "", &str_detail, - MicroOpcode::STR_DATA}; + str_detail.aarch64.operands[0].mem = mem; + cs_insn str_cs = {aarch64_insn::AARCH64_INS_STR, + aarch64_insn::AARCH64_INS_INVALID, + 0x0, + 4, + "", + "micro_str", + "", + false, + false, + &str_detail, + MicroOpcode::STR_ADDR}; InstructionMetadata str_metadata(str_cs); microMetadataCache_.emplace_front(str_metadata); Instruction str(architecture, microMetadataCache_.front(), diff --git a/src/lib/config/ModelConfig.cc b/src/lib/config/ModelConfig.cc index 1b12e629d7..67cb6a0453 100644 --- a/src/lib/config/ModelConfig.cc +++ b/src/lib/config/ModelConfig.cc @@ -660,7 +660,7 @@ void ModelConfig::setExpectations(bool isDefault) { // Get the upper bound of what the opcode value can be based on the ISA uint16_t maxOpcode = 0; if (isa_ == ISA::AArch64) { - maxOpcode = arch::aarch64::Opcode::AArch64_INSTRUCTION_LIST_END; + maxOpcode = arch::aarch64::Opcode::INSTRUCTION_LIST_END; } else if (isa_ == ISA::RV64) { maxOpcode = arch::riscv::Opcode::RISCV_INSTRUCTION_LIST_END; } From 75a0c3151c35d3a0870ea74a0726712b0a262167 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Wed, 4 Sep 2024 12:55:46 +0200 Subject: [PATCH 04/34] Further changes to try get regression tests to all pass. --- .../developer/arch/supported/aarch64.rst | 3 +- src/include/simeng/arch/aarch64/ArchInfo.hh | 6 +- .../aarch64/helpers/auxiliaryFunctions.hh | 2 + .../simeng/arch/aarch64/helpers/sve.hh | 3 +- src/lib/arch/aarch64/ExceptionHandler.cc | 3 - src/lib/arch/aarch64/InstructionMetadata.cc | 3465 +++++++++-------- src/lib/arch/aarch64/InstructionMetadata.hh | 6 +- src/lib/arch/aarch64/Instruction_decode.cc | 489 ++- src/lib/arch/aarch64/Instruction_execute.cc | 3 +- test/integration/ConfigTest.cc | 32 +- .../aarch64/AArch64RegressionTest.hh | 40 +- test/regression/aarch64/Exception.cc | 6 +- .../aarch64/instructions/comparison.cc | 8 +- test/regression/aarch64/instructions/sme.cc | 41 +- test/unit/aarch64/ArchInfoTest.cc | 16 +- test/unit/aarch64/ArchitectureTest.cc | 8 +- test/unit/aarch64/AuxiliaryFunctionsTest.cc | 162 +- test/unit/aarch64/InstructionTest.cc | 2 +- 18 files changed, 2287 insertions(+), 2008 deletions(-) diff --git a/docs/sphinx/developer/arch/supported/aarch64.rst b/docs/sphinx/developer/arch/supported/aarch64.rst index 092264e991..4728f1cd60 100644 --- a/docs/sphinx/developer/arch/supported/aarch64.rst +++ b/docs/sphinx/developer/arch/supported/aarch64.rst @@ -135,7 +135,8 @@ There are several useful variables that execution behaviours have access to: ``results`` This is the output vector, into which ``RegisterValue`` instances containing the results should be placed. Each entry in the vector corresponds to a destination register. - Some instructions have "implicit" destination registers: in these cases, the implicit destinations are added to the start of the results vector. For example, ``subs w0, w1, #1`` writes explicitly to ``w0``, but also implicitly sets the "NZCV" comparison flags. In this case, ``results[0]`` is expected to be the updated NZCV flags, while ``results[1]`` is expected to be the new value of ``w0``. + Some instructions have "implicit" destination registers: in these cases, the implicit destinations are added to the **start** of the results vector. For example, ``subs w0, w1, #1`` writes explicitly to ``w0``, but also implicitly sets the "NZCV" comparison flags. In this case, ``results[0]`` is expected to be the updated NZCV flags, while ``results[1]`` is expected to be the new value of ``w0``. + Some Load and Store instructions update the base memory address register (pre- or post-indexing). These registers are also classes as implicit destination registers and thus will be added to the start of the results vector. For example, ``ldr x1, [x0], #8`` writes explicitly to ``x1`` but also writes implicitly to ``x0``. In this case, ``results[0]`` is expected to be the updated ``x0`` value (``x0 + 8``) and ``results[1]`` is expected to be the new value of ``x1``. Memory instructions may have a "writeback" variant, where the register containing the address is updated by an offset during execution. In these cases, the address register is added as a destination *after* the other registers, corresponding with the textual representation of the registers. E.g., the instruction ``ldr x1, [x2, #8]!`` will expect the value of ``x1`` in ``results[0]``, while the updated address ``x2`` should be placed in ``results[1]``. diff --git a/src/include/simeng/arch/aarch64/ArchInfo.hh b/src/include/simeng/arch/aarch64/ArchInfo.hh index 40743f3ea2..e6280561c8 100644 --- a/src/include/simeng/arch/aarch64/ArchInfo.hh +++ b/src/include/simeng/arch/aarch64/ArchInfo.hh @@ -47,13 +47,15 @@ class ArchInfo : public simeng::arch::ArchInfo { {32, predCount}, {1, condCount}, {8, static_cast(sysRegisterEnums_.size())}, - {256, matCount}}; + {256, matCount}, + {64, 1}}; physRegQuantities_ = {gpCount, fpCount, predCount, condCount, static_cast(sysRegisterEnums_.size()), - matCount}; + matCount, + 1}; } /** Get the set of system register enums currently supported. */ diff --git a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh index 459ad4dc93..c1a74a5fb7 100644 --- a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh +++ b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh @@ -125,6 +125,8 @@ bitfieldManipulate(T value, T dest, uint8_t rotateBy, uint8_t sourceBits, /** Function to check if NZCV conditions hold. */ inline bool conditionHolds(uint8_t cond, uint8_t nzcv) { + // Due to Capstone enum changes, need to add 1 to cond + cond += 1; bool inverse = cond & 1; uint8_t upper = cond >> 1; bool n = (nzcv >> 3) & 1; diff --git a/src/include/simeng/arch/aarch64/helpers/sve.hh b/src/include/simeng/arch/aarch64/helpers/sve.hh index dc3b2dca21..4afb39d00c 100644 --- a/src/include/simeng/arch/aarch64/helpers/sve.hh +++ b/src/include/simeng/arch/aarch64/helpers/sve.hh @@ -177,7 +177,8 @@ std::tuple, uint8_t> sveCmpPredicated_toPred( template uint64_t sveCnt_gpr(const simeng::arch::aarch64::InstructionMetadata& metadata, const uint16_t VL_bits) { - const uint8_t imm = static_cast(metadata.operands[1].imm); + // SVE pattern stored in metadata_.operands[1] + const uint8_t imm = static_cast(metadata.operands[2].imm); const uint16_t elems = sveGetPattern(metadata.operandStr, (sizeof(T) * 8), VL_bits); diff --git a/src/lib/arch/aarch64/ExceptionHandler.cc b/src/lib/arch/aarch64/ExceptionHandler.cc index 983e8accb7..505c703467 100644 --- a/src/lib/arch/aarch64/ExceptionHandler.cc +++ b/src/lib/arch/aarch64/ExceptionHandler.cc @@ -656,9 +656,6 @@ bool ExceptionHandler::init() { // Check if exception was called by AArch64_MSR (msr systemreg, xt) or // AArch64_MSRpstatesvcrImm1 (msr svcr, #imm) if (metadata.opcode == Opcode::AArch64_MSR) { - // Enusre operand metadata is as expected - assert(metadata.operands[0].type == AARCH64_OP_SYSALIAS); - assert(metadata.operands[0].sysop.sub_type == AARCH64_OP_SVCR); newSVCR = instruction_.getSourceOperands()[0].get(); } else if (metadata.opcode == Opcode::AArch64_MSRpstatesvcrImm1) { // Enusre operand metadata is as expected diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index 7b7594ff73..0f0fc9cf6b 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -15,7 +15,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) groupCount(insn.detail->groups_count), cc(insn.detail->aarch64.cc - 1), setsFlags(insn.detail->aarch64.update_flags), - writeback(insn.detail->writeback), + isAlias(insn.is_alias), operandCount(insn.detail->aarch64.op_count) { std::memcpy(encoding, insn.bytes, sizeof(encoding)); // Copy printed output @@ -31,1728 +31,1745 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) std::memcpy(operands, insn.detail->aarch64.operands, sizeof(cs_aarch64_op) * operandCount); - // // Fix some inaccuracies in the decoded metadata - // switch (opcode) { - // case Opcode::AArch64_ADR_LSL_ZZZ_D_0: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_D_1: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_D_2: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_D_3: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_S_0: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_S_1: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_S_2: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_S_3: { - // // No defined access types - // operandCount = 3; - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[2].type = AARCH64_OP_REG; - // break; - // } - // case Opcode::AArch64_SMIN_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_EOR_ZPmZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_EOR_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_EOR_ZPmZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_EOR_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_AND_ZPmZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_AND_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_AND_ZPmZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_AND_ZPmZ_S: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_BICv4i32: - // // BIC incorrectly flags destination as WRITE only - // operands[0].access = CS_AC_WRITE | CS_AC_READ; - // break; - // case Opcode::AArch64_ADDSWri: - // // adds incorrectly flags destination as READ - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_BICv8i16: - // operands[0].access = CS_AC_WRITE | CS_AC_READ; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_BICv8i8: - // // access specifier for last operand was missing - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_CASALW: - // [[fallthrough]]; - // case Opcode::AArch64_CASALX: - // operandCount = 3; - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_CBNZW: - // [[fallthrough]]; - // case Opcode::AArch64_CBNZX: - // [[fallthrough]]; - // case Opcode::AArch64_CBZW: - // [[fallthrough]]; - // case Opcode::AArch64_CBZX: - // // incorrectly adds implicit nzcv dependency - // implicitSourceCount = 0; - // break; - // case Opcode::AArch64_CMPHI_PPzZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPHI_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPHI_PPzZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPHI_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_CMPGT_PPzZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPGT_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPGT_PPzZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPGT_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZI_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZI_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZI_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZI_S: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZI_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZI_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZI_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZI_S: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // // Doesn't identify implicit NZCV destination - // implicitDestinationCount = 1; - // implicitDestinations[0] = AARCH64_REG_NZCV; - // break; - // case Opcode::AArch64_CNTB_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_CNTH_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_CNTD_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_CNTW_XPiI: { - // // lacking access specifiers for destination - // operands[0].access = CS_AC_WRITE; - // if (operandStr.length() < 4) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - // operands[1].ext = AARCH64_EXT_INVALID; - // operands[1].vector_index = -1; - // } - // break; - // } - // case Opcode::AArch64_ADD_ZI_B: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZI_D: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZI_H: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZI_S: { - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[2].type = AARCH64_OP_IMM; - // operandCount = 3; - - // // Extract immediate in SVE add with immediate instruction - // size_t start = operandStr.find("#"); - // // Identify whether the immediate value is in base-10 or base-16 - // if (start != std::string::npos) { - // start++; - // bool hex = false; - // if (operandStr[start + 1] == 'x') { - // hex = true; - // start += 2; - // } - - // uint8_t end = operandStr.size(); - // size_t shifted = operandStr.find("LSL"); - // if (shifted != std::string::npos) { - // std::cerr << "[SimEng:arch] SVE add with immediate has shift value - // " - // "in operandStr which is unsupported." - // << std::endl; - // exit(1); - // } - // // Convert extracted immediate from string to int64_t - // std::string sub = operandStr.substr(start, end); - // if (hex) { - // operands[2].imm = std::stoul(sub, 0, 16); - // } else { - // operands[2].imm = stoi(sub); - // } - // } else { - // operands[2].imm = 0; - // } - // break; - // } - // case Opcode::AArch64_AND_ZI: { - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[2].type = AARCH64_OP_IMM; - // operandCount = 3; - - // char specifier = operandStr[operandStr.find(".") + 1]; - // switch (specifier) { - // case 'b': { - // uint8_t mask = static_cast(operands[2].imm); - // operands[2].imm = static_cast(0); - // for (int i = 0; i < 8; i++) - // operands[2].imm |= (static_cast(mask) << (i * 8)); - // break; - // } - // case 'h': { - // uint16_t mask = static_cast(operands[2].imm); - // operands[2].imm = static_cast(0); - // for (int i = 0; i < 4; i++) - // operands[2].imm |= (static_cast(mask) << (i * 16)); - // break; - // } - // case 's': { - // uint32_t mask = static_cast(operands[2].imm); - // operands[2].imm = static_cast(0); - // for (int i = 0; i < 2; i++) - // operands[2].imm |= (static_cast(mask) << (i * 32)); - // break; - // } - // default: - // break; - // } - // break; - // } - // case Opcode::AArch64_CNTP_XPP_B: - // [[fallthrough]]; - // case Opcode::AArch64_CNTP_XPP_D: - // [[fallthrough]]; - // case Opcode::AArch64_CNTP_XPP_H: - // [[fallthrough]]; - // case Opcode::AArch64_CNTP_XPP_S: - // [[fallthrough]]; - // case Opcode::AArch64_EOR_ZZZ: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_DECD_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_DECB_XPiI: { - // // lacking access specifiers for destination - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // std::string str(operandStr); - // if (str.length() < 4) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - // operands[1].ext = AARCH64_EXT_INVALID; - // operands[1].vector_index = -1; - // } - // break; - // } - // case Opcode::AArch64_EOR_PPzPP: { - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_FMOVXDHighr: - // // FMOVXDHighr incorrectly flags destination as only WRITE - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // break; - // case Opcode::AArch64_FNMSB_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FNMSB_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FNMLS_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FNMLS_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMAD_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMAD_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMLA_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMLA_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMLS_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMLS_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMSB_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMSB_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_MLA_ZPmZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_MLA_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_MLA_ZPmZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_MLA_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_SMAX_ZPmZ_S: - // // No defined access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_ADDPL_XXI: - // [[fallthrough]]; - // case Opcode::AArch64_ADDVL_XXI: - // [[fallthrough]]; - // case Opcode::AArch64_UADDV_VPZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_UADDV_VPZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_UADDV_VPZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_UADDV_VPZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_MOVPRFX_ZPzZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_MOVPRFX_ZPzZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_SUB_ZZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_SUB_ZZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_SUB_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_SUB_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_II_B: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_II_H: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_II_S: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_II_D: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_IR_B: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_IR_D: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_IR_H: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_IR_S: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RI_B: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RI_D: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RI_H: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RI_S: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RR_B: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RR_D: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RR_H: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RR_S: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FSUB_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FSUB_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMUL_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMUL_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_SMAX_ZI_S: - // [[fallthrough]]; - // case Opcode::AArch64_SMINV_VPZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_TRN1_ZZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_TRN1_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_TRN1_ZZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_TRN1_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_TRN2_ZZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_TRN2_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_TRN2_ZZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_TRN2_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_UZP1_ZZZ_S: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_MOVPRFX_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCPY_ZPmI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCPY_ZPmI_S: - // [[fallthrough]]; - // case Opcode::AArch64_FNEG_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FNEG_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FRINTN_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FRINTN_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FABS_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FABS_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FSQRT_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FSQRT_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCVTZS_ZPmZ_DtoD: - // [[fallthrough]]; - // case Opcode::AArch64_FCVTZS_ZPmZ_StoD: - // [[fallthrough]]; - // case Opcode::AArch64_FCVTZS_ZPmZ_StoS: - // [[fallthrough]]; - // case Opcode::AArch64_FCVTZS_ZPmZ_DtoS: - // // No defined access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_FMUL_ZPmI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMUL_ZPmI_S: { - // // No defined access types - // operandCount = 4; - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].type = AARCH64_OP_FP; - // operands[3].access = CS_AC_READ; - // // Doesn't recognise immediate operands - // // Extract two possible values, 0.5 or 2.0 - // if (operandStr.substr(operandStr.length() - 1, 1) == "5") { - // operands[3].fp = 0.5f; - // } else { - // operands[3].fp = 2.0f; - // } - - // break; - // } - // case Opcode::AArch64_FCMLA_ZPmZZ_D: { - // // No defined access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // operands[4].type = AARCH64_OP_IMM; - // break; - // } - // case Opcode::AArch64_FCADD_ZPmZ_D: { - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // operands[4].type = AARCH64_OP_IMM; - // break; - // } - // case Opcode::AArch64_FSUB_ZPmI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FSUB_ZPmI_S: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZPmI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZPmI_S: - // // No defined access types - // operandCount = 4; - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].type = AARCH64_OP_FP; - // operands[3].access = CS_AC_READ; - // // Doesn't recognise immediate operands - // // Extract two possible values, 0.5 or 1.0 - // if (operandStr.substr(operandStr.length() - 1, 1) == "5") { - // operands[3].fp = 0.5f; - // } else { - // operands[3].fp = 1.0f; - // } - // break; - // case Opcode::AArch64_FCMGT_PPzZ0_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGT_PPzZ0_S: { - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_FMLA_ZZZI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMLA_ZZZI_S: { - // // Need to define missing access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_FDIVR_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FDIVR_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FDIV_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_AND_PPzPP: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZPmZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZPmZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGE_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGE_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGE_PPzZ0_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGE_PPzZ0_S: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGT_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGT_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FCMLE_PPzZ0_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCMLE_PPzZ0_S: - // [[fallthrough]]; - // case Opcode::AArch64_FCMLT_PPzZ0_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMUL_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMUL_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FSUBR_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FSUBR_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FSUB_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FSUB_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FADDA_VPZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_MUL_ZPmZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_MUL_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_MUL_ZPmZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_MUL_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_ORR_PPzPP: - // [[fallthrough]]; - // case Opcode::AArch64_SMULH_ZPmZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_SMULH_ZPmZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_SMULH_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_SEL_ZPZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_SEL_ZPZZ_S: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_FRINTPDr: - // [[fallthrough]]; - // case Opcode::AArch64_FRINTPSr: - // [[fallthrough]]; - // case Opcode::AArch64_FDUP_ZI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FDUP_ZI_S: - // [[fallthrough]]; - // case Opcode::AArch64_PUNPKHI_PP: - // [[fallthrough]]; - // case Opcode::AArch64_PUNPKLO_PP: - // [[fallthrough]]; - // case Opcode::AArch64_RDVLI_XI: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_INCB_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_INCD_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_INCH_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_INCW_XPiI: { - // // lacking access specifiers for destination - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // if (operandStr.length() < 4) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - // operands[1].ext = AARCH64_EXT_INVALID; - // operands[1].vector_index = -1; - // } - // break; - // } - // case Opcode::AArch64_INCD_ZPiI: - // [[fallthrough]]; - // case Opcode::AArch64_INCH_ZPiI: - // [[fallthrough]]; - // case Opcode::AArch64_INCW_ZPiI: { - // // lacking access specifiers for destination - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // if (operandStr.length() < 6) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - // operands[1].ext = AARCH64_EXT_INVALID; - // operands[1].vector_index = -1; - // } - // break; - // } - // case Opcode::AArch64_INCP_XP_B: - // [[fallthrough]]; - // case Opcode::AArch64_INCP_XP_D: - // [[fallthrough]]; - // case Opcode::AArch64_INCP_XP_H: - // [[fallthrough]]; - // case Opcode::AArch64_INCP_XP_S: - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1i32: - // [[fallthrough]]; - // case Opcode::AArch64_LD1i64: - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_GLD1W_D_SCALED_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_GLD1W_SXTW_REAL: { - // // Access types are not set correctly - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_GLD1D_SCALED_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_GLD1D_REAL: { - // // LD1D gather instruction doesn't correctly identify destination - // // register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - // operands[0].reg = static_cast(reg_enum); - - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // LD1D gather instruction doesn't correctly identify memory operands - // operands[2].type = AARCH64_OP_MEM; - // operands[2].access = CS_AC_READ; - - // // LD1D doesn't correctly identify vector memory register correctly - // uint16_t vec_enum = AARCH64_REG_Z0; - // std::string tmp_str(operandStr.substr(operandStr.find("["))); - // // Single or double digit Z register identifier - // if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { - // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); - // } else { - // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); - // } - // operands[2].mem.index = static_cast(vec_enum); - // break; - // } - // case Opcode::AArch64_LD1RQ_W: - // [[fallthrough]]; - // case Opcode::AArch64_LD1RQ_W_IMM: { - // // LD1RQW doesn't identify correct access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_LD1RQ_D_IMM: { - // // LD1RQ gather instruction doesn't correctly identify destination - // // register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - // operands[0].reg = static_cast(reg_enum); - - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // LD1RQ gather instruction doesn't correctly identify memory operands - // operands[2].type = AARCH64_OP_MEM; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_GLD1SW_D_IMM_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_GLD1D_IMM_REAL: { - // // LD1D gather instruction doesn't correctly identify destination - // // register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // LD1D gather instruction doesn't correctly identify second Z reg as - // // memory operand - // operands[2].type = AARCH64_OP_MEM; - // operands[2].access = CS_AC_READ; - // // LD1D gather instruction doesn't recognise memory-offset immediate - // // correctly - // if (operandStr[operandStr.length() - 3] != '.') { - // int64_t startPos = operandStr.find('#') + 1; - // int64_t immSize = (operandStr.length() - 1) - startPos; - // if (immSize == 1) { - // operands[2].mem.disp = - // std::stoi(operandStr.substr(startPos, immSize)); - // } else { - // // double or triple digit immediates are converted to hex, and so - // // require a different conversion to uint - // operands[2].mem.disp = - // std::stoul(operandStr.substr(startPos, immSize), nullptr, 16); - // } - // } - // break; - // } - // case Opcode::AArch64_LD1B: - // [[fallthrough]]; - // case Opcode::AArch64_LD1D: - // [[fallthrough]]; - // case Opcode::AArch64_LD1B_IMM_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_LD1D_IMM_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_LD1RD_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_LD1RW_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_LD1H: - // [[fallthrough]]; - // case Opcode::AArch64_LD1W: - // [[fallthrough]]; - // case Opcode::AArch64_LD1W_IMM_REAL: { - // // LD1RW doesn't correctly identify destination register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_LD1Rv4s: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv1d: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv2d: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv2s: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv8b: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv16b: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv8h: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv4h: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1Rv4h_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv8h_POST: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ | CS_AC_WRITE; - // // Fix for exclusion of post_index immediate in disassembly - // operandCount = 3; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // // For vector arrangement of 16-bit, post_index immediate is 2 - // operands[2].imm = 2; - // break; - // case Opcode::AArch64_LD1Rv1d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv2d_POST: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ | CS_AC_WRITE; - // // Fix for exclusion of post_index immediate in disassembly - // operandCount = 3; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // // For vector arrangement of 64-bit, post_index immediate is 8 - // operands[2].imm = 8; - // break; - // case Opcode::AArch64_LD1Rv16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv8b_POST: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ | CS_AC_WRITE; - - // // Fix for exclusion of post_index immediate in disassembly - // operandCount = 3; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // // For vector arrangement of 8-bit, post_index immediate is 1 - // operands[2].imm = 1; - // break; - // case Opcode::AArch64_LD1Rv2s_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv4s_POST: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ | CS_AC_WRITE; - - // // Fix for exclusion of post_index immediate in disassembly - // operandCount = 3; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // // For vector arrangement of 32-bit, post_index immediate is 4 - // operands[2].imm = 4; - // break; - // case Opcode::AArch64_LD1Fourv16b: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Fourv4s: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Fourv2d: - // // Fix incorrect access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_WRITE; - // operands[2].access = CS_AC_WRITE; - // operands[3].access = CS_AC_WRITE; - // operands[4].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1Fourv16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Fourv2d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Fourv4s_POST: - // // Fix incorrect access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_WRITE; - // operands[2].access = CS_AC_WRITE; - // operands[3].access = CS_AC_WRITE; - // operands[4].access = CS_AC_READ | CS_AC_WRITE; - // operands[5].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1Onev16b: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1Onev16b_POST: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ | CS_AC_WRITE; - // break; - // case Opcode::AArch64_LD1Twov16b: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Twov4s: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Twov2d: - // // Fix incorrect access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_WRITE; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1Twov16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Twov2d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Twov4s_POST: - // // Fix incorrect access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_WRITE; - // operands[2].access = CS_AC_READ | CS_AC_WRITE; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LDADDLW: - // [[fallthrough]]; - // case Opcode::AArch64_LDADDW: - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_LD2Twov4s_POST: - // // Fixing wrong access flag for offset register operand - // if (operandCount == 4) { - // operands[3].access = CS_AC_READ; - // } - // break; - // case Opcode::AArch64_LDR_PXI: - // [[fallthrough]]; - // case Opcode::AArch64_LDR_ZXI: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LSL_ZZI_S: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // // No instruction id assigned - // id = AARCH64_INS_LSL; - // break; - // case Opcode::AArch64_LD2D: - // case Opcode::AArch64_LD2D_IMM: { - // // LD2D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_WRITE; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_WRITE; - - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_LD3D_IMM: { - // // LD3D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - // uint16_t reg_enum2 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d, znn.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest2 - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); - // } else { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_WRITE; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_WRITE; - // operands[2].reg = static_cast(reg_enum2); - // operands[2].access = CS_AC_WRITE; - - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_LD4D_IMM: { - // // LD4D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - // uint16_t reg_enum2 = AARCH64_REG_Z0; - // uint16_t reg_enum3 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d, znn.d, zmm.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest2 - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest3 - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum3 += std::stoi(tmpOpStr.substr(1, 1)); - // } else { - // reg_enum3 += std::stoi(tmpOpStr.substr(1, 2)); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_WRITE; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_WRITE; - // operands[2].reg = static_cast(reg_enum2); - // operands[2].access = CS_AC_WRITE; - // operands[3].reg = static_cast(reg_enum3); - // operands[3].access = CS_AC_WRITE; - - // operands[4].access = CS_AC_READ; - // operands[5].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_MOVNWi: - // [[fallthrough]]; - // case Opcode::AArch64_MOVNXi: - // [[fallthrough]]; - // case Opcode::AArch64_MOVZWi: - // [[fallthrough]]; - // case Opcode::AArch64_MOVZXi: - // // MOVZ incorrectly flags destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_MOVPRFX_ZZ: - // // Assign operand access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_MRS: - // // MRS incorrectly flags source/destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // MRS incorrectly tags AARCH64_OP_REG_MRS as AARCH64_OP_SYS - // operands[1].type = AARCH64_OP_REG_MRS; - // break; - // case Opcode::AArch64_MSR: - // // MSR incorrectly flags source/destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // MSR incorrectly tags AARCH64_OP_REG_MSR as AARCH64_OP_SYS - // operands[0].type = AARCH64_OP_REG_MSR; - // break; - // case Opcode::AArch64_PTEST_PP: { - // // PTEST doesn't label access types for operands - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // // Doesn't identify implicit NZCV destination - // implicitDestinationCount = 1; - // implicitDestinations[0] = AARCH64_REG_NZCV; - // break; - // } - // case Opcode::AArch64_PTRUE_B: - // [[fallthrough]]; - // case Opcode::AArch64_PTRUE_H: - // [[fallthrough]]; - // case Opcode::AArch64_PTRUE_D: - // [[fallthrough]]; - // case Opcode::AArch64_PTRUE_S: - // // PTRUE doesn't label access - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_RET: - // // If no register supplied to RET, default to x30 (LR) - // if (operandCount == 0) { - // operandCount = 1; - // operands[0].type = AARCH64_OP_REG; - // operands[0].reg = AARCH64_REG_LR; - // operands[0].access = CS_AC_READ; - // } - // groupCount = 1; - // groups[0] = CS_GRP_JUMP; - // break; - // case Opcode::AArch64_REV_ZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_REV_ZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_REV_ZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_REV_ZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_B: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_D: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_H: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_S: { - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_SST1B_D_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_SST1D_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { - // // ST1W doesn't correctly identify first source register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // // SST1D{_SCALED} gather instruction doesn't correctly identify memory - // // operands - // operands[2].type = AARCH64_OP_MEM; - // operands[2].access = CS_AC_READ; - - // // ST1D doesn't correctly identify vector memory register correctly - // uint16_t vec_enum = AARCH64_REG_Z0; - // std::string tmp_str(operandStr.substr(operandStr.find("["))); - // // Single or double digit Z register identifier - // if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { - // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); - // } else { - // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); - // } - // operands[2].mem.index = static_cast(vec_enum); - // break; - // } - // case Opcode::AArch64_ST2D_IMM: { - // // ST2D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_READ; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_READ; - - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_ST1B: - // [[fallthrough]]; - // case Opcode::AArch64_ST1D: - // [[fallthrough]]; - // case Opcode::AArch64_ST1B_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_ST1D_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_ST1W_IMM: { - // // ST1W doesn't correctly identify first source register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_ST1W: - // [[fallthrough]]; - // case Opcode::AArch64_ST1W_D: { - // // ST1W doesn't correctly identify first source register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_SST1D_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_SST1W_D_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_SST1W_IMM: { - // // ST1W scatter instruction doesn't correctly identify first source - // // register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // // ST1W scatter instruction doesn't correctly identify second Z reg as - // // memory operand - // operands[2].type = AARCH64_OP_MEM; - // operands[2].access = CS_AC_READ; - // // ST1W scatter instruction doesn't recognise memory-offset immediate - // // correctly - // if (operandStr[operandStr.length() - 3] != '.') { - // int64_t startPos = operandStr.find('#') + 1; - // int64_t immSize = (operandStr.length() - 1) - startPos; - // if (immSize == 1) { - // operands[2].mem.disp = - // std::stoi(operandStr.substr(startPos, immSize)); - // } else { - // // double or triple digit immediates are converted to hex, and so - // // require a different conversion to uint - // operands[2].mem.disp = - // std::stoul(operandStr.substr(startPos, immSize), nullptr, 16); - // } - // } - // break; - // } - // case Opcode::AArch64_ST1i8_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1i16_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1i32_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1i64_POST: - // // fixing incorrect access type for register offset - // if (operandCount == 3) { - // operands[2].access = CS_AC_READ; - // } - // break; - // case Opcode::AArch64_ST1Fourv16b: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv2d: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv4s: - // // ST1 incorrectly flags read and write - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // break; - // case Opcode::AArch64_ST1Fourv16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv2d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv2s_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv4s_POST: - // // ST1 incorrectly flags read and write - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ | CS_AC_WRITE; - // operands[5].access = CS_AC_READ; - // // determine correct type for operand 5 - // if (operandStr.find("#") != std::string::npos) { - // operands[5].type = AARCH64_OP_IMM; - // } else { - // operands[5].type = AARCH64_OP_REG; - // } - // break; - // case Opcode::AArch64_ST1Twov16b: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov2d: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov4s: - // // ST1 incorrectly flags read and write - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_ST1Twov16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov2d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov4s_POST: - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ | CS_AC_WRITE; - // operands[3].access = CS_AC_READ; - // // determine correct type for operand 3 - // if (operandStr.find("#") != std::string::npos) { - // operands[3].type = AARCH64_OP_IMM; - // } else { - // operands[3].type = AARCH64_OP_REG; - // } - // break; - // case Opcode::AArch64_ST2Twov4s_POST: - // // ST2 post incorrectly flags read and write - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ | CS_AC_WRITE; - // // Another incorrect access flag for register offset operand - // if (operandCount == 4) { - // operands[3].access = CS_AC_READ; - // } - // break; - // case Opcode::AArch64_STRBui: - // [[fallthrough]]; - // case Opcode::AArch64_STRDui: - // [[fallthrough]]; - // case Opcode::AArch64_STRHui: - // [[fallthrough]]; - // case Opcode::AArch64_STRQui: - // [[fallthrough]]; - // case Opcode::AArch64_STRSui: - // [[fallthrough]]; - // case Opcode::AArch64_STRWui: - // [[fallthrough]]; - // case Opcode::AArch64_STRXui: - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_PFALSE: - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_STR_PXI: - // [[fallthrough]]; - // case Opcode::AArch64_STR_ZXI: - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_SBFMWri: - // [[fallthrough]]; - // case Opcode::AArch64_SBFMXri: - // // SBFM incorrectly flags destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_SVC: - // // SVC is incorrectly marked as setting x30 - // implicitDestinationCount = 0; - // break; - // case Opcode::AArch64_SYSxt: - // // No defined metadata.id for SYS instructions - // id = AARCH64_INS_SYS; - // break; - // case Opcode::AArch64_PSEL_PPPRI_B: - // [[fallthrough]]; - // case Opcode::AArch64_PSEL_PPPRI_D: - // [[fallthrough]]; - // case Opcode::AArch64_PSEL_PPPRI_H: - // [[fallthrough]]; - // case Opcode::AArch64_PSEL_PPPRI_S: - // // Add correct access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_UBFMWri: - // [[fallthrough]]; - // case Opcode::AArch64_UBFMXri: - // // UBFM incorrectly flags destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_UQDECB_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECB_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECD_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECD_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECH_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECH_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECW_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECW_XPiI: - // // UQDEC lacks access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // if (operandCount == 1) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // } - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_UUNPKHI_ZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKHI_ZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKHI_ZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKLO_ZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKLO_ZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKLO_ZZ_S: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_WHILELT_PXX_B: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELT_PXX_D: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELT_PXX_H: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELT_PXX_S: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_B: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_D: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_H: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_S: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_B: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_D: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_H: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_S: - // // WHILELO doesn't label access or vector specifiers - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // // Doesn't identify implicit NZCV destination - // implicitDestinationCount = 1; - // implicitDestinations[0] = AARCH64_REG_NZCV; - // break; - // case Opcode::AArch64_XTNv16i8: - // case Opcode::AArch64_XTNv4i32: - // case Opcode::AArch64_XTNv8i16: - // // XTN2 incorrectly flags destination as only WRITE - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // break; - // case Opcode::AArch64_ZIP1_PPP_B: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_PPP_D: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_PPP_H: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_PPP_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_B: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_D: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_H: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_ZZZ_D: - // // ZIP lacks access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_SXTW_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCVT_ZPmZ_DtoS: - // [[fallthrough]]; - // case Opcode::AArch64_FCVT_ZPmZ_StoD: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_DtoS: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_StoD: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_StoS: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_DtoD: - // // Need to see if Destination vector elements are active - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8One: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8One: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8Two: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8Two: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8Three: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8Three: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8Four: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8Four: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // operands[5].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1_MXIPXX_H_D: - // [[fallthrough]]; - // case Opcode::AArch64_LD1_MXIPXX_V_D: - // [[fallthrough]]; - // case Opcode::AArch64_LD1_MXIPXX_V_S: - // [[fallthrough]]; - // case Opcode::AArch64_LD1_MXIPXX_H_S: { - // // Lacking access specifiers - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_ST1_MXIPXX_H_D: - // [[fallthrough]]; - // case Opcode::AArch64_ST1_MXIPXX_V_D: - // [[fallthrough]]; - // case Opcode::AArch64_ST1_MXIPXX_H_S: - // [[fallthrough]]; - // case Opcode::AArch64_ST1_MXIPXX_V_S: - // // Access types are not defined - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_FMOPA_MPPZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMOPA_MPPZZ_S: { - // // Need to add access specifiers - // // although operands[0] should be READ | WRITE, due to the implemented - // // decode logic for SME tile destinations, the register will be added - // as - // // both source and destination with just WRITE access. - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // operands[5].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_EXTRACT_ZPMXI_H_B: { - // operandCount = 4; - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].reg = operands[2].sme_index.base; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_ZERO_M: { - // // Operands often mangled from ZA tile overlap aliasing in decode. Need - // to - // // re-extract relevant tiles from operandStr - // operandCount = 0; - // size_t pos = operandStr.find("za", 0); - // while (pos != std::string::npos) { - // size_t pos_2 = operandStr.find(".", pos); - // if (pos_2 != std::string::npos) { - // char type = operandStr[pos_2 + 1]; - // // Tile Number can only ever be 1 digit - // uint8_t tileNum = std::stoi(operandStr.substr((pos + 2), 1)); - // switch (type) { - // case 'b': - // operands[operandCount].reg = AARCH64_REG_ZAB0; - // break; - // case 'h': - // operands[operandCount].reg = - // static_cast(AARCH64_REG_ZAH0 + tileNum); - // break; - // case 's': - // operands[operandCount].reg = - // static_cast(AARCH64_REG_ZAS0 + tileNum); - // break; - // case 'd': - // operands[operandCount].reg = - // static_cast(AARCH64_REG_ZAD0 + tileNum); - // break; - // case 'q': - // operands[operandCount].reg = - // static_cast(AARCH64_REG_ZAQ0 + tileNum); - // break; - // } - // } else { - // operands[operandCount].reg = AARCH64_REG_ZA; - // } - // operands[operandCount].type = AARCH64_OP_REG; - // operands[operandCount].access = CS_AC_WRITE; - // operandCount++; - // pos = operandStr.find("za", pos + 1); - // } - // break; - // } - // } + // Fix some inaccuracies in the decoded metadata + switch (opcode) { + // case Opcode::AArch64_ADR_LSL_ZZZ_D_0: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_D_1: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_D_2: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_D_3: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_S_0: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_S_1: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_S_2: + // [[fallthrough]]; + // case Opcode::AArch64_ADR_LSL_ZZZ_S_3: { + // // No defined access types + // operandCount = 3; + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[2].type = AARCH64_OP_REG; + // break; + // } + // case Opcode::AArch64_SMIN_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_EOR_ZPmZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_EOR_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_EOR_ZPmZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_EOR_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_AND_ZPmZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_AND_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_AND_ZPmZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_AND_ZPmZ_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_BICv4i32: + // // BIC incorrectly flags destination as WRITE only + // operands[0].access = CS_AC_WRITE | CS_AC_READ; + // break; + // case Opcode::AArch64_ADDSWri: + // // adds incorrectly flags destination as READ + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_BICv8i16: + // operands[0].access = CS_AC_WRITE | CS_AC_READ; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_BICv8i8: + // // access specifier for last operand was missing + // operands[2].access = CS_AC_READ; + // break; + case Opcode::AArch64_CASALW: + [[fallthrough]]; + case Opcode::AArch64_CASALX: + operandCount = 3; + operands[0].access = CS_AC_READ; + operands[1].access = CS_AC_READ; + operands[2].access = CS_AC_READ; + break; + // case Opcode::AArch64_CBNZW: + // [[fallthrough]]; + // case Opcode::AArch64_CBNZX: + // [[fallthrough]]; + // case Opcode::AArch64_CBZW: + // [[fallthrough]]; + // case Opcode::AArch64_CBZX: + // // incorrectly adds implicit nzcv dependency + // implicitSourceCount = 0; + // break; + // case Opcode::AArch64_CMPHI_PPzZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPHI_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPHI_PPzZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPHI_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_CMPGT_PPzZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPGT_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPGT_PPzZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPGT_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZI_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZI_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZI_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZI_S: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPEQ_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZI_B: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZI_D: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZI_H: + // [[fallthrough]]; + // case Opcode::AArch64_CMPNE_PPzZI_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // // Doesn't identify implicit NZCV destination + // implicitDestinationCount = 1; + // implicitDestinations[0] = AARCH64_REG_NZCV; + // break; + // case Opcode::AArch64_CNTB_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_CNTH_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_CNTD_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_CNTW_XPiI: { + // // lacking access specifiers for destination + // operands[0].access = CS_AC_WRITE; + // if (operandStr.length() < 4) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + // operands[1].ext = AARCH64_EXT_INVALID; + // operands[1].vector_index = -1; + // } + // break; + // } + // case Opcode::AArch64_ADD_ZI_B: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZI_D: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZI_H: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZI_S: { + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[2].type = AARCH64_OP_IMM; + // operandCount = 3; + + // // Extract immediate in SVE add with immediate instruction + // size_t start = operandStr.find("#"); + // // Identify whether the immediate value is in base-10 or base-16 + // if (start != std::string::npos) { + // start++; + // bool hex = false; + // if (operandStr[start + 1] == 'x') { + // hex = true; + // start += 2; + // } + + // uint8_t end = operandStr.size(); + // size_t shifted = operandStr.find("LSL"); + // if (shifted != std::string::npos) { + // std::cerr << "[SimEng:arch] SVE add with immediate has shift + // value + // " + // "in operandStr which is unsupported." + // << std::endl; + // exit(1); + // } + // // Convert extracted immediate from string to int64_t + // std::string sub = operandStr.substr(start, end); + // if (hex) { + // operands[2].imm = std::stoul(sub, 0, 16); + // } else { + // operands[2].imm = stoi(sub); + // } + // } else { + // operands[2].imm = 0; + // } + // break; + // } + // case Opcode::AArch64_AND_ZI: { + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[2].type = AARCH64_OP_IMM; + // operandCount = 3; + + // char specifier = operandStr[operandStr.find(".") + 1]; + // switch (specifier) { + // case 'b': { + // uint8_t mask = static_cast(operands[2].imm); + // operands[2].imm = static_cast(0); + // for (int i = 0; i < 8; i++) + // operands[2].imm |= (static_cast(mask) << (i * 8)); + // break; + // } + // case 'h': { + // uint16_t mask = static_cast(operands[2].imm); + // operands[2].imm = static_cast(0); + // for (int i = 0; i < 4; i++) + // operands[2].imm |= (static_cast(mask) << (i * 16)); + // break; + // } + // case 's': { + // uint32_t mask = static_cast(operands[2].imm); + // operands[2].imm = static_cast(0); + // for (int i = 0; i < 2; i++) + // operands[2].imm |= (static_cast(mask) << (i * 32)); + // break; + // } + // default: + // break; + // } + // break; + // } + // case Opcode::AArch64_CNTP_XPP_B: + // [[fallthrough]]; + // case Opcode::AArch64_CNTP_XPP_D: + // [[fallthrough]]; + // case Opcode::AArch64_CNTP_XPP_H: + // [[fallthrough]]; + // case Opcode::AArch64_CNTP_XPP_S: + // [[fallthrough]]; + // case Opcode::AArch64_EOR_ZZZ: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_DECD_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_DECB_XPiI: { + // // lacking access specifiers for destination + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // std::string str(operandStr); + // if (str.length() < 4) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + // operands[1].ext = AARCH64_EXT_INVALID; + // operands[1].vector_index = -1; + // } + // break; + // } + // case Opcode::AArch64_EOR_PPzPP: { + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_FMOVXDHighr: + // // FMOVXDHighr incorrectly flags destination as only WRITE + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // break; + // case Opcode::AArch64_FNMSB_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FNMSB_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FNMLS_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FNMLS_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMAD_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMAD_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMLA_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMLA_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMLS_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMLS_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMSB_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMSB_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_MLA_ZPmZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_MLA_ZPmZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_MLA_ZPmZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_MLA_ZPmZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_SMAX_ZPmZ_S: + // // No defined access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_ADDPL_XXI: + // [[fallthrough]]; + // case Opcode::AArch64_ADDVL_XXI: + // [[fallthrough]]; + // case Opcode::AArch64_UADDV_VPZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_UADDV_VPZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_UADDV_VPZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_UADDV_VPZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_MOVPRFX_ZPzZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_MOVPRFX_ZPzZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_SUB_ZZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_SUB_ZZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_SUB_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_SUB_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_II_B: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_II_H: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_II_S: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_II_D: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_IR_B: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_IR_D: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_IR_H: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_IR_S: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RI_B: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RI_D: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RI_H: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RI_S: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RR_B: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RR_D: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RR_H: + // [[fallthrough]]; + // case Opcode::AArch64_INDEX_RR_S: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FSUB_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FSUB_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMUL_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMUL_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_SMAX_ZI_S: + // [[fallthrough]]; + // case Opcode::AArch64_SMINV_VPZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_TRN1_ZZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_TRN1_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_TRN1_ZZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_TRN1_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_TRN2_ZZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_TRN2_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_TRN2_ZZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_TRN2_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_UZP1_ZZZ_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_MOVPRFX_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCPY_ZPmI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCPY_ZPmI_S: + // [[fallthrough]]; + // case Opcode::AArch64_FNEG_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FNEG_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FRINTN_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FRINTN_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FABS_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FABS_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FSQRT_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FSQRT_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCVTZS_ZPmZ_DtoD: + // [[fallthrough]]; + // case Opcode::AArch64_FCVTZS_ZPmZ_StoD: + // [[fallthrough]]; + // case Opcode::AArch64_FCVTZS_ZPmZ_StoS: + // [[fallthrough]]; + // case Opcode::AArch64_FCVTZS_ZPmZ_DtoS: + // // No defined access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_FMUL_ZPmI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMUL_ZPmI_S: { + // // No defined access types + // operandCount = 4; + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].type = AARCH64_OP_FP; + // operands[3].access = CS_AC_READ; + // // Doesn't recognise immediate operands + // // Extract two possible values, 0.5 or 2.0 + // if (operandStr.substr(operandStr.length() - 1, 1) == "5") { + // operands[3].fp = 0.5f; + // } else { + // operands[3].fp = 2.0f; + // } + + // break; + // } + // case Opcode::AArch64_FCMLA_ZPmZZ_D: { + // // No defined access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // operands[4].type = AARCH64_OP_IMM; + // break; + // } + // case Opcode::AArch64_FCADD_ZPmZ_D: { + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // operands[4].type = AARCH64_OP_IMM; + // break; + // } + // case Opcode::AArch64_FSUB_ZPmI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FSUB_ZPmI_S: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZPmI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZPmI_S: + // // No defined access types + // operandCount = 4; + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].type = AARCH64_OP_FP; + // operands[3].access = CS_AC_READ; + // // Doesn't recognise immediate operands + // // Extract two possible values, 0.5 or 1.0 + // if (operandStr.substr(operandStr.length() - 1, 1) == "5") { + // operands[3].fp = 0.5f; + // } else { + // operands[3].fp = 1.0f; + // } + // break; + // case Opcode::AArch64_FCMGT_PPzZ0_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGT_PPzZ0_S: { + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_FMLA_ZZZI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMLA_ZZZI_S: { + // // Need to define missing access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_FDIVR_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FDIVR_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FDIV_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_AND_PPzPP: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZPmZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZPmZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_ADD_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FADD_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGE_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGE_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGE_PPzZ0_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGE_PPzZ0_S: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGT_PPzZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCMGT_PPzZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FCMLE_PPzZ0_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCMLE_PPzZ0_S: + // [[fallthrough]]; + // case Opcode::AArch64_FCMLT_PPzZ0_S: + // [[fallthrough]]; + // case Opcode::AArch64_FMUL_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMUL_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FSUBR_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FSUBR_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FSUB_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FSUB_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_FADDA_VPZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_MUL_ZPmZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_MUL_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_MUL_ZPmZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_MUL_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_ORR_PPzPP: + // [[fallthrough]]; + // case Opcode::AArch64_SMULH_ZPmZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_SMULH_ZPmZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_SMULH_ZPmZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_SEL_ZPZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_SEL_ZPZZ_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_FRINTPDr: + // [[fallthrough]]; + // case Opcode::AArch64_FRINTPSr: + // [[fallthrough]]; + // case Opcode::AArch64_FDUP_ZI_D: + // [[fallthrough]]; + // case Opcode::AArch64_FDUP_ZI_S: + // [[fallthrough]]; + // case Opcode::AArch64_PUNPKHI_PP: + // [[fallthrough]]; + // case Opcode::AArch64_PUNPKLO_PP: + // [[fallthrough]]; + // case Opcode::AArch64_RDVLI_XI: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_INCB_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_INCD_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_INCH_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_INCW_XPiI: { + // // lacking access specifiers for destination + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // if (operandStr.length() < 4) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + // operands[1].ext = AARCH64_EXT_INVALID; + // operands[1].vector_index = -1; + // } + // break; + // } + // case Opcode::AArch64_INCD_ZPiI: + // [[fallthrough]]; + // case Opcode::AArch64_INCH_ZPiI: + // [[fallthrough]]; + // case Opcode::AArch64_INCW_ZPiI: { + // // lacking access specifiers for destination + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // if (operandStr.length() < 6) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // operands[1].access = CS_AC_READ; + // operands[1].shift = {AARCH64_SFT_INVALID, 0}; + // operands[1].ext = AARCH64_EXT_INVALID; + // operands[1].vector_index = -1; + // } + // break; + // } + // case Opcode::AArch64_INCP_XP_B: + // [[fallthrough]]; + // case Opcode::AArch64_INCP_XP_D: + // [[fallthrough]]; + // case Opcode::AArch64_INCP_XP_H: + // [[fallthrough]]; + // case Opcode::AArch64_INCP_XP_S: + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1i32: + // [[fallthrough]]; + // case Opcode::AArch64_LD1i64: + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_GLD1W_D_SCALED_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_GLD1W_SXTW_REAL: { + // // Access types are not set correctly + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_GLD1D_SCALED_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_GLD1D_REAL: { + // // LD1D gather instruction doesn't correctly identify destination + // // register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + // operands[0].reg = static_cast(reg_enum); + + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // LD1D gather instruction doesn't correctly identify memory + // operands operands[2].type = AARCH64_OP_MEM; operands[2].access = + // CS_AC_READ; + + // // LD1D doesn't correctly identify vector memory register correctly + // uint16_t vec_enum = AARCH64_REG_Z0; + // std::string tmp_str(operandStr.substr(operandStr.find("["))); + // // Single or double digit Z register identifier + // if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { + // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); + // } else { + // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); + // } + // operands[2].mem.index = static_cast(vec_enum); + // break; + // } + // case Opcode::AArch64_LD1RQ_W: + // [[fallthrough]]; + // case Opcode::AArch64_LD1RQ_W_IMM: { + // // LD1RQW doesn't identify correct access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_LD1RQ_D_IMM: { + // // LD1RQ gather instruction doesn't correctly identify destination + // // register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + // operands[0].reg = static_cast(reg_enum); + + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // LD1RQ gather instruction doesn't correctly identify memory + // operands operands[2].type = AARCH64_OP_MEM; operands[2].access = + // CS_AC_READ; break; + // } + // case Opcode::AArch64_GLD1SW_D_IMM_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_GLD1D_IMM_REAL: { + // // LD1D gather instruction doesn't correctly identify destination + // // register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // LD1D gather instruction doesn't correctly identify second Z reg + // as + // // memory operand + // operands[2].type = AARCH64_OP_MEM; + // operands[2].access = CS_AC_READ; + // // LD1D gather instruction doesn't recognise memory-offset + // immediate + // // correctly + // if (operandStr[operandStr.length() - 3] != '.') { + // int64_t startPos = operandStr.find('#') + 1; + // int64_t immSize = (operandStr.length() - 1) - startPos; + // if (immSize == 1) { + // operands[2].mem.disp = + // std::stoi(operandStr.substr(startPos, immSize)); + // } else { + // // double or triple digit immediates are converted to hex, and + // so + // // require a different conversion to uint + // operands[2].mem.disp = + // std::stoul(operandStr.substr(startPos, immSize), nullptr, + // 16); + // } + // } + // break; + // } + // case Opcode::AArch64_LD1B: + // [[fallthrough]]; + // case Opcode::AArch64_LD1D: + // [[fallthrough]]; + // case Opcode::AArch64_LD1B_IMM_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_LD1D_IMM_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_LD1RD_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_LD1RW_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_LD1H: + // [[fallthrough]]; + // case Opcode::AArch64_LD1W: + // [[fallthrough]]; + // case Opcode::AArch64_LD1W_IMM_REAL: { + // // LD1RW doesn't correctly identify destination register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_LD1Rv4s: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv1d: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv2d: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv2s: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv8b: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv16b: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv8h: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv4h: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1Rv4h_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv8h_POST: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ | CS_AC_WRITE; + // // Fix for exclusion of post_index immediate in disassembly + // operandCount = 3; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // // For vector arrangement of 16-bit, post_index immediate is 2 + // operands[2].imm = 2; + // break; + // case Opcode::AArch64_LD1Rv1d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv2d_POST: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ | CS_AC_WRITE; + // // Fix for exclusion of post_index immediate in disassembly + // operandCount = 3; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // // For vector arrangement of 64-bit, post_index immediate is 8 + // operands[2].imm = 8; + // break; + // case Opcode::AArch64_LD1Rv16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv8b_POST: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ | CS_AC_WRITE; + + // // Fix for exclusion of post_index immediate in disassembly + // operandCount = 3; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // // For vector arrangement of 8-bit, post_index immediate is 1 + // operands[2].imm = 1; + // break; + // case Opcode::AArch64_LD1Rv2s_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Rv4s_POST: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ | CS_AC_WRITE; + + // // Fix for exclusion of post_index immediate in disassembly + // operandCount = 3; + // operands[2].type = AARCH64_OP_IMM; + // operands[2].access = CS_AC_READ; + // // For vector arrangement of 32-bit, post_index immediate is 4 + // operands[2].imm = 4; + // break; + // case Opcode::AArch64_LD1Fourv16b: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Fourv4s: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Fourv2d: + // // Fix incorrect access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_WRITE; + // operands[2].access = CS_AC_WRITE; + // operands[3].access = CS_AC_WRITE; + // operands[4].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1Fourv16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Fourv2d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Fourv4s_POST: + // // Fix incorrect access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_WRITE; + // operands[2].access = CS_AC_WRITE; + // operands[3].access = CS_AC_WRITE; + // operands[4].access = CS_AC_READ | CS_AC_WRITE; + // operands[5].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1Onev16b: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1Onev16b_POST: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ | CS_AC_WRITE; + // break; + // case Opcode::AArch64_LD1Twov16b: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Twov4s: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Twov2d: + // // Fix incorrect access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_WRITE; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1Twov16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Twov2d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_LD1Twov4s_POST: + // // Fix incorrect access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_WRITE; + // operands[2].access = CS_AC_READ | CS_AC_WRITE; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LDADDLW: + // [[fallthrough]]; + // case Opcode::AArch64_LDADDW: + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_LD2Twov4s_POST: + // // Fixing wrong access flag for offset register operand + // if (operandCount == 4) { + // operands[3].access = CS_AC_READ; + // } + // break; + // case Opcode::AArch64_LDR_PXI: + // [[fallthrough]]; + // case Opcode::AArch64_LDR_ZXI: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LSL_ZZI_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // // No instruction id assigned + // id = AARCH64_INS_LSL; + // break; + // case Opcode::AArch64_LD2D: + // case Opcode::AArch64_LD2D_IMM: { + // // LD2D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - + // 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_WRITE; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_WRITE; + + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_LD3D_IMM: { + // // LD3D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + // uint16_t reg_enum2 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d, znn.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - + // 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest2 + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); + // } else { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_WRITE; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_WRITE; + // operands[2].reg = static_cast(reg_enum2); + // operands[2].access = CS_AC_WRITE; + + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_LD4D_IMM: { + // // LD4D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + // uint16_t reg_enum2 = AARCH64_REG_Z0; + // uint16_t reg_enum3 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d, znn.d, zmm.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - + // 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest2 + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest3 + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum3 += std::stoi(tmpOpStr.substr(1, 1)); + // } else { + // reg_enum3 += std::stoi(tmpOpStr.substr(1, 2)); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_WRITE; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_WRITE; + // operands[2].reg = static_cast(reg_enum2); + // operands[2].access = CS_AC_WRITE; + // operands[3].reg = static_cast(reg_enum3); + // operands[3].access = CS_AC_WRITE; + + // operands[4].access = CS_AC_READ; + // operands[5].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_MOVNWi: + // [[fallthrough]]; + // case Opcode::AArch64_MOVNXi: + // [[fallthrough]]; + // case Opcode::AArch64_MOVZWi: + // [[fallthrough]]; + // case Opcode::AArch64_MOVZXi: + // // MOVZ incorrectly flags destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_MOVPRFX_ZZ: + // // Assign operand access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_MRS: + // // MRS incorrectly flags source/destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // MRS incorrectly tags AARCH64_OP_REG_MRS as AARCH64_OP_SYS + // operands[1].type = AARCH64_OP_REG_MRS; + // break; + // case Opcode::AArch64_MSR: + // // MSR incorrectly flags source/destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // MSR incorrectly tags AARCH64_OP_REG_MSR as AARCH64_OP_SYS + // operands[0].type = AARCH64_OP_REG_MSR; + // break; + // case Opcode::AArch64_PTEST_PP: { + // // PTEST doesn't label access types for operands + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // // Doesn't identify implicit NZCV destination + // implicitDestinationCount = 1; + // implicitDestinations[0] = AARCH64_REG_NZCV; + // break; + // } + // case Opcode::AArch64_PTRUE_B: + // [[fallthrough]]; + // case Opcode::AArch64_PTRUE_H: + // [[fallthrough]]; + // case Opcode::AArch64_PTRUE_D: + // [[fallthrough]]; + // case Opcode::AArch64_PTRUE_S: + // // PTRUE doesn't label access + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_RET: + // // If no register supplied to RET, default to x30 (LR) + // if (operandCount == 0) { + // operandCount = 1; + // operands[0].type = AARCH64_OP_REG; + // operands[0].reg = AARCH64_REG_LR; + // operands[0].access = CS_AC_READ; + // } + // groupCount = 1; + // groups[0] = CS_GRP_JUMP; + // break; + // case Opcode::AArch64_REV_ZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_REV_ZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_REV_ZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_REV_ZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_B: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_D: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_H: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_S: { + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_SST1B_D_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_SST1D_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { + // // ST1W doesn't correctly identify first source register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // // SST1D{_SCALED} gather instruction doesn't correctly identify + // memory + // // operands + // operands[2].type = AARCH64_OP_MEM; + // operands[2].access = CS_AC_READ; + + // // ST1D doesn't correctly identify vector memory register correctly + // uint16_t vec_enum = AARCH64_REG_Z0; + // std::string tmp_str(operandStr.substr(operandStr.find("["))); + // // Single or double digit Z register identifier + // if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { + // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); + // } else { + // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); + // } + // operands[2].mem.index = static_cast(vec_enum); + // break; + // } + // case Opcode::AArch64_ST2D_IMM: { + // // ST2D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - + // 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_READ; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_READ; + + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_ST1B: + // [[fallthrough]]; + // case Opcode::AArch64_ST1D: + // [[fallthrough]]; + // case Opcode::AArch64_ST1B_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_ST1D_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_ST1W_IMM: { + // // ST1W doesn't correctly identify first source register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_ST1W: + // [[fallthrough]]; + // case Opcode::AArch64_ST1W_D: { + // // ST1W doesn't correctly identify first source register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_SST1D_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_SST1W_D_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_SST1W_IMM: { + // // ST1W scatter instruction doesn't correctly identify first source + // // register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // // ST1W scatter instruction doesn't correctly identify second Z reg + // as + // // memory operand + // operands[2].type = AARCH64_OP_MEM; + // operands[2].access = CS_AC_READ; + // // ST1W scatter instruction doesn't recognise memory-offset + // immediate + // // correctly + // if (operandStr[operandStr.length() - 3] != '.') { + // int64_t startPos = operandStr.find('#') + 1; + // int64_t immSize = (operandStr.length() - 1) - startPos; + // if (immSize == 1) { + // operands[2].mem.disp = + // std::stoi(operandStr.substr(startPos, immSize)); + // } else { + // // double or triple digit immediates are converted to hex, and + // so + // // require a different conversion to uint + // operands[2].mem.disp = + // std::stoul(operandStr.substr(startPos, immSize), nullptr, + // 16); + // } + // } + // break; + // } + // case Opcode::AArch64_ST1i8_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1i16_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1i32_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1i64_POST: + // // fixing incorrect access type for register offset + // if (operandCount == 3) { + // operands[2].access = CS_AC_READ; + // } + // break; + // case Opcode::AArch64_ST1Fourv16b: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv2d: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv4s: + // // ST1 incorrectly flags read and write + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // break; + // case Opcode::AArch64_ST1Fourv16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv2d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv2s_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv4s_POST: + // // ST1 incorrectly flags read and write + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ | CS_AC_WRITE; + // operands[5].access = CS_AC_READ; + // // determine correct type for operand 5 + // if (operandStr.find("#") != std::string::npos) { + // operands[5].type = AARCH64_OP_IMM; + // } else { + // operands[5].type = AARCH64_OP_REG; + // } + // break; + // case Opcode::AArch64_ST1Twov16b: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov2d: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov4s: + // // ST1 incorrectly flags read and write + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_ST1Twov16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov2d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov4s_POST: + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ | CS_AC_WRITE; + // operands[3].access = CS_AC_READ; + // // determine correct type for operand 3 + // if (operandStr.find("#") != std::string::npos) { + // operands[3].type = AARCH64_OP_IMM; + // } else { + // operands[3].type = AARCH64_OP_REG; + // } + // break; + // case Opcode::AArch64_ST2Twov4s_POST: + // // ST2 post incorrectly flags read and write + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ | CS_AC_WRITE; + // // Another incorrect access flag for register offset operand + // if (operandCount == 4) { + // operands[3].access = CS_AC_READ; + // } + // break; + // case Opcode::AArch64_STRBui: + // [[fallthrough]]; + // case Opcode::AArch64_STRDui: + // [[fallthrough]]; + // case Opcode::AArch64_STRHui: + // [[fallthrough]]; + // case Opcode::AArch64_STRQui: + // [[fallthrough]]; + // case Opcode::AArch64_STRSui: + // [[fallthrough]]; + // case Opcode::AArch64_STRWui: + // [[fallthrough]]; + // case Opcode::AArch64_STRXui: + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_PFALSE: + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_STR_PXI: + // [[fallthrough]]; + // case Opcode::AArch64_STR_ZXI: + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_SBFMWri: + // [[fallthrough]]; + // case Opcode::AArch64_SBFMXri: + // // SBFM incorrectly flags destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_SVC: + // // SVC is incorrectly marked as setting x30 + // implicitDestinationCount = 0; + // break; + // case Opcode::AArch64_SYSxt: + // // No defined metadata.id for SYS instructions + // id = AARCH64_INS_SYS; + // break; + // case Opcode::AArch64_PSEL_PPPRI_B: + // [[fallthrough]]; + // case Opcode::AArch64_PSEL_PPPRI_D: + // [[fallthrough]]; + // case Opcode::AArch64_PSEL_PPPRI_H: + // [[fallthrough]]; + // case Opcode::AArch64_PSEL_PPPRI_S: + // // Add correct access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_UBFMWri: + // [[fallthrough]]; + // case Opcode::AArch64_UBFMXri: + // // UBFM incorrectly flags destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_UQDECB_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECB_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECD_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECD_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECH_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECH_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECW_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECW_XPiI: + // // UQDEC lacks access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // if (operandCount == 1) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // } + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_UUNPKHI_ZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKHI_ZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKHI_ZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKLO_ZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKLO_ZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKLO_ZZ_S: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_WHILELT_PXX_B: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELT_PXX_D: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELT_PXX_H: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELT_PXX_S: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_B: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_D: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_H: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_S: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_B: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_D: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_H: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_S: + // // WHILELO doesn't label access or vector specifiers + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // // Doesn't identify implicit NZCV destination + // implicitDestinationCount = 1; + // implicitDestinations[0] = AARCH64_REG_NZCV; + // break; + // case Opcode::AArch64_XTNv16i8: + // case Opcode::AArch64_XTNv4i32: + // case Opcode::AArch64_XTNv8i16: + // // XTN2 incorrectly flags destination as only WRITE + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // break; + // case Opcode::AArch64_ZIP1_PPP_B: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_PPP_D: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_PPP_H: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_PPP_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_B: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_D: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_H: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_ZZZ_D: + // // ZIP lacks access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_SXTW_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCVT_ZPmZ_DtoS: + // [[fallthrough]]; + // case Opcode::AArch64_FCVT_ZPmZ_StoD: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_DtoS: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_StoD: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_StoS: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_DtoD: + // // Need to see if Destination vector elements are active + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8One: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8One: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8Two: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8Two: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8Three: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8Three: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8Four: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8Four: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // operands[5].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1_MXIPXX_H_D: + // [[fallthrough]]; + // case Opcode::AArch64_LD1_MXIPXX_V_D: + // [[fallthrough]]; + // case Opcode::AArch64_LD1_MXIPXX_V_S: + // [[fallthrough]]; + // case Opcode::AArch64_LD1_MXIPXX_H_S: { + // // Lacking access specifiers + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_ST1_MXIPXX_H_D: + // [[fallthrough]]; + // case Opcode::AArch64_ST1_MXIPXX_V_D: + // [[fallthrough]]; + // case Opcode::AArch64_ST1_MXIPXX_H_S: + // [[fallthrough]]; + // case Opcode::AArch64_ST1_MXIPXX_V_S: + // // Access types are not defined + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_FMOPA_MPPZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMOPA_MPPZZ_S: { + // // Need to add access specifiers + // // although operands[0] should be READ | WRITE, due to the + // implemented + // // decode logic for SME tile destinations, the register will be + // added as + // // both source and destination with just WRITE access. + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // operands[5].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_EXTRACT_ZPMXI_H_B: { + // operandCount = 4; + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].reg = operands[2].sme_index.base; + // operands[3].access = CS_AC_READ; + // break; + // } + case Opcode::AArch64_ZERO_M: { + // Operands often mangled from ZA tile overlap aliasing in decode. + // Need to re-extract relevant tiles from operandStr + operandCount = 0; + size_t pos = operandStr.find("za", 0); + while (pos != std::string::npos) { + size_t pos_2 = operandStr.find(".", pos); + if (pos_2 != std::string::npos) { + char type = operandStr[pos_2 + 1]; + // Tile Number can only ever be 1 digit + uint8_t tileNum = std::stoi(operandStr.substr((pos + 2), 1)); + switch (type) { + case 'b': + operands[operandCount].sme.tile = AARCH64_REG_ZAB0; + break; + case 'h': + + operands[operandCount].sme.tile = + static_cast(AARCH64_REG_ZAH0 + tileNum); + break; + case 's': + + operands[operandCount].sme.tile = + static_cast(AARCH64_REG_ZAS0 + tileNum); + break; + case 'd': + + operands[operandCount].sme.tile = + static_cast(AARCH64_REG_ZAD0 + tileNum); + break; + case 'q': + + operands[operandCount].sme.tile = + static_cast(AARCH64_REG_ZAQ0 + tileNum); + break; + } + } else { + operands[operandCount].sme.tile = AARCH64_REG_ZA; + } + operands[operandCount].type = AARCH64_OP_SME; + operands[operandCount].access = CS_AC_WRITE; + operandCount++; + pos = operandStr.find("za", pos + 1); + } + break; + } + } if (insn.is_alias) { // revertAliasing(); @@ -1767,7 +1784,7 @@ InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, implicitDestinationCount(0), groupCount(0), setsFlags(false), - writeback(false), + isAlias(false), operandCount(0) { assert(bytes <= sizeof(encoding)); std::memcpy(encoding, invalidEncoding, bytes); diff --git a/src/lib/arch/aarch64/InstructionMetadata.hh b/src/lib/arch/aarch64/InstructionMetadata.hh index 9e44b1980f..1c4a48048b 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.hh +++ b/src/lib/arch/aarch64/InstructionMetadata.hh @@ -88,9 +88,9 @@ struct InstructionMetadata { uint8_t cc; /** Whether this instruction sets the condition flags. */ bool setsFlags; - /** Whether this instruction performs a base-address register writeback - * operation. */ - bool writeback; + + /** Whether this instruction is an alias. */ + bool isAlias; /** The explicit operands. */ cs_aarch64_op operands[MAX_OPERANDS]; diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index b03934d81b..5dc5709071 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -1,3 +1,5 @@ +#include + #include "InstructionMetadata.hh" #define NOT(bits, length) (~bits & (1 << length - 1)) @@ -44,6 +46,7 @@ Register csRegToRegister(aarch64_reg reg) { // (full vector) or Dn (half vector). // As D and Q registers are also of type RegisterType::VECTOR, the outcome // will be the same + std::cerr << "Reg = " << reg << std::endl; // Assert that reg is not a SME tile as these should be passed to // `getZARowVectors()` @@ -197,6 +200,14 @@ void Instruction::decode() { return; } + std::cerr << metadata_.opcode << ":" << metadata_.mnemonic << " " + << metadata_.operandStr << ", reg count " + << (unsigned)metadata_.operandCount << " ---- " << std::hex + << (unsigned)metadata_.encoding[0] << " " + << (unsigned)metadata_.encoding[1] << " " + << (unsigned)metadata_.encoding[2] << " " + << (unsigned)metadata_.encoding[3] << " " << std::dec << std::endl; + // Extract implicit writes, including pre/post index writeback for (size_t i = 0; i < metadata_.implicitDestinationCount; i++) { if (metadata_.implicitDestinations[i] == AARCH64_REG_NZCV && @@ -206,6 +217,7 @@ void Instruction::decode() { // destination. Ignore continue; } + std::cerr << "\tImplicit write - "; destinationRegisters_[destinationRegisterCount_] = csRegToRegister( static_cast(metadata_.implicitDestinations[i])); destinationRegisterCount_++; @@ -213,6 +225,12 @@ void Instruction::decode() { // Extract implicit reads for (size_t i = 0; i < metadata_.implicitSourceCount; i++) { + // TODO: Implement FPCR usage properly + // Ignore implicit reading of FPCR + if (static_cast(metadata_.implicitSources[i]) == + AARCH64_REG_FPCR) + continue; + std::cerr << "\tImplicit Read - "; sourceRegisters_[sourceOperandsPending_] = csRegToRegister(static_cast(metadata_.implicitSources[i])); sourceRegisterCount_++; @@ -246,6 +264,7 @@ void Instruction::decode() { // Add register writes to destinations, but skip zero-register // destinations + std::cerr << "\tReg Write - "; destinationRegisters_[destinationRegisterCount_] = csRegToRegister(op.reg); destinationRegisterCount_++; @@ -253,7 +272,7 @@ void Instruction::decode() { } if (op.access & cs_ac_type::CS_AC_READ) { // Add register reads to destinations - + std::cerr << "\tReg read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.reg); sourceRegisterCount_++; sourceOperandsPending_++; @@ -273,19 +292,14 @@ void Instruction::decode() { // Check base register exists if (op.mem.base != AARCH64_REG_INVALID) { accessesMemory = true; + std::cerr << "\tMem base read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.mem.base); sourceRegisterCount_++; sourceOperandsPending_++; } - - // if (metadata_.writeback) { - // // Writeback instructions modify the base address - // destinationRegisters_[destinationRegisterCount_] = - // csRegToRegister(op.mem.base); - // destinationRegisterCount_++; - // } if (op.mem.index != AARCH64_REG_INVALID) { // Register offset; add to sources + std::cerr << "\tMem index read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.mem.index); sourceRegisterCount_++; sourceOperandsPending_++; @@ -317,6 +331,7 @@ void Instruction::decode() { if (op.sme.type == AARCH64_SME_OP_TILE_VEC) { // SME tile has slice determined by register and immidiate. // Add base register to source operands + std::cerr << "\tSME tile vec base - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.sme.slice_reg); sourceRegisterCount_++; @@ -324,16 +339,19 @@ void Instruction::decode() { } } else if (op.type == AARCH64_OP_PRED) { if (op.access == CS_AC_READ) { + std::cerr << "\tPred read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.pred.reg); sourceRegisterCount_++; sourceOperandsPending_++; } if (op.access == CS_AC_WRITE) { + std::cerr << "\tPred write - "; destinationRegisters_[destinationRegisterCount_] = csRegToRegister(op.pred.reg); destinationRegisterCount_++; } if (op.pred.vec_select != AARCH64_REG_INVALID) { + std::cerr << "\tPred vec select read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.pred.vec_select); sourceRegisterCount_++; @@ -361,8 +379,8 @@ void Instruction::decode() { } } else if (metadata_.operands[0].type == AARCH64_OP_SYSALIAS && metadata_.operands[0].sysop.sub_type == AARCH64_OP_SVCR) { - // Updating of SVCR is done via an exception and not via the sysreg file. - // No operands are required for this operation. + // This case is for instruction alias SMSTART and SMSTOP. Updating of SVCR + // value is done via an exception so no registers required. } } @@ -468,15 +486,15 @@ void Instruction::decode() { } // LDADD* are considered to be both a load and a store - if (AARCH64_INS_LDADDAB <= metadata_.id && - metadata_.id <= AARCH64_INS_LDADD) { + if (Opcode::AArch64_LDADDAB <= metadata_.opcode && + metadata_.opcode <= Opcode::AArch64_LDADDX) { setInstructionType(InsnType::isLoad); setInstructionType(InsnType::isStoreData); } // CASAL* are considered to be both a load and a store - if (metadata_.opcode == Opcode::AArch64_CASALW || - metadata_.opcode == Opcode::AArch64_CASALX) { + if (Opcode::AArch64_CASALB <= metadata_.opcode && + metadata_.opcode <= Opcode::AArch64_CASALX) { setInstructionType(InsnType::isLoad); setInstructionType(InsnType::isStoreData); } @@ -510,23 +528,72 @@ void Instruction::decode() { setInstructionType(InsnType::isLoad); } - if ((264 <= metadata_.opcode && metadata_.opcode <= 267) || // AND - (1063 <= metadata_.opcode && metadata_.opcode <= 1084) || // AND (pt.2) - (284 <= metadata_.opcode && metadata_.opcode <= 287) || // BIC - (1167 <= metadata_.opcode && metadata_.opcode <= 1183) || // BIC (pt.2) - (321 <= metadata_.opcode && metadata_.opcode <= 324) || // EOR/EON - (1707 <= metadata_.opcode && - metadata_.opcode <= 1736) || // EOR/EON (pt.2) - (771 <= metadata_.opcode && metadata_.opcode <= 774) || // ORR/ORN - (3748 <= metadata_.opcode && - metadata_.opcode <= 3771)) { // ORR/ORN (pt.2) + // Identify Logical (bitwise) instructions + if (regex_match(metadata_.mnemonic, std::regex("(and)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bic)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bif)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bit)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bsl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bcax)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bmop)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(eor)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(eon)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(mvn)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(not)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(nand)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(nbsl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(nor)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(rax)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(xar)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(orr)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(orq)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(orv)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(tst)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(orn)(.*)"))) { setInstructionType(InsnType::isLogical); } - if ((1252 <= metadata_.opcode && metadata_.opcode <= 1259) || - (1314 <= metadata_.opcode && metadata_.opcode <= 1501) || - (1778 <= metadata_.opcode && metadata_.opcode <= 1799) || - (1842 <= metadata_.opcode && metadata_.opcode <= 1969)) { + // Identify comparison insturctions (excluding atomic LD-CMP-STR) + if (regex_match(metadata_.mnemonic, std::regex("(ccmn)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmn)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmp)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmpp)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(ccmp)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmeq)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmge)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmgt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmtst)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmhi)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmhs)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmle)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmlt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmpeq)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmpge)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmpgt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmphi)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmphs)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmple)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmplo)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmpls)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmplt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmpne)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmptst)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(facge)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(facgt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(facle)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(faclt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fccmp)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fccmpe)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcmeq)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcmge)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcmgt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcmle)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcmlt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcmne)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcmp)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcmpe)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcmuo)(.*)"))) { setInstructionType(InsnType::isCompare); // Capture those floating point compare instructions with no destination // register @@ -539,14 +606,46 @@ void Instruction::decode() { } } - if ((347 <= metadata_.opcode && metadata_.opcode <= 366) || - (1142 <= metadata_.opcode && metadata_.opcode <= 1146) || - (1976 <= metadata_.opcode && metadata_.opcode <= 2186) || - (metadata_.opcode == 2207) || - (782 <= metadata_.opcode && metadata_.opcode <= 788) || - (4063 <= metadata_.opcode && metadata_.opcode <= 4097) || - (898 <= metadata_.opcode && metadata_.opcode <= 904) || - (5608 <= metadata_.opcode && metadata_.opcode <= 5642)) { + // Identify convert instructions + if (regex_match(metadata_.mnemonic, std::regex("(bf1cvtl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bf2cvtl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfcvt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfcvtn)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(f1cvtl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(f2cvtl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtas)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtau)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtms)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtmu)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtn)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtns)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtnu)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtps)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtpu)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtxn)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtzs)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtzu)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fjcvtzs)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(scvtf)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(ucvtf)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bf1cvt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bf2cvt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bf1cvtlt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bf2cvtlt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfcvtnt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(f1cvt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(f2cvt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(f1cvtlt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(f2cvtlt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtlt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtnb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtnt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtx)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtxnt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtzs)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcvtzu)(.*)"))) { setInstructionType(InsnType::isConvert); // Capture those floating point convert instructions whose destination // register is general purpose @@ -558,105 +657,263 @@ void Instruction::decode() { } // Identify divide or square root operations - if ((367 <= metadata_.opcode && metadata_.opcode <= 375) || - (789 <= metadata_.opcode && metadata_.opcode <= 790) || - (905 <= metadata_.opcode && metadata_.opcode <= 906) || - (2187 <= metadata_.opcode && metadata_.opcode <= 2200) || - (4098 <= metadata_.opcode && metadata_.opcode <= 4103) || - (5644 <= metadata_.opcode && metadata_.opcode <= 5649) || - (481 <= metadata_.opcode && metadata_.opcode <= 483) || - (metadata_.opcode == 940) || - (2640 <= metadata_.opcode && metadata_.opcode <= 2661) || - (2665 <= metadata_.opcode && metadata_.opcode <= 2675) || - (6066 <= metadata_.opcode && metadata_.opcode <= 6068)) { + if (regex_match(metadata_.mnemonic, std::regex("(sdiv)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(udiv)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fdiv)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fdivr)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sdivr)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(udivr)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(frsqrte)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(frsqrts)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fsqrt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(ursqrte)(.*)"))) { setInstructionType(InsnType::isDivideOrSqrt); } // Identify multiply operations - if ((433 <= metadata_.opcode && - metadata_.opcode <= 447) || // all MUL variants - (759 <= metadata_.opcode && metadata_.opcode <= 762) || - (816 <= metadata_.opcode && metadata_.opcode <= 819) || - (915 <= metadata_.opcode && metadata_.opcode <= 918) || - (2436 <= metadata_.opcode && metadata_.opcode <= 2482) || - (2512 <= metadata_.opcode && metadata_.opcode <= 2514) || - (2702 <= metadata_.opcode && metadata_.opcode <= 2704) || - (3692 <= metadata_.opcode && metadata_.opcode <= 3716) || - (3793 <= metadata_.opcode && metadata_.opcode <= 3805) || - (4352 <= metadata_.opcode && metadata_.opcode <= 4380) || - (4503 <= metadata_.opcode && metadata_.opcode <= 4543) || - (4625 <= metadata_.opcode && metadata_.opcode <= 4643) || - (5804 <= metadata_.opcode && metadata_.opcode <= 5832) || - (2211 <= metadata_.opcode && - metadata_.opcode <= 2216) || // all MADD/MAD variants - (2494 <= metadata_.opcode && metadata_.opcode <= 2499) || - (2699 <= metadata_.opcode && metadata_.opcode <= 2701) || - (3610 <= metadata_.opcode && metadata_.opcode <= 3615) || - (4227 == metadata_.opcode) || (5682 == metadata_.opcode) || - (2433 <= metadata_.opcode && - metadata_.opcode <= 2435) || // all MSUB variants - (2509 <= metadata_.opcode && metadata_.opcode <= 2511) || - (3690 <= metadata_.opcode && metadata_.opcode <= 3691) || - (4351 == metadata_.opcode) || (5803 == metadata_.opcode) || - (424 <= metadata_.opcode && - metadata_.opcode <= 426) || // all MLA variants - (451 <= metadata_.opcode && metadata_.opcode <= 453) || - (1151 <= metadata_.opcode && metadata_.opcode <= 1160) || - (1378 <= metadata_.opcode && metadata_.opcode <= 1383) || - (1914 <= metadata_.opcode && metadata_.opcode <= 1926) || - (2341 <= metadata_.opcode && metadata_.opcode <= 2371) || - (2403 <= metadata_.opcode && metadata_.opcode <= 2404) || - (2500 <= metadata_.opcode && metadata_.opcode <= 2502) || - (3618 <= metadata_.opcode && metadata_.opcode <= 3634) || - (4295 <= metadata_.opcode && metadata_.opcode <= 4314) || - (4335 <= metadata_.opcode && metadata_.opcode <= 4336) || - (4453 <= metadata_.opcode && metadata_.opcode <= 4477) || - (4581 <= metadata_.opcode && metadata_.opcode <= 4605) || - (5749 <= metadata_.opcode && metadata_.opcode <= 5768) || - (5789 <= metadata_.opcode && metadata_.opcode <= 5790) || - (6115 <= metadata_.opcode && metadata_.opcode <= 6116) || - (427 <= metadata_.opcode && - metadata_.opcode <= 429) || // all MLS variants - (454 <= metadata_.opcode && metadata_.opcode <= 456) || - (2372 <= metadata_.opcode && metadata_.opcode <= 2402) || - (2503 <= metadata_.opcode && metadata_.opcode <= 2505) || - (3635 <= metadata_.opcode && metadata_.opcode <= 3651) || - (4315 <= metadata_.opcode && metadata_.opcode <= 4334) || - (4478 <= metadata_.opcode && metadata_.opcode <= 4502) || - (4606 <= metadata_.opcode && metadata_.opcode <= 4624) || - (5769 <= metadata_.opcode && metadata_.opcode <= 5788) || - (2430 <= metadata_.opcode && - metadata_.opcode <= 2432) || // all MSB variants - (2506 <= metadata_.opcode && metadata_.opcode <= 2508) || - (3682 <= metadata_.opcode && metadata_.opcode <= 3685) || - (2405 <= metadata_.opcode && - metadata_.opcode <= 2408) || // all SME FMOPS & FMOPA variants - (4337 <= metadata_.opcode && metadata_.opcode <= 4340) || - (5391 <= metadata_.opcode && metadata_.opcode <= 5394) || - (5791 <= metadata_.opcode && metadata_.opcode <= 5794) || - (6117 <= metadata_.opcode && metadata_.opcode <= 6120)) { + if (regex_match(metadata_.mnemonic, std::regex("(madd)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(maddpt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(mneg)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(msub)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(msubpt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(mul)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smaddl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smnegl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smsubl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smulh)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smull)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umaddl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umnegl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umsubl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umulh)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umull)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmlalb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmlalt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmmla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fcmla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmadd)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlal)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlal2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlalb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlalt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlallbb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlallbt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlalltb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlalltt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmls)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlsl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlsl2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmsub)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmul)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmulx)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fnmadd)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fnmsub)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fnmul)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(mla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(mls)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(mul)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(pmul)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(pmull)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(pmull2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smlal)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smlal2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smlsl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smlsl2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smmla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smull)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smull2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmlal)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmlal2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmlsl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmlsl2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmulh)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmull)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmull2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqrdmlah)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqrdmlsh)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqrdmulh)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umlal)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umlal2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umlsl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umlsl2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(ummla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umull)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umull2)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(usmmla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmls)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmlslb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmlslt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmul)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cmla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmad)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlslb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlslt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmmla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmsb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fnmad)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fnmla)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fnmls)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fnmsb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(ftmad)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(mad)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(madpt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(mlapt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(msb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(pmullb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(pmullt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smlalb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smlalt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smlslb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smlslt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smullb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smullt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmlalb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmlalbt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmlalt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmlslb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmlslbt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmlslt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmullb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqdmullt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sqrdcmlah)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umlalb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umlalt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umlslb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umlslt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umullb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umullt)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmlal)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmlsl)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmlall)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smlall)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smlsll)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sumlall)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umlall)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umlsll)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(usmlall)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfdot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfvdot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fdot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fvdot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fvdotb)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fvdott)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sdot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sudot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(suvdot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(udot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(usdot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(usvdot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(uvdot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(cdot)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmopa)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bfmops)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bmopa)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(bmops)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmopa)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(fmops)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smopa)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(smops)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sumopa)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(sumops)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umopa)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(umops)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(usmopa)(.*)")) || + regex_match(metadata_.mnemonic, std::regex("(usmops)(.*)"))) { setInstructionType(InsnType::isMultiply); } + // + // if ((433 <= metadata_.opcode && + // metadata_.opcode <= 447) || // all MUL variants + // (759 <= metadata_.opcode && metadata_.opcode <= 762) || + // (816 <= metadata_.opcode && metadata_.opcode <= 819) || + // (915 <= metadata_.opcode && metadata_.opcode <= 918) || + // (2436 <= metadata_.opcode && metadata_.opcode <= 2482) || + // (2512 <= metadata_.opcode && metadata_.opcode <= 2514) || + // (2702 <= metadata_.opcode && metadata_.opcode <= 2704) || + // (3692 <= metadata_.opcode && metadata_.opcode <= 3716) || + // (3793 <= metadata_.opcode && metadata_.opcode <= 3805) || + // (4352 <= metadata_.opcode && metadata_.opcode <= 4380) || + // (4503 <= metadata_.opcode && metadata_.opcode <= 4543) || + // (4625 <= metadata_.opcode && metadata_.opcode <= 4643) || + // (5804 <= metadata_.opcode && metadata_.opcode <= 5832) || + // (2211 <= metadata_.opcode && + // metadata_.opcode <= 2216) || // all MADD/MAD variants + // (2494 <= metadata_.opcode && metadata_.opcode <= 2499) || + // (2699 <= metadata_.opcode && metadata_.opcode <= 2701) || + // (3610 <= metadata_.opcode && metadata_.opcode <= 3615) || + // (4227 == metadata_.opcode) || (5682 == metadata_.opcode) || + // (2433 <= metadata_.opcode && + // metadata_.opcode <= 2435) || // all MSUB variants + // (2509 <= metadata_.opcode && metadata_.opcode <= 2511) || + // (3690 <= metadata_.opcode && metadata_.opcode <= 3691) || + // (4351 == metadata_.opcode) || (5803 == metadata_.opcode) || + // (424 <= metadata_.opcode && + // metadata_.opcode <= 426) || // all MLA variants + // (451 <= metadata_.opcode && metadata_.opcode <= 453) || + // (1151 <= metadata_.opcode && metadata_.opcode <= 1160) || + // (1378 <= metadata_.opcode && metadata_.opcode <= 1383) || + // (1914 <= metadata_.opcode && metadata_.opcode <= 1926) || + // (2341 <= metadata_.opcode && metadata_.opcode <= 2371) || + // (2403 <= metadata_.opcode && metadata_.opcode <= 2404) || + // (2500 <= metadata_.opcode && metadata_.opcode <= 2502) || + // (3618 <= metadata_.opcode && metadata_.opcode <= 3634) || + // (4295 <= metadata_.opcode && metadata_.opcode <= 4314) || + // (4335 <= metadata_.opcode && metadata_.opcode <= 4336) || + // (4453 <= metadata_.opcode && metadata_.opcode <= 4477) || + // (4581 <= metadata_.opcode && metadata_.opcode <= 4605) || + // (5749 <= metadata_.opcode && metadata_.opcode <= 5768) || + // (5789 <= metadata_.opcode && metadata_.opcode <= 5790) || + // (6115 <= metadata_.opcode && metadata_.opcode <= 6116) || + // (427 <= metadata_.opcode && + // metadata_.opcode <= 429) || // all MLS variants + // (454 <= metadata_.opcode && metadata_.opcode <= 456) || + // (2372 <= metadata_.opcode && metadata_.opcode <= 2402) || + // (2503 <= metadata_.opcode && metadata_.opcode <= 2505) || + // (3635 <= metadata_.opcode && metadata_.opcode <= 3651) || + // (4315 <= metadata_.opcode && metadata_.opcode <= 4334) || + // (4478 <= metadata_.opcode && metadata_.opcode <= 4502) || + // (4606 <= metadata_.opcode && metadata_.opcode <= 4624) || + // (5769 <= metadata_.opcode && metadata_.opcode <= 5788) || + // (2430 <= metadata_.opcode && + // metadata_.opcode <= 2432) || // all MSB variants + // (2506 <= metadata_.opcode && metadata_.opcode <= 2508) || + // (3682 <= metadata_.opcode && metadata_.opcode <= 3685) || + // (2405 <= metadata_.opcode && + // metadata_.opcode <= 2408) || // all SME FMOPS & FMOPA variants + // (4337 <= metadata_.opcode && metadata_.opcode <= 4340) || + // (5391 <= metadata_.opcode && metadata_.opcode <= 5394) || + // (5791 <= metadata_.opcode && metadata_.opcode <= 5794) || + // (6117 <= metadata_.opcode && metadata_.opcode <= 6120)) { + // setInstructionType(InsnType::isMultiply); + // } + // Catch exceptions to the above identifier assignments // Uncaught predicate assignment due to lacking destination register if (metadata_.opcode == Opcode::AArch64_PTEST_PP) { setInstructionType(InsnType::isPredicate); } // Uncaught float data assignment for FMOV move to general instructions - if (((430 <= metadata_.opcode && metadata_.opcode <= 432) || - (2409 <= metadata_.opcode && metadata_.opcode <= 2429)) && + if (((Opcode::AArch64_FMOVD0 <= metadata_.opcode && + metadata_.opcode <= Opcode::AArch64_FMOVS0) || + (Opcode::AArch64_FMOVDXHighr <= metadata_.opcode && + metadata_.opcode <= Opcode::AArch64_FMOVv8f16_ns)) && !(isInstruction(InsnType::isScalarData) || isInstruction(InsnType::isVectorData))) { setInstructionType(InsnType::isScalarData); } // Uncaught vector data assignment for SMOV and UMOV instructions - if ((4341 <= metadata_.opcode && metadata_.opcode <= 4350) || - (5795 <= metadata_.opcode && metadata_.opcode <= 5802)) { + if ((Opcode::AArch64_SMOVvi16to32 <= metadata_.opcode && + metadata_.opcode <= Opcode::AArch64_SMOVvi8to64_idx0) || + (Opcode::AArch64_UMOVvi16 <= metadata_.opcode && + metadata_.opcode <= Opcode::AArch64_UMOVvi8_idx0)) { setInstructionType(InsnType::isVectorData); } // Uncaught float data assignment for FCVT convert to general instructions - if ((1976 <= metadata_.opcode && metadata_.opcode <= 2186) && + if ((Opcode::AArch64_FCVTASUWDr <= metadata_.opcode && + metadata_.opcode <= Opcode::AArch64_FCVT_ZPmZ_StoH) && !(isInstruction(InsnType::isScalarData) || isInstruction(InsnType::isVectorData))) { setInstructionType(InsnType::isScalarData); @@ -672,8 +929,8 @@ void Instruction::decode() { } } } else { - // For SME instructions, resize the following structures to have the exact - // amount of space required + // For SME instructions, resize the following structures to have the + // exact amount of space required sourceRegisters_.resize(sourceRegisterCount_); destinationRegisters_.resize(destinationRegisterCount_); sourceValues_.resize(sourceRegisterCount_); diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index 206e222916..d44251ed9d 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -3851,8 +3851,7 @@ void Instruction::execute() { case Opcode::AArch64_MSR: { // msr (systemreg|Sop0_op1_Cn_Cm_op2), xt // Handle case where SVCR is being updated as this invokes additional // functionality - if (metadata_.operands[0].type == AARCH64_OP_SYSALIAS && - metadata_.operands[0].sysop.sub_type == AARCH64_OP_SVCR) { + if (metadata_.operands[0].sysop.reg.sysreg == AARCH64_SYSREG_SVCR) { return SMZAupdated(); } else { results_[0] = sourceValues_[0]; diff --git a/test/integration/ConfigTest.cc b/test/integration/ConfigTest.cc index 4e6ac2ad68..805294a725 100644 --- a/test/integration/ConfigTest.cc +++ b/test/integration/ConfigTest.cc @@ -17,14 +17,14 @@ TEST(ConfigTest, Default) { simeng::config::SimulationMode::Emulation); EXPECT_EQ(simeng::config::SimInfo::getSimModeStr(), "Emulation"); std::vector sysRegisterEnums = { - arm64_sysreg::ARM64_SYSREG_DCZID_EL0, - arm64_sysreg::ARM64_SYSREG_FPCR, - arm64_sysreg::ARM64_SYSREG_FPSR, - arm64_sysreg::ARM64_SYSREG_TPIDR_EL0, - arm64_sysreg::ARM64_SYSREG_MIDR_EL1, - arm64_sysreg::ARM64_SYSREG_CNTVCT_EL0, - arm64_sysreg::ARM64_SYSREG_PMCCNTR_EL0, - arm64_sysreg::ARM64_SYSREG_SVCR}; + aarch64_sysreg::AARCH64_SYSREG_DCZID_EL0, + aarch64_sysreg::AARCH64_SYSREG_FPCR, + aarch64_sysreg::AARCH64_SYSREG_FPSR, + aarch64_sysreg::AARCH64_SYSREG_TPIDR_EL0, + aarch64_sysreg::AARCH64_SYSREG_MIDR_EL1, + aarch64_sysreg::AARCH64_SYSREG_CNTVCT_EL0, + aarch64_sysreg::AARCH64_SYSREG_PMCCNTR_EL0, + aarch64_sysreg::AARCH64_SYSREG_SVCR}; EXPECT_EQ(simeng::config::SimInfo::getSysRegVec(), sysRegisterEnums); std::vector archRegStruct = { {8, 32}, @@ -375,14 +375,14 @@ TEST(ConfigTest, configFromFile) { simeng::config::SimulationMode::Outoforder); EXPECT_EQ(simeng::config::SimInfo::getSimModeStr(), "Out-of-Order"); std::vector sysRegisterEnums = { - arm64_sysreg::ARM64_SYSREG_DCZID_EL0, - arm64_sysreg::ARM64_SYSREG_FPCR, - arm64_sysreg::ARM64_SYSREG_FPSR, - arm64_sysreg::ARM64_SYSREG_TPIDR_EL0, - arm64_sysreg::ARM64_SYSREG_MIDR_EL1, - arm64_sysreg::ARM64_SYSREG_CNTVCT_EL0, - arm64_sysreg::ARM64_SYSREG_PMCCNTR_EL0, - arm64_sysreg::ARM64_SYSREG_SVCR}; + aarch64_sysreg::AARCH64_SYSREG_DCZID_EL0, + aarch64_sysreg::AARCH64_SYSREG_FPCR, + aarch64_sysreg::AARCH64_SYSREG_FPSR, + aarch64_sysreg::AARCH64_SYSREG_TPIDR_EL0, + aarch64_sysreg::AARCH64_SYSREG_MIDR_EL1, + aarch64_sysreg::AARCH64_SYSREG_CNTVCT_EL0, + aarch64_sysreg::AARCH64_SYSREG_PMCCNTR_EL0, + aarch64_sysreg::AARCH64_SYSREG_SVCR}; EXPECT_EQ(simeng::config::SimInfo::getSysRegVec(), sysRegisterEnums); std::vector archRegStruct = { {8, 32}, diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index b0774c15c6..a0c06731c7 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -162,7 +162,7 @@ inline std::vector> genCoreTypeSVLPairs( * For example: * * // Compare za1h.s[0] to some expected 32-bit floating point values. - * CHECK_MAT_ROW(ARM64_REG_ZAS1, 0, float, {123.456f, 0.f, 42.f, -1.f}); + * CHECK_MAT_ROW(AARCH64_REG_ZAS1, 0, float, {123.456f, 0.f, 42.f, -1.f}); */ #define CHECK_MAT_ROW(tag, index, type, ...) \ { \ @@ -181,7 +181,7 @@ inline std::vector> genCoreTypeSVLPairs( * For example: * * // Compare za1v.s[0] to some expected 32-bit floating point values. - * CHECK_MAT_COL(ARM64_REG_ZAS1, 0, float, {123.456f, 0.f, 42.f, -1.f}); + * CHECK_MAT_COL(AARCH64_REG_ZAS1, 0, float, {123.456f, 0.f, 42.f, -1.f}); */ #define CHECK_MAT_COL(tag, index, type, ...) \ { \ @@ -289,22 +289,22 @@ class AArch64RegressionTest : public RegressionTest { // Get matrix row register tag uint8_t base = 0; uint8_t tileTypeCount = 0; - if (tag == ARM64_REG_ZA || tag == ARM64_REG_ZAB0) { + if (tag == AARCH64_REG_ZA || tag == AARCH64_REG_ZAB0) { // Treat ZA as byte tile : ZAB0 represents whole matrix, only 1 tile // Add all rows for this SVL // Don't need to set base as will always be 0 tileTypeCount = 1; - } else if (tag >= ARM64_REG_ZAH0 && tag <= ARM64_REG_ZAH1) { - base = tag - ARM64_REG_ZAH0; + } else if (tag >= AARCH64_REG_ZAH0 && tag <= AARCH64_REG_ZAH1) { + base = tag - AARCH64_REG_ZAH0; tileTypeCount = 2; - } else if (tag >= ARM64_REG_ZAS0 && tag <= ARM64_REG_ZAS3) { - base = tag - ARM64_REG_ZAS0; + } else if (tag >= AARCH64_REG_ZAS0 && tag <= AARCH64_REG_ZAS3) { + base = tag - AARCH64_REG_ZAS0; tileTypeCount = 4; - } else if (tag >= ARM64_REG_ZAD0 && tag <= ARM64_REG_ZAD7) { - base = tag - ARM64_REG_ZAD0; + } else if (tag >= AARCH64_REG_ZAD0 && tag <= AARCH64_REG_ZAD7) { + base = tag - AARCH64_REG_ZAD0; tileTypeCount = 8; - } else if (tag >= ARM64_REG_ZAQ0 && tag <= ARM64_REG_ZAQ15) { - base = tag - ARM64_REG_ZAQ0; + } else if (tag >= AARCH64_REG_ZAQ0 && tag <= AARCH64_REG_ZAQ15) { + base = tag - AARCH64_REG_ZAQ0; tileTypeCount = 16; } uint16_t reg_tag = base + (index * tileTypeCount); @@ -328,22 +328,22 @@ class AArch64RegressionTest : public RegressionTest { // Get matrix row register tag uint8_t base = 0; uint8_t tileTypeCount = 0; - if (tag == ARM64_REG_ZA || tag == ARM64_REG_ZAB0) { + if (tag == AARCH64_REG_ZA || tag == AARCH64_REG_ZAB0) { // Treat ZA as byte tile : ZAB0 represents whole matrix, only 1 tile // Add all rows for this SVL // Don't need to set base as will always be 0 tileTypeCount = 1; - } else if (tag >= ARM64_REG_ZAH0 && tag <= ARM64_REG_ZAH1) { - base = tag - ARM64_REG_ZAH0; + } else if (tag >= AARCH64_REG_ZAH0 && tag <= AARCH64_REG_ZAH1) { + base = tag - AARCH64_REG_ZAH0; tileTypeCount = 2; - } else if (tag >= ARM64_REG_ZAS0 && tag <= ARM64_REG_ZAS3) { - base = tag - ARM64_REG_ZAS0; + } else if (tag >= AARCH64_REG_ZAS0 && tag <= AARCH64_REG_ZAS3) { + base = tag - AARCH64_REG_ZAS0; tileTypeCount = 4; - } else if (tag >= ARM64_REG_ZAD0 && tag <= ARM64_REG_ZAD7) { - base = tag - ARM64_REG_ZAD0; + } else if (tag >= AARCH64_REG_ZAD0 && tag <= AARCH64_REG_ZAD7) { + base = tag - AARCH64_REG_ZAD0; tileTypeCount = 8; - } else if (tag >= ARM64_REG_ZAQ0 && tag <= ARM64_REG_ZAQ15) { - base = tag - ARM64_REG_ZAQ0; + } else if (tag >= AARCH64_REG_ZAQ0 && tag <= AARCH64_REG_ZAQ15) { + base = tag - AARCH64_REG_ZAQ0; tileTypeCount = 16; } diff --git a/test/regression/aarch64/Exception.cc b/test/regression/aarch64/Exception.cc index 1c90371ddc..b987ae4429 100644 --- a/test/regression/aarch64/Exception.cc +++ b/test/regression/aarch64/Exception.cc @@ -293,7 +293,8 @@ TEST_P(Exception, svcr) { smstart )"); for (uint64_t i = 0; i < (SVL / 8); i++) { - CHECK_MAT_ROW(ARM64_REG_ZA, i, uint32_t, fillNeon({0}, SVL / 8)); + CHECK_MAT_ROW(AARCH64_REG_ZA, i, uint32_t, + fillNeon({0}, SVL / 8)); } // Check that changes to SVCR using msr svcr, xn work correctly @@ -366,7 +367,8 @@ TEST_P(Exception, svcr) { msr svcr, x4 )"); for (uint64_t i = 0; i < (SVL / 8); i++) { - CHECK_MAT_ROW(ARM64_REG_ZA, i, uint32_t, fillNeon({0}, SVL / 8)); + CHECK_MAT_ROW(AARCH64_REG_ZA, i, uint32_t, + fillNeon({0}, SVL / 8)); } } #endif diff --git a/test/regression/aarch64/instructions/comparison.cc b/test/regression/aarch64/instructions/comparison.cc index 9c56501ae4..c91c48ee00 100644 --- a/test/regression/aarch64/instructions/comparison.cc +++ b/test/regression/aarch64/instructions/comparison.cc @@ -109,7 +109,7 @@ TEST_P(InstComparison, cmnw) { )"); EXPECT_EQ(getNZCV(), 0b0110); - EXPECT_GROUP(R"(cmn w0, #0x1)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(cmn w0, #0x1)", INT_SIMPLE_CMP); } // Test that NZCV flags are set correctly by the 64-bit cmn instruction @@ -136,7 +136,7 @@ TEST_P(InstComparison, cmnx) { )"); EXPECT_EQ(getNZCV(), 0b0110); - EXPECT_GROUP(R"(cmn X0, #0x1)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(cmn X0, #0x1)", INT_SIMPLE_CMP); } // Test that NZCV flags are set correctly by the 32-bit ccmn instruction @@ -265,7 +265,7 @@ TEST_P(InstComparison, cmpw) { )"); EXPECT_EQ(getNZCV(), 0b0011); - EXPECT_GROUP(R"(cmp w1, #1)", INT_SIMPLE_ARTH_NOSHIFT); + EXPECT_GROUP(R"(cmp w1, #1)", INT_SIMPLE_CMP); } // Test that NZCV flags are set correctly by 64-bit cmp @@ -347,7 +347,7 @@ TEST_P(InstComparison, cmpx) { )"); EXPECT_EQ(getNZCV(), 0b0010); - EXPECT_GROUP(R"(cmp x0, x2, uxtx 4)", INT_SIMPLE_ARTH); + EXPECT_GROUP(R"(cmp x0, x2, uxtx 4)", INT_SIMPLE_CMP); } // Test that NZCV flags are set correctly by 64-bit tst diff --git a/test/regression/aarch64/instructions/sme.cc b/test/regression/aarch64/instructions/sme.cc index e344cc14ee..55c7b945f3 100644 --- a/test/regression/aarch64/instructions/sme.cc +++ b/test/regression/aarch64/instructions/sme.cc @@ -71,9 +71,9 @@ TEST_P(InstSme, fmopa) { fmopa za2.s, p0/m, p2/m, z3.s, z4.s )"); for (uint64_t i = 0; i < (SVL / 32); i++) { - CHECK_MAT_ROW(ARM64_REG_ZAS0, i, float, + CHECK_MAT_ROW(AARCH64_REG_ZAS0, i, float, fillNeon({10.0f}, (SVL / 8))); - CHECK_MAT_ROW(ARM64_REG_ZAS2, i, float, + CHECK_MAT_ROW(AARCH64_REG_ZAS2, i, float, fillNeon({24.0f}, (SVL / 16))); } @@ -99,9 +99,9 @@ TEST_P(InstSme, fmopa) { fmopa za2.d, p0/m, p2/m, z3.d, z4.d )"); for (uint64_t i = 0; i < (SVL / 64); i++) { - CHECK_MAT_ROW(ARM64_REG_ZAD0, i, double, + CHECK_MAT_ROW(AARCH64_REG_ZAD0, i, double, fillNeon({10.0}, (SVL / 8))); - CHECK_MAT_ROW(ARM64_REG_ZAD2, i, double, + CHECK_MAT_ROW(AARCH64_REG_ZAD2, i, double, fillNeon({24.0}, (SVL / 16))); } } @@ -138,12 +138,12 @@ TEST_P(InstSme, ld1d) { ld1d {za1h.d[w12, 1]}, p1/z, [x0, x2, lsl #3] )"); CHECK_MAT_ROW( - ARM64_REG_ZAD0, 0, uint64_t, + AARCH64_REG_ZAD0, 0, uint64_t, fillNeon({0x98765432ABCDEF01, 0xDEADBEEF12345678}, SVL / 8)); CHECK_MAT_ROW( - ARM64_REG_ZAD0, 1, uint64_t, + AARCH64_REG_ZAD0, 1, uint64_t, fillNeon({0xDEADBEEF12345678, 0x98765432ABCDEF01}, SVL / 8)); - CHECK_MAT_ROW(ARM64_REG_ZAD1, 1, uint64_t, + CHECK_MAT_ROW(AARCH64_REG_ZAD1, 1, uint64_t, fillNeonCombined( {0xDEADBEEF12345678, 0x98765432ABCDEF01}, {0}, SVL / 8)); @@ -178,12 +178,12 @@ TEST_P(InstSme, ld1d) { ld1d {za1v.d[w12, 1]}, p1/z, [x0, x2, lsl #3] )"); CHECK_MAT_COL( - ARM64_REG_ZAD0, 0, uint64_t, + AARCH64_REG_ZAD0, 0, uint64_t, fillNeon({0x98765432ABCDEF01, 0xDEADBEEF12345678}, SVL / 8)); CHECK_MAT_COL( - ARM64_REG_ZAD0, 1, uint64_t, + AARCH64_REG_ZAD0, 1, uint64_t, fillNeon({0xDEADBEEF12345678, 0x98765432ABCDEF01}, SVL / 8)); - CHECK_MAT_COL(ARM64_REG_ZAD1, 1, uint64_t, + CHECK_MAT_COL(AARCH64_REG_ZAD1, 1, uint64_t, fillNeonCombined( {0xDEADBEEF12345678, 0x98765432ABCDEF01}, {0}, SVL / 8)); } @@ -220,12 +220,12 @@ TEST_P(InstSme, ld1w) { ld1w {za1h.s[w12, 0]}, p1/z, [x0, x2, lsl #2] )"); CHECK_MAT_ROW( - ARM64_REG_ZAS0, 1, uint64_t, + AARCH64_REG_ZAS0, 1, uint64_t, fillNeon({0x9876543212345678, 0xDEADBEEFABCDEF01}, SVL / 8)); CHECK_MAT_ROW( - ARM64_REG_ZAS0, 3, uint64_t, + AARCH64_REG_ZAS0, 3, uint64_t, fillNeon({0x12345678DEADBEEF, 0xABCDEF0198765432}, SVL / 8)); - CHECK_MAT_ROW(ARM64_REG_ZAS1, 1, uint64_t, + CHECK_MAT_ROW(AARCH64_REG_ZAS1, 1, uint64_t, fillNeonCombined( {0x12345678DEADBEEF, 0xABCDEF0198765432}, {0}, SVL / 8)); @@ -260,14 +260,14 @@ TEST_P(InstSme, ld1w) { whilelo p1.s, xzr, x1 ld1w {za1v.s[w12, 0]}, p1/z, [x0, x2, lsl #2] )"); - CHECK_MAT_COL(ARM64_REG_ZAS0, 1, uint32_t, + CHECK_MAT_COL(AARCH64_REG_ZAS0, 1, uint32_t, fillNeon( {0x12345678, 0x98765432, 0xABCDEF01, 0xDEADBEEF}, SVL / 8)); - CHECK_MAT_COL(ARM64_REG_ZAS0, 3, uint32_t, + CHECK_MAT_COL(AARCH64_REG_ZAS0, 3, uint32_t, fillNeon( {0xDEADBEEF, 0x12345678, 0x98765432, 0xABCDEF01}, SVL / 8)); CHECK_MAT_COL( - ARM64_REG_ZAS1, 1, uint32_t, + AARCH64_REG_ZAS1, 1, uint32_t, fillNeonCombined( {0xDEADBEEF, 0x12345678, 0x98765432, 0xABCDEF01}, {0}, SVL / 8)); } @@ -526,7 +526,8 @@ TEST_P(InstSme, zero) { zero {za} )"); for (uint64_t i = 0; i < (SVL / 8); i++) { - CHECK_MAT_ROW(ARM64_REG_ZA, i, uint64_t, fillNeon({0}, SVL / 8)); + CHECK_MAT_ROW(AARCH64_REG_ZA, i, uint64_t, + fillNeon({0}, SVL / 8)); } initialHeapData_.resize(SVL / 4); @@ -562,12 +563,12 @@ TEST_P(InstSme, zero) { zero {za0.s, za2.s} )"); for (uint64_t i = 0; i < (SVL / 32); i++) { - CHECK_MAT_ROW(ARM64_REG_ZAS0, i, uint32_t, + CHECK_MAT_ROW(AARCH64_REG_ZAS0, i, uint32_t, fillNeon({0}, SVL / 8)); - CHECK_MAT_ROW(ARM64_REG_ZAS2, i, uint32_t, + CHECK_MAT_ROW(AARCH64_REG_ZAS2, i, uint32_t, fillNeon({0}, SVL / 8)); } - CHECK_MAT_COL(ARM64_REG_ZAS1, 3, uint32_t, + CHECK_MAT_COL(AARCH64_REG_ZAS1, 3, uint32_t, fillNeon( {0xDEADBEEF, 0x12345678, 0x98765432, 0xABCDEF01}, SVL / 8)); } diff --git a/test/unit/aarch64/ArchInfoTest.cc b/test/unit/aarch64/ArchInfoTest.cc index 13978639e5..e29e9793d9 100644 --- a/test/unit/aarch64/ArchInfoTest.cc +++ b/test/unit/aarch64/ArchInfoTest.cc @@ -16,14 +16,14 @@ class AArch64ArchInfoTest : public ::testing::Test { protected: const std::vector sysRegisterEnums = { - arm64_sysreg::ARM64_SYSREG_DCZID_EL0, - arm64_sysreg::ARM64_SYSREG_FPCR, - arm64_sysreg::ARM64_SYSREG_FPSR, - arm64_sysreg::ARM64_SYSREG_TPIDR_EL0, - arm64_sysreg::ARM64_SYSREG_MIDR_EL1, - arm64_sysreg::ARM64_SYSREG_CNTVCT_EL0, - arm64_sysreg::ARM64_SYSREG_PMCCNTR_EL0, - arm64_sysreg::ARM64_SYSREG_SVCR}; + aarch64_sysreg::AARCH64_SYSREG_DCZID_EL0, + aarch64_sysreg::AARCH64_SYSREG_FPCR, + aarch64_sysreg::AARCH64_SYSREG_FPSR, + aarch64_sysreg::AARCH64_SYSREG_TPIDR_EL0, + aarch64_sysreg::AARCH64_SYSREG_MIDR_EL1, + aarch64_sysreg::AARCH64_SYSREG_CNTVCT_EL0, + aarch64_sysreg::AARCH64_SYSREG_PMCCNTR_EL0, + aarch64_sysreg::AARCH64_SYSREG_SVCR}; const std::vector archRegStruct = { {8, 32}, diff --git a/test/unit/aarch64/ArchitectureTest.cc b/test/unit/aarch64/ArchitectureTest.cc index 7ad5fcacf4..dbc1fa65ac 100644 --- a/test/unit/aarch64/ArchitectureTest.cc +++ b/test/unit/aarch64/ArchitectureTest.cc @@ -125,7 +125,7 @@ TEST_F(AArch64ArchitectureTest, getSystemRegisterTag) { EXPECT_EQ(output, -1); // Test for correct behaviour - output = arch->getSystemRegisterTag(ARM64_SYSREG_DCZID_EL0); + output = arch->getSystemRegisterTag(AARCH64_SYSREG_DCZID_EL0); EXPECT_EQ(output, 0); } @@ -162,7 +162,7 @@ TEST_F(AArch64ArchitectureTest, getInitialState) { std::vector regs = { {RegisterType::GENERAL, 31}, {RegisterType::SYSTEM, - (uint16_t)arch->getSystemRegisterTag(ARM64_SYSREG_DCZID_EL0)}}; + (uint16_t)arch->getSystemRegisterTag(AARCH64_SYSREG_DCZID_EL0)}}; std::vector regVals = {{kernel.getInitialStackPointer(), 8}, {20, 8}}; @@ -202,13 +202,13 @@ TEST_F(AArch64ArchitectureTest, updateSystemTimerRegisters) { EXPECT_EQ( regFile .get({RegisterType::SYSTEM, (uint16_t)arch->getSystemRegisterTag( - ARM64_SYSREG_PMCCNTR_EL0)}) + AARCH64_SYSREG_PMCCNTR_EL0)}) .get(), i); EXPECT_EQ( regFile .get({RegisterType::SYSTEM, (uint16_t)arch->getSystemRegisterTag( - ARM64_SYSREG_CNTVCT_EL0)}) + AARCH64_SYSREG_CNTVCT_EL0)}) .get(), vctCount); } diff --git a/test/unit/aarch64/AuxiliaryFunctionsTest.cc b/test/unit/aarch64/AuxiliaryFunctionsTest.cc index dd18b16a31..cf8d8e59d9 100644 --- a/test/unit/aarch64/AuxiliaryFunctionsTest.cc +++ b/test/unit/aarch64/AuxiliaryFunctionsTest.cc @@ -240,19 +240,19 @@ TEST(AArch64AuxiliaryFunctionTest, ConditionHolds) { /** `extendValue` Tests */ TEST(AArch64AuxiliaryFunctionTest, ExtendValue) { // Test special case - EXPECT_EQ(extendValue(123, ARM64_EXT_INVALID, 0), 123); + EXPECT_EQ(extendValue(123, AARCH64_EXT_INVALID, 0), 123); // Results validated on XCI and A64FX hardware - EXPECT_EQ(extendValue(270, ARM64_EXT_UXTB, 3), 112); - EXPECT_EQ(extendValue(65560, ARM64_EXT_UXTH, 3), 192); - EXPECT_EQ(extendValue(0xFFFFFFFF, ARM64_EXT_UXTW, 3), 34359738360); - EXPECT_EQ(extendValue(0x0F0F0F0F0F0F0F01, ARM64_EXT_UXTX, 4), + EXPECT_EQ(extendValue(270, AARCH64_EXT_UXTB, 3), 112); + EXPECT_EQ(extendValue(65560, AARCH64_EXT_UXTH, 3), 192); + EXPECT_EQ(extendValue(0xFFFFFFFF, AARCH64_EXT_UXTW, 3), 34359738360); + EXPECT_EQ(extendValue(0x0F0F0F0F0F0F0F01, AARCH64_EXT_UXTX, 4), 0xF0F0F0F0F0F0F010); - EXPECT_EQ(extendValue(133, ARM64_EXT_SXTB, 3), -984); - EXPECT_EQ(extendValue(32768, ARM64_EXT_SXTH, 3), -262144); - EXPECT_EQ(extendValue(2147483648, ARM64_EXT_SXTW, 3), -17179869184); - EXPECT_EQ(extendValue(0x8000000000000000, ARM64_EXT_SXTX, 3), 0); + EXPECT_EQ(extendValue(133, AARCH64_EXT_SXTB, 3), -984); + EXPECT_EQ(extendValue(32768, AARCH64_EXT_SXTH, 3), -262144); + EXPECT_EQ(extendValue(2147483648, AARCH64_EXT_SXTW, 3), -17179869184); + EXPECT_EQ(extendValue(0x8000000000000000, AARCH64_EXT_SXTX, 3), 0); } /** `getNZCVfromPred` Tests */ @@ -476,229 +476,229 @@ TEST(AArch64AuxiliaryFunctionTest, sveGetPattern) { TEST(AArch64AuxiliaryFunctionTest, ShiftValueTest_LSL) { // 8-bit const uint8_t a = 0x0F; - EXPECT_EQ(shiftValue(a, ARM64_SFT_LSL, 4), 0xF0); + EXPECT_EQ(shiftValue(a, AARCH64_SFT_LSL, 4), 0xF0); const uint8_t b = 0xF0; - EXPECT_EQ(shiftValue(b, ARM64_SFT_LSL, 7), 0x00); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_LSL, 7), 0x00); - EXPECT_EQ(shiftValue(b, ARM64_SFT_LSL, 0), b); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_LSL, 0), b); // 16-bit const uint16_t c = 0x00FF; - EXPECT_EQ(shiftValue(c, ARM64_SFT_LSL, 8), 0xFF00); + EXPECT_EQ(shiftValue(c, AARCH64_SFT_LSL, 8), 0xFF00); const uint16_t d = 0xFF00; - EXPECT_EQ(shiftValue(d, ARM64_SFT_LSL, 15), 0x0000); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_LSL, 15), 0x0000); - EXPECT_EQ(shiftValue(d, ARM64_SFT_LSL, 0), d); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_LSL, 0), d); // 32-bit const uint32_t e = 0x0000FFFF; - EXPECT_EQ(shiftValue(e, ARM64_SFT_LSL, 16), 0xFFFF0000); + EXPECT_EQ(shiftValue(e, AARCH64_SFT_LSL, 16), 0xFFFF0000); const uint32_t f = 0xFFFF0000; - EXPECT_EQ(shiftValue(f, ARM64_SFT_LSL, 31), 0x00000000); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_LSL, 31), 0x00000000); - EXPECT_EQ(shiftValue(f, ARM64_SFT_LSL, 0), f); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_LSL, 0), f); // 64-bit const uint64_t g = 0x00000000FFFFFFFF; - EXPECT_EQ(shiftValue(g, ARM64_SFT_LSL, 32), 0xFFFFFFFF00000000); + EXPECT_EQ(shiftValue(g, AARCH64_SFT_LSL, 32), 0xFFFFFFFF00000000); const uint64_t h = 0xFFFFFFFF00000000; - EXPECT_EQ(shiftValue(h, ARM64_SFT_LSL, 63), 0x0000000000000000); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_LSL, 63), 0x0000000000000000); - EXPECT_EQ(shiftValue(h, ARM64_SFT_LSL, 0), h); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_LSL, 0), h); } TEST(AArch64AuxiliaryFunctionTest, ShiftValueTest_LSR) { // 8-bit const uint8_t a = 0x0F; - EXPECT_EQ(shiftValue(a, ARM64_SFT_LSR, 4), 0x00); + EXPECT_EQ(shiftValue(a, AARCH64_SFT_LSR, 4), 0x00); const uint8_t b = 0xF0; - EXPECT_EQ(shiftValue(b, ARM64_SFT_LSR, 7), 0x01); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_LSR, 7), 0x01); - EXPECT_EQ(shiftValue(b, ARM64_SFT_LSR, 0), b); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_LSR, 0), b); // 16-bit const uint16_t c = 0x00FF; - EXPECT_EQ(shiftValue(c, ARM64_SFT_LSR, 8), 0x0); + EXPECT_EQ(shiftValue(c, AARCH64_SFT_LSR, 8), 0x0); const uint16_t d = 0xFF00; - EXPECT_EQ(shiftValue(d, ARM64_SFT_LSR, 15), 0x0001); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_LSR, 15), 0x0001); - EXPECT_EQ(shiftValue(d, ARM64_SFT_LSR, 0), d); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_LSR, 0), d); // 32-bit const uint32_t e = 0x0000FFFF; - EXPECT_EQ(shiftValue(e, ARM64_SFT_LSR, 16), 0x00000000); + EXPECT_EQ(shiftValue(e, AARCH64_SFT_LSR, 16), 0x00000000); const uint32_t f = 0xFFFF0000; - EXPECT_EQ(shiftValue(f, ARM64_SFT_LSR, 31), 0x00000001); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_LSR, 31), 0x00000001); - EXPECT_EQ(shiftValue(f, ARM64_SFT_LSR, 0), f); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_LSR, 0), f); // 64-bit const uint64_t g = 0x00000000FFFFFFFF; - EXPECT_EQ(shiftValue(g, ARM64_SFT_LSR, 32), 0x0000000000000000); + EXPECT_EQ(shiftValue(g, AARCH64_SFT_LSR, 32), 0x0000000000000000); const uint64_t h = 0xFFFFFFFF00000000; - EXPECT_EQ(shiftValue(h, ARM64_SFT_LSR, 63), 0x0000000000000001); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_LSR, 63), 0x0000000000000001); - EXPECT_EQ(shiftValue(h, ARM64_SFT_LSR, 0), h); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_LSR, 0), h); } TEST(AArch64AuxiliaryFunctionTest, ShiftValueTest_ASR) { // 8-bit const uint8_t a = 0x0F; - EXPECT_EQ(shiftValue(a, ARM64_SFT_ASR, 4), 0x00); + EXPECT_EQ(shiftValue(a, AARCH64_SFT_ASR, 4), 0x00); const uint8_t b = 0xF0; - EXPECT_EQ(shiftValue(b, ARM64_SFT_ASR, 7), 0xFF); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_ASR, 7), 0xFF); - EXPECT_EQ(shiftValue(b, ARM64_SFT_ASR, 0), b); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_ASR, 0), b); // 16-bit const uint16_t c = 0x00FF; - EXPECT_EQ(shiftValue(c, ARM64_SFT_ASR, 8), 0x0000); + EXPECT_EQ(shiftValue(c, AARCH64_SFT_ASR, 8), 0x0000); const uint16_t d = 0xFF00; - EXPECT_EQ(shiftValue(d, ARM64_SFT_ASR, 15), 0xFFFF); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_ASR, 15), 0xFFFF); - EXPECT_EQ(shiftValue(d, ARM64_SFT_ASR, 0), d); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_ASR, 0), d); // 32-bit const uint32_t e = 0x0000FFFF; - EXPECT_EQ(shiftValue(e, ARM64_SFT_ASR, 16), 0x00000000); + EXPECT_EQ(shiftValue(e, AARCH64_SFT_ASR, 16), 0x00000000); const uint32_t f = 0xFFFF0000; - EXPECT_EQ(shiftValue(f, ARM64_SFT_ASR, 31), 0xFFFFFFFF); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_ASR, 31), 0xFFFFFFFF); - EXPECT_EQ(shiftValue(f, ARM64_SFT_ASR, 0), f); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_ASR, 0), f); // 64-bit const uint64_t g = 0x00000000FFFFFFFF; - EXPECT_EQ(shiftValue(g, ARM64_SFT_ASR, 32), 0x0000000000000000); + EXPECT_EQ(shiftValue(g, AARCH64_SFT_ASR, 32), 0x0000000000000000); const uint64_t h = 0xFFFFFFFF00000000; - EXPECT_EQ(shiftValue(h, ARM64_SFT_ASR, 63), 0xFFFFFFFFFFFFFFFF); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_ASR, 63), 0xFFFFFFFFFFFFFFFF); - EXPECT_EQ(shiftValue(h, ARM64_SFT_ASR, 0), h); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_ASR, 0), h); } TEST(AArch64AuxiliaryFunctionTest, ShiftValueTest_ROR) { // 8-bit const uint8_t a = 0x0F; - EXPECT_EQ(shiftValue(a, ARM64_SFT_ROR, 4), 0xF0); + EXPECT_EQ(shiftValue(a, AARCH64_SFT_ROR, 4), 0xF0); const uint8_t b = 0xF0; - EXPECT_EQ(shiftValue(b, ARM64_SFT_ROR, 7), 0xE1); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_ROR, 7), 0xE1); - EXPECT_EQ(shiftValue(b, ARM64_SFT_ROR, 0), b); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_ROR, 0), b); // 16-bit const uint16_t c = 0x00FF; - EXPECT_EQ(shiftValue(c, ARM64_SFT_ROR, 8), 0xFF00); + EXPECT_EQ(shiftValue(c, AARCH64_SFT_ROR, 8), 0xFF00); const uint16_t d = 0xFF00; - EXPECT_EQ(shiftValue(d, ARM64_SFT_ROR, 15), 0xFE01); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_ROR, 15), 0xFE01); - EXPECT_EQ(shiftValue(d, ARM64_SFT_ROR, 0), d); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_ROR, 0), d); // 32-bit const uint32_t e = 0x0000FFFF; - EXPECT_EQ(shiftValue(e, ARM64_SFT_ROR, 16), 0xFFFF0000); + EXPECT_EQ(shiftValue(e, AARCH64_SFT_ROR, 16), 0xFFFF0000); const uint32_t f = 0xFFFF0000; - EXPECT_EQ(shiftValue(f, ARM64_SFT_ROR, 31), 0xFFFE0001); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_ROR, 31), 0xFFFE0001); - EXPECT_EQ(shiftValue(f, ARM64_SFT_ROR, 0), f); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_ROR, 0), f); // 64-bit const uint64_t g = 0x00000000FFFFFFFF; - EXPECT_EQ(shiftValue(g, ARM64_SFT_ROR, 32), 0xFFFFFFFF00000000); + EXPECT_EQ(shiftValue(g, AARCH64_SFT_ROR, 32), 0xFFFFFFFF00000000); const uint64_t h = 0xFFFFFFFF00000000; - EXPECT_EQ(shiftValue(h, ARM64_SFT_ROR, 63), 0xFFFFFFFE00000001); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_ROR, 63), 0xFFFFFFFE00000001); - EXPECT_EQ(shiftValue(h, ARM64_SFT_ROR, 0), h); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_ROR, 0), h); } TEST(AArch64AuxiliaryFunctionTest, ShiftValueTest_MSL) { // 8-bit const uint8_t a = 0x0F; - EXPECT_EQ(shiftValue(a, ARM64_SFT_MSL, 4), 0xFF); + EXPECT_EQ(shiftValue(a, AARCH64_SFT_MSL, 4), 0xFF); const uint8_t b = 0xF0; - EXPECT_EQ(shiftValue(b, ARM64_SFT_MSL, 7), 0x7F); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_MSL, 7), 0x7F); - EXPECT_EQ(shiftValue(b, ARM64_SFT_MSL, 0), b); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_MSL, 0), b); // 16-bit const uint16_t c = 0x00FF; - EXPECT_EQ(shiftValue(c, ARM64_SFT_MSL, 8), 0xFFFF); + EXPECT_EQ(shiftValue(c, AARCH64_SFT_MSL, 8), 0xFFFF); const uint16_t d = 0xFF00; - EXPECT_EQ(shiftValue(d, ARM64_SFT_MSL, 15), 0x7FFF); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_MSL, 15), 0x7FFF); - EXPECT_EQ(shiftValue(d, ARM64_SFT_MSL, 0), d); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_MSL, 0), d); // 32-bit const uint32_t e = 0x0000FFFF; - EXPECT_EQ(shiftValue(e, ARM64_SFT_MSL, 16), 0xFFFFFFFF); + EXPECT_EQ(shiftValue(e, AARCH64_SFT_MSL, 16), 0xFFFFFFFF); const uint32_t f = 0xFFFF0000; - EXPECT_EQ(shiftValue(f, ARM64_SFT_MSL, 31), 0x7FFFFFFF); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_MSL, 31), 0x7FFFFFFF); - EXPECT_EQ(shiftValue(f, ARM64_SFT_MSL, 0), f); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_MSL, 0), f); // 64-bit const uint64_t g = 0x00000000FFFFFFFF; - EXPECT_EQ(shiftValue(g, ARM64_SFT_MSL, 32), 0xFFFFFFFFFFFFFFFF); + EXPECT_EQ(shiftValue(g, AARCH64_SFT_MSL, 32), 0xFFFFFFFFFFFFFFFF); const uint64_t h = 0xFFFFFFFF00000000; - EXPECT_EQ(shiftValue(h, ARM64_SFT_MSL, 63), 0x7FFFFFFFFFFFFFFF); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_MSL, 63), 0x7FFFFFFFFFFFFFFF); - EXPECT_EQ(shiftValue(h, ARM64_SFT_MSL, 0), h); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_MSL, 0), h); } TEST(AArch64AuxiliaryFunctionTest, ShiftValueTest_INVALID) { // 8-bit const uint8_t a = 0x0F; - EXPECT_EQ(shiftValue(a, ARM64_SFT_INVALID, 4), a); + EXPECT_EQ(shiftValue(a, AARCH64_SFT_INVALID, 4), a); const uint8_t b = 0xF0; - EXPECT_EQ(shiftValue(b, ARM64_SFT_INVALID, 7), b); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_INVALID, 7), b); - EXPECT_EQ(shiftValue(b, ARM64_SFT_INVALID, 0), b); + EXPECT_EQ(shiftValue(b, AARCH64_SFT_INVALID, 0), b); // 16-bit const uint16_t c = 0x00FF; - EXPECT_EQ(shiftValue(c, ARM64_SFT_INVALID, 8), c); + EXPECT_EQ(shiftValue(c, AARCH64_SFT_INVALID, 8), c); const uint16_t d = 0xFF00; - EXPECT_EQ(shiftValue(d, ARM64_SFT_INVALID, 15), d); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_INVALID, 15), d); - EXPECT_EQ(shiftValue(d, ARM64_SFT_INVALID, 0), d); + EXPECT_EQ(shiftValue(d, AARCH64_SFT_INVALID, 0), d); // 32-bit const uint32_t e = 0x0000FFFF; - EXPECT_EQ(shiftValue(e, ARM64_SFT_INVALID, 16), e); + EXPECT_EQ(shiftValue(e, AARCH64_SFT_INVALID, 16), e); const uint32_t f = 0xFFFF0000; - EXPECT_EQ(shiftValue(f, ARM64_SFT_INVALID, 31), f); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_INVALID, 31), f); - EXPECT_EQ(shiftValue(f, ARM64_SFT_INVALID, 0), f); + EXPECT_EQ(shiftValue(f, AARCH64_SFT_INVALID, 0), f); // 64-bit const uint64_t g = 0x00000000FFFFFFFF; - EXPECT_EQ(shiftValue(g, ARM64_SFT_INVALID, 32), g); + EXPECT_EQ(shiftValue(g, AARCH64_SFT_INVALID, 32), g); const uint64_t h = 0xFFFFFFFF00000000; - EXPECT_EQ(shiftValue(h, ARM64_SFT_INVALID, 63), h); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_INVALID, 63), h); - EXPECT_EQ(shiftValue(h, ARM64_SFT_INVALID, 0), h); + EXPECT_EQ(shiftValue(h, AARCH64_SFT_INVALID, 0), h); } } // namespace aarch64 diff --git a/test/unit/aarch64/InstructionTest.cc b/test/unit/aarch64/InstructionTest.cc index 92b8e9393a..1ecf14a1a6 100644 --- a/test/unit/aarch64/InstructionTest.cc +++ b/test/unit/aarch64/InstructionTest.cc @@ -16,7 +16,7 @@ class AArch64InstructionTest : public testing::Test { .as()), arch(os) { // Create InstructionMetadata objects - cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &capstoneHandle); + cs_open(CS_ARCH_AARCH64, CS_MODE_ARM, &capstoneHandle); cs_option(capstoneHandle, CS_OPT_DETAIL, CS_OPT_ON); // Create instructions which cover the 3 main types: Arithmetic, Memory, From 893568b21e4b7d1f358c1af5008ab774c1aafecd Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Wed, 4 Sep 2024 21:11:14 +0200 Subject: [PATCH 05/34] More fixes after Capstone update. --- .../simeng/arch/aarch64/Instruction.hh | 22 +- .../simeng/arch/aarch64/helpers/neon.hh | 2 +- .../simeng/arch/aarch64/helpers/sve.hh | 9 +- src/lib/arch/aarch64/InstructionMetadata.cc | 1611 +++++++++-------- src/lib/arch/aarch64/Instruction_address.cc | 4 +- src/lib/arch/aarch64/Instruction_decode.cc | 20 +- src/lib/arch/aarch64/Instruction_execute.cc | 139 +- 7 files changed, 933 insertions(+), 874 deletions(-) diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index c926efe20e..07f2b21ff5 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -100,29 +100,27 @@ inline uint8_t getDataSize(cs_aarch64_op op) { case AARCH64LAYOUT_VL_8H: case AARCH64LAYOUT_VL_4S: case AARCH64LAYOUT_VL_2D: - case AARCH64LAYOUT_VL_1Q: { + case AARCH64LAYOUT_VL_1Q: + case AARCH64LAYOUT_VL_Q: return 16; - } case AARCH64LAYOUT_VL_8B: case AARCH64LAYOUT_VL_4H: case AARCH64LAYOUT_VL_2S: - case AARCH64LAYOUT_VL_1D: { + case AARCH64LAYOUT_VL_1D: + case AARCH64LAYOUT_VL_D: return 8; - } case AARCH64LAYOUT_VL_4B: case AARCH64LAYOUT_VL_2H: - case AARCH64LAYOUT_VL_1S: { + case AARCH64LAYOUT_VL_1S: + case AARCH64LAYOUT_VL_S: return 4; - } - case AARCH64LAYOUT_VL_H: { + case AARCH64LAYOUT_VL_H: return 2; - } - case AARCH64LAYOUT_VL_B: { + case AARCH64LAYOUT_VL_B: return 1; - } - default: { + default: assert(false && "Unknown VAS type"); - } + break; } } diff --git a/src/include/simeng/arch/aarch64/helpers/neon.hh b/src/include/simeng/arch/aarch64/helpers/neon.hh index 0fcf04f03f..c2626b7e91 100644 --- a/src/include/simeng/arch/aarch64/helpers/neon.hh +++ b/src/include/simeng/arch/aarch64/helpers/neon.hh @@ -752,7 +752,7 @@ template RegisterValue vecSshrShift_imm( srcValContainer& sourceValues, const simeng::arch::aarch64::InstructionMetadata& metadata) { - const T* n = sourceValues[1].getAsVector(); + const T* n = sourceValues[0].getAsVector(); uint64_t shift = metadata.operands[2].imm; T out[16 / sizeof(T)] = {0}; for (int i = 0; i < I; i++) { diff --git a/src/include/simeng/arch/aarch64/helpers/sve.hh b/src/include/simeng/arch/aarch64/helpers/sve.hh index 4afb39d00c..cf3e1b0266 100644 --- a/src/include/simeng/arch/aarch64/helpers/sve.hh +++ b/src/include/simeng/arch/aarch64/helpers/sve.hh @@ -268,7 +268,8 @@ int64_t sveDec_scalar( const simeng::arch::aarch64::InstructionMetadata& metadata, const uint16_t VL_bits) { const int64_t n = sourceValues[0].get(); - const uint8_t imm = static_cast(metadata.operands[1].imm); + // metadata_.operands[1] is the SVE pattern enum + const uint8_t imm = static_cast(metadata.operands[2].imm); const uint16_t elems = sveGetPattern(metadata.operandStr, sizeof(T) * 8, VL_bits); return (n - static_cast(elems * imm)); @@ -860,7 +861,8 @@ int64_t sveInc_gprImm( const simeng::arch::aarch64::InstructionMetadata& metadata, const uint16_t VL_bits) { const int64_t n = sourceValues[0].get(); - const uint8_t imm = static_cast(metadata.operands[1].imm); + // metadata_.operands[1] is the SVE pattern enum + const uint8_t imm = static_cast(metadata.operands[2].imm); const uint16_t elems = sveGetPattern(metadata.operandStr, sizeof(T) * 8, VL_bits); int64_t out = n + (elems * imm); @@ -877,7 +879,8 @@ RegisterValue sveInc_imm( const simeng::arch::aarch64::InstructionMetadata& metadata, const uint16_t VL_bits) { const T* n = sourceValues[0].getAsVector(); - const uint8_t imm = static_cast(metadata.operands[1].imm); + // metadata_.operands[1] is the SVE pattern enum + const uint8_t imm = static_cast(metadata.operands[2].imm); const uint16_t partition_num = VL_bits / (sizeof(T) * 8); typename std::make_signed::type out[256 / sizeof(T)] = {0}; diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index 0f0fc9cf6b..1c0c82ed95 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -33,29 +33,33 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // Fix some inaccuracies in the decoded metadata switch (opcode) { - // case Opcode::AArch64_ADR_LSL_ZZZ_D_0: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_D_1: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_D_2: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_D_3: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_S_0: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_S_1: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_S_2: - // [[fallthrough]]; - // case Opcode::AArch64_ADR_LSL_ZZZ_S_3: { - // // No defined access types - // operandCount = 3; - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[2].type = AARCH64_OP_REG; - // break; - // } + case Opcode::AArch64_ADR_LSL_ZZZ_D_0: + [[fallthrough]]; + case Opcode::AArch64_ADR_LSL_ZZZ_D_1: + [[fallthrough]]; + case Opcode::AArch64_ADR_LSL_ZZZ_D_2: + [[fallthrough]]; + case Opcode::AArch64_ADR_LSL_ZZZ_D_3: + [[fallthrough]]; + case Opcode::AArch64_ADR_LSL_ZZZ_S_0: + [[fallthrough]]; + case Opcode::AArch64_ADR_LSL_ZZZ_S_1: + [[fallthrough]]; + case Opcode::AArch64_ADR_LSL_ZZZ_S_2: + [[fallthrough]]; + case Opcode::AArch64_ADR_LSL_ZZZ_S_3: { + // Change the last 2 Z-regs from one MEM operand to two REG operands + operandCount = 3; + operands[1].type = AARCH64_OP_REG; + operands[1].access = CS_AC_READ; + operands[1].reg = operands[1].mem.base; + operands[2].type = AARCH64_OP_REG; + operands[2].access = CS_AC_READ; + operands[2].reg = operands[1].mem.index; + operands[2].vas = operands[1].vas; + operands[2].shift = operands[1].shift; + break; + } // case Opcode::AArch64_SMIN_ZPmZ_S: // [[fallthrough]]; // case Opcode::AArch64_EOR_ZPmZ_B: @@ -66,13 +70,16 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // [[fallthrough]]; // case Opcode::AArch64_EOR_ZPmZ_S: // [[fallthrough]]; - // case Opcode::AArch64_AND_ZPmZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_AND_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_AND_ZPmZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_AND_ZPmZ_S: + case Opcode::AArch64_AND_ZPmZ_D: + case Opcode::AArch64_AND_ZPmZ_H: + case Opcode::AArch64_AND_ZPmZ_S: + case Opcode::AArch64_AND_ZPmZ_B: + // Incorrect defined access types + operands[0].access = CS_AC_WRITE; + operands[1].access = CS_AC_READ; + operands[2].access = CS_AC_READ; + operands[3].access = CS_AC_READ; + break; // // No defined access types // operands[0].access = CS_AC_WRITE; // operands[1].access = CS_AC_READ; @@ -235,13 +242,36 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // } // break; // } - // case Opcode::AArch64_AND_ZI: { - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[2].type = AARCH64_OP_IMM; - // operandCount = 3; - + case Opcode::AArch64_ADD_ZI_B: + case Opcode::AArch64_ADD_ZI_D: + case Opcode::AArch64_ADD_ZI_H: + case Opcode::AArch64_ADD_ZI_S: { + // Incorrect access types + operands[0].access = CS_AC_WRITE; + operands[1].access = CS_AC_READ; + // If LSL #8 is present then immediate is not properly set. + // LSL is automatically applied to the imm for these instructions + std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); + if (tmpOpStr[1] == 'x') { + operands[2].imm = static_cast(std::stoi(tmpOpStr, 0, 16)); + } + break; + } + case Opcode::AArch64_AND_ZI: + // Incorrect access types + operands[0].access = CS_AC_WRITE; + operands[1].access = CS_AC_READ; + break; + case Opcode::AArch64_EOR_ZPmZ_B: + case Opcode::AArch64_EOR_ZPmZ_D: + case Opcode::AArch64_EOR_ZPmZ_H: + case Opcode::AArch64_EOR_ZPmZ_S: + // Incorrect access types + operands[0].access = CS_AC_WRITE; + operands[1].access = CS_AC_READ; + operands[2].access = CS_AC_READ; + operands[3].access = CS_AC_READ; + break; // char specifier = operandStr[operandStr.find(".") + 1]; // switch (specifier) { // case 'b': { @@ -307,10 +337,10 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // operands[3].access = CS_AC_READ; // break; // } - // case Opcode::AArch64_FMOVXDHighr: - // // FMOVXDHighr incorrectly flags destination as only WRITE - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // break; + case Opcode::AArch64_FMOVXDHighr: + // FMOVXDHighr incorrectly flags destination as only WRITE + operands[0].access = CS_AC_READ | CS_AC_WRITE; + break; // case Opcode::AArch64_FNMSB_ZPmZZ_D: // [[fallthrough]]; // case Opcode::AArch64_FNMSB_ZPmZZ_S: @@ -985,744 +1015,769 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // operands[0].access = CS_AC_READ; // operands[1].access = CS_AC_WRITE; // break; - // case Opcode::AArch64_LD2Twov4s_POST: - // // Fixing wrong access flag for offset register operand - // if (operandCount == 4) { - // operands[3].access = CS_AC_READ; - // } - // break; - // case Opcode::AArch64_LDR_PXI: - // [[fallthrough]]; - // case Opcode::AArch64_LDR_ZXI: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LSL_ZZI_S: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // // No instruction id assigned - // id = AARCH64_INS_LSL; - // break; - // case Opcode::AArch64_LD2D: - // case Opcode::AArch64_LD2D_IMM: { - // // LD2D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - - // 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_WRITE; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_WRITE; - - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_LD3D_IMM: { - // // LD3D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - // uint16_t reg_enum2 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d, znn.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - - // 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest2 - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); - // } else { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_WRITE; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_WRITE; - // operands[2].reg = static_cast(reg_enum2); - // operands[2].access = CS_AC_WRITE; - - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_LD4D_IMM: { - // // LD4D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - // uint16_t reg_enum2 = AARCH64_REG_Z0; - // uint16_t reg_enum3 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d, znn.d, zmm.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - - // 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest2 - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest3 - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum3 += std::stoi(tmpOpStr.substr(1, 1)); - // } else { - // reg_enum3 += std::stoi(tmpOpStr.substr(1, 2)); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_WRITE; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_WRITE; - // operands[2].reg = static_cast(reg_enum2); - // operands[2].access = CS_AC_WRITE; - // operands[3].reg = static_cast(reg_enum3); - // operands[3].access = CS_AC_WRITE; - - // operands[4].access = CS_AC_READ; - // operands[5].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_MOVNWi: - // [[fallthrough]]; - // case Opcode::AArch64_MOVNXi: - // [[fallthrough]]; - // case Opcode::AArch64_MOVZWi: - // [[fallthrough]]; - // case Opcode::AArch64_MOVZXi: - // // MOVZ incorrectly flags destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_MOVPRFX_ZZ: - // // Assign operand access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_MRS: - // // MRS incorrectly flags source/destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // MRS incorrectly tags AARCH64_OP_REG_MRS as AARCH64_OP_SYS - // operands[1].type = AARCH64_OP_REG_MRS; - // break; - // case Opcode::AArch64_MSR: - // // MSR incorrectly flags source/destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // MSR incorrectly tags AARCH64_OP_REG_MSR as AARCH64_OP_SYS - // operands[0].type = AARCH64_OP_REG_MSR; - // break; - // case Opcode::AArch64_PTEST_PP: { - // // PTEST doesn't label access types for operands - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // // Doesn't identify implicit NZCV destination - // implicitDestinationCount = 1; - // implicitDestinations[0] = AARCH64_REG_NZCV; - // break; - // } - // case Opcode::AArch64_PTRUE_B: - // [[fallthrough]]; - // case Opcode::AArch64_PTRUE_H: - // [[fallthrough]]; - // case Opcode::AArch64_PTRUE_D: - // [[fallthrough]]; - // case Opcode::AArch64_PTRUE_S: - // // PTRUE doesn't label access - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_RET: - // // If no register supplied to RET, default to x30 (LR) - // if (operandCount == 0) { - // operandCount = 1; - // operands[0].type = AARCH64_OP_REG; - // operands[0].reg = AARCH64_REG_LR; - // operands[0].access = CS_AC_READ; - // } - // groupCount = 1; - // groups[0] = CS_GRP_JUMP; - // break; - // case Opcode::AArch64_REV_ZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_REV_ZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_REV_ZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_REV_ZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_B: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_D: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_H: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_S: { - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_SST1B_D_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_SST1D_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { - // // ST1W doesn't correctly identify first source register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // // SST1D{_SCALED} gather instruction doesn't correctly identify - // memory - // // operands - // operands[2].type = AARCH64_OP_MEM; - // operands[2].access = CS_AC_READ; - - // // ST1D doesn't correctly identify vector memory register correctly - // uint16_t vec_enum = AARCH64_REG_Z0; - // std::string tmp_str(operandStr.substr(operandStr.find("["))); - // // Single or double digit Z register identifier - // if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { - // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); - // } else { - // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); - // } - // operands[2].mem.index = static_cast(vec_enum); - // break; - // } - // case Opcode::AArch64_ST2D_IMM: { - // // ST2D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - - // 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_READ; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_READ; - - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_ST1B: - // [[fallthrough]]; - // case Opcode::AArch64_ST1D: - // [[fallthrough]]; - // case Opcode::AArch64_ST1B_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_ST1D_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_ST1W_IMM: { - // // ST1W doesn't correctly identify first source register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_ST1W: - // [[fallthrough]]; - // case Opcode::AArch64_ST1W_D: { - // // ST1W doesn't correctly identify first source register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_SST1D_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_SST1W_D_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_SST1W_IMM: { - // // ST1W scatter instruction doesn't correctly identify first source - // // register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } + // case Opcode::AArch64_LD2Twov4s_POST: + // // Post offset register is not put as mem.index + // if (operands[3].type == AARCH64_OP_REG) { + // operands[2].mem.index = operands[3].reg; + // operands[3].type = AARCH64_OP_INVALID; + // } + // break; + case Opcode::AArch64_FCVTNv4i32: + // Wrong access type for destinatio operand + operands[0].access = CS_AC_WRITE; + break; + case Opcode::AArch64_CPY_ZPzI_B: + case Opcode::AArch64_CPY_ZPzI_D: + case Opcode::AArch64_CPY_ZPzI_H: + case Opcode::AArch64_CPY_ZPzI_S: { + // Imm value not correctly set + std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); + auto value = std::stoi(tmpOpStr, 0, 16); + operands[2].imm = tmpOpStr.length() == 4 ? static_cast(value) + : static_cast(value); + break; + } - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // // ST1W scatter instruction doesn't correctly identify second Z reg - // as - // // memory operand - // operands[2].type = AARCH64_OP_MEM; - // operands[2].access = CS_AC_READ; - // // ST1W scatter instruction doesn't recognise memory-offset - // immediate - // // correctly - // if (operandStr[operandStr.length() - 3] != '.') { - // int64_t startPos = operandStr.find('#') + 1; - // int64_t immSize = (operandStr.length() - 1) - startPos; - // if (immSize == 1) { - // operands[2].mem.disp = - // std::stoi(operandStr.substr(startPos, immSize)); - // } else { - // // double or triple digit immediates are converted to hex, and - // so - // // require a different conversion to uint - // operands[2].mem.disp = - // std::stoul(operandStr.substr(startPos, immSize), nullptr, - // 16); - // } - // } - // break; - // } - // case Opcode::AArch64_ST1i8_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1i16_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1i32_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1i64_POST: - // // fixing incorrect access type for register offset - // if (operandCount == 3) { - // operands[2].access = CS_AC_READ; - // } - // break; - // case Opcode::AArch64_ST1Fourv16b: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv2d: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv4s: - // // ST1 incorrectly flags read and write - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // break; - // case Opcode::AArch64_ST1Fourv16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv2d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv2s_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv4s_POST: - // // ST1 incorrectly flags read and write - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ | CS_AC_WRITE; - // operands[5].access = CS_AC_READ; - // // determine correct type for operand 5 - // if (operandStr.find("#") != std::string::npos) { - // operands[5].type = AARCH64_OP_IMM; - // } else { - // operands[5].type = AARCH64_OP_REG; - // } - // break; - // case Opcode::AArch64_ST1Twov16b: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov2d: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov4s: - // // ST1 incorrectly flags read and write - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_ST1Twov16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov2d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov4s_POST: - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ | CS_AC_WRITE; - // operands[3].access = CS_AC_READ; - // // determine correct type for operand 3 - // if (operandStr.find("#") != std::string::npos) { - // operands[3].type = AARCH64_OP_IMM; - // } else { - // operands[3].type = AARCH64_OP_REG; - // } - // break; - // case Opcode::AArch64_ST2Twov4s_POST: - // // ST2 post incorrectly flags read and write - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ | CS_AC_WRITE; - // // Another incorrect access flag for register offset operand - // if (operandCount == 4) { - // operands[3].access = CS_AC_READ; - // } - // break; - // case Opcode::AArch64_STRBui: - // [[fallthrough]]; - // case Opcode::AArch64_STRDui: - // [[fallthrough]]; - // case Opcode::AArch64_STRHui: - // [[fallthrough]]; - // case Opcode::AArch64_STRQui: - // [[fallthrough]]; - // case Opcode::AArch64_STRSui: - // [[fallthrough]]; - // case Opcode::AArch64_STRWui: - // [[fallthrough]]; - // case Opcode::AArch64_STRXui: - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_PFALSE: - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_STR_PXI: - // [[fallthrough]]; - // case Opcode::AArch64_STR_ZXI: - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_SBFMWri: - // [[fallthrough]]; - // case Opcode::AArch64_SBFMXri: - // // SBFM incorrectly flags destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_SVC: - // // SVC is incorrectly marked as setting x30 - // implicitDestinationCount = 0; - // break; - // case Opcode::AArch64_SYSxt: - // // No defined metadata.id for SYS instructions - // id = AARCH64_INS_SYS; - // break; - // case Opcode::AArch64_PSEL_PPPRI_B: - // [[fallthrough]]; - // case Opcode::AArch64_PSEL_PPPRI_D: - // [[fallthrough]]; - // case Opcode::AArch64_PSEL_PPPRI_H: - // [[fallthrough]]; - // case Opcode::AArch64_PSEL_PPPRI_S: - // // Add correct access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_UBFMWri: - // [[fallthrough]]; - // case Opcode::AArch64_UBFMXri: - // // UBFM incorrectly flags destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_UQDECB_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECB_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECD_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECD_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECH_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECH_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECW_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECW_XPiI: - // // UQDEC lacks access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // if (operandCount == 1) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // } - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_UUNPKHI_ZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKHI_ZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKHI_ZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKLO_ZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKLO_ZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKLO_ZZ_S: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_WHILELT_PXX_B: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELT_PXX_D: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELT_PXX_H: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELT_PXX_S: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_B: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_D: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_H: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_S: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_B: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_D: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_H: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_S: - // // WHILELO doesn't label access or vector specifiers - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // // Doesn't identify implicit NZCV destination - // implicitDestinationCount = 1; - // implicitDestinations[0] = AARCH64_REG_NZCV; - // break; - // case Opcode::AArch64_XTNv16i8: - // case Opcode::AArch64_XTNv4i32: - // case Opcode::AArch64_XTNv8i16: - // // XTN2 incorrectly flags destination as only WRITE - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // break; - // case Opcode::AArch64_ZIP1_PPP_B: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_PPP_D: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_PPP_H: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_PPP_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_B: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_D: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_H: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_ZZZ_D: - // // ZIP lacks access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_SXTW_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCVT_ZPmZ_DtoS: - // [[fallthrough]]; - // case Opcode::AArch64_FCVT_ZPmZ_StoD: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_DtoS: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_StoD: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_StoS: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_DtoD: - // // Need to see if Destination vector elements are active - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8One: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8One: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8Two: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8Two: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8Three: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8Three: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8Four: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8Four: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // operands[5].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1_MXIPXX_H_D: - // [[fallthrough]]; - // case Opcode::AArch64_LD1_MXIPXX_V_D: - // [[fallthrough]]; - // case Opcode::AArch64_LD1_MXIPXX_V_S: - // [[fallthrough]]; - // case Opcode::AArch64_LD1_MXIPXX_H_S: { - // // Lacking access specifiers - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_ST1_MXIPXX_H_D: - // [[fallthrough]]; - // case Opcode::AArch64_ST1_MXIPXX_V_D: - // [[fallthrough]]; - // case Opcode::AArch64_ST1_MXIPXX_H_S: - // [[fallthrough]]; - // case Opcode::AArch64_ST1_MXIPXX_V_S: - // // Access types are not defined - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_FMOPA_MPPZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMOPA_MPPZZ_S: { - // // Need to add access specifiers - // // although operands[0] should be READ | WRITE, due to the - // implemented - // // decode logic for SME tile destinations, the register will be - // added as - // // both source and destination with just WRITE access. - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // operands[5].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_EXTRACT_ZPMXI_H_B: { - // operandCount = 4; - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].reg = operands[2].sme_index.base; - // operands[3].access = CS_AC_READ; - // break; - // } + // case Opcode::AArch64_LDR_PXI: + // [[fallthrough]]; + // case Opcode::AArch64_LDR_ZXI: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LSL_ZZI_S: + // // No defined access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // // No instruction id assigned + // id = AARCH64_INS_LSL; + // break; + // case Opcode::AArch64_LD2D: + // case Opcode::AArch64_LD2D_IMM: { + // // LD2D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - + // 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_WRITE; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_WRITE; + + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_LD3D_IMM: { + // // LD3D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + // uint16_t reg_enum2 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d, znn.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - + // 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest2 + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); + // } else { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_WRITE; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_WRITE; + // operands[2].reg = static_cast(reg_enum2); + // operands[2].access = CS_AC_WRITE; + + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_LD4D_IMM: { + // // LD4D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + // uint16_t reg_enum2 = AARCH64_REG_Z0; + // uint16_t reg_enum3 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d, znn.d, zmm.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - + // 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest2 + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest3 + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum3 += std::stoi(tmpOpStr.substr(1, 1)); + // } else { + // reg_enum3 += std::stoi(tmpOpStr.substr(1, 2)); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_WRITE; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_WRITE; + // operands[2].reg = static_cast(reg_enum2); + // operands[2].access = CS_AC_WRITE; + // operands[3].reg = static_cast(reg_enum3); + // operands[3].access = CS_AC_WRITE; + + // operands[4].access = CS_AC_READ; + // operands[5].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_MOVNWi: + // [[fallthrough]]; + // case Opcode::AArch64_MOVNXi: + // [[fallthrough]]; + // case Opcode::AArch64_MOVZWi: + // [[fallthrough]]; + // case Opcode::AArch64_MOVZXi: + // // MOVZ incorrectly flags destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_MOVPRFX_ZZ: + // // Assign operand access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_MRS: + // // MRS incorrectly flags source/destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // MRS incorrectly tags AARCH64_OP_REG_MRS as AARCH64_OP_SYS + // operands[1].type = AARCH64_OP_REG_MRS; + // break; + // case Opcode::AArch64_MSR: + // // MSR incorrectly flags source/destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // // MSR incorrectly tags AARCH64_OP_REG_MSR as AARCH64_OP_SYS + // operands[0].type = AARCH64_OP_REG_MSR; + // break; + // case Opcode::AArch64_PTEST_PP: { + // // PTEST doesn't label access types for operands + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // // Doesn't identify implicit NZCV destination + // implicitDestinationCount = 1; + // implicitDestinations[0] = AARCH64_REG_NZCV; + // break; + // } + // case Opcode::AArch64_PTRUE_B: + // [[fallthrough]]; + // case Opcode::AArch64_PTRUE_H: + // [[fallthrough]]; + // case Opcode::AArch64_PTRUE_D: + // [[fallthrough]]; + // case Opcode::AArch64_PTRUE_S: + // // PTRUE doesn't label access + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_RET: + // // If no register supplied to RET, default to x30 (LR) + // if (operandCount == 0) { + // operandCount = 1; + // operands[0].type = AARCH64_OP_REG; + // operands[0].reg = AARCH64_REG_LR; + // operands[0].access = CS_AC_READ; + // } + // groupCount = 1; + // groups[0] = CS_GRP_JUMP; + // break; + // case Opcode::AArch64_REV_ZZ_B: + // [[fallthrough]]; + // case Opcode::AArch64_REV_ZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_REV_ZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_REV_ZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_B: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_D: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_H: + // [[fallthrough]]; + // case Opcode::AArch64_REV_PP_S: { + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_SST1B_D_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_SST1D_REAL: + // [[fallthrough]]; + // case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { + // // ST1W doesn't correctly identify first source register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // // SST1D{_SCALED} gather instruction doesn't correctly identify + // memory + // // operands + // operands[2].type = AARCH64_OP_MEM; + // operands[2].access = CS_AC_READ; + + // // ST1D doesn't correctly identify vector memory register correctly + // uint16_t vec_enum = AARCH64_REG_Z0; + // std::string tmp_str(operandStr.substr(operandStr.find("["))); + // // Single or double digit Z register identifier + // if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { + // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); + // } else { + // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); + // } + // operands[2].mem.index = static_cast(vec_enum); + // break; + // } + // case Opcode::AArch64_ST2D_IMM: { + // // ST2D doesn't correctly identify destination registers + // uint16_t reg_enum0 = AARCH64_REG_Z0; + // uint16_t reg_enum1 = AARCH64_REG_Z0; + + // // tmpOpStr = "zxx.d, zyy.d" + // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - + // 1)); + // // get dest0, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + // // get dest1, then remove from string + // // Single or double digit Z register identifier + // if (tmpOpStr[2] == '.') { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); + // tmpOpStr.erase(0, 6); + // } else { + // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); + // tmpOpStr.erase(0, 7); + // } + + // operands[0].reg = static_cast(reg_enum0); + // operands[0].access = CS_AC_READ; + // operands[1].reg = static_cast(reg_enum1); + // operands[1].access = CS_AC_READ; + + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_ST1B: + // [[fallthrough]]; + // case Opcode::AArch64_ST1D: + // [[fallthrough]]; + // case Opcode::AArch64_ST1B_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_ST1D_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_ST1W_IMM: { + // // ST1W doesn't correctly identify first source register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_ST1W: + // [[fallthrough]]; + // case Opcode::AArch64_ST1W_D: { + // // ST1W doesn't correctly identify first source register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_SST1D_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_SST1W_D_IMM: + // [[fallthrough]]; + // case Opcode::AArch64_SST1W_IMM: { + // // ST1W scatter instruction doesn't correctly identify first source + // // register + // uint16_t reg_enum = AARCH64_REG_Z0; + // // Single or double digit Z register identifier + // if (operandStr[3] == '.') { + // reg_enum += std::stoi(operandStr.substr(2, 1)); + // } else { + // reg_enum += std::stoi(operandStr.substr(2, 2)); + // } + + // operands[0].reg = static_cast(reg_enum); + // // No defined access types + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // // ST1W scatter instruction doesn't correctly identify second Z reg + // as + // // memory operand + // operands[2].type = AARCH64_OP_MEM; + // operands[2].access = CS_AC_READ; + // // ST1W scatter instruction doesn't recognise memory-offset + // immediate + // // correctly + // if (operandStr[operandStr.length() - 3] != '.') { + // int64_t startPos = operandStr.find('#') + 1; + // int64_t immSize = (operandStr.length() - 1) - startPos; + // if (immSize == 1) { + // operands[2].mem.disp = + // std::stoi(operandStr.substr(startPos, immSize)); + // } else { + // // double or triple digit immediates are converted to hex, and + // so + // // require a different conversion to uint + // operands[2].mem.disp = + // std::stoul(operandStr.substr(startPos, immSize), nullptr, + // 16); + // } + // } + // break; + // } + // case Opcode::AArch64_ST1i8_POST: + // case Opcode::AArch64_ST1i16_POST: + // case Opcode::AArch64_ST1i32_POST: + // case Opcode::AArch64_ST1i64_POST: + // // Post offset register is not put as mem.index + // if (operands[2].type == AARCH64_OP_REG) { + // operands[1].mem.index = operands[2].reg; + // operands[2].type = AARCH64_OP_INVALID; + // } + // break; + // case Opcode::AArch64_ST1i16_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1i32_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1i64_POST: + // // fixing incorrect access type for register offset + // if (operandCount == 3) { + // operands[2].access = CS_AC_READ; + // } + // break; + // case Opcode::AArch64_ST1Fourv16b: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv2d: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv4s: + // // ST1 incorrectly flags read and write + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // break; + // case Opcode::AArch64_ST1Fourv16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv2d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv2s_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Fourv4s_POST: + // // ST1 incorrectly flags read and write + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ | CS_AC_WRITE; + // operands[5].access = CS_AC_READ; + // // determine correct type for operand 5 + // if (operandStr.find("#") != std::string::npos) { + // operands[5].type = AARCH64_OP_IMM; + // } else { + // operands[5].type = AARCH64_OP_REG; + // } + // break; + // case Opcode::AArch64_ST1Twov16b: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov2d: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov4s: + // // ST1 incorrectly flags read and write + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_ST1Twov16b_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov2d_POST: + // [[fallthrough]]; + // case Opcode::AArch64_ST1Twov4s_POST: + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ | CS_AC_WRITE; + // operands[3].access = CS_AC_READ; + // // determine correct type for operand 3 + // if (operandStr.find("#") != std::string::npos) { + // operands[3].type = AARCH64_OP_IMM; + // } else { + // operands[3].type = AARCH64_OP_REG; + // } + // break; + // case Opcode::AArch64_ST2Twov4s_POST: + // // ST2 post incorrectly flags read and write + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ | CS_AC_WRITE; + // // Another incorrect access flag for register offset operand + // if (operandCount == 4) { + // operands[3].access = CS_AC_READ; + // } + // break; + // case Opcode::AArch64_STRBui: + // [[fallthrough]]; + // case Opcode::AArch64_STRDui: + // [[fallthrough]]; + // case Opcode::AArch64_STRHui: + // [[fallthrough]]; + // case Opcode::AArch64_STRQui: + // [[fallthrough]]; + // case Opcode::AArch64_STRSui: + // [[fallthrough]]; + // case Opcode::AArch64_STRWui: + // [[fallthrough]]; + // case Opcode::AArch64_STRXui: + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_PFALSE: + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_STR_PXI: + // [[fallthrough]]; + // case Opcode::AArch64_STR_ZXI: + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_SBFMWri: + // [[fallthrough]]; + // case Opcode::AArch64_SBFMXri: + // // SBFM incorrectly flags destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_SVC: + // // SVC is incorrectly marked as setting x30 + // implicitDestinationCount = 0; + // break; + // case Opcode::AArch64_SYSxt: + // // No defined metadata.id for SYS instructions + // id = AARCH64_INS_SYS; + // break; + // case Opcode::AArch64_PSEL_PPPRI_B: + // [[fallthrough]]; + // case Opcode::AArch64_PSEL_PPPRI_D: + // [[fallthrough]]; + // case Opcode::AArch64_PSEL_PPPRI_H: + // [[fallthrough]]; + // case Opcode::AArch64_PSEL_PPPRI_S: + // // Add correct access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_UBFMWri: + // [[fallthrough]]; + // case Opcode::AArch64_UBFMXri: + // // UBFM incorrectly flags destination as READ | WRITE + // operands[0].access = CS_AC_WRITE; + // break; + // case Opcode::AArch64_UQDECB_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECB_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECD_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECD_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECH_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECH_XPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECW_WPiI: + // [[fallthrough]]; + // case Opcode::AArch64_UQDECW_XPiI: + // // UQDEC lacks access types + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // if (operandCount == 1) { + // operandCount = 2; + // operands[1].type = AARCH64_OP_IMM; + // operands[1].imm = 1; + // } + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_UUNPKHI_ZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKHI_ZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKHI_ZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKLO_ZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKLO_ZZ_H: + // [[fallthrough]]; + // case Opcode::AArch64_UUNPKLO_ZZ_S: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_WHILELT_PXX_B: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELT_PXX_D: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELT_PXX_H: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELT_PXX_S: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_B: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_D: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_H: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PWW_S: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_B: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_D: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_H: + // [[fallthrough]]; + // case Opcode::AArch64_WHILELO_PXX_S: + // // WHILELO doesn't label access or vector specifiers + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // // Doesn't identify implicit NZCV destination + // implicitDestinationCount = 1; + // implicitDestinations[0] = AARCH64_REG_NZCV; + // break; + // case Opcode::AArch64_XTNv16i8: + // case Opcode::AArch64_XTNv4i32: + // case Opcode::AArch64_XTNv8i16: + // // XTN2 incorrectly flags destination as only WRITE + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // break; + // case Opcode::AArch64_ZIP1_PPP_B: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_PPP_D: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_PPP_H: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_PPP_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP1_ZZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_B: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_D: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_H: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_PPP_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_ZZZ_S: + // [[fallthrough]]; + // case Opcode::AArch64_ZIP2_ZZZ_D: + // // ZIP lacks access types + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_SXTW_ZPmZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FCVT_ZPmZ_DtoS: + // [[fallthrough]]; + // case Opcode::AArch64_FCVT_ZPmZ_StoD: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_DtoS: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_StoD: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_StoS: + // [[fallthrough]]; + // case Opcode::AArch64_SCVTF_ZPmZ_DtoD: + // // Need to see if Destination vector elements are active + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8One: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8One: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8Two: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8Two: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8Three: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8Three: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // break; + // case Opcode::AArch64_TBLv8i8Four: + // [[fallthrough]]; + // case Opcode::AArch64_TBLv16i8Four: + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // operands[5].access = CS_AC_READ; + // break; + // case Opcode::AArch64_LD1_MXIPXX_H_D: + // [[fallthrough]]; + // case Opcode::AArch64_LD1_MXIPXX_V_D: + // [[fallthrough]]; + // case Opcode::AArch64_LD1_MXIPXX_V_S: + // [[fallthrough]]; + // case Opcode::AArch64_LD1_MXIPXX_H_S: { + // // Lacking access specifiers + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_ST1_MXIPXX_H_D: + // [[fallthrough]]; + // case Opcode::AArch64_ST1_MXIPXX_V_D: + // [[fallthrough]]; + // case Opcode::AArch64_ST1_MXIPXX_H_S: + // [[fallthrough]]; + // case Opcode::AArch64_ST1_MXIPXX_V_S: + // // Access types are not defined + // operands[0].access = CS_AC_READ; + // operands[1].access = CS_AC_READ; + // break; + // case Opcode::AArch64_FMOPA_MPPZZ_D: + // [[fallthrough]]; + // case Opcode::AArch64_FMOPA_MPPZZ_S: { + // // Need to add access specifiers + // // although operands[0] should be READ | WRITE, due to the + // implemented + // // decode logic for SME tile destinations, the register will be + // added as + // // both source and destination with just WRITE access. + // operands[0].access = CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].access = CS_AC_READ; + // operands[4].access = CS_AC_READ; + // operands[5].access = CS_AC_READ; + // break; + // } + // case Opcode::AArch64_EXTRACT_ZPMXI_H_B: { + // operandCount = 4; + // operands[0].access = CS_AC_READ | CS_AC_WRITE; + // operands[1].access = CS_AC_READ; + // operands[2].access = CS_AC_READ; + // operands[3].reg = operands[2].sme_index.base; + // operands[3].access = CS_AC_READ; + // break; + // } case Opcode::AArch64_ZERO_M: { // Operands often mangled from ZA tile overlap aliasing in decode. // Need to re-extract relevant tiles from operandStr diff --git a/src/lib/arch/aarch64/Instruction_address.cc b/src/lib/arch/aarch64/Instruction_address.cc index 7462e0ab1b..4034cb9a46 100644 --- a/src/lib/arch/aarch64/Instruction_address.cc +++ b/src/lib/arch/aarch64/Instruction_address.cc @@ -99,7 +99,7 @@ span Instruction::generateAddresses() { const uint16_t partition_num = VL_bits / 64; const uint64_t n = sourceValues_[partition_num + 2].get(); uint64_t m = 0; - if (metadata_.operands[2].mem.index) + if (metadata_.operands[2].mem.index != AARCH64_REG_INVALID) m = sourceValues_[partition_num + 3].get() << 3; setMemoryAddresses({(n + m), static_cast(VL_bits / 8)}); break; @@ -429,7 +429,7 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LD2Twov4s_POST: { // ld2 {vt1.4s, vt2.4s}, [xn], // #imm - const uint64_t base = sourceValues_[2].get(); + const uint64_t base = sourceValues_[0].get(); setMemoryAddresses({{base, 16}, {base + 16, 16}}); break; } diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 5dc5709071..13568a0b3f 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -338,6 +338,7 @@ void Instruction::decode() { sourceOperandsPending_++; } } else if (op.type == AARCH64_OP_PRED) { + setInstructionType(InsnType::isPredicate); if (op.access == CS_AC_READ) { std::cerr << "\tPred read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.pred.reg); @@ -919,16 +920,17 @@ void Instruction::decode() { setInstructionType(InsnType::isScalarData); } - if (!(isInstruction(InsnType::isSMEData))) { - // Catch zero register references and pre-complete those operands - not - // applicable to SME instructions - for (uint16_t i = 0; i < sourceRegisterCount_; i++) { - if (sourceRegisters_[i] == RegisterType::ZERO_REGISTER) { - sourceValues_[i] = RegisterValue(0, 8); - sourceOperandsPending_--; - } + // if (!(isInstruction(InsnType::isSMEData))) { + // Catch zero register references and pre-complete those operands - not + // applicable to SME instructions + for (uint16_t i = 0; i < sourceRegisterCount_; i++) { + if (sourceRegisters_[i] == RegisterType::ZERO_REGISTER) { + sourceValues_[i] = RegisterValue(0, 8); + sourceOperandsPending_--; } - } else { + } + // } else { + if (isInstruction(InsnType::isSMEData)) { // For SME instructions, resize the following structures to have the // exact amount of space required sourceRegisters_.resize(sourceRegisterCount_); diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index d44251ed9d..62527af2b4 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -2786,14 +2786,13 @@ void Instruction::execute() { break; } case Opcode::AArch64_LD1Onev16b_POST: { // ld1 {vt.16b}, [xn], <#imm|xm> - results_[1] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); - // if #imm post-index, value can only be 16 const uint64_t postIndex = (metadata_.operands[2].type == AARCH64_OP_REG) ? sourceValues_[1].get() : 16; results_[0] = sourceValues_[0].get() + postIndex; + results_[1] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); break; } case Opcode::AArch64_LD1RD_IMM: { // ld1rd {zt.d}, pg/z, [xn, #imm] @@ -2936,9 +2935,9 @@ void Instruction::execute() { uint8_t val = memoryData_[0].get(); uint8_t out[16] = {val, val, val, val, val, val, val, val, val, val, val, val, val, val, val, val}; - results_[1] = {out, 256}; results_[0] = - sourceValues_[0].get() + metadata_.operands[2].imm; + sourceValues_[0].get() + metadata_.operands[1].mem.disp; + results_[1] = {out, 256}; break; } case Opcode::AArch64_LD1Rv1d: { // ld1r {vt.1d}, [xn] @@ -2952,9 +2951,9 @@ void Instruction::execute() { // LOAD uint64_t val = memoryData_[0].get(); uint64_t out[2] = {val, 0}; - results_[1] = {out, 256}; results_[0] = - sourceValues_[0].get() + metadata_.operands[2].imm; + sourceValues_[0].get() + metadata_.operands[1].mem.disp; + results_[1] = {out, 256}; break; } case Opcode::AArch64_LD1Rv2d: { // ld1r {vt.2d}, [xn] @@ -2968,9 +2967,9 @@ void Instruction::execute() { // LOAD uint64_t val = memoryData_[0].get(); uint64_t out[2] = {val, val}; - results_[1] = {out, 256}; results_[0] = - sourceValues_[0].get() + metadata_.operands[2].imm; + sourceValues_[0].get() + metadata_.operands[1].mem.disp; + results_[1] = {out, 256}; break; } case Opcode::AArch64_LD1Rv2s: { // ld1r {vt.2s}, [xn] @@ -2984,9 +2983,9 @@ void Instruction::execute() { // LOAD uint32_t val = memoryData_[0].get(); uint32_t out[4] = {val, val, 0, 0}; - results_[1] = {out, 256}; results_[0] = - sourceValues_[0].get() + metadata_.operands[2].imm; + sourceValues_[0].get() + metadata_.operands[1].mem.disp; + results_[1] = {out, 256}; break; } case Opcode::AArch64_LD1Rv4h: { // ld1r {vt.4h}, [xn] @@ -3000,9 +2999,9 @@ void Instruction::execute() { // LOAD uint16_t val = memoryData_[0].get(); uint16_t out[8] = {val, val, val, val, 0, 0, 0, 0}; - results_[1] = {out, 256}; results_[0] = - sourceValues_[0].get() + metadata_.operands[2].imm; + sourceValues_[0].get() + metadata_.operands[1].mem.disp; + results_[1] = {out, 256}; break; } case Opcode::AArch64_LD1Rv4s: { // ld1r {vt.4s}, [xn] @@ -3016,9 +3015,9 @@ void Instruction::execute() { // LOAD uint32_t val = memoryData_[0].get(); uint32_t out[4] = {val, val, val, val}; - results_[1] = {out, 256}; results_[0] = - sourceValues_[0].get() + metadata_.operands[2].imm; + sourceValues_[0].get() + metadata_.operands[1].mem.disp; + results_[1] = {out, 256}; break; } case Opcode::AArch64_LD1Rv8b: { // ld1r {vt.8b}, [xn] @@ -3034,9 +3033,9 @@ void Instruction::execute() { uint8_t val = memoryData_[0].get(); uint8_t out[16] = {val, val, val, val, val, val, val, val, 0, 0, 0, 0, 0, 0, 0, 0}; - results_[1] = {out, 256}; results_[0] = - sourceValues_[0].get() + metadata_.operands[2].imm; + sourceValues_[0].get() + metadata_.operands[1].mem.disp; + results_[1] = {out, 256}; break; } case Opcode::AArch64_LD1Rv8h: { // ld1r {vt.8h}, [xn] @@ -3050,9 +3049,9 @@ void Instruction::execute() { // LOAD uint16_t val = memoryData_[0].get(); uint16_t out[8] = {val, val, val, val, val, val, val, val}; - results_[1] = {out, 256}; results_[0] = - sourceValues_[0].get() + metadata_.operands[2].imm; + sourceValues_[0].get() + metadata_.operands[1].mem.disp; + results_[1] = {out, 256}; break; } case Opcode::AArch64_LD1Fourv16b: // ld1 {vt1.16b, vt2.16b, vt3.16b, @@ -3079,16 +3078,16 @@ void Instruction::execute() { case Opcode::AArch64_LD1Fourv4s_POST: { // ld1 {vt1.4s, vt2.4s, vt3.4s, // vt4.4s}, [xn], <#imm|xm> // LOAD - results_[1] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); - results_[2] = memoryData_[1].zeroExtend(memoryData_[1].size(), 256); - results_[3] = memoryData_[2].zeroExtend(memoryData_[2].size(), 256); - results_[4] = memoryData_[3].zeroExtend(memoryData_[3].size(), 256); // if #imm post-index, value can only be 64 const uint64_t postIndex = (metadata_.operands[5].type == AARCH64_OP_REG) ? sourceValues_[1].get() : 64; results_[0] = sourceValues_[0].get() + postIndex; + results_[1] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); + results_[2] = memoryData_[1].zeroExtend(memoryData_[1].size(), 256); + results_[3] = memoryData_[2].zeroExtend(memoryData_[2].size(), 256); + results_[4] = memoryData_[3].zeroExtend(memoryData_[3].size(), 256); break; } case Opcode::AArch64_LD1Twov16b: // ld1 {vt1.16b, vt2.16b}, [xn] @@ -3110,15 +3109,14 @@ void Instruction::execute() { case Opcode::AArch64_LD1Twov4s_POST: { // ld1 {vt1.4s, vt2.4s}, [xn], // <#imm|xm> // LOAD - results_[1] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); - results_[2] = memoryData_[1].zeroExtend(memoryData_[1].size(), 256); - // if #imm post-index, value can only be 32 const uint64_t postIndex = (metadata_.operands[3].type == AARCH64_OP_REG) ? sourceValues_[1].get() : 32; results_[0] = sourceValues_[0].get() + postIndex; + results_[1] = memoryData_[0].zeroExtend(memoryData_[0].size(), 256); + results_[2] = memoryData_[1].zeroExtend(memoryData_[1].size(), 256); break; } case Opcode::AArch64_LD1W: { // ld1w {zt.s}, pg/z, [xn, xm, lsl #2] @@ -3190,9 +3188,13 @@ void Instruction::execute() { for (int i = 0; i < 2; i++) { out[i] = (i == index) ? memoryData_[0].get() : vt[i]; } + // If post index is #imm, it can only be 8 + const uint64_t postIndex = + (metadata_.operands[2].type == AARCH64_OP_REG) + ? sourceValues_[1].get() + : 8; + results_[0] = sourceValues_[1].get() + postIndex; results_[1] = {out, 256}; - results_[0] = - sourceValues_[1].get() + metadata_.operands[2].imm; break; } case Opcode::AArch64_LD2D: // ld2d {zt1.d, zt2.d}, pg/z, [, xm, @@ -3234,19 +3236,19 @@ void Instruction::execute() { break; } case Opcode::AArch64_LD2Twov4s_POST: { // ld2 {vt1.4s, vt2.4s}, [xn], - // #imm + // // LOAD const float* region1 = memoryData_[0].getAsVector(); const float* region2 = memoryData_[1].getAsVector(); float t1[4] = {region1[0], region1[2], region2[0], region2[2]}; float t2[4] = {region1[1], region1[3], region2[1], region2[3]}; + // #imm can only be 32 + const uint64_t offset = (metadata_.operands[3].type == AARCH64_OP_REG) + ? sourceValues_[1].get() + : 32; + results_[0] = sourceValues_[0].get() + offset; results_[1] = {t1, 256}; results_[2] = {t2, 256}; - uint64_t offset = 32; - if (metadata_.operandCount == 4) { - offset = sourceValues_[3].get(); - } - results_[0] = sourceValues_[2].get() + offset; break; } case Opcode::AArch64_LD3D_IMM: { // ld3d {zt1.d, zt2.d, zt3.d}, pg/z, @@ -4813,16 +4815,16 @@ void Instruction::execute() { memoryData_[0] = t[metadata_.operands[0].vector_index]; break; } - case Opcode::AArch64_ST1i16_POST: { // st1 {vt.h}[index], [xn], xm - // st1 {vt.h}[index], [xn], #2 + case Opcode::AArch64_ST1i16_POST: { // st1 {vt.h}[index], [xn], // STORE const uint16_t* t = sourceValues_[0].getAsVector(); memoryData_[0] = t[metadata_.operands[0].vector_index]; - uint64_t offset = 2; - if (metadata_.operandCount == 3) { - offset = sourceValues_[2].get(); - } - results_[0] = sourceValues_[1].get() + offset; + // if #imm post-index, value can only be 2 + const uint64_t postIndex = + (metadata_.operands[2].type == AARCH64_OP_REG) + ? sourceValues_[2].get() + : 2; + results_[0] = sourceValues_[1].get() + postIndex; break; } case Opcode::AArch64_ST1i32: { // st1 {vt.s}[index], [xn] @@ -4831,16 +4833,16 @@ void Instruction::execute() { memoryData_[0] = t[metadata_.operands[0].vector_index]; break; } - case Opcode::AArch64_ST1i32_POST: { // st1 {vt.s}[index], [xn], xm - // st1 {vt.s}[index], [xn], #4 + case Opcode::AArch64_ST1i32_POST: { // st1 {vt.s}[index], [xn], // STORE const uint32_t* t = sourceValues_[0].getAsVector(); memoryData_[0] = t[metadata_.operands[0].vector_index]; - uint64_t offset = 4; - if (metadata_.operandCount == 3) { - offset = sourceValues_[2].get(); - } - results_[0] = sourceValues_[1].get() + offset; + // if #imm post-index, value can only be 4 + const uint64_t postIndex = + (metadata_.operands[2].type == AARCH64_OP_REG) + ? sourceValues_[2].get() + : 4; + results_[0] = sourceValues_[1].get() + postIndex; break; } case Opcode::AArch64_ST1i64: { // st1 {vt.d}[index], [xn] @@ -4849,16 +4851,16 @@ void Instruction::execute() { memoryData_[0] = t[metadata_.operands[0].vector_index]; break; } - case Opcode::AArch64_ST1i64_POST: { // st1 {vt.d}[index], [xn], xm - // st1 {vt.d}[index], [xn], #8 + case Opcode::AArch64_ST1i64_POST: { // st1 {vt.d}[index], [xn], // STORE const uint64_t* t = sourceValues_[0].getAsVector(); memoryData_[0] = t[metadata_.operands[0].vector_index]; - uint64_t offset = 8; - if (metadata_.operandCount == 3) { - offset = sourceValues_[2].get(); - } - results_[0] = sourceValues_[1].get() + offset; + // if #imm post-index, value can only be 8 + const uint64_t postIndex = + (metadata_.operands[2].type == AARCH64_OP_REG) + ? sourceValues_[2].get() + : 8; + results_[0] = sourceValues_[1].get() + postIndex; break; } case Opcode::AArch64_ST1i8: { // st1 {vt.b}[index], [xn] @@ -4867,17 +4869,16 @@ void Instruction::execute() { memoryData_[0] = t[metadata_.operands[0].vector_index]; break; } - case Opcode::AArch64_ST1i8_POST: { // st1 {vt.b}[index], [xn], xm - // st1 {vt.b}[index], [xn], #1 + case Opcode::AArch64_ST1i8_POST: { // st1 {vt.b}[index], [xn], // STORE const uint8_t* t = sourceValues_[0].getAsVector(); memoryData_[0] = t[metadata_.operands[0].vector_index]; - uint64_t offset = 1; - if (metadata_.operandCount == 3) { - offset = sourceValues_[2].get(); - } - results_[0] = - RegisterValue(sourceValues_[1].get() + offset, 8); + // if #imm post-index, value can only be 1 + const uint64_t postIndex = + (metadata_.operands[2].type == AARCH64_OP_REG) + ? sourceValues_[2].get() + : 1; + results_[0] = sourceValues_[1].get() + postIndex; break; } case Opcode::AArch64_ST2D_IMM: { // st2d {zt1.d, zt2.d}, pg, [{, @@ -4917,7 +4918,7 @@ void Instruction::execute() { break; } case Opcode::AArch64_ST2Twov4s_POST: { // st2 {vt1.4s, vt2.4s}, [xn], - // #imm + // // STORE const float* t1 = sourceValues_[0].getAsVector(); const float* t2 = sourceValues_[1].getAsVector(); @@ -4925,12 +4926,12 @@ void Instruction::execute() { std::vector m2 = {t1[2], t2[2], t1[3], t2[3]}; memoryData_[0] = RegisterValue((char*)m1.data(), 4 * sizeof(float)); memoryData_[1] = RegisterValue((char*)m2.data(), 4 * sizeof(float)); - - uint64_t offset = 32; - if (metadata_.operandCount == 4) { - offset = sourceValues_[3].get(); - } - results_[0] = sourceValues_[2].get() + offset; + // if #imm post-index, value can only be 32 + const uint64_t postIndex = + (metadata_.operands[3].type == AARCH64_OP_REG) + ? sourceValues_[3].get() + : 32; + results_[0] = sourceValues_[2].get() + postIndex; break; } case Opcode::AArch64_STLRB: { // stlrb wt, [xn] From dce6b112745aa0d134520d2cb09507ad5b02d2b5 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 5 Sep 2024 12:13:58 +0200 Subject: [PATCH 06/34] Finished ensuring regression tests pass. --- .../simeng/arch/aarch64/helpers/sve.hh | 16 +- src/lib/arch/aarch64/InstructionMetadata.cc | 2595 +---------------- src/lib/arch/aarch64/InstructionMetadata.hh | 7 - src/lib/arch/aarch64/Instruction_address.cc | 22 +- src/lib/arch/aarch64/Instruction_execute.cc | 22 +- 5 files changed, 118 insertions(+), 2544 deletions(-) diff --git a/src/include/simeng/arch/aarch64/helpers/sve.hh b/src/include/simeng/arch/aarch64/helpers/sve.hh index cf3e1b0266..75211fc155 100644 --- a/src/include/simeng/arch/aarch64/helpers/sve.hh +++ b/src/include/simeng/arch/aarch64/helpers/sve.hh @@ -1048,17 +1048,16 @@ RegisterValue sveMax_vecImm( return {out, 256}; } -/** Helper function for SVE instructions with the format `max zdn, zdn, - * #imm`. +/** Helper function for SVE instructions with the format `max zdn, pg/m zdn, + * zm`. * T represents the type of sourceValues (e.g. for zdn.d, T = uint64_t). * Returns correctly formatted RegisterValue. */ template RegisterValue sveMaxPredicated_vecs(srcValContainer& sourceValues, const uint16_t VL_bits) { - const T* d = sourceValues[0].getAsVector(); - const uint64_t* p = sourceValues[1].getAsVector(); - const T* n = sourceValues[2].getAsVector(); - const T* m = sourceValues[3].getAsVector(); + const uint64_t* p = sourceValues[0].getAsVector(); + const T* n = sourceValues[1].getAsVector(); + const T* m = sourceValues[2].getAsVector(); const uint16_t partition_num = VL_bits / (sizeof(T) * 8); T out[256 / sizeof(T)] = {0}; @@ -1068,7 +1067,7 @@ RegisterValue sveMaxPredicated_vecs(srcValContainer& sourceValues, if (p[i / (64 / sizeof(T))] & shifted_active) { out[i] = std::max(n[i], m[i]); } else - out[i] = d[i]; + out[i] = n[i]; } return {out, 256}; } @@ -1597,7 +1596,8 @@ uint64_t sveUqdec(srcValContainer& sourceValues, const simeng::arch::aarch64::InstructionMetadata& metadata, const uint16_t VL_bits) { const D d = sourceValues[0].get(); - const uint8_t imm = metadata.operands[1].imm; + // metadata.operands[1] contains the SVE pattern + const uint8_t imm = metadata.operands[2].imm; const uint16_t count = sveGetPattern(metadata.operandStr, N, VL_bits); // The range of possible values does not fit in the range of any integral diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index 1c0c82ed95..bd1600959c 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -33,20 +33,13 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // Fix some inaccuracies in the decoded metadata switch (opcode) { - case Opcode::AArch64_ADR_LSL_ZZZ_D_0: - [[fallthrough]]; + case Opcode::AArch64_ADR_LSL_ZZZ_D_0: // example bytecode = c8a0e704 case Opcode::AArch64_ADR_LSL_ZZZ_D_1: - [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_D_2: - [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_D_3: - [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_S_0: - [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_S_1: - [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_S_2: - [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_S_3: { // Change the last 2 Z-regs from one MEM operand to two REG operands operandCount = 3; @@ -60,17 +53,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].shift = operands[1].shift; break; } - // case Opcode::AArch64_SMIN_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_EOR_ZPmZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_EOR_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_EOR_ZPmZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_EOR_ZPmZ_S: - // [[fallthrough]]; - case Opcode::AArch64_AND_ZPmZ_D: + case Opcode::AArch64_AND_ZPmZ_D: // Example bytecode - 4901da04 case Opcode::AArch64_AND_ZPmZ_H: case Opcode::AArch64_AND_ZPmZ_S: case Opcode::AArch64_AND_ZPmZ_B: @@ -80,169 +63,15 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].access = CS_AC_READ; operands[3].access = CS_AC_READ; break; - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_BICv4i32: - // // BIC incorrectly flags destination as WRITE only - // operands[0].access = CS_AC_WRITE | CS_AC_READ; - // break; - // case Opcode::AArch64_ADDSWri: - // // adds incorrectly flags destination as READ - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_BICv8i16: - // operands[0].access = CS_AC_WRITE | CS_AC_READ; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_BICv8i8: - // // access specifier for last operand was missing - // operands[2].access = CS_AC_READ; - // break; - case Opcode::AArch64_CASALW: - [[fallthrough]]; + case Opcode::AArch64_CASALW: // Example bbytecode - 02fce188 case Opcode::AArch64_CASALX: + // Correct access types operandCount = 3; operands[0].access = CS_AC_READ; operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ; break; - // case Opcode::AArch64_CBNZW: - // [[fallthrough]]; - // case Opcode::AArch64_CBNZX: - // [[fallthrough]]; - // case Opcode::AArch64_CBZW: - // [[fallthrough]]; - // case Opcode::AArch64_CBZX: - // // incorrectly adds implicit nzcv dependency - // implicitSourceCount = 0; - // break; - // case Opcode::AArch64_CMPHI_PPzZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPHI_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPHI_PPzZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPHI_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_CMPGT_PPzZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPGT_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPGT_PPzZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPGT_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZI_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZI_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZI_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZI_S: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPEQ_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZI_B: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZI_D: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZI_H: - // [[fallthrough]]; - // case Opcode::AArch64_CMPNE_PPzZI_S: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // // Doesn't identify implicit NZCV destination - // implicitDestinationCount = 1; - // implicitDestinations[0] = AARCH64_REG_NZCV; - // break; - // case Opcode::AArch64_CNTB_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_CNTH_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_CNTD_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_CNTW_XPiI: { - // // lacking access specifiers for destination - // operands[0].access = CS_AC_WRITE; - // if (operandStr.length() < 4) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - // operands[1].ext = AARCH64_EXT_INVALID; - // operands[1].vector_index = -1; - // } - // break; - // } - // case Opcode::AArch64_ADD_ZI_B: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZI_D: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZI_H: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZI_S: { - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[2].type = AARCH64_OP_IMM; - // operandCount = 3; - - // // Extract immediate in SVE add with immediate instruction - // size_t start = operandStr.find("#"); - // // Identify whether the immediate value is in base-10 or base-16 - // if (start != std::string::npos) { - // start++; - // bool hex = false; - // if (operandStr[start + 1] == 'x') { - // hex = true; - // start += 2; - // } - - // uint8_t end = operandStr.size(); - // size_t shifted = operandStr.find("LSL"); - // if (shifted != std::string::npos) { - // std::cerr << "[SimEng:arch] SVE add with immediate has shift - // value - // " - // "in operandStr which is unsupported." - // << std::endl; - // exit(1); - // } - // // Convert extracted immediate from string to int64_t - // std::string sub = operandStr.substr(start, end); - // if (hex) { - // operands[2].imm = std::stoul(sub, 0, 16); - // } else { - // operands[2].imm = stoi(sub); - // } - // } else { - // operands[2].imm = 0; - // } - // break; - // } - case Opcode::AArch64_ADD_ZI_B: + case Opcode::AArch64_ADD_ZI_B: // Example bytecode - 00c12025 case Opcode::AArch64_ADD_ZI_D: case Opcode::AArch64_ADD_ZI_H: case Opcode::AArch64_ADD_ZI_S: { @@ -257,12 +86,87 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) } break; } - case Opcode::AArch64_AND_ZI: + case Opcode::AArch64_SMAX_ZI_B: + case Opcode::AArch64_SMAX_ZI_D: + case Opcode::AArch64_SMAX_ZI_H: + case Opcode::AArch64_SMAX_ZI_S: // Example bytecode - 03c0a825 + case Opcode::AArch64_AND_ZI: // Example bytecode - 00068005 + // Incorrect access types + operands[0].access = CS_AC_WRITE; + operands[1].access = CS_AC_READ; + break; + case Opcode::AArch64_FSUB_ZPmI_D: + case Opcode::AArch64_FSUB_ZPmI_H: + case Opcode::AArch64_FSUB_ZPmI_S: // Example bytecode - 00849965 + case Opcode::AArch64_FMUL_ZPmI_D: + case Opcode::AArch64_FMUL_ZPmI_H: + case Opcode::AArch64_FMUL_ZPmI_S: // Example bytecode - 00809a65 + case Opcode::AArch64_FADD_ZPmI_D: // Example bytecode - 0584d865 + case Opcode::AArch64_FADD_ZPmI_H: + case Opcode::AArch64_FADD_ZPmI_S: { // Incorrect access types operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; + operands[2].access = CS_AC_READ; + // Extract FP constant imm + aarch64_exactfpimm exactFp = operands[3].sysop.imm.exactfpimm; + if (exactFp == AARCH64_EXACTFPIMM_HALF) + operands[3].fp = 0.5; + else if (exactFp == AARCH64_EXACTFPIMM_ONE) + operands[3].fp = 1.0; + else if (exactFp == AARCH64_EXACTFPIMM_TWO) + operands[3].fp = 2.0; + else if (exactFp == AARCH64_EXACTFPIMM_ZERO) + operands[3].fp = 0.0; + else + assert(false && "Invalid FP immidate contant."); break; - case Opcode::AArch64_EOR_ZPmZ_B: + } + case Opcode::AArch64_SMULH_ZPmZ_B: // Example bytecode - 20001204 + case Opcode::AArch64_SMULH_ZPmZ_D: + case Opcode::AArch64_SMULH_ZPmZ_H: + case Opcode::AArch64_SMULH_ZPmZ_S: + case Opcode::AArch64_SMIN_ZPmZ_B: + case Opcode::AArch64_SMIN_ZPmZ_D: + case Opcode::AArch64_SMIN_ZPmZ_H: + case Opcode::AArch64_SMIN_ZPmZ_S: // Example bytecode - 01008a04 + case Opcode::AArch64_SMAX_ZPmZ_B: + case Opcode::AArch64_SMAX_ZPmZ_D: + case Opcode::AArch64_SMAX_ZPmZ_H: + case Opcode::AArch64_SMAX_ZPmZ_S: // Example bytecode - 01008804 + case Opcode::AArch64_MUL_ZPmZ_B: // Example bytecode - 40001004 + case Opcode::AArch64_MUL_ZPmZ_D: + case Opcode::AArch64_MUL_ZPmZ_H: + case Opcode::AArch64_MUL_ZPmZ_S: + case Opcode::AArch64_FSUBR_ZPmZ_D: + case Opcode::AArch64_FSUBR_ZPmZ_H: + case Opcode::AArch64_FSUBR_ZPmZ_S: // Example bytecode - 24808365 + case Opcode::AArch64_FSUB_ZPmZ_D: + case Opcode::AArch64_FSUB_ZPmZ_H: + case Opcode::AArch64_FSUB_ZPmZ_S: // Example bytecode - 24808165 + case Opcode::AArch64_FMUL_ZPmZ_D: + case Opcode::AArch64_FMUL_ZPmZ_H: + case Opcode::AArch64_FMUL_ZPmZ_S: // Example bytecode - 83808265 + case Opcode::AArch64_FDIV_ZPmZ_D: // Example bytecode - 0184cd65 + case Opcode::AArch64_FDIV_ZPmZ_H: + case Opcode::AArch64_FDIV_ZPmZ_S: + case Opcode::AArch64_FDIVR_ZPmZ_D: // Example bytecode - 0184cc65 + case Opcode::AArch64_FDIVR_ZPmZ_H: + case Opcode::AArch64_FDIVR_ZPmZ_S: + case Opcode::AArch64_FADDA_VPZ_D: + case Opcode::AArch64_FADDA_VPZ_H: + case Opcode::AArch64_FADDA_VPZ_S: // Example bytecode - 01249865 + case Opcode::AArch64_FADD_ZPmZ_D: // Example bytecode - 6480c065 + case Opcode::AArch64_FADD_ZPmZ_H: + case Opcode::AArch64_FADD_ZPmZ_S: + case Opcode::AArch64_FCADD_ZPmZ_D: // Example bytecode - 2080c064 + case Opcode::AArch64_FCADD_ZPmZ_H: + case Opcode::AArch64_FCADD_ZPmZ_S: + case Opcode::AArch64_ADD_ZPmZ_B: // Example bytecode - 00000004 + case Opcode::AArch64_ADD_ZPmZ_D: + case Opcode::AArch64_ADD_ZPmZ_H: + case Opcode::AArch64_ADD_ZPmZ_S: + case Opcode::AArch64_EOR_ZPmZ_B: // Example bytecode - 20001904 case Opcode::AArch64_EOR_ZPmZ_D: case Opcode::AArch64_EOR_ZPmZ_H: case Opcode::AArch64_EOR_ZPmZ_S: @@ -272,1512 +176,26 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].access = CS_AC_READ; operands[3].access = CS_AC_READ; break; - // char specifier = operandStr[operandStr.find(".") + 1]; - // switch (specifier) { - // case 'b': { - // uint8_t mask = static_cast(operands[2].imm); - // operands[2].imm = static_cast(0); - // for (int i = 0; i < 8; i++) - // operands[2].imm |= (static_cast(mask) << (i * 8)); - // break; - // } - // case 'h': { - // uint16_t mask = static_cast(operands[2].imm); - // operands[2].imm = static_cast(0); - // for (int i = 0; i < 4; i++) - // operands[2].imm |= (static_cast(mask) << (i * 16)); - // break; - // } - // case 's': { - // uint32_t mask = static_cast(operands[2].imm); - // operands[2].imm = static_cast(0); - // for (int i = 0; i < 2; i++) - // operands[2].imm |= (static_cast(mask) << (i * 32)); - // break; - // } - // default: - // break; - // } - // break; - // } - // case Opcode::AArch64_CNTP_XPP_B: - // [[fallthrough]]; - // case Opcode::AArch64_CNTP_XPP_D: - // [[fallthrough]]; - // case Opcode::AArch64_CNTP_XPP_H: - // [[fallthrough]]; - // case Opcode::AArch64_CNTP_XPP_S: - // [[fallthrough]]; - // case Opcode::AArch64_EOR_ZZZ: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_DECD_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_DECB_XPiI: { - // // lacking access specifiers for destination - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // std::string str(operandStr); - // if (str.length() < 4) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - // operands[1].ext = AARCH64_EXT_INVALID; - // operands[1].vector_index = -1; - // } - // break; - // } - // case Opcode::AArch64_EOR_PPzPP: { - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - case Opcode::AArch64_FMOVXDHighr: - // FMOVXDHighr incorrectly flags destination as only WRITE + case Opcode::AArch64_FMOVXDHighr: // Example bytecode - 4100af9e + // FMOVXDHighr incorrectly flags destination as WRITE only operands[0].access = CS_AC_READ | CS_AC_WRITE; break; - // case Opcode::AArch64_FNMSB_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FNMSB_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FNMLS_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FNMLS_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMAD_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMAD_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMLA_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMLA_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMLS_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMLS_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMSB_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMSB_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_MLA_ZPmZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_MLA_ZPmZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_MLA_ZPmZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_MLA_ZPmZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_SMAX_ZPmZ_S: - // // No defined access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_ADDPL_XXI: - // [[fallthrough]]; - // case Opcode::AArch64_ADDVL_XXI: - // [[fallthrough]]; - // case Opcode::AArch64_UADDV_VPZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_UADDV_VPZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_UADDV_VPZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_UADDV_VPZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_MOVPRFX_ZPzZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_MOVPRFX_ZPzZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_SUB_ZZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_SUB_ZZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_SUB_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_SUB_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_II_B: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_II_H: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_II_S: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_II_D: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_IR_B: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_IR_D: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_IR_H: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_IR_S: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RI_B: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RI_D: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RI_H: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RI_S: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RR_B: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RR_D: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RR_H: - // [[fallthrough]]; - // case Opcode::AArch64_INDEX_RR_S: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FSUB_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FSUB_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMUL_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMUL_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_SMAX_ZI_S: - // [[fallthrough]]; - // case Opcode::AArch64_SMINV_VPZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_TRN1_ZZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_TRN1_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_TRN1_ZZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_TRN1_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_TRN2_ZZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_TRN2_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_TRN2_ZZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_TRN2_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_UZP1_ZZZ_S: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_MOVPRFX_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCPY_ZPmI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCPY_ZPmI_S: - // [[fallthrough]]; - // case Opcode::AArch64_FNEG_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FNEG_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FRINTN_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FRINTN_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FABS_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FABS_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FSQRT_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FSQRT_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCVTZS_ZPmZ_DtoD: - // [[fallthrough]]; - // case Opcode::AArch64_FCVTZS_ZPmZ_StoD: - // [[fallthrough]]; - // case Opcode::AArch64_FCVTZS_ZPmZ_StoS: - // [[fallthrough]]; - // case Opcode::AArch64_FCVTZS_ZPmZ_DtoS: - // // No defined access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_FMUL_ZPmI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMUL_ZPmI_S: { - // // No defined access types - // operandCount = 4; - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].type = AARCH64_OP_FP; - // operands[3].access = CS_AC_READ; - // // Doesn't recognise immediate operands - // // Extract two possible values, 0.5 or 2.0 - // if (operandStr.substr(operandStr.length() - 1, 1) == "5") { - // operands[3].fp = 0.5f; - // } else { - // operands[3].fp = 2.0f; - // } - - // break; - // } - // case Opcode::AArch64_FCMLA_ZPmZZ_D: { - // // No defined access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // operands[4].type = AARCH64_OP_IMM; - // break; - // } - // case Opcode::AArch64_FCADD_ZPmZ_D: { - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // operands[4].type = AARCH64_OP_IMM; - // break; - // } - // case Opcode::AArch64_FSUB_ZPmI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FSUB_ZPmI_S: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZPmI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZPmI_S: - // // No defined access types - // operandCount = 4; - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].type = AARCH64_OP_FP; - // operands[3].access = CS_AC_READ; - // // Doesn't recognise immediate operands - // // Extract two possible values, 0.5 or 1.0 - // if (operandStr.substr(operandStr.length() - 1, 1) == "5") { - // operands[3].fp = 0.5f; - // } else { - // operands[3].fp = 1.0f; - // } - // break; - // case Opcode::AArch64_FCMGT_PPzZ0_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGT_PPzZ0_S: { - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_FMLA_ZZZI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMLA_ZZZI_S: { - // // Need to define missing access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_FDIVR_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FDIVR_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FDIV_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_AND_PPzPP: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZPmZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZPmZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_ADD_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FADD_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGE_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGE_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGE_PPzZ0_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGE_PPzZ0_S: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGT_PPzZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCMGT_PPzZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FCMLE_PPzZ0_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCMLE_PPzZ0_S: - // [[fallthrough]]; - // case Opcode::AArch64_FCMLT_PPzZ0_S: - // [[fallthrough]]; - // case Opcode::AArch64_FMUL_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMUL_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FSUBR_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FSUBR_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FSUB_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FSUB_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_FADDA_VPZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_MUL_ZPmZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_MUL_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_MUL_ZPmZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_MUL_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_ORR_PPzPP: - // [[fallthrough]]; - // case Opcode::AArch64_SMULH_ZPmZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_SMULH_ZPmZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_SMULH_ZPmZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_SEL_ZPZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_SEL_ZPZZ_S: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_FRINTPDr: - // [[fallthrough]]; - // case Opcode::AArch64_FRINTPSr: - // [[fallthrough]]; - // case Opcode::AArch64_FDUP_ZI_D: - // [[fallthrough]]; - // case Opcode::AArch64_FDUP_ZI_S: - // [[fallthrough]]; - // case Opcode::AArch64_PUNPKHI_PP: - // [[fallthrough]]; - // case Opcode::AArch64_PUNPKLO_PP: - // [[fallthrough]]; - // case Opcode::AArch64_RDVLI_XI: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_INCB_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_INCD_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_INCH_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_INCW_XPiI: { - // // lacking access specifiers for destination - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // if (operandStr.length() < 4) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - // operands[1].ext = AARCH64_EXT_INVALID; - // operands[1].vector_index = -1; - // } - // break; - // } - // case Opcode::AArch64_INCD_ZPiI: - // [[fallthrough]]; - // case Opcode::AArch64_INCH_ZPiI: - // [[fallthrough]]; - // case Opcode::AArch64_INCW_ZPiI: { - // // lacking access specifiers for destination - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // if (operandStr.length() < 6) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - // operands[1].ext = AARCH64_EXT_INVALID; - // operands[1].vector_index = -1; - // } - // break; - // } - // case Opcode::AArch64_INCP_XP_B: - // [[fallthrough]]; - // case Opcode::AArch64_INCP_XP_D: - // [[fallthrough]]; - // case Opcode::AArch64_INCP_XP_H: - // [[fallthrough]]; - // case Opcode::AArch64_INCP_XP_S: - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1i32: - // [[fallthrough]]; - // case Opcode::AArch64_LD1i64: - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_GLD1W_D_SCALED_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_GLD1W_SXTW_REAL: { - // // Access types are not set correctly - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_GLD1D_SCALED_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_GLD1D_REAL: { - // // LD1D gather instruction doesn't correctly identify destination - // // register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - // operands[0].reg = static_cast(reg_enum); - - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // LD1D gather instruction doesn't correctly identify memory - // operands operands[2].type = AARCH64_OP_MEM; operands[2].access = - // CS_AC_READ; - - // // LD1D doesn't correctly identify vector memory register correctly - // uint16_t vec_enum = AARCH64_REG_Z0; - // std::string tmp_str(operandStr.substr(operandStr.find("["))); - // // Single or double digit Z register identifier - // if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { - // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); - // } else { - // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); - // } - // operands[2].mem.index = static_cast(vec_enum); - // break; - // } - // case Opcode::AArch64_LD1RQ_W: - // [[fallthrough]]; - // case Opcode::AArch64_LD1RQ_W_IMM: { - // // LD1RQW doesn't identify correct access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_LD1RQ_D_IMM: { - // // LD1RQ gather instruction doesn't correctly identify destination - // // register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - // operands[0].reg = static_cast(reg_enum); - - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // LD1RQ gather instruction doesn't correctly identify memory - // operands operands[2].type = AARCH64_OP_MEM; operands[2].access = - // CS_AC_READ; break; - // } - // case Opcode::AArch64_GLD1SW_D_IMM_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_GLD1D_IMM_REAL: { - // // LD1D gather instruction doesn't correctly identify destination - // // register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // LD1D gather instruction doesn't correctly identify second Z reg - // as - // // memory operand - // operands[2].type = AARCH64_OP_MEM; - // operands[2].access = CS_AC_READ; - // // LD1D gather instruction doesn't recognise memory-offset - // immediate - // // correctly - // if (operandStr[operandStr.length() - 3] != '.') { - // int64_t startPos = operandStr.find('#') + 1; - // int64_t immSize = (operandStr.length() - 1) - startPos; - // if (immSize == 1) { - // operands[2].mem.disp = - // std::stoi(operandStr.substr(startPos, immSize)); - // } else { - // // double or triple digit immediates are converted to hex, and - // so - // // require a different conversion to uint - // operands[2].mem.disp = - // std::stoul(operandStr.substr(startPos, immSize), nullptr, - // 16); - // } - // } - // break; - // } - // case Opcode::AArch64_LD1B: - // [[fallthrough]]; - // case Opcode::AArch64_LD1D: - // [[fallthrough]]; - // case Opcode::AArch64_LD1B_IMM_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_LD1D_IMM_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_LD1RD_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_LD1RW_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_LD1H: - // [[fallthrough]]; - // case Opcode::AArch64_LD1W: - // [[fallthrough]]; - // case Opcode::AArch64_LD1W_IMM_REAL: { - // // LD1RW doesn't correctly identify destination register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_LD1Rv4s: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv1d: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv2d: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv2s: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv8b: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv16b: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv8h: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv4h: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1Rv4h_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv8h_POST: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ | CS_AC_WRITE; - // // Fix for exclusion of post_index immediate in disassembly - // operandCount = 3; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // // For vector arrangement of 16-bit, post_index immediate is 2 - // operands[2].imm = 2; - // break; - // case Opcode::AArch64_LD1Rv1d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv2d_POST: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ | CS_AC_WRITE; - // // Fix for exclusion of post_index immediate in disassembly - // operandCount = 3; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // // For vector arrangement of 64-bit, post_index immediate is 8 - // operands[2].imm = 8; - // break; - // case Opcode::AArch64_LD1Rv16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv8b_POST: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ | CS_AC_WRITE; - - // // Fix for exclusion of post_index immediate in disassembly - // operandCount = 3; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // // For vector arrangement of 8-bit, post_index immediate is 1 - // operands[2].imm = 1; - // break; - // case Opcode::AArch64_LD1Rv2s_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Rv4s_POST: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ | CS_AC_WRITE; - - // // Fix for exclusion of post_index immediate in disassembly - // operandCount = 3; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // // For vector arrangement of 32-bit, post_index immediate is 4 - // operands[2].imm = 4; - // break; - // case Opcode::AArch64_LD1Fourv16b: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Fourv4s: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Fourv2d: - // // Fix incorrect access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_WRITE; - // operands[2].access = CS_AC_WRITE; - // operands[3].access = CS_AC_WRITE; - // operands[4].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1Fourv16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Fourv2d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Fourv4s_POST: - // // Fix incorrect access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_WRITE; - // operands[2].access = CS_AC_WRITE; - // operands[3].access = CS_AC_WRITE; - // operands[4].access = CS_AC_READ | CS_AC_WRITE; - // operands[5].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1Onev16b: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1Onev16b_POST: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ | CS_AC_WRITE; - // break; - // case Opcode::AArch64_LD1Twov16b: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Twov4s: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Twov2d: - // // Fix incorrect access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_WRITE; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1Twov16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Twov2d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_LD1Twov4s_POST: - // // Fix incorrect access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_WRITE; - // operands[2].access = CS_AC_READ | CS_AC_WRITE; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LDADDLW: - // [[fallthrough]]; - // case Opcode::AArch64_LDADDW: - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_LD2Twov4s_POST: - // // Post offset register is not put as mem.index - // if (operands[3].type == AARCH64_OP_REG) { - // operands[2].mem.index = operands[3].reg; - // operands[3].type = AARCH64_OP_INVALID; - // } - // break; - case Opcode::AArch64_FCVTNv4i32: - // Wrong access type for destinatio operand + case Opcode::AArch64_FCVTNv4i32: // Example bytecode - 0168614e + // Wrong access type for destination operand operands[0].access = CS_AC_WRITE; break; case Opcode::AArch64_CPY_ZPzI_B: case Opcode::AArch64_CPY_ZPzI_D: - case Opcode::AArch64_CPY_ZPzI_H: + case Opcode::AArch64_CPY_ZPzI_H: // Example bytecode - 01215005 case Opcode::AArch64_CPY_ZPzI_S: { // Imm value not correctly set std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); auto value = std::stoi(tmpOpStr, 0, 16); + // Ensure #imm is kept within the spec defined limits operands[2].imm = tmpOpStr.length() == 4 ? static_cast(value) : static_cast(value); break; } - - // case Opcode::AArch64_LDR_PXI: - // [[fallthrough]]; - // case Opcode::AArch64_LDR_ZXI: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LSL_ZZI_S: - // // No defined access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // // No instruction id assigned - // id = AARCH64_INS_LSL; - // break; - // case Opcode::AArch64_LD2D: - // case Opcode::AArch64_LD2D_IMM: { - // // LD2D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - - // 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_WRITE; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_WRITE; - - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_LD3D_IMM: { - // // LD3D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - // uint16_t reg_enum2 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d, znn.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - - // 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest2 - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); - // } else { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_WRITE; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_WRITE; - // operands[2].reg = static_cast(reg_enum2); - // operands[2].access = CS_AC_WRITE; - - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_LD4D_IMM: { - // // LD4D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - // uint16_t reg_enum2 = AARCH64_REG_Z0; - // uint16_t reg_enum3 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d, znn.d, zmm.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - - // 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest2 - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum2 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest3 - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum3 += std::stoi(tmpOpStr.substr(1, 1)); - // } else { - // reg_enum3 += std::stoi(tmpOpStr.substr(1, 2)); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_WRITE; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_WRITE; - // operands[2].reg = static_cast(reg_enum2); - // operands[2].access = CS_AC_WRITE; - // operands[3].reg = static_cast(reg_enum3); - // operands[3].access = CS_AC_WRITE; - - // operands[4].access = CS_AC_READ; - // operands[5].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_MOVNWi: - // [[fallthrough]]; - // case Opcode::AArch64_MOVNXi: - // [[fallthrough]]; - // case Opcode::AArch64_MOVZWi: - // [[fallthrough]]; - // case Opcode::AArch64_MOVZXi: - // // MOVZ incorrectly flags destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_MOVPRFX_ZZ: - // // Assign operand access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_MRS: - // // MRS incorrectly flags source/destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // MRS incorrectly tags AARCH64_OP_REG_MRS as AARCH64_OP_SYS - // operands[1].type = AARCH64_OP_REG_MRS; - // break; - // case Opcode::AArch64_MSR: - // // MSR incorrectly flags source/destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // // MSR incorrectly tags AARCH64_OP_REG_MSR as AARCH64_OP_SYS - // operands[0].type = AARCH64_OP_REG_MSR; - // break; - // case Opcode::AArch64_PTEST_PP: { - // // PTEST doesn't label access types for operands - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // // Doesn't identify implicit NZCV destination - // implicitDestinationCount = 1; - // implicitDestinations[0] = AARCH64_REG_NZCV; - // break; - // } - // case Opcode::AArch64_PTRUE_B: - // [[fallthrough]]; - // case Opcode::AArch64_PTRUE_H: - // [[fallthrough]]; - // case Opcode::AArch64_PTRUE_D: - // [[fallthrough]]; - // case Opcode::AArch64_PTRUE_S: - // // PTRUE doesn't label access - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_RET: - // // If no register supplied to RET, default to x30 (LR) - // if (operandCount == 0) { - // operandCount = 1; - // operands[0].type = AARCH64_OP_REG; - // operands[0].reg = AARCH64_REG_LR; - // operands[0].access = CS_AC_READ; - // } - // groupCount = 1; - // groups[0] = CS_GRP_JUMP; - // break; - // case Opcode::AArch64_REV_ZZ_B: - // [[fallthrough]]; - // case Opcode::AArch64_REV_ZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_REV_ZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_REV_ZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_B: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_D: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_H: - // [[fallthrough]]; - // case Opcode::AArch64_REV_PP_S: { - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_SST1B_D_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_SST1D_REAL: - // [[fallthrough]]; - // case Opcode::AArch64_SST1D_SCALED_SCALED_REAL: { - // // ST1W doesn't correctly identify first source register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // // SST1D{_SCALED} gather instruction doesn't correctly identify - // memory - // // operands - // operands[2].type = AARCH64_OP_MEM; - // operands[2].access = CS_AC_READ; - - // // ST1D doesn't correctly identify vector memory register correctly - // uint16_t vec_enum = AARCH64_REG_Z0; - // std::string tmp_str(operandStr.substr(operandStr.find("["))); - // // Single or double digit Z register identifier - // if (tmp_str.substr(tmp_str.find("z"))[2] == '.') { - // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 1)); - // } else { - // vec_enum += std::stoi(tmp_str.substr(tmp_str.find("z") + 1, 2)); - // } - // operands[2].mem.index = static_cast(vec_enum); - // break; - // } - // case Opcode::AArch64_ST2D_IMM: { - // // ST2D doesn't correctly identify destination registers - // uint16_t reg_enum0 = AARCH64_REG_Z0; - // uint16_t reg_enum1 = AARCH64_REG_Z0; - - // // tmpOpStr = "zxx.d, zyy.d" - // std::string tmpOpStr(operandStr.substr(1, operandStr.find("}") - - // 1)); - // // get dest0, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum0 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - // // get dest1, then remove from string - // // Single or double digit Z register identifier - // if (tmpOpStr[2] == '.') { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 1)); - // tmpOpStr.erase(0, 6); - // } else { - // reg_enum1 += std::stoi(tmpOpStr.substr(1, 2)); - // tmpOpStr.erase(0, 7); - // } - - // operands[0].reg = static_cast(reg_enum0); - // operands[0].access = CS_AC_READ; - // operands[1].reg = static_cast(reg_enum1); - // operands[1].access = CS_AC_READ; - - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_ST1B: - // [[fallthrough]]; - // case Opcode::AArch64_ST1D: - // [[fallthrough]]; - // case Opcode::AArch64_ST1B_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_ST1D_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_ST1W_IMM: { - // // ST1W doesn't correctly identify first source register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_ST1W: - // [[fallthrough]]; - // case Opcode::AArch64_ST1W_D: { - // // ST1W doesn't correctly identify first source register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_SST1D_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_SST1W_D_IMM: - // [[fallthrough]]; - // case Opcode::AArch64_SST1W_IMM: { - // // ST1W scatter instruction doesn't correctly identify first source - // // register - // uint16_t reg_enum = AARCH64_REG_Z0; - // // Single or double digit Z register identifier - // if (operandStr[3] == '.') { - // reg_enum += std::stoi(operandStr.substr(2, 1)); - // } else { - // reg_enum += std::stoi(operandStr.substr(2, 2)); - // } - - // operands[0].reg = static_cast(reg_enum); - // // No defined access types - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // // ST1W scatter instruction doesn't correctly identify second Z reg - // as - // // memory operand - // operands[2].type = AARCH64_OP_MEM; - // operands[2].access = CS_AC_READ; - // // ST1W scatter instruction doesn't recognise memory-offset - // immediate - // // correctly - // if (operandStr[operandStr.length() - 3] != '.') { - // int64_t startPos = operandStr.find('#') + 1; - // int64_t immSize = (operandStr.length() - 1) - startPos; - // if (immSize == 1) { - // operands[2].mem.disp = - // std::stoi(operandStr.substr(startPos, immSize)); - // } else { - // // double or triple digit immediates are converted to hex, and - // so - // // require a different conversion to uint - // operands[2].mem.disp = - // std::stoul(operandStr.substr(startPos, immSize), nullptr, - // 16); - // } - // } - // break; - // } - // case Opcode::AArch64_ST1i8_POST: - // case Opcode::AArch64_ST1i16_POST: - // case Opcode::AArch64_ST1i32_POST: - // case Opcode::AArch64_ST1i64_POST: - // // Post offset register is not put as mem.index - // if (operands[2].type == AARCH64_OP_REG) { - // operands[1].mem.index = operands[2].reg; - // operands[2].type = AARCH64_OP_INVALID; - // } - // break; - // case Opcode::AArch64_ST1i16_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1i32_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1i64_POST: - // // fixing incorrect access type for register offset - // if (operandCount == 3) { - // operands[2].access = CS_AC_READ; - // } - // break; - // case Opcode::AArch64_ST1Fourv16b: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv2d: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv4s: - // // ST1 incorrectly flags read and write - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // break; - // case Opcode::AArch64_ST1Fourv16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv2d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv2s_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Fourv4s_POST: - // // ST1 incorrectly flags read and write - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ | CS_AC_WRITE; - // operands[5].access = CS_AC_READ; - // // determine correct type for operand 5 - // if (operandStr.find("#") != std::string::npos) { - // operands[5].type = AARCH64_OP_IMM; - // } else { - // operands[5].type = AARCH64_OP_REG; - // } - // break; - // case Opcode::AArch64_ST1Twov16b: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov2d: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov4s: - // // ST1 incorrectly flags read and write - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_ST1Twov16b_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov2d_POST: - // [[fallthrough]]; - // case Opcode::AArch64_ST1Twov4s_POST: - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ | CS_AC_WRITE; - // operands[3].access = CS_AC_READ; - // // determine correct type for operand 3 - // if (operandStr.find("#") != std::string::npos) { - // operands[3].type = AARCH64_OP_IMM; - // } else { - // operands[3].type = AARCH64_OP_REG; - // } - // break; - // case Opcode::AArch64_ST2Twov4s_POST: - // // ST2 post incorrectly flags read and write - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ | CS_AC_WRITE; - // // Another incorrect access flag for register offset operand - // if (operandCount == 4) { - // operands[3].access = CS_AC_READ; - // } - // break; - // case Opcode::AArch64_STRBui: - // [[fallthrough]]; - // case Opcode::AArch64_STRDui: - // [[fallthrough]]; - // case Opcode::AArch64_STRHui: - // [[fallthrough]]; - // case Opcode::AArch64_STRQui: - // [[fallthrough]]; - // case Opcode::AArch64_STRSui: - // [[fallthrough]]; - // case Opcode::AArch64_STRWui: - // [[fallthrough]]; - // case Opcode::AArch64_STRXui: - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_PFALSE: - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_STR_PXI: - // [[fallthrough]]; - // case Opcode::AArch64_STR_ZXI: - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_SBFMWri: - // [[fallthrough]]; - // case Opcode::AArch64_SBFMXri: - // // SBFM incorrectly flags destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_SVC: - // // SVC is incorrectly marked as setting x30 - // implicitDestinationCount = 0; - // break; - // case Opcode::AArch64_SYSxt: - // // No defined metadata.id for SYS instructions - // id = AARCH64_INS_SYS; - // break; - // case Opcode::AArch64_PSEL_PPPRI_B: - // [[fallthrough]]; - // case Opcode::AArch64_PSEL_PPPRI_D: - // [[fallthrough]]; - // case Opcode::AArch64_PSEL_PPPRI_H: - // [[fallthrough]]; - // case Opcode::AArch64_PSEL_PPPRI_S: - // // Add correct access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_UBFMWri: - // [[fallthrough]]; - // case Opcode::AArch64_UBFMXri: - // // UBFM incorrectly flags destination as READ | WRITE - // operands[0].access = CS_AC_WRITE; - // break; - // case Opcode::AArch64_UQDECB_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECB_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECD_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECD_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECH_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECH_XPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECW_WPiI: - // [[fallthrough]]; - // case Opcode::AArch64_UQDECW_XPiI: - // // UQDEC lacks access types - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // if (operandCount == 1) { - // operandCount = 2; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].imm = 1; - // } - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_UUNPKHI_ZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKHI_ZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKHI_ZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKLO_ZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKLO_ZZ_H: - // [[fallthrough]]; - // case Opcode::AArch64_UUNPKLO_ZZ_S: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_WHILELT_PXX_B: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELT_PXX_D: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELT_PXX_H: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELT_PXX_S: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_B: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_D: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_H: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PWW_S: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_B: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_D: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_H: - // [[fallthrough]]; - // case Opcode::AArch64_WHILELO_PXX_S: - // // WHILELO doesn't label access or vector specifiers - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // // Doesn't identify implicit NZCV destination - // implicitDestinationCount = 1; - // implicitDestinations[0] = AARCH64_REG_NZCV; - // break; - // case Opcode::AArch64_XTNv16i8: - // case Opcode::AArch64_XTNv4i32: - // case Opcode::AArch64_XTNv8i16: - // // XTN2 incorrectly flags destination as only WRITE - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // break; - // case Opcode::AArch64_ZIP1_PPP_B: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_PPP_D: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_PPP_H: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_PPP_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP1_ZZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_B: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_D: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_H: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_PPP_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_ZZZ_S: - // [[fallthrough]]; - // case Opcode::AArch64_ZIP2_ZZZ_D: - // // ZIP lacks access types - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_SXTW_ZPmZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FCVT_ZPmZ_DtoS: - // [[fallthrough]]; - // case Opcode::AArch64_FCVT_ZPmZ_StoD: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_DtoS: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_StoD: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_StoS: - // [[fallthrough]]; - // case Opcode::AArch64_SCVTF_ZPmZ_DtoD: - // // Need to see if Destination vector elements are active - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8One: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8One: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8Two: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8Two: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8Three: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8Three: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // break; - // case Opcode::AArch64_TBLv8i8Four: - // [[fallthrough]]; - // case Opcode::AArch64_TBLv16i8Four: - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // operands[5].access = CS_AC_READ; - // break; - // case Opcode::AArch64_LD1_MXIPXX_H_D: - // [[fallthrough]]; - // case Opcode::AArch64_LD1_MXIPXX_V_D: - // [[fallthrough]]; - // case Opcode::AArch64_LD1_MXIPXX_V_S: - // [[fallthrough]]; - // case Opcode::AArch64_LD1_MXIPXX_H_S: { - // // Lacking access specifiers - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_ST1_MXIPXX_H_D: - // [[fallthrough]]; - // case Opcode::AArch64_ST1_MXIPXX_V_D: - // [[fallthrough]]; - // case Opcode::AArch64_ST1_MXIPXX_H_S: - // [[fallthrough]]; - // case Opcode::AArch64_ST1_MXIPXX_V_S: - // // Access types are not defined - // operands[0].access = CS_AC_READ; - // operands[1].access = CS_AC_READ; - // break; - // case Opcode::AArch64_FMOPA_MPPZZ_D: - // [[fallthrough]]; - // case Opcode::AArch64_FMOPA_MPPZZ_S: { - // // Need to add access specifiers - // // although operands[0] should be READ | WRITE, due to the - // implemented - // // decode logic for SME tile destinations, the register will be - // added as - // // both source and destination with just WRITE access. - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].access = CS_AC_READ; - // operands[4].access = CS_AC_READ; - // operands[5].access = CS_AC_READ; - // break; - // } - // case Opcode::AArch64_EXTRACT_ZPMXI_H_B: { - // operandCount = 4; - // operands[0].access = CS_AC_READ | CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3].reg = operands[2].sme_index.base; - // operands[3].access = CS_AC_READ; - // break; - // } case Opcode::AArch64_ZERO_M: { // Operands often mangled from ZA tile overlap aliasing in decode. // Need to re-extract relevant tiles from operandStr @@ -1825,10 +243,6 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) break; } } - - if (insn.is_alias) { - // revertAliasing(); - } } InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, @@ -1847,839 +261,6 @@ InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, operandStr[0] = '\0'; } -void InstructionMetadata::revertAliasing() { - // // Check mnemonics known to be aliases and see if their opcode matches - // // something else - // switch (id) { - // case AARCH64_INS_ASR: - // if (opcode == Opcode::AArch64_ASRVWr || - // opcode == Opcode::AArch64_ASRVXr) { - // // asr rd, rn, rm; alias for: asrv rd, rn, rm - // return; - // } - // if (opcode == Opcode::AArch64_SBFMWri || - // opcode == Opcode::AArch64_SBFMXri) { - // operandCount = 4; - - // operands[3].type = AARCH64_OP_IMM; - // operands[3].access = CS_AC_READ; - // if (opcode == Opcode::AArch64_SBFMWri) { - // // 32-bit - // operands[3].imm = 31; - // } else { - // operands[3].imm = 63; - // } - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_AT: - // return aliasNYI(); - // case AARCH64_INS_BFI: - // // TODO no tests of alias - // if (opcode == Opcode::AArch64_BFMWri) { - // // bfi wd, wn, #lsb, #width; alias for - // // bfm wd, wn, #(-lsb MOD 32), #(width - 1) - // operands[2].imm = static_cast(-operands[2].imm) % 32; - // operands[3].imm = operands[3].imm - 1; - // return; - // } - // if (opcode == Opcode::AArch64_BFMXri) { - // // bfi xd, xn, #lsb, #width; alias for - // // bfm xd, xn, #(-lsb MOD 64), #(width - 1) - // operands[2].imm = static_cast(-operands[2].imm) % 64; - // operands[3].imm = operands[3].imm - 1; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_BFXIL: - // // TODO no tests for alias - // if (opcode == Opcode::AArch64_BFMWri || - // opcode == Opcode::AArch64_BFMXri) { - // // bfxil rd, rn, #lsb, #width; alias for - // // bfm rd, rn, #lsb, #(lsb + width - 1) - // operands[3].imm = operands[2].imm + operands[3].imm - 1; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_CINC: - // if (opcode == Opcode::AArch64_CSINCWr || - // opcode == Opcode::AArch64_CSINCXr) { - // // cinc rd, rn, cc; alias for: csinc rd, rn, rn, invert(cc) - // operandCount = 3; - - // operands[2].type = AARCH64_OP_REG; - // operands[2].access = CS_AC_READ; - // operands[2].reg = operands[1].reg; - - // cc ^= 1; // invert lowest bit to negate cc - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_CINV: - // return aliasNYI(); - // case AARCH64_INS_CMN: - // // cmn , alias for adds - // operandCount = 3; - // operands[2] = operands[1]; - // operands[1] = operands[0]; - // operands[1].access = CS_AC_READ; - - // operands[0].type = AARCH64_OP_REG; - // operands[0].access = CS_AC_WRITE; - - // if (opcode == Opcode::AArch64_ADDSXri || - // opcode == Opcode::AArch64_ADDSXrr || - // opcode == Opcode::AArch64_ADDSXrs) { - // // 64-bit version - // operands[0].reg = AARCH64_REG_XZR; - // } else { - // // 32-bit version - // operands[0].reg = AARCH64_REG_WZR; - // } - // return; - // case AARCH64_INS_CMP: - // if (opcode == Opcode::AArch64_SUBSWri || - // opcode == Opcode::AArch64_SUBSWrs || - // opcode == Opcode::AArch64_SUBSWrx || - // opcode == Opcode::AArch64_SUBSXri || - // opcode == Opcode::AArch64_SUBSXrs || - // opcode == Opcode::AArch64_SUBSXrx || - // opcode == Opcode::AArch64_SUBSXrx64) { - // operandCount = 3; - // operands[2] = operands[1]; - - // operands[1] = operands[0]; - // operands[1].access = CS_AC_READ; - - // operands[0].type = AARCH64_OP_REG; - // operands[0].access = CS_AC_WRITE; - - // if (opcode == Opcode::AArch64_SUBSWri || - // opcode == Opcode::AArch64_SUBSWrs || - // opcode == Opcode::AArch64_SUBSWrx) { - // operands[0].reg = AARCH64_REG_WZR; - // } else { - // operands[0].reg = AARCH64_REG_XZR; - // } - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_CNEG: - // if (opcode == Opcode::AArch64_CSNEGWr || - // opcode == Opcode::AArch64_CSNEGXr) { - // // cneg rd, rn, cc; alias for: csneg rd, rn, rn, invert(cc) - // operandCount = 3; - // operands[2] = operands[1]; - // cc ^= 1; // invert lowest bit to negate cc - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_CSET: - // // TODO no usage in regression tests - // if (opcode == Opcode::AArch64_CSINCWr || - // opcode == Opcode::AArch64_CSINCXr) { - // // cset rd, cc; alias for: csinc rd, zr, zr, invert(cc) - // operandCount = 3; - - // operands[1].type = AARCH64_OP_REG; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - - // operands[2].type = AARCH64_OP_REG; - // operands[2].access = CS_AC_READ; - // operands[2].shift = {AARCH64_SFT_INVALID, 0}; - - // if (opcode == Opcode::AArch64_CSINCWr) { - // operands[1].reg = AARCH64_REG_WZR; - // operands[2].reg = AARCH64_REG_WZR; - // } else { - // operands[1].reg = AARCH64_REG_XZR; - // operands[2].reg = AARCH64_REG_XZR; - // } - - // cc ^= 1; // invert lowest bit to negate cc - - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_CSETM: - // if (opcode == Opcode::AArch64_CSINVWr || - // opcode == Opcode::AArch64_CSINVXr) { - // // csetm rd, cc; alias for: csinv rd, zr, zr, invert(cc) - // operandCount = 3; - - // operands[1].type = AARCH64_OP_REG; - // operands[1].access = CS_AC_READ; - - // operands[2].type = AARCH64_OP_REG; - // operands[2].access = CS_AC_READ; - - // if (opcode == Opcode::AArch64_CSINVWr) { - // operands[1].reg = AARCH64_REG_WZR; - // operands[2].reg = AARCH64_REG_WZR; - // } else { - // operands[1].reg = AARCH64_REG_XZR; - // operands[2].reg = AARCH64_REG_XZR; - // } - - // cc ^= 1; // invert lowest bit to negate cc - - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_DC: - // return aliasNYI(); - // case AARCH64_INS_IC: - // return aliasNYI(); - // case AARCH64_INS_LSL: - // // TODO no usage in regression tests - // if (opcode == Opcode::AArch64_UBFMWri || - // opcode == Opcode::AArch64_UBFMXri) { - // // lsl rd, rn, #shift; alias for: - // // ubfm rd, rn, #(-shift MOD <32|64>), #(<31|63> - shift) - // operandCount = 4; - // uint8_t highestBit = 63; - // if (opcode == Opcode::AArch64_UBFMWri) { - // highestBit = 31; - // } - - // auto shift = operands[2].imm; - // operands[2].imm = (-shift) & highestBit; - // operands[3].type = AARCH64_OP_IMM; - // operands[3].imm = highestBit - shift; - // operands[3].access = CS_AC_READ; - // return; - // } - // if (opcode == Opcode::AArch64_LSLVWr || - // opcode == Opcode::AArch64_LSLVXr || - // opcode == Opcode::AArch64_LSL_ZZI_S) { - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_LSR: - // if (opcode == Opcode::AArch64_LSRVWr || - // opcode == Opcode::AArch64_LSRVXr) { - // // lsr rd, rn, rm; alias for lsrv rd, rn, rm - // return; - // } - // if (opcode == Opcode::AArch64_UBFMWri || - // opcode == Opcode::AArch64_UBFMXri) { - // // lsr rd, rn, #amount; alias for ubfm rd, rn, #amount, #<31|63> - // operandCount = 4; - - // operands[3].type = AARCH64_OP_IMM; - // operands[3].access = CS_AC_READ; - - // if (opcode == Opcode::AArch64_UBFMWri) { - // operands[3].imm = 31; - // } else { - // operands[3].imm = 63; - // } - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_MNEG: - // // TODO no test - // if (opcode == Opcode::AArch64_MSUBXrrr) { - // // mneg xd, xn, xm; alias for msub xd, xn, xm, xzr - // operandCount = 4; - // operands[3].type = AARCH64_OP_REG; - // operands[3].access = CS_AC_READ; - // operands[3].reg = AARCH64_REG_XZR; - // return; - // } - // if (opcode == Opcode::AArch64_MSUBWrrr) { - // // mneg wd, wn, wm; alias for msub wd, wn, wm, wzr - // operandCount = 4; - // operands[3].type = AARCH64_OP_REG; - // operands[3].access = CS_AC_READ; - // operands[3].reg = AARCH64_REG_WZR; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_MOV: - // // TODO no specific tests - // if (opcode == Opcode::AArch64_AND_PPzPP) { - // // mov pd.b, pg/z, pn.b; alias for: and pd.b, pg/z, pn.b, pn.b - // operandCount = 4; - // operands[3] = operands[2]; - // return; - // } - // if (opcode == Opcode::AArch64_ADDXri || - // opcode == Opcode::AArch64_ADDWri) { - // // mov to/from sp; alias for: add , , #0 - // operandCount = 3; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].imm = 0; - // operands[2].access = CS_AC_READ; - // operands[2].shift.type = AARCH64_SFT_INVALID; - // operands[2].vas = AARCH64_VAS_INVALID; - // operands[2].vector_index = -1; - // return; - // } - // if (opcode == Opcode::AArch64_DUPi8 || opcode == - // Opcode::AArch64_DUPi16 - // || - // opcode == Opcode::AArch64_DUPi32 || - // opcode == Opcode::AArch64_DUPi64) { - // // mov vd, Vn.T[index]; alias of dup vd, Vn.T[index] - // return; - // } - // if (opcode == Opcode ::AArch64_CPY_ZPzI_B || - // opcode == Opcode ::AArch64_CPY_ZPzI_D || - // opcode == Opcode ::AArch64_CPY_ZPzI_H || - // opcode == Opcode ::AArch64_CPY_ZPzI_S) { - // // mov zd.T, pg/z, #imm{, shift}; alias of cpy zd.T, pg/z, #imm{, - // // shift} - // operandCount = 3; - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - - // // get imm value - // std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); - // auto value = std::stoi(tmpOpStr, 0, 16); - // operands[2].imm = tmpOpStr.length() == 4 ? - // static_cast(value) - // : - // static_cast(value); - // return; - // } - // if (opcode == Opcode::AArch64_DUPM_ZI || - // opcode == Opcode::AArch64_DUP_ZI_B || - // opcode == Opcode::AArch64_DUP_ZI_D || - // opcode == Opcode::AArch64_DUP_ZI_H || - // opcode == Opcode::AArch64_DUP_ZI_S) { - // // mov Zd.T, #imm; alias for dupm Zd.T, #imm - // // or - // // mov Zd.T, #imm{, shift}; alias for dup Zd.T, #imm{, shift} - // operandCount = 2; - // operands[0].access = CS_AC_WRITE; - // operands[1].type = AARCH64_OP_IMM; - // operands[1].access = CS_AC_READ; - - // uint8_t start = operandStr[6] == '#' ? 7 : 8; - - // if (opcode == Opcode::AArch64_DUPM_ZI) { - // char specifier = operandStr[start - 4]; - // switch (specifier) { - // case 'b': - // operands[0].vas = AARCH64_VAS_1B; - // break; - // case 'h': - // operands[0].vas = AARCH64_VAS_1H; - // break; - // case 's': - // operands[0].vas = AARCH64_VAS_1S; - // break; - // case 'd': - // operands[0].vas = AARCH64_VAS_1D; - // break; - - // default: - // break; - // } - // } - - // bool hex = false; - // if (operandStr[start + 1] == 'x') { - // hex = true; - // start += 2; - // } - - // uint8_t end = start + 1; - // while (true) { - // if (operandStr[end] < '0') { - // break; - // } - // end++; - // } - - // std::string sub = operandStr.substr(start, end); - // if (hex) { - // operands[1].imm = std::stoul(sub, 0, 16); - // } else { - // operands[1].imm = stoi(sub); - // } - - // return; - // } - // if (opcode == Opcode::AArch64_DUP_ZR_S || - // opcode == Opcode::AArch64_DUP_ZR_D || - // opcode == Opcode::AArch64_DUP_ZR_B || - // opcode == Opcode::AArch64_DUP_ZR_H) { - // // mov Zd.T, ; alias for dup Zd.T, - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - - // char specifier = operandStr[operandStr.find(".") + 1]; - // switch (specifier) { - // case 'b': - // operands[0].vas = AARCH64_VAS_1B; - // break; - // case 'h': - // operands[0].vas = AARCH64_VAS_1H; - // break; - // case 's': - // operands[0].vas = AARCH64_VAS_1S; - // break; - // case 'd': - // operands[0].vas = AARCH64_VAS_1D; - // break; - - // default: - // break; - // } - // return; - // } - // if (opcode == Opcode::AArch64_DUP_ZZI_S || - // opcode == Opcode::AArch64_DUP_ZZI_D || - // opcode == Opcode::AArch64_DUP_ZZI_Q) { - // // mov Zd.T, Vn; alias for dup Zd.T, Zn.T[0] - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - - // uint8_t start = operandStr[2] == '.' ? 7 : 8; - // uint8_t end = operandStr.length() - start; - - // operands[1].reg = static_cast( - // AARCH64_REG_Z0 + stoi(operandStr.substr(start, end))); - // operands[1].vector_index = 0; - // return; - // } - // if (opcode == Opcode::AArch64_INSvi32lane || - // opcode == Opcode::AArch64_INSvi64lane) { - // // mov vd.T[index1], vn.T[index2]; alias for ins vd.T[index1], - // // vn.T[index2] - // return; - // } - // if (opcode == Opcode::AArch64_ORRv8i8) { - // // mov vd, vn; alias for orr vd.t, vn.t, vn.t - // operandCount = 3; - - // operands[2] = operands[1]; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // return; - // } - // if (opcode >= Opcode::AArch64_EXTRACT_ZPMXI_H_B && - // opcode <= Opcode::AArch64_EXTRACT_ZPMXI_V_S) { - // return; - // } - // if (opcode == Opcode::AArch64_ORRWri || - // opcode == Opcode::AArch64_ORRWrs || - // opcode == Opcode::AArch64_ORRXri || - // opcode == Opcode::AArch64_ORRXrs) { - // // mov rd, rn; alias for: orr rd, zr, rn - // operandCount = 3; - // operands[2] = operands[1]; - - // operands[1].type = AARCH64_OP_REG; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - // if (opcode == Opcode::AArch64_ORRWri || - // opcode == Opcode::AArch64_ORRWrs) { - // operands[1].reg = AARCH64_REG_WZR; - // } else { - // operands[1].reg = AARCH64_REG_XZR; - // } - // return; - // } - // if (opcode == Opcode::AArch64_ORR_PPzPP) { - // // mov Pd.b, Pn.b; alias for: orr Pd.b, Pn/z, Pn.b, Pn.b - // operandCount = 4; - // operands[0].access = CS_AC_WRITE; - // operands[0].vas = AARCH64_VAS_1B; - // operands[1].access = CS_AC_READ; - // operands[1].vas = AARCH64_VAS_1B; - // operands[2] = operands[1]; - // operands[3] = operands[1]; - // return; - // } - // if (opcode == Opcode::AArch64_ORR_ZZZ) { - // // mov Zd.d, Zn.d; alias for: orr Zd.d, Zn.d, Zn.d - // operandCount = 3; - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2] = operands[1]; - // return; - // } - // if (opcode == Opcode::AArch64_ORRv16i8) { - // // mov Vd.16b, Vn.16b; alias for: orr Vd.16b, Vn.16b, Vn.16b - // operandCount = 3; - // operands[2] = operands[1]; - // return; - // } - // if (opcode == Opcode::AArch64_SEL_ZPZZ_S || - // opcode == Opcode::AArch64_SEL_ZPZZ_D) { - // // mov Zd.T, Pg/M, Zn.T; alias for: sel Zd.T, Pg, Zn.T, Zd.T - // if (mnemonic[0] == 'm') { - // // SEL instructions id sometimes set as AARCH64_INS_MOV even if - // // aliasing hasn't occurred so double check mnemonic is MOV alias - // operandCount = 4; - // operands[3] = operands[0]; - // operands[3].access = CS_AC_READ; - // } - // return; - // } - // if (opcode == Opcode::AArch64_UMOVvi8 || - // opcode == Opcode::AArch64_UMOVvi16 || - // opcode == Opcode::AArch64_UMOVvi32 || - // opcode == Opcode::AArch64_UMOVvi64) { - // // mov rd, Vn.T[index]; alias for umov rd, Vn.T[index] - // return; - // } - // if (opcode == Opcode::AArch64_MOVZWi || - // opcode == Opcode::AArch64_MOVZXi) { - // // mov rd, #0; alias for: movz rd, #0{, shift #0} - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_LSL, 0}; - // return; - // } - // if (opcode == Opcode::AArch64_MOVNWi || - // opcode == Opcode::AArch64_MOVNXi) { - // // mov rd, #amount; alias for: movn rd, #amount{, shift #0} - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_LSL, 0}; - // operands[1].imm = ~(operands[1].imm); - // return; - // } - // if (opcode == Opcode::AArch64_INSvi8gpr || - // opcode == Opcode::AArch64_INSvi16gpr || - // opcode == Opcode::AArch64_INSvi32gpr || - // opcode == Opcode::AArch64_INSvi64gpr) { - // // mov vd.ts[index], rn; alias for: ins vd.ts[index], rn - // return; - // } - // if (opcode == Opcode::AArch64_UMOVvi32_idx0 || - // opcode == Opcode::AArch64_UMOVvi64_idx0) { - // // mov wd, vn.t[0]; alias for: umov wd, vn.t[0] - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_MUL: - // // TODO add comment - // if (opcode == Opcode::AArch64_MADDXrrr || - // opcode == Opcode::AArch64_MADDWrrr) { - // operandCount = 4; - // operands[3].type = AARCH64_OP_REG; - // operands[3].access = CS_AC_READ; - // if (opcode == Opcode::AArch64_MADDWrrr) { - // operands[3].reg = AARCH64_REG_WZR; - // } else { - // operands[3].reg = AARCH64_REG_XZR; - // } - // return; - // } - // if (opcode == Opcode::AArch64_MUL_ZPmZ_B || - // opcode == Opcode::AArch64_MUL_ZPmZ_D || - // opcode == Opcode::AArch64_MUL_ZPmZ_H || - // opcode == Opcode::AArch64_MUL_ZPmZ_S) { - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_MVN: - // if (opcode == Opcode::AArch64_ORNWrs || - // opcode == Opcode::AArch64_ORNXrs) { - // // mvn rd, rn; alias for: orn rd, zr, rn - // operandCount = 3; - // operands[2] = operands[1]; - - // operands[1].type = AARCH64_OP_REG; - // operands[1].access = CS_AC_READ; - // operands[1].shift = {AARCH64_SFT_INVALID, 0}; - // if (opcode == Opcode::AArch64_ORNWrs) { - // operands[1].reg = AARCH64_REG_WZR; - // } else { - // operands[1].reg = AARCH64_REG_XZR; - // } - // return; - // } - // if (opcode == Opcode::AArch64_NOTv16i8 || - // opcode == Opcode::AArch64_NOTv8i8) { - // // TODO needs tests - // // mvn vd.t, vn.t; alias for : not vd.t, vn.t - // // Blank entry was for a legitimate alias, however operands were - // // identical so nothing to alter between the instructions. - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_NEG: - // // TODO needs tests - // if (opcode == Opcode::AArch64_SUBWrs || - // opcode == Opcode::AArch64_SUBXrs) { - // // neg rd, rm{, shift #amount}; alias for: - // // sub rd, zr, rm{, shift #amount} - // operandCount = 3; - // operands[2] = operands[1]; - - // operands[1].type = AARCH64_OP_REG; - // operands[1].access = CS_AC_READ; - - // if (opcode == Opcode::AArch64_SUBWrs) { - // operands[1].reg = AARCH64_REG_WZR; - // } else { - // operands[1].reg = AARCH64_REG_XZR; - // } - // return; - // } - // if (opcode == Opcode::AArch64_NEGv2i64) { - // // No alias present, trying to alias self. - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_NEGS: - // if (opcode == Opcode::AArch64_SUBSWrs || - // opcode == Opcode::AArch64_SUBSXrs) { - // // negs rd, rm{, shift #amount}; alias for: - // // subs rd, zr, rm{, shift #amount} - // operandCount = 3; - // operands[2] = operands[1]; - - // operands[1].type = AARCH64_OP_REG; - // operands[1].access = CS_AC_READ; - - // if (opcode == Opcode::AArch64_SUBWrs) { - // operands[1].reg = AARCH64_REG_WZR; - // } else { - // operands[1].reg = AARCH64_REG_XZR; - // } - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_NGC: - // return aliasNYI(); - // case AARCH64_INS_NGCS: - // return aliasNYI(); - // case AARCH64_INS_NOT: - // if (opcode == Opcode::AArch64_EOR_PPzPP) { - // // not pd.b, pg/z, pn.b; alias for: eor pd.b, pg/z, pn.b, pg.b - // operandCount = 4; - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // operands[2].access = CS_AC_READ; - // operands[3] = operands[1]; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_REV64: - // // rev64 vd.t, vn.t - // if (opcode == Opcode::AArch64_REV64v16i8 || - // opcode == Opcode::AArch64_REV64v2i32 || - // opcode == Opcode::AArch64_REV64v4i16 || - // opcode == Opcode::AArch64_REV64v4i32 || - // opcode == Opcode::AArch64_REV64v8i16 || - // opcode == Opcode::AArch64_REV64v8i8) { - // operandCount = 2; - // operands[0].access = CS_AC_WRITE; - // operands[1].access = CS_AC_READ; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_ROR: - // // TODO needs test - // if (opcode == Opcode::AArch64_RORVWr || - // opcode == Opcode::AArch64_RORVXr) { - // // ror wd, wn, wm; alias for : rorv wd, wn, wm - // // ror xd, xn, xm; alias for : rorv xd, xn, xm - // // Blank entry was for a legitimate alias, however operands were - // // identical so nothing to alter between the instructions. - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_SBFIZ: - // // TODO needs test - // if (opcode == Opcode::AArch64_SBFMWri || - // opcode == Opcode::AArch64_SBFMXri) { - // operands[3].imm -= 1; - - // uint8_t highestBit = 63; - // if (opcode == Opcode::AArch64_SBFMWri) { - // highestBit = 31; - // } - - // operands[2].imm = (-operands[2].imm) & highestBit; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_SBFX: - // // TODO needs test - // if (opcode == Opcode::AArch64_SBFMWri || - // opcode == Opcode::AArch64_SBFMXri) { - // // sbfx rd, rn, #lsb, #width; alias for - // // sbfm rd, rn, #lsb, #(lsb + width - 1) - // operands[3].imm = operands[2].imm + operands[3].imm - 1; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_SMNEGL: - // return aliasNYI(); - // case AARCH64_INS_SMULL: - // if (opcode == Opcode::AArch64_SMADDLrrr) { - // operandCount = 4; - // operands[3].type = AARCH64_OP_REG; - // operands[3].access = CS_AC_READ; - // operands[3].reg = AARCH64_REG_XZR; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_SXTB: - // // sxtb rd, rn; alias for: sbfm rd, rn, #0, #7 - // if (opcode == Opcode::AArch64_SBFMWri || - // opcode == Opcode::AArch64_SBFMXri) { - // operandCount = 4; - - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // operands[2].imm = 0; - - // operands[3].type = AARCH64_OP_IMM; - // operands[3].access = CS_AC_READ; - // operands[3].imm = 7; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_SXTH: - // // sxth rd, rn; alias for: sbfm rd, rn, #0, #15 - // if (opcode == Opcode::AArch64_SBFMWri || - // opcode == Opcode::AArch64_SBFMXri) { - // operandCount = 4; - - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // operands[2].imm = 0; - - // operands[3].type = AARCH64_OP_IMM; - // operands[3].access = CS_AC_READ; - // operands[3].imm = 15; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_SXTW: - // // sxtw rd, rn; alias for: sbfm rd, rn, #0, #31 - // if (opcode == Opcode::AArch64_SBFMXri) { - // operandCount = 4; - - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // operands[2].imm = 0; - - // operands[3].type = AARCH64_OP_IMM; - // operands[3].access = CS_AC_READ; - // operands[3].imm = 31; - // return; - // } - // if (opcode == Opcode::AArch64_SXTW_ZPmZ_D) { - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_SYS: { - // // TODO no test - // // Extract IC/DC/AT/TLBI operation - // if (std::string(mnemonic) == "dc") { - // if (operandStr.substr(0, 3) == "zva") { - // id = AARCH64_INS_DC; - // operandCount = 3; - // operands[1] = operands[0]; - // operands[1].access = CS_AC_READ; - // operands[0].type = AARCH64_OP_SYS; - // operands[0].sys = AARCH64_DC_ZVA; - // operands[2].type = AARCH64_OP_REG_MRS; - // operands[2].access = CS_AC_READ; - // operands[2].imm = AARCH64_SYSREG_DCZID_EL0; - // return; - // } - // } - // return aliasNYI(); - // } - // case AARCH64_INS_TLBI: - // return aliasNYI(); - // case AARCH64_INS_TST: - // // TODO needs test for register case - // if (opcode == Opcode::AArch64_ANDSWrs || - // opcode == Opcode::AArch64_ANDSXrs || - // opcode == Opcode::AArch64_ANDSWri || - // opcode == Opcode::AArch64_ANDSXri) { - // // tst rn, rm; alias for: ands zr, rn, rm - // // tst rn, #imm; alias for: ands zr, rn, #imm - // operandCount = 3; - // operands[2] = operands[1]; - // operands[1] = operands[0]; - // operands[1].access = CS_AC_READ; - - // operands[0].type = AARCH64_OP_REG; - // operands[0].access = CS_AC_WRITE; - // if (opcode == Opcode::AArch64_ANDSWrs || - // opcode == Opcode::AArch64_ANDSWri) { - // operands[0].reg = AARCH64_REG_WZR; - // } else { - // operands[0].reg = AARCH64_REG_XZR; - // } - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_UBFIZ: - // // TODO needs test and comment - // if (opcode == Opcode::AArch64_UBFMWri || - // opcode == Opcode::AArch64_UBFMXri) { - // operands[3].imm -= 1; - - // uint8_t highestBit = 63; - // if (opcode == Opcode::AArch64_UBFMWri) { - // highestBit = 31; - // } - - // operands[2].imm = (-operands[2].imm) & highestBit; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_UBFX: - // // TODO needs test - // if (opcode == Opcode::AArch64_UBFMWri || - // opcode == Opcode::AArch64_UBFMXri) { - // // ubfx rd, rn, #lsb, #width; alias for - // // ubfm rd, rn, #lsb, #(lsb + width - 1) - // operands[3].imm = operands[2].imm + operands[3].imm - 1; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_UMNEGL: - // return aliasNYI(); - // case AARCH64_INS_UMULL: - // // umull xd, wn, wm; alias for: umaddl xd, wn, wm, xzr - // if (opcode == Opcode::AArch64_UMADDLrrr) { - // operandCount = 4; - // operands[3].type = AARCH64_OP_REG; - // operands[3].access = CS_AC_READ; - // operands[3].reg = AARCH64_REG_XZR; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_UXTB: - // // TODO needs test - // // uxtb wd, wn; alias for: ubfm wd, wn, #0, #7 - // if (opcode == Opcode::AArch64_UBFMWri) { - // operandCount = 4; - // operands[2].type = AARCH64_OP_IMM; - // operands[2].access = CS_AC_READ; - // operands[2].imm = 0; - // operands[3].type = AARCH64_OP_IMM; - // operands[3].access = CS_AC_READ; - // operands[3].imm = 7; - // return; - // } - // return aliasNYI(); - // case AARCH64_INS_UXTH: - // return aliasNYI(); - // } -} - -void InstructionMetadata::aliasNYI() { - metadataExceptionEncountered_ = true; - metadataException_ = InstructionException::AliasNotYetImplemented; -} - } // namespace aarch64 } // namespace arch } // namespace simeng \ No newline at end of file diff --git a/src/lib/arch/aarch64/InstructionMetadata.hh b/src/lib/arch/aarch64/InstructionMetadata.hh index 1c4a48048b..b3b241d619 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.hh +++ b/src/lib/arch/aarch64/InstructionMetadata.hh @@ -98,13 +98,6 @@ struct InstructionMetadata { uint8_t operandCount; private: - /** Detect instruction aliases and update metadata to match the de-aliased - * instruction. */ - void revertAliasing(); - - /** Flag the instruction as invalid due to a detected unsupported alias. */ - void aliasNYI(); - /** The current exception state of this instruction. */ InstructionException metadataException_ = InstructionException::None; diff --git a/src/lib/arch/aarch64/Instruction_address.cc b/src/lib/arch/aarch64/Instruction_address.cc index 4034cb9a46..9d4cbfd5fb 100644 --- a/src/lib/arch/aarch64/Instruction_address.cc +++ b/src/lib/arch/aarch64/Instruction_address.cc @@ -1090,7 +1090,7 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1D: { // ld1d {zt.d}, pg/z, [xn, zm.d] + case Opcode::AArch64_GLD1D_REAL: { // ld1d {zt.d}, pg/z, [xn, zm.d] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1110,8 +1110,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1D_SCALED: { // ld1d {zt.d}, pg/z, [xn, - // zm.d, LSL #3] + case Opcode::AArch64_GLD1D_SCALED_REAL: { // ld1d {zt.d}, pg/z, [xn, + // zm.d, LSL #3] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1131,8 +1131,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1D_IMM: { // ld1d {zd.d}, pg/z, [zn.d{, - // #imm}] + case Opcode::AArch64_GLD1D_IMM_REAL: { // ld1d {zd.d}, pg/z, [zn.d{, + // #imm}] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1153,8 +1153,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1SW_D_IMM: { // ld1sw {zd.d}, pg/z, - // [zn.d{, #imm}] + case Opcode::AArch64_GLD1SW_D_IMM_REAL: { // ld1sw {zd.d}, pg/z, + // [zn.d{, #imm}] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1175,8 +1175,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1W_D_SCALED: { // ld1w {zd.d}, pg/z, - // [, zm.d, lsl #2] + case Opcode::AArch64_GLD1W_D_SCALED_REAL: { // ld1w {zd.d}, pg/z, + // [, zm.d, lsl #2] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 64; @@ -1196,8 +1196,8 @@ span Instruction::generateAddresses() { setMemoryAddresses(addresses); break; } - case Opcode::AArch64_GLD1W_SXTW: { // ld1w {zd.s}, pg/z, - // [, zm.s, sxtw] + case Opcode::AArch64_GLD1W_SXTW_REAL: { // ld1w {zd.s}, pg/z, + // [, zm.s, sxtw] const uint64_t* p = sourceValues_[0].getAsVector(); const uint16_t partition_num = VL_bits / 32; diff --git a/src/lib/arch/aarch64/Instruction_execute.cc b/src/lib/arch/aarch64/Instruction_execute.cc index 62527af2b4..20b62904b9 100644 --- a/src/lib/arch/aarch64/Instruction_execute.cc +++ b/src/lib/arch/aarch64/Instruction_execute.cc @@ -2306,8 +2306,8 @@ void Instruction::execute() { sourceValues_, [](float x, float y) -> float { return x - y; }); break; } - case Opcode::AArch64_GLD1D_IMM: { // ld1d {zd.d}, pg/z, [zn.d{, - // #imm}] + case Opcode::AArch64_GLD1D_IMM_REAL: { // ld1d {zd.d}, pg/z, [zn.d{, + // #imm}] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2324,11 +2324,11 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_GLD1D: // ld1d {zt.d}, pg/z, [xn, zm.d] + case Opcode::AArch64_GLD1D_REAL: // ld1d {zt.d}, pg/z, [xn, zm.d] // LOAD [[fallthrough]]; - case Opcode::AArch64_GLD1D_SCALED: { // ld1d {zt.d}, pg/z, [xn, - // zm.d, LSL #3] + case Opcode::AArch64_GLD1D_SCALED_REAL: { // ld1d {zt.d}, pg/z, [xn, + // zm.d, LSL #3] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2347,8 +2347,8 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_GLD1SW_D_IMM: { // ld1sw {zd.d}, pg/z, [zn.d{, - // #imm}] + case Opcode::AArch64_GLD1SW_D_IMM_REAL: { // ld1sw {zd.d}, pg/z, [zn.d{, + // #imm}] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2365,8 +2365,8 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_GLD1W_D_SCALED: { // ld1w {zd.d}, pg/z, - // [, zm.d, lsl #2] + case Opcode::AArch64_GLD1W_D_SCALED_REAL: { // ld1w {zd.d}, pg/z, + // [, zm.d, lsl #2] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); @@ -2383,8 +2383,8 @@ void Instruction::execute() { results_[0] = {out, 256}; break; } - case Opcode::AArch64_GLD1W_SXTW: { // ld1w {zd.s}, pg/z, - // [, zm.s, sxtw] + case Opcode::AArch64_GLD1W_SXTW_REAL: { // ld1w {zd.s}, pg/z, + // [, zm.s, sxtw] // LOAD const uint64_t* p = sourceValues_[0].getAsVector(); From 584b13a5f6ff3319f283f70083fbb0f9b3d2d238 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 5 Sep 2024 12:45:03 +0200 Subject: [PATCH 07/34] Got unit tests to pass. --- .../arch/aarch64/helpers/auxiliaryFunctions.hh | 1 - src/lib/arch/aarch64/InstructionMetadata.cc | 2 +- src/lib/arch/aarch64/Instruction_decode.cc | 14 ++++++++------ test/unit/aarch64/ArchInfoTest.cc | 8 +++++--- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh index c1a74a5fb7..853e46dddd 100644 --- a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh +++ b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh @@ -126,7 +126,6 @@ bitfieldManipulate(T value, T dest, uint8_t rotateBy, uint8_t sourceBits, /** Function to check if NZCV conditions hold. */ inline bool conditionHolds(uint8_t cond, uint8_t nzcv) { // Due to Capstone enum changes, need to add 1 to cond - cond += 1; bool inverse = cond & 1; uint8_t upper = cond >> 1; bool n = (nzcv >> 3) & 1; diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index bd1600959c..b75d70eef8 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -13,7 +13,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) implicitSourceCount(insn.detail->regs_read_count), implicitDestinationCount(insn.detail->regs_write_count), groupCount(insn.detail->groups_count), - cc(insn.detail->aarch64.cc - 1), + cc(insn.detail->aarch64.cc), setsFlags(insn.detail->aarch64.update_flags), isAlias(insn.is_alias), operandCount(insn.detail->aarch64.op_count) { diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 13568a0b3f..48e9f841f0 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -251,14 +251,16 @@ void Instruction::decode() { // SME and Predicate based operations use individual op.type if (op.is_vreg) { setInstructionType(InsnType::isVectorData); - } else if ((AARCH64_REG_Z31 <= op.reg && op.reg >= AARCH64_REG_Z0) || + std::cerr << "\t\tIsVector" << std::endl; + } else if ((AARCH64_REG_Z0 <= op.reg && op.reg <= AARCH64_REG_Z31) || op.reg == AARCH64_REG_ZT0) { - // zT0 is an SME register, but we declare it as an SVE instruction + // ZT0 is an SME register, but we declare it as an SVE instruction // due to its 1D format. + std::cerr << "\t\tIsSVE" << std::endl; setInstructionType(InsnType::isSVEData); - } else if (op.reg <= AARCH64_REG_S31 && op.reg >= AARCH64_REG_Q0) { - setInstructionType(InsnType::isScalarData); - } else if (op.reg <= AARCH64_REG_H31 && op.reg >= AARCH64_REG_B0) { + } else if ((op.reg <= AARCH64_REG_S31 && op.reg >= AARCH64_REG_Q0) || + (op.reg <= AARCH64_REG_H31 && op.reg >= AARCH64_REG_B0)) { + std::cerr << "\t\tIsScalar" << std::endl; setInstructionType(InsnType::isScalarData); } @@ -338,7 +340,7 @@ void Instruction::decode() { sourceOperandsPending_++; } } else if (op.type == AARCH64_OP_PRED) { - setInstructionType(InsnType::isPredicate); + if (i == 0) setInstructionType(InsnType::isPredicate); if (op.access == CS_AC_READ) { std::cerr << "\tPred read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.pred.reg); diff --git a/test/unit/aarch64/ArchInfoTest.cc b/test/unit/aarch64/ArchInfoTest.cc index e29e9793d9..511e0fdd66 100644 --- a/test/unit/aarch64/ArchInfoTest.cc +++ b/test/unit/aarch64/ArchInfoTest.cc @@ -31,7 +31,8 @@ class AArch64ArchInfoTest : public ::testing::Test { {32, 17}, {1, 1}, {8, static_cast(sysRegisterEnums.size())}, - {256, 64}}; + {256, 64}, + {64, 1}}; const std::vector physRegStruct = { {8, 96}, @@ -39,10 +40,11 @@ class AArch64ArchInfoTest : public ::testing::Test { {32, 48}, {1, 128}, {8, static_cast(sysRegisterEnums.size())}, - {256, 128}}; + {256, 128}, + {64, 1}}; const std::vector physRegQuants = { - 96, 128, 48, 128, static_cast(sysRegisterEnums.size()), 128}; + 96, 128, 48, 128, static_cast(sysRegisterEnums.size()), 128, 1}; }; // Test for the getSysRegEnums() function From 547d14cbc460b432e5a3443e2cd83a37eeb4ea17 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 5 Sep 2024 15:31:06 +0200 Subject: [PATCH 08/34] Final fixes to get default program working in emulation mode. --- src/lib/arch/aarch64/InstructionMetadata.cc | 4 +++ src/lib/arch/aarch64/Instruction_address.cc | 2 +- src/lib/arch/aarch64/Instruction_decode.cc | 28 ++------------------- 3 files changed, 7 insertions(+), 27 deletions(-) diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index b75d70eef8..6ea963c838 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -33,6 +33,10 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // Fix some inaccuracies in the decoded metadata switch (opcode) { + case Opcode::AArch64_BLR: + // Incorrectly implicitly reads from SP + implicitSourceCount--; + break; case Opcode::AArch64_ADR_LSL_ZZZ_D_0: // example bytecode = c8a0e704 case Opcode::AArch64_ADR_LSL_ZZZ_D_1: case Opcode::AArch64_ADR_LSL_ZZZ_D_2: diff --git a/src/lib/arch/aarch64/Instruction_address.cc b/src/lib/arch/aarch64/Instruction_address.cc index 9d4cbfd5fb..357077e7b3 100644 --- a/src/lib/arch/aarch64/Instruction_address.cc +++ b/src/lib/arch/aarch64/Instruction_address.cc @@ -600,7 +600,7 @@ span Instruction::generateAddresses() { } case Opcode::AArch64_LDRXl: { // ldr xt, #imm setMemoryAddresses( - {{metadata_.operands[1].imm + instructionAddress_, 8}}); + {{metadata_.operands[1].mem.disp + instructionAddress_, 8}}); break; } case Opcode::AArch64_LDRXroW: { // ldr xt, [xn, wn{, extend {#amount}}] diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 48e9f841f0..4b88825162 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -46,7 +46,6 @@ Register csRegToRegister(aarch64_reg reg) { // (full vector) or Dn (half vector). // As D and Q registers are also of type RegisterType::VECTOR, the outcome // will be the same - std::cerr << "Reg = " << reg << std::endl; // Assert that reg is not a SME tile as these should be passed to // `getZARowVectors()` @@ -200,14 +199,6 @@ void Instruction::decode() { return; } - std::cerr << metadata_.opcode << ":" << metadata_.mnemonic << " " - << metadata_.operandStr << ", reg count " - << (unsigned)metadata_.operandCount << " ---- " << std::hex - << (unsigned)metadata_.encoding[0] << " " - << (unsigned)metadata_.encoding[1] << " " - << (unsigned)metadata_.encoding[2] << " " - << (unsigned)metadata_.encoding[3] << " " << std::dec << std::endl; - // Extract implicit writes, including pre/post index writeback for (size_t i = 0; i < metadata_.implicitDestinationCount; i++) { if (metadata_.implicitDestinations[i] == AARCH64_REG_NZCV && @@ -217,7 +208,6 @@ void Instruction::decode() { // destination. Ignore continue; } - std::cerr << "\tImplicit write - "; destinationRegisters_[destinationRegisterCount_] = csRegToRegister( static_cast(metadata_.implicitDestinations[i])); destinationRegisterCount_++; @@ -230,7 +220,6 @@ void Instruction::decode() { if (static_cast(metadata_.implicitSources[i]) == AARCH64_REG_FPCR) continue; - std::cerr << "\tImplicit Read - "; sourceRegisters_[sourceOperandsPending_] = csRegToRegister(static_cast(metadata_.implicitSources[i])); sourceRegisterCount_++; @@ -251,22 +240,18 @@ void Instruction::decode() { // SME and Predicate based operations use individual op.type if (op.is_vreg) { setInstructionType(InsnType::isVectorData); - std::cerr << "\t\tIsVector" << std::endl; } else if ((AARCH64_REG_Z0 <= op.reg && op.reg <= AARCH64_REG_Z31) || op.reg == AARCH64_REG_ZT0) { // ZT0 is an SME register, but we declare it as an SVE instruction // due to its 1D format. - std::cerr << "\t\tIsSVE" << std::endl; setInstructionType(InsnType::isSVEData); } else if ((op.reg <= AARCH64_REG_S31 && op.reg >= AARCH64_REG_Q0) || (op.reg <= AARCH64_REG_H31 && op.reg >= AARCH64_REG_B0)) { - std::cerr << "\t\tIsScalar" << std::endl; setInstructionType(InsnType::isScalarData); } // Add register writes to destinations, but skip zero-register // destinations - std::cerr << "\tReg Write - "; destinationRegisters_[destinationRegisterCount_] = csRegToRegister(op.reg); destinationRegisterCount_++; @@ -274,7 +259,6 @@ void Instruction::decode() { } if (op.access & cs_ac_type::CS_AC_READ) { // Add register reads to destinations - std::cerr << "\tReg read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.reg); sourceRegisterCount_++; sourceOperandsPending_++; @@ -294,14 +278,12 @@ void Instruction::decode() { // Check base register exists if (op.mem.base != AARCH64_REG_INVALID) { accessesMemory = true; - std::cerr << "\tMem base read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.mem.base); sourceRegisterCount_++; sourceOperandsPending_++; } if (op.mem.index != AARCH64_REG_INVALID) { // Register offset; add to sources - std::cerr << "\tMem index read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.mem.index); sourceRegisterCount_++; sourceOperandsPending_++; @@ -333,7 +315,6 @@ void Instruction::decode() { if (op.sme.type == AARCH64_SME_OP_TILE_VEC) { // SME tile has slice determined by register and immidiate. // Add base register to source operands - std::cerr << "\tSME tile vec base - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.sme.slice_reg); sourceRegisterCount_++; @@ -342,19 +323,16 @@ void Instruction::decode() { } else if (op.type == AARCH64_OP_PRED) { if (i == 0) setInstructionType(InsnType::isPredicate); if (op.access == CS_AC_READ) { - std::cerr << "\tPred read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.pred.reg); sourceRegisterCount_++; sourceOperandsPending_++; } if (op.access == CS_AC_WRITE) { - std::cerr << "\tPred write - "; destinationRegisters_[destinationRegisterCount_] = csRegToRegister(op.pred.reg); destinationRegisterCount_++; } if (op.pred.vec_select != AARCH64_REG_INVALID) { - std::cerr << "\tPred vec select read - "; sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.pred.vec_select); sourceRegisterCount_++; @@ -390,6 +368,8 @@ void Instruction::decode() { // Identify branches for (size_t i = 0; i < metadata_.groupCount; i++) { if (metadata_.groups[i] == AARCH64_GRP_JUMP || + metadata_.groups[i] == AARCH64_GRP_CALL || + metadata_.groups[i] == AARCH64_GRP_RET || metadata_.groups[i] == AARCH64_GRP_BRANCH_RELATIVE) { setInstructionType(InsnType::isBranch); } @@ -450,10 +430,6 @@ void Instruction::decode() { knownOffset_ = metadata_.operands[2].imm; break; } - case Opcode::AArch64_RET: { // ret {xr} - branchType_ = BranchType::Return; - break; - } default: break; } From b5d8d1cae7996b916db4a2fa4307f2b55ef796d1 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Fri, 6 Sep 2024 15:00:19 +0200 Subject: [PATCH 09/34] More changes and fixes. --- .../simeng/arch/aarch64/Instruction.hh | 1 - src/lib/arch/aarch64/ExceptionHandler.cc | 7 +- src/lib/arch/aarch64/InstructionMetadata.cc | 50 +- src/lib/arch/aarch64/InstructionMetadata.hh | 4 +- src/lib/arch/aarch64/Instruction_decode.cc | 630 ++++++++---------- test/unit/aarch64/ExceptionHandlerTest.cc | 18 - 6 files changed, 326 insertions(+), 384 deletions(-) diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index 07f2b21ff5..5841965820 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -50,7 +50,6 @@ enum class InstructionException { None = 0, EncodingUnallocated, ExecutionNotYetImplemented, - AliasNotYetImplemented, MisalignedPC, DataAbort, SupervisorCall, diff --git a/src/lib/arch/aarch64/ExceptionHandler.cc b/src/lib/arch/aarch64/ExceptionHandler.cc index 505c703467..3f606f4320 100644 --- a/src/lib/arch/aarch64/ExceptionHandler.cc +++ b/src/lib/arch/aarch64/ExceptionHandler.cc @@ -689,7 +689,7 @@ bool ExceptionHandler::init() { std::vector regs; std::vector regValues; - // If SVCR.ZA has changed state then zero out ZA register, else don't + // If SVCR.ZA has changed state then zero out ZA and ZT0 registers if (exception != InstructionException::StreamingModeUpdate) { if ((newSVCR & AARCH64_SVCR_SVCRZA) != (currSVCR & AARCH64_SVCR_SVCRZA)) { for (uint16_t i = 0; i < regFileStruct[RegisterType::MATRIX].quantity; @@ -697,6 +697,8 @@ bool ExceptionHandler::init() { regs.push_back({RegisterType::MATRIX, i}); regValues.push_back(RegisterValue(0, 256)); } + regs.push_back({RegisterType::TABLE, 0}); + regValues.push_back(RegisterValue(0, 64)); } } // If SVCR.SM has changed state then zero out SVE, NEON, Predicate @@ -886,9 +888,6 @@ void ExceptionHandler::printException(const Instruction& insn) const { case InstructionException::ExecutionNotYetImplemented: std::cout << "execution not-yet-implemented"; break; - case InstructionException::AliasNotYetImplemented: - std::cout << "alias not-yet-implemented"; - break; case InstructionException::MisalignedPC: std::cout << "misaligned program counter"; break; diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index 6ea963c838..9547b841b2 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -19,7 +19,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operandCount(insn.detail->aarch64.op_count) { std::memcpy(encoding, insn.bytes, sizeof(encoding)); // Copy printed output - std::strncpy(mnemonic, insn.mnemonic, CS_MNEMONIC_SIZE); + mnemonic = std::string(insn.mnemonic); operandStr = std::string(insn.op_str); // Copy register/group/operand information @@ -33,10 +33,22 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // Fix some inaccuracies in the decoded metadata switch (opcode) { - case Opcode::AArch64_BLR: + case Opcode::AArch64_BLR: // Example bytecode - 20003fd6 // Incorrectly implicitly reads from SP implicitSourceCount--; break; + case Opcode::AArch64_MRS: // Example bytecode - 42d03bd5 + // Incorrectly implicitly writes to NZCV + implicitDestinationCount--; + break; + case Opcode::AArch64_FMOVXDHighr: // Example bytecode - 4100af9e + // FMOVXDHighr incorrectly flags destination as WRITE only + operands[0].access = CS_AC_READ | CS_AC_WRITE; + break; + case Opcode::AArch64_FCVTNv4i32: // Example bytecode - 0168614e + // Wrong access type for destination operand + operands[0].access = CS_AC_WRITE; + break; case Opcode::AArch64_ADR_LSL_ZZZ_D_0: // example bytecode = c8a0e704 case Opcode::AArch64_ADR_LSL_ZZZ_D_1: case Opcode::AArch64_ADR_LSL_ZZZ_D_2: @@ -57,17 +69,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].shift = operands[1].shift; break; } - case Opcode::AArch64_AND_ZPmZ_D: // Example bytecode - 4901da04 - case Opcode::AArch64_AND_ZPmZ_H: - case Opcode::AArch64_AND_ZPmZ_S: - case Opcode::AArch64_AND_ZPmZ_B: - // Incorrect defined access types - operands[0].access = CS_AC_WRITE; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; - operands[3].access = CS_AC_READ; - break; - case Opcode::AArch64_CASALW: // Example bbytecode - 02fce188 + case Opcode::AArch64_CASALW: // Example bytecode - 02fce188 case Opcode::AArch64_CASALX: // Correct access types operandCount = 3; @@ -126,6 +128,10 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) assert(false && "Invalid FP immidate contant."); break; } + case Opcode::AArch64_AND_ZPmZ_D: // Example bytecode - 4901da04 + case Opcode::AArch64_AND_ZPmZ_H: + case Opcode::AArch64_AND_ZPmZ_S: + case Opcode::AArch64_AND_ZPmZ_B: case Opcode::AArch64_SMULH_ZPmZ_B: // Example bytecode - 20001204 case Opcode::AArch64_SMULH_ZPmZ_D: case Opcode::AArch64_SMULH_ZPmZ_H: @@ -180,14 +186,6 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].access = CS_AC_READ; operands[3].access = CS_AC_READ; break; - case Opcode::AArch64_FMOVXDHighr: // Example bytecode - 4100af9e - // FMOVXDHighr incorrectly flags destination as WRITE only - operands[0].access = CS_AC_READ | CS_AC_WRITE; - break; - case Opcode::AArch64_FCVTNv4i32: // Example bytecode - 0168614e - // Wrong access type for destination operand - operands[0].access = CS_AC_WRITE; - break; case Opcode::AArch64_CPY_ZPzI_B: case Opcode::AArch64_CPY_ZPzI_D: case Opcode::AArch64_CPY_ZPzI_H: // Example bytecode - 01215005 @@ -209,7 +207,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) size_t pos_2 = operandStr.find(".", pos); if (pos_2 != std::string::npos) { char type = operandStr[pos_2 + 1]; - // Tile Number can only ever be 1 digit + // Tile Number can only ever be 1 digit due to legal overlappings uint8_t tileNum = std::stoi(operandStr.substr((pos + 2), 1)); switch (type) { case 'b': @@ -247,6 +245,12 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) break; } } + + if (isAlias) { + exceptionString_ = + "This instruction is an alias. The printed mnemonic and operand string " + "differ from what is expected of the Capstone opcode."; + } } InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, @@ -267,4 +271,4 @@ InstructionMetadata::InstructionMetadata(const uint8_t* invalidEncoding, } // namespace aarch64 } // namespace arch -} // namespace simeng \ No newline at end of file +} // namespace simeng diff --git a/src/lib/arch/aarch64/InstructionMetadata.hh b/src/lib/arch/aarch64/InstructionMetadata.hh index b3b241d619..3100606d86 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.hh +++ b/src/lib/arch/aarch64/InstructionMetadata.hh @@ -65,7 +65,7 @@ struct InstructionMetadata { uint8_t encoding[4]; /** The instruction's mnemonic. */ - char mnemonic[CS_MNEMONIC_SIZE]; + std::string mnemonic; /** The remainder of the instruction's assembly representation. */ std::string operandStr; @@ -93,7 +93,7 @@ struct InstructionMetadata { bool isAlias; /** The explicit operands. */ - cs_aarch64_op operands[MAX_OPERANDS]; + cs_aarch64_op operands[MAX_OPERANDS * 2]; // Temp fix until Capstone updates /** The number of explicit operands. */ uint8_t operandCount; diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 4b88825162..077299b3d8 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -1,5 +1,3 @@ -#include - #include "InstructionMetadata.hh" #define NOT(bits, length) (~bits & (1 << length - 1)) @@ -40,7 +38,9 @@ constexpr int32_t signExtend(uint32_t value, int currentLength) { * * WARNING: this conversion is FRAGILE, and relies on the structure of the * `aarch64_reg` enum. Updates to the Capstone library version may cause this to - * break. */ + * break. + * TODO: Add multi-register enum decoding. + * */ Register csRegToRegister(aarch64_reg reg) { // Do not need check for AARCH64_REG_Vn as in Capstone, they are aliased as Qn // (full vector) or Dn (half vector). @@ -201,13 +201,6 @@ void Instruction::decode() { // Extract implicit writes, including pre/post index writeback for (size_t i = 0; i < metadata_.implicitDestinationCount; i++) { - if (metadata_.implicitDestinations[i] == AARCH64_REG_NZCV && - (metadata_.opcode == Opcode::AArch64_MRS || - metadata_.opcode == Opcode::AArch64_MSR)) { - // MRS / MSR instructions mistakenly have NZCV added as an implicit - // destination. Ignore - continue; - } destinationRegisters_[destinationRegisterCount_] = csRegToRegister( static_cast(metadata_.implicitDestinations[i])); destinationRegisterCount_++; @@ -508,71 +501,77 @@ void Instruction::decode() { } // Identify Logical (bitwise) instructions - if (regex_match(metadata_.mnemonic, std::regex("(and)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bic)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bif)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bit)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bsl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bcax)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bmop)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(eor)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(eon)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(mvn)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(not)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(nand)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(nbsl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(nor)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(rax)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(xar)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(orr)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(orq)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(orv)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(tst)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(orn)(.*)"))) { + // Opcode prefix-overlaps have been commented out but left in for clarity what + // is searched for. + if (metadata_.mnemonic.find("and") == 0 || + metadata_.mnemonic.find("bic") == 0 || + metadata_.mnemonic.find("bif") == 0 || + metadata_.mnemonic.find("bit") == 0 || + metadata_.mnemonic.find("bsl") == 0 || + metadata_.mnemonic.find("bcax") == 0 || + metadata_.mnemonic.find("bmop") == 0 || + metadata_.mnemonic.find("eor") == 0 || + metadata_.mnemonic.find("eon") == 0 || + metadata_.mnemonic.find("mvn") == 0 || + metadata_.mnemonic.find("not") == 0 || + metadata_.mnemonic.find("nand") == 0 || + metadata_.mnemonic.find("nbsl") == 0 || + metadata_.mnemonic.find("nor") == 0 || + metadata_.mnemonic.find("rax") == 0 || + metadata_.mnemonic.find("xar") == 0 || + metadata_.mnemonic.find("orr") == 0 || + metadata_.mnemonic.find("orq") == 0 || + metadata_.mnemonic.find("orv") == 0 || + metadata_.mnemonic.find("tst") == 0 || + metadata_.mnemonic.find("orn") == 0) { setInstructionType(InsnType::isLogical); } // Identify comparison insturctions (excluding atomic LD-CMP-STR) - if (regex_match(metadata_.mnemonic, std::regex("(ccmn)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmn)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmp)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmpp)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(ccmp)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmeq)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmge)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmgt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmtst)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmhi)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmhs)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmle)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmlt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmpeq)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmpge)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmpgt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmphi)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmphs)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmple)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmplo)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmpls)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmplt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmpne)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmptst)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(facge)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(facgt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(facle)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(faclt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fccmp)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fccmpe)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcmeq)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcmge)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcmgt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcmle)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcmlt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcmne)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcmp)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcmpe)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcmuo)(.*)"))) { + // Opcode prefix-overlaps have been commented out but left in for clarity what + // is searched for. + if (metadata_.mnemonic.find("ccmn") == 0 || + metadata_.mnemonic.find("cmn") == 0 || + metadata_.mnemonic.find("cmp") == 0 || + // metadata_.mnemonic.find("cmpp") == 0 || + // metadata_.mnemonic.find("cmpeq") == 0 || + // metadata_.mnemonic.find("cmpge") == 0 || + // metadata_.mnemonic.find("cmpgt") == 0 || + // metadata_.mnemonic.find("cmphi") == 0 || + // metadata_.mnemonic.find("cmphs") == 0 || + // metadata_.mnemonic.find("cmple") == 0 || + // metadata_.mnemonic.find("cmplo") == 0 || + // metadata_.mnemonic.find("cmpls") == 0 || + // metadata_.mnemonic.find("cmplt") == 0 || + // metadata_.mnemonic.find("cmpne") == 0 || + // metadata_.mnemonic.find("cmptst") == 0 || + metadata_.mnemonic.find("ccmp") == 0 || + metadata_.mnemonic.find("cmeq") == 0 || + metadata_.mnemonic.find("cmge") == 0 || + metadata_.mnemonic.find("cmgt") == 0 || + metadata_.mnemonic.find("cmtst") == 0 || + metadata_.mnemonic.find("cmhi") == 0 || + metadata_.mnemonic.find("cmhs") == 0 || + metadata_.mnemonic.find("cmla") == 0 || + metadata_.mnemonic.find("cmle") == 0 || + metadata_.mnemonic.find("cmlt") == 0 || + // The non-complete opcode prefix `fac` only yields compare uops + metadata_.mnemonic.find("fac") == 0 || + // metadata_.mnemonic.find("facge") == 0 || + // metadata_.mnemonic.find("facgt") == 0 || + // metadata_.mnemonic.find("facle") == 0 || + // metadata_.mnemonic.find("faclt") == 0 || + metadata_.mnemonic.find("fccmp") == 0 || + // metadata_.mnemonic.find("fccmpe") == 0 || + metadata_.mnemonic.find("fcmp") == 0 || + // metadata_.mnemonic.find("fcmpe") == 0 || + metadata_.mnemonic.find("fcmuo") == 0 || + metadata_.mnemonic.find("fcmeq") == 0 || + metadata_.mnemonic.find("fcmge") == 0 || + metadata_.mnemonic.find("fcmgt") == 0 || + metadata_.mnemonic.find("fcmle") == 0 || + metadata_.mnemonic.find("fcmlt") == 0 || + metadata_.mnemonic.find("fcmne") == 0) { setInstructionType(InsnType::isCompare); // Capture those floating point compare instructions with no destination // register @@ -586,45 +585,47 @@ void Instruction::decode() { } // Identify convert instructions - if (regex_match(metadata_.mnemonic, std::regex("(bf1cvtl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bf2cvtl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfcvt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfcvtn)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(f1cvtl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(f2cvtl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtas)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtau)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtms)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtmu)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtn)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtns)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtnu)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtps)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtpu)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtxn)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtzs)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtzu)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fjcvtzs)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(scvtf)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(ucvtf)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bf1cvt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bf2cvt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bf1cvtlt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bf2cvtlt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfcvtnt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(f1cvt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(f2cvt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(f1cvtlt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(f2cvtlt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtlt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtnb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtnt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtx)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtxnt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtzs)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcvtzu)(.*)"))) { + // Opcode prefix-overlaps have been commented out but left in for clarity what + // is searched for. + if (metadata_.mnemonic.find("bfcvt") == 0 || + // metadata_.mnemonic.find("bfcvtn") == 0 || + // metadata_.mnemonic.find("bfcvtnt") == 0 || + metadata_.mnemonic.find("bf1cvt") == 0 || + // metadata_.mnemonic.find("bf1cvtl") == 0 || + // metadata_.mnemonic.find("bf1cvtlt") == 0 || + metadata_.mnemonic.find("bf2cvt") == 0 || + // metadata_.mnemonic.find("bf2cvtl") == 0 || + // metadata_.mnemonic.find("bf2cvtlt") == 0 || + metadata_.mnemonic.find("fcvt") == 0 || + // metadata_.mnemonic.find("fcvtas") == 0 || + // metadata_.mnemonic.find("fcvtau") == 0 || + // metadata_.mnemonic.find("fcvtl") == 0 || + // metadata_.mnemonic.find("fcvtms") == 0 || + // metadata_.mnemonic.find("fcvtmu") == 0 || + // metadata_.mnemonic.find("fcvtn") == 0 || + // metadata_.mnemonic.find("fcvtns") == 0 || + // metadata_.mnemonic.find("fcvtnu") == 0 || + // metadata_.mnemonic.find("fcvtps") == 0 || + // metadata_.mnemonic.find("fcvtpu") == 0 || + // metadata_.mnemonic.find("fcvtxn") == 0 || + // metadata_.mnemonic.find("fcvtzs") == 0 || + // metadata_.mnemonic.find("fcvtzu") == 0 || + // metadata_.mnemonic.find("fcvtlt") == 0 || + // metadata_.mnemonic.find("fcvtnb") == 0 || + // metadata_.mnemonic.find("fcvtnt") == 0 || + // metadata_.mnemonic.find("fcvtx") == 0 || + // metadata_.mnemonic.find("fcvtxnt") == 0 || + // metadata_.mnemonic.find("fcvtzs") == 0 || + // metadata_.mnemonic.find("fcvtzu") == 0 || + metadata_.mnemonic.find("f1cvt") == 0 || + // metadata_.mnemonic.find("f1cvtl") == 0 || + // metadata_.mnemonic.find("f1cvtlt") == 0 || + metadata_.mnemonic.find("f2cvt") == 0 || + // metadata_.mnemonic.find("f2cvtl") == 0 || + // metadata_.mnemonic.find("f2cvtlt") == 0 || + metadata_.mnemonic.find("fjcvtzs") == 0 || + metadata_.mnemonic.find("scvtf") == 0 || + metadata_.mnemonic.find("ucvtf") == 0) { setInstructionType(InsnType::isConvert); // Capture those floating point convert instructions whose destination // register is general purpose @@ -636,239 +637,196 @@ void Instruction::decode() { } // Identify divide or square root operations - if (regex_match(metadata_.mnemonic, std::regex("(sdiv)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(udiv)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fdiv)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fdivr)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sdivr)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(udivr)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(frsqrte)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(frsqrts)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fsqrt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(ursqrte)(.*)"))) { + // Opcode prefix-overlaps have been commented out but left in for clarity what + // is searched for. + if (metadata_.mnemonic.find("sdiv") == 0 || + // metadata_.mnemonic.find("sdivr") == 0 || + metadata_.mnemonic.find("udiv") == 0 || + // metadata_.mnemonic.find("udivr") == 0 || + metadata_.mnemonic.find("fdiv") == 0 || + // metadata_.mnemonic.find("fdivr") == 0 || + // The non-complete opcode prefix `frsqrt` only yields divSqrt uops + metadata_.mnemonic.find("frsqrt") == 0 || + // metadata_.mnemonic.find("frsqrte") == 0 || + // metadata_.mnemonic.find("frsqrts") == 0 || + metadata_.mnemonic.find("fsqrt") == 0 || + metadata_.mnemonic.find("ursqrte") == 0) { setInstructionType(InsnType::isDivideOrSqrt); } // Identify multiply operations - if (regex_match(metadata_.mnemonic, std::regex("(madd)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(maddpt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(mneg)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(msub)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(msubpt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(mul)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smaddl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smnegl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smsubl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smulh)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smull)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umaddl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umnegl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umsubl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umulh)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umull)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmlalb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmlalt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmmla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fcmla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmadd)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlal)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlal2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlalb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlalt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlallbb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlallbt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlalltb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlalltt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmls)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlsl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlsl2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmsub)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmul)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmulx)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fnmadd)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fnmsub)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fnmul)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(mla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(mls)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(mul)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(pmul)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(pmull)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(pmull2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smlal)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smlal2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smlsl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smlsl2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smmla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smull)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smull2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmlal)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmlal2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmlsl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmlsl2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmulh)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmull)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmull2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqrdmlah)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqrdmlsh)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqrdmulh)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umlal)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umlal2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umlsl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umlsl2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(ummla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umull)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umull2)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(usmmla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmls)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmlslb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmlslt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmul)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cmla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmad)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlslb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlslt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmmla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmsb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fnmad)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fnmla)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fnmls)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fnmsb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(ftmad)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(mad)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(madpt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(mlapt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(msb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(pmullb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(pmullt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smlalb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smlalt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smlslb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smlslt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smullb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smullt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmlalb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmlalbt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmlalt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmlslb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmlslbt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmlslt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmullb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqdmullt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sqrdcmlah)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umlalb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umlalt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umlslb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umlslt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umullb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umullt)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmlal)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmlsl)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmlall)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smlall)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smlsll)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sumlall)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umlall)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umlsll)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(usmlall)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfdot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfvdot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fdot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fvdot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fvdotb)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fvdott)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sdot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sudot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(suvdot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(udot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(usdot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(usvdot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(uvdot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(cdot)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmopa)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bfmops)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bmopa)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(bmops)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmopa)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(fmops)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smopa)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(smops)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sumopa)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(sumops)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umopa)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(umops)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(usmopa)(.*)")) || - regex_match(metadata_.mnemonic, std::regex("(usmops)(.*)"))) { + // Opcode prefix-overlaps have been commented out but left in for clarity what + // is searched for. + if (metadata_.mnemonic.find("bfmmla") == 0 || + metadata_.mnemonic.find("bfmul") == 0 || + // The non-complete opcode prefix `bfml` only yields multiply uops + metadata_.mnemonic.find("bfml") == 0 || + // metadata_.mnemonic.find("bfmla") == 0 || + // metadata_.mnemonic.find("bfmlalb") == 0 || + // metadata_.mnemonic.find("bfmlalt") == 0 || + // metadata_.mnemonic.find("bfmlal") == 0 || + // metadata_.mnemonic.find("bfmls") == 0 || + // metadata_.mnemonic.find("bfmlslb") == 0 || + // metadata_.mnemonic.find("bfmlslt") == 0 || + // metadata_.mnemonic.find("bfmlsl") == 0 || + metadata_.mnemonic.find("cmla") == 0 || + // The substring `dot` only appears in dot-product opcodes + metadata_.mnemonic.find("dot") != std::string::npos || + // metadata_.mnemonic.find("bfdot") == 0 || + // metadata_.mnemonic.find("bfvdot") == 0 || + // metadata_.mnemonic.find("fdot") == 0 || + // metadata_.mnemonic.find("fvdot") == 0 || + // metadata_.mnemonic.find("fvdotb") == 0 || + // metadata_.mnemonic.find("fvdott") == 0 || + // metadata_.mnemonic.find("sdot") == 0 || + // metadata_.mnemonic.find("sudot") == 0 || + // metadata_.mnemonic.find("suvdot") == 0 || + // metadata_.mnemonic.find("udot") == 0 || + // metadata_.mnemonic.find("usdot") == 0 || + // metadata_.mnemonic.find("usvdot") == 0 || + // metadata_.mnemonic.find("uvdot") == 0 || + // metadata_.mnemonic.find("cdot") == 0 || + metadata_.mnemonic.find("fmla") == 0 || + // metadata_.mnemonic.find("fmlal") == 0 || + // metadata_.mnemonic.find("fmlal2") == 0 || + // metadata_.mnemonic.find("fmlalb") == 0 || + // metadata_.mnemonic.find("fmlalt") == 0 || + // metadata_.mnemonic.find("fmlallbb") == 0 || + // metadata_.mnemonic.find("fmlallbt") == 0 || + // metadata_.mnemonic.find("fmlalltb") == 0 || + // metadata_.mnemonic.find("fmlalltt") == 0 || + // metadata_.mnemonic.find("fmlall") == 0 || + metadata_.mnemonic.find("fmls") == 0 || + // metadata_.mnemonic.find("fmlsl") == 0 || + // metadata_.mnemonic.find("fmlsl2") == 0 || + // metadata_.mnemonic.find("fmlslb") == 0 || + // metadata_.mnemonic.find("fmlslt") == 0 || + metadata_.mnemonic.find("fmul") == 0 || + // metadata_.mnemonic.find("fmulx") == 0 || + metadata_.mnemonic.find("fmad") == 0 || + // metadata_.mnemonic.find("fmadd") == 0 || + metadata_.mnemonic.find("fmmla") == 0 || + metadata_.mnemonic.find("fmsb") == 0 || + metadata_.mnemonic.find("fmsub") == 0 || + metadata_.mnemonic.find("ftmad") == 0 || + metadata_.mnemonic.find("fcmla") == 0 || + // The non-complete opcode prefix `fnm` only yields multiply uops + metadata_.mnemonic.find("fnm") == 0 || + // metadata_.mnemonic.find("fnmad") == 0 || + // metadata_.mnemonic.find("fnmla") == 0 || + // metadata_.mnemonic.find("fnmls") == 0 || + // metadata_.mnemonic.find("fnmsb") == 0 || + // metadata_.mnemonic.find("fnmadd") == 0 || + // metadata_.mnemonic.find("fnmsub") == 0 || + // metadata_.mnemonic.find("fnmul") == 0 || + metadata_.mnemonic.find("madd") == 0 || + // metadata_.mnemonic.find("maddpt") == 0 || + metadata_.mnemonic.find("mul") == 0 || + metadata_.mnemonic.find("mla") == 0 || + // metadata_.mnemonic.find("mlapt") == 0 || + metadata_.mnemonic.find("mls") == 0 || + metadata_.mnemonic.find("mneg") == 0 || + metadata_.mnemonic.find("msub") == 0 || + // metadata_.mnemonic.find("msubpt") == 0 || + metadata_.mnemonic.find("mad") == 0 || + // metadata_.mnemonic.find("madpt") == 0 || + metadata_.mnemonic.find("msb") == 0 || + // The substring `mop` only appears in outer-product opcodes + metadata_.mnemonic.find("mop") != std::string::npos || + // metadata_.mnemonic.find("bfmopa") == 0 || + // metadata_.mnemonic.find("bfmops") == 0 || + // metadata_.mnemonic.find("bmopa") == 0 || + // metadata_.mnemonic.find("bmops") == 0 || + // metadata_.mnemonic.find("fmopa") == 0 || + // metadata_.mnemonic.find("fmops") == 0 || + // metadata_.mnemonic.find("smopa") == 0 || + // metadata_.mnemonic.find("smops") == 0 || + // metadata_.mnemonic.find("sumopa") == 0 || + // metadata_.mnemonic.find("sumops") == 0 || + // metadata_.mnemonic.find("umopa") == 0 || + // metadata_.mnemonic.find("umops") == 0 || + // metadata_.mnemonic.find("usmopa") == 0 || + // metadata_.mnemonic.find("usmops") == 0 + metadata_.mnemonic.find("pmul") == 0 || + // metadata_.mnemonic.find("pmull") == 0 || + // metadata_.mnemonic.find("pmull2") == 0 || + // metadata_.mnemonic.find("pmullb") == 0 || + // metadata_.mnemonic.find("pmullt") == 0 || + // The non-complete opcode prefix `sml` only yields multiply uops + metadata_.mnemonic.find("sml") == 0 || + // metadata_.mnemonic.find("smlalb") == 0 || + // metadata_.mnemonic.find("smlalt") == 0 || + // metadata_.mnemonic.find("smlslb") == 0 || + // metadata_.mnemonic.find("smlslt") == 0 || + // metadata_.mnemonic.find("smlal") == 0 || + // metadata_.mnemonic.find("smlal2") == 0 || + // metadata_.mnemonic.find("smlsl") == 0 || + // metadata_.mnemonic.find("smlsl2") == 0 || + // metadata_.mnemonic.find("smlall") == 0 || + // metadata_.mnemonic.find("smlsll") == 0 || + metadata_.mnemonic.find("smmla") == 0 || + // The non-complete opcode prefix `smul` only yields multiply uops + metadata_.mnemonic.find("smul") == 0 || + // metadata_.mnemonic.find("smulh") == 0 || + // metadata_.mnemonic.find("smull") == 0 || + // metadata_.mnemonic.find("smull2") == 0 || + // metadata_.mnemonic.find("smullb") == 0 || + // metadata_.mnemonic.find("smullt") == 0 || + // The non-complete opcode prefix `sqdm` only yields multiply uops + metadata_.mnemonic.find("sqdm") == 0 || + // metadata_.mnemonic.find("sqdmlal") == 0 || + // metadata_.mnemonic.find("sqdmlal2") == 0 || + // metadata_.mnemonic.find("sqdmlsl") == 0 || + // metadata_.mnemonic.find("sqdmlsl2") == 0 || + // metadata_.mnemonic.find("sqdmulh") == 0 || + // metadata_.mnemonic.find("sqdmull") == 0 || + // metadata_.mnemonic.find("sqdmull2") == 0 || + // metadata_.mnemonic.find("sqdmlalb") == 0 || + // metadata_.mnemonic.find("sqdmlalbt") == 0 || + // metadata_.mnemonic.find("sqdmlalt") == 0 || + // metadata_.mnemonic.find("sqdmlslb") == 0 || + // metadata_.mnemonic.find("sqdmlslbt") == 0 || + // metadata_.mnemonic.find("sqdmlslt") == 0 || + // metadata_.mnemonic.find("sqdmullb") == 0 || + // metadata_.mnemonic.find("sqdmullt") == 0 || + // The non-complete opcode prefix `sqrd` only yields multiply uops + metadata_.mnemonic.find("sqrd") == 0 || + // metadata_.mnemonic.find("sqrdmlah") == 0 || + // metadata_.mnemonic.find("sqrdmlsh") == 0 || + // metadata_.mnemonic.find("sqrdmulh") == 0 || + // metadata_.mnemonic.find("sqrdcmlah") == 0 || + metadata_.mnemonic.find("sumlall") == 0 || + metadata_.mnemonic.find("smaddl") == 0 || + metadata_.mnemonic.find("smnegl") == 0 || + metadata_.mnemonic.find("smsubl") == 0 || + // The non-complete opcode prefix `umul` only yields multiply uops + metadata_.mnemonic.find("umul") == 0 || + // metadata_.mnemonic.find("umulh") == 0 || + // metadata_.mnemonic.find("umull") == 0 || + // metadata_.mnemonic.find("umull2") == 0 || + // metadata_.mnemonic.find("umullb") == 0 || + // metadata_.mnemonic.find("umullt") == 0 || + // The non-complete opcode prefix `uml` only yields multiply uops + metadata_.mnemonic.find("uml") == 0 || + // metadata_.mnemonic.find("umlal") == 0 || + // metadata_.mnemonic.find("umlal2") == 0 || + // metadata_.mnemonic.find("umlsl") == 0 || + // metadata_.mnemonic.find("umlsl2") == 0 || + // metadata_.mnemonic.find("umlslt") == 0 || + // metadata_.mnemonic.find("umlalb") == 0 || + // metadata_.mnemonic.find("umlalt") == 0 || + // metadata_.mnemonic.find("umlslb") == 0 || + // metadata_.mnemonic.find("umlall") == 0 || + // metadata_.mnemonic.find("umlsll") == 0 || + metadata_.mnemonic.find("usmlall") == 0 || + metadata_.mnemonic.find("usmmla") == 0 || + metadata_.mnemonic.find("ummla") == 0 || + metadata_.mnemonic.find("umaddl") == 0 || + metadata_.mnemonic.find("umnegl") == 0 || + metadata_.mnemonic.find("umsubl") == 0) { setInstructionType(InsnType::isMultiply); } - // - // if ((433 <= metadata_.opcode && - // metadata_.opcode <= 447) || // all MUL variants - // (759 <= metadata_.opcode && metadata_.opcode <= 762) || - // (816 <= metadata_.opcode && metadata_.opcode <= 819) || - // (915 <= metadata_.opcode && metadata_.opcode <= 918) || - // (2436 <= metadata_.opcode && metadata_.opcode <= 2482) || - // (2512 <= metadata_.opcode && metadata_.opcode <= 2514) || - // (2702 <= metadata_.opcode && metadata_.opcode <= 2704) || - // (3692 <= metadata_.opcode && metadata_.opcode <= 3716) || - // (3793 <= metadata_.opcode && metadata_.opcode <= 3805) || - // (4352 <= metadata_.opcode && metadata_.opcode <= 4380) || - // (4503 <= metadata_.opcode && metadata_.opcode <= 4543) || - // (4625 <= metadata_.opcode && metadata_.opcode <= 4643) || - // (5804 <= metadata_.opcode && metadata_.opcode <= 5832) || - // (2211 <= metadata_.opcode && - // metadata_.opcode <= 2216) || // all MADD/MAD variants - // (2494 <= metadata_.opcode && metadata_.opcode <= 2499) || - // (2699 <= metadata_.opcode && metadata_.opcode <= 2701) || - // (3610 <= metadata_.opcode && metadata_.opcode <= 3615) || - // (4227 == metadata_.opcode) || (5682 == metadata_.opcode) || - // (2433 <= metadata_.opcode && - // metadata_.opcode <= 2435) || // all MSUB variants - // (2509 <= metadata_.opcode && metadata_.opcode <= 2511) || - // (3690 <= metadata_.opcode && metadata_.opcode <= 3691) || - // (4351 == metadata_.opcode) || (5803 == metadata_.opcode) || - // (424 <= metadata_.opcode && - // metadata_.opcode <= 426) || // all MLA variants - // (451 <= metadata_.opcode && metadata_.opcode <= 453) || - // (1151 <= metadata_.opcode && metadata_.opcode <= 1160) || - // (1378 <= metadata_.opcode && metadata_.opcode <= 1383) || - // (1914 <= metadata_.opcode && metadata_.opcode <= 1926) || - // (2341 <= metadata_.opcode && metadata_.opcode <= 2371) || - // (2403 <= metadata_.opcode && metadata_.opcode <= 2404) || - // (2500 <= metadata_.opcode && metadata_.opcode <= 2502) || - // (3618 <= metadata_.opcode && metadata_.opcode <= 3634) || - // (4295 <= metadata_.opcode && metadata_.opcode <= 4314) || - // (4335 <= metadata_.opcode && metadata_.opcode <= 4336) || - // (4453 <= metadata_.opcode && metadata_.opcode <= 4477) || - // (4581 <= metadata_.opcode && metadata_.opcode <= 4605) || - // (5749 <= metadata_.opcode && metadata_.opcode <= 5768) || - // (5789 <= metadata_.opcode && metadata_.opcode <= 5790) || - // (6115 <= metadata_.opcode && metadata_.opcode <= 6116) || - // (427 <= metadata_.opcode && - // metadata_.opcode <= 429) || // all MLS variants - // (454 <= metadata_.opcode && metadata_.opcode <= 456) || - // (2372 <= metadata_.opcode && metadata_.opcode <= 2402) || - // (2503 <= metadata_.opcode && metadata_.opcode <= 2505) || - // (3635 <= metadata_.opcode && metadata_.opcode <= 3651) || - // (4315 <= metadata_.opcode && metadata_.opcode <= 4334) || - // (4478 <= metadata_.opcode && metadata_.opcode <= 4502) || - // (4606 <= metadata_.opcode && metadata_.opcode <= 4624) || - // (5769 <= metadata_.opcode && metadata_.opcode <= 5788) || - // (2430 <= metadata_.opcode && - // metadata_.opcode <= 2432) || // all MSB variants - // (2506 <= metadata_.opcode && metadata_.opcode <= 2508) || - // (3682 <= metadata_.opcode && metadata_.opcode <= 3685) || - // (2405 <= metadata_.opcode && - // metadata_.opcode <= 2408) || // all SME FMOPS & FMOPA variants - // (4337 <= metadata_.opcode && metadata_.opcode <= 4340) || - // (5391 <= metadata_.opcode && metadata_.opcode <= 5394) || - // (5791 <= metadata_.opcode && metadata_.opcode <= 5794) || - // (6117 <= metadata_.opcode && metadata_.opcode <= 6120)) { - // setInstructionType(InsnType::isMultiply); - // } - // Catch exceptions to the above identifier assignments // Uncaught predicate assignment due to lacking destination register if (metadata_.opcode == Opcode::AArch64_PTEST_PP) { diff --git a/test/unit/aarch64/ExceptionHandlerTest.cc b/test/unit/aarch64/ExceptionHandlerTest.cc index b64e1bfbee..26e6f8dc7a 100644 --- a/test/unit/aarch64/ExceptionHandlerTest.cc +++ b/test/unit/aarch64/ExceptionHandlerTest.cc @@ -447,24 +447,6 @@ TEST_F(AArch64ExceptionHandlerTest, printException) { buffer.str(std::string()); uops.clear(); - // Create instruction for AliasNotYetImplemented - arch.predecode(validInstrBytes.data(), validInstrBytes.size(), insnAddr, - uops); - exception = InstructionException::AliasNotYetImplemented; - insn = std::make_shared( - arch, static_cast(uops[0].get())->getMetadata(), exception); - // Create ExceptionHandler - ExceptionHandler handler_2(insn, core, memory, kernel); - // Capture std::cout and tick exceptionHandler - sbuf = std::cout.rdbuf(); // Save cout's buffer - std::cout.rdbuf(buffer.rdbuf()); // Redirect cout to buffer - handler_2.printException(*static_cast(insn.get())); - std::cout.rdbuf(sbuf); // Restore cout - EXPECT_THAT(buffer.str(), HasSubstr("[SimEng:ExceptionHandler] Encountered " - "alias not-yet-implemented exception")); - buffer.str(std::string()); - uops.clear(); - // Create instruction for MisalignedPC arch.predecode(validInstrBytes.data(), validInstrBytes.size(), insnAddr, uops); From 5224317b1279a86bdd71bdd2a709fe62f044b64c Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Fri, 6 Sep 2024 17:10:43 +0200 Subject: [PATCH 10/34] Updated SVE predicate pattern to use new enum in instruction. --- .../aarch64/helpers/auxiliaryFunctions.hh | 99 ++++---- .../simeng/arch/aarch64/helpers/sve.hh | 31 ++- test/unit/aarch64/AuxiliaryFunctionsTest.cc | 224 +++++++++--------- 3 files changed, 167 insertions(+), 187 deletions(-) diff --git a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh index 853e46dddd..96bcf29233 100644 --- a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh +++ b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh @@ -263,63 +263,54 @@ inline uint64_t mulhi(uint64_t a, uint64_t b) { return multhi; } -/** Decode the instruction pattern from OperandStr. */ -inline uint16_t sveGetPattern(const std::string operandStr, const uint8_t esize, - const uint16_t VL_) { +/** Get the number of elements to work on for SVE instructions. */ +inline uint16_t getElemsFromPattern(const aarch64_svepredpat svePattern, + const uint8_t esize, const uint16_t VL_) { const uint16_t elements = VL_ / esize; - const std::vector patterns = { - "pow2", "vl1", "vl2", "vl3", "vl4", "vl5", "vl6", "vl7", "vl8", - "vl16", "vl32", "vl64", "vl128", "vl256", "mul3", "mul4", "all"}; - - // If no pattern present in operandStr then same behaviour as ALL - std::string pattern = "all"; - for (uint8_t i = 0; i < patterns.size(); i++) { - if (operandStr.find(patterns[i]) != std::string::npos) { - pattern = patterns[i]; - // Don't break when pattern found as vl1 will be found in vl128 etc + switch (svePattern) { + case AARCH64_SVEPREDPAT_ALL: + return elements; + case AARCH64_SVEPREDPAT_MUL3: + return elements - (elements % 3); + case AARCH64_SVEPREDPAT_MUL4: + return elements - (elements % 4); + case AARCH64_SVEPREDPAT_POW2: { + int n = 1; + while (elements >= std::pow(2, n)) { + n = n + 1; + } + return std::pow(2, n - 1); } + case AARCH64_SVEPREDPAT_VL1: + return (elements >= 1) ? 1 : 0; + case AARCH64_SVEPREDPAT_VL128: + return (elements >= 128) ? 128 : 0; + case AARCH64_SVEPREDPAT_VL16: + return (elements >= 16) ? 16 : 0; + case AARCH64_SVEPREDPAT_VL2: + return (elements >= 2) ? 2 : 0; + case AARCH64_SVEPREDPAT_VL256: + return (elements >= 256) ? 256 : 0; + case AARCH64_SVEPREDPAT_VL3: + return (elements >= 3) ? 3 : 0; + case AARCH64_SVEPREDPAT_VL32: + return (elements >= 32) ? 32 : 0; + case AARCH64_SVEPREDPAT_VL4: + return (elements >= 4) ? 4 : 0; + case AARCH64_SVEPREDPAT_VL5: + return (elements >= 5) ? 5 : 0; + case AARCH64_SVEPREDPAT_VL6: + return (elements >= 6) ? 6 : 0; + case AARCH64_SVEPREDPAT_VL64: + return (elements >= 64) ? 64 : 0; + case AARCH64_SVEPREDPAT_VL7: + return (elements >= 7) ? 7 : 0; + case AARCH64_SVEPREDPAT_VL8: + return (elements >= 8) ? 8 : 0; + default: + assert(false && "Unknown SVE Predicate Pattern."); + return 0; } - - if (pattern == "all") - return elements; - else if (pattern == "pow2") { - int n = 1; - while (elements >= std::pow(2, n)) { - n = n + 1; - } - return std::pow(2, n - 1); - } else if (pattern == "vl1") - return (elements >= 1) ? 1 : 0; - else if (pattern == "vl2") - return (elements >= 2) ? 2 : 0; - else if (pattern == "vl3") - return (elements >= 3) ? 3 : 0; - else if (pattern == "vl4") - return (elements >= 4) ? 4 : 0; - else if (pattern == "vl5") - return (elements >= 5) ? 5 : 0; - else if (pattern == "vl6") - return (elements >= 6) ? 6 : 0; - else if (pattern == "vl7") - return (elements >= 7) ? 7 : 0; - else if (pattern == "vl8") - return (elements >= 8) ? 8 : 0; - else if (pattern == "vl16") - return (elements >= 16) ? 16 : 0; - else if (pattern == "vl32") - return (elements >= 32) ? 32 : 0; - else if (pattern == "vl64") - return (elements >= 64) ? 64 : 0; - else if (pattern == "vl128") - return (elements >= 128) ? 128 : 0; - else if (pattern == "vl256") - return (elements >= 256) ? 256 : 0; - else if (pattern == "mul4") - return elements - (elements % 4); - else if (pattern == "mul3") - return elements - (elements % 3); - - return 0; } /** Apply the shift specified by `shiftType` to the unsigned integer `value`, diff --git a/src/include/simeng/arch/aarch64/helpers/sve.hh b/src/include/simeng/arch/aarch64/helpers/sve.hh index 75211fc155..fd092fcc04 100644 --- a/src/include/simeng/arch/aarch64/helpers/sve.hh +++ b/src/include/simeng/arch/aarch64/helpers/sve.hh @@ -177,11 +177,10 @@ std::tuple, uint8_t> sveCmpPredicated_toPred( template uint64_t sveCnt_gpr(const simeng::arch::aarch64::InstructionMetadata& metadata, const uint16_t VL_bits) { - // SVE pattern stored in metadata_.operands[1] const uint8_t imm = static_cast(metadata.operands[2].imm); - const uint16_t elems = - sveGetPattern(metadata.operandStr, (sizeof(T) * 8), VL_bits); + const uint16_t elems = getElemsFromPattern( + metadata.operands[1].sysop.alias.svepredpat, (sizeof(T) * 8), VL_bits); return (uint64_t)(elems * imm); } @@ -268,10 +267,9 @@ int64_t sveDec_scalar( const simeng::arch::aarch64::InstructionMetadata& metadata, const uint16_t VL_bits) { const int64_t n = sourceValues[0].get(); - // metadata_.operands[1] is the SVE pattern enum const uint8_t imm = static_cast(metadata.operands[2].imm); - const uint16_t elems = - sveGetPattern(metadata.operandStr, sizeof(T) * 8, VL_bits); + const uint16_t elems = getElemsFromPattern( + metadata.operands[1].sysop.alias.svepredpat, sizeof(T) * 8, VL_bits); return (n - static_cast(elems * imm)); } @@ -861,10 +859,10 @@ int64_t sveInc_gprImm( const simeng::arch::aarch64::InstructionMetadata& metadata, const uint16_t VL_bits) { const int64_t n = sourceValues[0].get(); - // metadata_.operands[1] is the SVE pattern enum + const uint8_t imm = static_cast(metadata.operands[2].imm); - const uint16_t elems = - sveGetPattern(metadata.operandStr, sizeof(T) * 8, VL_bits); + const uint16_t elems = getElemsFromPattern( + metadata.operands[1].sysop.alias.svepredpat, sizeof(T) * 8, VL_bits); int64_t out = n + (elems * imm); return out; } @@ -879,13 +877,13 @@ RegisterValue sveInc_imm( const simeng::arch::aarch64::InstructionMetadata& metadata, const uint16_t VL_bits) { const T* n = sourceValues[0].getAsVector(); - // metadata_.operands[1] is the SVE pattern enum + const uint8_t imm = static_cast(metadata.operands[2].imm); const uint16_t partition_num = VL_bits / (sizeof(T) * 8); typename std::make_signed::type out[256 / sizeof(T)] = {0}; - const uint16_t elems = - sveGetPattern(metadata.operandStr, sizeof(T) * 8, VL_bits); + const uint16_t elems = getElemsFromPattern( + metadata.operands[1].sysop.alias.svepredpat, sizeof(T) * 8, VL_bits); for (int i = 0; i < partition_num; i++) { out[i] = n[i] + (elems * imm); @@ -1307,8 +1305,8 @@ std::array svePtrue( std::array out = {0, 0, 0, 0}; // Get pattern - const uint16_t count = - sveGetPattern(metadata.operandStr, sizeof(T) * 8, VL_bits); + const uint16_t count = getElemsFromPattern( + metadata.operands[1].sysop.alias.svepredpat, sizeof(T) * 8, VL_bits); // Exit early if count == 0 if (count == 0) return out; @@ -1596,9 +1594,10 @@ uint64_t sveUqdec(srcValContainer& sourceValues, const simeng::arch::aarch64::InstructionMetadata& metadata, const uint16_t VL_bits) { const D d = sourceValues[0].get(); - // metadata.operands[1] contains the SVE pattern + const uint8_t imm = metadata.operands[2].imm; - const uint16_t count = sveGetPattern(metadata.operandStr, N, VL_bits); + const uint16_t count = getElemsFromPattern( + metadata.operands[1].sysop.alias.svepredpat, N, VL_bits); // The range of possible values does not fit in the range of any integral // type, so a double is used as an intermediate value. The end result must diff --git a/test/unit/aarch64/AuxiliaryFunctionsTest.cc b/test/unit/aarch64/AuxiliaryFunctionsTest.cc index cf8d8e59d9..f319b55dbb 100644 --- a/test/unit/aarch64/AuxiliaryFunctionsTest.cc +++ b/test/unit/aarch64/AuxiliaryFunctionsTest.cc @@ -344,132 +344,122 @@ TEST(AArch64AuxiliaryFunctionTest, Mulhi) { EXPECT_EQ(mulhi(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFF), 0xFFFFFFFE); } -/** `sveGetPattern` Tests */ -TEST(AArch64AuxiliaryFunctionTest, sveGetPattern) { +/** `getElemsFromPattern` Tests */ +TEST(AArch64AuxiliaryFunctionTest, getElemsFromPattern) { uint16_t vl = 128; - EXPECT_EQ(sveGetPattern("", 64, vl), 2); - EXPECT_EQ(sveGetPattern("", 16, vl), 8); - EXPECT_EQ(sveGetPattern("all", 64, vl), 2); - EXPECT_EQ(sveGetPattern("all", 16, vl), 8); - EXPECT_EQ(sveGetPattern("notValid", 64, vl), 2); - EXPECT_EQ(sveGetPattern("notValid", 16, vl), 8); - - EXPECT_EQ(sveGetPattern("vl1", 64, vl), 1); - EXPECT_EQ(sveGetPattern("vl2", 64, vl), 2); - EXPECT_EQ(sveGetPattern("vl3", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl4", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl5", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl6", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl7", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl8", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl16", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl32", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl64", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl128", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl256", 64, vl), 0); - - EXPECT_EQ(sveGetPattern("mul4", 8, vl), 16); - EXPECT_EQ(sveGetPattern("mul3", 8, vl), 15); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_ALL, 64, vl), 2); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_ALL, 16, vl), 8); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL1, 64, vl), 1); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL2, 64, vl), 2); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL3, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL4, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL5, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL6, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL7, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL8, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL16, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL32, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL64, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL128, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL256, 64, vl), 0); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_MUL4, 8, vl), 16); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_MUL3, 8, vl), 15); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_POW2, 8, vl), 16); vl = 256; - EXPECT_EQ(sveGetPattern("", 64, vl), 4); - EXPECT_EQ(sveGetPattern("", 16, vl), 16); - EXPECT_EQ(sveGetPattern("all", 64, vl), 4); - EXPECT_EQ(sveGetPattern("all", 16, vl), 16); - EXPECT_EQ(sveGetPattern("notValid", 64, vl), 4); - EXPECT_EQ(sveGetPattern("notValid", 16, vl), 16); - - EXPECT_EQ(sveGetPattern("vl1", 64, vl), 1); - EXPECT_EQ(sveGetPattern("vl2", 64, vl), 2); - EXPECT_EQ(sveGetPattern("vl3", 64, vl), 3); - EXPECT_EQ(sveGetPattern("vl4", 64, vl), 4); - EXPECT_EQ(sveGetPattern("vl5", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl6", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl7", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl8", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl16", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl32", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl64", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl128", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl256", 64, vl), 0); - - EXPECT_EQ(sveGetPattern("mul4", 8, vl), 32); - EXPECT_EQ(sveGetPattern("mul3", 8, vl), 30); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_ALL, 64, vl), 4); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_ALL, 16, vl), 16); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL1, 64, vl), 1); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL2, 64, vl), 2); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL3, 64, vl), 3); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL4, 64, vl), 4); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL5, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL6, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL7, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL8, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL16, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL32, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL64, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL128, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL256, 64, vl), 0); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_MUL4, 8, vl), 32); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_MUL3, 8, vl), 30); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_POW2, 8, vl), 32); vl = 512; - EXPECT_EQ(sveGetPattern("", 64, vl), 8); - EXPECT_EQ(sveGetPattern("", 16, vl), 32); - EXPECT_EQ(sveGetPattern("all", 64, vl), 8); - EXPECT_EQ(sveGetPattern("all", 16, vl), 32); - EXPECT_EQ(sveGetPattern("notValid", 64, vl), 8); - EXPECT_EQ(sveGetPattern("notValid", 16, vl), 32); - - EXPECT_EQ(sveGetPattern("vl1", 64, vl), 1); - EXPECT_EQ(sveGetPattern("vl2", 64, vl), 2); - EXPECT_EQ(sveGetPattern("vl3", 64, vl), 3); - EXPECT_EQ(sveGetPattern("vl4", 64, vl), 4); - EXPECT_EQ(sveGetPattern("vl5", 64, vl), 5); - EXPECT_EQ(sveGetPattern("vl6", 64, vl), 6); - EXPECT_EQ(sveGetPattern("vl7", 64, vl), 7); - EXPECT_EQ(sveGetPattern("vl8", 64, vl), 8); - EXPECT_EQ(sveGetPattern("vl16", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl32", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl64", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl128", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl256", 64, vl), 0); - - EXPECT_EQ(sveGetPattern("mul4", 8, vl), 64); - EXPECT_EQ(sveGetPattern("mul3", 8, vl), 63); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_ALL, 64, vl), 8); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_ALL, 16, vl), 32); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL1, 64, vl), 1); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL2, 64, vl), 2); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL3, 64, vl), 3); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL4, 64, vl), 4); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL5, 64, vl), 5); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL6, 64, vl), 6); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL7, 64, vl), 7); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL8, 64, vl), 8); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL16, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL32, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL64, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL128, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL256, 64, vl), 0); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_MUL4, 8, vl), 64); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_MUL3, 8, vl), 63); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_POW2, 8, vl), 64); vl = 1024; - EXPECT_EQ(sveGetPattern("", 64, vl), 16); - EXPECT_EQ(sveGetPattern("", 16, vl), 64); - EXPECT_EQ(sveGetPattern("all", 64, vl), 16); - EXPECT_EQ(sveGetPattern("all", 16, vl), 64); - EXPECT_EQ(sveGetPattern("notValid", 64, vl), 16); - EXPECT_EQ(sveGetPattern("notValid", 16, vl), 64); - - EXPECT_EQ(sveGetPattern("vl1", 64, vl), 1); - EXPECT_EQ(sveGetPattern("vl2", 64, vl), 2); - EXPECT_EQ(sveGetPattern("vl3", 64, vl), 3); - EXPECT_EQ(sveGetPattern("vl4", 64, vl), 4); - EXPECT_EQ(sveGetPattern("vl5", 64, vl), 5); - EXPECT_EQ(sveGetPattern("vl6", 64, vl), 6); - EXPECT_EQ(sveGetPattern("vl7", 64, vl), 7); - EXPECT_EQ(sveGetPattern("vl8", 64, vl), 8); - EXPECT_EQ(sveGetPattern("vl16", 64, vl), 16); - EXPECT_EQ(sveGetPattern("vl32", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl64", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl128", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl256", 64, vl), 0); - - EXPECT_EQ(sveGetPattern("mul4", 8, vl), 128); - EXPECT_EQ(sveGetPattern("mul3", 8, vl), 126); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_ALL, 64, vl), 16); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_ALL, 16, vl), 64); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL1, 64, vl), 1); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL2, 64, vl), 2); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL3, 64, vl), 3); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL4, 64, vl), 4); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL5, 64, vl), 5); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL6, 64, vl), 6); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL7, 64, vl), 7); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL8, 64, vl), 8); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL16, 64, vl), 16); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL32, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL64, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL128, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL256, 64, vl), 0); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_MUL4, 8, vl), 128); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_MUL3, 8, vl), 126); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_POW2, 8, vl), 128); vl = 2048; - EXPECT_EQ(sveGetPattern("", 64, vl), 32); - EXPECT_EQ(sveGetPattern("", 16, vl), 128); - EXPECT_EQ(sveGetPattern("all", 64, vl), 32); - EXPECT_EQ(sveGetPattern("all", 16, vl), 128); - EXPECT_EQ(sveGetPattern("notValid", 64, vl), 32); - EXPECT_EQ(sveGetPattern("notValid", 16, vl), 128); - - EXPECT_EQ(sveGetPattern("vl1", 64, vl), 1); - EXPECT_EQ(sveGetPattern("vl2", 64, vl), 2); - EXPECT_EQ(sveGetPattern("vl3", 64, vl), 3); - EXPECT_EQ(sveGetPattern("vl4", 64, vl), 4); - EXPECT_EQ(sveGetPattern("vl5", 64, vl), 5); - EXPECT_EQ(sveGetPattern("vl6", 64, vl), 6); - EXPECT_EQ(sveGetPattern("vl7", 64, vl), 7); - EXPECT_EQ(sveGetPattern("vl8", 64, vl), 8); - EXPECT_EQ(sveGetPattern("vl16", 64, vl), 16); - EXPECT_EQ(sveGetPattern("vl32", 64, vl), 32); - EXPECT_EQ(sveGetPattern("vl64", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl128", 64, vl), 0); - EXPECT_EQ(sveGetPattern("vl256", 64, vl), 0); - - EXPECT_EQ(sveGetPattern("mul4", 8, vl), 256); - EXPECT_EQ(sveGetPattern("mul3", 8, vl), 255); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_ALL, 64, vl), 32); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_ALL, 16, vl), 128); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL1, 64, vl), 1); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL2, 64, vl), 2); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL3, 64, vl), 3); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL4, 64, vl), 4); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL5, 64, vl), 5); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL6, 64, vl), 6); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL7, 64, vl), 7); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL8, 64, vl), 8); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL16, 64, vl), 16); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL32, 64, vl), 32); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL64, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL128, 64, vl), 0); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_VL256, 64, vl), 0); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_MUL4, 8, vl), 256); + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_MUL3, 8, vl), 255); + + EXPECT_EQ(getElemsFromPattern(AARCH64_SVEPREDPAT_POW2, 8, vl), 256); } /** `ShiftValue` Tests */ From 8cd7335a1400bc5d2b22e27ef180a152a2f8a29c Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Wed, 11 Sep 2024 17:05:48 +0100 Subject: [PATCH 11/34] Began changes to update LLVM version to 18.1.8 --- CMakeLists.txt | 24 +++++++------------ configs/a64fx_SME.yaml | 1 + test/regression/RegressionTest.cc | 11 +++++++++ test/regression/RegressionTest.hh | 1 + .../aarch64/AArch64RegressionTest.hh | 4 +++- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2fd31cc01..436462b726 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,21 +14,12 @@ macro(FetchContent_MakeAvailable_Args NAME ARGS) endif() endmacro() -# Need an additional macro for LLVM as a sub-directory needs to be targeted for llvm-14.0.5 -macro(FetchContent_MakeAvailable_SubDir_Args NAME SUBDIR ARGS) - FetchContent_GetProperties(${NAME}) - if(NOT ${NAME}_POPULATED) - FetchContent_Populate(${NAME}) - add_subdirectory(${${NAME}_SOURCE_DIR}/${SUBDIR}/ ${${NAME}_BINARY_DIR} ${ARGS}) - endif() -endmacro() - # we don't use git for LLVM here as it clones the entire LLVM repo which takes too long and we only need a small part of it FetchContent_Declare( llvm - URL https://github.com/llvm/llvm-project/releases/download/llvmorg-14.0.5/llvm-14.0.5.src.tar.xz - URL_HASH MD5=6bd202e403d950c78985048ce499a518 + URL https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.8/llvm-18.1.8.src.tar.xz + URL_HASH MD5=54e694dea8ba19db4a07d14507008e0b ) FetchContent_Declare( @@ -149,14 +140,17 @@ if(SIMENG_ENABLE_TESTS) find_package(LLVM REQUIRED CONFIG NO_CMAKE_BUILDS_PATH) # Check LLVM version - if ((${LLVM_PACKAGE_VERSION} VERSION_LESS "8.0") OR (${LLVM_PACKAGE_VERSION} VERSION_GREATER_EQUAL "14.1")) - message(FATAL_ERROR "LLVM version must be >= 8.0 and <= 14.0") + if ((${LLVM_PACKAGE_VERSION} VERSION_LESS "8.0") OR (${LLVM_PACKAGE_VERSION} VERSION_GREATER_EQUAL "18.2")) + message(FATAL_ERROR "LLVM version must be >= 8.0 and <= 18.2") endif() # Print message containing if the full test suite will run if (${LLVM_PACKAGE_VERSION} VERSION_LESS "14.0") message(STATUS "LLVM version does not support AArch64 extensions SME or SVE2. These test suites will be skipped.") endif() + if (${LLVM_PACKAGE_VERSION} VERSION_LESS "18.0") + message(STATUS "LLVM version does not support AArch64 extensions SME2. These test suites will be skipped.") + endif() else() @@ -186,9 +180,9 @@ if(SIMENG_ENABLE_TESTS) set(LLVM_ENABLE_WARNINGS OFF) # XXX all LLVM specific cmake variables must be set BEFORE FetchContent_MakeAvailable otherwise they have no effect - FetchContent_MakeAvailable_SubDir_Args(llvm llvm-14.0.5.src EXCLUDE_FROM_ALL) # make sure we get the headers too - include_directories("${llvm_BINARY_DIR}/include" "${llvm_SOURCE_DIR}/include") + FetchContent_MakeAvailable_Args(llvm EXCLUDE_FROM_ALL) + include_directories("${llvm_BINARY_DIR}/include/llvm" "${llvm_SOURCE_DIR}/include/llvm") find_package(LLVM REQUIRED CONFIG NO_DEFAULT_PATH PATHS "${llvm_BINARY_DIR}/lib/cmake/llvm") diff --git a/configs/a64fx_SME.yaml b/configs/a64fx_SME.yaml index b10f955f6f..966c86512f 100644 --- a/configs/a64fx_SME.yaml +++ b/configs/a64fx_SME.yaml @@ -22,6 +22,7 @@ Register-Set: Predicate-Count: 48 Conditional-Count: 128 Matrix-Count: 2 + # Table-Count: 16 Pipeline-Widths: Commit: 4 FrontEnd: 4 diff --git a/test/regression/RegressionTest.cc b/test/regression/RegressionTest.cc index 216a2c9297..4d2de4e440 100644 --- a/test/regression/RegressionTest.cc +++ b/test/regression/RegressionTest.cc @@ -239,8 +239,13 @@ void RegressionTest::assemble(const char* source, const char* triple, ASSERT_NE(asmBackend, nullptr) << "Failed to create LLVM asm backend"; // Create MC code emitter +#if SIMENG_LLVM_VERSION < 15 std::unique_ptr codeEmitter( target->createMCCodeEmitter(*instrInfo, *regInfo, context)); +#else + std::unique_ptr codeEmitter( + target->createMCCodeEmitter(*instrInfo, context)); +#endif ASSERT_NE(codeEmitter, nullptr) << "Failed to create LLVM code emitter"; // Create MC object writer @@ -275,8 +280,14 @@ void RegressionTest::assemble(const char* source, const char* triple, // Create ELF object from output llvm::StringRef objectData = objectStream.str(); +#if SIMENG_LLVM_VERSION < 15 auto elfOrErr = llvm::object::ELFFile< llvm::object::ELFType>::create(objectData); +#else + auto elfOrErr = + llvm::object::ELFFile>::create(objectData); +#endif ASSERT_FALSE(elfOrErr.takeError()) << "Failed to load ELF object"; auto& elf = *elfOrErr; diff --git a/test/regression/RegressionTest.hh b/test/regression/RegressionTest.hh index a110ff80d1..661584cd43 100644 --- a/test/regression/RegressionTest.hh +++ b/test/regression/RegressionTest.hh @@ -44,6 +44,7 @@ #if SIMENG_LLVM_VERSION < 14 #include "llvm/Support/TargetRegistry.h" #else +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/TargetRegistry.h" #endif diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index a0c06731c7..b8f20725dc 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -240,8 +240,10 @@ class AArch64RegressionTest : public RegressionTest { std::string getSubtargetFeaturesString() { #if SIMENG_LLVM_VERSION < 14 return "+sve,+lse"; -#else +#elif SIMENG_LLVM_VERSION < 18 return "+sve,+lse,+sve2,+sme,+sme-f64"; +#else + return "+sve,+lse,+sve2,+sme,+sme-f64f64,+sme-i16i64,+sme2"; #endif } From 0b9e7b8abc220a3b80a3614b929fb42c4972ff9e Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Tue, 17 Sep 2024 10:51:00 +0100 Subject: [PATCH 12/34] Updated valid SVE vector lengths inline with Arm A profile reference manual DDI0487K issue K.a 20th March 2024. --- src/lib/config/ModelConfig.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/config/ModelConfig.cc b/src/lib/config/ModelConfig.cc index 67cb6a0453..a192049a49 100644 --- a/src/lib/config/ModelConfig.cc +++ b/src/lib/config/ModelConfig.cc @@ -370,8 +370,7 @@ void ModelConfig::setExpectations(bool isDefault) { expectations_["Core"].addChild(ExpectationNode::createExpectation( 128, "Vector-Length", true)); expectations_["Core"]["Vector-Length"].setValueSet( - std::vector{128, 256, 384, 512, 640, 768, 896, 1024, 1152, - 1280, 1408, 1536, 1664, 1792, 1920, 2048}); + std::vector{128, 256, 512, 1024, 2048}); expectations_["Core"].addChild(ExpectationNode::createExpectation( 128, "Streaming-Vector-Length", true)); From 4f851b6ec96fcdb115c86a9c89410024030c74e1 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Tue, 17 Sep 2024 13:08:27 +0100 Subject: [PATCH 13/34] Added table physical register count to model config. --- configs/a64fx_SME.yaml | 2 +- src/include/simeng/arch/aarch64/ArchInfo.hh | 5 +++-- src/lib/config/ModelConfig.cc | 5 +++++ test/regression/aarch64/AArch64RegressionTest.hh | 2 +- test/unit/aarch64/ArchInfoTest.cc | 4 ++-- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/configs/a64fx_SME.yaml b/configs/a64fx_SME.yaml index 966c86512f..47c3951e2b 100644 --- a/configs/a64fx_SME.yaml +++ b/configs/a64fx_SME.yaml @@ -22,7 +22,7 @@ Register-Set: Predicate-Count: 48 Conditional-Count: 128 Matrix-Count: 2 - # Table-Count: 16 + Table-Count: 8 Pipeline-Widths: Commit: 4 FrontEnd: 4 diff --git a/src/include/simeng/arch/aarch64/ArchInfo.hh b/src/include/simeng/arch/aarch64/ArchInfo.hh index e6280561c8..0c7676421a 100644 --- a/src/include/simeng/arch/aarch64/ArchInfo.hh +++ b/src/include/simeng/arch/aarch64/ArchInfo.hh @@ -38,6 +38,7 @@ class ArchInfo : public simeng::arch::ArchInfo { uint16_t predCount = regConfig["Predicate-Count"].as(); uint16_t condCount = regConfig["Conditional-Count"].as(); uint16_t matCount = regConfig["Matrix-Count"].as(); + uint16_t tabCount = regConfig["Table-Count"].as(); // Matrix-Count multiplied by (SVL/8) as internal representation of ZA is a // block of row-vector-registers. Therefore, we need to convert physical // counts from whole-ZA to rows-in-ZA. @@ -48,14 +49,14 @@ class ArchInfo : public simeng::arch::ArchInfo { {1, condCount}, {8, static_cast(sysRegisterEnums_.size())}, {256, matCount}, - {64, 1}}; + {64, tabCount}}; physRegQuantities_ = {gpCount, fpCount, predCount, condCount, static_cast(sysRegisterEnums_.size()), matCount, - 1}; + tabCount}; } /** Get the set of system register enums currently supported. */ diff --git a/src/lib/config/ModelConfig.cc b/src/lib/config/ModelConfig.cc index a192049a49..a319d4d510 100644 --- a/src/lib/config/ModelConfig.cc +++ b/src/lib/config/ModelConfig.cc @@ -443,6 +443,11 @@ void ModelConfig::setExpectations(bool isDefault) { ExpectationNode::createExpectation(1, "Matrix-Count", true)); expectations_["Register-Set"]["Matrix-Count"].setValueBounds( 1, UINT16_MAX); + + expectations_["Register-Set"].addChild( + ExpectationNode::createExpectation(1, "Table-Count", true)); + expectations_["Register-Set"]["Table-Count"].setValueBounds( + 1, UINT16_MAX); } else if (isa_ == ISA::RV64) { // TODO: Reduce to 32 once renaming issue has been sorted. Also replace in // ConfigTest. diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index b8f20725dc..8ce53c16b2 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -76,7 +76,7 @@ inline std::string paramToString( inline std::vector> genCoreTypeVLPairs( CoreType type) { std::vector> coreVLPairs; - for (uint64_t i = 128; i <= 2048; i += 128) { + for (uint64_t i = 128; i <= 2048; i *= 2) { coreVLPairs.push_back(std::make_tuple( type, "{Core: {Vector-Length: " + std::to_string(i) + diff --git a/test/unit/aarch64/ArchInfoTest.cc b/test/unit/aarch64/ArchInfoTest.cc index 511e0fdd66..39e25a0bd1 100644 --- a/test/unit/aarch64/ArchInfoTest.cc +++ b/test/unit/aarch64/ArchInfoTest.cc @@ -41,10 +41,10 @@ class AArch64ArchInfoTest : public ::testing::Test { {1, 128}, {8, static_cast(sysRegisterEnums.size())}, {256, 128}, - {64, 1}}; + {64, 8}}; const std::vector physRegQuants = { - 96, 128, 48, 128, static_cast(sysRegisterEnums.size()), 128, 1}; + 96, 128, 48, 128, static_cast(sysRegisterEnums.size()), 128, 8}; }; // Test for the getSysRegEnums() function From df5e6869337c0626cd0c7b464624afaef1692bda Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Tue, 17 Sep 2024 14:21:00 +0100 Subject: [PATCH 14/34] Fixed integration test. --- test/integration/ConfigTest.cc | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/test/integration/ConfigTest.cc b/test/integration/ConfigTest.cc index 805294a725..432f307628 100644 --- a/test/integration/ConfigTest.cc +++ b/test/integration/ConfigTest.cc @@ -32,7 +32,8 @@ TEST(ConfigTest, Default) { {32, 17}, {1, 1}, {8, static_cast(sysRegisterEnums.size())}, - {256, 16}}; + {256, 16}, + {64, 1}}; EXPECT_EQ(simeng::config::SimInfo::getArchRegStruct(), archRegStruct); // Test that default config generated matches for AArch64 ISA @@ -47,26 +48,26 @@ TEST(ConfigTest, Default) { "5\n'Process-Image':\n 'Heap-Size': 100000\n 'Stack-Size': " "100000\n'Register-Set':\n 'GeneralPurpose-Count': 38\n " "'FloatingPoint/SVE-Count': 38\n 'Predicate-Count': 17\n " - "'Conditional-Count': 1\n 'Matrix-Count': 1\n'Pipeline-Widths':\n " - "Commit: 1\n FrontEnd: 1\n 'LSQ-Completion': 1\n'Queue-Sizes':\n ROB: " - "32\n Load: 16\n Store: 16\n'Port-Allocator':\n Type: " - "Balanced\n'Branch-Predictor':\n Type: Perceptron\n " - "'BTB-Tag-Bits': 8\n 'Global-History-Length': 8\n 'RAS-entries': " - "8\n'L1-Data-Memory':\n 'Interface-Type': " + "'Conditional-Count': 1\n 'Matrix-Count': 1\n 'Table-Count': " + "1\n'Pipeline-Widths':\n Commit: 1\n FrontEnd: 1\n 'LSQ-Completion': " + "1\n'Queue-Sizes':\n ROB: 32\n Load: 16\n Store: " + "16\n'Port-Allocator':\n Type: Balanced\n'Branch-Predictor':\n Type: " + "Perceptron\n 'BTB-Tag-Bits': 8\n 'Global-History-Length': 8\n " + "'RAS-entries': 8\n'L1-Data-Memory':\n 'Interface-Type': " "Flat\n'L1-Instruction-Memory':\n 'Interface-Type': " "Flat\n'LSQ-L1-Interface':\n 'Access-Latency': 4\n Exclusive: 0\n " "'Load-Bandwidth': 32\n 'Store-Bandwidth': 32\n " "'Permitted-Requests-Per-Cycle': 1\n 'Permitted-Loads-Per-Cycle': 1\n " "'Permitted-Stores-Per-Cycle': 1\nPorts:\n 0:\n Portname: 0\n " "'Instruction-Group-Support':\n - ALL\n " - "'Instruction-Opcode-Support':\n - 6343\n " + "'Instruction-Opcode-Support':\n - 8232\n " "'Instruction-Group-Support-Nums':\n - " "86\n'Reservation-Stations':\n 0:\n Size: 32\n 'Dispatch-Rate': " "4\n Ports:\n - 0\n 'Port-Nums':\n - " "0\n'Execution-Units':\n 0:\n Pipelined: 1\n 'Blocking-Groups':\n " " - NONE\n 'Blocking-Group-Nums':\n - 87\nLatencies:\n 0:\n " " 'Instruction-Groups':\n - NONE\n 'Instruction-Opcodes':\n " - " - 6343\n 'Execution-Latency': 1\n 'Execution-Throughput': 1\n " + " - 8232\n 'Execution-Latency': 1\n 'Execution-Throughput': 1\n " " 'Instruction-Group-Nums':\n - 87\n'CPU-Info':\n " "'Generate-Special-Dir': 1\n 'Special-File-Dir-Path': " SIMENG_BUILD_DIR "/specialFiles/\n 'Core-Count': 1\n 'Socket-Count': 1\n SMT: 1\n " @@ -390,7 +391,8 @@ TEST(ConfigTest, configFromFile) { {32, 17}, {1, 1}, {8, static_cast(sysRegisterEnums.size())}, - {256, 16}}; + {256, 16}, + {64, 1}}; EXPECT_EQ(simeng::config::SimInfo::getArchRegStruct(), archRegStruct); std::vector physRegStruct = { {8, 96}, @@ -398,10 +400,11 @@ TEST(ConfigTest, configFromFile) { {32, 48}, {1, 128}, {8, static_cast(sysRegisterEnums.size())}, - {256, 16}}; + {256, 16}, + {64, 1}}; EXPECT_EQ(simeng::config::SimInfo::getPhysRegStruct(), physRegStruct); std::vector physRegQuants = { - 96, 128, 48, 128, static_cast(sysRegisterEnums.size()), 16}; + 96, 128, 48, 128, static_cast(sysRegisterEnums.size()), 16, 1}; EXPECT_EQ(simeng::config::SimInfo::getPhysRegQuantities(), physRegQuants); } // getPhysRegStruct() From 11fc242bd0e8a7fdeed21f894f3aa89ac71995c1 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Tue, 17 Sep 2024 14:44:08 +0100 Subject: [PATCH 15/34] Added return identification properly. --- src/lib/arch/aarch64/Instruction_decode.cc | 27 ++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 077299b3d8..6206255220 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -423,6 +423,9 @@ void Instruction::decode() { knownOffset_ = metadata_.operands[2].imm; break; } + case Opcode::AArch64_RET: // ret {xt} + branchType_ = BranchType::Return; + break; default: break; } @@ -495,14 +498,14 @@ void Instruction::decode() { } if (metadata_.opcode == Opcode::AArch64_LDRXl || metadata_.opcode == Opcode::AArch64_LDRSWl) { - // Literal loads aren't flagged as having a memory operand, so these must be - // marked as loads manually + // Literal loads aren't flagged as having a memory operand, so these must + // be marked as loads manually setInstructionType(InsnType::isLoad); } // Identify Logical (bitwise) instructions - // Opcode prefix-overlaps have been commented out but left in for clarity what - // is searched for. + // Opcode prefix-overlaps have been commented out but left in for clarity + // what is searched for. if (metadata_.mnemonic.find("and") == 0 || metadata_.mnemonic.find("bic") == 0 || metadata_.mnemonic.find("bif") == 0 || @@ -528,8 +531,8 @@ void Instruction::decode() { } // Identify comparison insturctions (excluding atomic LD-CMP-STR) - // Opcode prefix-overlaps have been commented out but left in for clarity what - // is searched for. + // Opcode prefix-overlaps have been commented out but left in for clarity + // what is searched for. if (metadata_.mnemonic.find("ccmn") == 0 || metadata_.mnemonic.find("cmn") == 0 || metadata_.mnemonic.find("cmp") == 0 || @@ -585,8 +588,8 @@ void Instruction::decode() { } // Identify convert instructions - // Opcode prefix-overlaps have been commented out but left in for clarity what - // is searched for. + // Opcode prefix-overlaps have been commented out but left in for clarity + // what is searched for. if (metadata_.mnemonic.find("bfcvt") == 0 || // metadata_.mnemonic.find("bfcvtn") == 0 || // metadata_.mnemonic.find("bfcvtnt") == 0 || @@ -637,8 +640,8 @@ void Instruction::decode() { } // Identify divide or square root operations - // Opcode prefix-overlaps have been commented out but left in for clarity what - // is searched for. + // Opcode prefix-overlaps have been commented out but left in for clarity + // what is searched for. if (metadata_.mnemonic.find("sdiv") == 0 || // metadata_.mnemonic.find("sdivr") == 0 || metadata_.mnemonic.find("udiv") == 0 || @@ -655,8 +658,8 @@ void Instruction::decode() { } // Identify multiply operations - // Opcode prefix-overlaps have been commented out but left in for clarity what - // is searched for. + // Opcode prefix-overlaps have been commented out but left in for clarity + // what is searched for. if (metadata_.mnemonic.find("bfmmla") == 0 || metadata_.mnemonic.find("bfmul") == 0 || // The non-complete opcode prefix `bfml` only yields multiply uops From 3267c0d2492c936170737db5d119b1d4881255c0 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Tue, 17 Sep 2024 18:00:15 +0100 Subject: [PATCH 16/34] Fixed RV64 regression tests / compressed instruction implementation. --- src/lib/arch/riscv/InstructionMetadata.cc | 48 ++--------------------- src/lib/arch/riscv/Instruction_address.cc | 6 +-- 2 files changed, 7 insertions(+), 47 deletions(-) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index 85d27abcfa..ad25f8cc2a 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -33,6 +33,10 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) std::memcpy(operands, insn.detail->riscv.operands, sizeof(cs_riscv_op) * operandCount); + std::cerr << std::hex << (unsigned)encoding[0] << " " << (unsigned)encoding[1] + << " " << (unsigned)encoding[2] << " " << (unsigned)encoding[3] + << std::dec << std::endl; + convertCompressedInstruction(insn); alterPseudoInstructions(insn); } @@ -457,23 +461,6 @@ void InstructionMetadata::duplicateFirstOp() { operandCount = 3; } -void InstructionMetadata::createMemOpPosOne() { - // Given register sequence {Op_a, imm, reg} return {Op_a, mem, _} - assert(operands[1].type == RISCV_OP_IMM && - "Incorrect operand type when creating memory operand"); - assert(operands[2].type == RISCV_OP_REG && - "Incorrect operand type when creating memory operand"); - - cs_riscv_op temp; - temp.type = RISCV_OP_MEM; - temp.mem.base = operands[2].reg; - temp.mem.disp = operands[1].imm; - - operands[1] = temp; - - operandCount = 2; -} - void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { if (insnLengthBytes_ != 2) { return; @@ -533,9 +520,6 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { opcode = Opcode::RISCV_LD; - // Create operand formatted like LD instruction - createMemOpPosOne(); - break; } case Opcode::RISCV_C_ADDI4SPN: @@ -600,17 +584,12 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { opcode = Opcode::RISCV_SD; - // Create operand formatted like SD instruction - createMemOpPosOne(); - break; } case Opcode::RISCV_C_SWSP: { // sw rs2, offset[7:2](x2) opcode = Opcode::RISCV_SW; - createMemOpPosOne(); - break; } case Opcode::RISCV_C_ADD: @@ -642,9 +621,6 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { opcode = Opcode::RISCV_LD; - // Create operand formatted like LD instruction - createMemOpPosOne(); - break; } case Opcode::RISCV_C_ADDI: { @@ -678,8 +654,6 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // sd rs2 ′ , offset[7:3](rs1 ′) opcode = Opcode::RISCV_SD; - // Create operand formatted like SD instruction - createMemOpPosOne(); break; } @@ -728,8 +702,6 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { opcode = Opcode::RISCV_LW; - createMemOpPosOne(); - break; } case Opcode::RISCV_C_FLDSP: @@ -737,16 +709,12 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { // fld rd, offset[8:3](x2) opcode = Opcode::RISCV_FLD; - createMemOpPosOne(); - break; case Opcode::RISCV_C_SW: { // sw rs2 ′, offset[6:2](rs1 ′) opcode = Opcode::RISCV_SW; - createMemOpPosOne(); - break; } case Opcode::RISCV_C_J: @@ -793,8 +761,6 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { opcode = Opcode::RISCV_LW; - createMemOpPosOne(); - break; case Opcode::RISCV_C_SRLI: // srli rd ′ , rd ′ , shamt[5:0] @@ -881,8 +847,6 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { opcode = Opcode::RISCV_FSD; - createMemOpPosOne(); - break; case Opcode::RISCV_C_FLD: // TODO rv64dc ONLY, make check for this once RV32 implemented @@ -890,8 +854,6 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { opcode = Opcode::RISCV_FLD; - createMemOpPosOne(); - break; case Opcode::RISCV_C_FSDSP: // TODO rv64dc ONLY, make check for this once RV32 implemented @@ -899,8 +861,6 @@ void InstructionMetadata::convertCompressedInstruction(const cs_insn& insn) { opcode = Opcode::RISCV_FSD; - createMemOpPosOne(); - break; case Opcode::RISCV_C_SUBW: // TODO rv64 ONLY, make check for this once RV32 implemented diff --git a/src/lib/arch/riscv/Instruction_address.cc b/src/lib/arch/riscv/Instruction_address.cc index 3a9fce30ff..0d6bbb9843 100644 --- a/src/lib/arch/riscv/Instruction_address.cc +++ b/src/lib/arch/riscv/Instruction_address.cc @@ -17,7 +17,7 @@ span Instruction::generateAddresses() { isInstruction(InsnType::isAtomic)) { // Atomics // Metadata operands[2] corresponds to instruction sourceRegValues[1] - assert(metadata_.operands[2].type == RISCV_OP_REG && + assert(metadata_.operands[2].type == RISCV_OP_MEM && "metadata_ operand not of correct type during RISC-V address " "generation"); address = sourceValues_[1].get(); @@ -25,14 +25,14 @@ span Instruction::generateAddresses() { isInstruction(InsnType::isAtomic)) { // Load reserved // Metadata operands[1] corresponds to instruction sourceRegValues[0] - assert(metadata_.operands[1].type == RISCV_OP_REG && + assert(metadata_.operands[1].type == RISCV_OP_MEM && "metadata_ operand not of correct type during RISC-V address " "generation"); address = sourceValues_[0].get(); } else if (isInstruction(InsnType::isStore) && isInstruction(InsnType::isAtomic)) { // Store conditional - assert(metadata_.operands[2].type == RISCV_OP_REG && + assert(metadata_.operands[2].type == RISCV_OP_MEM && "metadata_ operand not of correct type during RISC-V address " "generation"); address = sourceValues_[1].get(); From f537e2046e12db4f0a05d35912065b63f792b75f Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Tue, 17 Sep 2024 18:04:37 +0100 Subject: [PATCH 17/34] Updated aarch64 comment. --- src/lib/arch/aarch64/InstructionMetadata.hh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/arch/aarch64/InstructionMetadata.hh b/src/lib/arch/aarch64/InstructionMetadata.hh index 3100606d86..88a03535fd 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.hh +++ b/src/lib/arch/aarch64/InstructionMetadata.hh @@ -92,8 +92,10 @@ struct InstructionMetadata { /** Whether this instruction is an alias. */ bool isAlias; + // Temp fix until Capstone updates as MAX_OPERANDS too small for SME2 /** The explicit operands. */ - cs_aarch64_op operands[MAX_OPERANDS * 2]; // Temp fix until Capstone updates + cs_aarch64_op operands[MAX_OPERANDS * 2]; + /** The number of explicit operands. */ uint8_t operandCount; From 08f47d38b84d46427fc8fefe553a8780417207ce Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 19 Sep 2024 10:19:21 +0100 Subject: [PATCH 18/34] Removed print out. --- src/lib/arch/riscv/InstructionMetadata.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/arch/riscv/InstructionMetadata.cc b/src/lib/arch/riscv/InstructionMetadata.cc index ad25f8cc2a..0d31ec00e0 100644 --- a/src/lib/arch/riscv/InstructionMetadata.cc +++ b/src/lib/arch/riscv/InstructionMetadata.cc @@ -33,10 +33,6 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) std::memcpy(operands, insn.detail->riscv.operands, sizeof(cs_riscv_op) * operandCount); - std::cerr << std::hex << (unsigned)encoding[0] << " " << (unsigned)encoding[1] - << " " << (unsigned)encoding[2] << " " << (unsigned)encoding[3] - << std::dec << std::endl; - convertCompressedInstruction(insn); alterPseudoInstructions(insn); } From a148bd216e1e9cffdbf80c535a501174168e2317 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 26 Sep 2024 12:01:58 +0100 Subject: [PATCH 19/34] Added new capstone archs to non-build list in cmake. --- CMakeLists.txt | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 436462b726..5ae6824d28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,20 +80,26 @@ set(CAPSTONE_BUILD_SHARED OFF CACHE BOOL "Disable Capstone shared library") set(CAPSTONE_BUILD_CSTOOL OFF CACHE BOOL "Disable cstool build") set(CAPSTONE_INSTALL OFF CACHE BOOL "Disable install of capstone") -set(CAPSTONE_ARM_SUPPORT OFF CACHE BOOL "Disable A32 support") +set(CAPSTONE_ARM_SUPPORT OFF CACHE BOOL "Disable Arm32 support") set(CAPSTONE_MIPS_SUPPORT OFF CACHE BOOL "Disable MIPS support") -set(CAPSTONE_X86_SUPPORT OFF CACHE BOOL "Disable x86 support") set(CAPSTONE_PPC_SUPPORT OFF CACHE BOOL "Disable PowerPC support") +set(CAPSTONE_X86_SUPPORT OFF CACHE BOOL "Disable x86 support") set(CAPSTONE_SPARC_SUPPORT OFF CACHE BOOL "Disable Sparc support") -set(CAPSTONE_SYSZ_SUPPORT OFF CACHE BOOL "Disable SystemZ support") +set(CAPSTONE_SYSTEMZ_SUPPORT OFF CACHE BOOL "Disable SystemZ support") set(CAPSTONE_XCORE_SUPPORT OFF CACHE BOOL "Disable XCore support") set(CAPSTONE_M68K_SUPPORT OFF CACHE BOOL "Disable M68K support") -set(CAPSTONE_TMS320C64X_SUPPORT OFF CACHE BOOL "Disable TMS320C64x") +set(CAPSTONE_TMS320C64X_SUPPORT OFF CACHE BOOL "Disable TMS320C64x support") set(CAPSTONE_M680X_SUPPORT OFF CACHE BOOL "Disable M680x support") set(CAPSTONE_EVM_SUPPORT OFF CACHE BOOL "Disable EVM support") -set(CAPSTONE_MOS65XX_SUPPORT OFF CACHE BOOL "Disable MSO65XX support") set(CAPSTONE_WASM_SUPPORT OFF CACHE BOOL "Disable WASM support") +set(CAPSTONE_MOS65XX_SUPPORT OFF CACHE BOOL "Disable MSO65XX support") set(CAPSTONE_BPF_SUPPORT OFF CACHE BOOL "Disable BPF support") +set(CAPSTONE_SH_SUPPORT OFF CACHE BOOL "Disable SH support") +set(CAPSTONE_TRICORE_SUPPORT OFF CACHE BOOL "Disable TriCore support") +set(CAPSTONE_ALPHA_SUPPORT OFF CACHE BOOL "Disable Alpha support") +set(CAPSTONE_HPPA_SUPPORT OFF CACHE BOOL "Disable HPPA support") +set(CAPSTONE_LOONGARCH_SUPPORT OFF CACHE BOOL "Disable LoongArch support") + FetchContent_MakeAvailable_Args(capstone-lib EXCLUDE_FROM_ALL) include_directories("${capstone_BINARY_DIR}/include" "${capstone_SOURCE_DIR}/include") From 72d990b8bfbf2a1ef5c756cd12e6821addccfbf3 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Tue, 1 Oct 2024 17:42:45 +0100 Subject: [PATCH 20/34] Fixed microDecode to accomodate new sysop member of aarch64_cs_op. --- src/include/simeng/arch/aarch64/MicroDecoder.hh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/simeng/arch/aarch64/MicroDecoder.hh b/src/include/simeng/arch/aarch64/MicroDecoder.hh index 18865167f1..c9a0d88c6f 100644 --- a/src/include/simeng/arch/aarch64/MicroDecoder.hh +++ b/src/include/simeng/arch/aarch64/MicroDecoder.hh @@ -94,6 +94,7 @@ class MicroDecoder { AARCH64_OP_INVALID, false, {}, + {}, CS_AC_READ, false}; From 26f4155951d90bcdb7d7d3e9516823599f70fdaa Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Wed, 2 Oct 2024 10:57:04 +0100 Subject: [PATCH 21/34] Updated aarch64 metadata. --- src/lib/arch/aarch64/InstructionMetadata.cc | 95 +++++++++++---------- src/lib/arch/aarch64/InstructionMetadata.hh | 3 +- 2 files changed, 53 insertions(+), 45 deletions(-) diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index 9547b841b2..5227b99573 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -31,16 +31,24 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) std::memcpy(operands, insn.detail->aarch64.operands, sizeof(cs_aarch64_op) * operandCount); + // std::cerr << mnemonic << " " << operandStr << " ---- " << std::hex + // << (unsigned)encoding[0] << " " << (unsigned)encoding[1] << " " + // << (unsigned)encoding[2] << " " << (unsigned)encoding[3] << + // std::dec + // << " ------ implicit dests = " << + // (unsigned)implicitDestinationCount + // << ", implicit src = " << (unsigned)implicitSourceCount + // << std::endl; // Fix some inaccuracies in the decoded metadata switch (opcode) { - case Opcode::AArch64_BLR: // Example bytecode - 20003fd6 - // Incorrectly implicitly reads from SP - implicitSourceCount--; - break; - case Opcode::AArch64_MRS: // Example bytecode - 42d03bd5 - // Incorrectly implicitly writes to NZCV - implicitDestinationCount--; - break; + // case Opcode::AArch64_BLR: // Example bytecode - 20003fd6 + // // Incorrectly implicitly reads from SP + // implicitSourceCount--; + // break; + // case Opcode::AArch64_MRS: // Example bytecode - 42d03bd5 + // // Incorrectly implicitly writes to NZCV + // implicitDestinationCount--; + // break; case Opcode::AArch64_FMOVXDHighr: // Example bytecode - 4100af9e // FMOVXDHighr incorrectly flags destination as WRITE only operands[0].access = CS_AC_READ | CS_AC_WRITE; @@ -62,6 +70,7 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[1].type = AARCH64_OP_REG; operands[1].access = CS_AC_READ; operands[1].reg = operands[1].mem.base; + operands[1].vas = operands[1].vas; operands[2].type = AARCH64_OP_REG; operands[2].access = CS_AC_READ; operands[2].reg = operands[1].mem.index; @@ -71,11 +80,8 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) } case Opcode::AArch64_CASALW: // Example bytecode - 02fce188 case Opcode::AArch64_CASALX: - // Correct access types - operandCount = 3; - operands[0].access = CS_AC_READ; - operands[1].access = CS_AC_READ; - operands[2].access = CS_AC_READ; + // Remove implicit destination (MEM base reg) + implicitDestinationCount = 0; break; case Opcode::AArch64_ADD_ZI_B: // Example bytecode - 00c12025 case Opcode::AArch64_ADD_ZI_D: @@ -84,12 +90,13 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // Incorrect access types operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; - // If LSL #8 is present then immediate is not properly set. - // LSL is automatically applied to the imm for these instructions - std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); - if (tmpOpStr[1] == 'x') { - operands[2].imm = static_cast(std::stoi(tmpOpStr, 0, 16)); - } + // // If LSL #8 is present then immediate is not properly set. + // // LSL is automatically applied to the imm for these instructions + // // std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); + // // if (tmpOpStr[1] == 'x') { + // // operands[2].imm = static_cast(std::stoi(tmpOpStr, 0, + // 16)); + // // } break; } case Opcode::AArch64_SMAX_ZI_B: @@ -114,18 +121,18 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ; - // Extract FP constant imm - aarch64_exactfpimm exactFp = operands[3].sysop.imm.exactfpimm; - if (exactFp == AARCH64_EXACTFPIMM_HALF) - operands[3].fp = 0.5; - else if (exactFp == AARCH64_EXACTFPIMM_ONE) - operands[3].fp = 1.0; - else if (exactFp == AARCH64_EXACTFPIMM_TWO) - operands[3].fp = 2.0; - else if (exactFp == AARCH64_EXACTFPIMM_ZERO) - operands[3].fp = 0.0; - else - assert(false && "Invalid FP immidate contant."); + // // Extract FP constant imm + // aarch64_exactfpimm exactFp = operands[3].sysop.imm.exactfpimm; + // if (exactFp == AARCH64_EXACTFPIMM_HALF) + // operands[3].fp = 0.5; + // else if (exactFp == AARCH64_EXACTFPIMM_ONE) + // operands[3].fp = 1.0; + // else if (exactFp == AARCH64_EXACTFPIMM_TWO) + // operands[3].fp = 2.0; + // else if (exactFp == AARCH64_EXACTFPIMM_ZERO) + // operands[3].fp = 0.0; + // else + // assert(false && "Invalid FP immidate contant."); break; } case Opcode::AArch64_AND_ZPmZ_D: // Example bytecode - 4901da04 @@ -186,18 +193,20 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].access = CS_AC_READ; operands[3].access = CS_AC_READ; break; - case Opcode::AArch64_CPY_ZPzI_B: - case Opcode::AArch64_CPY_ZPzI_D: - case Opcode::AArch64_CPY_ZPzI_H: // Example bytecode - 01215005 - case Opcode::AArch64_CPY_ZPzI_S: { - // Imm value not correctly set - std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); - auto value = std::stoi(tmpOpStr, 0, 16); - // Ensure #imm is kept within the spec defined limits - operands[2].imm = tmpOpStr.length() == 4 ? static_cast(value) - : static_cast(value); - break; - } + // case Opcode::AArch64_CPY_ZPzI_B: + // case Opcode::AArch64_CPY_ZPzI_D: + // case Opcode::AArch64_CPY_ZPzI_H: // Example bytecode - 01215005 + // case Opcode::AArch64_CPY_ZPzI_S: { + // // Imm value not correctly set + // std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); + // auto value = std::stoi(tmpOpStr, 0, 16); + // // Ensure #imm is kept within the spec defined limits + // operands[2].imm = tmpOpStr.length() == 4 ? + // static_cast(value) + // : + // static_cast(value); + // break; + // } case Opcode::AArch64_ZERO_M: { // Operands often mangled from ZA tile overlap aliasing in decode. // Need to re-extract relevant tiles from operandStr diff --git a/src/lib/arch/aarch64/InstructionMetadata.hh b/src/lib/arch/aarch64/InstructionMetadata.hh index 88a03535fd..d905d93e4d 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.hh +++ b/src/lib/arch/aarch64/InstructionMetadata.hh @@ -92,9 +92,8 @@ struct InstructionMetadata { /** Whether this instruction is an alias. */ bool isAlias; - // Temp fix until Capstone updates as MAX_OPERANDS too small for SME2 /** The explicit operands. */ - cs_aarch64_op operands[MAX_OPERANDS * 2]; + cs_aarch64_op operands[MAX_OPERANDS]; /** The number of explicit operands. */ uint8_t operandCount; From a4aa026712e607a9eb83fd083e1f88fd179b40ee Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Wed, 2 Oct 2024 11:37:43 +0100 Subject: [PATCH 22/34] Final fixes for capstone update. --- src/lib/arch/aarch64/InstructionMetadata.cc | 94 +-------------------- test/regression/aarch64/instructions/sve.cc | 2 +- 2 files changed, 4 insertions(+), 92 deletions(-) diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index 5227b99573..c06bd61c7b 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -31,24 +31,8 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) std::memcpy(operands, insn.detail->aarch64.operands, sizeof(cs_aarch64_op) * operandCount); - // std::cerr << mnemonic << " " << operandStr << " ---- " << std::hex - // << (unsigned)encoding[0] << " " << (unsigned)encoding[1] << " " - // << (unsigned)encoding[2] << " " << (unsigned)encoding[3] << - // std::dec - // << " ------ implicit dests = " << - // (unsigned)implicitDestinationCount - // << ", implicit src = " << (unsigned)implicitSourceCount - // << std::endl; // Fix some inaccuracies in the decoded metadata switch (opcode) { - // case Opcode::AArch64_BLR: // Example bytecode - 20003fd6 - // // Incorrectly implicitly reads from SP - // implicitSourceCount--; - // break; - // case Opcode::AArch64_MRS: // Example bytecode - 42d03bd5 - // // Incorrectly implicitly writes to NZCV - // implicitDestinationCount--; - // break; case Opcode::AArch64_FMOVXDHighr: // Example bytecode - 4100af9e // FMOVXDHighr incorrectly flags destination as WRITE only operands[0].access = CS_AC_READ | CS_AC_WRITE; @@ -90,13 +74,6 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) // Incorrect access types operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; - // // If LSL #8 is present then immediate is not properly set. - // // LSL is automatically applied to the imm for these instructions - // // std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); - // // if (tmpOpStr[1] == 'x') { - // // operands[2].imm = static_cast(std::stoi(tmpOpStr, 0, - // 16)); - // // } break; } case Opcode::AArch64_SMAX_ZI_B: @@ -121,18 +98,6 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; operands[2].access = CS_AC_READ; - // // Extract FP constant imm - // aarch64_exactfpimm exactFp = operands[3].sysop.imm.exactfpimm; - // if (exactFp == AARCH64_EXACTFPIMM_HALF) - // operands[3].fp = 0.5; - // else if (exactFp == AARCH64_EXACTFPIMM_ONE) - // operands[3].fp = 1.0; - // else if (exactFp == AARCH64_EXACTFPIMM_TWO) - // operands[3].fp = 2.0; - // else if (exactFp == AARCH64_EXACTFPIMM_ZERO) - // operands[3].fp = 0.0; - // else - // assert(false && "Invalid FP immidate contant."); break; } case Opcode::AArch64_AND_ZPmZ_D: // Example bytecode - 4901da04 @@ -193,63 +158,10 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[2].access = CS_AC_READ; operands[3].access = CS_AC_READ; break; - // case Opcode::AArch64_CPY_ZPzI_B: - // case Opcode::AArch64_CPY_ZPzI_D: - // case Opcode::AArch64_CPY_ZPzI_H: // Example bytecode - 01215005 - // case Opcode::AArch64_CPY_ZPzI_S: { - // // Imm value not correctly set - // std::string tmpOpStr(operandStr.substr(operandStr.find("#") + 1)); - // auto value = std::stoi(tmpOpStr, 0, 16); - // // Ensure #imm is kept within the spec defined limits - // operands[2].imm = tmpOpStr.length() == 4 ? - // static_cast(value) - // : - // static_cast(value); - // break; - // } case Opcode::AArch64_ZERO_M: { - // Operands often mangled from ZA tile overlap aliasing in decode. - // Need to re-extract relevant tiles from operandStr - operandCount = 0; - size_t pos = operandStr.find("za", 0); - while (pos != std::string::npos) { - size_t pos_2 = operandStr.find(".", pos); - if (pos_2 != std::string::npos) { - char type = operandStr[pos_2 + 1]; - // Tile Number can only ever be 1 digit due to legal overlappings - uint8_t tileNum = std::stoi(operandStr.substr((pos + 2), 1)); - switch (type) { - case 'b': - operands[operandCount].sme.tile = AARCH64_REG_ZAB0; - break; - case 'h': - - operands[operandCount].sme.tile = - static_cast(AARCH64_REG_ZAH0 + tileNum); - break; - case 's': - - operands[operandCount].sme.tile = - static_cast(AARCH64_REG_ZAS0 + tileNum); - break; - case 'd': - - operands[operandCount].sme.tile = - static_cast(AARCH64_REG_ZAD0 + tileNum); - break; - case 'q': - - operands[operandCount].sme.tile = - static_cast(AARCH64_REG_ZAQ0 + tileNum); - break; - } - } else { - operands[operandCount].sme.tile = AARCH64_REG_ZA; - } - operands[operandCount].type = AARCH64_OP_SME; - operands[operandCount].access = CS_AC_WRITE; - operandCount++; - pos = operandStr.find("za", pos + 1); + // Incorrect access type: All are READ but should all be WRITE + for (int i = 0; i < operandCount; i++) { + operands[i].access = CS_AC_WRITE; } break; } diff --git a/test/regression/aarch64/instructions/sve.cc b/test/regression/aarch64/instructions/sve.cc index a7cee561e3..6a52d46b95 100644 --- a/test/regression/aarch64/instructions/sve.cc +++ b/test/regression/aarch64/instructions/sve.cc @@ -8010,7 +8010,7 @@ TEST_P(InstSve, zip) { } #if SIMENG_LLVM_VERSION >= 14 -// If LLVm version supports SVE2 : +// If LLVM version supports SVE2 : TEST_P(InstSve, psel) { RUN_AARCH64(R"( mov w13, #0 From ee07deb7aabb439aa72aebbea66cc9d3720361bd Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Wed, 2 Oct 2024 11:52:11 +0100 Subject: [PATCH 23/34] Attended PR comments. --- src/include/simeng/arch/aarch64/Instruction.hh | 2 +- src/lib/arch/aarch64/ExceptionHandler.cc | 2 +- src/lib/arch/aarch64/Instruction_decode.cc | 11 +++-------- src/lib/config/ModelConfig.cc | 8 ++++---- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index 5841965820..7dbe2a8cdd 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -89,7 +89,7 @@ struct MicroOpInfo { inline uint8_t getDataSize(cs_aarch64_op op) { // No V-register enum identifiers exist. Instead, depending on whether a full // or half vector is accessed, a Q or D register is used instead. - // A `is_vreg` bool in `op` defines if we are using v-vecotr registers. + // A `is_vreg` bool in `op` defines if we are using v-vector registers. if (op.is_vreg && ((AARCH64_REG_D0 <= op.reg && op.reg <= AARCH64_REG_D31) || (AARCH64_REG_Q0 <= op.reg && op.reg <= AARCH64_REG_Q31))) { AArch64Layout_VectorLayout vas = op.vas; diff --git a/src/lib/arch/aarch64/ExceptionHandler.cc b/src/lib/arch/aarch64/ExceptionHandler.cc index 3f606f4320..ae98dddb1a 100644 --- a/src/lib/arch/aarch64/ExceptionHandler.cc +++ b/src/lib/arch/aarch64/ExceptionHandler.cc @@ -658,7 +658,7 @@ bool ExceptionHandler::init() { if (metadata.opcode == Opcode::AArch64_MSR) { newSVCR = instruction_.getSourceOperands()[0].get(); } else if (metadata.opcode == Opcode::AArch64_MSRpstatesvcrImm1) { - // Enusre operand metadata is as expected + // Ensure operand metadata is as expected assert(metadata.operands[0].type == AARCH64_OP_SYSALIAS); assert(metadata.operands[0].sysop.sub_type == AARCH64_OP_SVCR); // extract SVCR bits diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 6206255220..cca5d27f9e 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -256,15 +256,10 @@ void Instruction::decode() { sourceRegisterCount_++; sourceOperandsPending_++; - // TODO checking of the shift type is a temporary fix to help reduce the - // chance of incorrectly reverted aliases from being mis-classified as - // isShift when op.shift contains garbage data. This should be reviewed - // on the next capstone update which should remove the need to revert - // aliasing - if (op.shift.type > aarch64_shifter::AARCH64_SFT_INVALID && - op.shift.type <= aarch64_shifter::AARCH64_SFT_ROR && + // Identify shift operands + if (op.shift.type != aarch64_shifter::AARCH64_SFT_INVALID && op.shift.value > 0) { - setInstructionType(InsnType::isShift); // Identify shift operands + setInstructionType(InsnType::isShift); } } } else if (op.type == AARCH64_OP_MEM) { // Memory operand diff --git a/src/lib/config/ModelConfig.cc b/src/lib/config/ModelConfig.cc index a319d4d510..0a8d3de34f 100644 --- a/src/lib/config/ModelConfig.cc +++ b/src/lib/config/ModelConfig.cc @@ -367,15 +367,15 @@ void ModelConfig::setExpectations(bool isDefault) { std::vector{false, true}); if (isa_ == ISA::AArch64) { - expectations_["Core"].addChild(ExpectationNode::createExpectation( + expectations_["Core"].addChild(ExpectationNode::createExpectation( 128, "Vector-Length", true)); expectations_["Core"]["Vector-Length"].setValueSet( - std::vector{128, 256, 512, 1024, 2048}); + std::vector{128, 256, 512, 1024, 2048}); - expectations_["Core"].addChild(ExpectationNode::createExpectation( + expectations_["Core"].addChild(ExpectationNode::createExpectation( 128, "Streaming-Vector-Length", true)); expectations_["Core"]["Streaming-Vector-Length"].setValueSet( - std::vector{128, 256, 512, 1024, 2048}); + std::vector{128, 256, 512, 1024, 2048}); } // Fetch From b440a9342c491e197603dd9201cbabec80a1245a Mon Sep 17 00:00:00 2001 From: Tom Lin Date: Thu, 3 Oct 2024 12:04:12 +0100 Subject: [PATCH 24/34] Migrate away from add_subdirectory LLVM (#433) --- CMakeLists.txt | 114 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 80 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ae6824d28..f10a87ee3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.13) include(FetchContent) include(CheckCXXCompilerFlag) +include(ProcessorCount) set(FETCHCONTENT_QUIET OFF) # FetchContent_MakeAvailable was introduced in 3.14 @@ -14,12 +15,17 @@ macro(FetchContent_MakeAvailable_Args NAME ARGS) endif() endmacro() -# we don't use git for LLVM here as it clones the entire LLVM repo which takes too long and we only need a small part of it +if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") + cmake_policy(SET CMP0135 NEW) +endif() +# we don't use git for LLVM here as it clones the entire LLVM repo which takes too long and we only need a relatively small part of it FetchContent_Declare( - llvm - URL https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.8/llvm-18.1.8.src.tar.xz - URL_HASH MD5=54e694dea8ba19db4a07d14507008e0b + llvm + URL https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.0/llvm-project-19.1.0.src.tar.xz + URL_HASH MD5=cfecaf29f50dce67836d32ca6b927e1d + # URL https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.8/llvm-project-18.1.8.src.tar.xz + # URL_HASH MD5=81cd0be5ae6f1ad8961746116d426a96 ) FetchContent_Declare( @@ -160,35 +166,75 @@ if(SIMENG_ENABLE_TESTS) else() - set(LLVM_TARGETS_TO_BUILD "AArch64;RISCV" CACHE INTERNAL "") - - set(LLVM_BUILD_RUNTIME OFF) - - set(LLVM_BUILD_TOOLS OFF) - set(LLVM_INCLUDE_TOOLS OFF) - - set(LLVM_BUILD_EXAMPLES OFF) - set(LLVM_INCLUDE_EXAMPLES OFF) - - set(LLVM_BUILD_TESTS OFF) - set(LLVM_INCLUDE_TESTS OFF) - - set(LLVM_BUILD_BENCHMARKS OFF) - set(LLVM_INCLUDE_BENCHMARKS OFF) - - set(LLVM_BUILD_DOCS OFF) - set(LLVM_INCLUDE_DOCS OFF) - - set(LLVM_INCLUDE_DOCS OFF) - set(LLVM_ENABLE_BINDINGS OFF) - set(LLVM_INSTALL_UTILS OFF) - - set(LLVM_ENABLE_WARNINGS OFF) - - # XXX all LLVM specific cmake variables must be set BEFORE FetchContent_MakeAvailable otherwise they have no effect - # make sure we get the headers too - FetchContent_MakeAvailable_Args(llvm EXCLUDE_FROM_ALL) - include_directories("${llvm_BINARY_DIR}/include/llvm" "${llvm_SOURCE_DIR}/include/llvm") + FetchContent_GetProperties(llvm) + if(NOT llvm_POPULATED) + FetchContent_Populate(llvm) + + set(COMMAND_ECHO_OPTION "") + # COMMAND_ECHO supported only in CMake >= 3.15 + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.15") + set(COMMAND_ECHO_OPTION COMMAND_ECHO STDOUT) + endif() + + execute_process( + COMMAND ${CMAKE_COMMAND} + -S ${llvm_SOURCE_DIR}/llvm + -B ${llvm_BINARY_DIR} + -DCMAKE_WARN_DEPRECATED=OFF + -DCMAKE_INSTALL_MESSAGE=LAZY + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX=${llvm_BINARY_DIR}/dist + -DCMAKE_SKIP_RPATH=OFF # keep the rpath prefix to avoid libLLVM.so + -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE_MAKEFILE} + -G${CMAKE_GENERATOR} + + -DLLVM_INCLUDE_BENCHMARKS=OFF + -DLLVM_INCLUDE_TESTS=OFF + -DLLVM_INCLUDE_DOCS=OFF + -DLLVM_INCLUDE_EXAMPLES=OFF + -DLLVM_BUILD_TESTS=OFF + -DLLVM_BUILD_DOCS=OFF + -DLLVM_BUILD_RUNTIME=OFF + -DLLVM_BUILD_TOOLS=OFF + -DLLVM_BUILD_EXAMPLES=OFF + -DLLVM_ENABLE_BINDINGS=OFF + -DLLVM_ENABLE_WARNINGS=OFF + "-DLLVM_TARGETS_TO_BUILD=AArch64\\;RISCV" + + ${COMMAND_ECHO_OPTION} + RESULT_VARIABLE SUCCESS) + + # XXX replace with COMMAND_ERROR_IS_FATAL in the future (>= 3.19) + if (NOT SUCCESS EQUAL "0") + message(FATAL_ERROR "LLVM configure did not succeed") + else () + message(STATUS "LLVM configuration complete, starting build...") + endif () + + ProcessorCount(NPROC) + execute_process( + COMMAND ${CMAKE_COMMAND} + --build ${llvm_BINARY_DIR} + --target + # The full list of targets can be discovered via `ninja -t targets` inside the build + install-LLVMObject + install-LLVMAArch64AsmParser + install-LLVMRISCVAsmParser + # We also include the headers and CMake exports for a *complete* build + install-llvm-headers + install-cmake-exports + -- -j${N} + + ${COMMAND_ECHO_OPTION} + RESULT_VARIABLE SUCCESS) + + # XXX replace with COMMAND_ERROR_IS_FATAL in the future (>= 3.19) + if (NOT SUCCESS EQUAL "0") + message(FATAL_ERROR "LLVM build did not succeed") + endif () + endif() find_package(LLVM REQUIRED CONFIG NO_DEFAULT_PATH PATHS "${llvm_BINARY_DIR}/lib/cmake/llvm") @@ -238,7 +284,7 @@ if (SIMENG_ENABLE_SST) endif() else() message(WARNING "SST build was selected but SST install directory was not specified. - Please specify -DSST_INSTALL_DIR= for the SST build to proceed.") + Please specify -DSST_INSTALL_DIR= for the SST build to proceed.") endif() endif() From e974e98200162e6a9a0d39406fc1bc4591bb94de Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 3 Oct 2024 12:56:27 +0100 Subject: [PATCH 25/34] Updated LLVM version to 18.1.8 in CMake download. --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f10a87ee3b..52a1d5e7c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,10 +22,10 @@ endif() # we don't use git for LLVM here as it clones the entire LLVM repo which takes too long and we only need a relatively small part of it FetchContent_Declare( llvm - URL https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.0/llvm-project-19.1.0.src.tar.xz - URL_HASH MD5=cfecaf29f50dce67836d32ca6b927e1d - # URL https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.8/llvm-project-18.1.8.src.tar.xz - # URL_HASH MD5=81cd0be5ae6f1ad8961746116d426a96 + # URL https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.0/llvm-project-19.1.0.src.tar.xz + # URL_HASH MD5=cfecaf29f50dce67836d32ca6b927e1d + URL https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.8/llvm-project-18.1.8.src.tar.xz + URL_HASH MD5=81cd0be5ae6f1ad8961746116d426a96 ) FetchContent_Declare( @@ -165,7 +165,7 @@ if(SIMENG_ENABLE_TESTS) endif() else() - + # If external LLVM not provided, download LLVM and build only what we need. Then point SimEng to use this sub-build FetchContent_GetProperties(llvm) if(NOT llvm_POPULATED) FetchContent_Populate(llvm) From d198964e4cacfd75c78b945e22d9c5c8966a554d Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 3 Oct 2024 14:52:15 +0100 Subject: [PATCH 26/34] Updated docs. --- docs/sphinx/developer/arch/index.rst | 2 +- docs/sphinx/developer/arch/supported/aarch64.rst | 10 +++++----- docs/sphinx/index.rst | 4 ++-- docs/sphinx/user/building_simeng.rst | 2 +- docs/sphinx/user/configuring_simeng.rst | 3 +++ 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/docs/sphinx/developer/arch/index.rst b/docs/sphinx/developer/arch/index.rst index 6541ba55e2..360a546f60 100644 --- a/docs/sphinx/developer/arch/index.rst +++ b/docs/sphinx/developer/arch/index.rst @@ -5,7 +5,7 @@ SimEng architecture definitions are responsible for describing the features and To achieve this, SimEng defines a set of abstract architecture-related classes. Discrete implementations of these classes are provided for each of the ISAs SimEng supports by default, and must also be implemented for adding support for new or custom ISAs. -ISA support is achieved through the use of the `Capstone `_ disassembly framework, which disassembles a binary instruction into a C/C++ object that include operand registers, access types, and immediate values to name a few. In order to update SimEng's AArch64 support from Armv8.4-a to Armv9.2-a, we undertook a Capstone update to allow for disassembly of the Armv9.2-a ISA. The work done for this can be found `here `_, and other useful ISA updating tools present in Capstone can be found `here `_. +ISA support is achieved through the use of the `Capstone `_ disassembly framework, which disassembles a binary instruction into a C/C++ object that include operand registers, access types, and immediate values to name a few. In order to update SimEng's AArch64 support from Armv8.4-a to Armv9.2-a, we undertook a Capstone update to allow for disassembly of the Armv9.2-a ISA. The work done for this can be found `here `_. Extensive work continues to be done to Capstone by its community in order to allow for easier updating of ISA versions. This facilitated the recent update of SimEng's AArch64 ISA support to Armv9.4-a. Below provides more information on the abstract structure of a SimEng architecture and currently supported ISAs. diff --git a/docs/sphinx/developer/arch/supported/aarch64.rst b/docs/sphinx/developer/arch/supported/aarch64.rst index 4728f1cd60..6d1ac0ece4 100644 --- a/docs/sphinx/developer/arch/supported/aarch64.rst +++ b/docs/sphinx/developer/arch/supported/aarch64.rst @@ -1,7 +1,7 @@ AArch64 ======= -SimEng provides an implementation of the 64-bit AArch64 architecture, specifically the Armv9.2-a ISA. This implementation provides support for decoding and executing a range of common instructions, sufficient to run a number of simple benchmarks. It is also capable of handling supervisor call (syscall) exceptions via basic system call emulation, allowing the execution of programs that have been statically compiled with the standard library. +SimEng provides an implementation of the 64-bit AArch64 architecture, specifically the Armv9.4-a ISA. This implementation provides support for decoding and executing a range of common instructions, sufficient to run a number of simple benchmarks. It is also capable of handling supervisor call (syscall) exceptions via basic system call emulation, allowing the execution of programs that have been statically compiled with the standard library. .. contents:: Contents @@ -159,6 +159,8 @@ SME instructions can also operate on sub-tile slices; individual rows or columns Furthermore, a similar situation is present when a sub-tile slice is a destination operand. The ``results`` vector will expect a ``registerValue`` entry for each row of the targeted sub-tile, again due to the same two reasons listed previously. But, when a sub-tile slice is a destination operand, **all** associated rows of the sub-tile will also be added to the ``sourceValues_`` vector. Again, this is down to two key, similar reasons. First, when a destination is a sub-tile slice, we only want to update that row or column. As the we are unable to calculate which slice will be our destination before execution has commenced, all possible slices must be added to the ``results`` vector. If we were to not provide a ``RegisterValue`` to each entry of the ``results`` vector, the default value is 0. Therefore, in order to not zero-out the other slices within the sub-tile we will need access to their current values. Secondly, if the destination is a vertical slice (or sub-tile column) then only one element per row should be updated; the rest should remain unchanged. +Additionally, a fixed width 512-bit register ``ZT0`` was introduced with SME2 and is also now supported by SimEng. It can be treated in the same way as an SVE vector register. + Before implementing any further SME functionality we highly recommend familiarising yourself with the specification; found `here `_. .. Note:: We strongly encourage adding regression tests for each implemented instruction at the same time as adding execution behaviour to ensure functional validity. @@ -185,7 +187,7 @@ cstool Capstone provides a ``cstool`` utility, which provides a visual representation of the ``metadata`` information available for any given instruction. For example, feeding it the bytes for the ``str`` instruction displayed above results in the following:: - $ cstool -d arm64 f30f1ef8 + $ cstool -d -r aarch64 f30f1ef8 0 f3 0f 1e f8 str x19, [sp, #-0x20]! op_count: 2 operands[0].type: REG = x19 @@ -224,9 +226,7 @@ Concerning SVE & SME loads and stores, an effort should be made to merge contigu Instruction aliases ******************* -As Capstone is primarily a disassembler, it will attempt to generate the correct aliases for instructions: for example, the ``cmp w0, #0`` instruction is an alias for ``subs wzr, w0, #0``. As it's the underlying instruction that is of use (in this case, the ``subs`` instruction), this implementation includes a de-aliasing component that reverses this conversion. The logic for this may be found in ``src/lib/arch/aarch64/InstructionMetadata``. - -If a known but unsupported alias is encountered, it will generate an invalid instruction error, and the output will identify the instruction as unknown in place of the usual textual representation. It is recommended to reference a disassembled version of the program to identify what the instruction at this address should be correctly disassembled to, and implement the necessary dealiasing logic accordingly. +Although Capstone has been configured to produce the disassembly information for the "real" instruction rather than that of its (preferred) alias, the instruction's mnemonic and operand string will still be that of its alias. Hence, if an exception occurs the printed instruction informtion may not match the internal opcode used. Common Instruction Execution behaviour issues ********************************************* diff --git a/docs/sphinx/index.rst b/docs/sphinx/index.rst index ac7026f9a9..55d09d38ac 100644 --- a/docs/sphinx/index.rst +++ b/docs/sphinx/index.rst @@ -50,7 +50,7 @@ SimEng places an emphasis on performance and ease of use, whilst maintaining a c Features -------- -Currently, SimEng targets the Armv9.2-a ISA with support for the SVE, SVE2, and SME extensions as well as RISC-V rv64imafdc. SimEng has the ability to model up to out-of-order, superscalar, single-core processors, and to emulate a subset of Linux system-calls. It supports statically compiled C and Fortran binaries that run on real hardware, with additional support for single-threaded OpenMP binaries too. Internally, SimEng currently models memory as an infinite L1 cache, i.e. it assumes that all loads and stores hit the L1 cache. However, we have a tested integration with the `Structural Simulation Toolkit `_ (SST) allowing for a full memory model to be simulated; more information can be found in the :doc:`SST Integration section `. +Currently, SimEng targets the Armv9.4-a ISA with support for the SVE, SVE2, SME, and SME2 extensions as well as RISC-V rv64imafdc. SimEng has the ability to model up to out-of-order, superscalar, single-core processors, and to emulate a subset of Linux system-calls. It supports statically compiled C and Fortran binaries that run on real hardware, with additional support for single-threaded OpenMP binaries too. Internally, SimEng currently models memory as an infinite L1 cache, i.e. it assumes that all loads and stores hit the L1 cache. However, we have a tested integration with the `Structural Simulation Toolkit `_ (SST) allowing for a full memory model to be simulated; more information can be found in the :doc:`SST Integration section `. The main component provided by the simulator is a discrete processor core model, shown in diagrammatic form below. This model accepts a clock signal and supports a memory access interface. A single YAML format configuration file can be passed to the simulation to specify models of existing microarchitectures, such as Marvell's ThunderX2 or Fujitsu's A64fx, or to model hypothetical core designs. @@ -107,7 +107,6 @@ Current development team: - Jack Jones (lead developer) - Finn Wilkinson -- Rahat Muneeb - Dan Weaver - Alex Cockrean - Joseph Moore @@ -121,6 +120,7 @@ Additional Contributors: - Ainsley Rutterford - Andrei Poenaru +- Rahat Muneeb - Harry Waugh - Mutalib Mohammed - Seunghun Lee diff --git a/docs/sphinx/user/building_simeng.rst b/docs/sphinx/user/building_simeng.rst index 1a5cd41123..76ac1d39af 100644 --- a/docs/sphinx/user/building_simeng.rst +++ b/docs/sphinx/user/building_simeng.rst @@ -41,7 +41,7 @@ With this configuration, the build files will be generated in a directory called More information about the LLVM_DIR value can be found `here `_. .. Note:: - LLVM versions greater than 14 or less than 8 are not supported. We'd recommend using LLVM 14.0.5 where possible as this has been verified by us to work correctly. + LLVM versions greater than 18 or less than 8 are not supported. We'd recommend using LLVM 18.1.8 where possible as this has been verified by us to work correctly for the most recent version of SimEng. b. Two additional flags are available when building SimEng. Firstly is ``-DSIMENG_SANITIZE={ON, OFF}`` which adds a selection of sanitisation compilation flags (primarily used during the development of the framework). Secondly is ``-SIMENG_OPTIMIZE={ON, OFF}`` which attempts to optimise the framework's compilation for the host machine through a set of compiler flags and options. diff --git a/docs/sphinx/user/configuring_simeng.rst b/docs/sphinx/user/configuring_simeng.rst index 765e8c7e45..83eac9bdad 100644 --- a/docs/sphinx/user/configuring_simeng.rst +++ b/docs/sphinx/user/configuring_simeng.rst @@ -102,6 +102,9 @@ AArch64 - Matrix-Count (Optional) The number of physical ``za`` Arm SME registers. +- Table-Count (Optional) + The number of physical SME Lookup Table registers (``zt0``). + RISC-V - GeneralPurpose-Count From aef0ad4cc8f3372c2cb55e2719776cb944b9cfae Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Fri, 4 Oct 2024 09:27:51 +0100 Subject: [PATCH 27/34] Updated cmake file. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52a1d5e7c3..05d192fa5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,7 +225,7 @@ if(SIMENG_ENABLE_TESTS) # We also include the headers and CMake exports for a *complete* build install-llvm-headers install-cmake-exports - -- -j${N} + -j ${N} ${COMMAND_ECHO_OPTION} RESULT_VARIABLE SUCCESS) From fd44dd34982fff70810e06645444e2c00f10c755 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson <56131608+FinnWilkinson@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:32:20 +0100 Subject: [PATCH 28/34] Added note to CMakeLists about making a new capstone branch each time it is updated --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 05d192fa5b..1a3b1b085b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,10 +36,12 @@ FetchContent_Declare( GIT_PROGRESS TRUE ) +# WARNING: When updating capstone version, we MUST make a new, discrete branch in the UoB-HPC Capstone fork to ensure +# current / previous SimEng versions continue to operate correctly. FetchContent_Declare( capstone-lib GIT_REPOSITORY https://github.com/UoB-HPC/capstone.git - GIT_TAG next-update + GIT_TAG next-update # Branch for SimEng version 0.9.7 GIT_PROGRESS TRUE # Old Git tag pre-Armv9.2 @@ -290,4 +292,4 @@ endif() # Install SimEng model configs in the build directory set(SIMENG_CONFIG_INSTALL_DIR "${CMAKE_BINARY_DIR}/simeng-configs") -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/configs/ DESTINATION ${SIMENG_CONFIG_INSTALL_DIR}) \ No newline at end of file +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/configs/ DESTINATION ${SIMENG_CONFIG_INSTALL_DIR}) From 952075c3a17ea8dcb995f82e39823d200a44cfc9 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 31 Oct 2024 14:35:18 +0000 Subject: [PATCH 29/34] Attended PR comments. --- CMakeLists.txt | 7 +- configs/a64fx_SME.yaml | 4 +- docs/sphinx/developer/arch/index.rst | 2 +- .../developer/arch/supported/aarch64.rst | 4 +- docs/sphinx/user/building_simeng.rst | 2 +- docs/sphinx/user/configuring_simeng.rst | 4 +- src/include/simeng/arch/aarch64/ArchInfo.hh | 10 +-- .../simeng/arch/aarch64/Instruction.hh | 15 ++-- .../simeng/arch/aarch64/MicroDecoder.hh | 2 +- .../aarch64/helpers/auxiliaryFunctions.hh | 1 - .../simeng/arch/aarch64/helpers/sve.hh | 2 +- src/lib/arch/aarch64/Architecture.cc | 2 + src/lib/arch/aarch64/InstructionMetadata.cc | 78 ++++++++++++++++++- src/lib/arch/aarch64/Instruction_decode.cc | 34 ++++---- src/lib/arch/aarch64/MicroDecoder.cc | 32 ++++++++ src/lib/config/ModelConfig.cc | 12 +-- test/integration/ConfigTest.cc | 3 +- .../aarch64/AArch64RegressionTest.hh | 3 +- 18 files changed, 164 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a3b1b085b..aeb3752f65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,8 +22,6 @@ endif() # we don't use git for LLVM here as it clones the entire LLVM repo which takes too long and we only need a relatively small part of it FetchContent_Declare( llvm - # URL https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.0/llvm-project-19.1.0.src.tar.xz - # URL_HASH MD5=cfecaf29f50dce67836d32ca6b927e1d URL https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.8/llvm-project-18.1.8.src.tar.xz URL_HASH MD5=81cd0be5ae6f1ad8961746116d426a96 ) @@ -43,9 +41,6 @@ FetchContent_Declare( GIT_REPOSITORY https://github.com/UoB-HPC/capstone.git GIT_TAG next-update # Branch for SimEng version 0.9.7 GIT_PROGRESS TRUE - - # Old Git tag pre-Armv9.2 - # GIT_TAG e7be7d99e718ef9741026b80fc6f5e100fdf4f94 # trunk ) cmake_policy(SET CMP0048 NEW) @@ -155,7 +150,7 @@ if(SIMENG_ENABLE_TESTS) # Check LLVM version if ((${LLVM_PACKAGE_VERSION} VERSION_LESS "8.0") OR (${LLVM_PACKAGE_VERSION} VERSION_GREATER_EQUAL "18.2")) - message(FATAL_ERROR "LLVM version must be >= 8.0 and <= 18.2") + message(FATAL_ERROR "LLVM version must be >= 8.0 and < 18.2") endif() # Print message containing if the full test suite will run diff --git a/configs/a64fx_SME.yaml b/configs/a64fx_SME.yaml index 47c3951e2b..7fe7086d5e 100644 --- a/configs/a64fx_SME.yaml +++ b/configs/a64fx_SME.yaml @@ -21,8 +21,8 @@ Register-Set: FloatingPoint/SVE-Count: 128 Predicate-Count: 48 Conditional-Count: 128 - Matrix-Count: 2 - Table-Count: 8 + SME-Matrix-Count: 2 + SME-Lookup-Table-Count: 8 Pipeline-Widths: Commit: 4 FrontEnd: 4 diff --git a/docs/sphinx/developer/arch/index.rst b/docs/sphinx/developer/arch/index.rst index 360a546f60..e8f90085fd 100644 --- a/docs/sphinx/developer/arch/index.rst +++ b/docs/sphinx/developer/arch/index.rst @@ -5,7 +5,7 @@ SimEng architecture definitions are responsible for describing the features and To achieve this, SimEng defines a set of abstract architecture-related classes. Discrete implementations of these classes are provided for each of the ISAs SimEng supports by default, and must also be implemented for adding support for new or custom ISAs. -ISA support is achieved through the use of the `Capstone `_ disassembly framework, which disassembles a binary instruction into a C/C++ object that include operand registers, access types, and immediate values to name a few. In order to update SimEng's AArch64 support from Armv8.4-a to Armv9.2-a, we undertook a Capstone update to allow for disassembly of the Armv9.2-a ISA. The work done for this can be found `here `_. Extensive work continues to be done to Capstone by its community in order to allow for easier updating of ISA versions. This facilitated the recent update of SimEng's AArch64 ISA support to Armv9.4-a. +ISA support is achieved through the use of an in-house fork of the `Capstone `_ disassembly framework, which disassembles a binary instruction into a C/C++ object that includes operand registers, access types, and immediate values to name a few. In order to update SimEng's AArch64 support from Armv8.4-a to Armv9.2-a, we undertook a Capstone update to allow for disassembly of the Armv9.2-a ISA. The work done for this can be found `here `_. Extensive work continues to be done to Capstone by its community in order to allow for easier updating of ISA versions. This facilitated the recent update of SimEng's AArch64 ISA support to Armv9.4-a. Below provides more information on the abstract structure of a SimEng architecture and currently supported ISAs. diff --git a/docs/sphinx/developer/arch/supported/aarch64.rst b/docs/sphinx/developer/arch/supported/aarch64.rst index 6d1ac0ece4..464113e8fc 100644 --- a/docs/sphinx/developer/arch/supported/aarch64.rst +++ b/docs/sphinx/developer/arch/supported/aarch64.rst @@ -136,7 +136,7 @@ There are several useful variables that execution behaviours have access to: This is the output vector, into which ``RegisterValue`` instances containing the results should be placed. Each entry in the vector corresponds to a destination register. Some instructions have "implicit" destination registers: in these cases, the implicit destinations are added to the **start** of the results vector. For example, ``subs w0, w1, #1`` writes explicitly to ``w0``, but also implicitly sets the "NZCV" comparison flags. In this case, ``results[0]`` is expected to be the updated NZCV flags, while ``results[1]`` is expected to be the new value of ``w0``. - Some Load and Store instructions update the base memory address register (pre- or post-indexing). These registers are also classes as implicit destination registers and thus will be added to the start of the results vector. For example, ``ldr x1, [x0], #8`` writes explicitly to ``x1`` but also writes implicitly to ``x0``. In this case, ``results[0]`` is expected to be the updated ``x0`` value (``x0 + 8``) and ``results[1]`` is expected to be the new value of ``x1``. + Some Load and Store instructions update the base memory address register (pre- or post-indexing). These registers are also classed as implicit destination registers and thus will be added to the start of the results vector. For example, ``ldr x1, [x0], #8`` writes explicitly to ``x1`` but also writes implicitly to ``x0``. In this case, ``results[0]`` is expected to be the updated ``x0`` value (``x0 + 8``) and ``results[1]`` is expected to be the new value of ``x1``. Memory instructions may have a "writeback" variant, where the register containing the address is updated by an offset during execution. In these cases, the address register is added as a destination *after* the other registers, corresponding with the textual representation of the registers. E.g., the instruction ``ldr x1, [x2, #8]!`` will expect the value of ``x1`` in ``results[0]``, while the updated address ``x2`` should be placed in ``results[1]``. @@ -226,7 +226,7 @@ Concerning SVE & SME loads and stores, an effort should be made to merge contigu Instruction aliases ******************* -Although Capstone has been configured to produce the disassembly information for the "real" instruction rather than that of its (preferred) alias, the instruction's mnemonic and operand string will still be that of its alias. Hence, if an exception occurs the printed instruction informtion may not match the internal opcode used. +Although Capstone has been configured to produce the disassembly information for the "real" instruction rather than that of its (preferred) alias, the instruction's mnemonic and operand string will still be that of its alias. Hence, if an exception occurs the printed instruction information may not match the internal opcode used. Common Instruction Execution behaviour issues ********************************************* diff --git a/docs/sphinx/user/building_simeng.rst b/docs/sphinx/user/building_simeng.rst index 76ac1d39af..ed701ada40 100644 --- a/docs/sphinx/user/building_simeng.rst +++ b/docs/sphinx/user/building_simeng.rst @@ -41,7 +41,7 @@ With this configuration, the build files will be generated in a directory called More information about the LLVM_DIR value can be found `here `_. .. Note:: - LLVM versions greater than 18 or less than 8 are not supported. We'd recommend using LLVM 18.1.8 where possible as this has been verified by us to work correctly for the most recent version of SimEng. + LLVM versions greater than 18.2 or less than 8 are not supported. We'd recommend using LLVM 18.1.8 where possible as this has been verified by us to work correctly for the most recent version of SimEng. LLVM versions less than 14 will likely not support AArch64 SVE2, SME, or SME2 instructions. b. Two additional flags are available when building SimEng. Firstly is ``-DSIMENG_SANITIZE={ON, OFF}`` which adds a selection of sanitisation compilation flags (primarily used during the development of the framework). Secondly is ``-SIMENG_OPTIMIZE={ON, OFF}`` which attempts to optimise the framework's compilation for the host machine through a set of compiler flags and options. diff --git a/docs/sphinx/user/configuring_simeng.rst b/docs/sphinx/user/configuring_simeng.rst index 83eac9bdad..9a49893375 100644 --- a/docs/sphinx/user/configuring_simeng.rst +++ b/docs/sphinx/user/configuring_simeng.rst @@ -99,10 +99,10 @@ AArch64 - Conditional-Count The number of physical status/flag/conditional-code registers. -- Matrix-Count (Optional) +- SME-Matrix-Count (Optional) The number of physical ``za`` Arm SME registers. -- Table-Count (Optional) +- SME-Lookup-Table-Count (Optional) The number of physical SME Lookup Table registers (``zt0``). RISC-V diff --git a/src/include/simeng/arch/aarch64/ArchInfo.hh b/src/include/simeng/arch/aarch64/ArchInfo.hh index 0c7676421a..1403da08f8 100644 --- a/src/include/simeng/arch/aarch64/ArchInfo.hh +++ b/src/include/simeng/arch/aarch64/ArchInfo.hh @@ -37,11 +37,11 @@ class ArchInfo : public simeng::arch::ArchInfo { uint16_t fpCount = regConfig["FloatingPoint/SVE-Count"].as(); uint16_t predCount = regConfig["Predicate-Count"].as(); uint16_t condCount = regConfig["Conditional-Count"].as(); - uint16_t matCount = regConfig["Matrix-Count"].as(); - uint16_t tabCount = regConfig["Table-Count"].as(); - // Matrix-Count multiplied by (SVL/8) as internal representation of ZA is a - // block of row-vector-registers. Therefore, we need to convert physical - // counts from whole-ZA to rows-in-ZA. + uint16_t matCount = regConfig["SME-Matrix-Count"].as(); + uint16_t tabCount = regConfig["SME-Lookup-Table-Count"].as(); + // SME-Matrix-Count multiplied by (SVL/8) as internal representation of ZA + // is a block of row-vector-registers. Therefore, we need to convert + // physical counts from whole-ZA to rows-in-ZA. matCount *= zaSize_; physRegStruct_ = {{8, gpCount}, {256, fpCount}, diff --git a/src/include/simeng/arch/aarch64/Instruction.hh b/src/include/simeng/arch/aarch64/Instruction.hh index 7dbe2a8cdd..b5f1f07cc5 100644 --- a/src/include/simeng/arch/aarch64/Instruction.hh +++ b/src/include/simeng/arch/aarch64/Instruction.hh @@ -84,7 +84,6 @@ struct MicroOpInfo { int microOpIndex = 0; }; -// TODO: Handle multi-register aarch64_reg operands /** Get the size of the data to be accessed from/to memory. */ inline uint8_t getDataSize(cs_aarch64_op op) { // No V-register enum identifiers exist. Instead, depending on whether a full @@ -118,7 +117,11 @@ inline uint8_t getDataSize(cs_aarch64_op op) { case AARCH64LAYOUT_VL_B: return 1; default: - assert(false && "Unknown VAS type"); + std::cerr << "[SimEng] Cannot determine size of Arm V vector register " + "elements with `reg` value " + << op.reg << " and `vas` value of " << vas << ". Exiting..." + << std::endl; + exit(1); break; } } @@ -168,16 +171,14 @@ inline uint8_t getDataSize(cs_aarch64_op op) { return 16; } - // ARCH64_REG_PN0 -> +15 are scalable predicate registers + // ARCH64_REG_PN0 -> +15 are 256-bit (P) registers if (op.reg >= AARCH64_REG_PN0) { - /** TODO: Check functionality is correct when multi-vector operands + SME2 - * has been supported. */ - return 1; + return 32; } // AARCH64_REG_P0 -> +15 are 256-bit (P) registers if (op.reg >= AARCH64_REG_P0) { - return 1; + return 32; } // AARCH64_REG_H0 -> +31 are 16-bit arranged (H) neon registers diff --git a/src/include/simeng/arch/aarch64/MicroDecoder.hh b/src/include/simeng/arch/aarch64/MicroDecoder.hh index c9a0d88c6f..6503d370e8 100644 --- a/src/include/simeng/arch/aarch64/MicroDecoder.hh +++ b/src/include/simeng/arch/aarch64/MicroDecoder.hh @@ -84,7 +84,7 @@ class MicroDecoder { // Default objects /** Default capstone instruction structure. */ - cs_aarch64 default_info = {AArch64CC_Invalid, false, false, 0, {}}; + cs_aarch64 default_info = {AArch64CC_Invalid, false, false, false, 0, {}}; /** Default register. */ cs_aarch64_op default_op = {0, diff --git a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh index 96bcf29233..5880a75da9 100644 --- a/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh +++ b/src/include/simeng/arch/aarch64/helpers/auxiliaryFunctions.hh @@ -125,7 +125,6 @@ bitfieldManipulate(T value, T dest, uint8_t rotateBy, uint8_t sourceBits, /** Function to check if NZCV conditions hold. */ inline bool conditionHolds(uint8_t cond, uint8_t nzcv) { - // Due to Capstone enum changes, need to add 1 to cond bool inverse = cond & 1; uint8_t upper = cond >> 1; bool n = (nzcv >> 3) & 1; diff --git a/src/include/simeng/arch/aarch64/helpers/sve.hh b/src/include/simeng/arch/aarch64/helpers/sve.hh index fd092fcc04..2c33ccfbe6 100644 --- a/src/include/simeng/arch/aarch64/helpers/sve.hh +++ b/src/include/simeng/arch/aarch64/helpers/sve.hh @@ -1046,7 +1046,7 @@ RegisterValue sveMax_vecImm( return {out, 256}; } -/** Helper function for SVE instructions with the format `max zdn, pg/m zdn, +/** Helper function for SVE instructions with the format `max zdn, pg/m, zdn, * zm`. * T represents the type of sourceValues (e.g. for zdn.d, T = uint64_t). * Returns correctly formatted RegisterValue. */ diff --git a/src/lib/arch/aarch64/Architecture.cc b/src/lib/arch/aarch64/Architecture.cc index 0515c91eef..015dba62b1 100644 --- a/src/lib/arch/aarch64/Architecture.cc +++ b/src/lib/arch/aarch64/Architecture.cc @@ -21,6 +21,8 @@ Architecture::Architecture(kernel::Linux& kernel, ryml::ConstNodeRef config) } cs_option(capstoneHandle_, CS_OPT_DETAIL, CS_OPT_ON); + // This second Capstone option reverses instruction aliases, and instead + // means all operand information is that of the "real" underlying instruction. cs_option(capstoneHandle_, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL); // Generate zero-indexed system register map diff --git a/src/lib/arch/aarch64/InstructionMetadata.cc b/src/lib/arch/aarch64/InstructionMetadata.cc index c06bd61c7b..34ddca07d7 100644 --- a/src/lib/arch/aarch64/InstructionMetadata.cc +++ b/src/lib/arch/aarch64/InstructionMetadata.cc @@ -42,12 +42,19 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) operands[0].access = CS_AC_WRITE; break; case Opcode::AArch64_ADR_LSL_ZZZ_D_0: // example bytecode = c8a0e704 + [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_D_1: + [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_D_2: + [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_D_3: + [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_S_0: + [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_S_1: + [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_S_2: + [[fallthrough]]; case Opcode::AArch64_ADR_LSL_ZZZ_S_3: { // Change the last 2 Z-regs from one MEM operand to two REG operands operandCount = 3; @@ -63,13 +70,17 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) break; } case Opcode::AArch64_CASALW: // Example bytecode - 02fce188 + [[fallthrough]]; case Opcode::AArch64_CASALX: // Remove implicit destination (MEM base reg) implicitDestinationCount = 0; break; case Opcode::AArch64_ADD_ZI_B: // Example bytecode - 00c12025 + [[fallthrough]]; case Opcode::AArch64_ADD_ZI_D: + [[fallthrough]]; case Opcode::AArch64_ADD_ZI_H: + [[fallthrough]]; case Opcode::AArch64_ADD_ZI_S: { // Incorrect access types operands[0].access = CS_AC_WRITE; @@ -77,22 +88,34 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) break; } case Opcode::AArch64_SMAX_ZI_B: + [[fallthrough]]; case Opcode::AArch64_SMAX_ZI_D: + [[fallthrough]]; case Opcode::AArch64_SMAX_ZI_H: + [[fallthrough]]; case Opcode::AArch64_SMAX_ZI_S: // Example bytecode - 03c0a825 - case Opcode::AArch64_AND_ZI: // Example bytecode - 00068005 + [[fallthrough]]; + case Opcode::AArch64_AND_ZI: // Example bytecode - 00068005 // Incorrect access types operands[0].access = CS_AC_WRITE; operands[1].access = CS_AC_READ; break; case Opcode::AArch64_FSUB_ZPmI_D: + [[fallthrough]]; case Opcode::AArch64_FSUB_ZPmI_H: + [[fallthrough]]; case Opcode::AArch64_FSUB_ZPmI_S: // Example bytecode - 00849965 + [[fallthrough]]; case Opcode::AArch64_FMUL_ZPmI_D: + [[fallthrough]]; case Opcode::AArch64_FMUL_ZPmI_H: + [[fallthrough]]; case Opcode::AArch64_FMUL_ZPmI_S: // Example bytecode - 00809a65 + [[fallthrough]]; case Opcode::AArch64_FADD_ZPmI_D: // Example bytecode - 0584d865 + [[fallthrough]]; case Opcode::AArch64_FADD_ZPmI_H: + [[fallthrough]]; case Opcode::AArch64_FADD_ZPmI_S: { // Incorrect access types operands[0].access = CS_AC_WRITE; @@ -101,56 +124,107 @@ InstructionMetadata::InstructionMetadata(const cs_insn& insn) break; } case Opcode::AArch64_AND_ZPmZ_D: // Example bytecode - 4901da04 + [[fallthrough]]; case Opcode::AArch64_AND_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_AND_ZPmZ_S: + [[fallthrough]]; case Opcode::AArch64_AND_ZPmZ_B: + [[fallthrough]]; case Opcode::AArch64_SMULH_ZPmZ_B: // Example bytecode - 20001204 + [[fallthrough]]; case Opcode::AArch64_SMULH_ZPmZ_D: + [[fallthrough]]; case Opcode::AArch64_SMULH_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_SMULH_ZPmZ_S: + [[fallthrough]]; case Opcode::AArch64_SMIN_ZPmZ_B: + [[fallthrough]]; case Opcode::AArch64_SMIN_ZPmZ_D: + [[fallthrough]]; case Opcode::AArch64_SMIN_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_SMIN_ZPmZ_S: // Example bytecode - 01008a04 + [[fallthrough]]; case Opcode::AArch64_SMAX_ZPmZ_B: + [[fallthrough]]; case Opcode::AArch64_SMAX_ZPmZ_D: + [[fallthrough]]; case Opcode::AArch64_SMAX_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_SMAX_ZPmZ_S: // Example bytecode - 01008804 - case Opcode::AArch64_MUL_ZPmZ_B: // Example bytecode - 40001004 + [[fallthrough]]; + case Opcode::AArch64_MUL_ZPmZ_B: // Example bytecode - 40001004 + [[fallthrough]]; case Opcode::AArch64_MUL_ZPmZ_D: + [[fallthrough]]; case Opcode::AArch64_MUL_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_MUL_ZPmZ_S: + [[fallthrough]]; case Opcode::AArch64_FSUBR_ZPmZ_D: + [[fallthrough]]; case Opcode::AArch64_FSUBR_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_FSUBR_ZPmZ_S: // Example bytecode - 24808365 + [[fallthrough]]; case Opcode::AArch64_FSUB_ZPmZ_D: + [[fallthrough]]; case Opcode::AArch64_FSUB_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_FSUB_ZPmZ_S: // Example bytecode - 24808165 + [[fallthrough]]; case Opcode::AArch64_FMUL_ZPmZ_D: + [[fallthrough]]; case Opcode::AArch64_FMUL_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_FMUL_ZPmZ_S: // Example bytecode - 83808265 + [[fallthrough]]; case Opcode::AArch64_FDIV_ZPmZ_D: // Example bytecode - 0184cd65 + [[fallthrough]]; case Opcode::AArch64_FDIV_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_FDIV_ZPmZ_S: + [[fallthrough]]; case Opcode::AArch64_FDIVR_ZPmZ_D: // Example bytecode - 0184cc65 + [[fallthrough]]; case Opcode::AArch64_FDIVR_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_FDIVR_ZPmZ_S: + [[fallthrough]]; case Opcode::AArch64_FADDA_VPZ_D: + [[fallthrough]]; case Opcode::AArch64_FADDA_VPZ_H: + [[fallthrough]]; case Opcode::AArch64_FADDA_VPZ_S: // Example bytecode - 01249865 + [[fallthrough]]; case Opcode::AArch64_FADD_ZPmZ_D: // Example bytecode - 6480c065 + [[fallthrough]]; case Opcode::AArch64_FADD_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_FADD_ZPmZ_S: + [[fallthrough]]; case Opcode::AArch64_FCADD_ZPmZ_D: // Example bytecode - 2080c064 + [[fallthrough]]; case Opcode::AArch64_FCADD_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_FCADD_ZPmZ_S: + [[fallthrough]]; case Opcode::AArch64_ADD_ZPmZ_B: // Example bytecode - 00000004 + [[fallthrough]]; case Opcode::AArch64_ADD_ZPmZ_D: + [[fallthrough]]; case Opcode::AArch64_ADD_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_ADD_ZPmZ_S: + [[fallthrough]]; case Opcode::AArch64_EOR_ZPmZ_B: // Example bytecode - 20001904 + [[fallthrough]]; case Opcode::AArch64_EOR_ZPmZ_D: + [[fallthrough]]; case Opcode::AArch64_EOR_ZPmZ_H: + [[fallthrough]]; case Opcode::AArch64_EOR_ZPmZ_S: // Incorrect access types operands[0].access = CS_AC_WRITE; diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index cca5d27f9e..2d595533ff 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -39,7 +39,6 @@ constexpr int32_t signExtend(uint32_t value, int currentLength) { * WARNING: this conversion is FRAGILE, and relies on the structure of the * `aarch64_reg` enum. Updates to the Capstone library version may cause this to * break. - * TODO: Add multi-register enum decoding. * */ Register csRegToRegister(aarch64_reg reg) { // Do not need check for AARCH64_REG_Vn as in Capstone, they are aliased as Qn @@ -109,6 +108,7 @@ Register csRegToRegister(aarch64_reg reg) { // AARCH64_REG_P0 -> +15 are 256-bit (P) "predicate-as-mask" registers. // Excludes #16 (FFR). // AARCH64_REG_PN0 -> +15 are 256-bit (PN) "predicate-as-counter" registers. + // Occupy same registers as (P) predicates but use a different encoding. if (AARCH64_REG_P0 <= reg && reg <= AARCH64_REG_PN15) { return {RegisterType::PREDICATE, static_cast(static_cast(reg - AARCH64_REG_P0) % @@ -273,10 +273,16 @@ void Instruction::decode() { if (op.mem.index != AARCH64_REG_INVALID) { // Register offset; add to sources sourceRegisters_[sourceRegisterCount_] = csRegToRegister(op.mem.index); + // Early check for WZR/XZR registers used as scalar index. Allows SME + // instructions to avoid checking all source operands later on. + if (sourceRegisters_[sourceRegisterCount_] == + RegisterType::ZERO_REGISTER) { + sourceValues_[sourceRegisterCount_] = RegisterValue(0, 8); + } else { + sourceOperandsPending_++; + } sourceRegisterCount_++; - sourceOperandsPending_++; } - } else if (op.type == AARCH64_OP_SME) { setInstructionType(InsnType::isSMEData); std::vector regs = getZARowVectors( @@ -340,8 +346,7 @@ void Instruction::decode() { RegisterType::SYSTEM, static_cast(sysRegTag)}; sourceRegisterCount_++; sourceOperandsPending_++; - } - if (op.sysop.sub_type == AARCH64_OP_REG_MSR) { + } else if (op.sysop.sub_type == AARCH64_OP_REG_MSR) { destinationRegisters_[destinationRegisterCount_] = { RegisterType::SYSTEM, static_cast(sysRegTag)}; destinationRegisterCount_++; @@ -854,17 +859,16 @@ void Instruction::decode() { setInstructionType(InsnType::isScalarData); } - // if (!(isInstruction(InsnType::isSMEData))) { - // Catch zero register references and pre-complete those operands - not - // applicable to SME instructions - for (uint16_t i = 0; i < sourceRegisterCount_; i++) { - if (sourceRegisters_[i] == RegisterType::ZERO_REGISTER) { - sourceValues_[i] = RegisterValue(0, 8); - sourceOperandsPending_--; + if (!(isInstruction(InsnType::isSMEData))) { + // Catch zero register references and pre-complete those operands - not + // applicable to SME instructions + for (uint16_t i = 0; i < sourceRegisterCount_; i++) { + if (sourceRegisters_[i] == RegisterType::ZERO_REGISTER) { + sourceValues_[i] = RegisterValue(0, 8); + sourceOperandsPending_--; + } } - } - // } else { - if (isInstruction(InsnType::isSMEData)) { + } else { // For SME instructions, resize the following structures to have the // exact amount of space required sourceRegisters_.resize(sourceRegisterCount_); diff --git a/src/lib/arch/aarch64/MicroDecoder.cc b/src/lib/arch/aarch64/MicroDecoder.cc index 5b71fc3c8d..ea181c8d66 100644 --- a/src/lib/arch/aarch64/MicroDecoder.cc +++ b/src/lib/arch/aarch64/MicroDecoder.cc @@ -653,37 +653,69 @@ cs_detail MicroDecoder::createDefaultDetail(std::vector opTypes) { break; } case aarch64_op_type::AARCH64_OP_INVALID: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_MEM_REG: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_MEM_IMM: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_FP: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_CIMM: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_REG_MRS: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_REG_MSR: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_IMPLICIT_IMM_0: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_SVCR: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_AT: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_DB: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_DC: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_ISB: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_TSB: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_PRFM: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_SVEPRFM: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_RPRFM: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_PSTATEIMM0_15: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_PSTATEIMM0_1: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_PSB: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_BTI: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_SVEPREDPAT: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_SVEVECLENSPECIFIER: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_SME: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_IMM_RANGE: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_TLBI: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_IC: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_DBNXS: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_EXACTFPIMM: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_SYSREG: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_SYSIMM: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_SYSALIAS: + [[fallthrough]]; case aarch64_op_type::AARCH64_OP_PRED: break; } diff --git a/src/lib/config/ModelConfig.cc b/src/lib/config/ModelConfig.cc index 0a8d3de34f..d4d7786c61 100644 --- a/src/lib/config/ModelConfig.cc +++ b/src/lib/config/ModelConfig.cc @@ -440,14 +440,16 @@ void ModelConfig::setExpectations(bool isDefault) { 1, UINT16_MAX); expectations_["Register-Set"].addChild( - ExpectationNode::createExpectation(1, "Matrix-Count", true)); - expectations_["Register-Set"]["Matrix-Count"].setValueBounds( + ExpectationNode::createExpectation(1, "SME-Matrix-Count", + true)); + expectations_["Register-Set"]["SME-Matrix-Count"].setValueBounds( 1, UINT16_MAX); expectations_["Register-Set"].addChild( - ExpectationNode::createExpectation(1, "Table-Count", true)); - expectations_["Register-Set"]["Table-Count"].setValueBounds( - 1, UINT16_MAX); + ExpectationNode::createExpectation( + 1, "SME-Lookup-Table-Count", true)); + expectations_["Register-Set"]["SME-Lookup-Table-Count"] + .setValueBounds(1, UINT16_MAX); } else if (isa_ == ISA::RV64) { // TODO: Reduce to 32 once renaming issue has been sorted. Also replace in // ConfigTest. diff --git a/test/integration/ConfigTest.cc b/test/integration/ConfigTest.cc index 432f307628..48975eeacd 100644 --- a/test/integration/ConfigTest.cc +++ b/test/integration/ConfigTest.cc @@ -48,7 +48,8 @@ TEST(ConfigTest, Default) { "5\n'Process-Image':\n 'Heap-Size': 100000\n 'Stack-Size': " "100000\n'Register-Set':\n 'GeneralPurpose-Count': 38\n " "'FloatingPoint/SVE-Count': 38\n 'Predicate-Count': 17\n " - "'Conditional-Count': 1\n 'Matrix-Count': 1\n 'Table-Count': " + "'Conditional-Count': 1\n 'SME-Matrix-Count': 1\n " + "'SME-Lookup-Table-Count': " "1\n'Pipeline-Widths':\n Commit: 1\n FrontEnd: 1\n 'LSQ-Completion': " "1\n'Queue-Sizes':\n ROB: 32\n Load: 16\n Store: " "16\n'Port-Allocator':\n Type: Balanced\n'Branch-Predictor':\n Type: " diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index 8ce53c16b2..bef7ca560f 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -16,7 +16,8 @@ FloatingPoint/SVE-Count: 90, Predicate-Count: 17, Conditional-Count: 128, - Matrix-Count: 2, + SME-Matrix-Count: 2, + SME-Lookup-Table-Count: 8, }, L1-Data-Memory: { From 71466342e614ca5d8ecd8c45eacaeb7ae22539c8 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Mon, 4 Nov 2024 17:51:31 +0000 Subject: [PATCH 30/34] Reverted to using old-values for SVE VL and fixed AArch64 decode catch case. --- src/lib/arch/aarch64/Instruction_decode.cc | 2 +- src/lib/config/ModelConfig.cc | 3 ++- test/regression/aarch64/AArch64RegressionTest.hh | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 2d595533ff..9d411195b5 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -839,7 +839,7 @@ void Instruction::decode() { if (((Opcode::AArch64_FMOVD0 <= metadata_.opcode && metadata_.opcode <= Opcode::AArch64_FMOVS0) || (Opcode::AArch64_FMOVDXHighr <= metadata_.opcode && - metadata_.opcode <= Opcode::AArch64_FMOVv8f16_ns)) && + metadata_.opcode <= Opcode::AArch64_FMOVXHr)) && !(isInstruction(InsnType::isScalarData) || isInstruction(InsnType::isVectorData))) { setInstructionType(InsnType::isScalarData); diff --git a/src/lib/config/ModelConfig.cc b/src/lib/config/ModelConfig.cc index d4d7786c61..6d54b50d06 100644 --- a/src/lib/config/ModelConfig.cc +++ b/src/lib/config/ModelConfig.cc @@ -370,7 +370,8 @@ void ModelConfig::setExpectations(bool isDefault) { expectations_["Core"].addChild(ExpectationNode::createExpectation( 128, "Vector-Length", true)); expectations_["Core"]["Vector-Length"].setValueSet( - std::vector{128, 256, 512, 1024, 2048}); + std::vector{128, 256, 384, 512, 640, 768, 896, 1024, 1152, + 1280, 1408, 1536, 1664, 1792, 1920, 2048}); expectations_["Core"].addChild(ExpectationNode::createExpectation( 128, "Streaming-Vector-Length", true)); diff --git a/test/regression/aarch64/AArch64RegressionTest.hh b/test/regression/aarch64/AArch64RegressionTest.hh index bef7ca560f..32d975b09d 100644 --- a/test/regression/aarch64/AArch64RegressionTest.hh +++ b/test/regression/aarch64/AArch64RegressionTest.hh @@ -77,7 +77,7 @@ inline std::string paramToString( inline std::vector> genCoreTypeVLPairs( CoreType type) { std::vector> coreVLPairs; - for (uint64_t i = 128; i <= 2048; i *= 2) { + for (uint64_t i = 128; i <= 2048; i += 128) { coreVLPairs.push_back(std::make_tuple( type, "{Core: {Vector-Length: " + std::to_string(i) + From 2ddbe03b1f69f83008a5b71e306ffb185b6d829d Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 7 Nov 2024 11:46:20 +0000 Subject: [PATCH 31/34] Cmake fix for building LLVM. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aeb3752f65..edc9b204ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,7 +222,7 @@ if(SIMENG_ENABLE_TESTS) # We also include the headers and CMake exports for a *complete* build install-llvm-headers install-cmake-exports - -j ${N} + -j ${NPROC} ${COMMAND_ECHO_OPTION} RESULT_VARIABLE SUCCESS) From 5e73600d1db2457777267552ca741fbbc016efd7 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Thu, 14 Nov 2024 10:10:38 +0000 Subject: [PATCH 32/34] Updated LLVM version in LINUX_BUILD_TEST. --- .github/workflows/LINUX_BUILD_TEST.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/LINUX_BUILD_TEST.yml b/.github/workflows/LINUX_BUILD_TEST.yml index 11545d9870..d3dcb86516 100644 --- a/.github/workflows/LINUX_BUILD_TEST.yml +++ b/.github/workflows/LINUX_BUILD_TEST.yml @@ -13,7 +13,7 @@ on: env: ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true - LLVM-VERSION: 14 + LLVM-VERSION: 18 BENCHMARK_BRANCH: 'make-file-build-system' # The branch inside the benchmark repo that has the script to run all benchmarks. PAT: ${{ secrets.SIMENGUOB_PAT }} From fc308dbeddcffccf2a7981f25bd8f3e3f5d82e19 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Tue, 10 Dec 2024 16:44:21 +0000 Subject: [PATCH 33/34] Made instruction decode more efficient WRT group checking against mnemonic. --- src/lib/arch/aarch64/Instruction_decode.cc | 357 ++++----------------- 1 file changed, 66 insertions(+), 291 deletions(-) diff --git a/src/lib/arch/aarch64/Instruction_decode.cc b/src/lib/arch/aarch64/Instruction_decode.cc index 9d411195b5..6d2007cb55 100644 --- a/src/lib/arch/aarch64/Instruction_decode.cc +++ b/src/lib/arch/aarch64/Instruction_decode.cc @@ -1,3 +1,5 @@ +#include + #include "InstructionMetadata.hh" #define NOT(bits, length) (~bits & (1 << length - 1)) @@ -9,6 +11,65 @@ namespace simeng { namespace arch { namespace aarch64 { +/************************** + * HELPER DATA STRUCTURES + **************************/ + +static const std::unordered_set logicalOps = { + "and", "bic", "bif", "bit", "bsl", "bcax", "bmop", + "eor", "eon", "mvn", "not", "nand", "nbsl", "nor", + "rax", "xar", "orr", "orq", "orv", "tst", "orn"}; + +static const std::unordered_set cmpOps = { + "ccmn", "cmn", "cmp", "cmpp", "cmpeq", "cmpge", "cmpgt", + "cmphi", "cmphs", "cmple", "cmplo", "cmpls", "cmplt", "cmpne", + "cmptst", "ccmp", "cmeq", "cmge", "cmgt", "cmtst", "cmhi", + "cmhs", "cmla", "cmle", "cmlt", "fac", "facge", "facgt", + "facle", "faclt", "fccmp", "fccmpe", "fcmp", "fcmpe", "fcmuo", + "fcmeq", "fcmge", "fcmgt", "fcmle", "fcmlt", "fcmne"}; + +static const std::unordered_set cvtOps = { + "bfcvt", "bfcvtn", "bfcvtnt", "bf1cvt", "bf1cvtl", "bf1cvtlt", + "bf2cvt", "bf2cvtl", "bf2cvtlt", "fcvt", "fcvtas", "fcvtau", + "fcvtl", "fcvtms", "fcvtmu", "fcvtn", "fcvtns", "fcvtnu", + "fcvtps", "fcvtpu", "fcvtxn", "fcvtzs", "fcvtzu", "fcvtlt", + "fcvtnb", "fcvtnt", "fcvtx", "fcvtxnt", "fcvtzs", "fcvtzu", + "f1cvt", "f1cvtl", "f1cvtlt", "f2cvt", "f2cvtl", "f2cvtlt", + "fjcvtzs", "scvtf", "ucvtf"}; + +static const std::unordered_set divsqrtOps = { + "sdiv", "sdivr", "udiv", "udivr", "fdiv", "fdivr", + "frsqrt", "frsqrte", "frsqrts", "fsqrt", "ursqrte"}; + +static const std::unordered_set mulOps = { + "bfmmla", "bfmul", "bfml", "bfmla", "bfmlalb", "bfmlalt", + "bfmlal", "bfmls", "bfmlslb", "bfmlslt", "bfmlsl", "cmla", + "dot", "bfdot", "bfvdot", "fdot", "fvdot", "fvdotb", + "fvdott", "sdot", "sudot", "suvdot", "udot", "usdot", + "usvdot", "uvdot", "cdot", "fmla", "fmlal", "fmlal2", + "fmlalb", "fmlalt", "fmlallbb", "fmlallbt", "fmlalltb", "fmlalltt", + "fmlall", "fmls", "fmlsl", "fmlsl2", "fmlslb", "fmlslt", + "fmul", "fmulx", "fmad", "fmadd", "fmmla", "fmsb", + "fmsub", "ftmad", "fcmla", "fnm", "fnmad", "fnmla", + "fnmls", "fnmsb", "fnmadd", "fnmsub", "fnmul", "madd", + "maddpt", "mul", "mla", "mlapt", "mls", "mneg", + "msub", "msubpt", "mad", "madpt", "msb", "mop", + "bfmopa", "bfmops", "bmopa", "bmops", "fmopa", "fmops", + "smopa", "smops", "sumopa", "sumops", "umopa", "umops", + "usmopa", "usmops", "pmul", "pmull", "pmull2", "pmullb", + "pmullt", "sml", "smlalb", "smlalt", "smlslb", "smlslt", + "smlal", "smlal2", "smlsl", "smlsl2", "smlall", "smlsll", + "smmla", "smul", "smulh", "smull", "smull2", "smullb", + "smullt", "sqdm", "sqdmlal", "sqdmlal2", "sqdmlsl", "sqdmlsl2", + "sqdmulh", "sqdmull", "sqdmull2", "sqdmlalb", "sqdmlalbt", "sqdmlalt", + "sqdmlslb", "sqdmlslbt", "sqdmlslt", "sqdmullb", "sqdmullt", "sqrd", + "sqrdmlah", "sqrdmlsh", "sqrdmulh", "sqrdcmlah", "sumlall", "smaddl", + "smnegl", "smsubl", "umul", "umulh", "umull", "umull2", + "umullb", "umullt", "uml", "umlal", "umlal2", "umlsl", + "umlsl2", "umlslt", "umlalb", "umlalt", "umlslb", "umlall", + "umlsll", "usmlall", "usmmla", "ummla", "umaddl", "umnegl", + "umsubl"}; + /******************** * HELPER FUNCTIONS *******************/ @@ -504,77 +565,12 @@ void Instruction::decode() { } // Identify Logical (bitwise) instructions - // Opcode prefix-overlaps have been commented out but left in for clarity - // what is searched for. - if (metadata_.mnemonic.find("and") == 0 || - metadata_.mnemonic.find("bic") == 0 || - metadata_.mnemonic.find("bif") == 0 || - metadata_.mnemonic.find("bit") == 0 || - metadata_.mnemonic.find("bsl") == 0 || - metadata_.mnemonic.find("bcax") == 0 || - metadata_.mnemonic.find("bmop") == 0 || - metadata_.mnemonic.find("eor") == 0 || - metadata_.mnemonic.find("eon") == 0 || - metadata_.mnemonic.find("mvn") == 0 || - metadata_.mnemonic.find("not") == 0 || - metadata_.mnemonic.find("nand") == 0 || - metadata_.mnemonic.find("nbsl") == 0 || - metadata_.mnemonic.find("nor") == 0 || - metadata_.mnemonic.find("rax") == 0 || - metadata_.mnemonic.find("xar") == 0 || - metadata_.mnemonic.find("orr") == 0 || - metadata_.mnemonic.find("orq") == 0 || - metadata_.mnemonic.find("orv") == 0 || - metadata_.mnemonic.find("tst") == 0 || - metadata_.mnemonic.find("orn") == 0) { + if (logicalOps.find(metadata_.mnemonic) != logicalOps.end()) { setInstructionType(InsnType::isLogical); } // Identify comparison insturctions (excluding atomic LD-CMP-STR) - // Opcode prefix-overlaps have been commented out but left in for clarity - // what is searched for. - if (metadata_.mnemonic.find("ccmn") == 0 || - metadata_.mnemonic.find("cmn") == 0 || - metadata_.mnemonic.find("cmp") == 0 || - // metadata_.mnemonic.find("cmpp") == 0 || - // metadata_.mnemonic.find("cmpeq") == 0 || - // metadata_.mnemonic.find("cmpge") == 0 || - // metadata_.mnemonic.find("cmpgt") == 0 || - // metadata_.mnemonic.find("cmphi") == 0 || - // metadata_.mnemonic.find("cmphs") == 0 || - // metadata_.mnemonic.find("cmple") == 0 || - // metadata_.mnemonic.find("cmplo") == 0 || - // metadata_.mnemonic.find("cmpls") == 0 || - // metadata_.mnemonic.find("cmplt") == 0 || - // metadata_.mnemonic.find("cmpne") == 0 || - // metadata_.mnemonic.find("cmptst") == 0 || - metadata_.mnemonic.find("ccmp") == 0 || - metadata_.mnemonic.find("cmeq") == 0 || - metadata_.mnemonic.find("cmge") == 0 || - metadata_.mnemonic.find("cmgt") == 0 || - metadata_.mnemonic.find("cmtst") == 0 || - metadata_.mnemonic.find("cmhi") == 0 || - metadata_.mnemonic.find("cmhs") == 0 || - metadata_.mnemonic.find("cmla") == 0 || - metadata_.mnemonic.find("cmle") == 0 || - metadata_.mnemonic.find("cmlt") == 0 || - // The non-complete opcode prefix `fac` only yields compare uops - metadata_.mnemonic.find("fac") == 0 || - // metadata_.mnemonic.find("facge") == 0 || - // metadata_.mnemonic.find("facgt") == 0 || - // metadata_.mnemonic.find("facle") == 0 || - // metadata_.mnemonic.find("faclt") == 0 || - metadata_.mnemonic.find("fccmp") == 0 || - // metadata_.mnemonic.find("fccmpe") == 0 || - metadata_.mnemonic.find("fcmp") == 0 || - // metadata_.mnemonic.find("fcmpe") == 0 || - metadata_.mnemonic.find("fcmuo") == 0 || - metadata_.mnemonic.find("fcmeq") == 0 || - metadata_.mnemonic.find("fcmge") == 0 || - metadata_.mnemonic.find("fcmgt") == 0 || - metadata_.mnemonic.find("fcmle") == 0 || - metadata_.mnemonic.find("fcmlt") == 0 || - metadata_.mnemonic.find("fcmne") == 0) { + if (cmpOps.find(metadata_.mnemonic) != cmpOps.end()) { setInstructionType(InsnType::isCompare); // Capture those floating point compare instructions with no destination // register @@ -588,47 +584,7 @@ void Instruction::decode() { } // Identify convert instructions - // Opcode prefix-overlaps have been commented out but left in for clarity - // what is searched for. - if (metadata_.mnemonic.find("bfcvt") == 0 || - // metadata_.mnemonic.find("bfcvtn") == 0 || - // metadata_.mnemonic.find("bfcvtnt") == 0 || - metadata_.mnemonic.find("bf1cvt") == 0 || - // metadata_.mnemonic.find("bf1cvtl") == 0 || - // metadata_.mnemonic.find("bf1cvtlt") == 0 || - metadata_.mnemonic.find("bf2cvt") == 0 || - // metadata_.mnemonic.find("bf2cvtl") == 0 || - // metadata_.mnemonic.find("bf2cvtlt") == 0 || - metadata_.mnemonic.find("fcvt") == 0 || - // metadata_.mnemonic.find("fcvtas") == 0 || - // metadata_.mnemonic.find("fcvtau") == 0 || - // metadata_.mnemonic.find("fcvtl") == 0 || - // metadata_.mnemonic.find("fcvtms") == 0 || - // metadata_.mnemonic.find("fcvtmu") == 0 || - // metadata_.mnemonic.find("fcvtn") == 0 || - // metadata_.mnemonic.find("fcvtns") == 0 || - // metadata_.mnemonic.find("fcvtnu") == 0 || - // metadata_.mnemonic.find("fcvtps") == 0 || - // metadata_.mnemonic.find("fcvtpu") == 0 || - // metadata_.mnemonic.find("fcvtxn") == 0 || - // metadata_.mnemonic.find("fcvtzs") == 0 || - // metadata_.mnemonic.find("fcvtzu") == 0 || - // metadata_.mnemonic.find("fcvtlt") == 0 || - // metadata_.mnemonic.find("fcvtnb") == 0 || - // metadata_.mnemonic.find("fcvtnt") == 0 || - // metadata_.mnemonic.find("fcvtx") == 0 || - // metadata_.mnemonic.find("fcvtxnt") == 0 || - // metadata_.mnemonic.find("fcvtzs") == 0 || - // metadata_.mnemonic.find("fcvtzu") == 0 || - metadata_.mnemonic.find("f1cvt") == 0 || - // metadata_.mnemonic.find("f1cvtl") == 0 || - // metadata_.mnemonic.find("f1cvtlt") == 0 || - metadata_.mnemonic.find("f2cvt") == 0 || - // metadata_.mnemonic.find("f2cvtl") == 0 || - // metadata_.mnemonic.find("f2cvtlt") == 0 || - metadata_.mnemonic.find("fjcvtzs") == 0 || - metadata_.mnemonic.find("scvtf") == 0 || - metadata_.mnemonic.find("ucvtf") == 0) { + if (cvtOps.find(metadata_.mnemonic) != cvtOps.end()) { setInstructionType(InsnType::isConvert); // Capture those floating point convert instructions whose destination // register is general purpose @@ -640,193 +596,12 @@ void Instruction::decode() { } // Identify divide or square root operations - // Opcode prefix-overlaps have been commented out but left in for clarity - // what is searched for. - if (metadata_.mnemonic.find("sdiv") == 0 || - // metadata_.mnemonic.find("sdivr") == 0 || - metadata_.mnemonic.find("udiv") == 0 || - // metadata_.mnemonic.find("udivr") == 0 || - metadata_.mnemonic.find("fdiv") == 0 || - // metadata_.mnemonic.find("fdivr") == 0 || - // The non-complete opcode prefix `frsqrt` only yields divSqrt uops - metadata_.mnemonic.find("frsqrt") == 0 || - // metadata_.mnemonic.find("frsqrte") == 0 || - // metadata_.mnemonic.find("frsqrts") == 0 || - metadata_.mnemonic.find("fsqrt") == 0 || - metadata_.mnemonic.find("ursqrte") == 0) { + if (divsqrtOps.find(metadata_.mnemonic) != divsqrtOps.end()) { setInstructionType(InsnType::isDivideOrSqrt); } // Identify multiply operations - // Opcode prefix-overlaps have been commented out but left in for clarity - // what is searched for. - if (metadata_.mnemonic.find("bfmmla") == 0 || - metadata_.mnemonic.find("bfmul") == 0 || - // The non-complete opcode prefix `bfml` only yields multiply uops - metadata_.mnemonic.find("bfml") == 0 || - // metadata_.mnemonic.find("bfmla") == 0 || - // metadata_.mnemonic.find("bfmlalb") == 0 || - // metadata_.mnemonic.find("bfmlalt") == 0 || - // metadata_.mnemonic.find("bfmlal") == 0 || - // metadata_.mnemonic.find("bfmls") == 0 || - // metadata_.mnemonic.find("bfmlslb") == 0 || - // metadata_.mnemonic.find("bfmlslt") == 0 || - // metadata_.mnemonic.find("bfmlsl") == 0 || - metadata_.mnemonic.find("cmla") == 0 || - // The substring `dot` only appears in dot-product opcodes - metadata_.mnemonic.find("dot") != std::string::npos || - // metadata_.mnemonic.find("bfdot") == 0 || - // metadata_.mnemonic.find("bfvdot") == 0 || - // metadata_.mnemonic.find("fdot") == 0 || - // metadata_.mnemonic.find("fvdot") == 0 || - // metadata_.mnemonic.find("fvdotb") == 0 || - // metadata_.mnemonic.find("fvdott") == 0 || - // metadata_.mnemonic.find("sdot") == 0 || - // metadata_.mnemonic.find("sudot") == 0 || - // metadata_.mnemonic.find("suvdot") == 0 || - // metadata_.mnemonic.find("udot") == 0 || - // metadata_.mnemonic.find("usdot") == 0 || - // metadata_.mnemonic.find("usvdot") == 0 || - // metadata_.mnemonic.find("uvdot") == 0 || - // metadata_.mnemonic.find("cdot") == 0 || - metadata_.mnemonic.find("fmla") == 0 || - // metadata_.mnemonic.find("fmlal") == 0 || - // metadata_.mnemonic.find("fmlal2") == 0 || - // metadata_.mnemonic.find("fmlalb") == 0 || - // metadata_.mnemonic.find("fmlalt") == 0 || - // metadata_.mnemonic.find("fmlallbb") == 0 || - // metadata_.mnemonic.find("fmlallbt") == 0 || - // metadata_.mnemonic.find("fmlalltb") == 0 || - // metadata_.mnemonic.find("fmlalltt") == 0 || - // metadata_.mnemonic.find("fmlall") == 0 || - metadata_.mnemonic.find("fmls") == 0 || - // metadata_.mnemonic.find("fmlsl") == 0 || - // metadata_.mnemonic.find("fmlsl2") == 0 || - // metadata_.mnemonic.find("fmlslb") == 0 || - // metadata_.mnemonic.find("fmlslt") == 0 || - metadata_.mnemonic.find("fmul") == 0 || - // metadata_.mnemonic.find("fmulx") == 0 || - metadata_.mnemonic.find("fmad") == 0 || - // metadata_.mnemonic.find("fmadd") == 0 || - metadata_.mnemonic.find("fmmla") == 0 || - metadata_.mnemonic.find("fmsb") == 0 || - metadata_.mnemonic.find("fmsub") == 0 || - metadata_.mnemonic.find("ftmad") == 0 || - metadata_.mnemonic.find("fcmla") == 0 || - // The non-complete opcode prefix `fnm` only yields multiply uops - metadata_.mnemonic.find("fnm") == 0 || - // metadata_.mnemonic.find("fnmad") == 0 || - // metadata_.mnemonic.find("fnmla") == 0 || - // metadata_.mnemonic.find("fnmls") == 0 || - // metadata_.mnemonic.find("fnmsb") == 0 || - // metadata_.mnemonic.find("fnmadd") == 0 || - // metadata_.mnemonic.find("fnmsub") == 0 || - // metadata_.mnemonic.find("fnmul") == 0 || - metadata_.mnemonic.find("madd") == 0 || - // metadata_.mnemonic.find("maddpt") == 0 || - metadata_.mnemonic.find("mul") == 0 || - metadata_.mnemonic.find("mla") == 0 || - // metadata_.mnemonic.find("mlapt") == 0 || - metadata_.mnemonic.find("mls") == 0 || - metadata_.mnemonic.find("mneg") == 0 || - metadata_.mnemonic.find("msub") == 0 || - // metadata_.mnemonic.find("msubpt") == 0 || - metadata_.mnemonic.find("mad") == 0 || - // metadata_.mnemonic.find("madpt") == 0 || - metadata_.mnemonic.find("msb") == 0 || - // The substring `mop` only appears in outer-product opcodes - metadata_.mnemonic.find("mop") != std::string::npos || - // metadata_.mnemonic.find("bfmopa") == 0 || - // metadata_.mnemonic.find("bfmops") == 0 || - // metadata_.mnemonic.find("bmopa") == 0 || - // metadata_.mnemonic.find("bmops") == 0 || - // metadata_.mnemonic.find("fmopa") == 0 || - // metadata_.mnemonic.find("fmops") == 0 || - // metadata_.mnemonic.find("smopa") == 0 || - // metadata_.mnemonic.find("smops") == 0 || - // metadata_.mnemonic.find("sumopa") == 0 || - // metadata_.mnemonic.find("sumops") == 0 || - // metadata_.mnemonic.find("umopa") == 0 || - // metadata_.mnemonic.find("umops") == 0 || - // metadata_.mnemonic.find("usmopa") == 0 || - // metadata_.mnemonic.find("usmops") == 0 - metadata_.mnemonic.find("pmul") == 0 || - // metadata_.mnemonic.find("pmull") == 0 || - // metadata_.mnemonic.find("pmull2") == 0 || - // metadata_.mnemonic.find("pmullb") == 0 || - // metadata_.mnemonic.find("pmullt") == 0 || - // The non-complete opcode prefix `sml` only yields multiply uops - metadata_.mnemonic.find("sml") == 0 || - // metadata_.mnemonic.find("smlalb") == 0 || - // metadata_.mnemonic.find("smlalt") == 0 || - // metadata_.mnemonic.find("smlslb") == 0 || - // metadata_.mnemonic.find("smlslt") == 0 || - // metadata_.mnemonic.find("smlal") == 0 || - // metadata_.mnemonic.find("smlal2") == 0 || - // metadata_.mnemonic.find("smlsl") == 0 || - // metadata_.mnemonic.find("smlsl2") == 0 || - // metadata_.mnemonic.find("smlall") == 0 || - // metadata_.mnemonic.find("smlsll") == 0 || - metadata_.mnemonic.find("smmla") == 0 || - // The non-complete opcode prefix `smul` only yields multiply uops - metadata_.mnemonic.find("smul") == 0 || - // metadata_.mnemonic.find("smulh") == 0 || - // metadata_.mnemonic.find("smull") == 0 || - // metadata_.mnemonic.find("smull2") == 0 || - // metadata_.mnemonic.find("smullb") == 0 || - // metadata_.mnemonic.find("smullt") == 0 || - // The non-complete opcode prefix `sqdm` only yields multiply uops - metadata_.mnemonic.find("sqdm") == 0 || - // metadata_.mnemonic.find("sqdmlal") == 0 || - // metadata_.mnemonic.find("sqdmlal2") == 0 || - // metadata_.mnemonic.find("sqdmlsl") == 0 || - // metadata_.mnemonic.find("sqdmlsl2") == 0 || - // metadata_.mnemonic.find("sqdmulh") == 0 || - // metadata_.mnemonic.find("sqdmull") == 0 || - // metadata_.mnemonic.find("sqdmull2") == 0 || - // metadata_.mnemonic.find("sqdmlalb") == 0 || - // metadata_.mnemonic.find("sqdmlalbt") == 0 || - // metadata_.mnemonic.find("sqdmlalt") == 0 || - // metadata_.mnemonic.find("sqdmlslb") == 0 || - // metadata_.mnemonic.find("sqdmlslbt") == 0 || - // metadata_.mnemonic.find("sqdmlslt") == 0 || - // metadata_.mnemonic.find("sqdmullb") == 0 || - // metadata_.mnemonic.find("sqdmullt") == 0 || - // The non-complete opcode prefix `sqrd` only yields multiply uops - metadata_.mnemonic.find("sqrd") == 0 || - // metadata_.mnemonic.find("sqrdmlah") == 0 || - // metadata_.mnemonic.find("sqrdmlsh") == 0 || - // metadata_.mnemonic.find("sqrdmulh") == 0 || - // metadata_.mnemonic.find("sqrdcmlah") == 0 || - metadata_.mnemonic.find("sumlall") == 0 || - metadata_.mnemonic.find("smaddl") == 0 || - metadata_.mnemonic.find("smnegl") == 0 || - metadata_.mnemonic.find("smsubl") == 0 || - // The non-complete opcode prefix `umul` only yields multiply uops - metadata_.mnemonic.find("umul") == 0 || - // metadata_.mnemonic.find("umulh") == 0 || - // metadata_.mnemonic.find("umull") == 0 || - // metadata_.mnemonic.find("umull2") == 0 || - // metadata_.mnemonic.find("umullb") == 0 || - // metadata_.mnemonic.find("umullt") == 0 || - // The non-complete opcode prefix `uml` only yields multiply uops - metadata_.mnemonic.find("uml") == 0 || - // metadata_.mnemonic.find("umlal") == 0 || - // metadata_.mnemonic.find("umlal2") == 0 || - // metadata_.mnemonic.find("umlsl") == 0 || - // metadata_.mnemonic.find("umlsl2") == 0 || - // metadata_.mnemonic.find("umlslt") == 0 || - // metadata_.mnemonic.find("umlalb") == 0 || - // metadata_.mnemonic.find("umlalt") == 0 || - // metadata_.mnemonic.find("umlslb") == 0 || - // metadata_.mnemonic.find("umlall") == 0 || - // metadata_.mnemonic.find("umlsll") == 0 || - metadata_.mnemonic.find("usmlall") == 0 || - metadata_.mnemonic.find("usmmla") == 0 || - metadata_.mnemonic.find("ummla") == 0 || - metadata_.mnemonic.find("umaddl") == 0 || - metadata_.mnemonic.find("umnegl") == 0 || - metadata_.mnemonic.find("umsubl") == 0) { + if (mulOps.find(metadata_.mnemonic) != mulOps.end()) { setInstructionType(InsnType::isMultiply); } From 1f0084f3fe5aea2365c0e86d35ecd2679242b862 Mon Sep 17 00:00:00 2001 From: Finn Wilkinson Date: Wed, 18 Dec 2024 15:06:44 +0000 Subject: [PATCH 34/34] Updated cmake file comments. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index edc9b204ae..b8f4379b98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,7 +203,7 @@ if(SIMENG_ENABLE_TESTS) ${COMMAND_ECHO_OPTION} RESULT_VARIABLE SUCCESS) - # XXX replace with COMMAND_ERROR_IS_FATAL in the future (>= 3.19) + # TODO: replace with COMMAND_ERROR_IS_FATAL in the future (>= 3.19) if (NOT SUCCESS EQUAL "0") message(FATAL_ERROR "LLVM configure did not succeed") else () @@ -227,7 +227,7 @@ if(SIMENG_ENABLE_TESTS) ${COMMAND_ECHO_OPTION} RESULT_VARIABLE SUCCESS) - # XXX replace with COMMAND_ERROR_IS_FATAL in the future (>= 3.19) + # TODO: replace with COMMAND_ERROR_IS_FATAL in the future (>= 3.19) if (NOT SUCCESS EQUAL "0") message(FATAL_ERROR "LLVM build did not succeed") endif ()