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.
This commit is contained in:
parent
fe6c2f1b64
commit
76a493ab99
|
@ -1,3 +1,14 @@
|
|||
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.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
size_t i;
|
||||
|
||||
if (!ts)
|
||||
if (!ts || !ts->index.n_entries)
|
||||
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;
|
||||
i = xg_find_best_trampoline (&ts->index, source, target);
|
||||
|
||||
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 (tf == NULL)
|
||||
tf = search_trampolines (tinsn, fragP, FALSE); /* Try ones needing a jump-around, too. */
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
#...
|
||||
|
|
Loading…
Reference in New Issue