]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - ld/emultempl/xtensaelf.em
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / ld / emultempl / xtensaelf.em
CommitLineData
e0001a05 1# This shell script emits a C file. -*- C -*-
fd67aa11 2# Copyright (C) 2003-2024 Free Software Foundation, Inc.
e0001a05 3#
f96b4a7b 4# This file is part of the GNU Binutils.
e0001a05
NC
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
f96b4a7b 8# the Free Software Foundation; either version 3 of the License, or
e0001a05
NC
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
f96b4a7b
NC
18# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19# MA 02110-1301, USA.
e0001a05
NC
20#
21
075a2b89 22# This file is sourced from elf.em, and defines extra xtensa-elf
e0001a05
NC
23# specific routines.
24#
92b93329 25fragment <<EOF
e0001a05 26
d0a2cfbd 27#include <xtensa-dynconfig.h>
43cd72b9 28#include "../bfd/elf-bfd.h"
43cd72b9
BW
29#include "elf/xtensa.h"
30#include "bfd.h"
e0001a05 31
2caa7ca0 32/* Provide default values for new configuration settings. */
7a77f1ac
MF
33#ifndef XTHAL_ABI_UNDEFINED
34#define XTHAL_ABI_UNDEFINED -1
35#endif
36
0c7a8e5a
AM
37static void xtensa_wild_group_interleave (lang_statement_union_type *);
38static void xtensa_colocate_output_literals (lang_statement_union_type *);
a255b6c7
BW
39static void xtensa_strip_inconsistent_linkonce_sections
40 (lang_statement_list_type *);
e0001a05
NC
41
42
e0001a05
NC
43/* This number is irrelevant until we turn on use_literal_pages */
44static bfd_vma xtensa_page_power = 12; /* 4K pages. */
45
46/* To force a page break between literals and text, change
f38a2680
AM
47 xtensa_use_literal_pages to "true". */
48static bool xtensa_use_literal_pages = false;
e0001a05
NC
49
50#define EXTRA_VALIDATION 0
51
7a77f1ac
MF
52/* Xtensa ABI.
53 This option is defined in BDF library. */
54extern int elf32xtensa_abi;
55
e0001a05
NC
56
57static char *
0c7a8e5a
AM
58elf_xtensa_choose_target (int argc ATTRIBUTE_UNUSED,
59 char **argv ATTRIBUTE_UNUSED)
e0001a05
NC
60{
61 if (XCHAL_HAVE_BE)
62 return "${BIG_OUTPUT_FORMAT}";
63 else
64 return "${LITTLE_OUTPUT_FORMAT}";
65}
66
67
e0001a05 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
7fa3d080
BW
77static void
78remove_section (bfd *abfd, asection *os)
43cd72b9
BW
79{
80 asection **spp;
81 for (spp = &abfd->sections; *spp; spp = &(*spp)->next)
82 if (*spp == os)
83 {
84 *spp = os->next;
85 os->owner->section_count--;
86 break;
87 }
88}
89
90
f38a2680 91static bool
7fa3d080
BW
92replace_insn_sec_with_prop_sec (bfd *abfd,
93 const char *insn_sec_name,
94 const char *prop_sec_name,
95 char **error_message)
43cd72b9
BW
96{
97 asection *insn_sec;
98 asection *prop_sec;
99 bfd_byte *prop_contents = NULL;
100 bfd_byte *insn_contents = NULL;
101 unsigned entry_count;
102 unsigned entry;
d4730f92 103 Elf_Internal_Shdr *rel_hdr;
43cd72b9
BW
104 Elf_Internal_Rela *internal_relocs = NULL;
105 unsigned reloc_count;
92b93329 106
43cd72b9
BW
107 *error_message = "";
108 insn_sec = bfd_get_section_by_name (abfd, insn_sec_name);
109 if (insn_sec == NULL)
f38a2680 110 return true;
43cd72b9
BW
111 entry_count = insn_sec->size / 8;
112
113 prop_sec = bfd_get_section_by_name (abfd, prop_sec_name);
114 if (prop_sec != NULL && insn_sec != NULL)
115 {
116 *error_message = _("file already has property tables");
f38a2680 117 return false;
43cd72b9 118 }
92b93329 119
43cd72b9
BW
120 if (insn_sec->size != 0)
121 {
76e7a751 122 insn_contents = (bfd_byte *) xmalloc (insn_sec->size);
43cd72b9
BW
123 if (! bfd_get_section_contents (abfd, insn_sec, insn_contents,
124 (file_ptr) 0, insn_sec->size))
125 {
126 *error_message = _("failed to read section contents");
127 goto cleanup;
128 }
129 }
130
2caa7ca0 131 /* Create a property table section for it. */
43cd72b9 132 prop_sec_name = strdup (prop_sec_name);
2caa7ca0 133 prop_sec = bfd_make_section_with_flags
fd361982 134 (abfd, prop_sec_name, bfd_section_flags (insn_sec));
43cd72b9 135 if (prop_sec == NULL
fd361982 136 || !bfd_set_section_alignment (prop_sec, 2))
43cd72b9
BW
137 {
138 *error_message = _("could not create new section");
139 goto cleanup;
140 }
92b93329 141
43cd72b9
BW
142 prop_sec->size = entry_count * 12;
143 prop_contents = (bfd_byte *) bfd_zalloc (abfd, prop_sec->size);
144 elf_section_data (prop_sec)->this_hdr.contents = prop_contents;
145
146 /* The entry size and size must be set to allow the linker to compute
147 the number of relocations since it does not use reloc_count. */
d4730f92
BS
148 rel_hdr = _bfd_elf_single_rel_hdr (prop_sec);
149 rel_hdr->sh_entsize = sizeof (Elf32_External_Rela);
150 rel_hdr->sh_size = _bfd_elf_single_rel_hdr (insn_sec)->sh_size;
43cd72b9
BW
151
152 if (prop_contents == NULL && prop_sec->size != 0)
153 {
154 *error_message = _("could not allocate section contents");
155 goto cleanup;
156 }
157
158 /* Read the relocations. */
159 reloc_count = insn_sec->reloc_count;
160 if (reloc_count != 0)
161 {
162 /* If there is already an internal_reloc, then save it so that the
163 read_relocs function freshly allocates a copy. */
164 Elf_Internal_Rela *saved_relocs = elf_section_data (insn_sec)->relocs;
92b93329 165
43cd72b9 166 elf_section_data (insn_sec)->relocs = NULL;
92b93329 167 internal_relocs =
f38a2680 168 _bfd_elf_link_read_relocs (abfd, insn_sec, NULL, NULL, false);
43cd72b9 169 elf_section_data (insn_sec)->relocs = saved_relocs;
92b93329 170
43cd72b9
BW
171 if (internal_relocs == NULL)
172 {
173 *error_message = _("out of memory");
174 goto cleanup;
175 }
176 }
177
178 /* Create a relocation section for the property section. */
179 if (internal_relocs != NULL)
180 {
181 elf_section_data (prop_sec)->relocs = internal_relocs;
182 prop_sec->reloc_count = reloc_count;
183 }
92b93329 184
43cd72b9
BW
185 /* Now copy each insn table entry to the prop table entry with
186 appropriate flags. */
187 for (entry = 0; entry < entry_count; ++entry)
188 {
189 unsigned value;
99ded152 190 unsigned flags = (XTENSA_PROP_INSN | XTENSA_PROP_NO_TRANSFORM
43cd72b9
BW
191 | XTENSA_PROP_INSN_NO_REORDER);
192 value = bfd_get_32 (abfd, insn_contents + entry * 8 + 0);
193 bfd_put_32 (abfd, value, prop_contents + entry * 12 + 0);
194 value = bfd_get_32 (abfd, insn_contents + entry * 8 + 4);
195 bfd_put_32 (abfd, value, prop_contents + entry * 12 + 4);
196 bfd_put_32 (abfd, flags, prop_contents + entry * 12 + 8);
197 }
198
199 /* Now copy all of the relocations. Change offsets for the
200 instruction table section to offsets in the property table
201 section. */
202 if (internal_relocs)
203 {
204 unsigned i;
43cd72b9
BW
205
206 for (i = 0; i < reloc_count; i++)
207 {
208 Elf_Internal_Rela *rela;
209 unsigned r_offset;
210
211 rela = &internal_relocs[i];
212
92b93329 213 /* If this relocation is to the .xt.insn section,
43cd72b9
BW
214 change the section number and the offset. */
215 r_offset = rela->r_offset;
216 r_offset += 4 * (r_offset / 8);
217 rela->r_offset = r_offset;
218 }
219 }
220
221 remove_section (abfd, insn_sec);
92b93329 222
5e2ab612 223 free (insn_contents);
92b93329 224
f38a2680 225 return true;
43cd72b9
BW
226
227 cleanup:
228 if (prop_sec && prop_sec->owner)
229 remove_section (abfd, prop_sec);
5e2ab612
AM
230 free (insn_contents);
231 free (internal_relocs);
43cd72b9 232
f38a2680 233 return false;
43cd72b9
BW
234}
235
236
237#define PROP_SEC_BASE_NAME ".xt.prop"
238#define INSN_SEC_BASE_NAME ".xt.insn"
239#define LINKONCE_SEC_OLD_TEXT_BASE_NAME ".gnu.linkonce.x."
240
241
7fa3d080
BW
242static void
243replace_instruction_table_sections (bfd *abfd, asection *sec)
43cd72b9
BW
244{
245 char *message = "";
246 const char *insn_sec_name = NULL;
247 char *prop_sec_name = NULL;
248 char *owned_prop_sec_name = NULL;
249 const char *sec_name;
92b93329 250
fd361982 251 sec_name = bfd_section_name (sec);
43cd72b9
BW
252 if (strcmp (sec_name, INSN_SEC_BASE_NAME) == 0)
253 {
254 insn_sec_name = INSN_SEC_BASE_NAME;
255 prop_sec_name = PROP_SEC_BASE_NAME;
256 }
08dedd66 257 else if (startswith (sec_name, LINKONCE_SEC_OLD_TEXT_BASE_NAME))
43cd72b9
BW
258 {
259 insn_sec_name = sec_name;
260 owned_prop_sec_name = (char *) xmalloc (strlen (sec_name) + 20);
261 prop_sec_name = owned_prop_sec_name;
262 strcpy (prop_sec_name, ".gnu.linkonce.prop.t.");
263 strcat (prop_sec_name,
264 sec_name + strlen (LINKONCE_SEC_OLD_TEXT_BASE_NAME));
265 }
266 if (insn_sec_name != NULL)
267 {
268 if (! replace_insn_sec_with_prop_sec (abfd, insn_sec_name, prop_sec_name,
269 &message))
270 {
871b3ab2 271 einfo (_("%P: warning: failed to convert %s table in %pB (%s); subsequent disassembly may be incomplete\n"),
43cd72b9
BW
272 insn_sec_name, abfd, message);
273 }
274 }
5e2ab612 275 free (owned_prop_sec_name);
43cd72b9
BW
276}
277
278
279/* This is called after all input sections have been opened to convert
280 instruction tables (.xt.insn, gnu.linkonce.x.*) tables into property
281 tables (.xt.prop) before any section placement. */
282
283static void
284elf_xtensa_after_open (void)
285{
43cd72b9
BW
286 /* First call the ELF version. */
287 gld${EMULATION_NAME}_after_open ();
92b93329 288
43cd72b9 289 /* Now search the input files looking for instruction table sections. */
2caa7ca0 290 LANG_FOR_EACH_INPUT_STATEMENT (f)
43cd72b9 291 {
2caa7ca0 292 asection *sec = f->the_bfd->sections;
43cd72b9
BW
293 asection *next_sec;
294
295 /* Do not use bfd_map_over_sections here since we are removing
296 sections as we iterate. */
297 while (sec != NULL)
298 {
299 next_sec = sec->next;
2caa7ca0 300 replace_instruction_table_sections (f->the_bfd, sec);
43cd72b9
BW
301 sec = next_sec;
302 }
303 }
304}
305
306
f38a2680 307static bool
2caa7ca0 308xt_config_info_unpack_and_check (char *data,
f38a2680 309 bool *pmismatch,
2caa7ca0
BW
310 char **pmsg)
311{
312 char *d, *key;
7a77f1ac 313 int num;
2caa7ca0 314
f38a2680 315 *pmismatch = false;
2caa7ca0
BW
316
317 d = data;
318 while (*d)
319 {
320 key = d;
321 d = strchr (d, '=');
322 if (! d)
323 goto error;
324
325 /* Overwrite the equal sign. */
326 *d++ = 0;
327
328 /* Check if this is a quoted string or a number. */
329 if (*d == '"')
330 {
331 /* No string values are currently checked by LD;
332 just skip over the quotes. */
333 d++;
334 d = strchr (d, '"');
335 if (! d)
336 goto error;
337 /* Overwrite the trailing quote. */
338 *d++ = 0;
339 }
340 else
341 {
342 if (*d == 0)
343 goto error;
344 num = strtoul (d, &d, 0);
345
346 if (! strcmp (key, "ABI"))
347 {
7a77f1ac
MF
348 if (elf32xtensa_abi == XTHAL_ABI_UNDEFINED)
349 {
350 elf32xtensa_abi = num;
351 }
352 else if (num != elf32xtensa_abi)
2caa7ca0 353 {
f38a2680 354 *pmismatch = true;
2caa7ca0
BW
355 *pmsg = "ABI does not match";
356 }
357 }
358 else if (! strcmp (key, "USE_ABSOLUTE_LITERALS"))
359 {
360 if (num != XSHAL_USE_ABSOLUTE_LITERALS)
361 {
f38a2680 362 *pmismatch = true;
2caa7ca0
BW
363 *pmsg = "incompatible use of the Extended L32R option";
364 }
365 }
366 }
367
368 if (*d++ != '\n')
369 goto error;
370 }
371
f38a2680 372 return true;
2caa7ca0
BW
373
374 error:
f38a2680 375 return false;
2caa7ca0
BW
376}
377
378
379#define XTINFO_NAME "Xtensa_Info"
380#define XTINFO_NAMESZ 12
381#define XTINFO_TYPE 1
382
383static void
384check_xtensa_info (bfd *abfd, asection *info_sec)
385{
386 char *data, *errmsg = "";
f38a2680 387 bool mismatch;
2caa7ca0
BW
388
389 data = xmalloc (info_sec->size);
390 if (! bfd_get_section_contents (abfd, info_sec, data, 0, info_sec->size))
df5f2391 391 einfo (_("%F%P: %pB: cannot read contents of section %pA\n"), abfd, info_sec);
2caa7ca0
BW
392
393 if (info_sec->size > 24
394 && info_sec->size >= 24 + bfd_get_32 (abfd, data + 4)
395 && bfd_get_32 (abfd, data + 0) == XTINFO_NAMESZ
396 && bfd_get_32 (abfd, data + 8) == XTINFO_TYPE
397 && strcmp (data + 12, XTINFO_NAME) == 0
398 && xt_config_info_unpack_and_check (data + 12 + XTINFO_NAMESZ,
399 &mismatch, &errmsg))
400 {
401 if (mismatch)
df5f2391 402 einfo (_("%P: %pB: warning: incompatible Xtensa configuration (%s)\n"),
2caa7ca0
BW
403 abfd, errmsg);
404 }
405 else
df5f2391 406 einfo (_("%P: %pB: warning: cannot parse .xtensa.info section\n"), abfd);
2caa7ca0
BW
407
408 free (data);
409}
410
411
e0001a05
NC
412/* This is called after the sections have been attached to output
413 sections, but before any sizes or addresses have been set. */
414
0c7a8e5a
AM
415static void
416elf_xtensa_before_allocation (void)
e0001a05 417{
2caa7ca0
BW
418 asection *info_sec, *first_info_sec;
419 bfd *first_bfd;
f38a2680 420 bool is_big_endian = XCHAL_HAVE_BE;
e0001a05
NC
421
422 /* Check that the output endianness matches the Xtensa
423 configuration. The BFD library always includes both big and
424 little endian target vectors for Xtensa, but it only supports the
425 detailed instruction encode/decode operations (such as are
426 required to process relocations) for the selected Xtensa
427 configuration. */
428
f13a99db
AM
429 if (is_big_endian
430 && link_info.output_bfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
e0001a05
NC
431 {
432 einfo (_("%F%P: little endian output does not match "
433 "Xtensa configuration\n"));
434 }
f13a99db
AM
435 if (!is_big_endian
436 && link_info.output_bfd->xvec->byteorder == BFD_ENDIAN_BIG)
e0001a05
NC
437 {
438 einfo (_("%F%P: big endian output does not match "
439 "Xtensa configuration\n"));
440 }
441
2caa7ca0
BW
442 /* Keep track of the first input .xtensa.info section, and as a fallback,
443 the first input bfd where a .xtensa.info section could be created.
444 After the input .xtensa.info has been checked, the contents of the
445 first one will be replaced with the output .xtensa.info table. */
446 first_info_sec = 0;
447 first_bfd = 0;
e0001a05 448
2caa7ca0
BW
449 LANG_FOR_EACH_INPUT_STATEMENT (f)
450 {
451 /* Check that the endianness for each input file matches the output.
452 The merge_private_bfd_data hook has already reported any mismatches
453 as errors, but those errors are not fatal. At this point, we
454 cannot go any further if there are any mismatches. */
455 if ((is_big_endian && f->the_bfd->xvec->byteorder == BFD_ENDIAN_LITTLE)
456 || (!is_big_endian && f->the_bfd->xvec->byteorder == BFD_ENDIAN_BIG))
871b3ab2 457 einfo (_("%F%P: cross-endian linking for %pB not supported\n"),
2caa7ca0
BW
458 f->the_bfd);
459
460 if (! first_bfd)
461 first_bfd = f->the_bfd;
462
463 info_sec = bfd_get_section_by_name (f->the_bfd, ".xtensa.info");
464 if (! info_sec)
465 continue;
466
467 if (! first_info_sec)
468 first_info_sec = info_sec;
469
470 /* Unpack the .xtensa.info section and check it against the current
471 Xtensa configuration. */
472 check_xtensa_info (f->the_bfd, info_sec);
473
474 /* Do not include this copy of .xtensa.info in the output. */
475 info_sec->size = 0;
476 info_sec->flags |= SEC_EXCLUDE;
477 }
478
479 /* Reuse the first .xtensa.info input section to hold the output
480 .xtensa.info; or, if none were found, create a new section in the
481 first input bfd (assuming there is one). */
482 info_sec = first_info_sec;
483 if (! info_sec && first_bfd)
484 {
485 info_sec = bfd_make_section_with_flags (first_bfd, ".xtensa.info",
486 SEC_HAS_CONTENTS | SEC_READONLY);
487 if (! info_sec)
488 einfo (_("%F%P: failed to create .xtensa.info section\n"));
489 }
490 if (info_sec)
e0001a05 491 {
2caa7ca0 492 int xtensa_info_size;
eaf1fa5a 493 char data[100];
2caa7ca0
BW
494
495 info_sec->flags &= ~SEC_EXCLUDE;
496 info_sec->flags |= SEC_IN_MEMORY;
497
eaf1fa5a
AM
498 xtensa_info_size
499 = 1 + sprintf (data, "USE_ABSOLUTE_LITERALS=%d\nABI=%d\n",
500 XSHAL_USE_ABSOLUTE_LITERALS, xtensa_abi_choice ());
2caa7ca0
BW
501
502 /* Add enough null terminators to pad to a word boundary. */
503 do
504 data[xtensa_info_size++] = 0;
505 while ((xtensa_info_size & 3) != 0);
506
507 info_sec->size = 12 + XTINFO_NAMESZ + xtensa_info_size;
508 info_sec->contents = xmalloc (info_sec->size);
509 bfd_put_32 (info_sec->owner, XTINFO_NAMESZ, info_sec->contents + 0);
510 bfd_put_32 (info_sec->owner, xtensa_info_size, info_sec->contents + 4);
511 bfd_put_32 (info_sec->owner, XTINFO_TYPE, info_sec->contents + 8);
512 memcpy (info_sec->contents + 12, XTINFO_NAME, XTINFO_NAMESZ);
513 memcpy (info_sec->contents + 12 + XTINFO_NAMESZ, data, xtensa_info_size);
e0001a05
NC
514 }
515
516 /* Enable relaxation by default if the "--no-relax" option was not
517 specified. This is done here instead of in the before_parse hook
518 because there is a check in main() to prohibit use of --relax and
519 -r together and that combination should be allowed for Xtensa. */
28d5f677
NC
520 if (RELAXATION_DISABLED_BY_DEFAULT)
521 ENABLE_RELAXATION;
e0001a05 522
a255b6c7
BW
523 xtensa_strip_inconsistent_linkonce_sections (stat_ptr);
524
e0001a05
NC
525 gld${EMULATION_NAME}_before_allocation ();
526
527 xtensa_wild_group_interleave (stat_ptr->head);
28d5f677
NC
528
529 if (RELAXATION_ENABLED)
e0001a05
NC
530 xtensa_colocate_output_literals (stat_ptr->head);
531
532 /* TBD: We need to force the page alignments to here and only do
533 them as needed for the entire output section. Finally, if this
1049f94e 534 is a relocatable link then we need to add alignment notes so
e0001a05
NC
535 that the literals can be separated later. */
536}
537
538
539typedef struct wildcard_list section_name_list;
540
541typedef struct reloc_deps_e_t reloc_deps_e;
542typedef struct reloc_deps_section_t reloc_deps_section;
543typedef struct reloc_deps_graph_t reloc_deps_graph;
544
545
546struct reloc_deps_e_t
547{
548 asection *src; /* Contains l32rs. */
549 asection *tgt; /* Contains literals. */
550 reloc_deps_e *next;
551};
552
553/* Place these in the userdata field. */
554struct reloc_deps_section_t
555{
556 reloc_deps_e *preds;
557 reloc_deps_e *succs;
f38a2680 558 bool is_only_literal;
e0001a05
NC
559};
560
561
562struct reloc_deps_graph_t
563{
564 size_t count;
565 size_t size;
566 asection **sections;
567};
568
569static void xtensa_layout_wild
0c7a8e5a 570 (const reloc_deps_graph *, lang_wild_statement_type *);
e0001a05 571
0c7a8e5a
AM
572typedef void (*deps_callback_t) (asection *, /* src_sec */
573 bfd_vma, /* src_offset */
574 asection *, /* target_sec */
575 bfd_vma, /* target_offset */
576 void *); /* closure */
e0001a05 577
f38a2680 578extern bool xtensa_callback_required_dependence
0c7a8e5a 579 (bfd *, asection *, struct bfd_link_info *, deps_callback_t, void *);
7fa3d080 580static void xtensa_ldlang_clear_addresses (lang_statement_union_type *);
f38a2680 581static bool ld_local_file_relocations_fit
0c7a8e5a 582 (lang_statement_union_type *, const reloc_deps_graph *);
e0001a05 583static bfd_vma ld_assign_relative_paged_dot
0c7a8e5a 584 (bfd_vma, lang_statement_union_type *, const reloc_deps_graph *,
f38a2680 585 bool);
e0001a05 586static bfd_vma ld_xtensa_insert_page_offsets
f38a2680 587 (bfd_vma, lang_statement_union_type *, reloc_deps_graph *, bool);
e0001a05 588#if EXTRA_VALIDATION
7fa3d080 589static size_t ld_count_children (lang_statement_union_type *);
e0001a05 590#endif
e0001a05
NC
591
592extern lang_statement_list_type constructor_list;
593
0c7a8e5a
AM
594static reloc_deps_section *
595xtensa_get_section_deps (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
596 asection *sec)
e0001a05
NC
597{
598 /* We have a separate function for this so that
599 we could in the future keep a completely independent
600 structure that maps a section to its dependence edges.
a48931cc
AM
601 For now, we place these in the sec->userdata field.
602 This doesn't clash with ldlang.c use of userdata for output
603 sections, and during map output for input sections, since the
604 xtensa use is only for input sections and only extant in
605 before_allocation. */
606 reloc_deps_section *sec_deps = bfd_section_userdata (sec);
e0001a05
NC
607 return sec_deps;
608}
609
0c7a8e5a
AM
610static void
611xtensa_set_section_deps (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
612 asection *sec,
613 reloc_deps_section *deps_section)
e0001a05 614{
a48931cc 615 bfd_set_section_userdata (sec, deps_section);
e0001a05
NC
616}
617
618
619/* This is used to keep a list of all of the sections participating in
620 the graph so we can clean them up quickly. */
621
0c7a8e5a
AM
622static void
623xtensa_append_section_deps (reloc_deps_graph *deps, asection *sec)
e0001a05
NC
624{
625 if (deps->size <= deps->count)
626 {
627 asection **new_sections;
628 size_t i;
629 size_t new_size;
0c7a8e5a 630
e0001a05
NC
631 new_size = deps->size * 2;
632 if (new_size == 0)
633 new_size = 20;
0c7a8e5a
AM
634
635 new_sections = xmalloc (sizeof (asection *) * new_size);
636 memset (new_sections, 0, sizeof (asection *) * new_size);
637 for (i = 0; i < deps->count; i++)
e0001a05
NC
638 {
639 new_sections[i] = deps->sections[i];
640 }
5e2ab612 641 free (deps->sections);
e0001a05
NC
642 deps->sections = new_sections;
643 deps->size = new_size;
644 }
645 deps->sections[deps->count] = sec;
646 deps->count++;
647}
648
649
0c7a8e5a
AM
650static void
651free_reloc_deps_graph (reloc_deps_graph *deps)
e0001a05
NC
652{
653 size_t i;
654 for (i = 0; i < deps->count; i++)
655 {
656 asection *sec = deps->sections[i];
657 reloc_deps_section *sec_deps;
658 sec_deps = xtensa_get_section_deps (deps, sec);
0c7a8e5a 659 if (sec_deps)
e0001a05
NC
660 {
661 reloc_deps_e *next;
662 while (sec_deps->succs != NULL)
663 {
664 next = sec_deps->succs->next;
665 free (sec_deps->succs);
666 sec_deps->succs = next;
667 }
0c7a8e5a 668
e0001a05
NC
669 while (sec_deps->preds != NULL)
670 {
671 next = sec_deps->preds->next;
672 free (sec_deps->preds);
673 sec_deps->preds = next;
674 }
675 free (sec_deps);
676 }
677 xtensa_set_section_deps (deps, sec, NULL);
678 }
5e2ab612 679 free (deps->sections);
e0001a05
NC
680 free (deps);
681}
682
683
f38a2680 684static bool
0c7a8e5a
AM
685section_is_source (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
686 lang_statement_union_type *s)
e0001a05
NC
687{
688 asection *sec;
689 const reloc_deps_section *sec_deps;
690
691 if (s->header.type != lang_input_section_enum)
f38a2680 692 return false;
e0001a05
NC
693 sec = s->input_section.section;
694
695 sec_deps = xtensa_get_section_deps (deps, sec);
0c7a8e5a 696 return sec_deps && sec_deps->succs != NULL;
e0001a05
NC
697}
698
699
f38a2680 700static bool
0c7a8e5a
AM
701section_is_target (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
702 lang_statement_union_type *s)
e0001a05
NC
703{
704 asection *sec;
705 const reloc_deps_section *sec_deps;
706
707 if (s->header.type != lang_input_section_enum)
f38a2680 708 return false;
e0001a05
NC
709 sec = s->input_section.section;
710
711 sec_deps = xtensa_get_section_deps (deps, sec);
0c7a8e5a 712 return sec_deps && sec_deps->preds != NULL;
e0001a05
NC
713}
714
7fa3d080 715
f38a2680 716static bool
0c7a8e5a
AM
717section_is_source_or_target (const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
718 lang_statement_union_type *s)
e0001a05
NC
719{
720 return (section_is_source (deps, s)
721 || section_is_target (deps, s));
722}
723
724
725typedef struct xtensa_ld_iter_stack_t xtensa_ld_iter_stack;
726typedef struct xtensa_ld_iter_t xtensa_ld_iter;
727
728struct xtensa_ld_iter_t
729{
730 lang_statement_union_type *parent; /* Parent of the list. */
731 lang_statement_list_type *l; /* List that holds it. */
732 lang_statement_union_type **loc; /* Place in the list. */
733};
734
735struct xtensa_ld_iter_stack_t
736{
737 xtensa_ld_iter iterloc; /* List that hold it. */
0c7a8e5a 738
e0001a05
NC
739 xtensa_ld_iter_stack *next; /* Next in the stack. */
740 xtensa_ld_iter_stack *prev; /* Back pointer for stack. */
741};
742
e0001a05 743
0c7a8e5a
AM
744static void
745ld_xtensa_move_section_after (xtensa_ld_iter *to, xtensa_ld_iter *current)
e0001a05
NC
746{
747 lang_statement_union_type *to_next;
748 lang_statement_union_type *current_next;
749 lang_statement_union_type **e;
750
751#if EXTRA_VALIDATION
752 size_t old_to_count, new_to_count;
753 size_t old_current_count, new_current_count;
754#endif
755
756 if (to == current)
757 return;
0c7a8e5a 758
e0001a05
NC
759#if EXTRA_VALIDATION
760 old_to_count = ld_count_children (to->parent);
761 old_current_count = ld_count_children (current->parent);
762#endif
763
764 to_next = *(to->loc);
765 current_next = (*current->loc)->header.next;
0c7a8e5a 766
e0001a05 767 *(to->loc) = *(current->loc);
0c7a8e5a 768
e0001a05
NC
769 *(current->loc) = current_next;
770 (*(to->loc))->header.next = to_next;
771
772 /* reset "to" list tail */
773 for (e = &to->l->head; *e != NULL; e = &(*e)->header.next)
774 ;
775 to->l->tail = e;
776
777 /* reset "current" list tail */
778 for (e = &current->l->head; *e != NULL; e = &(*e)->header.next)
779 ;
780 current->l->tail = e;
781
782#if EXTRA_VALIDATION
783 new_to_count = ld_count_children (to->parent);
784 new_current_count = ld_count_children (current->parent);
785
0c7a8e5a 786 ASSERT ((old_to_count + old_current_count)
e0001a05
NC
787 == (new_to_count + new_current_count));
788#endif
789}
790
791
792/* Can only be called with lang_statements that have lists. Returns
43cd72b9 793 FALSE if the list is empty. */
e0001a05 794
f38a2680 795static bool
0c7a8e5a 796iter_stack_empty (xtensa_ld_iter_stack **stack_p)
e0001a05 797{
0c7a8e5a 798 return *stack_p == NULL;
e0001a05
NC
799}
800
801
f38a2680 802static bool
0c7a8e5a
AM
803iter_stack_push (xtensa_ld_iter_stack **stack_p,
804 lang_statement_union_type *parent)
e0001a05
NC
805{
806 xtensa_ld_iter_stack *stack;
807 lang_statement_list_type *l = NULL;
808
0c7a8e5a 809 switch (parent->header.type)
e0001a05
NC
810 {
811 case lang_output_section_statement_enum:
812 l = &parent->output_section_statement.children;
813 break;
814 case lang_wild_statement_enum:
815 l = &parent->wild_statement.children;
816 break;
817 case lang_group_statement_enum:
818 l = &parent->group_statement.children;
819 break;
820 default:
821 ASSERT (0);
f38a2680 822 return false;
e0001a05
NC
823 }
824
825 /* Empty. do not push. */
0c7a8e5a 826 if (l->tail == &l->head)
f38a2680 827 return false;
e0001a05 828
0c7a8e5a 829 stack = xmalloc (sizeof (xtensa_ld_iter_stack));
e0001a05
NC
830 memset (stack, 0, sizeof (xtensa_ld_iter_stack));
831 stack->iterloc.parent = parent;
832 stack->iterloc.l = l;
833 stack->iterloc.loc = &l->head;
834
835 stack->next = *stack_p;
836 stack->prev = NULL;
0c7a8e5a 837 if (*stack_p != NULL)
e0001a05
NC
838 (*stack_p)->prev = stack;
839 *stack_p = stack;
f38a2680 840 return true;
e0001a05
NC
841}
842
843
0c7a8e5a
AM
844static void
845iter_stack_pop (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
846{
847 xtensa_ld_iter_stack *stack;
848
849 stack = *stack_p;
850
0c7a8e5a 851 if (stack == NULL)
e0001a05
NC
852 {
853 ASSERT (stack != NULL);
854 return;
855 }
856
0c7a8e5a 857 if (stack->next != NULL)
e0001a05
NC
858 stack->next->prev = NULL;
859
860 *stack_p = stack->next;
861 free (stack);
862}
863
864
865/* This MUST be called if, during iteration, the user changes the
866 underlying structure. It will check for a NULL current and advance
867 accordingly. */
868
869static void
0c7a8e5a 870iter_stack_update (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
871{
872 if (!iter_stack_empty (stack_p)
0c7a8e5a 873 && (*(*stack_p)->iterloc.loc) == NULL)
e0001a05
NC
874 {
875 iter_stack_pop (stack_p);
876
877 while (!iter_stack_empty (stack_p)
878 && ((*(*stack_p)->iterloc.loc)->header.next == NULL))
879 {
880 iter_stack_pop (stack_p);
881 }
882 if (!iter_stack_empty (stack_p))
883 (*stack_p)->iterloc.loc = &(*(*stack_p)->iterloc.loc)->header.next;
884 }
885}
886
887
0c7a8e5a
AM
888static void
889iter_stack_next (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
890{
891 xtensa_ld_iter_stack *stack;
892 lang_statement_union_type *current;
893 stack = *stack_p;
894
895 current = *stack->iterloc.loc;
896 /* If we are on the first element. */
0c7a8e5a 897 if (current != NULL)
e0001a05 898 {
0c7a8e5a 899 switch (current->header.type)
e0001a05
NC
900 {
901 case lang_output_section_statement_enum:
902 case lang_wild_statement_enum:
903 case lang_group_statement_enum:
904 /* If the list if not empty, we are done. */
905 if (iter_stack_push (stack_p, *stack->iterloc.loc))
906 return;
907 /* Otherwise increment the pointer as normal. */
908 break;
909 default:
910 break;
911 }
912 }
913
914 while (!iter_stack_empty (stack_p)
915 && ((*(*stack_p)->iterloc.loc)->header.next == NULL))
916 {
917 iter_stack_pop (stack_p);
918 }
919 if (!iter_stack_empty (stack_p))
920 (*stack_p)->iterloc.loc = &(*(*stack_p)->iterloc.loc)->header.next;
921}
922
923
924static lang_statement_union_type *
0c7a8e5a 925iter_stack_current (xtensa_ld_iter_stack **stack_p)
e0001a05
NC
926{
927 return *((*stack_p)->iterloc.loc);
928}
929
930
931/* The iter stack is a preorder. */
932
0c7a8e5a
AM
933static void
934iter_stack_create (xtensa_ld_iter_stack **stack_p,
935 lang_statement_union_type *parent)
e0001a05
NC
936{
937 iter_stack_push (stack_p, parent);
938}
939
940
0c7a8e5a 941static void
7fa3d080 942iter_stack_copy_current (xtensa_ld_iter_stack **stack_p, xtensa_ld_iter *front)
e0001a05
NC
943{
944 *front = (*stack_p)->iterloc;
945}
946
947
0c7a8e5a
AM
948static void
949xtensa_colocate_literals (reloc_deps_graph *deps,
950 lang_statement_union_type *statement)
e0001a05
NC
951{
952 /* Keep a stack of pointers to control iteration through the contours. */
953 xtensa_ld_iter_stack *stack = NULL;
954 xtensa_ld_iter_stack **stack_p = &stack;
955
956 xtensa_ld_iter front; /* Location where new insertion should occur. */
957 xtensa_ld_iter *front_p = NULL;
958
959 xtensa_ld_iter current; /* Location we are checking. */
960 xtensa_ld_iter *current_p = NULL;
f38a2680 961 bool in_literals = false;
e0001a05
NC
962
963 if (deps->count == 0)
964 return;
965
e0001a05
NC
966 iter_stack_create (stack_p, statement);
967
0c7a8e5a 968 while (!iter_stack_empty (stack_p))
e0001a05 969 {
f38a2680 970 bool skip_increment = false;
e0001a05 971 lang_statement_union_type *l = iter_stack_current (stack_p);
0c7a8e5a
AM
972
973 switch (l->header.type)
e0001a05
NC
974 {
975 case lang_assignment_statement_enum:
976 /* Any assignment statement should block reordering across it. */
977 front_p = NULL;
f38a2680 978 in_literals = false;
e0001a05
NC
979 break;
980
981 case lang_input_section_enum:
982 if (front_p == NULL)
983 {
984 in_literals = (section_is_target (deps, l)
985 && !section_is_source (deps, l));
0c7a8e5a 986 if (in_literals)
e0001a05
NC
987 {
988 front_p = &front;
989 iter_stack_copy_current (stack_p, front_p);
990 }
0c7a8e5a 991 }
e0001a05
NC
992 else
993 {
f38a2680 994 bool is_target;
e0001a05
NC
995 current_p = &current;
996 iter_stack_copy_current (stack_p, current_p);
997 is_target = (section_is_target (deps, l)
998 && !section_is_source (deps, l));
999
1000 if (in_literals)
1001 {
1002 iter_stack_copy_current (stack_p, front_p);
1003 if (!is_target)
f38a2680 1004 in_literals = false;
e0001a05
NC
1005 }
1006 else
1007 {
0c7a8e5a 1008 if (is_target)
e0001a05
NC
1009 {
1010 /* Try to insert in place. */
1011 ld_xtensa_move_section_after (front_p, current_p);
0c7a8e5a 1012 ld_assign_relative_paged_dot (0x100000,
e0001a05
NC
1013 statement,
1014 deps,
1015 xtensa_use_literal_pages);
0c7a8e5a 1016
e0001a05
NC
1017 /* We use this code because it's already written. */
1018 if (!ld_local_file_relocations_fit (statement, deps))
1019 {
1020 /* Move it back. */
1021 ld_xtensa_move_section_after (current_p, front_p);
1022 /* Reset the literal placement. */
1023 iter_stack_copy_current (stack_p, front_p);
1024 }
0c7a8e5a 1025 else
e0001a05
NC
1026 {
1027 /* Move front pointer up by one. */
1028 front_p->loc = &(*front_p->loc)->header.next;
1029
1030 /* Do not increment the current pointer. */
f38a2680 1031 skip_increment = true;
e0001a05
NC
1032 }
1033 }
1034 }
1035 }
1036 break;
1037 default:
1038 break;
1039 }
1040
1041 if (!skip_increment)
1042 iter_stack_next (stack_p);
1043 else
1044 /* Be careful to update the stack_p if it now is a null. */
1045 iter_stack_update (stack_p);
1046 }
0c7a8e5a 1047
e0001a05
NC
1048 lang_for_each_statement_worker (xtensa_ldlang_clear_addresses, statement);
1049}
1050
1051
0c7a8e5a
AM
1052static void
1053xtensa_move_dependencies_to_front (reloc_deps_graph *deps,
1054 lang_wild_statement_type *w)
e0001a05
NC
1055{
1056 /* Keep a front pointer and a current pointer. */
1057 lang_statement_union_type **front;
1058 lang_statement_union_type **current;
1059
1060 /* Walk to the end of the targets. */
1061 for (front = &w->children.head;
1062 (*front != NULL) && section_is_source_or_target (deps, *front);
1063 front = &(*front)->header.next)
1064 ;
1065
1066 if (*front == NULL)
1067 return;
1068
1069 current = &(*front)->header.next;
0c7a8e5a 1070 while (*current != NULL)
e0001a05
NC
1071 {
1072 if (section_is_source_or_target (deps, *current))
1073 {
1074 /* Insert in place. */
1075 xtensa_ld_iter front_iter;
1076 xtensa_ld_iter current_iter;
1077
1078 front_iter.parent = (lang_statement_union_type *) w;
1079 front_iter.l = &w->children;
1080 front_iter.loc = front;
1081
1082 current_iter.parent = (lang_statement_union_type *) w;
1083 current_iter.l = &w->children;
1084 current_iter.loc = current;
1085
1086 ld_xtensa_move_section_after (&front_iter, &current_iter);
1087 front = &(*front)->header.next;
1088 }
1089 else
1090 {
1091 current = &(*current)->header.next;
1092 }
1093 }
1094}
1095
1096
f38a2680 1097static bool
7fa3d080 1098deps_has_sec_edge (const reloc_deps_graph *deps, asection *src, asection *tgt)
e0001a05
NC
1099{
1100 const reloc_deps_section *sec_deps;
1101 const reloc_deps_e *sec_deps_e;
1102
1103 sec_deps = xtensa_get_section_deps (deps, src);
1104 if (sec_deps == NULL)
f38a2680 1105 return false;
0c7a8e5a 1106
e0001a05 1107 for (sec_deps_e = sec_deps->succs;
0c7a8e5a 1108 sec_deps_e != NULL;
e0001a05
NC
1109 sec_deps_e = sec_deps_e->next)
1110 {
1111 ASSERT (sec_deps_e->src == src);
0c7a8e5a 1112 if (sec_deps_e->tgt == tgt)
f38a2680 1113 return true;
e0001a05 1114 }
f38a2680 1115 return false;
e0001a05
NC
1116}
1117
1118
f38a2680 1119static bool
0c7a8e5a
AM
1120deps_has_edge (const reloc_deps_graph *deps,
1121 lang_statement_union_type *src,
1122 lang_statement_union_type *tgt)
e0001a05
NC
1123{
1124 if (!section_is_source (deps, src))
f38a2680 1125 return false;
e0001a05 1126 if (!section_is_target (deps, tgt))
f38a2680 1127 return false;
e0001a05
NC
1128
1129 if (src->header.type != lang_input_section_enum)
f38a2680 1130 return false;
e0001a05 1131 if (tgt->header.type != lang_input_section_enum)
f38a2680 1132 return false;
0c7a8e5a 1133
e0001a05
NC
1134 return deps_has_sec_edge (deps, src->input_section.section,
1135 tgt->input_section.section);
1136}
1137
1138
1139static void
7fa3d080 1140add_deps_edge (reloc_deps_graph *deps, asection *src_sec, asection *tgt_sec)
e0001a05
NC
1141{
1142 reloc_deps_section *src_sec_deps;
1143 reloc_deps_section *tgt_sec_deps;
1144
1145 reloc_deps_e *src_edge;
1146 reloc_deps_e *tgt_edge;
1147
1148 if (deps_has_sec_edge (deps, src_sec, tgt_sec))
1149 return;
0c7a8e5a 1150
e0001a05
NC
1151 src_sec_deps = xtensa_get_section_deps (deps, src_sec);
1152 if (src_sec_deps == NULL)
1153 {
1154 /* Add a section. */
0c7a8e5a 1155 src_sec_deps = xmalloc (sizeof (reloc_deps_section));
e0001a05
NC
1156 memset (src_sec_deps, 0, sizeof (reloc_deps_section));
1157 src_sec_deps->is_only_literal = 0;
1158 src_sec_deps->preds = NULL;
1159 src_sec_deps->succs = NULL;
1160 xtensa_set_section_deps (deps, src_sec, src_sec_deps);
1161 xtensa_append_section_deps (deps, src_sec);
1162 }
1163
1164 tgt_sec_deps = xtensa_get_section_deps (deps, tgt_sec);
1165 if (tgt_sec_deps == NULL)
1166 {
1167 /* Add a section. */
0c7a8e5a 1168 tgt_sec_deps = xmalloc (sizeof (reloc_deps_section));
e0001a05
NC
1169 memset (tgt_sec_deps, 0, sizeof (reloc_deps_section));
1170 tgt_sec_deps->is_only_literal = 0;
1171 tgt_sec_deps->preds = NULL;
1172 tgt_sec_deps->succs = NULL;
1173 xtensa_set_section_deps (deps, tgt_sec, tgt_sec_deps);
1174 xtensa_append_section_deps (deps, tgt_sec);
1175 }
1176
1177 /* Add the edges. */
0c7a8e5a 1178 src_edge = xmalloc (sizeof (reloc_deps_e));
e0001a05
NC
1179 memset (src_edge, 0, sizeof (reloc_deps_e));
1180 src_edge->src = src_sec;
1181 src_edge->tgt = tgt_sec;
1182 src_edge->next = src_sec_deps->succs;
1183 src_sec_deps->succs = src_edge;
1184
0c7a8e5a 1185 tgt_edge = xmalloc (sizeof (reloc_deps_e));
e0001a05
NC
1186 memset (tgt_edge, 0, sizeof (reloc_deps_e));
1187 tgt_edge->src = src_sec;
1188 tgt_edge->tgt = tgt_sec;
1189 tgt_edge->next = tgt_sec_deps->preds;
1190 tgt_sec_deps->preds = tgt_edge;
1191}
1192
1193
0c7a8e5a
AM
1194static void
1195build_deps_graph_callback (asection *src_sec,
1196 bfd_vma src_offset ATTRIBUTE_UNUSED,
1197 asection *target_sec,
1198 bfd_vma target_offset ATTRIBUTE_UNUSED,
1199 void *closure)
e0001a05 1200{
0c7a8e5a 1201 reloc_deps_graph *deps = closure;
e0001a05
NC
1202
1203 /* If the target is defined. */
1204 if (target_sec != NULL)
1205 add_deps_edge (deps, src_sec, target_sec);
1206}
1207
1208
0c7a8e5a
AM
1209static reloc_deps_graph *
1210ld_build_required_section_dependence (lang_statement_union_type *s)
e0001a05
NC
1211{
1212 reloc_deps_graph *deps;
1213 xtensa_ld_iter_stack *stack = NULL;
1214
0c7a8e5a 1215 deps = xmalloc (sizeof (reloc_deps_graph));
e0001a05
NC
1216 deps->sections = NULL;
1217 deps->count = 0;
1218 deps->size = 0;
0c7a8e5a 1219
e0001a05
NC
1220 for (iter_stack_create (&stack, s);
1221 !iter_stack_empty (&stack);
0c7a8e5a 1222 iter_stack_next (&stack))
e0001a05
NC
1223 {
1224 lang_statement_union_type *l = iter_stack_current (&stack);
1225
abf874aa 1226 if (l == NULL && link_info.non_contiguous_regions)
53215f21
CL
1227 einfo (_("%F%P: Relaxation not supported with "
1228 "--enable-non-contiguous-regions.\n"));
abf874aa 1229
e0001a05
NC
1230 if (l->header.type == lang_input_section_enum)
1231 {
1232 lang_input_section_type *input;
1233 input = &l->input_section;
7b986e99 1234 xtensa_callback_required_dependence (input->section->owner,
e0001a05
NC
1235 input->section,
1236 &link_info,
1237 /* Use the same closure. */
1238 build_deps_graph_callback,
0c7a8e5a 1239 deps);
e0001a05
NC
1240 }
1241 }
1242 return deps;
1243}
1244
1245
1246#if EXTRA_VALIDATION
0c7a8e5a
AM
1247static size_t
1248ld_count_children (lang_statement_union_type *s)
e0001a05
NC
1249{
1250 size_t count = 0;
1251 xtensa_ld_iter_stack *stack = NULL;
1252 for (iter_stack_create (&stack, s);
1253 !iter_stack_empty (&stack);
0c7a8e5a 1254 iter_stack_next (&stack))
e0001a05
NC
1255 {
1256 lang_statement_union_type *l = iter_stack_current (&stack);
1257 ASSERT (l != NULL);
1258 count++;
1259 }
1260 return count;
1261}
1262#endif /* EXTRA_VALIDATION */
1263
1264
a255b6c7
BW
1265/* Check if a particular section is included in the link. This will only
1266 be true for one instance of a particular linkonce section. */
1267
f38a2680 1268static bool input_section_found = false;
a255b6c7
BW
1269static asection *input_section_target = NULL;
1270
1271static void
1272input_section_linked_worker (lang_statement_union_type *statement)
1273{
1274 if ((statement->header.type == lang_input_section_enum
1275 && (statement->input_section.section == input_section_target)))
f38a2680 1276 input_section_found = true;
a255b6c7
BW
1277}
1278
f38a2680 1279static bool
a255b6c7
BW
1280input_section_linked (asection *sec)
1281{
f38a2680 1282 input_section_found = false;
a255b6c7
BW
1283 input_section_target = sec;
1284 lang_for_each_statement_worker (input_section_linked_worker, stat_ptr->head);
1285 return input_section_found;
1286}
1287
1288
a77dc2cc 1289/* Strip out any linkonce property tables or XCC exception tables where the
a255b6c7
BW
1290 associated linkonce text is from a different object file. Normally,
1291 a matching set of linkonce sections is taken from the same object file,
1292 but sometimes the files are compiled differently so that some of the
1293 linkonce sections are not present in all files. Stripping the
1294 inconsistent sections like this is not completely robust -- a much
1295 better solution is to use comdat groups. */
1296
1297static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
1298
f38a2680 1299static bool
a255b6c7
BW
1300is_inconsistent_linkonce_section (asection *sec)
1301{
1302 bfd *abfd = sec->owner;
fd361982 1303 const char *sec_name = bfd_section_name (sec);
a77dc2cc 1304 const char *name;
a255b6c7 1305
fd361982 1306 if ((bfd_section_flags (sec) & SEC_LINK_ONCE) == 0
a255b6c7 1307 || strncmp (sec_name, ".gnu.linkonce.", linkonce_len) != 0)
f38a2680 1308 return false;
a255b6c7 1309
a77dc2cc
BW
1310 /* Check if this is an Xtensa property section or an exception table
1311 for Tensilica's XCC compiler. */
1312 name = sec_name + linkonce_len;
08dedd66 1313 if (startswith (name, "prop."))
e7d17e71 1314 name = strchr (name + 5, '.') ? strchr (name + 5, '.') + 1 : name + 5;
a77dc2cc
BW
1315 else if (name[1] == '.'
1316 && (name[0] == 'p' || name[0] == 'e' || name[0] == 'h'))
1317 name += 2;
1318 else
1319 name = 0;
644143c8
BW
1320
1321 if (name)
a255b6c7 1322 {
644143c8 1323 char *dep_sec_name = xmalloc (strlen (sec_name) + 1);
a255b6c7
BW
1324 asection *dep_sec;
1325
1326 /* Get the associated linkonce text section and check if it is
1327 included in the link. If not, this section is inconsistent
1328 and should be stripped. */
644143c8
BW
1329 strcpy (dep_sec_name, ".gnu.linkonce.t.");
1330 strcat (dep_sec_name, name);
a255b6c7
BW
1331 dep_sec = bfd_get_section_by_name (abfd, dep_sec_name);
1332 if (dep_sec == NULL || ! input_section_linked (dep_sec))
1333 {
1334 free (dep_sec_name);
f38a2680 1335 return true;
a255b6c7
BW
1336 }
1337 free (dep_sec_name);
1338 }
1339
f38a2680 1340 return false;
a255b6c7
BW
1341}
1342
1343
1344static void
1345xtensa_strip_inconsistent_linkonce_sections (lang_statement_list_type *slist)
1346{
1347 lang_statement_union_type **s_p = &slist->head;
1348 while (*s_p)
1349 {
1350 lang_statement_union_type *s = *s_p;
1351 lang_statement_union_type *s_next = (*s_p)->header.next;
1352
1353 switch (s->header.type)
1354 {
1355 case lang_input_section_enum:
1356 if (is_inconsistent_linkonce_section (s->input_section.section))
1357 {
b2f28975 1358 s->input_section.section->output_section = bfd_abs_section_ptr;
a255b6c7
BW
1359 *s_p = s_next;
1360 continue;
1361 }
1362 break;
1363
1364 case lang_constructors_statement_enum:
1365 xtensa_strip_inconsistent_linkonce_sections (&constructor_list);
1366 break;
1367
1368 case lang_output_section_statement_enum:
1369 if (s->output_section_statement.children.head)
1370 xtensa_strip_inconsistent_linkonce_sections
1371 (&s->output_section_statement.children);
1372 break;
1373
1374 case lang_wild_statement_enum:
1375 xtensa_strip_inconsistent_linkonce_sections
1376 (&s->wild_statement.children);
1377 break;
1378
1379 case lang_group_statement_enum:
1380 xtensa_strip_inconsistent_linkonce_sections
1381 (&s->group_statement.children);
1382 break;
1383
1384 case lang_data_statement_enum:
1385 case lang_reloc_statement_enum:
1386 case lang_object_symbols_statement_enum:
1387 case lang_output_statement_enum:
1388 case lang_target_statement_enum:
1389 case lang_input_statement_enum:
1390 case lang_assignment_statement_enum:
1391 case lang_padding_statement_enum:
1392 case lang_address_statement_enum:
1393 case lang_fill_statement_enum:
1394 break;
1395
1396 default:
1397 FAIL ();
1398 break;
1399 }
1400
1401 s_p = &(*s_p)->header.next;
1402 }
1403
1404 /* Reset the tail of the list, in case the last entry was removed. */
1405 if (s_p != slist->tail)
1406 slist->tail = s_p;
1407}
1408
1409
0c7a8e5a
AM
1410static void
1411xtensa_wild_group_interleave_callback (lang_statement_union_type *statement)
e0001a05
NC
1412{
1413 lang_wild_statement_type *w;
1414 reloc_deps_graph *deps;
1415 if (statement->header.type == lang_wild_statement_enum)
1416 {
1417#if EXTRA_VALIDATION
1418 size_t old_child_count;
1419 size_t new_child_count;
1420#endif
f38a2680 1421 bool no_reorder;
e0001a05
NC
1422
1423 w = &statement->wild_statement;
1424
f38a2680 1425 no_reorder = false;
e0001a05
NC
1426
1427 /* If it has 0 or 1 section bound, then do not reorder. */
1428 if (w->children.head == NULL
1429 || (w->children.head->header.type == lang_input_section_enum
1430 && w->children.head->header.next == NULL))
f38a2680 1431 no_reorder = true;
e0001a05
NC
1432
1433 if (w->filenames_sorted)
f38a2680 1434 no_reorder = true;
e0001a05
NC
1435
1436 /* Check for sorting in a section list wildcard spec as well. */
1437 if (!no_reorder)
1438 {
1439 struct wildcard_list *l;
1440 for (l = w->section_list; l != NULL; l = l->next)
1441 {
73d5923e 1442 if (l->spec.sorted == by_name)
e0001a05 1443 {
f38a2680 1444 no_reorder = true;
e0001a05
NC
1445 break;
1446 }
1447 }
0c7a8e5a 1448 }
e0001a05
NC
1449
1450 /* Special case until the NOREORDER linker directive is supported:
0c7a8e5a 1451 *(.init) output sections and *(.fini) specs may NOT be reordered. */
e0001a05
NC
1452
1453 /* Check for sorting in a section list wildcard spec as well. */
0c7a8e5a 1454 if (!no_reorder)
e0001a05
NC
1455 {
1456 struct wildcard_list *l;
1457 for (l = w->section_list; l != NULL; l = l->next)
1458 {
1459 if (l->spec.name
1460 && ((strcmp (".init", l->spec.name) == 0)
1461 || (strcmp (".fini", l->spec.name) == 0)))
1462 {
f38a2680 1463 no_reorder = true;
e0001a05
NC
1464 break;
1465 }
1466 }
1467 }
1468
1469#if EXTRA_VALIDATION
1470 old_child_count = ld_count_children (statement);
1471#endif
1472
1473 /* It is now officially a target. Build the graph of source
0c7a8e5a 1474 section -> target section (kept as a list of edges). */
e0001a05
NC
1475 deps = ld_build_required_section_dependence (statement);
1476
1477 /* If this wildcard does not reorder.... */
1478 if (!no_reorder && deps->count != 0)
1479 {
1480 /* First check for reverse dependences. Fix if possible. */
1481 xtensa_layout_wild (deps, w);
1482
1483 xtensa_move_dependencies_to_front (deps, w);
1484#if EXTRA_VALIDATION
1485 new_child_count = ld_count_children (statement);
1486 ASSERT (new_child_count == old_child_count);
1487#endif
1488
1489 xtensa_colocate_literals (deps, statement);
1490
1491#if EXTRA_VALIDATION
1492 new_child_count = ld_count_children (statement);
1493 ASSERT (new_child_count == old_child_count);
1494#endif
1495 }
1496
1497 /* Clean up. */
1498 free_reloc_deps_graph (deps);
1499 }
1500}
1501
1502
0c7a8e5a
AM
1503static void
1504xtensa_wild_group_interleave (lang_statement_union_type *s)
e0001a05
NC
1505{
1506 lang_for_each_statement_worker (xtensa_wild_group_interleave_callback, s);
1507}
1508
1509
0c7a8e5a 1510static void
7fa3d080 1511xtensa_layout_wild (const reloc_deps_graph *deps, lang_wild_statement_type *w)
e0001a05
NC
1512{
1513 /* If it does not fit initially, we need to do this step. Move all
1514 of the wild literal sections to a new list, then move each of
1515 them back in just before the first section they depend on. */
1516 lang_statement_union_type **s_p;
1517#if EXTRA_VALIDATION
1518 size_t old_count, new_count;
1519 size_t ct1, ct2;
1520#endif
0c7a8e5a 1521
e0001a05
NC
1522 lang_wild_statement_type literal_wild;
1523 literal_wild.header.next = NULL;
1524 literal_wild.header.type = lang_wild_statement_enum;
1525 literal_wild.filename = NULL;
f38a2680 1526 literal_wild.filenames_sorted = false;
e0001a05 1527 literal_wild.section_list = NULL;
f38a2680 1528 literal_wild.keep_sections = false;
e0001a05
NC
1529 literal_wild.children.head = NULL;
1530 literal_wild.children.tail = &literal_wild.children.head;
1531
1532#if EXTRA_VALIDATION
1533 old_count = ld_count_children ((lang_statement_union_type*) w);
1534#endif
1535
1536 s_p = &w->children.head;
1537 while (*s_p != NULL)
1538 {
1539 lang_statement_union_type *l = *s_p;
1540 if (l->header.type == lang_input_section_enum)
1541 {
1542 if (section_is_target (deps, l)
0c7a8e5a 1543 && ! section_is_source (deps, l))
e0001a05
NC
1544 {
1545 /* Detach. */
1546 *s_p = l->header.next;
1547 if (*s_p == NULL)
1548 w->children.tail = s_p;
1549 l->header.next = NULL;
1550
1551 /* Append. */
1552 *literal_wild.children.tail = l;
1553 literal_wild.children.tail = &l->header.next;
1554 continue;
0c7a8e5a 1555 }
e0001a05
NC
1556 }
1557 s_p = &(*s_p)->header.next;
1558 }
1559
1560#if EXTRA_VALIDATION
1561 ct1 = ld_count_children ((lang_statement_union_type*) w);
1562 ct2 = ld_count_children ((lang_statement_union_type*) &literal_wild);
0c7a8e5a 1563
e0001a05
NC
1564 ASSERT (old_count == (ct1 + ct2));
1565#endif
0c7a8e5a 1566
e0001a05
NC
1567 /* Now place them back in front of their dependent sections. */
1568
1569 while (literal_wild.children.head != NULL)
1570 {
1571 lang_statement_union_type *lit = literal_wild.children.head;
f38a2680 1572 bool placed = false;
e0001a05
NC
1573
1574#if EXTRA_VALIDATION
1575 ASSERT (ct2 > 0);
1576 ct2--;
1577#endif
1578
1579 /* Detach. */
1580 literal_wild.children.head = lit->header.next;
0c7a8e5a 1581 if (literal_wild.children.head == NULL)
e0001a05
NC
1582 literal_wild.children.tail = &literal_wild.children.head;
1583 lit->header.next = NULL;
1584
1585 /* Find a spot to place it. */
0c7a8e5a 1586 for (s_p = &w->children.head; *s_p != NULL; s_p = &(*s_p)->header.next)
e0001a05
NC
1587 {
1588 lang_statement_union_type *src = *s_p;
1589 if (deps_has_edge (deps, src, lit))
1590 {
1591 /* Place it here. */
1592 lit->header.next = *s_p;
1593 *s_p = lit;
f38a2680 1594 placed = true;
e0001a05
NC
1595 break;
1596 }
1597 }
0c7a8e5a 1598
e0001a05
NC
1599 if (!placed)
1600 {
1601 /* Put it at the end. */
1602 *w->children.tail = lit;
1603 w->children.tail = &lit->header.next;
1604 }
1605 }
1606
1607#if EXTRA_VALIDATION
1608 new_count = ld_count_children ((lang_statement_union_type*) w);
1609 ASSERT (new_count == old_count);
1610#endif
1611}
1612
1613
0c7a8e5a
AM
1614static void
1615xtensa_colocate_output_literals_callback (lang_statement_union_type *statement)
e0001a05 1616{
e0001a05
NC
1617 reloc_deps_graph *deps;
1618 if (statement->header.type == lang_output_section_statement_enum)
1619 {
1620 /* Now, we walk over the contours of the output section statement.
1621
1622 First we build the literal section dependences as before.
1623
1624 At the first uniquely_literal section, we mark it as a good
1625 spot to place other literals. Continue walking (and counting
1626 sizes) until we find the next literal section. If this
1627 section can be moved to the first one, then we move it. If
1628 we every find a modification of ".", start over. If we find
1629 a labeling of the current location, start over. Finally, at
1630 the end, if we require page alignment, add page alignments. */
1631
1632#if EXTRA_VALIDATION
1633 size_t old_child_count;
1634 size_t new_child_count;
1635#endif
f38a2680 1636 bool no_reorder = false;
e0001a05 1637
e0001a05
NC
1638#if EXTRA_VALIDATION
1639 old_child_count = ld_count_children (statement);
1640#endif
1641
1642 /* It is now officially a target. Build the graph of source
0c7a8e5a 1643 section -> target section (kept as a list of edges). */
e0001a05
NC
1644
1645 deps = ld_build_required_section_dependence (statement);
1646
1647 /* If this wildcard does not reorder.... */
1648 if (!no_reorder)
1649 {
1650 /* First check for reverse dependences. Fix if possible. */
1651 xtensa_colocate_literals (deps, statement);
1652
1653#if EXTRA_VALIDATION
1654 new_child_count = ld_count_children (statement);
1655 ASSERT (new_child_count == old_child_count);
1656#endif
1657 }
1658
1659 /* Insert align/offset assignment statement. */
1660 if (xtensa_use_literal_pages)
1661 {
0c7a8e5a 1662 ld_xtensa_insert_page_offsets (0, statement, deps,
e0001a05
NC
1663 xtensa_use_literal_pages);
1664 lang_for_each_statement_worker (xtensa_ldlang_clear_addresses,
1665 statement);
1666 }
1667
1668 /* Clean up. */
1669 free_reloc_deps_graph (deps);
1670 }
1671}
1672
1673
0c7a8e5a
AM
1674static void
1675xtensa_colocate_output_literals (lang_statement_union_type *s)
e0001a05
NC
1676{
1677 lang_for_each_statement_worker (xtensa_colocate_output_literals_callback, s);
1678}
1679
1680
0c7a8e5a
AM
1681static void
1682xtensa_ldlang_clear_addresses (lang_statement_union_type *statement)
e0001a05
NC
1683{
1684 switch (statement->header.type)
1685 {
0c7a8e5a 1686 case lang_input_section_enum:
e0001a05
NC
1687 {
1688 asection *bfd_section = statement->input_section.section;
1689 bfd_section->output_offset = 0;
1690 }
1691 break;
1692 default:
1693 break;
1694 }
1695}
1696
1697
0c7a8e5a
AM
1698static bfd_vma
1699ld_assign_relative_paged_dot (bfd_vma dot,
1700 lang_statement_union_type *s,
1701 const reloc_deps_graph *deps ATTRIBUTE_UNUSED,
f38a2680 1702 bool lit_align)
e0001a05
NC
1703{
1704 /* Walk through all of the input statements in this wild statement
1705 assign dot to all of them. */
0c7a8e5a 1706
e0001a05
NC
1707 xtensa_ld_iter_stack *stack = NULL;
1708 xtensa_ld_iter_stack **stack_p = &stack;
1709
f38a2680
AM
1710 bool first_section = false;
1711 bool in_literals = false;
e0001a05
NC
1712
1713 for (iter_stack_create (stack_p, s);
1714 !iter_stack_empty (stack_p);
0c7a8e5a 1715 iter_stack_next (stack_p))
e0001a05
NC
1716 {
1717 lang_statement_union_type *l = iter_stack_current (stack_p);
0c7a8e5a
AM
1718
1719 switch (l->header.type)
e0001a05
NC
1720 {
1721 case lang_input_section_enum:
1722 {
1723 asection *section = l->input_section.section;
1724 size_t align_pow = section->alignment_power;
f38a2680 1725 bool do_xtensa_alignment = false;
0c7a8e5a 1726
e0001a05
NC
1727 if (lit_align)
1728 {
f38a2680
AM
1729 bool sec_is_target = section_is_target (deps, l);
1730 bool sec_is_source = section_is_source (deps, l);
e0001a05 1731
eea6121a 1732 if (section->size != 0
e0001a05
NC
1733 && (first_section
1734 || (in_literals && !sec_is_target)
1735 || (!in_literals && sec_is_target)))
1736 {
f38a2680 1737 do_xtensa_alignment = true;
e0001a05 1738 }
f38a2680 1739 first_section = false;
eea6121a 1740 if (section->size != 0)
e0001a05
NC
1741 in_literals = (sec_is_target && !sec_is_source);
1742 }
1743
1744 if (do_xtensa_alignment && xtensa_page_power != 0)
1745 dot += (1 << xtensa_page_power);
1746
1747 dot = align_power (dot, align_pow);
1748 section->output_offset = dot;
eea6121a 1749 dot += section->size;
e0001a05
NC
1750 }
1751 break;
1752 case lang_fill_statement_enum:
1753 dot += l->fill_statement.size;
1754 break;
1755 case lang_padding_statement_enum:
1756 dot += l->padding_statement.size;
1757 break;
1758 default:
1759 break;
1760 }
1761 }
1762 return dot;
1763}
1764
1765
f38a2680 1766static bool
0c7a8e5a
AM
1767ld_local_file_relocations_fit (lang_statement_union_type *statement,
1768 const reloc_deps_graph *deps ATTRIBUTE_UNUSED)
e0001a05
NC
1769{
1770 /* Walk over all of the dependencies that we identified and make
1771 sure that IF the source and target are here (addr != 0):
1772 1) target addr < source addr
0c7a8e5a 1773 2) (roundup(source + source_size, 4) - rounddown(target, 4))
e0001a05
NC
1774 < (256K - (1 << bad align))
1775 Need a worst-case proof.... */
0c7a8e5a 1776
e0001a05
NC
1777 xtensa_ld_iter_stack *stack = NULL;
1778 xtensa_ld_iter_stack **stack_p = &stack;
1779 size_t max_align_power = 0;
1780 size_t align_penalty = 256;
1781 reloc_deps_e *e;
1782 size_t i;
1783
1784 /* Find the worst-case alignment requirement for this set of statements. */
1785 for (iter_stack_create (stack_p, statement);
1786 !iter_stack_empty (stack_p);
0c7a8e5a 1787 iter_stack_next (stack_p))
e0001a05
NC
1788 {
1789 lang_statement_union_type *l = iter_stack_current (stack_p);
0c7a8e5a 1790 if (l->header.type == lang_input_section_enum)
e0001a05
NC
1791 {
1792 lang_input_section_type *input = &l->input_section;
1793 asection *section = input->section;
1794 if (section->alignment_power > max_align_power)
1795 max_align_power = section->alignment_power;
1796 }
1797 }
1798
1799 /* Now check that everything fits. */
1800 for (i = 0; i < deps->count; i++)
1801 {
1802 asection *sec = deps->sections[i];
0c7a8e5a 1803 const reloc_deps_section *deps_section =
e0001a05
NC
1804 xtensa_get_section_deps (deps, sec);
1805 if (deps_section)
1806 {
1807 /* We choose to walk through the successors. */
1808 for (e = deps_section->succs; e != NULL; e = e->next)
1809 {
0c7a8e5a 1810 if (e->src != e->tgt
e0001a05
NC
1811 && e->src->output_section == e->tgt->output_section
1812 && e->src->output_offset != 0
1813 && e->tgt->output_offset != 0)
1814 {
0c7a8e5a 1815 bfd_vma l32r_addr =
eea6121a 1816 align_power (e->src->output_offset + e->src->size, 2);
0c7a8e5a 1817 bfd_vma target_addr = e->tgt->output_offset & ~3;
e0001a05
NC
1818 if (l32r_addr < target_addr)
1819 {
e922bcab 1820 fflush (stdout);
e0001a05
NC
1821 fprintf (stderr, "Warning: "
1822 "l32r target section before l32r\n");
e922bcab 1823 fflush (stderr);
f38a2680 1824 return false;
e0001a05
NC
1825 }
1826
0c7a8e5a 1827 if (l32r_addr - target_addr > 256 * 1024 - align_penalty)
f38a2680 1828 return false;
e0001a05
NC
1829 }
1830 }
1831 }
1832 }
1833
f38a2680 1834 return true;
e0001a05
NC
1835}
1836
1837
0c7a8e5a
AM
1838static bfd_vma
1839ld_xtensa_insert_page_offsets (bfd_vma dot,
1840 lang_statement_union_type *s,
1841 reloc_deps_graph *deps,
f38a2680 1842 bool lit_align)
e0001a05
NC
1843{
1844 xtensa_ld_iter_stack *stack = NULL;
1845 xtensa_ld_iter_stack **stack_p = &stack;
1846
f38a2680
AM
1847 bool first_section = false;
1848 bool in_literals = false;
0c7a8e5a 1849
e0001a05 1850 if (!lit_align)
f38a2680 1851 return false;
e0001a05
NC
1852
1853 for (iter_stack_create (stack_p, s);
1854 !iter_stack_empty (stack_p);
0c7a8e5a 1855 iter_stack_next (stack_p))
e0001a05
NC
1856 {
1857 lang_statement_union_type *l = iter_stack_current (stack_p);
1858
0c7a8e5a
AM
1859 switch (l->header.type)
1860 {
e0001a05
NC
1861 case lang_input_section_enum:
1862 {
1863 asection *section = l->input_section.section;
f38a2680 1864 bool do_xtensa_alignment = false;
0c7a8e5a 1865
e0001a05
NC
1866 if (lit_align)
1867 {
eea6121a 1868 if (section->size != 0
e0001a05
NC
1869 && (first_section
1870 || (in_literals && !section_is_target (deps, l))
1871 || (!in_literals && section_is_target (deps, l))))
1872 {
f38a2680 1873 do_xtensa_alignment = true;
e0001a05 1874 }
f38a2680 1875 first_section = false;
eea6121a 1876 if (section->size != 0)
e0001a05
NC
1877 {
1878 in_literals = (section_is_target (deps, l)
1879 && !section_is_source (deps, l));
1880 }
1881 }
1882
1883 if (do_xtensa_alignment && xtensa_page_power != 0)
1884 {
1885 /* Create an expression that increments the current address,
1886 i.e., "dot", by (1 << xtensa_align_power). */
1887 etree_type *name_op = exp_nameop (NAME, ".");
1888 etree_type *addend_op = exp_intop (1 << xtensa_page_power);
1889 etree_type *add_op = exp_binop ('+', name_op, addend_op);
f38a2680 1890 etree_type *assign_op = exp_assign (".", add_op, false);
e0001a05
NC
1891
1892 lang_assignment_statement_type *assign_stmt;
1893 lang_statement_union_type *assign_union;
1894 lang_statement_list_type tmplist;
0c7a8e5a 1895
e0001a05
NC
1896 /* There is hidden state in "lang_add_assignment". It
1897 appends the new assignment statement to the stat_ptr
1898 list. Thus, we swap it before and after the call. */
1899
bde18da4
AM
1900 lang_list_init (&tmplist);
1901 push_stat_ptr (&tmplist);
e0001a05
NC
1902 /* Warning: side effect; statement appended to stat_ptr. */
1903 assign_stmt = lang_add_assignment (assign_op);
1904 assign_union = (lang_statement_union_type *) assign_stmt;
bde18da4 1905 pop_stat_ptr ();
e0001a05
NC
1906
1907 assign_union->header.next = l;
1908 *(*stack_p)->iterloc.loc = assign_union;
1909 iter_stack_next (stack_p);
0c7a8e5a
AM
1910 }
1911 }
1912 break;
1913 default:
1914 break;
1915 }
e0001a05
NC
1916 }
1917 return dot;
1918}
1919
1920EOF
1921
43cd72b9 1922# Define some shell vars to insert bits of code into the standard ELF
e0001a05
NC
1923# parse_args and list_options functions.
1924#
1925PARSE_AND_LIST_PROLOGUE='
43cd72b9 1926#define OPTION_OPT_SIZEOPT (300)
28d5f677 1927#define OPTION_LITERAL_MOVEMENT (OPTION_OPT_SIZEOPT + 1)
43cd72b9 1928#define OPTION_NO_LITERAL_MOVEMENT (OPTION_LITERAL_MOVEMENT + 1)
7a77f1ac
MF
1929#define OPTION_ABI_WINDOWED (OPTION_NO_LITERAL_MOVEMENT + 1)
1930#define OPTION_ABI_CALL0 (OPTION_ABI_WINDOWED + 1)
43cd72b9
BW
1931extern int elf32xtensa_size_opt;
1932extern int elf32xtensa_no_literal_movement;
7a77f1ac 1933extern int elf32xtensa_abi;
e0001a05
NC
1934'
1935
1936PARSE_AND_LIST_LONGOPTS='
43cd72b9 1937 { "size-opt", no_argument, NULL, OPTION_OPT_SIZEOPT},
43cd72b9
BW
1938 { "literal-movement", no_argument, NULL, OPTION_LITERAL_MOVEMENT},
1939 { "no-literal-movement", no_argument, NULL, OPTION_NO_LITERAL_MOVEMENT},
7a77f1ac
MF
1940 { "abi-windowed", no_argument, NULL, OPTION_ABI_WINDOWED},
1941 { "abi-call0", no_argument, NULL, OPTION_ABI_CALL0},
e0001a05
NC
1942'
1943
1944PARSE_AND_LIST_OPTIONS='
442996ee
AM
1945 fprintf (file, _("\
1946 --size-opt When relaxing longcalls, prefer size\n\
1947 optimization over branch target alignment\n"));
7a77f1ac
MF
1948 fprintf (file, _("\
1949 --abi-windowed Choose windowed ABI for the output object\n"));
1950 fprintf (file, _("\
1951 --abi-call0 Choose call0 ABI for the output object\n"));
e0001a05
NC
1952'
1953
1954PARSE_AND_LIST_ARGS_CASES='
43cd72b9
BW
1955 case OPTION_OPT_SIZEOPT:
1956 elf32xtensa_size_opt = 1;
1957 break;
43cd72b9
BW
1958 case OPTION_LITERAL_MOVEMENT:
1959 elf32xtensa_no_literal_movement = 0;
1960 break;
1961 case OPTION_NO_LITERAL_MOVEMENT:
1962 elf32xtensa_no_literal_movement = 1;
1963 break;
7a77f1ac
MF
1964 case OPTION_ABI_WINDOWED:
1965 elf32xtensa_abi = XTHAL_ABI_WINDOWED;
1966 break;
1967 case OPTION_ABI_CALL0:
1968 elf32xtensa_abi = XTHAL_ABI_CALL0;
1969 break;
e0001a05
NC
1970'
1971
1972# Replace some of the standard ELF functions with our own versions.
1973#
1974LDEMUL_BEFORE_PARSE=elf_xtensa_before_parse
43cd72b9 1975LDEMUL_AFTER_OPEN=elf_xtensa_after_open
e0001a05 1976LDEMUL_CHOOSE_TARGET=elf_xtensa_choose_target
e0001a05 1977LDEMUL_BEFORE_ALLOCATION=elf_xtensa_before_allocation