diff options
Diffstat (limited to 'ld')
-rw-r--r-- | ld/ChangeLog | 18 | ||||
-rw-r--r-- | ld/Makefile.am | 19 | ||||
-rw-r--r-- | ld/Makefile.in | 19 | ||||
-rw-r--r-- | ld/configure.tgt | 2 | ||||
-rw-r--r-- | ld/emulparams/elf32_spu.sh | 19 | ||||
-rw-r--r-- | ld/emultempl/spu_inc.s | 7 | ||||
-rw-r--r-- | ld/emultempl/spu_ovl.S | 275 | ||||
-rw-r--r-- | ld/emultempl/spu_ovl.o | bin | 0 -> 1440 bytes | |||
-rw-r--r-- | ld/emultempl/spuelf.em | 297 | ||||
-rw-r--r-- | ld/ldlang.c | 4 | ||||
-rw-r--r-- | ld/ldlang.h | 2 | ||||
-rw-r--r-- | ld/scripttempl/elf.sc | 2 | ||||
-rw-r--r-- | ld/testsuite/ChangeLog | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/sec64k.exp | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/empty-orphan.exp | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/phdrs.exp | 10 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/phdrs2.exp | 8 | ||||
-rw-r--r-- | ld/testsuite/ld-spu/ovl.d | 117 | ||||
-rw-r--r-- | ld/testsuite/ld-spu/ovl.lnk | 13 | ||||
-rw-r--r-- | ld/testsuite/ld-spu/ovl.s | 82 | ||||
-rw-r--r-- | ld/testsuite/ld-spu/spu.exp | 27 |
21 files changed, 930 insertions, 14 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 15a994a..55ab937 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,21 @@ +2006-10-25 Alan Modra <amodra@bigpond.net.au> + Trevor Smigiel <Trevor_Smigiel@playstation.sony.com> + Yukishige Shibata <shibata@rd.scei.sony.co.jp> + Nobuhisa Fujinami <fnami@rd.scei.sony.co.jp> + Takeaki Fukuoka <fukuoka@rd.scei.sony.co.jp> + + * emulparams/elf32_spu.sh: New file. + * emultempl/spu_inc.s: New file. + * emultempl/spu_ovl.S: New file. + * emultempl/spu_ovl.o: New file. + * emultempl/spuelf.em: New file. + * Makefile.am: Add SPU support. + * configure.tgt: Likewise. + * ldlang.c (load_symbols): Make global. + * ldlang.h (load_symbols): Declare. + * scripttempl/elf.sc (OTHER_BSS_SECTIONS): Add. + * Makefile.in: Regenerate. + 2006-10-24 Ben Elliston <bje@au.ibm.com> * lexsup.c (parse_args): Add a comment noting a fall-through. diff --git a/ld/Makefile.am b/ld/Makefile.am index b07a41c..fd73660 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -134,6 +134,7 @@ ALL_EMULATIONS = \ eavr6.o \ ecoff_i860.o \ ecoff_sparc.o \ + eelf32_spu.o \ ecrisaout.o \ ecriself.o \ ecrislinux.o \ @@ -414,7 +415,8 @@ ALL_64_EMULATIONS = \ ALL_EMUL_EXTRA_OFILES = \ deffilep.o \ pe-dll.o \ - pep-dll.o + pep-dll.o \ + spu_inc.o CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \ ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \ @@ -709,6 +711,17 @@ eelf32_sparc_vxworks.c: $(srcdir)/emulparams/elf32_sparc_vxworks.sh \ $(srcdir)/emultempl/vxworks.em $(ELF_DEPS) \ $(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 \ + $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32_spu "$(tdir_elf32_spu)" +spu_inc.o: $(srcdir)/emultempl/spu_inc.s $(srcdir)/emultempl/spu_ovl.o + $(CC) -c -Wa,-I,$(srcdir)/emultempl -o $@ $< +$(srcdir)/emultempl/spu_ovl.o: @MAINT@ $(srcdir)/emultempl/spu_ovl.S + cpp -DOVLY_IRQ_SAVE $(srcdir)/emultempl/spu_ovl.S spu_ovl.s + if ../gas/as-new --version \ + | grep 'target.*spu' >/dev/null 2>/dev/null; then \ + ../gas/as-new -o $@ spu_ovl.s; \ + fi eelf32_i860.c: $(srcdir)/emulparams/elf32_i860.sh \ $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32_i860 "$(tdir_elf32_i860)" @@ -1772,7 +1785,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 +CLEANFILES = dep.sed DEP DEPA DEP1 DEP2 spu_ovl.s .PHONY: install-html install-html-am install-html-recursive @@ -1851,7 +1864,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 $(man_MANS) +EXTRA_DIST = ldgram.c ldgram.h ldlex.c spu_ovl.o $(man_MANS) diststuff: info $(EXTRA_DIST) all: info ld.1 diff --git a/ld/Makefile.in b/ld/Makefile.in index daed6f8..96f84c2 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -358,6 +358,7 @@ ALL_EMULATIONS = \ eavr6.o \ ecoff_i860.o \ ecoff_sparc.o \ + eelf32_spu.o \ ecrisaout.o \ ecriself.o \ ecrislinux.o \ @@ -638,7 +639,8 @@ ALL_64_EMULATIONS = \ ALL_EMUL_EXTRA_OFILES = \ deffilep.o \ pe-dll.o \ - pep-dll.o + pep-dll.o \ + spu_inc.o CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \ ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \ @@ -684,12 +686,12 @@ 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 +CLEANFILES = dep.sed DEP DEPA DEP1 DEP2 spu_ovl.s 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 $(man_MANS) +EXTRA_DIST = ldgram.c ldgram.h ldlex.c spu_ovl.o $(man_MANS) DISTCLEANFILES = tdirs site.exp site.bak stringify.sed all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -1520,6 +1522,17 @@ eelf32_sparc_vxworks.c: $(srcdir)/emulparams/elf32_sparc_vxworks.sh \ $(srcdir)/emultempl/vxworks.em $(ELF_DEPS) \ $(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 \ + $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32_spu "$(tdir_elf32_spu)" +spu_inc.o: $(srcdir)/emultempl/spu_inc.s $(srcdir)/emultempl/spu_ovl.o + $(CC) -c -Wa,-I,$(srcdir)/emultempl -o $@ $< +$(srcdir)/emultempl/spu_ovl.o: @MAINT@ $(srcdir)/emultempl/spu_ovl.S + cpp -DOVLY_IRQ_SAVE $(srcdir)/emultempl/spu_ovl.S spu_ovl.s + if ../gas/as-new --version \ + | grep 'target.*spu' >/dev/null 2>/dev/null; then \ + ../gas/as-new -o $@ spu_ovl.s; \ + fi eelf32_i860.c: $(srcdir)/emulparams/elf32_i860.sh \ $(ELF_GEN_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32_i860 "$(tdir_elf32_i860)" diff --git a/ld/configure.tgt b/ld/configure.tgt index 5dfec86..c2df86f 100644 --- a/ld/configure.tgt +++ b/ld/configure.tgt @@ -548,6 +548,8 @@ sparc*-*-solaris2*) targ_emul=elf32_sparc ;; sparc*-wrs-vxworks*) targ_emul=sparcaout ;; sparc*-*-rtems*) targ_emul=elf32_sparc ;; +spu-*-elf*) targ_emul=elf32_spu + targ_extra_ofiles="spu_inc.o" ;; tic30-*-*aout*) targ_emul=tic30aout ;; tic30-*-*coff*) targ_emul=tic30coff ;; tic4x-*-* | c4x-*-*) targ_emul=tic4xcoff ; targ_extra_emuls="tic3xcoff tic3xcoff_onchip" ;; diff --git a/ld/emulparams/elf32_spu.sh b/ld/emulparams/elf32_spu.sh new file mode 100644 index 0000000..bfeabb8 --- /dev/null +++ b/ld/emulparams/elf32_spu.sh @@ -0,0 +1,19 @@ +SCRIPT_NAME=elf +TEMPLATE_NAME=elf32 +EXTRA_EM_FILE=spuelf +OUTPUT_FORMAT="elf32-spu" +ARCH=spu +MACHINE= +ALIGNMENT=16 +TEXT_START_ADDR=0 +INITIAL_READONLY_SECTIONS='.interrupt : { KEEP(*(.interrupt)) }' +if test -z "${CREATE_SHLIB}"; then + INITIAL_READONLY_SECTIONS="${INITIAL_READONLY_SECTIONS} + .interp ${RELOCATING-0} : { *(.interp) }" +fi +OTHER_END_SYMBOLS='PROVIDE (__stack = 0x3fff0);' +NO_SMALL_DATA=true +EMBEDDED=true +MAXPAGESIZE=0x80 +DATA_ADDR="ALIGN(${MAXPAGESIZE})" +OTHER_BSS_SECTIONS=".toe ALIGN(128) : { *(.toe) } = 0" diff --git a/ld/emultempl/spu_inc.s b/ld/emultempl/spu_inc.s new file mode 100644 index 0000000..243bd10 --- /dev/null +++ b/ld/emultempl/spu_inc.s @@ -0,0 +1,7 @@ + .text + .globl _binary_builtin_ovl_mgr_start + .globl _binary_builtin_ovl_mgr_end + +_binary_builtin_ovl_mgr_start: + .incbin "spu_ovl.o" +_binary_builtin_ovl_mgr_end: diff --git a/ld/emultempl/spu_ovl.S b/ld/emultempl/spu_ovl.S new file mode 100644 index 0000000..75d0470 --- /dev/null +++ b/ld/emultempl/spu_ovl.S @@ -0,0 +1,275 @@ +/* Overlay manager for SPU. + + Copyright 2006 Free Software Foundation, Inc. + + This file is part of GLD, the Gnu Linker. + + GLD is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + GLD is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GLD; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/** + * MFC DMA defn's. + */ +#define MFC_GET_CMD 0x40 +#define MFC_MAX_DMA_SIZE 0x4000 +#define MFC_TAG_UPDATE_ALL 2 +#define MFC_TAG_ID 0 + + +/** + * Temporary register allocations. + * These are saved/restored here. + */ +#define tab $75 +#define cgbits $75 +#define add64 $75 +#define ealo $75 +#define newmask $75 +#define tagstat $75 +#define bchn $75 +#define rv1 $75 + +#define off $76 +#define off64 $76 +#define maxsize $76 +#define oldmask $76 +#define sz $76 +#define lnkr $76 +#define rv2 $76 + +#define cur $77 +#define cmp $77 +#define buf $77 +#define genwi $77 +#define tagid $77 +#define cmd $77 +#define rv3 $77 + +#define cgshuf $78 + +#define vma $6 + +#define map $7 +#define size $7 +#define cmp2 $7 + +#define ea64 $8 +#define retval $8 + +#ifdef OVLY_IRQ_SAVE +#define irqtmp $8 +#define irq_stat $9 +#endif + + .extern _ovly_table + .extern _ovly_buf_table + + .text + .align 4 +__rv_pattern: + .word 0x00010203, 0x1c1d1e1f, 0x00010203, 0x10111213 +__cg_pattern: + .word 0x04050607, 0x80808080, 0x80808080, 0x80808080 + +/** + * __ovly_return - stub for returning from overlay functions. + * + * inputs: + * $lr link register + * + * outputs: + * $78 old partition number, to be reloaded + * $79 return address in old partion number + */ + .global __ovly_return + .type __ovly_return, @function + + .word 0 +__ovly_return: + shlqbyi $78, $lr, 4 + shlqbyi $79, $lr, 8 + biz $78, $79 + +/** + * __ovly_load - copy an overlay partion to local store. + * + * inputs: + * $78 partition number to be loaded. + * $79 branch target in new partition. + * $lr link register, containing return addr. + * + * outputs: + * $lr new link register, returning through __ovly_return. + * + * Copy a new overlay partition into local store, or return + * immediately if the partition is already resident. + */ + .global __ovly_load + .type __ovly_load, @function + +__ovly_load: +/* Save temporary registers to stack. */ + stqd $6, -16($sp) + stqd $7, -32($sp) + stqd $8, -48($sp) + +#ifdef OVLY_IRQ_SAVE +/* Save irq state, then disable interrupts. */ + stqd $9, -64($sp) + ila irqtmp, __ovly_irq_save + rdch irq_stat, $SPU_RdMachStat + bid irqtmp +__ovly_irq_save: +#endif + +/* Set branch hint to overlay target. */ + hbr __ovly_load_ret, $79 + +/* Get caller's overlay index by back chaining through stack frames. + * Loop until end of stack (back chain all-zeros) or + * encountered a link register we set here. */ + lqd bchn, 0($sp) + ila retval, __ovly_return + +__ovly_backchain_loop: + lqd lnkr, 16(bchn) + lqd bchn, 0(bchn) + ceq cmp, lnkr, retval + ceqi cmp2, bchn, 0 + or cmp, cmp, cmp2 + brz cmp, __ovly_backchain_loop + +/* If we reached the zero back-chain, then lnkr is bogus. Clear the + * part of lnkr that we use later (slot 3). */ + rotqbyi cmp2, cmp2, 4 + andc lnkr, lnkr, cmp2 + +/* Set lr = {__ovly_return, prev ovl ndx, caller return adr, callee ovl ndx}. */ + lqd rv1, (__rv_pattern-__ovly_return+4)(retval) + shufb rv2, retval, lnkr, rv1 + shufb rv3, $lr, $78, rv1 + fsmbi rv1, 0xff + selb $lr, rv2, rv3, rv1 + +/* Branch to $79 if non-overlay */ + brz $78, __ovly_load_restore + +/* Load values from _ovly_table[$78]. + * extern struct { + * u32 vma; + * u32 size; + * u32 file_offset; + * u32 buf; + * } _ovly_table[]; + */ + shli off, $78, 4 + ila tab, _ovly_table - 16 + lqx vma, tab, off + rotqbyi buf, vma, 12 + +/* Load values from _ovly_buf_table[buf]. + * extern struct { + * u32 mapped; + * } _ovly_buf_table[]; + */ + ila tab, _ovly_buf_table + ai off, buf, -1 + shli off, off, 2 + lqx map, tab, off + rotqby cur, map, off + +/* Branch to $79 now if overlay is already mapped. */ + ceq cmp, $78, cur + brnz cmp, __ovly_load_restore + +/* Set _ovly_buf_table[buf].mapped = $78. */ + cwx genwi, tab, off + shufb map, $78, map, genwi + stqx map, tab, off + +/* A new partition needs to be loaded. Prepare for DMA loop. + * _EAR_ is the 64b base EA, filled in at run time by the + * loader, and indicating the value for SPU executable image start. + */ + lqd cgshuf, (__cg_pattern-__ovly_return+4)(retval) + rotqbyi size, vma, 4 + rotqbyi sz, vma, 8 + lqa ea64, _EAR_ + +__ovly_xfer_loop: +/* 64b add to compute next ea64. */ + rotqmbyi off64, sz, -4 + cg cgbits, ea64, off64 + shufb add64, cgbits, cgbits, cgshuf + addx add64, ea64, off64 + ori ea64, add64, 0 + +/* Setup DMA parameters, then issue DMA request. */ + rotqbyi ealo, add64, 4 + ila maxsize, MFC_MAX_DMA_SIZE + cgt cmp, size, maxsize + selb sz, size, maxsize, cmp + ila tagid, MFC_TAG_ID + wrch $MFC_LSA, vma + wrch $MFC_EAH, ea64 + wrch $MFC_EAL, ealo + wrch $MFC_Size, sz + wrch $MFC_TagId, tagid + ila cmd, MFC_GET_CMD + wrch $MFC_Cmd, cmd + +/* Increment vma, decrement size, branch back as needed. */ + a vma, vma, sz + sf size, sz, size + brnz size, __ovly_xfer_loop + +/* Save app's tagmask, wait for DMA complete, restore mask. */ + rdch oldmask, $MFC_RdTagMask +#if MFC_TAG_ID < 16 + ilh newmask, 1 << MFC_TAG_ID +#else + ilhu newmask, 1 << (MFC_TAG_ID - 16) +#endif + wrch $MFC_WrTagMask, newmask + ila tagstat, MFC_TAG_UPDATE_ALL + wrch $MFC_WrTagUpdate, tagstat + rdch tagstat, $MFC_RdTagStat + sync + wrch $MFC_WrTagMask, oldmask + + .global _ovly_debug_event + .type _ovly_debug_event, @function +_ovly_debug_event: +/* GDB inserts debugger trap here. */ + nop + +__ovly_load_restore: +#ifdef OVLY_IRQ_SAVE +/* Conditionally re-enable interrupts. */ + andi irq_stat, irq_stat, 1 + ila irqtmp, __ovly_irq_restore + binze irq_stat, irqtmp +__ovly_irq_restore: + lqd $9, -64($sp) +#endif + +/* Restore saved registers. */ + lqd $8, -48($sp) + lqd $7, -32($sp) + lqd $6, -16($sp) + +__ovly_load_ret: +/* Branch to target address. */ + bi $79 diff --git a/ld/emultempl/spu_ovl.o b/ld/emultempl/spu_ovl.o Binary files differnew file mode 100644 index 0000000..1d48c00 --- /dev/null +++ b/ld/emultempl/spu_ovl.o diff --git a/ld/emultempl/spuelf.em b/ld/emultempl/spuelf.em new file mode 100644 index 0000000..de6a914 --- /dev/null +++ b/ld/emultempl/spuelf.em @@ -0,0 +1,297 @@ +# This shell script emits a C file. -*- C -*- +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GLD, the Gnu Linker. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. +# + +# This file is sourced from elf32.em, and defines extra spu specific +# features. +# +cat >>e${EMULATION_NAME}.c <<EOF +#include "ldctor.h" +#include "elf32-spu.h" + +/* Non-zero if no overlay processing should be done. */ +static int no_overlays = 0; + +/* Non-zero if we want stubs on all calls out of overlay regions. */ +static int non_overlay_stubs = 0; + +/* Whether to emit symbols for stubs. */ +static int emit_stub_syms = 0; + +/* Range of valid addresses for loadable sections. */ +static bfd_vma local_store_lo = 0; +static bfd_vma local_store_hi = 0x3ffff; + +extern void *_binary_builtin_ovl_mgr_start; +extern void *_binary_builtin_ovl_mgr_end; + +static const struct _ovl_stream ovl_mgr_stream = { + &_binary_builtin_ovl_mgr_start, + &_binary_builtin_ovl_mgr_end +}; + +static asection *toe = NULL; + + +static int +is_spu_target (void) +{ + extern const bfd_target bfd_elf32_spu_vec; + + return link_info.hash->creator == &bfd_elf32_spu_vec; +} + +/* Create our note section. */ + +static void +spu_after_open (void) +{ + if (is_spu_target () + && !link_info.relocatable + && link_info.input_bfds != NULL + && !spu_elf_create_sections (output_bfd, &link_info)) + einfo ("%X%P: can not create note section: %E\n"); + + gld${EMULATION_NAME}_after_open (); +} + +/* Add section S at the end of output section OUTPUT_NAME. + + Really, we should be duplicating ldlang.c map_input_to_output_sections + logic here, ie. using the linker script to find where the section + goes. That's rather a lot of code, and we don't want to run + map_input_to_output_sections again because most sections are already + mapped. So cheat, and put the section in a fixed place, ignoring any + attempt via a linker script to put .stub, .ovtab, and built-in + overlay manager code somewhere else. */ + +static void +spu_place_special_section (asection *s, const char *output_name) +{ + lang_output_section_statement_type *os; + + os = lang_output_section_find (output_name); + if (os == NULL) + { + const char *save = s->name; + s->name = output_name; + gld${EMULATION_NAME}_place_orphan (s); + s->name = save; + } + else + lang_add_section (&os->children, s, os); + + s->output_section->size += s->size; +} + +/* Load built-in overlay manager, and tweak overlay section alignment. */ + +static void +spu_elf_load_ovl_mgr (void) +{ + lang_output_section_statement_type *os; + struct elf_link_hash_entry *h; + + h = elf_link_hash_lookup (elf_hash_table (&link_info), + "__ovly_load", FALSE, FALSE, FALSE); + + if (h != NULL + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && h->def_regular) + { + /* User supplied __ovly_load. */ + } + else + { + lang_input_statement_type *ovl_is; + + ovl_is = lang_add_input_file ("builtin ovl_mgr", + lang_input_file_is_file_enum, + NULL); + + if (!spu_elf_open_builtin_lib (&ovl_is->the_bfd, &ovl_mgr_stream)) + einfo ("%X%P: can not open built-in overlay manager: %E\n"); + else + { + asection *in; + + 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. */ + for (in = ovl_is->the_bfd->sections; in != NULL; in = in->next) + if ((in->flags & (SEC_ALLOC | SEC_LOAD)) + == (SEC_ALLOC | SEC_LOAD)) + spu_place_special_section (in, ".text"); + } + } + + /* Ensure alignment of overlay sections is sufficient. */ + for (os = &lang_output_section_statement.head->output_section_statement; + os != NULL; + os = os->next) + if (os->bfd_section != NULL + && spu_elf_section_data (os->bfd_section) != NULL + && spu_elf_section_data (os->bfd_section)->ovl_index != 0) + { + if (os->bfd_section->alignment_power < 4) + os->bfd_section->alignment_power = 4; + + /* Also ensure size rounds up. */ + os->block_value = 16; + } +} + +/* Go find if we need to do anything special for overlays. */ + +static void +spu_before_allocation (void) +{ + if (is_spu_target () + && !link_info.relocatable + && !no_overlays) + { + /* Size the sections. This is premature, but we need to know the + rough layout so that overlays can be found. */ + expld.phase = lang_mark_phase_enum; + expld.dataseg.phase = exp_dataseg_none; + one_lang_size_sections_pass (NULL, TRUE); + + /* Find overlays by inspecting section vmas. */ + if (spu_elf_find_overlays (output_bfd, &link_info)) + { + asection *stub, *ovtab; + + if (!spu_elf_size_stubs (output_bfd, &link_info, non_overlay_stubs, + &stub, &ovtab, &toe)) + einfo ("%X%P: can not size overlay stubs: %E\n"); + + if (stub != NULL) + { + spu_place_special_section (stub, ".text"); + spu_place_special_section (ovtab, ".data"); + spu_place_special_section (toe, ".toe"); + + spu_elf_load_ovl_mgr (); + } + } + + /* We must not cache anything from the preliminary sizing. */ + lang_reset_memory_regions (); + } + + gld${EMULATION_NAME}_before_allocation (); +} + +/* Final emulation specific call. */ + +static void +gld${EMULATION_NAME}_finish (void) +{ + int need_laying_out; + + need_laying_out = bfd_elf_discard_info (output_bfd, &link_info); + + gld${EMULATION_NAME}_map_segments (need_laying_out); + + if (is_spu_target () && local_store_lo < local_store_hi) + { + asection *s; + + s = spu_elf_check_vma (output_bfd, local_store_lo, local_store_hi); + if (s != NULL) + einfo ("%X%P: %A exceeds local store range\n", s); + } + + if (toe != NULL + && !spu_elf_build_stubs (&link_info, + emit_stub_syms || link_info.emitrelocations, + toe)) + einfo ("%X%P: can not build overlay stubs: %E\n"); + + finish_default (); +} + +EOF + +# Define some shell vars to insert bits of code into the standard elf +# parse_args and list_options functions. +# +PARSE_AND_LIST_PROLOGUE=' +#define OPTION_SPU_PLUGIN 301 +#define OPTION_SPU_NO_OVERLAYS (OPTION_SPU_PLUGIN + 1) +#define OPTION_SPU_STUB_SYMS (OPTION_SPU_NO_OVERLAYS + 1) +#define OPTION_SPU_NON_OVERLAY_STUBS (OPTION_SPU_STUB_SYMS + 1) +#define OPTION_SPU_LOCAL_STORE (OPTION_SPU_NON_OVERLAY_STUBS + 1) +' + +PARSE_AND_LIST_LONGOPTS=' + { "plugin", no_argument, NULL, OPTION_SPU_PLUGIN }, + { "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 }, + { "local-store", required_argument, NULL, OPTION_SPU_LOCAL_STORE }, +' + +PARSE_AND_LIST_OPTIONS=' + fprintf (file, _("\ + --plugin Make SPU plugin.\n\ + --no-overlays No overlay handling.\n\ + --emit-stub-syms Add symbols on overlay call stubs.\n\ + --extra-overlay-stubs Add stubs on all calls out of overlay regions.\n\ + --local-store=lo:hi Valid address range.\n" + )); +' + +PARSE_AND_LIST_ARGS_CASES=' + case OPTION_SPU_PLUGIN: + spu_elf_plugin (1); + break; + + case OPTION_SPU_NO_OVERLAYS: + no_overlays = 1; + break; + + case OPTION_SPU_STUB_SYMS: + emit_stub_syms = 1; + break; + + case OPTION_SPU_NON_OVERLAY_STUBS: + non_overlay_stubs = 1; + break; + + case OPTION_SPU_LOCAL_STORE: + { + char *end; + local_store_lo = strtoul (optarg, &end, 0); + if (*end == '\'':'\'') + { + local_store_hi = strtoul (end + 1, &end, 0); + if (*end == 0) + break; + } + einfo (_("%P%F: invalid --local-store address range `%s'\''\n"), optarg); + } + break; +' + +LDEMUL_AFTER_OPEN=spu_after_open +LDEMUL_BEFORE_ALLOCATION=spu_before_allocation +LDEMUL_FINISH=gld${EMULATION_NAME}_finish diff --git a/ld/ldlang.c b/ld/ldlang.c index 2c9426e..391fc1f 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -68,8 +68,6 @@ static struct bfd_hash_table lang_definedness_table; static void exp_init_os (etree_type *); static void init_map_userdata (bfd *, asection *, void *); static lang_input_statement_type *lookup_name (const char *); -static bfd_boolean load_symbols (lang_input_statement_type *, - lang_statement_list_type *); static struct bfd_hash_entry *lang_definedness_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); static void insert_undefined (const char *); @@ -2387,7 +2385,7 @@ check_excluded_libs (bfd *abfd) /* Get the symbols for an input file. */ -static bfd_boolean +bfd_boolean load_symbols (lang_input_statement_type *entry, lang_statement_list_type *place) { diff --git a/ld/ldlang.h b/ld/ldlang.h index 99b786d..08d3f30 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -619,5 +619,7 @@ extern void lang_update_definedness (const char *, struct bfd_link_hash_entry *); extern void add_excluded_libs (const char *); +extern bfd_boolean load_symbols + (lang_input_statement_type *, lang_statement_list_type *); #endif diff --git a/ld/scripttempl/elf.sc b/ld/scripttempl/elf.sc index 7ee4c1c..9a2d8b8 100644 --- a/ld/scripttempl/elf.sc +++ b/ld/scripttempl/elf.sc @@ -14,6 +14,7 @@ # (e.g., .PARISC.global) # OTHER_RELRO_SECTIONS - other than .data.rel.ro ... # (e.g. PPC32 .fixup, .got[12]) +# OTHER_BSS_SECTIONS - other than .bss .sbss ... # OTHER_SECTIONS - at the end # EXECUTABLE_SYMBOLS - symbols that must be defined for an # executable (e.g., _DYNAMIC_LINK) @@ -452,6 +453,7 @@ cat <<EOF pad the .data section. */ ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);} } + ${OTHER_BSS_SECTIONS} ${RELOCATING+${OTHER_BSS_END_SYMBOLS}} ${RELOCATING+. = ALIGN(${ALIGNMENT});} ${LARGE_SECTIONS} diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 909f6ee..8ed5b46 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2006-10-25 Alan Modra <amodra@bigpond.net.au> + + * ld-spu/ovl.d: New file. + * ld-spu/ovl.lnk: New file. + * ld-spu/ovl.s: New file. + * ld-spu/spu.exp: New file. + * ld-elf/sec64k.exp: Tweak ld options for SPU. + * ld-scripts/empty-orphan.exp: Likewise. + * ld-scripts/phdrs.exp: Likewise. + * ld-scripts/phdrs2.exp: Likewise. + 2006-10-24 Alan Modra <amodra@bigpond.net.au> * ld-powerpc/plt1.s: New. diff --git a/ld/testsuite/ld-elf/sec64k.exp b/ld/testsuite/ld-elf/sec64k.exp index 784ed71..50abcc1 100644 --- a/ld/testsuite/ld-elf/sec64k.exp +++ b/ld/testsuite/ld-elf/sec64k.exp @@ -127,7 +127,11 @@ if [catch { set ofd [open "tmpdir/$test2.d" w] } x] { return } foreach sfile $sfiles { puts $ofd "#source: $sfile" } -puts $ofd "#ld:" +if { [istarget spu*-*-*] } { + puts $ofd "#ld: --local-store 0:0" +} else { + puts $ofd "#ld:" +} puts $ofd "#readelf: -W -Ss" puts $ofd "There are 660.. section headers.*:" puts $ofd "#..." diff --git a/ld/testsuite/ld-scripts/empty-orphan.exp b/ld/testsuite/ld-scripts/empty-orphan.exp index fa845e0..847e8f4 100644 --- a/ld/testsuite/ld-scripts/empty-orphan.exp +++ b/ld/testsuite/ld-scripts/empty-orphan.exp @@ -1,6 +1,6 @@ # Make sure orphan sections do not lead to huge output files. # By David Heine, Tensilica, Inc. -# Copyright 2005 +# Copyright 2005, 2006 # Free Software Foundation, Inc. # # This file is free software; you can redistribute it and/or modify @@ -22,6 +22,10 @@ if ![is_elf_format] { return } +if { [istarget spu*-*-*] } { + set LDFLAGS "--local-store 0:0" +} + set testname "empty-orphan" run_dump_test empty-orphan diff --git a/ld/testsuite/ld-scripts/phdrs.exp b/ld/testsuite/ld-scripts/phdrs.exp index 67af6ad..7dca555 100644 --- a/ld/testsuite/ld-scripts/phdrs.exp +++ b/ld/testsuite/ld-scripts/phdrs.exp @@ -1,6 +1,6 @@ # Test PHDRS in a linker script. # By Ian Lance Taylor, Cygnus Support. -# Copyright 1999, 2000, 2001, 2002, 2003 +# Copyright 1999, 2000, 2001, 2002, 2003, 2006 # Free Software Foundation, Inc. # # This file is free software; you can redistribute it and/or modify @@ -26,6 +26,11 @@ if ![is_elf_format] { set testname "PHDRS" +set ldopt "" +if { [istarget spu*-*-*] } { + set ldopt "--local-store 0:0" +} + if ![ld_assemble $as $srcdir/$subdir/phdrs.s tmpdir/phdrs.o] { unresolved $testname return @@ -40,7 +45,8 @@ if [is_elf64 tmpdir/phdrs.o] { ".*Program Header:.*PHDR *off *0x00*40 *vaddr *0x00*800040 *paddr *0x00*800040.*filesz *0x0\[0-9a-f\]* *memsz *0x0\[0-9a-f\]* flags r--.*LOAD *off *0x00* *vaddr *0x00*800000 *paddr *0x00*800000.*filesz *0x00*\[0-9a-f\]* *memsz *0x0\[0-9a-f\]* *flags r-x.*LOAD *off *0x0\[0-9a-f\]* *vaddr *0x00*80*\[0-9a-f\]* *paddr *0x00*80*\[0-9a-f\]*.*filesz *0x0\[0-9a-f\]* *memsz *0x0\[0-9a-f\]* *flags *rw-.*" } -if ![ld_simple_link $ld tmpdir/phdrs "-T $srcdir/$subdir/phdrs.t tmpdir/phdrs.o"] { +set ldopt "$ldopt -T $srcdir/$subdir/phdrs.t tmpdir/phdrs.o" +if ![ld_simple_link $ld tmpdir/phdrs $ldopt] { fail $testname } else { if {[which $objdump] == 0} { diff --git a/ld/testsuite/ld-scripts/phdrs2.exp b/ld/testsuite/ld-scripts/phdrs2.exp index 5fbc2fa..8c41ffe 100644 --- a/ld/testsuite/ld-scripts/phdrs2.exp +++ b/ld/testsuite/ld-scripts/phdrs2.exp @@ -36,6 +36,11 @@ if { [istarget *-*-linux*aout*] \ set testname "PHDRS2" +set ldopt "" +if { [istarget spu*-*-*] } { + set ldopt "--local-store 0:0" +} + if ![ld_assemble $as $srcdir/$subdir/phdrs2.s tmpdir/phdrs2.o] { unresolved $testname return @@ -44,7 +49,8 @@ if ![ld_assemble $as $srcdir/$subdir/phdrs2.s tmpdir/phdrs2.o] { set phdrs_regexp \ ".*Program Header:.*LOAD *off *0x00\[0-9a-f\]* *vaddr *0x00*800000 *paddr *0x00*800000.*filesz *0x0\[0-9a-f\]* *memsz *0x0\[0-9a-f\]*.*LOAD *off *0x00\[0-9a-f\]* *vaddr *0x00*800004 *paddr *0x00*800004.*filesz *0x00*\[0-9a-f\]* *memsz *0x0\[0-9a-f\]* *flags rw.*" -if ![ld_simple_link $ld tmpdir/phdrs2 "-T $srcdir/$subdir/phdrs2.t tmpdir/phdrs2.o"] { +set ldopt "$ldopt -T $srcdir/$subdir/phdrs2.t tmpdir/phdrs2.o" +if ![ld_simple_link $ld tmpdir/phdrs2 $ldopt] { fail $testname } else { if {[which $objdump] == 0} { diff --git a/ld/testsuite/ld-spu/ovl.d b/ld/testsuite/ld-spu/ovl.d new file mode 100644 index 0000000..2edf985 --- /dev/null +++ b/ld/testsuite/ld-spu/ovl.d @@ -0,0 +1,117 @@ +#source: ovl.s +#ld: -N -T ovl.lnk +#objdump: -D + +.*elf32-spu + +Disassembly of section \.text: + +00000100 <_start>: + 100: 1c f8 00 81 ai \$1,\$1,-32 + 104: 48 20 00 00 xor \$0,\$0,\$0 + 108: 24 00 00 80 stqd \$0,0\(\$1\) + 10c: 24 00 40 80 stqd \$0,16\(\$1\) + 110: 33 00 04 00 brsl \$0,130 <f0\+0x4> # 130 + 114: 33 00 04 80 brsl \$0,138 <f0\+0xc> # 138 + 118: 33 00 07 00 brsl \$0,150 <f0\+0x24> # 150 + 11c: 42 00 ac 09 ila \$9,344 # 158 + 120: 35 20 04 80 bisl \$0,\$9 + 124: 1c 08 00 81 ai \$1,\$1,32 # 20 + 128: 32 7f fb 00 br 100 <_start> # 100 + +0000012c <f0>: + 12c: 35 00 00 00 bi \$0 + 130: 42 02 00 4f ila \$79,1024 # 400 + 134: 32 00 02 80 br 148 <f0\+0x1c> # 148 + 138: 42 02 02 4f ila \$79,1028 # 404 + 13c: 32 00 01 80 br 148 <f0\+0x1c> # 148 + 140: 42 02 08 4f ila \$79,1040 # 410 + 144: 40 20 00 00 nop \$0 + 148: 42 00 00 ce ila \$78,1 + 14c: 32 00 0a 80 br 1a0 <__ovly_load> # 1a0 + 150: 42 02 00 4f ila \$79,1024 # 400 + 154: 32 00 02 80 br 168 <f0\+0x3c> # 168 + 158: 42 02 12 4f ila \$79,1060 # 424 + 15c: 32 00 01 80 br 168 <f0\+0x3c> # 168 + 160: 42 02 1a 4f ila \$79,1076 # 434 + 164: 40 20 00 00 nop \$0 + 168: 42 00 01 4e ila \$78,2 + 16c: 32 00 06 80 br 1a0 <__ovly_load> # 1a0 +#... +[0-9a-f]+ <__ovly_return>: +[0-9a-f ]+: 3f e1 00 4e shlqbyi \$78,\$0,4 +[0-9a-f ]+: 3f e2 00 4f shlqbyi \$79,\$0,8 +[0-9a-f ]+: 25 00 27 ce biz \$78,\$79 + +[0-9a-f]+ <__ovly_load>: +#... +[0-9a-f]+ <_ovly_debug_event>: +#... +Disassembly of section \.ov_a1: + +00000400 <f1_a1>: + 400: 32 00 01 80 br 40c <f3_a1> # 40c + +00000404 <f2_a1>: + 404: 42 00 a0 03 ila \$3,320 # 140 + 408: 35 00 00 00 bi \$0 + +0000040c <f3_a1>: + 40c: 35 00 00 00 bi \$0 + +00000410 <f4_a1>: + 410: 35 00 00 00 bi \$0 + \.\.\. +Disassembly of section \.ov_a2: + +00000400 <f1_a2>: + 400: 24 00 40 80 stqd \$0,16\(\$1\) + 404: 24 ff 80 81 stqd \$1,-32\(\$1\) + 408: 1c f8 00 81 ai \$1,\$1,-32 + 40c: 33 7f a4 00 brsl \$0,12c <f0> # 12c + 410: 33 7f a4 00 brsl \$0,130 <f0\+0x4> # 130 + 414: 33 00 03 80 brsl \$0,430 <f3_a2> # 430 + 418: 34 00 c0 80 lqd \$0,48\(\$1\) # 30 + 41c: 1c 08 00 81 ai \$1,\$1,32 # 20 + 420: 35 00 00 00 bi \$0 + +00000424 <f2_a2>: + 424: 41 00 00 03 ilhu \$3,0 + 428: 60 80 b0 03 iohl \$3,352 # 160 + 42c: 35 00 00 00 bi \$0 + +00000430 <f3_a2>: + 430: 35 00 00 00 bi \$0 + +00000434 <f4_a2>: + 434: 35 00 00 00 bi \$0 + \.\.\. +Disassembly of section .data: + +00000440 <_ovly_table>: + 440: 00 00 04 00 .* + 444: 00 00 00 20 .* + 448: 00 00 02 e0 .* + 44c: 00 00 00 01 .* + 450: 00 00 04 00 .* + 454: 00 00 00 40 .* + 458: 00 00 03 00 .* + 45c: 00 00 00 01 .* + +00000460 <_ovly_buf_table>: + 460: 00 00 00 00 .* +Disassembly of section \.toe: + +00000470 <_EAR_>: + \.\.\. +Disassembly of section \.note\.spu_name: + +.* <\.note\.spu_name>: +.*: 00 00 00 08 .* +.*: 00 00 00 0c .* +.*: 00 00 00 01 .* +.*: 53 50 55 4e .* +.*: 41 4d 45 00 .* +.*: 74 6d 70 64 .* +.*: 69 72 2f 64 .* +.*: 75 6d 70 00 .* diff --git a/ld/testsuite/ld-spu/ovl.lnk b/ld/testsuite/ld-spu/ovl.lnk new file mode 100644 index 0000000..84701d4 --- /dev/null +++ b/ld/testsuite/ld-spu/ovl.lnk @@ -0,0 +1,13 @@ +SECTIONS +{ + . = SIZEOF_HEADERS; + .text : { *(.text) *(.stub) } + + . = 0x400; + .ov_a1 : { *(.ov_a1) } + .ov_a2 ADDR (.ov_a1) : { *(.ov_a2) } + . = ADDR (.ov_a1) + MAX (SIZEOF (.ov_a1), SIZEOF (.ov_a2)); + + .data : { *(.data) *(.ovtab) } + .bss : { *(.bss) } +} diff --git a/ld/testsuite/ld-spu/ovl.s b/ld/testsuite/ld-spu/ovl.s new file mode 100644 index 0000000..c4bc68c --- /dev/null +++ b/ld/testsuite/ld-spu/ovl.s @@ -0,0 +1,82 @@ + .text + .p2align 2 + .globl _start +_start: + ai sp,sp,-32 + xor lr,lr,lr + stqd lr,0(sp) + stqd lr,16(sp) + brsl lr,f1_a1 + brsl lr,f2_a1 + brsl lr,f1_a2 + ila 9,f2_a2 + bisl lr,9 + ai sp,sp,32 + br _start + + .type f0,@function +f0: + bi lr + .size f0,.-f0 + + .section .ov_a1,"ax",@progbits + .p2align 2 + .global f1_a1 + .type f1_a1,@function +f1_a1: + br f3_a1 + .size f1_a1,.-f1_a1 + + .global f2_a1 + .type f2_a1,@function +f2_a1: + ila 3,f4_a1 + bi lr + .size f2_a1,.-f2_a1 + + .global f3_a1 + .type f3_a1,@function +f3_a1: + bi lr + .size f3_a1,.-f3_a1 + + .global f4_a1 + .type f4_a1,@function +f4_a1: + bi lr + .size f4_a1,.-f4_a1 + + + .section .ov_a2,"ax",@progbits + .p2align 2 + .global f1_a2 + .type f1_a2,@function +f1_a2: + stqd lr,16(sp) + stqd sp,-32(sp) + ai sp,sp,-32 + brsl lr,f0 + brsl lr,f1_a1 + brsl lr,f3_a2 + lqd lr,48(sp) + ai sp,sp,32 + bi lr + .size f1_a2,.-f1_a2 + + .global f2_a2 + .type f2_a2,@function +f2_a2: + ilhu 3,f4_a2@h + iohl 3,f4_a2@l + bi lr + .size f2_a2,.-f2_a2 + + .type f3_a2,@function +f3_a2: + bi lr + .size f3_a2,.-f3_a2 + + .type f4_a2,@function +f4_a2: + bi lr + .size f4_a2,.-f4_a2 diff --git a/ld/testsuite/ld-spu/spu.exp b/ld/testsuite/ld-spu/spu.exp new file mode 100644 index 0000000..e538f59 --- /dev/null +++ b/ld/testsuite/ld-spu/spu.exp @@ -0,0 +1,27 @@ +# Expect script for ld-spu tests +# Copyright (C) 2006 Free Software Foundation +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# 51 Franklin Street - Fifth Floor, Boston, MA 02111-1307, USA. +# + +if { ![istarget "spu-*-*"] } { + return +} + +set rd_test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]] +foreach sputest $rd_test_list { + verbose [file rootname $sputest] + run_dump_test [file rootname $sputest] +} |