llvm-6502/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp
Tim Northover 369e565f23 ARM64: model pre/post-indexed operations properly.
We should be keeping track of the writeback on these instructions,
otherwise we're relying on LLVM's stupidity for correct code.

Fortunately, the MC layer can now handle all required constraints,
which means we can get rid of the CodeGen only PseudoInsts too.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209426 91177308-0d34-0410-b5e6-96231b3b80d8
2014-05-22 11:56:20 +00:00

1540 lines
57 KiB
C++

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