OSDN Git Service

(delay_slots_for_epilogue, eligible_for_epilogue_delay,
authorwood <wood@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 29 Jun 1992 20:46:51 +0000 (20:46 +0000)
committerwood <wood@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 29 Jun 1992 20:46:51 +0000 (20:46 +0000)
ok_for_epilogue_p): Delete epilogue delay slot functions.
(m88k_begin_prologue m88k_end_prologue m88k_expand_prologue): New
functions replacing m88k_output_prologue.
(m88k_begin_epilogue m88k_end_epilogue m88k_expand_epilogue): Ditto.
(preserve_registers): Delete epilogue delay slot mechanism and
change to output insns.
(emit_add, emit_ldst): New functions.

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

gcc/config/m88k/m88k.c

index e1bc52a..9984464 100644 (file)
@@ -46,7 +46,7 @@ extern char *ctime ();
 extern int flag_traditional;
 extern FILE *asm_out_file;
 
-static char out_sccs_id[] = "@(#)m88k.c        2.1.11.11 29 May 1992 11:12:23";
+static char out_sccs_id[] = "@(#)m88k.c        2.2.3.6 29 Jun 1992 16:06:14";
 static char tm_sccs_id [] = TM_SCCS_ID;
 
 char *m88k_pound_sign = "";    /* Either # for SVR4 or empty for SVR3 */
@@ -1619,8 +1619,9 @@ m88k_handle_pragma_token (string, token)
   variable space.
   */
 
-static void output_reg_adjust ();
+static void emit_add ();
 static void preserve_registers ();
+static void emit_ldst ();
 static void output_tdesc ();
 
 static int  nregs;
@@ -1629,6 +1630,7 @@ static char save_regs[FIRST_PSEUDO_REGISTER];
 static int  frame_laid_out;
 static int  frame_size;
 static int  variable_args_p;
+static int  epilogue_marked;
 
 extern char call_used_regs[];
 extern int  current_function_pretend_args_size;
@@ -1770,97 +1772,6 @@ null_epilogue ()
          && m88k_stack_size == 0);
 }
 
-/* Determine the number of instructions needed for the function epilogue.  */
-
-#define MAX_EPILOGUE_DELAY_INSNS 4
-
-static char epilogue_dead_regs[FIRST_PSEUDO_REGISTER];
-
-delay_slots_for_epilogue ()
-{
-  register int insns = save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
-  register int regs = nregs - insns;
-
-  if (regs > 3)
-    insns += 1 + (regs & 1);
-  else if (nregs == 4)
-    /* This is a special cases of ld/ld/ld.d which has no start-up delay.  */
-    return 0;
-
-  if (insns)
-    {
-      bzero ((char *) &epilogue_dead_regs[0], sizeof (epilogue_dead_regs));
-      epilogue_dead_regs[1] = save_regs[1];
-      epilogue_dead_regs[STACK_POINTER_REGNUM] = frame_pointer_needed;
-      epilogue_dead_regs[TEMP_REGNUM] = ! ADD_INTVAL (m88k_fp_offset);
-    }
-
-  return insns;
-}
-
-/* Return 1 if X is safe to use as an epilogue insn.  */
-
-int
-ok_for_epilogue_p (x)
-     rtx x;
-{
-  register char *fmt;
-  register int i, j;
-
-  switch (GET_CODE (x))
-    {
-    case REG:
-      for (i = REGNO (x), j = i + HARD_REGNO_NREGS (i, GET_MODE (x));
-          i < j;
-          i++)
-       if (epilogue_dead_regs[i])
-         return 0;
-
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST:
-    case PC:
-    case CC0:
-    case LABEL_REF:
-    case SYMBOL_REF:
-    case CODE_LABEL:
-      return 1;
-    }
-
-  fmt = GET_RTX_FORMAT (GET_CODE (x));
-  for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       {
-         if (!ok_for_epilogue_p (XEXP (x, i)))
-           return 0;
-       }
-      else if (fmt[i] == 'E')
-       {
-         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-           if (!ok_for_epilogue_p (XVECEXP (x, i, j)))
-             return 0;
-       }
-    }
-  return 1;
-}
-
-int
-eligible_for_epilogue_delay (insn)
-     rtx insn;
-{
-  switch (get_attr_type (insn))
-    {
-    case TYPE_STORE:
-    case TYPE_LOADA:
-    case TYPE_ARITH:
-    case TYPE_MARITH:
-      return ok_for_epilogue_p (PATTERN (insn));
-    default:
-      return 0;
-    }
-}
-
 /* Determine if the current function has any references to the arg pointer.
    This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
    It is OK to return TRUE if there are no references, but FALSE must be
@@ -1892,10 +1803,27 @@ uses_arg_area_p ()
 }
 \f
 void
-m88k_output_prologue (stream, size)
+m88k_begin_prologue (stream, size)
      FILE *stream;
      int size;
 {
+  epilogue_marked = 0;
+  m88k_prologue_done = 1;      /* it's ok now to put out ln directives */
+}
+
+void
+m88k_end_prologue (stream)
+     FILE *stream;
+{
+  if (TARGET_OCS_DEBUG_INFO)
+    PUT_OCS_FUNCTION_START (stream);
+  if (epilogue_marked)
+    abort ();
+}
+
+void
+m88k_expand_prologue ()
+{
   int old_fp_offset = m88k_fp_offset;
   int old_stack_size = m88k_stack_size;
 
@@ -1924,43 +1852,34 @@ m88k_output_prologue (stream, size)
     }
 
   if (m88k_stack_size)
-    output_reg_adjust (stream, 31, 31, -m88k_stack_size, 0);
+    emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
 
   if (nregs || nxregs)
-    preserve_registers (stream, m88k_fp_offset + 4, 1);
+    preserve_registers (m88k_fp_offset + 4, 1);
 
   if (frame_pointer_needed)
-    output_reg_adjust (stream, 30, 31, m88k_fp_offset, 0);
-
-  if (TARGET_OCS_DEBUG_INFO)
-    PUT_OCS_FUNCTION_START (stream);
+    emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
 
   if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
     {
-      char label[256];
+      rtx return_reg = gen_rtx (REG, SImode, 1);
+      rtx label = gen_label_rtx ();
+      rtx temp_reg;
 
       if (! save_regs[1])
-       fprintf (stream, "\tor\t %s,%s,0\n",
-                reg_names[TEMP_REGNUM], reg_names[1]);
-      ASM_GENERATE_INTERNAL_LABEL (label, "Lab", m88k_function_number);
-      fprintf (stream, "\tbsr.n\t %s\n", &label[1]);
-      fprintf (stream, "\tor.u\t %s,%s,%shi16(%s#abdiff)\n",
-              reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[0],
-              m88k_pound_sign, &label[1]);
-      ASM_OUTPUT_INTERNAL_LABEL (stream, "Lab", m88k_function_number);
-      fprintf (stream, "\tor\t %s,%s,%slo16(%s#abdiff)\n",
-              reg_names[PIC_OFFSET_TABLE_REGNUM],
-              reg_names[PIC_OFFSET_TABLE_REGNUM],
-              m88k_pound_sign, &label[1]);
-      fprintf (stream, "\taddu\t %s,%s,%s\n",
-              reg_names[PIC_OFFSET_TABLE_REGNUM],
-              reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[1]);
+       {
+         temp_reg = gen_rtx (REG, SImode, TEMP_REGNUM);
+         emit_move_insn (temp_reg, return_reg);
+       }
+      emit_insn (gen_locate1 (pic_offset_table_rtx, label));
+      emit_insn (gen_locate2 (pic_offset_table_rtx, label));
+      emit_insn (gen_addsi3 (pic_offset_table_rtx,
+                            pic_offset_table_rtx, return_reg));
       if (! save_regs[1])
-       fprintf (stream, "\tor\t %s,%s,0\n",
-                reg_names[1], reg_names[TEMP_REGNUM]);
+       emit_move_insn (return_reg, temp_reg);
     }
-
-  m88k_prologue_done = 1;      /* it's ok now to put out ln directives */
+  if (profile_flag || profile_block_flag)
+    emit_insn (gen_profiler ());
 }
 \f
 /* This function generates the assembly code for function exit,
@@ -1972,39 +1891,23 @@ m88k_output_prologue (stream, size)
    omit stack adjustments before returning.  */
 
 void
-m88k_output_epilogue (stream, size)
+m88k_begin_epilogue (stream)
      FILE *stream;
-     int size;
 {
-  rtx insn = get_last_insn ();
-#if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values?  */
-  fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
-          size, m88k_fp_offset, m88k_stack_size);
-#endif
-
-  output_short_branch_defs (stream);
-
   if (TARGET_OCS_DEBUG_INFO)
     PUT_OCS_FUNCTION_END (stream);
+  epilogue_marked = 1;
+}
 
-  /* If the last insn was a BARRIER, we don't have to write any code.  */
-  if (GET_CODE (insn) == NOTE)
-    insn = prev_nonnote_insn (insn);
-  if (insn && GET_CODE (insn) == BARRIER)
-    {
-      if (current_function_epilogue_delay_list)
-       abort ();
-    }
-  else
-    {
-      if (frame_pointer_needed)
-       output_reg_adjust (stream, 31, 30, -m88k_fp_offset, 0);
-
-      if (nregs || nxregs)
-       preserve_registers (stream, m88k_fp_offset + 4, 0);
+void
+m88k_end_epilogue (stream, size)
+     FILE *stream;
+     int size;
+{
+  if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
+    PUT_OCS_FUNCTION_END (stream);
 
-      output_reg_adjust (stream, 31, 31, m88k_stack_size, 1);
-    }
+  output_short_branch_defs (stream);
 
   fprintf (stream, "\n");
 
@@ -2015,68 +1918,54 @@ m88k_output_epilogue (stream, size)
   m88k_prologue_done   = 0;            /* don't put out ln directives */
   variable_args_p      = 0;            /* has variable args */
 }
-\f
-/* Output code to STREAM to set DSTREG to SRCREG + AMOUNT.  Issue
-   a return instruction and use it's delay slot based on RETURN_P.  */
 
-static void
-output_reg_adjust (stream, dstreg, srcreg, amount, return_p)
-     FILE *stream;
-     int dstreg, srcreg, amount, return_p;
+void
+m88k_expand_epilogue ()
 {
-  char *opname;
-  char incr[256];
+#if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values?  */
+  fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
+          size, m88k_fp_offset, m88k_stack_size);
+#endif
 
-  if (amount < 0)
-    {
-      opname = "subu";
-      amount = -amount;
-    }
-  else
-    opname = "addu";
+  if (frame_pointer_needed)
+    emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
 
-  if (amount == 0 && dstreg == srcreg)
-    {
-      if (return_p)
-       fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
-      return;
-    }
-  else if (SMALL_INTVAL (amount))
-    sprintf (incr, "\t%s\t %s,%s,%d", opname,
-            reg_names[dstreg], reg_names[srcreg], amount);
-  else
+  if (nregs || nxregs)
+    preserve_registers (m88k_fp_offset + 4, 0);
+
+  if (m88k_stack_size)
+    emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
+}
+\f
+/* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
+   epilogue.  */
+
+static void
+emit_add (dstreg, srcreg, amount)
+     rtx dstreg;
+     rtx srcreg;
+     int amount;
+{
+  rtx incr = gen_rtx (CONST_INT, VOIDmode, abs (amount));
+  if (! ADD_INTVAL (amount))
     {
-      rtx operands[2];
-
-      operands[0] = gen_rtx (REG, SImode, TEMP_REGNUM);
-      operands[1] = gen_rtx (CONST_INT, VOIDmode, amount);
-      output_asm_insn (output_load_const_int (SImode, operands),
-                      operands);
-      sprintf (incr, "\t%s\t %s,%s,%s", opname,
-              reg_names[dstreg], reg_names[srcreg], reg_names[TEMP_REGNUM]);
+      rtx temp = gen_rtx (REG, SImode, TEMP_REGNUM);
+      emit_move_insn (temp, incr);
+      incr = temp;
     }
-
-  if (!return_p)
-    fprintf (stream, "%s\n", incr);
-  else if (flag_delayed_branch)
-    fprintf (stream, "\tjmp.n\t %s\n%s\n", reg_names[1], incr);
-  else
-    fprintf (stream, "%s\n\tjmp\t %s\n", incr, reg_names[1]);
+  emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
 }
 
 /* Save/restore the preserve registers.  base is the highest offset from
    r31 at which a register is stored.  store_p is true if stores are to
-   be done; otherwise loads.  When loading, output the epilogue delay
-   insns.  */
+   be done; otherwise loads.  */
 
 static void
-preserve_registers (stream, base, store_p)
-     FILE *stream;
+preserve_registers (base, store_p)
      int base;
      int store_p;
 {
   int regno, offset;
-  char *fmt = (store_p ? "\tst%s\t %s,%s,%d\n" : "\tld%s\t %s,%s,%d\n");
   struct mem_op {
     int regno;
     int nregs;
@@ -2095,7 +1984,7 @@ preserve_registers (stream, base, store_p)
         memory ops.  */
       if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
        offset -= 4;
-      fprintf (stream, fmt, "", reg_names[1], reg_names[31], offset);
+      emit_ldst (store_p, 1, SImode, offset);
       offset -= 4;
       base = offset;
     }
@@ -2156,71 +2045,32 @@ preserve_registers (stream, base, store_p)
 
   mo_ptr->regno = 0;
 
-  /* Output the delay insns interleaved with the memory operations.  */
-  if (! store_p && current_function_epilogue_delay_list)
-    {
-      rtx delay_insns = current_function_epilogue_delay_list;
-      rtx insn;
-
-      /* The first delay insn goes after the restore of r1.  */
-      if (save_regs[1])
-       {
-         final_scan_insn (XEXP (delay_insns, 0), stream, 1, 0, 1);
-         delay_insns = XEXP (delay_insns, 1);
-       }
-
-      while (delay_insns)
-       {
-         /* Find a memory operation that doesn't conflict with this insn.  */
-         for (mo_ptr = mem_op; mo_ptr->regno != 0; mo_ptr++)
-           {
-             if (mo_ptr->nregs)
-               {
-                 int nregs = (mo_ptr->regno < FIRST_EXTENDED_REGISTER
-                              ? mo_ptr->nregs : 1);
-                 rtx ok_insns = delay_insns;
-                 int i;
-
-                 for (i = 0; i < nregs; i++)
-                   epilogue_dead_regs[mo_ptr->regno + i] = 1;
-
-                 while (ok_insns)
-                   {
-                     insn = XEXP (ok_insns, 0);
-                     ok_insns = XEXP (ok_insns, 1);
-
-                     if (! ok_for_epilogue_p (PATTERN (insn)))
-                       {
-                         for (i = 0; i < nregs; i++)
-                           epilogue_dead_regs[mo_ptr->regno + i] = 0;
-                         insn = 0;
-                         break; /* foreach delay insn */
-                       }
-                   }
-                 if (insn)
-                   {
-                     fprintf (stream, fmt, mo_ptr->nregs > 1 ? ".d" : "",
-                              reg_names[mo_ptr->regno], reg_names[31],
-                              mo_ptr->offset);
-                     mo_ptr->nregs = 0;
-                     break; /* foreach memory operation */
-                   }
-               }
-           }
-         final_scan_insn (XEXP (delay_insns, 0), stream, 1, 0, 1);
-         delay_insns = XEXP (delay_insns, 1);
-       }
-    }
-
   /* Output the memory operations.  */
   for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
     {
       if (mo_ptr->nregs)
-       fprintf (stream, fmt, mo_ptr->nregs > 1 ? ".d" : "",
-                reg_names[mo_ptr->regno], reg_names[31], mo_ptr->offset);
+       emit_ldst (store_p, mo_ptr->regno,
+                  (mo_ptr->nregs > 1 ? DImode : SImode),
+                  mo_ptr->offset);
     }
 }
 
+static void
+emit_ldst (store_p, regno, mode, offset)
+     int store_p;
+     int regno;
+     enum machine_mode mode;
+     int offset;
+{
+  rtx reg = gen_rtx (REG, mode, regno);
+  rtx mem = gen_rtx (MEM, mode, plus_constant (stack_pointer_rtx, offset));
+
+  if (store_p)
+    emit_move_insn (mem, reg);
+  else
+    emit_move_insn (reg, mem);
+}
+
 /* Convert the address expression REG to a CFA offset.  */
 
 int
@@ -2348,7 +2198,7 @@ output_tdesc (file, offset)
 
   text_section ();
 }
-
+\f
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  NAME is the mcount function name
    (varies), SAVEP indicates whether the parameter registers need to