aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorSterling Augustine <saugustine@google.com>2010-02-09 19:36:50 +0000
committerSterling Augustine <saugustine@google.com>2010-02-09 19:36:50 +0000
commit3a1e9c4a2d2ad390c012cc593da777ceee36b391 (patch)
tree667e8d8b72b524fef6e6a3d03316961f0c57efc6 /gas/config
parent075b51b7790dbf939b30a9e11b246f25bda9c201 (diff)
downloadfsf-binutils-gdb-3a1e9c4a2d2ad390c012cc593da777ceee36b391.zip
fsf-binutils-gdb-3a1e9c4a2d2ad390c012cc593da777ceee36b391.tar.gz
fsf-binutils-gdb-3a1e9c4a2d2ad390c012cc593da777ceee36b391.tar.bz2
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.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-xtensa.c39
1 files changed, 36 insertions, 3 deletions
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. */