This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [m68k] Fix and improve ColdFire function prologue/epilogue generation(rev. 3)



This is the final revision of the previosuly submitted patch with all suggested changes applied.

The following improvements are still pending, but I'm planning to postpone
them to avoid perturbing all pending patches:

- figure out why the elimination between ARG_POINTER_REGNUM and
  FRAME_POINTER_REGNUM has to be 0 instead of something sane;

- compute num_saved_regs only once in m68k_emit_function_offset();

- merge the ColdFire special case movem handling with other m68k cases
  where possible;

- pre-compute frame_pointer_offset and stack_pointer_offset in
  m68k_compute_frame_layout() for use in several places;

- Call m68k_compute_frame_layout() once per compiled function and
  cache results for efficiency (but how does the back-end get to
  know about function boundaries?).

--------------------------------------------------------------------------

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.


2003-09-08 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 @@ -70,7 +70,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
@@ -158,7 +158,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
@@ -68,7 +68,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 (int from, int to);
extern const char *output_move_const_into_data_reg (rtx *);
extern const char *output_move_simode_const (rtx *);
extern const char *output_move_simode (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
@@ -212,6 +212,84 @@ 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 stack_pointer_offset;
+};
+
+static void
+m68k_compute_frame_layout (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 /* || 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 * 12 /* (TARGET_CFV4E ? 8 : 12) */;
+ frame->fpu_no = saved;
+ frame->fpu_mask = mask;
+ frame->fpu_rev_mask = rmask;
+ }
+}
+
+HOST_WIDE_INT
+m68k_initial_elimination_offset (int from, int to)
+{
+ struct m68k_frame frame;
+
+ /* FIXME: The correct offset to compute here would appear to be
+ (frame_pointer_needed ? -UNITS_PER_WORD * 2 : -UNITS_PER_WORD);
+ but for some obscure reason, this must be 0 to get correct code. */
+ if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
+ return 0;
+
+ m68k_compute_frame_layout (&frame);
+
+ 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;
+
+ abort();
+}
+
/* Return 1 if we need to save REGNO. */
static int
m68k_save_reg (unsigned int regno)
@@ -258,6 +354,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;
@@ -275,6 +371,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,32 +452,32 @@ 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)
{
- 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 if (TARGET_68040)
@@ -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,57 +974,57 @@ 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)
{
- 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 if (fsize + 4 < 0x8000)
+ else 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,38 @@ __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 m68k.
+   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, FRAME_POINTER_REGNUM },	\
+ { FRAME_POINTER_REGNUM, STACK_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




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]