[llvm] [ARM] Remove most post-decoding instruction adjustments (PR #156540)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Sun Sep 21 12:54:28 PDT 2025
https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/156540
>From 2a6e2fa516f8586682350da3a62d6671d299302e Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 21 Sep 2025 01:17:44 +0300
Subject: [PATCH 1/6] [TableGen][Decoder] Always handle `bits<0>`
Previously, `bits<0>` only had effect if `ignore-non-decodable-operands`
wasn't specified. Handle it even if the option wasn't specified. This
should allow for a smoother transition.
---
llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp | 8 ++++++++
llvm/lib/Target/RISCV/RISCVInstrInfoC.td | 5 ++---
llvm/utils/TableGen/Common/InstructionEncoding.cpp | 8 ++++++++
llvm/utils/TableGen/DecoderEmitter.cpp | 2 --
4 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index ff07122b61378..9f070fb2ff3e2 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -206,6 +206,14 @@ static DecodeStatus DecodeSPRegisterClass(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeSPRegisterClass(MCInst &Inst, uint64_t RegNo,
+ uint32_t Address,
+ const MCDisassembler *Decoder) {
+ assert(RegNo == 2);
+ Inst.addOperand(MCOperand::createReg(RISCV::X2));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeGPRX5RegisterClass(MCInst &Inst,
const MCDisassembler *Decoder) {
Inst.addOperand(MCOperand::createReg(RISCV::X5));
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
index 9fc73662d9704..24e7a0ee5a79f 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
@@ -298,7 +298,7 @@ def C_ADDI4SPN : RVInst16CIW<0b000, 0b00, (outs GPRC:$rd),
(ins SP:$rs1, uimm10_lsb00nonzero:$imm),
"c.addi4spn", "$rd, $rs1, $imm">,
Sched<[WriteIALU, ReadIALU]> {
- bits<5> rs1;
+ bits<0> rs1;
let Inst{12-11} = imm{5-4};
let Inst{10-7} = imm{9-6};
let Inst{6} = imm{2};
@@ -404,8 +404,8 @@ def C_ADDI16SP : RVInst16CI<0b011, 0b01, (outs SP:$rd_wb),
"c.addi16sp", "$rd, $imm">,
Sched<[WriteIALU, ReadIALU]> {
let Constraints = "$rd = $rd_wb";
+ let rd = 2;
let Inst{12} = imm{9};
- let Inst{11-7} = 2;
let Inst{6} = imm{4};
let Inst{5} = imm{6};
let Inst{4-3} = imm{8-7};
@@ -965,4 +965,3 @@ let Predicates = [HasStdExtCOrZcd, HasStdExtD] in {
def : CompressPat<(FSD FPR64:$rs2, SPMem:$rs1, uimm9_lsb000:$imm),
(C_FSDSP FPR64:$rs2, SPMem:$rs1, uimm9_lsb000:$imm)>;
} // Predicates = [HasStdExtCOrZcd, HasStdExtD]
-
diff --git a/llvm/utils/TableGen/Common/InstructionEncoding.cpp b/llvm/utils/TableGen/Common/InstructionEncoding.cpp
index 7260ee3d9b534..30bbac463c0f4 100644
--- a/llvm/utils/TableGen/Common/InstructionEncoding.cpp
+++ b/llvm/utils/TableGen/Common/InstructionEncoding.cpp
@@ -316,6 +316,14 @@ static void addOneOperandFields(const Record *EncodingDef,
else
OpInfo.addField(I, J - I, Offset);
}
+
+ if (!OpInfo.InitValue && OpInfo.fields().empty()) {
+ // We found a field in InstructionEncoding record that corresponds to the
+ // named operand, but that field has no constant bits and doesn't contribute
+ // to the Inst field. For now, treat that field as if it didn't exist.
+ // TODO: Remove along with IgnoreNonDecodableOperands.
+ OpInfo.HasNoEncoding = true;
+ }
}
void InstructionEncoding::parseFixedLenOperands(const BitsInit &Bits) {
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index e83df47d541c6..961dc2815f6b9 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -696,8 +696,6 @@ static void emitBinaryParser(raw_ostream &OS, indent Indent,
// Special case for 'bits<0>'.
if (OpInfo.Fields.empty() && !OpInfo.InitValue) {
- if (IgnoreNonDecodableOperands)
- return;
assert(!OpInfo.Decoder.empty());
// The operand has no encoding, so the corresponding argument is omitted.
// This avoids confusion and allows the function to be overloaded if the
>From 98c2be1f7f92fc0df4e030d13248371e308e90ec Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 21 Sep 2025 00:32:02 +0300
Subject: [PATCH 2/6] [ARM] Auto-decode Thumb1 S-bit
---
llvm/lib/Target/ARM/ARMInstrFormats.td | 1 +
.../ARM/Disassembler/ARMDisassembler.cpp | 41 ++++++-------------
2 files changed, 14 insertions(+), 28 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td
index e50740f7d57c5..1ad2485dce17f 100644
--- a/llvm/lib/Target/ARM/ARMInstrFormats.td
+++ b/llvm/lib/Target/ARM/ARMInstrFormats.td
@@ -1219,6 +1219,7 @@ 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;
let OutOperandList = !con(oops, (outs s_cc_out:$s));
let InOperandList = !con(iops, (ins pred:$p));
let AsmString = !strconcat(opc, "${s}${p}", asm);
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 56112112a0293..b25b7e7104f20 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -119,6 +119,8 @@ class VPTStatus {
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 @@ class ARMDisassembler : public MCDisassembler {
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;
@@ -636,6 +634,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) {
@@ -6130,26 +6139,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 +6332,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 +6398,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;
}
>From dd053e6517a4700850051f6ecc31ca429b378102 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 21 Sep 2025 07:56:28 +0300
Subject: [PATCH 3/6] [ARM] Auto-decode vpred_n/vpred_r operands
Make the operands auto-decodable by adding `bits<0>` fields.
---
llvm/lib/Target/ARM/ARMInstrCDE.td | 1 +
llvm/lib/Target/ARM/ARMInstrMVE.td | 1 +
.../ARM/Disassembler/ARMDisassembler.cpp | 99 ++++++++-----------
3 files changed, 45 insertions(+), 56 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMInstrCDE.td b/llvm/lib/Target/ARM/ARMInstrCDE.td
index 54e27a6be5583..f4326de5ed667 100644
--- a/llvm/lib/Target/ARM/ARMInstrCDE.td
+++ b/llvm/lib/Target/ARM/ARMInstrCDE.td
@@ -268,6 +268,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/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td
index 9dffd945d5baa..e24413465799f 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/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index b25b7e7104f20..1f37cf8f5837d 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -645,6 +645,41 @@ static DecodeStatus DecodeCCOutOperand(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeVpredNOperand(MCInst &Inst,
+ const MCDisassembler *Decoder) {
+ const auto *D = static_cast<const ARMDisassembler *>(Decoder);
+ unsigned VCC = D->VPTBlock.getVPTPred();
+ MCRegister CondReg = VCC == ARMVCC::None ? ARM::NoRegister : ARM::P0;
+
+ Inst.addOperand(MCOperand::createImm(VCC)); // $cond
+ Inst.addOperand(MCOperand::createReg(CondReg)); // $cond_reg
+ Inst.addOperand(MCOperand::createReg(ARM::NoRegister)); // $tp_reg
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeVpredROperand(MCInst &Inst,
+ const MCDisassembler *Decoder) {
+ const auto *D = static_cast<const ARMDisassembler *>(Decoder);
+ unsigned VCC = D->VPTBlock.getVPTPred();
+ MCRegister CondReg = VCC == ARMVCC::None ? ARM::NoRegister : ARM::P0;
+
+ Inst.addOperand(MCOperand::createImm(VCC)); // $cond
+ Inst.addOperand(MCOperand::createReg(CondReg)); // $cond_reg
+ Inst.addOperand(MCOperand::createReg(ARM::NoRegister)); // $tp_reg
+
+ const MCInstrDesc &MCID = D->MCII->get(Inst.getOpcode());
+ unsigned InactiveOpIdx = Inst.getNumOperands();
+ int TiedOpIdx = MCID.getOperandConstraint(InactiveOpIdx, MCOI::TIED_TO);
+ assert(TiedOpIdx >= 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(TiedOpIdx))); // $inactive
+
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const MCDisassembler *Decoder) {
@@ -2783,6 +2818,7 @@ static DecodeStatus DecodeMVEModImmInstruction(MCInst &Inst, unsigned Insn,
Inst.addOperand(MCOperand::createImm(imm));
+ Check(S, DecodeVpredROperand(Inst, Decoder));
return S;
}
@@ -2808,6 +2844,7 @@ static DecodeStatus DecodeMVEVADCInstruction(MCInst &Inst, unsigned Insn,
if (!fieldFromInstruction(Insn, 12, 1)) // I bit clear => need input FPSCR
Inst.addOperand(MCOperand::createReg(ARM::FPSCR_NZCV));
+ Check(S, DecodeVpredROperand(Inst, Decoder));
return S;
}
@@ -5472,30 +5509,6 @@ static DecodeStatus DecodeVPTMaskOperand(MCInst &Inst, unsigned Val,
return S;
}
-static DecodeStatus DecodeVpredROperand(MCInst &Inst, unsigned RegNo,
- uint64_t Address,
- 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.
- 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) {
@@ -5674,6 +5687,7 @@ DecodeMVE_MEM_pre(MCInst &Inst, unsigned Val, uint64_t Address,
if (!Check(S, AddrDecoder(Inst, addr, Address, Decoder)))
return MCDisassembler::Fail;
+ Check(S, DecodeVpredNOperand(Inst, Decoder));
return S;
}
@@ -5877,7 +5891,7 @@ static DecodeStatus DecodeMVEVCVTt1fp(MCInst &Inst, unsigned Insn,
return MCDisassembler::Fail;
if (!Check(S, DecodeVCVTImmOperand(Inst, imm6, Address, Decoder)))
return MCDisassembler::Fail;
-
+ Check(S, DecodeVpredROperand(Inst, Decoder));
return S;
}
@@ -5912,6 +5926,7 @@ static DecodeStatus DecodeMVEVCMP(MCInst &Inst, unsigned Insn, uint64_t Address,
if (!Check(S, predicate_decoder(Inst, fc, Address, Decoder)))
return MCDisassembler::Fail;
+ Check(S, DecodeVpredNOperand(Inst, Decoder));
return S;
}
@@ -5922,6 +5937,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;
+ Check(S, DecodeVpredNOperand(Inst, Decoder));
return S;
}
@@ -5931,6 +5947,7 @@ static DecodeStatus DecodeMVEVPNOT(MCInst &Inst, unsigned Insn,
DecodeStatus S = MCDisassembler::Success;
Inst.addOperand(MCOperand::createReg(ARM::VPR));
Inst.addOperand(MCOperand::createReg(ARM::VPR));
+ Check(S, DecodeVpredNOperand(Inst, Decoder));
return S;
}
@@ -6205,15 +6222,13 @@ 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,
+ // If we're in an IT 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();
ITBlock.advanceITState();
} else if (VPTBlock.instrInVPTBlock()) {
- VCC = VPTBlock.getVPTPred();
VPTBlock.advanceVPTState();
}
@@ -6236,34 +6251,6 @@ ARMDisassembler::AddThumbPredicate(MCInst &MI) const {
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;
}
>From 23f77e47ca02a35b20f9214d691b915482ae641a Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 7 Sep 2025 22:29:07 +0300
Subject: [PATCH 4/6] [ARM] Remove most post-decoding instruction adjustments
---
llvm/lib/Target/ARM/ARMInstrCDE.td | 3 +
llvm/lib/Target/ARM/ARMInstrFormats.td | 8 +-
llvm/lib/Target/ARM/ARMInstrThumb.td | 10 ++
llvm/lib/Target/ARM/ARMInstrThumb2.td | 23 ++-
llvm/lib/Target/ARM/CMakeLists.txt | 3 +-
.../ARM/Disassembler/ARMDisassembler.cpp | 156 ++++++++++++------
6 files changed, 151 insertions(+), 52 deletions(-)
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..dc815e1124fa5 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);
@@ -1342,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);
@@ -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 1f37cf8f5837d..8da25eabc34a1 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -624,6 +624,23 @@ static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val,
return S;
}
+// This overload is called when decoding a `pred` operand that is not encoded
+// into instruction. For Thumb instructions, this means we should get the
+// condition from the enclosing IT block.
+// There are some Thumb instructions equivalent to ARM instructions, but with
+// slightly different encoding. (NEONData, NEONLoadStore).
+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) {
@@ -1054,6 +1071,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;
}
@@ -1221,6 +1272,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;
}
@@ -1654,6 +1707,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;
@@ -1679,6 +1733,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;
@@ -1706,6 +1761,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;
}
@@ -1910,6 +1966,7 @@ static DecodeStatus DecodeT2BInstruction(MCInst &Inst, unsigned Insn,
true, 4, Inst, Decoder))
Inst.addOperand(MCOperand::createImm(imm32));
+ DecodePredicateOperand(Inst, Decoder);
return Status;
}
@@ -2235,6 +2292,7 @@ static DecodeStatus DecodeVLDInstruction(MCInst &Inst, unsigned Insn,
break;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2506,6 +2564,7 @@ static DecodeStatus DecodeVSTInstruction(MCInst &Inst, unsigned Insn,
break;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2609,6 +2668,7 @@ static DecodeStatus DecodeVLD1DupInstruction(MCInst &Inst, unsigned Insn,
!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
return MCDisassembler::Fail;
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2658,6 +2718,7 @@ static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Insn,
return MCDisassembler::Fail;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2694,6 +2755,7 @@ static DecodeStatus DecodeVLD3DupInstruction(MCInst &Inst, unsigned Insn,
return MCDisassembler::Fail;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2747,6 +2809,7 @@ static DecodeStatus DecodeVLD4DupInstruction(MCInst &Inst, unsigned Insn,
return MCDisassembler::Fail;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2793,6 +2856,7 @@ static DecodeStatus DecodeVMOVModImmInstruction(MCInst &Inst, unsigned Insn,
break;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2865,6 +2929,7 @@ static DecodeStatus DecodeVSHLMaxInstruction(MCInst &Inst, unsigned Insn,
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(8 << size));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2930,6 +2995,7 @@ static DecodeStatus DecodeTBLInstruction(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodeDPRRegisterClass(Inst, Rm, Address, Decoder)))
return MCDisassembler::Fail;
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -2955,6 +3021,7 @@ static DecodeStatus DecodeThumbAddSpecialReg(MCInst &Inst, uint16_t Insn,
}
Inst.addOperand(MCOperand::createImm(imm));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -3117,6 +3184,7 @@ static DecodeStatus DecodeT2LoadLabel(MCInst &Inst, unsigned Insn,
}
Inst.addOperand(MCOperand::createImm(imm));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -3201,6 +3269,7 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder)))
return MCDisassembler::Fail;
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -3286,6 +3355,7 @@ static DecodeStatus DecodeT2LoadImm8(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodeT2AddrModeImm8(Inst, imm, Address, Decoder)))
return MCDisassembler::Fail;
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -3394,6 +3464,7 @@ static DecodeStatus DecodeT2LoadImm12(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodeT2AddrModeImm12(Inst, imm, Address, Decoder)))
return MCDisassembler::Fail;
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -3433,6 +3504,7 @@ 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;
}
@@ -3682,6 +3754,7 @@ static DecodeStatus DecodeT2LdStPre(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodeT2AddrModeImm8(Inst, addr, Address, Decoder)))
return MCDisassembler::Fail;
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -3694,6 +3767,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;
}
@@ -3720,6 +3794,7 @@ static DecodeStatus DecodeThumbAddSPReg(MCInst &Inst, uint16_t Insn,
return MCDisassembler::Fail;
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -3844,6 +3919,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;
}
@@ -4309,6 +4385,7 @@ static DecodeStatus DecodeVLD1LN(MCInst &Inst, unsigned Insn, uint64_t Address,
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(index));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -4374,6 +4451,7 @@ static DecodeStatus DecodeVST1LN(MCInst &Inst, unsigned Insn, uint64_t Address,
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(index));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -4441,6 +4519,7 @@ static DecodeStatus DecodeVLD2LN(MCInst &Inst, unsigned Insn, uint64_t Address,
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(index));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -4504,6 +4583,7 @@ static DecodeStatus DecodeVST2LN(MCInst &Inst, unsigned Insn, uint64_t Address,
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(index));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -4574,6 +4654,7 @@ static DecodeStatus DecodeVLD3LN(MCInst &Inst, unsigned Insn, uint64_t Address,
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(index));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -4637,6 +4718,7 @@ static DecodeStatus DecodeVST3LN(MCInst &Inst, unsigned Insn, uint64_t Address,
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(index));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -4718,6 +4800,7 @@ static DecodeStatus DecodeVLD4LN(MCInst &Inst, unsigned Insn, uint64_t Address,
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(index));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -4790,6 +4873,7 @@ static DecodeStatus DecodeVST4LN(MCInst &Inst, unsigned Insn, uint64_t Address,
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(index));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -4908,6 +4992,7 @@ static DecodeStatus DecodeT2LDRDPreInstruction(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodeT2AddrModeImm8s4(Inst, addr, Address, Decoder)))
return MCDisassembler::Fail;
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -4943,6 +5028,7 @@ static DecodeStatus DecodeT2STRDPreInstruction(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodeT2AddrModeImm8s4(Inst, addr, Address, Decoder)))
return MCDisassembler::Fail;
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -4969,6 +5055,7 @@ static DecodeStatus DecodeT2Adr(MCInst &Inst, uint32_t Insn, uint64_t Address,
Val = -Val;
}
Inst.addOperand(MCOperand::createImm(Val));
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -5066,6 +5153,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;
}
@@ -5125,6 +5213,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;
}
@@ -5330,8 +5419,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;
@@ -5376,6 +5467,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,
@@ -5766,6 +5858,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;
}
@@ -5792,6 +5885,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;
}
@@ -5837,6 +5931,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;
@@ -5872,6 +5968,7 @@ DecodeMVEOverlappingLongShift(MCInst &Inst, unsigned Insn, uint64_t Address,
Inst.addOperand(MCOperand::createImm(Saturate));
}
+ DecodePredicateOperand(Inst, Decoder);
return S;
}
@@ -5975,10 +6072,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;
}
@@ -5998,7 +6097,7 @@ static DecodeStatus DecodeLazyLoadStoreMul(MCInst &Inst, unsigned Insn,
if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
return MCDisassembler::Fail;
// An optional predicate, '$p' in the assembly.
- DecodePredicateOperand(Inst, ARMCC::AL, Address, Decoder);
+ DecodePredicateOperand(Inst, Decoder);
// An immediate that represents a floating point registers list. '$regs' in
// the assembly.
Inst.addOperand(MCOperand::createImm(0)); // Arbitrary value, has no effect.
@@ -6119,28 +6218,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 DecodeTable Tables[] = {
- {DecoderTableVFP32, false}, {DecoderTableVFPV832, false},
- {DecoderTableNEONData32, true}, {DecoderTableNEONLoadStore32, true},
- {DecoderTableNEONDup32, false}, {DecoderTablev8NEON32, false},
- {DecoderTablev8Crypto32, false},
+ const uint8_t *Tables[] = {
+ DecoderTableVFP32, DecoderTableVFPV832,
+ DecoderTableNEONData32, DecoderTableNEONLoadStore32,
+ DecoderTableNEONDup32, DecoderTablev8NEON32,
+ DecoderTablev8Crypto32,
};
- 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 && MCII->get(MI.getOpcode()).isPredicable()) {
- MI.addOperand(MCOperand::createImm(ARMCC::AL));
- MI.addOperand(MCOperand::createReg(ARM::NoRegister));
- }
return Result;
}
}
@@ -6222,34 +6310,10 @@ ARMDisassembler::AddThumbPredicate(MCInst &MI) const {
(isVectorPredicable(MI) && ITBlock.instrInITBlock()))
S = SoftFail;
- // If we're in an IT block, base the predicate on that. Otherwise,
- // assume a predicate of AL.
- unsigned CC = ARMCC::AL;
- if (ITBlock.instrInITBlock()) {
- CC = ITBlock.getITCC();
+ if (ITBlock.instrInITBlock())
ITBlock.advanceITState();
- } else if (VPTBlock.instrInVPTBlock()) {
+ 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);
- }
return S;
}
>From 98d7627a04b6106c2cbf0c7695170c92599b8e58 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 21 Sep 2025 08:51:03 +0300
Subject: [PATCH 5/6] [ARM] Auto-decode MVE instructions with VCCR output
operand (NFC)
---
llvm/lib/Target/ARM/ARMInstrMVE.td | 23 +++----
.../ARM/Disassembler/ARMDisassembler.cpp | 62 ++-----------------
2 files changed, 13 insertions(+), 72 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td
index e24413465799f..4608ed5120267 100644
--- a/llvm/lib/Target/ARM/ARMInstrMVE.td
+++ b/llvm/lib/Target/ARM/ARMInstrMVE.td
@@ -4128,11 +4128,12 @@ defm MVE_VMINNMAf16 : MVE_VMINNMA<MVE_v8f16, 0b1>;
// start of MVE compares
+// Base class for comparing two vector registers
class MVE_VCMPqq<string suffix, bit bit_28, bits<2> bits_21_20,
VCMPPredicateOperand predtype, bits<2> vecsize, list<dag> pattern=[]>
: MVE_p<(outs VCCR:$P0), (ins MQPR:$Qn, MQPR:$Qm, predtype:$fc),
NoItinerary, "vcmp", suffix, "$fc, $Qn, $Qm", vpred_n, "", vecsize, pattern> {
- // Base class for comparing two vector registers
+ bits<0> P0;
bits<3> fc;
bits<4> Qn;
bits<4> Qm;
@@ -4152,16 +4153,6 @@ class MVE_VCMPqq<string suffix, bit bit_28, bits<2> bits_21_20,
let Inst{0} = fc{1};
let Constraints = "";
-
- // We need a custom decoder method for these instructions because of
- // the output VCCR operand, which isn't encoded in the instruction
- // bits anywhere (there is only one choice for it) but has to be
- // included in the MC operands so that codegen will be able to track
- // its data flow between instructions, spill/reload it when
- // necessary, etc. There seems to be no way to get the Tablegen
- // decoder to emit an operand that isn't affected by any instruction
- // bit.
- let DecoderMethod = "DecodeMVEVCMP<false," # predtype.DecoderMethod # ">";
let validForTailPredication = 1;
}
@@ -4202,11 +4193,12 @@ def MVE_VCMPs8 : MVE_VCMPqqs<"s8", 0b00>;
def MVE_VCMPs16 : MVE_VCMPqqs<"s16", 0b01>;
def MVE_VCMPs32 : MVE_VCMPqqs<"s32", 0b10>;
+// Base class for comparing a vector register with a scalar
class MVE_VCMPqr<string suffix, bit bit_28, bits<2> bits_21_20,
VCMPPredicateOperand predtype, bits<2> vecsize, list<dag> pattern=[]>
: MVE_p<(outs VCCR:$P0), (ins MQPR:$Qn, GPRwithZR:$Rm, predtype:$fc),
NoItinerary, "vcmp", suffix, "$fc, $Qn, $Rm", vpred_n, "", vecsize, pattern> {
- // Base class for comparing a vector register with a scalar
+ bits<0> P0;
bits<3> fc;
bits<4> Qn;
bits<4> Rm;
@@ -4225,8 +4217,6 @@ class MVE_VCMPqr<string suffix, bit bit_28, bits<2> bits_21_20,
let Inst{3-0} = Rm{3-0};
let Constraints = "";
- // Custom decoder method, for the same reason as MVE_VCMPqq
- let DecoderMethod = "DecodeMVEVCMP<true," # predtype.DecoderMethod # ">";
let validForTailPredication = 1;
}
@@ -5762,6 +5752,7 @@ let isReMaterializable = 1 in
class MVE_VCTPInst<string suffix, bits<2> size, list<dag> pattern=[]>
: MVE_p<(outs VCCR:$P0), (ins rGPR:$Rn), NoItinerary, "vctp", suffix,
"$Rn", vpred_n, "", size, pattern> {
+ bits<0> P0;
bits<4> Rn;
let Inst{28-27} = 0b10;
@@ -5773,7 +5764,6 @@ class MVE_VCTPInst<string suffix, bits<2> size, list<dag> pattern=[]>
let Unpredictable{10-0} = 0b11111111111;
let Constraints = "";
- let DecoderMethod = "DecodeMveVCTP";
let validForTailPredication = 1;
}
@@ -6813,6 +6803,8 @@ let Predicates = [HasMVEFloat] in {
def MVE_VPNOT : MVE_p<(outs VCCR:$P0), (ins VCCR:$P0_in), NoItinerary,
"vpnot", "", "", vpred_n, "", 0b00, []> {
+ bits<0> P0;
+ bits<0> P0_in;
let Inst{31-0} = 0b11111110001100010000111101001101;
let Unpredictable{19-17} = 0b111;
let Unpredictable{12} = 0b1;
@@ -6820,7 +6812,6 @@ def MVE_VPNOT : MVE_p<(outs VCCR:$P0), (ins VCCR:$P0_in), NoItinerary,
let Unpredictable{5} = 0b1;
let Constraints = "";
- let DecoderMethod = "DecodeMVEVPNOT";
}
let Predicates = [HasMVEInt] in {
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 8da25eabc34a1..b622debd3840c 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -602,6 +602,12 @@ static DecodeStatus DecodeMQQQQPRRegisterClass(MCInst &Inst, unsigned RegNo,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeVCCRRegisterClass(MCInst &Inst,
+ const MCDisassembler *Decoder) {
+ Inst.addOperand(MCOperand::createReg(ARM::VPR));
+ return MCDisassembler::Success;
+}
+
// Operand decoding functions.
static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val,
@@ -5992,62 +5998,6 @@ static DecodeStatus DecodeMVEVCVTt1fp(MCInst &Inst, unsigned Insn,
return S;
}
-template <bool scalar, OperandDecoder predicate_decoder>
-static DecodeStatus DecodeMVEVCMP(MCInst &Inst, unsigned Insn, uint64_t Address,
- const MCDisassembler *Decoder) {
- DecodeStatus S = MCDisassembler::Success;
- Inst.addOperand(MCOperand::createReg(ARM::VPR));
- unsigned Qn = fieldFromInstruction(Insn, 17, 3);
- if (!Check(S, DecodeMQPRRegisterClass(Inst, Qn, Address, Decoder)))
- return MCDisassembler::Fail;
-
- unsigned fc;
-
- if (scalar) {
- fc = fieldFromInstruction(Insn, 12, 1) << 2 |
- fieldFromInstruction(Insn, 7, 1) |
- fieldFromInstruction(Insn, 5, 1) << 1;
- unsigned Rm = fieldFromInstruction(Insn, 0, 4);
- if (!Check(S, DecodeGPRwithZRRegisterClass(Inst, Rm, Address, Decoder)))
- return MCDisassembler::Fail;
- } else {
- fc = fieldFromInstruction(Insn, 12, 1) << 2 |
- fieldFromInstruction(Insn, 7, 1) |
- fieldFromInstruction(Insn, 0, 1) << 1;
- unsigned Qm = fieldFromInstruction(Insn, 5, 1) << 4 |
- fieldFromInstruction(Insn, 1, 3);
- if (!Check(S, DecodeMQPRRegisterClass(Inst, Qm, Address, Decoder)))
- return MCDisassembler::Fail;
- }
-
- if (!Check(S, predicate_decoder(Inst, fc, Address, Decoder)))
- return MCDisassembler::Fail;
-
- Check(S, DecodeVpredNOperand(Inst, Decoder));
- return S;
-}
-
-static DecodeStatus DecodeMveVCTP(MCInst &Inst, unsigned Insn, uint64_t Address,
- const MCDisassembler *Decoder) {
- DecodeStatus S = MCDisassembler::Success;
- Inst.addOperand(MCOperand::createReg(ARM::VPR));
- unsigned Rn = fieldFromInstruction(Insn, 16, 4);
- if (!Check(S, DecoderGPRRegisterClass(Inst, Rn, Address, Decoder)))
- return MCDisassembler::Fail;
- Check(S, DecodeVpredNOperand(Inst, Decoder));
- return S;
-}
-
-static DecodeStatus DecodeMVEVPNOT(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- DecodeStatus S = MCDisassembler::Success;
- Inst.addOperand(MCOperand::createReg(ARM::VPR));
- Inst.addOperand(MCOperand::createReg(ARM::VPR));
- Check(S, DecodeVpredNOperand(Inst, Decoder));
- return S;
-}
-
static DecodeStatus DecodeT2AddSubSPImm(MCInst &Inst, unsigned Insn,
uint64_t Address,
const MCDisassembler *Decoder) {
>From 9853907c53b2ecd0f690c80fd0d58f9cd739b9da Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 21 Sep 2025 09:17:36 +0300
Subject: [PATCH 6/6] [ARM] Remove MVE VADC/VSBC custom decoders
---
llvm/lib/Target/ARM/ARMInstrMVE.td | 13 ++++----
.../ARM/Disassembler/ARMDisassembler.cpp | 32 ++++---------------
2 files changed, 13 insertions(+), 32 deletions(-)
diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td
index 4608ed5120267..7a81f84b20e95 100644
--- a/llvm/lib/Target/ARM/ARMInstrMVE.td
+++ b/llvm/lib/Target/ARM/ARMInstrMVE.td
@@ -5027,6 +5027,7 @@ class MVE_VADCSBC<string iname, bit I, bit subtract,
: MVE_qDest_qSrc<iname, "i32", (outs MQPR:$Qd, cl_FPSCR_NZCV:$carryout),
!con((ins MQPR:$Qn, MQPR:$Qm), carryin),
"$Qd, $Qn, $Qm", vpred_r, "", 0b10, pattern> {
+ bits<0> carryout;
bits<4> Qn;
let Inst{28} = subtract;
@@ -5037,16 +5038,16 @@ class MVE_VADCSBC<string iname, bit I, bit subtract,
let Inst{8} = 0b1;
let Inst{7} = Qn{3};
let Inst{0} = 0b0;
-
- // Custom decoder method in order to add the FPSCR operand(s), which
- // Tablegen won't do right
- let DecoderMethod = "DecodeMVEVADCInstruction";
}
-def MVE_VADC : MVE_VADCSBC<"vadc", 0b0, 0b0, (ins cl_FPSCR_NZCV:$carryin)>;
+def MVE_VADC : MVE_VADCSBC<"vadc", 0b0, 0b0, (ins cl_FPSCR_NZCV:$carryin)> {
+ bits<0> carryin;
+}
def MVE_VADCI : MVE_VADCSBC<"vadci", 0b1, 0b0, (ins)>;
-def MVE_VSBC : MVE_VADCSBC<"vsbc", 0b0, 0b1, (ins cl_FPSCR_NZCV:$carryin)>;
+def MVE_VSBC : MVE_VADCSBC<"vsbc", 0b0, 0b1, (ins cl_FPSCR_NZCV:$carryin)> {
+ bits<0> carryin;
+}
def MVE_VSBCI : MVE_VADCSBC<"vsbci", 0b1, 0b1, (ins)>;
class MVE_VQDMULL<string iname, string suffix, bit size, bit T,
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index b622debd3840c..a09c33148dacc 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -608,6 +608,12 @@ static DecodeStatus DecodeVCCRRegisterClass(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus
+Decodecl_FPSCR_NZCVRegisterClass(MCInst &Inst, const MCDisassembler *Decoder) {
+ Inst.addOperand(MCOperand::createReg(ARM::FPSCR_NZCV));
+ return MCDisassembler::Success;
+}
+
// Operand decoding functions.
static DecodeStatus DecodePredicateOperand(MCInst &Inst, unsigned Val,
@@ -2892,32 +2898,6 @@ static DecodeStatus DecodeMVEModImmInstruction(MCInst &Inst, unsigned Insn,
return S;
}
-static DecodeStatus DecodeMVEVADCInstruction(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const MCDisassembler *Decoder) {
- DecodeStatus S = MCDisassembler::Success;
-
- unsigned Qd = fieldFromInstruction(Insn, 13, 3);
- Qd |= fieldFromInstruction(Insn, 22, 1) << 3;
- if (!Check(S, DecodeMQPRRegisterClass(Inst, Qd, Address, Decoder)))
- return MCDisassembler::Fail;
- Inst.addOperand(MCOperand::createReg(ARM::FPSCR_NZCV));
-
- unsigned Qn = fieldFromInstruction(Insn, 17, 3);
- Qn |= fieldFromInstruction(Insn, 7, 1) << 3;
- if (!Check(S, DecodeMQPRRegisterClass(Inst, Qn, Address, Decoder)))
- return MCDisassembler::Fail;
- unsigned Qm = fieldFromInstruction(Insn, 1, 3);
- Qm |= fieldFromInstruction(Insn, 5, 1) << 3;
- if (!Check(S, DecodeMQPRRegisterClass(Inst, Qm, Address, Decoder)))
- return MCDisassembler::Fail;
- if (!fieldFromInstruction(Insn, 12, 1)) // I bit clear => need input FPSCR
- Inst.addOperand(MCOperand::createReg(ARM::FPSCR_NZCV));
-
- Check(S, DecodeVpredROperand(Inst, Decoder));
- return S;
-}
-
static DecodeStatus DecodeVSHLMaxInstruction(MCInst &Inst, unsigned Insn,
uint64_t Address,
const MCDisassembler *Decoder) {
More information about the llvm-commits
mailing list