gas: xtensa: extract jump assembling for trampolines
authorMax Filippov <jcmvbkbc@gmail.com>
Thu, 9 Nov 2017 22:51:18 +0000 (14:51 -0800)
committerMax Filippov <jcmvbkbc@gmail.com>
Mon, 27 Nov 2017 23:11:38 +0000 (15:11 -0800)
init_trampoline_frag, add_jump_to_trampoline and xg_relax_trampoline add
a jump to the end of a trampoline frag. Extract it into a separate
funciton and use it in all these places. No functional changes.

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

* config/tc-xtensa.c (xg_append_jump): New function.
(xg_relax_trampoline, init_trampoline_frag)
(add_jump_to_trampoline): Replace trampoline jump assembling
code with a call to xg_append_jump.

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

index 683ebbfc80e8b81fa40a99bb2008687093e3ba51..d156052944112aa68d57dd4f9875340f43454141 100644 (file)
@@ -1,3 +1,10 @@
+2017-11-27  Max Filippov  <jcmvbkbc@gmail.com>
+
+       * config/tc-xtensa.c (xg_append_jump): New function.
+       (xg_relax_trampoline, init_trampoline_frag)
+       (add_jump_to_trampoline): Replace trampoline jump assembling
+       code with a call to xg_append_jump.
+
 2017-11-27  Max Filippov  <jcmvbkbc@gmail.com>
 
        * config/tc-xtensa.c (xg_relax_trampoline): New function.
index 087caad202dac370be593c158556b81186902a92..eccf3c310087b110e0c17fac1d00dfa8a41c0902 100644 (file)
@@ -485,6 +485,8 @@ static void xtensa_create_trampoline_frag (bfd_boolean);
 static void xtensa_maybe_create_trampoline_frag (void);
 struct trampoline_frag;
 static int init_trampoline_frag (struct trampoline_frag *);
+static fixS *xg_append_jump (fragS *fragP, fixS *jump_around,
+                            symbolS *sym, offsetT offset);
 static void xtensa_maybe_create_literal_pool_frag (bfd_boolean, bfd_boolean);
 static bfd_boolean auto_litpools = FALSE;
 static int auto_litpool_limit = 10000;
@@ -9166,13 +9168,10 @@ static bfd_boolean xtensa_add_cached_fixup (fixup_cacheS *cache, fixS *fixP)
 
 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 ||
@@ -9203,8 +9202,6 @@ static void xg_relax_trampoline (fragS *fragP, long stretch, long *new_stretch)
       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);
@@ -9264,55 +9261,26 @@ static void xg_relax_trampoline (fragS *fragP, long stretch, long *new_stretch)
              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);
+                 new_stretch += init_trampoline_frag (tf) + 3;
+                 /* Assemble a jump to the target label in the trampoline frag.  */
+                 newfixP = xg_append_jump (fragP, tf->fixP,
+                                           fixP->fx_addsy, fixP->fx_offset);
 
-                 /* 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;
+                 /* Adjust the fixup for the original "j" instruction to
+                    point to the newly added jump.  */
+                 fixP->fx_addsy = fragP->fr_symbol;
+                 fixP->fx_offset = fragP->fr_fix - 3;
+                 fixP->tc_fix_data.X_add_symbol = fragP->fr_symbol;
+                 fixP->tc_fix_data.X_add_number = fragP->fr_fix - 3;
 
-                 xtensa_add_cached_fixup (&fixup_cache, fixP);
+                 fixP = newfixP;
+                 xtensa_delete_cached_fixup (&fixup_cache, i);
+                 xtensa_add_cached_fixup (&fixup_cache, newfixP);
 
                  /* 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)
@@ -10017,6 +9985,39 @@ check_and_update_trampolines (void)
     }
 }
 
+static fixS *xg_append_jump (fragS *fragP, fixS *jump_around,
+                            symbolS *sym, offsetT offset)
+{
+  fixS *fixP;
+  TInsn insn;
+  xtensa_format fmt;
+  xtensa_isa isa = xtensa_default_isa;
+
+  gas_assert (fragP->fr_var >= 3);
+  tinsn_init (&insn);
+  insn.insn_type = ITYPE_INSN;
+  insn.opcode = xtensa_j_opcode;
+  insn.ntok = 1;
+  set_expr_symbol_offset (&insn.tok[0], sym, 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 + fragP->fr_fix, 3);
+  fixP = fix_new (fragP, fragP->fr_fix, 3, sym, offset, TRUE,
+                 BFD_RELOC_XTENSA_SLOT0_OP);
+  fixP->tc_fix_data.slot = 0;
+
+  fragP->fr_fix += 3;
+  fragP->fr_var -= 3;
+
+  /* Adjust the jump around this trampoline (if present).  */
+  if (jump_around)
+    jump_around->fx_offset += 3;
+
+  return fixP;
+}
+
 
 static int
 init_trampoline_frag (struct trampoline_frag *trampP)
@@ -10028,35 +10029,14 @@ init_trampoline_frag (struct trampoline_frag *trampP)
     {
       symbolS *lsym;
       char label[10 + 2 * sizeof(fp)];
-      sprintf (label, ".L0_TR_%p", fp);
 
+      sprintf (label, ".L0_TR_%p", fp);
       lsym = (symbolS *)local_symbol_make (label, now_seg, 0, fp);
       fp->fr_symbol = lsym;
       if (trampP->needs_jump_around)
         {
-         /* Add a jump around this block of jumps, in case
-            control flows into this block.  */
-         fixS *fixP;
-         TInsn insn;
-         xtensa_format fmt;
-         xtensa_isa isa = xtensa_default_isa;
-
-         fp->tc_frag_data.is_insn = 1;
-         /* Assemble a jump insn.  */
-         tinsn_init (&insn);
-         insn.insn_type = ITYPE_INSN;
-         insn.opcode = xtensa_j_opcode;
-         insn.ntok = 1;
-         set_expr_symbol_offset (&insn.tok[0], lsym, 3);
-         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 *)fp->fr_literal, 3);
-         fp->fr_fix += 3;
-         fp->fr_var -= 3;
+         trampP->fixP = xg_append_jump (fp, NULL, lsym, 3);
          growth = 3;
-         fixP = fix_new (fp, 0, 3, lsym, 3, TRUE, BFD_RELOC_XTENSA_SLOT0_OP);
-         trampP->fixP = fixP;
         }
     }
   return growth;
@@ -10067,15 +10047,6 @@ static int
 add_jump_to_trampoline (struct trampoline_frag *trampP, fragS *origfrag)
 {
   fragS *tramp = trampP->fragP;
-  fixS *fixP;
-  int offset = tramp->fr_fix; /* Where to assemble the j insn.  */
-  TInsn insn;
-  symbolS *lsym;
-  symbolS *tsym;
-  int toffset;
-  xtensa_format fmt;
-  xtensa_isa isa = xtensa_default_isa;
-  int growth = 0;
   int i, slot = -1;
 
   for (i = 0; i < MAX_SLOTS; ++i)
@@ -10087,35 +10058,19 @@ add_jump_to_trampoline (struct trampoline_frag *trampP, fragS *origfrag)
 
   gas_assert (slot >= 0 && slot < MAX_SLOTS);
 
-  lsym = tramp->fr_symbol;
   /* Assemble a jump to the target label in the trampoline frag.  */
-  tsym = origfrag->tc_frag_data.slot_symbols[slot];
-  toffset = origfrag-> tc_frag_data.slot_offsets[slot];
-  tinsn_init (&insn);
-  insn.insn_type = ITYPE_INSN;
-  insn.opcode = xtensa_j_opcode;
-  insn.ntok = 1;
-  set_expr_symbol_offset (&insn.tok[0], tsym, toffset);
-  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 *)tramp->fr_literal + offset, 3);
-  tramp->fr_fix += 3;
-  tramp->fr_var -= 3;
-  growth = 3;
-  /* add a fix-up for the trampoline jump.  */
-  fixP = fix_new (tramp, tramp->fr_fix - 3, 3, tsym, toffset, TRUE, BFD_RELOC_XTENSA_SLOT0_OP);
-  /* Modify the jump at the start of this trampoline to point past the newly-added jump.  */
-  fixP = trampP->fixP;
-  if (fixP)
-    fixP->fx_offset += 3;
+  xg_append_jump (tramp, trampP->fixP,
+                 origfrag->tc_frag_data.slot_symbols[slot],
+                 origfrag->tc_frag_data.slot_offsets[slot]);
+
   /* Modify the original j to point here.  */
-  origfrag->tc_frag_data.slot_symbols[slot] = lsym;
+  origfrag->tc_frag_data.slot_symbols[slot] = tramp->fr_symbol;
   origfrag->tc_frag_data.slot_offsets[slot] = tramp->fr_fix - 3;
+
   /* If trampoline is full, remove it from the list.  */
   check_and_update_trampolines ();
 
-  return growth;
+  return 3;
 }