xref: /netbsd-src/external/gpl3/binutils.old/dist/ld/emultempl/msp430.em (revision aef5eb5f59cdfe8314f1b5f78ac04eb144e44010)
1# This shell script emits a C file. -*- C -*-
2# It does some substitutions.
3fragment <<EOF
4/* This file is is generated by a shell script.  DO NOT EDIT! */
5
6/* Emulate the original gld for the given ${EMULATION_NAME}
7   Copyright (C) 2014-2018 Free Software Foundation, Inc.
8   Written by Steve Chamberlain steve@cygnus.com
9   Extended for the MSP430 by Nick Clifton  nickc@redhat.com
10
11   This file is part of the GNU Binutils.
12
13   This program is free software; you can redistribute it and/or modify
14   it under the terms of the GNU General Public License as published by
15   the Free Software Foundation; either version 3 of the License, or
16   (at your option) any later version.
17
18   This program is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details.
22
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
26   MA 02110-1301, USA.  */
27
28#define TARGET_IS_${EMULATION_NAME}
29
30#include "sysdep.h"
31#include "bfd.h"
32#include "bfdlink.h"
33
34#include "ld.h"
35#include "getopt.h"
36#include "ldmain.h"
37#include "ldmisc.h"
38#include "ldexp.h"
39#include "ldlang.h"
40#include "ldfile.h"
41#include "ldemul.h"
42#include "libiberty.h"
43#include <ldgram.h>
44
45enum regions
46{
47  REGION_NONE = 0,
48  REGION_LOWER,
49  REGION_UPPER,
50  REGION_EITHER = 3,
51};
52
53enum either_placement_stage
54{
55  LOWER_TO_UPPER,
56  UPPER_TO_LOWER,
57};
58
59enum { ROM, RAM };
60
61static int data_region = REGION_NONE;
62static int code_region = REGION_NONE;
63static bfd_boolean disable_sec_transformation = FALSE;
64
65#define MAX_PREFIX_LENGTH 7
66
67EOF
68
69# Import any needed special functions and/or overrides.
70#
71if test -n "$EXTRA_EM_FILE" ; then
72  source_em ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
73fi
74
75if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
76fragment <<EOF
77
78static void
79gld${EMULATION_NAME}_before_parse (void)
80{
81#ifndef TARGET_			/* I.e., if not generic.  */
82  ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
83#endif /* not TARGET_ */
84
85  /* The MSP430 port *needs* linker relaxtion in order to cope with large
86     functions where conditional branches do not fit into a +/- 1024 byte range.  */
87  if (!bfd_link_relocatable (&link_info))
88    TARGET_ENABLE_RELAXATION;
89}
90
91EOF
92fi
93
94if test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
95fragment <<EOF
96
97static char *
98gld${EMULATION_NAME}_get_script (int *isfile)
99EOF
100
101if test x"$COMPILE_IN" = xyes
102then
103# Scripts compiled in.
104
105# sed commands to quote an ld script as a C string.
106sc="-f stringify.sed"
107
108fragment <<EOF
109{
110  *isfile = 0;
111
112  if (bfd_link_relocatable (&link_info) && config.build_constructors)
113    return
114EOF
115sed $sc ldscripts/${EMULATION_NAME}.xu                 >> e${EMULATION_NAME}.c
116echo '  ; else if (bfd_link_relocatable (&link_info)) return' >> e${EMULATION_NAME}.c
117sed $sc ldscripts/${EMULATION_NAME}.xr                 >> e${EMULATION_NAME}.c
118echo '  ; else if (!config.text_read_only) return'     >> e${EMULATION_NAME}.c
119sed $sc ldscripts/${EMULATION_NAME}.xbn                >> e${EMULATION_NAME}.c
120echo '  ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
121sed $sc ldscripts/${EMULATION_NAME}.xn                 >> e${EMULATION_NAME}.c
122echo '  ; else return'                                 >> e${EMULATION_NAME}.c
123sed $sc ldscripts/${EMULATION_NAME}.x                  >> e${EMULATION_NAME}.c
124echo '; }'                                             >> e${EMULATION_NAME}.c
125
126else
127# Scripts read from the filesystem.
128
129fragment <<EOF
130{
131  *isfile = 1;
132
133  if (bfd_link_relocatable (&link_info) && config.build_constructors)
134    return "ldscripts/${EMULATION_NAME}.xu";
135  else if (bfd_link_relocatable (&link_info))
136    return "ldscripts/${EMULATION_NAME}.xr";
137  else if (!config.text_read_only)
138    return "ldscripts/${EMULATION_NAME}.xbn";
139  else if (!config.magic_demand_paged)
140    return "ldscripts/${EMULATION_NAME}.xn";
141  else
142    return "ldscripts/${EMULATION_NAME}.x";
143}
144EOF
145fi
146fi
147
148if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
149fragment <<EOF
150
151static unsigned int
152data_statement_size (lang_data_statement_type *d)
153{
154  unsigned int size = 0;
155  switch (d->type)
156    {
157    case QUAD:
158    case SQUAD:
159      size = QUAD_SIZE;
160      break;
161    case LONG:
162      size = LONG_SIZE;
163      break;
164    case SHORT:
165      size = SHORT_SIZE;
166      break;
167    case BYTE:
168      size = BYTE_SIZE;
169      break;
170    default:
171      einfo (_("%P: error: unhandled data_statement size\n"));
172      FAIL ();
173    }
174  return size;
175}
176
177/* Helper function for place_orphan that computes the size
178   of sections already mapped to the given statement.  */
179
180static bfd_size_type
181scan_children (lang_statement_union_type * l)
182{
183  bfd_size_type amount = 0;
184
185  while (l != NULL)
186    {
187      switch (l->header.type)
188	{
189	case lang_input_section_enum:
190	  if (l->input_section.section->flags & SEC_ALLOC)
191	    amount += l->input_section.section->size;
192	  break;
193
194	case lang_constructors_statement_enum:
195	case lang_assignment_statement_enum:
196	case lang_padding_statement_enum:
197	  break;
198
199	case lang_wild_statement_enum:
200	  amount += scan_children (l->wild_statement.children.head);
201	  break;
202
203	case lang_data_statement_enum:
204	  amount += data_statement_size (&l->data_statement);
205	  break;
206
207	default:
208	  fprintf (stderr, "msp430 orphan placer: unhandled lang type %d\n", l->header.type);
209	  break;
210	}
211
212      l = l->header.next;
213    }
214
215  return amount;
216}
217
218/* Place an orphan section.  We use this to put .either sections
219   into either their lower or their upper equivalents.  */
220
221static lang_output_section_statement_type *
222gld${EMULATION_NAME}_place_orphan (asection * s,
223				   const char * secname,
224				   int constraint)
225{
226  char * lower_name;
227  char * upper_name;
228  char * name;
229  char * buf = NULL;
230  lang_output_section_statement_type * lower;
231  lang_output_section_statement_type * upper;
232
233  if ((s->flags & SEC_ALLOC) == 0)
234    return NULL;
235
236  if (bfd_link_relocatable (&link_info))
237    return NULL;
238
239  /* If constraints are involved let the linker handle the placement normally.  */
240  if (constraint != 0)
241    return NULL;
242
243  /* We only need special handling for .either sections.  */
244  if (strncmp (secname, ".either.", 8) != 0)
245    return NULL;
246
247  /* Skip the .either prefix.  */
248  secname += 7;
249
250  /* Compute the names of the corresponding upper and lower
251     sections.  If the input section name contains another period,
252     only use the part of the name before the second dot.  */
253  if (strchr (secname + 1, '.') != NULL)
254    {
255      buf = name = xstrdup (secname);
256
257      * strchr (name + 1, '.') = 0;
258    }
259  else
260    name = (char *) secname;
261
262  lower_name = concat (".lower", name, NULL);
263  upper_name = concat (".upper", name, NULL);
264
265  /* Find the corresponding lower and upper sections.  */
266  lower = lang_output_section_find (lower_name);
267  upper = lang_output_section_find (upper_name);
268
269  if (lower == NULL && upper == NULL)
270    {
271      einfo (_("%P: error: no section named %s or %s in linker script\n"),
272	     lower_name, upper_name);
273      goto end;
274    }
275  else if (lower == NULL)
276    {
277      lower = lang_output_section_find (name);
278      if (lower == NULL)
279	{
280	  einfo (_("%P: error: no section named %s in linker script\n"), name);
281	  goto end;
282	}
283    }
284
285  /* Always place orphaned sections in lower.  Optimal placement of either
286     sections is performed later, once section sizes have been finalized.  */
287  lang_add_section (& lower->children, s, NULL, lower);
288 end:
289  free (upper_name);
290  free (lower_name);
291  if (buf)
292    free (buf);
293  return lower;
294}
295EOF
296fi
297
298fragment <<EOF
299
300static bfd_boolean
301change_output_section (lang_statement_union_type ** head,
302		       asection *s,
303		       lang_output_section_statement_type * new_output_section)
304{
305  asection *is;
306  lang_statement_union_type * prev = NULL;
307  lang_statement_union_type * curr;
308
309  curr = *head;
310  while (curr != NULL)
311    {
312      switch (curr->header.type)
313	{
314	case lang_input_section_enum:
315	  is = curr->input_section.section;
316	  if (is == s)
317	    {
318	      s->output_section = NULL;
319	      lang_add_section (& (new_output_section->children), s, NULL,
320				new_output_section);
321	      /* Remove the section from the old output section.  */
322	      if (prev == NULL)
323		*head = curr->header.next;
324	      else
325		prev->header.next = curr->header.next;
326	      return TRUE;
327	    }
328	  break;
329	case lang_wild_statement_enum:
330	  if (change_output_section (&(curr->wild_statement.children.head),
331				     s, new_output_section))
332	    return TRUE;
333	  break;
334	default:
335	  break;
336	}
337      prev = curr;
338      curr = curr->header.next;
339    }
340  return FALSE;
341}
342
343static void
344move_prefixed_section (asection *s, char *new_name,
345		       lang_output_section_statement_type * new_output_sec)
346{
347  s->name = new_name;
348  if (s->output_section == NULL)
349    lang_add_section (& (new_output_sec->children), s, NULL, new_output_sec);
350  else
351    {
352      lang_output_section_statement_type * curr_output_sec
353	= lang_output_section_find (s->output_section->name);
354      change_output_section (&(curr_output_sec->children.head), s,
355			     new_output_sec);
356    }
357}
358
359static void
360add_region_prefix (bfd *abfd, asection *s,
361		   ATTRIBUTE_UNUSED void *unused)
362{
363  const char *curr_name = bfd_get_section_name (abfd, s);
364  char * base_name;
365  char * new_input_sec_name = NULL;
366  char * new_output_sec_name = NULL;
367  int region = REGION_NONE;
368
369  if (strncmp (curr_name, ".text", 5) == 0)
370    {
371      region = code_region;
372      base_name = concat (".text", NULL);
373    }
374  else if (strncmp (curr_name, ".data", 5) == 0)
375    {
376      region = data_region;
377      base_name = concat (".data", NULL);
378    }
379  else if (strncmp (curr_name, ".bss", 4) == 0)
380    {
381      region = data_region;
382      base_name = concat (".bss", NULL);
383    }
384  else if (strncmp (curr_name, ".rodata", 7) == 0)
385    {
386      region = data_region;
387      base_name = concat (".rodata", NULL);
388    }
389  else
390    return;
391
392  switch (region)
393    {
394    case REGION_NONE:
395      break;
396    case REGION_UPPER:
397      new_input_sec_name = concat (".upper", curr_name, NULL);
398      new_output_sec_name = concat (".upper", base_name, NULL);
399      lang_output_section_statement_type * upper
400	= lang_output_section_find (new_output_sec_name);
401      if (upper != NULL)
402	{
403	  move_prefixed_section (s, new_input_sec_name, upper);
404	}
405      else
406	einfo (_("%P: error: no section named %s in linker script\n"),
407	       new_output_sec_name);
408      break;
409    case REGION_LOWER:
410      new_input_sec_name = concat (".lower", curr_name, NULL);
411      new_output_sec_name = concat (".lower", base_name, NULL);
412      lang_output_section_statement_type * lower
413	= lang_output_section_find (new_output_sec_name);
414      if (lower != NULL)
415	{
416	  move_prefixed_section (s, new_input_sec_name, lower);
417	}
418      else
419	einfo (_("%P: error: no section named %s in linker script\n"),
420	       new_output_sec_name);
421      break;
422    case REGION_EITHER:
423      s->name = concat (".either", curr_name, NULL);
424      break;
425    default:
426      /* Unreachable.  */
427      FAIL ();
428      break;
429    }
430  free (base_name);
431  if (new_input_sec_name)
432    {
433      free (new_input_sec_name);
434      free (new_output_sec_name);
435    }
436}
437
438static void
439msp430_elf_after_open (void)
440{
441  bfd *abfd;
442
443  gld${EMULATION_NAME}_after_open ();
444
445  /* If neither --code-region or --data-region have been passed, do not
446     transform sections names.  */
447  if ((code_region == REGION_NONE && data_region == REGION_NONE)
448      || disable_sec_transformation)
449    return;
450
451  for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next)
452    bfd_map_over_sections (abfd, add_region_prefix, NULL);
453}
454
455#define OPTION_CODE_REGION		321
456#define OPTION_DATA_REGION		(OPTION_CODE_REGION + 1)
457#define OPTION_DISABLE_TRANS		(OPTION_CODE_REGION + 2)
458
459static void
460gld${EMULATION_NAME}_add_options
461  (int ns, char **shortopts, int nl, struct option **longopts,
462   int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED)
463{
464  static const char xtra_short[] = { };
465
466  static const struct option xtra_long[] =
467    {
468      { "code-region", required_argument, NULL, OPTION_CODE_REGION },
469      { "data-region", required_argument, NULL, OPTION_DATA_REGION },
470      { "disable-sec-transformation", no_argument, NULL,
471	OPTION_DISABLE_TRANS },
472      { NULL, no_argument, NULL, 0 }
473    };
474
475  *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
476  memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
477  *longopts = (struct option *)
478    xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
479  memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
480}
481
482static void
483gld${EMULATION_NAME}_list_options (FILE * file)
484{
485  fprintf (file, _("  --code-region={either,lower,upper,none}\n\
486        Transform .text* sections to {either,lower,upper,none}.text* sections\n"));
487  fprintf (file, _("  --data-region={either,lower,upper,none}\n\
488        Transform .data*, .rodata* and .bss* sections to\n\
489        {either,lower,upper,none}.{bss,data,rodata}* sections\n"));
490  fprintf (file, _("  --disable-sec-transformation\n\
491        Disable transformation of .{text,data,bss,rodata}* sections to\n\
492        add the {either,lower,upper,none} prefixes\n"));
493}
494
495static bfd_boolean
496gld${EMULATION_NAME}_handle_option (int optc)
497{
498  switch (optc)
499    {
500    case OPTION_CODE_REGION:
501      if (strcmp (optarg, "upper") == 0)
502	code_region = REGION_UPPER;
503      else if (strcmp (optarg, "lower") == 0)
504	code_region = REGION_LOWER;
505      else if (strcmp (optarg, "either") == 0)
506	code_region = REGION_EITHER;
507      else if (strcmp (optarg, "none") == 0)
508	code_region = REGION_NONE;
509      else if (strlen (optarg) == 0)
510	{
511	  einfo (_("%P: --code-region requires an argument: "
512		   "{upper,lower,either,none}\n"));
513	  return FALSE;
514	}
515      else
516	{
517	  einfo (_("%P: error: unrecognized argument to --code-region= option: "
518		   "\"%s\"\n"), optarg);
519	  return FALSE;
520	}
521      break;
522
523    case OPTION_DATA_REGION:
524      if (strcmp (optarg, "upper") == 0)
525	data_region = REGION_UPPER;
526      else if (strcmp (optarg, "lower") == 0)
527	data_region = REGION_LOWER;
528      else if (strcmp (optarg, "either") == 0)
529	data_region = REGION_EITHER;
530      else if (strcmp (optarg, "none") == 0)
531	data_region = REGION_NONE;
532      else if (strlen (optarg) == 0)
533	{
534	  einfo (_("%P: --data-region requires an argument: "
535		   "{upper,lower,either,none}\n"));
536	  return FALSE;
537	}
538      else
539	{
540	  einfo (_("%P: error: unrecognized argument to --data-region= option: "
541		   "\"%s\"\n"), optarg);
542	  return FALSE;
543	}
544      break;
545
546    case OPTION_DISABLE_TRANS:
547      disable_sec_transformation = TRUE;
548      break;
549
550    default:
551      return FALSE;
552    }
553  return TRUE;
554}
555
556static void
557eval_upper_either_sections (bfd *abfd, asection *s, void *data)
558{
559  const char * base_sec_name;
560  const char * curr_name;
561  char * either_name;
562  int curr_region;
563
564  lang_output_section_statement_type * lower;
565  lang_output_section_statement_type * upper;
566  static bfd_size_type *lower_size = 0;
567  static bfd_size_type *upper_size = 0;
568  static bfd_size_type lower_size_rom = 0;
569  static bfd_size_type lower_size_ram = 0;
570  static bfd_size_type upper_size_rom = 0;
571  static bfd_size_type upper_size_ram = 0;
572
573  if ((s->flags & SEC_ALLOC) == 0)
574    return;
575  if (bfd_link_relocatable (&link_info))
576    return;
577
578  base_sec_name = (const char *) data;
579  curr_name = bfd_get_section_name (abfd, s);
580
581  /* Only concerned with .either input sections in the upper output section.  */
582  either_name = concat (".either", base_sec_name, NULL);
583  if (strncmp (curr_name, either_name, strlen (either_name)) != 0
584      || strncmp (s->output_section->name, ".upper", 6) != 0)
585    goto end;
586
587  lower = lang_output_section_find (concat (".lower", base_sec_name, NULL));
588  upper = lang_output_section_find (concat (".upper", base_sec_name, NULL));
589
590  if (upper == NULL || upper->region == NULL)
591    goto end;
592  else if (lower == NULL)
593    lower = lang_output_section_find (base_sec_name);
594  if (lower == NULL || lower->region == NULL)
595    goto end;
596
597  if (strcmp (base_sec_name, ".text") == 0
598      || strcmp (base_sec_name, ".rodata") == 0)
599    curr_region = ROM;
600  else
601    curr_region = RAM;
602
603  if (curr_region == ROM)
604    {
605      if (lower_size_rom == 0)
606	{
607	  lower_size_rom = lower->region->current - lower->region->origin;
608	  upper_size_rom = upper->region->current - upper->region->origin;
609	}
610      lower_size = &lower_size_rom;
611      upper_size = &upper_size_rom;
612    }
613  else if (curr_region == RAM)
614    {
615      if (lower_size_ram == 0)
616	{
617	  lower_size_ram = lower->region->current - lower->region->origin;
618	  upper_size_ram = upper->region->current - upper->region->origin;
619	}
620      lower_size = &lower_size_ram;
621      upper_size = &upper_size_ram;
622    }
623
624  /* Move sections in the upper region that would fit in the lower
625     region to the lower region.  */
626  if (*lower_size + s->size < lower->region->length)
627    {
628      if (change_output_section (&(upper->children.head), s, lower))
629	{
630	  *upper_size -= s->size;
631	  *lower_size += s->size;
632	}
633    }
634 end:
635  free (either_name);
636}
637
638static void
639eval_lower_either_sections (bfd *abfd, asection *s, void *data)
640{
641  const char * base_sec_name;
642  const char * curr_name;
643  char * either_name;
644  int curr_region;
645  lang_output_section_statement_type * output_sec;
646  lang_output_section_statement_type * lower;
647  lang_output_section_statement_type * upper;
648
649  static bfd_size_type *lower_size = 0;
650  static bfd_size_type lower_size_rom = 0;
651  static bfd_size_type lower_size_ram = 0;
652
653  if ((s->flags & SEC_ALLOC) == 0)
654    return;
655  if (bfd_link_relocatable (&link_info))
656    return;
657
658  base_sec_name = (const char *) data;
659  curr_name = bfd_get_section_name (abfd, s);
660
661  /* Only concerned with .either input sections in the lower or "default"
662     output section i.e. not in the upper output section.  */
663  either_name = concat (".either", base_sec_name, NULL);
664  if (strncmp (curr_name, either_name, strlen (either_name)) != 0
665      || strncmp (s->output_section->name, ".upper", 6) == 0)
666    return;
667
668  if (strcmp (base_sec_name, ".text") == 0
669      || strcmp (base_sec_name, ".rodata") == 0)
670    curr_region = ROM;
671  else
672    curr_region = RAM;
673
674  output_sec = lang_output_section_find (s->output_section->name);
675
676  /* If the output_section doesn't exist, this has already been reported in
677     place_orphan, so don't need to warn again.  */
678  if (output_sec == NULL || output_sec->region == NULL)
679    goto end;
680
681  /* lower and output_sec might be the same, but in some cases an .either
682     section can end up in base_sec_name if it hasn't been placed by
683     place_orphan.  */
684  lower = lang_output_section_find (concat (".lower", base_sec_name, NULL));
685  upper = lang_output_section_find (concat (".upper", base_sec_name, NULL));
686  if (upper == NULL)
687    goto end;
688
689  if (curr_region == ROM)
690    {
691      if (lower_size_rom == 0)
692	{
693	  /* Get the size of other items in the lower region that aren't the
694	     sections to be moved around.  */
695	  lower_size_rom
696	    = (output_sec->region->current - output_sec->region->origin)
697	    - scan_children (output_sec->children.head);
698	  if (output_sec != lower && lower != NULL)
699	    lower_size_rom -= scan_children (lower->children.head);
700	}
701      lower_size = &lower_size_rom;
702    }
703  else if (curr_region == RAM)
704    {
705      if (lower_size_ram == 0)
706	{
707	  lower_size_ram
708	    = (output_sec->region->current - output_sec->region->origin)
709	    - scan_children (output_sec->children.head);
710	  if (output_sec != lower && lower != NULL)
711	    lower_size_ram -= scan_children (lower->children.head);
712	}
713      lower_size = &lower_size_ram;
714    }
715  /* Move sections that cause the lower region to overflow to the upper region.  */
716  if (*lower_size + s->size > output_sec->region->length)
717    change_output_section (&(output_sec->children.head), s, upper);
718  else
719    *lower_size += s->size;
720 end:
721  free (either_name);
722}
723
724/* This function is similar to lang_relax_sections, but without the size
725   evaluation code that is always executed after relaxation.  */
726static void
727intermediate_relax_sections (void)
728{
729  int i = link_info.relax_pass;
730
731  /* The backend can use it to determine the current pass.  */
732  link_info.relax_pass = 0;
733
734  while (i--)
735    {
736      bfd_boolean relax_again;
737
738      link_info.relax_trip = -1;
739      do
740	{
741	  link_info.relax_trip++;
742
743	  lang_do_assignments (lang_assigning_phase_enum);
744
745	  lang_reset_memory_regions ();
746
747	  relax_again = FALSE;
748	  lang_size_sections (&relax_again, FALSE);
749	}
750      while (relax_again);
751
752      link_info.relax_pass++;
753    }
754}
755
756static void
757msp430_elf_after_allocation (void)
758{
759  int relax_count = 0;
760  unsigned int i;
761  /* Go over each section twice, once to place either sections that don't fit
762     in lower into upper, and then again to move any sections in upper that
763     fit in lower into lower.  */
764  for (i = 0; i < 8; i++)
765    {
766      int placement_stage = (i < 4) ? LOWER_TO_UPPER : UPPER_TO_LOWER;
767      const char * base_sec_name;
768      lang_output_section_statement_type * upper;
769
770      switch (i % 4)
771	{
772	default:
773	case 0:
774	  base_sec_name = ".text";
775	  break;
776	case 1:
777	  base_sec_name = ".data";
778	  break;
779	case 2:
780	  base_sec_name = ".bss";
781	  break;
782	case 3:
783	  base_sec_name = ".rodata";
784	  break;
785	}
786      upper = lang_output_section_find (concat (".upper", base_sec_name, NULL));
787      if (upper != NULL)
788	{
789	  /* Can't just use one iteration over the all the sections to make
790	     both lower->upper and upper->lower transformations because the
791	     iterator encounters upper sections before all lower sections have
792	     been examined.  */
793	  bfd *abfd;
794
795	  if (placement_stage == LOWER_TO_UPPER)
796	    {
797	      /* Perform relaxation and get the final size of sections
798		 before trying to fit .either sections in the correct
799		 ouput sections.  */
800	      if (relax_count == 0)
801		{
802		  intermediate_relax_sections ();
803		  relax_count++;
804		}
805	      for (abfd = link_info.input_bfds; abfd != NULL;
806		   abfd = abfd->link.next)
807		{
808		  bfd_map_over_sections (abfd, eval_lower_either_sections,
809					 (void *) base_sec_name);
810		}
811	    }
812	  else if (placement_stage == UPPER_TO_LOWER)
813	    {
814	      /* Relax again before moving upper->lower.  */
815	      if (relax_count == 1)
816		{
817		  intermediate_relax_sections ();
818		  relax_count++;
819		}
820	      for (abfd = link_info.input_bfds; abfd != NULL;
821		   abfd = abfd->link.next)
822		{
823		  bfd_map_over_sections (abfd, eval_upper_either_sections,
824					 (void *) base_sec_name);
825		}
826	    }
827
828	}
829    }
830  gld${EMULATION_NAME}_after_allocation ();
831}
832
833struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
834{
835  ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
836  ${LDEMUL_SYSLIB-syslib_default},
837  ${LDEMUL_HLL-hll_default},
838  ${LDEMUL_AFTER_PARSE-after_parse_default},
839  msp430_elf_after_open,
840  after_check_relocs_default,
841  msp430_elf_after_allocation,
842  ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
843  ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
844  ${LDEMUL_BEFORE_ALLOCATION-before_allocation_default},
845  ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
846  "${EMULATION_NAME}",
847  "${OUTPUT_FORMAT}",
848  ${LDEMUL_FINISH-finish_default},
849  ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL},
850  ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-NULL},
851  ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
852  ${LDEMUL_SET_SYMBOLS-NULL},
853  ${LDEMUL_PARSE_ARGS-NULL},
854  gld${EMULATION_NAME}_add_options,
855  gld${EMULATION_NAME}_handle_option,
856  ${LDEMUL_UNRECOGNIZED_FILE-NULL},
857  gld${EMULATION_NAME}_list_options,
858  ${LDEMUL_RECOGNIZED_FILE-NULL},
859  ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
860  ${LDEMUL_NEW_VERS_PATTERN-NULL},
861  ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL}
862};
863EOF
864#
865# Local Variables:
866# mode: c
867# End:
868