| //===- 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 "ARM64Subtarget.h" |
| #include "MCTargetDesc/ARM64BaseInfo.h" |
| #include "MCTargetDesc/ARM64AddressingModes.h" |
| #include "llvm/MC/MCInst.h" |
| #include "llvm/MC/MCExpr.h" |
| #include "llvm/MC/MCContext.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" |
| #include "llvm/Support/Format.h" |
| #include "llvm/Support/raw_ostream.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 DecodeFixedPointScaleImm(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 DecodeSystemRegister(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) { |
| return new ARM64Disassembler(STI); |
| } |
| |
| 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]; |
| |
| // We want to read exactly 4 bytes of data. |
| if (Region.readBytes(Address, 4, (uint8_t *)bytes) == -1) |
| return Fail; |
| |
| // 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; |
| |
| Size = 4; |
| |
| return Success; |
| } |
| |
| static MCSymbolRefExpr::VariantKind |
| getVariant(uint64_t LLVMDisassembler_VariantKind) { |
| switch (LLVMDisassembler_VariantKind) { |
| case LLVMDisassembler_VariantKind_None: |
| return MCSymbolRefExpr::VK_None; |
| case LLVMDisassembler_VariantKind_ARM64_PAGE: |
| return MCSymbolRefExpr::VK_PAGE; |
| case LLVMDisassembler_VariantKind_ARM64_PAGEOFF: |
| return MCSymbolRefExpr::VK_PAGEOFF; |
| case LLVMDisassembler_VariantKind_ARM64_GOTPAGE: |
| return MCSymbolRefExpr::VK_GOTPAGE; |
| case LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF: |
| return MCSymbolRefExpr::VK_GOTPAGEOFF; |
| case LLVMDisassembler_VariantKind_ARM64_TLVP: |
| case LLVMDisassembler_VariantKind_ARM64_TLVOFF: |
| default: |
| assert("bad LLVMDisassembler_VariantKind"); |
| return MCSymbolRefExpr::VK_None; |
| } |
| } |
| |
| /// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic |
| /// operand in place of the immediate Value in the MCInst. The immediate |
| /// Value has not had any PC adjustment made by the caller. If the instruction |
| /// is a branch that adds the PC to the immediate Value then isBranch is |
| /// Success, else Fail. If the getOpInfo() function was set as part of the |
| /// setupForSymbolicDisassembly() call then that function is called to get any |
| /// symbolic information at the Address for this instrution. If that returns |
| /// non-zero then the symbolic information it returns is used to create an |
| /// MCExpr and that is added as an operand to the MCInst. If getOpInfo() |
| /// returns zero and isBranch is Success then a symbol look up for |
| /// Address + Value is done and if a symbol is found an MCExpr is created with |
| /// that, else an MCExpr with Address + Value is created. If getOpInfo() |
| /// returns zero and isBranch is Fail then the the Opcode of the MCInst is |
| /// tested and for ADRP an other instructions that help to load of pointers |
| /// a symbol look up is done to see it is returns a specific reference type |
| /// to add to the comment stream. This function returns Success if it adds |
| /// an operand to the MCInst and Fail otherwise. |
| bool ARM64Disassembler::tryAddingSymbolicOperand(uint64_t Address, int Value, |
| bool isBranch, |
| uint64_t InstSize, MCInst &MI, |
| uint32_t insn) const { |
| LLVMOpInfoCallback getOpInfo = getLLVMOpInfoCallback(); |
| |
| struct LLVMOpInfo1 SymbolicOp; |
| memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); |
| SymbolicOp.Value = Value; |
| void *DisInfo = getDisInfoBlock(); |
| uint64_t ReferenceType; |
| const char *ReferenceName; |
| const char *Name; |
| LLVMSymbolLookupCallback SymbolLookUp = getLLVMSymbolLookupCallback(); |
| if (!getOpInfo || |
| !getOpInfo(DisInfo, Address, 0 /* Offset */, InstSize, 1, &SymbolicOp)) { |
| if (isBranch) { |
| if (SymbolLookUp) { |
| ReferenceType = LLVMDisassembler_ReferenceType_In_Branch; |
| Name = SymbolLookUp(DisInfo, Address + Value, &ReferenceType, Address, |
| &ReferenceName); |
| if (Name) { |
| SymbolicOp.AddSymbol.Name = Name; |
| SymbolicOp.AddSymbol.Present = Success; |
| SymbolicOp.Value = 0; |
| } else { |
| SymbolicOp.Value = Address + Value; |
| } |
| if (ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub) |
| (*CommentStream) << "symbol stub for: " << ReferenceName; |
| else if (ReferenceType == |
| LLVMDisassembler_ReferenceType_Out_Objc_Message) |
| (*CommentStream) << "Objc message: " << ReferenceName; |
| } else { |
| return false; |
| } |
| } else if (MI.getOpcode() == ARM64::ADRP) { |
| if (SymbolLookUp) { |
| ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_ADRP; |
| Name = SymbolLookUp(DisInfo, insn, &ReferenceType, Address, |
| &ReferenceName); |
| (*CommentStream) << format("0x%llx", |
| 0xfffffffffffff000LL & (Address + Value)); |
| } else { |
| return false; |
| } |
| } else if (MI.getOpcode() == ARM64::ADDXri || |
| MI.getOpcode() == ARM64::LDRXui || |
| MI.getOpcode() == ARM64::LDRXl || MI.getOpcode() == ARM64::ADR) { |
| if (SymbolLookUp) { |
| if (MI.getOpcode() == ARM64::ADDXri) |
| ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_ADDXri; |
| else if (MI.getOpcode() == ARM64::LDRXui) |
| ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_LDRXui; |
| if (MI.getOpcode() == ARM64::LDRXl) { |
| ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_LDRXl; |
| Name = SymbolLookUp(DisInfo, Address + Value, &ReferenceType, Address, |
| &ReferenceName); |
| } else if (MI.getOpcode() == ARM64::ADR) { |
| ReferenceType = LLVMDisassembler_ReferenceType_In_ARM64_ADR; |
| Name = SymbolLookUp(DisInfo, Address + Value, &ReferenceType, Address, |
| &ReferenceName); |
| } else { |
| Name = SymbolLookUp(DisInfo, insn, &ReferenceType, Address, |
| &ReferenceName); |
| } |
| if (ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr) |
| (*CommentStream) << "literal pool symbol address: " << ReferenceName; |
| else if (ReferenceType == |
| LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) |
| (*CommentStream) << "literal pool for: \"" << ReferenceName << "\""; |
| else if (ReferenceType == |
| LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref) |
| (*CommentStream) << "Objc cfstring ref: @\"" << ReferenceName << "\""; |
| else if (ReferenceType == |
| LLVMDisassembler_ReferenceType_Out_Objc_Message) |
| (*CommentStream) << "Objc message: " << ReferenceName; |
| else if (ReferenceType == |
| LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref) |
| (*CommentStream) << "Objc message ref: " << ReferenceName; |
| else if (ReferenceType == |
| LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref) |
| (*CommentStream) << "Objc selector ref: " << ReferenceName; |
| else if (ReferenceType == |
| LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref) |
| (*CommentStream) << "Objc class ref: " << ReferenceName; |
| // For these instructions, the SymbolLookUp() above is just to get the |
| // ReferenceType and ReferenceName. We want to make sure not to |
| // fall through so we don't build an MCExpr to leave the disassembly |
| // of the immediate values of these instructions to the InstPrinter. |
| return false; |
| } else { |
| return false; |
| } |
| } else { |
| return false; |
| } |
| } |
| |
| MCContext *Ctx = getMCContext(); |
| const MCExpr *Add = NULL; |
| if (SymbolicOp.AddSymbol.Present) { |
| if (SymbolicOp.AddSymbol.Name) { |
| StringRef Name(SymbolicOp.AddSymbol.Name); |
| MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name); |
| MCSymbolRefExpr::VariantKind Variant = getVariant(SymbolicOp.VariantKind); |
| if (Variant != MCSymbolRefExpr::VK_None) |
| Add = MCSymbolRefExpr::Create(Sym, Variant, *Ctx); |
| else |
| Add = MCSymbolRefExpr::Create(Sym, *Ctx); |
| } else { |
| Add = MCConstantExpr::Create(SymbolicOp.AddSymbol.Value, *Ctx); |
| } |
| } |
| |
| const MCExpr *Sub = NULL; |
| if (SymbolicOp.SubtractSymbol.Present) { |
| if (SymbolicOp.SubtractSymbol.Name) { |
| StringRef Name(SymbolicOp.SubtractSymbol.Name); |
| MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name); |
| Sub = MCSymbolRefExpr::Create(Sym, *Ctx); |
| } else { |
| Sub = MCConstantExpr::Create(SymbolicOp.SubtractSymbol.Value, *Ctx); |
| } |
| } |
| |
| const MCExpr *Off = NULL; |
| if (SymbolicOp.Value != 0) |
| Off = MCConstantExpr::Create(SymbolicOp.Value, *Ctx); |
| |
| const MCExpr *Expr; |
| if (Sub) { |
| const MCExpr *LHS; |
| if (Add) |
| LHS = MCBinaryExpr::CreateSub(Add, Sub, *Ctx); |
| else |
| LHS = MCUnaryExpr::CreateMinus(Sub, *Ctx); |
| if (Off != 0) |
| Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx); |
| else |
| Expr = LHS; |
| } else if (Add) { |
| if (Off != 0) |
| Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx); |
| else |
| Expr = Add; |
| } else { |
| if (Off != 0) |
| Expr = Off; |
| else |
| Expr = MCConstantExpr::Create(0, *Ctx); |
| } |
| |
| MI.addOperand(MCOperand::CreateExpr(Expr)); |
| |
| return true; |
| } |
| |
| extern "C" void LLVMInitializeARM64Disassembler() { |
| TargetRegistry::RegisterMCDisassembler(TheARM64Target, |
| createARM64Disassembler); |
| } |
| |
| 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 DecodeFixedPointScaleImm(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<const ARM64Disassembler *>(Decoder); |
| |
| // Sign-extend 19-bit immediate. |
| if (ImmVal & (1 << (19 - 1))) |
| ImmVal |= ~((1LL << 19) - 1); |
| |
| if (!Dis->tryAddingSymbolicOperand(Addr, ImmVal << 2, |
| Inst.getOpcode() != ARM64::LDRXl, 4, Inst)) |
| Inst.addOperand(MCOperand::CreateImm(ImmVal)); |
| return Success; |
| } |
| |
| static DecodeStatus DecodeSystemRegister(llvm::MCInst &Inst, unsigned Imm, |
| uint64_t Address, |
| const void *Decoder) { |
| Inst.addOperand(MCOperand::CreateImm(Imm | 0x8000)); |
| 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::ANDWrs: |
| case ARM64::ANDSWrs: |
| case ARM64::BICWrs: |
| case ARM64::BICSWrs: |
| case ARM64::ORRWrs: |
| case ARM64::ORNWrs: |
| case ARM64::EORWrs: |
| case ARM64::EONWrs: |
| case ARM64::ADDWrs: |
| case ARM64::ADDSWrs: |
| case ARM64::SUBWrs: |
| case ARM64::SUBSWrs: { |
| DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); |
| DecodeGPR32RegisterClass(Inst, Rn, Addr, Decoder); |
| DecodeGPR32RegisterClass(Inst, Rm, Addr, Decoder); |
| break; |
| } |
| case ARM64::ANDXrs: |
| case ARM64::ANDSXrs: |
| case ARM64::BICXrs: |
| case ARM64::BICSXrs: |
| case ARM64::ORRXrs: |
| case ARM64::ORNXrs: |
| case ARM64::EORXrs: |
| case ARM64::EONXrs: |
| case ARM64::ADDXrs: |
| case ARM64::ADDSXrs: |
| case ARM64::SUBXrs: |
| case ARM64::SUBSXrs: |
| 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: |
| 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(Addr, offset, Fail, 4, Inst, insn)) |
| 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 = 0; |
| |
| switch (Inst.getOpcode()) { |
| default: |
| return Fail; |
| case ARM64::LDRSWro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRXro: |
| case ARM64::STRXro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRWro: |
| case ARM64::STRWro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRQro: |
| case ARM64::STRQro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRDro: |
| case ARM64::STRDro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRSro: |
| case ARM64::STRSro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRHro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRBro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRBBro: |
| case ARM64::STRBBro: |
| case ARM64::LDRSBWro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRHHro: |
| case ARM64::STRHHro: |
| case ARM64::LDRSHWro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRSHXro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::LDRSBXro: |
| extend = (extendHi << 1) | extendLo; |
| DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); |
| break; |
| case ARM64::PRFMro: |
| extend = (extendHi << 1) | extendLo; |
| Inst.addOperand(MCOperand::CreateImm(Rt)); |
| } |
| |
| DecodeGPR64spRegisterClass(Inst, Rn, Addr, Decoder); |
| |
| if (extendHi == 0x3) |
| DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder); |
| else |
| DecodeGPR64RegisterClass(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); |
| |
| 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::ADDSXrx64: |
| case ARM64::SUBXrx64: |
| case ARM64::SUBSXrx64: |
| DecodeGPR64spRegisterClass(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) { |
| DecodeGPR64spRegisterClass(Inst, Rd, Addr, Decoder); |
| DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder); |
| imm = fieldFromInstruction(insn, 10, 13); |
| if (!ARM64_AM::isValidDecodeLogicalImmediate(imm, 64)) |
| return Fail; |
| } else { |
| DecodeGPR32RegisterClass(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(Addr, imm, Fail, 4, Inst, insn)) |
| 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(Addr, ImmVal, Fail, 4, Inst, insn)) |
| 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(Addr, imm << 2, Success, 4, Inst)) |
| 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); |
| |
| Inst.addOperand(MCOperand::CreateImm((op1 << 3) | op2)); |
| Inst.addOperand(MCOperand::CreateImm(crm)); |
| |
| return Success; |
| } |
| |
| 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); |
| |
| DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); |
| Inst.addOperand(MCOperand::CreateImm(bit)); |
| if (!Dis->tryAddingSymbolicOperand(Addr, dst << 2, Success, 4, Inst)) |
| 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)); |
| } |
| |
| DecodeGPR64RegisterClass(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)); |
| DecodeGPR64RegisterClass(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; |
| } |