* elf32-spu.c (struct spu_link_hash_table): Add init, line_size_log2,
	num_lines_log2.
	(struct got_entry): Add br_addr.
	(struct call_info): Add priority.
	(struct function_info): Add lr_store and sp_adjust.
	(spu_elf_setup): Init line_size_log2 and num_lines_log2.
	(spu_elf_find_overlays): For soft-icache, mark any section within cache
	area as an overlay, and check that no other overlays exist.  Look up
	icache overlay manager entry sym.
	(BRA_STUBS, BRA, BRASL): Define.
	(enum _stub_type): Replace ovl_stub with call_ovl_stub and br*_ovl_stub.
	(needs_ovl_stub): Adjust for soft-icache.  Return priority encoded
	in branch insn.
	(count_stub, build_stub): Support soft-icache.
	(build_spuear_stubs, process_stubs): Adjust build_stub call.
	(spu_elf_size_stubs): Size soft-icache stubs.
	(overlay_index): New function.
	(spu_elf_build_stubs): Make static.  Support soft-icache.
	(spu_elf_check_vma): Don't turn off auto_overlay if soft-icache.
	(find_function_stack_adjust): Save lr store and stack adjust insn
	offsets.
	(maybe_insert_function): Adjust find_function_stack_adjust call.
	(mark_functions_via_relocs): Retrieve priority.
	(remove_cycles): Only warn about pruned arcs when stack_analysis.
	(sort_calls): Sort by priority first.
	(mark_overlay_section): Ignore .ovl.init.
	(sum_stack): Only print when stack_analysis.
	(print_one_overlay_section): New function, extracted from..
	(spu_elf_auto_overlay): ..here.  Support soft-icache overlays.
	(spu_elf_stack_analysis): Only print when htab->stack_analysis.
	(spu_elf_final_link): Call spu_elf_stack_analysis for lrlive
	analysis.  Call spu_elf_build_stubs.
	(spu_elf_relocate_section): For soft-icache encode overlay index
	into addresses.
	(spu_elf_output_symbol_hook): Support soft-icache.
	(spu_elf_modify_program_headers: Likewise.
	* elf32-spu.h (struct spu_elf_params): Add lrlive_analysis.  Rename
	num_regions to num_lines.  Add line_size and max_branch.
	(enum _ovly_flavour): Add ovly_soft_icache.
	(spu_elf_build_stubs): Delete.
gas/
	* config/tc-spu.c (md_pseudo_table): Add "brinfo".
	(brinfo): New var.
	(md_assemble): Poke brinfo into branch instructions.
	(spu_brinfo): New function.
	(md_apply_fix): Don't assume insn fields start off at zero, mask
	them to remove possible brinfo.
ld/
	* emultempl/spuelf.em (params): Init new fields.
	(num_lines_set, line_size_set, icache_mgr, icache_mgr_stream): New vars.
	(spu_place_special_section): Adjust placement for soft-icache.  Pad
	soft-icache section to a fixed size.  Clear addr_tree.
	(spu_elf_load_ovl_mgr): Support soft-icache.  Map overlay manager
	sections a little more intelligently.
	(gld${EMULATION_NAME}_finish): Don't call spu_elf_build_stubs.
	(OPTION_SPU_NUM_LINES): Rename from OPTION_SPU_NUM_REGIONS.
	(OPTION_SPU_SOFT_ICACHE, OPTION_SPU_LINE_SIZE): Define.
	(OPTION_SPU_LRLIVE): Define.
	(PARSE_AND_LIST_LONGOPTS): Add new soft-icache options.
	(PARSE_AND_LIST_OPTIONS): Likewise.
	(PARSE_AND_LIST_ARGS_CASES): Handle them.
	* emultempl/spu_icache.S: Dummy file.
	* emultempl/spu_icache.o_c: Regenerate.
	* Makefile.am (eelf32_spu.c): Depend on spu_icache.o_c.
	(spu_icache.o_c): Add rule to build.
	(CLEANFILES): Zap temp files.
	(EXTRA_DIST): Add spu_icache.o_c.
	* Makefile.in: Regenerate.
ld/testsuite/
	* ld-spu/ovl.d: Allow for absolute branches in stubs.
	* ld-spu/ovl2.d: Likewise.
This commit is contained in:
Alan Modra 2009-01-12 00:23:58 +00:00
parent 2c0fbbe09e
commit cd4a7468c9
14 changed files with 1311 additions and 386 deletions

View file

@ -1,3 +1,46 @@
2009-01-12 Alan Modra <amodra@bigpond.net.au>
* elf32-spu.c (struct spu_link_hash_table): Add init, line_size_log2,
num_lines_log2.
(struct got_entry): Add br_addr.
(struct call_info): Add priority.
(struct function_info): Add lr_store and sp_adjust.
(spu_elf_setup): Init line_size_log2 and num_lines_log2.
(spu_elf_find_overlays): For soft-icache, mark any section within cache
area as an overlay, and check that no other overlays exist. Look up
icache overlay manager entry sym.
(BRA_STUBS, BRA, BRASL): Define.
(enum _stub_type): Replace ovl_stub with call_ovl_stub and br*_ovl_stub.
(needs_ovl_stub): Adjust for soft-icache. Return priority encoded
in branch insn.
(count_stub, build_stub): Support soft-icache.
(build_spuear_stubs, process_stubs): Adjust build_stub call.
(spu_elf_size_stubs): Size soft-icache stubs.
(overlay_index): New function.
(spu_elf_build_stubs): Make static. Support soft-icache.
(spu_elf_check_vma): Don't turn off auto_overlay if soft-icache.
(find_function_stack_adjust): Save lr store and stack adjust insn
offsets.
(maybe_insert_function): Adjust find_function_stack_adjust call.
(mark_functions_via_relocs): Retrieve priority.
(remove_cycles): Only warn about pruned arcs when stack_analysis.
(sort_calls): Sort by priority first.
(mark_overlay_section): Ignore .ovl.init.
(sum_stack): Only print when stack_analysis.
(print_one_overlay_section): New function, extracted from..
(spu_elf_auto_overlay): ..here. Support soft-icache overlays.
(spu_elf_stack_analysis): Only print when htab->stack_analysis.
(spu_elf_final_link): Call spu_elf_stack_analysis for lrlive
analysis. Call spu_elf_build_stubs.
(spu_elf_relocate_section): For soft-icache encode overlay index
into addresses.
(spu_elf_output_symbol_hook): Support soft-icache.
(spu_elf_modify_program_headers: Likewise.
* elf32-spu.h (struct spu_elf_params): Add lrlive_analysis. Rename
num_regions to num_lines. Add line_size and max_branch.
(enum _ovly_flavour): Add ovly_soft_icache.
(spu_elf_build_stubs): Delete.
2009-01-11 Jan Kratochvil <jan.kratochvil@redhat.com>
* elflink.c (_bfd_elf_section_already_linked): Handle g++-3.4

File diff suppressed because it is too large Load diff

View file

@ -44,6 +44,9 @@ struct spu_elf_params
non-overlay regions. */
unsigned int non_overlay_stubs : 1;
/* Set if lr liveness analysis should be done. */
unsigned int lrlive_analysis : 1;
/* Set if stack size analysis should be done. */
unsigned int stack_analysis : 1;
@ -55,7 +58,9 @@ struct spu_elf_params
bfd_vma local_store_hi;
/* Control --auto-overlay feature. */
unsigned int num_regions;
unsigned int num_lines;
unsigned int line_size;
unsigned int max_branch;
unsigned int auto_overlay_fixed;
unsigned int auto_overlay_reserved;
int extra_stack_space;
@ -92,6 +97,7 @@ enum _ovly_flavour
{
ovly_compact,
ovly_normal,
ovly_soft_icache,
ovly_none
};
@ -108,5 +114,4 @@ extern bfd_boolean spu_elf_open_builtin_lib (bfd **,
extern bfd_boolean spu_elf_create_sections (struct bfd_link_info *);
extern bfd_boolean spu_elf_find_overlays (struct bfd_link_info *);
extern int spu_elf_size_stubs (struct bfd_link_info *);
extern bfd_boolean spu_elf_build_stubs (struct bfd_link_info *);
extern asection *spu_elf_check_vma (struct bfd_link_info *);

View file

@ -1,3 +1,12 @@
2009-01-12 Alan Modra <amodra@bigpond.net.au>
* config/tc-spu.c (md_pseudo_table): Add "brinfo".
(brinfo): New var.
(md_assemble): Poke brinfo into branch instructions.
(spu_brinfo): New function.
(md_apply_fix): Don't assume insn fields start off at zero, mask
them to remove possible brinfo.
2009-01-10 H.J. Lu <hongjiu.lu@intel.com>
* doc/c-i386.texi: Reformat.

View file

@ -1,6 +1,6 @@
/* spu.c -- Assembler for the IBM Synergistic Processing Unit (SPU)
Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@ -53,6 +53,7 @@ static const char *get_reg (const char *param, struct spu_insn *insn, int arg,
int accept_expr);
static int calcop (struct spu_opcode *format, const char *param,
struct spu_insn *insn);
static void spu_brinfo (int);
static void spu_cons (int);
extern char *myname;
@ -82,6 +83,7 @@ const char FLT_CHARS[] = "dDfF";
const pseudo_typeS md_pseudo_table[] =
{
{"align", s_align_ptwo, 4},
{"brinfo", spu_brinfo, 0},
{"bss", s_lcomm_bytes, 1},
{"def", s_set, 0},
{"dfloat", float_cons, 'd'},
@ -104,6 +106,9 @@ const pseudo_typeS md_pseudo_table[] =
{0,0,0}
};
/* Bits plugged into branch instruction offset field. */
unsigned int brinfo;
void
md_begin (void)
{
@ -342,6 +347,16 @@ md_assemble (char *op)
as_warn (_("Treating '%-*s' as a symbol."), (int)(syntax_error_param - d), d);
}
if (brinfo != 0
&& (insn.tag <= M_BRASL
|| (insn.tag >= M_BRZ && insn.tag <= M_BRHNZ))
&& (insn.opcode & 0x7ff80) == 0
&& (insn.reloc_arg[0] == A_R18
|| insn.reloc_arg[0] == A_S18
|| insn.reloc_arg[1] == A_R18
|| insn.reloc_arg[1] == A_S18))
insn.opcode |= brinfo << 7;
/* grow the current frag and plop in the opcode */
thisfrag = frag_more (4);
@ -370,6 +385,9 @@ md_assemble (char *op)
fixP->tc_fix_data.insn_tag = insn.tag;
}
dwarf2_emit_insn (4);
/* .brinfo lasts exactly one instruction. */
brinfo = 0;
}
static int
@ -752,6 +770,39 @@ md_create_long_jump (char *ptr,
}
#endif
/* Handle .brinfo <priority>,<lrlive>. */
static void
spu_brinfo (int ignore ATTRIBUTE_UNUSED)
{
addressT priority;
addressT lrlive;
priority = get_absolute_expression ();
SKIP_WHITESPACE ();
lrlive = 0;
if (*input_line_pointer == ',')
{
++input_line_pointer;
lrlive = get_absolute_expression ();
}
if (priority > 0x1fff)
{
as_bad (_("invalid priority '%lu'"), (unsigned long) priority);
priority = 0;
}
if (lrlive > 7)
{
as_bad (_("invalid lrlive '%lu'"), (unsigned long) lrlive);
lrlive = 0;
}
brinfo = (lrlive << 13) | priority;
demand_empty_rest_of_line ();
}
/* Support @ppu on symbols referenced in .int/.long/.word/.quad. */
static void
spu_cons (int nbytes)
@ -898,6 +949,7 @@ void
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
unsigned int res;
unsigned int mask;
valueT val = *valP;
char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
@ -944,6 +996,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
fixP->fx_done = 1;
res = 0;
mask = 0;
if (fixP->tc_fix_data.arg_format > A_P)
{
int hi = arg_encode[fixP->tc_fix_data.arg_format].hi;
@ -955,84 +1008,94 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
}
switch (fixP->fx_r_type)
{
case BFD_RELOC_8:
{
case BFD_RELOC_8:
md_number_to_chars (place, val, 1);
return;
case BFD_RELOC_16:
case BFD_RELOC_16:
md_number_to_chars (place, val, 2);
return;
case BFD_RELOC_32:
case BFD_RELOC_32:
case BFD_RELOC_32_PCREL:
md_number_to_chars (place, val, 4);
return;
case BFD_RELOC_64:
case BFD_RELOC_64:
md_number_to_chars (place, val, 8);
return;
case BFD_RELOC_SPU_IMM7:
res = (val & 0x7f) << 14;
break;
case BFD_RELOC_SPU_IMM7:
res = val << 14;
mask = 0x7f << 14;
break;
case BFD_RELOC_SPU_IMM8:
res = (val & 0xff) << 14;
break;
case BFD_RELOC_SPU_IMM8:
res = val << 14;
mask = 0xff << 14;
break;
case BFD_RELOC_SPU_IMM10:
res = (val & 0x3ff) << 14;
break;
case BFD_RELOC_SPU_IMM10:
res = val << 14;
mask = 0x3ff << 14;
break;
case BFD_RELOC_SPU_IMM10W:
res = (val & 0x3ff0) << 10;
break;
case BFD_RELOC_SPU_IMM10W:
res = val << 10;
mask = 0x3ff0 << 10;
break;
case BFD_RELOC_SPU_IMM16:
res = (val & 0xffff) << 7;
break;
case BFD_RELOC_SPU_IMM16:
res = val << 7;
mask = 0xffff << 7;
break;
case BFD_RELOC_SPU_IMM16W:
res = (val & 0x3fffc) << 5;
break;
case BFD_RELOC_SPU_IMM16W:
res = val << 5;
mask = 0x3fffc << 5;
break;
case BFD_RELOC_SPU_IMM18:
res = (val & 0x3ffff) << 7;
break;
case BFD_RELOC_SPU_IMM18:
res = val << 7;
mask = 0x3ffff << 7;
break;
case BFD_RELOC_SPU_PCREL9a:
res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 14);
break;
case BFD_RELOC_SPU_PCREL9a:
res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 14);
mask = (0x1fc >> 2) | (0x600 << 14);
break;
case BFD_RELOC_SPU_PCREL9b:
res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 5);
break;
case BFD_RELOC_SPU_PCREL9b:
res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 5);
mask = (0x1fc >> 2) | (0x600 << 5);
break;
case BFD_RELOC_SPU_PCREL16:
res = (val & 0x3fffc) << 5;
break;
case BFD_RELOC_SPU_PCREL16:
res = val << 5;
mask = 0x3fffc << 5;
break;
case BFD_RELOC_SPU_HI16:
res = (val >> 9) & 0x7fff80;
res = val >> 9;
mask = 0xffff << 7;
break;
case BFD_RELOC_SPU_LO16:
res = (val << 7) & 0x7fff80;
res = val << 7;
mask = 0xffff << 7;
break;
default:
as_bad_where (fixP->fx_file, fixP->fx_line,
_("reloc %d not supported by object file format"),
(int) fixP->fx_r_type);
}
default:
as_bad_where (fixP->fx_file, fixP->fx_line,
_("reloc %d not supported by object file format"),
(int) fixP->fx_r_type);
}
if (res != 0)
{
place[0] |= (res >> 24) & 0xff;
place[1] |= (res >> 16) & 0xff;
place[2] |= (res >> 8) & 0xff;
place[3] |= (res) & 0xff;
}
res &= mask;
place[0] = (place[0] & (~mask >> 24)) | ((res >> 24) & 0xff);
place[1] = (place[1] & (~mask >> 16)) | ((res >> 16) & 0xff);
place[2] = (place[2] & (~mask >> 8)) | ((res >> 8) & 0xff);
place[3] = (place[3] & ~mask) | (res & 0xff);
}
}

View file

@ -1,3 +1,26 @@
2009-01-12 Alan Modra <amodra@bigpond.net.au>
* emultempl/spuelf.em (params): Init new fields.
(num_lines_set, line_size_set, icache_mgr, icache_mgr_stream): New vars.
(spu_place_special_section): Adjust placement for soft-icache. Pad
soft-icache section to a fixed size. Clear addr_tree.
(spu_elf_load_ovl_mgr): Support soft-icache. Map overlay manager
sections a little more intelligently.
(gld${EMULATION_NAME}_finish): Don't call spu_elf_build_stubs.
(OPTION_SPU_NUM_LINES): Rename from OPTION_SPU_NUM_REGIONS.
(OPTION_SPU_SOFT_ICACHE, OPTION_SPU_LINE_SIZE): Define.
(OPTION_SPU_LRLIVE): Define.
(PARSE_AND_LIST_LONGOPTS): Add new soft-icache options.
(PARSE_AND_LIST_OPTIONS): Likewise.
(PARSE_AND_LIST_ARGS_CASES): Handle them.
* emultempl/spu_icache.S: Dummy file.
* emultempl/spu_icache.o_c: Regenerate.
* Makefile.am (eelf32_spu.c): Depend on spu_icache.o_c.
(spu_icache.o_c): Add rule to build.
(CLEANFILES): Zap temp files.
(EXTRA_DIST): Add spu_icache.o_c.
* Makefile.in: Regenerate.
2009-01-08 Kai Tietz <kai.tietz@onevision.com>
* pe.em (OPTION_USE_NUL_PREFIXED_IMPORT_TABLES): New.

View file

@ -753,7 +753,7 @@ eelf32_sparc_vxworks.c: $(srcdir)/emulparams/elf32_sparc_vxworks.sh \
$(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32_sparc_vxworks "$(tdir_elf32_sparc_vxworks)"
eelf32_spu.c: $(srcdir)/emulparams/elf32_spu.sh $(srcdir)/emultempl/spuelf.em \
$(srcdir)/emultempl/spu_ovl.o_c \
$(srcdir)/emultempl/spu_ovl.o_c $(srcdir)/emultempl/spu_icache.o_c \
ldemul-list.h \
$(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32_spu "$(tdir_elf32_spu)"
@ -764,6 +764,13 @@ $(srcdir)/emultempl/spu_ovl.o_c: @MAINT@ $(srcdir)/emultempl/spu_ovl.S
../gas/as-new -o spu_ovl.o spu_ovl.s; \
../binutils/bin2c <spu_ovl.o >$@; \
fi
$(srcdir)/emultempl/spu_icache.o_c: @MAINT@ $(srcdir)/emultempl/spu_icache.S
if ../gas/as-new --version \
| grep 'target.*spu' >/dev/null 2>/dev/null; then \
cpp -DOVLY_IRQ_SAVE $(srcdir)/emultempl/spu_icache.S spu_icache.s; \
../gas/as-new -o spu_icache.o spu_icache.s; \
../binutils/bin2c <spu_icache.o >$@; \
fi
eelf32_i860.c: $(srcdir)/emulparams/elf32_i860.sh \
$(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32_i860 "$(tdir_elf32_i860)"
@ -1844,7 +1851,7 @@ MOSTLYCLEANFILES = $(STAGESTUFF) ld1$(EXEEXT) ld2$(EXEEXT) ld3$(EXEEXT) \
ldemul-list.h crtbegin.o crtend.o ld.log ld.sum
mostlyclean-local:
-rm -rf tmpdir
CLEANFILES = dep.sed DEP DEPA DEP1 DEP2 spu_ovl.s spu_ovl.o
CLEANFILES = dep.sed DEP DEPA DEP1 DEP2 spu_ovl.s spu_ovl.o spu_icache.s spu_icache.o
.PHONY: install-html install-html-am install-html-recursive
@ -1924,7 +1931,7 @@ install-data-local: install-info
# Stuff that should be included in a distribution. The diststuff
# target is run by the taz target in ../Makefile.in.
EXTRA_DIST = ldgram.c ldgram.h ldlex.c emultempl/spu_ovl.o_c \
deffilep.c deffilep.h $(man_MANS)
emultempl/spu_icache.o_c deffilep.c deffilep.h $(man_MANS)
diststuff: info $(EXTRA_DIST)
all: info ld.1

View file

@ -739,13 +739,13 @@ CONFIG_STATUS_DEPENDENCIES = $(srcdir)/configure.host $(srcdir)/configure.tgt \
MOSTLYCLEANFILES = $(STAGESTUFF) ld1$(EXEEXT) ld2$(EXEEXT) ld3$(EXEEXT) \
ldemul-list.h crtbegin.o crtend.o ld.log ld.sum
CLEANFILES = dep.sed DEP DEPA DEP1 DEP2 spu_ovl.s spu_ovl.o
CLEANFILES = dep.sed DEP DEPA DEP1 DEP2 spu_ovl.s spu_ovl.o spu_icache.s spu_icache.o
html__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
# Stuff that should be included in a distribution. The diststuff
# target is run by the taz target in ../Makefile.in.
EXTRA_DIST = ldgram.c ldgram.h ldlex.c emultempl/spu_ovl.o_c \
deffilep.c deffilep.h $(man_MANS)
emultempl/spu_icache.o_c deffilep.c deffilep.h $(man_MANS)
DISTCLEANFILES = tdirs site.exp site.bak stringify.sed $(am__append_1)
all: config.h
@ -1597,7 +1597,7 @@ eelf32_sparc_vxworks.c: $(srcdir)/emulparams/elf32_sparc_vxworks.sh \
$(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32_sparc_vxworks "$(tdir_elf32_sparc_vxworks)"
eelf32_spu.c: $(srcdir)/emulparams/elf32_spu.sh $(srcdir)/emultempl/spuelf.em \
$(srcdir)/emultempl/spu_ovl.o_c \
$(srcdir)/emultempl/spu_ovl.o_c $(srcdir)/emultempl/spu_icache.o_c \
ldemul-list.h \
$(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32_spu "$(tdir_elf32_spu)"
@ -1608,6 +1608,13 @@ $(srcdir)/emultempl/spu_ovl.o_c: @MAINT@ $(srcdir)/emultempl/spu_ovl.S
../gas/as-new -o spu_ovl.o spu_ovl.s; \
../binutils/bin2c <spu_ovl.o >$@; \
fi
$(srcdir)/emultempl/spu_icache.o_c: @MAINT@ $(srcdir)/emultempl/spu_icache.S
if ../gas/as-new --version \
| grep 'target.*spu' >/dev/null 2>/dev/null; then \
cpp -DOVLY_IRQ_SAVE $(srcdir)/emultempl/spu_icache.S spu_icache.s; \
../gas/as-new -o spu_icache.o spu_icache.s; \
../binutils/bin2c <spu_icache.o >$@; \
fi
eelf32_i860.c: $(srcdir)/emulparams/elf32_i860.sh \
$(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32_i860 "$(tdir_elf32_i860)"

View file

@ -0,0 +1,4 @@
.text
.global __icache_br_handler
__icache_br_handler:
stop

View file

View file

@ -1,5 +1,5 @@
# This shell script emits a C file. -*- C -*-
# Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
# Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of the GNU Binutils.
#
@ -37,11 +37,13 @@ static struct spu_elf_params params =
&spu_elf_load_ovl_mgr,
&spu_elf_open_overlay_script,
&spu_elf_relink,
0, ovly_normal, 0, 0, 0, 0,
0, ovly_normal, 0, 0, 0, 0, 0,
0, 0x3ffff,
1, 0, 0, 2000
1, 0, 16, 0, 0, 2000
};
static unsigned int num_lines_set = 0;
static unsigned int line_size_set = 0;
static char *auto_overlay_file = 0;
int my_argc;
char **my_argv;
@ -52,7 +54,20 @@ EOF
if ! cat ${srcdir}/emultempl/spu_ovl.o_c >> e${EMULATION_NAME}.c
then
echo >&2 "Missing ${srcdir}/emultempl/spu_ovl.o_c"
echo >&2 "You must build gas/as-new with --target=spu to build spu_ovl.o"
echo >&2 "You must build gas/as-new with --target=spu"
exit 1
fi
fragment <<EOF
};
static const char icache_mgr[] = {
EOF
if ! cat ${srcdir}/emultempl/spu_icache.o_c >> e${EMULATION_NAME}.c
then
echo >&2 "Missing ${srcdir}/emultempl/spu_icache.o_c"
echo >&2 "You must build gas/as-new with --target=spu"
exit 1
fi
@ -64,6 +79,11 @@ static const struct _ovl_stream ovl_mgr_stream = {
ovl_mgr + sizeof (ovl_mgr)
};
static const struct _ovl_stream icache_mgr_stream = {
icache_mgr,
icache_mgr + sizeof (icache_mgr)
};
static int
is_spu_target (void)
@ -96,7 +116,8 @@ spu_after_open (void)
}
/* If O is NULL, add section S at the end of output section OUTPUT_NAME.
If O is not NULL, add section S at the beginning of output section O.
If O is not NULL, add section S at the beginning of output section O,
except for soft-icache which adds to the end.
Really, we should be duplicating ldlang.c map_input_to_output_sections
logic here, ie. using the linker script to find where the section
@ -115,8 +136,12 @@ spu_place_special_section (asection *s, asection *o, const char *output_name)
output_name = o->name;
os = lang_output_section_find (output_name);
if (os == NULL)
gld${EMULATION_NAME}_place_orphan (s, output_name, 0);
else if (o != NULL && os->children.head != NULL)
{
os = gld${EMULATION_NAME}_place_orphan (s, output_name, 0);
os->addr_tree = NULL;
}
else if (params.ovly_flavour != ovly_soft_icache
&& o != NULL && os->children.head != NULL)
{
lang_statement_list_type add;
@ -126,7 +151,21 @@ spu_place_special_section (asection *s, asection *o, const char *output_name)
os->children.head = add.head;
}
else
lang_add_section (&os->children, s, os);
{
if (params.ovly_flavour == ovly_soft_icache && o != NULL)
{
/* Pad this stub section so that it finishes at the
end of the icache line. */
etree_type *e_size;
lang_statement_list_type *save = stat_ptr;
stat_ptr = &os->children;
e_size = exp_intop (params.line_size - s->size);
lang_add_assignment (exp_assop ('=', ".", e_size));
stat_ptr = save;
}
lang_add_section (&os->children, s, os);
}
s->output_section->size += s->size;
}
@ -137,10 +176,19 @@ static bfd_size_type
spu_elf_load_ovl_mgr (void)
{
struct elf_link_hash_entry *h;
const char *ovly_mgr_entry;
const struct _ovl_stream *mgr_stream;
bfd_size_type total = 0;
ovly_mgr_entry = "__ovly_load";
mgr_stream = &ovl_mgr_stream;
if (params.ovly_flavour == ovly_soft_icache)
{
ovly_mgr_entry = "__icache_br_handler";
mgr_stream = &icache_mgr_stream;
}
h = elf_link_hash_lookup (elf_hash_table (&link_info),
"__ovly_load", FALSE, FALSE, FALSE);
ovly_mgr_entry, FALSE, FALSE, FALSE);
if (h != NULL
&& (h->root.type == bfd_link_hash_defined
@ -149,7 +197,7 @@ spu_elf_load_ovl_mgr (void)
{
/* User supplied __ovly_load. */
}
else if (ovl_mgr_stream.start == ovl_mgr_stream.end)
else if (mgr_stream->start == mgr_stream->end)
einfo ("%F%P: no built-in overlay manager\n");
else
{
@ -159,7 +207,7 @@ spu_elf_load_ovl_mgr (void)
lang_input_file_is_file_enum,
NULL);
if (!spu_elf_open_builtin_lib (&ovl_is->the_bfd, &ovl_mgr_stream))
if (!spu_elf_open_builtin_lib (&ovl_is->the_bfd, mgr_stream))
einfo ("%X%P: can not open built-in overlay manager: %E\n");
else
{
@ -168,13 +216,38 @@ spu_elf_load_ovl_mgr (void)
if (!load_symbols (ovl_is, NULL))
einfo ("%X%P: can not load built-in overlay manager: %E\n");
/* Map overlay manager sections to output sections. */
/* Map overlay manager sections to output sections.
First try for a matching output section name, if that
fails then try mapping .abc.xyz to .abc, otherwise map
to .text. */
for (in = ovl_is->the_bfd->sections; in != NULL; in = in->next)
if ((in->flags & (SEC_ALLOC | SEC_LOAD))
== (SEC_ALLOC | SEC_LOAD))
{
total += in->size;
spu_place_special_section (in, NULL, ".text");
const char *oname = in->name;
if (strncmp (in->name, ".ovl.init", 9) != 0)
{
total += in->size;
if (!lang_output_section_find (oname))
{
lang_output_section_statement_type *os = NULL;
char *p = strchr (oname + 1, '.');
if (p != NULL)
{
size_t len = p - oname;
p = memcpy (xmalloc (len + 1), oname, len);
p[len] = '\0';
os = lang_output_section_find (p);
free (p);
}
if (os != NULL)
oname = os->name;
else
oname = ".text";
}
}
spu_place_special_section (in, NULL, oname);
}
}
}
@ -338,9 +411,6 @@ gld${EMULATION_NAME}_finish (void)
}
else if (params.auto_overlay)
einfo ("%P: --auto-overlay ignored with zero local store range\n");
if (!spu_elf_build_stubs (&link_info))
einfo ("%F%P: can not build overlay stubs: %E\n");
}
finish_default ();
@ -520,8 +590,11 @@ 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_NUM_REGIONS (OPTION_SPU_OVERLAY_RODATA + 1)
#define OPTION_SPU_FIXED_SPACE (OPTION_SPU_NUM_REGIONS + 1)
#define OPTION_SPU_SOFT_ICACHE (OPTION_SPU_OVERLAY_RODATA + 1)
#define OPTION_SPU_LINE_SIZE (OPTION_SPU_SOFT_ICACHE + 1)
#define OPTION_SPU_NUM_LINES (OPTION_SPU_LINE_SIZE + 1)
#define OPTION_SPU_LRLIVE (OPTION_SPU_NUM_LINES + 1)
#define OPTION_SPU_FIXED_SPACE (OPTION_SPU_LRLIVE + 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)
@ -529,6 +602,10 @@ PARSE_AND_LIST_PROLOGUE='
PARSE_AND_LIST_LONGOPTS='
{ "plugin", no_argument, NULL, OPTION_SPU_PLUGIN },
{ "soft-icache", no_argument, NULL, OPTION_SPU_SOFT_ICACHE },
{ "lrlive-analysis", no_argument, NULL, OPTION_SPU_LRLIVE },
{ "num-lines", required_argument, NULL, OPTION_SPU_NUM_LINES },
{ "line-size", required_argument, NULL, OPTION_SPU_LINE_SIZE },
{ "no-overlays", no_argument, NULL, OPTION_SPU_NO_OVERLAYS },
{ "emit-stub-syms", no_argument, NULL, OPTION_SPU_STUB_SYMS },
{ "extra-overlay-stubs", no_argument, NULL, OPTION_SPU_NON_OVERLAY_STUBS },
@ -538,7 +615,8 @@ 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 },
{ "num-regions", required_argument, NULL, OPTION_SPU_NUM_LINES },
{ "region-size", required_argument, NULL, OPTION_SPU_LINE_SIZE },
{ "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 },
@ -560,11 +638,16 @@ PARSE_AND_LIST_OPTIONS='
--overlay-rodata Place read-only data with associated function\n\
code in overlays.\n\
--num-regions Number of overlay buffers (default 1).\n\
--region-size Size of overlay buffers (default 0, auto).\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\
--extra-stack-space=bytes Space for negative sp access (default 2000) if\n\
--reserved-space not given.\n"
--reserved-space not given.\n\
--soft-icache Generate software icache overlays.\n\
--num-lines Number of soft-icache lines (default 32).\n\
--line-size Size of soft-icache lines (default 1k).\n\
--lrlive-analysis Scan function prologue for lr liveness.\n"
));
'
@ -624,13 +707,47 @@ PARSE_AND_LIST_ARGS_CASES='
params.auto_overlay |= 4;
break;
case OPTION_SPU_NUM_REGIONS:
case OPTION_SPU_SOFT_ICACHE:
params.ovly_flavour = ovly_soft_icache;
if (!num_lines_set)
params.num_lines = 32;
else if ((params.num_lines & -params.num_lines) != params.num_lines)
einfo (_("%P%F: invalid --num-lines/--num-regions `%u'\''\n"),
params.num_lines);
if (!line_size_set)
params.line_size = 1024;
else if ((params.line_size & -params.line_size) != params.line_size)
einfo (_("%P%F: invalid --line-size/--region-size `%u'\''\n"),
params.line_size);
break;
case OPTION_SPU_LRLIVE:
params.lrlive_analysis = 1;
break;
case OPTION_SPU_NUM_LINES:
{
char *end;
params.num_regions = strtoul (optarg, &end, 0);
if (*end == 0)
params.num_lines = strtoul (optarg, &end, 0);
num_lines_set = 1;
if (*end == 0
&& (params.ovly_flavour != ovly_soft_icache
|| (params.num_lines & -params.num_lines) == params.num_lines))
break;
einfo (_("%P%F: invalid --num-regions `%s'\''\n"), optarg);
einfo (_("%P%F: invalid --num-lines/--num-regions `%s'\''\n"), optarg);
}
break;
case OPTION_SPU_LINE_SIZE:
{
char *end;
params.line_size = strtoul (optarg, &end, 0);
line_size_set = 1;
if (*end == 0
&& (params.ovly_flavour != ovly_soft_icache
|| (params.line_size & -params.line_size) == params.line_size))
break;
einfo (_("%P%F: invalid --line-size/--region-size `%s'\''\n"), optarg);
}
break;

View file

@ -1,3 +1,8 @@
2009-01-12 Alan Modra <amodra@bigpond.net.au>
* ld-spu/ovl.d: Allow for absolute branches in stubs.
* ld-spu/ovl2.d: Likewise.
2009-01-11 Jan Kratochvil <jan.kratochvil@redhat.com>
* ld-elf/linkoncerdiff.d, ld-elf/linkoncerdiff1.s,

View file

@ -29,64 +29,64 @@ Disassembly of section \.text:
.* bi \$0
#00000130 <00000000\.ovl_call\.f1_a1>:
#.* brsl \$75,.* <__ovly_load>.*
#.* bra?sl \$75,.* <__ovly_load>.*
#.*00 04 04 00.*
#
#00000138 <00000000\.ovl_call\.f2_a1>:
#.* brsl \$75,.* <__ovly_load>.*
#.* bra?sl \$75,.* <__ovly_load>.*
#.*00 04 04 04.*
#
#00000140 <00000000\.ovl_call\.f1_a2>:
#.* brsl \$75,.* <__ovly_load>.*
#.* bra?sl \$75,.* <__ovly_load>.*
#.*00 08 04 00.*
#
#00000148 <00000000\.ovl_call\.f2_a2>:
#.* brsl \$75,.* <__ovly_load>.*
#.* bra?sl \$75,.* <__ovly_load>.*
#.*00 08 04 24.*
#
#00000150 <00000000\.ovl_call\.f4_a1>:
#.* brsl \$75,.* <__ovly_load>.*
#.* bra?sl \$75,.* <__ovly_load>.*
#.*00 04 04 10.*
#
#00000158 <00000000.ovl_call.14:8>:
#.* brsl \$75,.* <__ovly_load>.*
#.* bra?sl \$75,.* <__ovly_load>.*
#.*00 08 04 34.*
00000130 <00000000\.ovl_call\.f1_a1>:
.* ila \$78,1
.* lnop
.* ila \$79,1024 # 400
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
00000140 <00000000\.ovl_call\.f2_a1>:
.* ila \$78,1
.* lnop
.* ila \$79,1028 # 404
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
00000150 <00000000.ovl_call.f1_a2>:
.* ila \$78,2
.* lnop
.* ila \$79,1024 # 400
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
00000160 <00000000\.ovl_call\.f2_a2>:
.* ila \$78,2
.* lnop
.* ila \$79,1060 # 424
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
00000170 <00000000\.ovl_call\.f4_a1>:
.* ila \$78,1
.* lnop
.* ila \$79,1040 # 410
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
00000180 <00000000.ovl_call.14:8>:
.* ila \$78,2
.* lnop
.* ila \$79,1076 # 434
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
#...
[0-9a-f]+ <__ovly_return>:

View file

@ -24,40 +24,40 @@ Disassembly of section \.text:
\.\.\.
#00000118 <00000000\.ovl_call.f1_a1>:
#.* brsl \$75,.* <__ovly_load>.*
#.* bra?sl \$75,.* <__ovly_load>.*
#.*00 04 04 00.*
#
#00000120 <00000000\.ovl_call.setjmp>:
#.* brsl \$75,.* <__ovly_load>.*
#.* bra?sl \$75,.* <__ovly_load>.*
#.*00 00 01 0c.*
#
#00000128 <_SPUEAR_f1_a2>:
#.* brsl \$75,.* <__ovly_load>.*
#.* bra?sl \$75,.* <__ovly_load>.*
#.*00 08 04 00.*
00000120 <00000000\.ovl_call.f1_a1>:
.* ila \$78,1
.* lnop
.* ila \$79,1040 # 410
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
00000130 <00000000\.ovl_call.setjmp>:
.* ila \$78,0
.* lnop
.* ila \$79,268 # 10c
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
00000140 <00000000\.ovl_call\.13:5>:
.* ila \$78,1
.* lnop
.* ila \$79,1044 # 414
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
00000150 <_SPUEAR_f1_a2>:
.* ila \$78,2
.* lnop
.* ila \$79,1040 # 410
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
#...
Disassembly of section \.ov_a1:
@ -66,7 +66,7 @@ Disassembly of section \.ov_a1:
.* ila \$78,2
.* lnop
.* ila \$79,1044 # 414
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
00000410 <f1_a1>:
.* bi \$0
@ -83,7 +83,7 @@ Disassembly of section \.ov_a2:
.* ila \$78,1
.* lnop
.* ila \$79,1056 # 420
.* br .* <__ovly_load>.*
.* bra? .* <__ovly_load>.*
00000410 <f1_a2>:
.* br .* <longjmp>.*