/* Capstone Disassembly Engine, http://www.capstone-engine.org */ /* By Nguyen Anh Quynh , 2013-2022, */ /* Rot127 2022-2023 */ /* Automatically translated source file from LLVM. */ /* LLVM-commit: */ /* LLVM-tag: */ /* Only small edits allowed. */ /* For multiple similar edits, please create a Patch for the translator. */ /* Capstone's C++ file translator: */ /* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */ //===- AArch64Disassembler.cpp - Disassembler for AArch64 -----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // //===----------------------------------------------------------------------===// #include #include #include #include #include "../../MCFixedLenDisassembler.h" #include "../../MCInst.h" #include "../../MCInstrDesc.h" #include "../../MCRegisterInfo.h" #include "../../LEB128.h" #include "../../MCDisassembler.h" #include "../../cs_priv.h" #include "../../utils.h" #include "AArch64AddressingModes.h" #include "AArch64BaseInfo.h" #include "AArch64DisassemblerExtension.h" #include "AArch64Linkage.h" #include "AArch64Mapping.h" #define GET_INSTRINFO_MC_DESC #include "AArch64GenInstrInfo.inc" #define CONCAT(a, b) CONCAT_(a, b) #define CONCAT_(a, b) a##_##b #define DEBUG_TYPE "aarch64-disassembler" // Pull DecodeStatus and its enum values into the global namespace. // Forward declare these because the autogenerated code will reference them. // Definitions are further down. static DecodeStatus DecodeFPR128RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR128_loRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR128_0to7RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR64RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR32RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR16RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR8RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR64commonRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR64RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR64x8ClassRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR64spRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMatrixIndexGPR32_8_11RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMatrixIndexGPR32_12_15RegisterClass( MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR32RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR32spRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeQQRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeQQQRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeQQQQRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDDRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDDDRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDDDDRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeZPRRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeZPR_4bRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeZPR_3bRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeZPR2RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeZPR3RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeZPR4RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeZPR2Mul2RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeZPR4Mul4RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeZPR2StridedRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeZPR4StridedRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); #define DECLARE_DecodeMatrixTile(NumBitsForTile) \ static DecodeStatus CONCAT(DecodeMatrixTile, NumBitsForTile)( \ MCInst * Inst, unsigned RegNo, uint64_t Address, \ const void *Decoder); DECLARE_DecodeMatrixTile(2); DECLARE_DecodeMatrixTile(1); DECLARE_DecodeMatrixTile(3); DECLARE_DecodeMatrixTile(4); static DecodeStatus DecodeMatrixTileListRegisterClass(MCInst *Inst, unsigned RegMask, uint64_t Address, const void *Decoder); static DecodeStatus DecodePPRRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodePNRRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodePPR_3bRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodePNR_p8to15RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodePPR2RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodePPR2Mul2RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFixedPointScaleImm32(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFixedPointScaleImm64(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodePCRelLabel16(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodePCRelLabel19(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMemExtend(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMRSSystemRegister(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMSRSystemRegister(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeThreeAddrSRegInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMoveImmInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeUnsignedLdStInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSignedLdStInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeExclusiveLdStInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodePairLdStInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeAuthLoadInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeAddSubERegInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeLogicalImmInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeModImmInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeModImmTiedInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeAdrInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeAddSubImmShift(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeUnconditionalBranch(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSystemPStateImm0_15Instruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSystemPStateImm0_1Instruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeTestAndBranch(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFMOVLaneInstruction(MCInst *Inst, unsigned Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeVecShiftR64Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR64ImmNarrow(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR32Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR32ImmNarrow(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR16Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR16ImmNarrow(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR8Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftL64Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftL32Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftL16Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftL8Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeWSeqPairsClassRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeXSeqPairsClassRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeSyspXzrInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeSVELogicalImmInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); #define DECLARE_DecodeSImm(Bits) \ static DecodeStatus CONCAT(DecodeSImm, Bits)(MCInst * Inst, \ uint64_t Imm, \ uint64_t Address, \ const void *Decoder); DECLARE_DecodeSImm(4); DECLARE_DecodeSImm(5); DECLARE_DecodeSImm(6); DECLARE_DecodeSImm(8); DECLARE_DecodeSImm(9); DECLARE_DecodeSImm(10); #define DECLARE_DecodeImm8OptLsl(ElementWidth) \ static DecodeStatus CONCAT(DecodeImm8OptLsl, ElementWidth)( \ MCInst * Inst, unsigned Imm, uint64_t Addr, \ const void *Decoder); DECLARE_DecodeImm8OptLsl(8); DECLARE_DecodeImm8OptLsl(16); DECLARE_DecodeImm8OptLsl(32); DECLARE_DecodeImm8OptLsl(64); static DecodeStatus DecodeSVEIncDecImm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeSVCROp(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeCPYMemOpInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeSETMemOpInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder); static DecodeStatus DecodePRFMRegInstruction(MCInst *Inst, uint32_t insn, uint64_t Address, const void *Decoder); #include "AArch64GenDisassemblerTables.inc" #define Success MCDisassembler_Success #define Fail MCDisassembler_Fail #define SoftFail MCDisassembler_SoftFail static DecodeStatus getInstruction(csh handle, const uint8_t *Bytes, size_t ByteLen, MCInst *MI, uint16_t *Size, uint64_t Address, void *Info) { *Size = 0; // We want to read exactly 4 bytes of data. if (ByteLen < 4) return Fail; *Size = 4; // Encoded as a small-endian 32-bit word in the stream. uint32_t Insn = readBytes32(MI, Bytes); const uint8_t *Tables[] = { DecoderTable32, DecoderTableFallback32 }; for (int i = 0; i < (sizeof(Tables) / sizeof(Tables[0])); ++i) { void *Decoder = NULL; DecodeStatus Result = decodeInstruction_4(Tables[i], MI, Insn, Address, Decoder); // Table is indexed backwards const MCInstrDesc Desc = AArch64Descs.Insts[ARR_SIZE(AArch64Descs.Insts) - 1 - MCInst_getOpcode(MI)]; // For Scalable Matrix Extension (SME) instructions that have an // implicit operand for the accumulator (ZA) or implicit immediate zero // which isn't encoded, manually insert operand. for (unsigned j = 0; j < Desc.NumOperands; j++) { if (Desc.OpInfo[j].OperandType == MCOI_OPERAND_REGISTER) { switch (Desc.OpInfo[j].RegClass) { default: break; case AArch64_MPRRegClassID: MCInst_insert0(MI, j, MCOperand_CreateReg1( MI, AArch64_ZA)); break; case AArch64_MPR8RegClassID: MCInst_insert0(MI, j, MCOperand_CreateReg1( MI, AArch64_ZAB0)); break; case AArch64_ZTRRegClassID: MCInst_insert0(MI, j, MCOperand_CreateReg1( MI, AArch64_ZT0)); break; } } else if (Desc.OpInfo[j].OperandType == AARCH64_OP_IMPLICIT_IMM_0) { MCInst_insert0(MI, j, MCOperand_CreateImm1(MI, 0)); } } if (MCInst_getOpcode(MI) == AArch64_LDR_ZA || MCInst_getOpcode(MI) == AArch64_STR_ZA) { // Spill and fill instructions have a single immediate used for both // the vector select offset and optional memory offset. Replicate // the decoded immediate. MCOperand *Imm4Op = MCInst_getOperand(MI, (2)); MCInst_addOperand2(MI, (Imm4Op)); } if (Result != MCDisassembler_Fail) return Result; } return MCDisassembler_Fail; } DecodeStatus AArch64_LLVM_getInstruction(csh handle, const uint8_t *Bytes, size_t ByteLen, MCInst *MI, uint16_t *Size, uint64_t Address, void *Info) { DecodeStatus Result = MCDisassembler_Fail; Result = getInstruction(handle, Bytes, ByteLen, MI, Size, Address, Info); MCInst_handleWriteback(MI, AArch64Descs.Insts, ARR_SIZE(AArch64Descs.Insts)); return Result; } uint64_t suggestBytesToSkip(const uint8_t *Bytes, uint64_t Address) { // AArch64 instructions are always 4 bytes wide, so there's no point // in skipping any smaller number of bytes if an instruction can't // be decoded. return 4; } static DecodeStatus DecodeFPR128RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_FPR128RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeFPR128_loRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 15) return Fail; return DecodeFPR128RegisterClass(Inst, RegNo, Addr, Decoder); } static DecodeStatus DecodeFPR128_0to7RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 7) return Fail; return DecodeFPR128RegisterClass(Inst, RegNo, Addr, Decoder); } static DecodeStatus DecodeFPR64RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_FPR64RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeFPR32RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_FPR32RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeFPR16RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_FPR16RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeFPR8RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_FPR8RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeGPR64commonRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 30) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_GPR64commonRegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeGPR64RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_GPR64RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeGPR64x8ClassRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 22) return Fail; if (RegNo & 1) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_GPR64x8ClassRegClassID] .RegsBegin[RegNo >> 1]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeGPR64spRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_GPR64spRegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeMatrixIndexGPR32_8_11RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 3) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_MatrixIndexGPR32_8_11RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeMatrixIndexGPR32_12_15RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 3) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_MatrixIndexGPR32_12_15RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeGPR32RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_GPR32RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeGPR32spRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_GPR32spRegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeZPRRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_ZPRRegClassID].RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeZPR_4bRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 15) return Fail; return DecodeZPRRegisterClass(Inst, RegNo, Address, Decoder); } static DecodeStatus DecodeZPR_3bRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) return Fail; return DecodeZPRRegisterClass(Inst, RegNo, Address, Decoder); } static DecodeStatus DecodeZPR2RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_ZPR2RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeZPR3RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_ZPR3RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeZPR4RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_ZPR4RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeZPR2Mul2RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo * 2 > 30) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_ZPR2RegClassID] .RegsBegin[RegNo * 2]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeZPR4Mul4RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo * 4 > 28) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_ZPR4RegClassID] .RegsBegin[RegNo * 4]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeZPR2StridedRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 15) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_ZPR2StridedRegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeZPR4StridedRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_ZPR4StridedRegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeMatrixTileListRegisterClass(MCInst *Inst, unsigned RegMask, uint64_t Address, const void *Decoder) { if (RegMask > 0xFF) return Fail; MCOperand_CreateImm0(Inst, (RegMask)); return Success; } static const MCPhysReg MatrixZATileDecoderTable[5][16] = { { AArch64_ZAB0 }, { AArch64_ZAH0, AArch64_ZAH1 }, { AArch64_ZAS0, AArch64_ZAS1, AArch64_ZAS2, AArch64_ZAS3 }, { AArch64_ZAD0, AArch64_ZAD1, AArch64_ZAD2, AArch64_ZAD3, AArch64_ZAD4, AArch64_ZAD5, AArch64_ZAD6, AArch64_ZAD7 }, { AArch64_ZAQ0, AArch64_ZAQ1, AArch64_ZAQ2, AArch64_ZAQ3, AArch64_ZAQ4, AArch64_ZAQ5, AArch64_ZAQ6, AArch64_ZAQ7, AArch64_ZAQ8, AArch64_ZAQ9, AArch64_ZAQ10, AArch64_ZAQ11, AArch64_ZAQ12, AArch64_ZAQ13, AArch64_ZAQ14, AArch64_ZAQ15 } }; #define DEFINE_DecodeMatrixTile(NumBitsForTile) \ static DecodeStatus CONCAT(DecodeMatrixTile, NumBitsForTile)( \ MCInst * Inst, unsigned RegNo, uint64_t Address, \ const void *Decoder) \ { \ unsigned LastReg = (1 << NumBitsForTile) - 1; \ if (RegNo > LastReg) \ return Fail; \ MCOperand_CreateReg0( \ Inst, \ (MatrixZATileDecoderTable[NumBitsForTile][RegNo])); \ return Success; \ } DEFINE_DecodeMatrixTile(2); DEFINE_DecodeMatrixTile(1); DEFINE_DecodeMatrixTile(3); DEFINE_DecodeMatrixTile(4); static DecodeStatus DecodePPRRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 15) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_PPRRegClassID].RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodePNRRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 15) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_PNRRegClassID].RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodePPR_3bRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 7) return Fail; // Just reuse the PPR decode table return DecodePPRRegisterClass(Inst, RegNo, Addr, Decoder); } static DecodeStatus DecodePNR_p8to15RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 7) return Fail; // Just reuse the PPR decode table return DecodePNRRegisterClass(Inst, RegNo + 8, Addr, Decoder); } static DecodeStatus DecodePPR2RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 15) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_PPR2RegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodePPR2Mul2RegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if ((RegNo * 2) > 14) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_PPR2RegClassID] .RegsBegin[RegNo * 2]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeQQRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_QQRegClassID].RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeQQQRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_QQQRegClassID].RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeQQQQRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_QQQQRegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeDDRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_DDRegClassID].RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeDDDRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_DDDRegClassID].RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeDDDDRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = AArch64MCRegisterClasses[AArch64_DDDDRegClassID] .RegsBegin[RegNo]; MCOperand_CreateReg0(Inst, (Register)); return Success; } static DecodeStatus DecodeFixedPointScaleImm32(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { // scale{5} is asserted as 1 in tblgen. Imm |= 0x20; MCOperand_CreateImm0(Inst, (64 - Imm)); return Success; } static DecodeStatus DecodeFixedPointScaleImm64(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { MCOperand_CreateImm0(Inst, (64 - Imm)); return Success; } static DecodeStatus DecodePCRelLabel16(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { // Immediate is encoded as the top 16-bits of an unsigned 18-bit negative // PC-relative offset. uint64_t ImmVal = Imm; if (ImmVal > (1 << 16)) return Fail; // Symbols are not supported by Capstone return Success; } static DecodeStatus DecodePCRelLabel19(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { int64_t ImmVal = Imm; // Sign-extend 19-bit immediate. if (ImmVal & (1 << (19 - 1))) ImmVal |= ~((1LL << 19) - 1); // No symbols supported in Capstone // if (!Decoder->tryAddingSymbolicOperand( // Inst, ImmVal * 4, Addr, MCInst_getOpcode(Inst) != AArch64_LDRXl, 0, // 0, 4)) MCOperand_CreateImm0(Inst, (ImmVal)); return Success; } static DecodeStatus DecodeMemExtend(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder) { MCOperand_CreateImm0(Inst, ((Imm >> 1) & 1)); MCOperand_CreateImm0(Inst, (Imm & 1)); return Success; } static DecodeStatus DecodeMRSSystemRegister(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder) { MCOperand_CreateImm0(Inst, (Imm)); // Every system register in the encoding space is valid with the syntax // S____, so decoding system registers always // succeeds. return Success; } static DecodeStatus DecodeMSRSystemRegister(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder) { MCOperand_CreateImm0(Inst, (Imm)); return Success; } static DecodeStatus DecodeFMOVLaneInstruction(MCInst *Inst, unsigned Insn, uint64_t Address, const void *Decoder) { // This decoder exists to add the dummy Lane operand to the MCInst, which // must be 1 in assembly but has no other real manifestation. unsigned Rd = fieldFromInstruction_4(Insn, 0, 5); unsigned Rn = fieldFromInstruction_4(Insn, 5, 5); unsigned IsToVec = fieldFromInstruction_4(Insn, 16, 1); if (IsToVec) { DecodeFPR128RegisterClass(Inst, Rd, Address, Decoder); DecodeGPR64RegisterClass(Inst, Rn, Address, Decoder); } else { DecodeGPR64RegisterClass(Inst, Rd, Address, Decoder); DecodeFPR128RegisterClass(Inst, Rn, Address, Decoder); } // Add the lane MCOperand_CreateImm0(Inst, (1)); return Success; } static DecodeStatus DecodeVecShiftRImm(MCInst *Inst, unsigned Imm, unsigned Add) { MCOperand_CreateImm0(Inst, (Add - Imm)); return Success; } static DecodeStatus DecodeVecShiftLImm(MCInst *Inst, unsigned Imm, unsigned Add) { MCOperand_CreateImm0(Inst, ((Imm + Add) & (Add - 1))); return Success; } static DecodeStatus DecodeVecShiftR64Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm, 64); } static DecodeStatus DecodeVecShiftR64ImmNarrow(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm | 0x20, 64); } static DecodeStatus DecodeVecShiftR32Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm, 32); } static DecodeStatus DecodeVecShiftR32ImmNarrow(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm | 0x10, 32); } static DecodeStatus DecodeVecShiftR16Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm, 16); } static DecodeStatus DecodeVecShiftR16ImmNarrow(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm | 0x8, 16); } static DecodeStatus DecodeVecShiftR8Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm, 8); } static DecodeStatus DecodeVecShiftL64Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftLImm(Inst, Imm, 64); } static DecodeStatus DecodeVecShiftL32Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftLImm(Inst, Imm, 32); } static DecodeStatus DecodeVecShiftL16Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftLImm(Inst, Imm, 16); } static DecodeStatus DecodeVecShiftL8Imm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftLImm(Inst, Imm, 8); } static DecodeStatus DecodeThreeAddrSRegInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction_4(insn, 0, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); unsigned Rm = fieldFromInstruction_4(insn, 16, 5); unsigned shiftHi = fieldFromInstruction_4(insn, 22, 2); unsigned shiftLo = fieldFromInstruction_4(insn, 10, 6); unsigned shift = (shiftHi << 6) | shiftLo; switch (MCInst_getOpcode(Inst)) { default: return Fail; case AArch64_ADDWrs: case AArch64_ADDSWrs: case AArch64_SUBWrs: case AArch64_SUBSWrs: // if shift == '11' then ReservedValue() if (shiftHi == 0x3) return Fail; // fall through case AArch64_ANDWrs: case AArch64_ANDSWrs: case AArch64_BICWrs: case AArch64_BICSWrs: case AArch64_ORRWrs: case AArch64_ORNWrs: case AArch64_EORWrs: case AArch64_EONWrs: { // if sf == '0' and imm6<5> == '1' then ReservedValue() if (shiftLo >> 5 == 1) return Fail; DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); break; } case AArch64_ADDXrs: case AArch64_ADDSXrs: case AArch64_SUBXrs: case AArch64_SUBSXrs: // if shift == '11' then ReservedValue() if (shiftHi == 0x3) return Fail; // fall through case AArch64_ANDXrs: case AArch64_ANDSXrs: case AArch64_BICXrs: case AArch64_BICSXrs: case AArch64_ORRXrs: case AArch64_ORNXrs: case AArch64_EORXrs: case AArch64_EONXrs: DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); break; } MCOperand_CreateImm0(Inst, (shift)); return Success; } static DecodeStatus DecodeMoveImmInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction_4(insn, 0, 5); unsigned imm = fieldFromInstruction_4(insn, 5, 16); unsigned shift = fieldFromInstruction_4(insn, 21, 2); shift <<= 4; switch (MCInst_getOpcode(Inst)) { default: return Fail; case AArch64_MOVZWi: case AArch64_MOVNWi: case AArch64_MOVKWi: if (shift & (1U << 5)) return Fail; DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); break; case AArch64_MOVZXi: case AArch64_MOVNXi: case AArch64_MOVKXi: DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); break; } if (MCInst_getOpcode(Inst) == AArch64_MOVKWi || MCInst_getOpcode(Inst) == AArch64_MOVKXi) MCInst_addOperand2(Inst, (MCInst_getOperand(Inst, (0)))); MCOperand_CreateImm0(Inst, (imm)); MCOperand_CreateImm0(Inst, (shift)); return Success; } static DecodeStatus DecodeUnsignedLdStInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rt = fieldFromInstruction_4(insn, 0, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); unsigned offset = fieldFromInstruction_4(insn, 10, 12); switch (MCInst_getOpcode(Inst)) { default: return Fail; case AArch64_PRFMui: // Rt is an immediate in prefetch. MCOperand_CreateImm0(Inst, (Rt)); break; case AArch64_STRBBui: case AArch64_LDRBBui: case AArch64_LDRSBWui: case AArch64_STRHHui: case AArch64_LDRHHui: case AArch64_LDRSHWui: case AArch64_STRWui: case AArch64_LDRWui: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDRSBXui: case AArch64_LDRSHXui: case AArch64_LDRSWui: case AArch64_STRXui: case AArch64_LDRXui: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDRQui: case AArch64_STRQui: DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDRDui: case AArch64_STRDui: DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDRSui: case AArch64_STRSui: DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDRHui: case AArch64_STRHui: DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDRBui: case AArch64_STRBui: DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder); break; } DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); // No symbols supported in Capstone // if (!Decoder->tryAddingSymbolicOperand(Inst, offset, Addr, Fail, 0, 0, 4)) MCOperand_CreateImm0(Inst, (offset)); return Success; } static DecodeStatus DecodeSignedLdStInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rt = fieldFromInstruction_4(insn, 0, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); int64_t offset = fieldFromInstruction_4(insn, 12, 9); // offset is a 9-bit signed immediate, so sign extend it to // fill the unsigned. if (offset & (1 << (9 - 1))) offset |= ~((1LL << 9) - 1); // First operand is always the writeback to the address register, if needed. switch (MCInst_getOpcode(Inst)) { default: break; case AArch64_LDRSBWpre: case AArch64_LDRSHWpre: case AArch64_STRBBpre: case AArch64_LDRBBpre: case AArch64_STRHHpre: case AArch64_LDRHHpre: case AArch64_STRWpre: case AArch64_LDRWpre: case AArch64_LDRSBWpost: case AArch64_LDRSHWpost: case AArch64_STRBBpost: case AArch64_LDRBBpost: case AArch64_STRHHpost: case AArch64_LDRHHpost: case AArch64_STRWpost: case AArch64_LDRWpost: case AArch64_LDRSBXpre: case AArch64_LDRSHXpre: case AArch64_STRXpre: case AArch64_LDRSWpre: case AArch64_LDRXpre: case AArch64_LDRSBXpost: case AArch64_LDRSHXpost: case AArch64_STRXpost: case AArch64_LDRSWpost: case AArch64_LDRXpost: case AArch64_LDRQpre: case AArch64_STRQpre: case AArch64_LDRQpost: case AArch64_STRQpost: case AArch64_LDRDpre: case AArch64_STRDpre: case AArch64_LDRDpost: case AArch64_STRDpost: case AArch64_LDRSpre: case AArch64_STRSpre: case AArch64_LDRSpost: case AArch64_STRSpost: case AArch64_LDRHpre: case AArch64_STRHpre: case AArch64_LDRHpost: case AArch64_STRHpost: case AArch64_LDRBpre: case AArch64_STRBpre: case AArch64_LDRBpost: case AArch64_STRBpost: DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); break; } switch (MCInst_getOpcode(Inst)) { default: return Fail; case AArch64_PRFUMi: // Rt is an immediate in prefetch. MCOperand_CreateImm0(Inst, (Rt)); break; case AArch64_STURBBi: case AArch64_LDURBBi: case AArch64_LDURSBWi: case AArch64_STURHHi: case AArch64_LDURHHi: case AArch64_LDURSHWi: case AArch64_STURWi: case AArch64_LDURWi: case AArch64_LDTRSBWi: case AArch64_LDTRSHWi: case AArch64_STTRWi: case AArch64_LDTRWi: case AArch64_STTRHi: case AArch64_LDTRHi: case AArch64_LDTRBi: case AArch64_STTRBi: case AArch64_LDRSBWpre: case AArch64_LDRSHWpre: case AArch64_STRBBpre: case AArch64_LDRBBpre: case AArch64_STRHHpre: case AArch64_LDRHHpre: case AArch64_STRWpre: case AArch64_LDRWpre: case AArch64_LDRSBWpost: case AArch64_LDRSHWpost: case AArch64_STRBBpost: case AArch64_LDRBBpost: case AArch64_STRHHpost: case AArch64_LDRHHpost: case AArch64_STRWpost: case AArch64_LDRWpost: case AArch64_STLURBi: case AArch64_STLURHi: case AArch64_STLURWi: case AArch64_LDAPURBi: case AArch64_LDAPURSBWi: case AArch64_LDAPURHi: case AArch64_LDAPURSHWi: case AArch64_LDAPURi: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDURSBXi: case AArch64_LDURSHXi: case AArch64_LDURSWi: case AArch64_STURXi: case AArch64_LDURXi: case AArch64_LDTRSBXi: case AArch64_LDTRSHXi: case AArch64_LDTRSWi: case AArch64_STTRXi: case AArch64_LDTRXi: case AArch64_LDRSBXpre: case AArch64_LDRSHXpre: case AArch64_STRXpre: case AArch64_LDRSWpre: case AArch64_LDRXpre: case AArch64_LDRSBXpost: case AArch64_LDRSHXpost: case AArch64_STRXpost: case AArch64_LDRSWpost: case AArch64_LDRXpost: case AArch64_LDAPURSWi: case AArch64_LDAPURSHXi: case AArch64_LDAPURSBXi: case AArch64_STLURXi: case AArch64_LDAPURXi: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDURQi: case AArch64_STURQi: case AArch64_LDRQpre: case AArch64_STRQpre: case AArch64_LDRQpost: case AArch64_STRQpost: DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDURDi: case AArch64_STURDi: case AArch64_LDRDpre: case AArch64_STRDpre: case AArch64_LDRDpost: case AArch64_STRDpost: DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDURSi: case AArch64_STURSi: case AArch64_LDRSpre: case AArch64_STRSpre: case AArch64_LDRSpost: case AArch64_STRSpost: DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDURHi: case AArch64_STURHi: case AArch64_LDRHpre: case AArch64_STRHpre: case AArch64_LDRHpost: case AArch64_STRHpost: DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_LDURBi: case AArch64_STURBi: case AArch64_LDRBpre: case AArch64_STRBpre: case AArch64_LDRBpost: case AArch64_STRBpost: DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder); break; } DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); MCOperand_CreateImm0(Inst, (offset)); bool IsLoad = fieldFromInstruction_4(insn, 22, 1); bool IsIndexed = fieldFromInstruction_4(insn, 10, 2) != 0; bool IsFP = fieldFromInstruction_4(insn, 26, 1); // Cannot write back to a transfer register (but xzr != sp). if (IsLoad && IsIndexed && !IsFP && Rn != 31 && Rt == Rn) return SoftFail; return Success; } static DecodeStatus DecodeExclusiveLdStInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rt = fieldFromInstruction_4(insn, 0, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); unsigned Rt2 = fieldFromInstruction_4(insn, 10, 5); unsigned Rs = fieldFromInstruction_4(insn, 16, 5); unsigned Opcode = MCInst_getOpcode(Inst); switch (Opcode) { default: return Fail; case AArch64_STLXRW: case AArch64_STLXRB: case AArch64_STLXRH: case AArch64_STXRW: case AArch64_STXRB: case AArch64_STXRH: DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); // fall through case AArch64_LDARW: case AArch64_LDARB: case AArch64_LDARH: case AArch64_LDAXRW: case AArch64_LDAXRB: case AArch64_LDAXRH: case AArch64_LDXRW: case AArch64_LDXRB: case AArch64_LDXRH: case AArch64_STLRW: case AArch64_STLRB: case AArch64_STLRH: case AArch64_STLLRW: case AArch64_STLLRB: case AArch64_STLLRH: case AArch64_LDLARW: case AArch64_LDLARB: case AArch64_LDLARH: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_STLXRX: case AArch64_STXRX: DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); // fall through case AArch64_LDARX: case AArch64_LDAXRX: case AArch64_LDXRX: case AArch64_STLRX: case AArch64_LDLARX: case AArch64_STLLRX: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case AArch64_STLXPW: case AArch64_STXPW: DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); // fall through case AArch64_LDAXPW: case AArch64_LDXPW: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rt2, Addr, Decoder); break; case AArch64_STLXPX: case AArch64_STXPX: DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); // fall through case AArch64_LDAXPX: case AArch64_LDXPX: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rt2, Addr, Decoder); break; } DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); // You shouldn't load to the same register twice in an instruction... if ((Opcode == AArch64_LDAXPW || Opcode == AArch64_LDXPW || Opcode == AArch64_LDAXPX || Opcode == AArch64_LDXPX) && Rt == Rt2) return SoftFail; return Success; } static DecodeStatus DecodePairLdStInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rt = fieldFromInstruction_4(insn, 0, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); unsigned Rt2 = fieldFromInstruction_4(insn, 10, 5); int64_t offset = fieldFromInstruction_4(insn, 15, 7); bool IsLoad = fieldFromInstruction_4(insn, 22, 1); // offset is a 7-bit signed immediate, so sign extend it to // fill the unsigned. if (offset & (1 << (7 - 1))) offset |= ~((1LL << 7) - 1); unsigned Opcode = MCInst_getOpcode(Inst); bool NeedsDisjointWritebackTransfer = false; // First operand is always writeback of base register. switch (Opcode) { default: break; case AArch64_LDPXpost: case AArch64_STPXpost: case AArch64_LDPSWpost: case AArch64_LDPXpre: case AArch64_STPXpre: case AArch64_LDPSWpre: case AArch64_LDPWpost: case AArch64_STPWpost: case AArch64_LDPWpre: case AArch64_STPWpre: case AArch64_LDPQpost: case AArch64_STPQpost: case AArch64_LDPQpre: case AArch64_STPQpre: case AArch64_LDPDpost: case AArch64_STPDpost: case AArch64_LDPDpre: case AArch64_STPDpre: case AArch64_LDPSpost: case AArch64_STPSpost: case AArch64_LDPSpre: case AArch64_STPSpre: case AArch64_STGPpre: case AArch64_STGPpost: DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); break; } switch (Opcode) { default: return Fail; case AArch64_LDPXpost: case AArch64_STPXpost: case AArch64_LDPSWpost: case AArch64_LDPXpre: case AArch64_STPXpre: case AArch64_LDPSWpre: case AArch64_STGPpre: case AArch64_STGPpost: NeedsDisjointWritebackTransfer = true; // fall through case AArch64_LDNPXi: case AArch64_STNPXi: case AArch64_LDPXi: case AArch64_STPXi: case AArch64_LDPSWi: case AArch64_STGPi: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rt2, Addr, Decoder); break; case AArch64_LDPWpost: case AArch64_STPWpost: case AArch64_LDPWpre: case AArch64_STPWpre: NeedsDisjointWritebackTransfer = true; // fall through case AArch64_LDNPWi: case AArch64_STNPWi: case AArch64_LDPWi: case AArch64_STPWi: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rt2, Addr, Decoder); break; case AArch64_LDNPQi: case AArch64_STNPQi: case AArch64_LDPQpost: case AArch64_STPQpost: case AArch64_LDPQi: case AArch64_STPQi: case AArch64_LDPQpre: case AArch64_STPQpre: DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); DecodeFPR128RegisterClass(Inst, Rt2, Addr, Decoder); break; case AArch64_LDNPDi: case AArch64_STNPDi: case AArch64_LDPDpost: case AArch64_STPDpost: case AArch64_LDPDi: case AArch64_STPDi: case AArch64_LDPDpre: case AArch64_STPDpre: DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); DecodeFPR64RegisterClass(Inst, Rt2, Addr, Decoder); break; case AArch64_LDNPSi: case AArch64_STNPSi: case AArch64_LDPSpost: case AArch64_STPSpost: case AArch64_LDPSi: case AArch64_STPSi: case AArch64_LDPSpre: case AArch64_STPSpre: DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); DecodeFPR32RegisterClass(Inst, Rt2, Addr, Decoder); break; } DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); MCOperand_CreateImm0(Inst, (offset)); // You shouldn't load to the same register twice in an instruction... if (IsLoad && Rt == Rt2) return SoftFail; // ... or do any operation that writes-back to a transfer register. But note // that "stp xzr, xzr, [sp], #4" is fine because xzr and sp are different. if (NeedsDisjointWritebackTransfer && Rn != 31 && (Rt == Rn || Rt2 == Rn)) return SoftFail; return Success; } static DecodeStatus DecodeAuthLoadInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rt = fieldFromInstruction_4(insn, 0, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); uint64_t offset = fieldFromInstruction_4(insn, 22, 1) << 9 | fieldFromInstruction_4(insn, 12, 9); unsigned writeback = fieldFromInstruction_4(insn, 11, 1); switch (MCInst_getOpcode(Inst)) { default: return Fail; case AArch64_LDRAAwriteback: case AArch64_LDRABwriteback: DecodeGPR64spRegisterClass(Inst, Rn /* writeback register */, Addr, Decoder); break; case AArch64_LDRAAindexed: case AArch64_LDRABindexed: break; } DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); CONCAT(DecodeSImm, 10)(Inst, offset, Addr, Decoder); if (writeback && Rt == Rn && Rn != 31) { return SoftFail; } return Success; } static DecodeStatus DecodeAddSubERegInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction_4(insn, 0, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); unsigned Rm = fieldFromInstruction_4(insn, 16, 5); unsigned extend = fieldFromInstruction_4(insn, 10, 6); unsigned shift = extend & 0x7; if (shift > 4) return Fail; switch (MCInst_getOpcode(Inst)) { default: return Fail; case AArch64_ADDWrx: case AArch64_SUBWrx: DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); break; case AArch64_ADDSWrx: case AArch64_SUBSWrx: DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); break; case AArch64_ADDXrx: case AArch64_SUBXrx: DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); break; case AArch64_ADDSXrx: case AArch64_SUBSXrx: DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); break; case AArch64_ADDXrx64: case AArch64_SUBXrx64: DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); break; case AArch64_SUBSXrx64: case AArch64_ADDSXrx64: DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); break; } MCOperand_CreateImm0(Inst, (extend)); return Success; } static DecodeStatus DecodeLogicalImmInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction_4(insn, 0, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); unsigned Datasize = fieldFromInstruction_4(insn, 31, 1); unsigned imm; if (Datasize) { if (MCInst_getOpcode(Inst) == AArch64_ANDSXri) DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); else DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder); imm = fieldFromInstruction_4(insn, 10, 13); if (!AArch64_AM_isValidDecodeLogicalImmediate(imm, 64)) return Fail; } else { if (MCInst_getOpcode(Inst) == AArch64_ANDSWri) DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); else DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rn, Addr, Decoder); imm = fieldFromInstruction_4(insn, 10, 12); if (!AArch64_AM_isValidDecodeLogicalImmediate(imm, 32)) return Fail; } MCOperand_CreateImm0(Inst, (imm)); return Success; } static DecodeStatus DecodeModImmInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction_4(insn, 0, 5); unsigned cmode = fieldFromInstruction_4(insn, 12, 4); unsigned imm = fieldFromInstruction_4(insn, 16, 3) << 5; imm |= fieldFromInstruction_4(insn, 5, 5); if (MCInst_getOpcode(Inst) == AArch64_MOVID) DecodeFPR64RegisterClass(Inst, Rd, Addr, Decoder); else DecodeFPR128RegisterClass(Inst, Rd, Addr, Decoder); MCOperand_CreateImm0(Inst, (imm)); switch (MCInst_getOpcode(Inst)) { default: break; case AArch64_MOVIv4i16: case AArch64_MOVIv8i16: case AArch64_MVNIv4i16: case AArch64_MVNIv8i16: case AArch64_MOVIv2i32: case AArch64_MOVIv4i32: case AArch64_MVNIv2i32: case AArch64_MVNIv4i32: MCOperand_CreateImm0(Inst, ((cmode & 6) << 2)); break; case AArch64_MOVIv2s_msl: case AArch64_MOVIv4s_msl: case AArch64_MVNIv2s_msl: case AArch64_MVNIv4s_msl: MCOperand_CreateImm0(Inst, ((cmode & 1) ? 0x110 : 0x108)); break; } return Success; } static DecodeStatus DecodeModImmTiedInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction_4(insn, 0, 5); unsigned cmode = fieldFromInstruction_4(insn, 12, 4); unsigned imm = fieldFromInstruction_4(insn, 16, 3) << 5; imm |= fieldFromInstruction_4(insn, 5, 5); // Tied operands added twice. DecodeFPR128RegisterClass(Inst, Rd, Addr, Decoder); DecodeFPR128RegisterClass(Inst, Rd, Addr, Decoder); MCOperand_CreateImm0(Inst, (imm)); MCOperand_CreateImm0(Inst, ((cmode & 6) << 2)); return Success; } static DecodeStatus DecodeAdrInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction_4(insn, 0, 5); int64_t imm = fieldFromInstruction_4(insn, 5, 19) << 2; imm |= fieldFromInstruction_4(insn, 29, 2); // Sign-extend the 21-bit immediate. if (imm & (1 << (21 - 1))) imm |= ~((1LL << 21) - 1); DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); // No symbols supported in Capstone // if (!Decoder->tryAddingSymbolicOperand(Inst, imm, Addr, Fail, 0, 0, 4)) MCOperand_CreateImm0(Inst, (imm)); return Success; } static DecodeStatus DecodeAddSubImmShift(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction_4(insn, 0, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); unsigned Imm = fieldFromInstruction_4(insn, 10, 14); unsigned S = fieldFromInstruction_4(insn, 29, 1); unsigned Datasize = fieldFromInstruction_4(insn, 31, 1); unsigned ShifterVal = (Imm >> 12) & 3; unsigned ImmVal = Imm & 0xFFF; if (ShifterVal != 0 && ShifterVal != 1) return Fail; if (Datasize) { if (Rd == 31 && !S) DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); else DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); } else { if (Rd == 31 && !S) DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder); else DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder); } // No symbols supported in Capstone // if (!Decoder->tryAddingSymbolicOperand(Inst, Imm, Addr, Fail, 0, 0, 4)) MCOperand_CreateImm0(Inst, (ImmVal)); MCOperand_CreateImm0(Inst, (12 * ShifterVal)); return Success; } static DecodeStatus DecodeUnconditionalBranch(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { int64_t imm = fieldFromInstruction_4(insn, 0, 26); // Sign-extend the 26-bit immediate. if (imm & (1 << (26 - 1))) imm |= ~((1LL << 26) - 1); // No symbols supported in Capstone // if (!Decoder->tryAddingSymbolicOperand(Inst, imm * 4, Addr, true, 0, 0, 4)) MCOperand_CreateImm0(Inst, (imm)); return Success; } static bool isInvalidPState(uint64_t Op1, uint64_t Op2) { return Op1 == 0 && (Op2 == 0 || // CFINV Op2 == 1 || // XAFlag Op2 == 2); // AXFlag } static DecodeStatus DecodeSystemPStateImm0_15Instruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { uint64_t op1 = fieldFromInstruction_4(insn, 16, 3); uint64_t op2 = fieldFromInstruction_4(insn, 5, 3); uint64_t imm = fieldFromInstruction_4(insn, 8, 4); uint64_t pstate_field = (op1 << 3) | op2; if (isInvalidPState(op1, op2)) return Fail; MCOperand_CreateImm0(Inst, (pstate_field)); MCOperand_CreateImm0(Inst, (imm)); const AArch64PState_PStateImm0_15 *PState = AArch64PState_lookupPStateImm0_15ByEncoding(pstate_field); if (PState && AArch64_testFeatureList(Inst->csh->mode, PState->FeaturesRequired)) return Success; return Fail; } static DecodeStatus DecodeSystemPStateImm0_1Instruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { uint64_t op1 = fieldFromInstruction_4(insn, 16, 3); uint64_t op2 = fieldFromInstruction_4(insn, 5, 3); uint64_t crm_high = fieldFromInstruction_4(insn, 9, 3); uint64_t imm = fieldFromInstruction_4(insn, 8, 1); uint64_t pstate_field = (crm_high << 6) | (op1 << 3) | op2; if (isInvalidPState(op1, op2)) return Fail; MCOperand_CreateImm0(Inst, (pstate_field)); MCOperand_CreateImm0(Inst, (imm)); const AArch64PState_PStateImm0_1 *PState = AArch64PState_lookupPStateImm0_1ByEncoding(pstate_field); if (PState && AArch64_testFeatureList(Inst->csh->mode, PState->FeaturesRequired)) return Success; return Fail; } static DecodeStatus DecodeTestAndBranch(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { uint64_t Rt = fieldFromInstruction_4(insn, 0, 5); uint64_t bit = fieldFromInstruction_4(insn, 31, 1) << 5; bit |= fieldFromInstruction_4(insn, 19, 5); int64_t dst = fieldFromInstruction_4(insn, 5, 14); // Sign-extend 14-bit immediate. if (dst & (1 << (14 - 1))) dst |= ~((1LL << 14) - 1); if (fieldFromInstruction_4(insn, 31, 1) == 0) DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); else DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); MCOperand_CreateImm0(Inst, (bit)); // No symbols supported in Capstone // if (!Decoder->tryAddingSymbolicOperand(Inst, dst * 4, Addr, true, 0, 0, 4)) MCOperand_CreateImm0(Inst, (dst)); return Success; } static DecodeStatus DecodeGPRSeqPairsClassRegisterClass(MCInst *Inst, unsigned RegClassID, unsigned RegNo, uint64_t Addr, const void *Decoder) { // Register number must be even (see CASP instruction) if (RegNo & 0x1) return Fail; unsigned Reg = AArch64MCRegisterClasses[RegClassID].RegsBegin[RegNo / 2]; MCOperand_CreateReg0(Inst, (Reg)); return Success; } static DecodeStatus DecodeWSeqPairsClassRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { return DecodeGPRSeqPairsClassRegisterClass( Inst, AArch64_WSeqPairsClassRegClassID, RegNo, Addr, Decoder); } static DecodeStatus DecodeXSeqPairsClassRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { return DecodeGPRSeqPairsClassRegisterClass( Inst, AArch64_XSeqPairsClassRegClassID, RegNo, Addr, Decoder); } static DecodeStatus DecodeSyspXzrInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned op1 = fieldFromInstruction_4(insn, 16, 3); unsigned CRn = fieldFromInstruction_4(insn, 12, 4); unsigned CRm = fieldFromInstruction_4(insn, 8, 4); unsigned op2 = fieldFromInstruction_4(insn, 5, 3); unsigned Rt = fieldFromInstruction_4(insn, 0, 5); if (Rt != 0x1f) return Fail; MCOperand_CreateImm0(Inst, (op1)); MCOperand_CreateImm0(Inst, (CRn)); MCOperand_CreateImm0(Inst, (CRm)); MCOperand_CreateImm0(Inst, (op2)); DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); return Success; } static DecodeStatus DecodeSVELogicalImmInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Zdn = fieldFromInstruction_4(insn, 0, 5); unsigned imm = fieldFromInstruction_4(insn, 5, 13); if (!AArch64_AM_isValidDecodeLogicalImmediate(imm, 64)) return Fail; // The same (tied) operand is added twice to the instruction. DecodeZPRRegisterClass(Inst, Zdn, Addr, Decoder); if (MCInst_getOpcode(Inst) != AArch64_DUPM_ZI) DecodeZPRRegisterClass(Inst, Zdn, Addr, Decoder); MCOperand_CreateImm0(Inst, (imm)); return Success; } #define DEFINE_DecodeSImm(Bits) \ static DecodeStatus CONCAT(DecodeSImm, Bits)(MCInst * Inst, \ uint64_t Imm, \ uint64_t Address, \ const void *Decoder) \ { \ if (Imm & ~((1LL << Bits) - 1)) \ return Fail; \ \ if (Imm & (1 << (Bits - 1))) \ Imm |= ~((1LL << Bits) - 1); \ \ MCOperand_CreateImm0(Inst, (Imm)); \ return Success; \ } DEFINE_DecodeSImm(4); DEFINE_DecodeSImm(5); DEFINE_DecodeSImm(6); DEFINE_DecodeSImm(8); DEFINE_DecodeSImm(9); DEFINE_DecodeSImm(10); // Decode 8-bit signed/unsigned immediate for a given element width. #define DEFINE_DecodeImm8OptLsl(ElementWidth) \ static DecodeStatus CONCAT(DecodeImm8OptLsl, ElementWidth)( \ MCInst * Inst, unsigned Imm, uint64_t Addr, \ const void *Decoder) \ { \ unsigned Val = (uint8_t)Imm; \ unsigned Shift = (Imm & 0x100) ? 8 : 0; \ if (ElementWidth == 8 && Shift) \ return Fail; \ MCOperand_CreateImm0(Inst, (Val)); \ MCOperand_CreateImm0(Inst, (Shift)); \ return Success; \ } DEFINE_DecodeImm8OptLsl(8); DEFINE_DecodeImm8OptLsl(16); DEFINE_DecodeImm8OptLsl(32); DEFINE_DecodeImm8OptLsl(64); // Decode uimm4 ranged from 1-16. static DecodeStatus DecodeSVEIncDecImm(MCInst *Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { MCOperand_CreateImm0(Inst, (Imm + 1)); return Success; } static DecodeStatus DecodeSVCROp(MCInst *Inst, unsigned Imm, uint64_t Address, const void *Decoder) { if (AArch64SVCR_lookupSVCRByEncoding(Imm)) { MCOperand_CreateImm0(Inst, (Imm)); return Success; } return Fail; } static DecodeStatus DecodeCPYMemOpInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction_4(insn, 0, 5); unsigned Rs = fieldFromInstruction_4(insn, 16, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); // None of the registers may alias: if they do, then the instruction is not // merely unpredictable but actually entirely unallocated. if (Rd == Rs || Rs == Rn || Rd == Rn) return MCDisassembler_Fail; // All three register operands are written back, so they all appear // twice in the operand list, once as outputs and once as inputs. if (!DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) || !DecodeGPR64commonRegisterClass(Inst, Rs, Addr, Decoder) || !DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder) || !DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) || !DecodeGPR64commonRegisterClass(Inst, Rs, Addr, Decoder) || !DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder)) return MCDisassembler_Fail; return MCDisassembler_Success; } static DecodeStatus DecodeSETMemOpInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction_4(insn, 0, 5); unsigned Rm = fieldFromInstruction_4(insn, 16, 5); unsigned Rn = fieldFromInstruction_4(insn, 5, 5); // None of the registers may alias: if they do, then the instruction is not // merely unpredictable but actually entirely unallocated. if (Rd == Rm || Rm == Rn || Rd == Rn) return MCDisassembler_Fail; // Rd and Rn (not Rm) register operands are written back, so they appear // twice in the operand list, once as outputs and once as inputs. if (!DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) || !DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder) || !DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) || !DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder) || !DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder)) return MCDisassembler_Fail; return MCDisassembler_Success; } static DecodeStatus DecodePRFMRegInstruction(MCInst *Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { // PRFM with Rt = '11xxx' should be decoded as RPRFM. // Fail to decode and defer to fallback decoder table to decode RPRFM. unsigned Mask = 0x18; uint64_t Rt = fieldFromInstruction_4(insn, 0, 5); if ((Rt & Mask) == Mask) return Fail; uint64_t Rn = fieldFromInstruction_4(insn, 5, 5); uint64_t Shift = fieldFromInstruction_4(insn, 12, 1); uint64_t Extend = fieldFromInstruction_4(insn, 15, 1); uint64_t Rm = fieldFromInstruction_4(insn, 16, 5); MCOperand_CreateImm0(Inst, (Rt)); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); switch (MCInst_getOpcode(Inst)) { default: return Fail; case AArch64_PRFMroW: DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); break; case AArch64_PRFMroX: DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); break; } DecodeMemExtend(Inst, (Extend << 1) | Shift, Addr, Decoder); return Success; }