aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJin Ma <jinma@linux.alibaba.com>2023-11-10 15:14:31 +0800
committerChristoph Müllner <christoph.muellner@vrull.eu>2023-11-10 14:26:12 +0100
commitb70ad8c19aa8be672cdba6afe9cbab2d1254d127 (patch)
tree12bcbc9d77bc8cb01fd3522308d8e7a36a3853d3 /gcc
parente5f1956498251a4973d52c8aad3faf34d0443169 (diff)
downloadgcc-b70ad8c19aa8be672cdba6afe9cbab2d1254d127.zip
gcc-b70ad8c19aa8be672cdba6afe9cbab2d1254d127.tar.gz
gcc-b70ad8c19aa8be672cdba6afe9cbab2d1254d127.tar.bz2
RISC-V: XTheadMemPair: Fix missing fcsr handling in ISR prologue/epilogue
The t0 register is used as a temporary register for interrupts, so it needs special treatment. It is necessary to avoid using "th.ldd" in the interrupt program to stop the subsequent operation of the t0 register, so they need to exchange positions in the function "riscv_for_each_saved_reg". gcc/ChangeLog: * config/riscv/riscv.cc (riscv_for_each_saved_reg): Place the interrupt operation before the XTheadMemPair.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/riscv/riscv.cc56
-rw-r--r--gcc/testsuite/gcc.target/riscv/xtheadmempair-interrupt-fcsr.c18
2 files changed, 46 insertions, 28 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index e25692b..fa2d4d4 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -6346,6 +6346,34 @@ riscv_for_each_saved_reg (poly_int64 sp_offset, riscv_save_restore_fn fn,
&& riscv_is_eh_return_data_register (regno))
continue;
+ /* In an interrupt function, save and restore some necessary CSRs in the stack
+ to avoid changes in CSRs. */
+ if (regno == RISCV_PROLOGUE_TEMP_REGNUM
+ && cfun->machine->interrupt_handler_p
+ && ((TARGET_HARD_FLOAT && cfun->machine->frame.fmask)
+ || (TARGET_ZFINX
+ && (cfun->machine->frame.mask & ~(1 << RISCV_PROLOGUE_TEMP_REGNUM)))))
+ {
+ unsigned int fcsr_size = GET_MODE_SIZE (SImode);
+ if (!epilogue)
+ {
+ riscv_save_restore_reg (word_mode, regno, offset, fn);
+ offset -= fcsr_size;
+ emit_insn (gen_riscv_frcsr (RISCV_PROLOGUE_TEMP (SImode)));
+ riscv_save_restore_reg (SImode, RISCV_PROLOGUE_TEMP_REGNUM,
+ offset, riscv_save_reg);
+ }
+ else
+ {
+ riscv_save_restore_reg (SImode, RISCV_PROLOGUE_TEMP_REGNUM,
+ offset - fcsr_size, riscv_restore_reg);
+ emit_insn (gen_riscv_fscsr (RISCV_PROLOGUE_TEMP (SImode)));
+ riscv_save_restore_reg (word_mode, regno, offset, fn);
+ offset -= fcsr_size;
+ }
+ continue;
+ }
+
if (TARGET_XTHEADMEMPAIR)
{
/* Get the next reg/offset pair. */
@@ -6376,34 +6404,6 @@ riscv_for_each_saved_reg (poly_int64 sp_offset, riscv_save_restore_fn fn,
}
}
- /* In an interrupt function, save and restore some necessary CSRs in the stack
- to avoid changes in CSRs. */
- if (regno == RISCV_PROLOGUE_TEMP_REGNUM
- && cfun->machine->interrupt_handler_p
- && ((TARGET_HARD_FLOAT && cfun->machine->frame.fmask)
- || (TARGET_ZFINX
- && (cfun->machine->frame.mask & ~(1 << RISCV_PROLOGUE_TEMP_REGNUM)))))
- {
- unsigned int fcsr_size = GET_MODE_SIZE (SImode);
- if (!epilogue)
- {
- riscv_save_restore_reg (word_mode, regno, offset, fn);
- offset -= fcsr_size;
- emit_insn (gen_riscv_frcsr (RISCV_PROLOGUE_TEMP (SImode)));
- riscv_save_restore_reg (SImode, RISCV_PROLOGUE_TEMP_REGNUM,
- offset, riscv_save_reg);
- }
- else
- {
- riscv_save_restore_reg (SImode, RISCV_PROLOGUE_TEMP_REGNUM,
- offset - fcsr_size, riscv_restore_reg);
- emit_insn (gen_riscv_fscsr (RISCV_PROLOGUE_TEMP (SImode)));
- riscv_save_restore_reg (word_mode, regno, offset, fn);
- offset -= fcsr_size;
- }
- continue;
- }
-
riscv_save_restore_reg (word_mode, regno, offset, fn);
}
diff --git a/gcc/testsuite/gcc.target/riscv/xtheadmempair-interrupt-fcsr.c b/gcc/testsuite/gcc.target/riscv/xtheadmempair-interrupt-fcsr.c
new file mode 100644
index 0000000..d06f05f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xtheadmempair-interrupt-fcsr.c
@@ -0,0 +1,18 @@
+/* Verify that fcsr instructions emitted. */
+/* { dg-do compile } */
+/* { dg-require-effective-target hard_float } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-g" "-Oz" "-Os" "-flto" } } */
+/* { dg-options "-march=rv64gc_xtheadmempair -mtune=thead-c906 -funwind-tables" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xtheadmempair -mtune=thead-c906 -funwind-tables" { target { rv32 } } } */
+
+
+extern int foo (void);
+
+void __attribute__ ((interrupt))
+sub (void)
+{
+ foo ();
+}
+
+/* { dg-final { scan-assembler-times "frcsr\t" 1 } } */
+/* { dg-final { scan-assembler-times "fscsr\t" 1 } } */