diff options
author | Bob Wilson <bob.wilson@acm.org> | 2007-06-22 18:44:50 +0000 |
---|---|---|
committer | Bob Wilson <bob.wilson@acm.org> | 2007-06-22 18:44:50 +0000 |
commit | b81bf389ecc8103ffe23da2f1abbbdda608c132e (patch) | |
tree | f8ad98caf2571dd9d07b560d8cba60395659835c /gas/config/tc-xtensa.c | |
parent | 184d813c13d958ec971c07a5db3145fd8ca0d404 (diff) | |
download | binutils-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.c | 42 |
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, |