From def13efb269ed312576e3c5022e3ab7eb7bd4899 Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Tue, 11 Dec 2007 21:52:39 +0000 Subject: [PATCH] * config/tc-xtensa.c (frag_format_size): Handle frags that expand to wide branches. (get_aligned_diff): For RELAX_ALIGN_NEXT_OPCODE, skip to the next non-empty frag to find the LOOP instruction. Change comma typo to a semicolon. (relax_frag_immed, convert_frag_immed): Rename wide_insn variable to from_widen_insn. --- gas/ChangeLog | 11 +++++++++++ gas/config/tc-xtensa.c | 51 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 33b0341..8b6c8cd 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,14 @@ +2007-12-11 Sterling Augustine + Bob Wilson + + * config/tc-xtensa.c (frag_format_size): Handle frags that expand to + wide branches. + (get_aligned_diff): For RELAX_ALIGN_NEXT_OPCODE, skip to the next + non-empty frag to find the LOOP instruction. Change comma typo to + a semicolon. + (relax_frag_immed, convert_frag_immed): Rename wide_insn variable to + from_widen_insn. + 2007-12-11 Alan Modra * config/tc-m32r.c (md_begin): Mark .sbss as being bss style section. diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index 5599a1d..699eb7c 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -4424,7 +4424,26 @@ frag_format_size (const fragS *fragP) if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP1 || fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP2 || fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP3) - return 3; + { + /* For most frags at RELAX_IMMED_STEPX, with X > 0, the first + instruction in the relaxed version is of length 3. (The case + where we have to pull the instruction out of a FLIX bundle + is handled conservatively above.) However, frags with opcodes + that are expanding to wide branches end up having formats that + are not determinable by the RELAX_IMMED_STEPX enumeration, and + we can't tell directly what format the relaxer picked. This + is a wart in the design of the relaxer that should someday be + fixed, but would require major changes, or at least should + be accompanied by major changes to make use of that data. + + In any event, we can tell that we are expanding from a single-slot + three-byte format to a wider one with the logic below. */ + + if (fmt_size <= 3 && fragP->tc_frag_data.text_expansion[0] != 3) + return 3 + fragP->tc_frag_data.text_expansion[0]; + else + return 3; + } if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW) return 2 + fragP->tc_frag_data.text_expansion[0]; @@ -8259,6 +8278,7 @@ get_aligned_diff (fragS *fragP, addressT address, offsetT *max_diff) int align_power; offsetT opt_diff; offsetT branch_align; + fragS *loop_frag; assert (fragP->fr_type == rs_machine_dependent); switch (fragP->fr_subtype) @@ -8281,15 +8301,19 @@ get_aligned_diff (fragS *fragP, addressT address, offsetT *max_diff) return opt_diff; case RELAX_ALIGN_NEXT_OPCODE: - target_size = get_loop_align_size (next_frag_format_size (fragP)); + /* The next non-empty frag after this one holds the LOOP instruction + that needs to be aligned. The required alignment depends on the + size of the next non-empty frag after the loop frag, i.e., the + first instruction in the loop. */ + loop_frag = next_non_empty_frag (fragP); + target_size = get_loop_align_size (next_frag_format_size (loop_frag)); loop_insn_offset = 0; is_loop = next_frag_opcode_is_loop (fragP, &loop_opcode); assert (is_loop); /* If the loop has been expanded then the LOOP instruction could be at an offset from this fragment. */ - if (next_non_empty_frag(fragP)->tc_frag_data.slot_subtypes[0] - != RELAX_IMMED) + if (loop_frag->tc_frag_data.slot_subtypes[0] != RELAX_IMMED) loop_insn_offset = get_expanded_loop_offset (loop_opcode); /* In an ideal world, which is what we are shooting for here, @@ -8298,7 +8322,7 @@ get_aligned_diff (fragS *fragP, addressT address, offsetT *max_diff) will call get_noop_aligned_address. */ target_address = address + loop_insn_offset + xg_get_single_size (loop_opcode); - align_power = get_text_align_power (target_size), + align_power = get_text_align_power (target_size); opt_diff = get_text_align_fill_size (target_address, align_power, target_size, FALSE, FALSE); @@ -8949,7 +8973,7 @@ relax_frag_immed (segT segP, int old_size; bfd_boolean negatable_branch = FALSE; bfd_boolean branch_jmp_to_next = FALSE; - bfd_boolean wide_insn = FALSE; + bfd_boolean from_wide_insn = FALSE; xtensa_isa isa = xtensa_default_isa; IStack istack; offsetT frag_offset; @@ -8963,7 +8987,7 @@ relax_frag_immed (segT segP, xg_clear_vinsn (&cur_vinsn); vinsn_from_chars (&cur_vinsn, fragP->fr_opcode); if (cur_vinsn.num_slots > 1) - wide_insn = TRUE; + from_wide_insn = TRUE; tinsn = cur_vinsn.slots[slot]; tinsn_immed_from_frag (&tinsn, fragP, slot); @@ -9017,13 +9041,16 @@ relax_frag_immed (segT segP, first = 0; while (istack.insn[first].opcode == XTENSA_UNDEFINED) first++; + num_text_bytes = get_num_stack_text_bytes (&istack); - if (wide_insn) + + if (from_wide_insn) { num_text_bytes += old_size; if (opcode_fits_format_slot (istack.insn[first].opcode, fmt, slot)) num_text_bytes -= xg_get_single_size (istack.insn[first].opcode); } + total_text_diff = num_text_bytes - old_size; this_text_diff = total_text_diff - fragP->tc_frag_data.text_expansion[slot]; @@ -9316,7 +9343,7 @@ convert_frag_immed (segT segP, bfd_boolean branch_jmp_to_next = FALSE; char *fr_opcode = fragP->fr_opcode; xtensa_isa isa = xtensa_default_isa; - bfd_boolean wide_insn = FALSE; + bfd_boolean from_wide_insn = FALSE; int bytes; bfd_boolean is_loop; @@ -9326,7 +9353,7 @@ convert_frag_immed (segT segP, vinsn_from_chars (&cur_vinsn, fr_opcode); if (cur_vinsn.num_slots > 1) - wide_insn = TRUE; + from_wide_insn = TRUE; orig_tinsn = cur_vinsn.slots[slot]; tinsn_immed_from_frag (&orig_tinsn, fragP, slot); @@ -9434,7 +9461,7 @@ convert_frag_immed (segT segP, break; case ITYPE_INSN: - if (first && wide_insn) + if (first && from_wide_insn) { target_offset += xtensa_format_length (isa, fmt); first = FALSE; @@ -9480,7 +9507,7 @@ convert_frag_immed (segT segP, case ITYPE_INSN: xg_resolve_labels (tinsn, gen_label); xg_resolve_literals (tinsn, lit_sym); - if (wide_insn && first) + if (from_wide_insn && first) { first = FALSE; if (opcode_fits_format_slot (tinsn->opcode, fmt, slot)) -- 2.7.4