Home | History | Annotate | Download | only in emultempl
      1 # This shell script emits a C file. -*- C -*-
      2 #   Copyright (C) 2006-2014 Free Software Foundation, Inc.
      3 #
      4 # This file is part of the GNU Binutils.
      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
      8 # the Free Software Foundation; either version 3 of the License, or
      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
     18 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19 # MA 02110-1301, USA.
     20 #
     21 
     22 # This file is sourced from elf32.em, and defines extra spu specific
     23 # features.
     24 #
     25 fragment <<EOF
     26 #include "ldctor.h"
     27 #include "elf32-spu.h"
     28 
     29 static void spu_place_special_section (asection *, asection *, const char *);
     30 static bfd_size_type spu_elf_load_ovl_mgr (void);
     31 static FILE *spu_elf_open_overlay_script (void);
     32 static void spu_elf_relink (void);
     33 
     34 static struct spu_elf_params params =
     35 {
     36   &spu_place_special_section,
     37   &spu_elf_load_ovl_mgr,
     38   &spu_elf_open_overlay_script,
     39   &spu_elf_relink,
     40   0, ovly_normal, 0, 0, 0, 0, 0, 0, 0, 0,
     41   0, 0x3ffff,
     42   1, 0, 16, 0, 0, 2000
     43 };
     44 
     45 static unsigned int no_overlays = 0;
     46 static unsigned int num_lines_set = 0;
     47 static unsigned int line_size_set = 0;
     48 static char *auto_overlay_file = 0;
     49 int my_argc;
     50 char **my_argv;
     51 
     52 static const char ovl_mgr[] = {
     53 EOF
     54 
     55 if ! cat ${srcdir}/emultempl/spu_ovl.o_c >> e${EMULATION_NAME}.c
     56 then
     57   echo >&2 "Missing ${srcdir}/emultempl/spu_ovl.o_c"
     58   echo >&2 "You must build gas/as-new with --target=spu"
     59   exit 1
     60 fi
     61 
     62 fragment <<EOF
     63 };
     64 
     65 static const char icache_mgr[] = {
     66 EOF
     67 
     68 if ! cat ${srcdir}/emultempl/spu_icache.o_c >> e${EMULATION_NAME}.c
     69 then
     70   echo >&2 "Missing ${srcdir}/emultempl/spu_icache.o_c"
     71   echo >&2 "You must build gas/as-new with --target=spu"
     72   exit 1
     73 fi
     74 
     75 fragment <<EOF
     76 };
     77 
     78 static const struct _ovl_stream ovl_mgr_stream = {
     79   ovl_mgr,
     80   ovl_mgr + sizeof (ovl_mgr)
     81 };
     82 
     83 static const struct _ovl_stream icache_mgr_stream = {
     84   icache_mgr,
     85   icache_mgr + sizeof (icache_mgr)
     86 };
     87 
     88 
     89 static int
     90 is_spu_target (void)
     91 {
     92   extern const bfd_target spu_elf32_vec;
     93 
     94   return link_info.output_bfd->xvec == &spu_elf32_vec;
     95 }
     96 
     97 /* Create our note section.  */
     98 
     99 static void
    100 spu_after_open (void)
    101 {
    102   if (is_spu_target ())
    103     {
    104       /* Pass params to backend.  */
    105       if ((params.auto_overlay & AUTO_OVERLAY) == 0)
    106 	params.auto_overlay = 0;
    107       params.emit_stub_syms |= link_info.emitrelocations;
    108       spu_elf_setup (&link_info, &params);
    109 
    110       if (link_info.relocatable)
    111 	lang_add_unique (".text.ia.*");
    112 
    113       if (!link_info.relocatable
    114 	  && link_info.input_bfds != NULL
    115 	  && !spu_elf_create_sections (&link_info))
    116 	einfo ("%X%P: can not create note section: %E\n");
    117     }
    118 
    119   gld${EMULATION_NAME}_after_open ();
    120 }
    121 
    122 /* If O is NULL, add section S at the end of output section OUTPUT_NAME.
    123    If O is not NULL, add section S at the beginning of output section O,
    124    except for soft-icache which adds to the end.
    125 
    126    Really, we should be duplicating ldlang.c map_input_to_output_sections
    127    logic here, ie. using the linker script to find where the section
    128    goes.  That's rather a lot of code, and we don't want to run
    129    map_input_to_output_sections again because most sections are already
    130    mapped.  So cheat, and put the section in a fixed place, ignoring any
    131    attempt via a linker script to put .stub, .ovtab, and built-in
    132    overlay manager code somewhere else.  */
    133 
    134 static void
    135 spu_place_special_section (asection *s, asection *o, const char *output_name)
    136 {
    137   lang_output_section_statement_type *os;
    138 
    139   if (o != NULL)
    140     os = lang_output_section_get (o);
    141   else
    142     os = lang_output_section_find (output_name);
    143   if (os == NULL)
    144     {
    145       os = gld${EMULATION_NAME}_place_orphan (s, output_name, 0);
    146       os->addr_tree = NULL;
    147     }
    148   else if (params.ovly_flavour != ovly_soft_icache
    149 	   && o != NULL && os->children.head != NULL)
    150     {
    151       lang_statement_list_type add;
    152 
    153       lang_list_init (&add);
    154       lang_add_section (&add, s, NULL, os);
    155       *add.tail = os->children.head;
    156       os->children.head = add.head;
    157     }
    158   else
    159     {
    160       if (params.ovly_flavour == ovly_soft_icache && o != NULL)
    161 	{
    162 	  /* Pad this stub section so that it finishes at the
    163 	     end of the icache line.  */
    164 	  etree_type *e_size;
    165 
    166 	  push_stat_ptr (&os->children);
    167 	  e_size = exp_intop (params.line_size - s->size);
    168 	  lang_add_assignment (exp_assign (".", e_size, FALSE));
    169 	  pop_stat_ptr ();
    170 	}
    171       lang_add_section (&os->children, s, NULL, os);
    172     }
    173 
    174   s->output_section->size += s->size;
    175 }
    176 
    177 /* Load built-in overlay manager.  */
    178 
    179 static bfd_size_type
    180 spu_elf_load_ovl_mgr (void)
    181 {
    182   struct elf_link_hash_entry *h;
    183   const char *ovly_mgr_entry;
    184   const struct _ovl_stream *mgr_stream;
    185   bfd_size_type total = 0;
    186 
    187   ovly_mgr_entry = "__ovly_load";
    188   mgr_stream = &ovl_mgr_stream;
    189   if (params.ovly_flavour == ovly_soft_icache)
    190     {
    191       ovly_mgr_entry = "__icache_br_handler";
    192       mgr_stream = &icache_mgr_stream;
    193     }
    194   h = elf_link_hash_lookup (elf_hash_table (&link_info),
    195 			    ovly_mgr_entry, FALSE, FALSE, FALSE);
    196 
    197   if (h != NULL
    198       && (h->root.type == bfd_link_hash_defined
    199 	  || h->root.type == bfd_link_hash_defweak)
    200       && h->def_regular)
    201     {
    202       /* User supplied __ovly_load.  */
    203     }
    204   else if (mgr_stream->start == mgr_stream->end)
    205     einfo ("%F%P: no built-in overlay manager\n");
    206   else
    207     {
    208       lang_input_statement_type *ovl_is;
    209 
    210       ovl_is = lang_add_input_file ("builtin ovl_mgr",
    211 				    lang_input_file_is_file_enum,
    212 				    NULL);
    213 
    214       if (!spu_elf_open_builtin_lib (&ovl_is->the_bfd, mgr_stream))
    215 	einfo ("%X%P: can not open built-in overlay manager: %E\n");
    216       else
    217 	{
    218 	  asection *in;
    219 
    220 	  if (!load_symbols (ovl_is, NULL))
    221 	    einfo ("%X%P: can not load built-in overlay manager: %E\n");
    222 
    223 	  /* Map overlay manager sections to output sections.
    224 	     First try for a matching output section name, if that
    225 	     fails then try mapping .abc.xyz to .abc, otherwise map
    226 	     to .text.  */
    227 	  for (in = ovl_is->the_bfd->sections; in != NULL; in = in->next)
    228 	    if ((in->flags & (SEC_ALLOC | SEC_LOAD))
    229 		== (SEC_ALLOC | SEC_LOAD))
    230 	      {
    231 		const char *oname = in->name;
    232 		if (strncmp (in->name, ".ovl.init", 9) != 0)
    233 		  {
    234 		    total += in->size;
    235 		    if (!lang_output_section_find (oname))
    236 		      {
    237 			lang_output_section_statement_type *os = NULL;
    238 			char *p = strchr (oname + 1, '.');
    239 			if (p != NULL)
    240 			  {
    241 			    size_t len = p - oname;
    242 			    p = memcpy (xmalloc (len + 1), oname, len);
    243 			    p[len] = '\0';
    244 			    os = lang_output_section_find (p);
    245 			    free (p);
    246 			  }
    247 			if (os != NULL)
    248 			  oname = os->name;
    249 			else
    250 			  oname = ".text";
    251 		      }
    252 		  }
    253 
    254 		spu_place_special_section (in, NULL, oname);
    255 	      }
    256 	}
    257     }
    258   return total;
    259 }
    260 
    261 /* Go find if we need to do anything special for overlays.  */
    262 
    263 static void
    264 spu_before_allocation (void)
    265 {
    266   if (is_spu_target ()
    267       && !link_info.relocatable
    268       && !no_overlays)
    269     {
    270       int ret;
    271 
    272       /* Size the sections.  This is premature, but we need to know the
    273 	 rough layout so that overlays can be found.  */
    274       expld.phase = lang_mark_phase_enum;
    275       expld.dataseg.phase = exp_dataseg_none;
    276       one_lang_size_sections_pass (NULL, TRUE);
    277 
    278       /* Find overlays by inspecting section vmas.  */
    279       ret = spu_elf_find_overlays (&link_info);
    280       if (ret == 0)
    281 	einfo ("%X%P: can not find overlays: %E\n");
    282       else if (ret == 2)
    283 	{
    284 	  lang_output_section_statement_type *os;
    285 
    286 	  if (params.auto_overlay != 0)
    287 	    {
    288 	      einfo ("%P: --auto-overlay ignored with user overlay script\n");
    289 	      params.auto_overlay = 0;
    290 	    }
    291 
    292 	  /* Ensure alignment of overlay sections is sufficient.  */
    293 	  for (os = &lang_output_section_statement.head->output_section_statement;
    294 	       os != NULL;
    295 	       os = os->next)
    296 	    if (os->bfd_section != NULL
    297 		&& spu_elf_section_data (os->bfd_section) != NULL
    298 		&& spu_elf_section_data (os->bfd_section)->u.o.ovl_index != 0)
    299 	      {
    300 		if (os->bfd_section->alignment_power < 4)
    301 		  os->bfd_section->alignment_power = 4;
    302 
    303 		/* Also ensure size rounds up.  */
    304 		os->block_value = 16;
    305 	      }
    306 
    307 	  ret = spu_elf_size_stubs (&link_info);
    308 	  if (ret == 0)
    309 	    einfo ("%X%P: can not size overlay stubs: %E\n");
    310 	  else if (ret == 2)
    311 	    spu_elf_load_ovl_mgr ();
    312 
    313 	  spu_elf_place_overlay_data (&link_info);
    314 	}
    315 
    316       /* We must not cache anything from the preliminary sizing.  */
    317       lang_reset_memory_regions ();
    318     }
    319 
    320   if (is_spu_target ()
    321       && !link_info.relocatable)
    322     spu_elf_size_sections (link_info.output_bfd, &link_info);
    323 
    324   gld${EMULATION_NAME}_before_allocation ();
    325 }
    326 
    327 struct tflist {
    328   struct tflist *next;
    329   char name[9];
    330 };
    331 
    332 static struct tflist *tmp_file_list;
    333 
    334 static void clean_tmp (void)
    335 {
    336   for (; tmp_file_list != NULL; tmp_file_list = tmp_file_list->next)
    337     unlink (tmp_file_list->name);
    338 }
    339 
    340 static int
    341 new_tmp_file (char **fname)
    342 {
    343   struct tflist *tf;
    344   int fd;
    345 
    346   if (tmp_file_list == NULL)
    347     atexit (clean_tmp);
    348   tf = xmalloc (sizeof (*tf));
    349   tf->next = tmp_file_list;
    350   tmp_file_list = tf;
    351   memcpy (tf->name, "ldXXXXXX", sizeof (tf->name));
    352   *fname = tf->name;
    353 #ifdef HAVE_MKSTEMP
    354   fd = mkstemp (*fname);
    355 #else
    356   *fname = mktemp (*fname);
    357   if (*fname == NULL)
    358     return -1;
    359   fd = open (*fname, O_RDWR | O_CREAT | O_EXCL, 0600);
    360 #endif
    361   return fd;
    362 }
    363 
    364 static FILE *
    365 spu_elf_open_overlay_script (void)
    366 {
    367   FILE *script = NULL;
    368 
    369   if (auto_overlay_file == NULL)
    370     {
    371       int fd = new_tmp_file (&auto_overlay_file);
    372       if (fd == -1)
    373 	goto file_err;
    374       script = fdopen (fd, "w");
    375     }
    376   else
    377     script = fopen (auto_overlay_file, "w");
    378 
    379   if (script == NULL)
    380     {
    381     file_err:
    382       einfo ("%F%P: can not open script: %E\n");
    383     }
    384   return script;
    385 }
    386 
    387 #include <errno.h>
    388 
    389 static void
    390 spu_elf_relink (void)
    391 {
    392   const char *pex_return;
    393   int status;
    394   char **argv = xmalloc ((my_argc + 4) * sizeof (*argv));
    395 
    396   memcpy (argv, my_argv, my_argc * sizeof (*argv));
    397   argv[my_argc++] = "--no-auto-overlay";
    398   if (tmp_file_list->name == auto_overlay_file)
    399     argv[my_argc - 1] = concat (argv[my_argc - 1], "=",
    400 				auto_overlay_file, (const char *) NULL);
    401   argv[my_argc++] = "-T";
    402   argv[my_argc++] = auto_overlay_file;
    403   argv[my_argc] = 0;
    404 
    405   pex_return = pex_one (PEX_SEARCH | PEX_LAST, (const char *) argv[0],
    406 			(char * const *) argv, (const char *) argv[0],
    407 			NULL, NULL, & status, & errno);
    408   if (pex_return != NULL)
    409     {
    410       perror (pex_return);
    411       _exit (127);
    412     }
    413   exit (status);
    414 }
    415 
    416 /* Final emulation specific call.  */
    417 
    418 static void
    419 gld${EMULATION_NAME}_finish (void)
    420 {
    421   if (is_spu_target ())
    422     {
    423       if (params.local_store_lo < params.local_store_hi)
    424         {
    425 	  asection *s;
    426 
    427 	  s = spu_elf_check_vma (&link_info);
    428 	  if (s != NULL && !params.auto_overlay)
    429 	    einfo ("%X%P: %A exceeds local store range\n", s);
    430 	}
    431       else if (params.auto_overlay)
    432 	einfo ("%P: --auto-overlay ignored with zero local store range\n");
    433     }
    434 
    435   finish_default ();
    436 }
    437 
    438 static char *
    439 gld${EMULATION_NAME}_choose_target (int argc, char *argv[])
    440 {
    441   my_argc = argc;
    442   my_argv = argv;
    443   return ldemul_default_target (argc, argv);
    444 }
    445 
    446 EOF
    447 
    448 if grep -q 'ld_elf.*ppc.*_emulation' ldemul-list.h; then
    449   fragment <<EOF
    450 #include "safe-ctype.h"
    451 #include "filenames.h"
    452 #include "libiberty.h"
    453 
    454 static const char *
    455 base_name (const char *path)
    456 {
    457   const char *file = strrchr (path, '/');
    458 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
    459   {
    460     char *bslash = strrchr (path, '\\\\');
    461 
    462     if (file == NULL || (bslash != NULL && bslash > file))
    463       file = bslash;
    464     if (file == NULL
    465 	&& path[0] != '\0'
    466 	&& path[1] == ':')
    467       file = path + 1;
    468   }
    469 #endif
    470   if (file == NULL)
    471     file = path;
    472   else
    473     ++file;
    474   return file;
    475 }
    476 
    477 /* This function is called when building a ppc32 or ppc64 executable
    478    to handle embedded spu images.  */
    479 extern bfd_boolean embedded_spu_file (lang_input_statement_type *, const char *);
    480 
    481 bfd_boolean
    482 embedded_spu_file (lang_input_statement_type *entry, const char *flags)
    483 {
    484   const char *cmd[6];
    485   const char *pex_return;
    486   const char *sym;
    487   char *handle, *p;
    488   char *oname;
    489   int fd;
    490   int status;
    491   union lang_statement_union **old_stat_tail;
    492   union lang_statement_union **old_file_tail;
    493   union lang_statement_union *new_ent;
    494   lang_input_statement_type *search;
    495 
    496   if (entry->the_bfd->format != bfd_object
    497       || strcmp (entry->the_bfd->xvec->name, "elf32-spu") != 0
    498       || (entry->the_bfd->tdata.elf_obj_data->elf_header->e_type != ET_EXEC
    499 	  && entry->the_bfd->tdata.elf_obj_data->elf_header->e_type != ET_DYN))
    500     return FALSE;
    501 
    502   /* Use the filename as the symbol marking the program handle struct.  */
    503   sym = base_name (entry->the_bfd->filename);
    504 
    505   handle = xstrdup (sym);
    506   for (p = handle; *p; ++p)
    507     if (!(ISALNUM (*p) || *p == '$' || *p == '.'))
    508       *p = '_';
    509 
    510   fd = new_tmp_file (&oname);
    511   if (fd == -1)
    512     return FALSE;
    513   close (fd);
    514 
    515   for (search = (lang_input_statement_type *) input_file_chain.head;
    516        search != NULL;
    517        search = (lang_input_statement_type *) search->next_real_file)
    518     if (search->filename != NULL)
    519       {
    520 	const char *infile = base_name (search->filename);
    521 
    522 	if (strncmp (infile, "crtbegin", 8) == 0)
    523 	  {
    524 	    if (infile[8] == 'S')
    525 	      flags = concat (flags, " -fPIC", (const char *) NULL);
    526 	    else if (infile[8] == 'T')
    527 	      flags = concat (flags, " -fpie", (const char *) NULL);
    528 	    break;
    529 	  }
    530       }
    531 
    532   cmd[0] = EMBEDSPU;
    533   cmd[1] = flags;
    534   cmd[2] = handle;
    535   cmd[3] = entry->the_bfd->filename;
    536   cmd[4] = oname;
    537   cmd[5] = NULL;
    538   if (verbose)
    539     {
    540       info_msg (_("running: %s \"%s\" \"%s\" \"%s\" \"%s\"\n"),
    541 		cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);
    542       fflush (stdout);
    543     }
    544 
    545   pex_return = pex_one (PEX_SEARCH | PEX_LAST, cmd[0], (char *const *) cmd,
    546 			cmd[0], NULL, NULL, &status, &errno);
    547   if (NULL != pex_return) {
    548       if (strcmp ("embedspu", EMBEDSPU) != 0)
    549 	{
    550 	  cmd[0] = "embedspu";
    551 	  pex_return = pex_one (PEX_SEARCH | PEX_LAST, cmd[0], (char *const *) cmd,
    552 				cmd[0], NULL, NULL, &status, &errno);
    553 	}
    554       if (NULL != pex_return) {
    555 	perror (pex_return);
    556 	_exit (127);
    557       }
    558   }
    559   if (status)
    560     return FALSE;
    561 
    562 
    563   old_stat_tail = stat_ptr->tail;
    564   old_file_tail = input_file_chain.tail;
    565   if (lang_add_input_file (oname, lang_input_file_is_file_enum, NULL) == NULL)
    566     return FALSE;
    567 
    568   /* lang_add_input_file puts the new list entry at the end of the statement
    569      and input file lists.  Move it to just after the current entry.  */
    570   new_ent = *old_stat_tail;
    571   *old_stat_tail = NULL;
    572   stat_ptr->tail = old_stat_tail;
    573   *old_file_tail = NULL;
    574   input_file_chain.tail = old_file_tail;
    575   new_ent->header.next = entry->header.next;
    576   entry->header.next = new_ent;
    577   new_ent->input_statement.next_real_file = entry->next_real_file;
    578   entry->next_real_file = new_ent;
    579 
    580   /* Ensure bfd sections are excluded from the output.  */
    581   bfd_section_list_clear (entry->the_bfd);
    582   entry->flags.loaded = TRUE;
    583   return TRUE;
    584 }
    585 
    586 EOF
    587 fi
    588 
    589 # Define some shell vars to insert bits of code into the standard elf
    590 # parse_args and list_options functions.
    591 #
    592 PARSE_AND_LIST_PROLOGUE='
    593 #define OPTION_SPU_PLUGIN		301
    594 #define OPTION_SPU_NO_OVERLAYS		(OPTION_SPU_PLUGIN + 1)
    595 #define OPTION_SPU_COMPACT_STUBS	(OPTION_SPU_NO_OVERLAYS + 1)
    596 #define OPTION_SPU_STUB_SYMS		(OPTION_SPU_COMPACT_STUBS + 1)
    597 #define OPTION_SPU_NON_OVERLAY_STUBS	(OPTION_SPU_STUB_SYMS + 1)
    598 #define OPTION_SPU_LOCAL_STORE		(OPTION_SPU_NON_OVERLAY_STUBS + 1)
    599 #define OPTION_SPU_STACK_ANALYSIS	(OPTION_SPU_LOCAL_STORE + 1)
    600 #define OPTION_SPU_STACK_SYMS		(OPTION_SPU_STACK_ANALYSIS + 1)
    601 #define OPTION_SPU_AUTO_OVERLAY		(OPTION_SPU_STACK_SYMS + 1)
    602 #define OPTION_SPU_AUTO_RELINK		(OPTION_SPU_AUTO_OVERLAY + 1)
    603 #define OPTION_SPU_OVERLAY_RODATA	(OPTION_SPU_AUTO_RELINK + 1)
    604 #define OPTION_SPU_SOFT_ICACHE		(OPTION_SPU_OVERLAY_RODATA + 1)
    605 #define OPTION_SPU_LINE_SIZE		(OPTION_SPU_SOFT_ICACHE + 1)
    606 #define OPTION_SPU_NUM_LINES		(OPTION_SPU_LINE_SIZE + 1)
    607 #define OPTION_SPU_LRLIVE		(OPTION_SPU_NUM_LINES + 1)
    608 #define OPTION_SPU_NON_IA_TEXT		(OPTION_SPU_LRLIVE + 1)
    609 #define OPTION_SPU_FIXED_SPACE		(OPTION_SPU_NON_IA_TEXT + 1)
    610 #define OPTION_SPU_RESERVED_SPACE	(OPTION_SPU_FIXED_SPACE + 1)
    611 #define OPTION_SPU_EXTRA_STACK		(OPTION_SPU_RESERVED_SPACE + 1)
    612 #define OPTION_SPU_NO_AUTO_OVERLAY	(OPTION_SPU_EXTRA_STACK + 1)
    613 #define OPTION_SPU_EMIT_FIXUPS		(OPTION_SPU_NO_AUTO_OVERLAY + 1)
    614 '
    615 
    616 PARSE_AND_LIST_LONGOPTS='
    617   { "plugin", no_argument, NULL, OPTION_SPU_PLUGIN },
    618   { "soft-icache", no_argument, NULL, OPTION_SPU_SOFT_ICACHE },
    619   { "lrlive-analysis", no_argument, NULL, OPTION_SPU_LRLIVE },
    620   { "num-lines", required_argument, NULL, OPTION_SPU_NUM_LINES },
    621   { "line-size", required_argument, NULL, OPTION_SPU_LINE_SIZE },
    622   { "non-ia-text", no_argument, NULL, OPTION_SPU_NON_IA_TEXT },
    623   { "no-overlays", no_argument, NULL, OPTION_SPU_NO_OVERLAYS },
    624   { "compact-stubs", no_argument, NULL, OPTION_SPU_COMPACT_STUBS },
    625   { "emit-stub-syms", no_argument, NULL, OPTION_SPU_STUB_SYMS },
    626   { "extra-overlay-stubs", no_argument, NULL, OPTION_SPU_NON_OVERLAY_STUBS },
    627   { "local-store", required_argument, NULL, OPTION_SPU_LOCAL_STORE },
    628   { "stack-analysis", no_argument, NULL, OPTION_SPU_STACK_ANALYSIS },
    629   { "emit-stack-syms", no_argument, NULL, OPTION_SPU_STACK_SYMS },
    630   { "auto-overlay", optional_argument, NULL, OPTION_SPU_AUTO_OVERLAY },
    631   { "auto-relink", no_argument, NULL, OPTION_SPU_AUTO_RELINK },
    632   { "overlay-rodata", no_argument, NULL, OPTION_SPU_OVERLAY_RODATA },
    633   { "num-regions", required_argument, NULL, OPTION_SPU_NUM_LINES },
    634   { "region-size", required_argument, NULL, OPTION_SPU_LINE_SIZE },
    635   { "fixed-space", required_argument, NULL, OPTION_SPU_FIXED_SPACE },
    636   { "reserved-space", required_argument, NULL, OPTION_SPU_RESERVED_SPACE },
    637   { "extra-stack-space", required_argument, NULL, OPTION_SPU_EXTRA_STACK },
    638   { "no-auto-overlay", optional_argument, NULL, OPTION_SPU_NO_AUTO_OVERLAY },
    639   { "emit-fixups", optional_argument, NULL, OPTION_SPU_EMIT_FIXUPS },
    640 '
    641 
    642 PARSE_AND_LIST_OPTIONS='
    643   fprintf (file, _("\
    644   --plugin                    Make SPU plugin.\n\
    645   --no-overlays               No overlay handling.\n\
    646   --compact-stubs             Use smaller and possibly slower call stubs.\n\
    647   --emit-stub-syms            Add symbols on overlay call stubs.\n\
    648   --extra-overlay-stubs       Add stubs on all calls out of overlay regions.\n\
    649   --local-store=lo:hi         Valid address range.\n\
    650   --stack-analysis            Estimate maximum stack requirement.\n\
    651   --emit-stack-syms           Add sym giving stack needed for each func.\n\
    652   --auto-overlay [=filename]  Create an overlay script in filename if\n\
    653                               executable does not fit in local store.\n\
    654   --auto-relink               Rerun linker using auto-overlay script.\n\
    655   --overlay-rodata            Place read-only data with associated function\n\
    656                               code in overlays.\n\
    657   --num-regions               Number of overlay buffers (default 1).\n\
    658   --region-size               Size of overlay buffers (default 0, auto).\n\
    659   --fixed-space=bytes         Local store for non-overlay code and data.\n\
    660   --reserved-space=bytes      Local store for stack and heap.  If not specified\n\
    661                               ld will estimate stack size and assume no heap.\n\
    662   --extra-stack-space=bytes   Space for negative sp access (default 2000) if\n\
    663                               --reserved-space not given.\n\
    664   --soft-icache               Generate software icache overlays.\n\
    665   --num-lines                 Number of soft-icache lines (default 32).\n\
    666   --line-size                 Size of soft-icache lines (default 1k).\n\
    667   --non-ia-text               Allow non-icache code in icache lines.\n\
    668   --lrlive-analysis           Scan function prologue for lr liveness.\n"
    669 		   ));
    670 '
    671 
    672 PARSE_AND_LIST_ARGS_CASES='
    673     case OPTION_SPU_PLUGIN:
    674       spu_elf_plugin (1);
    675       break;
    676 
    677     case OPTION_SPU_NO_OVERLAYS:
    678       no_overlays = 1;
    679       break;
    680 
    681     case OPTION_SPU_COMPACT_STUBS:
    682       params.compact_stub = 1;
    683       break;
    684 
    685     case OPTION_SPU_STUB_SYMS:
    686       params.emit_stub_syms = 1;
    687       break;
    688 
    689     case OPTION_SPU_NON_OVERLAY_STUBS:
    690       params.non_overlay_stubs = 1;
    691       break;
    692 
    693     case OPTION_SPU_LOCAL_STORE:
    694       {
    695 	char *end;
    696 	params.local_store_lo = strtoul (optarg, &end, 0);
    697 	if (*end == '\'':'\'')
    698 	  {
    699 	    params.local_store_hi = strtoul (end + 1, &end, 0);
    700 	    if (*end == 0)
    701 	      break;
    702 	  }
    703 	einfo (_("%P%F: invalid --local-store address range `%s'\''\n"), optarg);
    704       }
    705       break;
    706 
    707     case OPTION_SPU_STACK_ANALYSIS:
    708       params.stack_analysis = 1;
    709       break;
    710 
    711     case OPTION_SPU_STACK_SYMS:
    712       params.emit_stack_syms = 1;
    713       break;
    714 
    715     case OPTION_SPU_AUTO_OVERLAY:
    716       params.auto_overlay |= 1;
    717       if (optarg != NULL)
    718 	{
    719 	  auto_overlay_file = optarg;
    720 	  break;
    721 	}
    722       /* Fall thru */
    723 
    724     case OPTION_SPU_AUTO_RELINK:
    725       params.auto_overlay |= 2;
    726       break;
    727 
    728     case OPTION_SPU_OVERLAY_RODATA:
    729       params.auto_overlay |= 4;
    730       break;
    731 
    732     case OPTION_SPU_SOFT_ICACHE:
    733       params.ovly_flavour = ovly_soft_icache;
    734       /* Software i-cache stubs are always "compact".  */
    735       params.compact_stub = 1;
    736       if (!num_lines_set)
    737 	params.num_lines = 32;
    738       else if ((params.num_lines & -params.num_lines) != params.num_lines)
    739 	einfo (_("%P%F: invalid --num-lines/--num-regions `%u'\''\n"),
    740 	       params.num_lines);
    741       if (!line_size_set)
    742 	params.line_size = 1024;
    743       else if ((params.line_size & -params.line_size) != params.line_size)
    744 	einfo (_("%P%F: invalid --line-size/--region-size `%u'\''\n"),
    745 	       params.line_size);
    746       break;
    747 
    748     case OPTION_SPU_LRLIVE:
    749       params.lrlive_analysis = 1;
    750       break;
    751 
    752     case OPTION_SPU_NON_IA_TEXT:
    753       params.non_ia_text = 1;
    754       break;
    755 
    756     case OPTION_SPU_NUM_LINES:
    757       {
    758 	char *end;
    759 	params.num_lines = strtoul (optarg, &end, 0);
    760 	num_lines_set = 1;
    761 	if (*end == 0
    762 	    && (params.ovly_flavour != ovly_soft_icache
    763 		|| (params.num_lines & -params.num_lines) == params.num_lines))
    764 	  break;
    765 	einfo (_("%P%F: invalid --num-lines/--num-regions `%s'\''\n"), optarg);
    766       }
    767       break;
    768 
    769     case OPTION_SPU_LINE_SIZE:
    770       {
    771 	char *end;
    772 	params.line_size = strtoul (optarg, &end, 0);
    773 	line_size_set = 1;
    774 	if (*end == 0
    775 	    && (params.ovly_flavour != ovly_soft_icache
    776 		|| (params.line_size & -params.line_size) == params.line_size))
    777 	  break;
    778 	einfo (_("%P%F: invalid --line-size/--region-size `%s'\''\n"), optarg);
    779       }
    780       break;
    781 
    782     case OPTION_SPU_FIXED_SPACE:
    783       {
    784 	char *end;
    785 	params.auto_overlay_fixed = strtoul (optarg, &end, 0);
    786 	if (*end != 0)
    787 	  einfo (_("%P%F: invalid --fixed-space value `%s'\''\n"), optarg);
    788       }
    789       break;
    790 
    791     case OPTION_SPU_RESERVED_SPACE:
    792       {
    793 	char *end;
    794 	params.auto_overlay_reserved = strtoul (optarg, &end, 0);
    795 	if (*end != 0)
    796 	  einfo (_("%P%F: invalid --reserved-space value `%s'\''\n"), optarg);
    797       }
    798       break;
    799 
    800     case OPTION_SPU_EXTRA_STACK:
    801       {
    802 	char *end;
    803 	params.extra_stack_space = strtol (optarg, &end, 0);
    804 	if (*end != 0)
    805 	  einfo (_("%P%F: invalid --extra-stack-space value `%s'\''\n"), optarg);
    806       }
    807       break;
    808 
    809     case OPTION_SPU_NO_AUTO_OVERLAY:
    810       params.auto_overlay = 0;
    811       if (optarg != NULL)
    812 	{
    813 	  struct tflist *tf;
    814 	  size_t len;
    815 
    816 	  if (tmp_file_list == NULL)
    817 	    atexit (clean_tmp);
    818 
    819 	  len = strlen (optarg) + 1;
    820 	  tf = xmalloc (sizeof (*tf) - sizeof (tf->name) + len);
    821 	  memcpy (tf->name, optarg, len);
    822 	  tf->next = tmp_file_list;
    823 	  tmp_file_list = tf;
    824 	  break;
    825 	}
    826       break;
    827 
    828     case OPTION_SPU_EMIT_FIXUPS:
    829       params.emit_fixups = 1;
    830       break;
    831 '
    832 
    833 LDEMUL_AFTER_OPEN=spu_after_open
    834 LDEMUL_BEFORE_ALLOCATION=spu_before_allocation
    835 LDEMUL_FINISH=gld${EMULATION_NAME}_finish
    836 LDEMUL_CHOOSE_TARGET=gld${EMULATION_NAME}_choose_target
    837