aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog18
-rw-r--r--ld/Makefile.am19
-rw-r--r--ld/Makefile.in19
-rw-r--r--ld/configure.tgt2
-rw-r--r--ld/emulparams/elf32_spu.sh19
-rw-r--r--ld/emultempl/spu_inc.s7
-rw-r--r--ld/emultempl/spu_ovl.S275
-rw-r--r--ld/emultempl/spu_ovl.obin0 -> 1440 bytes
-rw-r--r--ld/emultempl/spuelf.em297
-rw-r--r--ld/ldlang.c4
-rw-r--r--ld/ldlang.h2
-rw-r--r--ld/scripttempl/elf.sc2
-rw-r--r--ld/testsuite/ChangeLog11
-rw-r--r--ld/testsuite/ld-elf/sec64k.exp6
-rw-r--r--ld/testsuite/ld-scripts/empty-orphan.exp6
-rw-r--r--ld/testsuite/ld-scripts/phdrs.exp10
-rw-r--r--ld/testsuite/ld-scripts/phdrs2.exp8
-rw-r--r--ld/testsuite/ld-spu/ovl.d117
-rw-r--r--ld/testsuite/ld-spu/ovl.lnk13
-rw-r--r--ld/testsuite/ld-spu/ovl.s82
-rw-r--r--ld/testsuite/ld-spu/spu.exp27
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
new file mode 100644
index 0000000..1d48c00
--- /dev/null
+++ b/ld/emultempl/spu_ovl.o
Binary files differ
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]
+}