//===- 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. // //===----------------------------------------------------------------------===// // // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "arm64-disassembler" #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" // 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 DecodeCondBranchTarget(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 DecodeRegOffsetLdStInstruction(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 DecodeSystemCPSRInstruction(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 DecodeSIMDLdStPost(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeSIMDLdStSingle(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeSIMDLdStSingleTied(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, 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); #include "ARM64GenDisassemblerTables.inc" #include "ARM64GenInstrInfo.inc" using namespace llvm; #define Success llvm::MCDisassembler::Success #define Fail llvm::MCDisassembler::Fail 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. DecodeStatus result = decodeInstruction(DecoderTable32, MI, insn, Address, this, STI); if (!result) return Fail; return Success; } 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(TheARM64Target, createARM64Disassembler); TargetRegistry::RegisterMCSymbolizer(TheARM64Target, 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 DecodeCondBranchTarget(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 DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder) { Imm |= 0x8000; Inst.addOperand(MCOperand::CreateImm(Imm)); bool ValidNamed; (void)ARM64SysReg::MRSMapper().toString(Imm, ValidNamed); return ValidNamed ? Success : Fail; } static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder) { Imm |= 0x8000; Inst.addOperand(MCOperand::CreateImm(Imm)); bool ValidNamed; (void)ARM64SysReg::MSRMapper().toString(Imm, ValidNamed); return ValidNamed ? Success : Fail; } 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); 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)); 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); switch (Inst.getOpcode()) { 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); 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); // offset is a 7-bit signed immediate, so sign extend it to // fill the unsigned. if (offset & (1 << (7 - 1))) offset |= ~((1LL << 7) - 1); switch (Inst.getOpcode()) { default: return Fail; case ARM64::LDNPXi: case ARM64::STNPXi: case ARM64::LDPXpost: case ARM64::STPXpost: case ARM64::LDPSWpost: case ARM64::LDPXi: case ARM64::STPXi: case ARM64::LDPSWi: case ARM64::LDPXpre: case ARM64::STPXpre: case ARM64::LDPSWpre: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rt2, Addr, Decoder); break; case ARM64::LDNPWi: case ARM64::STNPWi: case ARM64::LDPWpost: case ARM64::STPWpost: case ARM64::LDPWi: case ARM64::STPWi: case ARM64::LDPWpre: case ARM64::STPWpre: 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)); return Success; } static DecodeStatus DecodeRegOffsetLdStInstruction(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 Rm = fieldFromInstruction(insn, 16, 5); unsigned extendHi = fieldFromInstruction(insn, 13, 3); unsigned extendLo = fieldFromInstruction(insn, 12, 1); unsigned extend = (extendHi << 1) | extendLo; // All RO load-store instructions are undefined if option == 00x or 10x. if (extend >> 2 == 0x0 || extend >> 2 == 0x2) return Fail; switch (Inst.getOpcode()) { default: return Fail; case ARM64::LDRSWro: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRXro: case ARM64::STRXro: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRWro: case ARM64::STRWro: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRQro: case ARM64::STRQro: DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRDro: case ARM64::STRDro: DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRSro: case ARM64::STRSro: DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRHro: case ARM64::STRHro: DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRBro: case ARM64::STRBro: DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRBBro: case ARM64::STRBBro: case ARM64::LDRSBWro: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRHHro: case ARM64::STRHHro: case ARM64::LDRSHWro: DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRSHXro: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRSBXro: DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::PRFMro: Inst.addOperand(MCOperand::CreateImm(Rt)); } DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); if ((extendHi & 0x3) == 0x3) DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); else DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); Inst.addOperand(MCOperand::CreateImm(extend)); 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 DecodeSystemCPSRInstruction(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 cpsr_field = (op1 << 3) | op2; Inst.addOperand(MCOperand::CreateImm(cpsr_field)); Inst.addOperand(MCOperand::CreateImm(crm)); bool ValidNamed; (void)ARM64PState::PStateMapper().toString(cpsr_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); 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; } static DecodeStatus DecodeSIMDLdStPost(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { uint64_t Rd = fieldFromInstruction(insn, 0, 5); uint64_t Rn = fieldFromInstruction(insn, 5, 5); uint64_t Rm = fieldFromInstruction(insn, 16, 5); switch (Inst.getOpcode()) { default: return Fail; case ARM64::ST1Onev8b_POST: case ARM64::ST1Onev4h_POST: case ARM64::ST1Onev2s_POST: case ARM64::ST1Onev1d_POST: case ARM64::LD1Onev8b_POST: case ARM64::LD1Onev4h_POST: case ARM64::LD1Onev2s_POST: case ARM64::LD1Onev1d_POST: DecodeFPR64RegisterClass(Inst, Rd, Addr, Decoder); break; case ARM64::ST1Onev16b_POST: case ARM64::ST1Onev8h_POST: case ARM64::ST1Onev4s_POST: case ARM64::ST1Onev2d_POST: case ARM64::LD1Onev16b_POST: case ARM64::LD1Onev8h_POST: case ARM64::LD1Onev4s_POST: case ARM64::LD1Onev2d_POST: DecodeFPR128RegisterClass(Inst, Rd, Addr, Decoder); break; case ARM64::ST1Twov8b_POST: case ARM64::ST1Twov4h_POST: case ARM64::ST1Twov2s_POST: case ARM64::ST1Twov1d_POST: case ARM64::ST2Twov8b_POST: case ARM64::ST2Twov4h_POST: case ARM64::ST2Twov2s_POST: case ARM64::LD1Twov8b_POST: case ARM64::LD1Twov4h_POST: case ARM64::LD1Twov2s_POST: case ARM64::LD1Twov1d_POST: case ARM64::LD2Twov8b_POST: case ARM64::LD2Twov4h_POST: case ARM64::LD2Twov2s_POST: DecodeDDRegisterClass(Inst, Rd, Addr, Decoder); break; case ARM64::ST1Threev8b_POST: case ARM64::ST1Threev4h_POST: case ARM64::ST1Threev2s_POST: case ARM64::ST1Threev1d_POST: case ARM64::ST3Threev8b_POST: case ARM64::ST3Threev4h_POST: case ARM64::ST3Threev2s_POST: case ARM64::LD1Threev8b_POST: case ARM64::LD1Threev4h_POST: case ARM64::LD1Threev2s_POST: case ARM64::LD1Threev1d_POST: case ARM64::LD3Threev8b_POST: case ARM64::LD3Threev4h_POST: case ARM64::LD3Threev2s_POST: DecodeDDDRegisterClass(Inst, Rd, Addr, Decoder); break; case ARM64::ST1Fourv8b_POST: case ARM64::ST1Fourv4h_POST: case ARM64::ST1Fourv2s_POST: case ARM64::ST1Fourv1d_POST: case ARM64::ST4Fourv8b_POST: case ARM64::ST4Fourv4h_POST: case ARM64::ST4Fourv2s_POST: case ARM64::LD1Fourv8b_POST: case ARM64::LD1Fourv4h_POST: case ARM64::LD1Fourv2s_POST: case ARM64::LD1Fourv1d_POST: case ARM64::LD4Fourv8b_POST: case ARM64::LD4Fourv4h_POST: case ARM64::LD4Fourv2s_POST: DecodeDDDDRegisterClass(Inst, Rd, Addr, Decoder); break; case ARM64::ST1Twov16b_POST: case ARM64::ST1Twov8h_POST: case ARM64::ST1Twov4s_POST: case ARM64::ST1Twov2d_POST: case ARM64::ST2Twov16b_POST: case ARM64::ST2Twov8h_POST: case ARM64::ST2Twov4s_POST: case ARM64::ST2Twov2d_POST: case ARM64::LD1Twov16b_POST: case ARM64::LD1Twov8h_POST: case ARM64::LD1Twov4s_POST: case ARM64::LD1Twov2d_POST: case ARM64::LD2Twov16b_POST: case ARM64::LD2Twov8h_POST: case ARM64::LD2Twov4s_POST: case ARM64::LD2Twov2d_POST: DecodeQQRegisterClass(Inst, Rd, Addr, Decoder); break; case ARM64::ST1Threev16b_POST: case ARM64::ST1Threev8h_POST: case ARM64::ST1Threev4s_POST: case ARM64::ST1Threev2d_POST: case ARM64::ST3Threev16b_POST: case ARM64::ST3Threev8h_POST: case ARM64::ST3Threev4s_POST: case ARM64::ST3Threev2d_POST: case ARM64::LD1Threev16b_POST: case ARM64::LD1Threev8h_POST: case ARM64::LD1Threev4s_POST: case ARM64::LD1Threev2d_POST: case ARM64::LD3Threev16b_POST: case ARM64::LD3Threev8h_POST: case ARM64::LD3Threev4s_POST: case ARM64::LD3Threev2d_POST: DecodeQQQRegisterClass(Inst, Rd, Addr, Decoder); break; case ARM64::ST1Fourv16b_POST: case ARM64::ST1Fourv8h_POST: case ARM64::ST1Fourv4s_POST: case ARM64::ST1Fourv2d_POST: case ARM64::ST4Fourv16b_POST: case ARM64::ST4Fourv8h_POST: case ARM64::ST4Fourv4s_POST: case ARM64::ST4Fourv2d_POST: case ARM64::LD1Fourv16b_POST: case ARM64::LD1Fourv8h_POST: case ARM64::LD1Fourv4s_POST: case ARM64::LD1Fourv2d_POST: case ARM64::LD4Fourv16b_POST: case ARM64::LD4Fourv8h_POST: case ARM64::LD4Fourv4s_POST: case ARM64::LD4Fourv2d_POST: DecodeQQQQRegisterClass(Inst, Rd, Addr, Decoder); break; } DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); return Success; } static DecodeStatus DecodeSIMDLdStSingle(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { uint64_t Rt = fieldFromInstruction(insn, 0, 5); uint64_t Rn = fieldFromInstruction(insn, 5, 5); uint64_t Rm = fieldFromInstruction(insn, 16, 5); uint64_t size = fieldFromInstruction(insn, 10, 2); uint64_t S = fieldFromInstruction(insn, 12, 1); uint64_t Q = fieldFromInstruction(insn, 30, 1); uint64_t index = 0; switch (Inst.getOpcode()) { case ARM64::ST1i8: case ARM64::ST1i8_POST: case ARM64::ST2i8: case ARM64::ST2i8_POST: case ARM64::ST3i8_POST: case ARM64::ST3i8: case ARM64::ST4i8_POST: case ARM64::ST4i8: index = (Q << 3) | (S << 2) | size; break; case ARM64::ST1i16: case ARM64::ST1i16_POST: case ARM64::ST2i16: case ARM64::ST2i16_POST: case ARM64::ST3i16_POST: case ARM64::ST3i16: case ARM64::ST4i16_POST: case ARM64::ST4i16: index = (Q << 2) | (S << 1) | (size >> 1); break; case ARM64::ST1i32: case ARM64::ST1i32_POST: case ARM64::ST2i32: case ARM64::ST2i32_POST: case ARM64::ST3i32_POST: case ARM64::ST3i32: case ARM64::ST4i32_POST: case ARM64::ST4i32: index = (Q << 1) | S; break; case ARM64::ST1i64: case ARM64::ST1i64_POST: case ARM64::ST2i64: case ARM64::ST2i64_POST: case ARM64::ST3i64_POST: case ARM64::ST3i64: case ARM64::ST4i64_POST: case ARM64::ST4i64: index = Q; break; } switch (Inst.getOpcode()) { default: return Fail; case ARM64::LD1Rv8b: case ARM64::LD1Rv8b_POST: case ARM64::LD1Rv4h: case ARM64::LD1Rv4h_POST: case ARM64::LD1Rv2s: case ARM64::LD1Rv2s_POST: case ARM64::LD1Rv1d: case ARM64::LD1Rv1d_POST: DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LD1Rv16b: case ARM64::LD1Rv16b_POST: case ARM64::LD1Rv8h: case ARM64::LD1Rv8h_POST: case ARM64::LD1Rv4s: case ARM64::LD1Rv4s_POST: case ARM64::LD1Rv2d: case ARM64::LD1Rv2d_POST: case ARM64::ST1i8: case ARM64::ST1i8_POST: case ARM64::ST1i16: case ARM64::ST1i16_POST: case ARM64::ST1i32: case ARM64::ST1i32_POST: case ARM64::ST1i64: case ARM64::ST1i64_POST: DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LD2Rv16b: case ARM64::LD2Rv16b_POST: case ARM64::LD2Rv8h: case ARM64::LD2Rv8h_POST: case ARM64::LD2Rv4s: case ARM64::LD2Rv4s_POST: case ARM64::LD2Rv2d: case ARM64::LD2Rv2d_POST: case ARM64::ST2i8: case ARM64::ST2i8_POST: case ARM64::ST2i16: case ARM64::ST2i16_POST: case ARM64::ST2i32: case ARM64::ST2i32_POST: case ARM64::ST2i64: case ARM64::ST2i64_POST: DecodeQQRegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LD2Rv8b: case ARM64::LD2Rv8b_POST: case ARM64::LD2Rv4h: case ARM64::LD2Rv4h_POST: case ARM64::LD2Rv2s: case ARM64::LD2Rv2s_POST: case ARM64::LD2Rv1d: case ARM64::LD2Rv1d_POST: DecodeDDRegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LD3Rv8b: case ARM64::LD3Rv8b_POST: case ARM64::LD3Rv4h: case ARM64::LD3Rv4h_POST: case ARM64::LD3Rv2s: case ARM64::LD3Rv2s_POST: case ARM64::LD3Rv1d: case ARM64::LD3Rv1d_POST: DecodeDDDRegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LD3Rv16b: case ARM64::LD3Rv16b_POST: case ARM64::LD3Rv8h: case ARM64::LD3Rv8h_POST: case ARM64::LD3Rv4s: case ARM64::LD3Rv4s_POST: case ARM64::LD3Rv2d: case ARM64::LD3Rv2d_POST: case ARM64::ST3i8: case ARM64::ST3i8_POST: case ARM64::ST3i16: case ARM64::ST3i16_POST: case ARM64::ST3i32: case ARM64::ST3i32_POST: case ARM64::ST3i64: case ARM64::ST3i64_POST: DecodeQQQRegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LD4Rv8b: case ARM64::LD4Rv8b_POST: case ARM64::LD4Rv4h: case ARM64::LD4Rv4h_POST: case ARM64::LD4Rv2s: case ARM64::LD4Rv2s_POST: case ARM64::LD4Rv1d: case ARM64::LD4Rv1d_POST: DecodeDDDDRegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LD4Rv16b: case ARM64::LD4Rv16b_POST: case ARM64::LD4Rv8h: case ARM64::LD4Rv8h_POST: case ARM64::LD4Rv4s: case ARM64::LD4Rv4s_POST: case ARM64::LD4Rv2d: case ARM64::LD4Rv2d_POST: case ARM64::ST4i8: case ARM64::ST4i8_POST: case ARM64::ST4i16: case ARM64::ST4i16_POST: case ARM64::ST4i32: case ARM64::ST4i32_POST: case ARM64::ST4i64: case ARM64::ST4i64_POST: DecodeQQQQRegisterClass(Inst, Rt, Addr, Decoder); break; } switch (Inst.getOpcode()) { case ARM64::LD1Rv8b: case ARM64::LD1Rv8b_POST: case ARM64::LD1Rv16b: case ARM64::LD1Rv16b_POST: case ARM64::LD1Rv4h: case ARM64::LD1Rv4h_POST: case ARM64::LD1Rv8h: case ARM64::LD1Rv8h_POST: case ARM64::LD1Rv4s: case ARM64::LD1Rv4s_POST: case ARM64::LD1Rv2s: case ARM64::LD1Rv2s_POST: case ARM64::LD1Rv1d: case ARM64::LD1Rv1d_POST: case ARM64::LD1Rv2d: case ARM64::LD1Rv2d_POST: case ARM64::LD2Rv8b: case ARM64::LD2Rv8b_POST: case ARM64::LD2Rv16b: case ARM64::LD2Rv16b_POST: case ARM64::LD2Rv4h: case ARM64::LD2Rv4h_POST: case ARM64::LD2Rv8h: case ARM64::LD2Rv8h_POST: case ARM64::LD2Rv2s: case ARM64::LD2Rv2s_POST: case ARM64::LD2Rv4s: case ARM64::LD2Rv4s_POST: case ARM64::LD2Rv2d: case ARM64::LD2Rv2d_POST: case ARM64::LD2Rv1d: case ARM64::LD2Rv1d_POST: case ARM64::LD3Rv8b: case ARM64::LD3Rv8b_POST: case ARM64::LD3Rv16b: case ARM64::LD3Rv16b_POST: case ARM64::LD3Rv4h: case ARM64::LD3Rv4h_POST: case ARM64::LD3Rv8h: case ARM64::LD3Rv8h_POST: case ARM64::LD3Rv2s: case ARM64::LD3Rv2s_POST: case ARM64::LD3Rv4s: case ARM64::LD3Rv4s_POST: case ARM64::LD3Rv2d: case ARM64::LD3Rv2d_POST: case ARM64::LD3Rv1d: case ARM64::LD3Rv1d_POST: case ARM64::LD4Rv8b: case ARM64::LD4Rv8b_POST: case ARM64::LD4Rv16b: case ARM64::LD4Rv16b_POST: case ARM64::LD4Rv4h: case ARM64::LD4Rv4h_POST: case ARM64::LD4Rv8h: case ARM64::LD4Rv8h_POST: case ARM64::LD4Rv2s: case ARM64::LD4Rv2s_POST: case ARM64::LD4Rv4s: case ARM64::LD4Rv4s_POST: case ARM64::LD4Rv2d: case ARM64::LD4Rv2d_POST: case ARM64::LD4Rv1d: case ARM64::LD4Rv1d_POST: break; default: Inst.addOperand(MCOperand::CreateImm(index)); } DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); switch (Inst.getOpcode()) { case ARM64::ST1i8_POST: case ARM64::ST1i16_POST: case ARM64::ST1i32_POST: case ARM64::ST1i64_POST: case ARM64::LD1Rv8b_POST: case ARM64::LD1Rv16b_POST: case ARM64::LD1Rv4h_POST: case ARM64::LD1Rv8h_POST: case ARM64::LD1Rv2s_POST: case ARM64::LD1Rv4s_POST: case ARM64::LD1Rv1d_POST: case ARM64::LD1Rv2d_POST: case ARM64::ST2i8_POST: case ARM64::ST2i16_POST: case ARM64::ST2i32_POST: case ARM64::ST2i64_POST: case ARM64::LD2Rv8b_POST: case ARM64::LD2Rv16b_POST: case ARM64::LD2Rv4h_POST: case ARM64::LD2Rv8h_POST: case ARM64::LD2Rv2s_POST: case ARM64::LD2Rv4s_POST: case ARM64::LD2Rv2d_POST: case ARM64::LD2Rv1d_POST: case ARM64::ST3i8_POST: case ARM64::ST3i16_POST: case ARM64::ST3i32_POST: case ARM64::ST3i64_POST: case ARM64::LD3Rv8b_POST: case ARM64::LD3Rv16b_POST: case ARM64::LD3Rv4h_POST: case ARM64::LD3Rv8h_POST: case ARM64::LD3Rv2s_POST: case ARM64::LD3Rv4s_POST: case ARM64::LD3Rv2d_POST: case ARM64::LD3Rv1d_POST: case ARM64::ST4i8_POST: case ARM64::ST4i16_POST: case ARM64::ST4i32_POST: case ARM64::ST4i64_POST: case ARM64::LD4Rv8b_POST: case ARM64::LD4Rv16b_POST: case ARM64::LD4Rv4h_POST: case ARM64::LD4Rv8h_POST: case ARM64::LD4Rv2s_POST: case ARM64::LD4Rv4s_POST: case ARM64::LD4Rv2d_POST: case ARM64::LD4Rv1d_POST: DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); break; } return Success; } static DecodeStatus DecodeSIMDLdStSingleTied(llvm::MCInst &Inst, uint32_t insn, uint64_t Addr, const void *Decoder) { uint64_t Rt = fieldFromInstruction(insn, 0, 5); uint64_t Rn = fieldFromInstruction(insn, 5, 5); uint64_t Rm = fieldFromInstruction(insn, 16, 5); uint64_t size = fieldFromInstruction(insn, 10, 2); uint64_t S = fieldFromInstruction(insn, 12, 1); uint64_t Q = fieldFromInstruction(insn, 30, 1); uint64_t index = 0; switch (Inst.getOpcode()) { case ARM64::LD1i8: case ARM64::LD1i8_POST: case ARM64::LD2i8: case ARM64::LD2i8_POST: case ARM64::LD3i8_POST: case ARM64::LD3i8: case ARM64::LD4i8_POST: case ARM64::LD4i8: index = (Q << 3) | (S << 2) | size; break; case ARM64::LD1i16: case ARM64::LD1i16_POST: case ARM64::LD2i16: case ARM64::LD2i16_POST: case ARM64::LD3i16_POST: case ARM64::LD3i16: case ARM64::LD4i16_POST: case ARM64::LD4i16: index = (Q << 2) | (S << 1) | (size >> 1); break; case ARM64::LD1i32: case ARM64::LD1i32_POST: case ARM64::LD2i32: case ARM64::LD2i32_POST: case ARM64::LD3i32_POST: case ARM64::LD3i32: case ARM64::LD4i32_POST: case ARM64::LD4i32: index = (Q << 1) | S; break; case ARM64::LD1i64: case ARM64::LD1i64_POST: case ARM64::LD2i64: case ARM64::LD2i64_POST: case ARM64::LD3i64_POST: case ARM64::LD3i64: case ARM64::LD4i64_POST: case ARM64::LD4i64: index = Q; break; } switch (Inst.getOpcode()) { default: return Fail; case ARM64::LD1i8: case ARM64::LD1i8_POST: case ARM64::LD1i16: case ARM64::LD1i16_POST: case ARM64::LD1i32: case ARM64::LD1i32_POST: case ARM64::LD1i64: case ARM64::LD1i64_POST: DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LD2i8: case ARM64::LD2i8_POST: case ARM64::LD2i16: case ARM64::LD2i16_POST: case ARM64::LD2i32: case ARM64::LD2i32_POST: case ARM64::LD2i64: case ARM64::LD2i64_POST: DecodeQQRegisterClass(Inst, Rt, Addr, Decoder); DecodeQQRegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LD3i8: case ARM64::LD3i8_POST: case ARM64::LD3i16: case ARM64::LD3i16_POST: case ARM64::LD3i32: case ARM64::LD3i32_POST: case ARM64::LD3i64: case ARM64::LD3i64_POST: DecodeQQQRegisterClass(Inst, Rt, Addr, Decoder); DecodeQQQRegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LD4i8: case ARM64::LD4i8_POST: case ARM64::LD4i16: case ARM64::LD4i16_POST: case ARM64::LD4i32: case ARM64::LD4i32_POST: case ARM64::LD4i64: case ARM64::LD4i64_POST: DecodeQQQQRegisterClass(Inst, Rt, Addr, Decoder); DecodeQQQQRegisterClass(Inst, Rt, Addr, Decoder); break; } Inst.addOperand(MCOperand::CreateImm(index)); DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); switch (Inst.getOpcode()) { case ARM64::LD1i8_POST: case ARM64::LD1i16_POST: case ARM64::LD1i32_POST: case ARM64::LD1i64_POST: case ARM64::LD2i8_POST: case ARM64::LD2i16_POST: case ARM64::LD2i32_POST: case ARM64::LD2i64_POST: case ARM64::LD3i8_POST: case ARM64::LD3i16_POST: case ARM64::LD3i32_POST: case ARM64::LD3i64_POST: case ARM64::LD4i8_POST: case ARM64::LD4i16_POST: case ARM64::LD4i32_POST: case ARM64::LD4i64_POST: DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); break; } return Success; }