Skip to content

Commit faece38

Browse files
veselypetajrtc27arichardson
committed
[RISC-V][MC] Introduce initial support for Y extension (CHERI)
This adds MC-level support for most of the base Y extension instructions, restricted to the execution-mode-independent subset. The Y extension (CHERI for RISC-V) also introduces an execution mode that determines whether certain register operands use the full extended register or only the address subset (the current XLEN registers). The instructions that depend on execution mode (loads/stores/jumps + AUIPC) will be added in the next commit in this stack of changes. Co-authored-by: Jessica Clarke <[email protected]> Co-authored-by: Alexander Richardson <[email protected]> Co-authored-by: Petr Vesely <[email protected]>
1 parent 2778acb commit faece38

File tree

10 files changed

+478
-6
lines changed

10 files changed

+478
-6
lines changed

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {
491491
RISCVMCRegisterClasses[RISCV::GPRRegClassID].contains(Reg.RegNum);
492492
}
493493

494+
bool isYGPR() const {
495+
return Kind == KindTy::Register &&
496+
RISCVMCRegisterClasses[RISCV::YGPRRegClassID].contains(Reg.RegNum);
497+
}
498+
494499
bool isGPRPair() const {
495500
return Kind == KindTy::Register &&
496501
RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(
@@ -767,6 +772,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {
767772
});
768773
}
769774

775+
bool isUImm7Srliy() const {
776+
return isUImmPred(
777+
[this](int64_t Imm) { return isRV64Expr() ? Imm == 64 : Imm == 32; });
778+
}
779+
770780
bool isUImm8GE32() const {
771781
return isUImmPred([](int64_t Imm) { return isUInt<8>(Imm) && Imm >= 32; });
772782
}
@@ -799,6 +809,29 @@ struct RISCVOperand final : public MCParsedAsmOperand {
799809
return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, isRV64Expr()));
800810
}
801811

812+
bool isYBNDSWImm() const {
813+
if (!isExpr())
814+
return false;
815+
816+
int64_t Imm;
817+
bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
818+
if (!IsConstantImm)
819+
return false;
820+
// The immediate is encoded using `((imm[7:0] + 257) << imm[9:8]) - 256`
821+
// which gives the following valid ranges:
822+
if (Imm < 1)
823+
return false;
824+
if (Imm <= 256)
825+
return true;
826+
if (Imm <= 768)
827+
return (Imm % 2) == 0;
828+
if (Imm <= 1792)
829+
return (Imm % 4) == 0;
830+
if (Imm <= 3840)
831+
return (Imm % 8) == 0;
832+
return false;
833+
}
834+
802835
template <class Pred> bool isSImmPred(Pred p) const {
803836
int64_t Imm;
804837
if (!isExpr())
@@ -1306,6 +1339,11 @@ static MCRegister convertFPR64ToFPR128(MCRegister Reg) {
13061339
return Reg - RISCV::F0_D + RISCV::F0_Q;
13071340
}
13081341

1342+
static MCRegister convertGPRToYGPR(MCRegister Reg) {
1343+
assert(Reg >= RISCV::X0 && Reg <= RISCV::X31 && "Invalid register");
1344+
return Reg - RISCV::X0 + RISCV::X0_Y;
1345+
}
1346+
13091347
static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
13101348
unsigned Kind) {
13111349
unsigned RegClassID;
@@ -1333,7 +1371,11 @@ unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
13331371
bool IsRegFPR64C =
13341372
RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
13351373
bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
1336-
1374+
if (Op.isGPR() && Kind == MCK_YGPR) {
1375+
// GPR and capability GPR use the same register names, convert if required.
1376+
Op.Reg.RegNum = convertGPRToYGPR(Reg);
1377+
return Match_Success;
1378+
}
13371379
if (IsRegFPR64 && Kind == MCK_FPR128) {
13381380
Op.Reg.RegNum = convertFPR64ToFPR128(Reg);
13391381
return Match_Success;
@@ -1708,6 +1750,18 @@ bool RISCVAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
17081750
ErrorLoc,
17091751
"stack adjustment is invalid for this instruction and register list");
17101752
}
1753+
case Match_InvalidYBNDSWImm: {
1754+
const SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1755+
return Error(ErrorLoc, "immediate must be an integer in the range "
1756+
"[1, 256], a multiple of 2 in the range [258, 768], "
1757+
"a multiple of 4 in the range [772, 1792], or "
1758+
"a multiple of 8 in the range [1800, 3840]");
1759+
}
1760+
case Match_InvalidUImm7Srliy: {
1761+
const SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
1762+
return Error(ErrorLoc, "immediate must be an integer equal to XLEN (" +
1763+
Twine(isRV64() ? "64" : "32") + ")");
1764+
}
17111765
}
17121766

17131767
if (const char *MatchDiag = getMatchKindDiag((RISCVMatchResultTy)Result)) {

llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,19 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint32_t RegNo,
9191
return MCDisassembler::Success;
9292
}
9393

94+
static DecodeStatus DecodeYGPRRegisterClass(MCInst &Inst, uint32_t RegNo,
95+
uint64_t Address,
96+
const MCDisassembler *Decoder) {
97+
bool IsRVE = Decoder->getSubtargetInfo().hasFeature(RISCV::FeatureStdExtE);
98+
99+
if (RegNo >= 32 || (IsRVE && RegNo >= 16))
100+
return MCDisassembler::Fail;
101+
102+
MCRegister Reg = RISCV::X0_Y + RegNo;
103+
Inst.addOperand(MCOperand::createReg(Reg));
104+
return MCDisassembler::Success;
105+
}
106+
94107
static DecodeStatus DecodeGPRF16RegisterClass(MCInst &Inst, uint32_t RegNo,
95108
uint64_t Address,
96109
const MCDisassembler *Decoder) {
@@ -416,6 +429,15 @@ static DecodeStatus DecodeTRM4RegisterClass(MCInst &Inst, uint32_t RegNo,
416429
return MCDisassembler::Success;
417430
}
418431

432+
static DecodeStatus DecodeYBNDSWImm(MCInst &Inst, uint64_t Imm, int64_t Address,
433+
const MCDisassembler *Decoder) {
434+
assert(isUInt<10>(Imm) && "Invalid immediate");
435+
const uint32_t Shift = Imm >> 8;
436+
uint64_t Result = (((Imm & maxUIntN(8)) + 257) << Shift) - 256;
437+
Inst.addOperand(MCOperand::createImm(Result));
438+
return MCDisassembler::Success;
439+
}
440+
419441
static DecodeStatus decodeVMaskReg(MCInst &Inst, uint32_t RegNo,
420442
uint64_t Address,
421443
const MCDisassembler *Decoder) {
@@ -497,6 +519,20 @@ static DecodeStatus decodeUImmLog2XLenOperand(MCInst &Inst, uint32_t Imm,
497519
return MCDisassembler::Success;
498520
}
499521

522+
static DecodeStatus decodeUImm7SrliyOperand(MCInst &Inst, uint32_t Imm,
523+
int64_t Address,
524+
const MCDisassembler *Decoder) {
525+
assert(isUInt<7>(Imm) && "Invalid immediate");
526+
527+
uint32_t ExpectedValue =
528+
Decoder->getSubtargetInfo().hasFeature(RISCV::Feature64Bit) ? 64 : 32;
529+
if (Imm != ExpectedValue)
530+
return MCDisassembler::Fail;
531+
532+
Inst.addOperand(MCOperand::createImm(Imm));
533+
return MCDisassembler::Success;
534+
}
535+
500536
template <unsigned N>
501537
static DecodeStatus decodeUImmNonZeroOperand(MCInst &Inst, uint32_t Imm,
502538
int64_t Address,
@@ -699,6 +735,9 @@ static constexpr DecoderListEntry DecoderList32[]{
699735
{DecoderTableXAndes32, XAndesGroup, "Andes extensions"},
700736
{DecoderTableXSMT32, XSMTGroup, "SpacemiT extensions"},
701737
// Standard Extensions
738+
{DecoderTableRVYOnly32,
739+
{RISCV::FeatureStdExtY},
740+
"RVY-only standard 32-bit instructions"},
702741
{DecoderTable32, {}, "standard 32-bit instructions"},
703742
{DecoderTableRV32Only32, {}, "RV32-only standard 32-bit instructions"},
704743
{DecoderTableZfinx32, {}, "Zfinx (Float in Integer)"},

llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ enum OperandType : unsigned {
320320
OPERAND_UIMM7,
321321
OPERAND_UIMM7_LSB00,
322322
OPERAND_UIMM7_LSB000,
323+
OPERAND_UIMM7_SRLIY,
323324
OPERAND_UIMM8_LSB00,
324325
OPERAND_UIMM8,
325326
OPERAND_UIMM8_LSB000,

llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ class RISCVMCCodeEmitter : public MCCodeEmitter {
105105
SmallVectorImpl<MCFixup> &Fixups,
106106
const MCSubtargetInfo &STI) const;
107107

108+
unsigned getYBNDSWImmOpValue(const MCInst &MI, unsigned OpNo,
109+
SmallVectorImpl<MCFixup> &Fixups,
110+
const MCSubtargetInfo &STI) const;
111+
108112
unsigned getVMaskReg(const MCInst &MI, unsigned OpNo,
109113
SmallVectorImpl<MCFixup> &Fixups,
110114
const MCSubtargetInfo &STI) const;
@@ -718,6 +722,31 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
718722
return 0;
719723
}
720724

725+
unsigned
726+
RISCVMCCodeEmitter::getYBNDSWImmOpValue(const MCInst &MI, unsigned OpNo,
727+
SmallVectorImpl<MCFixup> &Fixups,
728+
const MCSubtargetInfo &STI) const {
729+
unsigned Imm = getImmOpValue(MI, OpNo, Fixups, STI);
730+
// The 10-bit immediate is encoded as `((imm[7:0] + 257) << imm[9:8]) - 256`.
731+
if (Imm <= 256) {
732+
assert(Imm > 0); // 1, 2, ..., 255, 256
733+
return Imm - 1;
734+
}
735+
if (Imm <= 768) {
736+
assert(Imm % 2 == 0); // 258, 260, ..., 766, 768
737+
return ((Imm - 258) >> 1) | (1 << 8);
738+
}
739+
if (Imm <= 1792) {
740+
assert(Imm % 4 == 0); // 772, 776, ..., 1788, 1792
741+
return ((Imm - 772) >> 2) | (2 << 8);
742+
}
743+
if (Imm <= 3840) {
744+
assert(Imm % 8 == 0); // 1800, 1808, ..., 3832, 3840
745+
return ((Imm - 1800) >> 3) | (3 << 8);
746+
}
747+
llvm_unreachable("Invalid immediate for YBNDSWI");
748+
}
749+
721750
unsigned RISCVMCCodeEmitter::getVMaskReg(const MCInst &MI, unsigned OpNo,
722751
SmallVectorImpl<MCFixup> &Fixups,
723752
const MCSubtargetInfo &STI) const {

llvm/lib/Target/RISCV/RISCVFeatures.td

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,9 @@ class RISCVExtensionBitmask<bits<3> groupID, int bitPos> {
6060

6161
// Version of RISCVExtension to be used for Experimental extensions. This
6262
// sets the Experimental flag and prepends experimental- to the -mattr name.
63-
class RISCVExperimentalExtension<int major, int minor, string desc,
64-
list<SubtargetFeature> implies = [],
65-
string fieldname = !subst("Feature", "Has", NAME),
66-
string value = "true">
63+
class RISCVExperimentalExtension<
64+
int major, int minor, string desc, list<SubtargetFeature> implies = [],
65+
string fieldname = !subst("Feature", "Has", NAME), string value = "true">
6766
: RISCVExtension<major, minor, desc, implies, fieldname, value, true> {
6867
let Experimental = true;
6968
}
@@ -1145,7 +1144,7 @@ def IsCapMode
11451144
: Predicate<"Subtarget->isCapMode()">,
11461145
AssemblerPredicate<(all_of FeatureCapMode), "Capability Pointer Mode">;
11471146
def NotCapMode : Predicate<"!Subtarget->isCapMode()">,
1148-
AssemblerPredicate<(all_of(not FeatureCapMode)),
1147+
AssemblerPredicate<(all_of (not FeatureCapMode)),
11491148
"Not Capability Pointer Mode">;
11501149

11511150
//===----------------------------------------------------------------------===//
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===-- RISCVInstrFormatsY.td --------------------------------*- tablegen -*-=//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file describes the RISC-V Y extension instruction formats.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
//===----------------------------------------------------------------------===//
14+
// Operand definitions.
15+
//===----------------------------------------------------------------------===//
16+
17+
def YBNDSWImmOperand : AsmOperandClass {
18+
let Name = "YBNDSWImm";
19+
let RenderMethod = "addImmOperands";
20+
let DiagnosticType = "InvalidYBNDSWImm";
21+
}
22+
23+
def ybndsw_imm : Operand<XLenVT>, ImmLeaf<XLenVT, [{
24+
return (Imm >= 1 && Imm <= 256) ||
25+
(Imm >= 258 && Imm <= 768 && (Imm % 2) == 0) ||
26+
(Imm >= 772 && Imm <= 1792 && (Imm % 4) == 0) ||
27+
(Imm >= 1800 && Imm <= 3840 && (Imm % 8) == 0);
28+
}]> {
29+
let EncoderMethod = "getYBNDSWImmOpValue";
30+
let ParserMatchClass = YBNDSWImmOperand;
31+
let DecoderMethod = "DecodeYBNDSWImm";
32+
let MIOperandInfo = (ops i32imm);
33+
}
34+
35+
def uimm7_srliy : RISCVUImmOp<7>, ImmLeaf<XLenVT, [{
36+
return Subtarget->is64Bit() ? Imm == 64 : Imm == 32;
37+
}]> {
38+
let ParserMatchClass = UImmAsmOperand<7, "Srliy">;
39+
let DecoderMethod = "decodeUImm7SrliyOperand";
40+
let MCOperandPredicate = [{
41+
int64_t Imm;
42+
if (!MCOp.evaluateAsConstantImm(Imm))
43+
return false;
44+
return Subtarget->is64Bit() ? Imm == 64 : Imm == 32;
45+
}];
46+
let OperandType = "OPERAND_UIMM7_SRLIY";
47+
}
48+
49+
//===----------------------------------------------------------------------===//
50+
// Instruction Formats
51+
//===----------------------------------------------------------------------===//
52+
53+
// Like an RVInstR, except rs2 is now an additional function code.
54+
class RVYInstSrcDst<bits<7> funct7, bits<5> funct5, bits<3> funct3,
55+
RISCVOpcode opcode, dag outs, dag ins, string opcodestr,
56+
string argstr>
57+
: RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
58+
bits<5> rs1;
59+
bits<5> rd;
60+
61+
let Inst{31 -25} = funct7;
62+
let Inst{24 -20} = funct5;
63+
let Inst{19 -15} = rs1;
64+
let Inst{14 -12} = funct3;
65+
let Inst{11 -7} = rd;
66+
let Inst{6 -0} = opcode.Value;
67+
}
68+
69+
class RVYInstSetBoundsImmFmt<dag outs, dag ins, string opcodestr, string argstr>
70+
: RVInstIBase<0b011, OPC_OP_IMM_32, outs, ins, opcodestr, argstr> {
71+
bits<5> rd;
72+
bits<5> rs1;
73+
bits<10> imm;
74+
75+
let Inst{31 -30} = 0b00;
76+
let Inst{29 -20} = imm;
77+
}

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2363,6 +2363,9 @@ include "RISCVInstrInfoZicfiss.td"
23632363
// Short Forward Branch
23642364
include "RISCVInstrInfoSFB.td"
23652365

2366+
// CHERI
2367+
include "RISCVInstrInfoY.td"
2368+
23662369
//===----------------------------------------------------------------------===//
23672370
// Vendor extensions
23682371
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)