* 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:
parent
14b3d9c967
commit
c9049d301b
7 changed files with 454 additions and 508 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
/* 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 (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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
/* 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 (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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
|
38
gas/debug.c
38
gas/debug.c
|
@ -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.
|
||||
|
@ -25,26 +25,28 @@
|
|||
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
|
182
gas/subsegs.c
182
gas/subsegs.c
|
@ -27,20 +27,12 @@
|
|||
#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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
seginfo = seg_info (seg);
|
||||
|
||||
assert (frchain_now == 0
|
||||
|| now_seg == undefined_section
|
||||
|| frchain_now->frch_last == frag_now);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
fprintf (file, "frag chains:\n");
|
||||
for (frchp = frchain_root; frchp; frchp = frchp->frch_next)
|
||||
{
|
||||
int count = 0;
|
||||
fragS *fragp;
|
||||
asection *s;
|
||||
|
||||
/* 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)
|
||||
continue;
|
||||
fprintf (file, "frag chains:\n");
|
||||
for (s = stdoutput->sections; s; s = s->next)
|
||||
{
|
||||
segment_info_type *seginfo;
|
||||
|
||||
/* Skip gas-internal sections. */
|
||||
if (segment_name (frchp->frch_seg)[0] == '*')
|
||||
if (segment_name (s)[0] == '*')
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
|
|
83
gas/write.c
83
gas/write.c
|
@ -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)
|
||||
int alignment = 0;
|
||||
|
||||
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;
|
||||
int entalign = 0;
|
||||
|
||||
while ((entsize & 1) == 0)
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue