aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1993-04-10 10:56:57 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1993-04-10 10:56:57 -0400
commitc97e3db7fadce82fa3719b1b167f73fdce74c363 (patch)
treeb795a7c9d20ddd3da48c072e5beda42218f1086f /gcc
parent26958509940f82795f35673f4003a16e60cb5da1 (diff)
downloadgcc-c97e3db7fadce82fa3719b1b167f73fdce74c363.zip
gcc-c97e3db7fadce82fa3719b1b167f73fdce74c363.tar.gz
gcc-c97e3db7fadce82fa3719b1b167f73fdce74c363.tar.bz2
(alpha_sa_size): Need to save $26 if it is used or if any other register is saved...
(alpha_sa_size): Need to save $26 if it is used or if any other register is saved, but not just because a stack space is needed. (output_prolog): Add code to probe the stack if we allocate more than 4096 bytes; required by chapter 7 (for threads). Know when to save $26. (output_epilog): Know when to restore $26. From-SVN: r4079
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/alpha/alpha.c104
1 files changed, 72 insertions, 32 deletions
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index f36a604..6ecb98e 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -1066,12 +1066,9 @@ alpha_sa_size ()
if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])
size++;
- /* If we are going to need a frame, we MUST save $26. */
- if (! regs_ever_live[26]
- && (size != 0
- || get_frame_size () != 0
- || current_function_outgoing_args_size != 0
- || current_function_pretend_args_size != 0))
+ /* If some registers were saved but not reg 26, reg 26 must also
+ be saved, so leave space for it. */
+ if (size != 0 && ! regs_ever_live[26])
size++;
return size * 8;
@@ -1146,27 +1143,57 @@ output_prolog (file, size)
/* Put a label after the GP load so we can enter the function at it. */
fprintf (file, "%s..ng:\n", alpha_function_name);
- /* Adjust the stack by the frame size. If the frame size is > 32768
- bytes, we have to load it into a register first and then subtract
- from sp. Note that we are only allowed to adjust sp once in the
- prologue. */
+ /* Adjust the stack by the frame size. If the frame size is > 4096
+ bytes, we need to be sure we probe somewhere in the first and last
+ 4096 bytes (we can probably get away without the latter test) and
+ every 8192 bytes in between. If the frame size is > 32768, we
+ do this in a loop. Otherwise, we generate the explicit probe
+ instructions.
- if (frame_size > 32768)
+ Note that we are only allowed to adjust sp once in the prologue. */
+
+ if (frame_size < 32768)
+ {
+ if (frame_size > 4096)
+ {
+ int probed = 4096;
+ int regnum = 2;
+
+ fprintf (file, "\tldq $%d,-%d($30)\n", regnum++, probed);
+
+ while (probed + 8192 < frame_size)
+ fprintf (file, "\tldq $%d,-%d($30)\n", regnum++, probed += 8192);
+
+ if (probed + 4096 < frame_size)
+ fprintf (file, "\tldq $%d,-%d($30)\n", regnum++, probed += 4096);
+
+ if (regnum > 9)
+ abort ();
+ }
+
+ if (frame_size != 0)
+ fprintf (file, "\tlda $30,-%d($30)\n", frame_size);
+ }
+ else
{
- HOST_WIDE_INT low = (frame_size & 0xffff) - 2 * (frame_size & 0x8000);
- HOST_WIDE_INT tmp1 = frame_size - low;
+ /* Here we generate code to set R4 to SP + 4096 and set R5 to the
+ number of 8192 byte blocks to probe. We then probe each block
+ in the loop and then set SP to the proper location. If the
+ amount remaining is > 4096, we have to do one more probe.
+
+ This is complicated by the code we would generate if
+ the number of blocks > 32767. */
+
+ HOST_WIDE_INT blocks = (frame_size + 4096) / 8192;
+ HOST_WIDE_INT leftover = frame_size + 4096 - blocks * 8192;
+ HOST_WIDE_INT low = (blocks & 0xffff) - 2 * (blocks & 0x8000);
+ HOST_WIDE_INT tmp1 = blocks - low;
HOST_WIDE_INT high
- = ((tmp1 >> 16) & 0xfff) - 2 * ((tmp1 >> 16) & 0x8000);
- HOST_WIDE_INT tmp2 = frame_size - (high << 16) - low;
+ = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000);
+ HOST_WIDE_INT tmp2 = blocks - (high << 16) - low;
HOST_WIDE_INT extra = 0;
int in_reg = 31;
- /* We haven't written code to handle frames > 4GB. */
-#if HOST_BITS_PER_LONG_INT == 64
- if ((unsigned HOST_WIDE_INT) frame_size >> 32 != 0)
- abort ();
-#endif
-
if (tmp2)
{
extra = 0x4000;
@@ -1176,29 +1203,42 @@ output_prolog (file, size)
if (low != 0)
{
- fprintf (file, "\tlda $28,%d($%d)\n", low, in_reg);
- in_reg = 28;
+ if (low < 255)
+ fprintf (file, "\tbis $31,%d,$5\n", low);
+ else
+ fprintf (file, "\tlda $5,%d($31)\n", low);
+ in_reg = 5;
}
if (extra)
{
- fprintf (file, "\tldah $28,%d($%d)\n", extra, in_reg);
- in_reg = 28;
+ fprintf (file, "\tldah $5,%d($%d)\n", extra, in_reg);
+ in_reg = 5;
}
- fprintf (file, "\tldah $28,%d($%d)\n", high, in_reg);
- fprintf (file, "\tsubq $30,$28,$30\n");
+ if (high)
+ fprintf (file, "\tldah $5,%d($%d)\n", high, in_reg);
+
+ fprintf (file, "\tlda $4,4096($30)\n");
+ fprintf (file, "%s..sc:\n", alpha_function_name);
+ fprintf (file, "\tldq $6,-8192($4)\n");
+ fprintf (file, "\tsubq $5,1,$5\n");
+ fprintf (file, "\tlda $4,-8192($4)\n");
+ fprintf (file, "\tbne $5,%s..sc\n", alpha_function_name);
+ fprintf (file, "\tlda $30,-%d($4)\n", leftover);
+
+ if (leftover > 4096)
+ fprintf (file, "\tldq $2,%d(sp)\n", leftover - 4096);
}
- else if (frame_size)
- fprintf (file, "\tlda $30,-%d($30)\n", frame_size);
/* Describe our frame. */
fprintf (file, "\t.frame $%d,%d,$26,%d\n",
frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM,
frame_size, current_function_pretend_args_size);
- /* Save register 26 if we have a frame. */
- if (frame_size != 0)
+ /* Save register 26 if it is used or if any other register needs to
+ be saved. */
+ if (regs_ever_live[26] || alpha_sa_size () != 0)
{
reg_mask |= 1 << 26;
fprintf (file, "\tstq $26,%d($30)\n", reg_offset);
@@ -1272,7 +1312,7 @@ output_epilog (file, size)
/* Restore all the registers, starting with the return address
register. */
- if (frame_size != 0)
+ if (regs_ever_live[26] || alpha_sa_size () != 0)
{
fprintf (file, "\tldq $26,%d($30)\n", reg_offset);
reg_offset += 8;