This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] gas: extract xg_relax_trampoline from xtensa_relax_frag


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=120bc8b8b91cba4a8d4092ea0fb3d76bcbe98712

commit 120bc8b8b91cba4a8d4092ea0fb3d76bcbe98712
Author: Max Filippov <jcmvbkbc@gmail.com>
Date:   Fri Oct 20 16:23:28 2017 -0700

    gas: extract xg_relax_trampoline from xtensa_relax_frag
    
    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.

Diff:
---
 gas/ChangeLog          |   6 +
 gas/config/tc-xtensa.c | 327 +++++++++++++++++++++++++------------------------
 2 files changed, 174 insertions(+), 159 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index 4dd6820..683ebbf 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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
diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
index a48ce1e..087caad 100644
--- a/gas/config/tc-xtensa.c
+++ b/gas/config/tc-xtensa.c
@@ -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:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]