aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/elf32-spu.c181
-rw-r--r--bfd/elf32-spu.h1
-rw-r--r--ld/ChangeLog7
-rw-r--r--ld/emultempl/spuelf.em17
5 files changed, 136 insertions, 75 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index ebb847b7016..704a418843c 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,10 @@
2008-12-10 Alan Modra <amodra@bigpond.net.au>
+ * elf32-spu.h (struct spu_elf_params): Add num_regions.
+ * elf32-spu.c (spu_elf_auto_overlay): Handle multiple overlay regions.
+
+2008-12-10 Alan Modra <amodra@bigpond.net.au>
+
* elf32-spu.g (struct spu_elf_params, enum _ovly_flavour): New.
(spu_elf_setup): Declare.
(spu_elf_create_sections, spu_elf_size_stubs): Update prototype.
diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c
index 3908ecd125c..447aa8da0a0 100644
--- a/bfd/elf32-spu.c
+++ b/bfd/elf32-spu.c
@@ -3444,8 +3444,9 @@ spu_elf_auto_overlay (struct bfd_link_info *info)
unsigned int fixed_size, lo, hi;
struct spu_link_hash_table *htab;
unsigned int base, i, count, bfd_count;
- int ovlynum;
+ unsigned int region, ovlynum;
asection **ovly_sections, **ovly_p;
+ unsigned int *ovly_map;
FILE *script;
unsigned int total_overlay_size, overlay_size;
struct elf_link_hash_entry *h;
@@ -3625,20 +3626,17 @@ spu_elf_auto_overlay (struct bfd_link_info *info)
if (!for_each_node (collect_overlays, info, &ovly_p, TRUE))
goto err_exit;
count = (size_t) (ovly_p - ovly_sections) / 2;
-
- script = (*htab->params->spu_elf_open_overlay_script) ();
-
- if (fprintf (script, "SECTIONS\n{\n OVERLAY :\n {\n") <= 0)
- goto file_err;
+ ovly_map = bfd_malloc (count * sizeof (*ovly_map));
+ if (ovly_map == NULL)
+ goto err_exit;
memset (&dummy_caller, 0, sizeof (dummy_caller));
- overlay_size = htab->local_store - fixed_size;
+ overlay_size = (htab->local_store - fixed_size) / htab->params->num_regions;
base = 0;
ovlynum = 0;
while (base < count)
{
unsigned int size = 0;
- unsigned int j;
for (i = base; i < count; i++)
{
@@ -3741,90 +3739,127 @@ spu_elf_auto_overlay (struct bfd_link_info *info)
goto err_exit;
}
- if (fprintf (script, " .ovly%d {\n", ++ovlynum) <= 0)
+ while (dummy_caller.call_list != NULL)
+ {
+ struct call_info *call = dummy_caller.call_list;
+ dummy_caller.call_list = call->next;
+ free (call);
+ }
+
+ ++ovlynum;
+ while (base < i)
+ ovly_map[base++] = ovlynum;
+ }
+
+ script = htab->params->spu_elf_open_overlay_script ();
+
+ if (fprintf (script, "SECTIONS\n{\n") <= 0)
+ goto file_err;
+
+ for (region = 1; region <= htab->params->num_regions; region++)
+ {
+ ovlynum = region;
+ base = 0;
+ while (base < count && ovly_map[base] < ovlynum)
+ base++;
+
+ if (base == count)
+ break;
+
+ if (fprintf (script, " OVERLAY :\n {\n") <= 0)
goto file_err;
- for (j = base; j < i; j++)
+
+ while (base < count)
{
- asection *sec = ovly_sections[2 * j];
-
- if (fprintf (script, " %s%c%s (%s)\n",
- (sec->owner->my_archive != NULL
- ? sec->owner->my_archive->filename : ""),
- info->path_separator,
- sec->owner->filename,
- sec->name) <= 0)
+ unsigned int j;
+
+ if (fprintf (script, " .ovly%u {\n", ovlynum) <= 0)
goto file_err;
- if (sec->segment_mark)
+
+ for (j = base; j < count && ovly_map[j] == ovlynum; j++)
{
- struct call_info *call = find_pasted_call (sec);
- while (call != NULL)
+ asection *sec = ovly_sections[2 * j];
+
+ if (fprintf (script, " %s%c%s (%s)\n",
+ (sec->owner->my_archive != NULL
+ ? sec->owner->my_archive->filename : ""),
+ info->path_separator,
+ sec->owner->filename,
+ sec->name) <= 0)
+ goto file_err;
+ if (sec->segment_mark)
{
- struct function_info *call_fun = call->fun;
- sec = call_fun->sec;
- if (fprintf (script, " %s%c%s (%s)\n",
- (sec->owner->my_archive != NULL
- ? sec->owner->my_archive->filename : ""),
- info->path_separator,
- sec->owner->filename,
- sec->name) <= 0)
- goto file_err;
- for (call = call_fun->call_list; call; call = call->next)
- if (call->is_pasted)
- break;
+ struct call_info *call = find_pasted_call (sec);
+ while (call != NULL)
+ {
+ struct function_info *call_fun = call->fun;
+ sec = call_fun->sec;
+ if (fprintf (script, " %s%c%s (%s)\n",
+ (sec->owner->my_archive != NULL
+ ? sec->owner->my_archive->filename : ""),
+ info->path_separator,
+ sec->owner->filename,
+ sec->name) <= 0)
+ goto file_err;
+ for (call = call_fun->call_list; call; call = call->next)
+ if (call->is_pasted)
+ break;
+ }
}
}
- }
- for (j = base; j < i; j++)
- {
- asection *sec = ovly_sections[2 * j + 1];
- if (sec != NULL
- && fprintf (script, " %s%c%s (%s)\n",
- (sec->owner->my_archive != NULL
- ? sec->owner->my_archive->filename : ""),
- info->path_separator,
- sec->owner->filename,
- sec->name) <= 0)
- goto file_err;
-
- sec = ovly_sections[2 * j];
- if (sec->segment_mark)
+ for (j = base; j < count && ovly_map[j] == ovlynum; j++)
{
- struct call_info *call = find_pasted_call (sec);
- while (call != NULL)
+ asection *sec = ovly_sections[2 * j + 1];
+ if (sec != NULL
+ && fprintf (script, " %s%c%s (%s)\n",
+ (sec->owner->my_archive != NULL
+ ? sec->owner->my_archive->filename : ""),
+ info->path_separator,
+ sec->owner->filename,
+ sec->name) <= 0)
+ goto file_err;
+
+ sec = ovly_sections[2 * j];
+ if (sec->segment_mark)
{
- struct function_info *call_fun = call->fun;
- sec = call_fun->rodata;
- if (sec != NULL
- && fprintf (script, " %s%c%s (%s)\n",
- (sec->owner->my_archive != NULL
- ? sec->owner->my_archive->filename : ""),
- info->path_separator,
- sec->owner->filename,
- sec->name) <= 0)
- goto file_err;
- for (call = call_fun->call_list; call; call = call->next)
- if (call->is_pasted)
- break;
+ struct call_info *call = find_pasted_call (sec);
+ while (call != NULL)
+ {
+ struct function_info *call_fun = call->fun;
+ sec = call_fun->rodata;
+ if (sec != NULL
+ && fprintf (script, " %s%c%s (%s)\n",
+ (sec->owner->my_archive != NULL
+ ? sec->owner->my_archive->filename : ""),
+ info->path_separator,
+ sec->owner->filename,
+ sec->name) <= 0)
+ goto file_err;
+ for (call = call_fun->call_list; call; call = call->next)
+ if (call->is_pasted)
+ break;
+ }
}
}
- }
- if (fprintf (script, " }\n") <= 0)
- goto file_err;
+ if (fprintf (script, " }\n") <= 0)
+ goto file_err;
- while (dummy_caller.call_list != NULL)
- {
- struct call_info *call = dummy_caller.call_list;
- dummy_caller.call_list = call->next;
- free (call);
+ base = j;
+ ovlynum += htab->params->num_regions;
+ while (base < count && ovly_map[base] < ovlynum)
+ base++;
}
- base = i;
+ if (fprintf (script, " }\n") <= 0)
+ goto file_err;
}
+
+ free (ovly_map);
free (ovly_sections);
- if (fprintf (script, " }\n}\nINSERT AFTER .text;\n") <= 0)
+ if (fprintf (script, "}\nINSERT BEFORE .text;\n") <= 0)
goto file_err;
if (fclose (script) != 0)
goto file_err;
diff --git a/bfd/elf32-spu.h b/bfd/elf32-spu.h
index 8cac3a33760..442dd5d3b2e 100644
--- a/bfd/elf32-spu.h
+++ b/bfd/elf32-spu.h
@@ -55,6 +55,7 @@ struct spu_elf_params
bfd_vma local_store_hi;
/* Control --auto-overlay feature. */
+ unsigned int num_regions;
unsigned int auto_overlay_fixed;
unsigned int auto_overlay_reserved;
int extra_stack_space;
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 864cba31f1c..b9588c36c1f 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,12 @@
2008-12-10 Alan Modra <amodra@bigpond.net.au>
+ * emultempl/spuelf.em (params): Init new field.
+ (OPTION_SPU_NUM_REGIONS): Define.
+ (PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS): Add --num-regions.
+ (PARSE_AND_LIST_ARGS_CASES): Handle --num-regions.
+
+2008-12-10 Alan Modra <amodra@bigpond.net.au>
+
* emultempl/spuelf.em (params): New var, used instead of various others.
Adjust use throughout file.
(spu_after_open): Call spu_elf_setup.
diff --git a/ld/emultempl/spuelf.em b/ld/emultempl/spuelf.em
index cb80c45cbf3..bfabb8b72ee 100644
--- a/ld/emultempl/spuelf.em
+++ b/ld/emultempl/spuelf.em
@@ -39,7 +39,7 @@ static struct spu_elf_params params =
&spu_elf_relink,
0, ovly_normal, 0, 0, 0, 0,
0, 0x3ffff,
- 0, 0, 2000
+ 1, 0, 0, 2000
};
static char *auto_overlay_file = 0;
@@ -520,7 +520,8 @@ PARSE_AND_LIST_PROLOGUE='
#define OPTION_SPU_AUTO_OVERLAY (OPTION_SPU_STACK_SYMS + 1)
#define OPTION_SPU_AUTO_RELINK (OPTION_SPU_AUTO_OVERLAY + 1)
#define OPTION_SPU_OVERLAY_RODATA (OPTION_SPU_AUTO_RELINK + 1)
-#define OPTION_SPU_FIXED_SPACE (OPTION_SPU_OVERLAY_RODATA + 1)
+#define OPTION_SPU_NUM_REGIONS (OPTION_SPU_OVERLAY_RODATA + 1)
+#define OPTION_SPU_FIXED_SPACE (OPTION_SPU_NUM_REGIONS + 1)
#define OPTION_SPU_RESERVED_SPACE (OPTION_SPU_FIXED_SPACE + 1)
#define OPTION_SPU_EXTRA_STACK (OPTION_SPU_RESERVED_SPACE + 1)
#define OPTION_SPU_NO_AUTO_OVERLAY (OPTION_SPU_EXTRA_STACK + 1)
@@ -537,6 +538,7 @@ PARSE_AND_LIST_LONGOPTS='
{ "auto-overlay", optional_argument, NULL, OPTION_SPU_AUTO_OVERLAY },
{ "auto-relink", no_argument, NULL, OPTION_SPU_AUTO_RELINK },
{ "overlay-rodata", no_argument, NULL, OPTION_SPU_OVERLAY_RODATA },
+ { "num-regions", required_argument, NULL, OPTION_SPU_NUM_REGIONS },
{ "fixed-space", required_argument, NULL, OPTION_SPU_FIXED_SPACE },
{ "reserved-space", required_argument, NULL, OPTION_SPU_RESERVED_SPACE },
{ "extra-stack-space", required_argument, NULL, OPTION_SPU_EXTRA_STACK },
@@ -557,6 +559,7 @@ PARSE_AND_LIST_OPTIONS='
--auto-relink Rerun linker using auto-overlay script.\n\
--overlay-rodata Place read-only data with associated function\n\
code in overlays.\n\
+ --num-regions Number of overlay buffers (default 1).\n\
--fixed-space=bytes Local store for non-overlay code and data.\n\
--reserved-space=bytes Local store for stack and heap. If not specified\n\
ld will estimate stack size and assume no heap.\n\
@@ -621,6 +624,16 @@ PARSE_AND_LIST_ARGS_CASES='
params.auto_overlay |= 4;
break;
+ case OPTION_SPU_NUM_REGIONS:
+ {
+ char *end;
+ params.num_regions = strtoul (optarg, &end, 0);
+ if (*end == 0)
+ break;
+ einfo (_("%P%F: invalid --num-regions `%s'\''\n"), optarg);
+ }
+ break;
+
case OPTION_SPU_FIXED_SPACE:
{
char *end;