};
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 {
}
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;
}
}
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 ());
}
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;
}
UNSPECV_MRET
UNSPECV_SRET
UNSPECV_URET
+ UNSPECV_MNRET
;; Blockage and synchronization.
UNSPECV_BLOCKAGE
"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")
@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