mirror of
https://git.proxmox.com/git/llvm-toolchain
synced 2025-10-18 18:37:45 +00:00
Add patch to fix insn support on riscv
This commit is contained in:
parent
ac224cb321
commit
2c91d993b2
566
debian/patches/risc/riscv-insn-support.patch
vendored
Normal file
566
debian/patches/risc/riscv-insn-support.patch
vendored
Normal file
@ -0,0 +1,566 @@
|
||||
From d5ea5842d627e63f780b524dddf67dac7222779c Mon Sep 17 00:00:00 2001
|
||||
From: Craig Topper <craig.topper@sifive.com>
|
||||
Date: Sun, 12 Sep 2021 13:45:52 -0700
|
||||
Origin: upstream + rustc: https://github.com/rust-lang/llvm-project/pull/121
|
||||
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/llvm-toolchain-13/+bug/1973041
|
||||
Applied-Upstream: from version 14.0.0-rc1
|
||||
Subject: [PATCH] [RISCV] Initial support .insn directive for the assembler.
|
||||
|
||||
This allows for a custom encoding to be emitted. It can also be
|
||||
used with inline assembly to allow the custom instruction to be
|
||||
register allocated like other instructions.
|
||||
|
||||
I initially started from SystemZ's implementation, but some of
|
||||
the formats allow operands to be specified in multiple ways so I
|
||||
had to add support for matching different operand class lists for
|
||||
the same format. That implementation is a simplified version of
|
||||
what is emitted by tablegen for regular instructions.
|
||||
|
||||
I've left out the compressed formats. And I haven't supported the
|
||||
named opcodes like LUI or OP_IMM_32. Those can be added in future
|
||||
patches.
|
||||
|
||||
Documentation can be found here https://sourceware.org/binutils/docs-2.37/as/RISC_002dV_002dFormats.html
|
||||
|
||||
Reviewed By: jrtc27, MaskRay
|
||||
|
||||
Differential Revision: https://reviews.llvm.org/D108602
|
||||
---
|
||||
.../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 63 ++++++++-
|
||||
.../Target/RISCV/MCTargetDesc/RISCVBaseInfo.h | 5 +-
|
||||
.../RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp | 2 +-
|
||||
llvm/lib/Target/RISCV/RISCVInstrFormats.td | 132 ++++++++++++++++++
|
||||
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 102 ++++++++++++++
|
||||
llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 12 ++
|
||||
llvm/test/MC/RISCV/insn-invalid.s | 17 +++
|
||||
llvm/test/MC/RISCV/insn.s | 77 ++++++++++
|
||||
8 files changed, 407 insertions(+), 3 deletions(-)
|
||||
create mode 100644 llvm/test/MC/RISCV/insn-invalid.s
|
||||
create mode 100644 llvm/test/MC/RISCV/insn.s
|
||||
|
||||
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
|
||||
index 87496e0b9330f..ff2841a50d2d3 100644
|
||||
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
|
||||
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
|
||||
@@ -169,6 +169,7 @@ class RISCVAsmParser : public MCTargetAsmParser {
|
||||
|
||||
bool parseDirectiveOption();
|
||||
bool parseDirectiveAttribute();
|
||||
+ bool parseDirectiveInsn(SMLoc L);
|
||||
|
||||
void setFeatureBits(uint64_t Feature, StringRef FeatureString) {
|
||||
if (!(getSTI().getFeatureBits()[Feature])) {
|
||||
@@ -504,6 +505,24 @@ struct RISCVOperand : public MCParsedAsmOperand {
|
||||
return (isRV64() && isUInt<5>(Imm)) || isUInt<4>(Imm);
|
||||
}
|
||||
|
||||
+ bool isUImm2() const {
|
||||
+ int64_t Imm;
|
||||
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
|
||||
+ if (!isImm())
|
||||
+ return false;
|
||||
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
|
||||
+ return IsConstantImm && isUInt<2>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
|
||||
+ }
|
||||
+
|
||||
+ bool isUImm3() const {
|
||||
+ int64_t Imm;
|
||||
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
|
||||
+ if (!isImm())
|
||||
+ return false;
|
||||
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
|
||||
+ return IsConstantImm && isUInt<3>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
|
||||
+ }
|
||||
+
|
||||
bool isUImm5() const {
|
||||
int64_t Imm;
|
||||
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
|
||||
@@ -513,6 +532,15 @@ struct RISCVOperand : public MCParsedAsmOperand {
|
||||
return IsConstantImm && isUInt<5>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
|
||||
}
|
||||
|
||||
+ bool isUImm7() const {
|
||||
+ int64_t Imm;
|
||||
+ RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
|
||||
+ if (!isImm())
|
||||
+ return false;
|
||||
+ bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
|
||||
+ return IsConstantImm && isUInt<7>(Imm) && VK == RISCVMCExpr::VK_RISCV_None;
|
||||
+ }
|
||||
+
|
||||
bool isSImm5() const {
|
||||
if (!isImm())
|
||||
return false;
|
||||
@@ -1835,8 +1863,10 @@ bool RISCVAsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
|
||||
if (IDVal == ".option")
|
||||
return parseDirectiveOption();
|
||||
- else if (IDVal == ".attribute")
|
||||
+ if (IDVal == ".attribute")
|
||||
return parseDirectiveAttribute();
|
||||
+ if (IDVal == ".insn")
|
||||
+ return parseDirectiveInsn(DirectiveID.getLoc());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2200,6 +2230,37 @@ bool RISCVAsmParser::parseDirectiveAttribute() {
|
||||
return false;
|
||||
}
|
||||
|
||||
+/// parseDirectiveInsn
|
||||
+/// ::= .insn [ format encoding, (operands (, operands)*) ]
|
||||
+bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
|
||||
+ MCAsmParser &Parser = getParser();
|
||||
+
|
||||
+ // Expect instruction format as identifier.
|
||||
+ StringRef Format;
|
||||
+ SMLoc ErrorLoc = Parser.getTok().getLoc();
|
||||
+ 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")
|
||||
+ return Error(ErrorLoc, "invalid instruction format");
|
||||
+
|
||||
+ std::string FormatName = (".insn_" + Format).str();
|
||||
+
|
||||
+ ParseInstructionInfo Info;
|
||||
+ SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> Operands;
|
||||
+
|
||||
+ if (ParseInstruction(Info, FormatName, L, Operands))
|
||||
+ return true;
|
||||
+
|
||||
+ unsigned Opcode;
|
||||
+ uint64_t ErrorInfo;
|
||||
+ return MatchAndEmitInstruction(L, Opcode, Operands, Parser.getStreamer(),
|
||||
+ ErrorInfo,
|
||||
+ /*MatchingInlineAsm=*/false);
|
||||
+}
|
||||
+
|
||||
void RISCVAsmParser::emitToStreamer(MCStreamer &S, const MCInst &Inst) {
|
||||
MCInst CInst;
|
||||
bool Res = compressInst(CInst, Inst, getSTI(), S.getContext());
|
||||
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
|
||||
index 9bdd2003cb15d..b837c4e25270b 100644
|
||||
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
|
||||
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
|
||||
@@ -158,8 +158,11 @@ enum {
|
||||
namespace RISCVOp {
|
||||
enum OperandType : unsigned {
|
||||
OPERAND_FIRST_RISCV_IMM = MCOI::OPERAND_FIRST_TARGET,
|
||||
- OPERAND_UIMM4 = OPERAND_FIRST_RISCV_IMM,
|
||||
+ OPERAND_UIMM2 = OPERAND_FIRST_RISCV_IMM,
|
||||
+ OPERAND_UIMM3,
|
||||
+ OPERAND_UIMM4,
|
||||
OPERAND_UIMM5,
|
||||
+ OPERAND_UIMM7,
|
||||
OPERAND_UIMM12,
|
||||
OPERAND_SIMM12,
|
||||
OPERAND_UIMM20,
|
||||
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
|
||||
index 1ef276b101003..14d0191a505fc 100644
|
||||
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
|
||||
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp
|
||||
@@ -358,7 +358,7 @@ unsigned RISCVMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo,
|
||||
}
|
||||
} else if (Kind == MCExpr::SymbolRef &&
|
||||
cast<MCSymbolRefExpr>(Expr)->getKind() == MCSymbolRefExpr::VK_None) {
|
||||
- if (Desc.getOpcode() == RISCV::JAL) {
|
||||
+ if (MIFrm == RISCVII::InstFormatJ) {
|
||||
FixupKind = RISCV::fixup_riscv_jal;
|
||||
} else if (MIFrm == RISCVII::InstFormatB) {
|
||||
FixupKind = RISCV::fixup_riscv_branch;
|
||||
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
|
||||
index 8e9d245f13eb0..944650c870b62 100644
|
||||
--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
|
||||
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
|
||||
@@ -406,3 +406,135 @@ class RVInstJ<RISCVOpcode opcode, dag outs, dag ins, string opcodestr,
|
||||
let Inst{11-7} = rd;
|
||||
let Opcode = opcode.Value;
|
||||
}
|
||||
+
|
||||
+//===----------------------------------------------------------------------===//
|
||||
+// Instruction classes for .insn directives
|
||||
+//===----------------------------------------------------------------------===//
|
||||
+
|
||||
+class DirectiveInsnR<dag outs, dag ins, string argstr>
|
||||
+ : RVInst<outs, ins, "", "", [], InstFormatR> {
|
||||
+ bits<7> opcode;
|
||||
+ bits<7> funct7;
|
||||
+ bits<3> funct3;
|
||||
+
|
||||
+ bits<5> rs2;
|
||||
+ bits<5> rs1;
|
||||
+ bits<5> rd;
|
||||
+
|
||||
+ let Inst{31-25} = funct7;
|
||||
+ let Inst{24-20} = rs2;
|
||||
+ let Inst{19-15} = rs1;
|
||||
+ let Inst{14-12} = funct3;
|
||||
+ let Inst{11-7} = rd;
|
||||
+ let Opcode = opcode;
|
||||
+
|
||||
+ let AsmString = ".insn r " # argstr;
|
||||
+}
|
||||
+
|
||||
+class DirectiveInsnR4<dag outs, dag ins, string argstr>
|
||||
+ : RVInst<outs, ins, "", "", [], InstFormatR4> {
|
||||
+ bits<7> opcode;
|
||||
+ bits<2> funct2;
|
||||
+ bits<3> funct3;
|
||||
+
|
||||
+ bits<5> rs3;
|
||||
+ bits<5> rs2;
|
||||
+ bits<5> rs1;
|
||||
+ bits<5> rd;
|
||||
+
|
||||
+ let Inst{31-27} = rs3;
|
||||
+ let Inst{26-25} = funct2;
|
||||
+ let Inst{24-20} = rs2;
|
||||
+ let Inst{19-15} = rs1;
|
||||
+ let Inst{14-12} = funct3;
|
||||
+ let Inst{11-7} = rd;
|
||||
+ let Opcode = opcode;
|
||||
+
|
||||
+ let AsmString = ".insn r4 " # argstr;
|
||||
+}
|
||||
+
|
||||
+class DirectiveInsnI<dag outs, dag ins, string argstr>
|
||||
+ : RVInst<outs, ins, "", "", [], InstFormatI> {
|
||||
+ bits<7> opcode;
|
||||
+ bits<3> funct3;
|
||||
+
|
||||
+ bits<12> imm12;
|
||||
+ bits<5> rs1;
|
||||
+ bits<5> rd;
|
||||
+
|
||||
+ let Inst{31-20} = imm12;
|
||||
+ let Inst{19-15} = rs1;
|
||||
+ let Inst{14-12} = funct3;
|
||||
+ let Inst{11-7} = rd;
|
||||
+ let Opcode = opcode;
|
||||
+
|
||||
+ let AsmString = ".insn i " # argstr;
|
||||
+}
|
||||
+
|
||||
+class DirectiveInsnS<dag outs, dag ins, string argstr>
|
||||
+ : RVInst<outs, ins, "", "", [], InstFormatS> {
|
||||
+ bits<7> opcode;
|
||||
+ bits<3> funct3;
|
||||
+
|
||||
+ bits<12> imm12;
|
||||
+ bits<5> rs2;
|
||||
+ bits<5> rs1;
|
||||
+
|
||||
+ let Inst{31-25} = imm12{11-5};
|
||||
+ let Inst{24-20} = rs2;
|
||||
+ let Inst{19-15} = rs1;
|
||||
+ let Inst{14-12} = funct3;
|
||||
+ let Inst{11-7} = imm12{4-0};
|
||||
+ let Opcode = opcode;
|
||||
+
|
||||
+ let AsmString = ".insn s " # argstr;
|
||||
+}
|
||||
+
|
||||
+class DirectiveInsnB<dag outs, dag ins, string argstr>
|
||||
+ : RVInst<outs, ins, "", "", [], InstFormatB> {
|
||||
+ bits<7> opcode;
|
||||
+ bits<3> funct3;
|
||||
+
|
||||
+ bits<12> imm12;
|
||||
+ bits<5> rs2;
|
||||
+ bits<5> rs1;
|
||||
+
|
||||
+ let Inst{31} = imm12{11};
|
||||
+ let Inst{30-25} = imm12{9-4};
|
||||
+ let Inst{24-20} = rs2;
|
||||
+ let Inst{19-15} = rs1;
|
||||
+ let Inst{14-12} = funct3;
|
||||
+ let Inst{11-8} = imm12{3-0};
|
||||
+ let Inst{7} = imm12{10};
|
||||
+ let Opcode = opcode;
|
||||
+
|
||||
+ let AsmString = ".insn b " # argstr;
|
||||
+}
|
||||
+
|
||||
+class DirectiveInsnU<dag outs, dag ins, string argstr>
|
||||
+ : RVInst<outs, ins, "", "", [], InstFormatU> {
|
||||
+ bits<7> opcode;
|
||||
+
|
||||
+ bits<20> imm20;
|
||||
+ bits<5> rd;
|
||||
+
|
||||
+ let Inst{31-12} = imm20;
|
||||
+ let Inst{11-7} = rd;
|
||||
+ let Opcode = opcode;
|
||||
+
|
||||
+ let AsmString = ".insn u " # argstr;
|
||||
+}
|
||||
+
|
||||
+class DirectiveInsnJ<dag outs, dag ins, string argstr>
|
||||
+ : RVInst<outs, ins, "", "", [], InstFormatJ> {
|
||||
+ bits<7> opcode;
|
||||
+
|
||||
+ bits<20> imm20;
|
||||
+ bits<5> rd;
|
||||
+
|
||||
+ let Inst{31-12} = imm20;
|
||||
+ let Inst{11-7} = rd;
|
||||
+ let Opcode = opcode;
|
||||
+
|
||||
+ let AsmString = ".insn j " # argstr;
|
||||
+}
|
||||
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
|
||||
index 949fff25e9e0a..1d6e4f04fce49 100644
|
||||
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
|
||||
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
|
||||
@@ -152,6 +152,20 @@ def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{
|
||||
let OperandNamespace = "RISCVOp";
|
||||
}
|
||||
|
||||
+def uimm2 : Operand<XLenVT> {
|
||||
+ let ParserMatchClass = UImmAsmOperand<2>;
|
||||
+ let DecoderMethod = "decodeUImmOperand<2>";
|
||||
+ let OperandType = "OPERAND_UIMM2";
|
||||
+ let OperandNamespace = "RISCVOp";
|
||||
+}
|
||||
+
|
||||
+def uimm3 : Operand<XLenVT> {
|
||||
+ let ParserMatchClass = UImmAsmOperand<3>;
|
||||
+ let DecoderMethod = "decodeUImmOperand<3>";
|
||||
+ let OperandType = "OPERAND_UIMM3";
|
||||
+ let OperandNamespace = "RISCVOp";
|
||||
+}
|
||||
+
|
||||
def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> {
|
||||
let ParserMatchClass = UImmAsmOperand<5>;
|
||||
let DecoderMethod = "decodeUImmOperand<5>";
|
||||
@@ -159,6 +173,13 @@ def uimm5 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<5>(Imm);}]> {
|
||||
let OperandNamespace = "RISCVOp";
|
||||
}
|
||||
|
||||
+def uimm7 : Operand<XLenVT> {
|
||||
+ let ParserMatchClass = UImmAsmOperand<7>;
|
||||
+ let DecoderMethod = "decodeUImmOperand<7>";
|
||||
+ let OperandType = "OPERAND_UIMM7";
|
||||
+ let OperandNamespace = "RISCVOp";
|
||||
+}
|
||||
+
|
||||
def simm12 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isInt<12>(Imm);}]> {
|
||||
let ParserMatchClass = SImmAsmOperand<12>;
|
||||
let EncoderMethod = "getImmOpValue";
|
||||
@@ -848,6 +869,87 @@ def : MnemonicAlias<"sbreak", "ebreak">;
|
||||
// that don't support this alias.
|
||||
def : InstAlias<"zext.b $rd, $rs", (ANDI GPR:$rd, GPR:$rs, 0xFF), 0>;
|
||||
|
||||
+//===----------------------------------------------------------------------===//
|
||||
+// .insn directive instructions
|
||||
+//===----------------------------------------------------------------------===//
|
||||
+
|
||||
+// isCodeGenOnly = 1 to hide them from the tablegened assembly parser.
|
||||
+let isCodeGenOnly = 1, hasSideEffects = 1, mayLoad = 1, mayStore = 1,
|
||||
+ hasNoSchedulingInfo = 1 in {
|
||||
+def InsnR : DirectiveInsnR<(outs AnyReg:$rd), (ins uimm7:$opcode, uimm3:$funct3,
|
||||
+ uimm7:$funct7, AnyReg:$rs1,
|
||||
+ AnyReg:$rs2),
|
||||
+ "$opcode, $funct3, $funct7, $rd, $rs1, $rs2">;
|
||||
+def InsnR4 : DirectiveInsnR4<(outs AnyReg:$rd), (ins uimm7:$opcode,
|
||||
+ uimm3:$funct3,
|
||||
+ uimm2:$funct2,
|
||||
+ AnyReg:$rs1, AnyReg:$rs2,
|
||||
+ AnyReg:$rs3),
|
||||
+ "$opcode, $funct3, $funct2, $rd, $rs1, $rs2, $rs3">;
|
||||
+def InsnI : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7:$opcode, uimm3:$funct3,
|
||||
+ AnyReg:$rs1, simm12:$imm12),
|
||||
+ "$opcode, $funct3, $rd, $rs1, $imm12">;
|
||||
+def InsnI_Mem : DirectiveInsnI<(outs AnyReg:$rd), (ins uimm7:$opcode,
|
||||
+ uimm3:$funct3,
|
||||
+ AnyReg:$rs1,
|
||||
+ simm12:$imm12),
|
||||
+ "$opcode, $funct3, $rd, ${imm12}(${rs1})">;
|
||||
+def InsnB : DirectiveInsnB<(outs), (ins uimm7:$opcode, uimm3:$funct3,
|
||||
+ AnyReg:$rs1, AnyReg:$rs2,
|
||||
+ simm13_lsb0:$imm12),
|
||||
+ "$opcode, $funct3, $rs1, $rs2, $imm12">;
|
||||
+def InsnU : DirectiveInsnU<(outs AnyReg:$rd), (ins uimm7:$opcode,
|
||||
+ uimm20_lui:$imm20),
|
||||
+ "$opcode, $rd, $imm20">;
|
||||
+def InsnJ : DirectiveInsnJ<(outs AnyReg:$rd), (ins uimm7:$opcode,
|
||||
+ simm21_lsb0_jal:$imm20),
|
||||
+ "$opcode, $rd, $imm20">;
|
||||
+def InsnS : DirectiveInsnS<(outs), (ins uimm7:$opcode, uimm3:$funct3,
|
||||
+ AnyReg:$rs2, AnyReg:$rs1,
|
||||
+ simm12:$imm12),
|
||||
+ "$opcode, $funct3, $rs2, ${imm12}(${rs1})">;
|
||||
+}
|
||||
+
|
||||
+// Use InstAliases to match these so that we can combine the insn and format
|
||||
+// into a mnemonic to use as the key for the tablegened asm matcher table. The
|
||||
+// parser will take care of creating these fake mnemonics and will only do it
|
||||
+// for known formats.
|
||||
+let EmitPriority = 0 in {
|
||||
+def : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2",
|
||||
+ (InsnR AnyReg:$rd, uimm7:$opcode, uimm3:$funct3, uimm7:$funct7,
|
||||
+ AnyReg:$rs1, AnyReg:$rs2)>;
|
||||
+// Accept 4 register form of ".insn r" as alias for ".insn r4".
|
||||
+def : InstAlias<".insn_r $opcode, $funct3, $funct7, $rd, $rs1, $rs2, $rs3",
|
||||
+ (InsnR4 AnyReg:$rd, uimm7:$opcode, uimm3:$funct3, uimm7:$funct7,
|
||||
+ AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>;
|
||||
+def : InstAlias<".insn_r4 $opcode, $funct3, $funct7, $rd, $rs1, $rs2, $rs3",
|
||||
+ (InsnR4 AnyReg:$rd, uimm7:$opcode, uimm3:$funct3, uimm7:$funct7,
|
||||
+ AnyReg:$rs1, AnyReg:$rs2, AnyReg:$rs3)>;
|
||||
+def : InstAlias<".insn_i $opcode, $funct3, $rd, $rs1, $imm12",
|
||||
+ (InsnI AnyReg:$rd, uimm7:$opcode, uimm3:$funct3, AnyReg:$rs1,
|
||||
+ simm12:$imm12)>;
|
||||
+def : InstAlias<".insn_i $opcode, $funct3, $rd, ${imm12}(${rs1})",
|
||||
+ (InsnI_Mem AnyReg:$rd, uimm7:$opcode, uimm3:$funct3,
|
||||
+ AnyReg:$rs1, simm12:$imm12)>;
|
||||
+def : InstAlias<".insn_b $opcode, $funct3, $rs1, $rs2, $imm12",
|
||||
+ (InsnB uimm7:$opcode, uimm3:$funct3, AnyReg:$rs1,
|
||||
+ AnyReg:$rs2, simm13_lsb0:$imm12)>;
|
||||
+// Accept sb as an alias for b.
|
||||
+def : InstAlias<".insn_sb $opcode, $funct3, $rs1, $rs2, $imm12",
|
||||
+ (InsnB uimm7:$opcode, uimm3:$funct3, AnyReg:$rs1,
|
||||
+ AnyReg:$rs2, simm13_lsb0:$imm12)>;
|
||||
+def : InstAlias<".insn_u $opcode, $rd, $imm20",
|
||||
+ (InsnU AnyReg:$rd, uimm7:$opcode, uimm20_lui:$imm20)>;
|
||||
+def : InstAlias<".insn_j $opcode, $rd, $imm20",
|
||||
+ (InsnJ AnyReg:$rd, uimm7:$opcode, simm21_lsb0_jal:$imm20)>;
|
||||
+// Accept uj as an alias for j.
|
||||
+def : InstAlias<".insn_uj $opcode, $rd, $imm20",
|
||||
+ (InsnJ AnyReg:$rd, uimm7:$opcode, simm21_lsb0_jal:$imm20)>;
|
||||
+def : InstAlias<".insn_s $opcode, $funct3, $rs2, ${imm12}(${rs1})",
|
||||
+ (InsnS uimm7:$opcode, uimm3:$funct3, AnyReg:$rs2,
|
||||
+ AnyReg:$rs1, simm12:$imm12)>;
|
||||
+}
|
||||
+
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pseudo-instructions and codegen patterns
|
||||
//
|
||||
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
|
||||
index fde75206889c8..4dbeb61c48159 100644
|
||||
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
|
||||
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
|
||||
@@ -557,3 +557,15 @@ foreach m = LMULList.m in {
|
||||
def FFLAGS : RISCVReg<0, "fflags">;
|
||||
def FRM : RISCVReg<0, "frm">;
|
||||
def FCSR : RISCVReg<0, "fcsr">;
|
||||
+
|
||||
+// Any type register. Used for .insn directives when we don't know what the
|
||||
+// register types could be.
|
||||
+// NOTE: The alignment and size are bogus values. The Size needs to be non-zero
|
||||
+// or tablegen will use "untyped" to determine the size which will assert.
|
||||
+let isAllocatable = 0 in
|
||||
+def AnyReg : RegisterClass<"RISCV", [untyped], 32,
|
||||
+ (add (sequence "X%u", 0, 31),
|
||||
+ (sequence "F%u_D", 0, 31),
|
||||
+ (sequence "V%u", 0, 31))> {
|
||||
+ let Size = 32;
|
||||
+}
|
||||
diff --git a/llvm/test/MC/RISCV/insn-invalid.s b/llvm/test/MC/RISCV/insn-invalid.s
|
||||
new file mode 100644
|
||||
index 0000000000000..5d7eaf69f01dc
|
||||
--- /dev/null
|
||||
+++ b/llvm/test/MC/RISCV/insn-invalid.s
|
||||
@@ -0,0 +1,17 @@
|
||||
+# RUN: not llvm-mc -triple riscv32 < %s 2>&1 | FileCheck %s
|
||||
+
|
||||
+# Too many operands
|
||||
+.insn i 0x13, 0, a0, a1, 13, 14 # CHECK: :[[@LINE]]:33: error: invalid operand for instruction
|
||||
+.insn r 0x43, 0, 0, fa0, fa1, fa2, fa3, fa4 # CHECK: :[[@LINE]]:44: error: invalid operand for instruction
|
||||
+
|
||||
+# Too few operands
|
||||
+.insn r 0x33, 0, 0, a0, a1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
|
||||
+.insn i 0x13, 0, a0, a1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
|
||||
+
|
||||
+.insn r 0x33, 0, 0, a0, 13 # CHECK: :[[@LINE]]:28: error: invalid operand for instruction
|
||||
+.insn i 0x13, 0, a0, a1, a2 # CHECK: :[[@LINE]]:28: error: operand must be a symbol with %lo/%pcrel_lo/%tprel_lo modifier or an integer in the range [-2048, 2047]
|
||||
+
|
||||
+.insn q 0x13, 0, a0, a1, 13, 14 # CHECK: :[[@LINE]]:7: error: invalid instruction format
|
||||
+
|
||||
+# Make fake mnemonics we use to match these in the tablegened asm match table isn't exposed.
|
||||
+.insn_i 0x13, 0, a0, a1, 13, 14 # CHECK: :[[@LINE]]:1: error: unknown directive
|
||||
diff --git a/llvm/test/MC/RISCV/insn.s b/llvm/test/MC/RISCV/insn.s
|
||||
new file mode 100644
|
||||
index 0000000000000..1e02e22f965ad
|
||||
--- /dev/null
|
||||
+++ b/llvm/test/MC/RISCV/insn.s
|
||||
@@ -0,0 +1,77 @@
|
||||
+# RUN: llvm-mc %s -triple=riscv32 -mattr=+f -riscv-no-aliases -show-encoding \
|
||||
+# RUN: | FileCheck -check-prefixes=CHECK-ASM %s
|
||||
+# RUN: llvm-mc %s -triple riscv64 -mattr=+f -riscv-no-aliases -show-encoding \
|
||||
+# RUN: | FileCheck -check-prefixes=CHECK-ASM %s
|
||||
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+f < %s \
|
||||
+# RUN: | llvm-objdump --mattr=+f -M no-aliases -d -r - \
|
||||
+# RUN: | FileCheck -check-prefixes=CHECK-OBJ %s
|
||||
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+f < %s \
|
||||
+# RUN: | llvm-objdump --mattr=+f -M no-aliases -d -r - \
|
||||
+# RUN: | FileCheck -check-prefixes=CHECK-OBJ %s
|
||||
+
|
||||
+target:
|
||||
+
|
||||
+# CHECK-ASM: .insn r 51, 0, 0, a0, a1, a2
|
||||
+# CHECK-ASM: encoding: [0x33,0x85,0xc5,0x00]
|
||||
+# CHECK-OBJ: add a0, a1, a2
|
||||
+.insn r 0x33, 0, 0, a0, a1, a2
|
||||
+
|
||||
+# CHECK-ASM: .insn i 19, 0, a0, a1, 13
|
||||
+# CHECK-ASM: encoding: [0x13,0x85,0xd5,0x00]
|
||||
+# CHECK-OBJ: addi a0, a1, 13
|
||||
+.insn i 0x13, 0, a0, a1, 13
|
||||
+
|
||||
+# CHECK-ASM: .insn i 103, 0, a0, 10(a1)
|
||||
+# CHECK-ASM: encoding: [0x67,0x85,0xa5,0x00]
|
||||
+# CHECK-OBJ: jalr a0, 10(a1)
|
||||
+.insn i 0x67, 0, a0, 10(a1)
|
||||
+
|
||||
+# CHECK-ASM: .insn i 3, 0, a0, 4(a1)
|
||||
+# CHECK-ASM: encoding: [0x03,0x85,0x45,0x00]
|
||||
+# CHECK-OBJ: lb a0, 4(a1)
|
||||
+.insn i 0x3, 0, a0, 4(a1)
|
||||
+
|
||||
+# CHECK-ASM: .insn b 99, 0, a0, a1, target
|
||||
+# CHECK-ASM: [0x63'A',A,0xb5'A',A]
|
||||
+# CHECK-OBJ: beq a0, a1, 0x0 <target>
|
||||
+.insn sb 0x63, 0, a0, a1, target
|
||||
+
|
||||
+# CHECK-ASM: .insn b 99, 0, a0, a1, target
|
||||
+# CHECK-ASM: [0x63'A',A,0xb5'A',A]
|
||||
+# CHECK-OBJ: beq a0, a1, 0x0 <target>
|
||||
+.insn b 0x63, 0, a0, a1, target
|
||||
+
|
||||
+# CHECK-ASM: .insn s 35, 0, a0, 4(a1)
|
||||
+# CHECK-ASM: encoding: [0x23,0x82,0xa5,0x00]
|
||||
+# CHECK-OBJ: sb a0, 4(a1)
|
||||
+.insn s 0x23, 0, a0, 4(a1)
|
||||
+
|
||||
+# CHECK-ASM: .insn u 55, a0, 4095
|
||||
+# CHECK-ASM: encoding: [0x37,0xf5,0xff,0x00]
|
||||
+# CHECK-OBJ: lui a0, 4095
|
||||
+.insn u 0x37, a0, 0xfff
|
||||
+
|
||||
+# CHECK-ASM: .insn j 111, a0, target
|
||||
+# CHECK-ASM: encoding: [0x6f,0bAAAA0101,A,A]
|
||||
+# CHECK-OBJ: jal a0, 0x0 <target>
|
||||
+.insn uj 0x6f, a0, target
|
||||
+
|
||||
+# CHECK-ASM: .insn j 111, a0, target
|
||||
+# CHECK-ASM: encoding: [0x6f,0bAAAA0101,A,A]
|
||||
+# CHECK-OBJ: jal a0, 0x0 <target>
|
||||
+.insn j 0x6f, a0, target
|
||||
+
|
||||
+# CHECK-ASM: .insn r4 67, 0, 0, fa0, fa1, fa2, fa3
|
||||
+# CHECK-ASM: encoding: [0x43,0x85,0xc5,0x68]
|
||||
+# CHECK-OBJ: fmadd.s fa0, fa1, fa2, fa3, rne
|
||||
+.insn r 0x43, 0, 0, fa0, fa1, fa2, fa3
|
||||
+
|
||||
+# CHECK-ASM: .insn r4 67, 0, 0, fa0, fa1, fa2, fa3
|
||||
+# CHECK-ASM: encoding: [0x43,0x85,0xc5,0x68]
|
||||
+# CHECK-OBJ: fmadd.s fa0, fa1, fa2, fa3, rne
|
||||
+.insn r4 0x43, 0, 0, fa0, fa1, fa2, fa3
|
||||
+
|
||||
+# CHECK-ASM: .insn i 3, 5, t1, -2048(t2)
|
||||
+# CHECK-ASM: encoding: [0x03,0xd3,0x03,0x80]
|
||||
+# CHECK-OBJ: lhu t1, -2048(t2)
|
||||
+.insn i 0x3, 0x5, x6, %lo(2048)(x7)
|
1
debian/patches/series
vendored
1
debian/patches/series
vendored
@ -119,6 +119,7 @@ bootstrap-fix-include-next.diff
|
||||
|
||||
# riscv64
|
||||
risc/clang-riscv64-multiarch.diff
|
||||
risc/riscv-insn-support.patch
|
||||
|
||||
# sparc64
|
||||
D98574.patch
|
||||
|
Loading…
Reference in New Issue
Block a user