Skip to content

Commit

Permalink
[RISCV][MC] MC layer support for xcvmem and xcvelw extensions
Browse files Browse the repository at this point in the history
This commit is part of a patch-set to upstream the 7 vendor specific extensions of CV32E40P.
Several other extensions have been merged.
Spec:
https://github.com/openhwgroup/cv32e40p/blob/master/docs/source/instruction_set_extensions.rst
Contributors: @CharKeaney, @jeremybennett, @lewis-revill, Nandni Jamnadas, @paolos, @simoncook, @xmj, @realqhc, @melonedo, @adeelahmad81299

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D158824
  • Loading branch information
ChunyuLiao committed Nov 16, 2023
1 parent 10cc3a8 commit 71a7108
Show file tree
Hide file tree
Showing 17 changed files with 827 additions and 1 deletion.
2 changes: 2 additions & 0 deletions clang/test/Preprocessor/riscv-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
// CHECK-NOT: __riscv_xcvalu {{.*$}}
// CHECK-NOT: __riscv_xcvbi {{.*$}}
// CHECK-NOT: __riscv_xcvbitmanip {{.*$}}
// CHECK-NOT: __riscv_xcvelw {{.*$}}
// CHECK-NOT: __riscv_xcvmac {{.*$}}
// CHECK-NOT: __riscv_xcvmem {{.*$}}
// CHECK-NOT: __riscv_xcvsimd {{.*$}}
// CHECK-NOT: __riscv_xsfcie {{.*$}}
// CHECK-NOT: __riscv_xsfvcp {{.*$}}
Expand Down
6 changes: 6 additions & 0 deletions llvm/docs/RISCVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,15 @@ The current vendor extensions supported are:
``XCVbitmanip``
LLVM implements `version 1.0.0 of the CORE-V Bit Manipulation custom instructions specification <https://github.com/openhwgroup/cv32e40p/blob/62bec66b36182215e18c9cf10f723567e23878e9/docs/source/instruction_set_extensions.rst>`_ by OpenHW Group. All instructions are prefixed with `cv.` as described in the specification.

``XCVelw``
LLVM implements `version 1.0.0 of the CORE-V Event load custom instructions specification <https://github.com/openhwgroup/cv32e40p/blob/master/docs/source/instruction_set_extensions.rst>`_ by OpenHW Group. All instructions are prefixed with `cv.` as described in the specification. These instructions are only available for riscv32 at this time.

``XCVmac``
LLVM implements `version 1.0.0 of the CORE-V Multiply-Accumulate (MAC) custom instructions specification <https://github.com/openhwgroup/cv32e40p/blob/4f024fe4b15a68b76615b0630c07a6745c620da7/docs/source/instruction_set_extensions.rst>`_ by OpenHW Group. All instructions are prefixed with `cv.mac` as described in the specification. These instructions are only available for riscv32 at this time.

``XCVmem``
LLVM implements `version 1.0.0 of the CORE-V Post-Increment load and stores custom instructions specification <https://github.com/openhwgroup/cv32e40p/blob/master/docs/source/instruction_set_extensions.rst>`_ by OpenHW Group. All instructions are prefixed with `cv.` as described in the specification. These instructions are only available for riscv32 at this time.

``XCValu``
LLVM implements `version 1.0.0 of the Core-V ALU custom instructions specification <https://github.com/openhwgroup/cv32e40p/blob/4f024fe4b15a68b76615b0630c07a6745c620da7/docs/source/instruction_set_extensions.rst>`_ by Core-V. All instructions are prefixed with `cv.` as described in the specification. These instructions are only available for riscv32 at this time.

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Support/RISCVISAInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
{"xcvalu", RISCVExtensionVersion{1, 0}},
{"xcvbi", RISCVExtensionVersion{1, 0}},
{"xcvbitmanip", RISCVExtensionVersion{1, 0}},
{"xcvelw", RISCVExtensionVersion{1, 0}},
{"xcvmac", RISCVExtensionVersion{1, 0}},
{"xcvmem", RISCVExtensionVersion{1, 0}},
{"xcvsimd", RISCVExtensionVersion{1, 0}},
{"xsfcie", RISCVExtensionVersion{1, 0}},
{"xsfvcp", RISCVExtensionVersion{1, 0}},
Expand Down
67 changes: 67 additions & 0 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
ParseStatus parseFRMArg(OperandVector &Operands);
ParseStatus parseFenceArg(OperandVector &Operands);
ParseStatus parseReglist(OperandVector &Operands);
ParseStatus parseRegReg(OperandVector &Operands);
ParseStatus parseRetval(OperandVector &Operands);
ParseStatus parseZcmpSpimm(OperandVector &Operands);

Expand Down Expand Up @@ -324,6 +325,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
Fence,
Rlist,
Spimm,
RegReg,
} Kind;

struct RegOp {
Expand Down Expand Up @@ -368,6 +370,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {
unsigned Val;
};

struct RegRegOp {
MCRegister Reg1;
MCRegister Reg2;
};

SMLoc StartLoc, EndLoc;
union {
StringRef Tok;
Expand All @@ -380,6 +387,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
struct FenceOp Fence;
struct RlistOp Rlist;
struct SpimmOp Spimm;
struct RegRegOp RegReg;
};

RISCVOperand(KindTy K) : Kind(K) {}
Expand Down Expand Up @@ -420,6 +428,9 @@ struct RISCVOperand final : public MCParsedAsmOperand {
case KindTy::Spimm:
Spimm = o.Spimm;
break;
case KindTy::RegReg:
RegReg = o.RegReg;
break;
}
}

Expand All @@ -444,6 +455,7 @@ struct RISCVOperand final : public MCParsedAsmOperand {
bool isImm() const override { return Kind == KindTy::Immediate; }
bool isMem() const override { return false; }
bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
bool isRegReg() const { return Kind == KindTy::RegReg; }
bool isRlist() const { return Kind == KindTy::Rlist; }
bool isSpimm() const { return Kind == KindTy::Spimm; }

Expand Down Expand Up @@ -1025,6 +1037,10 @@ struct RISCVOperand final : public MCParsedAsmOperand {
RISCVZC::printSpimm(Spimm.Val, OS);
OS << '>';
break;
case KindTy::RegReg:
OS << "<RegReg: Reg1 " << RegName(RegReg.Reg1);
OS << " Reg2 " << RegName(RegReg.Reg2);
break;
}
}

Expand Down Expand Up @@ -1108,6 +1124,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
return Op;
}

static std::unique_ptr<RISCVOperand> createRegReg(unsigned Reg1No,
unsigned Reg2No, SMLoc S) {
auto Op = std::make_unique<RISCVOperand>(KindTy::RegReg);
Op->RegReg.Reg1 = Reg1No;
Op->RegReg.Reg2 = Reg2No;
Op->StartLoc = S;
Op->EndLoc = S;
return Op;
}

static std::unique_ptr<RISCVOperand> createSpimm(unsigned Spimm, SMLoc S) {
auto Op = std::make_unique<RISCVOperand>(KindTy::Spimm);
Op->Spimm.Val = Spimm;
Expand Down Expand Up @@ -1183,6 +1209,12 @@ struct RISCVOperand final : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::createImm(Rlist.Val));
}

void addRegRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(RegReg.Reg1));
Inst.addOperand(MCOperand::createReg(RegReg.Reg2));
}

void addSpimmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createImm(Spimm.Val));
Expand Down Expand Up @@ -1549,6 +1581,10 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidRnumArg: {
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 10);
}
case Match_InvalidRegReg: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(ErrorLoc, "operands must be register and register");
}
}

llvm_unreachable("Unknown match type detected!");
Expand Down Expand Up @@ -2381,6 +2417,37 @@ ParseStatus RISCVAsmParser::parseZeroOffsetMemOp(OperandVector &Operands) {
return ParseStatus::Success;
}

ParseStatus RISCVAsmParser::parseRegReg(OperandVector &Operands) {
// RR : a2(a1)
if (getLexer().getKind() != AsmToken::Identifier)
return ParseStatus::NoMatch;

StringRef RegName = getLexer().getTok().getIdentifier();
MCRegister Reg = matchRegisterNameHelper(isRVE(), RegName);
if (!Reg)
return Error(getLoc(), "invalid register");
getLexer().Lex();

if (parseToken(AsmToken::LParen, "expected '(' or invalid operand"))
return ParseStatus::Failure;

if (getLexer().getKind() != AsmToken::Identifier)
return Error(getLoc(), "expected register");

StringRef Reg2Name = getLexer().getTok().getIdentifier();
MCRegister Reg2 = matchRegisterNameHelper(isRVE(), Reg2Name);
if (!Reg2)
return Error(getLoc(), "invalid register");
getLexer().Lex();

if (parseToken(AsmToken::RParen, "expected ')'"))
return ParseStatus::Failure;

Operands.push_back(RISCVOperand::createRegReg(Reg, Reg2, getLoc()));

return ParseStatus::Success;
}

ParseStatus RISCVAsmParser::parseReglist(OperandVector &Operands) {
// Rlist: {ra [, s0[-sN]]}
// XRlist: {x1 [, x8[-x9][, x18[-xN]]]}
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,9 @@ static DecodeStatus decodeXTHeadMemPair(MCInst &Inst, uint32_t Insn,
static DecodeStatus decodeZcmpRlist(MCInst &Inst, unsigned Imm,
uint64_t Address, const void *Decoder);

static DecodeStatus decodeRegReg(MCInst &Inst, uint32_t Insn, uint64_t Address,
const MCDisassembler *Decoder);

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

Expand Down Expand Up @@ -450,6 +453,15 @@ static DecodeStatus decodeZcmpRlist(MCInst &Inst, unsigned Imm,
return MCDisassembler::Success;
}

static DecodeStatus decodeRegReg(MCInst &Inst, uint32_t Insn, uint64_t Address,
const MCDisassembler *Decoder) {
uint32_t Rs1 = fieldFromInstruction(Insn, 0, 5);
uint32_t Rs2 = fieldFromInstruction(Insn, 5, 5);
DecodeGPRRegisterClass(Inst, Rs1, Address, Decoder);
DecodeGPRRegisterClass(Inst, Rs2, Address, Decoder);
return MCDisassembler::Success;
}

// spimm is based on rlist now.
static DecodeStatus decodeZcmpSpimm(MCInst &Inst, unsigned Imm,
uint64_t Address, const void *Decoder) {
Expand Down Expand Up @@ -561,8 +573,12 @@ DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXCVbitmanip,
DecoderTableXCVbitmanip32,
"CORE-V Bit Manipulation custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXCVelw, DecoderTableXCVelw32,
"CORE-V Event load custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXCVmac, DecoderTableXCVmac32,
"CORE-V MAC custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXCVmem, DecoderTableXCVmem32,
"CORE-V MEM custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXCValu, DecoderTableXCValu32,
"CORE-V ALU custom opcode table");
TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXCVsimd, DecoderTableXCVsimd32,
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,22 @@ void RISCVInstPrinter::printRlist(const MCInst *MI, unsigned OpNo,
O << "}";
}

void RISCVInstPrinter::printRegReg(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O) {
const MCOperand &MO = MI->getOperand(OpNo);

assert(MO.isReg() && "printRegReg can only print register operands");
if (MO.getReg() == RISCV::NoRegister)
return;
printRegName(O, MO.getReg());

O << "(";
const MCOperand &MO1 = MI->getOperand(OpNo + 1);
assert(MO1.isReg() && "printRegReg can only print register operands");
printRegName(O, MO1.getReg());
O << ")";
}

void RISCVInstPrinter::printSpimm(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI, raw_ostream &O) {
int64_t Imm = MI->getOperand(OpNo).getImm();
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class RISCVInstPrinter : public MCInstPrinter {
raw_ostream &O);
void printSpimm(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);

void printRegReg(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
raw_ostream &O);
// Autogenerated by tblgen.
std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) override;
void printInstruction(const MCInst *MI, uint64_t Address,
Expand Down
17 changes: 17 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
unsigned getRlistOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;

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

Expand Down Expand Up @@ -506,4 +510,17 @@ unsigned RISCVMCCodeEmitter::getRlistOpValue(const MCInst &MI, unsigned OpNo,
return Imm;
}

unsigned RISCVMCCodeEmitter::getRegReg(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
const MCOperand &MO = MI.getOperand(OpNo);
const MCOperand &MO1 = MI.getOperand(OpNo + 1);
assert(MO.isReg() && MO1.isReg() && "Expected registers.");

unsigned Op = Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
unsigned Op1 = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg());

return Op | Op1 << 5;
}

#include "RISCVGenMCCodeEmitter.inc"
15 changes: 15 additions & 0 deletions llvm/lib/Target/RISCV/RISCVFeatures.td
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,13 @@ def FeatureVendorXSfvfnrclipxfqf
def HasVendorXSfvfnrclipxfqf : Predicate<"Subtarget->hasVendorXSfvfnrclipxfqf()">,
AssemblerPredicate<(all_of FeatureVendorXSfvfnrclipxfqf),
"'XSfvfnrclipxfqf' (SiFive FP32-to-int8 Ranged Clip Instructions)">;
def FeatureVendorXCVelw
: SubtargetFeature<"xcvelw", "HasVendorXCVelw", "true",
"'XCVelw' (CORE-V Event Load Word)">;
def HasVendorXCVelw
: Predicate<"Subtarget->hasVendorXCVelw()">,
AssemblerPredicate<(any_of FeatureVendorXCVelw),
"'XCVelw' (CORE-V Event Load Word)">;

def FeatureVendorXCVbitmanip
: SubtargetFeature<"xcvbitmanip", "HasVendorXCVbitmanip", "true",
Expand All @@ -866,6 +873,14 @@ def HasVendorXCVmac : Predicate<"Subtarget->hasVendorXCVmac()">,
AssemblerPredicate<(all_of FeatureVendorXCVmac),
"'XCVmac' (CORE-V Multiply-Accumulate)">;

def FeatureVendorXCVmem
: SubtargetFeature<"xcvmem", "HasVendorXCVmem", "true",
"'XCVmem' (CORE-V Post-incrementing Load & Store)">;
def HasVendorXCVmem
: Predicate<"Subtarget->hasVendorXCVmem()">,
AssemblerPredicate<(any_of FeatureVendorXCVmem),
"'XCVmem' (CORE-V Post-incrementing Load & Store)">;

def FeatureVendorXCValu
: SubtargetFeature<"xcvalu", "HasVendorXCValu", "true",
"'XCValu' (CORE-V ALU Operations)">;
Expand Down

0 comments on commit 71a7108

Please sign in to comment.