//===- ARM64Disassembler.cpp - Disassembler for ARM64 -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // //===----------------------------------------------------------------------===// #include "ARM64Disassembler.h" #include "ARM64ExternalSymbolizer.h" #include "ARM64Subtarget.h" #include "MCTargetDesc/ARM64AddressingModes.h" #include "Utils/ARM64BaseInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCFixedLenDisassembler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; #define DEBUG_TYPE "arm64-disassembler" // Pull DecodeStatus and its enum values into the global namespace. typedef llvm::MCDisassembler::DecodeStatus DecodeStatus; // Forward declare these because the autogenerated code will reference them. // Definitions are further down. static DecodeStatus DecodeFPR128RegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR128_loRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR16RegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFPR8RegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR64RegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR64spRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR32RegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeGPR32spRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeQQRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeQQQRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeQQQQRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDDRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDDDRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeDDDDRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFixedPointScaleImm32(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFixedPointScaleImm64(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMemExtend(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); static DecodeStatus DecodeThreeAddrSRegInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeMoveImmInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeUnsignedLdStInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSignedLdStInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeExclusiveLdStInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodePairLdStInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeAddSubERegInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeLogicalImmInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeModImmInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeModImmTiedInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeAdrInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeBaseAddSubImm(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeUnconditionalBranch(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeSystemPStateInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeTestAndBranch(llvm::MCInst &Inst, uint32_t insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeFMOVLaneInstruction(llvm::MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); static DecodeStatus DecodeVecShiftR64Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR64ImmNarrow(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR32Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR32ImmNarrow(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR16Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR16ImmNarrow(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftR8Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftL64Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftL32Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftL16Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeVecShiftL8Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static bool Check(DecodeStatus &Out, DecodeStatus In) { switch (In) { case MCDisassembler::Success: // Out stays the same. return true; case MCDisassembler::SoftFail: Out = In; return true; case MCDisassembler::Fail: Out = In; return false; } llvm_unreachable("Invalid DecodeStatus!"); } #include "ARM64GenDisassemblerTables.inc" #include "ARM64GenInstrInfo.inc" #define Success llvm::MCDisassembler::Success #define Fail llvm::MCDisassembler::Fail #define SoftFail llvm::MCDisassembler::SoftFail static MCDisassembler *createARM64Disassembler(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx) { return new ARM64Disassembler(STI, Ctx); } DecodeStatus ARM64Disassembler::getInstruction(MCInst &MI, uint64_t &Size, const MemoryObject &Region, uint64_t Address, raw_ostream &os, raw_ostream &cs) const { CommentStream = &cs; uint8_t bytes[4]; Size = 0; // We want to read exactly 4 bytes of data. if (Region.readBytes(Address, 4, (uint8_t *)bytes) == -1) return Fail; Size = 4; // Encoded as a small-endian 32-bit word in the stream. uint32_t insn = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | (bytes[0] << 0); // Calling the auto-generated decoder function. return decodeInstruction(DecoderTable32, MI, insn, Address, this, STI); } static MCSymbolizer * createARM64ExternalSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx, MCRelocationInfo *RelInfo) { return new llvm::ARM64ExternalSymbolizer( *Ctx, std::unique_ptr(RelInfo), GetOpInfo, SymbolLookUp, DisInfo); } extern "C" void LLVMInitializeARM64Disassembler() { TargetRegistry::RegisterMCDisassembler(TheARM64leTarget, createARM64Disassembler); TargetRegistry::RegisterMCDisassembler(TheARM64beTarget, createARM64Disassembler); TargetRegistry::RegisterMCSymbolizer(TheARM64leTarget, createARM64ExternalSymbolizer); TargetRegistry::RegisterMCSymbolizer(TheARM64beTarget, createARM64ExternalSymbolizer); } static const unsigned FPR128DecoderTable[] = { ARM64::Q0, ARM64::Q1, ARM64::Q2, ARM64::Q3, ARM64::Q4, ARM64::Q5, ARM64::Q6, ARM64::Q7, ARM64::Q8, ARM64::Q9, ARM64::Q10, ARM64::Q11, ARM64::Q12, ARM64::Q13, ARM64::Q14, ARM64::Q15, ARM64::Q16, ARM64::Q17, ARM64::Q18, ARM64::Q19, ARM64::Q20, ARM64::Q21, ARM64::Q22, ARM64::Q23, ARM64::Q24, ARM64::Q25, ARM64::Q26, ARM64::Q27, ARM64::Q28, ARM64::Q29, ARM64::Q30, ARM64::Q31 }; static DecodeStatus DecodeFPR128RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = FPR128DecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(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 const unsigned FPR64DecoderTable[] = { ARM64::D0, ARM64::D1, ARM64::D2, ARM64::D3, ARM64::D4, ARM64::D5, ARM64::D6, ARM64::D7, ARM64::D8, ARM64::D9, ARM64::D10, ARM64::D11, ARM64::D12, ARM64::D13, ARM64::D14, ARM64::D15, ARM64::D16, ARM64::D17, ARM64::D18, ARM64::D19, ARM64::D20, ARM64::D21, ARM64::D22, ARM64::D23, ARM64::D24, ARM64::D25, ARM64::D26, ARM64::D27, ARM64::D28, ARM64::D29, ARM64::D30, ARM64::D31 }; static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = FPR64DecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned FPR32DecoderTable[] = { ARM64::S0, ARM64::S1, ARM64::S2, ARM64::S3, ARM64::S4, ARM64::S5, ARM64::S6, ARM64::S7, ARM64::S8, ARM64::S9, ARM64::S10, ARM64::S11, ARM64::S12, ARM64::S13, ARM64::S14, ARM64::S15, ARM64::S16, ARM64::S17, ARM64::S18, ARM64::S19, ARM64::S20, ARM64::S21, ARM64::S22, ARM64::S23, ARM64::S24, ARM64::S25, ARM64::S26, ARM64::S27, ARM64::S28, ARM64::S29, ARM64::S30, ARM64::S31 }; static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = FPR32DecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned FPR16DecoderTable[] = { ARM64::H0, ARM64::H1, ARM64::H2, ARM64::H3, ARM64::H4, ARM64::H5, ARM64::H6, ARM64::H7, ARM64::H8, ARM64::H9, ARM64::H10, ARM64::H11, ARM64::H12, ARM64::H13, ARM64::H14, ARM64::H15, ARM64::H16, ARM64::H17, ARM64::H18, ARM64::H19, ARM64::H20, ARM64::H21, ARM64::H22, ARM64::H23, ARM64::H24, ARM64::H25, ARM64::H26, ARM64::H27, ARM64::H28, ARM64::H29, ARM64::H30, ARM64::H31 }; static DecodeStatus DecodeFPR16RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = FPR16DecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned FPR8DecoderTable[] = { ARM64::B0, ARM64::B1, ARM64::B2, ARM64::B3, ARM64::B4, ARM64::B5, ARM64::B6, ARM64::B7, ARM64::B8, ARM64::B9, ARM64::B10, ARM64::B11, ARM64::B12, ARM64::B13, ARM64::B14, ARM64::B15, ARM64::B16, ARM64::B17, ARM64::B18, ARM64::B19, ARM64::B20, ARM64::B21, ARM64::B22, ARM64::B23, ARM64::B24, ARM64::B25, ARM64::B26, ARM64::B27, ARM64::B28, ARM64::B29, ARM64::B30, ARM64::B31 }; static DecodeStatus DecodeFPR8RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = FPR8DecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned GPR64DecoderTable[] = { ARM64::X0, ARM64::X1, ARM64::X2, ARM64::X3, ARM64::X4, ARM64::X5, ARM64::X6, ARM64::X7, ARM64::X8, ARM64::X9, ARM64::X10, ARM64::X11, ARM64::X12, ARM64::X13, ARM64::X14, ARM64::X15, ARM64::X16, ARM64::X17, ARM64::X18, ARM64::X19, ARM64::X20, ARM64::X21, ARM64::X22, ARM64::X23, ARM64::X24, ARM64::X25, ARM64::X26, ARM64::X27, ARM64::X28, ARM64::FP, ARM64::LR, ARM64::XZR }; static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = GPR64DecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static DecodeStatus DecodeGPR64spRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = GPR64DecoderTable[RegNo]; if (Register == ARM64::XZR) Register = ARM64::SP; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned GPR32DecoderTable[] = { ARM64::W0, ARM64::W1, ARM64::W2, ARM64::W3, ARM64::W4, ARM64::W5, ARM64::W6, ARM64::W7, ARM64::W8, ARM64::W9, ARM64::W10, ARM64::W11, ARM64::W12, ARM64::W13, ARM64::W14, ARM64::W15, ARM64::W16, ARM64::W17, ARM64::W18, ARM64::W19, ARM64::W20, ARM64::W21, ARM64::W22, ARM64::W23, ARM64::W24, ARM64::W25, ARM64::W26, ARM64::W27, ARM64::W28, ARM64::W29, ARM64::W30, ARM64::WZR }; static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = GPR32DecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static DecodeStatus DecodeGPR32spRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = GPR32DecoderTable[RegNo]; if (Register == ARM64::WZR) Register = ARM64::WSP; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned VectorDecoderTable[] = { ARM64::Q0, ARM64::Q1, ARM64::Q2, ARM64::Q3, ARM64::Q4, ARM64::Q5, ARM64::Q6, ARM64::Q7, ARM64::Q8, ARM64::Q9, ARM64::Q10, ARM64::Q11, ARM64::Q12, ARM64::Q13, ARM64::Q14, ARM64::Q15, ARM64::Q16, ARM64::Q17, ARM64::Q18, ARM64::Q19, ARM64::Q20, ARM64::Q21, ARM64::Q22, ARM64::Q23, ARM64::Q24, ARM64::Q25, ARM64::Q26, ARM64::Q27, ARM64::Q28, ARM64::Q29, ARM64::Q30, ARM64::Q31 }; static DecodeStatus DecodeVectorRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = VectorDecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned QQDecoderTable[] = { ARM64::Q0_Q1, ARM64::Q1_Q2, ARM64::Q2_Q3, ARM64::Q3_Q4, ARM64::Q4_Q5, ARM64::Q5_Q6, ARM64::Q6_Q7, ARM64::Q7_Q8, ARM64::Q8_Q9, ARM64::Q9_Q10, ARM64::Q10_Q11, ARM64::Q11_Q12, ARM64::Q12_Q13, ARM64::Q13_Q14, ARM64::Q14_Q15, ARM64::Q15_Q16, ARM64::Q16_Q17, ARM64::Q17_Q18, ARM64::Q18_Q19, ARM64::Q19_Q20, ARM64::Q20_Q21, ARM64::Q21_Q22, ARM64::Q22_Q23, ARM64::Q23_Q24, ARM64::Q24_Q25, ARM64::Q25_Q26, ARM64::Q26_Q27, ARM64::Q27_Q28, ARM64::Q28_Q29, ARM64::Q29_Q30, ARM64::Q30_Q31, ARM64::Q31_Q0 }; static DecodeStatus DecodeQQRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = QQDecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned QQQDecoderTable[] = { ARM64::Q0_Q1_Q2, ARM64::Q1_Q2_Q3, ARM64::Q2_Q3_Q4, ARM64::Q3_Q4_Q5, ARM64::Q4_Q5_Q6, ARM64::Q5_Q6_Q7, ARM64::Q6_Q7_Q8, ARM64::Q7_Q8_Q9, ARM64::Q8_Q9_Q10, ARM64::Q9_Q10_Q11, ARM64::Q10_Q11_Q12, ARM64::Q11_Q12_Q13, ARM64::Q12_Q13_Q14, ARM64::Q13_Q14_Q15, ARM64::Q14_Q15_Q16, ARM64::Q15_Q16_Q17, ARM64::Q16_Q17_Q18, ARM64::Q17_Q18_Q19, ARM64::Q18_Q19_Q20, ARM64::Q19_Q20_Q21, ARM64::Q20_Q21_Q22, ARM64::Q21_Q22_Q23, ARM64::Q22_Q23_Q24, ARM64::Q23_Q24_Q25, ARM64::Q24_Q25_Q26, ARM64::Q25_Q26_Q27, ARM64::Q26_Q27_Q28, ARM64::Q27_Q28_Q29, ARM64::Q28_Q29_Q30, ARM64::Q29_Q30_Q31, ARM64::Q30_Q31_Q0, ARM64::Q31_Q0_Q1 }; static DecodeStatus DecodeQQQRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = QQQDecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned QQQQDecoderTable[] = { ARM64::Q0_Q1_Q2_Q3, ARM64::Q1_Q2_Q3_Q4, ARM64::Q2_Q3_Q4_Q5, ARM64::Q3_Q4_Q5_Q6, ARM64::Q4_Q5_Q6_Q7, ARM64::Q5_Q6_Q7_Q8, ARM64::Q6_Q7_Q8_Q9, ARM64::Q7_Q8_Q9_Q10, ARM64::Q8_Q9_Q10_Q11, ARM64::Q9_Q10_Q11_Q12, ARM64::Q10_Q11_Q12_Q13, ARM64::Q11_Q12_Q13_Q14, ARM64::Q12_Q13_Q14_Q15, ARM64::Q13_Q14_Q15_Q16, ARM64::Q14_Q15_Q16_Q17, ARM64::Q15_Q16_Q17_Q18, ARM64::Q16_Q17_Q18_Q19, ARM64::Q17_Q18_Q19_Q20, ARM64::Q18_Q19_Q20_Q21, ARM64::Q19_Q20_Q21_Q22, ARM64::Q20_Q21_Q22_Q23, ARM64::Q21_Q22_Q23_Q24, ARM64::Q22_Q23_Q24_Q25, ARM64::Q23_Q24_Q25_Q26, ARM64::Q24_Q25_Q26_Q27, ARM64::Q25_Q26_Q27_Q28, ARM64::Q26_Q27_Q28_Q29, ARM64::Q27_Q28_Q29_Q30, ARM64::Q28_Q29_Q30_Q31, ARM64::Q29_Q30_Q31_Q0, ARM64::Q30_Q31_Q0_Q1, ARM64::Q31_Q0_Q1_Q2 }; static DecodeStatus DecodeQQQQRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = QQQQDecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned DDDecoderTable[] = { ARM64::D0_D1, ARM64::D1_D2, ARM64::D2_D3, ARM64::D3_D4, ARM64::D4_D5, ARM64::D5_D6, ARM64::D6_D7, ARM64::D7_D8, ARM64::D8_D9, ARM64::D9_D10, ARM64::D10_D11, ARM64::D11_D12, ARM64::D12_D13, ARM64::D13_D14, ARM64::D14_D15, ARM64::D15_D16, ARM64::D16_D17, ARM64::D17_D18, ARM64::D18_D19, ARM64::D19_D20, ARM64::D20_D21, ARM64::D21_D22, ARM64::D22_D23, ARM64::D23_D24, ARM64::D24_D25, ARM64::D25_D26, ARM64::D26_D27, ARM64::D27_D28, ARM64::D28_D29, ARM64::D29_D30, ARM64::D30_D31, ARM64::D31_D0 }; static DecodeStatus DecodeDDRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = DDDecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned DDDDecoderTable[] = { ARM64::D0_D1_D2, ARM64::D1_D2_D3, ARM64::D2_D3_D4, ARM64::D3_D4_D5, ARM64::D4_D5_D6, ARM64::D5_D6_D7, ARM64::D6_D7_D8, ARM64::D7_D8_D9, ARM64::D8_D9_D10, ARM64::D9_D10_D11, ARM64::D10_D11_D12, ARM64::D11_D12_D13, ARM64::D12_D13_D14, ARM64::D13_D14_D15, ARM64::D14_D15_D16, ARM64::D15_D16_D17, ARM64::D16_D17_D18, ARM64::D17_D18_D19, ARM64::D18_D19_D20, ARM64::D19_D20_D21, ARM64::D20_D21_D22, ARM64::D21_D22_D23, ARM64::D22_D23_D24, ARM64::D23_D24_D25, ARM64::D24_D25_D26, ARM64::D25_D26_D27, ARM64::D26_D27_D28, ARM64::D27_D28_D29, ARM64::D28_D29_D30, ARM64::D29_D30_D31, ARM64::D30_D31_D0, ARM64::D31_D0_D1 }; static DecodeStatus DecodeDDDRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = DDDDecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static const unsigned DDDDDecoderTable[] = { ARM64::D0_D1_D2_D3, ARM64::D1_D2_D3_D4, ARM64::D2_D3_D4_D5, ARM64::D3_D4_D5_D6, ARM64::D4_D5_D6_D7, ARM64::D5_D6_D7_D8, ARM64::D6_D7_D8_D9, ARM64::D7_D8_D9_D10, ARM64::D8_D9_D10_D11, ARM64::D9_D10_D11_D12, ARM64::D10_D11_D12_D13, ARM64::D11_D12_D13_D14, ARM64::D12_D13_D14_D15, ARM64::D13_D14_D15_D16, ARM64::D14_D15_D16_D17, ARM64::D15_D16_D17_D18, ARM64::D16_D17_D18_D19, ARM64::D17_D18_D19_D20, ARM64::D18_D19_D20_D21, ARM64::D19_D20_D21_D22, ARM64::D20_D21_D22_D23, ARM64::D21_D22_D23_D24, ARM64::D22_D23_D24_D25, ARM64::D23_D24_D25_D26, ARM64::D24_D25_D26_D27, ARM64::D25_D26_D27_D28, ARM64::D26_D27_D28_D29, ARM64::D27_D28_D29_D30, ARM64::D28_D29_D30_D31, ARM64::D29_D30_D31_D0, ARM64::D30_D31_D0_D1, ARM64::D31_D0_D1_D2 }; static DecodeStatus DecodeDDDDRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const void *Decoder) { if (RegNo > 31) return Fail; unsigned Register = DDDDDecoderTable[RegNo]; Inst.addOperand(MCOperand::CreateReg(Register)); return Success; } static DecodeStatus DecodeFixedPointScaleImm32(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { // scale{5} is asserted as 1 in tblgen. Imm |= 0x20; Inst.addOperand(MCOperand::CreateImm(64 - Imm)); return Success; } static DecodeStatus DecodeFixedPointScaleImm64(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { Inst.addOperand(MCOperand::CreateImm(64 - Imm)); return Success; } static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { int64_t ImmVal = Imm; const ARM64Disassembler *Dis = static_cast(Decoder); // Sign-extend 19-bit immediate. if (ImmVal & (1 << (19 - 1))) ImmVal |= ~((1LL << 19) - 1); if (!Dis->tryAddingSymbolicOperand(Inst, ImmVal << 2, Addr, Inst.getOpcode() != ARM64::LDRXl, 0, 4)) Inst.addOperand(MCOperand::CreateImm(ImmVal)); return Success; } static DecodeStatus DecodeMemExtend(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder) { Inst.addOperand(MCOperand::CreateImm((Imm >> 1) & 1)); Inst.addOperand(MCOperand::CreateImm(Imm & 1)); return Success; } static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder) { const ARM64Disassembler *Dis = static_cast(Decoder); const MCSubtargetInfo &STI = Dis->getSubtargetInfo(); Imm |= 0x8000; Inst.addOperand(MCOperand::CreateImm(Imm)); bool ValidNamed; (void)ARM64SysReg::MRSMapper(STI.getFeatureBits()).toString(Imm, ValidNamed); return ValidNamed ? Success : Fail; } static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder) { const ARM64Disassembler *Dis = static_cast(Decoder); const MCSubtargetInfo &STI = Dis->getSubtargetInfo(); Imm |= 0x8000; Inst.addOperand(MCOperand::CreateImm(Imm)); bool ValidNamed; (void)ARM64SysReg::MSRMapper(STI.getFeatureBits()).toString(Imm, ValidNamed); return ValidNamed ? Success : Fail; } static DecodeStatus DecodeFMOVLaneInstruction(llvm::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(Insn, 0, 5); unsigned Rn = fieldFromInstruction(Insn, 5, 5); unsigned IsToVec = fieldFromInstruction(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 Inst.addOperand(MCOperand::CreateImm(1)); return Success; } static DecodeStatus DecodeVecShiftRImm(llvm::MCInst &Inst, unsigned Imm, unsigned Add) { Inst.addOperand(MCOperand::CreateImm(Add - Imm)); return Success; } static DecodeStatus DecodeVecShiftLImm(llvm::MCInst &Inst, unsigned Imm, unsigned Add) { Inst.addOperand(MCOperand::CreateImm((Imm + Add) & (Add - 1))); return Success; } static DecodeStatus DecodeVecShiftR64Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm, 64); } static DecodeStatus DecodeVecShiftR64ImmNarrow(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm | 0x20, 64); } static DecodeStatus DecodeVecShiftR32Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm, 32); } static DecodeStatus DecodeVecShiftR32ImmNarrow(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm | 0x10, 32); } static DecodeStatus DecodeVecShiftR16Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm, 16); } static DecodeStatus DecodeVecShiftR16ImmNarrow(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm | 0x8, 16); } static DecodeStatus DecodeVecShiftR8Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftRImm(Inst, Imm, 8); } static DecodeStatus DecodeVecShiftL64Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftLImm(Inst, Imm, 64); } static DecodeStatus DecodeVecShiftL32Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftLImm(Inst, Imm, 32); } static DecodeStatus DecodeVecShiftL16Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftLImm(Inst, Imm, 16); } static DecodeStatus DecodeVecShiftL8Imm(llvm::MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder) { return DecodeVecShiftLImm(Inst, Imm, 8); } static DecodeStatus DecodeThreeAddrSRegInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction(insn, 0, 5); unsigned Rn = fieldFromInstruction(insn, 5, 5); unsigned Rm = fieldFromInstruction(insn, 16, 5); unsigned shiftHi = fieldFromInstruction(insn, 22, 2); unsigned shiftLo = fieldFromInstruction(insn, 10, 6); unsigned shift = (shiftHi << 6) | shiftLo; switch (Inst.getOpcode()) { default: return Fail; case ARM64::ADDWrs: case ARM64::ADDSWrs: case ARM64::SUBWrs: case ARM64::SUBSWrs: // if shift == '11' then ReservedValue() if (shiftHi == 0x3) return Fail; // Deliberate fallthrough case ARM64::ANDWrs: case ARM64::ANDSWrs: case ARM64::BICWrs: case ARM64::BICSWrs: case ARM64::ORRWrs: case ARM64::ORNWrs: case ARM64::EORWrs: case ARM64::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 ARM64::ADDXrs: case ARM64::ADDSXrs: case ARM64::SUBXrs: case ARM64::SUBSXrs: // if shift == '11' then ReservedValue() if (shiftHi == 0x3) return Fail; // Deliberate fallthrough case ARM64::ANDXrs: case ARM64::ANDSXrs: case ARM64::BICXrs: case ARM64::BICSXrs: case ARM64::ORRXrs: case ARM64::ORNXrs: case ARM64::EORXrs: case ARM64::EONXrs: DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); break; } Inst.addOperand(MCOperand::CreateImm(shift)); return Success; } static DecodeStatus DecodeMoveImmInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction(insn, 0, 5); unsigned imm = fieldFromInstruction(insn, 5, 16); unsigned shift = fieldFromInstruction(insn, 21, 2); shift <<= 4; switch (Inst.getOpcode()) { default: return Fail; case ARM64::MOVZWi: case ARM64::MOVNWi: case ARM64::MOVKWi: if (shift & (1U << 5)) return Fail; DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); break; case ARM64::MOVZXi: case ARM64::MOVNXi: case ARM64::MOVKXi: DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); break; } if (Inst.getOpcode() == ARM64::MOVKWi || Inst.getOpcode() == ARM64::MOVKXi) Inst.addOperand(Inst.getOperand(0)); Inst.addOperand(MCOperand::CreateImm(imm)); Inst.addOperand(MCOperand::CreateImm(shift)); return Success; } static DecodeStatus DecodeUnsignedLdStInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rt = fieldFromInstruction(insn, 0, 5); unsigned Rn = fieldFromInstruction(insn, 5, 5); unsigned offset = fieldFromInstruction(insn, 10, 12); const ARM64Disassembler *Dis = static_cast(Decoder); switch (Inst.getOpcode()) { default: return Fail; case ARM64::PRFMui: // Rt is an immediate in prefetch. Inst.addOperand(MCOperand::CreateImm(Rt)); break; case ARM64::STRBBui: case ARM64::LDRBBui: case ARM64::LDRSBWui: case ARM64::STRHHui: case ARM64::LDRHHui: case ARM64::LDRSHWui: case ARM64::STRWui: case ARM64::LDRWui: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRSBXui: case ARM64::LDRSHXui: case ARM64::LDRSWui: case ARM64::STRXui: case ARM64::LDRXui: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRQui: case ARM64::STRQui: DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRDui: case ARM64::STRDui: DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRSui: case ARM64::STRSui: DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRHui: case ARM64::STRHui: DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRBui: case ARM64::STRBui: DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder); break; } DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); if (!Dis->tryAddingSymbolicOperand(Inst, offset, Addr, Fail, 0, 4)) Inst.addOperand(MCOperand::CreateImm(offset)); return Success; } static DecodeStatus DecodeSignedLdStInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rt = fieldFromInstruction(insn, 0, 5); unsigned Rn = fieldFromInstruction(insn, 5, 5); int64_t offset = fieldFromInstruction(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 (Inst.getOpcode()) { default: break; case ARM64::LDRSBWpre: case ARM64::LDRSHWpre: case ARM64::STRBBpre: case ARM64::LDRBBpre: case ARM64::STRHHpre: case ARM64::LDRHHpre: case ARM64::STRWpre: case ARM64::LDRWpre: case ARM64::LDRSBWpost: case ARM64::LDRSHWpost: case ARM64::STRBBpost: case ARM64::LDRBBpost: case ARM64::STRHHpost: case ARM64::LDRHHpost: case ARM64::STRWpost: case ARM64::LDRWpost: case ARM64::LDRSBXpre: case ARM64::LDRSHXpre: case ARM64::STRXpre: case ARM64::LDRSWpre: case ARM64::LDRXpre: case ARM64::LDRSBXpost: case ARM64::LDRSHXpost: case ARM64::STRXpost: case ARM64::LDRSWpost: case ARM64::LDRXpost: case ARM64::LDRQpre: case ARM64::STRQpre: case ARM64::LDRQpost: case ARM64::STRQpost: case ARM64::LDRDpre: case ARM64::STRDpre: case ARM64::LDRDpost: case ARM64::STRDpost: case ARM64::LDRSpre: case ARM64::STRSpre: case ARM64::LDRSpost: case ARM64::STRSpost: case ARM64::LDRHpre: case ARM64::STRHpre: case ARM64::LDRHpost: case ARM64::STRHpost: case ARM64::LDRBpre: case ARM64::STRBpre: case ARM64::LDRBpost: case ARM64::STRBpost: DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); break; } switch (Inst.getOpcode()) { default: return Fail; case ARM64::PRFUMi: // Rt is an immediate in prefetch. Inst.addOperand(MCOperand::CreateImm(Rt)); break; case ARM64::STURBBi: case ARM64::LDURBBi: case ARM64::LDURSBWi: case ARM64::STURHHi: case ARM64::LDURHHi: case ARM64::LDURSHWi: case ARM64::STURWi: case ARM64::LDURWi: case ARM64::LDTRSBWi: case ARM64::LDTRSHWi: case ARM64::STTRWi: case ARM64::LDTRWi: case ARM64::STTRHi: case ARM64::LDTRHi: case ARM64::LDTRBi: case ARM64::STTRBi: case ARM64::LDRSBWpre: case ARM64::LDRSHWpre: case ARM64::STRBBpre: case ARM64::LDRBBpre: case ARM64::STRHHpre: case ARM64::LDRHHpre: case ARM64::STRWpre: case ARM64::LDRWpre: case ARM64::LDRSBWpost: case ARM64::LDRSHWpost: case ARM64::STRBBpost: case ARM64::LDRBBpost: case ARM64::STRHHpost: case ARM64::LDRHHpost: case ARM64::STRWpost: case ARM64::LDRWpost: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDURSBXi: case ARM64::LDURSHXi: case ARM64::LDURSWi: case ARM64::STURXi: case ARM64::LDURXi: case ARM64::LDTRSBXi: case ARM64::LDTRSHXi: case ARM64::LDTRSWi: case ARM64::STTRXi: case ARM64::LDTRXi: case ARM64::LDRSBXpre: case ARM64::LDRSHXpre: case ARM64::STRXpre: case ARM64::LDRSWpre: case ARM64::LDRXpre: case ARM64::LDRSBXpost: case ARM64::LDRSHXpost: case ARM64::STRXpost: case ARM64::LDRSWpost: case ARM64::LDRXpost: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDURQi: case ARM64::STURQi: case ARM64::LDRQpre: case ARM64::STRQpre: case ARM64::LDRQpost: case ARM64::STRQpost: DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDURDi: case ARM64::STURDi: case ARM64::LDRDpre: case ARM64::STRDpre: case ARM64::LDRDpost: case ARM64::STRDpost: DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDURSi: case ARM64::STURSi: case ARM64::LDRSpre: case ARM64::STRSpre: case ARM64::LDRSpost: case ARM64::STRSpost: DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDURHi: case ARM64::STURHi: case ARM64::LDRHpre: case ARM64::STRHpre: case ARM64::LDRHpost: case ARM64::STRHpost: DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDURBi: case ARM64::STURBi: case ARM64::LDRBpre: case ARM64::STRBpre: case ARM64::LDRBpost: case ARM64::STRBpost: DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder); break; } DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); Inst.addOperand(MCOperand::CreateImm(offset)); bool IsLoad = fieldFromInstruction(insn, 22, 1); bool IsIndexed = fieldFromInstruction(insn, 10, 2) != 0; bool IsFP = fieldFromInstruction(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(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rt = fieldFromInstruction(insn, 0, 5); unsigned Rn = fieldFromInstruction(insn, 5, 5); unsigned Rt2 = fieldFromInstruction(insn, 10, 5); unsigned Rs = fieldFromInstruction(insn, 16, 5); unsigned Opcode = Inst.getOpcode(); switch (Opcode) { default: return Fail; case ARM64::STLXRW: case ARM64::STLXRB: case ARM64::STLXRH: case ARM64::STXRW: case ARM64::STXRB: case ARM64::STXRH: DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); // FALLTHROUGH case ARM64::LDARW: case ARM64::LDARB: case ARM64::LDARH: case ARM64::LDAXRW: case ARM64::LDAXRB: case ARM64::LDAXRH: case ARM64::LDXRW: case ARM64::LDXRB: case ARM64::LDXRH: case ARM64::STLRW: case ARM64::STLRB: case ARM64::STLRH: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::STLXRX: case ARM64::STXRX: DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); // FALLTHROUGH case ARM64::LDARX: case ARM64::LDAXRX: case ARM64::LDXRX: case ARM64::STLRX: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::STLXPW: case ARM64::STXPW: DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); // FALLTHROUGH case ARM64::LDAXPW: case ARM64::LDXPW: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rt2, Addr, Decoder); break; case ARM64::STLXPX: case ARM64::STXPX: DecodeGPR32RegisterClass(Inst, Rs, Addr, Decoder); // FALLTHROUGH case ARM64::LDAXPX: case ARM64::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 == ARM64::LDAXPW || Opcode == ARM64::LDXPW || Opcode == ARM64::LDAXPX || Opcode == ARM64::LDXPX) && Rt == Rt2) return SoftFail; return Success; } static DecodeStatus DecodePairLdStInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rt = fieldFromInstruction(insn, 0, 5); unsigned Rn = fieldFromInstruction(insn, 5, 5); unsigned Rt2 = fieldFromInstruction(insn, 10, 5); int64_t offset = fieldFromInstruction(insn, 15, 7); bool IsLoad = fieldFromInstruction(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 = Inst.getOpcode(); bool NeedsDisjointWritebackTransfer = false; // First operand is always writeback of base register. switch (Opcode) { default: break; case ARM64::LDPXpost: case ARM64::STPXpost: case ARM64::LDPSWpost: case ARM64::LDPXpre: case ARM64::STPXpre: case ARM64::LDPSWpre: case ARM64::LDPWpost: case ARM64::STPWpost: case ARM64::LDPWpre: case ARM64::STPWpre: case ARM64::LDPQpost: case ARM64::STPQpost: case ARM64::LDPQpre: case ARM64::STPQpre: case ARM64::LDPDpost: case ARM64::STPDpost: case ARM64::LDPDpre: case ARM64::STPDpre: case ARM64::LDPSpost: case ARM64::STPSpost: case ARM64::LDPSpre: case ARM64::STPSpre: DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); break; } switch (Opcode) { default: return Fail; case ARM64::LDPXpost: case ARM64::STPXpost: case ARM64::LDPSWpost: case ARM64::LDPXpre: case ARM64::STPXpre: case ARM64::LDPSWpre: NeedsDisjointWritebackTransfer = true; // Fallthrough case ARM64::LDNPXi: case ARM64::STNPXi: case ARM64::LDPXi: case ARM64::STPXi: case ARM64::LDPSWi: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rt2, Addr, Decoder); break; case ARM64::LDPWpost: case ARM64::STPWpost: case ARM64::LDPWpre: case ARM64::STPWpre: NeedsDisjointWritebackTransfer = true; // Fallthrough case ARM64::LDNPWi: case ARM64::STNPWi: case ARM64::LDPWi: case ARM64::STPWi: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rt2, Addr, Decoder); break; case ARM64::LDNPQi: case ARM64::STNPQi: case ARM64::LDPQpost: case ARM64::STPQpost: case ARM64::LDPQi: case ARM64::STPQi: case ARM64::LDPQpre: case ARM64::STPQpre: DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); DecodeFPR128RegisterClass(Inst, Rt2, Addr, Decoder); break; case ARM64::LDNPDi: case ARM64::STNPDi: case ARM64::LDPDpost: case ARM64::STPDpost: case ARM64::LDPDi: case ARM64::STPDi: case ARM64::LDPDpre: case ARM64::STPDpre: DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); DecodeFPR64RegisterClass(Inst, Rt2, Addr, Decoder); break; case ARM64::LDNPSi: case ARM64::STNPSi: case ARM64::LDPSpost: case ARM64::STPSpost: case ARM64::LDPSi: case ARM64::STPSi: case ARM64::LDPSpre: case ARM64::STPSpre: DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); DecodeFPR32RegisterClass(Inst, Rt2, Addr, Decoder); break; } DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); Inst.addOperand(MCOperand::CreateImm(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 DecodeAddSubERegInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction(insn, 0, 5); unsigned Rn = fieldFromInstruction(insn, 5, 5); unsigned Rm = fieldFromInstruction(insn, 16, 5); unsigned extend = fieldFromInstruction(insn, 10, 6); unsigned shift = extend & 0x7; if (shift > 4) return Fail; switch (Inst.getOpcode()) { default: return Fail; case ARM64::ADDWrx: case ARM64::SUBWrx: DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); break; case ARM64::ADDSWrx: case ARM64::SUBSWrx: DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR32spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); break; case ARM64::ADDXrx: case ARM64::SUBXrx: DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); break; case ARM64::ADDSXrx: case ARM64::SUBSXrx: DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); break; case ARM64::ADDXrx64: case ARM64::SUBXrx64: DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); break; case ARM64::SUBSXrx64: case ARM64::ADDSXrx64: DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); break; } Inst.addOperand(MCOperand::CreateImm(extend)); return Success; } static DecodeStatus DecodeLogicalImmInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction(insn, 0, 5); unsigned Rn = fieldFromInstruction(insn, 5, 5); unsigned Datasize = fieldFromInstruction(insn, 31, 1); unsigned imm; if (Datasize) { if (Inst.getOpcode() == ARM64::ANDSXri) DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); else DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder); imm = fieldFromInstruction(insn, 10, 13); if (!ARM64_AM::isValidDecodeLogicalImmediate(imm, 64)) return Fail; } else { if (Inst.getOpcode() == ARM64::ANDSWri) DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); else DecodeGPR32spRegisterClass(Inst, Rd, Addr, Decoder); DecodeGPR32RegisterClass(Inst, Rn, Addr, Decoder); imm = fieldFromInstruction(insn, 10, 12); if (!ARM64_AM::isValidDecodeLogicalImmediate(imm, 32)) return Fail; } Inst.addOperand(MCOperand::CreateImm(imm)); return Success; } static DecodeStatus DecodeModImmInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction(insn, 0, 5); unsigned cmode = fieldFromInstruction(insn, 12, 4); unsigned imm = fieldFromInstruction(insn, 16, 3) << 5; imm |= fieldFromInstruction(insn, 5, 5); if (Inst.getOpcode() == ARM64::MOVID) DecodeFPR64RegisterClass(Inst, Rd, Addr, Decoder); else DecodeVectorRegisterClass(Inst, Rd, Addr, Decoder); Inst.addOperand(MCOperand::CreateImm(imm)); switch (Inst.getOpcode()) { default: break; case ARM64::MOVIv4i16: case ARM64::MOVIv8i16: case ARM64::MVNIv4i16: case ARM64::MVNIv8i16: case ARM64::MOVIv2i32: case ARM64::MOVIv4i32: case ARM64::MVNIv2i32: case ARM64::MVNIv4i32: Inst.addOperand(MCOperand::CreateImm((cmode & 6) << 2)); break; case ARM64::MOVIv2s_msl: case ARM64::MOVIv4s_msl: case ARM64::MVNIv2s_msl: case ARM64::MVNIv4s_msl: Inst.addOperand(MCOperand::CreateImm(cmode & 1 ? 0x110 : 0x108)); break; } return Success; } static DecodeStatus DecodeModImmTiedInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction(insn, 0, 5); unsigned cmode = fieldFromInstruction(insn, 12, 4); unsigned imm = fieldFromInstruction(insn, 16, 3) << 5; imm |= fieldFromInstruction(insn, 5, 5); // Tied operands added twice. DecodeVectorRegisterClass(Inst, Rd, Addr, Decoder); DecodeVectorRegisterClass(Inst, Rd, Addr, Decoder); Inst.addOperand(MCOperand::CreateImm(imm)); Inst.addOperand(MCOperand::CreateImm((cmode & 6) << 2)); return Success; } static DecodeStatus DecodeAdrInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction(insn, 0, 5); int64_t imm = fieldFromInstruction(insn, 5, 19) << 2; imm |= fieldFromInstruction(insn, 29, 2); const ARM64Disassembler *Dis = static_cast(Decoder); // Sign-extend the 21-bit immediate. if (imm & (1 << (21 - 1))) imm |= ~((1LL << 21) - 1); DecodeGPR64RegisterClass(Inst, Rd, Addr, Decoder); if (!Dis->tryAddingSymbolicOperand(Inst, imm, Addr, Fail, 0, 4)) Inst.addOperand(MCOperand::CreateImm(imm)); return Success; } static DecodeStatus DecodeBaseAddSubImm(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { unsigned Rd = fieldFromInstruction(insn, 0, 5); unsigned Rn = fieldFromInstruction(insn, 5, 5); unsigned Imm = fieldFromInstruction(insn, 10, 14); unsigned S = fieldFromInstruction(insn, 29, 1); unsigned Datasize = fieldFromInstruction(insn, 31, 1); unsigned ShifterVal = (Imm >> 12) & 3; unsigned ImmVal = Imm & 0xFFF; const ARM64Disassembler *Dis = static_cast(Decoder); 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); } if (!Dis->tryAddingSymbolicOperand(Inst, Imm, Addr, Fail, 0, 4)) Inst.addOperand(MCOperand::CreateImm(ImmVal)); Inst.addOperand(MCOperand::CreateImm(12 * ShifterVal)); return Success; } static DecodeStatus DecodeUnconditionalBranch(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { int64_t imm = fieldFromInstruction(insn, 0, 26); const ARM64Disassembler *Dis = static_cast(Decoder); // Sign-extend the 26-bit immediate. if (imm & (1 << (26 - 1))) imm |= ~((1LL << 26) - 1); if (!Dis->tryAddingSymbolicOperand(Inst, imm << 2, Addr, true, 0, 4)) Inst.addOperand(MCOperand::CreateImm(imm)); return Success; } static DecodeStatus DecodeSystemPStateInstruction(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { uint64_t op1 = fieldFromInstruction(insn, 16, 3); uint64_t op2 = fieldFromInstruction(insn, 5, 3); uint64_t crm = fieldFromInstruction(insn, 8, 4); uint64_t pstate_field = (op1 << 3) | op2; Inst.addOperand(MCOperand::CreateImm(pstate_field)); Inst.addOperand(MCOperand::CreateImm(crm)); bool ValidNamed; (void)ARM64PState::PStateMapper().toString(pstate_field, ValidNamed); return ValidNamed ? Success : Fail; } static DecodeStatus DecodeTestAndBranch(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { uint64_t Rt = fieldFromInstruction(insn, 0, 5); uint64_t bit = fieldFromInstruction(insn, 31, 1) << 5; bit |= fieldFromInstruction(insn, 19, 5); int64_t dst = fieldFromInstruction(insn, 5, 14); const ARM64Disassembler *Dis = static_cast(Decoder); // Sign-extend 14-bit immediate. if (dst & (1 << (14 - 1))) dst |= ~((1LL << 14) - 1); if (fieldFromInstruction(insn, 31, 1) == 0) DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); else DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); Inst.addOperand(MCOperand::CreateImm(bit)); if (!Dis->tryAddingSymbolicOperand(Inst, dst << 2, Addr, true, 0, 4)) Inst.addOperand(MCOperand::CreateImm(dst)); return Success; }