aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJim Wilson <wilson@gcc.gnu.org>1995-11-30 12:31:06 -0800
committerJim Wilson <wilson@gcc.gnu.org>1995-11-30 12:31:06 -0800
commit956a5206b05d26a2b9bc52813eeeb1686279caa1 (patch)
tree0381a6eb514d956a2d8275e75c4b435f1d701a8d /gcc
parentb6c9286a86e351a50cd49fc0cd8934d99875e14d (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/sh/sh.c22
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;