diff options
author | Sergei Barannikov <barannikov88@gmail.com> | 2025-09-02 10:26:16 +0300 |
---|---|---|
committer | Sergei Barannikov <barannikov88@gmail.com> | 2025-09-04 18:34:46 +0300 |
commit | b45bd86fad339ca32cd93d07e867c0fb23524522 (patch) | |
tree | 5e52448ec403649a2fc3977b6bef5cf890e6437c | |
parent | 1cb47c19f8eca4badd8fb5e1a1b1cf4aaab607b8 (diff) | |
download | llvm-users/s.barannikov/decoder-operands-7-arm.zip llvm-users/s.barannikov/decoder-operands-7-arm.tar.gz llvm-users/s.barannikov/decoder-operands-7-arm.tar.bz2 |
[ARM] Remove most post-decoding instruction adjustmentsusers/s.barannikov/decoder-operands-7-arm
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrCDE.td | 4 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrFormats.td | 9 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrMVE.td | 1 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb.td | 10 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb2.td | 23 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/CMakeLists.txt | 3 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 364 | ||||
-rw-r--r-- | llvm/test/MC/Disassembler/ARM/arm-tests.txt | 2 |
8 files changed, 267 insertions, 149 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrCDE.td b/llvm/lib/Target/ARM/ARMInstrCDE.td index 54e27a6..5d4e3ac 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; @@ -268,6 +271,7 @@ class CDE_Vec_Instr<bit acc, dag oops, dag iops, string asm, string cstr, !con(iops, (ins vpred:$vp)), asm, !strconcat(cstr, vpred.vpred_constraint)>, CDE_RequiresQReg { + bits<0> vp; } diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index e50740f..dc815e1 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -1219,6 +1219,8 @@ class Thumb1sI<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> 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); @@ -1243,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); @@ -1341,7 +1344,8 @@ class T1Misc<bits<7> opcode> : Encoding16 { 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> { + : 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); @@ -1360,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; @@ -2220,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); @@ -2233,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/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td index 9dffd94..e244134 100644 --- a/llvm/lib/Target/ARM/ARMInstrMVE.td +++ b/llvm/lib/Target/ARM/ARMInstrMVE.td @@ -409,6 +409,7 @@ class MVE_p<dag oops, dag iops, InstrItinClass itin, string iname, !strconcat(iname, "${vp}", !if(!eq(suffix, ""), "", !strconcat(".", suffix))), ops, !strconcat(cstr, vpred.vpred_constraint), vecsize, pattern> { + bits<0> vp; let Inst{31-29} = 0b111; let Inst{27-26} = 0b11; } diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index 0c5ea3e..bc1b34c 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 c00d616..b5485c5 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; @@ -5488,6 +5498,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; @@ -5516,6 +5527,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; @@ -5547,6 +5559,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; @@ -5558,6 +5571,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; @@ -5570,6 +5584,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; @@ -5810,6 +5825,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; @@ -5825,6 +5841,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 fa778ca..a39629b 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 41d554f..a7aaf46 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 UpdateThumbVFPPredicate(DecodeStatus &, MCInst&) const; @@ -195,6 +193,10 @@ static DecodeStatus DecodeT2AddrModeImm8(MCInst &Inst, unsigned Val, static DecodeStatus DecodeT2AddrModeImm12(MCInst &Inst, unsigned Val, uint64_t Address, const MCDisassembler *Decoder); +static DecodeStatus DecodeVpredROperand(MCInst &Inst, + const MCDisassembler *Decoder); +static DecodeStatus DecodeVpredNOperand(MCInst &Inst, + const MCDisassembler *Decoder); typedef DecodeStatus OperandDecoder(MCInst &Inst, unsigned Val, uint64_t Address, @@ -613,6 +615,33 @@ static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val, return S; } +static DecodeStatus DecodePredicateOperand(MCInst &Inst, + const MCDisassembler *Decoder) { + const auto *D = static_cast<const ARMDisassembler *>(Decoder); + + if (!D->getSubtargetInfo().hasFeature(ARM::ModeThumb)) { + // Add a fake predicate operand, because we share these instruction + // definitions with Thumb2 where these instructions are predicable. + Inst.addOperand(MCOperand::createImm(ARMCC::AL)); + Inst.addOperand(MCOperand::createReg(ARM::NoRegister)); + return MCDisassembler::Success; + } + + ARMCC::CondCodes CC = ARMCC::AL; + if (D->ITBlock.instrInITBlock()) + CC = static_cast<ARMCC::CondCodes>(D->ITBlock.getITCC()); + + Inst.addOperand(MCOperand::createImm(CC)); + Inst.addOperand( + MCOperand::createReg(CC == ARMCC::AL ? ARM::NoRegister : ARM::CPSR)); + + const MCInstrDesc &MCID = D->MCII->get(Inst.getOpcode()); + if (CC != ARMCC::AL && !MCID.isPredicable()) + return MCDisassembler::SoftFail; + + return MCDisassembler::Success; +} + static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val, uint64_t Address, const MCDisassembler *Decoder) { @@ -623,6 +652,14 @@ static DecodeStatus DecodeCCOutOperand(MCInst &Inst, unsigned Val, return MCDisassembler::Success; } +static DecodeStatus DecodeCCOutOperand(MCInst &Inst, + const MCDisassembler *Decoder) { + const auto *D = static_cast<const ARMDisassembler *>(Decoder); + Inst.addOperand(MCOperand::createReg( + D->ITBlock.instrInITBlock() ? ARM::NoRegister : ARM::CPSR)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Val, uint64_t Address, const MCDisassembler *Decoder) { @@ -997,7 +1034,59 @@ 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; + case ARM::LDC2L_OFFSET: + case ARM::LDC2L_OPTION: + case ARM::LDC2L_POST: + case ARM::LDC2L_PRE: + case ARM::LDC2_OFFSET: + case ARM::LDC2_OPTION: + case ARM::LDC2_POST: + case ARM::LDC2_PRE: + case ARM::STC2L_OFFSET: + case ARM::STC2L_OPTION: + case ARM::STC2L_POST: + case ARM::STC2L_PRE: + case ARM::STC2_OFFSET: + case ARM::STC2_OPTION: + case ARM::STC2_POST: + case ARM::STC2_PRE: + break; default: + llvm_unreachable("Unexpected opcode"); break; } @@ -1164,6 +1253,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; } @@ -1365,24 +1456,6 @@ static DecodeStatus DecodeRFEInstruction(MCInst &Inst, unsigned Insn, DecodeStatus S = MCDisassembler::Success; unsigned Rn = fieldFromInstruction(Insn, 16, 4); - unsigned mode = fieldFromInstruction(Insn, 23, 2); - - switch (mode) { - case 0: - mode = ARM_AM::da; - break; - case 1: - mode = ARM_AM::ia; - break; - case 2: - mode = ARM_AM::db; - break; - case 3: - mode = ARM_AM::ib; - break; - } - - Inst.addOperand(MCOperand::createImm(mode)); if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; @@ -1615,6 +1688,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; @@ -1640,6 +1714,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; @@ -1667,6 +1742,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; } @@ -1871,6 +1947,7 @@ static DecodeStatus DecodeT2BInstruction(MCInst &Inst, unsigned Insn, true, 4, Inst, Decoder)) Inst.addOperand(MCOperand::createImm(imm32)); + DecodePredicateOperand(Inst, Decoder); return Status; } @@ -2196,6 +2273,7 @@ static DecodeStatus DecodeVLDInstruction(MCInst &Inst, unsigned Insn, break; } + DecodePredicateOperand(Inst, Decoder); return S; } @@ -2522,6 +2600,7 @@ static DecodeStatus DecodeVSTInstruction(MCInst &Inst, unsigned Insn, break; } + DecodePredicateOperand(Inst, Decoder); return S; } @@ -2570,6 +2649,7 @@ static DecodeStatus DecodeVLD1DupInstruction(MCInst &Inst, unsigned Insn, !Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder))) return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); return S; } @@ -2619,6 +2699,7 @@ static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Insn, return MCDisassembler::Fail; } + DecodePredicateOperand(Inst, Decoder); return S; } @@ -2655,6 +2736,7 @@ static DecodeStatus DecodeVLD3DupInstruction(MCInst &Inst, unsigned Insn, return MCDisassembler::Fail; } + DecodePredicateOperand(Inst, Decoder); return S; } @@ -2708,6 +2790,7 @@ static DecodeStatus DecodeVLD4DupInstruction(MCInst &Inst, unsigned Insn, return MCDisassembler::Fail; } + DecodePredicateOperand(Inst, Decoder); return S; } @@ -2754,6 +2837,7 @@ static DecodeStatus DecodeVMOVModImmInstruction(MCInst &Inst, unsigned Insn, break; } + DecodePredicateOperand(Inst, Decoder); return S; } @@ -2779,9 +2863,11 @@ static DecodeStatus DecodeMVEModImmInstruction(MCInst &Inst, unsigned Insn, Inst.addOperand(MCOperand::createImm(imm)); + // vpred_r operand. Inst.addOperand(MCOperand::createImm(ARMVCC::None)); Inst.addOperand(MCOperand::createReg(0)); Inst.addOperand(MCOperand::createImm(0)); + DecodeMQPRRegisterClass(Inst, Qd, Address, Decoder); return S; } @@ -2807,8 +2893,8 @@ static DecodeStatus DecodeMVEVADCInstruction(MCInst &Inst, unsigned Insn, return MCDisassembler::Fail; if (!fieldFromInstruction(Insn, 12, 1)) // I bit clear => need input FPSCR Inst.addOperand(MCOperand::createReg(ARM::FPSCR_NZCV)); - Inst.addOperand(MCOperand::createImm(Qd)); + DecodeVpredROperand(Inst, Decoder); return S; } @@ -2829,6 +2915,7 @@ static DecodeStatus DecodeVSHLMaxInstruction(MCInst &Inst, unsigned Insn, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(8 << size)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -2894,6 +2981,7 @@ static DecodeStatus DecodeTBLInstruction(MCInst &Inst, unsigned Insn, if (!Check(S, DecodeDPRRegisterClass(Inst, Rm, Address, Decoder))) return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); return S; } @@ -2919,6 +3007,7 @@ static DecodeStatus DecodeThumbAddSpecialReg(MCInst &Inst, uint16_t Insn, } Inst.addOperand(MCOperand::createImm(imm)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -3111,6 +3200,7 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn, if (!Check(S, DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder))) return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); return S; } @@ -3196,6 +3286,8 @@ static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn, if (!Check(S, DecodeT2AddrModeImm8(Inst, imm, Address, Decoder))) return MCDisassembler::Fail; + + DecodePredicateOperand(Inst, Decoder); return S; } @@ -3277,6 +3369,8 @@ static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn, if (!Check(S, DecodeT2AddrModeImm12(Inst, imm, Address, Decoder))) return MCDisassembler::Fail; + + DecodePredicateOperand(Inst, Decoder); return S; } @@ -3316,6 +3410,8 @@ static DecodeStatus DecodeT2LoadT(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; if (!Check(S, DecodeT2AddrModeImm8(Inst, imm, Address, Decoder))) return MCDisassembler::Fail; + + DecodePredicateOperand(Inst, Decoder); return S; } @@ -3370,6 +3466,7 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn, } Inst.addOperand(MCOperand::createImm(imm)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -3619,6 +3716,7 @@ static DecodeStatus DecodeT2LdStPre(MCInst &Inst, unsigned Insn, if (!Check(S, DecodeT2AddrModeImm8(Inst, addr, Address, Decoder))) return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); return S; } @@ -3658,6 +3756,7 @@ static DecodeStatus DecodeThumbAddSPImm(MCInst &Inst, uint16_t Insn, Inst.addOperand(MCOperand::createReg(ARM::SP)); Inst.addOperand(MCOperand::createImm(imm)); + DecodePredicateOperand(Inst, Decoder); return MCDisassembler::Success; } @@ -3684,6 +3783,7 @@ static DecodeStatus DecodeThumbAddSPReg(MCInst &Inst, uint16_t Insn, return MCDisassembler::Fail; } + DecodePredicateOperand(Inst, Decoder); return S; } @@ -3808,6 +3908,7 @@ static DecodeStatus DecodeThumbTableBranch(MCInst &Inst, unsigned Insn, return MCDisassembler::Fail; if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder))) return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4273,6 +4374,7 @@ static DecodeStatus DecodeVLD1LN(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(index)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4338,6 +4440,7 @@ static DecodeStatus DecodeVST1LN(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(index)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4405,6 +4508,7 @@ static DecodeStatus DecodeVLD2LN(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(index)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4468,6 +4572,7 @@ static DecodeStatus DecodeVST2LN(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(index)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4538,6 +4643,7 @@ static DecodeStatus DecodeVLD3LN(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(index)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4601,6 +4707,7 @@ static DecodeStatus DecodeVST3LN(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(index)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4682,6 +4789,7 @@ static DecodeStatus DecodeVLD4LN(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(index)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4754,6 +4862,7 @@ static DecodeStatus DecodeVST4LN(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(index)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4872,6 +4981,7 @@ static DecodeStatus DecodeT2LDRDPreInstruction(MCInst &Inst, unsigned Insn, if (!Check(S, DecodeT2AddrModeImm8s4(Inst, addr, Address, Decoder))) return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4907,6 +5017,7 @@ static DecodeStatus DecodeT2STRDPreInstruction(MCInst &Inst, unsigned Insn, if (!Check(S, DecodeT2AddrModeImm8s4(Inst, addr, Address, Decoder))) return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); return S; } @@ -4933,6 +5044,7 @@ static DecodeStatus DecodeT2Adr(MCInst &Inst, uint32_t Insn, uint64_t Address, Val = -Val; } Inst.addOperand(MCOperand::createImm(Val)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -5030,6 +5142,7 @@ static DecodeStatus DecodeVCVTD(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(64 - imm)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -5089,6 +5202,7 @@ static DecodeStatus DecodeVCVTQ(MCInst &Inst, unsigned Insn, uint64_t Address, return MCDisassembler::Fail; Inst.addOperand(MCOperand::createImm(64 - imm)); + DecodePredicateOperand(Inst, Decoder); return S; } @@ -5294,8 +5408,10 @@ static DecodeStatus DecodeLOLoop(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder) { DecodeStatus S = MCDisassembler::Success; - if (Inst.getOpcode() == ARM::MVE_LCTP) + if (Inst.getOpcode() == ARM::MVE_LCTP) { + DecodePredicateOperand(Inst, Decoder); return S; + } unsigned Imm = fieldFromInstruction(Insn, 11, 1) | fieldFromInstruction(Insn, 1, 10) << 1; @@ -5340,6 +5456,7 @@ static DecodeStatus DecodeLOLoop(MCInst &Inst, unsigned Insn, uint64_t Address, Check(S, MCDisassembler::SoftFail); // an SBZ bit is wrong: soft fail Inst.setOpcode(ARM::MVE_LCTP); + DecodePredicateOperand(Inst, Decoder); } else { Inst.addOperand(MCOperand::createReg(ARM::LR)); if (!Check(S, DecoderGPRRegisterClass(Inst, @@ -5516,27 +5633,55 @@ static DecodeStatus DecodeVPTMaskOperand(MCInst &Inst, unsigned Val, return S; } -static DecodeStatus DecodeVpredROperand(MCInst &Inst, unsigned RegNo, - uint64_t Address, +static DecodeStatus DecodeVpredROperand(MCInst &Inst, const MCDisassembler *Decoder) { - // The vpred_r operand type includes an MQPR register field derived - // from the encoding. But we don't actually want to add an operand - // to the MCInst at this stage, because AddThumbPredicate will do it - // later, and will infer the register number from the TIED_TO - // constraint. So this is a deliberately empty decoder method that - // will inhibit the auto-generated disassembly code from adding an - // operand at all. + const auto *D = static_cast<const ARMDisassembler *>(Decoder); + + ARMVCC::VPTCodes VCC = ARMVCC::None; + if (D->VPTBlock.instrInVPTBlock()) + VCC = static_cast<ARMVCC::VPTCodes>(D->VPTBlock.getVPTPred()); + + const MCInstrDesc &MCID = D->MCII->get(Inst.getOpcode()); + unsigned VCCPos; + for (VCCPos = 0; VCCPos != MCID.NumOperands; ++VCCPos) { + if (MCID.operands()[VCCPos].OperandType == ARM::OPERAND_VPRED_R) + break; + } + assert(VCCPos != MCID.NumOperands); + + Inst.addOperand(MCOperand::createImm(VCC)); + Inst.addOperand( + MCOperand::createReg(VCC == ARMVCC::None ? ARM::NoRegister : ARM::P0)); + Inst.addOperand(MCOperand::createReg(ARM::NoRegister)); + + 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. + Inst.addOperand(MCOperand(Inst.getOperand(TiedOp))); + + if (D->ITBlock.instrInITBlock()) + return MCDisassembler::SoftFail; + 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.) +static DecodeStatus DecodeVpredNOperand(MCInst &Inst, + const MCDisassembler *Decoder) { + const auto *D = static_cast<const ARMDisassembler *>(Decoder); + + ARMVCC::VPTCodes VCC = ARMVCC::None; + if (D->VPTBlock.instrInVPTBlock()) + VCC = static_cast<ARMVCC::VPTCodes>(D->VPTBlock.getVPTPred()); + + Inst.addOperand(MCOperand::createImm(VCC)); + Inst.addOperand( + MCOperand::createReg(VCC == ARMVCC::None ? ARM::NoRegister : ARM::P0)); + Inst.addOperand(MCOperand::createReg(ARM::NoRegister)); + + if (D->ITBlock.instrInITBlock()) + return MCDisassembler::SoftFail; + return MCDisassembler::Success; } @@ -5718,6 +5863,7 @@ DecodeMVE_MEM_pre(MCInst &Inst, unsigned Val, uint64_t Address, if (!Check(S, AddrDecoder(Inst, addr, Address, Decoder))) return MCDisassembler::Fail; + DecodeVpredNOperand(Inst, Decoder); return S; } @@ -5796,6 +5942,7 @@ static DecodeStatus DecodeMVEVMOVQtoDReg(MCInst &Inst, unsigned Insn, if (!Check(S, DecodeMVEPairVectorIndexOperand<0>(Inst, index, Address, Decoder))) return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); return S; } @@ -5822,6 +5969,7 @@ static DecodeStatus DecodeMVEVMOVDRegtoQ(MCInst &Inst, unsigned Insn, if (!Check(S, DecodeMVEPairVectorIndexOperand<0>(Inst, index, Address, Decoder))) return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); return S; } @@ -5867,6 +6015,8 @@ DecodeMVEOverlappingLongShift(MCInst &Inst, unsigned Insn, uint64_t Address, if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder))) return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); + if (fieldFromInstruction (Insn, 6, 3) != 4) return MCDisassembler::SoftFail; @@ -5902,6 +6052,7 @@ DecodeMVEOverlappingLongShift(MCInst &Inst, unsigned Insn, uint64_t Address, Inst.addOperand(MCOperand::createImm(Saturate)); } + DecodePredicateOperand(Inst, Decoder); return S; } @@ -5921,7 +6072,8 @@ static DecodeStatus DecodeMVEVCVTt1fp(MCInst &Inst, unsigned Insn, return MCDisassembler::Fail; if (!Check(S, DecodeVCVTImmOperand(Inst, imm6, Address, Decoder))) return MCDisassembler::Fail; - + if (!Check(S, DecodeVpredROperand(Inst, Decoder))) + return MCDisassembler::Fail; return S; } @@ -5956,6 +6108,7 @@ static DecodeStatus DecodeMVEVCMP(MCInst &Inst, unsigned Insn, uint64_t Address, if (!Check(S, predicate_decoder(Inst, fc, Address, Decoder))) return MCDisassembler::Fail; + // vpred_n operand. Inst.addOperand(MCOperand::createImm(ARMVCC::None)); Inst.addOperand(MCOperand::createReg(0)); Inst.addOperand(MCOperand::createImm(0)); @@ -5970,6 +6123,7 @@ static DecodeStatus DecodeMveVCTP(MCInst &Inst, unsigned Insn, uint64_t Address, unsigned Rn = fieldFromInstruction(Insn, 16, 4); if (!Check(S, DecoderGPRRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; + DecodeVpredNOperand(Inst, Decoder); return S; } @@ -5979,6 +6133,7 @@ static DecodeStatus DecodeMVEVPNOT(MCInst &Inst, unsigned Insn, DecodeStatus S = MCDisassembler::Success; Inst.addOperand(MCOperand::createReg(ARM::VPR)); Inst.addOperand(MCOperand::createReg(ARM::VPR)); + DecodeVpredNOperand(Inst, Decoder); return S; } @@ -6006,10 +6161,12 @@ static DecodeStatus DecodeT2AddSubSPImm(MCInst &Inst, unsigned Insn, if (TypeT3) { Inst.setOpcode(sign1 ? ARM::t2SUBspImm12 : ARM::t2ADDspImm12); Inst.addOperand(MCOperand::createImm(Imm12)); // zext imm12 + DecodePredicateOperand(Inst, Decoder); } else { Inst.setOpcode(sign1 ? ARM::t2SUBspImm : ARM::t2ADDspImm); if (!Check(DS, DecodeT2SOImm(Inst, Imm12, Address, Decoder))) // imm12 return MCDisassembler::Fail; + DecodePredicateOperand(Inst, Decoder); if (!Check(DS, DecodeCCOutOperand(Inst, S, Address, Decoder))) // cc_out return MCDisassembler::Fail; } @@ -6103,9 +6260,21 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address, raw_ostream &CS) const { + DecodeStatus S; if (STI.hasFeature(ARM::ModeThumb)) - return getThumbInstruction(MI, Size, Bytes, Address, CS); - return getARMInstruction(MI, Size, Bytes, Address, CS); + S = getThumbInstruction(MI, Size, Bytes, Address, CS); + else + S = getARMInstruction(MI, Size, Bytes, Address, CS); + if (S != DecodeStatus::Fail) { + const MCInstrDesc &MCID = MCII->get(MI.getOpcode()); + if (!MCID.isVariadic() && MI.getNumOperands() != MCID.getNumOperands()) { + reportFatalInternalError(MCII->getName(MI.getOpcode()) + ": expected " + + Twine(MCID.getNumOperands()) + + " operands, got " + Twine(MI.getNumOperands()) + + "\n"); + } + } + return S; } DecodeStatus ARMDisassembler::getARMInstruction(MCInst &MI, uint64_t &Size, @@ -6136,26 +6305,17 @@ DecodeStatus ARMDisassembler::getARMInstruction(MCInst &MI, uint64_t &Size, return checkDecodedInstruction(MI, Size, Address, CS, Insn, Result); } - struct DecodeTable { - const uint8_t *P; - bool DecodePred; + const uint8_t *Tables[] = { + DecoderTableVFP32, DecoderTableVFPV832, + DecoderTableNEONData32, DecoderTableNEONLoadStore32, + DecoderTableNEONDup32, DecoderTablev8NEON32, + DecoderTablev8Crypto32, }; - const DecodeTable Tables[] = { - {DecoderTableVFP32, false}, {DecoderTableVFPV832, false}, - {DecoderTableNEONData32, true}, {DecoderTableNEONLoadStore32, true}, - {DecoderTableNEONDup32, true}, {DecoderTablev8NEON32, false}, - {DecoderTablev8Crypto32, false}, - }; - - for (auto Table : Tables) { - Result = decodeInstruction(Table.P, MI, Insn, Address, this, STI); + for (const uint8_t *Table : Tables) { + Result = decodeInstruction(Table, MI, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; - // Add a fake predicate operand, because we share these instruction - // definitions with Thumb2 where these instructions are predicable. - if (Table.DecodePred && !DecodePredicateOperand(MI, 0xE, Address, this)) - return MCDisassembler::Fail; return Result; } } @@ -6171,28 +6331,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; - } - } - - MI.insert(I, MCOperand::createReg(InITBlock ? ARM::NoRegister : ARM::CPSR)); -} - bool ARMDisassembler::isVectorPredicable(const MCInst &MI) const { const MCInstrDesc &MCID = MCII->get(MI.getOpcode()); for (unsigned i = 0; i < MCID.NumOperands; ++i) { @@ -6259,64 +6397,10 @@ ARMDisassembler::AddThumbPredicate(MCInst &MI) const { (isVectorPredicable(MI) && ITBlock.instrInITBlock())) S = SoftFail; - // If we're in an IT/VPT block, base the predicate on that. Otherwise, - // assume a predicate of AL. - unsigned CC = ARMCC::AL; - unsigned VCC = ARMVCC::None; - if (ITBlock.instrInITBlock()) { - CC = ITBlock.getITCC(); + if (ITBlock.instrInITBlock()) ITBlock.advanceITState(); - } else if (VPTBlock.instrInVPTBlock()) { - VCC = VPTBlock.getVPTPred(); + else if (VPTBlock.instrInVPTBlock()) VPTBlock.advanceVPTState(); - } - - const MCInstrDesc &MCID = MCII->get(MI.getOpcode()); - - MCInst::iterator CCI = MI.begin(); - for (unsigned i = 0; i < MCID.NumOperands; ++i, ++CCI) { - if (MCID.operands()[i].isPredicate() || CCI == MI.end()) - break; - } - - if (MCID.isPredicable()) { - CCI = MI.insert(CCI, MCOperand::createImm(CC)); - ++CCI; - if (CC == ARMCC::AL) - MI.insert(CCI, MCOperand::createReg(ARM::NoRegister)); - else - MI.insert(CCI, MCOperand::createReg(ARM::CPSR)); - } else if (CC != ARMCC::AL) { - Check(S, SoftFail); - } - - MCInst::iterator VCCI = MI.begin(); - unsigned VCCPos; - for (VCCPos = 0; VCCPos < MCID.NumOperands; ++VCCPos, ++VCCI) { - if (ARM::isVpred(MCID.operands()[VCCPos].OperandType) || VCCI == MI.end()) - break; - } - - if (isVectorPredicable(MI)) { - VCCI = MI.insert(VCCI, MCOperand::createImm(VCC)); - ++VCCI; - if (VCC == ARMVCC::None) - VCCI = MI.insert(VCCI, MCOperand::createReg(0)); - else - VCCI = MI.insert(VCCI, MCOperand::createReg(ARM::P0)); - ++VCCI; - VCCI = MI.insert(VCCI, MCOperand::createReg(0)); - ++VCCI; - 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. - MI.insert(VCCI, MCOperand(MI.getOperand(TiedOp))); - } - } else if (VCC != ARMVCC::None) { - Check(S, SoftFail); - } return S; } @@ -6387,9 +6471,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; } @@ -6455,9 +6537,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; } diff --git a/llvm/test/MC/Disassembler/ARM/arm-tests.txt b/llvm/test/MC/Disassembler/ARM/arm-tests.txt index 008bb11..a1016cd 100644 --- a/llvm/test/MC/Disassembler/ARM/arm-tests.txt +++ b/llvm/test/MC/Disassembler/ARM/arm-tests.txt @@ -354,7 +354,7 @@ # CHECK: strheq r0, [r0, -r0] 0xb0 0x00 0x00 0x01 -# CHECK: rfedb #4! +# CHECK: rfedb r2! 0x14 0x0 0x32 0xf9 # CHECK: stc2l p0, c0, [r2], #-96 |