aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-04-14 21:41:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-06-22 18:20:56 +0000
commitbdd1243df58e60e85101c09001d9812a789b6bc4 (patch)
treea1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
parent781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff)
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp134
1 files changed, 72 insertions, 62 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/contrib/llvm-project/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index f81495985405..fa696d8952e4 100644
--- a/contrib/llvm-project/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/contrib/llvm-project/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -17,6 +17,7 @@
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/MC/TargetRegistry.h"
@@ -129,8 +130,14 @@ namespace {
/// ARM disassembler for all ARM platforms.
class ARMDisassembler : public MCDisassembler {
public:
- ARMDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) :
- MCDisassembler(STI, Ctx) {
+ std::unique_ptr<const MCInstrInfo> MCII;
+
+ ARMDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
+ const MCInstrInfo *MCII)
+ : MCDisassembler(STI, Ctx), MCII(MCII) {
+ InstructionEndianness = STI.getFeatureBits()[ARM::ModeBigEndianInstructions]
+ ? llvm::support::big
+ : llvm::support::little;
}
~ARMDisassembler() override = default;
@@ -154,27 +161,16 @@ private:
mutable ITStatus ITBlock;
mutable VPTStatus VPTBlock;
+ void AddThumb1SBit(MCInst &MI, bool InITBlock) const;
+ bool isVectorPredicable(const MCInst &MI) const;
DecodeStatus AddThumbPredicate(MCInst&) const;
void UpdateThumbVFPPredicate(DecodeStatus &, MCInst&) const;
+
+ llvm::support::endianness InstructionEndianness;
};
} // end anonymous namespace
-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!");
-}
-
// Forward declare these because the autogenerated code will reference them.
// Definitions are further down.
static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
@@ -639,6 +635,9 @@ static DecodeStatus DecodeVPTMaskOperand(MCInst &Inst, unsigned Val,
static DecodeStatus DecodeVpredROperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const MCDisassembler *Decoder);
+static DecodeStatus DecodeVpredNOperand(MCInst &Inst, unsigned Val,
+ uint64_t Address,
+ const MCDisassembler *Decoder);
static DecodeStatus
DecodeRestrictedIPredicateOperand(MCInst &Inst, unsigned Val, uint64_t Address,
const MCDisassembler *Decoder);
@@ -707,7 +706,7 @@ static DecodeStatus DecodeT2AddSubSPImm(MCInst &Inst, unsigned Insn,
static MCDisassembler *createARMDisassembler(const Target &T,
const MCSubtargetInfo &STI,
MCContext &Ctx) {
- return new ARMDisassembler(STI, Ctx);
+ return new ARMDisassembler(STI, Ctx, T.createMCInstrInfo());
}
// Post-decoding checks
@@ -765,7 +764,8 @@ uint64_t ARMDisassembler::suggestBytesToSkip(ArrayRef<uint8_t> Bytes,
if (Bytes.size() < 2)
return 2;
- uint16_t Insn16 = (Bytes[1] << 8) | Bytes[0];
+ uint16_t Insn16 = llvm::support::endian::read<uint16_t>(
+ Bytes.data(), InstructionEndianness);
return Insn16 < 0xE800 ? 2 : 4;
}
@@ -794,9 +794,9 @@ DecodeStatus ARMDisassembler::getARMInstruction(MCInst &MI, uint64_t &Size,
return MCDisassembler::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);
+ // Encoded as a 32-bit word in the stream.
+ uint32_t Insn = llvm::support::endian::read<uint32_t>(Bytes.data(),
+ InstructionEndianness);
// Calling the auto-generated decoder function.
DecodeStatus Result =
@@ -841,12 +841,6 @@ DecodeStatus ARMDisassembler::getARMInstruction(MCInst &MI, uint64_t &Size,
return MCDisassembler::Fail;
}
-namespace llvm {
-
-extern const MCInstrDesc ARMInsts[];
-
-} // end namespace llvm
-
/// tryAddingSymbolicOperand - trys to add a symbolic operand in place of the
/// immediate Value in the MCInst. The immediate Value has had any PC
/// adjustment made by the caller. If the instruction is a branch instruction
@@ -888,14 +882,15 @@ static void tryAddingPcLoadReferenceComment(uint64_t Address, int Value,
// implicitly set CPSR. Since it's not represented in the encoding, the
// auto-generated decoder won't inject the CPSR operand. We need to fix
// that as a post-pass.
-static void AddThumb1SBit(MCInst &MI, bool InITBlock) {
- const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
- unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
+void ARMDisassembler::AddThumb1SBit(MCInst &MI, bool InITBlock) const {
+ const MCInstrDesc &MCID = MCII->get(MI.getOpcode());
MCInst::iterator I = MI.begin();
- for (unsigned i = 0; i < NumOps; ++i, ++I) {
+ for (unsigned i = 0; i < MCID.NumOperands; ++i, ++I) {
if (I == MI.end()) break;
- if (OpInfo[i].isOptionalDef() && OpInfo[i].RegClass == ARM::CCRRegClassID) {
- if (i > 0 && OpInfo[i-1].isPredicate()) continue;
+ if (MCID.operands()[i].isOptionalDef() &&
+ MCID.operands()[i].RegClass == ARM::CCRRegClassID) {
+ if (i > 0 && MCID.operands()[i - 1].isPredicate())
+ continue;
MI.insert(I, MCOperand::createReg(InITBlock ? 0 : ARM::CPSR));
return;
}
@@ -904,11 +899,10 @@ static void AddThumb1SBit(MCInst &MI, bool InITBlock) {
MI.insert(I, MCOperand::createReg(InITBlock ? 0 : ARM::CPSR));
}
-static bool isVectorPredicable(unsigned Opcode) {
- const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
- unsigned short NumOps = ARMInsts[Opcode].NumOperands;
- for (unsigned i = 0; i < NumOps; ++i) {
- if (ARM::isVpred(OpInfo[i].OperandType))
+bool ARMDisassembler::isVectorPredicable(const MCInst &MI) const {
+ const MCInstrDesc &MCID = MCII->get(MI.getOpcode());
+ for (unsigned i = 0; i < MCID.NumOperands; ++i) {
+ if (ARM::isVpred(MCID.operands()[i].OperandType))
return true;
}
return false;
@@ -967,8 +961,8 @@ ARMDisassembler::AddThumbPredicate(MCInst &MI) const {
// Warn on non-VPT predicable instruction in a VPT block and a VPT
// predicable instruction in an IT block
- if ((!isVectorPredicable(MI.getOpcode()) && VPTBlock.instrInVPTBlock()) ||
- (isVectorPredicable(MI.getOpcode()) && ITBlock.instrInITBlock()))
+ if ((!isVectorPredicable(MI) && VPTBlock.instrInVPTBlock()) ||
+ (isVectorPredicable(MI) && ITBlock.instrInITBlock()))
S = SoftFail;
// If we're in an IT/VPT block, base the predicate on that. Otherwise,
@@ -983,15 +977,15 @@ ARMDisassembler::AddThumbPredicate(MCInst &MI) const {
VPTBlock.advanceVPTState();
}
- const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
- unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
+ const MCInstrDesc &MCID = MCII->get(MI.getOpcode());
MCInst::iterator CCI = MI.begin();
- for (unsigned i = 0; i < NumOps; ++i, ++CCI) {
- if (OpInfo[i].isPredicate() || CCI == MI.end()) break;
+ for (unsigned i = 0; i < MCID.NumOperands; ++i, ++CCI) {
+ if (MCID.operands()[i].isPredicate() || CCI == MI.end())
+ break;
}
- if (ARMInsts[MI.getOpcode()].isPredicable()) {
+ if (MCID.isPredicable()) {
CCI = MI.insert(CCI, MCOperand::createImm(CC));
++CCI;
if (CC == ARMCC::AL)
@@ -1004,11 +998,12 @@ ARMDisassembler::AddThumbPredicate(MCInst &MI) const {
MCInst::iterator VCCI = MI.begin();
unsigned VCCPos;
- for (VCCPos = 0; VCCPos < NumOps; ++VCCPos, ++VCCI) {
- if (ARM::isVpred(OpInfo[VCCPos].OperandType) || VCCI == MI.end()) break;
+ for (VCCPos = 0; VCCPos < MCID.NumOperands; ++VCCPos, ++VCCI) {
+ if (ARM::isVpred(MCID.operands()[VCCPos].OperandType) || VCCI == MI.end())
+ break;
}
- if (isVectorPredicable(MI.getOpcode())) {
+ if (isVectorPredicable(MI)) {
VCCI = MI.insert(VCCI, MCOperand::createImm(VCC));
++VCCI;
if (VCC == ARMVCC::None)
@@ -1018,9 +1013,8 @@ ARMDisassembler::AddThumbPredicate(MCInst &MI) const {
++VCCI;
VCCI = MI.insert(VCCI, MCOperand::createReg(0));
++VCCI;
- if (OpInfo[VCCPos].OperandType == ARM::OPERAND_VPRED_R) {
- int TiedOp = ARMInsts[MI.getOpcode()].getOperandConstraint(
- VCCPos + 3, MCOI::TIED_TO);
+ if (MCID.operands()[VCCPos].OperandType == ARM::OPERAND_VPRED_R) {
+ int TiedOp = MCID.getOperandConstraint(VCCPos + 3, MCOI::TIED_TO);
assert(TiedOp >= 0 &&
"Inactive register in vpred_r is not tied to an output!");
// Copy the operand to ensure it's not invalidated when MI grows.
@@ -1051,12 +1045,13 @@ void ARMDisassembler::UpdateThumbVFPPredicate(
VPTBlock.advanceVPTState();
}
- const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
+ const MCInstrDesc &MCID = MCII->get(MI.getOpcode());
+ ArrayRef<MCOperandInfo> OpInfo = MCID.operands();
MCInst::iterator I = MI.begin();
- unsigned short NumOps = ARMInsts[MI.getOpcode()].NumOperands;
+ unsigned short NumOps = MCID.NumOperands;
for (unsigned i = 0; i < NumOps; ++i, ++I) {
if (OpInfo[i].isPredicate() ) {
- if (CC != ARMCC::AL && !ARMInsts[MI.getOpcode()].isPredicable())
+ if (CC != ARMCC::AL && !MCID.isPredicable())
Check(S, SoftFail);
I->setImm(CC);
++I;
@@ -1084,7 +1079,8 @@ DecodeStatus ARMDisassembler::getThumbInstruction(MCInst &MI, uint64_t &Size,
return MCDisassembler::Fail;
}
- uint16_t Insn16 = (Bytes[1] << 8) | Bytes[0];
+ uint16_t Insn16 = llvm::support::endian::read<uint16_t>(
+ Bytes.data(), InstructionEndianness);
DecodeStatus Result =
decodeInstruction(DecoderTableThumb16, MI, Insn16, Address, this, STI);
if (Result != MCDisassembler::Fail) {
@@ -1138,7 +1134,8 @@ DecodeStatus ARMDisassembler::getThumbInstruction(MCInst &MI, uint64_t &Size,
}
uint32_t Insn32 =
- (Bytes[3] << 8) | (Bytes[2] << 0) | (Bytes[1] << 24) | (Bytes[0] << 16);
+ (uint32_t(Insn16) << 16) | llvm::support::endian::read<uint16_t>(
+ Bytes.data() + 2, InstructionEndianness);
Result =
decodeInstruction(DecoderTableMVE32, MI, Insn32, Address, this, STI);
@@ -1637,7 +1634,9 @@ static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val,
// AL predicate is not allowed on Thumb1 branches.
if (Inst.getOpcode() == ARM::tBcc && Val == 0xE)
return MCDisassembler::Fail;
- if (Val != ARMCC::AL && !ARMInsts[Inst.getOpcode()].isPredicable())
+ const MCInstrInfo *MCII =
+ static_cast<const ARMDisassembler *>(Decoder)->MCII.get();
+ if (Val != ARMCC::AL && !MCII->get(Inst.getOpcode()).isPredicable())
Check(S, MCDisassembler::SoftFail);
Inst.addOperand(MCOperand::createImm(Val));
if (Val == ARMCC::AL) {
@@ -2002,7 +2001,7 @@ static DecodeStatus DecodeCopMemInstruction(MCInst &Inst, unsigned Insn,
case ARM::STC_POST:
case ARM::STCL_POST:
imm |= U << 8;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
default:
// The 'option' variant doesn't encode 'U' in the immediate since
// the immediate is unsigned [0,255].
@@ -3185,7 +3184,7 @@ static DecodeStatus DecodeVLDInstruction(MCInst &Inst, unsigned Insn,
break;
}
// Fall through to handle the register offset variant.
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case ARM::VLD1d8wb_fixed:
case ARM::VLD1d16wb_fixed:
case ARM::VLD1d32wb_fixed:
@@ -5007,7 +5006,7 @@ static DecodeStatus DecodeMSRMask(MCInst &Inst, unsigned Val, uint64_t Address,
case 0x93: // faultmask_ns
if (!(FeatureBits[ARM::HasV8MMainlineOps]))
return MCDisassembler::Fail;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case 10: // msplim
case 11: // psplim
case 0x88: // msp_ns
@@ -6337,7 +6336,7 @@ static DecodeStatus DecodeLOLoop(MCInst &Inst, unsigned Insn, uint64_t Address,
case ARM::MVE_LETP:
Inst.addOperand(MCOperand::createReg(ARM::LR));
Inst.addOperand(MCOperand::createReg(ARM::LR));
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case ARM::t2LE:
if (!Check(S, DecodeBFLabelOperand<false, true, true, 11>(
Inst, Imm, Address, Decoder)))
@@ -6551,6 +6550,17 @@ static DecodeStatus DecodeVpredROperand(MCInst &Inst, unsigned RegNo,
return MCDisassembler::Success;
}
+[[maybe_unused]] static DecodeStatus
+DecodeVpredNOperand(MCInst &Inst, unsigned RegNo, uint64_t Address,
+ const MCDisassembler *Decoder) {
+ // Similar to above, we want to ensure that no operands are added for the
+ // vpred operands. (This is marked "maybe_unused" for the moment; because
+ // DecoderEmitter currently (wrongly) omits operands with no instruction bits,
+ // the decoder doesn't actually call it yet. That will be addressed in a
+ // future change.)
+ return MCDisassembler::Success;
+}
+
static DecodeStatus
DecodeRestrictedIPredicateOperand(MCInst &Inst, unsigned Val, uint64_t Address,
const MCDisassembler *Decoder) {