There was once a RISC-V extension draft ("N"), which introduced user-level interrupts. However, it was never ratified and the specification draft has been removed from the RISC-V ISA manual in commit `b6cade07034` with the comment "it'll likely need to be redesigned".
Support for a N extension never made it to GCC, but we support fuction attributes for user-level interrupt handlers that use the URET instruction. The "user" interrupt attribute was documented in the RISC-V C API, but has been removed in PR #106 in May 2025 (driven by LLVM devs/ maintainers and ack'ed by at least one GCC maintainer). Let's drop URET support from GCC as well. gcc/ChangeLog: * config/riscv/riscv.cc (enum riscv_privilege_levels): Remove USER_MODE. (riscv_handle_type_attribute): Remove "user" interrupts. (riscv_expand_epilogue): Likewise. (riscv_get_interrupt_type): Likewise. * config/riscv/riscv.md (riscv_uret): Remove URET pattern. * doc/extend.texi: Remove documentation of user interrupts. gcc/testsuite/ChangeLog: * gcc.target/riscv/interrupt-conflict-mode.c: Remove "user" interrupts. * gcc.target/riscv/xtheadint-push-pop.c: Likewise. * gcc.target/riscv/interrupt-umode.c: Removed. Reported-by: Sam Elliott <quic_aelli...@quicinc.com> Signed-off-by: Christoph Müllner <christoph.muell...@vrull.eu> --- gcc/config/riscv/riscv.cc | 19 ++++++++----------- gcc/config/riscv/riscv.md | 8 -------- gcc/doc/extend.texi | 4 ++-- .../riscv/interrupt-conflict-mode.c | 2 +- .../gcc.target/riscv/interrupt-umode.c | 8 -------- .../gcc.target/riscv/xtheadint-push-pop.c | 6 ------ 6 files changed, 11 insertions(+), 36 deletions(-) delete mode 100644 gcc/testsuite/gcc.target/riscv/interrupt-umode.c diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index b80d2a0efab4..b4f2d138efa9 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, RNMI_MODE + UNKNOWN_MODE, SUPERVISOR_MODE, MACHINE_MODE, RNMI_MODE }; struct GTY(()) mode_switching_info { @@ -6929,11 +6929,12 @@ riscv_handle_type_attribute (tree *node ATTRIBUTE_UNUSED, tree name, tree args, 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")) + else if (strcmp (string, "supervisor") + && strcmp (string, "machine") + && strcmp (string, "rnmi")) { warning (OPT_Wattributes, - "argument to %qE attribute is not %<\"user\"%>, %<\"supervisor\"%>, " + "argument to %qE attribute is not %<\"supervisor\"%>, " "%<\"machine\"%>, or %<\"rnmi\"%>", name); *no_add_attrs = true; } @@ -9715,14 +9716,12 @@ riscv_expand_epilogue (int style) if (th_int_mask && TH_INT_INTERRUPT (cfun)) emit_jump_insn (gen_th_int_pop ()); - else if (mode == MACHINE_MODE) - 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 ()); + else /* Must be MACHINE_MODE. */ + emit_jump_insn (gen_riscv_mret ()); } else if (style != SIBCALL_RETURN) { @@ -12064,9 +12063,7 @@ riscv_get_interrupt_type (tree decl) { const char *string = TREE_STRING_POINTER (TREE_VALUE (attr_args)); - if (!strcmp (string, "user")) - return USER_MODE; - else if (!strcmp (string, "supervisor")) + if (!strcmp (string, "supervisor")) return SUPERVISOR_MODE; else if (!strcmp (string, "rnmi")) return RNMI_MODE; diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 0f29baa47e20..578dd43441e2 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -120,7 +120,6 @@ (define_c_enum "unspecv" [ ;; Interrupt handler instructions. UNSPECV_MRET UNSPECV_SRET - UNSPECV_URET UNSPECV_MNRET ;; Blockage and synchronization. @@ -4167,13 +4166,6 @@ (define_insn "riscv_sret" "sret" [(set_attr "type" "ret")]) -(define_insn "riscv_uret" - [(return) - (unspec_volatile [(const_int 0)] UNSPECV_URET)] - "" - "uret" - [(set_attr "type" "ret")]) - (define_insn "riscv_mnret" [(return) (unspec_volatile [(const_int 0)] UNSPECV_MNRET)] diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 125eaf46331b..224d6197d639 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -5654,10 +5654,10 @@ You can specify the kind of interrupt to be handled by adding an optional parameter to the interrupt attribute like this: @smallexample -void f (void) __attribute__ ((interrupt ("user"))); +void f (void) __attribute__ ((interrupt ("supervisor"))); @end smallexample -Permissible values for this parameter are @code{user}, @code{supervisor}, +Permissible values for this parameter are @code{supervisor}, @code{machine}, and @code{rnmi}. If there is no parameter, then it defaults to @code{machine}. diff --git a/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c b/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c index 81ebf5fba67d..15cc3eeb7304 100644 --- a/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c +++ b/gcc/testsuite/gcc.target/riscv/interrupt-conflict-mode.c @@ -1,7 +1,7 @@ /* Verify proper errors are generated for conflicted interrupt type. */ /* { dg-do compile } */ /* { dg-options "" } */ -void __attribute__ ((interrupt ("user"))) +void __attribute__ ((interrupt ("supervisor"))) foo(void); void __attribute__ ((interrupt ("machine"))) diff --git a/gcc/testsuite/gcc.target/riscv/interrupt-umode.c b/gcc/testsuite/gcc.target/riscv/interrupt-umode.c deleted file mode 100644 index 042abf02ad29..000000000000 --- a/gcc/testsuite/gcc.target/riscv/interrupt-umode.c +++ /dev/null @@ -1,8 +0,0 @@ -/* Verify the return instruction is mret. */ -/* { dg-do compile } */ -/* { dg-options "" } */ -void __attribute__ ((interrupt ("user"))) -foo (void) -{ -} -/* { dg-final { scan-assembler {\muret} } } */ diff --git a/gcc/testsuite/gcc.target/riscv/xtheadint-push-pop.c b/gcc/testsuite/gcc.target/riscv/xtheadint-push-pop.c index dc5609c8f76e..167fa15843ce 100644 --- a/gcc/testsuite/gcc.target/riscv/xtheadint-push-pop.c +++ b/gcc/testsuite/gcc.target/riscv/xtheadint-push-pop.c @@ -20,12 +20,6 @@ void func_machine (void) /* { dg-final { scan-assembler-times {\mth\.ipop\M} 2 { target { rv32 } } } } */ -__attribute__ ((interrupt ("user"))) -void func_usr (void) -{ - f (); -} - __attribute__ ((interrupt ("supervisor"))) void func_supervisor (void) { -- 2.50.1