* config/tc-mips.h (mips_flush_pending_output): Delete.
authorRichard Sandiford <rdsandiford@googlemail.com>
Wed, 9 Mar 2005 09:22:25 +0000 (09:22 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Wed, 9 Mar 2005 09:22:25 +0000 (09:22 +0000)
(mips_emit_delays): Declare.
(md_flush_pending_output): Use mips_emit_delays.
* config/tc-mips.c (mips_no_prev_insn): Remove parameter; always forget
the previous instructions.
(md_begin, append_insn, md_parse_option): Update callers.
(mips_emit_delay): Remove parameter.  Move INSNS != 0 code to
start_noreorder.
(mips_align, s_change_sec, s_cons, s_float_cons, s_gpword)
(s_gpdword): Update callers.
(start_noreorder, end_noreorder): New functions.
(macro, macro2, mips16_macro, s_mipsset): Use them instead of
manipulating mips_opts or prev_nop_frag directly.
(mips_flush_pending_output): Delete.

gas/ChangeLog
gas/config/tc-mips.c
gas/config/tc-mips.h

index 15e12c81cb01eddc3ecb5bafad6a18beca1dbaee..160fb722b29c446261c0d3dfa14da8d216b79caa 100644 (file)
@@ -1,3 +1,20 @@
+2005-03-09  Richard Sandiford  <rsandifo@redhat.com>
+
+       * config/tc-mips.h (mips_flush_pending_output): Delete.
+       (mips_emit_delays): Declare.
+       (md_flush_pending_output): Use mips_emit_delays.
+       * config/tc-mips.c (mips_no_prev_insn): Remove parameter; always forget
+       the previous instructions.
+       (md_begin, append_insn, md_parse_option): Update callers.
+       (mips_emit_delay): Remove parameter.  Move INSNS != 0 code to
+       start_noreorder.
+       (mips_align, s_change_sec, s_cons, s_float_cons, s_gpword)
+       (s_gpdword): Update callers.
+       (start_noreorder, end_noreorder): New functions.
+       (macro, macro2, mips16_macro, s_mipsset): Use them instead of
+       manipulating mips_opts or prev_nop_frag directly.
+       (mips_flush_pending_output): Delete.
+
 2005-03-09  Richard Sandiford  <rsandifo@redhat.com>
 
        * config/tc-mips.c (mips_move_labels): New function, taken from...
index dac280133515cb0942a3eb5df22f3834ae469ef3..8e464f631de3fa172c49a59338dc49147d273a1b 100644 (file)
@@ -928,7 +928,7 @@ enum mips_regclass { MIPS_GR_REG, MIPS_FP_REG, MIPS16_REG };
 
 static void append_insn
   (struct mips_cl_insn *ip, expressionS *p, bfd_reloc_code_real_type *r);
-static void mips_no_prev_insn (int);
+static void mips_no_prev_insn (void);
 static void mips16_macro_build
   (expressionS *, const char *, const char *, va_list);
 static void load_register (int, expressionS *, int);
@@ -1477,7 +1477,7 @@ md_begin (void)
                                       &zero_address_frag));
     }
 
-  mips_no_prev_insn (FALSE);
+  mips_no_prev_insn ();
 
   mips_gprmask = 0;
   mips_cprmask[0] = 0;
@@ -2664,7 +2664,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
          /* If that was an unconditional branch, forget the previous
             insn information.  */
          if (pinfo & INSN_UNCOND_BRANCH_DELAY)
-           mips_no_prev_insn (FALSE);
+           mips_no_prev_insn ();
        }
       else if (pinfo & INSN_COND_BRANCH_LIKELY)
        {
@@ -2685,49 +2685,57 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
   mips_clear_insn_labels ();
 }
 
-/* This function forgets that there was any previous instruction or
-   label.  If PRESERVE is non-zero, it remembers enough information to
-   know whether nops are needed before a noreorder section.  */
+/* Forget that there was any previous instruction or label.  */
 
 static void
-mips_no_prev_insn (int preserve)
+mips_no_prev_insn (void)
 {
-  size_t i;
-  if (! preserve)
-    {
-      prev_nop_frag = NULL;
-      prev_nop_frag_holds = 0;
-      prev_nop_frag_required = 0;
-      prev_nop_frag_since = 0;
-      for (i = 0; i < ARRAY_SIZE (history); i++)
-       history[i] = (mips_opts.mips16 ? mips16_nop_insn : nop_insn);
-    }
-  else
-    for (i = 0; i < ARRAY_SIZE (history); i++)
-      {
-       history[i].fixed_p = 1;
-       history[i].noreorder_p = 0;
-       history[i].mips16_absolute_jump_p = 0;
-      }
+  prev_nop_frag = NULL;
+  insert_into_history (0, ARRAY_SIZE (history), NOP_INSN);
   mips_clear_insn_labels ();
 }
 
-/* This function must be called whenever we turn on noreorder or emit
-   something other than instructions.  It inserts any NOPS which might
-   be needed by the previous instruction, and clears the information
-   kept for the previous instructions.  The INSNS parameter is true if
-   instructions are to follow.  */
+/* This function must be called before we emit something other than
+   instructions.  It is like mips_no_prev_insn except that it inserts
+   any NOPS that might be needed by previous instructions.  */
 
-static void
-mips_emit_delays (bfd_boolean insns)
+void
+mips_emit_delays (void)
 {
   if (! mips_opts.noreorder)
     {
       int nops = nops_for_insn (history, NULL);
       if (nops > 0)
        {
-         if (insns && mips_optimize != 0)
+         while (nops-- > 0)
+           add_fixed_insn (NOP_INSN);
+         mips_move_labels ();
+       }
+    }
+  mips_no_prev_insn ();
+}
+
+/* Start a (possibly nested) noreorder block.  */
+
+static void
+start_noreorder (void)
+{
+  if (mips_opts.noreorder == 0)
+    {
+      unsigned int i;
+      int nops;
+
+      /* None of the instructions before the .set noreorder can be moved.  */
+      for (i = 0; i < ARRAY_SIZE (history); i++)
+       history[i].fixed_p = 1;
+
+      /* Insert any nops that might be needed between the .set noreorder
+        block and the previous instructions.  We will later remove any
+        nops that turn out not to be needed.  */
+      nops = nops_for_insn (history, NULL);
+      if (nops > 0)
+       {
+         if (mips_optimize != 0)
            {
              /* Record the frag which holds the nop instructions, so
                  that we can remove them if we don't need them.  */
@@ -2741,23 +2749,35 @@ mips_emit_delays (bfd_boolean insns)
          for (; nops > 0; --nops)
            add_fixed_insn (NOP_INSN);
 
-         if (insns)
-           {
-             /* Move on to a new frag, so that it is safe to simply
-                 decrease the size of prev_nop_frag.  */
-             frag_wane (frag_now);
-             frag_new (0);
-           }
-
+         /* Move on to a new frag, so that it is safe to simply
+            decrease the size of prev_nop_frag.  */
+         frag_wane (frag_now);
+         frag_new (0);
          mips_move_labels ();
        }
+      mips16_mark_labels ();
+      mips_clear_insn_labels ();
     }
+  mips_opts.noreorder++;
+  mips_any_noreorder = 1;
+}
 
-  /* Mark instruction labels in mips16 mode.  */
-  if (insns)
-    mips16_mark_labels ();
+/* End a nested noreorder block.  */
 
-  mips_no_prev_insn (insns);
+static void
+end_noreorder (void)
+{
+  mips_opts.noreorder--;
+  if (mips_opts.noreorder == 0 && prev_nop_frag != NULL)
+    {
+      /* Commit to inserting prev_nop_frag_required nops and go back to
+        handling nop insertion the .set reorder way.  */
+      prev_nop_frag->fr_fix -= ((prev_nop_frag_holds - prev_nop_frag_required)
+                               * (mips_opts.mips16 ? 2 : 4));
+      insert_into_history (prev_nop_frag_since,
+                          prev_nop_frag_required, NOP_INSN);
+      prev_nop_frag = NULL;
+    }
 }
 
 /* Set up global variables for the start of a new macro.  */
@@ -4061,9 +4081,7 @@ macro (struct mips_cl_insn *ip)
         sub v0,$zero,$a0
         */
 
-      mips_emit_delays (TRUE);
-      ++mips_opts.noreorder;
-      mips_any_noreorder = 1;
+      start_noreorder ();
 
       expr1.X_add_number = 8;
       macro_build (&expr1, "bgez", "s,p", sreg);
@@ -4073,7 +4091,7 @@ macro (struct mips_cl_insn *ip)
        move_register (dreg, sreg);
       macro_build (NULL, dbl ? "dsub" : "sub", "d,v,t", dreg, 0, sreg);
 
-      --mips_opts.noreorder;
+      end_noreorder ();
       break;
 
     case M_ADD_I:
@@ -4581,9 +4599,7 @@ macro (struct mips_cl_insn *ip)
          break;
        }
 
-      mips_emit_delays (TRUE);
-      ++mips_opts.noreorder;
-      mips_any_noreorder = 1;
+      start_noreorder ();
       if (mips_trap)
        {
          macro_build (NULL, "teq", "s,t,q", treg, 0, 7);
@@ -4617,7 +4633,7 @@ macro (struct mips_cl_insn *ip)
          macro_build (NULL, "teq", "s,t,q", sreg, AT, 6);
          /* We want to close the noreorder block as soon as possible, so
             that later insns are available for delay slot filling.  */
-         --mips_opts.noreorder;
+         end_noreorder ();
        }
       else
        {
@@ -4627,7 +4643,7 @@ macro (struct mips_cl_insn *ip)
 
          /* We want to close the noreorder block as soon as possible, so
             that later insns are available for delay slot filling.  */
-         --mips_opts.noreorder;
+         end_noreorder ();
 
          macro_build (NULL, "break", "c", 6);
        }
@@ -4722,16 +4738,14 @@ macro (struct mips_cl_insn *ip)
       s = "ddivu";
       s2 = "mfhi";
     do_divu3:
-      mips_emit_delays (TRUE);
-      ++mips_opts.noreorder;
-      mips_any_noreorder = 1;
+      start_noreorder ();
       if (mips_trap)
        {
          macro_build (NULL, "teq", "s,t,q", treg, 0, 7);
          macro_build (NULL, s, "z,s,t", sreg, treg);
          /* We want to close the noreorder block as soon as possible, so
             that later insns are available for delay slot filling.  */
-         --mips_opts.noreorder;
+         end_noreorder ();
        }
       else
        {
@@ -4741,7 +4755,7 @@ macro (struct mips_cl_insn *ip)
 
          /* We want to close the noreorder block as soon as possible, so
             that later insns are available for delay slot filling.  */
-         --mips_opts.noreorder;
+         end_noreorder ();
          macro_build (NULL, "break", "c", 7);
        }
       macro_build (NULL, s2, "d", dreg);
@@ -6669,9 +6683,7 @@ macro2 (struct mips_cl_insn *ip)
       dbl = 1;
     case M_MULO:
     do_mulo:
-      mips_emit_delays (TRUE);
-      ++mips_opts.noreorder;
-      mips_any_noreorder = 1;
+      start_noreorder ();
       used_at = 1;
       if (imm)
        load_register (AT, &imm_expr, dbl);
@@ -6688,7 +6700,7 @@ macro2 (struct mips_cl_insn *ip)
          macro_build (NULL, "nop", "", 0);
          macro_build (NULL, "break", "c", 6);
        }
-      --mips_opts.noreorder;
+      end_noreorder ();
       macro_build (NULL, "mflo", "d", dreg);
       break;
 
@@ -6702,9 +6714,7 @@ macro2 (struct mips_cl_insn *ip)
       dbl = 1;
     case M_MULOU:
     do_mulou:
-      mips_emit_delays (TRUE);
-      ++mips_opts.noreorder;
-      mips_any_noreorder = 1;
+      start_noreorder ();
       used_at = 1;
       if (imm)
        load_register (AT, &imm_expr, dbl);
@@ -6721,7 +6731,7 @@ macro2 (struct mips_cl_insn *ip)
          macro_build (NULL, "nop", "", 0);
          macro_build (NULL, "break", "c", 6);
        }
-      --mips_opts.noreorder;
+      end_noreorder ();
       break;
 
     case M_DROL:
@@ -7186,9 +7196,7 @@ macro2 (struct mips_cl_insn *ip)
        * Is the double cfc1 instruction a bug in the mips assembler;
        * or is there a reason for it?
        */
-      mips_emit_delays (TRUE);
-      ++mips_opts.noreorder;
-      mips_any_noreorder = 1;
+      start_noreorder ();
       macro_build (NULL, "cfc1", "t,G", treg, RA);
       macro_build (NULL, "cfc1", "t,G", treg, RA);
       macro_build (NULL, "nop", "");
@@ -7202,7 +7210,7 @@ macro2 (struct mips_cl_insn *ip)
                   dreg, sreg);
       macro_build (NULL, "ctc1", "t,G", treg, RA);
       macro_build (NULL, "nop", "");
-      --mips_opts.noreorder;
+      end_noreorder ();
       break;
 
     case M_ULH:
@@ -7442,9 +7450,7 @@ mips16_macro (struct mips_cl_insn *ip)
     case M_REM_3:
       s = "mfhi";
     do_div3:
-      mips_emit_delays (TRUE);
-      ++mips_opts.noreorder;
-      mips_any_noreorder = 1;
+      start_noreorder ();
       macro_build (NULL, dbl ? "ddiv" : "div", "0,x,y", xreg, yreg);
       expr1.X_add_number = 2;
       macro_build (&expr1, "bnez", "x,p", yreg);
@@ -7454,7 +7460,7 @@ mips16_macro (struct mips_cl_insn *ip)
          since that causes an overflow.  We should do that as well,
          but I don't see how to do the comparisons without a temporary
          register.  */
-      --mips_opts.noreorder;
+      end_noreorder ();
       macro_build (NULL, s, "x", zreg);
       break;
 
@@ -7474,14 +7480,12 @@ mips16_macro (struct mips_cl_insn *ip)
       s = "ddivu";
       s2 = "mfhi";
     do_divu3:
-      mips_emit_delays (TRUE);
-      ++mips_opts.noreorder;
-      mips_any_noreorder = 1;
+      start_noreorder ();
       macro_build (NULL, s, "0,x,y", xreg, yreg);
       expr1.X_add_number = 2;
       macro_build (&expr1, "bnez", "x,p", yreg);
       macro_build (NULL, "break", "6", 7);
-      --mips_opts.noreorder;
+      end_noreorder ();
       macro_build (NULL, s2, "x", zreg);
       break;
 
@@ -10194,12 +10198,12 @@ md_parse_option (int c, char *arg)
 
     case OPTION_MIPS16:
       mips_opts.mips16 = 1;
-      mips_no_prev_insn (FALSE);
+      mips_no_prev_insn ();
       break;
 
     case OPTION_NO_MIPS16:
       mips_opts.mips16 = 0;
-      mips_no_prev_insn (FALSE);
+      mips_no_prev_insn ();
       break;
 
     case OPTION_MIPS3D:
@@ -11058,7 +11062,7 @@ get_symbol (void)
 static void
 mips_align (int to, int fill, symbolS *label)
 {
-  mips_emit_delays (FALSE);
+  mips_emit_delays ();
   frag_align (to, fill, 0);
   record_alignment (now_seg, to);
   if (label != NULL)
@@ -11120,13 +11124,6 @@ s_align (int x ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
-void
-mips_flush_pending_output (void)
-{
-  mips_emit_delays (FALSE);
-  mips_clear_insn_labels ();
-}
-
 static void
 s_change_sec (int sec)
 {
@@ -11142,7 +11139,7 @@ s_change_sec (int sec)
   obj_elf_section_change_hook ();
 #endif
 
-  mips_emit_delays (FALSE);
+  mips_emit_delays ();
   switch (sec)
     {
     case 't':
@@ -11273,7 +11270,7 @@ s_cons (int log_size)
   symbolS *label;
 
   label = insn_labels != NULL ? insn_labels->label : NULL;
-  mips_emit_delays (FALSE);
+  mips_emit_delays ();
   if (log_size > 0 && auto_align)
     mips_align (log_size, 0, label);
   mips_clear_insn_labels ();
@@ -11287,7 +11284,7 @@ s_float_cons (int type)
 
   label = insn_labels != NULL ? insn_labels->label : NULL;
 
-  mips_emit_delays (FALSE);
+  mips_emit_delays ();
 
   if (auto_align)
     {
@@ -11415,22 +11412,13 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
 
   if (strcmp (name, "reorder") == 0)
     {
-      if (mips_opts.noreorder && prev_nop_frag != NULL)
-       {
-         /* If we still have pending nops, we can discard them.  The
-            usual nop handling will insert any that are still
-            needed.  */
-         prev_nop_frag->fr_fix -= (prev_nop_frag_holds
-                                   * (mips_opts.mips16 ? 2 : 4));
-         prev_nop_frag = NULL;
-       }
-      mips_opts.noreorder = 0;
+      if (mips_opts.noreorder)
+       end_noreorder ();
     }
   else if (strcmp (name, "noreorder") == 0)
     {
-      mips_emit_delays (TRUE);
-      mips_opts.noreorder = 1;
-      mips_any_noreorder = 1;
+      if (!mips_opts.noreorder)
+       start_noreorder ();
     }
   else if (strcmp (name, "at") == 0)
     {
@@ -11575,16 +11563,9 @@ s_mipsset (int x ATTRIBUTE_UNUSED)
          /* If we're changing the reorder mode we need to handle
              delay slots correctly.  */
          if (s->options.noreorder && ! mips_opts.noreorder)
-           mips_emit_delays (TRUE);
+           start_noreorder ();
          else if (! s->options.noreorder && mips_opts.noreorder)
-           {
-             if (prev_nop_frag != NULL)
-               {
-                 prev_nop_frag->fr_fix -= (prev_nop_frag_holds
-                                           * (mips_opts.mips16 ? 2 : 4));
-                 prev_nop_frag = NULL;
-               }
-           }
+           end_noreorder ();
 
          mips_opts = s->options;
          mips_opts_stack = s->next;
@@ -11924,7 +11905,7 @@ s_gpword (int ignore ATTRIBUTE_UNUSED)
     }
 
   label = insn_labels != NULL ? insn_labels->label : NULL;
-  mips_emit_delays (TRUE);
+  mips_emit_delays ();
   if (auto_align)
     mips_align (2, 0, label);
   mips_clear_insn_labels ();
@@ -11960,7 +11941,7 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED)
     }
 
   label = insn_labels != NULL ? insn_labels->label : NULL;
-  mips_emit_delays (TRUE);
+  mips_emit_delays ();
   if (auto_align)
     mips_align (3, 0, label);
   mips_clear_insn_labels ();
index e1e66b25621fdd311d1c0005390c25c31f1c2251..720f644fe38b079a4772a88b9e672b82114a5114 100644 (file)
@@ -149,8 +149,8 @@ extern void md_mips_end (void);
 extern void mips_pop_insert (void);
 #define md_pop_insert()                mips_pop_insert()
 
-extern void mips_flush_pending_output (void);
-#define md_flush_pending_output mips_flush_pending_output
+extern void mips_emit_delays (void);
+#define md_flush_pending_output mips_emit_delays
 
 extern void mips_enable_auto_align (void);
 #define md_elf_section_change_hook()   mips_enable_auto_align()