Skip to content

Commit a0222b5

Browse files
arichardsonjrtc27veselypeta
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 862c654 commit a0222b5

File tree

10 files changed

+491
-6
lines changed

10 files changed

+491
-6
lines changed

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

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

492+
bool isYGPR() const {
493+
return Kind == KindTy::Register &&
494+
RISCVMCRegisterClasses[RISCV::YGPRRegClassID].contains(Reg.Reg);
495+
}
496+
492497
bool isGPRPair() const {
493498
return Kind == KindTy::Register &&
494499
RISCVMCRegisterClasses[RISCV::GPRPairRegClassID].contains(Reg.Reg);
@@ -763,6 +768,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {
763768
});
764769
}
765770

771+
bool isUImm7Srliy() const {
772+
return isUImmPred(
773+
[this](int64_t Imm) { return isRV64Expr() ? Imm == 64 : Imm == 32; });
774+
}
775+
766776
bool isUImm8GE32() const {
767777
return isUImmPred([](int64_t Imm) { return isUInt<8>(Imm) && Imm >= 32; });
768778
}
@@ -795,6 +805,29 @@ struct RISCVOperand final : public MCParsedAsmOperand {
795805
return IsConstantImm && isInt<N>(fixImmediateForRV32(Imm, isRV64Expr()));
796806
}
797807

808+
bool isYBNDSWImm() const {
809+
if (!isExpr())
810+
return false;
811+
812+
int64_t Imm;
813+
bool IsConstantImm = evaluateConstantExpr(getExpr(), Imm);
814+
if (!IsConstantImm)
815+
return false;
816+
// The immediate is encoded using `((imm[7:0] + 257) << imm[9:8]) - 256`
817+
// which gives the following valid ranges:
818+
if (Imm < 1)
819+
return false;
820+
if (Imm <= 256)
821+
return true;
822+
if (Imm <= 768)
823+
return (Imm % 2) == 0;
824+
if (Imm <= 1792)
825+
return (Imm % 4) == 0;
826+
if (Imm <= 3840)
827+
return (Imm % 8) == 0;
828+
return false;
829+
}
830+
798831
template <class Pred> bool isSImmPred(Pred p) const {
799832
int64_t Imm;
800833
if (!isExpr())
@@ -1302,6 +1335,11 @@ static MCRegister convertFPR64ToFPR128(MCRegister Reg) {
13021335
return Reg - RISCV::F0_D + RISCV::F0_Q;
13031336
}
13041337

1338+
static MCRegister convertGPRToYGPR(MCRegister Reg) {
1339+
assert(Reg >= RISCV::X0 && Reg <= RISCV::X31 && "Invalid register");
1340+
return Reg - RISCV::X0 + RISCV::X0_Y;
1341+
}
1342+
13051343
static MCRegister convertVRToVRMx(const MCRegisterInfo &RI, MCRegister Reg,
13061344
unsigned Kind) {
13071345
unsigned RegClassID;
@@ -1329,7 +1367,11 @@ unsigned RISCVAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
13291367
bool IsRegFPR64C =
13301368
RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(Reg);
13311369
bool IsRegVR = RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg);
1332-
1370+
if (Op.isGPR() && Kind == MCK_YGPR) {
1371+
// GPR and capability GPR use the same register names, convert if required.
1372+
Op.Reg.Reg = convertGPRToYGPR(Reg);
1373+
return Match_Success;
1374+
}
13331375
if (IsRegFPR64 && Kind == MCK_FPR128) {
13341376
Op.Reg.Reg = convertFPR64ToFPR128(Reg);
13351377
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,
@@ -702,6 +738,9 @@ static constexpr DecoderListEntry DecoderList32[]{
702738
{DecoderTableXAndes32, XAndesGroup, "Andes extensions"},
703739
{DecoderTableXSMT32, XSMTGroup, "SpacemiT extensions"},
704740
// Standard Extensions
741+
{DecoderTableRVYOnly32,
742+
{RISCV::FeatureStdExtY},
743+
"RVY-only standard 32-bit instructions"},
705744
{DecoderTable32, {}, "standard 32-bit instructions"},
706745
{DecoderTableRV32Only32, {}, "RV32-only standard 32-bit instructions"},
707746
{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
@@ -380,6 +380,7 @@ enum OperandType : unsigned {
380380
OPERAND_UIMM7,
381381
OPERAND_UIMM7_LSB00,
382382
OPERAND_UIMM7_LSB000,
383+
OPERAND_UIMM7_SRLIY,
383384
OPERAND_UIMM8_LSB00,
384385
OPERAND_UIMM8,
385386
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;
@@ -719,6 +723,31 @@ uint64_t RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
719723
return 0;
720724
}
721725

726+
unsigned
727+
RISCVMCCodeEmitter::getYBNDSWImmOpValue(const MCInst &MI, unsigned OpNo,
728+
SmallVectorImpl<MCFixup> &Fixups,
729+
const MCSubtargetInfo &STI) const {
730+
unsigned Imm = getImmOpValue(MI, OpNo, Fixups, STI);
731+
// The 10-bit immediate is encoded as `((imm[7:0] + 257) << imm[9:8]) - 256`.
732+
if (Imm <= 256) {
733+
assert(Imm > 0); // 1, 2, ..., 255, 256
734+
return Imm - 1;
735+
}
736+
if (Imm <= 768) {
737+
assert(Imm % 2 == 0); // 258, 260, ..., 766, 768
738+
return ((Imm - 258) >> 1) | (1 << 8);
739+
}
740+
if (Imm <= 1792) {
741+
assert(Imm % 4 == 0); // 772, 776, ..., 1788, 1792
742+
return ((Imm - 772) >> 2) | (2 << 8);
743+
}
744+
if (Imm <= 3840) {
745+
assert(Imm % 8 == 0); // 1800, 1808, ..., 3832, 3840
746+
return ((Imm - 1800) >> 3) | (3 << 8);
747+
}
748+
llvm_unreachable("Invalid immediate for YBNDSWI");
749+
}
750+
722751
unsigned RISCVMCCodeEmitter::getVMaskReg(const MCInst &MI, unsigned OpNo,
723752
SmallVectorImpl<MCFixup> &Fixups,
724753
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
}
@@ -1153,7 +1152,7 @@ def IsCapMode
11531152
: Predicate<"Subtarget->isCapMode()">,
11541153
AssemblerPredicate<(all_of FeatureCapMode), "Capability Pointer Mode">;
11551154
def NotCapMode : Predicate<"!Subtarget->isCapMode()">,
1156-
AssemblerPredicate<(all_of(not FeatureCapMode)),
1155+
AssemblerPredicate<(all_of (not FeatureCapMode)),
11571156
"Not Capability Pointer Mode">;
11581157

11591158
//===----------------------------------------------------------------------===//
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
@@ -2366,6 +2366,9 @@ include "RISCVInstrInfoZicfiss.td"
23662366
// Short Forward Branch
23672367
include "RISCVInstrInfoSFB.td"
23682368

2369+
// CHERI
2370+
include "RISCVInstrInfoY.td"
2371+
23692372
//===----------------------------------------------------------------------===//
23702373
// Vendor extensions
23712374
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)