diff options
-rw-r--r-- | gas/ChangeLog | 6 | ||||
-rw-r--r-- | gas/config/tc-xtensa.c | 39 |
2 files changed, 42 insertions, 3 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 294cc0c..6e30f26 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,9 @@ +2010-02-09 Sterling Augustine <sterling@tensilica.com> + + * config/tc-xtensa.c (RELAXED_LOOP_INSN_BYTES): New. + (next_frag_pre_opcode_bytes): Use RELAXED_LOOP_INSN_BYTES. + (xtensa_mark_zcl_first_insns): Rewrite to handle corner case. + 2010-02-08 Christophe Lyon <christophe.lyon@st.com> * config/tc-arm.c (md_pcrel_from_section): Keep base to zero for diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index d56cecd..85a3fe7 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -4649,6 +4649,12 @@ next_frag_is_loop_target (const fragS *fragP) } +/* As specified in the relaxation table, when a loop instruction is + relaxed, there are 24 bytes between the loop instruction itself and + the first instruction in the loop. */ + +#define RELAXED_LOOP_INSN_BYTES 24 + static addressT next_frag_pre_opcode_bytes (const fragS *fragp) { @@ -4671,7 +4677,7 @@ next_frag_pre_opcode_bytes (const fragS *fragp) been relaxed. Note that we can assume that the LOOP instruction is in slot 0 because loops aren't bundleable. */ if (next_fragp->tc_frag_data.slot_subtypes[0] > RELAX_IMMED) - return get_expanded_loop_offset (next_opcode); + return get_expanded_loop_offset (next_opcode) + RELAXED_LOOP_INSN_BYTES; return 0; } @@ -7401,9 +7407,36 @@ xtensa_mark_zcl_first_insns (void) || fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE)) { /* Find the loop frag. */ - fragS *targ_frag = next_non_empty_frag (fragP); + fragS *loop_frag = next_non_empty_frag (fragP); /* Find the first insn frag. */ - targ_frag = next_non_empty_frag (targ_frag); + fragS *targ_frag = next_non_empty_frag (loop_frag); + + /* Handle a corner case that comes up in hardware + diagnostics. The original assembly looks like this: + + loop aX, LabelA + <empty_frag>--not found by next_non_empty_frag + loop aY, LabelB + + Depending on the start address, the assembler may or + may not change it to look something like this: + + loop aX, LabelA + nop--frag isn't empty anymore + loop aY, LabelB + + So set up to check the alignment of the nop if it + exists */ + while (loop_frag != targ_frag) + { + if (loop_frag->fr_type == rs_machine_dependent + && (loop_frag->fr_subtype == RELAX_ALIGN_NEXT_OPCODE + || loop_frag->fr_subtype + == RELAX_CHECK_ALIGN_NEXT_OPCODE)) + targ_frag = loop_frag; + else + loop_frag = loop_frag->fr_next; + } /* Of course, sometimes (mostly for toy test cases) a zero-cost loop instruction is the last in a section. */ |