gas: extract xg_relax_trampoline from xtensa_relax_frag
authorMax Filippov <jcmvbkbc@gmail.com>
Fri, 20 Oct 2017 23:23:28 +0000 (16:23 -0700)
committerMax Filippov <jcmvbkbc@gmail.com>
Mon, 27 Nov 2017 23:10:49 +0000 (15:10 -0800)
To make measurement and changes easier extract trampoline relaxation
function. No functional changes.

gas/
2017-11-27  Max Filippov  <jcmvbkbc@gmail.com>

* config/tc-xtensa.c (xg_relax_trampoline): New function.
(xtensa_relax_frag): Replace trampoline relaxation code with a
call to xg_relax_trampoline.

gas/ChangeLog
gas/config/tc-xtensa.c

index 4dd68208a04fb0c5fb101e9ceb96bf99320c45fa..683ebbfc80e8b81fa40a99bb2008687093e3ba51 100644 (file)
@@ -1,3 +1,9 @@
+2017-11-27  Max Filippov  <jcmvbkbc@gmail.com>
+
+       * config/tc-xtensa.c (xg_relax_trampoline): New function.
+       (xtensa_relax_frag): Replace trampoline relaxation code with a
+       call to xg_relax_trampoline.
+
 2017-11-27  Nick Clifton  <nickc@redhat.com>
 
        PR 22492
index a48ce1e5437f8e2a740023bbb78afc2b1c647f9c..087caad202dac370be593c158556b81186902a92 100644 (file)
@@ -9164,6 +9164,173 @@ static bfd_boolean xtensa_add_cached_fixup (fixup_cacheS *cache, fixS *fixP)
   return TRUE;
 }
 
+static void xg_relax_trampoline (fragS *fragP, long stretch, long *new_stretch)
+{
+  xtensa_isa isa = xtensa_default_isa;
+  static fixup_cacheS fixup_cache;
+  segment_info_type *seginfo = seg_info (now_seg);
+  int trampaddr = fragP->fr_address + fragP->fr_fix;
+  int searchaddr = trampaddr < J_RANGE ? 0 : trampaddr - J_RANGE;
+  int slot;
+  xtensa_format fmt;
+  unsigned i;
+
+  if (now_seg != fixup_cache.seg ||
+      fragP == fixup_cache.first_frag ||
+      fixup_cache.first_frag == NULL)
+    {
+      xtensa_cache_relaxable_fixups (&fixup_cache, seginfo);
+      fixup_cache.seg = now_seg;
+      fixup_cache.first_frag = fragP;
+    }
+
+  /* Scan for jumps that will not reach.  */
+  for (i = xtensa_find_first_cached_fixup (&fixup_cache, searchaddr);
+       i < fixup_cache.n_fixups; ++i)
+
+    {
+      fixS *fixP = fixup_cache.fixups[i].fixP;
+      int target = fixup_cache.fixups[i].target;
+      int addr = fixup_cache.fixups[i].addr;
+      int delta = fixup_cache.fixups[i].delta + stretch;
+
+      trampaddr = fragP->fr_address + fragP->fr_fix;
+
+      if (addr + J_RANGE < trampaddr)
+       continue;
+      if (addr > trampaddr + J_RANGE)
+       break;
+      if (abs (delta) < J_RANGE)
+       continue;
+
+      slot = fixP->tc_fix_data.slot;
+
+      if (delta > J_RANGE  || delta < -1 * J_RANGE)
+       { /* Found an out-of-range jump; scan the list of trampolines for the best match.  */
+         struct trampoline_seg *ts = find_trampoline_seg (now_seg);
+         struct trampoline_frag *tf = ts->trampoline_list.next;
+         struct trampoline_frag *prev = &ts->trampoline_list;
+         int lower = (target < addr) ? target : addr;
+         int upper = (target > addr) ? target : addr;
+         int midpoint = lower + (upper - lower) / 2;
+
+         if ((upper - lower) > 2 * J_RANGE)
+           {
+             /* One trampoline won't suffice; we need multiple jumps.
+                Jump to the trampoline that's farthest, but still in
+                range relative to the original "j" instruction.  */
+             for ( ; tf; prev = tf, tf = tf->next )
+               {
+                 int this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
+                 int next_addr = (tf->next) ? tf->next->fragP->fr_address + tf->next->fragP->fr_fix : 0 ;
+
+                 if (addr == lower)
+                   {
+                     /* Forward jump.  */
+                     if (this_addr - addr < J_RANGE)
+                       break;
+                   }
+                 else
+                   {
+                     /* Backward jump.  */
+                     if (next_addr == 0 || addr - next_addr > J_RANGE)
+                       break;
+                   }
+               }
+           }
+         else
+           {
+             struct trampoline_frag *best_tf = NULL;
+             struct trampoline_frag *best_tf_prev = NULL;
+             int best_delta = 0;
+
+             for ( ; tf; prev = tf, tf = tf->next )
+               {
+                 int this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
+                 int this_delta = abs (this_addr - midpoint);
+
+                 if (!best_tf || this_delta < best_delta)
+                   {
+                     best_tf = tf;
+                     best_delta = this_delta;
+                     best_tf_prev = prev;
+                   }
+               }
+             tf = best_tf;
+             prev = best_tf_prev;
+           }
+         if (tf->fragP == fragP)
+           {
+             if (abs (addr - trampaddr) < J_RANGE)
+               { /* The trampoline is in range of original; fix it!  */
+                 fixS *newfixP;
+                 int offset;
+                 TInsn insn;
+                 symbolS *lsym;
+                 fragS *fP; /* The out-of-range jump.  */
+
+                 new_stretch += init_trampoline_frag (tf);
+                 offset = fragP->fr_fix; /* Where to assemble the j insn.  */
+                 lsym = fragP->fr_symbol;
+                 fP = fixP->fx_frag;
+                 /* Assemble a jump to the target label here.  */
+                 tinsn_init (&insn);
+                 insn.insn_type = ITYPE_INSN;
+                 insn.opcode = xtensa_j_opcode;
+                 insn.ntok = 1;
+                 set_expr_symbol_offset (&insn.tok[0], lsym, offset);
+                 fmt = xg_get_single_format (xtensa_j_opcode);
+                 tinsn_to_slotbuf (fmt, 0, &insn, trampoline_slotbuf);
+                 xtensa_format_set_slot (isa, fmt, 0, trampoline_buf, trampoline_slotbuf);
+                 xtensa_insnbuf_to_chars (isa, trampoline_buf, (unsigned char *)fragP->fr_literal + offset, 3);
+                 fragP->fr_fix += 3;
+                 fragP->fr_var -= 3;
+                 /* Add a fix-up for the original j insn.  */
+                 newfixP = fix_new (fP, fixP->fx_where, fixP->fx_size, lsym, fragP->fr_fix - 3, TRUE, fixP->fx_r_type);
+                 newfixP->fx_no_overflow = 1;
+                 newfixP->tc_fix_data.X_add_symbol = lsym;
+                 newfixP->tc_fix_data.X_add_number = offset;
+                 newfixP->tc_fix_data.slot = slot;
+
+                 xtensa_delete_cached_fixup (&fixup_cache, i);
+                 xtensa_add_cached_fixup (&fixup_cache, newfixP);
+
+                 /* Move the fix-up from the original j insn to this one.  */
+                 fixP->fx_frag = fragP;
+                 fixP->fx_where = fragP->fr_fix - 3;
+                 fixP->fx_size = 3;
+                 fixP->tc_fix_data.slot = 0;
+                 fixP->fx_r_type = BFD_RELOC_XTENSA_SLOT0_OP;
+
+                 xtensa_add_cached_fixup (&fixup_cache, fixP);
+
+                 /* re-do current fixup */
+                 --i;
+
+                 /* Adjust the jump around this trampoline (if present).  */
+                 if (tf->fixP != NULL)
+                   {
+                     tf->fixP->fx_offset += 3;
+                   }
+                 new_stretch += 3;
+                 fragP->tc_frag_data.relax_seen = FALSE; /* Need another pass.  */
+                 /* Do we have room for more?  */
+                 if (fragP->fr_var < 3)
+                   { /* No, convert to fill.  */
+                     frag_wane (fragP);
+                     fragP->fr_subtype = 0;
+                     /* Remove from the trampoline_list.  */
+                     prev->next = tf->next;
+                     if (fragP == fixup_cache.first_frag)
+                       fixup_cache.first_frag = NULL;
+                     break;
+                   }
+               }
+           }
+       }
+    }
+}
+
 /* Return the number of bytes added to this fragment, given that the
    input has been stretched already by "stretch".  */
 
@@ -9307,165 +9474,7 @@ xtensa_relax_frag (fragS *fragP, long stretch, int *stretched_p)
 
     case RELAX_TRAMPOLINE:
       if (fragP->tc_frag_data.relax_seen)
-        {
-         static fixup_cacheS fixup_cache;
-         segment_info_type *seginfo = seg_info (now_seg);
-         int trampaddr = fragP->fr_address + fragP->fr_fix;
-         int searchaddr = trampaddr < J_RANGE ? 0 : trampaddr - J_RANGE;
-         unsigned i;
-
-         if (now_seg != fixup_cache.seg ||
-             fragP == fixup_cache.first_frag ||
-             fixup_cache.first_frag == NULL)
-           {
-             xtensa_cache_relaxable_fixups (&fixup_cache, seginfo);
-             fixup_cache.seg = now_seg;
-             fixup_cache.first_frag = fragP;
-           }
-
-          /* Scan for jumps that will not reach.  */
-          for (i = xtensa_find_first_cached_fixup (&fixup_cache, searchaddr);
-              i < fixup_cache.n_fixups; ++i)
-
-            {
-             fixS *fixP = fixup_cache.fixups[i].fixP;
-             int target = fixup_cache.fixups[i].target;
-             int addr = fixup_cache.fixups[i].addr;
-             int delta = fixup_cache.fixups[i].delta + stretch;
-
-             trampaddr = fragP->fr_address + fragP->fr_fix;
-
-             if (addr + J_RANGE < trampaddr)
-               continue;
-             if (addr > trampaddr + J_RANGE)
-               break;
-             if (abs (delta) < J_RANGE)
-               continue;
-
-             slot = fixP->tc_fix_data.slot;
-
-              if (delta > J_RANGE  || delta < -1 * J_RANGE)
-                { /* Found an out-of-range jump; scan the list of trampolines for the best match.  */
-                 struct trampoline_seg *ts = find_trampoline_seg (now_seg);
-                 struct trampoline_frag *tf = ts->trampoline_list.next;
-                 struct trampoline_frag *prev = &ts->trampoline_list;
-                 int lower = (target < addr) ? target : addr;
-                 int upper = (target > addr) ? target : addr;
-                 int midpoint = lower + (upper - lower) / 2;
-
-                 if ((upper - lower) > 2 * J_RANGE)
-                   {
-                     /* One trampoline won't suffice; we need multiple jumps.
-                        Jump to the trampoline that's farthest, but still in
-                        range relative to the original "j" instruction.  */
-                     for ( ; tf; prev = tf, tf = tf->next )
-                       {
-                         int this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
-                         int next_addr = (tf->next) ? tf->next->fragP->fr_address + tf->next->fragP->fr_fix : 0 ;
-
-                         if (addr == lower)
-                           {
-                             /* Forward jump.  */
-                             if (this_addr - addr < J_RANGE)
-                               break;
-                           }
-                         else
-                           {
-                             /* Backward jump.  */
-                             if (next_addr == 0 || addr - next_addr > J_RANGE)
-                               break;
-                           }
-                       }
-                   }
-                 else
-                   {
-                     struct trampoline_frag *best_tf = NULL;
-                     int best_delta = 0;
-
-                     for ( ; tf; prev = tf, tf = tf->next )
-                       {
-                         int this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
-                         int this_delta = abs (this_addr - midpoint);
-
-                         if (!best_tf || this_delta < best_delta)
-                           {
-                              best_tf = tf;
-                              best_delta = this_delta;
-                           }
-                       }
-                     tf = best_tf;
-                   }
-                 if (tf->fragP == fragP)
-                   {
-                     if (abs (addr - trampaddr) < J_RANGE)
-                       { /* The trampoline is in range of original; fix it!  */
-                         fixS *newfixP;
-                         int offset;
-                         TInsn insn;
-                         symbolS *lsym;
-                         fragS *fP; /* The out-of-range jump.  */
-
-                         new_stretch += init_trampoline_frag (tf);
-                         offset = fragP->fr_fix; /* Where to assemble the j insn.  */
-                         lsym = fragP->fr_symbol;
-                         fP = fixP->fx_frag;
-                         /* Assemble a jump to the target label here.  */
-                         tinsn_init (&insn);
-                         insn.insn_type = ITYPE_INSN;
-                         insn.opcode = xtensa_j_opcode;
-                         insn.ntok = 1;
-                         set_expr_symbol_offset (&insn.tok[0], lsym, offset);
-                         fmt = xg_get_single_format (xtensa_j_opcode);
-                         tinsn_to_slotbuf (fmt, 0, &insn, trampoline_slotbuf);
-                         xtensa_format_set_slot (isa, fmt, 0, trampoline_buf, trampoline_slotbuf);
-                         xtensa_insnbuf_to_chars (isa, trampoline_buf, (unsigned char *)fragP->fr_literal + offset, 3);
-                         fragP->fr_fix += 3;
-                         fragP->fr_var -= 3;
-                         /* Add a fix-up for the original j insn.  */
-                         newfixP = fix_new (fP, fixP->fx_where, fixP->fx_size, lsym, fragP->fr_fix - 3, TRUE, fixP->fx_r_type);
-                         newfixP->fx_no_overflow = 1;
-                         newfixP->tc_fix_data.X_add_symbol = lsym;
-                         newfixP->tc_fix_data.X_add_number = offset;
-                         newfixP->tc_fix_data.slot = slot;
-
-                         xtensa_delete_cached_fixup (&fixup_cache, i);
-                         xtensa_add_cached_fixup (&fixup_cache, newfixP);
-
-                         /* Move the fix-up from the original j insn to this one.  */
-                         fixP->fx_frag = fragP;
-                         fixP->fx_where = fragP->fr_fix - 3;
-                         fixP->fx_size = 3;
-                         fixP->tc_fix_data.slot = 0;
-                         fixP->fx_r_type = BFD_RELOC_XTENSA_SLOT0_OP;
-
-                         xtensa_add_cached_fixup (&fixup_cache, fixP);
-
-                         /* re-do current fixup */
-                         --i;
-
-                         /* Adjust the jump around this trampoline (if present).  */
-                         if (tf->fixP != NULL)
-                           {
-                             tf->fixP->fx_offset += 3;
-                           }
-                         new_stretch += 3;
-                         fragP->tc_frag_data.relax_seen = FALSE; /* Need another pass.  */
-                         /* Do we have room for more?  */
-                         if (fragP->fr_var < 3)
-                           { /* No, convert to fill.  */
-                             frag_wane (fragP);
-                             fragP->fr_subtype = 0;
-                             /* Remove from the trampoline_list.  */
-                             prev->next = tf->next;
-                             if (fragP == fixup_cache.first_frag)
-                               fixup_cache.first_frag = NULL;
-                             break;
-                           }
-                       }
-                   }
-                }
-            }
-        }
+       xg_relax_trampoline (fragP, stretch, &new_stretch);
       break;
 
     default:
This page took 0.034139 seconds and 4 git commands to generate.