Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISCV][MC] Add support for hardcode encoding of .insn directive #98030

Merged
merged 2 commits into from
Jul 9, 2024

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Jul 8, 2024

This patch adds support for the following two hardcode encodings of .insn directive:

.insn <insn-length>, <value>
.insn <value>

See also gas's patch bminor/binutils-gdb@a262b82
NOTE: This patch doesn't support long instructions.

Closes #97498.

@llvmbot llvmbot added backend:RISC-V mc Machine (object) code labels Jul 8, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 8, 2024

@llvm/pr-subscribers-mc

@llvm/pr-subscribers-backend-risc-v

Author: Yingwei Zheng (dtcxzyw)

Changes

This patch adds support for the following two hardcode encodings of .insn directive:

.insn &lt;insn-length&gt;, &lt;value&gt;
.insn &lt;value&gt;

See also gas's patch bminor/binutils-gdb@a262b82
NOTE: This patch doesn't support long instructions.

Closes #97498.


Full diff: https://github.com/llvm/llvm-project/pull/98030.diff

8 Files Affected:

  • (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+38-4)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+2)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoC.td (+6)
  • (modified) llvm/test/MC/RISCV/insn-invalid.s (+8)
  • (modified) llvm/test/MC/RISCV/insn.s (+10)
  • (modified) llvm/test/MC/RISCV/insn_c-invalid.s (+1)
  • (modified) llvm/test/MC/RISCV/insn_c.s (+10)
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 8ac1cdf0a7a9c..d599c2b9b7b30 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -703,7 +703,9 @@ struct RISCVOperand final : public MCParsedAsmOperand {
   bool isUImm6() const { return IsUImm<6>(); }
   bool isUImm7() const { return IsUImm<7>(); }
   bool isUImm8() const { return IsUImm<8>(); }
+  bool isUImm16() const { return IsUImm<16>(); }
   bool isUImm20() const { return IsUImm<20>(); }
+  bool isUImm32() const { return IsUImm<32>(); }
 
   bool isUImm8GE32() const {
     int64_t Imm;
@@ -3055,17 +3057,49 @@ bool isValidInsnFormat(StringRef Format, bool AllowC) {
 
 /// parseDirectiveInsn
 /// ::= .insn [ format encoding, (operands (, operands)*) ]
+/// ::= .insn [ length, value ]
+/// ::= .insn [ value ]
 bool RISCVAsmParser::parseDirectiveInsn(SMLoc L) {
   MCAsmParser &Parser = getParser();
 
+  bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
+                getSTI().hasFeature(RISCV::FeatureStdExtZca);
+
   // Expect instruction format as identifier.
   StringRef Format;
   SMLoc ErrorLoc = Parser.getTok().getLoc();
-  if (Parser.parseIdentifier(Format))
-    return Error(ErrorLoc, "expected instruction format");
+  if (Parser.parseIdentifier(Format)) {
+    // Try parsing .insn [length], value
+    int64_t Length = 0;
+    int64_t Value = 0;
+    if (Parser.parseIntToken(
+            Value, "expected instruction format or an integer constant"))
+      return true;
+    if (Parser.parseOptionalToken(AsmToken::Comma)) {
+      Length = Value;
+      if (Parser.parseIntToken(Value, "expected an integer constant"))
+        return true;
+    }
+
+    int64_t RealLength = (Value & 3) == 3 ? 4 : 2;
+    if (!isUIntN(RealLength * 8, Value))
+      return Error(ErrorLoc, "invalid operand for instruction");
+    if (RealLength == 2 && !AllowC)
+      return Error(ErrorLoc, "compressed instructions are not allowed");
+    if (Length != 0 && Length != RealLength)
+      return Error(ErrorLoc, "instruction length mismatch");
+
+    if (getParser().parseEOL("invalid operand for instruction")) {
+      getParser().eatToEndOfStatement();
+      return true;
+    }
+
+    emitToStreamer(getStreamer(), MCInstBuilder(RealLength == 2 ? RISCV::Insn16
+                                                                : RISCV::Insn32)
+                                      .addImm(Value));
+    return false;
+  }
 
-  bool AllowC = getSTI().hasFeature(RISCV::FeatureStdExtC) ||
-                getSTI().hasFeature(RISCV::FeatureStdExtZca);
   if (!isValidInsnFormat(Format, AllowC))
     return Error(ErrorLoc, "invalid instruction format");
 
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 550904516ac8e..cf83bd977939e 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -279,6 +279,8 @@ enum OperandType : unsigned {
   OPERAND_UIMM9_LSB000,
   OPERAND_UIMM10_LSB00_NONZERO,
   OPERAND_UIMM12,
+  OPERAND_UIMM16,
+  OPERAND_UIMM32,
   OPERAND_ZERO,
   OPERAND_SIMM5,
   OPERAND_SIMM5_PLUS1,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 4cdf08a46f285..075aaae2ce507 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -233,6 +233,8 @@ def uimm7_opcode : RISCVUImmOp<7> {
 }
 def uimm7 : RISCVUImmOp<7>;
 def uimm8 : RISCVUImmOp<8>;
+def uimm16 : RISCVUImmOp<16>;
+def uimm32 : RISCVUImmOp<32>;
 def simm12 : RISCVSImmLeafOp<12> {
   let MCOperandPredicate = [{
     int64_t Imm;
@@ -1120,6 +1122,12 @@ def InsnS : DirectiveInsnS<(outs), (ins uimm7_opcode:$opcode, uimm3:$funct3,
                                         AnyReg:$rs2, AnyReg:$rs1,
                                         simm12:$imm12),
                            "$opcode, $funct3, $rs2, ${imm12}(${rs1})">;
+def Insn32 : RVInst<(outs), (ins uimm32:$value), "", "", [], InstFormatOther> {
+  bits<32> value;
+
+  let Inst{31-0} = value;
+  let AsmString = ".insn 0x4, $value";
+}
 }
 
 // Use InstAliases to match these so that we can combine the insn and format
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
index 458d081763e93..82eeef0ae10a3 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td
@@ -801,6 +801,12 @@ def InsnCJ : DirectiveInsnCJ<(outs), (ins uimm2_opcode:$opcode,
                                           uimm3:$funct3,
                                           simm12_lsb0:$imm11),
                              "$opcode, $funct3, $imm11">;
+def Insn16 : RVInst16<(outs), (ins uimm16:$value), "", "", [], InstFormatOther> {
+  bits<16> value;
+
+  let Inst{15-0} = value;
+  let AsmString = ".insn 0x2, $value";
+}
 }
 
 // Use InstAliases to match these so that we can combine the insn and format
diff --git a/llvm/test/MC/RISCV/insn-invalid.s b/llvm/test/MC/RISCV/insn-invalid.s
index 32ebd6867377c..d6fabea4e1701 100644
--- a/llvm/test/MC/RISCV/insn-invalid.s
+++ b/llvm/test/MC/RISCV/insn-invalid.s
@@ -23,3 +23,11 @@
 
 # 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
+
+.insn . # CHECK: :[[@LINE]]:7: error: expected instruction format or an integer constant
+.insn 0x2, # CHECK: :[[@LINE]]:12: error: expected an integer constant
+.insn 0x2, 0xffff # CHECK: :[[@LINE]]:7: error: instruction length mismatch
+.insn 0x2, 0xffffffff # CHECK: :[[@LINE]]:7: error: instruction length mismatch
+.insn 0xffffffffff # CHECK: :[[@LINE]]:7: error: invalid operand for instruction
+.insn 0x0010 # CHECK: :[[@LINE]]:7: error: compressed instructions are not allowed
+.insn 0x4, 0x13, 0 # CHECK: :[[@LINE]]:16: error: invalid operand for instruction
diff --git a/llvm/test/MC/RISCV/insn.s b/llvm/test/MC/RISCV/insn.s
index 4eb9a8a7ebf25..b95c3b87b442f 100644
--- a/llvm/test/MC/RISCV/insn.s
+++ b/llvm/test/MC/RISCV/insn.s
@@ -154,3 +154,13 @@ target:
 # CHECK-ASM: encoding: [0x03,0xd3,0x03,0x80]
 # CHECK-OBJ: lhu t1, -0x800(t2)
 .insn i LOAD, 0x5, x6, %lo(2048)(x7)
+
+# CHECK-ASM: .insn 0x4, 19
+# CHECK-ASM: encoding: [0x13,0x00,0x00,0x00]
+# CHECK-OBJ: addi zero, zero, 0x0
+.insn 0x13
+
+# CHECK-ASM: .insn 0x4, 19
+# CHECK-ASM: encoding: [0x13,0x00,0x00,0x00]
+# CHECK-OBJ: addi zero, zero, 0x0
+.insn 0x4, 0x13
diff --git a/llvm/test/MC/RISCV/insn_c-invalid.s b/llvm/test/MC/RISCV/insn_c-invalid.s
index c983d32e7fe97..3b424b2a9fd32 100644
--- a/llvm/test/MC/RISCV/insn_c-invalid.s
+++ b/llvm/test/MC/RISCV/insn_c-invalid.s
@@ -24,3 +24,4 @@
 ## Make fake mnemonics we use to match these in the tablegened asm match table isn't exposed.
 .insn_cr  2, 9, a0, a1 # CHECK: :[[#@LINE]]:1: error: unknown directive
 
+.insn 0xfffffff0 # CHECK: :[[@LINE]]:7: error: invalid operand for instruction
diff --git a/llvm/test/MC/RISCV/insn_c.s b/llvm/test/MC/RISCV/insn_c.s
index e1b3003e0200d..19169e8b08c94 100644
--- a/llvm/test/MC/RISCV/insn_c.s
+++ b/llvm/test/MC/RISCV/insn_c.s
@@ -80,3 +80,13 @@ target:
 # CHECK-ASM: encoding: [0bAAAAAA01,0b101AAAAA]
 # CHECK-OBJ: c.j 0x0 <target>
 .insn cj  1, 5, target
+
+# CHECK-ASM: .insn 0x2, 1
+# CHECK-ASM: encoding: [0x01,0x00]
+# CHECK-OBJ: c.nop
+.insn 0x0001
+
+# CHECK-ASM: .insn 0x2, 1
+# CHECK-ASM: encoding: [0x01,0x00]
+# CHECK-OBJ: c.nop
+.insn 0x2, 0x0001

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dtcxzyw dtcxzyw merged commit 2a086dc into llvm:main Jul 9, 2024
7 checks passed
@dtcxzyw dtcxzyw deleted the riscv-insn-word branch July 9, 2024 16:39
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
…m#98030)

This patch adds support for the following two hardcode encodings of
.insn directive:
```
.insn <insn-length>, <value>
.insn <value>
```

See also gas's patch
bminor/binutils-gdb@a262b82
NOTE: This patch doesn't support long instructions. 

Closes llvm#97498.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RISC-V] .insn directive does not support constant arg
3 participants