summaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2017-11-13 00:42:43 -0800
committerMax Filippov <jcmvbkbc@gmail.com>2017-11-27 15:14:48 -0800
commit76a493ab99d9276180db6e791f95d1d6d86d2954 (patch)
tree87a026ec0dfcf483c671287b36abaa842ba4b6af /gas
parentfe6c2f1b6409867a03dd32214679dd825f74ec48 (diff)
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')
-rw-r--r--gas/ChangeLog11
-rw-r--r--gas/config/tc-xtensa.c97
-rw-r--r--gas/testsuite/gas/xtensa/trampoline.d6
3 files changed, 23 insertions, 91 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 24c1eb001d..c1299417bb 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,16 @@
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.
+
+2017-11-27 Max Filippov <jcmvbkbc@gmail.com>
+
* config/tc-xtensa.c (trampoline_index): New structure.
(trampoline_seg): Replace trampoline list with trampoline index.
(xg_find_trampoline, xg_add_trampoline_to_index)
diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
index 7d8b62bd39..b507d4425a 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)
{
diff --git a/gas/testsuite/gas/xtensa/trampoline.d b/gas/testsuite/gas/xtensa/trampoline.d
index c0bac6d19e..f9aa5d97ed 100644
--- a/gas/testsuite/gas/xtensa/trampoline.d
+++ b/gas/testsuite/gas/xtensa/trampoline.d
@@ -23,11 +23,11 @@
#...
.*49404:.*j.0x49404
.*49407:.*beqz.n.a2,.0x4940c
-.*49409:.*j.0x693ce
+.*49409:.*j.0x61aa2
#...
-.*693ce:.*j.0x7ddd1
+.*61aa2:.*j.0x7a13b
#...
-.*7ddd1:.*j.0x927f5
+.*7a13b:.*j.0x927f5
#...
.*927f5:.*j.0x927f5
#...