aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-xtensa.c
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@acm.org>2007-06-22 18:44:50 +0000
committerBob Wilson <bob.wilson@acm.org>2007-06-22 18:44:50 +0000
commitb81bf389ecc8103ffe23da2f1abbbdda608c132e (patch)
treef8ad98caf2571dd9d07b560d8cba60395659835c /gas/config/tc-xtensa.c
parent184d813c13d958ec971c07a5db3145fd8ca0d404 (diff)
downloadbinutils-b81bf389ecc8103ffe23da2f1abbbdda608c132e.zip
binutils-b81bf389ecc8103ffe23da2f1abbbdda608c132e.tar.gz
binutils-b81bf389ecc8103ffe23da2f1abbbdda608c132e.tar.bz2
* config/tc-xtensa.c (xg_assembly_relax): Comment termination rules.
(frag_format_size): Handle RELAX_IMMED_STEP3. (xtensa_relax_frag, md_convert_frag): Likewise. * config/tc-xtensa.h (xtensa_relax_statesE): Add RELAX_IMMED_STEP3. (RELAX_IMMED_MAXSTEPS): Adjust. * config/xtensa-relax.c (widen_spec_list): Add transitions from wide branches to branch-over-jumps. (build_transition): Handle wide branches in transition patterns.
Diffstat (limited to 'gas/config/tc-xtensa.c')
-rw-r--r--gas/config/tc-xtensa.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
index 7011a17..aef6b65 100644
--- a/gas/config/tc-xtensa.c
+++ b/gas/config/tc-xtensa.c
@@ -3498,7 +3498,33 @@ xg_expand_to_stack (IStack *istack, TInsn *insn, int lateral_steps)
/* Relax the assembly instruction at least "min_steps".
- Return the number of steps taken. */
+ Return the number of steps taken.
+
+ For relaxation to correctly terminate, every relaxation chain must
+ terminate in one of two ways:
+
+ 1. If the chain from one instruction to the next consists entirely of
+ single instructions, then the chain *must* handle all possible
+ immediates without failing. It must not ever fail because an
+ immediate is out of range. The MOVI.N -> MOVI -> L32R relaxation
+ chain is one example. L32R loads 32 bits, and there cannot be an
+ immediate larger than 32 bits, so it satisfies this condition.
+ Single instruction relaxation chains are as defined by
+ xg_is_single_relaxable_instruction.
+
+ 2. Otherwise, the chain must end in a multi-instruction expansion: e.g.,
+ BNEZ.N -> BNEZ -> BNEZ.W15 -> BENZ.N/J
+
+ Strictly speaking, in most cases you can violate condition 1 and be OK
+ -- in particular when the last two instructions have the same single
+ size. But nevertheless, you should guarantee the above two conditions.
+
+ We could fix this so that single-instruction expansions correctly
+ terminate when they can't handle the range, but the error messages are
+ worse, and it actually turns out that in every case but one (18-bit wide
+ branches), you need a multi-instruction expansion to get the full range
+ anyway. And because 18-bit branches are handled identically to 15-bit
+ branches, there isn't any point in changing it. */
static int
xg_assembly_relax (IStack *istack,
@@ -3511,12 +3537,9 @@ xg_assembly_relax (IStack *istack,
{
int steps_taken = 0;
- /* assert (has no symbolic operands)
- Some of its immeds don't fit.
- Try to build a relaxed version.
- This may go through a couple of stages
- of single instruction transformations before
- we get there. */
+ /* Some of its immeds don't fit. Try to build a relaxed version.
+ This may go through a couple of stages of single instruction
+ transformations before we get there. */
TInsn single_target;
TInsn current_insn;
@@ -4384,7 +4407,8 @@ frag_format_size (const fragS *fragP)
/* If an instruction is about to grow, return the longer size. */
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_STEP2
+ || fragP->tc_frag_data.slot_subtypes[0] == RELAX_IMMED_STEP3)
return 3;
if (fragP->tc_frag_data.slot_subtypes[0] == RELAX_NARROW)
@@ -8324,6 +8348,7 @@ xtensa_relax_frag (fragS *fragP, long stretch, int *stretched_p)
case RELAX_IMMED:
case RELAX_IMMED_STEP1:
case RELAX_IMMED_STEP2:
+ case RELAX_IMMED_STEP3:
/* Place the immediate. */
new_stretch += relax_frag_immed
(now_seg, fragP, stretch,
@@ -9041,6 +9066,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragp)
case RELAX_IMMED:
case RELAX_IMMED_STEP1:
case RELAX_IMMED_STEP2:
+ case RELAX_IMMED_STEP3:
/* Place the immediate. */
convert_frag_immed
(sec, fragp,