-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[ARM] Auto-decode pred operands of Thumb instructions #156540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
8b97be9 to
8e6e8dd
Compare
46fc93b to
ee67c36
Compare
8e6e8dd to
a4b0131
Compare
ee67c36 to
9709854
Compare
a4b0131 to
611d87c
Compare
9709854 to
aa97c88
Compare
611d87c to
6029b96
Compare
aa97c88 to
f31a7b8
Compare
408cfbc to
b06dce1
Compare
f31a7b8 to
5f3f11d
Compare
b06dce1 to
b45bd86
Compare
b45bd86 to
204f13a
Compare
204f13a to
67bdfe0
Compare
This change adds basic `MCInst` verification (checks the number of operands) and fixes detected bugs. * `RFE*` instructions have only one operand, but `DecodeRFEInstruction` added two. * `DecodeMVEModImmInstruction` and `DecodeMVEVCMP` added a `vpred` operand, but this is what `AddThumbPredicate` normally does. This resulted in an extra `vpred` operand. * `DecodeMVEVADCInstruction` added an extra immediate operand. * `getARMInstruction` added a `pred` operand to instructions that don't have one (via `DecodePredicateOperand`). * `AddThumb1SBit` appended an extra register operand to instructions that don't modify CPSR (such as `tBL`). * Instructions in `NEONDup` namespace have `pred` operand that the generated code successfully decodes. The operand was added once again by `getARMInstruction`/`getThumbInstruction` via `AddThumbPredicate`. Functional changes extracted from #156540.
ea21c47 to
23f77e4
Compare
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
0aa1f38 to
9853907
Compare
The operand can be decoded automatically, without the need for post-decoding instruction modification. Part of #156540.
Make the operands auto-decodable by adding `bits<0>` fields to instructions. Now we try to decode a vpred_n/vpred_r operand only if the instruction being decoded has one. We still need post-decoding pass to check/advance VPT state. Part of #156540.
c32bc56 to
91d92fe
Compare
Make the operands auto-decodable by adding `bits<0>` fields to instructions. Now we try to decode a vpred_n/vpred_r operand only if the instruction being decoded has one. We still need post-decoding pass to check/advance VPT state. Part of llvm#156540.
91d92fe to
9114707
Compare
9114707 to
bb5577b
Compare
| ARMDisassembler::checkThumbPredicate(MCInst &MI) const { | ||
| MCDisassembler::DecodeStatus S = Success; | ||
|
|
||
| const FeatureBitset &FeatureBits = getSubtargetInfo().getFeatureBits(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The switch a little down below could probably be moved to DecodePredicateOperand. Not sure if that would be a better place for it. Let me know what you think.
|
@llvm/pr-subscribers-backend-arm Author: Sergei Barannikov (s-barannikov) ChangesMost predicable Thumb instructions do not encode the predicate operand, but rather take it from an enclosing IT block. The previous approach was to analyze an instruction after it has been decoded and add missing predicate operand if necessary. The post-decoding pass is still required to check predicate applicability and advance IT block state, but it no longer modifies a decoded instruction. Some of the custom decoder methods have become redundant and can be removed in the future, delegating the decoding task to TableGen-erated decoder. Patch is 36.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/156540.diff 8 Files Affected:
diff --git a/llvm/lib/Target/ARM/ARMInstrCDE.td b/llvm/lib/Target/ARM/ARMInstrCDE.td
index f4326de5ed667..5d4e3acf5b581 100644
--- a/llvm/lib/Target/ARM/ARMInstrCDE.td
+++ b/llvm/lib/Target/ARM/ARMInstrCDE.td
@@ -115,6 +115,7 @@ class CDE_CX1_Instr<string iname, CX_Params params>
!con(params.Iops1, (ins imm_13b:$imm), params.PredOp),
!strconcat(iname, params.PAsm, "\t$coproc, $Rd, $imm"),
params.Cstr> {
+ bits<0> p;
bits<13> imm;
bits<4> Rd;
@@ -131,6 +132,7 @@ class CDE_CX2_Instr<string iname, CX_Params params>
!con(params.Iops2, (ins imm_9b:$imm), params.PredOp),
!strconcat(iname, params.PAsm, "\t$coproc, $Rd, $Rn, $imm"),
params.Cstr> {
+ bits<0> p;
bits<9> imm;
bits<4> Rd;
bits<4> Rn;
@@ -149,6 +151,7 @@ class CDE_CX3_Instr<string iname, CX_Params params>
!con(params.Iops3, (ins imm_6b:$imm), params.PredOp),
!strconcat(iname, params.PAsm, "\t$coproc, $Rd, $Rn, $Rm, $imm"),
params.Cstr> {
+ bits<0> p;
bits<6> imm;
bits<4> Rd;
bits<4> Rn;
diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td
index 1ad2485dce17f..1cd1a9a0f7331 100644
--- a/llvm/lib/Target/ARM/ARMInstrFormats.td
+++ b/llvm/lib/Target/ARM/ARMInstrFormats.td
@@ -1220,6 +1220,7 @@ class Thumb1sI<dag oops, dag iops, AddrMode am, int sz,
string opc, string asm, string cstr, list<dag> pattern>
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
bits<0> s;
+ bits<0> p;
let OutOperandList = !con(oops, (outs s_cc_out:$s));
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${s}${p}", asm);
@@ -1244,6 +1245,7 @@ class Thumb1pI<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
+ bits<0> p;
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${p}", asm);
@@ -1343,6 +1345,7 @@ class Thumb2I<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
+ bits<0> p;
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${p}", asm);
@@ -1361,6 +1364,7 @@ class Thumb2sI<dag oops, dag iops, AddrMode am, int sz,
InstrItinClass itin,
string opc, string asm, string cstr, list<dag> pattern>
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
+ bits<0> p;
bits<1> s; // condition-code set flag ('1' if the insn should set the flags)
let Inst{20} = s;
@@ -2221,6 +2225,7 @@ class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
InstrItinClass itin, string opc, string dt, string asm, string cstr,
list<dag> pattern>
: InstARM<am, 4, im, f, NeonDomain, cstr, itin> {
+ bits<0> p;
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
@@ -2234,6 +2239,7 @@ class NeonXI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
InstrItinClass itin, string opc, string asm, string cstr,
list<dag> pattern>
: InstARM<am, 4, im, f, NeonDomain, cstr, itin> {
+ bits<0> p;
let OutOperandList = oops;
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${p}", "\t", asm);
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td
index 0c5ea3e0fa8d5..bc1b34c691e39 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb.td
@@ -483,6 +483,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
def tBX : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bx${p}\t$Rm", []>,
T1Special<{1,1,0,?}>, Sched<[WriteBr]> {
// A6.2.3 & A8.6.25
+ bits<0> p;
bits<4> Rm;
let Inst{6-3} = Rm;
let Inst{2-0} = 0b000;
@@ -491,6 +492,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
def tBXNS : TI<(outs), (ins GPR:$Rm, pred:$p), IIC_Br, "bxns${p}\t$Rm", []>,
Requires<[IsThumb, Has8MSecExt]>,
T1Special<{1,1,0,?}>, Sched<[WriteBr]> {
+ bits<0> p;
bits<4> Rm;
let Inst{6-3} = Rm;
let Inst{2-0} = 0b100;
@@ -523,6 +525,7 @@ let isCall = 1,
"bl${p}\t$func",
[(ARMcall tglobaladdr:$func)]>,
Requires<[IsThumb]>, Sched<[WriteBrL]> {
+ bits<0> p;
bits<24> func;
let Inst{26} = func{23};
let Inst{25-16} = func{20-11};
@@ -536,6 +539,7 @@ let isCall = 1,
(outs), (ins pred:$p, thumb_blx_target:$func), IIC_Br,
"blx${p}\t$func", []>,
Requires<[IsThumb, HasV5T, IsNotMClass]>, Sched<[WriteBrL]> {
+ bits<0> p;
bits<24> func;
let Inst{26} = func{23};
let Inst{25-16} = func{20-11};
@@ -550,6 +554,7 @@ let isCall = 1,
"blx${p}\t$func", []>,
Requires<[IsThumb, HasV5T]>,
T1Special<{1,1,1,?}>, Sched<[WriteBrL]> { // A6.2.3 & A8.6.24;
+ bits<0> p;
bits<4> func;
let Inst{6-3} = func;
let Inst{2-0} = 0b000;
@@ -565,6 +570,7 @@ let isCall = 1,
"blxns${p}\t$func", []>,
Requires<[IsThumb, Has8MSecExt]>,
T1Special<{1,1,1,?}>, Sched<[WriteBrL]> {
+ bits<0> p;
bits<4> func;
let Inst{6-3} = func;
let Inst{2-0} = 0b100;
@@ -824,6 +830,7 @@ let hasSideEffects = 0 in {
let mayLoad = 1, hasExtraDefRegAllocReq = 1, variadicOpsAreDefs = 1 in
def tLDMIA : T1I<(outs), (ins tGPR:$Rn, pred:$p, reglist:$regs, variable_ops),
IIC_iLoad_m, "ldm${p}\t$Rn, $regs", []>, T1Encoding<{1,1,0,0,1,?}> {
+ bits<0> p;
bits<3> Rn;
bits<8> regs;
let Inst{10-8} = Rn;
@@ -854,6 +861,7 @@ def tSTMIA_UPD : Thumb1I<(outs tGPR:$wb),
AddrModeNone, 2, IIC_iStore_mu,
"stm${p}\t$Rn!, $regs", "$Rn = $wb", []>,
T1Encoding<{1,1,0,0,0,?}> {
+ bits<0> p;
bits<3> Rn;
bits<8> regs;
let Inst{10-8} = Rn;
@@ -872,6 +880,7 @@ def tPOP : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops),
IIC_iPop,
"pop${p}\t$regs", []>,
T1Misc<{1,1,0,?,?,?,?}>, Sched<[WriteLd]> {
+ bits<0> p;
bits<16> regs;
let Inst{8} = regs{15};
let Inst{7-0} = regs{7-0};
@@ -882,6 +891,7 @@ def tPUSH : T1I<(outs), (ins pred:$p, reglist:$regs, variable_ops),
IIC_iStore_m,
"push${p}\t$regs", []>,
T1Misc<{0,1,0,?,?,?,?}>, Sched<[WriteST]> {
+ bits<0> p;
bits<16> regs;
let Inst{8} = regs{14};
let Inst{7-0} = regs{7-0};
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index c229c8e4491df..290dd05fc84cb 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -2059,6 +2059,7 @@ multiclass thumb2_ld_mult<string asm, InstrItinClass itin,
def IA :
T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
itin, !strconcat(asm, "${p}.w\t$Rn, $regs"), []> {
+ bits<0> p;
bits<4> Rn;
bits<16> regs;
@@ -2074,6 +2075,7 @@ multiclass thumb2_ld_mult<string asm, InstrItinClass itin,
def IA_UPD :
T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
itin_upd, !strconcat(asm, "${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
+ bits<0> p;
bits<4> Rn;
bits<16> regs;
@@ -2089,6 +2091,7 @@ multiclass thumb2_ld_mult<string asm, InstrItinClass itin,
def DB :
T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
itin, !strconcat(asm, "db${p}\t$Rn, $regs"), []> {
+ bits<0> p;
bits<4> Rn;
bits<16> regs;
@@ -2104,6 +2107,7 @@ multiclass thumb2_ld_mult<string asm, InstrItinClass itin,
def DB_UPD :
T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
itin_upd, !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+ bits<0> p;
bits<4> Rn;
bits<16> regs;
@@ -2128,6 +2132,7 @@ multiclass thumb2_st_mult<string asm, InstrItinClass itin,
def IA :
T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
itin, !strconcat(asm, "${p}.w\t$Rn, $regs"), []> {
+ bits<0> p;
bits<4> Rn;
bits<16> regs;
@@ -2146,6 +2151,7 @@ multiclass thumb2_st_mult<string asm, InstrItinClass itin,
def IA_UPD :
T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
itin_upd, !strconcat(asm, "${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> {
+ bits<0> p;
bits<4> Rn;
bits<16> regs;
@@ -2164,6 +2170,7 @@ multiclass thumb2_st_mult<string asm, InstrItinClass itin,
def DB :
T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
itin, !strconcat(asm, "db${p}\t$Rn, $regs"), []> {
+ bits<0> p;
bits<4> Rn;
bits<16> regs;
@@ -2182,6 +2189,7 @@ multiclass thumb2_st_mult<string asm, InstrItinClass itin,
def DB_UPD :
T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
itin_upd, !strconcat(asm, "db${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+ bits<0> p;
bits<4> Rn;
bits<16> regs;
@@ -4030,9 +4038,11 @@ def t2TBH : T2I<(outs), (ins (addrmode_tbh $Rn, $Rm):$addr), IIC_Br,
// FIXME: should be able to write a pattern for ARMBrcond, but can't use
// a two-value operand where a dag node expects ", "two operands. :(
let isBranch = 1, isTerminator = 1 in
-def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
- "b", ".w\t$target",
- [/*(ARMbrcond bb:$target, imm:$cc)*/]>, Sched<[WriteBr]> {
+def t2Bcc : Thumb2XI<(outs), (ins brtarget:$target, pred:$p),
+ AddrModeNone, 4, IIC_Br,
+ "b${p}.w\t$target", "",
+ [/*(ARMbrcond bb:$target, imm:$cc)*/]>,
+ Sched<[WriteBr]> {
let Inst{31-27} = 0b11110;
let Inst{15-14} = 0b10;
let Inst{12} = 0;
@@ -5481,6 +5491,7 @@ class V8_1MI<dag oops, dag iops, AddrMode am, InstrItinClass itin, string asm,
def t2CLRM : V8_1MI<(outs),
(ins pred:$p, reglist_with_apsr:$regs, variable_ops),
AddrModeNone, NoItinerary, "clrm${p}", "$regs", "", []> {
+ bits<0> p;
bits<16> regs;
let Inst{31-16} = 0b1110100010011111;
@@ -5509,6 +5520,7 @@ def t2BF_LabelPseudo
def t2BFi : t2BF<(ins bflabel_u4:$b_label, bflabel_s16:$label, pred:$p),
!strconcat("bf", "${p}"), "$b_label, $label"> {
+ bits<0> p;
bits<4> b_label;
bits<16> label;
@@ -5540,6 +5552,7 @@ def t2BFic : t2BF<(ins bflabel_u4:$b_label, bflabel_s12:$label,
def t2BFr : t2BF<(ins bflabel_u4:$b_label, rGPR:$Rn, pred:$p),
!strconcat("bfx", "${p}"), "$b_label, $Rn"> {
+ bits<0> p;
bits<4> b_label;
bits<4> Rn;
@@ -5551,6 +5564,7 @@ def t2BFr : t2BF<(ins bflabel_u4:$b_label, rGPR:$Rn, pred:$p),
def t2BFLi : t2BF<(ins bflabel_u4:$b_label, bflabel_s18:$label, pred:$p),
!strconcat("bfl", "${p}"), "$b_label, $label"> {
+ bits<0> p;
bits<4> b_label;
bits<18> label;
@@ -5563,6 +5577,7 @@ def t2BFLi : t2BF<(ins bflabel_u4:$b_label, bflabel_s18:$label, pred:$p),
def t2BFLr : t2BF<(ins bflabel_u4:$b_label, rGPR:$Rn, pred:$p),
!strconcat("bflx", "${p}"), "$b_label, $Rn"> {
+ bits<0> p;
bits<4> b_label;
bits<4> Rn;
@@ -5803,6 +5818,7 @@ let Predicates = [IsThumb2, HasV8_1MMainline, HasPACBTI] in {
def t2PACG : V8_1MI<(outs rGPR:$Rd),
(ins pred:$p, GPRnopc:$Rn, GPRnopc:$Rm),
AddrModeNone, NoItinerary, "pacg${p}", "$Rd, $Rn, $Rm", "", []> {
+ bits<0> p;
bits<4> Rd;
bits<4> Rn;
bits<4> Rm;
@@ -5818,6 +5834,7 @@ let hasSideEffects = 1 in {
class PACBTIAut<dag iops, string asm, bit b>
: V8_1MI<(outs), iops,
AddrModeNone, NoItinerary, asm, "$Ra, $Rn, $Rm", "", []> {
+ bits<0> p;
bits<4> Ra;
bits<4> Rn;
bits<4> Rm;
diff --git a/llvm/lib/Target/ARM/CMakeLists.txt b/llvm/lib/Target/ARM/CMakeLists.txt
index fa778cad4af8e..a39629bd8aeb0 100644
--- a/llvm/lib/Target/ARM/CMakeLists.txt
+++ b/llvm/lib/Target/ARM/CMakeLists.txt
@@ -6,8 +6,7 @@ tablegen(LLVM ARMGenAsmMatcher.inc -gen-asm-matcher)
tablegen(LLVM ARMGenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM ARMGenCallingConv.inc -gen-callingconv)
tablegen(LLVM ARMGenDAGISel.inc -gen-dag-isel)
-tablegen(LLVM ARMGenDisassemblerTables.inc -gen-disassembler
- -ignore-non-decodable-operands)
+tablegen(LLVM ARMGenDisassemblerTables.inc -gen-disassembler)
tablegen(LLVM ARMGenFastISel.inc -gen-fast-isel)
tablegen(LLVM ARMGenGlobalISel.inc -gen-global-isel)
tablegen(LLVM ARMGenInstrInfo.inc -gen-instr-info)
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index b119146576569..0a3e6d2f89e1c 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -149,7 +149,7 @@ class ARMDisassembler : public MCDisassembler {
raw_ostream &CStream) const;
bool isVectorPredicable(const MCInst &MI) const;
- DecodeStatus AddThumbPredicate(MCInst&) const;
+ DecodeStatus checkThumbPredicate(MCInst &) const;
void UpdateThumbPredicate(DecodeStatus &S, MCInst &MI) const;
llvm::endianness InstructionEndianness;
@@ -618,6 +618,23 @@ static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val,
return S;
}
+// This overload is used to decode a `pred` operand that is not encoded into
+// instruction. This is the case for almost all predicable Thumb instructions
+// (exceptions are tBcc and t2Bcc). Some predicable Thumb instructions have ARM
+// equivalents where they are not predicable (always executed). This function
+// is used to decode `pred` operand of these ARM instructions, too.
+static DecodeStatus DecodePredicateOperand(MCInst &Inst,
+ const MCDisassembler *Decoder) {
+ const auto *D = static_cast<const ARMDisassembler *>(Decoder);
+ unsigned CC = ARMCC::AL;
+ if (D->getSubtargetInfo().hasFeature(ARM::ModeThumb))
+ CC = D->ITBlock.getITCC();
+ MCRegister CondReg = CC == ARMCC::AL ? ARM::NoRegister : ARM::CPSR;
+ Inst.addOperand(MCOperand::createImm(CC));
+ Inst.addOperand(MCOperand::createReg(CondReg));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const MCDisassembler *Decoder) {
@@ -1050,6 +1067,40 @@ static DecodeStatus DecodeCopMemInstruction(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodePredicateOperand(Inst, pred, Address, Decoder)))
return MCDisassembler::Fail;
break;
+ case ARM::t2LDC2L_OFFSET:
+ case ARM::t2LDC2L_OPTION:
+ case ARM::t2LDC2L_POST:
+ case ARM::t2LDC2L_PRE:
+ case ARM::t2LDC2_OFFSET:
+ case ARM::t2LDC2_OPTION:
+ case ARM::t2LDC2_POST:
+ case ARM::t2LDC2_PRE:
+ case ARM::t2LDCL_OFFSET:
+ case ARM::t2LDCL_OPTION:
+ case ARM::t2LDCL_POST:
+ case ARM::t2LDCL_PRE:
+ case ARM::t2LDC_OFFSET:
+ case ARM::t2LDC_OPTION:
+ case ARM::t2LDC_POST:
+ case ARM::t2LDC_PRE:
+ case ARM::t2STC2L_OFFSET:
+ case ARM::t2STC2L_OPTION:
+ case ARM::t2STC2L_POST:
+ case ARM::t2STC2L_PRE:
+ case ARM::t2STC2_OFFSET:
+ case ARM::t2STC2_OPTION:
+ case ARM::t2STC2_POST:
+ case ARM::t2STC2_PRE:
+ case ARM::t2STCL_OFFSET:
+ case ARM::t2STCL_OPTION:
+ case ARM::t2STCL_POST:
+ case ARM::t2STCL_PRE:
+ case ARM::t2STC_OFFSET:
+ case ARM::t2STC_OPTION:
+ case ARM::t2STC_POST:
+ case ARM::t2STC_PRE:
+ DecodePredicateOperand(Inst, Decoder);
+ break;
default:
break;
}
@@ -1217,6 +1268,8 @@ static DecodeStatus DecodeTSBInstruction(MCInst &Inst, unsigned Insn,
// the only available operand), but LLVM expects the instruction to have one
// operand, so we need to add the csync when decoding.
Inst.addOperand(MCOperand::createImm(ARM_TSB::CSYNC));
+ if (Inst.getOpcode() == ARM::t2TSB)
+ DecodePredicateOperand(Inst, Decoder);
return MCDisassembler::Success;
}
@@ -1650,6 +1703,7 @@ static DecodeStatus DecodeT2CPSInstruction(MCInst &Inst, unsigned Insn,
if(imm > 4) return MCDisassembler::Fail;
Inst.setOpcode(ARM::t2HINT);
Inst.addOperand(MCOperand::createImm(imm));
+ DecodePredicateOperand(Inst, Decoder);
}
return S;
@@ -1675,6 +1729,7 @@ DecodeT2HintSpaceInstruction(MCInst &Inst, unsigned Insn, uint64_t Address,
Inst.setOpcode(Opcode);
if (Opcode == ARM::t2HINT) {
Inst.addOperand(MCOperand::createImm(imm));
+ DecodePredicateOperand(Inst, Decoder);
}
return MCDisassembler::Success;
@@ -1702,6 +1757,7 @@ static DecodeStatus DecodeT2MOVTWInstruction(MCInst &Inst, unsigned Insn,
if (!tryAddingSymbolicOperand(Address, imm, false, 4, Inst, Decoder))
Inst.addOperand(MCOperand::createImm(imm));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -1906,6 +1962,7 @@ static DecodeStatus DecodeT2BInstruction(MCInst &Inst, unsigned Insn,
true, 4, Inst, Decoder))
Inst.addOperand(MCOperand::createImm(imm32));
+ DecodePredicateOperand(Inst, Decoder);
return Status;
}
@@ -2231,6 +2288,7 @@ static DecodeStatus DecodeVLDInstruction(MCInst &Inst, unsigned Insn,
break;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2502,6 +2560,7 @@ static DecodeStatus DecodeVSTInstruction(MCInst &Inst, unsigned Insn,
break;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2605,6 +2664,7 @@ static DecodeStatus DecodeVLD1DupInstruction(MCInst &Inst, unsigned Insn,
!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
return MCDisassembler::Fail;
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2654,6 +2714,7 @@ static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Insn,
return MCDisassembler::Fail;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2690,6 +2751,7 @@ static DecodeStatus DecodeVLD3DupInstruction(MCInst &Inst, unsigned Insn,
return MCDisassembler::Fail;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2743,6 +2805,7 @@ static DecodeStatus DecodeVLD4DupInstruction(MCInst &Inst, unsigned Insn,
return MCDisassembler::Fail;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2789,6 +2852,7 @@ static DecodeStatus DecodeVMOVModImmInstruction(MCInst &Inst, unsigned Insn,
break;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2861,6 +2925,7 @@ static DecodeStatus DecodeVSHLMaxInstruction(MCInst &Inst, unsigned Insn,
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(8 << size));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2926,6 +2991,7 @@ static DecodeStatus DecodeTBLInstruction(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodeDPRRegisterClass(Inst, Rm, Address, Decoder)))
return MCDisassembler::Fail;
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2951,6 +3017,7 @@ static DecodeStatus DecodeThumbAddSpecialReg(MCInst &Inst, uint16_t Insn,
}
Inst.addOperand(MCOperand::createImm(imm));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -3113,6 +3180,7 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
}
Inst.addOperand(MCOperand::createImm(imm));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -3197,6 +3265,7 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder)))
return MCDisassemb...
[truncated]
|

Most predicable Thumb instructions do not encode the predicate operand, but rather take it from an enclosing IT block.
Add
bits<0> pto the encoding of these instructions to make the predicate operand decodable by the generated code.The previous approach was to analyze an instruction after it has been decoded and add missing predicate operand if necessary. The post-decoding pass is still required to check predicate applicability and advance IT block state, but it no longer modifies a decoded instruction.
Some of the custom decoder methods have become redundant and can be removed in the future, delegating the decoding task to TableGen-erated decoder.