diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2017-11-13 00:42:43 -0800 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2017-11-27 15:14:48 -0800 |
commit | 76a493ab99d9276180db6e791f95d1d6d86d2954 (patch) | |
tree | 87a026ec0dfcf483c671287b36abaa842ba4b6af /gas/config | |
parent | fe6c2f1b6409867a03dd32214679dd825f74ec48 (diff) | |
download | gdb-76a493ab99d9276180db6e791f95d1d6d86d2954.zip gdb-76a493ab99d9276180db6e791f95d1d6d86d2954.tar.gz gdb-76a493ab99d9276180db6e791f95d1d6d86d2954.tar.bz2 |
gas: xtensa: reuse trampoline placement code
There's almost exact copy of the trampoline placement code in the
search_trampolines function that is used for jumps generated for relaxed
branch instructions. Get rid of the duplication and reuse
xg_find_best_trampoline function for that.
gas/
2017-11-27 Max Filippov <jcmvbkbc@gmail.com>
* config/tc-xtensa.c (search_trampolines, get_best_trampoline):
Remove definitions.
(xg_find_best_trampoline_for_tinsn): New function.
(relax_frag_immed): Replace call to get_best_trampoline with a
call to xg_find_best_trampoline_for_tinsn.
* testsuite/gas/xtensa/trampoline.d: Adjust absolute addresses
as the placement of trampolines for relaxed branches has been
changed.
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-xtensa.c | 97 |
1 files changed, 9 insertions, 88 deletions
diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index 7d8b62b..b507d44 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -9806,99 +9806,20 @@ bytes_to_stretch (fragS *this_frag, static fragS * -search_trampolines (TInsn *tinsn, fragS *fragP, bfd_boolean unreachable_only) +xg_find_best_trampoline_for_tinsn (TInsn *tinsn, fragS *fragP) { + symbolS *sym = tinsn->tok[0].X_add_symbol; + addressT source = fragP->fr_address; + addressT target = S_GET_VALUE (sym) + tinsn->tok[0].X_add_number; struct trampoline_seg *ts = find_trampoline_seg (now_seg); - fragS *tf = NULL; size_t i; - fragS *best_tf = NULL; - offsetT best_delta = 0; - offsetT best_addr = 0; - symbolS *sym = tinsn->tok[0].X_add_symbol; - offsetT target = S_GET_VALUE (sym) + tinsn->tok[0].X_add_number; - offsetT addr = fragP->fr_address; - offsetT lower = (addr < target) ? addr : target; - offsetT upper = (addr > target) ? addr : target; - offsetT delta = upper - lower; - offsetT midpoint = lower + delta / 2; - offsetT this_delta = -1; - offsetT this_addr = -1; - - if (!ts) - return NULL; - - if (delta > 2 * J_RANGE) - { - /* One trampoline won't do; we need multiple. - Choose the farthest trampoline that's still in range of the original - and let a later pass finish the job. */ - for (i = 0; i < ts->index.n_entries; ++i) - { - tf = ts->index.entry[i]; - this_addr = tf->fr_address + tf->fr_fix; - if (upper == addr) - { - /* Backward jump. */ - if (addr - this_addr < J_RANGE) - break; - } - else if (i + 1 < ts->index.n_entries) - { - /* Forward jump. */ - fragS *next = ts->index.entry[i + 1]; - offsetT next_addr = next->fr_address + next->fr_fix; - - if (next_addr - addr > J_RANGE) - break; - } - else - { - break; - } - } - if (i < ts->index.n_entries && - labs (addr - this_addr) < J_RANGE) - return tf; - - return NULL; - } - - for (i = 0; i < ts->index.n_entries; ++i) - { - tf = ts->index.entry[i]; - this_addr = tf->fr_address + tf->fr_fix; - this_delta = labs (this_addr - midpoint); - if (unreachable_only && tf->tc_frag_data.needs_jump_around) - continue; - if (!best_tf || this_delta < best_delta) - { - best_tf = tf; - best_delta = this_delta; - best_addr = this_addr; - } - } - - if (best_tf && - best_delta < J_RANGE && - labs(best_addr - lower) < J_RANGE && - labs(best_addr - upper) < J_RANGE) - return best_tf; - - return NULL; /* No suitable trampoline found. */ -} - -static fragS * -get_best_trampoline (TInsn *tinsn, fragS *fragP) -{ - fragS *tf = NULL; - - tf = search_trampolines (tinsn, fragP, TRUE); /* Try unreachable first. */ + if (!ts || !ts->index.n_entries) + return NULL; - if (tf == NULL) - tf = search_trampolines (tinsn, fragP, FALSE); /* Try ones needing a jump-around, too. */ + i = xg_find_best_trampoline (&ts->index, source, target); - return tf; + return ts->index.entry[i]; } @@ -10154,7 +10075,7 @@ relax_frag_immed (segT segP, if (!xg_symbolic_immeds_fit (jinsn, segP, fragP, fragP->fr_offset, total_text_diff)) { - fragS *tf = get_best_trampoline (jinsn, fragP); + fragS *tf = xg_find_best_trampoline_for_tinsn (jinsn, fragP); if (tf) { |