LGTM :)

Christoph Müllner <christoph.muell...@vrull.eu> 於 2025年7月25日 週五 05:33 寫道:

> 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>
> ---
>  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(-)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/interrupt-rnmi.c
>
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index cb9fe31c8b14..ac8bc9e99e48 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 {
> @@ -6899,12 +6899,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;
>             }
>         }
> @@ -9689,6 +9694,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 ());
>      }
> @@ -12036,6 +12043,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 @@ (define_c_enum "unspecv" [
>    UNSPECV_MRET
>    UNSPECV_SRET
>    UNSPECV_URET
> +  UNSPECV_MNRET
>
>    ;; Blockage and synchronization.
>    UNSPECV_BLOCKAGE
> @@ -4173,6 +4174,13 @@ (define_insn "riscv_uret"
>    "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 8c29e24c2670..86d539aa29f5 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} } } */
> --
> 2.50.1
>
>

Reply via email to