summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp')
-rw-r--r--llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp165
1 files changed, 72 insertions, 93 deletions
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 56112112a029..d358913d38af 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -119,6 +119,8 @@ private:
class ARMDisassembler : public MCDisassembler {
public:
std::unique_ptr<const MCInstrInfo> MCII;
+ mutable ITStatus ITBlock;
+ mutable VPTStatus VPTBlock;
ARMDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
const MCInstrInfo *MCII)
@@ -146,10 +148,6 @@ private:
ArrayRef<uint8_t> Bytes, uint64_t Address,
raw_ostream &CStream) const;
- mutable ITStatus ITBlock;
- mutable VPTStatus VPTBlock;
-
- void AddThumb1SBit(MCInst &MI, bool InITBlock) const;
bool isVectorPredicable(const MCInst &MI) const;
DecodeStatus AddThumbPredicate(MCInst&) const;
void UpdateThumbPredicate(DecodeStatus &S, MCInst &MI) const;
@@ -159,12 +157,6 @@ private:
} // end anonymous namespace
-// Forward declare these because the autogenerated code will reference them.
-// Definitions are further down.
-static DecodeStatus DecodeT2AddrModeImm8(MCInst &Inst, unsigned Val,
- uint64_t Address,
- const MCDisassembler *Decoder);
-
typedef DecodeStatus OperandDecoder(MCInst &Inst, unsigned Val,
uint64_t Address,
const MCDisassembler *Decoder);
@@ -636,6 +628,17 @@ static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val,
return MCDisassembler::Success;
}
+// This overload is called when decoding `s_cc_out` operand, which is not
+// encoded into instruction. It is only used in Thumb1 instructions.
+static DecodeStatus DecodeCCOutOperand(MCInst &Inst,
+ const MCDisassembler *Decoder) {
+ const auto *D = static_cast<const ARMDisassembler *>(Decoder);
+ // Thumb1 instructions define CPSR unless they are inside an IT block.
+ MCRegister CCR = D->ITBlock.instrInITBlock() ? ARM::NoRegister : ARM::CPSR;
+ Inst.addOperand(MCOperand::createReg(CCR));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const MCDisassembler *Decoder) {
@@ -3158,6 +3161,65 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
return S;
}
+static DecodeStatus DecodeT2Imm8(MCInst &Inst, unsigned Val, uint64_t Address,
+ const MCDisassembler *Decoder) {
+ int imm = Val & 0xFF;
+ if (Val == 0)
+ imm = INT32_MIN;
+ else if (!(Val & 0x100))
+ imm *= -1;
+ Inst.addOperand(MCOperand::createImm(imm));
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeT2AddrModeImm8(MCInst &Inst, unsigned Val,
+ uint64_t Address,
+ const MCDisassembler *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned Rn = fieldFromInstruction(Val, 9, 4);
+ unsigned imm = fieldFromInstruction(Val, 0, 9);
+
+ // Thumb stores cannot use PC as dest register.
+ switch (Inst.getOpcode()) {
+ case ARM::t2STRT:
+ case ARM::t2STRBT:
+ case ARM::t2STRHT:
+ case ARM::t2STRi8:
+ case ARM::t2STRHi8:
+ case ARM::t2STRBi8:
+ if (Rn == 15)
+ return MCDisassembler::Fail;
+ break;
+ default:
+ break;
+ }
+
+ // Some instructions always use an additive offset.
+ switch (Inst.getOpcode()) {
+ case ARM::t2LDRT:
+ case ARM::t2LDRBT:
+ case ARM::t2LDRHT:
+ case ARM::t2LDRSBT:
+ case ARM::t2LDRSHT:
+ case ARM::t2STRT:
+ case ARM::t2STRBT:
+ case ARM::t2STRHT:
+ imm |= 0x100;
+ break;
+ default:
+ break;
+ }
+
+ if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeT2Imm8(Inst, imm, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
+
static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
uint64_t Address,
const MCDisassembler *Decoder) {
@@ -3467,18 +3529,6 @@ static DecodeStatus DecodeT2AddrModeImm0_1020s4(MCInst &Inst, unsigned Val,
return S;
}
-static DecodeStatus DecodeT2Imm8(MCInst &Inst, unsigned Val, uint64_t Address,
- const MCDisassembler *Decoder) {
- int imm = Val & 0xFF;
- if (Val == 0)
- imm = INT32_MIN;
- else if (!(Val & 0x100))
- imm *= -1;
- Inst.addOperand(MCOperand::createImm(imm));
-
- return MCDisassembler::Success;
-}
-
template <int shift>
static DecodeStatus DecodeT2Imm7(MCInst &Inst, unsigned Val, uint64_t Address,
const MCDisassembler *Decoder) {
@@ -3494,53 +3544,6 @@ static DecodeStatus DecodeT2Imm7(MCInst &Inst, unsigned Val, uint64_t Address,
return MCDisassembler::Success;
}
-static DecodeStatus DecodeT2AddrModeImm8(MCInst &Inst, unsigned Val,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- DecodeStatus S = MCDisassembler::Success;
-
- unsigned Rn = fieldFromInstruction(Val, 9, 4);
- unsigned imm = fieldFromInstruction(Val, 0, 9);
-
- // Thumb stores cannot use PC as dest register.
- switch (Inst.getOpcode()) {
- case ARM::t2STRT:
- case ARM::t2STRBT:
- case ARM::t2STRHT:
- case ARM::t2STRi8:
- case ARM::t2STRHi8:
- case ARM::t2STRBi8:
- if (Rn == 15)
- return MCDisassembler::Fail;
- break;
- default:
- break;
- }
-
- // Some instructions always use an additive offset.
- switch (Inst.getOpcode()) {
- case ARM::t2LDRT:
- case ARM::t2LDRBT:
- case ARM::t2LDRHT:
- case ARM::t2LDRSBT:
- case ARM::t2LDRSHT:
- case ARM::t2STRT:
- case ARM::t2STRBT:
- case ARM::t2STRHT:
- imm |= 0x100;
- break;
- default:
- break;
- }
-
- if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
- return MCDisassembler::Fail;
- if (!Check(S, DecodeT2Imm8(Inst, imm, Address, Decoder)))
- return MCDisassembler::Fail;
-
- return S;
-}
-
template <int shift>
static DecodeStatus DecodeTAddrModeImm7(MCInst &Inst, unsigned Val,
uint64_t Address,
@@ -6130,26 +6133,6 @@ DecodeStatus ARMDisassembler::getARMInstruction(MCInst &MI, uint64_t &Size,
return MCDisassembler::Fail;
}
-// Thumb1 instructions don't have explicit S bits. Rather, they
-// 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.
-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 < MCID.NumOperands; ++i, ++I) {
- if (I == MI.end()) break;
- 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 ? ARM::NoRegister : ARM::CPSR));
- return;
- }
- }
-}
-
bool ARMDisassembler::isVectorPredicable(const MCInst &MI) const {
const MCInstrDesc &MCID = MCII->get(MI.getOpcode());
for (unsigned i = 0; i < MCID.NumOperands; ++i) {
@@ -6343,9 +6326,7 @@ DecodeStatus ARMDisassembler::getThumbInstruction(MCInst &MI, uint64_t &Size,
STI);
if (Result) {
Size = 2;
- bool InITBlock = ITBlock.instrInITBlock();
Check(Result, AddThumbPredicate(MI));
- AddThumb1SBit(MI, InITBlock);
return Result;
}
@@ -6411,9 +6392,7 @@ DecodeStatus ARMDisassembler::getThumbInstruction(MCInst &MI, uint64_t &Size,
decodeInstruction(DecoderTableThumb32, MI, Insn32, Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
- bool InITBlock = ITBlock.instrInITBlock();
Check(Result, AddThumbPredicate(MI));
- AddThumb1SBit(MI, InITBlock);
return Result;
}