aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@acm.org>2006-03-21 20:34:38 +0000
committerBob Wilson <bob.wilson@acm.org>2006-03-21 20:34:38 +0000
commit03aaa5932ec1a285ed94ddd86a5af380a3abeff9 (patch)
treeaaf68687e3fbb18a3955f5510e0ffe5c8dd9619c /gas
parenta75b402ae4e4366cb70f319451c6e0e2026a0105 (diff)
downloadbinutils-03aaa5932ec1a285ed94ddd86a5af380a3abeff9.zip
binutils-03aaa5932ec1a285ed94ddd86a5af380a3abeff9.tar.gz
binutils-03aaa5932ec1a285ed94ddd86a5af380a3abeff9.tar.bz2
* config/tc-xtensa.c (enforce_three_byte_loop_align): New flag.
(xtensa_setup_hw_workarounds): Set this new flag for older hardware. (get_loop_align_size): New. (xtensa_end): Skip xtensa_mark_narrow_branches when not aligning. (xtensa_mark_zcl_first_insns): Prevent widening of first loop frag. (get_text_align_power): Rewrite to handle inputs in the range 2-8. (get_noop_aligned_address): Use get_loop_align_size. (get_aligned_diff): Likewise.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog11
-rw-r--r--gas/config/tc-xtensa.c76
2 files changed, 62 insertions, 25 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 5d39cb6..a70bb80 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,14 @@
+2006-03-21 Sterling Augustine <sterling@tensilica.com>
+
+ * config/tc-xtensa.c (enforce_three_byte_loop_align): New flag.
+ (xtensa_setup_hw_workarounds): Set this new flag for older hardware.
+ (get_loop_align_size): New.
+ (xtensa_end): Skip xtensa_mark_narrow_branches when not aligning.
+ (xtensa_mark_zcl_first_insns): Prevent widening of first loop frag.
+ (get_text_align_power): Rewrite to handle inputs in the range 2-8.
+ (get_noop_aligned_address): Use get_loop_align_size.
+ (get_aligned_diff): Likewise.
+
2006-03-21 Paul Brook <paul@codesourcery.com>
* config/tc-arm.c (insns): Correct opcodes for ldrbt and strbt.
diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
index 5a7f202..fd34e4b 100644
--- a/gas/config/tc-xtensa.c
+++ b/gas/config/tc-xtensa.c
@@ -566,6 +566,7 @@ static bfd_boolean workaround_short_loop = FALSE;
static bfd_boolean maybe_has_short_loop = FALSE;
static bfd_boolean workaround_close_loop_end = FALSE;
static bfd_boolean maybe_has_close_loop_end = FALSE;
+static bfd_boolean enforce_three_byte_loop_align = FALSE;
/* When workaround_short_loops is TRUE, all loops with early exits must
have at least 3 instructions. workaround_all_short_loops is a modifier
@@ -590,6 +591,7 @@ xtensa_setup_hw_workarounds (int earliest, int latest)
workaround_short_loop |= TRUE;
workaround_close_loop_end |= TRUE;
workaround_all_short_loops |= TRUE;
+ enforce_three_byte_loop_align = TRUE;
}
}
@@ -4430,6 +4432,26 @@ next_frag_format_size (const fragS *fragP)
}
+/* In early Xtensa Processors, for reasons that are unclear, the ISA
+ required two-byte instructions to be treated as three-byte instructions
+ for loop instruction alignment. This restriction was removed beginning
+ with Xtensa LX. Now the only requirement on loop instruction alignment
+ is that the first instruction of the loop must appear at an address that
+ does not cross a fetch boundary. */
+
+static int
+get_loop_align_size (int insn_size)
+{
+ if (insn_size == XTENSA_UNDEFINED)
+ return xtensa_fetch_width;
+
+ if (enforce_three_byte_loop_align && insn_size == 2)
+ return 3;
+
+ return insn_size;
+}
+
+
/* If the next legit fragment is an end-of-loop marker,
switch its state so it will instantiate a NOP. */
@@ -6918,7 +6940,8 @@ xtensa_end (void)
if (workaround_short_loop && maybe_has_short_loop)
xtensa_fix_short_loop_frags ();
- xtensa_mark_narrow_branches ();
+ if (align_targets)
+ xtensa_mark_narrow_branches ();
xtensa_mark_zcl_first_insns ();
xtensa_sanity_check ();
@@ -7113,7 +7136,24 @@ xtensa_mark_zcl_first_insns (void)
/* 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;
+ {
+ 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);
}
@@ -7835,16 +7875,10 @@ is_local_forward_loop (const TInsn *insn, fragS *fragP)
static int
get_text_align_power (unsigned target_size)
{
- int i = 0;
- unsigned power = 1;
-
- assert (target_size <= INT_MAX);
- while (target_size > power)
- {
- power <<= 1;
- i += 1;
- }
- return i;
+ if (target_size <= 4)
+ return 2;
+ assert (target_size == 8);
+ return 3;
}
@@ -8038,14 +8072,9 @@ get_noop_aligned_address (fragS *fragP, addressT address)
instruction following the loop, not the LOOP instruction. */
if (first_insn == NULL)
- return address;
-
- assert (first_insn->tc_frag_data.is_first_loop_insn);
-
- first_insn_size = frag_format_size (first_insn);
-
- if (first_insn_size == 2 || first_insn_size == XTENSA_UNDEFINED)
- first_insn_size = 3; /* ISA specifies this */
+ first_insn_size = xtensa_fetch_width;
+ else
+ first_insn_size = get_loop_align_size (frag_format_size (first_insn));
/* If it was 8, then we'll need a larger alignment for the section. */
align_power = get_text_align_power (first_insn_size);
@@ -8108,7 +8137,7 @@ get_aligned_diff (fragS *fragP, addressT address, offsetT *max_diff)
return opt_diff;
case RELAX_ALIGN_NEXT_OPCODE:
- target_size = next_frag_format_size (fragP);
+ target_size = get_loop_align_size (next_frag_format_size (fragP));
loop_insn_offset = 0;
is_loop = next_frag_opcode_is_loop (fragP, &loop_opcode);
assert (is_loop);
@@ -8119,9 +8148,6 @@ get_aligned_diff (fragS *fragP, addressT address, offsetT *max_diff)
!= RELAX_IMMED)
loop_insn_offset = get_expanded_loop_offset (loop_opcode);
- if (target_size == 2)
- target_size = 3; /* ISA specifies this */
-
/* In an ideal world, which is what we are shooting for here,
we wouldn't need to use any NOPs immediately prior to the
LOOP instruction. If this approach fails, relax_frag_loop_align
@@ -8725,7 +8751,7 @@ bytes_to_stretch (fragS *this_frag,
/* We will need a NOP no matter what, but should we widen
this instruction to help?
- This is a RELAX_FRAG_NARROW frag. */
+ This is a RELAX_NARROW frag. */
switch (desired_diff)
{
case 1: