Skip to content

[RISCV][Disassembler] Use a table to store all the decoder tables and their associated features. NFC #130883

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 13, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 100 additions & 70 deletions llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,29 +620,20 @@ void RISCVDisassembler::addSPOperands(MCInst &MI) const {
MI.insert(MI.begin() + i, MCOperand::createReg(RISCV::X2));
}

#define TRY_TO_DECODE_WITH_ADDITIONAL_OPERATION(FEATURE_CHECKS, DECODER_TABLE, \
DESC, ADDITIONAL_OPERATION) \
do { \
if (FEATURE_CHECKS) { \
LLVM_DEBUG(dbgs() << "Trying " << DESC << " table:\n"); \
DecodeStatus Result = \
decodeInstruction(DECODER_TABLE, MI, Insn, Address, this, STI); \
if (Result != MCDisassembler::Fail) { \
ADDITIONAL_OPERATION; \
return Result; \
} \
} \
} while (false)
#define TRY_TO_DECODE_AND_ADD_SP(FEATURE_CHECKS, DECODER_TABLE, DESC) \
TRY_TO_DECODE_WITH_ADDITIONAL_OPERATION(FEATURE_CHECKS, DECODER_TABLE, DESC, \
addSPOperands(MI))
#define TRY_TO_DECODE(FEATURE_CHECKS, DECODER_TABLE, DESC) \
TRY_TO_DECODE_WITH_ADDITIONAL_OPERATION(FEATURE_CHECKS, DECODER_TABLE, DESC, \
(void)nullptr)
#define TRY_TO_DECODE_FEATURE(FEATURE, DECODER_TABLE, DESC) \
TRY_TO_DECODE(STI.hasFeature(FEATURE), DECODER_TABLE, DESC)
#define TRY_TO_DECODE_FEATURE_ANY(FEATURES, DECODER_TABLE, DESC) \
TRY_TO_DECODE((STI.getFeatureBits() & (FEATURES)).any(), DECODER_TABLE, DESC)
namespace {

struct DecoderListEntry {
const uint8_t *Table;
FeatureBitset ContainedFeatures;
const char *Desc;

bool haveContainedFeatures(const FeatureBitset &ActiveFeatures) const {
return ContainedFeatures.none() ||
(ContainedFeatures & ActiveFeatures).any();
}
};

} // end anonymous namespace

static constexpr FeatureBitset XCVFeatureGroup = {
RISCV::FeatureVendorXCVbitmanip, RISCV::FeatureVendorXCVelw,
Expand Down Expand Up @@ -681,6 +672,31 @@ static constexpr FeatureBitset XTHeadGroup = {
RISCV::FeatureVendorXTHeadMemPair, RISCV::FeatureVendorXTHeadSync,
RISCV::FeatureVendorXTHeadVdot};

static constexpr DecoderListEntry DecoderList32[]{
// Vendor Extensions
{DecoderTableXVentana32,
{RISCV::FeatureVendorXVentanaCondOps},
"XVentanaCondOps"},
{DecoderTableXTHead32, XTHeadGroup, "T-Head extensions"},
{DecoderTableXSfvector32, XSfVectorGroup, "SiFive vector extensions"},
{DecoderTableXSfsystem32, XSfSystemGroup, "SiFive system extensions"},
{DecoderTableXSfcease32, {RISCV::FeatureVendorXSfcease}, "SiFive sf.cease"},
{DecoderTableXmipslsp32, {RISCV::FeatureVendorXMIPSLSP}, "MIPS mips.lsp"},
{DecoderTableXmipscmove32,
{RISCV::FeatureVendorXMIPSCMove},
"MIPS mips.ccmov"},
// Standard Extensions
{DecoderTableXCV32, XCVFeatureGroup, "CORE-V extensions"},
{DecoderTableXqci32, XqciFeatureGroup, "Qualcomm uC Extensions"},
{DecoderTableXRivos32, XRivosFeatureGroup, "Rivos"},
{DecoderTable32, {}, "RISCV32"},
{DecoderTableRV32GPRPair32, {}, "RV32GPRPair (rv32 and GPR pairs)"},
{DecoderTableZfinx32, {}, "Zfinx (Float in Integer)"},
{DecoderTableZdinxRV32GPRPair32,
{},
"ZdinxRV32GPRPair (rv32 and Double in Integer)"},
};

DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
ArrayRef<uint8_t> Bytes,
uint64_t Address,
Expand All @@ -693,37 +709,40 @@ DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,

uint32_t Insn = support::endian::read32le(Bytes.data());

TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXVentanaCondOps,
DecoderTableXVentana32, "XVentanaCondOps");
TRY_TO_DECODE_FEATURE_ANY(XTHeadGroup, DecoderTableXTHead32,
"T-Head extensions");
TRY_TO_DECODE_FEATURE_ANY(XSfVectorGroup, DecoderTableXSfvector32,
"SiFive vector extensions");
TRY_TO_DECODE_FEATURE_ANY(XSfSystemGroup, DecoderTableXSfsystem32,
"SiFive system extensions");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXSfcease, DecoderTableXSfcease32,
"SiFive sf.cease");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXMIPSLSP, DecoderTableXmipslsp32,
"MIPS mips.lsp");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXMIPSCMove,
DecoderTableXmipscmove32, "MIPS mips.ccmov");
TRY_TO_DECODE_FEATURE_ANY(XCVFeatureGroup, DecoderTableXCV32,
"CORE-V extensions");
TRY_TO_DECODE_FEATURE_ANY(XqciFeatureGroup, DecoderTableXqci32,
"Qualcomm uC Extensions");

TRY_TO_DECODE_FEATURE_ANY(XRivosFeatureGroup, DecoderTableXRivos32, "Rivos");

TRY_TO_DECODE(true, DecoderTable32, "RISCV32");
TRY_TO_DECODE(true, DecoderTableRV32GPRPair32,
"RV32GPRPair (rv32 and GPR pairs)");
TRY_TO_DECODE(true, DecoderTableZfinx32, "Zfinx (Float in Integer)");
TRY_TO_DECODE(true, DecoderTableZdinxRV32GPRPair32,
"ZdinxRV32GPRPair (rv32 and Double in Integer)");
for (const DecoderListEntry &Entry : DecoderList32) {
if (!Entry.haveContainedFeatures(STI.getFeatureBits()))
continue;

LLVM_DEBUG(dbgs() << "Trying " << Entry.Desc << "table:\n");
DecodeStatus Result =
decodeInstruction(Entry.Table, MI, Insn, Address, this, STI);
if (Result == MCDisassembler::Fail)
continue;

return Result;
}

return MCDisassembler::Fail;
}

static constexpr DecoderListEntry DecoderList16[]{
// Vendor Extensions
{DecoderTableXqci16, XqciFeatureGroup, "Qualcomm uC 16bit"},
{DecoderTableXqccmp16,
{RISCV::FeatureVendorXqccmp},
"Xqccmp (Qualcomm 16-bit Push/Pop & Double Move Instructions)"},
{DecoderTableXwchc16, {RISCV::FeatureVendorXwchc}, "WCH QingKe XW"},
// Standard Extensions
// DecoderTableZicfiss16 must be checked before DecoderTable16.
{DecoderTableZicfiss16, {}, "RVZicfiss (Shadow Stack)"},
{DecoderTable16, {}, "RISCV_C (16-bit Instruction)"},
{DecoderTableRISCV32Only_16, {}, "RISCV32Only_16 (16-bit Instruction)"},
// Zc* instructions incompatible with Zcf or Zcd
{DecoderTableZcOverlap16,
{},
"ZcOverlap (16-bit Instructions overlapping with Zcf/Zcd)"},
};

DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size,
ArrayRef<uint8_t> Bytes,
uint64_t Address,
Expand All @@ -736,27 +755,28 @@ DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size,

uint32_t Insn = support::endian::read16le(Bytes.data());

TRY_TO_DECODE_FEATURE_ANY(XqciFeatureGroup, DecoderTableXqci16,
"Qualcomm uC 16bit");
TRY_TO_DECODE_FEATURE(
RISCV::FeatureVendorXqccmp, DecoderTableXqccmp16,
"Xqccmp (Qualcomm 16-bit Push/Pop & Double Move Instructions)");
TRY_TO_DECODE_AND_ADD_SP(STI.hasFeature(RISCV::FeatureVendorXwchc),
DecoderTableXwchc16, "WCH QingKe XW");

// DecoderTableZicfiss16 must be checked before DecoderTable16.
TRY_TO_DECODE(true, DecoderTableZicfiss16, "RVZicfiss (Shadow Stack)");
TRY_TO_DECODE_AND_ADD_SP(true, DecoderTable16,
"RISCV_C (16-bit Instruction)");
TRY_TO_DECODE_AND_ADD_SP(true, DecoderTableRISCV32Only_16,
"RISCV32Only_16 (16-bit Instruction)");
// Zc* instructions incompatible with Zcf or Zcd.
TRY_TO_DECODE(true, DecoderTableZcOverlap16,
"ZcOverlap (16-bit Instructions overlapping with Zcf/Zcd)");
for (const DecoderListEntry &Entry : DecoderList16) {
if (!Entry.haveContainedFeatures(STI.getFeatureBits()))
continue;

LLVM_DEBUG(dbgs() << "Trying " << Entry.Desc << "table:\n");
DecodeStatus Result =
decodeInstruction(Entry.Table, MI, Insn, Address, this, STI);
if (Result == MCDisassembler::Fail)
continue;

addSPOperands(MI);

return Result;
}

return MCDisassembler::Fail;
}

static constexpr DecoderListEntry DecoderList48[]{
{DecoderTableXqci48, XqciFeatureGroup, "Qualcomm uC 48bit"},
};

DecodeStatus RISCVDisassembler::getInstruction48(MCInst &MI, uint64_t &Size,
ArrayRef<uint8_t> Bytes,
uint64_t Address,
Expand All @@ -768,11 +788,21 @@ DecodeStatus RISCVDisassembler::getInstruction48(MCInst &MI, uint64_t &Size,
Size = 6;

uint64_t Insn = 0;
for (size_t i = Size; i-- != 0;) {
for (size_t i = Size; i-- != 0;)
Insn += (static_cast<uint64_t>(Bytes[i]) << 8 * i);

for (const DecoderListEntry &Entry : DecoderList48) {
if (!Entry.haveContainedFeatures(STI.getFeatureBits()))
continue;

LLVM_DEBUG(dbgs() << "Trying " << Entry.Desc << "table:\n");
DecodeStatus Result =
decodeInstruction(Entry.Table, MI, Insn, Address, this, STI);
if (Result == MCDisassembler::Fail)
continue;

return Result;
}
TRY_TO_DECODE_FEATURE_ANY(XqciFeatureGroup, DecoderTableXqci48,
"Qualcomm uC 48bit");

return MCDisassembler::Fail;
}
Expand Down