]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - ld/emultempl/xtensaelf.em
bfd/
[thirdparty/binutils-gdb.git] / ld / emultempl / xtensaelf.em
CommitLineData
e0001a05 1# This shell script emits a C file. -*- C -*-
eea6121a 2# Copyright 2003, 2004
e0001a05
NC
3# Free Software Foundation, Inc.
4#
5# This file is part of GLD, the Gnu Linker.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20#
21
22# This file is sourced from elf32.em, and defines extra xtensa-elf
23# specific routines.
24#
25cat >>e${EMULATION_NAME}.c <<EOF
26
27#include <xtensa-config.h>
28
0c7a8e5a
AM
29static void xtensa_wild_group_interleave (lang_statement_union_type *);
30static void xtensa_colocate_output_literals (lang_statement_union_type *);
e0001a05
NC
31
32
33/* Flag for the emulation-specific "--no-relax" option. */
34static bfd_boolean disable_relaxation = FALSE;
35
36/* This number is irrelevant until we turn on use_literal_pages */
37static bfd_vma xtensa_page_power = 12; /* 4K pages. */
38
39/* To force a page break between literals and text, change
40 xtensa_use_literal_pages to "true". */
41static bfd_boolean xtensa_use_literal_pages = FALSE;
42
43#define EXTRA_VALIDATION 0
44
45
46static char *
0c7a8e5a
AM
47elf_xtensa_choose_target (int argc ATTRIBUTE_UNUSED,
48 char **argv ATTRIBUTE_UNUSED)
e0001a05
NC
49{
50 if (XCHAL_HAVE_BE)
51 return "${BIG_OUTPUT_FORMAT}";
52 else
53 return "${LITTLE_OUTPUT_FORMAT}";
54}
55
56
57static bfd_boolean
0c7a8e5a 58elf_xtensa_place_orphan (lang_input_statement_type *file, asection *s)
e0001a05
NC
59{
60 /* Early exit for relocatable links. */
1049f94e 61 if (link_info.relocatable)
e0001a05
NC
62 return FALSE;
63
64 return gld${EMULATION_NAME}_place_orphan (file, s);
65}
66
67
68static void
0c7a8e5a 69elf_xtensa_before_parse (void)
e0001a05
NC
70{
71 /* Just call the default hook.... Tensilica's version of this function
72 does some other work that isn't relevant here. */
73 gld${EMULATION_NAME}_before_parse ();
74}
75
76
77/* This is called after the sections have been attached to output
78 sections, but before any sizes or addresses have been set. */
79
0c7a8e5a
AM
80static void
81elf_xtensa_before_allocation (void)
e0001a05
NC
82{
83 bfd *in_bfd;
84 bfd_boolean is_big_endian = XCHAL_HAVE_BE;
85
86 /* Check that the output endianness matches the Xtensa
87 configuration. The BFD library always includes both big and
88 little endian target vectors for Xtensa, but it only supports the
89 detailed instruction encode/decode operations (such as are
90 required to process relocations) for the selected Xtensa
91 configuration. */
92
93 if (is_big_endian && output_bfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
94 {
95 einfo (_("%F%P: little endian output does not match "
96 "Xtensa configuration\n"));
97 }
98 if (!is_big_endian && output_bfd->xvec->byteorder == BFD_ENDIAN_BIG)
99 {
100 einfo (_("%F%P: big endian output does not match "
101 "Xtensa configuration\n"));
102 }
103
104 /* Check that the endianness for each input file matches the output.
105 The merge_private_bfd_data hook has already reported any mismatches
106 as errors, but those errors are not fatal. At this point, we
107 cannot go any further if there are any mismatches. */
108
109 for (in_bfd = link_info.input_bfds;
110 in_bfd != NULL;
111 in_bfd = in_bfd->link_next)
112 {
113 if ((is_big_endian && in_bfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
114 || (!is_big_endian && in_bfd->xvec->byteorder == BFD_ENDIAN_BIG))
115 einfo (_("%F%P: cross-endian linking not supported\n"));
116 }
117
118 /* Enable relaxation by default if the "--no-relax" option was not
119 specified. This is done here instead of in the before_parse hook
120 because there is a check in main() to prohibit use of --relax and
121 -r together and that combination should be allowed for Xtensa. */
122
123 if (!disable_relaxation)
124 command_line.relax = TRUE;
125
126 gld${EMULATION_NAME}_before_allocation ();
127
128 xtensa_wild_group_interleave (stat_ptr->head);
0c7a8e5a 129 if (command_line.relax)
e0001a05
NC
130 xtensa_colocate_output_literals (stat_ptr->head);
131
132 /* TBD: We need to force the page alignments to here and only do
133 them as needed for the entire output section. Finally, if this
1049f94e 134 is a relocatable link then we need to add alignment notes so
e0001a05
NC
135 that the literals can be separated later. */
136}
137
138
139typedef struct wildcard_list section_name_list;
140
141typedef struct reloc_deps_e_t reloc_deps_e;
142typedef struct reloc_deps_section_t reloc_deps_section;
143typedef struct reloc_deps_graph_t reloc_deps_graph;
144
145
146struct reloc_deps_e_t
147{
148 asection *src; /* Contains l32rs. */
149 asection *tgt; /* Contains literals. */
150 reloc_deps_e *next;
151};
152
153/* Place these in the userdata field. */
154struct reloc_deps_section_t
155{
156 reloc_deps_e *preds;
157 reloc_deps_e *succs;
158 bfd_boolean is_only_literal;
159};
160
161
162struct reloc_deps_graph_t
163{
164 size_t count;
165 size_t size;
166 asection **sections;
167};
168
169static void xtensa_layout_wild
0c7a8e5a 170 (const reloc_deps_graph *, lang_wild_statement_type *);
e0001a05 171
0c7a8e5a
AM
172typedef void (*deps_callback_t) (asection *, /* src_sec */
173 bfd_vma, /* src_offset */
174 asection *, /* target_sec */
175 bfd_vma, /* target_offset */
176 void *); /* closure */
e0001a05 177
e0001a05 178extern bfd_boolean xtensa_callback_required_dependence
0c7a8e5a 179 (bfd *, asection *, struct bfd_link_info *, deps_callback_t, void *);
e0001a05 180static void xtensa_ldlang_clear_addresses
0c7a8e5a 181 (lang_statement_union_type *);
e0001a05 182static bfd_boolean ld_local_file_relocations_fit
0c7a8e5a 183 (lang_statement_union_type *, const reloc_deps_graph *);
e0001a05 184static bfd_vma ld_assign_relative_paged_dot
0c7a8e5a
AM
185 (bfd_vma, lang_statement_union_type *, const reloc_deps_graph *,
186 bfd_boolean);
e0001a05 187static bfd_vma ld_xtensa_insert_page_offsets
0c7a8e5a 188 (bfd_vma, lang_statement_union_type *, reloc_deps_graph *, bfd_boolean);
e0001a05
NC
189#if EXTRA_VALIDATION
190static size_t ld_count_children
0c7a8e5a 191 (lang_statement_union_type *);
e0001a05 192#endif
e0001a05
NC
193
194extern lang_statement_list_type constructor_list;
195
196/* Begin verbatim code from ldlang.c:
197 the following are copied from ldlang.c because they are defined
198 there statically. */
199
200static void
0c7a8e5a
AM
201lang_for_each_statement_worker (void (*func) (lang_statement_union_type *),
202 lang_statement_union_type *s)
e0001a05
NC
203{
204 for (; s != (lang_statement_union_type *) NULL; s = s->header.next)
205 {
206 func (s);
207
208 switch (s->header.type)
0c7a8e5a
AM
209 {
210 case lang_constructors_statement_enum:
211 lang_for_each_statement_worker (func, constructor_list.head);
212 break;
213 case lang_output_section_statement_enum:
214 lang_for_each_statement_worker
215 (func,
216 s->output_section_statement.children.head);
217 break;
218 case lang_wild_statement_enum:
219 lang_for_each_statement_worker
220 (func,
221 s->wild_statement.children.head);
222 break;
223 case lang_group_statement_enum:
224 lang_for_each_statement_worker (func,
225 s->group_statement.children.head);
226 break;
227 case lang_data_statement_enum:
228 case lang_reloc_statement_enum:
229 case lang_object_symbols_statement_enum:
230 case lang_output_statement_enum:
231 case lang_target_statement_enum:
232 case lang_input_section_enum:
233 case lang_input_statement_enum:
234 case lang_assignment_statement_enum:
235 case lang_padding_statement_enum:
236 case lang_address_statement_enum:
237 case lang_fill_statement_enum:
238 break;
239 default:
240 FAIL ();
241 break;
242 }
e0001a05
NC
243 }
244}
245
246/* End of verbatim code from ldlang.c. */
247
248
0c7a8e5a
AM
249static reloc_deps_section *
250xtensa_get_section_deps (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
251 asection *sec)
e0001a05
NC
252{
253 /* We have a separate function for this so that
254 we could in the future keep a completely independent
255 structure that maps a section to its dependence edges.
256 For now, we place these in the sec->userdata field. */
0c7a8e5a 257 reloc_deps_section *sec_deps = sec->userdata;
e0001a05
NC
258 return sec_deps;
259}
260
0c7a8e5a
AM
261static void
262xtensa_set_section_deps (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
263 asection *sec,
264 reloc_deps_section *deps_section)
e0001a05 265{
0c7a8e5a 266 sec->userdata = deps_section;
e0001a05
NC
267}
268
269
270/* This is used to keep a list of all of the sections participating in
271 the graph so we can clean them up quickly. */
272
0c7a8e5a
AM
273static void
274xtensa_append_section_deps (reloc_deps_graph *deps, asection *sec)
e0001a05
NC
275{
276 if (deps->size <= deps->count)
277 {
278 asection **new_sections;
279 size_t i;
280 size_t new_size;
0c7a8e5a 281
e0001a05
NC
282 new_size = deps->size * 2;
283 if (new_size == 0)
284 new_size = 20;
0c7a8e5a
AM
285
286 new_sections = xmalloc (sizeof (asection *) * new_size);
287 memset (new_sections, 0, sizeof (asection *) * new_size);
288 for (i = 0; i < deps->count; i++)
e0001a05
NC
289 {
290 new_sections[i] = deps->sections[i];
291 }
292 if (deps->sections != NULL)
293 free (deps->sections);
294 deps->sections = new_sections;
295 deps->size = new_size;
296 }
297 deps->sections[deps->count] = sec;
298 deps->count++;
299}
300
301
0c7a8e5a
AM
302static void
303free_reloc_deps_graph (reloc_deps_graph *deps)
e0001a05
NC
304{
305 size_t i;
306 for (i = 0; i < deps->count; i++)
307 {
308 asection *sec = deps->sections[i];
309 reloc_deps_section *sec_deps;
310 sec_deps = xtensa_get_section_deps (deps, sec);
0c7a8e5a 311 if (sec_deps)
e0001a05
NC
312 {
313 reloc_deps_e *next;
314 while (sec_deps->succs != NULL)
315 {
316 next = sec_deps->succs->next;
317 free (sec_deps->succs);
318 sec_deps->succs = next;
319 }
0c7a8e5a 320
e0001a05
NC
321 while (sec_deps->preds != NULL)
322 {
323 next = sec_deps->preds->next;
324 free (sec_deps->preds);
325 sec_deps->preds = next;
326 }
327 free (sec_deps);
328 }
329 xtensa_set_section_deps (deps, sec, NULL);
330 }
331 if (deps->sections)
332 free (deps->sections);
333
334 free (deps);
335}
336
337
0c7a8e5a
AM
338static bfd_boolean
339section_is_source (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
340 lang_statement_union_type *s)
e0001a05
NC
341{
342 asection *sec;
343 const reloc_deps_section *sec_deps;
344
345 if (s->header.type != lang_input_section_enum)
346 return FALSE;
347 sec = s->input_section.section;
348
349 sec_deps = xtensa_get_section_deps (deps, sec);
0c7a8e5a 350 return sec_deps && sec_deps->succs != NULL;
e0001a05
NC
351}
352
353
0c7a8e5a
AM
354static bfd_boolean
355section_is_target (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
356 lang_statement_union_type *s)
e0001a05
NC
357{
358 asection *sec;
359 const reloc_deps_section *sec_deps;
360
361 if (s->header.type != lang_input_section_enum)
362 return FALSE;
363 sec = s->input_section.section;
364
365 sec_deps = xtensa_get_section_deps (deps, sec);
0c7a8e5a 366 return sec_deps && sec_deps->preds != NULL;
e0001a05
NC
367}
368
0c7a8e5a
AM
369static bfd_boolean
370section_is_source_or_target (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
371 lang_statement_union_type *s)
e0001a05
NC
372{
373 return (section_is_source (deps, s)
374 || section_is_target (deps, s));
375}
376
377
378typedef struct xtensa_ld_iter_stack_t xtensa_ld_iter_stack;
379typedef struct xtensa_ld_iter_t xtensa_ld_iter;
380
381struct xtensa_ld_iter_t
382{
383 lang_statement_union_type *parent; /* Parent of the list. */
384 lang_statement_list_type *l; /* List that holds it. */
385 lang_statement_union_type **loc; /* Place in the list. */
386};
387
388struct xtensa_ld_iter_stack_t
389{
390 xtensa_ld_iter iterloc; /* List that hold it. */
0c7a8e5a 391
e0001a05
NC
392 xtensa_ld_iter_stack *next; /* Next in the stack. */
393 xtensa_ld_iter_stack *prev; /* Back pointer for stack. */
394};
395
e0001a05 396
0c7a8e5a
AM
397static void
398ld_xtensa_move_section_after (xtensa_ld_iter *to, xtensa_ld_iter *current)
e0001a05
NC
399{
400 lang_statement_union_type *to_next;
401 lang_statement_union_type *current_next;
402 lang_statement_union_type **e;
403
404#if EXTRA_VALIDATION
405 size_t old_to_count, new_to_count;
406 size_t old_current_count, new_current_count;
407#endif
408
409 if (to == current)
410 return;
0c7a8e5a 411
e0001a05
NC
412#if EXTRA_VALIDATION
413 old_to_count = ld_count_children (to->parent);
414 old_current_count = ld_count_children (current->parent);
415#endif
416
417 to_next = *(to->loc);
418 current_next = (*current->loc)->header.next;
0c7a8e5a 419
e0001a05 420 *(to->loc) = *(current->loc);
0c7a8e5a 421
e0001a05
NC
422 *(current->loc) = current_next;
423 (*(to->loc))->header.next = to_next;
424
425 /* reset "to" list tail */
426 for (e = &to->l->head; *e != NULL; e = &(*e)->header.next)
427 ;
428 to->l->tail = e;
429
430 /* reset "current" list tail */
431 for (e = &current->l->head; *e != NULL; e = &(*e)->header.next)
432 ;
433 current->l->tail = e;
434
435#if EXTRA_VALIDATION
436 new_to_count = ld_count_children (to->parent);
437 new_current_count = ld_count_children (current->parent);
438
0c7a8e5a 439 ASSERT ((old_to_count + old_current_count)
e0001a05
NC
440 == (new_to_count + new_current_count));
441#endif
442}
443
444
445/* Can only be called with lang_statements that have lists. Returns
446 false if the list is empty. */
447
0c7a8e5a
AM
448static bfd_boolean
449iter_stack_empty (xtensa_ld_iter_stack **stack_p)
e0001a05 450{
0c7a8e5a 451 return *stack_p == NULL;
e0001a05
NC
452}
453
454
455static bfd_boolean
0c7a8e5a
AM
456iter_stack_push (xtensa_ld_iter_stack **stack_p,
457 lang_statement_union_type *parent)
e0001a05
NC
458{
459 xtensa_ld_iter_stack *stack;
460 lang_statement_list_type *l = NULL;
461
0c7a8e5a 462 switch (parent->header.type)
e0001a05
NC
463 {
464 case lang_output_section_statement_enum:
465 l = &parent->output_section_statement.children;
466 break;
467 case lang_wild_statement_enum:
468 l = &parent->wild_statement.children;
469 break;
470 case lang_group_statement_enum:
471 l = &parent->group_statement.children;
472 break;
473 default:
474 ASSERT (0);
475 return FALSE;
476 }
477
478 /* Empty. do not push. */
0c7a8e5a 479 if (l->tail == &l->head)
e0001a05
NC
480 return FALSE;
481
0c7a8e5a 482 stack = xmalloc (sizeof (xtensa_ld_iter_stack));
e0001a05
NC
483 memset (stack, 0, sizeof (xtensa_ld_iter_stack));
484 stack->iterloc.parent = parent;
485 stack->iterloc.l = l;
486 stack->iterloc.loc = &l->head;
487
488 stack->next = *stack_p;
489 stack->prev = NULL;
0c7a8e5a 490 if (*stack_p != NULL)
e0001a05
NC
491 (*stack_p)->prev = stack;
492 *stack_p = stack;
493 return TRUE;
494}
495
496
0c7a8e5a
AM
497static void
498iter_stack_pop (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
499{
500 xtensa_ld_iter_stack *stack;
501
502 stack = *stack_p;
503
0c7a8e5a 504 if (stack == NULL)
e0001a05
NC
505 {
506 ASSERT (stack != NULL);
507 return;
508 }
509
0c7a8e5a 510 if (stack->next != NULL)
e0001a05
NC
511 stack->next->prev = NULL;
512
513 *stack_p = stack->next;
514 free (stack);
515}
516
517
518/* This MUST be called if, during iteration, the user changes the
519 underlying structure. It will check for a NULL current and advance
520 accordingly. */
521
522static void
0c7a8e5a 523iter_stack_update (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
524{
525 if (!iter_stack_empty (stack_p)
0c7a8e5a 526 && (*(*stack_p)->iterloc.loc) == NULL)
e0001a05
NC
527 {
528 iter_stack_pop (stack_p);
529
530 while (!iter_stack_empty (stack_p)
531 && ((*(*stack_p)->iterloc.loc)->header.next == NULL))
532 {
533 iter_stack_pop (stack_p);
534 }
535 if (!iter_stack_empty (stack_p))
536 (*stack_p)->iterloc.loc = &(*(*stack_p)->iterloc.loc)->header.next;
537 }
538}
539
540
0c7a8e5a
AM
541static void
542iter_stack_next (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
543{
544 xtensa_ld_iter_stack *stack;
545 lang_statement_union_type *current;
546 stack = *stack_p;
547
548 current = *stack->iterloc.loc;
549 /* If we are on the first element. */
0c7a8e5a 550 if (current != NULL)
e0001a05 551 {
0c7a8e5a 552 switch (current->header.type)
e0001a05
NC
553 {
554 case lang_output_section_statement_enum:
555 case lang_wild_statement_enum:
556 case lang_group_statement_enum:
557 /* If the list if not empty, we are done. */
558 if (iter_stack_push (stack_p, *stack->iterloc.loc))
559 return;
560 /* Otherwise increment the pointer as normal. */
561 break;
562 default:
563 break;
564 }
565 }
566
567 while (!iter_stack_empty (stack_p)
568 && ((*(*stack_p)->iterloc.loc)->header.next == NULL))
569 {
570 iter_stack_pop (stack_p);
571 }
572 if (!iter_stack_empty (stack_p))
573 (*stack_p)->iterloc.loc = &(*(*stack_p)->iterloc.loc)->header.next;
574}
575
576
577static lang_statement_union_type *
0c7a8e5a 578iter_stack_current (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
579{
580 return *((*stack_p)->iterloc.loc);
581}
582
583
584/* The iter stack is a preorder. */
585
0c7a8e5a
AM
586static void
587iter_stack_create (xtensa_ld_iter_stack **stack_p,
588 lang_statement_union_type *parent)
e0001a05
NC
589{
590 iter_stack_push (stack_p, parent);
591}
592
593
0c7a8e5a
AM
594static void
595iter_stack_copy_current (xtensa_ld_iter_stack **stack_p,
596 xtensa_ld_iter *front)
e0001a05
NC
597{
598 *front = (*stack_p)->iterloc;
599}
600
601
0c7a8e5a
AM
602static void
603xtensa_colocate_literals (reloc_deps_graph *deps,
604 lang_statement_union_type *statement)
e0001a05
NC
605{
606 /* Keep a stack of pointers to control iteration through the contours. */
607 xtensa_ld_iter_stack *stack = NULL;
608 xtensa_ld_iter_stack **stack_p = &stack;
609
610 xtensa_ld_iter front; /* Location where new insertion should occur. */
611 xtensa_ld_iter *front_p = NULL;
612
613 xtensa_ld_iter current; /* Location we are checking. */
614 xtensa_ld_iter *current_p = NULL;
615 bfd_boolean in_literals = FALSE;
616
617 if (deps->count == 0)
618 return;
619
620#if 0
621 ld_assign_relative_paged_dot (0x100000, statement, deps,
622 xtensa_use_literal_pages);
623
624 if (!ld_local_file_relocations_fit (statement, deps))
625 fprintf (stderr, "initial relocation placement does not fit\n");
626
627 lang_for_each_statement_worker (xtensa_ldlang_clear_addresses, statement);
628#endif
0c7a8e5a 629
e0001a05
NC
630 iter_stack_create (stack_p, statement);
631
0c7a8e5a 632 while (!iter_stack_empty (stack_p))
e0001a05
NC
633 {
634 bfd_boolean skip_increment = FALSE;
635 lang_statement_union_type *l = iter_stack_current (stack_p);
0c7a8e5a
AM
636
637 switch (l->header.type)
e0001a05
NC
638 {
639 case lang_assignment_statement_enum:
640 /* Any assignment statement should block reordering across it. */
641 front_p = NULL;
642 in_literals = FALSE;
643 break;
644
645 case lang_input_section_enum:
646 if (front_p == NULL)
647 {
648 in_literals = (section_is_target (deps, l)
649 && !section_is_source (deps, l));
0c7a8e5a 650 if (in_literals)
e0001a05
NC
651 {
652 front_p = &front;
653 iter_stack_copy_current (stack_p, front_p);
654 }
0c7a8e5a 655 }
e0001a05
NC
656 else
657 {
658 bfd_boolean is_target;
659 current_p = &current;
660 iter_stack_copy_current (stack_p, current_p);
661 is_target = (section_is_target (deps, l)
662 && !section_is_source (deps, l));
663
664 if (in_literals)
665 {
666 iter_stack_copy_current (stack_p, front_p);
667 if (!is_target)
668 in_literals = FALSE;
669 }
670 else
671 {
0c7a8e5a 672 if (is_target)
e0001a05
NC
673 {
674 /* Try to insert in place. */
675 ld_xtensa_move_section_after (front_p, current_p);
0c7a8e5a 676 ld_assign_relative_paged_dot (0x100000,
e0001a05
NC
677 statement,
678 deps,
679 xtensa_use_literal_pages);
0c7a8e5a 680
e0001a05
NC
681 /* We use this code because it's already written. */
682 if (!ld_local_file_relocations_fit (statement, deps))
683 {
684 /* Move it back. */
685 ld_xtensa_move_section_after (current_p, front_p);
686 /* Reset the literal placement. */
687 iter_stack_copy_current (stack_p, front_p);
688 }
0c7a8e5a 689 else
e0001a05
NC
690 {
691 /* Move front pointer up by one. */
692 front_p->loc = &(*front_p->loc)->header.next;
693
694 /* Do not increment the current pointer. */
695 skip_increment = TRUE;
696 }
697 }
698 }
699 }
700 break;
701 default:
702 break;
703 }
704
705 if (!skip_increment)
706 iter_stack_next (stack_p);
707 else
708 /* Be careful to update the stack_p if it now is a null. */
709 iter_stack_update (stack_p);
710 }
0c7a8e5a 711
e0001a05
NC
712 lang_for_each_statement_worker (xtensa_ldlang_clear_addresses, statement);
713}
714
715
0c7a8e5a
AM
716static void
717xtensa_move_dependencies_to_front (reloc_deps_graph *deps,
718 lang_wild_statement_type *w)
e0001a05
NC
719{
720 /* Keep a front pointer and a current pointer. */
721 lang_statement_union_type **front;
722 lang_statement_union_type **current;
723
724 /* Walk to the end of the targets. */
725 for (front = &w->children.head;
726 (*front != NULL) && section_is_source_or_target (deps, *front);
727 front = &(*front)->header.next)
728 ;
729
730 if (*front == NULL)
731 return;
732
733 current = &(*front)->header.next;
0c7a8e5a 734 while (*current != NULL)
e0001a05
NC
735 {
736 if (section_is_source_or_target (deps, *current))
737 {
738 /* Insert in place. */
739 xtensa_ld_iter front_iter;
740 xtensa_ld_iter current_iter;
741
742 front_iter.parent = (lang_statement_union_type *) w;
743 front_iter.l = &w->children;
744 front_iter.loc = front;
745
746 current_iter.parent = (lang_statement_union_type *) w;
747 current_iter.l = &w->children;
748 current_iter.loc = current;
749
750 ld_xtensa_move_section_after (&front_iter, &current_iter);
751 front = &(*front)->header.next;
752 }
753 else
754 {
755 current = &(*current)->header.next;
756 }
757 }
758}
759
760
761static bfd_boolean
0c7a8e5a
AM
762deps_has_sec_edge (const reloc_deps_graph *deps,
763 asection *src,
764 asection *tgt)
e0001a05
NC
765{
766 const reloc_deps_section *sec_deps;
767 const reloc_deps_e *sec_deps_e;
768
769 sec_deps = xtensa_get_section_deps (deps, src);
770 if (sec_deps == NULL)
771 return FALSE;
0c7a8e5a 772
e0001a05 773 for (sec_deps_e = sec_deps->succs;
0c7a8e5a 774 sec_deps_e != NULL;
e0001a05
NC
775 sec_deps_e = sec_deps_e->next)
776 {
777 ASSERT (sec_deps_e->src == src);
0c7a8e5a 778 if (sec_deps_e->tgt == tgt)
e0001a05
NC
779 return TRUE;
780 }
781 return FALSE;
782}
783
784
785static bfd_boolean
0c7a8e5a
AM
786deps_has_edge (const reloc_deps_graph *deps,
787 lang_statement_union_type *src,
788 lang_statement_union_type *tgt)
e0001a05
NC
789{
790 if (!section_is_source (deps, src))
791 return FALSE;
792 if (!section_is_target (deps, tgt))
793 return FALSE;
794
795 if (src->header.type != lang_input_section_enum)
796 return FALSE;
797 if (tgt->header.type != lang_input_section_enum)
798 return FALSE;
0c7a8e5a 799
e0001a05
NC
800 return deps_has_sec_edge (deps, src->input_section.section,
801 tgt->input_section.section);
802}
803
804
805static void
0c7a8e5a
AM
806add_deps_edge (reloc_deps_graph *deps,
807 asection *src_sec,
808 asection *tgt_sec)
e0001a05
NC
809{
810 reloc_deps_section *src_sec_deps;
811 reloc_deps_section *tgt_sec_deps;
812
813 reloc_deps_e *src_edge;
814 reloc_deps_e *tgt_edge;
815
816 if (deps_has_sec_edge (deps, src_sec, tgt_sec))
817 return;
0c7a8e5a 818
e0001a05
NC
819 src_sec_deps = xtensa_get_section_deps (deps, src_sec);
820 if (src_sec_deps == NULL)
821 {
822 /* Add a section. */
0c7a8e5a 823 src_sec_deps = xmalloc (sizeof (reloc_deps_section));
e0001a05
NC
824 memset (src_sec_deps, 0, sizeof (reloc_deps_section));
825 src_sec_deps->is_only_literal = 0;
826 src_sec_deps->preds = NULL;
827 src_sec_deps->succs = NULL;
828 xtensa_set_section_deps (deps, src_sec, src_sec_deps);
829 xtensa_append_section_deps (deps, src_sec);
830 }
831
832 tgt_sec_deps = xtensa_get_section_deps (deps, tgt_sec);
833 if (tgt_sec_deps == NULL)
834 {
835 /* Add a section. */
0c7a8e5a 836 tgt_sec_deps = xmalloc (sizeof (reloc_deps_section));
e0001a05
NC
837 memset (tgt_sec_deps, 0, sizeof (reloc_deps_section));
838 tgt_sec_deps->is_only_literal = 0;
839 tgt_sec_deps->preds = NULL;
840 tgt_sec_deps->succs = NULL;
841 xtensa_set_section_deps (deps, tgt_sec, tgt_sec_deps);
842 xtensa_append_section_deps (deps, tgt_sec);
843 }
844
845 /* Add the edges. */
0c7a8e5a 846 src_edge = xmalloc (sizeof (reloc_deps_e));
e0001a05
NC
847 memset (src_edge, 0, sizeof (reloc_deps_e));
848 src_edge->src = src_sec;
849 src_edge->tgt = tgt_sec;
850 src_edge->next = src_sec_deps->succs;
851 src_sec_deps->succs = src_edge;
852
0c7a8e5a 853 tgt_edge = xmalloc (sizeof (reloc_deps_e));
e0001a05
NC
854 memset (tgt_edge, 0, sizeof (reloc_deps_e));
855 tgt_edge->src = src_sec;
856 tgt_edge->tgt = tgt_sec;
857 tgt_edge->next = tgt_sec_deps->preds;
858 tgt_sec_deps->preds = tgt_edge;
859}
860
861
0c7a8e5a
AM
862static void
863build_deps_graph_callback (asection *src_sec,
864 bfd_vma src_offset ATTRIBUTE_UNUSED,
865 asection *target_sec,
866 bfd_vma target_offset ATTRIBUTE_UNUSED,
867 void *closure)
e0001a05 868{
0c7a8e5a 869 reloc_deps_graph *deps = closure;
e0001a05
NC
870
871 /* If the target is defined. */
872 if (target_sec != NULL)
873 add_deps_edge (deps, src_sec, target_sec);
874}
875
876
0c7a8e5a
AM
877static reloc_deps_graph *
878ld_build_required_section_dependence (lang_statement_union_type *s)
e0001a05
NC
879{
880 reloc_deps_graph *deps;
881 xtensa_ld_iter_stack *stack = NULL;
882
0c7a8e5a 883 deps = xmalloc (sizeof (reloc_deps_graph));
e0001a05
NC
884 deps->sections = NULL;
885 deps->count = 0;
886 deps->size = 0;
0c7a8e5a 887
e0001a05
NC
888 for (iter_stack_create (&stack, s);
889 !iter_stack_empty (&stack);
0c7a8e5a 890 iter_stack_next (&stack))
e0001a05
NC
891 {
892 lang_statement_union_type *l = iter_stack_current (&stack);
893
894 if (l->header.type == lang_input_section_enum)
895 {
896 lang_input_section_type *input;
897 input = &l->input_section;
898 xtensa_callback_required_dependence (input->ifile->the_bfd,
899 input->section,
900 &link_info,
901 /* Use the same closure. */
902 build_deps_graph_callback,
0c7a8e5a 903 deps);
e0001a05
NC
904 }
905 }
906 return deps;
907}
908
909
910#if EXTRA_VALIDATION
0c7a8e5a
AM
911static size_t
912ld_count_children (lang_statement_union_type *s)
e0001a05
NC
913{
914 size_t count = 0;
915 xtensa_ld_iter_stack *stack = NULL;
916 for (iter_stack_create (&stack, s);
917 !iter_stack_empty (&stack);
0c7a8e5a 918 iter_stack_next (&stack))
e0001a05
NC
919 {
920 lang_statement_union_type *l = iter_stack_current (&stack);
921 ASSERT (l != NULL);
922 count++;
923 }
924 return count;
925}
926#endif /* EXTRA_VALIDATION */
927
928
0c7a8e5a
AM
929static void
930xtensa_wild_group_interleave_callback (lang_statement_union_type *statement)
e0001a05
NC
931{
932 lang_wild_statement_type *w;
933 reloc_deps_graph *deps;
934 if (statement->header.type == lang_wild_statement_enum)
935 {
936#if EXTRA_VALIDATION
937 size_t old_child_count;
938 size_t new_child_count;
939#endif
940 bfd_boolean no_reorder;
941
942 w = &statement->wild_statement;
943
944 no_reorder = FALSE;
945
946 /* If it has 0 or 1 section bound, then do not reorder. */
947 if (w->children.head == NULL
948 || (w->children.head->header.type == lang_input_section_enum
949 && w->children.head->header.next == NULL))
950 no_reorder = TRUE;
951
952 if (w->filenames_sorted)
953 no_reorder = TRUE;
954
955 /* Check for sorting in a section list wildcard spec as well. */
956 if (!no_reorder)
957 {
958 struct wildcard_list *l;
959 for (l = w->section_list; l != NULL; l = l->next)
960 {
961 if (l->spec.sorted == TRUE)
962 {
963 no_reorder = TRUE;
964 break;
965 }
966 }
0c7a8e5a 967 }
e0001a05
NC
968
969 /* Special case until the NOREORDER linker directive is supported:
0c7a8e5a 970 *(.init) output sections and *(.fini) specs may NOT be reordered. */
e0001a05
NC
971
972 /* Check for sorting in a section list wildcard spec as well. */
0c7a8e5a 973 if (!no_reorder)
e0001a05
NC
974 {
975 struct wildcard_list *l;
976 for (l = w->section_list; l != NULL; l = l->next)
977 {
978 if (l->spec.name
979 && ((strcmp (".init", l->spec.name) == 0)
980 || (strcmp (".fini", l->spec.name) == 0)))
981 {
982 no_reorder = TRUE;
983 break;
984 }
985 }
986 }
987
988#if EXTRA_VALIDATION
989 old_child_count = ld_count_children (statement);
990#endif
991
992 /* It is now officially a target. Build the graph of source
0c7a8e5a 993 section -> target section (kept as a list of edges). */
e0001a05
NC
994 deps = ld_build_required_section_dependence (statement);
995
996 /* If this wildcard does not reorder.... */
997 if (!no_reorder && deps->count != 0)
998 {
999 /* First check for reverse dependences. Fix if possible. */
1000 xtensa_layout_wild (deps, w);
1001
1002 xtensa_move_dependencies_to_front (deps, w);
1003#if EXTRA_VALIDATION
1004 new_child_count = ld_count_children (statement);
1005 ASSERT (new_child_count == old_child_count);
1006#endif
1007
1008 xtensa_colocate_literals (deps, statement);
1009
1010#if EXTRA_VALIDATION
1011 new_child_count = ld_count_children (statement);
1012 ASSERT (new_child_count == old_child_count);
1013#endif
1014 }
1015
1016 /* Clean up. */
1017 free_reloc_deps_graph (deps);
1018 }
1019}
1020
1021
0c7a8e5a
AM
1022static void
1023xtensa_wild_group_interleave (lang_statement_union_type *s)
e0001a05
NC
1024{
1025 lang_for_each_statement_worker (xtensa_wild_group_interleave_callback, s);
1026}
1027
1028
0c7a8e5a
AM
1029static void
1030xtensa_layout_wild (const reloc_deps_graph *deps,
1031 lang_wild_statement_type *w)
e0001a05
NC
1032{
1033 /* If it does not fit initially, we need to do this step. Move all
1034 of the wild literal sections to a new list, then move each of
1035 them back in just before the first section they depend on. */
1036 lang_statement_union_type **s_p;
1037#if EXTRA_VALIDATION
1038 size_t old_count, new_count;
1039 size_t ct1, ct2;
1040#endif
0c7a8e5a 1041
e0001a05
NC
1042 lang_wild_statement_type literal_wild;
1043 literal_wild.header.next = NULL;
1044 literal_wild.header.type = lang_wild_statement_enum;
1045 literal_wild.filename = NULL;
1046 literal_wild.filenames_sorted = FALSE;
1047 literal_wild.section_list = NULL;
1048 literal_wild.keep_sections = FALSE;
1049 literal_wild.children.head = NULL;
1050 literal_wild.children.tail = &literal_wild.children.head;
1051
1052#if EXTRA_VALIDATION
1053 old_count = ld_count_children ((lang_statement_union_type*) w);
1054#endif
1055
1056 s_p = &w->children.head;
1057 while (*s_p != NULL)
1058 {
1059 lang_statement_union_type *l = *s_p;
1060 if (l->header.type == lang_input_section_enum)
1061 {
1062 if (section_is_target (deps, l)
0c7a8e5a 1063 && ! section_is_source (deps, l))
e0001a05
NC
1064 {
1065 /* Detach. */
1066 *s_p = l->header.next;
1067 if (*s_p == NULL)
1068 w->children.tail = s_p;
1069 l->header.next = NULL;
1070
1071 /* Append. */
1072 *literal_wild.children.tail = l;
1073 literal_wild.children.tail = &l->header.next;
1074 continue;
0c7a8e5a 1075 }
e0001a05
NC
1076 }
1077 s_p = &(*s_p)->header.next;
1078 }
1079
1080#if EXTRA_VALIDATION
1081 ct1 = ld_count_children ((lang_statement_union_type*) w);
1082 ct2 = ld_count_children ((lang_statement_union_type*) &literal_wild);
0c7a8e5a 1083
e0001a05
NC
1084 ASSERT (old_count == (ct1 + ct2));
1085#endif
0c7a8e5a 1086
e0001a05
NC
1087 /* Now place them back in front of their dependent sections. */
1088
1089 while (literal_wild.children.head != NULL)
1090 {
1091 lang_statement_union_type *lit = literal_wild.children.head;
1092 bfd_boolean placed = FALSE;
1093
1094#if EXTRA_VALIDATION
1095 ASSERT (ct2 > 0);
1096 ct2--;
1097#endif
1098
1099 /* Detach. */
1100 literal_wild.children.head = lit->header.next;
0c7a8e5a 1101 if (literal_wild.children.head == NULL)
e0001a05
NC
1102 literal_wild.children.tail = &literal_wild.children.head;
1103 lit->header.next = NULL;
1104
1105 /* Find a spot to place it. */
0c7a8e5a 1106 for (s_p = &w->children.head; *s_p != NULL; s_p = &(*s_p)->header.next)
e0001a05
NC
1107 {
1108 lang_statement_union_type *src = *s_p;
1109 if (deps_has_edge (deps, src, lit))
1110 {
1111 /* Place it here. */
1112 lit->header.next = *s_p;
1113 *s_p = lit;
1114 placed = TRUE;
1115 break;
1116 }
1117 }
0c7a8e5a 1118
e0001a05
NC
1119 if (!placed)
1120 {
1121 /* Put it at the end. */
1122 *w->children.tail = lit;
1123 w->children.tail = &lit->header.next;
1124 }
1125 }
1126
1127#if EXTRA_VALIDATION
1128 new_count = ld_count_children ((lang_statement_union_type*) w);
1129 ASSERT (new_count == old_count);
1130#endif
1131}
1132
1133
0c7a8e5a
AM
1134static void
1135xtensa_colocate_output_literals_callback (lang_statement_union_type *statement)
e0001a05
NC
1136{
1137 lang_output_section_statement_type *os;
1138 reloc_deps_graph *deps;
1139 if (statement->header.type == lang_output_section_statement_enum)
1140 {
1141 /* Now, we walk over the contours of the output section statement.
1142
1143 First we build the literal section dependences as before.
1144
1145 At the first uniquely_literal section, we mark it as a good
1146 spot to place other literals. Continue walking (and counting
1147 sizes) until we find the next literal section. If this
1148 section can be moved to the first one, then we move it. If
1149 we every find a modification of ".", start over. If we find
1150 a labeling of the current location, start over. Finally, at
1151 the end, if we require page alignment, add page alignments. */
1152
1153#if EXTRA_VALIDATION
1154 size_t old_child_count;
1155 size_t new_child_count;
1156#endif
1157 bfd_boolean no_reorder = FALSE;
1158
1159 os = &statement->output_section_statement;
1160
1161#if EXTRA_VALIDATION
1162 old_child_count = ld_count_children (statement);
1163#endif
1164
1165 /* It is now officially a target. Build the graph of source
0c7a8e5a 1166 section -> target section (kept as a list of edges). */
e0001a05
NC
1167
1168 deps = ld_build_required_section_dependence (statement);
1169
1170 /* If this wildcard does not reorder.... */
1171 if (!no_reorder)
1172 {
1173 /* First check for reverse dependences. Fix if possible. */
1174 xtensa_colocate_literals (deps, statement);
1175
1176#if EXTRA_VALIDATION
1177 new_child_count = ld_count_children (statement);
1178 ASSERT (new_child_count == old_child_count);
1179#endif
1180 }
1181
1182 /* Insert align/offset assignment statement. */
1183 if (xtensa_use_literal_pages)
1184 {
0c7a8e5a 1185 ld_xtensa_insert_page_offsets (0, statement, deps,
e0001a05
NC
1186 xtensa_use_literal_pages);
1187 lang_for_each_statement_worker (xtensa_ldlang_clear_addresses,
1188 statement);
1189 }
1190
1191 /* Clean up. */
1192 free_reloc_deps_graph (deps);
1193 }
1194}
1195
1196
0c7a8e5a
AM
1197static void
1198xtensa_colocate_output_literals (lang_statement_union_type *s)
e0001a05
NC
1199{
1200 lang_for_each_statement_worker (xtensa_colocate_output_literals_callback, s);
1201}
1202
1203
0c7a8e5a
AM
1204static void
1205xtensa_ldlang_clear_addresses (lang_statement_union_type *statement)
e0001a05
NC
1206{
1207 switch (statement->header.type)
1208 {
0c7a8e5a 1209 case lang_input_section_enum:
e0001a05
NC
1210 {
1211 asection *bfd_section = statement->input_section.section;
1212 bfd_section->output_offset = 0;
1213 }
1214 break;
1215 default:
1216 break;
1217 }
1218}
1219
1220
0c7a8e5a
AM
1221static bfd_vma
1222ld_assign_relative_paged_dot (bfd_vma dot,
1223 lang_statement_union_type *s,
1224 const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
1225 bfd_boolean lit_align)
e0001a05
NC
1226{
1227 /* Walk through all of the input statements in this wild statement
1228 assign dot to all of them. */
0c7a8e5a 1229
e0001a05
NC
1230 xtensa_ld_iter_stack *stack = NULL;
1231 xtensa_ld_iter_stack **stack_p = &stack;
1232
1233 bfd_boolean first_section = FALSE;
1234 bfd_boolean in_literals = FALSE;
1235
1236 for (iter_stack_create (stack_p, s);
1237 !iter_stack_empty (stack_p);
0c7a8e5a 1238 iter_stack_next (stack_p))
e0001a05
NC
1239 {
1240 lang_statement_union_type *l = iter_stack_current (stack_p);
0c7a8e5a
AM
1241
1242 switch (l->header.type)
e0001a05
NC
1243 {
1244 case lang_input_section_enum:
1245 {
1246 asection *section = l->input_section.section;
1247 size_t align_pow = section->alignment_power;
1248 bfd_boolean do_xtensa_alignment = FALSE;
0c7a8e5a 1249
e0001a05
NC
1250 if (lit_align)
1251 {
1252 bfd_boolean sec_is_target = section_is_target (deps, l);
1253 bfd_boolean sec_is_source = section_is_source (deps, l);
1254
eea6121a 1255 if (section->size != 0
e0001a05
NC
1256 && (first_section
1257 || (in_literals && !sec_is_target)
1258 || (!in_literals && sec_is_target)))
1259 {
1260 do_xtensa_alignment = TRUE;
1261 }
1262 first_section = FALSE;
eea6121a 1263 if (section->size != 0)
e0001a05
NC
1264 in_literals = (sec_is_target && !sec_is_source);
1265 }
1266
1267 if (do_xtensa_alignment && xtensa_page_power != 0)
1268 dot += (1 << xtensa_page_power);
1269
1270 dot = align_power (dot, align_pow);
1271 section->output_offset = dot;
eea6121a 1272 dot += section->size;
e0001a05
NC
1273 }
1274 break;
1275 case lang_fill_statement_enum:
1276 dot += l->fill_statement.size;
1277 break;
1278 case lang_padding_statement_enum:
1279 dot += l->padding_statement.size;
1280 break;
1281 default:
1282 break;
1283 }
1284 }
1285 return dot;
1286}
1287
1288
0c7a8e5a
AM
1289static bfd_boolean
1290ld_local_file_relocations_fit (lang_statement_union_type *statement,
1291 const reloc_deps_graph *deps ATTRIBUTE_UNUSED)
e0001a05
NC
1292{
1293 /* Walk over all of the dependencies that we identified and make
1294 sure that IF the source and target are here (addr != 0):
1295 1) target addr < source addr
0c7a8e5a 1296 2) (roundup(source + source_size, 4) - rounddown(target, 4))
e0001a05
NC
1297 < (256K - (1 << bad align))
1298 Need a worst-case proof.... */
0c7a8e5a 1299
e0001a05
NC
1300 xtensa_ld_iter_stack *stack = NULL;
1301 xtensa_ld_iter_stack **stack_p = &stack;
1302 size_t max_align_power = 0;
1303 size_t align_penalty = 256;
1304 reloc_deps_e *e;
1305 size_t i;
1306
1307 /* Find the worst-case alignment requirement for this set of statements. */
1308 for (iter_stack_create (stack_p, statement);
1309 !iter_stack_empty (stack_p);
0c7a8e5a 1310 iter_stack_next (stack_p))
e0001a05
NC
1311 {
1312 lang_statement_union_type *l = iter_stack_current (stack_p);
0c7a8e5a 1313 if (l->header.type == lang_input_section_enum)
e0001a05
NC
1314 {
1315 lang_input_section_type *input = &l->input_section;
1316 asection *section = input->section;
1317 if (section->alignment_power > max_align_power)
1318 max_align_power = section->alignment_power;
1319 }
1320 }
1321
1322 /* Now check that everything fits. */
1323 for (i = 0; i < deps->count; i++)
1324 {
1325 asection *sec = deps->sections[i];
0c7a8e5a 1326 const reloc_deps_section *deps_section =
e0001a05
NC
1327 xtensa_get_section_deps (deps, sec);
1328 if (deps_section)
1329 {
1330 /* We choose to walk through the successors. */
1331 for (e = deps_section->succs; e != NULL; e = e->next)
1332 {
0c7a8e5a 1333 if (e->src != e->tgt
e0001a05
NC
1334 && e->src->output_section == e->tgt->output_section
1335 && e->src->output_offset != 0
1336 && e->tgt->output_offset != 0)
1337 {
0c7a8e5a 1338 bfd_vma l32r_addr =
eea6121a 1339 align_power (e->src->output_offset + e->src->size, 2);
0c7a8e5a 1340 bfd_vma target_addr = e->tgt->output_offset & ~3;
e0001a05
NC
1341 if (l32r_addr < target_addr)
1342 {
1343 fprintf (stderr, "Warning: "
1344 "l32r target section before l32r\n");
1345 return FALSE;
1346 }
1347
0c7a8e5a 1348 if (l32r_addr - target_addr > 256 * 1024 - align_penalty)
e0001a05
NC
1349 return FALSE;
1350 }
1351 }
1352 }
1353 }
1354
1355 return TRUE;
1356}
1357
1358
0c7a8e5a
AM
1359static bfd_vma
1360ld_xtensa_insert_page_offsets (bfd_vma dot,
1361 lang_statement_union_type *s,
1362 reloc_deps_graph *deps,
1363 bfd_boolean lit_align)
e0001a05
NC
1364{
1365 xtensa_ld_iter_stack *stack = NULL;
1366 xtensa_ld_iter_stack **stack_p = &stack;
1367
1368 bfd_boolean first_section = FALSE;
1369 bfd_boolean in_literals = FALSE;
0c7a8e5a 1370
e0001a05
NC
1371 if (!lit_align)
1372 return FALSE;
1373
1374 for (iter_stack_create (stack_p, s);
1375 !iter_stack_empty (stack_p);
0c7a8e5a 1376 iter_stack_next (stack_p))
e0001a05
NC
1377 {
1378 lang_statement_union_type *l = iter_stack_current (stack_p);
1379
0c7a8e5a
AM
1380 switch (l->header.type)
1381 {
e0001a05
NC
1382 case lang_input_section_enum:
1383 {
1384 asection *section = l->input_section.section;
1385 bfd_boolean do_xtensa_alignment = FALSE;
0c7a8e5a 1386
e0001a05
NC
1387 if (lit_align)
1388 {
eea6121a 1389 if (section->size != 0
e0001a05
NC
1390 && (first_section
1391 || (in_literals && !section_is_target (deps, l))
1392 || (!in_literals && section_is_target (deps, l))))
1393 {
1394 do_xtensa_alignment = TRUE;
1395 }
1396 first_section = FALSE;
eea6121a 1397 if (section->size != 0)
e0001a05
NC
1398 {
1399 in_literals = (section_is_target (deps, l)
1400 && !section_is_source (deps, l));
1401 }
1402 }
1403
1404 if (do_xtensa_alignment && xtensa_page_power != 0)
1405 {
1406 /* Create an expression that increments the current address,
1407 i.e., "dot", by (1 << xtensa_align_power). */
1408 etree_type *name_op = exp_nameop (NAME, ".");
1409 etree_type *addend_op = exp_intop (1 << xtensa_page_power);
1410 etree_type *add_op = exp_binop ('+', name_op, addend_op);
1411 etree_type *assign_op = exp_assop ('=', ".", add_op);
1412
1413 lang_assignment_statement_type *assign_stmt;
1414 lang_statement_union_type *assign_union;
1415 lang_statement_list_type tmplist;
1416 lang_statement_list_type *old_stat_ptr = stat_ptr;
0c7a8e5a 1417
e0001a05
NC
1418 /* There is hidden state in "lang_add_assignment". It
1419 appends the new assignment statement to the stat_ptr
1420 list. Thus, we swap it before and after the call. */
1421
1422 tmplist.head = NULL;
1423 tmplist.tail = &tmplist.head;
1424
1425 stat_ptr = &tmplist;
1426 /* Warning: side effect; statement appended to stat_ptr. */
1427 assign_stmt = lang_add_assignment (assign_op);
1428 assign_union = (lang_statement_union_type *) assign_stmt;
1429 stat_ptr = old_stat_ptr;
1430
1431 assign_union->header.next = l;
1432 *(*stack_p)->iterloc.loc = assign_union;
1433 iter_stack_next (stack_p);
0c7a8e5a
AM
1434 }
1435 }
1436 break;
1437 default:
1438 break;
1439 }
e0001a05
NC
1440 }
1441 return dot;
1442}
1443
1444EOF
1445
1446# Define some shell vars to insert bits of code into the standard elf
1447# parse_args and list_options functions.
1448#
1449PARSE_AND_LIST_PROLOGUE='
1450#define OPTION_NO_RELAX 301
1451'
1452
1453PARSE_AND_LIST_LONGOPTS='
1454 { "no-relax", no_argument, NULL, OPTION_NO_RELAX},
1455'
1456
1457PARSE_AND_LIST_OPTIONS='
1458 fprintf (file, _(" --no-relax\t\tDo not relax branches or coalesce literals\n"));
1459'
1460
1461PARSE_AND_LIST_ARGS_CASES='
1462 case OPTION_NO_RELAX:
1463 disable_relaxation = TRUE;
1464 break;
1465'
1466
1467# Replace some of the standard ELF functions with our own versions.
1468#
1469LDEMUL_BEFORE_PARSE=elf_xtensa_before_parse
1470LDEMUL_CHOOSE_TARGET=elf_xtensa_choose_target
1471LDEMUL_PLACE_ORPHAN=elf_xtensa_place_orphan
1472LDEMUL_BEFORE_ALLOCATION=elf_xtensa_before_allocation
1473