| //===- 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<MCRelocationInfo>(RelInfo), |
| GetOpInfo, SymbolLookUp, DisInfo); |
| } |
| |
| extern "C" void LLVMInitializeARM64Disassembler() { |
| TargetRegistry::RegisterMCDisassembler(TheARM64leTarget, |
| createARM64Disassembler); |
| TargetRegistry::RegisterMCDisassembler(TheARM64beTarget, |
| createARM64Disassembler); |
| TargetRegistry::RegisterMCSymbolizer(TheARM64leTarget, |
| createARM64ExternalSymbolizer); |
| TargetRegistry::RegisterMCSymbolizer(TheARM64beTarget, |
| createARM64ExternalSymbolizer); |
| |
| TargetRegistry::RegisterMCDisassembler(TheAArch64leTarget, |
| createARM64Disassembler); |
| TargetRegistry::RegisterMCDisassembler(TheAArch64beTarget, |
| createARM64Disassembler); |
| TargetRegistry::RegisterMCSymbolizer(TheAArch64leTarget, |
| createARM64ExternalSymbolizer); |
| TargetRegistry::RegisterMCSymbolizer(TheAArch64beTarget, |
| 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<const ARM64Disassembler *>(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<const ARM64Disassembler *>(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<const ARM64Disassembler *>(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<const ARM64Disassembler *>(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<const ARM64Disassembler *>(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<const ARM64Disassembler *>(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<const ARM64Disassembler *>(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<const ARM64Disassembler *>(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; |
| } |