From 2a22db391d1819f6068aa43e63632b350a0b4bec Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng@sifive.com>
Date: Thu, 14 Nov 2024 17:24:45 +0800
Subject: [PATCH] RISC-V: Implment N modifier for printing the register number
 rather than the register name

The modifier `N`, to print the raw encoding of a register. This is used
when using `.insn <length>, <encoding>`, where the user wants to pass
a value to the instruction in a known register, but where the
instruction doesn't follow the existing instruction formats, so the
assembly parser is not expecting a register name, just a raw integer.

gcc/ChangeLog:

	* config/riscv/riscv.cc (riscv_print_operand): Add N.
	* doc/extend.texi: Document for N,

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/modifier-N-fpr.c: New.
	* gcc.target/riscv/modifier-N-vr.c: New.
	* gcc.target/riscv/modifier-N.c: New.
---
 gcc/config/riscv/riscv.cc                     | 23 +++++++++++++++++++
 gcc/doc/extend.texi                           |  1 +
 .../gcc.target/riscv/modifier-N-fpr.c         | 16 +++++++++++++
 .../gcc.target/riscv/modifier-N-vr.c          | 18 +++++++++++++++
 gcc/testsuite/gcc.target/riscv/modifier-N.c   | 16 +++++++++++++
 5 files changed, 74 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/modifier-N-fpr.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/modifier-N-vr.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/modifier-N.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index db2329c03193..ed75c653481f 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -6833,6 +6833,7 @@ riscv_asm_output_opcode (FILE *asm_out_file, const char *p)
    'S'	Print shift-index of single-bit mask OP.
    'T'	Print shift-index of inverted single-bit mask OP.
    '~'	Print w if TARGET_64BIT is true; otherwise not print anything.
+   'N'  Print register encoding as integer (0-31).
 
    Note please keep this list and the list in riscv.md in sync.  */
 
@@ -7079,6 +7080,28 @@ riscv_print_operand (FILE *file, rtx op, int letter)
 	output_addr_const (file, newop);
 	break;
       }
+    case 'N':
+      {
+	if (!REG_P(op))
+	  {
+	    output_operand_lossage ("modifier 'N' require register operand");
+	    break;
+	  }
+
+	unsigned regno = REGNO (op);
+	unsigned offset = 0;
+	if (IN_RANGE (regno, GP_REG_FIRST, GP_REG_LAST))
+	  offset = GP_REG_FIRST;
+	else if (IN_RANGE (regno, FP_REG_FIRST, FP_REG_LAST))
+	  offset = FP_REG_FIRST;
+	else if (IN_RANGE (regno, V_REG_FIRST, V_REG_LAST))
+	  offset = V_REG_FIRST;
+	else
+	  output_operand_lossage ("invalid register number for 'N' modifie");
+
+	asm_fprintf (file, "%u", (regno - offset));
+	break;
+      }
     default:
       switch (code)
 	{
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index ebd970155f78..d991aa0a5081 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -12594,6 +12594,7 @@ The list below describes the supported modifiers and their effects for RISC-V.
 @headitem Modifier @tab Description
 @item @code{z} @tab Print ''@code{zero}'' instead of 0 if the operand is an immediate with a value of zero.
 @item @code{i} @tab Print the character ''@code{i}'' if the operand is an immediate.
+@item @code{N} @tab Print the register encoding as integer (0 - 31).
 @end multitable
 
 @anchor{shOperandmodifiers}
diff --git a/gcc/testsuite/gcc.target/riscv/modifier-N-fpr.c b/gcc/testsuite/gcc.target/riscv/modifier-N-fpr.c
new file mode 100644
index 000000000000..42590e00c0d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/modifier-N-fpr.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+void foo() {
+/*
+** foo:
+**   ...
+**   fadd.s\s*ft0,\s*8,\s*9
+**   ...
+*/
+  register float fs0 __asm__ ("fs0");
+  register float fs1 __asm__ ("fs1");
+  __asm__ volatile("fadd.s ft0, %N0, %N1" : : "f" (fs0), "f" (fs1) : "memory");
+}
diff --git a/gcc/testsuite/gcc.target/riscv/modifier-N-vr.c b/gcc/testsuite/gcc.target/riscv/modifier-N-vr.c
new file mode 100644
index 000000000000..ea591b021386
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/modifier-N-vr.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gv -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#pragma riscv intrinsic "vector"
+
+void foo() {
+/*
+** foo:
+**   ...
+**   vadd.vv\s*v0,\s*1,\s*2
+**   ...
+*/
+  register vint32m1_t v1 __asm__ ("v1");
+  register vint32m1_t v2 __asm__ ("v2");
+  __asm__ volatile("vadd.vv v0, %N0, %N1" : : "vr" (v1), "vr" (v2) : "memory");
+}
diff --git a/gcc/testsuite/gcc.target/riscv/modifier-N.c b/gcc/testsuite/gcc.target/riscv/modifier-N.c
new file mode 100644
index 000000000000..fef281611efb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/modifier-N.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+
+void foo() {
+/*
+** foo:
+**   ...
+**   addi\s*t0,\s*9,\s*4
+**   ...
+*/
+  register int s1 __asm__ ("s1");
+  register int tp __asm__ ("tp");
+  __asm__ volatile("addi t0, %N0, %N1" : : "r" (s1), "r" (tp) : "memory");
+}
-- 
GitLab