diff options
author | Jim Wilson <wilson@gcc.gnu.org> | 1995-11-30 12:31:06 -0800 |
---|---|---|
committer | Jim Wilson <wilson@gcc.gnu.org> | 1995-11-30 12:31:06 -0800 |
commit | 956a5206b05d26a2b9bc52813eeeb1686279caa1 (patch) | |
tree | 0381a6eb514d956a2d8275e75c4b435f1d701a8d | |
parent | b6c9286a86e351a50cd49fc0cd8934d99875e14d (diff) | |
download | gcc-956a5206b05d26a2b9bc52813eeeb1686279caa1.zip gcc-956a5206b05d26a2b9bc52813eeeb1686279caa1.tar.gz gcc-956a5206b05d26a2b9bc52813eeeb1686279caa1.tar.bz2 |
(insn-attr.h): Include.
(pragma_nosave_low_regs): New global variable.
(calc_live_regs): If SH3 and pragma_nosave_low_regs, then don't
save registers r0 through r7 for interrupt functions.
(function_epilogue): Clear pragma_nosave_low_regs.
(handle_pragma): Set pragma_nosave_low_regs if see pragma for it.
From-SVN: r10649
-rw-r--r-- | gcc/config/sh/sh.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index bbb708c..f6ff44c 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */ #include "regs.h" #include "hard-reg-set.h" #include "output.h" +#include "insn-attr.h" #define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0) #define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1) @@ -46,6 +47,13 @@ int pragma_interrupt; the compiler doesn't emit code to preserve all registers. */ static int pragma_trapa; +/* This is set by #pragma nosave_low_regs. This is useful on the SH3, + which has a separate set of low regs for User and Supervisor modes. + This should only be used for the lowest level of interrupts. Higher levels + of interrupts must save the registers in case they themselves are + interrupted. */ +int pragma_nosave_low_regs; + /* This is used for communication between SETUP_INCOMING_VARARGS and sh_expand_prologue. */ int current_function_anonymous_args; @@ -1509,11 +1517,14 @@ calc_live_regs (count_ptr) { if (pragma_interrupt && ! pragma_trapa) { - /* Need to save all the regs ever live. */ + /* Normally, we must save all the regs ever live. + If pragma_nosave_low_regs, then don't save any of the + registers which are banked on the SH3. */ if ((regs_ever_live[reg] || (call_used_regs[reg] && regs_ever_live[PR_REG])) && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM - && reg != T_REG && reg != GBR_REG) + && reg != T_REG && reg != GBR_REG + && ! (sh_cpu == CPU_SH3 && pragma_nosave_low_regs && reg < 8)) { live_regs_mask |= 1 << reg; count++; @@ -1613,7 +1624,7 @@ function_epilogue (stream, size) FILE *stream; int size; { - pragma_interrupt = pragma_trapa = 0; + pragma_interrupt = pragma_trapa = pragma_nosave_low_regs = 0; } /* Define the offset between two registers, one to be eliminated, and @@ -1675,6 +1686,11 @@ handle_pragma (file) pragma_interrupt = pragma_trapa = 1; return ' '; } + if (psize == 15 && strncmp (pbuf, "nosave_low_regs", 15) == 0) + { + pragma_nosave_low_regs = 1; + return ' '; + } c = getc (file); } return c; |