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: patch for prologue/epilogue generation


On Thursday 21 August 2003 11:08, Gunther Nikl wrote:
> Hello!
>
> Could you please update the patch to accomodate the removal of NO_ADDSUB_Q?
> It causes rejects now.

I've updated the patch. I'm very happy someone is going to test it.
I can't currently test on a real m68k system, therefore I was quite
worried my patch could break something.

If you can't run the GCC testsuite, please try it on a very large code
base, both with and without -fomit-frame-pointer.

Back when I was debugging this code, I experienced subtle problems sneaking
in a Linux kernel that could bootstrap almost perfectly despite the fact that
some registers saved on the stack were being overwritten by local vars :-)

> Then there is another problem (at least for me): the 
> first hunk of the patch to m68k.c cannot be applied because the diff is
> missing the ^L after override_options. This might be caused by the ML (I
> downloaded the raw message from the ML)

This is a known KMail problem. I've already reported it some months ago along
with other patch corruption problems, but they seem to think the same way the
Microsoft Outlook team would.

-- 
  // 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

[SUBMITTED]

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,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,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.  */

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