summaryrefslogtreecommitdiffstats
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.cpp73
1 files changed, 69 insertions, 4 deletions
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index eabc26d05f4..97a28fa233d 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -204,6 +204,9 @@ static DecodeStatus DecoderGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeGPRspRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodeHPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSPRRegisterClass(MCInst &Inst, unsigned RegNo,
@@ -566,6 +569,9 @@ static DecodeStatus DecodeMVEVPNOT(MCInst &Inst, unsigned Insn,
static DecodeStatus DecodeMVEOverlappingLongShift(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeT2AddSubSPImm(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
#include "ARMGenDisassemblerTables.inc"
static MCDisassembler *createARMDisassembler(const Target &T,
@@ -1231,6 +1237,17 @@ static DecodeStatus DecodeGPRPairRegisterClass(MCInst &Inst, unsigned RegNo,
return S;
}
+static DecodeStatus DecodeGPRspRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo != 13)
+ return MCDisassembler::Fail;
+
+ unsigned Register = GPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Register));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodetcGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
unsigned Register = 0;
@@ -5588,14 +5605,25 @@ static DecodeStatus DecodeT2Adr(MCInst &Inst, uint32_t Insn,
unsigned sign1 = fieldFromInstruction(Insn, 21, 1);
unsigned sign2 = fieldFromInstruction(Insn, 23, 1);
if (sign1 != sign2) return MCDisassembler::Fail;
+ const unsigned Rd = fieldFromInstruction(Insn, 8, 4);
+ assert(Inst.getNumOperands() == 0 && "We should receive an empty Inst");
+ DecodeStatus S = DecoderGPRRegisterClass(Inst, Rd, Address, Decoder);
unsigned Val = fieldFromInstruction(Insn, 0, 8);
Val |= fieldFromInstruction(Insn, 12, 3) << 8;
Val |= fieldFromInstruction(Insn, 26, 1) << 11;
- Val |= sign1 << 12;
- Inst.addOperand(MCOperand::createImm(SignExtend32<13>(Val)));
-
- return MCDisassembler::Success;
+ // If sign, then it is decreasing the address.
+ if (sign1) {
+ // Following ARMv7 Architecture Manual, when the offset
+ // is zero, it is decoded as a subw, not as a adr.w
+ if (!Val) {
+ Inst.setOpcode(ARM::t2SUBri12);
+ Inst.addOperand(MCOperand::createReg(ARM::PC));
+ } else
+ Val = -Val;
+ }
+ Inst.addOperand(MCOperand::createImm(Val));
+ return S;
}
static DecodeStatus DecodeT2ShifterImmOperand(MCInst &Inst, uint32_t Val,
@@ -6595,3 +6623,40 @@ static DecodeStatus DecodeMVEVPNOT(MCInst &Inst, unsigned Insn, uint64_t Address
Inst.addOperand(MCOperand::createReg(ARM::VPR));
return S;
}
+
+static DecodeStatus DecodeT2AddSubSPImm(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ const unsigned Rd = fieldFromInstruction(Insn, 8, 4);
+ const unsigned Rn = fieldFromInstruction(Insn, 16, 4);
+ const unsigned Imm12 = fieldFromInstruction(Insn, 26, 1) << 11 |
+ fieldFromInstruction(Insn, 12, 3) << 8 |
+ fieldFromInstruction(Insn, 0, 8);
+ const unsigned TypeT3 = fieldFromInstruction(Insn, 25, 1);
+ unsigned sign1 = fieldFromInstruction(Insn, 21, 1);
+ unsigned sign2 = fieldFromInstruction(Insn, 23, 1);
+ unsigned S = fieldFromInstruction(Insn, 20, 1);
+ if (sign1 != sign2)
+ return MCDisassembler::Fail;
+
+ // T3 does a zext of imm12, where T2 does a ThumbExpandImm (T2SOImm)
+ DecodeStatus DS = MCDisassembler::Success;
+ if ((!Check(DS,
+ DecodeGPRspRegisterClass(Inst, Rd, Address, Decoder))) || // dst
+ (!Check(DS, DecodeGPRspRegisterClass(Inst, Rn, Address, Decoder))))
+ return MCDisassembler::Fail;
+ if (TypeT3) {
+ Inst.setOpcode(sign1 ? ARM::t2SUBspImm12 : ARM::t2ADDspImm12);
+ S = 0;
+ Inst.addOperand(MCOperand::createImm(Imm12)); // zext imm12
+ } else {
+ Inst.setOpcode(sign1 ? ARM::t2SUBspImm : ARM::t2ADDspImm);
+ if (!Check(DS, DecodeT2SOImm(Inst, Imm12, Address, Decoder))) // imm12
+ return MCDisassembler::Fail;
+ }
+ if (!Check(DS, DecodeCCOutOperand(Inst, S, Address, Decoder))) // cc_out
+ return MCDisassembler::Fail;
+
+ Inst.addOperand(MCOperand::createReg(0)); // pred
+
+ return DS;
+}
OpenPOWER on IntegriCloud