Commit 956a5206 by Jim Wilson

(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
parent b6c9286a
...@@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */
#include "regs.h" #include "regs.h"
#include "hard-reg-set.h" #include "hard-reg-set.h"
#include "output.h" #include "output.h"
#include "insn-attr.h"
#define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0) #define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)
#define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1) #define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)
...@@ -46,6 +47,13 @@ int pragma_interrupt; ...@@ -46,6 +47,13 @@ int pragma_interrupt;
the compiler doesn't emit code to preserve all registers. */ the compiler doesn't emit code to preserve all registers. */
static int pragma_trapa; 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 /* This is used for communication between SETUP_INCOMING_VARARGS and
sh_expand_prologue. */ sh_expand_prologue. */
int current_function_anonymous_args; int current_function_anonymous_args;
...@@ -1509,11 +1517,14 @@ calc_live_regs (count_ptr) ...@@ -1509,11 +1517,14 @@ calc_live_regs (count_ptr)
{ {
if (pragma_interrupt && ! pragma_trapa) 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] if ((regs_ever_live[reg]
|| (call_used_regs[reg] && regs_ever_live[PR_REG])) || (call_used_regs[reg] && regs_ever_live[PR_REG]))
&& reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM && 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; live_regs_mask |= 1 << reg;
count++; count++;
...@@ -1613,7 +1624,7 @@ function_epilogue (stream, size) ...@@ -1613,7 +1624,7 @@ function_epilogue (stream, size)
FILE *stream; FILE *stream;
int size; 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 /* Define the offset between two registers, one to be eliminated, and
...@@ -1675,6 +1686,11 @@ handle_pragma (file) ...@@ -1675,6 +1686,11 @@ handle_pragma (file)
pragma_interrupt = pragma_trapa = 1; pragma_interrupt = pragma_trapa = 1;
return ' '; return ' ';
} }
if (psize == 15 && strncmp (pbuf, "nosave_low_regs", 15) == 0)
{
pragma_nosave_low_regs = 1;
return ' ';
}
c = getc (file); c = getc (file);
} }
return c; return c;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment