From c9049d301b7f5b254df47b61ae2e52b94c2dbb6b Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 3 May 2006 23:52:15 +0000 Subject: [PATCH] * 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. --- gas/ChangeLog | 31 +++ gas/config/tc-xtensa.c | 602 +++++++++++++++++++++++++------------------------ gas/debug.c | 38 ++-- gas/dwarf2dbg.c | 29 +-- gas/subsegs.c | 178 ++++----------- gas/subsegs.h | 13 +- gas/write.c | 79 ++++--- 7 files changed, 458 insertions(+), 512 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 1ed8d70..0d51e96 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,34 @@ +2006-05-04 Alan Modra + + * 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 * subsegs.c (subseg_get): Don't call obj_sec_set_private_data. diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index 85d1b37..31e0eea 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -6954,44 +6954,46 @@ static void xtensa_cleanup_align_frags (void) { frchainS *frchP; + asection *s; - for (frchP = frchain_root; frchP; frchP = frchP->frch_next) - { - fragS *fragP; - /* Walk over all of the fragments in a subsection. */ - for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) - { - if ((fragP->fr_type == rs_align - || fragP->fr_type == rs_align_code - || (fragP->fr_type == rs_machine_dependent - && (fragP->fr_subtype == RELAX_DESIRE_ALIGN - || fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET))) - && fragP->fr_fix == 0) - { - fragS *next = fragP->fr_next; - - while (next - && next->fr_fix == 0 - && next->fr_type == rs_machine_dependent - && next->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET) - { - frag_wane (next); - next = next->fr_next; - } - } - /* If we don't widen branch targets, then they - will be easier to align. */ - if (fragP->tc_frag_data.is_branch_target - && fragP->fr_opcode == fragP->fr_literal - && fragP->fr_type == rs_machine_dependent - && fragP->fr_subtype == RELAX_SLOTS - && fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW) - frag_wane (fragP); - if (fragP->fr_type == rs_machine_dependent - && fragP->fr_subtype == RELAX_UNREACHABLE) - fragP->tc_frag_data.is_unreachable = TRUE; - } - } + for (s = stdoutput->sections; s; s = s->next) + for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next) + { + fragS *fragP; + /* Walk over all of the fragments in a subsection. */ + for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) + { + if ((fragP->fr_type == rs_align + || fragP->fr_type == rs_align_code + || (fragP->fr_type == rs_machine_dependent + && (fragP->fr_subtype == RELAX_DESIRE_ALIGN + || fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET))) + && fragP->fr_fix == 0) + { + fragS *next = fragP->fr_next; + + while (next + && next->fr_fix == 0 + && next->fr_type == rs_machine_dependent + && next->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET) + { + frag_wane (next); + next = next->fr_next; + } + } + /* If we don't widen branch targets, then they + will be easier to align. */ + if (fragP->tc_frag_data.is_branch_target + && fragP->fr_opcode == fragP->fr_literal + && fragP->fr_type == rs_machine_dependent + && fragP->fr_subtype == RELAX_SLOTS + && fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW) + frag_wane (fragP); + if (fragP->fr_type == rs_machine_dependent + && fragP->fr_subtype == RELAX_UNREACHABLE) + fragP->tc_frag_data.is_unreachable = TRUE; + } + } } @@ -7004,26 +7006,28 @@ static void xtensa_fix_target_frags (void) { frchainS *frchP; + asection *s; /* When this routine is called, all of the subsections are still intact so we walk over subsections instead of sections. */ - for (frchP = frchain_root; frchP; frchP = frchP->frch_next) - { - fragS *fragP; + for (s = stdoutput->sections; s; s = s->next) + for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next) + { + fragS *fragP; - /* Walk over all of the fragments in a subsection. */ - for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) - { - if (fragP->fr_type == rs_machine_dependent - && fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET) - { - if (next_frag_is_branch_target (fragP)) - fragP->fr_subtype = RELAX_DESIRE_ALIGN; - else - frag_wane (fragP); - } - } - } + /* Walk over all of the fragments in a subsection. */ + for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) + { + if (fragP->fr_type == rs_machine_dependent + && fragP->fr_subtype == RELAX_DESIRE_ALIGN_IF_TARGET) + { + if (next_frag_is_branch_target (fragP)) + fragP->fr_subtype = RELAX_DESIRE_ALIGN; + else + frag_wane (fragP); + } + } + } } @@ -7033,36 +7037,38 @@ static void xtensa_mark_narrow_branches (void) { frchainS *frchP; + asection *s; - for (frchP = frchain_root; frchP; frchP = frchP->frch_next) - { - fragS *fragP; - /* Walk over all of the fragments in a subsection. */ - for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) - { - if (fragP->fr_type == rs_machine_dependent - && fragP->fr_subtype == RELAX_SLOTS - && fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED) - { - vliw_insn vinsn; - - vinsn_from_chars (&vinsn, fragP->fr_opcode); - tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0); - - if (vinsn.num_slots == 1 - && xtensa_opcode_is_branch (xtensa_default_isa, - vinsn.slots[0].opcode) - && xg_get_single_size (vinsn.slots[0].opcode) == 2 - && is_narrow_branch_guaranteed_in_range (fragP, - &vinsn.slots[0])) - { - fragP->fr_subtype = RELAX_SLOTS; - fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW; - fragP->tc_frag_data.is_aligning_branch = 1; - } - } - } - } + for (s = stdoutput->sections; s; s = s->next) + for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next) + { + fragS *fragP; + /* Walk over all of the fragments in a subsection. */ + for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) + { + if (fragP->fr_type == rs_machine_dependent + && fragP->fr_subtype == RELAX_SLOTS + && fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED) + { + vliw_insn vinsn; + + vinsn_from_chars (&vinsn, fragP->fr_opcode); + tinsn_immed_from_frag (&vinsn.slots[0], fragP, 0); + + if (vinsn.num_slots == 1 + && xtensa_opcode_is_branch (xtensa_default_isa, + vinsn.slots[0].opcode) + && xg_get_single_size (vinsn.slots[0].opcode) == 2 + && is_narrow_branch_guaranteed_in_range (fragP, + &vinsn.slots[0])) + { + fragP->fr_subtype = RELAX_SLOTS; + fragP->tc_frag_data.slot_subtypes[0] = RELAX_NARROW; + fragP->tc_frag_data.is_aligning_branch = 1; + } + } + } + } } @@ -7119,48 +7125,50 @@ static void xtensa_mark_zcl_first_insns (void) { frchainS *frchP; + asection *s; - for (frchP = frchain_root; frchP; frchP = frchP->frch_next) - { - fragS *fragP; - /* Walk over all of the fragments in a subsection. */ - for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) - { - if (fragP->fr_type == rs_machine_dependent - && (fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE - || fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)) - { - /* Find the loop frag. */ - fragS *targ_frag = next_non_empty_frag (fragP); - /* Find the first insn frag. */ - targ_frag = next_non_empty_frag (targ_frag); - - /* Of course, sometimes (mostly for toy test cases) a - zero-cost loop instruction is the last in a section. */ - if (targ_frag) - { - targ_frag->tc_frag_data.is_first_loop_insn = TRUE; - /* Do not widen a frag that is the first instruction of a - zero-cost loop. It makes that loop harder to align. */ - if (targ_frag->fr_type == rs_machine_dependent - && targ_frag->fr_subtype == RELAX_SLOTS - && (targ_frag->tc_frag_data.slot_subtypes[0] - == RELAX_NARROW)) - { - if (targ_frag->tc_frag_data.is_aligning_branch) - targ_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED; - else - { - frag_wane (targ_frag); - targ_frag->tc_frag_data.slot_subtypes[0] = 0; - } - } - } - if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE) - frag_wane (fragP); - } - } - } + for (s = stdoutput->sections; s; s = s->next) + for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next) + { + fragS *fragP; + /* Walk over all of the fragments in a subsection. */ + for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) + { + if (fragP->fr_type == rs_machine_dependent + && (fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE + || fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)) + { + /* Find the loop frag. */ + fragS *targ_frag = next_non_empty_frag (fragP); + /* Find the first insn frag. */ + targ_frag = next_non_empty_frag (targ_frag); + + /* Of course, sometimes (mostly for toy test cases) a + zero-cost loop instruction is the last in a section. */ + if (targ_frag) + { + targ_frag->tc_frag_data.is_first_loop_insn = TRUE; + /* Do not widen a frag that is the first instruction of a + zero-cost loop. It makes that loop harder to align. */ + if (targ_frag->fr_type == rs_machine_dependent + && targ_frag->fr_subtype == RELAX_SLOTS + && (targ_frag->tc_frag_data.slot_subtypes[0] + == RELAX_NARROW)) + { + if (targ_frag->tc_frag_data.is_aligning_branch) + targ_frag->tc_frag_data.slot_subtypes[0] = RELAX_IMMED; + else + { + frag_wane (targ_frag); + targ_frag->tc_frag_data.slot_subtypes[0] = 0; + } + } + } + if (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE) + frag_wane (fragP); + } + } + } } @@ -7175,30 +7183,32 @@ static void xtensa_fix_a0_b_retw_frags (void) { frchainS *frchP; + asection *s; /* When this routine is called, all of the subsections are still intact so we walk over subsections instead of sections. */ - for (frchP = frchain_root; frchP; frchP = frchP->frch_next) - { - fragS *fragP; + for (s = stdoutput->sections; s; s = s->next) + for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next) + { + fragS *fragP; - /* Walk over all of the fragments in a subsection. */ - for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) - { - if (fragP->fr_type == rs_machine_dependent - && fragP->fr_subtype == RELAX_ADD_NOP_IF_A0_B_RETW) - { - if (next_instrs_are_b_retw (fragP)) - { - if (fragP->tc_frag_data.is_no_transform) - as_bad (_("instruction sequence (write a0, branch, retw) may trigger hardware errata")); - else - relax_frag_add_nop (fragP); - } - frag_wane (fragP); - } - } - } + /* Walk over all of the fragments in a subsection. */ + for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) + { + if (fragP->fr_type == rs_machine_dependent + && fragP->fr_subtype == RELAX_ADD_NOP_IF_A0_B_RETW) + { + if (next_instrs_are_b_retw (fragP)) + { + if (fragP->tc_frag_data.is_no_transform) + as_bad (_("instruction sequence (write a0, branch, retw) may trigger hardware errata")); + else + relax_frag_add_nop (fragP); + } + frag_wane (fragP); + } + } + } } @@ -7285,30 +7295,32 @@ static void xtensa_fix_b_j_loop_end_frags (void) { frchainS *frchP; + asection *s; /* When this routine is called, all of the subsections are still intact so we walk over subsections instead of sections. */ - for (frchP = frchain_root; frchP; frchP = frchP->frch_next) - { - fragS *fragP; + for (s = stdoutput->sections; s; s = s->next) + for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next) + { + fragS *fragP; - /* Walk over all of the fragments in a subsection. */ - for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) - { - if (fragP->fr_type == rs_machine_dependent - && fragP->fr_subtype == RELAX_ADD_NOP_IF_PRE_LOOP_END) - { - if (next_instr_is_loop_end (fragP)) - { - if (fragP->tc_frag_data.is_no_transform) - as_bad (_("branching or jumping to a loop end may trigger hardware errata")); - else - relax_frag_add_nop (fragP); - } - frag_wane (fragP); - } - } - } + /* Walk over all of the fragments in a subsection. */ + for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) + { + if (fragP->fr_type == rs_machine_dependent + && fragP->fr_subtype == RELAX_ADD_NOP_IF_PRE_LOOP_END) + { + if (next_instr_is_loop_end (fragP)) + { + if (fragP->tc_frag_data.is_no_transform) + as_bad (_("branching or jumping to a loop end may trigger hardware errata")); + else + relax_frag_add_nop (fragP); + } + frag_wane (fragP); + } + } + } } @@ -7349,66 +7361,68 @@ static void xtensa_fix_close_loop_end_frags (void) { frchainS *frchP; + asection *s; /* When this routine is called, all of the subsections are still intact so we walk over subsections instead of sections. */ - for (frchP = frchain_root; frchP; frchP = frchP->frch_next) - { - fragS *fragP; + for (s = stdoutput->sections; s; s = s->next) + for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next) + { + fragS *fragP; - fragS *current_target = NULL; + fragS *current_target = NULL; - /* Walk over all of the fragments in a subsection. */ - for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) - { - if (fragP->fr_type == rs_machine_dependent - && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE) - || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))) + /* Walk over all of the fragments in a subsection. */ + for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) + { + if (fragP->fr_type == rs_machine_dependent + && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE) + || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))) current_target = symbol_get_frag (fragP->fr_symbol); - if (current_target - && fragP->fr_type == rs_machine_dependent - && fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END) - { - offsetT min_bytes; - int bytes_added = 0; + if (current_target + && fragP->fr_type == rs_machine_dependent + && fragP->fr_subtype == RELAX_ADD_NOP_IF_CLOSE_LOOP_END) + { + offsetT min_bytes; + int bytes_added = 0; #define REQUIRED_LOOP_DIVIDING_BYTES 12 - /* Max out at 12. */ - min_bytes = min_bytes_to_other_loop_end - (fragP->fr_next, current_target, REQUIRED_LOOP_DIVIDING_BYTES); - - if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES) - { - if (fragP->tc_frag_data.is_no_transform) - as_bad (_("loop end too close to another loop end may trigger hardware errata")); - else - { - while (min_bytes + bytes_added - < REQUIRED_LOOP_DIVIDING_BYTES) - { - int length = 3; - - if (fragP->fr_var < length) - as_fatal (_("fr_var %lu < length %d"), - (long) fragP->fr_var, length); - else - { - assemble_nop (length, - fragP->fr_literal + fragP->fr_fix); - fragP->fr_fix += length; - fragP->fr_var -= length; - } - bytes_added += length; - } - } - } - frag_wane (fragP); - } - assert (fragP->fr_type != rs_machine_dependent - || fragP->fr_subtype != RELAX_ADD_NOP_IF_CLOSE_LOOP_END); - } - } + /* Max out at 12. */ + min_bytes = min_bytes_to_other_loop_end + (fragP->fr_next, current_target, REQUIRED_LOOP_DIVIDING_BYTES); + + if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES) + { + if (fragP->tc_frag_data.is_no_transform) + as_bad (_("loop end too close to another loop end may trigger hardware errata")); + else + { + while (min_bytes + bytes_added + < REQUIRED_LOOP_DIVIDING_BYTES) + { + int length = 3; + + if (fragP->fr_var < length) + as_fatal (_("fr_var %lu < length %d"), + (long) fragP->fr_var, length); + else + { + assemble_nop (length, + fragP->fr_literal + fragP->fr_fix); + fragP->fr_fix += length; + fragP->fr_var -= length; + } + bytes_added += length; + } + } + } + frag_wane (fragP); + } + assert (fragP->fr_type != rs_machine_dependent + || fragP->fr_subtype != RELAX_ADD_NOP_IF_CLOSE_LOOP_END); + } + } } @@ -7512,49 +7526,51 @@ static void xtensa_fix_short_loop_frags (void) { frchainS *frchP; + asection *s; /* When this routine is called, all of the subsections are still intact so we walk over subsections instead of sections. */ - for (frchP = frchain_root; frchP; frchP = frchP->frch_next) - { - fragS *fragP; - fragS *current_target = NULL; - xtensa_opcode current_opcode = XTENSA_UNDEFINED; + for (s = stdoutput->sections; s; s = s->next) + for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next) + { + fragS *fragP; + fragS *current_target = NULL; + xtensa_opcode current_opcode = XTENSA_UNDEFINED; - /* Walk over all of the fragments in a subsection. */ - for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) - { - if (fragP->fr_type == rs_machine_dependent - && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE) - || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))) - { - TInsn t_insn; - fragS *loop_frag = next_non_empty_frag (fragP); - tinsn_from_chars (&t_insn, loop_frag->fr_opcode, 0); - current_target = symbol_get_frag (fragP->fr_symbol); - current_opcode = t_insn.opcode; - assert (xtensa_opcode_is_loop (xtensa_default_isa, - current_opcode)); - } + /* Walk over all of the fragments in a subsection. */ + for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) + { + if (fragP->fr_type == rs_machine_dependent + && ((fragP->fr_subtype == RELAX_ALIGN_NEXT_OPCODE) + || (fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))) + { + TInsn t_insn; + fragS *loop_frag = next_non_empty_frag (fragP); + tinsn_from_chars (&t_insn, loop_frag->fr_opcode, 0); + current_target = symbol_get_frag (fragP->fr_symbol); + current_opcode = t_insn.opcode; + assert (xtensa_opcode_is_loop (xtensa_default_isa, + current_opcode)); + } - if (fragP->fr_type == rs_machine_dependent - && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP) - { - if (count_insns_to_loop_end (fragP->fr_next, TRUE, 3) < 3 - && (branch_before_loop_end (fragP->fr_next) - || (workaround_all_short_loops - && current_opcode != XTENSA_UNDEFINED - && current_opcode != xtensa_loop_opcode))) - { - if (fragP->tc_frag_data.is_no_transform) - as_bad (_("loop containing less than three instructions may trigger hardware errata")); - else - relax_frag_add_nop (fragP); - } - frag_wane (fragP); - } - } - } + if (fragP->fr_type == rs_machine_dependent + && fragP->fr_subtype == RELAX_ADD_NOP_IF_SHORT_LOOP) + { + if (count_insns_to_loop_end (fragP->fr_next, TRUE, 3) < 3 + && (branch_before_loop_end (fragP->fr_next) + || (workaround_all_short_loops + && current_opcode != XTENSA_UNDEFINED + && current_opcode != xtensa_loop_opcode))) + { + if (fragP->tc_frag_data.is_no_transform) + as_bad (_("loop containing less than three instructions may trigger hardware errata")); + else + relax_frag_add_nop (fragP); + } + frag_wane (fragP); + } + } + } } @@ -7697,50 +7713,51 @@ xtensa_sanity_check (void) { char *file_name; unsigned line; - frchainS *frchP; + asection *s; as_where (&file_name, &line); - for (frchP = frchain_root; frchP; frchP = frchP->frch_next) - { - fragS *fragP; - - /* Walk over all of the fragments in a subsection. */ - for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) - { - /* Currently we only check for empty loops here. */ - if (fragP->fr_type == rs_machine_dependent - && fragP->fr_subtype == RELAX_IMMED) - { - static xtensa_insnbuf insnbuf = NULL; - TInsn t_insn; - - if (fragP->fr_opcode != NULL) - { - if (!insnbuf) - insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa); - tinsn_from_chars (&t_insn, fragP->fr_opcode, 0); - tinsn_immed_from_frag (&t_insn, fragP, 0); + for (s = stdoutput->sections; s; s = s->next) + for (frchP = seg_info (s)->frchainP; frchP; frchP = frchP->frch_next) + { + fragS *fragP; - if (xtensa_opcode_is_loop (xtensa_default_isa, - t_insn.opcode) == 1) - { - if (is_empty_loop (&t_insn, fragP)) - { - new_logical_line (fragP->fr_file, fragP->fr_line); - as_bad (_("invalid empty loop")); - } - if (!is_local_forward_loop (&t_insn, fragP)) - { - new_logical_line (fragP->fr_file, fragP->fr_line); - as_bad (_("loop target does not follow " - "loop instruction in section")); - } - } - } - } - } - } + /* Walk over all of the fragments in a subsection. */ + for (fragP = frchP->frch_root; fragP; fragP = fragP->fr_next) + { + /* Currently we only check for empty loops here. */ + if (fragP->fr_type == rs_machine_dependent + && fragP->fr_subtype == RELAX_IMMED) + { + static xtensa_insnbuf insnbuf = NULL; + TInsn t_insn; + + if (fragP->fr_opcode != NULL) + { + if (!insnbuf) + insnbuf = xtensa_insnbuf_alloc (xtensa_default_isa); + tinsn_from_chars (&t_insn, fragP->fr_opcode, 0); + tinsn_immed_from_frag (&t_insn, fragP, 0); + + if (xtensa_opcode_is_loop (xtensa_default_isa, + t_insn.opcode) == 1) + { + if (is_empty_loop (&t_insn, fragP)) + { + new_logical_line (fragP->fr_file, fragP->fr_line); + as_bad (_("invalid empty loop")); + } + if (!is_local_forward_loop (&t_insn, fragP)) + { + new_logical_line (fragP->fr_file, fragP->fr_line); + as_bad (_("loop target does not follow " + "loop instruction in section")); + } + } + } + } + } + } new_logical_line (file_name, line); } @@ -10384,7 +10401,6 @@ retrieve_segment_info (segT seg) frchainP->frch_root = NULL; frchainP->frch_last = NULL; frchainP->frch_next = NULL; - frchainP->frch_seg = seg; frchainP->frch_subseg = 0; frchainP->fix_root = NULL; frchainP->fix_tail = NULL; diff --git a/gas/debug.c b/gas/debug.c index fe2ed8c..3218fff 100644 --- a/gas/debug.c +++ b/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) diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index 16666fa..661962f 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -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; diff --git a/gas/subsegs.c b/gas/subsegs.c index c81c09a..e77bce8 100644 --- a/gas/subsegs.c +++ b/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; - } - - assert (frchain_now == 0 - || now_seg == undefined_section - || frchain_now->frch_last == frag_now); + seginfo = seg_info (seg); - /* - * Attempt to find or make a frchain for that sub seg. - * Crawl along chain of frchainSs, begins @ frchain_root. - * If we need to make a frchainS, link it into correct - * position of chain rooted in frchain_root. - */ - for (frcP = *(lastPP = &frchain_root); - frcP && frcP->frch_seg <= seg; + /* Attempt to find or make a frchain for that subsection. + We keep the list sorted by subsection number. */ + for (frcP = *(lastPP = &seginfo->frchainP); + frcP != NULL; frcP = *(lastPP = &frcP->frch_next)) + if (frcP->frch_subseg >= subseg) + break; + + if (frcP == NULL || frcP->frch_subseg != subseg) { - if (frcP->frch_seg == seg - && frcP->frch_subseg >= subseg) - { - break; - } - } - /* - * frcP: Address of the 1st frchainS in correct segment with - * frch_subseg >= subseg. - * We want to either use this frchainS, or we want - * to insert a new frchainS just before it. - * - * If frcP==NULL, then we are at the end of the chain - * of frchainS-s. A NULL frcP means we fell off the end - * of the chain looking for a - * frch_subseg >= subseg, so we - * must make a new frchainS. - * - * If we ever maintain a pointer to - * the last frchainS in the chain, we change that pointer - * ONLY when frcP==NULL. - * - * lastPP: Address of the pointer with value frcP; - * Never NULL. - * May point to frchain_root. - * - */ - if (!frcP - || (frcP->frch_seg > seg - || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */ - { - /* - * This should be the only code that creates a frchainS. - */ - segment_info_type *seginfo; + /* This should be the only code that creates a frchainS. */ newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS)); newP->frch_subseg = subseg; - newP->frch_seg = seg; newP->fix_root = NULL; newP->fix_tail = NULL; obstack_begin (&newP->frch_obstack, chunksize); @@ -191,17 +121,10 @@ subseg_set_rest (segT seg, subsegT subseg) newP->frch_root = newP->frch_last = newP->frch_frag_now; *lastPP = newP; - newP->frch_next = frcP; /* perhaps NULL */ - - seginfo = seg_info (seg); - if (seginfo && (!seginfo->frchainP || seginfo->frchainP == frcP)) - seginfo->frchainP = newP; - + newP->frch_next = frcP; frcP = newP; } - /* - * Here with frcP pointing to the frchainS for subseg. - */ + frchain_now = frcP; frag_now = frcP->frch_frag_now; @@ -221,7 +144,6 @@ subseg_set_rest (segT seg, subsegT subseg) * Out: now_subseg, now_seg updated. * Frchain_now points to the (possibly new) struct frchain for this * sub-segment. - * Frchain_root updated if needed. */ segT @@ -247,21 +169,13 @@ subseg_get (const char *segname, int force_new) seginfo = seg_info (secptr); if (! seginfo) { - /* Check whether output_section is set first because secptr may - be bfd_abs_section_ptr. */ - if (secptr->output_section != secptr) - secptr->output_section = secptr; + secptr->output_section = secptr; seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo)); memset ((PTR) seginfo, 0, sizeof (*seginfo)); seginfo->fix_root = NULL; seginfo->fix_tail = NULL; seginfo->bfd_section = secptr; - if (secptr == bfd_abs_section_ptr) - abs_seg_info = seginfo; - else if (secptr == bfd_und_section_ptr) - und_seg_info = seginfo; - else - bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo); + bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo); seginfo->frchainP = NULL; seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL; seginfo->sym = NULL; @@ -274,13 +188,9 @@ segT subseg_new (const char *segname, subsegT subseg) { segT secptr; - segment_info_type *seginfo; secptr = subseg_get (segname, 0); subseg_set_rest (secptr, subseg); - seginfo = seg_info (secptr); - if (! seginfo->frchainP) - seginfo->frchainP = frchain_now; return secptr; } @@ -290,13 +200,9 @@ segT subseg_force_new (const char *segname, subsegT subseg) { segT secptr; - segment_info_type *seginfo; secptr = subseg_get (segname, 1); subseg_set_rest (secptr, subseg); - seginfo = seg_info (secptr); - if (! seginfo->frchainP) - seginfo->frchainP = frchain_now; return secptr; } @@ -312,19 +218,6 @@ subseg_set (segT secptr, subsegT subseg) #define obj_sec_sym_ok_for_reloc(SEC) 0 #endif -/* Get the gas information we are storing for a section. */ - -segment_info_type * -seg_info (segT sec) -{ - if (sec == bfd_abs_section_ptr) - return abs_seg_info; - else if (sec == bfd_und_section_ptr) - return und_seg_info; - else - return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec); -} - symbolS * section_symbol (segT sec) { @@ -414,28 +307,33 @@ void subsegs_print_statistics (FILE *file) { frchainS *frchp; + asection *s; + fprintf (file, "frag chains:\n"); - for (frchp = frchain_root; frchp; frchp = frchp->frch_next) + for (s = stdoutput->sections; s; s = s->next) { - int count = 0; - fragS *fragp; + segment_info_type *seginfo; - /* If frch_subseg is non-zero, it's probably been chained onto - the end of a previous subsection. Don't count it again. */ - if (frchp->frch_subseg != 0) + /* Skip gas-internal sections. */ + if (segment_name (s)[0] == '*') continue; - /* Skip gas-internal sections. */ - if (segment_name (frchp->frch_seg)[0] == '*') + seginfo = seg_info (s); + if (!seginfo) continue; - for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next) + for (frchp = seginfo->frchainP; frchp; frchp = frchp->frch_next) { - count++; + int count = 0; + fragS *fragp; + + for (fragp = frchp->frch_root; fragp; fragp = fragp->fr_next) + count++; + + fprintf (file, "\n"); + fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp, + segment_name (s), count); } - fprintf (file, "\n"); - fprintf (file, "\t%p %-10s\t%10d frags\n", (void *) frchp, - segment_name (frchp->frch_seg), count); } } diff --git a/gas/subsegs.h b/gas/subsegs.h index 23ab4f9..f950285 100644 --- a/gas/subsegs.h +++ b/gas/subsegs.h @@ -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 *); diff --git a/gas/write.c b/gas/write.c index 5c336d8..93b157f 100644 --- a/gas/write.c +++ b/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) - { - unsigned int entsize = now_seg->entsize; - int entalign = 0; + int alignment = 0; + + subseg_set (s, frchainP->frch_subseg); - while ((entsize & 1) == 0) + /* This now gets called even if we had errors. In that case, + any alignment is meaningless, and, moreover, will look weird + if we are generating a listing. */ + if (!had_errors ()) + { + alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP); + if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE) + && now_seg->entsize) { - ++entalign; - entsize >>= 1; + unsigned int entsize = now_seg->entsize; + int entalign = 0; + + while ((entsize & 1) == 0) + { + ++entalign; + entsize >>= 1; + } + if (entalign > alignment) + alignment = entalign; } - if (entalign > alignment) - alignment = entalign; } - } - if (subseg_text_p (now_seg)) - frag_align_code (alignment, 0); - else - frag_align (alignment, 0, 0); + if (subseg_text_p (now_seg)) + frag_align_code (alignment, 0); + else + frag_align (alignment, 0, 0); - /* frag_align will have left a new frag. - Use this last frag for an empty ".fill". + /* frag_align will have left a new frag. + Use this last frag for an empty ".fill". - For this segment ... - Create a last frag. Do not leave a "being filled in frag". */ - frag_wane (frag_now); - frag_now->fr_fix = 0; - know (frag_now->fr_next == NULL); + For this segment ... + Create a last frag. Do not leave a "being filled in frag". */ + frag_wane (frag_now); + frag_now->fr_fix = 0; + know (frag_now->fr_next == NULL); + } } } -- 2.7.4