]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: XTheadMemPair: Fix missing fcsr handling in ISR prologue/epilogue
authorJin Ma <jinma@linux.alibaba.com>
Fri, 10 Nov 2023 07:14:31 +0000 (15:14 +0800)
committerChristoph Müllner <christoph.muellner@vrull.eu>
Fri, 10 Nov 2023 13:26:12 +0000 (14:26 +0100)
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.

gcc/config/riscv/riscv.cc
gcc/testsuite/gcc.target/riscv/xtheadmempair-interrupt-fcsr.c [new file with mode: 0644]

index e25692b86fc183c0b4f55e35d089e0e7b2a82a1a..fa2d4d4b7795f13ece43b192b10c2c6ee32d2c3e 100644 (file)
@@ -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 (file)
index 0000000..d06f05f
--- /dev/null
@@ -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 } } */