This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
alpha reg save area patch
- To: egcs at cygnus dot com
- Subject: alpha reg save area patch
- From: Richard Henderson <rth at cygnus dot com>
- Date: Thu, 11 Sep 1997 11:39:30 -0700 (PDT)
- Cc: wilson at cygnus dot com
- Reply-To: rth at cygnus dot com (Richard Henderson)
The following program outputs bad assembly on the Alpha:
struct bigstruct { long x[10000]; };
void foo(struct bigstruct x);
main()
{
struct bigstruct bar;
foo(bar);
return 0;
}
And here's a patch.
r~
--- config/alpha/alpha.c.orig Thu Sep 11 11:00:00 1997
+++ config/alpha/alpha.c Thu Sep 11 11:21:57 1997
@@ -2326,7 +2326,7 @@ output_prolog (file, size)
int int_reg_save_area_size = 0;
rtx insn;
unsigned reg_mask = 0;
- int i;
+ int i, sa_reg;
/* Ecoff can handle multiple .file directives, so put out file and lineno.
We have to do that before the .ent directive as we cannot switch
@@ -2472,12 +2472,30 @@ output_prolog (file, size)
? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM),
frame_size, current_function_pretend_args_size);
}
+
+ /* Cope with very large offsets to the register save area. */
+ sa_reg = 30;
+ if (reg_offset + sa_size > 0x8000)
+ {
+ int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
+ if (low + sa_size <= 0x8000)
+ {
+ add_long_const (file, reg_offset - low, 30, 24, 24);
+ reg_offset = low;
+ }
+ else
+ {
+ add_long_const (file, reg_offset, 30, 24, 24);
+ reg_offset = 0;
+ }
+ sa_reg = 24;
+ }
/* Save register 26 if any other register needs to be saved. */
if (sa_size != 0)
{
reg_mask |= 1 << 26;
- fprintf (file, "\tstq $26,%d($30)\n", reg_offset);
+ fprintf (file, "\tstq $26,%d($%d)\n", reg_offset, sa_reg);
reg_offset += 8;
int_reg_save_area_size += 8;
}
@@ -2487,7 +2505,7 @@ output_prolog (file, size)
if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] && i != 26)
{
reg_mask |= 1 << i;
- fprintf (file, "\tstq $%d,%d($30)\n", i, reg_offset);
+ fprintf (file, "\tstq $%d,%d($%d)\n", i, reg_offset, sa_reg);
reg_offset += 8;
int_reg_save_area_size += 8;
}
@@ -2505,7 +2523,7 @@ output_prolog (file, size)
&& regs_ever_live[i + 32])
{
reg_mask |= 1 << i;
- fprintf (file, "\tstt $f%d,%d($30)\n", i, reg_offset);
+ fprintf (file, "\tstt $f%d,%d($%d)\n", i, reg_offset, sa_reg);
reg_offset += 8;
}
@@ -2551,6 +2569,7 @@ output_epilog (file, size)
if (insn == 0 || GET_CODE (insn) != BARRIER)
{
int fp_offset = 0;
+ int sa_reg;
final_prescan_insn (NULL_RTX, NULL_PTR, 0);
@@ -2558,11 +2577,29 @@ output_epilog (file, size)
if (frame_pointer_needed)
fprintf (file, "\tbis $15,$15,$30\n");
+ /* Cope with large offsets to the register save area. */
+ sa_reg = 30;
+ if (reg_offset + sa_size > 0x8000)
+ {
+ int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
+ if (low + sa_size <= 0x8000)
+ {
+ add_long_const (file, reg_offset - low, 30, 24, 24);
+ reg_offset = low;
+ }
+ else
+ {
+ add_long_const (file, reg_offset, 30, 24, 24);
+ reg_offset = 0;
+ }
+ sa_reg = 24;
+ }
+
/* Restore all the registers, starting with the return address
register. */
if (sa_size != 0)
{
- fprintf (file, "\tldq $26,%d($30)\n", reg_offset);
+ fprintf (file, "\tldq $26,%d($%d)\n", reg_offset, sa_reg);
reg_offset += 8;
}
@@ -2577,7 +2614,7 @@ output_epilog (file, size)
if (i == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
fp_offset = reg_offset;
else
- fprintf (file, "\tldq $%d,%d($30)\n", i, reg_offset);
+ fprintf (file, "\tldq $%d,%d($%d)\n", i, reg_offset, sa_reg);
reg_offset += 8;
}
@@ -2585,7 +2622,7 @@ output_epilog (file, size)
if (! fixed_regs[i + 32] && ! call_used_regs[i + 32]
&& regs_ever_live[i + 32])
{
- fprintf (file, "\tldt $f%d,%d($30)\n", i, reg_offset);
+ fprintf (file, "\tldt $f%d,%d($%d)\n", i, reg_offset, sa_reg);
reg_offset += 8;
}
@@ -2600,7 +2637,7 @@ output_epilog (file, size)
now. This must be done in one instruction immediately
before the SP update. */
if (restore_fp && fp_offset)
- fprintf (file, "\tldq $15,%d($30)\n", fp_offset);
+ fprintf (file, "\tldq $15,%d($%d)\n", fp_offset, sa_reg);
/* Now update the stack pointer, if needed. Only one instruction must
modify the stack pointer. It must be the last instruction in the