OSDN Git Service

* config/m68k/m68k.h (EH_RETURN_DATA_REGNO): Define.
authorschwab <schwab@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Dec 2002 19:45:30 +0000 (19:45 +0000)
committerschwab <schwab@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Dec 2002 19:45:30 +0000 (19:45 +0000)
(EH_RETURN_STACKADJ_RTX): Define.
(EH_RETURN_HANDLER_RTX): Define.
(ASM_PREFERRED_EH_DATA_FORMAT): Define.
* config/m68k/m68k.c (m68k_save_reg): New function.  Handle eh
registers and don't save fixed registers.
(m68k_output_function_prologue): Use it.
(use_return_insn): Likewise.
(m68k_output_function_epilogue): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@59780 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.h

index a0e4f2c..fbc2bd5 100644 (file)
@@ -1,3 +1,15 @@
+2002-12-03  Andreas Schwab  <schwab@suse.de>
+
+       * config/m68k/m68k.h (EH_RETURN_DATA_REGNO): Define.
+       (EH_RETURN_STACKADJ_RTX): Define.
+       (EH_RETURN_HANDLER_RTX): Define.
+       (ASM_PREFERRED_EH_DATA_FORMAT): Define.
+       * config/m68k/m68k.c (m68k_save_reg): New function.  Handle eh
+       registers and don't save fixed registers.
+       (m68k_output_function_prologue): Use it.
+       (use_return_insn): Likewise.
+       (m68k_output_function_epilogue): Likewise.
+
 2002-12-03  Kazu Hirata  <kazu@cs.umass.edu>
 
        * config/h8300/h8300.c (single_one_operand): Fix a warning.
index f29595b..0407dd6 100644 (file)
@@ -67,6 +67,7 @@ static void m68k_svr3_asm_out_constructor PARAMS ((rtx, int));
 #endif
 static void m68k_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
                                          HOST_WIDE_INT, tree));
+static int m68k_save_reg PARAMS ((unsigned int));
 \f
 
 /* Alignment to use for loops and jumps */
@@ -207,6 +208,34 @@ override_options ()
   real_format_for_mode[XFmode - QFmode] = &ieee_extended_motorola_format;
 }
 \f
+/* Return 1 if we need to save REGNO.  */
+static int
+m68k_save_reg (regno)
+     unsigned int regno;
+{
+  if (flag_pic && current_function_uses_pic_offset_table
+      && regno == PIC_OFFSET_TABLE_REGNUM)
+    return 1;
+
+  if (current_function_calls_eh_return)
+    {
+      unsigned int i;
+      for (i = 0; ; i++)
+       {
+         unsigned int test = EH_RETURN_DATA_REGNO (i);
+         if (test == INVALID_REGNUM)
+           break;
+         if (test == regno)
+           return 1;
+       }
+    }
+
+  return (regs_ever_live[regno]
+         && !call_used_regs[regno]
+         && !fixed_regs[regno]
+         && !(regno == FRAME_POINTER_REGNUM && frame_pointer_needed));
+}
+
 /* This function generates the assembly code for function entry.
    STREAM is a stdio stream to output the code to.
    SIZE is an int: how many units of temporary storage to allocate.
@@ -251,13 +280,13 @@ m68k_output_function_prologue (stream, size)
     {
       /* Adding negative number is faster on the 68040.  */
       if (fsize + 4 < 0x8000)
-         fprintf (stream, "\tadd.w #%d,sp\n", - (fsize + 4));
+       fprintf (stream, "\tadd.w $%d,sp\n", - (fsize + 4));
       else
-         fprintf (stream, "\tadd.l #%d,sp\n", - (fsize + 4));
+       fprintf (stream, "\tadd.l $%d,sp\n", - (fsize + 4));
     }
 
   for (regno = 16; regno < 24; regno++)
-    if (regs_ever_live[regno] && ! call_used_regs[regno])
+    if (m68k_save_reg (regno))
       mask |= 1 << (regno - 16);
 
   if ((mask & 0xff) != 0)
@@ -265,10 +294,8 @@ m68k_output_function_prologue (stream, size)
 
   mask = 0;
   for (regno = 0; regno < 16; regno++)
-    if (regs_ever_live[regno] && ! call_used_regs[regno])
+    if (m68k_save_reg (regno))
       mask |= 1 << (15 - regno);
-  if (frame_pointer_needed)
-    mask &= ~ (1 << (15-FRAME_POINTER_REGNUM));
 
   if (exact_log2 (mask) >= 0)
     fprintf (stream, "\tmovel %s,-(sp)\n", reg_names[15 - exact_log2 (mask)]);
@@ -441,7 +468,7 @@ m68k_output_function_prologue (stream, size)
     }
 #ifdef SUPPORT_SUN_FPA
   for (regno = 24; regno < 56; regno++)
-    if (regs_ever_live[regno] && ! call_used_regs[regno])
+    if (m68k_save_reg (regno))
       {
 #ifdef MOTOROLA
        asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
@@ -467,7 +494,7 @@ m68k_output_function_prologue (stream, size)
   if (TARGET_68881)
     {
       for (regno = 16; regno < 24; regno++)
-       if (regs_ever_live[regno] && ! call_used_regs[regno])
+       if (m68k_save_reg (regno))
          {
            mask |= 1 << (regno - 16);
            num_saved_regs++;
@@ -500,21 +527,11 @@ m68k_output_function_prologue (stream, size)
       num_saved_regs = 0;
     }
   for (regno = 0; regno < 16; regno++)
-    if (regs_ever_live[regno] && ! call_used_regs[regno])
+    if (m68k_save_reg (regno))
       {
         mask |= 1 << (15 - regno);
         num_saved_regs++;
       }
-  if (frame_pointer_needed)
-    {
-      mask &= ~ (1 << (15 - FRAME_POINTER_REGNUM));
-      num_saved_regs--;
-    }
-  if (flag_pic && current_function_uses_pic_offset_table)
-    {
-      mask |= 1 << (15 - PIC_OFFSET_TABLE_REGNUM);
-      num_saved_regs++;
-    }
 
 #if NEED_PROBE
 #ifdef MOTOROLA
@@ -656,16 +673,10 @@ use_return_insn ()
   if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
     return 0;
   
-  /* Copied from output_function_epilogue ().  We should probably create a
-     separate layout routine to perform the common work.  */
-  
-  for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
-    if (regs_ever_live[regno] && ! call_used_regs[regno])
+  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+    if (m68k_save_reg (regno))
       return 0;
 
-  if (flag_pic && current_function_uses_pic_offset_table)
-    return 0;
-
   return 1;
 }
 
@@ -693,7 +704,7 @@ m68k_output_function_epilogue (stream, size)
 
   nregs = 0;  fmask = 0; fpoffset = 0;
   for (regno = 16; regno < 24; regno++)
-    if (regs_ever_live[regno] && ! call_used_regs[regno])
+    if (m68k_save_reg (regno))
       {
        nregs++;
        fmask |= 1 << (23 - regno);
@@ -701,11 +712,9 @@ m68k_output_function_epilogue (stream, size)
 
   foffset = fpoffset + nregs * 12;
   nregs = 0;  mask = 0;
-  if (frame_pointer_needed)
-    regs_ever_live[FRAME_POINTER_REGNUM] = 0;
 
   for (regno = 0; regno < 16; regno++)
-    if (regs_ever_live[regno] && ! call_used_regs[regno])
+    if (m68k_save_reg (regno))
       {
        nregs++;
        mask |= 1 << regno;
@@ -758,7 +767,7 @@ m68k_output_function_epilogue (stream, size)
 
   if (fpoffset != 0)
     for (regno = 55; regno >= 24; regno--)
-      if (regs_ever_live[regno] && ! call_used_regs[regno])
+      if (m68k_save_reg (regno))
        {
          if (big)
            fprintf(stream, "\tfpmoved -%d(a6,a0.l), %s\n",
@@ -777,11 +786,14 @@ m68k_output_function_epilogue (stream, size)
   else if (fsize)
     {
       if (fsize + 4 < 0x8000)
-       fprintf (stream, "\tadd.w #%d,sp\n", fsize + 4);
+       fprintf (stream, "\tadd.w $%d,sp\n", fsize + 4);
       else
-       fprintf (stream, "\tadd.l #%d,sp\n", fsize + 4);
+       fprintf (stream, "\tadd.l $%d,sp\n", fsize + 4);
     }
 
+  if (current_function_calls_eh_return)
+    fprintf (stream, "\tadd.l a0,sp\n");
+
   if (current_function_pops_args)
     fprintf (stream, "\trtd $%d\n", current_function_pops_args);
   else
@@ -821,7 +833,7 @@ m68k_output_function_epilogue (stream, size)
   nregs = 0;  fmask = 0; fpoffset = 0;
 #ifdef SUPPORT_SUN_FPA
   for (regno = 24 ; regno < 56 ; regno++)
-    if (regs_ever_live[regno] && ! call_used_regs[regno])
+    if (m68k_save_reg (regno))
       nregs++;
   fpoffset = nregs * 8;
 #endif
@@ -829,7 +841,7 @@ m68k_output_function_epilogue (stream, size)
   if (TARGET_68881)
     {
       for (regno = 16; regno < 24; regno++)
-       if (regs_ever_live[regno] && ! call_used_regs[regno])
+       if (m68k_save_reg (regno))
          {
            nregs++;
            fmask |= 1 << (23 - regno);
@@ -837,19 +849,12 @@ m68k_output_function_epilogue (stream, size)
     }
   foffset = fpoffset + nregs * 12;
   nregs = 0;  mask = 0;
-  if (frame_pointer_needed)
-    regs_ever_live[FRAME_POINTER_REGNUM] = 0;
   for (regno = 0; regno < 16; regno++)
-    if (regs_ever_live[regno] && ! call_used_regs[regno])
+    if (m68k_save_reg (regno))
       {
         nregs++;
        mask |= 1 << regno;
       }
-  if (flag_pic && current_function_uses_pic_offset_table)
-    {
-      nregs++;
-      mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
-    }
   offset = foffset + nregs * 4;
   /* FIXME : leaf_function_p below is too strong.
      What we really need to know there is if there could be pending
@@ -995,7 +1000,7 @@ m68k_output_function_epilogue (stream, size)
     }
   if (fpoffset != 0)
     for (regno = 55; regno >= 24; regno--)
-      if (regs_ever_live[regno] && ! call_used_regs[regno])
+      if (m68k_save_reg (regno))
         {
          if (big)
            {
@@ -1105,6 +1110,14 @@ m68k_output_function_epilogue (stream, size)
 #endif
        }
     }
+  if (current_function_calls_eh_return)
+    {
+#ifdef MOTOROLA
+      asm_fprintf (stream, "\tadd.l %Ra0,%Rsp\n");
+#else
+      asm_fprintf (stream, "\taddl %Ra0,%Rsp\n");
+#endif
+    }
   if (current_function_pops_args)
     asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
   else
index eff0ce2..795a979 100644 (file)
@@ -1665,6 +1665,8 @@ __transfer_from_trampoline ()                                     \
 
 #define DATA_SECTION_ASM_OP "\t.data"
 
+#define GLOBAL_ASM_OP "\t.globl\t"
+
 /* Here are four prefixes that are used by asm_fprintf to
    facilitate customization for alternate assembler syntaxes.
    Machines with no likelihood of an alternate syntax need not
@@ -1732,7 +1734,23 @@ __transfer_from_trampoline ()                                    \
 /* Before the prologue, the top of the frame is at 4(%sp).  */
 #define INCOMING_FRAME_SP_OFFSET 4
 
-#define GLOBAL_ASM_OP "\t.globl\t"
+/* Describe how we implement __builtin_eh_return.  */
+#define EH_RETURN_DATA_REGNO(N) \
+  ((N) < 2 ? (N) : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, 8)
+#define EH_RETURN_HANDLER_RTX                                      \
+  gen_rtx_MEM (Pmode,                                              \
+              gen_rtx_PLUS (Pmode, arg_pointer_rtx,                \
+                            plus_constant (EH_RETURN_STACKADJ_RTX, \
+                                           UNITS_PER_WORD)))
+
+/* Select a format to encode pointers in exception handling data.  CODE
+   is 0 for data, 1 for code labels, 2 for function pointers.  GLOBAL is
+   true if the symbol may be affected by dynamic relocations.  */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL)                        \
+  (flag_pic                                                               \
+   ? ((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4 \
+   : DW_EH_PE_absptr)
 
 /* This is how to output a reference to a user-level label named NAME.
    `assemble_name' uses this.  */