]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: xtensa: reuse trampoline placement code
authorMax Filippov <jcmvbkbc@gmail.com>
Mon, 13 Nov 2017 08:42:43 +0000 (00:42 -0800)
committerMax Filippov <jcmvbkbc@gmail.com>
Mon, 27 Nov 2017 23:14:48 +0000 (15:14 -0800)
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.

gas/ChangeLog
gas/config/tc-xtensa.c
gas/testsuite/gas/xtensa/trampoline.d

index 24c1eb001d96ad89141d0da5bb05f09b90fc3bfb..c1299417bb849b7520a57bea32c7aaa2cd45ab26 100644 (file)
@@ -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.
index 7d8b62bd39d750729d2385d554f7f7ca5cb3e197..b507d4425a368049089f50b1924df4498a6907d0 100644 (file)
@@ -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)
            {
index c0bac6d19e3d2ae9ac592e3d7f6eb258fdc8c9fa..f9aa5d97edb223fa341242ad1c9c034de47c06a9 100644 (file)
 #...
 .*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
 #...