Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: xpack-dev-tools/riscv-none-elf-gcc-xpack
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: xpack
Choose a base ref
...
head repository: hydrausb3/riscv-none-elf-gcc-xpack
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: xpack
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
  • 2 commits
  • 2 files changed
  • 1 contributor

Commits on Dec 20, 2022

  1. Copy the full SHA
    90893d7 View commit details
  2. Copy the full SHA
    b9b8527 View commit details
Showing with 114 additions and 1 deletion.
  1. +113 −0 patches/gcc-12.2.0.patch.diff
  2. +1 −1 scripts/common-versions-source.sh
113 changes: 113 additions & 0 deletions patches/gcc-12.2.0.patch.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 4939d9964db..17f09a331ad 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -126,7 +126,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, WCH_FAST_MODE
};

struct GTY(()) machine_function {
@@ -3320,11 +3320,11 @@ 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"))
+ && strcmp (string, "machine") && strcmp(string, "WCH-Interrupt-fast"))
{
warning (OPT_Wattributes,
"argument to %qE attribute is not %<\"user\"%>, %<\"supervisor\"%>, "
- "or %<\"machine\"%>", name);
+ "%<\"machine\"%> or %<\"WCH-Interrupt-fast\"%>", name);
*no_add_attrs = true;
}
}
@@ -3879,6 +3879,14 @@ riscv_frame_set (rtx mem, rtx reg)
return set;
}

+/* Return true if WCH fast interrupt hardware saves register REGNO */
+static bool
+riscv_wch_fast_interrupt_saved_reg (unsigned int regno)
+{
+ return call_used_or_fixed_reg_p(regno) || regno == RETURN_ADDR_REGNUM;
+}
+
+
/* Return true if the current function must save register REGNO. */

static bool
@@ -3888,6 +3896,16 @@ riscv_save_reg_p (unsigned int regno)
bool might_clobber = crtl->saves_all_registers
|| df_regs_ever_live_p (regno);

+ /* WCH Fast interrupts are hardware-saved.
+ *
+ * If this is a WCH fast mode interrupt, and if the register is one of
+ * the caller-saved set, or ra (which is what WCH saves for us), then we can
+ * rely on hardware to save the register */
+ if (cfun->machine->interrupt_handler_p
+ && cfun->machine->interrupt_mode == WCH_FAST_MODE
+ && riscv_wch_fast_interrupt_saved_reg(regno))
+ return false;
+
if (call_saved && might_clobber)
return true;

@@ -4000,6 +4018,8 @@ riscv_compute_frame_info (void)

/* In an interrupt function, if we have a large frame, then we need to
save/restore t0. We check for this before clearing the frame struct. */
+
+ // TODO OPT - does this matter? T0 is theoretically restored for us; can we skip cleanup?
if (cfun->machine->interrupt_handler_p)
{
HOST_WIDE_INT step1 = riscv_first_stack_step (frame);
@@ -4603,7 +4623,7 @@ riscv_expand_epilogue (int style)

gcc_assert (mode != UNKNOWN_MODE);

- if (mode == MACHINE_MODE)
+ if (mode == MACHINE_MODE || mode == WCH_FAST_MODE)
emit_jump_insn (gen_riscv_mret ());
else if (mode == SUPERVISOR_MODE)
emit_jump_insn (gen_riscv_sret ());
@@ -4619,6 +4639,13 @@ riscv_expand_epilogue (int style)
bool
riscv_epilogue_uses (unsigned int regno)
{
+ /* The WCH hardware will restore some regs in a fast interrupt
+ * so those regs are dead */
+ if (epilogue_completed && cfun->machine->interrupt_handler_p
+ && cfun->machine->interrupt_mode == WCH_FAST_MODE
+ && riscv_wch_fast_interrupt_saved_reg (regno))
+ return false;
+
if (regno == RETURN_ADDR_REGNUM)
return true;

@@ -5348,6 +5375,8 @@ riscv_get_interrupt_type (tree decl)
return USER_MODE;
else if (!strcmp (string, "supervisor"))
return SUPERVISOR_MODE;
+ else if (!strcmp (string, "WCH-Interrupt-fast"))
+ return WCH_FAST_MODE;
else /* Must be "machine". */
return MACHINE_MODE;
}
@@ -5499,6 +5528,12 @@ bool
riscv_hard_regno_rename_ok (unsigned from_regno ATTRIBUTE_UNUSED,
unsigned to_regno)
{
+ /* For WCH fast interrupts, TO_REG may also be any of the hardware saved registers */
+ if (cfun->machine->interrupt_handler_p
+ && cfun->machine->interrupt_mode == WCH_FAST_MODE
+ && riscv_wch_fast_interrupt_saved_reg (to_regno))
+ return true;
+
/* Interrupt functions can only use registers that have already been
saved by the prologue, even if they would normally be
call-clobbered. */
2 changes: 1 addition & 1 deletion scripts/common-versions-source.sh
Original file line number Diff line number Diff line change
@@ -234,7 +234,7 @@ function build_versions()
build_cross_binutils

# -----------------------------------------------------------------------

GCC_PATCH_FILE_NAME="gcc-${GCC_VERSION}.patch.diff"
# Download GCC earlier, to have time to run the multilib generator.
download_cross_gcc
generate_multilib_file