The cirros image was rebuilt against the 3.13.0-83 kernel, drivers e1000e, igbvf...
[packages/trusty/cirros-testvm.git] / cirros-testvm / src-cirros / buildroot-2015.05 / package / binutils / 2.24 / 900-xtensa-trampolines.patch
1 From a82c7d9030b67a6a76a5403d0e1641f9e42141ac Mon Sep 17 00:00:00 2001
2 From: David Weatherford <weath@cadence.com>
3 Date: Fri, 21 Mar 2014 11:53:42 +0000
4 Subject: [PATCH] Add support to the Xtensa target for creating trampolines for
5  out-of-range branches.
6
7     * tc-xtensa.c (xtensa_check_frag_count, xtensa_create_trampoline_frag)
8     (xtensa_maybe_create_trampoline_frag, init_trampoline_frag)
9     (find_trampoline_seg, search_trampolines, get_best_trampoline)
10     (check_and_update_trampolines, add_jump_to_trampoline)
11     (dump_trampolines): New function.
12     (md_parse_option): Add cases for --[no-]trampolines options.
13     (md_assemble, finish_vinsn, xtensa_end): Add call to
14     xtensa_check_frag_count.
15     (xg_assemble_vliw_tokens): Add call to
16     xtensa_maybe_create_trampoline_frag.
17     (xtensa_relax_frag): Relax fragments with RELAX_TRAMPOLINE state.
18     (relax_frag_immed): Relax jump instructions that cannot reach its
19     target.
20     * tc-xtensa.h (xtensa_relax_statesE::RELAX_TRAMPOLINE): New relax
21     state.
22
23     * as.texinfo: Document --[no-]trampolines command-line options.
24     * c-xtensa.texi: Document trampolines relaxation and command line
25     options.
26
27     * frags.c (get_frag_count, clear_frag_count): New function.
28     (frag_alloc): Increment totalfrags counter.
29     * frags.h (get_frag_count, clear_frag_count): New function.
30
31     * all.exp: Add test for trampoline relaxation.
32     * trampoline.d: Trampoline relaxation expected dump.
33     * trampoline.s: Trampoline relaxation test source.
34 ---
35 Backported from: a82c7d9030b67a6a76a5403d0e1641f9e42141ac
36 Changes to Changelog files are dropped.
37
38  gas/config/tc-xtensa.c                | 558 +++++++++++++++++++++++++++++++++-
39  gas/config/tc-xtensa.h                |   5 +
40  gas/frags.c                           |  15 +
41  gas/frags.h                           |   3 +
42  gas/testsuite/gas/xtensa/all.exp      |   1 +
43  gas/testsuite/gas/xtensa/trampoline.d |  26 ++
44  gas/testsuite/gas/xtensa/trampoline.s |  21 ++
45  11 files changed, 753 insertions(+), 2 deletions(-)
46  create mode 100644 gas/testsuite/gas/xtensa/trampoline.d
47  create mode 100644 gas/testsuite/gas/xtensa/trampoline.s
48
49 diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c
50 index fe8ec0f..ea23c96 100644
51 --- a/gas/config/tc-xtensa.c
52 +++ b/gas/config/tc-xtensa.c
53 @@ -468,6 +468,12 @@ static void xtensa_set_frag_assembly_state (fragS *);
54  static void finish_vinsn (vliw_insn *);
55  static bfd_boolean emit_single_op (TInsn *);
56  static int total_frag_text_expansion (fragS *);
57 +static bfd_boolean use_trampolines = TRUE;
58 +static void xtensa_check_frag_count (void);
59 +static void xtensa_create_trampoline_frag (bfd_boolean);
60 +static void xtensa_maybe_create_trampoline_frag (void);
61 +struct trampoline_frag;
62 +static int init_trampoline_frag (struct trampoline_frag *);
63  
64  /* Alignment Functions.  */
65  
66 @@ -520,6 +526,7 @@ static void tinsn_from_chars (TInsn *, char *, int);
67  static void tinsn_immed_from_frag (TInsn *, fragS *, int);
68  static int get_num_stack_text_bytes (IStack *);
69  static int get_num_stack_literal_bytes (IStack *);
70 +static bfd_boolean tinsn_to_slotbuf (xtensa_format, int, TInsn *, xtensa_insnbuf);
71  
72  /* vliw_insn functions.  */
73  
74 @@ -687,7 +694,10 @@ enum
75    option_prefer_l32r,
76    option_prefer_const16,
77  
78 -  option_target_hardware
79 +  option_target_hardware,
80 +
81 +  option_trampolines,
82 +  option_no_trampolines,
83  };
84  
85  const char *md_shortopts = "";
86 @@ -760,6 +770,9 @@ struct option md_longopts[] =
87  
88    { "target-hardware", required_argument, NULL, option_target_hardware },
89  
90 +  { "trampolines", no_argument, NULL, option_trampolines },
91 +  { "no-trampolines", no_argument, NULL, option_no_trampolines },
92 +
93    { NULL, no_argument, NULL, 0 }
94  };
95  
96 @@ -940,6 +953,14 @@ md_parse_option (int c, char *arg)
97        directive_state[directive_transform] = FALSE;
98        return 1;
99  
100 +    case option_trampolines:
101 +      use_trampolines = TRUE;
102 +      return 1;
103 +
104 +    case option_no_trampolines:
105 +      use_trampolines = FALSE;
106 +      return 1;
107 +
108      default:
109        return 0;
110      }
111 @@ -963,7 +984,9 @@ Xtensa options:\n\
112                            flix bundles\n\
113    --no-allow-flix         neither allow hand-written nor generate\n\
114                            flix bundles\n\
115 -  --rename-section old=new Rename section 'old' to 'new'\n", stream);
116 +  --rename-section old=new Rename section 'old' to 'new'\n\
117 +  --[no-]trampolines      [Do not] generate trampolines (jumps to jumps)\n\
118 +                          when jumps do not reach their targets\n", stream);
119  }
120  
121  \f
122 @@ -5568,6 +5591,8 @@ md_assemble (char *str)
123  
124    /* We've just emitted a new instruction so clear the list of labels.  */
125    xtensa_clear_insn_labels ();
126 +
127 +  xtensa_check_frag_count ();
128  }
129  
130  
131 @@ -6372,6 +6397,8 @@ finish_vinsn (vliw_insn *vinsn)
132    xg_assemble_vliw_tokens (vinsn);
133  
134    xg_clear_vinsn (vinsn);
135 +
136 +  xtensa_check_frag_count ();
137  }
138  
139  
140 @@ -7140,6 +7167,7 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
141                     RELAX_UNREACHABLE,
142                     frag_now->fr_symbol, frag_now->fr_offset, NULL);
143           xtensa_set_frag_assembly_state (frag_now);
144 +         xtensa_maybe_create_trampoline_frag ();
145         }
146        else if (is_branch && do_align_targets ())
147         {
148 @@ -7222,9 +7250,164 @@ xtensa_end (void)
149    xtensa_sanity_check ();
150  
151    xtensa_add_config_info ();
152 +
153 +  xtensa_check_frag_count ();
154 +}
155 +
156 +
157 +struct trampoline_frag
158 +{
159 +  struct trampoline_frag *next;
160 +  bfd_boolean needs_jump_around;
161 +  fragS *fragP;
162 +  fixS *fixP;
163 +};
164 +
165 +struct trampoline_seg
166 +{
167 +  struct trampoline_seg *next;
168 +  asection *seg;
169 +  struct trampoline_frag trampoline_list;
170 +};
171 +
172 +static struct trampoline_seg trampoline_seg_list;
173 +#define J_RANGE (128 * 1024)
174 +
175 +static int unreachable_count = 0;
176 +
177 +
178 +static void
179 +xtensa_maybe_create_trampoline_frag (void)
180 +{
181 +  if (!use_trampolines)
182 +    return;
183 +
184 +  /* We create an area for possible trampolines every 10 unreachable frags.
185 +     These are preferred over the ones not preceded by an unreachable frag,
186 +     because we don't have to jump around them. This function is called after
187 +     each RELAX_UNREACHABLE frag is created.  */
188 +
189 +  if (++unreachable_count > 10)
190 +    {
191 +      xtensa_create_trampoline_frag (FALSE);
192 +      clear_frag_count ();
193 +      unreachable_count = 0;
194 +    }
195 +}
196 +
197 +static void
198 +xtensa_check_frag_count (void)
199 +{
200 +  if (!use_trampolines || frag_now->tc_frag_data.is_no_transform)
201 +    return;
202 +
203 +  /* We create an area for possible trampolines every 8000 frags or so. This
204 +     is an estimate based on the max range of a "j" insn (+/-128K) divided
205 +     by a typical frag byte count (16), minus a few for safety. This function
206 +     is called after each source line is processed.  */
207 +
208 +  if (get_frag_count () > 8000)
209 +    {
210 +      xtensa_create_trampoline_frag (TRUE);
211 +      clear_frag_count ();
212 +      unreachable_count = 0;
213 +    }
214 +}
215 +
216 +static xtensa_insnbuf trampoline_buf = NULL;
217 +static xtensa_insnbuf trampoline_slotbuf = NULL;
218 +
219 +#define TRAMPOLINE_FRAG_SIZE 3000
220 +
221 +static void
222 +xtensa_create_trampoline_frag (bfd_boolean needs_jump_around)
223 +{
224 +  /* Emit a frag where we can place intermediate jump instructions,
225 +     in case we need to jump farther than 128K bytes.
226 +     Each jump instruction takes three bytes.
227 +     We allocate enough for 1000 trampolines in each frag.
228 +     If that's not enough, oh well.  */
229 +
230 +  struct trampoline_seg *ts = trampoline_seg_list.next;
231 +  struct trampoline_frag *tf;
232 +  char *varP;
233 +  fragS *fragP;
234 +  int size = TRAMPOLINE_FRAG_SIZE;
235 +
236 +  for ( ; ts; ts = ts->next)
237 +    {
238 +      if (ts->seg == now_seg)
239 +       break;
240 +    }
241 +
242 +  if (ts == NULL)
243 +    {
244 +      ts = (struct trampoline_seg *)xcalloc(sizeof (struct trampoline_seg), 1);
245 +      ts->next = trampoline_seg_list.next;
246 +      trampoline_seg_list.next = ts;
247 +      ts->seg = now_seg;
248 +    }
249 +
250 +  frag_wane (frag_now);
251 +  frag_new (0);
252 +  xtensa_set_frag_assembly_state (frag_now);
253 +  varP = frag_var (rs_machine_dependent, size, size, RELAX_TRAMPOLINE, NULL, 0, NULL);
254 +  fragP = (fragS *)(varP - SIZEOF_STRUCT_FRAG);
255 +  if (trampoline_buf == NULL)
256 +    {
257 +      trampoline_buf = xtensa_insnbuf_alloc (xtensa_default_isa);
258 +      trampoline_slotbuf = xtensa_insnbuf_alloc (xtensa_default_isa);
259 +    }
260 +  tf = (struct trampoline_frag *)xmalloc(sizeof (struct trampoline_frag));
261 +  tf->next = ts->trampoline_list.next;
262 +  ts->trampoline_list.next = tf;
263 +  tf->needs_jump_around = needs_jump_around;
264 +  tf->fragP = fragP;
265 +  tf->fixP = NULL;
266 +}
267 +
268 +
269 +static struct trampoline_seg *
270 +find_trampoline_seg (asection *seg)
271 +{
272 +  struct trampoline_seg *ts = trampoline_seg_list.next;
273 +
274 +  for ( ; ts; ts = ts->next)
275 +    {
276 +      if (ts->seg == seg)
277 +       return ts;
278 +    }
279 +
280 +  return NULL;
281  }
282  
283  
284 +void dump_trampolines (void);
285 +
286 +void
287 +dump_trampolines (void)
288 +{
289 +  struct trampoline_seg *ts = trampoline_seg_list.next;
290 +
291 +  for ( ; ts; ts = ts->next)
292 +    {
293 +      asection *seg = ts->seg;
294 +
295 +      if (seg == NULL)
296 +       continue;
297 +      fprintf(stderr, "SECTION %s\n", seg->name);
298 +      struct trampoline_frag *tf = ts->trampoline_list.next;
299 +      for ( ; tf; tf = tf->next)
300 +       {
301 +         if (tf->fragP == NULL)
302 +           continue;
303 +         fprintf(stderr, "   0x%08x: fix=%d, jump_around=%s\n",
304 +                 (int)tf->fragP->fr_address, (int)tf->fragP->fr_fix,
305 +                 tf->needs_jump_around ? "T" : "F");
306 +       }
307 +    }
308 +}
309 +
310  static void
311  xtensa_cleanup_align_frags (void)
312  {
313 @@ -8708,6 +8891,149 @@ xtensa_relax_frag (fragS *fragP, long stretch, int *stretched_p)
314         new_stretch += relax_frag_for_align (fragP, stretch);
315        break;
316  
317 +    case RELAX_TRAMPOLINE:
318 +      if (fragP->tc_frag_data.relax_seen)
319 +        {
320 +          segment_info_type *seginfo = seg_info (now_seg);
321 +          fragS *fP; /* The out-of-range jump.  */
322 +          fixS *fixP;
323 +
324 +          /* Scan for jumps that will not reach.  */
325 +          for (fixP = seginfo->fix_root; fixP ; fixP = fixP->fx_next)
326 +            {
327 +              symbolS *s = fixP->fx_addsy;
328 +             xtensa_opcode opcode;
329 +              int target;
330 +              int addr;
331 +              int delta;
332 +
333 +              if (fixP->fx_r_type < BFD_RELOC_XTENSA_SLOT0_OP ||
334 +                  fixP->fx_r_type > BFD_RELOC_XTENSA_SLOT14_OP)
335 +                continue;
336 +             xtensa_insnbuf_from_chars (isa, trampoline_buf,
337 +                                        (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where,
338 +                                        0);
339 +             fmt = xtensa_format_decode (isa, trampoline_buf);
340 +             gas_assert (fmt != XTENSA_UNDEFINED);
341 +             slot = fixP->tc_fix_data.slot;
342 +             xtensa_format_get_slot (isa, fmt, slot, trampoline_buf, trampoline_slotbuf);
343 +             opcode = xtensa_opcode_decode (isa, fmt, slot, trampoline_slotbuf);
344 +             if (opcode != xtensa_j_opcode)
345 +               continue;
346 +              target = S_GET_VALUE (s);
347 +              addr = fixP->fx_frag->fr_address;
348 +              delta = target - addr + stretch;
349 +              if (delta > J_RANGE  || delta < -1 * J_RANGE)
350 +                { /* Found an out-of-range jump; scan the list of trampolines for the best match.  */
351 +                 struct trampoline_seg *ts = find_trampoline_seg (now_seg);
352 +                 struct trampoline_frag *tf = ts->trampoline_list.next;
353 +                 struct trampoline_frag *prev = &ts->trampoline_list;
354 +                 int lower = (target < addr) ? target : addr;
355 +                 int upper = (target > addr) ? target : addr;
356 +                 int midpoint = lower + (upper - lower) / 2;
357 +
358 +                 if ((upper - lower) > 2 * J_RANGE)
359 +                   {
360 +                     /* One trampoline won't suffice; we need multiple jumps.
361 +                        Jump to the trampoline that's farthest, but still in
362 +                        range relative to the original "j" instruction.  */
363 +                     for ( ; tf; prev = tf, tf = tf->next )
364 +                       {
365 +                         int this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
366 +                         int next_addr = (tf->next) ? tf->next->fragP->fr_address + tf->next->fragP->fr_fix : 0 ;
367 +
368 +                         if (addr == lower)
369 +                           {
370 +                             /* Forward jump.  */
371 +                             if (this_addr - addr < J_RANGE)
372 +                               break;
373 +                           }
374 +                         else
375 +                           {
376 +                             /* Backward jump.  */
377 +                             if (next_addr == 0 || addr - next_addr > J_RANGE)
378 +                               break;
379 +                           }
380 +                       }
381 +                   }
382 +                 else
383 +                   {
384 +                     struct trampoline_frag *best_tf = NULL;
385 +                     int best_delta = 0;
386 +
387 +                     for ( ; tf; prev = tf, tf = tf->next )
388 +                       {
389 +                         int this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
390 +                         int this_delta = abs (this_addr - midpoint);
391 +
392 +                         if (!best_tf || this_delta < best_delta)
393 +                           {
394 +                              best_tf = tf;
395 +                              best_delta = this_delta;
396 +                           }
397 +                       }
398 +                     tf = best_tf;
399 +                   }
400 +                 if (tf->fragP == fragP)
401 +                   {
402 +                     int trampaddr = fragP->fr_address + fragP->fr_fix;
403 +
404 +                     if (abs (addr - trampaddr) < J_RANGE)
405 +                       { /* The trampoline is in range of original; fix it!  */
406 +                         fixS *newfixP;
407 +                         int offset;
408 +                         TInsn insn;
409 +                         symbolS *lsym;
410 +
411 +                         new_stretch += init_trampoline_frag (tf);
412 +                         offset = fragP->fr_fix; /* Where to assemble the j insn.  */
413 +                         lsym = fragP->fr_symbol;
414 +                         fP = fixP->fx_frag;
415 +                         /* Assemble a jump to the target label here.  */
416 +                         tinsn_init (&insn);
417 +                         insn.insn_type = ITYPE_INSN;
418 +                         insn.opcode = xtensa_j_opcode;
419 +                         insn.ntok = 1;
420 +                         set_expr_symbol_offset (&insn.tok[0], lsym, offset);
421 +                         fmt = xg_get_single_format (xtensa_j_opcode);
422 +                         tinsn_to_slotbuf (fmt, 0, &insn, trampoline_slotbuf);
423 +                         xtensa_format_set_slot (isa, fmt, 0, trampoline_buf, trampoline_slotbuf);
424 +                         xtensa_insnbuf_to_chars (isa, trampoline_buf, (unsigned char *)fragP->fr_literal + offset, 3);
425 +                         fragP->fr_fix += 3;
426 +                         fragP->fr_var -= 3;
427 +                         /* Add a fix-up for the original j insn.  */
428 +                         newfixP = fix_new (fP, fixP->fx_where, fixP->fx_size, lsym, fragP->fr_fix - 3, TRUE, fixP->fx_r_type);
429 +                         newfixP->fx_no_overflow = 1;
430 +                         newfixP->tc_fix_data.X_add_symbol = lsym;
431 +                         newfixP->tc_fix_data.X_add_number = offset;
432 +                         newfixP->tc_fix_data.slot = slot;
433 +                         /* Move the fix-up from the original j insn to this one.  */
434 +                         fixP->fx_frag = fragP;
435 +                         fixP->fx_where = fragP->fr_fix - 3;
436 +                         fixP->tc_fix_data.slot = 0;
437 +                         /* Adjust the jump around this trampoline (if present).  */
438 +                         if (tf->fixP != NULL)
439 +                           {
440 +                             tf->fixP->fx_offset += 3;
441 +                           }
442 +                         new_stretch += 3;
443 +                         fragP->tc_frag_data.relax_seen = FALSE; /* Need another pass.  */
444 +                         /* Do we have room for more?  */
445 +                         if (fragP->fr_var < 3)
446 +                           { /* No, convert to fill.  */
447 +                             frag_wane (fragP);
448 +                             fragP->fr_subtype = 0;
449 +                             /* Remove from the trampoline_list.  */
450 +                             prev->next = tf->next;
451 +                             break;
452 +                           }
453 +                       }
454 +                   }
455 +                }
456 +            }
457 +        }
458 +      break;
459 +
460      default:
461        as_bad (_("bad relaxation state"));
462      }
463 @@ -9146,6 +9472,200 @@ bytes_to_stretch (fragS *this_frag,
464  }
465  
466  
467 +static struct trampoline_frag *
468 +search_trampolines (TInsn *tinsn, fragS *fragP, bfd_boolean unreachable_only)
469 +{
470 +  struct trampoline_seg *ts = find_trampoline_seg (now_seg);
471 +  struct trampoline_frag *tf = (ts) ? ts->trampoline_list.next : NULL;
472 +  struct trampoline_frag *best_tf = NULL;
473 +  int best_delta = 0;
474 +  int best_addr = 0;
475 +  symbolS *sym = tinsn->tok[0].X_add_symbol;
476 +  offsetT target = S_GET_VALUE (sym) + tinsn->tok[0].X_add_number;
477 +  offsetT addr = fragP->fr_address;
478 +  offsetT lower = (addr < target) ? addr : target;
479 +  offsetT upper = (addr > target) ? addr : target;
480 +  int delta = upper - lower;
481 +  offsetT midpoint = lower + delta / 2;
482 +  int this_delta = -1;
483 +  int this_addr = -1;
484 +
485 +  if (delta > 2 * J_RANGE)
486 +    {
487 +      /* One trampoline won't do; we need multiple.
488 +        Choose the farthest trampoline that's still in range of the original
489 +        and let a later pass finish the job.  */
490 +      for ( ; tf; tf = tf->next)
491 +       {
492 +         int next_addr = (tf->next) ? tf->next->fragP->fr_address + tf->next->fragP->fr_fix : 0;
493 +
494 +         this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
495 +         if (lower == addr)
496 +           {
497 +             /* Forward jump.  */
498 +             if (this_addr - addr < J_RANGE)
499 +               break;
500 +           }
501 +         else
502 +           {
503 +             /* Backward jump.  */
504 +             if (next_addr == 0 || addr - next_addr > J_RANGE)
505 +               break;
506 +           }
507 +         if (abs (addr - this_addr) < J_RANGE)
508 +           return tf;
509 +
510 +         return NULL;
511 +       }
512 +    }
513 +  for ( ; tf; tf = tf->next)
514 +    {
515 +      this_addr = tf->fragP->fr_address + tf->fragP->fr_fix;
516 +      this_delta = abs (this_addr - midpoint);
517 +      if (unreachable_only && tf->needs_jump_around)
518 +       continue;
519 +      if (!best_tf || this_delta < best_delta)
520 +        {
521 +         best_tf = tf;
522 +         best_delta = this_delta;
523 +         best_addr = this_addr;
524 +        }
525 +    }
526 +
527 +  if (best_tf &&
528 +      best_delta < J_RANGE &&
529 +      abs(best_addr - lower) < J_RANGE &&
530 +      abs(best_addr - upper) < J_RANGE)
531 +    return best_tf;
532 +
533 +  return NULL; /* No suitable trampoline found.  */
534 +}
535 +
536 +
537 +static struct trampoline_frag *
538 +get_best_trampoline (TInsn *tinsn, fragS *fragP)
539 +{
540 +  struct trampoline_frag *tf = NULL;
541 +
542 +  tf = search_trampolines (tinsn, fragP, TRUE); /* Try unreachable first.  */
543 +
544 +  if (tf == NULL)
545 +    tf = search_trampolines (tinsn, fragP, FALSE); /* Try ones needing a jump-around, too.  */
546 +
547 +  return tf;
548 +}
549 +
550 +
551 +static void
552 +check_and_update_trampolines (void)
553 +{
554 +  struct trampoline_seg *ts = find_trampoline_seg (now_seg);
555 +  struct trampoline_frag *tf = ts->trampoline_list.next;
556 +  struct trampoline_frag *prev = &ts->trampoline_list;
557 +
558 +  for ( ; tf; prev = tf, tf = tf->next)
559 +    {
560 +      if (tf->fragP->fr_var < 3)
561 +       {
562 +         frag_wane (tf->fragP);
563 +         prev->next = tf->next;
564 +         tf->fragP = NULL;
565 +       }
566 +    }
567 +}
568 +
569 +
570 +static int
571 +init_trampoline_frag (struct trampoline_frag *trampP)
572 +{
573 +  fragS *fp = trampP->fragP;
574 +  int growth = 0;
575 +
576 +  if (fp->fr_fix == 0)
577 +    {
578 +      symbolS *lsym;
579 +      char label[10 + 2 * sizeof(fp)];
580 +      sprintf (label, ".L0_TR_%p", fp);
581 +
582 +      lsym = (symbolS *)local_symbol_make (label, now_seg, 0, fp);
583 +      fp->fr_symbol = lsym;
584 +      if (trampP->needs_jump_around)
585 +        {
586 +         /* Add a jump around this block of jumps, in case
587 +            control flows into this block.  */
588 +         fixS *fixP;
589 +         TInsn insn;
590 +         xtensa_format fmt;
591 +         xtensa_isa isa = xtensa_default_isa;
592 +
593 +         fp->tc_frag_data.is_insn = 1;
594 +         /* Assemble a jump insn.  */
595 +         tinsn_init (&insn);
596 +         insn.insn_type = ITYPE_INSN;
597 +         insn.opcode = xtensa_j_opcode;
598 +         insn.ntok = 1;
599 +         set_expr_symbol_offset (&insn.tok[0], lsym, 3);
600 +         fmt = xg_get_single_format (xtensa_j_opcode);
601 +         tinsn_to_slotbuf (fmt, 0, &insn, trampoline_slotbuf);
602 +         xtensa_format_set_slot (isa, fmt, 0, trampoline_buf, trampoline_slotbuf);
603 +         xtensa_insnbuf_to_chars (isa, trampoline_buf, (unsigned char *)fp->fr_literal, 3);
604 +         fp->fr_fix += 3;
605 +         fp->fr_var -= 3;
606 +         growth = 3;
607 +         fixP = fix_new (fp, 0, 3, lsym, 3, TRUE, BFD_RELOC_XTENSA_SLOT0_OP);
608 +         trampP->fixP = fixP;
609 +        }
610 +    }
611 +  return growth;
612 +}
613 +
614 +
615 +static int
616 +add_jump_to_trampoline (struct trampoline_frag *trampP, fragS *origfrag)
617 +{
618 +  fragS *tramp = trampP->fragP;
619 +  fixS *fixP;
620 +  int offset = tramp->fr_fix; /* Where to assemble the j insn.  */
621 +  TInsn insn;
622 +  symbolS *lsym;
623 +  symbolS *tsym;
624 +  int toffset;
625 +  xtensa_format fmt;
626 +  xtensa_isa isa = xtensa_default_isa;
627 +  int growth = 0;
628 +
629 +  lsym = tramp->fr_symbol;
630 +  /* Assemble a jump to the target label in the trampoline frag.  */
631 +  tsym = origfrag->tc_frag_data.slot_symbols[0];
632 +  toffset = origfrag-> tc_frag_data.slot_offsets[0];
633 +  tinsn_init (&insn);
634 +  insn.insn_type = ITYPE_INSN;
635 +  insn.opcode = xtensa_j_opcode;
636 +  insn.ntok = 1;
637 +  set_expr_symbol_offset (&insn.tok[0], tsym, toffset);
638 +  fmt = xg_get_single_format (xtensa_j_opcode);
639 +  tinsn_to_slotbuf (fmt, 0, &insn, trampoline_slotbuf);
640 +  xtensa_format_set_slot (isa, fmt, 0, trampoline_buf, trampoline_slotbuf);
641 +  xtensa_insnbuf_to_chars (isa, trampoline_buf, (unsigned char *)tramp->fr_literal + offset, 3);
642 +  tramp->fr_fix += 3;
643 +  tramp->fr_var -= 3;
644 +  growth = 3;
645 +  /* add a fix-up for the trampoline jump.  */
646 +  fixP = fix_new (tramp, tramp->fr_fix - 3, 3, tsym, toffset, TRUE, BFD_RELOC_XTENSA_SLOT0_OP);
647 +  /* Modify the jump at the start of this trampoline to point past the newly-added jump.  */
648 +  fixP = trampP->fixP;
649 +  if (fixP)
650 +    fixP->fx_offset += 3;
651 +  /* Modify the original j to point here.  */
652 +  origfrag->tc_frag_data.slot_symbols[0] = lsym;
653 +  origfrag->tc_frag_data.slot_offsets[0] = tramp->fr_fix - 3;
654 +  /* If trampoline is full, remove it from the list.  */
655 +  check_and_update_trampolines ();
656 +
657 +  return growth;
658 +}
659 +
660 +
661  static long
662  relax_frag_immed (segT segP,
663                   fragS *fragP,
664 @@ -9284,6 +9804,37 @@ relax_frag_immed (segT segP,
665    if (negatable_branch && istack.ninsn > 1)
666      update_next_frag_state (fragP);
667  
668 +  /* If last insn is a jump, and it cannot reach its target, try to find a trampoline.  */
669 +  if (istack.ninsn > 2 &&
670 +      istack.insn[istack.ninsn - 1].insn_type == ITYPE_LABEL &&
671 +      istack.insn[istack.ninsn - 2].insn_type == ITYPE_INSN &&
672 +      istack.insn[istack.ninsn - 2].opcode == xtensa_j_opcode)
673 +    {
674 +      TInsn *jinsn = &istack.insn[istack.ninsn - 2];
675 +
676 +      if (!xg_symbolic_immeds_fit (jinsn, segP, fragP, fragP->fr_offset, total_text_diff))
677 +       {
678 +         struct trampoline_frag *tf = get_best_trampoline (jinsn, fragP);
679 +
680 +         if (tf)
681 +           {
682 +             this_text_diff += init_trampoline_frag (tf);
683 +             this_text_diff += add_jump_to_trampoline (tf, fragP);
684 +           }
685 +         else
686 +           {
687 +             /* If target symbol is undefined, assume it will reach once linked.  */
688 +             expressionS *exp = &istack.insn[istack.ninsn - 2].tok[0];
689 +
690 +             if (exp->X_op == O_symbol && S_IS_DEFINED (exp->X_add_symbol))
691 +               {
692 +                 as_bad_where (fragP->fr_file, fragP->fr_line,
693 +                   _("jump target out of range; no usable trampoline found"));
694 +               }
695 +           }
696 +       }
697 +    }
698 +
699    return this_text_diff;
700  }
701  
702 @@ -9404,6 +9955,9 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragp)
703        else
704         as_bad (_("invalid relaxation fragment result"));
705        break;
706 +
707 +    case RELAX_TRAMPOLINE:
708 +      break;
709      }
710  
711    fragp->fr_var = 0;
712 diff --git a/gas/config/tc-xtensa.h b/gas/config/tc-xtensa.h
713 index 0bf1240..4672bc6 100644
714 --- a/gas/config/tc-xtensa.h
715 +++ b/gas/config/tc-xtensa.h
716 @@ -180,6 +180,11 @@ enum xtensa_relax_statesE
717       prevent the linker from changing the size of any frag between the
718       section start and the org frag.  */
719  
720 +  RELAX_TRAMPOLINE,
721 +  /* Every few thousand frags, we insert one of these, just in case we may
722 +     need some space for a trampoline (jump to a jump) because the function
723 +     has gotten too big. If not needed, it disappears. */
724 +
725    RELAX_NONE
726  };
727  
728 diff --git a/gas/frags.c b/gas/frags.c
729 index 5f68480..e14099d 100644
730 --- a/gas/frags.c
731 +++ b/gas/frags.c
732 @@ -24,6 +24,20 @@
733  
734  extern fragS zero_address_frag;
735  extern fragS predefined_address_frag;
736 +
737 +static int totalfrags;
738 +
739 +int
740 +get_frag_count (void)
741 +{
742 +  return totalfrags;
743 +}
744 +
745 +void
746 +clear_frag_count (void)
747 +{
748 +  totalfrags = 0;
749 +}
750  \f
751  /* Initialization for frag routines.  */
752  
753 @@ -70,6 +84,7 @@ frag_alloc (struct obstack *ob)
754    ptr = (fragS *) obstack_alloc (ob, SIZEOF_STRUCT_FRAG);
755    obstack_alignment_mask (ob) = oalign;
756    memset (ptr, 0, SIZEOF_STRUCT_FRAG);
757 +  totalfrags++;
758    return ptr;
759  }
760  \f
761 diff --git a/gas/frags.h b/gas/frags.h
762 index 319898f..2f9e1b5 100644
763 --- a/gas/frags.h
764 +++ b/gas/frags.h
765 @@ -155,4 +155,7 @@ char *frag_var (relax_stateT type,
766  
767  bfd_boolean frag_offset_fixed_p (const fragS *, const fragS *, offsetT *);
768  
769 +int get_frag_count (void);
770 +void clear_frag_count (void);
771 +
772  #endif /* FRAGS_H */
773 diff --git a/gas/testsuite/gas/xtensa/all.exp b/gas/testsuite/gas/xtensa/all.exp
774 index 2b2c294..3683b78 100644
775 --- a/gas/testsuite/gas/xtensa/all.exp
776 +++ b/gas/testsuite/gas/xtensa/all.exp
777 @@ -98,6 +98,7 @@ if [istarget xtensa*-*-*] then {
778      run_dump_test "pcrel"
779      run_dump_test "weak-call"
780      run_dump_test "jlong"
781 +    run_dump_test "trampoline"
782  }
783  
784  if [info exists errorInfo] then {
785 diff --git a/gas/testsuite/gas/xtensa/trampoline.d b/gas/testsuite/gas/xtensa/trampoline.d
786 new file mode 100644
787 index 0000000..b4f65dc
788 --- /dev/null
789 +++ b/gas/testsuite/gas/xtensa/trampoline.d
790 @@ -0,0 +1,26 @@
791 +#as:
792 +#objdump: -d
793 +#name: trampolines relaxation
794 +
795 +.*: +file format .*xtensa.*
796 +#...
797 +.*0:.*j.0x1194c
798 +.*3:.*j.0x1194f
799 +.*6:.*j.0x11952
800 +.*9:.*j.0x1d4e4
801 +#...
802 +.*11949:.*j.0x11955
803 +.*1194c:.*j.0x24a0e
804 +.*1194f:.*j.0x24a0e
805 +.*11952:.*j.0x24a11
806 +#...
807 +.*1d4e1:.*j.0x1d4e7
808 +.*1d4e4:.*j.0x33462
809 +#...
810 +.*24a0e:.*j.0x24a0e
811 +.*24a11:.*j.0x24a11
812 +#...
813 +.*3345f:.*ret
814 +.*33462:.*j.0x49407
815 +#...
816 +.*49407:.*j.0x49407
817 diff --git a/gas/testsuite/gas/xtensa/trampoline.s b/gas/testsuite/gas/xtensa/trampoline.s
818 new file mode 100644
819 index 0000000..259a3bb
820 --- /dev/null
821 +++ b/gas/testsuite/gas/xtensa/trampoline.s
822 @@ -0,0 +1,21 @@
823 +       .text
824 +       j       1f
825 +       j       1f
826 +       j       2f
827 +       j       3f
828 +       .rep    25000
829 +99:
830 +       and     a2, a2, a3
831 +       bne     a2, a3, 99b
832 +       .endr
833 +1:
834 +       j       1b
835 +2:
836 +       j       2b
837 +
838 +       .rep    25000
839 +       and     a2, a2, a3
840 +       _ret
841 +       .endr
842 +3:
843 +       j       3b
844 -- 
845 1.8.1.4
846