Skip to content

[RISCV][Xqccmp] Correctly Parse/Disassemble pushfp #133188

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 10 commits into from
Mar 28, 2025
Merged
Show file tree
Hide file tree
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
38 changes: 34 additions & 4 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,14 @@ class RISCVAsmParser : public MCTargetAsmParser {
ParseStatus parseGPRPair(OperandVector &Operands, bool IsRV64Inst);
ParseStatus parseFRMArg(OperandVector &Operands);
ParseStatus parseFenceArg(OperandVector &Operands);
ParseStatus parseReglist(OperandVector &Operands);
ParseStatus parseReglist(OperandVector &Operands) {
return parseRegListCommon(Operands, /*MustIncludeS0=*/false);
}
ParseStatus parseReglistS0(OperandVector &Operands) {
return parseRegListCommon(Operands, /*MustIncludeS0=*/true);
}
ParseStatus parseRegListCommon(OperandVector &Operands, bool MustIncludeS0);

ParseStatus parseRegReg(OperandVector &Operands);
ParseStatus parseRetval(OperandVector &Operands);
ParseStatus parseZcmpStackAdj(OperandVector &Operands,
Expand Down Expand Up @@ -474,6 +481,9 @@ struct RISCVOperand final : public MCParsedAsmOperand {
bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
bool isRegReg() const { return Kind == KindTy::RegReg; }
bool isRlist() const { return Kind == KindTy::Rlist; }
bool isRlistS0() const {
return Kind == KindTy::Rlist && Rlist.Val != RISCVZC::RA;
}
bool isSpimm() const { return Kind == KindTy::Spimm; }

bool isGPR() const {
Expand Down Expand Up @@ -2794,9 +2804,15 @@ ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
return ParseStatus::Success;
}

ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
ParseStatus RISCVAsmParser::parseRegListCommon(OperandVector &Operands,
bool MustIncludeS0) {
// Rlist: {ra [, s0[-sN]]}
// XRlist: {x1 [, x8[-x9][, x18[-xN]]]}

// When MustIncludeS0 = true (not the default) (used for `qc.cm.pushfp`) which
// must include `fp`/`s0` in the list:
// Rlist: {ra, s0[-sN]}
// XRlist: {x1, x8[-x9][, x18[-xN]]}
SMLoc S = getLoc();

if (parseToken(AsmToken::LCurly, "register list must start with '{'"))
Expand All @@ -2814,8 +2830,20 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
return Error(getLoc(), "register list must start from 'ra' or 'x1'");
getLexer().Lex();

// parse case like ,s0
if (parseOptionalToken(AsmToken::Comma)) {
bool SeenComma = parseOptionalToken(AsmToken::Comma);

// There are two choices here:
// - `s0` is not required (usual case), so only try to parse `s0` if there is
// a comma
// - `s0` is required (qc.cm.pushfp), and so we must see the comma between
// `ra` and `s0` and must always try to parse `s0`, below
if (MustIncludeS0 && !SeenComma) {
Error(getLoc(), "register list must include 's0' or 'x8'");
return ParseStatus::Failure;
}

// parse case like ,s0 (knowing the comma must be there if required)
if (SeenComma) {
if (getLexer().isNot(AsmToken::Identifier))
return Error(getLoc(), "invalid register");
StringRef RegName = getLexer().getTok().getIdentifier();
Expand Down Expand Up @@ -2884,6 +2912,8 @@ ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {

auto Encode = RISCVZC::encodeRlist(RegEnd, IsEABI);
assert(Encode != RISCVZC::INVALID_RLIST);
if (MustIncludeS0)
assert(Encode != RISCVZC::RA);
Operands.push_back(RISCVOperand::createRlist(Encode, S));

return ParseStatus::Success;
Expand Down
13 changes: 12 additions & 1 deletion llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,9 @@ static DecodeStatus decodeXTHeadMemPair(MCInst &Inst, uint32_t Insn,
static DecodeStatus decodeZcmpRlist(MCInst &Inst, uint32_t Imm,
uint64_t Address, const void *Decoder);

static DecodeStatus decodeXqccmpRlistS0(MCInst &Inst, uint32_t Imm,
uint64_t Address, const void *Decoder);

static DecodeStatus decodeZcmpSpimm(MCInst &Inst, uint32_t Imm,
uint64_t Address, const void *Decoder);

Expand Down Expand Up @@ -612,7 +615,15 @@ static DecodeStatus decodeXTHeadMemPair(MCInst &Inst, uint32_t Insn,

static DecodeStatus decodeZcmpRlist(MCInst &Inst, uint32_t Imm,
uint64_t Address, const void *Decoder) {
if (Imm <= 3)
if (Imm < RISCVZC::RA)
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(Imm));
return MCDisassembler::Success;
}

static DecodeStatus decodeXqccmpRlistS0(MCInst &Inst, uint32_t Imm,
uint64_t Address, const void *Decoder) {
if (Imm < RISCVZC::RA_S0)
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createImm(Imm));
return MCDisassembler::Success;
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,12 @@ float RISCVLoadFPImm::getFPImm(unsigned Imm) {

void RISCVZC::printRlist(unsigned SlistEncode, raw_ostream &OS) {
OS << "{ra";
if (SlistEncode > 4) {
if (SlistEncode > RISCVZC::RA) {
OS << ", s0";
if (SlistEncode == 15)
if (SlistEncode == RISCVZC::RA_S0_S11)
OS << "-s11";
else if (SlistEncode > 5 && SlistEncode <= 14)
OS << "-s" << (SlistEncode - 5);
else if (SlistEncode > RISCVZC::RA_S0 && SlistEncode <= RISCVZC::RA_S0_S11)
OS << "-s" << (SlistEncode - RISCVZC::RA_S0);
}
OS << "}";
}
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ enum OperandType : unsigned {
OPERAND_RVKRNUM_0_7,
OPERAND_RVKRNUM_1_10,
OPERAND_RVKRNUM_2_14,
OPERAND_RLIST,
OPERAND_RLIST_S0,
OPERAND_SPIMM,
// Operand is a 3-bit rounding mode, '111' indicates FRM register.
// Represents 'frm' argument passing to floating-point operations.
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
unsigned getRlistOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

unsigned getRlistS0OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
};
} // end anonymous namespace

Expand Down Expand Up @@ -616,5 +620,16 @@ unsigned RISCVMCCodeEmitter::getRlistOpValue(const MCInst &MI, unsigned OpNo,
assert(Imm >= 4 && "EABI is currently not implemented");
return Imm;
}
unsigned
RISCVMCCodeEmitter::getRlistS0OpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
assert(MO.isImm() && "Rlist operand must be immediate");
auto Imm = MO.getImm();
assert(Imm >= 4 && "EABI is currently not implemented");
assert(Imm != RISCVZC::RA && "Rlist operand must include s0");
return Imm;
}

#include "RISCVGenMCCodeEmitter.inc"
6 changes: 6 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2679,6 +2679,12 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
case RISCVOp::OPERAND_RVKRNUM_2_14:
Ok = Imm >= 2 && Imm <= 14;
break;
case RISCVOp::OPERAND_RLIST:
Ok = Imm >= RISCVZC::RA && Imm <= RISCVZC::RA_S0_S11;
break;
case RISCVOp::OPERAND_RLIST_S0:
Ok = Imm >= RISCVZC::RA_S0 && Imm <= RISCVZC::RA_S0_S11;
break;
case RISCVOp::OPERAND_SPIMM:
Ok = (Imm & 0xf) == 0;
break;
Expand Down
40 changes: 39 additions & 1 deletion llvm/lib/Target/RISCV/RISCVInstrInfoXqccmp.td
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,30 @@
// Operand and SDNode transformation definitions.
//===----------------------------------------------------------------------===//

def RlistS0AsmOperand : AsmOperandClass {
let Name = "RlistS0";
let ParserMethod = "parseReglistS0";
let RenderMethod = "addRlistOperands";
let DiagnosticType = "InvalidRlistS0";
let DiagnosticString = "operand must be {ra, s0[-sN]} or {x1, x8[-x9][, x18[-xN]]}";
}

def rlist_s0 : RISCVOp<OtherVT> {
let ParserMatchClass = RlistS0AsmOperand;
let PrintMethod = "printRlist";
let DecoderMethod = "decodeXqccmpRlistS0";
let EncoderMethod = "getRlistS0OpValue";
let MCOperandPredicate = [{
int64_t Imm;
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
// 0~4 invalid for `qc.cm.pushfp`
return isUInt<4>(Imm) && Imm >= RISCVZC::RA_S0;
}];

string OperandType = "OPERAND_RLIST_S0";
}

//===----------------------------------------------------------------------===//
// Instruction Formats
//===----------------------------------------------------------------------===//
Expand All @@ -33,6 +57,20 @@
// Instruction Class Templates
//===----------------------------------------------------------------------===//

class RVInstXqccmpCPPPFP<bits<5> funct5, string opcodestr,
DAGOperand immtype = stackadj>
: RVInst16<(outs), (ins rlist_s0:$rlist, immtype:$stackadj),
opcodestr, "$rlist, $stackadj", [], InstFormatOther> {
bits<4> rlist;
bits<16> stackadj;

let Inst{1-0} = 0b10;
let Inst{3-2} = stackadj{5-4};
let Inst{7-4} = rlist;
let Inst{12-8} = funct5;
let Inst{15-13} = 0b101;
}

//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
Expand All @@ -59,7 +97,7 @@ def QC_CM_PUSH : RVInstZcCPPP<0b11000, "qc.cm.push", negstackadj>,
ReadStoreData, ReadStoreData, ReadStoreData]>;

let hasSideEffects = 0, mayLoad = 0, mayStore = 1, Uses = [X2], Defs = [X2, X8] in
def QC_CM_PUSHFP : RVInstZcCPPP<0b11001, "qc.cm.pushfp", negstackadj>,
def QC_CM_PUSHFP : RVInstXqccmpCPPPFP<0b11001, "qc.cm.pushfp", negstackadj>,
Sched<[WriteIALU, WriteIALU, ReadIALU, ReadStoreData, ReadStoreData,
ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
ReadStoreData, ReadStoreData, ReadStoreData, ReadStoreData,
Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/Target/RISCV/RISCVInstrInfoZc.td
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def NegStackAdjAsmOperand : AsmOperandClass {
let RenderMethod = "addSpimmOperands";
}

def rlist : Operand<OtherVT> {
def rlist : RISCVOp<OtherVT> {
let ParserMatchClass = RlistAsmOperand;
let PrintMethod = "printRlist";
let DecoderMethod = "decodeZcmpRlist";
Expand All @@ -68,8 +68,10 @@ def rlist : Operand<OtherVT> {
if (!MCOp.evaluateAsConstantImm(Imm))
return false;
// 0~3 Reserved for EABI
return isUInt<4>(Imm) && Imm >= 4;
return isUInt<4>(Imm) && Imm >= RISCVZC::RA;
}];

let OperandType = "OPERAND_RLIST";
}

def stackadj : RISCVOp<OtherVT> {
Expand Down
11 changes: 11 additions & 0 deletions llvm/test/MC/Disassembler/RISCV/xqccmp-invalid-rlist.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# RUN: not llvm-mc -disassemble -triple=riscv32 -mattr=+experimental-xqccmp %s \
# RUN: | FileCheck -check-prefixes=CHECK,CHECK-XQCCMP %s

[0x00,0x00]
# CHECK: unimp

[0x42,0xb9]
# CHECK-XQCCMP-NOT: qc.cm.pushfp {ra}, -{{[0-9]+}}

[0x00,0x00]
# CHECK: unimp
4 changes: 4 additions & 0 deletions llvm/test/MC/RISCV/rv32xqccmp-invalid.s
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ qc.cm.pushfp {ra, s0}, -12

# CHECK-ERROR: error: stack adjustment for register list must be a multiple of 16 bytes in the range [16, 64]
qc.cm.pop {ra, s0-s1}, -40

# CHECK-ERROR: error: register list must include 's0' or 'x8'
qc.cm.pushfp {ra}, -16

8 changes: 0 additions & 8 deletions llvm/test/MC/RISCV/rv32xqccmp-valid.s
Original file line number Diff line number Diff line change
Expand Up @@ -288,14 +288,6 @@ qc.cm.push {ra, s0-s11}, -112
# CHECK-ASM: encoding: [0xfe,0xb8]
qc.cm.push {x1, x8-x9, x18-x27}, -112

# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra}, -16
# CHECK-ASM: encoding: [0x42,0xb9]
qc.cm.pushfp {ra}, -16

# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra}, -16
# CHECK-ASM: encoding: [0x42,0xb9]
qc.cm.pushfp {x1}, -16

# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra, s0}, -32
# CHECK-ASM: encoding: [0x56,0xb9]
qc.cm.pushfp {ra, s0}, -32
Expand Down
4 changes: 0 additions & 4 deletions llvm/test/MC/RISCV/rv64e-xqccmp-valid.s
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ qc.cm.push {ra, s0}, -32
# CHECK-ASM: encoding: [0x62,0xb8]
qc.cm.push {ra, s0-s1}, -32

# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra}, -16
# CHECK-ASM: encoding: [0x42,0xb9]
qc.cm.pushfp {ra}, -16

# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra, s0}, -32
# CHECK-ASM: encoding: [0x56,0xb9]
qc.cm.pushfp {ra, s0}, -32
Expand Down
4 changes: 0 additions & 4 deletions llvm/test/MC/RISCV/rv64xqccmp-valid.s
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,6 @@ qc.cm.push {ra, s0-s11}, -112
# CHECK-ASM: encoding: [0xf6,0xb8]
qc.cm.push {ra, s0-s11}, -128

# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra}, -16
# CHECK-ASM: encoding: [0x42,0xb9]
qc.cm.pushfp {ra}, -16

# CHECK-ASM-AND-OBJ: qc.cm.pushfp {ra, s0}, -32
# CHECK-ASM: encoding: [0x56,0xb9]
qc.cm.pushfp {ra, s0}, -32
Expand Down