https://gcc.gnu.org/g:1603eeb6c8ea9cf68762a7755307077c7fb143d3

commit r16-2494-g1603eeb6c8ea9cf68762a7755307077c7fb143d3
Author: Christoph Müllner <christoph.muell...@vrull.eu>
Date:   Thu Jul 24 23:08:40 2025 +0200

    RISC-V: Add support for resumable non-maskable interrupt (RNMI) handlers
    
    The Smrnmi extension introduces the nmret instruction to return from RNMI
    handlers.  We already have basic Smrnmi support.  This patch introduces
    support for the nmret instruction and the ability to set the function
    attribute `__attribute__ ((interrupt ("rnmi")))` to let the compiler
    generate RNMI handlers.
    
    The attribute name is proposed in a PR for the RISC C API and approved
    by LLVM maintainers:
      https://github.com/riscv-non-isa/riscv-c-api-doc/pull/116
    
    gcc/ChangeLog:
    
            * config/riscv/riscv.cc (enum riscv_privilege_levels): Add
            RNMI_MODE.
            (riscv_handle_type_attribute): Handle 'rnmi' interrupt attribute.
            (riscv_expand_epilogue): Generate nmret for RNMI handlers.
            (riscv_get_interrupt_type): Handle 'rnmi' interrupt attribute.
            * config/riscv/riscv.md (riscv_rnmi): Add nmret INSN.
            * doc/extend.texi: Add documentation for 'rnmi' interrupt attribute.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/interrupt-rnmi.c: New test.
    
    Signed-off-by: Christoph Müllner <christoph.muell...@vrull.eu>

Diff:
---
 gcc/config/riscv/riscv.cc                       | 17 +++++++++++++----
 gcc/config/riscv/riscv.md                       |  8 ++++++++
 gcc/doc/extend.texi                             |  4 ++--
 gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c | 11 +++++++++++
 4 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index c6fa4289346d..b80d2a0efab4 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -170,7 +170,7 @@ struct GTY(())  riscv_frame_info {
 };
 
 enum riscv_privilege_levels {
-  UNKNOWN_MODE, USER_MODE, SUPERVISOR_MODE, MACHINE_MODE
+  UNKNOWN_MODE, USER_MODE, SUPERVISOR_MODE, MACHINE_MODE, RNMI_MODE
 };
 
 struct GTY(()) mode_switching_info {
@@ -6924,12 +6924,17 @@ riscv_handle_type_attribute (tree *node 
ATTRIBUTE_UNUSED, tree name, tree args,
            }
 
          string = TREE_STRING_POINTER (cst);
-         if (strcmp (string, "user") && strcmp (string, "supervisor")
-             && strcmp (string, "machine"))
+         if (!strcmp (string, "rnmi") && !TARGET_SMRNMI)
+           {
+             error ("attribute 'rnmi' requires the Smrnmi ISA extension");
+             *no_add_attrs = true;
+           }
+         else if (strcmp (string, "user") && strcmp (string, "supervisor")
+             && strcmp (string, "machine") && strcmp (string, "rnmi"))
            {
              warning (OPT_Wattributes,
                       "argument to %qE attribute is not %<\"user\"%>, 
%<\"supervisor\"%>, "
-                      "or %<\"machine\"%>", name);
+                      "%<\"machine\"%>, or %<\"rnmi\"%>", name);
              *no_add_attrs = true;
            }
        }
@@ -9714,6 +9719,8 @@ riscv_expand_epilogue (int style)
        emit_jump_insn (gen_riscv_mret ());
       else if (mode == SUPERVISOR_MODE)
        emit_jump_insn (gen_riscv_sret ());
+      else if (mode == RNMI_MODE)
+       emit_jump_insn (gen_riscv_mnret ());
       else
        emit_jump_insn (gen_riscv_uret ());
     }
@@ -12061,6 +12068,8 @@ riscv_get_interrupt_type (tree decl)
        return USER_MODE;
       else if (!strcmp (string, "supervisor"))
        return SUPERVISOR_MODE;
+      else if (!strcmp (string, "rnmi"))
+       return RNMI_MODE;
       else /* Must be "machine".  */
        return MACHINE_MODE;
     }
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index c3b504d08836..0f29baa47e20 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -121,6 +121,7 @@
   UNSPECV_MRET
   UNSPECV_SRET
   UNSPECV_URET
+  UNSPECV_MNRET
 
   ;; Blockage and synchronization.
   UNSPECV_BLOCKAGE
@@ -4173,6 +4174,13 @@
   "uret"
   [(set_attr "type" "ret")])
 
+(define_insn "riscv_mnret"
+  [(return)
+   (unspec_volatile [(const_int 0)] UNSPECV_MNRET)]
+  "TARGET_SMRNMI"
+  "mnret"
+  [(set_attr "type" "ret")])
+
 (define_insn "stack_tie<mode>"
   [(set (mem:BLK (scratch))
        (unspec:BLK [(match_operand:X 0 "register_operand" "r")
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 76fed32918f6..125eaf46331b 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -5658,8 +5658,8 @@ void f (void) __attribute__ ((interrupt ("user")));
 @end smallexample
 
 Permissible values for this parameter are @code{user}, @code{supervisor},
-and @code{machine}.  If there is no parameter, then it defaults to
-@code{machine}.
+@code{machine}, and @code{rnmi}.  If there is no parameter, then it
+defaults to @code{machine}.
 
 @cindex @code{riscv_vector_cc} function attribute, RISC-V
 @item riscv_vector_cc
diff --git a/gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c 
b/gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c
new file mode 100644
index 000000000000..f3401080823e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c
@@ -0,0 +1,11 @@
+/* Verify the return instruction is mnret.  */
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_smrnmi" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_smrnmi" { target { rv64 } } } */
+
+void __attribute__ ((interrupt ("rnmi")))
+foo (void)
+{
+}
+
+/* { dg-final { scan-assembler {\mmnret} } } */

Reply via email to