* 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.
This commit is contained in:
Alan Modra 2006-05-03 23:52:15 +00:00
parent 14b3d9c967
commit c9049d301b
7 changed files with 454 additions and 508 deletions

View 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> 2006-05-03 Alan Modra <amodra@bigpond.net.au>
* subsegs.c (subseg_get): Don't call obj_sec_set_private_data. * subsegs.c (subseg_get): Don't call obj_sec_set_private_data.

View file

@ -6954,44 +6954,46 @@ static void
xtensa_cleanup_align_frags (void) xtensa_cleanup_align_frags (void)
{ {
frchainS *frchP; frchainS *frchP;
asection *s;
for (frchP = frchain_root; frchP; frchP = frchP->frch_next) 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. */ fragS *fragP;
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) /* 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 if ((fragP->fr_type == rs_align
|| (fragP->fr_type == rs_machine_dependent || fragP->fr_type == rs_align_code
&& (fragP->fr_subtype == RELAX_DESIRE_ALIGN || (fragP->fr_type == rs_machine_dependent
|| fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET))) && (fragP->fr_subtype == RELAX_DESIRE_ALIGN
&& fragP->fr_fix == 0) || fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)))
{ && fragP->fr_fix == 0)
fragS *next = fragP->fr_next; {
fragS *next = fragP->fr_next;
while (next while (next
&& next->fr_fix == 0 && next->fr_fix == 0
&& next->fr_type == rs_machine_dependent && next->fr_type == rs_machine_dependent
&& next->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET) && next->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
{ {
frag_wane (next); frag_wane (next);
next = next->fr_next; next = next->fr_next;
} }
} }
/* If we don't widen branch targets, then they /* If we don't widen branch targets, then they
will be easier to align. */ will be easier to align. */
if (fragP->tc_frag_data.is_branch_target if (fragP->tc_frag_data.is_branch_target
&& fragP->fr_opcode == fragP->fr_literal && fragP->fr_opcode == fragP->fr_literal
&& fragP->fr_type == rs_machine_dependent && fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_SLOTS && fragP->fr_subtype == RELAX_SLOTS
&& fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW) && fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
frag_wane (fragP); frag_wane (fragP);
if (fragP->fr_type == rs_machine_dependent if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_UNREACHABLE) && fragP->fr_subtype == RELAX_UNREACHABLE)
fragP->tc_frag_data.is_unreachable = TRUE; fragP->tc_frag_data.is_unreachable = TRUE;
} }
} }
} }
@ -7004,26 +7006,28 @@ static void
xtensa_fix_target_frags (void) xtensa_fix_target_frags (void)
{ {
frchainS *frchP; frchainS *frchP;
asection *s;
/* When this routine is called, all of the subsections are still intact /* When this routine is called, all of the subsections are still intact
so we walk over subsections instead of sections. */ so we walk over subsections instead of sections. */
for (frchP = frchain_root; frchP; frchP = frchP->frch_next) for (s = stdoutput->sections; s; s = s->next)
{ for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
fragS *fragP; {
fragS *fragP;
/* Walk over all of the fragments in a subsection. */ /* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{ {
if (fragP->fr_type == rs_machine_dependent if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET) && fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET)
{ {
if (next_frag_is_branch_target (fragP)) if (next_frag_is_branch_target (fragP))
fragP->fr_subtype = RELAX_DESIRE_ALIGN; fragP->fr_subtype = RELAX_DESIRE_ALIGN;
else else
frag_wane (fragP); frag_wane (fragP);
} }
} }
} }
} }
@ -7033,36 +7037,38 @@ static void
xtensa_mark_narrow_branches (void) xtensa_mark_narrow_branches (void)
{ {
frchainS *frchP; frchainS *frchP;
asection *s;
for (frchP = frchain_root; frchP; frchP = frchP->frch_next) 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. */ fragS *fragP;
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) /* 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 if (fragP->fr_type == rs_machine_dependent
&& fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED) && fragP->fr_subtype == RELAX_SLOTS
{ && fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED)
vliw_insn vinsn; {
vliw_insn vinsn;
vinsn_from_chars (&vinsn, fragP->fr_opcode); vinsn_from_chars (&vinsn, fragP->fr_opcode);
tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0); tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0);
if (vinsn.num_slots == 1 if (vinsn.num_slots == 1
&& xtensa_opcode_is_branch (xtensa_default_isa, && xtensa_opcode_is_branch (xtensa_default_isa,
vinsn.slots[0].opcode) vinsn.slots[0].opcode)
&& xg_get_single_size (vinsn.slots[0].opcode) == 2 && xg_get_single_size (vinsn.slots[0].opcode) == 2
&& is_narrow_branch_guaranteed_in_range (fragP, && is_narrow_branch_guaranteed_in_range (fragP,
&vinsn.slots[0])) &vinsn.slots[0]))
{ {
fragP->fr_subtype = RELAX_SLOTS; fragP->fr_subtype = RELAX_SLOTS;
fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW; fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW;
fragP->tc_frag_data.is_aligning_branch = 1; fragP->tc_frag_data.is_aligning_branch = 1;
} }
} }
} }
} }
} }
@ -7119,48 +7125,50 @@ static void
xtensa_mark_zcl_first_insns (void) xtensa_mark_zcl_first_insns (void)
{ {
frchainS *frchP; frchainS *frchP;
asection *s;
for (frchP = frchain_root; frchP; frchP = frchP->frch_next) 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. */ fragS *fragP;
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) /* 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 if (fragP->fr_type == rs_machine_dependent
|| fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)) && (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 loop frag. */
/* Find the first insn frag. */ fragS *targ_frag = next_non_empty_frag (fragP);
targ_frag = next_non_empty_frag (targ_frag); /* Find the first insn frag. */
targ_frag = next_non_empty_frag (targ_frag);
/* Of course, sometimes (mostly for toy test cases) a /* Of course, sometimes (mostly for toy test cases) a
zero-cost loop instruction is the last in a section. */ zero-cost loop instruction is the last in a section. */
if (targ_frag) if (targ_frag)
{ {
targ_frag->tc_frag_data.is_first_loop_insn = TRUE; targ_frag->tc_frag_data.is_first_loop_insn = TRUE;
/* Do not widen a frag that is the first instruction of a /* Do not widen a frag that is the first instruction of a
zero-cost loop. It makes that loop harder to align. */ zero-cost loop. It makes that loop harder to align. */
if (targ_frag->fr_type == rs_machine_dependent if (targ_frag->fr_type == rs_machine_dependent
&& targ_frag->fr_subtype == RELAX_SLOTS && targ_frag->fr_subtype == RELAX_SLOTS
&& (targ_frag->tc_frag_data.slot_subtypes[0] && (targ_frag->tc_frag_data.slot_subtypes[0]
== RELAX_NARROW)) == RELAX_NARROW))
{ {
if (targ_frag->tc_frag_data.is_aligning_branch) if (targ_frag->tc_frag_data.is_aligning_branch)
targ_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED; targ_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED;
else else
{ {
frag_wane (targ_frag); frag_wane (targ_frag);
targ_frag->tc_frag_data.slot_subtypes[0] = 0; targ_frag->tc_frag_data.slot_subtypes[0] = 0;
} }
} }
} }
if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE) if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)
frag_wane (fragP); frag_wane (fragP);
} }
} }
} }
} }
@ -7175,30 +7183,32 @@ static void
xtensa_fix_a0_b_retw_frags (void) xtensa_fix_a0_b_retw_frags (void)
{ {
frchainS *frchP; frchainS *frchP;
asection *s;
/* When this routine is called, all of the subsections are still intact /* When this routine is called, all of the subsections are still intact
so we walk over subsections instead of sections. */ so we walk over subsections instead of sections. */
for (frchP = frchain_root; frchP; frchP = frchP->frch_next) for (s = stdoutput->sections; s; s = s->next)
{ for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
fragS *fragP; {
fragS *fragP;
/* Walk over all of the fragments in a subsection. */ /* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{ {
if (fragP->fr_type == rs_machine_dependent if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_A0_B_RETW) && fragP->fr_subtype == RELAX_ADD_NOP_IF_A0_B_RETW)
{ {
if (next_instrs_are_b_retw (fragP)) if (next_instrs_are_b_retw (fragP))
{ {
if (fragP->tc_frag_data.is_no_transform) if (fragP->tc_frag_data.is_no_transform)
as_bad (_("instruction sequence (write a0, branch, retw) may trigger hardware errata")); as_bad (_("instruction sequence (write a0, branch, retw) may trigger hardware errata"));
else else
relax_frag_add_nop (fragP); relax_frag_add_nop (fragP);
} }
frag_wane (fragP); frag_wane (fragP);
} }
} }
} }
} }
@ -7285,30 +7295,32 @@ static void
xtensa_fix_b_j_loop_end_frags (void) xtensa_fix_b_j_loop_end_frags (void)
{ {
frchainS *frchP; frchainS *frchP;
asection *s;
/* When this routine is called, all of the subsections are still intact /* When this routine is called, all of the subsections are still intact
so we walk over subsections instead of sections. */ so we walk over subsections instead of sections. */
for (frchP = frchain_root; frchP; frchP = frchP->frch_next) for (s = stdoutput->sections; s; s = s->next)
{ for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
fragS *fragP; {
fragS *fragP;
/* Walk over all of the fragments in a subsection. */ /* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{ {
if (fragP->fr_type == rs_machine_dependent if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_PRE_LOOP_END) && fragP->fr_subtype == RELAX_ADD_NOP_IF_PRE_LOOP_END)
{ {
if (next_instr_is_loop_end (fragP)) if (next_instr_is_loop_end (fragP))
{ {
if (fragP->tc_frag_data.is_no_transform) if (fragP->tc_frag_data.is_no_transform)
as_bad (_("branching or jumping to a loop end may trigger hardware errata")); as_bad (_("branching or jumping to a loop end may trigger hardware errata"));
else else
relax_frag_add_nop (fragP); relax_frag_add_nop (fragP);
} }
frag_wane (fragP); frag_wane (fragP);
} }
} }
} }
} }
@ -7349,66 +7361,68 @@ static void
xtensa_fix_close_loop_end_frags (void) xtensa_fix_close_loop_end_frags (void)
{ {
frchainS *frchP; frchainS *frchP;
asection *s;
/* When this routine is called, all of the subsections are still intact /* When this routine is called, all of the subsections are still intact
so we walk over subsections instead of sections. */ so we walk over subsections instead of sections. */
for (frchP = frchain_root; frchP; frchP = frchP->frch_next) for (s = stdoutput->sections; s; s = s->next)
{ for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
fragS *fragP; {
fragS *fragP;
fragS *current_target = NULL; fragS *current_target = NULL;
/* Walk over all of the fragments in a subsection. */ /* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{ {
if (fragP->fr_type == rs_machine_dependent if (fragP->fr_type == rs_machine_dependent
&& ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE) && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
|| (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))) || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
current_target = symbol_get_frag (fragP->fr_symbol); current_target = symbol_get_frag (fragP->fr_symbol);
if (current_target if (current_target
&& fragP->fr_type == rs_machine_dependent && fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END) && fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END)
{ {
offsetT min_bytes; offsetT min_bytes;
int bytes_added = 0; int bytes_added = 0;
#define REQUIRED_LOOP_DIVIDING_BYTES 12 #define REQUIRED_LOOP_DIVIDING_BYTES 12
/* Max out at 12. */ /* Max out at 12. */
min_bytes = min_bytes_to_other_loop_end min_bytes = min_bytes_to_other_loop_end
(fragP->fr_next, current_target, REQUIRED_LOOP_DIVIDING_BYTES); (fragP->fr_next, current_target, REQUIRED_LOOP_DIVIDING_BYTES);
if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES) if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES)
{ {
if (fragP->tc_frag_data.is_no_transform) if (fragP->tc_frag_data.is_no_transform)
as_bad (_("loop end too close to another loop end may trigger hardware errata")); as_bad (_("loop end too close to another loop end may trigger hardware errata"));
else else
{ {
while (min_bytes + bytes_added while (min_bytes + bytes_added
< REQUIRED_LOOP_DIVIDING_BYTES) < REQUIRED_LOOP_DIVIDING_BYTES)
{ {
int length = 3; int length = 3;
if (fragP->fr_var < length) if (fragP->fr_var < length)
as_fatal (_("fr_var %lu < length %d"), as_fatal (_("fr_var %lu < length %d"),
(long) fragP->fr_var, length); (long) fragP->fr_var, length);
else else
{ {
assemble_nop (length, assemble_nop (length,
fragP->fr_literal + fragP->fr_fix); fragP->fr_literal + fragP->fr_fix);
fragP->fr_fix += length; fragP->fr_fix += length;
fragP->fr_var -= length; fragP->fr_var -= length;
} }
bytes_added += length; bytes_added += length;
} }
} }
} }
frag_wane (fragP); frag_wane (fragP);
} }
assert (fragP->fr_type != rs_machine_dependent assert (fragP->fr_type != rs_machine_dependent
|| fragP->fr_subtype != RELAX_ADD_NOP_IF_CLOSE_LOOP_END); || fragP->fr_subtype != RELAX_ADD_NOP_IF_CLOSE_LOOP_END);
} }
} }
} }
@ -7512,49 +7526,51 @@ static void
xtensa_fix_short_loop_frags (void) xtensa_fix_short_loop_frags (void)
{ {
frchainS *frchP; frchainS *frchP;
asection *s;
/* When this routine is called, all of the subsections are still intact /* When this routine is called, all of the subsections are still intact
so we walk over subsections instead of sections. */ so we walk over subsections instead of sections. */
for (frchP = frchain_root; frchP; frchP = frchP->frch_next) 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 *fragP;
xtensa_opcode current_opcode = XTENSA_UNDEFINED; fragS *current_target = NULL;
xtensa_opcode current_opcode = XTENSA_UNDEFINED;
/* Walk over all of the fragments in a subsection. */ /* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{ {
if (fragP->fr_type == rs_machine_dependent if (fragP->fr_type == rs_machine_dependent
&& ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE) && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE)
|| (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))) || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)))
{ {
TInsn t_insn; TInsn t_insn;
fragS *loop_frag = next_non_empty_frag (fragP); fragS *loop_frag = next_non_empty_frag (fragP);
tinsn_from_chars (&t_insn, loop_frag->fr_opcode, 0); tinsn_from_chars (&t_insn, loop_frag->fr_opcode, 0);
current_target = symbol_get_frag (fragP->fr_symbol); current_target = symbol_get_frag (fragP->fr_symbol);
current_opcode = t_insn.opcode; current_opcode = t_insn.opcode;
assert (xtensa_opcode_is_loop (xtensa_default_isa, assert (xtensa_opcode_is_loop (xtensa_default_isa,
current_opcode)); current_opcode));
} }
if (fragP->fr_type == rs_machine_dependent if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP) && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP)
{ {
if (count_insns_to_loop_end (fragP->fr_next, TRUE, 3) < 3 if (count_insns_to_loop_end (fragP->fr_next, TRUE, 3) < 3
&& (branch_before_loop_end (fragP->fr_next) && (branch_before_loop_end (fragP->fr_next)
|| (workaround_all_short_loops || (workaround_all_short_loops
&& current_opcode != XTENSA_UNDEFINED && current_opcode != XTENSA_UNDEFINED
&& current_opcode != xtensa_loop_opcode))) && current_opcode != xtensa_loop_opcode)))
{ {
if (fragP->tc_frag_data.is_no_transform) if (fragP->tc_frag_data.is_no_transform)
as_bad (_("loop containing less than three instructions may trigger hardware errata")); as_bad (_("loop containing less than three instructions may trigger hardware errata"));
else else
relax_frag_add_nop (fragP); relax_frag_add_nop (fragP);
} }
frag_wane (fragP); frag_wane (fragP);
} }
} }
} }
} }
@ -7697,50 +7713,51 @@ xtensa_sanity_check (void)
{ {
char *file_name; char *file_name;
unsigned line; unsigned line;
frchainS *frchP; frchainS *frchP;
asection *s;
as_where (&file_name, &line); as_where (&file_name, &line);
for (frchP = frchain_root; frchP; frchP = frchP->frch_next) for (s = stdoutput->sections; s; s = s->next)
{ for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next)
fragS *fragP; {
fragS *fragP;
/* Walk over all of the fragments in a subsection. */ /* Walk over all of the fragments in a subsection. */
for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next)
{ {
/* Currently we only check for empty loops here. */ /* Currently we only check for empty loops here. */
if (fragP->fr_type == rs_machine_dependent if (fragP->fr_type == rs_machine_dependent
&& fragP->fr_subtype == RELAX_IMMED) && fragP->fr_subtype == RELAX_IMMED)
{ {
static xtensa_insnbuf insnbuf = NULL; static xtensa_insnbuf insnbuf = NULL;
TInsn t_insn; TInsn t_insn;
if (fragP->fr_opcode != NULL) if (fragP->fr_opcode != NULL)
{ {
if (!insnbuf) if (!insnbuf)
insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa); insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
tinsn_from_chars (&t_insn, fragP->fr_opcode, 0); tinsn_from_chars (&t_insn, fragP->fr_opcode, 0);
tinsn_immed_from_frag (&t_insn, fragP, 0); tinsn_immed_from_frag (&t_insn, fragP, 0);
if (xtensa_opcode_is_loop (xtensa_default_isa, if (xtensa_opcode_is_loop (xtensa_default_isa,
t_insn.opcode) == 1) t_insn.opcode) == 1)
{ {
if (is_empty_loop (&t_insn, fragP)) if (is_empty_loop (&t_insn, fragP))
{ {
new_logical_line (fragP->fr_file, fragP->fr_line); new_logical_line (fragP->fr_file, fragP->fr_line);
as_bad (_("invalid empty loop")); as_bad (_("invalid empty loop"));
} }
if (!is_local_forward_loop (&t_insn, fragP)) if (!is_local_forward_loop (&t_insn, fragP))
{ {
new_logical_line (fragP->fr_file, fragP->fr_line); new_logical_line (fragP->fr_file, fragP->fr_line);
as_bad (_("loop target does not follow " as_bad (_("loop target does not follow "
"loop instruction in section")); "loop instruction in section"));
} }
} }
} }
} }
} }
} }
new_logical_line (file_name, line); new_logical_line (file_name, line);
} }
@ -10384,7 +10401,6 @@ retrieve_segment_info (segT seg)
frchainP->frch_root = NULL; frchainP->frch_root = NULL;
frchainP->frch_last = NULL; frchainP->frch_last = NULL;
frchainP->frch_next = NULL; frchainP->frch_next = NULL;
frchainP->frch_seg = seg;
frchainP->frch_subseg = 0; frchainP->frch_subseg = 0;
frchainP->fix_root = NULL; frchainP->fix_root = NULL;
frchainP->fix_tail = NULL; frchainP->fix_tail = NULL;

View file

@ -1,5 +1,5 @@
/* This file is debug.c /* 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. Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler. This file is part of GAS, the GNU Assembler.
@ -25,26 +25,28 @@
dmp_frags () dmp_frags ()
{ {
asection *s;
frchainS *chp; frchainS *chp;
char *p; char *p;
for (chp = frchain_root; chp; chp = chp->frch_next) for (s = stdoutput->sections; s; s = s->next)
{ for (chp = seg_info (s)->frchainP; chp; chp = chp->frch_next)
switch (chp->frch_seg) {
{ switch (s)
case SEG_DATA: {
p = "Data"; case SEG_DATA:
break; p = "Data";
case SEG_TEXT: break;
p = "Text"; case SEG_TEXT:
break; p = "Text";
default: break;
p = "???"; default:
break; p = "???";
} break;
printf ("\nSEGMENT %s %d\n", p, chp->frch_subseg); }
dmp_frag (chp->frch_root, "\t"); printf ("\nSEGMENT %s %d\n", p, chp->frch_subseg);
} dmp_frag (chp->frch_root, "\t");
}
} }
dmp_frag (fp, indent) dmp_frag (fp, indent)

View file

@ -169,7 +169,7 @@ static void out_two (int);
static void out_four (int); static void out_four (int);
static void out_abbrev (int, int); static void out_abbrev (int, int);
static void out_uleb128 (addressT); 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 void out_set_addr (symbolS *);
static int size_inc_line_addr (int, addressT); static int size_inc_line_addr (int, addressT);
static void emit_inc_line_addr (int, addressT, char *, int); 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 * static struct frag *
first_frag_for_seg (segT seg) first_frag_for_seg (segT seg)
{ {
frchainS *f, *first = NULL; return seg_info (seg)->frchainP->frch_root;
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;
} }
static struct frag * static struct frag *
last_frag_for_seg (segT seg) 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) while (f->frch_next != NULL)
if (f->frch_seg == seg f = f->frch_next;
&& (! last || last->frch_subseg < f->frch_subseg))
last= f;
return last ? last->frch_last : NULL; return f->frch_last;
} }
/* Emit a single byte into the current segment. */ /* Emit a single byte into the current segment. */
@ -745,7 +736,7 @@ out_abbrev (int name, int form)
/* Get the size of a fragment. */ /* Get the size of a fragment. */
static offsetT static offsetT
get_frag_fix (fragS *frag) get_frag_fix (fragS *frag, segT seg)
{ {
frchainS *fr; frchainS *fr;
@ -755,7 +746,7 @@ get_frag_fix (fragS *frag)
/* If a fragment is the last in the chain, special measures must be /* 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 taken to find its size before relaxation, since it may be pending
on some subsegment chain. */ 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) if (fr->frch_last == frag)
return (char *) obstack_next_free (&fr->frch_obstack) - frag->fr_literal; 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. */ /* Emit a DW_LNE_end_sequence for the end of the section. */
frag = last_frag_for_seg (seg); frag = last_frag_for_seg (seg);
frag_ofs = get_frag_fix (frag); frag_ofs = get_frag_fix (frag, seg);
if (frag == last_frag) if (frag == last_frag)
out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs); out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
else else
@ -1332,7 +1323,7 @@ out_debug_aranges (segT aranges_seg, segT info_seg)
s->text_start = beg; s->text_start = beg;
frag = last_frag_for_seg (s->seg); 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; s->text_end = end;
expr.X_op = O_symbol; expr.X_op = O_symbol;

View file

@ -27,20 +27,12 @@
#include "subsegs.h" #include "subsegs.h"
#include "obstack.h" #include "obstack.h"
frchainS *frchain_root, *frchain_now; frchainS *frchain_now;
static struct obstack frchains; 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 fragS dummy_frag;
static frchainS absolute_frchain;
void void
subsegs_begin (void) subsegs_begin (void)
@ -50,16 +42,8 @@ subsegs_begin (void)
obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1; obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
#endif #endif
frchain_root = NULL;
frchain_now = NULL; /* Warn new_subseg() that we are booting. */ frchain_now = NULL; /* Warn new_subseg() that we are booting. */
frag_now = &dummy_frag; 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;
} }
/* /*
@ -75,14 +59,10 @@ subsegs_begin (void)
void void
subseg_change (register segT seg, register int subseg) subseg_change (register segT seg, register int subseg)
{ {
segment_info_type *seginfo; segment_info_type *seginfo = seg_info (seg);
now_seg = seg; now_seg = seg;
now_subseg = subseg; now_subseg = subseg;
if (now_seg == absolute_section)
return;
seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
if (! seginfo) if (! seginfo)
{ {
seginfo = (segment_info_type *) xmalloc (sizeof (*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->fix_tail = NULL;
seginfo->bfd_section = seg; seginfo->bfd_section = seg;
seginfo->sym = 0; seginfo->sym = 0;
if (seg == bfd_abs_section_ptr) bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
abs_seg_info = seginfo;
else if (seg == bfd_und_section_ptr)
und_seg_info = seginfo;
else
bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
} }
} }
static void static void
subseg_set_rest (segT seg, subsegT subseg) subseg_set_rest (segT seg, subsegT subseg)
{ {
register frchainS *frcP; /* crawl frchain chain */ frchainS *frcP; /* crawl frchain chain */
register frchainS **lastPP; /* address of last pointer */ frchainS **lastPP; /* address of last pointer */
frchainS *newP; /* address of new frchain */ frchainS *newP; /* address of new frchain */
segment_info_type *seginfo;
mri_common_symbol = NULL; mri_common_symbol = NULL;
@ -113,72 +89,26 @@ subseg_set_rest (segT seg, subsegT subseg)
frchain_now->frch_frag_now = frag_now; frchain_now->frch_frag_now = frag_now;
assert (frchain_now == 0 assert (frchain_now == 0
|| now_seg == undefined_section
|| now_seg == absolute_section
|| frchain_now->frch_last == frag_now); || frchain_now->frch_last == frag_now);
subseg_change (seg, (int) subseg); subseg_change (seg, (int) subseg);
if (seg == absolute_section) seginfo = seg_info (seg);
{
frchain_now = &absolute_frchain;
frag_now = &zero_address_frag;
return;
}
assert (frchain_now == 0 /* Attempt to find or make a frchain for that subsection.
|| now_seg == undefined_section We keep the list sorted by subsection number. */
|| frchain_now->frch_last == frag_now); for (frcP = *(lastPP = &seginfo->frchainP);
frcP != NULL;
/*
* 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;
frcP = *(lastPP = &frcP->frch_next)) frcP = *(lastPP = &frcP->frch_next))
if (frcP->frch_subseg >= subseg)
break;
if (frcP == NULL || frcP->frch_subseg != subseg)
{ {
if (frcP->frch_seg == seg /* This should be the only code that creates a frchainS. */
&& 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;
newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS)); newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
newP->frch_subseg = subseg; newP->frch_subseg = subseg;
newP->frch_seg = seg;
newP->fix_root = NULL; newP->fix_root = NULL;
newP->fix_tail = NULL; newP->fix_tail = NULL;
obstack_begin (&newP->frch_obstack, chunksize); 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; newP->frch_root = newP->frch_last = newP->frch_frag_now;
*lastPP = newP; *lastPP = newP;
newP->frch_next = frcP; /* perhaps NULL */ newP->frch_next = frcP;
seginfo = seg_info (seg);
if (seginfo && (!seginfo->frchainP || seginfo->frchainP == frcP))
seginfo->frchainP = newP;
frcP = newP; frcP = newP;
} }
/*
* Here with frcP pointing to the frchainS for subseg.
*/
frchain_now = frcP; frchain_now = frcP;
frag_now = frcP->frch_frag_now; frag_now = frcP->frch_frag_now;
@ -221,7 +144,6 @@ subseg_set_rest (segT seg, subsegT subseg)
* Out: now_subseg, now_seg updated. * Out: now_subseg, now_seg updated.
* Frchain_now points to the (possibly new) struct frchain for this * Frchain_now points to the (possibly new) struct frchain for this
* sub-segment. * sub-segment.
* Frchain_root updated if needed.
*/ */
segT segT
@ -247,21 +169,13 @@ subseg_get (const char *segname, int force_new)
seginfo = seg_info (secptr); seginfo = seg_info (secptr);
if (! seginfo) if (! seginfo)
{ {
/* Check whether output_section is set first because secptr may secptr->output_section = secptr;
be bfd_abs_section_ptr. */
if (secptr->output_section != secptr)
secptr->output_section = secptr;
seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo)); seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
memset ((PTR) seginfo, 0, sizeof (*seginfo)); memset ((PTR) seginfo, 0, sizeof (*seginfo));
seginfo->fix_root = NULL; seginfo->fix_root = NULL;
seginfo->fix_tail = NULL; seginfo->fix_tail = NULL;
seginfo->bfd_section = secptr; seginfo->bfd_section = secptr;
if (secptr == bfd_abs_section_ptr) bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
abs_seg_info = seginfo;
else if (secptr == bfd_und_section_ptr)
und_seg_info = seginfo;
else
bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
seginfo->frchainP = NULL; seginfo->frchainP = NULL;
seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL; seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
seginfo->sym = NULL; seginfo->sym = NULL;
@ -274,13 +188,9 @@ segT
subseg_new (const char *segname, subsegT subseg) subseg_new (const char *segname, subsegT subseg)
{ {
segT secptr; segT secptr;
segment_info_type *seginfo;
secptr = subseg_get (segname, 0); secptr = subseg_get (segname, 0);
subseg_set_rest (secptr, subseg); subseg_set_rest (secptr, subseg);
seginfo = seg_info (secptr);
if (! seginfo->frchainP)
seginfo->frchainP = frchain_now;
return secptr; return secptr;
} }
@ -290,13 +200,9 @@ segT
subseg_force_new (const char *segname, subsegT subseg) subseg_force_new (const char *segname, subsegT subseg)
{ {
segT secptr; segT secptr;
segment_info_type *seginfo;
secptr = subseg_get (segname, 1); secptr = subseg_get (segname, 1);
subseg_set_rest (secptr, subseg); subseg_set_rest (secptr, subseg);
seginfo = seg_info (secptr);
if (! seginfo->frchainP)
seginfo->frchainP = frchain_now;
return secptr; return secptr;
} }
@ -312,19 +218,6 @@ subseg_set (segT secptr, subsegT subseg)
#define obj_sec_sym_ok_for_reloc(SEC) 0 #define obj_sec_sym_ok_for_reloc(SEC) 0
#endif #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 * symbolS *
section_symbol (segT sec) section_symbol (segT sec)
{ {
@ -414,28 +307,33 @@ void
subsegs_print_statistics (FILE *file) subsegs_print_statistics (FILE *file)
{ {
frchainS *frchp; frchainS *frchp;
fprintf (file, "frag chains:\n"); asection *s;
for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
{
int count = 0;
fragS *fragp;
/* If frch_subseg is non-zero, it's probably been chained onto fprintf (file, "frag chains:\n");
the end of a previous subsection. Don't count it again. */ for (s = stdoutput->sections; s; s = s->next)
if (frchp->frch_subseg != 0) {
continue; segment_info_type *seginfo;
/* Skip gas-internal sections. */ /* Skip gas-internal sections. */
if (segment_name (frchp->frch_seg)[0] == '*') if (segment_name (s)[0] == '*')
continue; continue;
for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next) seginfo = seg_info (s);
if (!seginfo)
continue;
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);
} }
} }

View file

@ -1,6 +1,6 @@
/* subsegs.h -> subsegs.c /* subsegs.h -> subsegs.c
Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2003, 2005 Copyright 1987, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2003, 2005,
Free Software Foundation, Inc. 2006 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler. 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_root; /* 1st struct frag in chain, or NULL */
struct frag *frch_last; /* last 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 */ 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 */ subsegT frch_subseg; /* subsegment number of this chain */
fixS *fix_root; /* Root of fixups for this subsegment. */ fixS *fix_root; /* Root of fixups for this subsegment. */
fixS *fix_tail; /* Last fixup 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; 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 /* Frchain we are assembling into now. That is, the current segment's
frag chain, even if it contains no (complete) frags. */ frag chain, even if it contains no (complete) frags. */
extern frchainS *frchain_now; extern frchainS *frchain_now;
@ -109,7 +105,10 @@ typedef struct segment_info_struct {
#endif #endif
} segment_info_type; } 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 symbolS *section_symbol (segT);
extern void subsegs_print_statistics (FILE *); extern void subsegs_print_statistics (FILE *);

View file

@ -1,6 +1,6 @@
/* write.c - emit .o file /* write.c - emit .o file
Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 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. Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler. 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; fragS dummy, *prev_frag = &dummy;
fixS fix_dummy, *prev_fix = &fix_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->fr_next = frchp->frch_root;
prev_frag = frchp->frch_last; prev_frag = frchp->frch_last;
@ -1136,8 +1136,7 @@ set_symtab (void)
of the section. This allows proper nop-filling at the end of of the section. This allows proper nop-filling at the end of
code-bearing sections. */ code-bearing sections. */
#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \ #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \
(!(FRCHAIN)->frch_next || (FRCHAIN)->frch_next->frch_seg != (SEG) \ (!(FRCHAIN)->frch_next ? get_recorded_alignment (SEG) : 0)
? get_recorded_alignment (SEG) : 0)
#else #else
#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0 #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
#endif #endif
@ -1147,48 +1146,58 @@ void
subsegs_finish (void) subsegs_finish (void)
{ {
struct frchain *frchainP; 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); for (frchainP = seginfo->frchainP;
frchainP != NULL;
/* This now gets called even if we had errors. In that case, frchainP = frchainP->frch_next)
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); int alignment = 0;
if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
&& now_seg->entsize) subseg_set (s, 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 ())
{ {
unsigned int entsize = now_seg->entsize; alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
int entalign = 0; if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
&& now_seg->entsize)
while ((entsize & 1) == 0)
{ {
++entalign; unsigned int entsize = now_seg->entsize;
entsize >>= 1; 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);
/* 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);
} }
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".
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);
} }
} }