Skip to content

Commit

Permalink
[RISCV] Add .insn support for compressed formats.
Browse files Browse the repository at this point in the history
We've supported .insn for non-compressed for a while. This finishes the compressed supported.

Reviewed By: asb

Differential Revision: https://reviews.llvm.org/D146663
  • Loading branch information
topperc committed Mar 27, 2023
1 parent 5c5fe3a commit 5e2445a
Show file tree
Hide file tree
Showing 8 changed files with 476 additions and 3 deletions.
90 changes: 87 additions & 3 deletions llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
Expand Up @@ -172,6 +172,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseVTypeI(OperandVector &Operands);
OperandMatchResultTy parseMaskReg(OperandVector &Operands);
OperandMatchResultTy parseInsnDirectiveOpcode(OperandVector &Operands);
OperandMatchResultTy parseInsnCDirectiveOpcode(OperandVector &Operands);
OperandMatchResultTy parseGPRAsFPR(OperandVector &Operands);
OperandMatchResultTy parseFRMArg(OperandVector &Operands);
OperandMatchResultTy parseFenceArg(OperandVector &Operands);
Expand Down Expand Up @@ -374,6 +375,13 @@ struct RISCVOperand final : public MCParsedAsmOperand {
RISCVMCRegisterClasses[RISCV::FPR64RegClassID].contains(Reg.RegNum) ||
RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg.RegNum));
}
bool isAnyRegC() const {
return Kind == KindTy::Register &&
(RISCVMCRegisterClasses[RISCV::GPRCRegClassID].contains(
Reg.RegNum) ||
RISCVMCRegisterClasses[RISCV::FPR64CRegClassID].contains(
Reg.RegNum));
}
bool isImm() const override { return Kind == KindTy::Immediate; }
bool isMem() const override { return false; }
bool isSystemRegister() const { return Kind == KindTy::SystemRegister; }
Expand Down Expand Up @@ -569,9 +577,11 @@ struct RISCVOperand final : public MCParsedAsmOperand {

bool isUImm2() const { return IsUImm<2>(); }
bool isUImm3() const { return IsUImm<3>(); }
bool isUImm4() const { return IsUImm<4>(); }
bool isUImm5() const { return IsUImm<5>(); }
bool isUImm6() const { return IsUImm<6>(); }
bool isUImm7() const { return IsUImm<7>(); }
bool isUImm8() const { return IsUImm<8>(); }

bool isRnumArg() const {
int64_t Imm;
Expand Down Expand Up @@ -1250,10 +1260,16 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
"immediate must be one of");
case Match_InvalidUImm3:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
case Match_InvalidUImm4:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
case Match_InvalidUImm5:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 5) - 1);
case Match_InvalidUImm6:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 6) - 1);
case Match_InvalidUImm7:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 7) - 1);
case Match_InvalidUImm8:
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 8) - 1);
case Match_InvalidSImm5:
return generateImmOutOfRangeError(Operands, ErrorInfo, -(1 << 4),
(1 << 4) - 1);
Expand Down Expand Up @@ -1539,6 +1555,67 @@ RISCVAsmParser::parseInsnDirectiveOpcode(OperandVector &Operands) {
return MatchOperand_ParseFail;
}

OperandMatchResultTy
RISCVAsmParser::parseInsnCDirectiveOpcode(OperandVector &Operands) {
SMLoc S = getLoc();
SMLoc E;
const MCExpr *Res;

switch (getLexer().getKind()) {
default:
return MatchOperand_NoMatch;
case AsmToken::LParen:
case AsmToken::Minus:
case AsmToken::Plus:
case AsmToken::Exclaim:
case AsmToken::Tilde:
case AsmToken::Integer:
case AsmToken::String: {
if (getParser().parseExpression(Res, E))
return MatchOperand_ParseFail;

auto *CE = dyn_cast<MCConstantExpr>(Res);
if (CE) {
int64_t Imm = CE->getValue();
if (Imm >= 0 && Imm <= 2) {
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
return MatchOperand_Success;
}
}

break;
}
case AsmToken::Identifier: {
StringRef Identifier;
if (getParser().parseIdentifier(Identifier))
return MatchOperand_ParseFail;

unsigned Opcode;
if (Identifier == "C0")
Opcode = 0;
else if (Identifier == "C1")
Opcode = 1;
else if (Identifier == "C2")
Opcode = 2;
else
break;

Res = MCConstantExpr::create(Opcode, getContext());
E = SMLoc::getFromPointer(S.getPointer() + Identifier.size());
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
return MatchOperand_Success;
}
case AsmToken::Percent: {
// Discard operand with modifier.
break;
}
}

Error(S, "opcode must be a valid opcode name or an immediate in the range "
"[0, 2]");
return MatchOperand_ParseFail;
}

OperandMatchResultTy
RISCVAsmParser::parseCSRSystemRegister(OperandVector &Operands) {
SMLoc S = getLoc();
Expand Down Expand Up @@ -2472,6 +2549,13 @@ bool RISCVAsmParser::parseDirectiveAttribute() {
return false;
}

bool isValidInsnFormat(StringRef Format, bool AllowC) {
return StringSwitch<bool>(Format)
.Cases("r", "r4", "i", "b", "sb", "u", "j", "uj", "s", true)
.Cases("cr", "ci", "ciw", "css", "cl", "cs", "ca", "cb", "cj", AllowC)
.Default(false);
}

/// parseDirectiveInsn
/// ::= .insn [ format encoding, (operands (, operands)*) ]
bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
Expand All @@ -2483,9 +2567,9 @@ bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
if (Parser.parseIdentifier(Format))
return Error(ErrorLoc, "expected instruction format");

if (Format != "r" && Format != "r4" && Format != "i" && Format != "b" &&
Format != "sb" && Format != "u" && Format != "j" && Format != "uj" &&
Format != "s")
bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
getSTI().hasFeature(RISCV::FeatureExtZca);
if (!isValidInsnFormat(Format, AllowC))
return Error(ErrorLoc, "invalid instruction format");

std::string FormatName = (".insn_" + Format).str();
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
Expand Up @@ -249,6 +249,7 @@ enum OperandType : unsigned {
OPERAND_UIMM7,
OPERAND_UIMM7_LSB00,
OPERAND_UIMM8_LSB00,
OPERAND_UIMM8,
OPERAND_UIMM8_LSB000,
OPERAND_UIMM9_LSB000,
OPERAND_UIMM10_LSB00_NONZERO,
Expand Down
166 changes: 166 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrFormatsC.td
Expand Up @@ -229,3 +229,169 @@ class RVInst16CSH<bits<6> funct6, bit funct1, bits<2> opcode, dag outs,
let Inst{4-2} = rs2;
let Inst{1-0} = opcode;
}

//===----------------------------------------------------------------------===//
// Instruction classes for .insn directives
//===----------------------------------------------------------------------===//

class DirectiveInsnCR<dag outs, dag ins, string argstr>
: RVInst16<outs, ins, "", "", [], InstFormatCR> {
bits<2> opcode;
bits<4> funct4;

bits<5> rs2;
bits<5> rd;

let Inst{15-12} = funct4;
let Inst{11-7} = rd;
let Inst{6-2} = rs2;
let Inst{1-0} = opcode;

let AsmString = ".insn cr " # argstr;
}

class DirectiveInsnCI<dag outs, dag ins, string argstr>
: RVInst16<outs, ins, "", "", [], InstFormatCI> {
bits<2> opcode;
bits<3> funct3;

bits<6> imm6;
bits<5> rd;

let Inst{15-13} = funct3;
let Inst{12} = imm6{5};
let Inst{11-7} = rd;
let Inst{6-2} = imm6{4-0};
let Inst{1-0} = opcode;

let AsmString = ".insn ci " # argstr;
}

class DirectiveInsnCIW<dag outs, dag ins, string argstr>
: RVInst16<outs, ins, "", "", [], InstFormatCIW> {
bits<2> opcode;
bits<3> funct3;

bits<8> imm8;
bits<3> rd;

let Inst{15-13} = funct3;
let Inst{12-5} = imm8;
let Inst{4-2} = rd;
let Inst{1-0} = opcode;

let AsmString = ".insn ciw " # argstr;
}

class DirectiveInsnCSS<dag outs, dag ins, string argstr>
: RVInst16<outs, ins, "", "", [], InstFormatCSS> {
bits<2> opcode;
bits<3> funct3;

bits<6> imm6;
bits<5> rs2;

let Inst{15-13} = funct3;
let Inst{12-7} = imm6;
let Inst{6-2} = rs2;
let Inst{1-0} = opcode;

let AsmString = ".insn css " # argstr;
}

class DirectiveInsnCL<dag outs, dag ins, string argstr>
: RVInst16<outs, ins, "", "", [], InstFormatCL> {
bits<2> opcode;
bits<3> funct3;

bits<5> imm5;
bits<3> rd;
bits<3> rs1;

let Inst{15-13} = funct3;
let Inst{12-10} = imm5{4-2};
let Inst{9-7} = rs1;
let Inst{6-5} = imm5{1-0};
let Inst{4-2} = rd;
let Inst{1-0} = opcode;

let AsmString = ".insn cl " # argstr;
}

class DirectiveInsnCS<dag outs, dag ins, string argstr>
: RVInst16<outs, ins, "", "", [], InstFormatCS> {
bits<2> opcode;
bits<3> funct3;

bits<5> imm5;
bits<3> rs2;
bits<3> rs1;

let Inst{15-13} = funct3;
let Inst{12-10} = imm5{4-2};
let Inst{9-7} = rs1;
let Inst{6-5} = imm5{1-0};
let Inst{4-2} = rs2;
let Inst{1-0} = opcode;

let AsmString = ".insn cs " # argstr;
}

class DirectiveInsnCA<dag outs, dag ins, string argstr>
: RVInst16<outs, ins, "", "", [], InstFormatCA> {
bits<2> opcode;
bits<6> funct6;
bits<2> funct2;

bits<3> rd;
bits<3> rs2;

let Inst{15-10} = funct6;
let Inst{9-7} = rd;
let Inst{6-5} = funct2;
let Inst{4-2} = rs2;
let Inst{1-0} = opcode;

let AsmString = ".insn ca " # argstr;
}

class DirectiveInsnCB<dag outs, dag ins, string argstr>
: RVInst16<outs, ins, "", "", [], InstFormatCB> {
bits<2> opcode;
bits<3> funct3;

bits<8> imm8;
bits<3> rs1;

let Inst{15-13} = funct3;
let Inst{12} = imm8{7};
let Inst{11-10} = imm8{3-2};
let Inst{9-7} = rs1;
let Inst{6-5} = imm8{6-5};
let Inst{4-3} = imm8{1-0};
let Inst{2} = imm8{4};
let Inst{1-0} = opcode;

let AsmString = ".insn cb " # argstr;
}

class DirectiveInsnCJ<dag outs, dag ins, string argstr>
: RVInst16<outs, ins, "", "", [], InstFormatCJ> {
bits<2> opcode;
bits<3> funct3;

bits<11> imm11;

let Inst{15-13} = funct3;
let Inst{12} = imm11{10};
let Inst{11} = imm11{3};
let Inst{10-9} = imm11{8-7};
let Inst{8} = imm11{9};
let Inst{7} = imm11{5};
let Inst{6} = imm11{6};
let Inst{5-3} = imm11{2-0};
let Inst{2} = imm11{4};
let Inst{1-0} = opcode;

let AsmString = ".insn cj " # argstr;
}
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
Expand Up @@ -1672,7 +1672,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
CASE_OPERAND_UIMM(3)
CASE_OPERAND_UIMM(4)
CASE_OPERAND_UIMM(5)
CASE_OPERAND_UIMM(6)
CASE_OPERAND_UIMM(7)
CASE_OPERAND_UIMM(8)
CASE_OPERAND_UIMM(12)
CASE_OPERAND_UIMM(20)
// clang-format on
Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Expand Up @@ -211,6 +211,13 @@ def uimm3 : Operand<XLenVT> {
let OperandNamespace = "RISCVOp";
}

def uimm4 : Operand<XLenVT> {
let ParserMatchClass = UImmAsmOperand<4>;
let DecoderMethod = "decodeUImmOperand<4>";
let OperandType = "OPERAND_UIMM4";
let OperandNamespace = "RISCVOp";
}

def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> {
let ParserMatchClass = UImmAsmOperand<5>;
let DecoderMethod = "decodeUImmOperand<5>";
Expand Down Expand Up @@ -246,6 +253,13 @@ def uimm7 : Operand<XLenVT> {
let OperandNamespace = "RISCVOp";
}

def uimm8 : Operand<XLenVT> {
let ParserMatchClass = UImmAsmOperand<8>;
let DecoderMethod = "decodeUImmOperand<8>";
let OperandType = "OPERAND_UIMM8";
let OperandNamespace = "RISCVOp";
}

def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> {
let ParserMatchClass = SImmAsmOperand<12>;
let EncoderMethod = "getImmOpValue";
Expand Down

0 comments on commit 5e2445a

Please sign in to comment.