diff --git a/debian/patches/risc/riscv-insn-support.patch b/debian/patches/risc/riscv-insn-support.patch new file mode 100644 index 00000000..30283f6d --- /dev/null +++ b/debian/patches/risc/riscv-insn-support.patch @@ -0,0 +1,566 @@ +From d5ea5842d627e63f780b524dddf67dac7222779c Mon Sep 17 00:00:00 2001 +From: Craig Topper +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, 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(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 ++ : RVInst { ++ 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 ++ : RVInst { ++ 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 ++ : RVInst { ++ 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 ++ : RVInst { ++ 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 ++ : RVInst { ++ 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 ++ : RVInst { ++ 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 ++ : RVInst { ++ 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, ImmLeaf { ++ let ParserMatchClass = UImmAsmOperand<2>; ++ let DecoderMethod = "decodeUImmOperand<2>"; ++ let OperandType = "OPERAND_UIMM2"; ++ let OperandNamespace = "RISCVOp"; ++} ++ ++def uimm3 : Operand { ++ let ParserMatchClass = UImmAsmOperand<3>; ++ let DecoderMethod = "decodeUImmOperand<3>"; ++ let OperandType = "OPERAND_UIMM3"; ++ let OperandNamespace = "RISCVOp"; ++} ++ + def uimm5 : Operand, ImmLeaf(Imm);}]> { + let ParserMatchClass = UImmAsmOperand<5>; + let DecoderMethod = "decodeUImmOperand<5>"; +@@ -159,6 +173,13 @@ def uimm5 : Operand, ImmLeaf(Imm);}]> { + let OperandNamespace = "RISCVOp"; + } + ++def uimm7 : Operand { ++ let ParserMatchClass = UImmAsmOperand<7>; ++ let DecoderMethod = "decodeUImmOperand<7>"; ++ let OperandType = "OPERAND_UIMM7"; ++ let OperandNamespace = "RISCVOp"; ++} ++ + def simm12 : Operand, ImmLeaf(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 ++.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 ++.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 ++.insn uj 0x6f, a0, target ++ ++# CHECK-ASM: .insn j 111, a0, target ++# CHECK-ASM: encoding: [0x6f,0bAAAA0101,A,A] ++# CHECK-OBJ: jal a0, 0x0 ++.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) diff --git a/debian/patches/series b/debian/patches/series index 083272b5..2307c344 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -119,6 +119,7 @@ bootstrap-fix-include-next.diff # riscv64 risc/clang-riscv64-multiarch.diff +risc/riscv-insn-support.patch # sparc64 D98574.patch