diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-04-14 21:41:27 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-06-22 18:20:56 +0000 |
commit | bdd1243df58e60e85101c09001d9812a789b6bc4 (patch) | |
tree | a1ce621c7301dd47ba2ddc3b8eaa63b441389481 /contrib/llvm-project/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp | |
parent | 781624ca2d054430052c828ba8d2c2eaf2d733e7 (diff) | |
parent | e3b557809604d036af6e00c60f012c2025b59a5e (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.cpp | 134 |
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) { |