* subsegs.h (struct frchain): Delete frch_seg.
authorAlan Modra <amodra@gmail.com>
Wed, 3 May 2006 23:52:15 +0000 (23:52 +0000)
committerAlan Modra <amodra@gmail.com>
Wed, 3 May 2006 23:52:15 +0000 (23:52 +0000)
(frchain_root): Delete.
(seg_info): Define as macro.
* subsegs.c (frchain_root): Delete.
(abs_seg_info, und_seg_info, absolute_frchain): Delete.
(subsegs_begin, subseg_change): Adjust for above.
(subseg_set_rest): Likewise.  Add new frchain structs to seginfo
rather than to one big list.
(subseg_get): Don't special case abs, und sections.
(subseg_new, subseg_force_new): Don't set frchainP here.
(seg_info): Delete.
(subsegs_print_statistics): Adjust frag chain control list traversal.
* debug.c (dmp_frags):  Likewise.
* dwarf2dbg.c (first_frag_for_seg): Don't start looking for frag
at frchain_root.  Make use of known frchain ordering.
(last_frag_for_seg): Likewise.
(get_frag_fix): Likewise.  Add seg param.
(process_entries, out_debug_aranges): Adjust get_frag_fix calls.
* write.c (chain_frchains_together_1): Adjust for struct frchain.
(SUB_SEGMENT_ALIGN): Likewise.
(subsegs_finish): Adjust frchain list traversal.
* config/tc-xtensa.c (xtensa_cleanup_align_frags): Likewise.
(xtensa_fix_target_frags, xtensa_mark_narrow_branches): Likewise.
(xtensa_mark_zcl_first_insns, xtensa_fix_a0_b_retw_frags): Likewise.
(xtensa_fix_b_j_loop_end_frags): Likewise.
(xtensa_fix_close_loop_end_frags): Likewise.
(xtensa_fix_short_loop_frags, xtensa_sanity_check): Likewise.
(retrieve_segment_info): Delete frch_seg initialisation.

gas/ChangeLog
gas/config/tc-xtensa.c
gas/debug.c
gas/dwarf2dbg.c
gas/subsegs.c
gas/subsegs.h
gas/write.c

index 1ed8d70..0d51e96 100644 (file)
@@ -1,3 +1,34 @@
+2006-05-04  Alan Modra  <amodra@bigpond.net.au>
+
+       * subsegs.h (struct frchain): Delete frch_seg.
+       (frchain_root): Delete.
+       (seg_info): Define as macro.
+       * subsegs.c (frchain_root): Delete.
+       (abs_seg_info, und_seg_info, absolute_frchain): Delete.
+       (subsegs_begin, subseg_change): Adjust for above.
+       (subseg_set_rest): Likewise.  Add new frchain structs to seginfo
+       rather than to one big list.
+       (subseg_get): Don't special case abs, und sections.
+       (subseg_new, subseg_force_new): Don't set frchainP here.
+       (seg_info): Delete.
+       (subsegs_print_statistics): Adjust frag chain control list traversal.
+       * debug.c (dmp_frags):  Likewise.
+       * dwarf2dbg.c (first_frag_for_seg): Don't start looking for frag
+       at frchain_root.  Make use of known frchain ordering.
+       (last_frag_for_seg): Likewise.
+       (get_frag_fix): Likewise.  Add seg param.
+       (process_entries, out_debug_aranges): Adjust get_frag_fix calls.
+       * write.c (chain_frchains_together_1): Adjust for struct frchain.
+       (SUB_SEGMENT_ALIGN): Likewise.
+       (subsegs_finish): Adjust frchain list traversal.
+       * config/tc-xtensa.c (xtensa_cleanup_align_frags): Likewise.
+       (xtensa_fix_target_frags, xtensa_mark_narrow_branches): Likewise.
+       (xtensa_mark_zcl_first_insns, xtensa_fix_a0_b_retw_frags): Likewise.
+       (xtensa_fix_b_j_loop_end_frags): Likewise.
+       (xtensa_fix_close_loop_end_frags): Likewise.
+       (xtensa_fix_short_loop_frags, xtensa_sanity_check): Likewise.
+       (retrieve_segment_info): Delete frch_seg initialisation.
+
 2006-05-03  Alan Modra  <amodra@bigpond.net.au>
 
        * subsegs.c (subseg_get): Don't call obj_sec_set_private_data.
index 85d1b37..31e0eea 100644 (file)
@@ -6954,44 +6954,46 @@ static void
 xtensa_cleanup_align_frags (void)
 {
   frchainS *frchP;
+  asection *s;
 
-  for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
-    {
-      fragS *fragP;
-      /* Walk over all of the fragments in a subsection.  */
-      for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
-       {
-         if ((fragP->fr_type == rs_align
-              || fragP->fr_type == rs_align_code
-              || (fragP->fr_type == rs_machine_dependent
-                  && (fragP->fr_subtype == RELAX_DESIRE_ALIGN
-                      || fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)))
-             && fragP->fr_fix == 0)
-           {
-             fragS *next = fragP->fr_next;
-
-             while (next
-                    && next->fr_fix == 0
-                    && next->fr_type == rs_machine_dependent
-                    && next->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
-               {
-                 frag_wane (next);
-                 next = next->fr_next;
-               }
-           }
-         /* If we don't widen branch targets, then they
-            will be easier to align.  */
-         if (fragP->tc_frag_data.is_branch_target
-             && fragP->fr_opcode == fragP->fr_literal
-             && fragP->fr_type == rs_machine_dependent
-             && fragP->fr_subtype == RELAX_SLOTS
-             && fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
-           frag_wane (fragP);
-         if (fragP->fr_type == rs_machine_dependent
-             && fragP->fr_subtype == RELAX_UNREACHABLE)
-           fragP->tc_frag_data.is_unreachable = TRUE;
-       }
-    }
+  for (s = stdoutput->sections; s; s = s->next)
+    for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
+      {
+       fragS *fragP;
+       /* Walk over all of the fragments in a subsection.  */
+       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
+         {
+           if ((fragP->fr_type == rs_align
+                || fragP->fr_type == rs_align_code
+                || (fragP->fr_type == rs_machine_dependent
+                    && (fragP->fr_subtype == RELAX_DESIRE_ALIGN
+                        || fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)))
+               && fragP->fr_fix == 0)
+             {
+               fragS *next = fragP->fr_next;
+
+               while (next
+                      && next->fr_fix == 0
+                      && next->fr_type == rs_machine_dependent
+                      && next->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
+                 {
+                   frag_wane (next);
+                   next = next->fr_next;
+                 }
+             }
+           /* If we don't widen branch targets, then they
+              will be easier to align.  */
+           if (fragP->tc_frag_data.is_branch_target
+               && fragP->fr_opcode == fragP->fr_literal
+               && fragP->fr_type == rs_machine_dependent
+               && fragP->fr_subtype == RELAX_SLOTS
+               && fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
+             frag_wane (fragP);
+           if (fragP->fr_type == rs_machine_dependent
+               && fragP->fr_subtype == RELAX_UNREACHABLE)
+             fragP->tc_frag_data.is_unreachable = TRUE;
+         }
+      }
 }
 
 
@@ -7004,26 +7006,28 @@ static void
 xtensa_fix_target_frags (void)
 {
   frchainS *frchP;
+  asection *s;
 
   /* When this routine is called, all of the subsections are still intact
      so we walk over subsections instead of sections.  */
-  for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
-    {
-      fragS *fragP;
+  for (s = stdoutput->sections; s; s = s->next)
+    for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
+      {
+       fragS *fragP;
 
-      /* Walk over all of the fragments in a subsection.  */
-      for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
-       {
-         if (fragP->fr_type == rs_machine_dependent
-             && fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
-           {
-             if (next_frag_is_branch_target (fragP))
-               fragP->fr_subtype = RELAX_DESIRE_ALIGN;
-             else
-               frag_wane (fragP);
-           }
-       }
-    }
+       /* Walk over all of the fragments in a subsection.  */
+       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
+         {
+           if (fragP->fr_type == rs_machine_dependent
+               && fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
+             {
+               if (next_frag_is_branch_target (fragP))
+                 fragP->fr_subtype = RELAX_DESIRE_ALIGN;
+               else
+                 frag_wane (fragP);
+             }
+         }
+      }
 }
 
 
@@ -7033,36 +7037,38 @@ static void
 xtensa_mark_narrow_branches (void)
 {
   frchainS *frchP;
+  asection *s;
 
-  for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
-    {
-      fragS *fragP;
-      /* Walk over all of the fragments in a subsection.  */
-      for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
-       {
-         if (fragP->fr_type == rs_machine_dependent
-             && fragP->fr_subtype == RELAX_SLOTS
-             && fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED)
-           {
-             vliw_insn vinsn;
-
-             vinsn_from_chars (&vinsn, fragP->fr_opcode);
-             tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0);
-
-             if (vinsn.num_slots == 1
-                 && xtensa_opcode_is_branch (xtensa_default_isa,
-                                             vinsn.slots[0].opcode)
-                 && xg_get_single_size (vinsn.slots[0].opcode) == 2
-                 && is_narrow_branch_guaranteed_in_range (fragP,
-                                                          &vinsn.slots[0]))
-               {
-                 fragP->fr_subtype = RELAX_SLOTS;
-                 fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW;
-                 fragP->tc_frag_data.is_aligning_branch = 1;
-               }
-           }
-       }
-    }
+  for (s = stdoutput->sections; s; s = s->next)
+    for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
+      {
+       fragS *fragP;
+       /* Walk over all of the fragments in a subsection.  */
+       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
+         {
+           if (fragP->fr_type == rs_machine_dependent
+               && fragP->fr_subtype == RELAX_SLOTS
+               && fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED)
+             {
+               vliw_insn vinsn;
+
+               vinsn_from_chars (&vinsn, fragP->fr_opcode);
+               tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0);
+
+               if (vinsn.num_slots == 1
+                   && xtensa_opcode_is_branch (xtensa_default_isa,
+                                               vinsn.slots[0].opcode)
+                   && xg_get_single_size (vinsn.slots[0].opcode) == 2
+                   && is_narrow_branch_guaranteed_in_range (fragP,
+                                                            &vinsn.slots[0]))
+                 {
+                   fragP->fr_subtype = RELAX_SLOTS;
+                   fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW;
+                   fragP->tc_frag_data.is_aligning_branch = 1;
+                 }
+             }
+         }
+      }
 }
 
 
@@ -7119,48 +7125,50 @@ static void
 xtensa_mark_zcl_first_insns (void)
 {
   frchainS *frchP;
+  asection *s;
 
-  for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
-    {
-      fragS *fragP;
-      /* Walk over all of the fragments in a subsection.  */
-      for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
-       {
-         if (fragP->fr_type == rs_machine_dependent
-             && (fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE
-                 || fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))
-           {
-             /* Find the loop frag.  */
-             fragS *targ_frag = next_non_empty_frag (fragP);
-             /* Find the first insn frag.  */
-             targ_frag = next_non_empty_frag (targ_frag);
-
-             /* Of course, sometimes (mostly for toy test cases) a
-                zero-cost loop instruction is the last in a section.  */
-             if (targ_frag)
-               {
-                 targ_frag->tc_frag_data.is_first_loop_insn = TRUE;
-                 /* Do not widen a frag that is the first instruction of a
-                    zero-cost loop.  It makes that loop harder to align.  */
-                 if (targ_frag->fr_type == rs_machine_dependent
-                     && targ_frag->fr_subtype == RELAX_SLOTS
-                     && (targ_frag->tc_frag_data.slot_subtypes[0]
-                         == RELAX_NARROW))
-                   {
-                     if (targ_frag->tc_frag_data.is_aligning_branch)
-                       targ_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED;
-                     else
-                       {
-                         frag_wane (targ_frag);
-                         targ_frag->tc_frag_data.slot_subtypes[0] = 0;
-                       }
-                   }
-               }
-             if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)
-               frag_wane (fragP);
-           }
-       }
-    }
+  for (s = stdoutput->sections; s; s = s->next)
+    for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
+      {
+       fragS *fragP;
+       /* Walk over all of the fragments in a subsection.  */
+       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
+         {
+           if (fragP->fr_type == rs_machine_dependent
+               && (fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE
+                   || fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))
+             {
+               /* Find the loop frag.  */
+               fragS *targ_frag = next_non_empty_frag (fragP);
+               /* Find the first insn frag.  */
+               targ_frag = next_non_empty_frag (targ_frag);
+
+               /* Of course, sometimes (mostly for toy test cases) a
+                  zero-cost loop instruction is the last in a section.  */
+               if (targ_frag)
+                 {
+                   targ_frag->tc_frag_data.is_first_loop_insn = TRUE;
+                   /* Do not widen a frag that is the first instruction of a
+                      zero-cost loop.  It makes that loop harder to align.  */
+                   if (targ_frag->fr_type == rs_machine_dependent
+                       && targ_frag->fr_subtype == RELAX_SLOTS
+                       && (targ_frag->tc_frag_data.slot_subtypes[0]
+                           == RELAX_NARROW))
+                     {
+                       if (targ_frag->tc_frag_data.is_aligning_branch)
+                         targ_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED;
+                       else
+                         {
+                           frag_wane (targ_frag);
+                           targ_frag->tc_frag_data.slot_subtypes[0] = 0;
+                         }
+                     }
+                 }
+               if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)
+                 frag_wane (fragP);
+             }
+         }
+      }
 }
 
 
@@ -7175,30 +7183,32 @@ static void
 xtensa_fix_a0_b_retw_frags (void)
 {
   frchainS *frchP;
+  asection *s;
 
   /* When this routine is called, all of the subsections are still intact
      so we walk over subsections instead of sections.  */
-  for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
-    {
-      fragS *fragP;
+  for (s = stdoutput->sections; s; s = s->next)
+    for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
+      {
+       fragS *fragP;
 
-      /* Walk over all of the fragments in a subsection.  */
-      for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
-       {
-         if (fragP->fr_type == rs_machine_dependent
-             && fragP->fr_subtype == RELAX_ADD_NOP_IF_A0_B_RETW)
-           {
-             if (next_instrs_are_b_retw (fragP))
-               {
-                 if (fragP->tc_frag_data.is_no_transform)
-                   as_bad (_("instruction sequence (write a0, branch, retw) may trigger hardware errata"));
-                 else
-                   relax_frag_add_nop (fragP);
-               }
-             frag_wane (fragP);
-           }
-       }
-    }
+       /* Walk over all of the fragments in a subsection.  */
+       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
+         {
+           if (fragP->fr_type == rs_machine_dependent
+               && fragP->fr_subtype == RELAX_ADD_NOP_IF_A0_B_RETW)
+             {
+               if (next_instrs_are_b_retw (fragP))
+                 {
+                   if (fragP->tc_frag_data.is_no_transform)
+                     as_bad (_("instruction sequence (write a0, branch, retw) may trigger hardware errata"));
+                   else
+                     relax_frag_add_nop (fragP);
+                 }
+               frag_wane (fragP);
+             }
+         }
+      }
 }
 
 
@@ -7285,30 +7295,32 @@ static void
 xtensa_fix_b_j_loop_end_frags (void)
 {
   frchainS *frchP;
+  asection *s;
 
   /* When this routine is called, all of the subsections are still intact
      so we walk over subsections instead of sections.  */
-  for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
-    {
-      fragS *fragP;
+  for (s = stdoutput->sections; s; s = s->next)
+    for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
+      {
+       fragS *fragP;
 
-      /* Walk over all of the fragments in a subsection.  */
-      for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
-       {
-         if (fragP->fr_type == rs_machine_dependent
-             && fragP->fr_subtype == RELAX_ADD_NOP_IF_PRE_LOOP_END)
-           {
-             if (next_instr_is_loop_end (fragP))
-               {
-                 if (fragP->tc_frag_data.is_no_transform)
-                   as_bad (_("branching or jumping to a loop end may trigger hardware errata"));
-                 else
-                   relax_frag_add_nop (fragP);
-               }
-             frag_wane (fragP);
-           }
-       }
-    }
+       /* Walk over all of the fragments in a subsection.  */
+       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
+         {
+           if (fragP->fr_type == rs_machine_dependent
+               && fragP->fr_subtype == RELAX_ADD_NOP_IF_PRE_LOOP_END)
+             {
+               if (next_instr_is_loop_end (fragP))
+                 {
+                   if (fragP->tc_frag_data.is_no_transform)
+                     as_bad (_("branching or jumping to a loop end may trigger hardware errata"));
+                   else
+                     relax_frag_add_nop (fragP);
+                 }
+               frag_wane (fragP);
+             }
+         }
+      }
 }
 
 
@@ -7349,66 +7361,68 @@ static void
 xtensa_fix_close_loop_end_frags (void)
 {
   frchainS *frchP;
+  asection *s;
 
   /* When this routine is called, all of the subsections are still intact
      so we walk over subsections instead of sections.  */
-  for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
-    {
-      fragS *fragP;
+  for (s = stdoutput->sections; s; s = s->next)
+    for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
+      {
+       fragS *fragP;
 
-      fragS *current_target = NULL;
+       fragS *current_target = NULL;
 
-      /* Walk over all of the fragments in a subsection.  */
-      for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
-       {
-         if (fragP->fr_type == rs_machine_dependent
-             && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
-                 || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
+       /* Walk over all of the fragments in a subsection.  */
+       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
+         {
+           if (fragP->fr_type == rs_machine_dependent
+               && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
+                   || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
              current_target = symbol_get_frag (fragP->fr_symbol);
 
-         if (current_target
-             && fragP->fr_type == rs_machine_dependent
-             && fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END)
-           {
-             offsetT min_bytes;
-             int bytes_added = 0;
+           if (current_target
+               && fragP->fr_type == rs_machine_dependent
+               && fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END)
+             {
+               offsetT min_bytes;
+               int bytes_added = 0;
 
 #define REQUIRED_LOOP_DIVIDING_BYTES 12
-             /* Max out at 12.  */
-             min_bytes = min_bytes_to_other_loop_end
-               (fragP->fr_next, current_target, REQUIRED_LOOP_DIVIDING_BYTES);
-
-             if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES)
-               {
-                 if (fragP->tc_frag_data.is_no_transform)
-                   as_bad (_("loop end too close to another loop end may trigger hardware errata"));
-                 else
-                   {
-                     while (min_bytes + bytes_added
-                            < REQUIRED_LOOP_DIVIDING_BYTES)
-                       {
-                         int length = 3;
-
-                         if (fragP->fr_var < length)
-                           as_fatal (_("fr_var %lu < length %d"),
-                                     (long) fragP->fr_var, length);
-                         else
-                           {
-                             assemble_nop (length,
-                                           fragP->fr_literal + fragP->fr_fix);
-                             fragP->fr_fix += length;
-                             fragP->fr_var -= length;
-                           }
-                         bytes_added += length;
-                       }
-                   }
-               }
-             frag_wane (fragP);
-           }
-         assert (fragP->fr_type != rs_machine_dependent
-                 || fragP->fr_subtype != RELAX_ADD_NOP_IF_CLOSE_LOOP_END);
-       }
-    }
+               /* Max out at 12.  */
+               min_bytes = min_bytes_to_other_loop_end
+                 (fragP->fr_next, current_target, REQUIRED_LOOP_DIVIDING_BYTES);
+
+               if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES)
+                 {
+                   if (fragP->tc_frag_data.is_no_transform)
+                     as_bad (_("loop end too close to another loop end may trigger hardware errata"));
+                   else
+                     {
+                       while (min_bytes + bytes_added
+                              < REQUIRED_LOOP_DIVIDING_BYTES)
+                         {
+                           int length = 3;
+
+                           if (fragP->fr_var < length)
+                             as_fatal (_("fr_var %lu < length %d"),
+                                       (long) fragP->fr_var, length);
+                           else
+                             {
+                               assemble_nop (length,
+                                             fragP->fr_literal + fragP->fr_fix);
+                               fragP->fr_fix += length;
+                               fragP->fr_var -= length;
+                             }
+                           bytes_added += length;
+                         }
+                     }
+                 }
+               frag_wane (fragP);
+             }
+           assert (fragP->fr_type != rs_machine_dependent
+                   || fragP->fr_subtype != RELAX_ADD_NOP_IF_CLOSE_LOOP_END);
+         }
+      }
 }
 
 
@@ -7512,49 +7526,51 @@ static void
 xtensa_fix_short_loop_frags (void)
 {
   frchainS *frchP;
+  asection *s;
 
   /* When this routine is called, all of the subsections are still intact
      so we walk over subsections instead of sections.  */
-  for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
-    {
-      fragS *fragP;
-      fragS *current_target = NULL;
-      xtensa_opcode current_opcode = XTENSA_UNDEFINED;
+  for (s = stdoutput->sections; s; s = s->next)
+    for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
+      {
+       fragS *fragP;
+       fragS *current_target = NULL;
+       xtensa_opcode current_opcode = XTENSA_UNDEFINED;
 
-      /* Walk over all of the fragments in a subsection.  */
-      for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
-       {
-         if (fragP->fr_type == rs_machine_dependent
-             && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
-                 || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
-           {
-             TInsn t_insn;
-             fragS *loop_frag = next_non_empty_frag (fragP);
-             tinsn_from_chars (&t_insn, loop_frag->fr_opcode, 0);
-             current_target = symbol_get_frag (fragP->fr_symbol);
-             current_opcode = t_insn.opcode;
-             assert (xtensa_opcode_is_loop (xtensa_default_isa,
-                                            current_opcode));
-           }
+       /* Walk over all of the fragments in a subsection.  */
+       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
+         {
+           if (fragP->fr_type == rs_machine_dependent
+               && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
+                   || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
+             {
+               TInsn t_insn;
+               fragS *loop_frag = next_non_empty_frag (fragP);
+               tinsn_from_chars (&t_insn, loop_frag->fr_opcode, 0);
+               current_target = symbol_get_frag (fragP->fr_symbol);
+               current_opcode = t_insn.opcode;
+               assert (xtensa_opcode_is_loop (xtensa_default_isa,
+                                              current_opcode));
+             }
 
-         if (fragP->fr_type == rs_machine_dependent
-             && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
-           {
-             if (count_insns_to_loop_end (fragP->fr_next, TRUE, 3) < 3
-                 && (branch_before_loop_end (fragP->fr_next)
-                     || (workaround_all_short_loops
-                         && current_opcode != XTENSA_UNDEFINED
-                         && current_opcode != xtensa_loop_opcode)))
-               {
-                 if (fragP->tc_frag_data.is_no_transform)
-                   as_bad (_("loop containing less than three instructions may trigger hardware errata"));
-                 else
-                   relax_frag_add_nop (fragP);
-               }
-             frag_wane (fragP);
-           }
-       }
-    }
+           if (fragP->fr_type == rs_machine_dependent
+               && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
+             {
+               if (count_insns_to_loop_end (fragP->fr_next, TRUE, 3) < 3
+                   && (branch_before_loop_end (fragP->fr_next)
+                       || (workaround_all_short_loops
+                           && current_opcode != XTENSA_UNDEFINED
+                           && current_opcode != xtensa_loop_opcode)))
+                 {
+                   if (fragP->tc_frag_data.is_no_transform)
+                     as_bad (_("loop containing less than three instructions may trigger hardware errata"));
+                   else
+                     relax_frag_add_nop (fragP);
+                 }
+               frag_wane (fragP);
+             }
+         }
+      }
 }
 
 
@@ -7697,50 +7713,51 @@ xtensa_sanity_check (void)
 {
   char *file_name;
   unsigned line;
-
   frchainS *frchP;
+  asection *s;
 
   as_where (&file_name, &line);
-  for (frchP = frchain_root; frchP; frchP = frchP->frch_next)
-    {
-      fragS *fragP;
-
-      /* Walk over all of the fragments in a subsection.  */
-      for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
-       {
-         /* Currently we only check for empty loops here.  */
-         if (fragP->fr_type == rs_machine_dependent
-             && fragP->fr_subtype == RELAX_IMMED)
-           {
-             static xtensa_insnbuf insnbuf = NULL;
-             TInsn t_insn;
-
-             if (fragP->fr_opcode != NULL)
-               {
-                 if (!insnbuf)
-                   insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
-                 tinsn_from_chars (&t_insn, fragP->fr_opcode, 0);
-                 tinsn_immed_from_frag (&t_insn, fragP, 0);
+  for (s = stdoutput->sections; s; s = s->next)
+    for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
+      {
+       fragS *fragP;
 
-                 if (xtensa_opcode_is_loop (xtensa_default_isa,
-                                            t_insn.opcode) == 1)
-                   {
-                     if (is_empty_loop (&t_insn, fragP))
-                       {
-                         new_logical_line (fragP->fr_file, fragP->fr_line);
-                         as_bad (_("invalid empty loop"));
-                       }
-                     if (!is_local_forward_loop (&t_insn, fragP))
-                       {
-                         new_logical_line (fragP->fr_file, fragP->fr_line);
-                         as_bad (_("loop target does not follow "
-                                   "loop instruction in section"));
-                       }
-                   }
-               }
-           }
-       }
-    }
+       /* Walk over all of the fragments in a subsection.  */
+       for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
+         {
+           /* Currently we only check for empty loops here.  */
+           if (fragP->fr_type == rs_machine_dependent
+               && fragP->fr_subtype == RELAX_IMMED)
+             {
+               static xtensa_insnbuf insnbuf = NULL;
+               TInsn t_insn;
+
+               if (fragP->fr_opcode != NULL)
+                 {
+                   if (!insnbuf)
+                     insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
+                   tinsn_from_chars (&t_insn, fragP->fr_opcode, 0);
+                   tinsn_immed_from_frag (&t_insn, fragP, 0);
+
+                   if (xtensa_opcode_is_loop (xtensa_default_isa,
+                                              t_insn.opcode) == 1)
+                     {
+                       if (is_empty_loop (&t_insn, fragP))
+                         {
+                           new_logical_line (fragP->fr_file, fragP->fr_line);
+                           as_bad (_("invalid empty loop"));
+                         }
+                       if (!is_local_forward_loop (&t_insn, fragP))
+                         {
+                           new_logical_line (fragP->fr_file, fragP->fr_line);
+                           as_bad (_("loop target does not follow "
+                                     "loop instruction in section"));
+                         }
+                     }
+                 }
+             }
+         }
+      }
   new_logical_line (file_name, line);
 }
 
@@ -10384,7 +10401,6 @@ retrieve_segment_info (segT seg)
       frchainP->frch_root = NULL;
       frchainP->frch_last = NULL;
       frchainP->frch_next = NULL;
-      frchainP->frch_seg = seg;
       frchainP->frch_subseg = 0;
       frchainP->fix_root = NULL;
       frchainP->fix_tail = NULL;
index fe2ed8c..3218fff 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is debug.c
-   Copyright 1987, 1988, 1989, 1990, 1991, 1992, 2000
+   Copyright 1987, 1988, 1989, 1990, 1991, 1992, 2000, 2006
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
 dmp_frags ()
 {
+  asection *s;
   frchainS *chp;
   char *p;
 
-  for (chp = frchain_root; chp; chp = chp->frch_next)
-    {
-      switch (chp->frch_seg)
-       {
-       case SEG_DATA:
-         p = "Data";
-         break;
-       case SEG_TEXT:
-         p = "Text";
-         break;
-       default:
-         p = "???";
-         break;
-       }
-      printf ("\nSEGMENT %s %d\n", p, chp->frch_subseg);
-      dmp_frag (chp->frch_root, "\t");
-    }
+  for (s = stdoutput->sections; s; s = s->next)
+    for (chp = seg_info (s)->frchainP; chp; chp = chp->frch_next)
+      {
+       switch (s)
+         {
+         case SEG_DATA:
+           p = "Data";
+           break;
+         case SEG_TEXT:
+           p = "Text";
+           break;
+         default:
+           p = "???";
+           break;
+         }
+       printf ("\nSEGMENT %s %d\n", p, chp->frch_subseg);
+       dmp_frag (chp->frch_root, "\t");
+      }
 }
 
 dmp_frag (fp, indent)
index 16666fa..661962f 100644 (file)
@@ -169,7 +169,7 @@ static void out_two (int);
 static void out_four (int);
 static void out_abbrev (int, int);
 static void out_uleb128 (addressT);
-static offsetT get_frag_fix (fragS *);
+static offsetT get_frag_fix (fragS *, segT);
 static void out_set_addr (symbolS *);
 static int size_inc_line_addr (int, addressT);
 static void emit_inc_line_addr (int, addressT, char *, int);
@@ -670,27 +670,18 @@ dwarf2_directive_loc_mark_labels (int dummy ATTRIBUTE_UNUSED)
 static struct frag *
 first_frag_for_seg (segT seg)
 {
-  frchainS *f, *first = NULL;
-
-  for (f = frchain_root; f; f = f->frch_next)
-    if (f->frch_seg == seg
-       && (! first || first->frch_subseg > f->frch_subseg))
-      first = f;
-
-  return first ? first->frch_root : NULL;
+  return seg_info (seg)->frchainP->frch_root;
 }
 
 static struct frag *
 last_frag_for_seg (segT seg)
 {
-  frchainS *f, *last = NULL;
+  frchainS *f = seg_info (seg)->frchainP;
 
-  for (f = frchain_root; f; f = f->frch_next)
-    if (f->frch_seg == seg
-       && (! last || last->frch_subseg < f->frch_subseg))
-      last= f;
+  while (f->frch_next != NULL)
+    f = f->frch_next;
 
-  return last ? last->frch_last : NULL;
+  return f->frch_last;
 }
 \f
 /* Emit a single byte into the current segment.  */
@@ -745,7 +736,7 @@ out_abbrev (int name, int form)
 /* Get the size of a fragment.  */
 
 static offsetT
-get_frag_fix (fragS *frag)
+get_frag_fix (fragS *frag, segT seg)
 {
   frchainS *fr;
 
@@ -755,7 +746,7 @@ get_frag_fix (fragS *frag)
   /* If a fragment is the last in the chain, special measures must be
      taken to find its size before relaxation, since it may be pending
      on some subsegment chain.  */
-  for (fr = frchain_root; fr; fr = fr->frch_next)
+  for (fr = seg_info (seg)->frchainP; fr; fr = fr->frch_next)
     if (fr->frch_last == frag)
       return (char *) obstack_next_free (&fr->frch_obstack) - frag->fr_literal;
 
@@ -1134,7 +1125,7 @@ process_entries (segT seg, struct line_entry *e)
 
   /* Emit a DW_LNE_end_sequence for the end of the section.  */
   frag = last_frag_for_seg (seg);
-  frag_ofs = get_frag_fix (frag);
+  frag_ofs = get_frag_fix (frag, seg);
   if (frag == last_frag)
     out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
   else
@@ -1332,7 +1323,7 @@ out_debug_aranges (segT aranges_seg, segT info_seg)
       s->text_start = beg;
 
       frag = last_frag_for_seg (s->seg);
-      end = symbol_temp_new (s->seg, get_frag_fix (frag), frag);
+      end = symbol_temp_new (s->seg, get_frag_fix (frag, s->seg), frag);
       s->text_end = end;
 
       expr.X_op = O_symbol;
index c81c09a..e77bce8 100644 (file)
 #include "subsegs.h"
 #include "obstack.h"
 
-frchainS *frchain_root, *frchain_now;
+frchainS *frchain_now;
 
 static struct obstack frchains;
 
-/* Gas segment information for bfd_abs_section_ptr and
-   bfd_und_section_ptr.  */
-static segment_info_type *abs_seg_info;
-static segment_info_type *und_seg_info;
-
-static void subseg_set_rest (segT, subsegT);
-
 static fragS dummy_frag;
 
-static frchainS absolute_frchain;
 \f
 void
 subsegs_begin (void)
@@ -50,16 +42,8 @@ subsegs_begin (void)
   obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
 #endif
 
-  frchain_root = NULL;
   frchain_now = NULL;          /* Warn new_subseg() that we are booting.  */
-
   frag_now = &dummy_frag;
-
-  absolute_frchain.frch_seg = absolute_section;
-  absolute_frchain.frch_subseg = 0;
-  absolute_frchain.fix_root = absolute_frchain.fix_tail = 0;
-  absolute_frchain.frch_frag_now = &zero_address_frag;
-  absolute_frchain.frch_root = absolute_frchain.frch_last = &zero_address_frag;
 }
 \f
 /*
@@ -75,14 +59,10 @@ subsegs_begin (void)
 void
 subseg_change (register segT seg, register int subseg)
 {
-  segment_info_type *seginfo;
+  segment_info_type *seginfo = seg_info (seg);
   now_seg = seg;
   now_subseg = subseg;
 
-  if (now_seg == absolute_section)
-    return;
-
-  seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
   if (! seginfo)
     {
       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
@@ -91,21 +71,17 @@ subseg_change (register segT seg, register int subseg)
       seginfo->fix_tail = NULL;
       seginfo->bfd_section = seg;
       seginfo->sym = 0;
-      if (seg == bfd_abs_section_ptr)
-       abs_seg_info = seginfo;
-      else if (seg == bfd_und_section_ptr)
-       und_seg_info = seginfo;
-      else
-       bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
+      bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
     }
 }
 \f
 static void
 subseg_set_rest (segT seg, subsegT subseg)
 {
-  register frchainS *frcP;     /* crawl frchain chain */
-  register frchainS **lastPP;  /* address of last pointer */
+  frchainS *frcP;              /* crawl frchain chain */
+  frchainS **lastPP;           /* address of last pointer */
   frchainS *newP;              /* address of new frchain */
+  segment_info_type *seginfo;
 
   mri_common_symbol = NULL;
 
@@ -113,72 +89,26 @@ subseg_set_rest (segT seg, subsegT subseg)
     frchain_now->frch_frag_now = frag_now;
 
   assert (frchain_now == 0
-         || now_seg == undefined_section
-         || now_seg == absolute_section
          || frchain_now->frch_last == frag_now);
 
   subseg_change (seg, (int) subseg);
 
-  if (seg == absolute_section)
-    {
-      frchain_now = &absolute_frchain;
-      frag_now = &zero_address_frag;
-      return;
-    }
-
-  assert (frchain_now == 0
-         || now_seg == undefined_section
-         || frchain_now->frch_last == frag_now);
+  seginfo = seg_info (seg);
 
-  /*
-   * Attempt to find or make a frchain for that sub seg.
-   * Crawl along chain of frchainSs, begins @ frchain_root.
-   * If we need to make a frchainS, link it into correct
-   * position of chain rooted in frchain_root.
-   */
-  for (frcP = *(lastPP = &frchain_root);
-       frcP && frcP->frch_seg <= seg;
+  /* Attempt to find or make a frchain for that subsection.
+     We keep the list sorted by subsection number.  */
+  for (frcP = *(lastPP = &seginfo->frchainP);
+       frcP != NULL;
        frcP = *(lastPP = &frcP->frch_next))
+    if (frcP->frch_subseg >= subseg)
+      break;
+
+  if (frcP == NULL || frcP->frch_subseg != subseg)
     {
-      if (frcP->frch_seg == seg
-         && frcP->frch_subseg >= subseg)
-       {
-         break;
-       }
-    }
-  /*
-   * frcP:             Address of the 1st frchainS in correct segment with
-   *           frch_subseg >= subseg.
-   *           We want to either use this frchainS, or we want
-   *           to insert a new frchainS just before it.
-   *
-   *           If frcP==NULL, then we are at the end of the chain
-   *           of frchainS-s. A NULL frcP means we fell off the end
-   *           of the chain looking for a
-   *           frch_subseg >= subseg, so we
-   *           must make a new frchainS.
-   *
-   *           If we ever maintain a pointer to
-   *           the last frchainS in the chain, we change that pointer
-   *           ONLY when frcP==NULL.
-   *
-   * lastPP:   Address of the pointer with value frcP;
-   *           Never NULL.
-   *           May point to frchain_root.
-   *
-   */
-  if (!frcP
-      || (frcP->frch_seg > seg
-         || frcP->frch_subseg > subseg))       /* Kinky logic only works with 2 segments.  */
-    {
-      /*
-       * This should be the only code that creates a frchainS.
-       */
-      segment_info_type *seginfo;
+      /* This should be the only code that creates a frchainS.  */
 
       newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
       newP->frch_subseg = subseg;
-      newP->frch_seg = seg;
       newP->fix_root = NULL;
       newP->fix_tail = NULL;
       obstack_begin (&newP->frch_obstack, chunksize);
@@ -191,17 +121,10 @@ subseg_set_rest (segT seg, subsegT subseg)
       newP->frch_root = newP->frch_last = newP->frch_frag_now;
 
       *lastPP = newP;
-      newP->frch_next = frcP;  /* perhaps NULL */
-
-      seginfo = seg_info (seg);
-      if (seginfo && (!seginfo->frchainP || seginfo->frchainP == frcP))
-       seginfo->frchainP = newP;
-
+      newP->frch_next = frcP;
       frcP = newP;
     }
-  /*
-   * Here with frcP pointing to the frchainS for subseg.
-   */
+
   frchain_now = frcP;
   frag_now = frcP->frch_frag_now;
 
@@ -221,7 +144,6 @@ subseg_set_rest (segT seg, subsegT subseg)
  * Out:        now_subseg, now_seg updated.
  *     Frchain_now points to the (possibly new) struct frchain for this
  *     sub-segment.
- *     Frchain_root updated if needed.
  */
 
 segT
@@ -247,21 +169,13 @@ subseg_get (const char *segname, int force_new)
   seginfo = seg_info (secptr);
   if (! seginfo)
     {
-      /* Check whether output_section is set first because secptr may
-        be bfd_abs_section_ptr.  */
-      if (secptr->output_section != secptr)
-       secptr->output_section = secptr;
+      secptr->output_section = secptr;
       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
       memset ((PTR) seginfo, 0, sizeof (*seginfo));
       seginfo->fix_root = NULL;
       seginfo->fix_tail = NULL;
       seginfo->bfd_section = secptr;
-      if (secptr == bfd_abs_section_ptr)
-       abs_seg_info = seginfo;
-      else if (secptr == bfd_und_section_ptr)
-       und_seg_info = seginfo;
-      else
-       bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
+      bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
       seginfo->frchainP = NULL;
       seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
       seginfo->sym = NULL;
@@ -274,13 +188,9 @@ segT
 subseg_new (const char *segname, subsegT subseg)
 {
   segT secptr;
-  segment_info_type *seginfo;
 
   secptr = subseg_get (segname, 0);
   subseg_set_rest (secptr, subseg);
-  seginfo = seg_info (secptr);
-  if (! seginfo->frchainP)
-    seginfo->frchainP = frchain_now;
   return secptr;
 }
 
@@ -290,13 +200,9 @@ segT
 subseg_force_new (const char *segname, subsegT subseg)
 {
   segT secptr;
-  segment_info_type *seginfo;
 
   secptr = subseg_get (segname, 1);
   subseg_set_rest (secptr, subseg);
-  seginfo = seg_info (secptr);
-  if (! seginfo->frchainP)
-    seginfo->frchainP = frchain_now;
   return secptr;
 }
 
@@ -312,19 +218,6 @@ subseg_set (segT secptr, subsegT subseg)
 #define obj_sec_sym_ok_for_reloc(SEC)  0
 #endif
 
-/* Get the gas information we are storing for a section.  */
-
-segment_info_type *
-seg_info (segT sec)
-{
-  if (sec == bfd_abs_section_ptr)
-    return abs_seg_info;
-  else if (sec == bfd_und_section_ptr)
-    return und_seg_info;
-  else
-    return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
-}
-
 symbolS *
 section_symbol (segT sec)
 {
@@ -414,28 +307,33 @@ void
 subsegs_print_statistics (FILE *file)
 {
   frchainS *frchp;
+  asection *s;
+
   fprintf (file, "frag chains:\n");
-  for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
+  for (s = stdoutput->sections; s; s = s->next)
     {
-      int count = 0;
-      fragS *fragp;
+      segment_info_type *seginfo;
 
-      /* If frch_subseg is non-zero, it's probably been chained onto
-        the end of a previous subsection.  Don't count it again.  */
-      if (frchp->frch_subseg != 0)
+      /* Skip gas-internal sections.  */
+      if (segment_name (s)[0] == '*')
        continue;
 
-      /* Skip gas-internal sections.  */
-      if (segment_name (frchp->frch_seg)[0] == '*')
+      seginfo = seg_info (s);
+      if (!seginfo)
        continue;
 
-      for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
+      for (frchp = seginfo->frchainP; frchp; frchp = frchp->frch_next)
        {
-         count++;
+         int count = 0;
+         fragS *fragp;
+
+         for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next)
+           count++;
+
+         fprintf (file, "\n");
+         fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
+                  segment_name (s), count);
        }
-      fprintf (file, "\n");
-      fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp,
-              segment_name (frchp->frch_seg), count);
     }
 }
 
index 23ab4f9..f950285 100644 (file)
@@ -1,6 +1,6 @@
 /* subsegs.h -> subsegs.c
-   Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2003, 2005
-   Free Software Foundation, Inc.
+   Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2003, 2005,
+   2006 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -45,7 +45,6 @@ struct frchain                        /* control building of a frag chain */
   struct frag *frch_root;      /* 1st struct frag in chain, or NULL */
   struct frag *frch_last;      /* last struct frag in chain, or NULL */
   struct frchain *frch_next;   /* next in chain of struct frchain-s */
-  segT frch_seg;               /* SEG_TEXT or SEG_DATA.  */
   subsegT frch_subseg;         /* subsegment number of this chain */
   fixS *fix_root;              /* Root of fixups for this subsegment.  */
   fixS *fix_tail;              /* Last fixup for this subsegment.  */
@@ -55,9 +54,6 @@ struct frchain                        /* control building of a frag chain */
 
 typedef struct frchain frchainS;
 
-/* All subsegments' chains hang off here.  NULL means no frchains yet.  */
-extern frchainS *frchain_root;
-
 /* Frchain we are assembling into now.  That is, the current segment's
    frag chain, even if it contains no (complete) frags.  */
 extern frchainS *frchain_now;
@@ -109,7 +105,10 @@ typedef struct segment_info_struct {
 #endif
 } segment_info_type;
 
-extern segment_info_type *seg_info (segT);
+
+#define seg_info(sec) \
+  ((segment_info_type *) bfd_get_section_userdata (stdoutput, sec))
+
 extern symbolS *section_symbol (segT);
 
 extern void subsegs_print_statistics (FILE *);
index 5c336d8..93b157f 100644 (file)
@@ -1,6 +1,6 @@
 /* write.c - emit .o file
    Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -379,7 +379,7 @@ chain_frchains_together_1 (segT section, struct frchain *frchp)
   fragS dummy, *prev_frag = &dummy;
   fixS fix_dummy, *prev_fix = &fix_dummy;
 
-  for (; frchp && frchp->frch_seg == section; frchp = frchp->frch_next)
+  for (; frchp; frchp = frchp->frch_next)
     {
       prev_frag->fr_next = frchp->frch_root;
       prev_frag = frchp->frch_last;
@@ -1136,8 +1136,7 @@ set_symtab (void)
    of the section.  This allows proper nop-filling at the end of
    code-bearing sections.  */
 #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN)                                        \
-  (!(FRCHAIN)->frch_next || (FRCHAIN)->frch_next->frch_seg != (SEG)    \
-   ? get_recorded_alignment (SEG) : 0)
+  (!(FRCHAIN)->frch_next ? get_recorded_alignment (SEG) : 0)
 #else
 #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
 #endif
@@ -1147,48 +1146,58 @@ void
 subsegs_finish (void)
 {
   struct frchain *frchainP;
+  asection *s;
 
-  for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
+  for (s = stdoutput->sections; s; s = s->next)
     {
-      int alignment = 0;
+      segment_info_type *seginfo = seg_info (s);
+      if (!seginfo)
+       continue;
 
-      subseg_set (frchainP->frch_seg, frchainP->frch_subseg);
-
-      /* This now gets called even if we had errors.  In that case,
-         any alignment is meaningless, and, moreover, will look weird
-         if we are generating a listing.  */
-      if (!had_errors ())
+      for (frchainP = seginfo->frchainP;
+          frchainP != NULL;
+          frchainP = frchainP->frch_next)
        {
-         alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
-         if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
-             && now_seg->entsize)
-           {
-             unsigned int entsize = now_seg->entsize;
-             int entalign = 0;
+         int alignment = 0;
+
+         subseg_set (s, frchainP->frch_subseg);
 
-             while ((entsize & 1) == 0)
+         /* This now gets called even if we had errors.  In that case,
+            any alignment is meaningless, and, moreover, will look weird
+            if we are generating a listing.  */
+         if (!had_errors ())
+           {
+             alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
+             if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
+                 && now_seg->entsize)
                {
-                 ++entalign;
-                 entsize >>= 1;
+                 unsigned int entsize = now_seg->entsize;
+                 int entalign = 0;
+
+                 while ((entsize & 1) == 0)
+                   {
+                     ++entalign;
+                     entsize >>= 1;
+                   }
+                 if (entalign > alignment)
+                   alignment = entalign;
                }
-             if (entalign > alignment)
-               alignment = entalign;
            }
-       }
 
-      if (subseg_text_p (now_seg))
-       frag_align_code (alignment, 0);
-      else
-       frag_align (alignment, 0, 0);
+         if (subseg_text_p (now_seg))
+           frag_align_code (alignment, 0);
+         else
+           frag_align (alignment, 0, 0);
 
-      /* frag_align will have left a new frag.
-        Use this last frag for an empty ".fill".
+         /* frag_align will have left a new frag.
+            Use this last frag for an empty ".fill".
 
-        For this segment ...
-        Create a last frag. Do not leave a "being filled in frag".  */
-      frag_wane (frag_now);
-      frag_now->fr_fix = 0;
-      know (frag_now->fr_next == NULL);
+            For this segment ...
+            Create a last frag. Do not leave a "being filled in frag".  */
+         frag_wane (frag_now);
+         frag_now->fr_fix = 0;
+         know (frag_now->fr_next == NULL);
+       }
     }
 }