* 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>
|
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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
38
gas/debug.c
38
gas/debug.c
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
182
gas/subsegs.c
182
gas/subsegs.c
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 *);
|
||||||
|
|
83
gas/write.c
83
gas/write.c
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue