`interrupt` function will backup fcsr register, but it fixed to SImode,
it's not big issue since fcsr only used 8 bits so far, however the
offset should still using UNITS_PER_WORD to prevent the stack offset
become non 8 byte aligned, it will cause problem for RV64.
gcc/ChangeLog:
* config/riscv/riscv.cc (riscv_for_each_saved_reg): Adjust the
offset of fcsr.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/interrupt-misaligned.c: New.
|| (TARGET_ZFINX
&& (cfun->machine->frame.mask & ~(1 << RISCV_PROLOGUE_TEMP_REGNUM)))))
{
- unsigned int fcsr_size = GET_MODE_SIZE (SImode);
+ /* Always assume FCSR occupy UNITS_PER_WORD to prevent stack
+ offset misaligned later. */
+ unsigned int fcsr_size = UNITS_PER_WORD;
if (!epilogue)
{
riscv_save_restore_reg (word_mode, regno, offset, fn);
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc -mabi=lp64d -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-skip-if "" { *-*-* } { "-flto -fno-fat-lto-objects" } } */
+
+/* Make sure no stack offset are misaligned.
+** interrupt:
+** ...
+** sd\tt0,40\(sp\)
+** frcsr\tt0
+** sw\tt0,32\(sp\)
+** sd\tt1,24\(sp\)
+** fsd\tft0,8\(sp\)
+** ...
+** lw\tt0,32\(sp\)
+** fscsr\tt0
+** ld\tt0,40\(sp\)
+** ld\tt1,24\(sp\)
+** fld\tft0,8\(sp\)
+** ...
+*/
+
+
+void interrupt(void) __attribute__((interrupt));
+void interrupt(void)
+{
+ asm volatile ("# clobber!":::"t0", "t1", "ft0");
+}
+
+/* { dg-final { check-function-bodies "**" "" } } */