This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[m68k] Fix and improve ColdFire function prologue/epilogue generation
- From: Bernardo Innocenti <bernie at develer dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Peter Barada <peter at baradas dot org>
- Date: Wed, 13 Aug 2003 02:40:03 +0200
- Subject: [m68k] Fix and improve ColdFire function prologue/epilogue generation
- Organization: Develer S.r.l.
This patch optimizes the function prologue and epilogue generation for ColdFire
targets, where the movem instructions lacks addressing modes with post-increment
and pre-decrement. It also fixes -fomit-frame-pointer on the ColdFire.
- Replace obsolete INITIAL_FRAME_POINTER_OFFSET() macro
with INITIAL_ELIMINATION_OFFSET();
- move ARG_POINTER_REGNUM to a distinct regno, to avoid
confusion with FRAME_POINTER_REGNUM in register elimination;
- Correct computation of coalesced frame + saved regs size at
function prologue and epilogue output.
(This work is partially based on Peter Barada's GCC 3.2.3 patches for ColdFire targets)
NOTE: This should be applied over the previously submitted ColdFire patches which
are still uncommitted.
ALSO NOTE: I've not yet been able to validate these changes through the testsuite,
but all of uClinux (kernel and userland) currently build and run with this patch
applied (and won't work at all without it ;-). Testing again on 680x0 targets
would be highly advisable.
2003-08-06 Bernardo Innocenti <bernie@develer.com>
Peter Barada <peter@baradas.org>
* config/m68k/coff.h (REGISTER_NAMES): Add fake register `argptr'
* config/m68k/hp320.h (REGISTER_NAMES): Likewise.
* config/m68k/linux.h (REGISTER_NAMES): Likewise.
* config/m68k/m68kelf.h (REGISTER_NAMES): Likewise.
* gcc/config/m68k/sgs.h (REGISTER_NAMES): Likewise.
* config/m68k/m68k-protos.h (m68k_initial_elimination_offset): Add prototype.
* config/m68k/m68k.c (m68k_frame): New struct, simular to ix86 back-end.
(m68k_compute_frame_layout): New function.
(m68k_initial_elimination_offset): New function.
(m68k_output_function_prologue): ColdFire-specific movem handling.
(m68k_output_function_epilogue): Likewise.
* config/m68k/m68k.h (FIRST_PSEOUDO_REGISTER): Make room for argptr reg.
(ARG_POINTER_REGNUM): Add new definition.
(INITIAL_FRAME_POINTER_OFFSET): Remove macro.
(ELIMINABLE_REGS): Define new macro, like in ix86 back-end.
(CAN_ELIMINATE): Likewise.
(INITIAL_ELIMINATION_OFFSET): Likewise.
diff -Nrup gcc-3.4-20030730.orig/gcc/config/m68k/coff.h gcc-3.4-20030730/gcc/config/m68k/coff.h
--- gcc-3.4-20030730.orig/gcc/config/m68k/coff.h 2003-08-02 19:02:52.000000000 +0200
+++ gcc-3.4-20030730/gcc/config/m68k/coff.h 2003-08-02 23:33:58.000000000 +0200
@@ -74,7 +74,7 @@ Boston, MA 02111-1307, USA. */
#define REGISTER_NAMES \
{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
"%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
- "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7" }
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", "argptr" }
#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
diff -Nrup gcc-3.4-20030730.orig/gcc/config/m68k/hp320.h gcc-3.4-20030730/gcc/config/m68k/hp320.h
--- gcc-3.4-20030730.orig/gcc/config/m68k/hp320.h 2003-07-07 05:42:23.000000000 +0200
+++ gcc-3.4-20030730/gcc/config/m68k/hp320.h 2003-08-02 23:33:58.000000000 +0200
@@ -188,7 +188,7 @@ Boston, MA 02111-1307, USA. */
#define REGISTER_NAMES \
{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
"%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
- "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7"}
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", "argptr"}
#define IMMEDIATE_PREFIX "&"
#define REGISTER_PREFIX "%"
diff -Nrup gcc-3.4-20030730.orig/gcc/config/m68k/linux.h gcc-3.4-20030730/gcc/config/m68k/linux.h
--- gcc-3.4-20030730.orig/gcc/config/m68k/linux.h 2003-08-02 19:02:52.000000000 +0200
+++ gcc-3.4-20030730/gcc/config/m68k/linux.h 2003-08-02 23:33:58.000000000 +0200
@@ -83,7 +83,7 @@ Boston, MA 02111-1307, USA. */
#define REGISTER_NAMES \
{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
"%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
- "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7" }
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", "argptr" }
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
diff -Nrup gcc-3.4-20030730.orig/gcc/config/m68k/m68k-protos.h gcc-3.4-20030730/gcc/config/m68k/m68k-protos.h
--- gcc-3.4-20030730.orig/gcc/config/m68k/m68k-protos.h 2003-01-28 05:46:29.000000000 +0100
+++ gcc-3.4-20030730/gcc/config/m68k/m68k-protos.h 2003-08-02 19:08:48.000000000 +0200
@@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */
/* Define functions defined in aux-output.c and used in templates. */
#ifdef RTX_CODE
+extern HOST_WIDE_INT m68k_initial_elimination_offset PARAMS ((int, int));
extern const char *output_move_const_into_data_reg PARAMS ((rtx *));
extern const char *output_move_simode_const PARAMS ((rtx *));
extern const char *output_move_simode PARAMS ((rtx *));
diff -Nrup gcc-3.4-20030730.orig/gcc/config/m68k/m68k.c gcc-3.4-20030730/gcc/config/m68k/m68k.c
--- gcc-3.4-20030730.orig/gcc/config/m68k/m68k.c 2003-08-02 19:02:52.000000000 +0200
+++ gcc-3.4-20030730/gcc/config/m68k/m68k.c 2003-08-02 23:33:58.000000000 +0200
@@ -216,6 +216,101 @@ override_options ()
real_format_for_mode[XFmode - QFmode] = &ieee_extended_motorola_format;
}
+/* Structure describing stack frame layout. */
+struct m68k_frame {
+ HOST_WIDE_INT offset;
+ HOST_WIDE_INT size;
+ /* data and address register */
+ int reg_no;
+ unsigned int reg_mask;
+ unsigned int reg_rev_mask;
+ /* fpu registers */
+ int fpu_no;
+ unsigned int fpu_mask;
+ unsigned int fpu_rev_mask;
+ /* fpa registers */
+ int fpa_no;
+ /* offsets relative to ARG_POINTER. */
+ HOST_WIDE_INT frame_pointer_offset;
+ HOST_WIDE_INT hard_frame_pointer_offset;
+ HOST_WIDE_INT stack_pointer_offset;
+};
+
+static void
+m68k_compute_frame_layout (frame)
+ struct m68k_frame *frame;
+{
+ int regno, saved;
+ unsigned int mask, rmask;
+
+ frame->size = (get_frame_size () + 3) & -4;
+
+ mask = rmask = saved = 0;
+ for (regno = 0; regno < 16; regno++)
+ if (m68k_save_reg (regno))
+ {
+ mask |= 1 << regno;
+ rmask |= 1 << (15 - regno);
+ saved++;
+ }
+ frame->offset = saved * 4;
+ frame->reg_no = saved;
+ frame->reg_mask = mask;
+ frame->reg_rev_mask = rmask;
+
+ if (TARGET_68881)
+ {
+ mask = rmask = saved = 0;
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ mask |= 1 << (23 - regno);
+ rmask |= 1 << (regno - 16);
+ saved++;
+ }
+ frame->offset += saved * 12;
+ frame->fpu_no = saved;
+ frame->fpu_mask = mask;
+ frame->fpu_rev_mask = rmask;
+ }
+ if (0 /* || TARGET_CFV4E */)
+ {
+ mask = rmask = saved = 0;
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ mask |= 1 << (23 - regno);
+ rmask |= 1 << (regno - 16);
+ saved++;
+ }
+ frame->offset += saved * 8;
+ frame->fpu_no = saved;
+ frame->fpu_mask = mask;
+ frame->fpu_rev_mask = rmask;
+ }
+}
+
+HOST_WIDE_INT
+m68k_initial_elimination_offset (from, to)
+ int from;
+ int to;
+{
+ struct m68k_frame frame;
+
+ m68k_compute_frame_layout (&frame);
+
+ if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+ return 0;
+ else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+ return frame.offset + frame.size + (frame_pointer_needed ? -UNITS_PER_WORD * 2 : -UNITS_PER_WORD);
+ else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+ return frame.offset + frame.size;
+ else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+ return 0;
+
+ abort();
+}
+
/* Return 1 if we need to save REGNO. */
static int
m68k_save_reg (regno)
@@ -265,6 +360,7 @@ m68k_output_function_prologue (stream, s
register int mask = 0;
int num_saved_regs = 0;
HOST_WIDE_INT fsize = (size + 3) & -4;
+ HOST_WIDE_INT fsize_with_regs;
HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;
HOST_WIDE_INT cfa_store_offset = cfa_offset;
@@ -282,6 +378,21 @@ m68k_output_function_prologue (stream, s
#endif
}
+ if (TARGET_COLDFIRE)
+ {
+ /* on Coldfire add register save into initial stack frame setup, if possible */
+ for (regno = 0; regno < 16; regno++)
+ if (m68k_save_reg (regno))
+ num_saved_regs++;
+
+ if (num_saved_regs <= 2)
+ num_saved_regs = 0;
+ }
+ else
+ num_saved_regs = 0;
+
+ fsize_with_regs = fsize + num_saved_regs * 4;
+
if (frame_pointer_needed)
{
if (fsize == 0 && TARGET_68040)
@@ -299,35 +410,35 @@ m68k_output_function_prologue (stream, s
reg_names[FRAME_POINTER_REGNUM]);
#endif
}
- else if (fsize < 0x8000)
+ else if (fsize_with_regs < 0x8000)
{
#ifdef MOTOROLA
- asm_fprintf (stream, "\tlink.w %s,%I%wd\n",
- reg_names[FRAME_POINTER_REGNUM], -fsize);
+ asm_fprintf (stream, "\tlink.w %s,%I%wd\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize_with_regs);
#else
- asm_fprintf (stream, "\tlink %s,%I%wd\n",
- reg_names[FRAME_POINTER_REGNUM], -fsize);
+ asm_fprintf (stream, "\tlink %s,%I%wd\n",
+ reg_names[FRAME_POINTER_REGNUM], -fsize_with_regs);
#endif
}
else if (TARGET_68020)
{
#ifdef MOTOROLA
asm_fprintf (stream, "\tlink.l %s,%I%wd\n",
- reg_names[FRAME_POINTER_REGNUM], -fsize);
+ reg_names[FRAME_POINTER_REGNUM], -fsize_with_regs);
#else
asm_fprintf (stream, "\tlink %s,%I%wd\n",
- reg_names[FRAME_POINTER_REGNUM], -fsize);
+ reg_names[FRAME_POINTER_REGNUM], -fsize_with_regs);
#endif
}
else
{
- /* Adding negative number is faster on the 68040. */
+ /* Adding negative number is faster on the 68040. */
#ifdef MOTOROLA
asm_fprintf (stream, "\tlink.w %s,%I0\n\tadd.l %I%wd,%Rsp\n",
- reg_names[FRAME_POINTER_REGNUM], -fsize);
+ reg_names[FRAME_POINTER_REGNUM], -fsize_with_regs);
#else
asm_fprintf (stream, "\tlink %s,%I0\n\taddl %I%wd,%Rsp\n",
- reg_names[FRAME_POINTER_REGNUM], -fsize);
+ reg_names[FRAME_POINTER_REGNUM], -fsize_with_regs);
#endif
}
if (dwarf2out_do_frame ())
@@ -341,33 +452,33 @@ m68k_output_function_prologue (stream, s
cfa_store_offset += fsize;
}
}
- else if (fsize)
+ else if (fsize_with_regs) /* !frame_pointer_needed */
{
- if (fsize + 4 < 0x8000)
+ if (fsize_with_regs < 0x8000)
{
#ifndef NO_ADDSUB_Q
- if (fsize + 4 <= 8)
+ if (fsize_with_regs <= 8)
{
if (!TARGET_COLDFIRE)
{
/* asm_fprintf() cannot handle %. */
#ifdef MOTOROLA
- asm_fprintf (stream, "\tsubq.w %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\tsubq.w %I%wd,%Rsp\n", fsize_with_regs);
#else
- asm_fprintf (stream, "\tsubqw %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\tsubqw %I%wd,%Rsp\n", fsize_with_regs);
#endif
}
else
{
/* asm_fprintf() cannot handle %. */
#ifdef MOTOROLA
- asm_fprintf (stream, "\tsubq.l %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\tsubq.l %I%wd,%Rsp\n", fsize_with_regs);
#else
- asm_fprintf (stream, "\tsubql %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\tsubql %I%wd,%Rsp\n", fsize_with_regs);
#endif
}
}
- else if (fsize + 4 <= 16 && TARGET_CPU32)
+ else if (fsize_with_regs <= 16 && TARGET_CPU32)
{
/* On the CPU32 it is faster to use two subqw instructions to
subtract a small integer (8 < N <= 16) to a register. */
@@ -375,10 +486,10 @@ m68k_output_function_prologue (stream, s
#ifdef MOTOROLA
asm_fprintf (stream,
"\tsubq.w %I8,%Rsp\n\tsubq.w %I%wd,%Rsp\n",
- fsize + 4 - 8);
+ fsize_with_regs - 8);
#else
asm_fprintf (stream, "\tsubqw %I8,%Rsp\n\tsubqw %I%wd,%Rsp\n",
- fsize + 4 - 8);
+ fsize_with_regs - 8);
#endif
}
else
@@ -388,27 +499,26 @@ m68k_output_function_prologue (stream, s
/* Adding negative number is faster on the 68040. */
/* asm_fprintf() cannot handle %. */
#ifdef MOTOROLA
- asm_fprintf (stream, "\tadd.w %I%wd,%Rsp\n", - (fsize + 4));
+ asm_fprintf (stream, "\tadd.w %I%wd,%Rsp\n", -fsize_with_regs);
#else
- asm_fprintf (stream, "\taddw %I%wd,%Rsp\n", - (fsize + 4));
+ asm_fprintf (stream, "\taddw %I%wd,%Rsp\n", -fsize_with_regs);
#endif
}
else
{
#ifdef MOTOROLA
- asm_fprintf (stream, "\tlea (%wd,%Rsp),%Rsp\n", - (fsize + 4));
+ asm_fprintf (stream, "\tlea (%wd,%Rsp),%Rsp\n", -fsize_with_regs);
#else
- asm_fprintf (stream, "\tlea %Rsp@(%wd),%Rsp\n", - (fsize + 4));
+ asm_fprintf (stream, "\tlea %Rsp@(%wd),%Rsp\n", -fsize_with_regs);
#endif
}
}
- else
+ else /* fsize_with_regs >= 0x8000 */
{
- /* asm_fprintf() cannot handle %. */
#ifdef MOTOROLA
- asm_fprintf (stream, "\tadd.l %I%wd,%Rsp\n", - (fsize + 4));
+ asm_fprintf (stream, "\tadd.l %I%wd,%Rsp\n", -fsize_with_regs);
#else
- asm_fprintf (stream, "\taddl %I%wd,%Rsp\n", - (fsize + 4));
+ asm_fprintf (stream, "\taddl %I%wd,%Rsp\n", -fsize_with_regs);
#endif
}
if (dwarf2out_do_frame ())
@@ -417,7 +527,10 @@ m68k_output_function_prologue (stream, s
cfa_offset = cfa_store_offset;
dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
}
- }
+ } /* !frame_pointer_needed */
+
+ num_saved_regs = 0;
+
if (TARGET_68881)
{
for (regno = 16; regno < 24; regno++)
@@ -521,10 +634,8 @@ m68k_output_function_prologue (stream, s
then use the plain address register indirect mode. We also
have to invert the register save mask to use the new mode.
- FIXME: if num_saved_regs was calculated earlier, we could
- combine the stack pointer adjustment with any adjustment
- done when the initial stack frame is created. This would
- save an instruction */
+ The required register save space was combined earlier with
+ the fsize amount. Don't add it again. */
int newmask = 0;
int i;
@@ -534,10 +645,8 @@ m68k_output_function_prologue (stream, s
newmask |= (1 << (15-i));
#ifdef MOTOROLA
- asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs*4);
asm_fprintf (stream, "\tmovm.l %I0x%x,(%Rsp)\n", newmask);
#else
- asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs*4);
asm_fprintf (stream, "\tmoveml %I0x%x,%Rsp@\n", newmask);
#endif
}
@@ -616,6 +725,7 @@ m68k_output_function_epilogue (stream, s
register int nregs;
HOST_WIDE_INT offset, foffset;
HOST_WIDE_INT fsize = (size + 3) & -4;
+ HOST_WIDE_INT fsize_with_regs;
int big = 0;
rtx insn = get_last_insn ();
int restore_from_sp = 0;
@@ -658,18 +768,45 @@ m68k_output_function_epilogue (stream, s
stack adjustment needed at that point. */
restore_from_sp = ! frame_pointer_needed
|| (! current_function_calls_alloca && leaf_function_p ());
+
+ /* fsize_with_regs is the size we need to adjust the sp when
+ popping the frame */
+ fsize_with_regs = fsize;
+
+ /* Because the ColdFire doesn't support moveml with
+ complex address modes, we must adjust the stack manually
+ after restoring registers. When the frame pointer isn't used,
+ we can merge movem adjustment into frame unlinking
+ made immediately after it. */
+ if (TARGET_COLDFIRE && restore_from_sp && (nregs > 2))
+ fsize_with_regs += nregs * 4;
+
if (offset + fsize >= 0x8000
&& ! restore_from_sp
&& (mask || fmask))
{
+ /* Because the ColdFire doesn't support moveml with
+ complex address modes we make an extra correction here */
+ if (TARGET_COLDFIRE)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\t%Omove.l %I%d,%Ra1\n", -fsize - offset);
+#else
+ asm_fprintf (stream, "\tmovel %I%d,%Ra1\n", -fsize - offset);
+#endif
+ }
+ else
+ {
#ifdef MOTOROLA
- asm_fprintf (stream, "\t%Omove.l %I%wd,%Ra1\n", -fsize);
+ asm_fprintf (stream, "\t%Omove.l %I%wd,%Ra1\n", -fsize);
#else
- asm_fprintf (stream, "\tmovel %I%wd,%Ra1\n", -fsize);
+ asm_fprintf (stream, "\tmovel %I%wd,%Ra1\n", -fsize);
#endif
+ }
+
fsize = 0, big = 1;
}
- if (TARGET_COLDFIRE || nregs <= 2)
+ if (nregs <= 2)
{
/* Restore each separately in the same order moveml does.
Using two movel instructions instead of a single moveml
@@ -724,39 +861,77 @@ m68k_output_function_epilogue (stream, s
}
else if (mask)
{
- if (big)
- {
+ /* The ColdFire requires special handling due to its limited moveml insn */
+ if (TARGET_COLDFIRE)
+ {
+ if (big)
+ {
#ifdef MOTOROLA
- asm_fprintf (stream, "\tmovm.l -%wd(%s,%Ra1.l),%I0x%x\n",
- offset + fsize,
- reg_names[FRAME_POINTER_REGNUM],
- mask);
+ asm_fprintf (stream, "\tadd.l %s,%Ra1\n", reg_names[FRAME_POINTER_REGNUM]);
+ asm_fprintf (stream, "\tmovm.l (%Ra1),%I0x%x\n", mask);
#else
- asm_fprintf (stream, "\tmoveml %s@(-%wd,%Ra1:l),%I0x%x\n",
- reg_names[FRAME_POINTER_REGNUM],
- offset + fsize, mask);
+ asm_fprintf (stream, "\taddl %s,%Ra1\n", reg_names[FRAME_POINTER_REGNUM]);
+ asm_fprintf (stream, "\tmoveml %Ra1@,%I0x%x\n", mask);
#endif
- }
- else if (restore_from_sp)
- {
+ }
+ else if (restore_from_sp)
+ {
#ifdef MOTOROLA
- asm_fprintf (stream, "\tmovm.l (%Rsp)+,%I0x%x\n", mask);
+ asm_fprintf (stream, "\tmovm.l (%Rsp),%I0x%x\n", mask);
#else
- asm_fprintf (stream, "\tmoveml %Rsp@+,%I0x%x\n", mask);
+ asm_fprintf (stream, "\tmoveml %Rsp@,%I0x%x\n", mask);
#endif
- }
- else
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ mask);
+#else
+ asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ offset + fsize, mask);
+#endif
+ }
+ }
+ else /* !TARGET_COLDFIRE */
{
+ if (big)
+ {
#ifdef MOTOROLA
- asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n",
- offset + fsize,
- reg_names[FRAME_POINTER_REGNUM],
- mask);
+ asm_fprintf (stream, "\tmovm.l -%wd(%s,%Ra1.l),%I0x%x\n",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ mask);
+#else
+ asm_fprintf (stream, "\tmoveml %s@(-%wd,%Ra1:l),%I0x%x\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ offset + fsize, mask);
+#endif
+ }
+ else if (restore_from_sp)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tmovm.l (%Rsp)+,%I0x%x\n", mask);
#else
- asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n",
- reg_names[FRAME_POINTER_REGNUM],
- offset + fsize, mask);
+ asm_fprintf (stream, "\tmoveml %Rsp@+,%I0x%x\n", mask);
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tmovm.l -%wd(%s),%I0x%x\n",
+ offset + fsize,
+ reg_names[FRAME_POINTER_REGNUM],
+ mask);
+#else
+ asm_fprintf (stream, "\tmoveml %s@(-%wd),%I0x%x\n",
+ reg_names[FRAME_POINTER_REGNUM],
+ offset + fsize, mask);
#endif
+ }
}
}
if (fmask)
@@ -799,60 +974,60 @@ m68k_output_function_epilogue (stream, s
if (frame_pointer_needed)
fprintf (stream, "\tunlk %s\n",
reg_names[FRAME_POINTER_REGNUM]);
- else if (fsize)
+ else if (fsize_with_regs)
{
#ifndef NO_ADDSUB_Q
- if (fsize + 4 <= 8)
+ if (fsize_with_regs <= 8)
{
if (!TARGET_COLDFIRE)
{
#ifdef MOTOROLA
- asm_fprintf (stream, "\taddq.w %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\taddq.w %I%wd,%Rsp\n", fsize_with_regs);
#else
- asm_fprintf (stream, "\taddqw %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\taddqw %I%wd,%Rsp\n", fsize_with_regs);
#endif
}
- else
+ else /* TARGET_COLDFIRE */
{
#ifdef MOTOROLA
- asm_fprintf (stream, "\taddq.l %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\taddq.l %I%wd,%Rsp\n", fsize_with_regs);
#else
- asm_fprintf (stream, "\taddql %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\taddql %I%wd,%Rsp\n", fsize_with_regs);
#endif
}
}
- else if (fsize + 4 <= 16 && TARGET_CPU32)
+ else if (fsize_with_regs <= 16 && TARGET_CPU32)
{
/* On the CPU32 it is faster to use two addqw instructions to
add a small integer (8 < N <= 16) to a register. */
/* asm_fprintf() cannot handle %. */
#ifdef MOTOROLA
asm_fprintf (stream, "\taddq.w %I8,%Rsp\n\taddq.w %I%wd,%Rsp\n",
- fsize + 4 - 8);
+ fsize_with_regs - 8);
#else
asm_fprintf (stream, "\taddqw %I8,%Rsp\n\taddqw %I%wd,%Rsp\n",
- fsize + 4 - 8);
+ fsize_with_regs - 8);
#endif
}
else
#endif /* not NO_ADDSUB_Q */
- if (fsize + 4 < 0x8000)
+ if (fsize_with_regs < 0x8000)
{
if (TARGET_68040)
{
/* asm_fprintf() cannot handle %. */
#ifdef MOTOROLA
- asm_fprintf (stream, "\tadd.w %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\tadd.w %I%wd,%Rsp\n", fsize_with_regs);
#else
- asm_fprintf (stream, "\taddw %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\taddw %I%wd,%Rsp\n", fsize_with_regs);
#endif
}
else
{
#ifdef MOTOROLA
- asm_fprintf (stream, "\tlea (%wd,%Rsp),%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\tlea (%wd,%Rsp),%Rsp\n", fsize_with_regs);
#else
- asm_fprintf (stream, "\tlea %Rsp@(%wd),%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\tlea %Rsp@(%wd),%Rsp\n", fsize_with_regs);
#endif
}
}
@@ -860,9 +1035,9 @@ m68k_output_function_epilogue (stream, s
{
/* asm_fprintf() cannot handle %. */
#ifdef MOTOROLA
- asm_fprintf (stream, "\tadd.l %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\tadd.l %I%wd,%Rsp\n", fsize_with_regs);
#else
- asm_fprintf (stream, "\taddl %I%wd,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\taddl %I%wd,%Rsp\n", fsize_with_regs);
#endif
}
}
diff -Nrup gcc-3.4-20030730.orig/gcc/config/m68k/m68k.h gcc-3.4-20030730/gcc/config/m68k/m68k.h
--- gcc-3.4-20030730.orig/gcc/config/m68k/m68k.h 2003-08-02 19:02:52.000000000 +0200
+++ gcc-3.4-20030730/gcc/config/m68k/m68k.h 2003-08-02 23:33:58.000000000 +0200
@@ -386,7 +386,7 @@ extern int target_flags;
For the 68000, we give the data registers numbers 0-7,
the address registers numbers 010-017,
and the 68881 floating point registers numbers 020-027. */
-#define FIRST_PSEUDO_REGISTER 24
+#define FIRST_PSEUDO_REGISTER 25
/* This defines the register which is used to hold the offset table for PIC. */
#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 13 : INVALID_REGNUM)
@@ -493,8 +493,11 @@ extern int target_flags;
This is computed in `reload', in reload1.c. */
#define FRAME_POINTER_REQUIRED 0
-/* Base register for access to arguments of the function. */
-#define ARG_POINTER_REGNUM 14
+/* Base register for access to arguments of the function.
+ * This isn't a hardware register. It will be eliminated to the
+ * stack pointer or frame pointer.
+ */
+#define ARG_POINTER_REGNUM 24
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM 8
@@ -879,32 +882,6 @@ enum reg_class {
You should override this if you define FUNCTION_EXTRA_EPILOGUE. */
#define USE_RETURN_INSN use_return_insn ()
-/* Store in the variable DEPTH the initial difference between the
- frame pointer reg contents and the stack pointer reg contents,
- as of the start of the function body. This depends on the layout
- of the fixed parts of the stack frame and on how registers are saved.
-
- On the 68k, if we have a frame, we must add one word to its length
- to allow for the place that a6 is stored when we do have a frame pointer.
- Otherwise, we would need to compute the offset from the frame pointer
- of a local variable as a function of frame_pointer_needed, which
- is hard. */
-
-#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \
-{ int regno; \
- int offset = -4; \
- for (regno = 16; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- offset += 12; \
- for (regno = 0; regno < 16; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- offset += 4; \
- if (flag_pic && current_function_uses_pic_offset_table) \
- offset += 4; \
- (DEPTH) = (offset + ((get_frame_size () + 3) & -4) \
- + (get_frame_size () == 0 ? 0 : 4)); \
-}
-
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts. */
@@ -982,6 +959,39 @@ __transfer_from_trampoline () \
asm ("rts":); \
}
+/* Definitions for register eliminations.
+
+ This is an array of structures. Each structure initializes one pair
+ of eliminable registers. The "from" register number is given first,
+ followed by "to". Eliminations of the same "from" register are listed
+ in order of preference.
+
+ There are two registers that can always be eliminated on the i386.
+ The frame pointer and the arg pointer can be replaced by either the
+ hard frame pointer or to the stack pointer, depending upon the
+ circumstances. The hard frame pointer is not used before reload and
+ so it is not eligible for elimination. */
+
+#define ELIMINABLE_REGS \
+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} \
+
+/* Given FROM and TO register numbers, say whether this elimination is
+ allowed. Frame pointer elimination is automatically handled.
+
+ All other eliminations are valid. */
+
+#define CAN_ELIMINATE(FROM, TO) \
+ ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1)
+
+/* Define the offset between two registers, one to be eliminated, and the other
+ its replacement, at the start of a routine. */
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ (OFFSET) = m68k_initial_elimination_offset(FROM, TO)
+
/* Addressing modes, and classification of registers for them. */
#define HAVE_POST_INCREMENT 1
@@ -1381,7 +1391,7 @@ __transfer_from_trampoline () \
#define REGISTER_NAMES \
{"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \
- "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7" }
+ "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7", "argptr" }
/* How to renumber registers for dbx and gdb.
On the Sun-3, the floating point registers have numbers
diff -Nrup gcc-3.4-20030730.orig/gcc/config/m68k/m68kelf.h gcc-3.4-20030730/gcc/config/m68k/m68kelf.h
--- gcc-3.4-20030730.orig/gcc/config/m68k/m68kelf.h 2003-08-02 19:02:52.000000000 +0200
+++ gcc-3.4-20030730/gcc/config/m68k/m68kelf.h 2003-08-02 23:33:58.000000000 +0200
@@ -96,7 +96,7 @@ Boston, MA 02111-1307, USA. */
#define REGISTER_NAMES \
{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
"%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%sp", \
- "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7" }
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", "argptr" }
/* This is how to output an assembler line that says to advance the
location counter to a multiple of 2**LOG bytes. */
diff -Nrup gcc-3.4-20030730.orig/gcc/config/m68k/sgs.h gcc-3.4-20030730/gcc/config/m68k/sgs.h
--- gcc-3.4-20030730.orig/gcc/config/m68k/sgs.h 2003-05-17 20:20:55.000000000 +0200
+++ gcc-3.4-20030730/gcc/config/m68k/sgs.h 2003-08-02 23:33:58.000000000 +0200
@@ -82,7 +82,7 @@ Boston, MA 02111-1307, USA. */
#define REGISTER_NAMES \
{"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", \
"%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp", \
- "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7" }
+ "%fp0", "%fp1", "%fp2", "%fp3", "%fp4", "%fp5", "%fp6", "%fp7", "argptr" }
/* This is how to output an assembler line that says to advance the
location counter to a multiple of 2**LOG bytes. */
--
// Bernardo Innocenti - Develer S.r.l., R&D dept.
\X/ http://www.develer.com/
Please don't send Word attachments - http://www.gnu.org/philosophy/no-word-attachments.html