diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/Makefile.am binutils/bfd/Makefile.am --- binutils-2.16.1/bfd/Makefile.am 2005-06-12 20:58:52.000000000 +0200 +++ binutils/bfd/Makefile.am 2006-03-30 01:23:21.000000000 +0200 @@ -58,6 +58,7 @@ cpu-s390.lo \ cpu-sh.lo \ cpu-sparc.lo \ + cpu-spu.lo \ cpu-tic30.lo \ cpu-tic4x.lo \ cpu-tic54x.lo \ @@ -116,6 +117,7 @@ cpu-s390.c \ cpu-sh.c \ cpu-sparc.c \ + cpu-spu.c \ cpu-tic30.c \ cpu-tic4x.c \ cpu-tic54x.c \ @@ -262,6 +264,7 @@ elf32-sh64.lo \ elf32-sh64-com.lo \ elf32-sparc.lo \ + elf32-spu.lo \ elf32-v850.lo \ elf32-vax.lo \ elf32-xstormy16.lo \ @@ -430,6 +433,7 @@ elf32-sh64-com.c \ elfxx-sparc.c \ elf32-sparc.c \ + elf32-spu.c \ elf32-v850.c \ elf32-vax.c \ elf32-xstormy16.c \ @@ -944,6 +948,7 @@ cpu-sh.lo: cpu-sh.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \ $(srcdir)/../opcodes/sh-opc.h cpu-sparc.lo: cpu-sparc.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h +cpu-spu.lo: cpu-spu.c $(INCDIR)/filenames.h cpu-tic30.lo: cpu-tic30.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h cpu-tic4x.lo: cpu-tic4x.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h cpu-tic54x.lo: cpu-tic54x.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h @@ -1336,6 +1341,10 @@ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/elf/sparc.h \ $(INCDIR)/elf/reloc-macros.h $(INCDIR)/opcode/sparc.h \ elfxx-sparc.h elf32-target.h elf-vxworks.h +elf32-spu.lo: elf32-spu.c $(INCDIR)/filenames.h elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ + $(INCDIR)/bfdlink.h $(INCDIR)/elf/spu.h $(INCDIR)/elf/reloc-macros.h \ + elf32-target.h elf32-v850.lo: elf32-v850.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/elf/v850.h \ diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/archures.c binutils/bfd/archures.c --- binutils-2.16.1/bfd/archures.c 2005-01-17 15:08:03.000000000 +0100 +++ binutils/bfd/archures.c 2006-03-30 01:23:21.000000000 +0200 @@ -204,11 +204,14 @@ .#define bfd_mach_ppc_rs64iii 643 .#define bfd_mach_ppc_7400 7400 .#define bfd_mach_ppc_e500 500 +.#define bfd_mach_cell_ppu 501 . bfd_arch_rs6000, {* IBM RS/6000 *} .#define bfd_mach_rs6k 6000 .#define bfd_mach_rs6k_rs1 6001 .#define bfd_mach_rs6k_rsc 6003 .#define bfd_mach_rs6k_rs2 6002 +. bfd_arch_spu, {* PowerPC SPU *} +.#define bfd_mach_spu 256 . bfd_arch_hppa, {* HP PA RISC *} .#define bfd_mach_hppa10 10 .#define bfd_mach_hppa11 11 @@ -442,6 +445,7 @@ extern const bfd_arch_info_type bfd_s390_arch; extern const bfd_arch_info_type bfd_sh_arch; extern const bfd_arch_info_type bfd_sparc_arch; +extern const bfd_arch_info_type bfd_spu_arch; extern const bfd_arch_info_type bfd_tic30_arch; extern const bfd_arch_info_type bfd_tic4x_arch; extern const bfd_arch_info_type bfd_tic54x_arch; @@ -503,6 +507,7 @@ &bfd_s390_arch, &bfd_sh_arch, &bfd_sparc_arch, + &bfd_spu_arch, &bfd_tic30_arch, &bfd_tic4x_arch, &bfd_tic54x_arch, diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/bfd-in2.h binutils/bfd/bfd-in2.h --- binutils-2.16.1/bfd/bfd-in2.h 2005-03-02 22:23:20.000000000 +0100 +++ binutils/bfd/bfd-in2.h 2006-03-30 01:23:21.000000000 +0200 @@ -921,6 +921,8 @@ bfd_boolean bfd_fill_in_gnu_debuglink_section (bfd *abfd, struct bfd_section *sect, const char *filename); +void bfd_set_direction(bfd *abfd, int fdflags); + /* Extracted from libbfd.c. */ /* Byte swapping macros for user section data. */ @@ -1649,11 +1651,15 @@ #define bfd_mach_ppc_rs64iii 643 #define bfd_mach_ppc_7400 7400 #define bfd_mach_ppc_e500 500 +#define bfd_mach_cell_ppu 501 +#define bfd_mach_cell_ppu_mambo 502 bfd_arch_rs6000, /* IBM RS/6000 */ #define bfd_mach_rs6k 6000 #define bfd_mach_rs6k_rs1 6001 #define bfd_mach_rs6k_rsc 6003 #define bfd_mach_rs6k_rs2 6002 + bfd_arch_spu, /* PowerPC SPU */ +#define bfd_mach_spu 256 bfd_arch_hppa, /* HP PA RISC */ #define bfd_mach_hppa10 10 #define bfd_mach_hppa11 11 @@ -3638,6 +3644,20 @@ BFD_RELOC_860_HIGOT, BFD_RELOC_860_HIGOTOFF, +/* SPU Relocations. */ + BFD_RELOC_SPU_IMM7, + BFD_RELOC_SPU_IMM8, + BFD_RELOC_SPU_IMM10, + BFD_RELOC_SPU_IMM10W, + BFD_RELOC_SPU_IMM16, + BFD_RELOC_SPU_IMM16W, + BFD_RELOC_SPU_IMM18, + BFD_RELOC_SPU_PCREL9a, + BFD_RELOC_SPU_PCREL9b, + BFD_RELOC_SPU_PCREL16, + BFD_RELOC_SPU_LO16, + BFD_RELOC_SPU_HI16, + /* OpenRISC Relocations. */ BFD_RELOC_OPENRISC_ABS_26, BFD_RELOC_OPENRISC_REL_26, diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/config.bfd binutils/bfd/config.bfd --- binutils-2.16.1/bfd/config.bfd 2005-01-31 18:18:47.000000000 +0100 +++ binutils/bfd/config.bfd 2006-03-30 01:23:21.000000000 +0200 @@ -77,10 +77,12 @@ pdp11*) targ_archs=bfd_pdp11_arch ;; pj*) targ_archs="bfd_pj_arch bfd_i386_arch";; powerpc*) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;; +ppu*) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;; rs6000) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;; s390*) targ_archs=bfd_s390_arch ;; sh*) targ_archs=bfd_sh_arch ;; sparc*) targ_archs=bfd_sparc_arch ;; +spu*) targ_archs=bfd_spu_arch ;; strongarm*) targ_archs=bfd_arm_arch ;; thumb*) targ_archs=bfd_arm_arch ;; v850*) targ_archs=bfd_v850_arch ;; @@ -1053,6 +1055,12 @@ targ_selvecs="bfd_powerpcle_pei_vec bfd_powerpc_pei_vec bfd_powerpcle_pe_vec bfd_powerpc_pe_vec" ;; + ppu-*-lv2) + targ_defvec=bfd_elf64_powerpc_vec + targ_selvecs="bfd_elf32_spu_vec" + want64=true + ;; + s390-*-linux*) targ_defvec=bfd_elf32_s390_vec targ64_selvecs=bfd_elf64_s390_vec @@ -1286,6 +1294,16 @@ targ_underscore=yes ;; + spu-*-lv2) + targ_defvec=bfd_elf32_spu_vec + targ_selvecs="bfd_elf64_powerpc_vec" + ;; + + spu-*-elf) + targ_defvec=bfd_elf32_spu_vec + targ_selvecs="bfd_elf32_powerpc_vec bfd_elf64_powerpc_vec" + ;; + #if HAVE_host_aout_vec tahoe-*-*) targ_defvec=host_aout_vec diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/configure.in binutils/bfd/configure.in --- binutils-2.16.1/bfd/configure.in 2005-06-12 20:58:40.000000000 +0200 +++ binutils/bfd/configure.in 2006-03-30 01:23:21.000000000 +0200 @@ -659,6 +659,7 @@ bfd_elf32_shlnbsd_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo cofflink.lo" ;; bfd_elf32_shnbsd_vec) tb="$tb elf32-sh.lo elf32.lo $elf coff-sh.lo cofflink.lo" ;; bfd_elf32_sparc_vec) tb="$tb elf32-sparc.lo elfxx-sparc.lo elf-vxworks.lo elf32.lo $elf" ;; + bfd_elf32_spu_vec) tb="$tb elf32-spu.lo elf32.lo $elf" ;; bfd_elf32_sparc_vxworks_vec) tb="$tb elf32-sparc.lo elfxx-sparc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_tradbigmips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; bfd_elf32_tradlittlemips_vec) tb="$tb elf32-mips.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo" ;; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/cpu-powerpc.c binutils/bfd/cpu-powerpc.c --- binutils-2.16.1/bfd/cpu-powerpc.c 2005-03-03 12:40:58.000000000 +0100 +++ binutils/bfd/cpu-powerpc.c 2006-03-30 01:23:21.000000000 +0200 @@ -295,6 +295,34 @@ FALSE, /* not the default */ powerpc_compatible, bfd_default_scan, - 0 + &bfd_powerpc_archs[15], + }, + { + 64, /* 64 bits in a word */ + 64, /* 64 bits in an address */ + 8, /* 8 bits in a byte */ + bfd_arch_powerpc, + bfd_mach_cell_ppu, + "powerpc", + "Cell:PPU", + 3, + FALSE, + powerpc_compatible, + bfd_default_scan, + &bfd_powerpc_archs[16], + }, + { + 64, /* 64 bits in a word */ + 64, /* 64 bits in an address */ + 8, /* 8 bits in a byte */ + bfd_arch_powerpc, + bfd_mach_cell_ppu_mambo, + "powerpc", + "Cell:Mambo", + 3, + FALSE, + powerpc_compatible, + bfd_default_scan, + 0 /* pointer to next bfd_arch_info_type objenct */ } }; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/cpu-spu.c binutils/bfd/cpu-spu.c --- binutils-2.16.1/bfd/cpu-spu.c 1970-01-01 01:00:00.000000000 +0100 +++ binutils/bfd/cpu-spu.c 2006-03-30 01:23:21.000000000 +0200 @@ -0,0 +1,63 @@ + +/* (C) Copyright + Sony Computer Entertainment, Inc., + Toshiba Corporation, + International Business Machines Corporation, + 2001,2002,2003,2004,2005. + + 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 file 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 file; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" + + +static const bfd_arch_info_type *spu_compatible + PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *)); + +static const bfd_arch_info_type * +spu_compatible (a,b) + const bfd_arch_info_type *a; + const bfd_arch_info_type *b; +{ + BFD_ASSERT (a->arch == bfd_arch_spu); + switch (b->arch) + { + default: + return NULL; + case bfd_arch_spu: + return bfd_default_compatible (a, b); + } + /*NOTREACHED*/ +} + +const bfd_arch_info_type bfd_spu_arch[] = +{ + { + 32, /* 32 bits in a word */ + 32, /* 32 bits in an address */ + 8, /* 8 bits in a byte */ + bfd_arch_spu, /* architecture */ + bfd_mach_spu, /* machine */ + "spu", /* architecture name */ + "spu:256K", /* printable name */ + 3, /* aligned power */ + TRUE, /* the default machine for the architecture */ + spu_compatible, /* the spu is only compatible with itself, see above */ + bfd_default_scan, + 0, /* next -- there are none! */ + } +}; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/elf.c binutils/bfd/elf.c --- binutils-2.16.1/bfd/elf.c 2005-05-30 00:00:10.000000000 +0200 +++ binutils/bfd/elf.c 2006-03-30 01:23:21.000000000 +0200 @@ -41,6 +41,10 @@ #include "elf-bfd.h" #include "libiberty.h" +#if (defined(BPA)) +#include "elf/spu.h" +#endif + static int elf_sort_sections (const void *, const void *); static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *); static bfd_boolean prep_headers (bfd *); @@ -3400,6 +3404,10 @@ asection *dynsec, *eh_frame_hdr; bfd_size_type amt; +#if defined(BPA) + bfd_boolean toe_segment=FALSE; +#endif + if (elf_tdata (abfd)->segment_map != NULL) return TRUE; @@ -3511,6 +3519,19 @@ one (we build the last one after this loop). */ new_segment = FALSE; } +#if defined(BPA) + else if (strcmp (hdr->name, ".toe") == 0) + { + new_segment = TRUE; + toe_segment = TRUE; + } + else if (toe_segment == TRUE) + { + /* no longer in toe_segment */ + new_segment = TRUE; + toe_segment = FALSE; + } +#endif else if (last_hdr->lma - last_hdr->vma != hdr->lma - hdr->vma) { /* If this section has a different relation between the @@ -3964,7 +3985,11 @@ bfd_size_type align; bfd_vma adjust; - if ((abfd->flags & D_PAGED) != 0 && bed->maxpagesize > align) + /* CELL LOCAL Begin */ + /* FIXME - need to double check this merge */ + if ((abfd->flags & D_PAGED) != 0 && bed->maxpagesize > align + || m == elf_tdata (abfd)->segment_map) + /* CELL LOCAL End */ align = bed->maxpagesize; else { @@ -4263,7 +4288,152 @@ p->p_flags |= PF_W; } } + +#if (defined(BPA)) + if ((bfd_get_arch(abfd) == bfd_arch_spu)) { +#define SPU_SEG_ALIGN 0x10 + if( p->p_type == PT_LOAD ) { + bfd_vma adjust_segment; + bfd_vma adjust_memsz; + /* segment file size is increased to multiple of SPU_SEG_ALIGN byte for DMA transfer. */ + adjust_segment = p->p_filesz % SPU_SEG_ALIGN ; + if ( adjust_segment != 0 ) { + p->p_filesz += (SPU_SEG_ALIGN - adjust_segment); + off += (SPU_SEG_ALIGN - adjust_segment) ; + voff += (SPU_SEG_ALIGN - adjust_segment) ; + } + /* The memory size of the segment is aligned to 16byte boundary.*/ + adjust_memsz = p->p_memsz % SPU_SEG_ALIGN ; + if ( adjust_memsz != 0) + p->p_memsz += (SPU_SEG_ALIGN - adjust_memsz); + } + } +#endif + + } + + +#if (defined(BPA)) + + /* Offset for PT_NOTE segment contains SPU_PTNOTE_SPUNAME section is set in this routine. + + In actual assign_file_positions_for_segments() doesn't gurantee to set file offset + in program header for non PT_LOAD segment. + + In detail, procedure are below. + 1) offset is set for sections in PT_LOAD segments. (in assign_file_positions_for_segments()) + 2) program headers are created and written. (in assign_file_positions_for_segments()) + 3) offset is set for sections in non PT_LOAD segments. (in assign_file_positions_except_relocs()) + + Note: + For example, file offset of PT_NOTE are set in normal system. + Because .note is contained in both PT_LOAD and PT_NOTE, + its offset are set in 1) and no problem occured. + + So this routine is added to gurantee to set offset for SPU_PTNOTE_SPUNAME only contained in PT_NOTE. + */ + + { + unsigned int i; + Elf_Internal_Shdr **hdrpp; + Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd); + unsigned int num_sec = elf_numsections (abfd); + Elf_Internal_Ehdr * const i_ehdrp = elf_elfheader (abfd); + + if (bfd_get_arch(abfd) == bfd_arch_spu) { + for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++) { + Elf_Internal_Shdr *hdr; + + hdr = *hdrpp; + if (hdr->bfd_section != NULL + && hdr->bfd_section->name != NULL + && (strcmp(hdr->bfd_section->name, SPU_PTNOTE_SPUNAME) == 0 )) { + + off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); + + elf_tdata (abfd)->next_file_pos = off; + } + } + } + } +#endif /* BPA */ + + +/* This is for SPU dynamic loading initial step. */ +#if 0 +#if (defined(BPA)) + /* Offset for non PT_LOAD segments is set in this routine. + This added routine is exactly same in assign_file_positions_except_relocs(). + + In actual assign_file_positions_for_segments() doesn't gurantee to set file offset + in program header for non PT_LOAD segment. + + In detail, procedure are below. + 1) offset is set for sections in PT_LOAD segments. (in assign_file_positions_for_segments()) + 2) program headers are created and written. (in assign_file_positions_for_segments()) + 3) offset is set for sections in non PT_LOAD segments. (in assign_file_positions_except_relocs()) + + So this routine is added to gurantee to set offset for not PT_LOAD segments. + + Note: + For example, file offset of PT_DYNAMIC are set in normal system. + Because .dynamic are contained in both PT_LOAD and PT_DYNAMIC. + So its offset are set in 1) and no problem occured. */ + + { + unsigned int i; + Elf_Internal_Shdr **hdrpp; + Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd); + unsigned int num_sec = elf_numsections (abfd); + struct elf_obj_tdata * const tdata = elf_tdata (abfd); + Elf_Internal_Ehdr * const i_ehdrp = elf_elfheader (abfd); + + if ((bfd_get_arch(abfd) == bfd_arch_spu) && (i_ehdrp->e_type == ET_DYN)) { + /* Assign file positions for the other sections. */ + + for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++) + { + Elf_Internal_Shdr *hdr; + + hdr = *hdrpp; + if (hdr->bfd_section != NULL + && hdr->bfd_section->filepos != 0) + hdr->sh_offset = hdr->bfd_section->filepos; + else if ((hdr->sh_flags & SHF_ALLOC) != 0) + { + ((*_bfd_error_handler) + (_("%s: warning: allocated section `%s' not in segment"), + bfd_get_filename (abfd), + (hdr->bfd_section == NULL + ? "*unknown*" + : hdr->bfd_section->name))); + if ((abfd->flags & D_PAGED) != 0) + off += (hdr->sh_addr - off) % bed->maxpagesize; + else + off += (hdr->sh_addr - off) % hdr->sh_addralign; + off = _bfd_elf_assign_file_position_for_section (hdr, off, + false); + } + else if (hdr->sh_type == SHT_REL + || hdr->sh_type == SHT_RELA + || hdr == i_shdrpp[tdata->symtab_section] + || hdr == i_shdrpp[tdata->symtab_shndx_section] + || hdr == i_shdrpp[tdata->strtab_section]) + hdr->sh_offset = -1; + else + off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE); + + if (i == SHN_LORESERVE - 1) + { + i += SHN_HIRESERVE + 1 - SHN_LORESERVE; + hdrpp += SHN_HIRESERVE + 1 - SHN_LORESERVE; + } + } + } + elf_tdata (abfd)->next_file_pos = off; } +#endif +#endif /* Now that we have set the section file positions, we can set up the file positions for the non PT_LOAD segments. */ diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/elf32-spu.c binutils/bfd/elf32-spu.c --- binutils-2.16.1/bfd/elf32-spu.c 1970-01-01 01:00:00.000000000 +0100 +++ binutils/bfd/elf32-spu.c 2006-03-30 01:23:21.000000000 +0200 @@ -0,0 +1,1015 @@ +/* SPU specific support for 32-bit ELF */ + +/* (C) Copyright + Sony Computer Entertainment, Inc., + Toshiba Corporation, + International Business Machines Corporation, + 2001,2002,2003,2004,2005. + + 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 file 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 file; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "bfdlink.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "elf/spu.h" + +void spu_elf_info_to_howto PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); +void spu_elf_info_to_howto_rel PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); +reloc_howto_type *spu_elf_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type)); +static void spu_elf_final_write_processing PARAMS ((bfd *, bfd_boolean)); +static bfd_boolean spu_elf_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, + asection *, bfd_byte *, Elf_Internal_Rela *, + Elf_Internal_Sym *, asection **)); +static asection * spu_elf_gc_mark_hook PARAMS ((asection *, struct bfd_link_info *, + Elf_Internal_Rela *, struct elf_link_hash_entry *, + Elf_Internal_Sym *)); +static bfd_boolean spu_elf_gc_sweep_hook PARAMS ((bfd *, struct bfd_link_info *, asection *, + const Elf_Internal_Rela *)); + +#if defined(BPA) +static void spu_elf_post_process_headers PARAMS ((bfd *, struct bfd_link_info *)); +static bfd_boolean spu_elf_section_processing PARAMS ((bfd *, Elf_Internal_Shdr *)); +static bfd_boolean spu_elf_always_size_sections PARAMS ((bfd *, struct bfd_link_info *)); +#endif + +/* When USE_REL is not defined bfd uses reloc entry addends + * instead of inserting the addend into the instruction. + * #define USE_REL 0 + */ + + +/* Values of type 'enum elf_spu_reloc_type' are used to index this + * array, so it must be declared in the order of that type. */ +static reloc_howto_type elf_howto_table[] = { + HOWTO(R_SPU_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont, bfd_elf_generic_reloc, "SPU_NONE", FALSE, 0x00000000, 0x00000000, FALSE), + HOWTO(R_SPU_ADDR10, 4, 2,10, FALSE, 14, complain_overflow_bitfield, bfd_elf_generic_reloc, "SPU_ADDR10", FALSE, 0x00ffc000, 0x00ffc000, FALSE), + HOWTO(R_SPU_ADDR16, 2, 2,16, FALSE, 7, complain_overflow_bitfield, bfd_elf_generic_reloc, "SPU_ADDR16", FALSE, 0x007fff80, 0x007fff80, FALSE), + HOWTO(R_SPU_ADDR16_HI,16,2,16, FALSE, 7, complain_overflow_bitfield, bfd_elf_generic_reloc, "SPU_ADDR16_HI", FALSE, 0x007fff80, 0x007fff80, FALSE), + HOWTO(R_SPU_ADDR16_LO,0, 2,16, FALSE, 7, complain_overflow_dont, bfd_elf_generic_reloc, "SPU_ADDR16_LO", FALSE, 0x007fff80, 0x007fff80, FALSE), + HOWTO(R_SPU_ADDR18, 0, 2,18, FALSE, 7, complain_overflow_bitfield, bfd_elf_generic_reloc, "SPU_ADDR18", FALSE, 0x01ffff80, 0x01ffff80, FALSE), + HOWTO(R_SPU_GLOB_DAT, 0, 2,32, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "SPU_GLOB_DAT", FALSE, 0xffffffff, 0xffffffff, FALSE), + HOWTO(R_SPU_REL16, 2, 2,16, TRUE, 7, complain_overflow_bitfield, bfd_elf_generic_reloc, "SPU_REL16", FALSE, 0x007fff80, 0x007fff80, TRUE), + HOWTO(R_SPU_ADDR7, 0, 2, 7, FALSE, 14, complain_overflow_dont, bfd_elf_generic_reloc, "SPU_ADDR7", FALSE, 0x001fc000, 0x001fc000, FALSE), + HOWTO(R_SPU_REL9, 2, 2, 9, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "SPU_REL9", FALSE, 0x0180007f, 0x0180007f, TRUE), + HOWTO(R_SPU_REL9I, 2, 2, 9, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "SPU_REL9I", FALSE, 0x0000c07f, 0x0000c07f, TRUE), + HOWTO(R_SPU_ADDR10I, 0, 2,10, FALSE, 14, complain_overflow_signed, bfd_elf_generic_reloc, "SPU_ADDR10I", FALSE, 0x00ffc000, 0x00ffc000, FALSE), + HOWTO(R_SPU_ADDR16I, 0, 2,16, FALSE, 7, complain_overflow_signed, bfd_elf_generic_reloc, "SPU_ADDR16I", FALSE, 0x007fff80, 0x007fff80, FALSE), +}; + +static struct bfd_elf_special_section const spu_elf_special_sections[]= +{ + { ".toe", 4, 0, SHT_PROGBITS, SHF_ALLOC }, + { NULL, 0, 0, 0, 0 } +}; + +static enum elf_spu_reloc_type +spu_elf_bfd_to_reloc_type (bfd_reloc_code_real_type code) +{ + switch (code) + { + default: + return R_SPU_NONE; + case BFD_RELOC_SPU_IMM10W: + return R_SPU_ADDR10; + case BFD_RELOC_SPU_IMM16W: + return R_SPU_ADDR16; + case BFD_RELOC_SPU_LO16: + return R_SPU_ADDR16_LO; + case BFD_RELOC_SPU_HI16: + return R_SPU_ADDR16_HI; + case BFD_RELOC_SPU_IMM18: + return R_SPU_ADDR18; + case BFD_RELOC_32: + return R_SPU_GLOB_DAT; + case BFD_RELOC_SPU_PCREL16: + return R_SPU_REL16; + case BFD_RELOC_SPU_IMM7: + return R_SPU_ADDR7; + case BFD_RELOC_SPU_IMM8: + return R_SPU_NONE; + case BFD_RELOC_SPU_PCREL9a: + return R_SPU_REL9; + case BFD_RELOC_SPU_PCREL9b: + return R_SPU_REL9I; + case BFD_RELOC_SPU_IMM10: + return R_SPU_ADDR10I; + case BFD_RELOC_SPU_IMM16: + return R_SPU_ADDR16I; + } +} + +void +spu_elf_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, + arelent * cache_ptr ATTRIBUTE_UNUSED, + Elf_Internal_Rela * dst ATTRIBUTE_UNUSED) +{ + enum elf_spu_reloc_type r_type; + + r_type = (enum elf_spu_reloc_type) ELF32_R_TYPE (dst->r_info); + BFD_ASSERT (r_type < R_SPU_max); + cache_ptr->howto = &elf_howto_table[(int) r_type]; +} + +void +spu_elf_info_to_howto_rel (bfd * abfd ATTRIBUTE_UNUSED, + arelent * cache_ptr, Elf_Internal_Rela * dst) +{ + enum elf_spu_reloc_type type; + + type = (enum elf_spu_reloc_type) ELF32_R_TYPE (dst->r_info); + BFD_ASSERT (type < R_SPU_max); + cache_ptr->howto = &elf_howto_table[(int) type]; +} + +reloc_howto_type * +spu_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) +{ + return elf_howto_table + spu_elf_bfd_to_reloc_type (code); +} + +/* Look through the relocs for a section during the first phase and + make any required dynamic sections. + + We iterate over the relocations three times: + + spu_elf_check_relocs + This creates any needed dynamic sections as we first read all the + input objects. We need to do create the sections now so they get + mapped to the correct output sections. At this points we don't + know which symbols are resolved from dynamic objects. + + allocate_dynrelocs + This computes sizes of the sections. Now we do know which + symbols come from where, so we can determine the correct amount + of space to allocate. Some sections will require no space and + are stripped by spu_elf_size_dynamic_sections. + + spu_elf_relocate_section + This finally creates the relocations in the correct section. + */ +static bfd_boolean +spu_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, + asection *sec, const Elf_Internal_Rela *relocs) +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; + const Elf_Internal_Rela *rel; + const Elf_Internal_Rela *rel_end; + asection *sreloc; + bfd *dynobj; + + if (info->relocatable) + return TRUE; + + /* Don't do anything special with non-loaded, non-alloced sections. + In particular, there's not much point in propagating relocs to + shared libs that the dynamic linker won't relocate. */ + if ((sec->flags & SEC_ALLOC) == 0) + return TRUE; + + dynobj = elf_hash_table (info)->dynobj; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + + sym_hashes = elf_sym_hashes (abfd); + sym_hashes_end = (sym_hashes + + symtab_hdr->sh_size / sizeof (Elf32_External_Sym) + - symtab_hdr->sh_info); + + sreloc = NULL; + + rel_end = relocs + sec->reloc_count; + for (rel = relocs; rel < rel_end; rel++) + { + unsigned long r_symndx; + struct elf_link_hash_entry *h; + enum elf_spu_reloc_type r_type; + + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx < symtab_hdr->sh_info) + h = NULL; + else + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + + r_type = ELF32_R_TYPE (rel->r_info); + switch (r_type) + { + case R_SPU_ADDR10: + case R_SPU_ADDR16: + case R_SPU_ADDR16_HI: + case R_SPU_ADDR16_LO: + case R_SPU_ADDR18: + case R_SPU_GLOB_DAT: + case R_SPU_REL16: + case R_SPU_ADDR7: + case R_SPU_ADDR10I: + case R_SPU_ADDR16I: + if (h != NULL + && (!h->def_regular + || h->root.type == bfd_link_hash_defweak + || (info->shared && ! info->symbolic))) + { + /* We might need to copy these reloc types into the output file. + Create a reloc section in dynobj. */ + if (sreloc == NULL) + { + const char *name; + + name = (bfd_elf_string_from_elf_section + (abfd, + elf_elfheader (abfd)->e_shstrndx, + elf_section_data (sec)->rel_hdr.sh_name)); + if (name == NULL) + return FALSE; + + if (strncmp (name, ".rela", 5) != 0 + || strcmp (bfd_get_section_name (abfd, sec), + name + 5) != 0) + { + (*_bfd_error_handler) + (_("%B: bad relocation section name `%s\'"), + abfd, name); + bfd_set_error (bfd_error_bad_value); + } + + if (dynobj == NULL) + dynobj = elf_hash_table (info)->dynobj = abfd; + + sreloc = bfd_get_section_by_name (dynobj, name); + if (sreloc == NULL) + { + flagword flags; + + sreloc = bfd_make_section (dynobj, name); + flags = (SEC_HAS_CONTENTS | SEC_READONLY + | SEC_IN_MEMORY | SEC_LINKER_CREATED); + if ((sec->flags & SEC_ALLOC) != 0) + flags |= SEC_ALLOC | SEC_LOAD; + if (sreloc == NULL + || ! bfd_set_section_flags (dynobj, sreloc, flags) + || ! bfd_set_section_alignment (dynobj, sreloc, 3)) + return FALSE; + } + elf_section_data (sec)->sreloc = sreloc; + } + } + break; + + default: + break; + } + } + return TRUE; +} + + +static bfd_boolean +spu_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info, + bfd * input_bfd, + asection * input_section, + bfd_byte * contents, + Elf_Internal_Rela * relocs, + Elf_Internal_Sym * local_syms, + asection ** local_sections) +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + Elf_Internal_Rela *rel, *relend; + bfd_boolean ret = TRUE; + + if (info->relocatable) + return TRUE; + + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + sym_hashes = (struct elf_link_hash_entry **) (elf_sym_hashes (input_bfd)); + + rel = relocs; + relend = relocs + input_section->reloc_count; + for (; rel < relend; rel++) + { + int r_type; + reloc_howto_type *howto; + unsigned long r_symndx; + Elf_Internal_Sym *sym; + asection *sec; + struct elf_link_hash_entry *h; + const char *sym_name; + bfd_vma relocation; + bfd_reloc_status_type r; + bfd_boolean unresolved_reloc; + bfd_boolean warned; + + r_symndx = ELF32_R_SYM (rel->r_info); + r_type = ELF32_R_TYPE (rel->r_info); + howto = elf_howto_table + r_type; + unresolved_reloc = FALSE; + warned = FALSE; + + h = NULL; + sym = NULL; + sec = NULL; + if (r_symndx < symtab_hdr->sh_info) + { + sym = local_syms + r_symndx; + sec = local_sections[r_symndx]; + sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym); + relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); + } + else + { + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned); + sym_name = h->root.root.string; + } + + switch (r_type) + { + /* Relocations that always need to be propagated if this is a shared + object. */ + case R_SPU_ADDR10: + case R_SPU_ADDR16: + case R_SPU_ADDR16_HI: + case R_SPU_ADDR16_LO: + case R_SPU_ADDR18: + case R_SPU_GLOB_DAT: + case R_SPU_REL16: + case R_SPU_ADDR7: + case R_SPU_ADDR10I: + case R_SPU_ADDR16I: + /* r_symndx will be zero only for relocs against symbols + from removed linkonce sections, or sections discarded by + a linker script. */ + if (r_symndx == 0) + break; + /* Fall thru. */ + + if ((info->shared + && (h == NULL + || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak) + && (!SYMBOL_CALLS_LOCAL (info, h))) + || (!info->shared + && h != NULL + && h->dynindx != -1 + && h->def_dynamic + && !h->def_regular)) + { + Elf_Internal_Rela outrel; + bfd_boolean skip, relocate; + asection *sreloc; + bfd_byte *loc; + bfd_vma out_off; + + /* When generating a dynamic object, these relocations + are copied into the output file to be resolved at run + time. */ + + skip = FALSE; + relocate = FALSE; + + out_off = _bfd_elf_section_offset (output_bfd, info, + input_section, rel->r_offset); + if (out_off == (bfd_vma) -1) + skip = TRUE; + else if (out_off == (bfd_vma) -2) + skip = TRUE, relocate = TRUE; + out_off += (input_section->output_section->vma + + input_section->output_offset); + outrel.r_offset = out_off; + outrel.r_addend = rel->r_addend; + + if (skip) + memset (&outrel, 0, sizeof outrel); + else if (!SYMBOL_REFERENCES_LOCAL (info, h)) + outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); + else + { + /* This symbol is local, or marked to become local. */ + outrel.r_addend += relocation; + if (r_type == R_SPU_GLOB_DAT) + { + outrel.r_info = ELF32_R_INFO (0, R_SPU_GLOB_DAT); + + /* Prelink also wants simple and consistent rules + for relocs. This make all RELATIVE relocs have + *r_offset equal to r_addend. */ + relocate = TRUE; + } + else + { + long indx = 0; + + if (bfd_is_abs_section (sec)) + ; + else if (sec == NULL || sec->owner == NULL) + { + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + else + { + asection *osec; + + osec = sec->output_section; + indx = elf_section_data (osec)->dynindx; + + /* We are turning this relocation into one + against a section symbol, so subtract out + the output section's address but not the + offset of the input section in the output + section. */ + outrel.r_addend -= osec->vma; + } + + outrel.r_info = ELF32_R_INFO (indx, r_type); + } + } + + sreloc = elf_section_data (input_section)->sreloc; + if (sreloc == NULL) + abort (); + + loc = sreloc->contents; + loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + + /* If this reloc is against an external symbol, it will + be computed at runtime, so there's no need to do + anything now. However, for the sake of prelink ensure + that the section contents are a known value. */ + if (! relocate) + { + unresolved_reloc = FALSE; + /* The value chosen here is quite arbitrary as ld.so + ignores section contents except for the special + case of .opd where the contents might be accessed + before relocation. Choose zero, as that won't + cause reloc overflow. */ + relocation = 0; + rel->r_addend = 0; + /* Adjust pc_relative relocs to have zero in *r_offset. */ + if (howto->pc_relative) + rel->r_addend = (input_section->output_section->vma + + input_section->output_offset + + rel->r_offset); + } + } + break; + } + + if (unresolved_reloc + && !((input_section->flags & SEC_DEBUGGING) != 0 + && h->def_dynamic)) + { + (*_bfd_error_handler) + (_("%B(%s+0x%lx): unresolvable %s relocation against symbol `%s'"), + input_bfd, + bfd_get_section_name (input_bfd, input_section), + (long) rel->r_offset, + howto->name, + sym_name); + ret = FALSE; + } + + r = _bfd_final_link_relocate (howto, + input_bfd, + input_section, + contents, + rel->r_offset, relocation, rel->r_addend); + + if (r != bfd_reloc_ok) + { + const char *name; + const char *msg = (const char *) 0; + + if (h != NULL) + name = h->root.root.string; + else + { + name = (bfd_elf_string_from_elf_section + (input_bfd, symtab_hdr->sh_link, sym->st_name)); + if (name == NULL || *name == '\0') + name = bfd_section_name (input_bfd, sec); + } + + switch (r) + { + case bfd_reloc_overflow: + if (!((*info->callbacks->reloc_overflow) + (info, (h ? &h->root : NULL), name, howto->name, + (bfd_vma) 0, input_bfd, input_section, rel->r_offset))) + return FALSE; + break; + + case bfd_reloc_undefined: + if (!((*info->callbacks->undefined_symbol) + (info, name, input_bfd, input_section, + rel->r_offset, TRUE))) + return FALSE; + break; + + case bfd_reloc_outofrange: + msg = _("internal error: out of range error"); + goto common_error; + + case bfd_reloc_notsupported: + msg = _("internal error: unsupported relocation error"); + goto common_error; + + case bfd_reloc_dangerous: + msg = _("internal error: dangerous error"); + goto common_error; + + default: + msg = _("internal error: unknown error"); + /* fall through */ + + common_error: + if (!((*info->callbacks->warning) + (info, msg, name, input_bfd, input_section, + rel->r_offset))) + return FALSE; + break; + } + } + } + + return ret; +} + +static asection * +spu_elf_gc_mark_hook (asection *sec, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + Elf_Internal_Rela *rel ATTRIBUTE_UNUSED, struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) +{ + if (h != NULL) + { + switch (h->root.type) + { + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + return h->root.u.def.section; + + case bfd_link_hash_common: + return h->root.u.c.p->section; + + default: + break; + } + } + else + return bfd_section_from_elf_index (sec->owner, sym->st_shndx); + + return NULL; +} + +static bfd_boolean +spu_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED) +{ + return TRUE; +} + +static void +spu_elf_final_write_processing (bfd * abfd, + bfd_boolean linker ATTRIBUTE_UNUSED) +{ + elf_elfheader (abfd)->e_machine = EM_SPU; + + /* We do these verifications here because this function is called only + * once. There may be a better place to do it, I didn't look. */ + + BFD_ASSERT (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32); + BFD_ASSERT (elf_elfheader (abfd)->e_ident[EI_DATA] == ELFDATA2MSB); + BFD_ASSERT (elf_elfheader (abfd)->e_flags == 0); + + /* Verify that elf_howto_table is in the correct order. */ + { + unsigned int i; + for (i = 0; i < sizeof (elf_howto_table) / sizeof (*elf_howto_table); i++) + { + BFD_ASSERT (elf_howto_table[i].type == i); + } + } +} + + +#if defined(BPA) +static void +spu_elf_post_process_headers (bfd * abfd, struct bfd_link_info *link_info) +{ + Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ + + /* e_type is set if -plugin assigned. */ + + i_ehdrp = elf_elfheader (abfd); + + if (link_info != NULL) + { + if (link_info->spuplugin) + { + i_ehdrp->e_type = ET_DYN; + } + } +} + +#endif + +#if defined(BPA) +static bfd_boolean +spu_elf_section_processing (bfd * abfd ATTRIBUTE_UNUSED, + Elf_Internal_Shdr * i_shdrp) +{ + /* Content of PT_NOTE segment for SPU plugin is set here. + Because it doesn't have SEC_ALLOC attribute, + it is not written in file as usual process. + + If this routine is not used, some special writing process has to be done somewhere. + (e.g., special function would be needed as string table writing process.) */ + + asection *sec; + + sec = i_shdrp->bfd_section; + if ((sec != NULL) && + (sec->name != NULL) && (strcmp (sec->name, SPU_PTNOTE_SPUNAME) == 0)) + { + + SPUPLUGIN_INFO *spuplugin_info; + spuplugin_info = bfd_alloc (abfd, sizeof (SPUPLUGIN_INFO)); + + bfd_put_32(abfd, (bfd_vma) SPU_PLUGIN_NAMESZ, &spuplugin_info->namesz) ; + bfd_put_32(abfd, (bfd_vma) SPU_PLUGIN_LOOKUPNAMESZ, &spuplugin_info->descsz) ; + bfd_put_32(abfd, (bfd_vma) 1, &spuplugin_info->type) ; + strncpy( spuplugin_info->name, SPU_PLUGIN_NAME, SPU_PLUGIN_NAMESZ); + strncpy( spuplugin_info->lookupname, bfd_get_filename(abfd), SPU_PLUGIN_LOOKUPNAMESZ); + + i_shdrp->contents = (unsigned char*)spuplugin_info ; + } + return TRUE; +} +#endif + +#if defined(BPA) +/* + * Make SPU_PTNOTE_SPUNAME section + * */ +static bfd_boolean +spu_elf_always_size_sections (bfd * abfd, struct bfd_link_info *link_info ATTRIBUTE_UNUSED) +{ + + register asection *s; + char *sname = SPU_PTNOTE_SPUNAME; + + s = bfd_get_section_by_name(abfd, sname); + /* don't create the section if already exists */ + if (s == NULL) { + s = bfd_make_section (abfd, sname); + if (s == NULL) { + return FALSE; + } + } + + if (!bfd_set_section_flags + (abfd, s, + (SEC_LOAD | SEC_IN_MEMORY | SEC_HAS_CONTENTS | SEC_LINKER_CREATED | + SEC_READONLY))) { + return FALSE; + } + + if (!bfd_set_section_alignment (abfd, s, 2)) { + return FALSE; + } + + if (!bfd_set_section_size (abfd, s, sizeof (SPUPLUGIN_INFO))) { + return FALSE; + } + + return TRUE; +} +#endif + +static bfd_boolean +spu_elf_finish_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) +{ + return TRUE; +} +static bfd_boolean +spu_elf_finish_dynamic_symbol (bfd *output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct elf_link_hash_entry *h ATTRIBUTE_UNUSED, + Elf_Internal_Sym *sym ATTRIBUTE_UNUSED) +{ + return TRUE; +} + +/* compute the sizes of the required dynamic relocatios */ +static bfd_boolean +allocate_dynrelocs (bfd *abfd, struct bfd_link_info *info, + asection *sec, const Elf_Internal_Rela *relocs) +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; + const Elf_Internal_Rela *rel; + const Elf_Internal_Rela *rel_end; + asection *sreloc; + bfd *dynobj; + + if (info->relocatable) + return TRUE; + + /* Don't do anything special with non-loaded, non-alloced sections. + In particular, there's not much point in propagating relocs to + shared libs that the dynamic linker won't relocate. */ + if ((sec->flags & SEC_ALLOC) == 0) + return TRUE; + + /* spu_elf_check_relocs will have set sreloc for the sections we + need to check. */ + sreloc = elf_section_data (sec)->sreloc; + if (sreloc == NULL) + return TRUE; + + dynobj = elf_hash_table (info)->dynobj; + if (dynobj == NULL) + abort(); + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + + sym_hashes = elf_sym_hashes (abfd); + sym_hashes_end = (sym_hashes + + symtab_hdr->sh_size / sizeof (Elf32_External_Sym) + - symtab_hdr->sh_info); + + + rel_end = relocs + sec->reloc_count; + for (rel = relocs; rel < rel_end; rel++) + { + unsigned long r_symndx; + struct elf_link_hash_entry *h; + enum elf_spu_reloc_type r_type; + + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx < symtab_hdr->sh_info) + h = NULL; + else + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + + r_type = ELF32_R_TYPE (rel->r_info); + switch (r_type) + { + case R_SPU_ADDR10: + case R_SPU_ADDR16: + case R_SPU_ADDR16_HI: + case R_SPU_ADDR16_LO: + case R_SPU_ADDR18: + case R_SPU_GLOB_DAT: + case R_SPU_REL16: + case R_SPU_ADDR7: + case R_SPU_ADDR10I: + case R_SPU_ADDR16I: + if ((info->shared + && (h == NULL + || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak) + && (!SYMBOL_CALLS_LOCAL (info, h))) + || (!info->shared + && h != NULL + && h->dynindx != -1 + && h->def_dynamic + && !h->def_regular)) + { + /* We must copy these reloc types into the output file. + Increase the size of the reloc section. */ + sreloc->rawsize += sizeof (Elf32_External_Rela); + } + break; + + default: + break; + } + } + return TRUE; +} + +/* Set the sizes of the dynamic sections. */ + +static bfd_boolean +spu_elf_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info * info) +{ + bfd * dynobj; + asection * s; + bfd_boolean relocs; + bfd_boolean reltext; + asection *o; + bfd *inputobj; + + /* Check all the relocations of all input objects to determine + the size of dynamic sections. */ + for (inputobj = info->input_bfds; + inputobj; + inputobj = inputobj->link_next) + { + for (o = inputobj->sections; o != NULL; o = o->next) + { + Elf_Internal_Rela *internal_relocs; + bfd_boolean ok; + + if ((o->flags & SEC_RELOC) == 0 + || o->reloc_count == 0 + || ((info->strip == strip_all || info->strip == strip_debugger) + && (o->flags & SEC_DEBUGGING) != 0) + || bfd_is_abs_section (o->output_section)) + continue; + + internal_relocs = _bfd_elf_link_read_relocs (inputobj, o, NULL, NULL, + info->keep_memory); + if (internal_relocs == NULL) + return FALSE; + + ok = allocate_dynrelocs (inputobj, info, o, internal_relocs); + + if (elf_section_data (o)->relocs != internal_relocs) + free (internal_relocs); + + if (! ok) + return FALSE; + } + } + + dynobj = elf_hash_table (info)->dynobj; + BFD_ASSERT (dynobj != NULL); + + /* The code above has determined the sizes of the various dynamic + sections. Allocate memory for them. */ + relocs = FALSE; + reltext = FALSE; + for (s = dynobj->sections; s != NULL; s = s->next) + { + const char * name; + bfd_boolean strip; + + if ((s->flags & SEC_LINKER_CREATED) == 0) + continue; + + if (s->contents != NULL) + continue; + + /* It's OK to base decisions on the section name, because none + of the dynobj section names depend upon the input files. */ + name = bfd_get_section_name (dynobj, s); + + strip = FALSE; + + if (strncmp (name, ".rela", 5) == 0) + { + if (s->rawsize == 0) + { + /* If we don't need this section, strip it from the output + file. */ + strip = TRUE; + } + else + { + /* We use the reloc_count field as a counter if we need + to copy relocs into the output file. */ + s->reloc_count = 0; + } + } + else + /* It's not one of our sections, so don't allocate space. */ + continue; + + if (strip) + { + _bfd_strip_section_from_output (info, s); + continue; + } + + /* Allocate memory for the section contents. We use bfd_zalloc + here in case unused entries are not reclaimed before the + section's contents are written out. This should not happen, + but this way if it does, we get a R_SPU_NONE reloc instead of + garbage. */ + s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->rawsize); + if (s->contents == NULL && s->rawsize != 0) + return FALSE; + } + + return TRUE; +} + +/* Create dynamic sections when linking against a dynamic object. */ + +static bfd_boolean +spu_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) +{ + flagword flags; + asection *s; + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + + /* We need to create .dynbss, and .rel[a].bss sections. */ + + flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_LINKER_CREATED); + + if (bed->want_dynbss) + { + /* The .dynbss section is a place to put symbols which are defined + by dynamic objects, are referenced by regular objects, and are + not functions. We must allocate space for them in the process + image and use a R_*_COPY reloc to tell the dynamic linker to + initialize them at run time. The linker script puts the .dynbss + section into the .bss section of the final image. */ + s = bfd_make_section (abfd, ".dynbss"); + if (s == NULL + || ! bfd_set_section_flags (abfd, s, SEC_ALLOC | SEC_LINKER_CREATED)) + return FALSE; + + /* The .rel[a].bss section holds copy relocs. This section is not + normally needed. We need to create it here, though, so that the + linker will map it to an output section. We can't just create it + only if we need it, because we will not know whether we need it + until we have seen all the input files, and the first time the + main linker code calls BFD after examining all the input files + (size_dynamic_sections) the input sections have already been + mapped to the output sections. If the section turns out not to + be needed, we can discard it later. We will never need this + section when generating a shared object, since they do not use + copy relocs. */ + if (! info->shared) + { + s = bfd_make_section (abfd, + (bed->default_use_rela_p + ? ".rela.bss" : ".rel.bss")); + if (s == NULL + || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) + || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) + return FALSE; + } + } + + return TRUE; +} + +static bfd_boolean +spu_elf_adjust_dynamic_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct elf_link_hash_entry *h ATTRIBUTE_UNUSED) +{ + return TRUE; +} + + +#define elf_backend_can_gc_sections 1 +#define elf_backend_rela_normal 1 + + +#define bfd_elf32_bfd_reloc_type_lookup spu_elf_reloc_type_lookup +#define elf_info_to_howto spu_elf_info_to_howto +#define elf_info_to_howto_rel spu_elf_info_to_howto_rel +#define elf_backend_relocate_section spu_elf_relocate_section +#define elf_backend_final_write_processing spu_elf_final_write_processing +#define elf_backend_gc_mark_hook spu_elf_gc_mark_hook +#define elf_backend_gc_sweep_hook spu_elf_gc_sweep_hook +#define elf_backend_adjust_dynamic_symbol spu_elf_adjust_dynamic_symbol +#define elf_backend_check_relocs spu_elf_check_relocs + +#define elf_backend_create_dynamic_sections spu_elf_create_dynamic_sections +#define elf_backend_finish_dynamic_sections spu_elf_finish_dynamic_sections +#define elf_backend_finish_dynamic_symbol spu_elf_finish_dynamic_symbol +#define elf_backend_size_dynamic_sections spu_elf_size_dynamic_sections + +#define TARGET_BIG_SYM bfd_elf32_spu_vec +#define TARGET_BIG_NAME "elf32-spu" +#define ELF_ARCH bfd_arch_spu +#define ELF_MACHINE_CODE EM_SPU +#define ELF_MAXPAGESIZE 0x80 /* This matches the alignment need for DMA. */ + +#if defined(BPA) +#define elf_backend_post_process_headers spu_elf_post_process_headers +#define elf_backend_section_processing spu_elf_section_processing +#define elf_backend_always_size_sections spu_elf_always_size_sections +#define elf_backend_special_sections spu_elf_special_sections +#endif + +#include "elf32-target.h" diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/elf64-ppc.c binutils/bfd/elf64-ppc.c --- binutils-2.16.1/bfd/elf64-ppc.c 2005-06-12 19:37:59.000000000 +0200 +++ binutils/bfd/elf64-ppc.c 2006-03-30 01:23:21.000000000 +0200 @@ -3967,7 +3967,8 @@ newsym->value = 0; newsym->flags = BSF_WEAK; - bh = NULL; + /* We don't want to search the "wrap" hash table */ + bh = bfd_link_hash_lookup (info->hash, newsym->name, TRUE, FALSE, FALSE); if (!_bfd_generic_link_add_one_symbol (info, abfd, newsym->name, newsym->flags, newsym->section, newsym->value, NULL, FALSE, FALSE, @@ -8985,6 +8986,8 @@ if (stub_type != ppc_stub_plt_call) { + /* CELL Local: Fix for lib00001372 in 2.15, not sure + if it is necessary in 2.16.1, but leaving it in. */ /* Check whether we need a TOC adjusting stub. Since the linker pastes together pieces from different object files when creating the diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/opncls.c binutils/bfd/opncls.c --- binutils-2.16.1/bfd/opncls.c 2005-03-07 11:32:38.000000000 +0100 +++ binutils/bfd/opncls.c 2006-03-30 01:23:21.000000000 +0200 @@ -1357,3 +1357,18 @@ return TRUE; } + +/* + * Added at SCEA - set direction. Needed to compensate for WIN32 + * lack of fcntl + */ +void +bfd_set_direction(bfd *abfd, int fdflags) +{ + switch (fdflags & (O_ACCMODE)) { + case O_RDONLY: abfd->direction = read_direction; break; + case O_WRONLY: abfd->direction = write_direction; break; + case O_RDWR: abfd->direction = both_direction; break; + default: abort (); + } +} diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/reloc.c binutils/bfd/reloc.c --- binutils-2.16.1/bfd/reloc.c 2005-03-02 22:23:21.000000000 +0100 +++ binutils/bfd/reloc.c 2006-03-30 01:23:21.000000000 +0200 @@ -4159,6 +4159,33 @@ Intel i860 Relocations. ENUM + BFD_RELOC_SPU_IMM7 +ENUMX + BFD_RELOC_SPU_IMM8 +ENUMX + BFD_RELOC_SPU_IMM10 +ENUMX + BFD_RELOC_SPU_IMM10W +ENUMX + BFD_RELOC_SPU_IMM16 +ENUMX + BFD_RELOC_SPU_IMM16W +ENUMX + BFD_RELOC_SPU_IMM18 +ENUMX + BFD_RELOC_SPU_PCREL9a +ENUMX + BFD_RELOC_SPU_PCREL9b +ENUMX + BFD_RELOC_SPU_PCREL16 +ENUMX + BFD_RELOC_SPU_LO16 +ENUMX + BFD_RELOC_SPU_HI16 +ENUMDOC + SPU Relocations. + +ENUM BFD_RELOC_OPENRISC_ABS_26 ENUMX BFD_RELOC_OPENRISC_REL_26 diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/bfd/targets.c binutils/bfd/targets.c --- binutils-2.16.1/bfd/targets.c 2005-03-01 02:56:27.000000000 +0100 +++ binutils/bfd/targets.c 2006-03-30 01:23:21.000000000 +0200 @@ -613,6 +613,7 @@ extern const bfd_target bfd_elf32_shlnbsd_vec; extern const bfd_target bfd_elf32_shnbsd_vec; extern const bfd_target bfd_elf32_sparc_vec; +extern const bfd_target bfd_elf32_spu_vec; extern const bfd_target bfd_elf32_sparc_vxworks_vec; extern const bfd_target bfd_elf32_tradbigmips_vec; extern const bfd_target bfd_elf32_tradlittlemips_vec; @@ -918,6 +919,7 @@ &bfd_elf32_sh64blin_vec, #endif &bfd_elf32_sparc_vec, + &bfd_elf32_spu_vec, &bfd_elf32_sparc_vxworks_vec, &bfd_elf32_tradbigmips_vec, &bfd_elf32_tradlittlemips_vec, diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/binutils/doc/objcopy.1 binutils/binutils/doc/objcopy.1 --- binutils-2.16.1/binutils/doc/objcopy.1 2005-04-20 20:49:51.000000000 +0200 +++ binutils/binutils/doc/objcopy.1 2006-03-30 01:23:21.000000000 +0200 @@ -164,6 +164,8 @@ [\fB\-\-change\-section\-vma\fR \fIsection\fR{=,+,\-}\fIval\fR] [\fB\-\-change\-warnings\fR] [\fB\-\-no\-change\-warnings\fR] [\fB\-\-set\-section\-flags\fR \fIsection\fR=\fIflags\fR] + [\fB\-\-set\-section\-align\fR \fIsection\fR=\fIalignment\fR] + [\fB\-\-set\-section\-pad\fR \fIsection\fR=\fIalignment\fR] [\fB\-\-add\-section\fR \fIsectionname\fR=\fIfilename\fR] [\fB\-\-rename\-section\fR \fIoldname\fR=\fInewname\fR[,\fIflags\fR]] [\fB\-\-change\-leading\-char\fR] [\fB\-\-remove\-leading\-char\fR] @@ -526,6 +528,13 @@ \&\fBcontents\fR flag of a section which does have contents\*(--just remove the section instead. Not all flags are meaningful for all object file formats. +.IP "\fB\-\-set\-section\-align\fR \fIsection\fR\fB=\fR\fIalignment\fR" 4 +.IX Item "--set-section-align section=align" +Set the alignment for the named section to 2**align. +.IP "\fB\-\-set\-section\-pad\fR \fIsection\fR\fB=\fR\fIalignment\fR" 4 +.IX Item "--set-section-pad section=pad_align" +Set the size for the named section such that its size is a multiple +of pad_align. .IP "\fB\-\-add\-section\fR \fIsectionname\fR\fB=\fR\fIfilename\fR" 4 .IX Item "--add-section sectionname=filename" Add a new section named \fIsectionname\fR while copying the file. The diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/binutils/objcopy.c binutils/binutils/objcopy.c --- binutils-2.16.1/binutils/objcopy.c 2005-03-03 12:46:12.000000000 +0100 +++ binutils/binutils/objcopy.c 2006-03-30 01:23:21.000000000 +0200 @@ -120,6 +120,10 @@ bfd_vma lma_val; /* Amount to change by or set to. */ bfd_boolean set_flags; /* Whether to set the section flags. */ flagword flags; /* What to set the section flags to. */ + bfd_boolean set_align; /* Whether to set the section alignment. */ + int alignment; /* What to set the section alignment to. */ + bfd_boolean set_pad; /* Whether to set the section alignment. */ + int pad_align; /* What to set the section alignment to. */ }; static struct section_list *change_sections; @@ -249,7 +253,9 @@ OPTION_READONLY_TEXT, OPTION_WRITABLE_TEXT, OPTION_PURE, - OPTION_IMPURE + OPTION_IMPURE, + OPTION_SET_SECTION_ALIGN, + OPTION_SET_SECTION_PAD }; /* Options to handle if running as "strip". */ @@ -336,7 +342,9 @@ {"remove-leading-char", no_argument, 0, OPTION_REMOVE_LEADING_CHAR}, {"remove-section", required_argument, 0, 'R'}, {"rename-section", required_argument, 0, OPTION_RENAME_SECTION}, + {"set-section-align", required_argument, 0, OPTION_SET_SECTION_ALIGN}, {"set-section-flags", required_argument, 0, OPTION_SET_SECTION_FLAGS}, + {"set-section-pad", required_argument, 0, OPTION_SET_SECTION_PAD}, {"set-start", required_argument, 0, OPTION_SET_START}, {"srec-len", required_argument, 0, OPTION_SREC_LEN}, {"srec-forceS3", no_argument, 0, OPTION_SREC_FORCES3}, @@ -441,6 +449,12 @@ Warn if a named section does not exist\n\ --set-section-flags =\n\ Set section 's properties to \n\ + --set-section-align =\n\ + Set section 's alignment to\n\ + 2**\n\ + --set-section-pad =\n\ + Set section 's size to a multiple of\n\ + \n\ --add-section = Add section found in to output\n\ --rename-section =[,] Rename section to \n\ --change-leading-char Force output format's leading character style\n\ @@ -1907,6 +1921,8 @@ size = bfd_section_size (ibfd, isection); if (copy_byte >= 0) size = (size + interleave - 1) / interleave; + if (p != NULL && p->set_pad) + size += p->pad_align - (size % p->pad_align); if (! bfd_set_section_size (obfd, osection, size)) { err = _("size"); @@ -1942,9 +1958,18 @@ osection->lma = lma; + if (p != NULL && p->set_align) + { + if (! bfd_set_section_alignment (obfd, osection, p->alignment)) + { + bfd_nonfatal (bfd_get_filename (obfd)); + return FALSE; + } + } + /* FIXME: This is probably not enough. If we change the LMA we may have to recompute the header for the file as well. */ - if (!bfd_set_section_alignment (obfd, + else if (!bfd_set_section_alignment (obfd, osection, bfd_section_alignment (ibfd, isection))) { @@ -2816,6 +2841,51 @@ } break; + case OPTION_SET_SECTION_ALIGN: + { + const char *s; + int len; + char *name; + + s = strchr (optarg, '='); + if (s == NULL) + fatal (_("bad format for %s"), "--set-section-align"); + + len = s - optarg; + name = xmalloc (len + 1); + strncpy (name, optarg, len); + name[len] = '\0'; + + p = find_section_list (name, TRUE); + + p->set_align = TRUE; + p->alignment = atoi (s + 1); + } + break; + + case OPTION_SET_SECTION_PAD: + { + const char *s; + int len; + char *name; + + s = strchr (optarg, '='); + if (s == NULL) + fatal (_("bad format for %s"), "--set-section-align"); + + len = s - optarg; + name = xmalloc (len + 1); + strncpy (name, optarg, len); + name[len] = '\0'; + + p = find_section_list (name, TRUE); + + p->pad_align = atoi (s + 1); + if (p->pad_align > 0) + p->set_pad = TRUE; + } + break; + case OPTION_RENAME_SECTION: { flagword flags; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/binutils/readelf.c binutils/binutils/readelf.c --- binutils-2.16.1/binutils/readelf.c 2005-04-20 20:43:36.000000000 +0200 +++ binutils/binutils/readelf.c 2006-03-30 01:23:21.000000000 +0200 @@ -102,6 +102,7 @@ #include "elf/s390.h" #include "elf/sh.h" #include "elf/sparc.h" +#include "elf/spu.h" #include "elf/v850.h" #include "elf/vax.h" #include "elf/x86-64.h" @@ -723,6 +724,7 @@ case EM_XSTORMY16: case EM_CRX: case EM_VAX: + case EM_SPU: case EM_IP2K: case EM_IP2K_OLD: case EM_IQ2000: @@ -1219,6 +1221,10 @@ rtype = elf_vax_reloc_type (type); break; + case EM_SPU: + rtype = elf_spu_reloc_type (type); + break; + case EM_IP2K: case EM_IP2K_OLD: rtype = elf_ip2k_reloc_type (type); @@ -1715,6 +1721,7 @@ case EM_OR32: return "OpenRISC"; case EM_CRX: return "National Semiconductor CRX microprocessor"; case EM_DLX: return "OpenDLX"; + case EM_SPU: return "SPU"; case EM_IP2K_OLD: case EM_IP2K: return "Ubicom IP2xxx 8-bit microcontrollers"; case EM_IQ2000: return "Vitesse IQ2000"; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/gas/Makefile.am binutils/gas/Makefile.am --- binutils-2.16.1/gas/Makefile.am 2005-03-22 16:31:44.000000000 +0100 +++ binutils/gas/Makefile.am 2006-03-30 01:23:21.000000000 +0200 @@ -81,6 +81,7 @@ sh \ sh64 \ sparc \ + spu \ tic30 \ tic4x \ tic54x \ @@ -279,6 +280,7 @@ config/tc-sh.c \ config/tc-sh64.c \ config/tc-sparc.c \ + config/tc-spu.c \ config/tc-tic30.c \ config/tc-tic54x.c \ config/tc-vax.c \ @@ -332,6 +334,7 @@ config/tc-sh.h \ config/tc-sh64.h \ config/tc-sparc.h \ + config/tc-spu.h \ config/tc-tic30.h \ config/tc-tic54x.h \ config/tc-vax.h \ @@ -1451,6 +1454,12 @@ dwarf2dbg.h $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \ $(INCDIR)/opcode/sparc.h dw2gencfi.h $(INCDIR)/elf/dwarf2.h \ $(INCDIR)/elf/sparc.h $(INCDIR)/elf/reloc-macros.h +DEPTC_spu_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ + $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ + $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-spu.h \ + $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \ + $(INCDIR)/opcode/spu.h $(INCDIR)/elf/spu.h $(INCDIR)/elf/reloc-macros.h \ + $(INCDIR)/opcode/spu-insns.h dwarf2dbg.h DEPTC_tic30_aout = $(INCDIR)/symcat.h $(srcdir)/config/obj-aout.h \ $(srcdir)/config/tc-tic30.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \ $(INCDIR)/safe-ctype.h $(INCDIR)/opcode/tic30.h @@ -1980,6 +1989,10 @@ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sparc.h \ dwarf2dbg.h $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \ struc-symbol.h $(INCDIR)/aout/aout64.h +DEPOBJ_spu_elf = $(INCDIR)/symcat.h $(srcdir)/config/obj-elf.h \ + $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ + $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-spu.h \ + $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h DEPOBJ_tic30_aout = $(INCDIR)/symcat.h $(srcdir)/config/obj-aout.h \ $(srcdir)/config/tc-tic30.h $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h \ $(INCDIR)/aout/aout64.h $(INCDIR)/obstack.h @@ -2362,6 +2375,9 @@ $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-sparc.h \ dwarf2dbg.h +DEP_spu_elf = $(srcdir)/config/obj-elf.h $(INCDIR)/symcat.h \ + $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ + $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h $(srcdir)/config/tc-spu.h DEP_tic30_aout = $(srcdir)/config/obj-aout.h $(srcdir)/config/tc-tic30.h \ $(BFDDIR)/libaout.h $(INCDIR)/bfdlink.h DEP_tic30_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-tic30.h \ diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/gas/config/tc-ppc.c binutils/gas/config/tc-ppc.c --- binutils-2.16.1/gas/config/tc-ppc.c 2005-03-02 14:24:01.000000000 +0100 +++ binutils/gas/config/tc-ppc.c 2006-03-30 01:23:21.000000000 +0200 @@ -906,6 +912,15 @@ ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64 | PPC_OPCODE_POWER4); } + /* -mcellppu and -mppu means assemble for the CELL PPU arhictecrue */ + /* -mdd1.0, -mdd2.0 and -mdd3.0 are here for completeness. */ + else if (strcmp (arg, "cellppu") == 0 || strcmp (arg, "ppu") == 0 + || strcmp (arg, "dd1.0") == 0 || strcmp (arg, "dd2.0") == 0 + || strcmp (arg, "dd3.0") == 0 ) + { + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_CELLPPU + | PPC_OPCODE_ALTIVEC; + } /* -mcom means assemble for the common intersection between Power and PowerPC. At present, we just allow the union, rather than the intersection. */ @@ -1100,6 +1115,7 @@ -mppc64bridge generate code for PowerPC 64, including bridge insns\n\ -mbooke64 generate code for 64-bit PowerPC BookE\n\ -mbooke, mbooke32 generate code for 32-bit PowerPC BookE\n\ +-mcellppu, mppu generate code for CELL PPU architecture\n\ -mpower4 generate code for Power4 architecture\n\ -mpower5 generate code for Power5 architecture\n\ -mcom generate code Power/PowerPC common instructions\n\ @@ -1134,7 +1150,13 @@ if ((ppc_cpu & ~PPC_OPCODE_ANY) == 0) { - if (ppc_obj64) + if (strncmp (default_cpu, "ppu", 2) == 0 + || strncmp (default_cpu, "cellppu", 6) == 0) + { + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_CELLPPU + | PPC_OPCODE_ALTIVEC; + } + else if (ppc_obj64) ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64; else if (strncmp (default_os, "aix", 3) == 0 && default_os[3] >= '4' && default_os[3] <= '9') @@ -1266,7 +1288,7 @@ if ((ppc_cpu & PPC_OPCODE_601) != 0 && (op->flags & PPC_OPCODE_POWER) != 0) continue; - + as_bad (_("Internal assembler error for instruction %s"), op->name); dup_insn = TRUE; @@ -1579,6 +1601,7 @@ MAP64 ("highesta", BFD_RELOC_PPC64_HIGHEST_S), MAP64 ("tocbase", BFD_RELOC_PPC64_TOC), MAP64 ("toc", BFD_RELOC_PPC_TOC16), + MAP ("sdatoc", BFD_RELOC_PPC_TOC16), MAP64 ("toc@l", BFD_RELOC_PPC64_TOC16_LO), MAP64 ("toc@h", BFD_RELOC_PPC64_TOC16_HI), MAP64 ("toc@ha", BFD_RELOC_PPC64_TOC16_HA), @@ -2363,8 +2386,6 @@ if (ex.X_op == O_illegal) as_bad (_("illegal operand")); - else if (ex.X_op == O_absent) - as_bad (_("missing operand")); else if (ex.X_op == O_register) { insn = ppc_insert_operand (insn, operand, ex.X_add_number, diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/gas/config/tc-spu.c binutils/gas/config/tc-spu.c --- binutils-2.16.1/gas/config/tc-spu.c 1970-01-01 01:00:00.000000000 +0100 +++ binutils/gas/config/tc-spu.c 2006-03-30 01:23:21.000000000 +0200 @@ -0,0 +1,1006 @@ +/* spu.c -- Assembler for the IBM Synergistic Processing Unit (SPU) */ + +/* (C) Copyright + Sony Computer Entertainment, Inc., + Toshiba Corporation, + International Business Machines Corporation, + 2001,2002,2003,2004,2005. + + 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 file 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 file; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + + +#include "as.h" +#include "safe-ctype.h" +#include "subsegs.h" +#include "opcode/spu.h" +#include "dwarf2dbg.h" + +const struct spu_opcode spu_opcodes[] = { +#define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \ + { MACFORMAT, (OPCODE) << (32-11), MNEMONIC, ASMFORMAT }, +#define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \ + { MACFORMAT, ((OPCODE) << (32-11)) | ((FB) << (32-18)), MNEMONIC, ASMFORMAT }, +#include "opcode/spu-insns.h" +#undef APUOP +#undef APUOPFB +}; + +static const int spu_num_opcodes = + sizeof (spu_opcodes) / sizeof (spu_opcodes[0]); + +#define MAX_RELOCS 2 + +struct spu_insn +{ + unsigned int opcode; + expressionS exp[MAX_RELOCS]; + int reloc_arg[MAX_RELOCS]; + int flag[MAX_RELOCS]; + enum spu_insns tag; +}; + +static const char *get_imm PARAMS ((const char *param, struct spu_insn *insn, int arg)); +static const char *get_reg PARAMS ((const char *param, struct spu_insn *insn, int arg, int accept_expr)); + +static int calcop PARAMS ((struct spu_opcode *format, + const char *param, struct spu_insn *insn)); + +extern char *myname; +static struct hash_control *op_hash = NULL; + +/* These bits should be turned off in the first address of every segment */ +int md_seg_align = 7; + +/* These chars start a comment anywhere in a source file (except inside + another comment */ +const char comment_chars[] = "#"; + +/* These chars only start a comment at the beginning of a line. */ +const char line_comment_chars[] = "#"; + +/* gods own line continuation char */ +const char line_separator_chars[] = ";"; + +/* Chars that can be used to separate mant from exp in floating point nums */ +const char EXP_CHARS[] = "eE"; + +/* Chars that mean this number is a floating point constant */ +/* as in 0f123.456 */ +/* or 0H1.234E-12 (see exp chars above) */ +const char FLT_CHARS[] = "dDfF"; + +const pseudo_typeS md_pseudo_table[] = +{ + {"align", s_align_ptwo, 4}, + {"def", s_set, 0}, + {"dfloat", float_cons, 'd'}, + {"ffloat", float_cons, 'f'}, + {"global", s_globl, 0}, + {"half", cons, 2}, + {"bss", s_lcomm_bytes, 1}, + {"string", stringer, 1}, + {"word", cons, 4}, + /* Force set to be treated as an instruction. */ + {"set", NULL, 0}, + {".set", s_set, 0}, + {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0 }, + {"loc", dwarf2_directive_loc, 0}, + {0,0,0} +}; + +void +md_begin () +{ + const char *retval = NULL; + int i; + + /* initialize hash table */ + + op_hash = hash_new (); + + /* loop until you see the end of the list */ + + for (i = 0; i < spu_num_opcodes; i++) + { + /* hash each mnemonic and record its position */ + + retval = hash_insert (op_hash, spu_opcodes[i].mnemonic, (PTR)&spu_opcodes[i]); + + if (retval != NULL && strcmp(retval, "exists") != 0) + as_fatal (_("Can't hash instruction '%s':%s"), + spu_opcodes[i].mnemonic, retval); + } +} + +CONST char *md_shortopts = ""; +struct option md_longopts[] = { +#define OPTION_APUASM (OPTION_MD_BASE) + {"apuasm", no_argument, NULL, OPTION_APUASM}, +#define OPTION_DD2 (OPTION_MD_BASE+1) + {"mdd2.0", no_argument, NULL, OPTION_DD2}, +#define OPTION_DD1 (OPTION_MD_BASE+2) + {"mdd1.0", no_argument, NULL, OPTION_DD1}, +#define OPTION_DD3 (OPTION_MD_BASE+3) + {"mdd3.0", no_argument, NULL, OPTION_DD3}, + { NULL, no_argument, NULL, 0 } +}; +size_t md_longopts_size = sizeof (md_longopts); + +/* When set (by -apuasm) our assembler emulates the behaviour of apuasm. + * e.g. don't add bias to float conversion and don't right shift + * immediate values. */ +static int emulate_apuasm; + +/* Use the dd2.0 instructions set. The only differences are some new + * register names and the orx insn */ +static int use_dd2 = 1; + +int +md_parse_option (c, arg) + int c; + char *arg ATTRIBUTE_UNUSED; +{ + switch(c) + { + case OPTION_APUASM: emulate_apuasm = 1; break; + case OPTION_DD3: use_dd2 = 1; break; + case OPTION_DD2: use_dd2 = 1; break; + case OPTION_DD1: use_dd2 = 0; break; + default: return 0; + } + return 1; +} + +void +md_show_usage (stream) + FILE *stream; +{ + fputs (_("\ +SPU options:\n\ + --apuasm emulate behaviour of apuasm\n"), + stream); +} + + +struct arg_encode { + int size; + int pos; + int rshift; + int lo, hi; + int wlo, whi; + bfd_reloc_code_real_type reloc; +}; +static struct arg_encode arg_encode[A_MAX] = { + { 7, 0, 0, 0, 127, 0, -1, 0 }, /* A_T */ + { 7, 7, 0, 0, 127, 0, -1, 0 }, /* A_A */ + { 7, 14, 0, 0, 127, 0, -1, 0 }, /* A_B */ + { 7, 21, 0, 0, 127, 0, -1, 0 }, /* A_C */ + { 7, 7, 0, 0, 127, 0, -1, 0 }, /* A_S */ + { 7, 7, 0, 0, 127, 0, -1, 0 }, /* A_H */ + { 0, 0, 0, 0, -1, 0, -1, 0 }, /* A_P */ + { 7, 14, 0, 0, -1, 0, -1, BFD_RELOC_SPU_IMM7 }, /* A_S3 */ + { 7, 14, 0, -32, 31, -31, 0, BFD_RELOC_SPU_IMM7 }, /* A_S6 */ + { 7, 14, 0, 0, -1, 0, -1, BFD_RELOC_SPU_IMM7 }, /* A_S7N */ + { 7, 14, 0, -64, 63, -63, 0, BFD_RELOC_SPU_IMM7 }, /* A_S7 */ + { 8, 14, 0, 0, 127, 0, -1, BFD_RELOC_SPU_IMM8 }, /* A_U7A */ + { 8, 14, 0, 0, 127, 0, -1, BFD_RELOC_SPU_IMM8 }, /* A_U7B */ + { 10, 14, 0, -512, 511, -128, 255, BFD_RELOC_SPU_IMM10 }, /* A_S10B */ + { 10, 14, 0, -512, 511, 0, -1, BFD_RELOC_SPU_IMM10 }, /* A_S10 */ + { 2, 23, 9, -1024, 1023, 0, -1, BFD_RELOC_SPU_PCREL9a }, /* A_S11 */ + { 2, 14, 9, -1024, 1023, 0, -1, BFD_RELOC_SPU_PCREL9b }, /* A_S11I */ + { 10, 14, 4, -8192, 8191, 0, -1, BFD_RELOC_SPU_IMM10W }, /* A_S14 */ + { 16, 7, 0, -32768, 32767, 0, -1, BFD_RELOC_SPU_IMM16 }, /* A_S16 */ + { 16, 7, 2, -131072, 262143, 0, -1, BFD_RELOC_SPU_IMM16W }, /* A_S18 */ + { 16, 7, 2, -262144, 262143, 0, -1, BFD_RELOC_SPU_PCREL16 }, /* A_R18 */ + { 7, 14, 0, 0, -1, 0, -1, BFD_RELOC_SPU_IMM7 }, /* A_U3 */ + { 7, 14, 0, 0, 127, 0, 31, BFD_RELOC_SPU_IMM7 }, /* A_U5 */ + { 7, 14, 0, 0, 127, 0, 63, BFD_RELOC_SPU_IMM7 }, /* A_U6 */ + { 7, 14, 0, 0, -1, 0, -1, BFD_RELOC_SPU_IMM7 }, /* A_U7 */ + { 14, 0, 0, 0, 16383, 0, -1, 0 }, /* A_U14 */ + { 16, 7, 0, -32768, 65535, 0, -1, BFD_RELOC_SPU_IMM16 }, /* A_X16 */ + { 18, 7, 0, 0, 262143, 0, -1, BFD_RELOC_SPU_IMM18 }, /* A_U18 */ +}; + +/* Some flags for handling errors. This is very hackish and added after + * the fact. */ +static int syntax_error_arg; +static char * syntax_error_param; +static int syntax_reg; + +static char * +insn_fmt_string(struct spu_opcode *format) +{ + static char buf[64]; + int len = 0; + int i; + int paren; + len += sprintf (&buf[len], "%s\t", format->mnemonic); + for (i = 1; i <= format->arg[0]; i++) + { + int arg = format->arg[i]; + char *exp; + if (i > 1 && arg != A_P && format->arg[i-1] != A_P) + buf[len++] = ','; + if (arg == A_P) + exp = "("; + else if (arg < A_P) + exp = i == syntax_error_arg ? "REG" : "reg"; + else + exp = i == syntax_error_arg ? "IMM" : "imm"; + len += sprintf (&buf[len], "%s", exp); + if (i > 1 && format->arg[i-1] == A_P) + buf[len++] = ')'; + } + buf[len] = 0; + return buf; +} + +void +md_assemble (op) + char *op; +{ + char *param, *thisfrag; + char c; + struct spu_opcode *format; + struct spu_insn insn; + int i; + + assert (op); + + /* skip over instruction to find parameters */ + + for (param = op; *param != 0 && !ISSPACE (*param); param++) + ; + c = *param; + *param = 0; + + if (c != 0 && c != '\n') + param++; + + /* try to find the instruction in the hash table */ + + if ((format = (struct spu_opcode *) hash_find (op_hash, op)) == NULL) + { + as_bad (_("Invalid mnemonic '%s'"), op); + return; + } + + if (!use_dd2 && strcmp(format->mnemonic, "orx") == 0) + { + as_bad (_("'%s' is only available in DD2.0 or higher."), op); + return; + } + + while (1) + { + /* try parsing this instruction into insn */ + + for (i = 0; i < MAX_RELOCS; i++) + { + insn.exp[i].X_add_symbol = 0; + insn.exp[i].X_op_symbol = 0; + insn.exp[i].X_add_number = 0; + insn.exp[i].X_op = O_illegal; + insn.reloc_arg[i] = -1; + insn.flag[i] = 0; + } + insn.opcode = format->opcode; + insn.tag = (enum spu_insns)(format - spu_opcodes); + + syntax_error_arg = 0; + syntax_error_param = 0; + syntax_reg = 0; + if (calcop (format, param, &insn)) + break; + + /* if it doesn't parse try the next instruction */ + if (!strcmp (format[0].mnemonic, format[1].mnemonic)) + format++; + else + { + int parg = format[0].arg[syntax_error_arg-1]; + char *exp; + as_fatal (_("Error in argument %d. Expecting: \"%s\""), + syntax_error_arg - (parg == A_P), + insn_fmt_string(format)); + return; + } + } + + if ((syntax_reg & 4) + && ! (insn.tag == M_RDCH + || insn.tag == M_RCHCNT + || insn.tag == M_WRCH)) + as_warn (_("Mixing register syntax, with and without '$'.")); + if (syntax_error_param) + { + char *d = syntax_error_param; + while (*d != '$') + d--; + as_warn (_("Treating '%-*s' as a symbol."), syntax_error_param-d, d); + } + + /* grow the current frag and plop in the opcode */ + + thisfrag = frag_more (4); + md_number_to_chars (thisfrag, insn.opcode, 4); + + /* if this instruction requires labels mark it for later */ + + for (i = 0; i < MAX_RELOCS; i++) + if (insn.reloc_arg[i] >= 0) + { + fixS *fixP; + bfd_reloc_code_real_type reloc = arg_encode[insn.reloc_arg[i]].reloc; + int pcrel = 0; + if (reloc == BFD_RELOC_SPU_PCREL9a + || reloc == BFD_RELOC_SPU_PCREL9b + || reloc == BFD_RELOC_SPU_PCREL16) + pcrel = 1; + if (insn.flag[i] & 1) reloc = BFD_RELOC_SPU_HI16; + else if (insn.flag[i] & 2) reloc = BFD_RELOC_SPU_LO16; + fixP = fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal, + 4, + &insn.exp[i], + pcrel, + reloc); + fixP->tc_fix_data = insn.reloc_arg[i]; + } + dwarf2_emit_insn(4); +} + +static int +calcop (format, param, insn) + struct spu_opcode *format; + const char *param; + struct spu_insn *insn; +{ + int i; + int paren = 0; + int arg; + + for (i = 1; i <= format->arg[0]; i++) + { + arg = format->arg[i]; + syntax_error_arg = i; + + while (ISSPACE(*param)) + param++; + if (*param == 0 || *param == ',') + return 0; + if (arg < A_P) + param = get_reg (param, insn, arg, 1); + else if (arg > A_P) + param = get_imm (param, insn, arg); + else if (arg == A_P) + { + paren++; + if ('(' != *param++) + return 0; + } + + if (!param) + return 0; + + while (ISSPACE(*param)) + param++; + + if (arg != A_P && paren) + { + paren--; + if (')' != *param++) + return 0; + } + else if (i < format->arg[0] + && format->arg[i] != A_P + && format->arg[i+1] != A_P) + { + if (',' != *param++) + { + syntax_error_arg++; + return 0; + } + } + } + while (ISSPACE(*param)) + param++; + return !paren && (*param == 0 || *param == '\n'); +} + +struct reg_name { + int regno; + int length; + char name[32]; +}; +#define REG_NAME(NO,NM) { NO, sizeof(NM)-1, NM } +static struct reg_name reg_name[] = { + REG_NAME(0, "lr"), /* link register */ + REG_NAME(1, "sp"), /* stack pointer */ + REG_NAME(0, "rp"), /* link register */ + REG_NAME(127, "fp"), /* frame pointer */ +}; +static struct reg_name sp_reg_name[] = { +}; +static struct reg_name ch_reg_name[] = { + REG_NAME( 0, "SPU_RdEventStat"), + REG_NAME( 1, "SPU_WrEventMask"), + REG_NAME( 2, "SPU_WrEventAck"), + REG_NAME( 3, "SPU_RdSigNotify1"), + REG_NAME( 4, "SPU_RdSigNotify2"), + REG_NAME( 7, "SPU_WrDec"), + REG_NAME( 8, "SPU_RdDec"), + REG_NAME( 11, "SPU_RdEventStatMask"), /* DD2.0 only */ + REG_NAME( 13, "SPU_RdMachStat"), + REG_NAME( 14, "SPU_WrSRR0"), + REG_NAME( 15, "SPU_RdSRR0"), + REG_NAME( 28, "SPU_WrOutMbox"), + REG_NAME( 29, "SPU_RdInMbox"), + REG_NAME( 30, "SPU_WrOutIntrMbox"), + REG_NAME( 9, "MFC_WrMSSyncReq"), + REG_NAME( 12, "MFC_RdTagMask"), /* DD2.0 only */ + REG_NAME( 16, "MFC_LSA"), + REG_NAME( 17, "MFC_EAH"), + REG_NAME( 18, "MFC_EAL"), + REG_NAME( 19, "MFC_Size"), + REG_NAME( 20, "MFC_TagID"), + REG_NAME( 21, "MFC_Cmd"), + REG_NAME( 22, "MFC_WrTagMask"), + REG_NAME( 23, "MFC_WrTagUpdate"), + REG_NAME( 24, "MFC_RdTagStat"), + REG_NAME( 25, "MFC_RdListStallStat"), + REG_NAME( 26, "MFC_WrListStallAck"), + REG_NAME( 27, "MFC_RdAtomicStat"), +}; +#undef REG_NAME + +static const char * +get_reg (param, insn, arg, accept_expr) + const char *param; + struct spu_insn *insn; + int arg; + int accept_expr; +{ + unsigned regno; + int saw_prefix = 0; + + if (*param == '$') + { + saw_prefix = 1; + param++; + } + + if (arg == A_H) /* Channel */ + { + if ((param[0] == 'c' || param[0] == 'C') + && (param[1] == 'h' || param[1] == 'H') + && ISDIGIT(param[2])) + param += 2; + } + else if (arg == A_S) /* Special purpose register */ + { + if ((param[0] == 's' || param[0] == 'S') + && (param[1] == 'p' || param[1] == 'P') + && ISDIGIT(param[2])) + param += 2; + } + + if (ISDIGIT(*param)) + { + regno = 0; + while (ISDIGIT(*param)) + regno = regno * 10 + *param++ - '0'; + } + else + { + struct reg_name *rn; + unsigned int i, n, l = 0; + + if (arg == A_H) /* Channel */ + { + rn = ch_reg_name; + n = sizeof(ch_reg_name)/sizeof(*ch_reg_name); + } + else if (arg == A_S) /* Special purpose register */ + { + rn = sp_reg_name; + n = sizeof(sp_reg_name)/sizeof(*sp_reg_name); + } + else + { + rn = reg_name; + n = sizeof(reg_name)/sizeof(*reg_name); + } + regno = 128; + for (i = 0; i < n; i++) + if (rn[i].length > l + && 0 == strncasecmp(param, rn[i].name, rn[i].length)) + { + l = rn[i].length; + regno = rn[i].regno; + } + param += l; + } + + if (!use_dd2 + && arg == A_H) + { + if (regno == 11) + as_bad (_("'SPU_RdEventStatMask' (channel 11) is only available in DD2.0 or higher.")); + else if (regno == 12) + as_bad (_("'MFC_RdTagMask' (channel 12) is only available in DD2.0 or higher.")); + } + + if (regno < 128) + { + insn->opcode |= regno << arg_encode[arg].pos; + if ((!saw_prefix && syntax_reg == 1) + || (saw_prefix && syntax_reg == 2)) + syntax_reg |= 4; + syntax_reg |= saw_prefix ? 1 : 2; + return param; + } + if (accept_expr) + { + char *save_ptr; + expressionS ex; + save_ptr = input_line_pointer; + input_line_pointer = (char *)param; + expression (&ex); + param = input_line_pointer; + input_line_pointer = save_ptr; + if (ex.X_op == O_register || ex.X_op == O_constant) + { + insn->opcode |= ex.X_add_number << arg_encode[arg].pos; + return param; + } + } + return 0; +} + +static const char * +get_imm (param, insn, arg) + const char *param; + struct spu_insn *insn; + int arg; +{ + int val; + char *save_ptr; + int low = 0, high = 0; + int reloc_i = insn->reloc_arg[0] >= 0 ? 1 : 0; + + if (strncmp(param, "%lo(", 4) == 0) + { + param += 3; + low = 1; + as_warn (_("Using old style, %%lo(expr), please change to PPC style, expr@l.")); + } + else if (strncmp(param, "%hi(", 4) == 0) + { + param += 3; + high = 1; + as_warn (_("Using old style, %%hi(expr), please change to PPC style, expr@h.")); + } + else if (strncmp(param, "%pic(", 5) == 0) + { + /* Currently we expect %pic(expr) == expr, so do nothing here. + * i.e. for code loaded at address 0 $toc will be 0. */ + param += 4; + } + + if (*param == '$') + { + /* Symbols can start with $, but if this symbol matches a register + * name, it's probably a mistake. The only way to avoid this + * warning is to rename the symbol. */ + struct spu_insn tmp_insn; + char *np; + if ((np = get_reg (param, &tmp_insn, arg, 0))) + syntax_error_param = np; + } + + save_ptr = input_line_pointer; + input_line_pointer = (char *)param; + expression (&insn->exp[reloc_i]); + param = input_line_pointer; + input_line_pointer = save_ptr; + + /* Similar to ppc_elf_suffix in tc-ppc.c. We have so few cases to + * handle we do it inlined here. */ + if (param[0] == '@' && !ISALNUM(param[2]) && param[2] != '@') + { + if (param[1] == 'h' || param[1] == 'H') + { + high = 1; + param += 2; + } + else if (param[1] == 'l' || param[1] == 'L') + { + low = 1; + param += 2; + } + } + + val = insn->exp[reloc_i].X_add_number; + + if (insn->exp[reloc_i].X_op == O_constant) + { + if (emulate_apuasm) + { + /* Convert the value to a format we expect. */ + val <<= arg_encode[arg].rshift; + if (arg == A_U7A) + val = 173 - val; + else if (arg == A_U7B) + val = 155 - val; + } + + if (high) + val = val >> 16; + else if (low) + val = val & 0xffff; + + /* Warn about out of range expressions. */ + { + int hi = arg_encode[arg].hi; + int lo = arg_encode[arg].lo; + int whi = arg_encode[arg].whi; + int wlo = arg_encode[arg].wlo; + if (hi > lo && (val < lo || val > hi)) + as_fatal (_("Constant expression %d out of range, [%d, %d]."), val, lo, hi); + else if (whi > wlo && (val < wlo || val > whi)) + as_warn (_("Constant expression %d out of range, [%d, %d]."), val, wlo, whi); + } + + if (arg == A_U7A) + val = 173 - val; + else if (arg == A_U7B) + val = 155 - val; + + /* Branch hints have a split encoding. Do the bottom part. */ + if (arg == A_S11 || arg == A_S11I) + insn->opcode |= ((val >> 2) & 0x7f); + + insn->opcode |= ((val >> arg_encode[arg].rshift) + & ((1<reloc_arg[reloc_i] = -1; + insn->flag[reloc_i] = 0; + } + else + { + insn->reloc_arg[reloc_i] = arg; + if (high) insn->flag[reloc_i] |= 1; + if (low) insn->flag[reloc_i] |= 2; + } + + return param; +} + +void +md_number_to_chars (buf, val, nbytes) + char *buf; + valueT val; + int nbytes; +{ + number_to_chars_bigendian (buf, val, nbytes); +} + +#define MAX_LITTLENUMS 6 + +/* Turn a string in input_line_pointer into a floating point constant of type + type, and store the appropriate bytes in *litP. The number of LITTLENUMS + emitted is stored in *sizeP . An error message is returned, or NULL on OK. + */ +char * +md_atof (type, litP, sizeP) + char type; + char *litP; + int *sizeP; +{ + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + + switch (type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + case 'x': + case 'X': + prec = 6; + break; + + case 'p': + case 'P': + prec = 6; + break; + + default: + *sizeP = 0; + return _("Bad call to MD_ATOF()"); + } + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + + *sizeP = prec * sizeof (LITTLENUM_TYPE); + for (wordP = words; prec--;) + { + md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + return 0; +} + +int md_short_jump_size = 4; + +void +md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr ATTRIBUTE_UNUSED, to_addr ATTRIBUTE_UNUSED; + fragS *frag; + symbolS *to_symbol; +{ + ptr[0] = (char) 0xc0; + ptr[1] = 0x00; + ptr[2] = 0x00; + ptr[3] = 0x00; + fix_new (frag, + ptr - frag->fr_literal, + 4, + to_symbol, + (offsetT) 0, + 0, + BFD_RELOC_SPU_PCREL16); +} + +int md_long_jump_size = 4; + +void +md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) + char *ptr; + addressT from_addr ATTRIBUTE_UNUSED, to_addr ATTRIBUTE_UNUSED; + fragS *frag; + symbolS *to_symbol; +{ + ptr[0] = (char) 0xc0; + ptr[1] = 0x00; + ptr[2] = 0x00; + ptr[3] = 0x00; + fix_new (frag, + ptr - frag->fr_literal, + 4, + to_symbol, + (offsetT) 0, + 0, + BFD_RELOC_SPU_PCREL16); +} + +int +md_estimate_size_before_relax (fragP, segment_type) + fragS *fragP ATTRIBUTE_UNUSED; + segT segment_type ATTRIBUTE_UNUSED; +{ + as_fatal (_("Relaxation should never occur")); + return (-1); +} + +/* If while processing a fixup, a reloc really needs to be created, + then it is done here. */ + +arelent * +tc_gen_reloc (seg, fixp) + asection *seg ATTRIBUTE_UNUSED; + fixS *fixp; +{ + arelent *reloc; + reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + if (fixp->fx_addsy) + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + else if (fixp->fx_subsy) + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy); + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); + if (reloc->howto == (reloc_howto_type *) NULL) + { + as_bad_where (fixp->fx_file, fixp->fx_line, + _("reloc %d not supported by object file format"), + (int) fixp->fx_r_type); + return NULL; + } + reloc->addend = fixp->fx_addnumber; + return reloc; +} + +/* Round up a section's size to the appropriate boundary. */ + +valueT +md_section_align (seg, size) + segT seg; + valueT size; +{ + int align = bfd_get_section_alignment (stdoutput, seg); + valueT mask = ((valueT) 1 << align) - 1; + + return (size + mask) & ~mask; +} + +/* Where a PC relative offset is calculated from. On the spu they + are calculated from the beginning of the branch instruction. */ + +long +md_pcrel_from (fixp) + fixS *fixp; +{ + switch (fixp->fx_r_type) + { + case BFD_RELOC_SPU_PCREL9a: + case BFD_RELOC_SPU_PCREL9b: + case BFD_RELOC_SPU_PCREL16: + return fixp->fx_frag->fr_address + fixp->fx_where; + default: + abort (); + } + /*NOTREACHED*/ +} + +/* Fill in rs_align_code fragments. */ + +void +spu_handle_align (fragp) + fragS *fragp; +{ + static const unsigned char nop_pattern[8] = { + 0x40, 0x20, 0x00, 0x00, /* even nop */ + 0x00, 0x20, 0x00, 0x00, /* odd nop */ + }; + + int bytes; + char *p; + + if (fragp->fr_type != rs_align_code) + return; + + bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; + p = fragp->fr_literal + fragp->fr_fix; + + if (bytes & 3) + { + int fix = bytes & 3; + memset (p, 0, fix); + p += fix; + bytes -= fix; + fragp->fr_fix += fix; + } + if (bytes & 4) + { + memcpy (p, &nop_pattern[4], 4); + p += 4; + bytes -= 4; + fragp->fr_fix += 4; + } + + memcpy (p, nop_pattern, 8); + fragp->fr_var = 8; +} + +void +md_apply_fix3 (fixP, valP, seg) + fixS *fixP; + valueT * valP; + segT seg ATTRIBUTE_UNUSED; +{ + unsigned int res; + long val = (long)*valP; + char *place = fixP->fx_where + fixP->fx_frag->fr_literal; + + if (fixP->fx_addsy != NULL) + { + /* Hack around bfd_install_relocation brain damage. */ + if (fixP->fx_pcrel) + val += fixP->fx_frag->fr_address + fixP->fx_where; + } + + fixP->fx_addnumber = val; + + if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) + { + fixP->fx_done = 1; + res = 0; + if (fixP->tc_fix_data > A_P) + { + int hi = arg_encode[fixP->tc_fix_data].hi; + int lo = arg_encode[fixP->tc_fix_data].lo; + if (hi > lo && (val < lo || val > hi)) + as_bad_where (fixP->fx_file, fixP->fx_line, + "Relocation doesn't fit. (relocation value = 0x%x)", + (int) val); + } + switch (fixP->fx_r_type) + { + case 0: + break; + case BFD_RELOC_SPU_IMM7: + res = (val & 0x7f) << 14; + break; + case BFD_RELOC_SPU_IMM8: + res = (val & 0xff) << 14; + break; + case BFD_RELOC_SPU_IMM10: + res = (val & 0xcff) << 14; + break; + case BFD_RELOC_SPU_IMM10W: + res = (val & 0xcff0) << 10; + break; + case BFD_RELOC_SPU_IMM16: + res = (val & 0xffff) << 7; + break; + case BFD_RELOC_SPU_IMM16W: + res = (val & 0x3fffc) << 5; + break; + case BFD_RELOC_SPU_IMM18: + res = (val & 0x3ffff) << 7; + break; + case BFD_RELOC_16: +#if 0 + val = fixP->fx_offset; + number_to_chars_bigendian (place, val, 2); +#endif + res = val; + break; + case BFD_RELOC_32: + res = val; + break; + case BFD_RELOC_SPU_PCREL9a: + res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 14); + break; + case BFD_RELOC_SPU_PCREL9b: + res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 5); + break; + case BFD_RELOC_SPU_PCREL16: + res = (val & 0x3fffc) << 5; + break; + + default: + as_bad_where (fixP->fx_file, fixP->fx_line, + _("reloc %d not supported by object file format"), + (int) fixP->fx_r_type); + abort (); + } + if (res != 0) + { + place[0] |= (res >> 24) & 0xff; + place[1] |= (res >> 16) & 0xff; + place[2] |= (res >> 8) & 0xff; + place[3] |= (res) & 0xff; + } + } +} diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/gas/config/tc-spu.h binutils/gas/config/tc-spu.h --- binutils-2.16.1/gas/config/tc-spu.h 1970-01-01 01:00:00.000000000 +0100 +++ binutils/gas/config/tc-spu.h 2006-03-30 01:23:21.000000000 +0200 @@ -0,0 +1,107 @@ +/* spu.h -- Assembler for spu */ + +/* (C) Copyright + Sony Computer Entertainment, Inc., + Toshiba Corporation, + International Business Machines Corporation, + 2001,2002,2003,2004,2005. + + 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 file 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 file; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#define TC_SPU + +#ifdef OBJ_ELF +#define TARGET_FORMAT "elf32-spu" +#define TARGET_ARCH bfd_arch_spu +#define TARGET_NAME "elf32-spu" +#endif + +#define TARGET_BYTES_BIG_ENDIAN 1 + +#ifndef TARGET_NAME +#define TARGET_NAME "coff-spu" +#endif + +#ifndef TARGET_ARCH +#define TARGET_ARCH bfd_arch_spu +#endif + +#define COFF_MAGIC SPU_MAGIC +#define BFD_ARCH bfd_arch_spu + +#define NEED_FX_R_TYPE +#define TC_KEEP_FX_OFFSET +/* #define TC_CONS_RELOC RELOC_32 */ + +/* If defined, fixS will have a member named tc_fix_data of this type. */ +#define TC_FIX_TYPE int +#define TC_INIT_FIX_DATA(FIXP) ((FIXP)->tc_fix_data = 0) + +#define TC_FIX_ADJUSTABLE(FIXP) 0 + +/* Values passed to md_apply_fix3 don't include symbol values. */ +#define MD_APPLY_SYM_VALUE(FIX) 0 + +/* This expression evaluates to false if the relocation is for a local + object for which we still want to do the relocation at runtime. + True if we are willing to perform this relocation while building + the .o file. This is only used for pcrel relocations. */ + +#define TC_RELOC_RTSYM_LOC_FIXUP(FIX) \ + ((FIX)->fx_addsy == NULL \ + || (! S_IS_EXTERNAL ((FIX)->fx_addsy) \ + && ! S_IS_WEAK ((FIX)->fx_addsy) \ + && S_IS_DEFINED ((FIX)->fx_addsy) \ + && ! S_IS_COMMON ((FIX)->fx_addsy))) + +/* The spu uses pseudo-ops with no leading period. */ +#define NO_PSEUDO_DOT 1 + +/* Don't warn on word overflow; it happens on %hi relocs. */ +#undef WARN_SIGNED_OVERFLOW_WORD + +#define md_convert_frag(b,s,f) {as_fatal (_("spu convert_frag\n"));} + +/* We don't need to do anything special for undefined symbols. */ +#define md_undefined_symbol(s) 0 + +/* We have no special operand handling. */ +#define md_operand(e) + +/* Fill in rs_align_code fragments. */ +extern void spu_handle_align PARAMS ((fragS *)); +#define HANDLE_ALIGN(frag) spu_handle_align (frag) + +#define MAX_MEM_FOR_RS_ALIGN_CODE (7 + 8) + +#ifdef SPUCOFF + +/* Whether a reloc should be output. */ +#define TC_COUNT_RELOC(fixp) ((fixp)->fx_addsy != NULL || (fixp)->fx_subsy != NULL) + +/* Get the BFD reloc type to use for a gas fixS structure. */ +#define TC_COFF_FIX2RTYPE(fixp) tc_coff_fix2rtype (fixp) + +/* No special hook needed for symbols. */ +#define tc_coff_symbol_emit_hook(s) + +/* Align sections to a four byte boundary. */ +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#define SUB_SEGMENT_ALIGN(SEG) max (section_alignment[(int) (SEG)], 4) + +#endif /* SPUCOFF */ diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/gas/configure.tgt binutils/gas/configure.tgt --- binutils-2.16.1/gas/configure.tgt 2005-01-31 18:18:51.000000000 +0100 +++ binutils/gas/configure.tgt 2006-03-30 01:23:21.000000000 +0200 @@ -58,6 +58,7 @@ pj*) cpu_type=pj endian=big ;; powerpc*le*) cpu_type=ppc endian=little ;; powerpc*) cpu_type=ppc endian=big ;; + ppu*) cpu_type=ppc endian=big ;; rs6000*) cpu_type=ppc ;; s390x*) cpu_type=s390 arch=s390x ;; s390*) cpu_type=s390 arch=s390 ;; @@ -338,6 +339,7 @@ ppc-*-macos*) fmt=coff em=macos ;; ppc-*-nto*) fmt=elf ;; ppc-*-kaos*) fmt=elf ;; + ppc-*-lv2*) fmt=elf ;; ppc-*-lynxos*) fmt=elf em=lynx ;; s390-*-linux-*) fmt=elf em=linux ;; @@ -385,6 +387,9 @@ strongarm-*-elf) fmt=elf ;; strongarm-*-kaos*) fmt=elf ;; + spu-*-elf) fmt=elf bfd_gas=yes ;; + spu-*-lv2) fmt=elf bfd_gas=yes ;; + tic30-*-*aout*) fmt=aout bfd_gas=yes ;; tic30-*-*coff*) fmt=coff bfd_gas=yes ;; tic4x-*-* | c4x-*-*) fmt=coff bfd_gas=yes ;; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/gas/testsuite/gas/sh/sh64/err-dsp.s binutils/gas/testsuite/gas/sh/sh64/err-dsp.s --- binutils-2.16.1/gas/testsuite/gas/sh/sh64/err-dsp.s 2004-03-04 02:24:21.000000000 +0100 +++ binutils/gas/testsuite/gas/sh/sh64/err-dsp.s 2004-05-22 01:10:38.000000000 +0200 @@ -11,5 +11,5 @@ .text start: ldc r3,mod ! { dg-error "invalid operands" } - ldre @(16,pc) ! { dg-error "opcode not valid for this cpu variant" } + ldre @(16,pc) ! { dg-error "unknown opcode" } lds r4,a0 ! { dg-error "invalid operands" } diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/include/bfdlink.h binutils/include/bfdlink.h --- binutils-2.16.1/include/bfdlink.h 2005-03-03 12:58:00.000000000 +0100 +++ binutils/include/bfdlink.h 2006-03-30 01:23:21.000000000 +0200 @@ -416,6 +416,12 @@ /* Start and end of RELRO region. */ bfd_vma relro_start, relro_end; + + /* CELL LOCAL Begin */ + /* for IBM STI BPA */ + /* TRUE if SPU file is plugin. */ + bfd_boolean spuplugin; + /* CELL LOCAL End */ }; /* This structures holds a set of callback functions. These are diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/include/dis-asm.h binutils/include/dis-asm.h --- binutils-2.16.1/include/dis-asm.h 2005-03-03 12:58:01.000000000 +0100 +++ binutils/include/dis-asm.h 2006-03-30 01:23:21.000000000 +0200 @@ -263,6 +263,7 @@ extern int print_insn_rs6000 (bfd_vma, disassemble_info *); extern int print_insn_s390 (bfd_vma, disassemble_info *); extern int print_insn_sh (bfd_vma, disassemble_info *); +extern int print_insn_spu (bfd_vma, disassemble_info *); extern int print_insn_tic30 (bfd_vma, disassemble_info *); extern int print_insn_tic4x (bfd_vma, disassemble_info *); extern int print_insn_tic54x (bfd_vma, disassemble_info *); diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/include/elf/common.h binutils/include/elf/common.h --- binutils-2.16.1/include/elf/common.h 2004-10-08 15:55:08.000000000 +0200 +++ binutils/include/elf/common.h 2006-03-30 01:23:21.000000000 +0200 @@ -118,6 +118,7 @@ #define EM_PPC 20 /* PowerPC */ #define EM_PPC64 21 /* 64-bit PowerPC */ #define EM_S390 22 /* IBM S/390 */ +#define EM_SPU 23 /* Sony SPU */ #define EM_V800 36 /* NEC V800 series */ #define EM_FR20 37 /* Fujitsu FR20 */ diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/include/elf/spu.h binutils/include/elf/spu.h --- binutils-2.16.1/include/elf/spu.h 1970-01-01 01:00:00.000000000 +0100 +++ binutils/include/elf/spu.h 2006-03-30 01:23:21.000000000 +0200 @@ -0,0 +1,87 @@ +/* SPU ELF support for BFD. + Copyright 1999, 2000 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _ELF_SPU_H +#define _ELF_SPU_H + +#include "elf/reloc-macros.h" + +/* elf32-spu.c depends on these being consecutive. */ +START_RELOC_NUMBERS (elf_spu_reloc_type) + RELOC_NUMBER (R_SPU_NONE, 0) + RELOC_NUMBER (R_SPU_ADDR10, 1) + RELOC_NUMBER (R_SPU_ADDR16, 2) + RELOC_NUMBER (R_SPU_ADDR16_HI, 3) + RELOC_NUMBER (R_SPU_ADDR16_LO, 4) + RELOC_NUMBER (R_SPU_ADDR18, 5) + RELOC_NUMBER (R_SPU_GLOB_DAT, 6) + RELOC_NUMBER (R_SPU_REL16, 7) + RELOC_NUMBER (R_SPU_ADDR7, 8) + RELOC_NUMBER (R_SPU_REL9, 9) + RELOC_NUMBER (R_SPU_REL9I, 10) + RELOC_NUMBER (R_SPU_ADDR10I, 11) + RELOC_NUMBER (R_SPU_ADDR16I, 12) +END_RELOC_NUMBERS (R_SPU_max) + + +/* Processor specific flags for the ELF header e_flags field. */ + +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + + /* CYGNUS local bits below */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag */ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib flag */ + +/* Processor specific section headers, sh_type field */ + +#define SHT_ORDERED SHT_HIPROC /* Link editor is to sort the \ + entries in this section \ + based on the address \ + specified in the associated \ + symbol table entry. */ + +/* Processor specific section flags, sh_flags field */ + +#define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude \ + this section from executable \ + and shared objects that it \ + builds when those objects \ + are not to be furhter \ + relocated. */ + +#if (defined(BPA)) +/* Program header extensions */ +#define PT_SPU_INFO 0x70000000 /* SPU Dynamic Object Information */ +#endif + +/* SPU plugin information */ +#define SPU_PLUGIN_NAMESZ 8 +#define SPU_PLUGIN_NAME "SPUNAME" +#define SPU_PTNOTE_SPUNAME ".note.spu_name" +#define SPU_PLUGIN_LOOKUPNAMESZ 32 + +typedef struct { + unsigned long namesz; + unsigned long descsz; + unsigned long type; + char name[SPU_PLUGIN_NAMESZ]; + char lookupname[SPU_PLUGIN_LOOKUPNAMESZ]; +} SPUPLUGIN_INFO; + +#endif /* _ELF_SPU_H */ diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/include/opcode/ppc.h binutils/include/opcode/ppc.h --- binutils-2.16.1/include/opcode/ppc.h 2004-09-09 14:42:37.000000000 +0200 +++ binutils/include/opcode/ppc.h 2006-03-30 01:23:21.000000000 +0200 @@ -134,6 +134,9 @@ /* Opcode is supported by machine check APU. */ #define PPC_OPCODE_RFMCI 0x800000 +/* Opcode is suppered by CELL PPU architecture. */ +#define PPC_OPCODE_CELLPPU PPC_OPCODE_CLASSIC + /* A macro to extract the major opcode from an instruction. */ #define PPC_OP(i) (((i) >> 26) & 0x3f) diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/include/opcode/spu-insns.h binutils/include/opcode/spu-insns.h --- binutils-2.16.1/include/opcode/spu-insns.h 1970-01-01 01:00:00.000000000 +0100 +++ binutils/include/opcode/spu-insns.h 2006-03-30 01:23:21.000000000 +0200 @@ -0,0 +1,412 @@ + +/* (C) Copyright + Sony Computer Entertainment, Inc., + Toshiba Corporation, + International Business Machines Corporation, + 2001,2002,2003,2004,2005. + + 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 file 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 file; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* SPU Opcode Table + +-=-=-= FORMAT =-=-=- + + +----+-------+-------+-------+-------+ +------------+-------+-------+-------+ +RRR | op | RC | RB | RA | RT | RI7 | op | I7 | RA | RT | + +----+-------+-------+-------+-------+ +------------+-------+-------+-------+ + 0 3 1 1 2 3 0 1 1 2 3 + 0 7 4 1 0 7 4 1 + + +-----------+--------+-------+-------+ +---------+----------+-------+-------+ +RI8 | op | I8 | RA | RT | RI10 | op | I10 | RA | RT | + +-----------+--------+-------+-------+ +---------+----------+-------+-------+ + 0 9 1 2 3 0 7 1 2 3 + 7 4 1 7 4 1 + + +----------+-----------------+-------+ +--------+-------------------+-------+ +RI16 | op | I16 | RT | RI18 | op | I18 | RT | + +----------+-----------------+-------+ +--------+-------------------+-------+ + 0 8 2 3 0 6 2 3 + 4 1 4 1 + + +------------+-------+-------+-------+ +-------+--+-----------------+-------+ +RR | op | RB | RA | RT | LBT | op |RO| I16 | RO | + +------------+-------+-------+-------+ +-------+--+-----------------+-------+ + 0 1 1 2 3 0 6 8 2 3 + 0 7 4 1 4 1 + + +------------+----+--+-------+-------+ + LBTI | op | // |RO| RA | RO | + +------------+----+--+-------+-------+ + 0 1 1 1 2 3 + 0 5 7 4 1 + +-=-=-= OPCODE =-=-=- + +OPCODE field specifies the most significant 11bit of the instruction. Some formats don't have 11bits for opcode field, and in this +case, bit field other than op are defined as 0s. For example, opcode of fma instruction which is RRR format is defined as 0x700, +since 0x700 -> 11'b11100000000, this means opcode is 4'b1110, and other 7bits are defined as 7'b0000000. + +-=-=-= ASM_FORMAT =-=-=- + +RRR category RI7 category + ASM_RRR mnemonic RC, RA, RB, RT ASM_RI4 mnemonic RT, RA, I4 + ASM_RI7 mnemonic RT, RA, I7 + +RI8 category RI10 category + ASM_RUI8 mnemonic RT, RA, UI8 ASM_AI10 mnemonic RA, I10 + ASM_RI10 mnemonic RT, RA, R10 + ASM_RI10IDX mnemonic RT, I10(RA) + +RI16 category RI18 category + ASM_I16W mnemonic I16W ASM_RI18 mnemonic RT, I18 + ASM_RI16 mnemonic RT, I16 + ASM_RI16W mnemonic RT, I16W + +RR category LBT category + ASM_MFSPR mnemonic RT, SA ASM_LBT mnemonic brinst, brtarg + ASM_MTSPR mnemonic SA, RT + ASM_NOOP mnemonic LBTI category + ASM_RA mnemonic RA ASM_LBTI mnemonic brinst, RA + ASM_RAB mnemonic RA, RB + ASM_RDCH mnemonic RT, CA + ASM_RR mnemonic RT, RA, RB + ASM_RT mnemonic RT + ASM_RTA mnemonic RT, RA + ASM_WRCH mnemonic CA, RT + +Note that RRR instructions have the names for RC and RT reversed from +what's in the ISA, in order to put RT in the same position it appears +for other formats. + +-=-=-= DEPENDENCY =-=-=- + +DEPENDENCY filed consists of 5 digits. This represents which register is used as source and which register is used as target. +The first(most significant) digit is always 0. Then it is followd by RC, RB, RA and RT digits. +If the digit is 0, this means the corresponding register is not used in the instruction. +If the digit is 1, this means the corresponding register is used as a source in the instruction. +If the digit is 2, this means the corresponding register is used as a target in the instruction. +If the digit is 3, this means the corresponding register is used as both source and target in the instruction. +For example, fms instruction has 00113 as the DEPENDENCY field. This means RC is not used in this operation, RB and RA are +used as sources and RT is the target. + +-=-=-= PIPE =-=-=- + +This field shows which execution pipe is used for the instruction + +pipe0 execution pipelines: + FP6 SP floating pipeline + FP7 integer operations executed in SP floating pipeline + FPD DP floating pipeline + FX2 FXU pipeline + FX3 Rotate/Shift pipeline + FXB Byte pipeline + NOP No pipeline + +pipe1 execution pipelines: + BR Branch pipeline + LNOP No pipeline + LS Load/Store pipeline + SHUF Shuffle pipeline + SPR SPR/CH pipeline + +*/ + +#define _A0() {0} +#define _A1(a) {1,a} +#define _A2(a,b) {2,a,b} +#define _A3(a,b,c) {3,a,b,c} +#define _A4(a,b,c,d) {4,a,b,c,d} + +/* TAG FORMAT OPCODE MNEMONIC ASM_FORMAT DEPENDENCY PIPE COMMENT */ +/* 0[RC][RB][RA][RT] */ +/* 1:src, 2:target */ + +APUOP(M_BR, RI16, 0x190, "br", _A1(A_R18), 00000, BR) /* BRel IP<-IP+I16 */ +APUOP(M_BRSL, RI16, 0x198, "brsl", _A2(A_T,A_R18), 00002, BR) /* BRelSetLink RT,IP<-IP,IP+I16 */ +APUOP(M_BRA, RI16, 0x180, "bra", _A1(A_S18), 00000, BR) /* BRAbs IP<-I16 */ +APUOP(M_BRASL, RI16, 0x188, "brasl", _A2(A_T,A_S18), 00002, BR) /* BRAbsSetLink RT,IP<-IP,I16 */ +APUOP(M_FSMBI, RI16, 0x194, "fsmbi", _A2(A_T,A_X16), 00002, SHUF) /* FormSelMask%I RT<-fsm(I16) */ +APUOP(M_LQA, RI16, 0x184, "lqa", _A2(A_T,A_S18), 00002, LS) /* LoadQAbs RT<-M[I16] */ +APUOP(M_LQR, RI16, 0x19C, "lqr", _A2(A_T,A_R18), 00002, LS) /* LoadQRel RT<-M[IP+I16] */ +APUOP(M_STOP, RR, 0x000, "stop", _A0(), 00000, BR) /* STOP stop */ +APUOP(M_STOP2, RR, 0x000, "stop", _A1(A_U14), 00000, BR) /* STOP stop */ +APUOP(M_STOPD, RR, 0x140, "stopd", _A3(A_T,A_A,A_B), 00111, BR) /* STOPD stop (with register dependencies) */ +APUOP(M_LNOP, RR, 0x001, "lnop", _A0(), 00000, LNOP) /* LNOP no_operation */ +APUOP(M_SYNC, RR, 0x002, "sync", _A0(), 00000, BR) /* SYNC flush_pipe */ +APUOP(M_DSYNC, RR, 0x003, "dsync", _A0(), 00000, BR) /* DSYNC flush_store_queue */ +APUOP(M_MFSPR, RR, 0x00c, "mfspr", _A2(A_T,A_S), 00002, SPR) /* MFSPR RT<-SA */ +APUOP(M_RDCH, RR, 0x00d, "rdch", _A2(A_T,A_H), 00002, SPR) /* ReaDCHannel RT<-CA:data */ +APUOP(M_RCHCNT, RR, 0x00f, "rchcnt", _A2(A_T,A_H), 00002, SPR) /* ReaDCHanCouNT RT<-CA:count */ +APUOP(M_HBRA, LBT, 0x080, "hbra", _A2(A_S11,A_S18), 00000, LS) /* HBRA BTB[B9]<-M[I16] */ +APUOP(M_HBRR, LBT, 0x090, "hbrr", _A2(A_S11,A_R18), 00000, LS) /* HBRR BTB[B9]<-M[IP+I16] */ +APUOP(M_BRZ, RI16, 0x100, "brz", _A2(A_T,A_R18), 00001, BR) /* BRZ IP<-IP+I16_if(RT) */ +APUOP(M_BRNZ, RI16, 0x108, "brnz", _A2(A_T,A_R18), 00001, BR) /* BRNZ IP<-IP+I16_if(RT) */ +APUOP(M_BRHZ, RI16, 0x110, "brhz", _A2(A_T,A_R18), 00001, BR) /* BRHZ IP<-IP+I16_if(RT) */ +APUOP(M_BRHNZ, RI16, 0x118, "brhnz", _A2(A_T,A_R18), 00001, BR) /* BRHNZ IP<-IP+I16_if(RT) */ +APUOP(M_STQA, RI16, 0x104, "stqa", _A2(A_T,A_S18), 00001, LS) /* SToreQAbs M[I16]<-RT */ +APUOP(M_STQR, RI16, 0x11C, "stqr", _A2(A_T,A_R18), 00001, LS) /* SToreQRel M[IP+I16]<-RT */ +APUOP(M_MTSPR, RR, 0x10c, "mtspr", _A2(A_S,A_T), 00001, SPR) /* MTSPR SA<-RT */ +APUOP(M_WRCH, RR, 0x10d, "wrch", _A2(A_H,A_T), 00001, SPR) /* ChanWRite CA<-RT */ +APUOP(M_LQD, RI10, 0x1a0, "lqd", _A4(A_T,A_S14,A_P,A_A), 00012, LS) /* LoadQDisp RT<-M[Ra+I10] */ +APUOP(M_BI, RR, 0x1a8, "bi", _A1(A_A), 00010, BR) /* BI IP<-RA */ +APUOP(M_BISL, RR, 0x1a9, "bisl", _A2(A_T,A_A), 00012, BR) /* BISL RT,IP<-IP,RA */ +APUOP(M_IRET, RR, 0x1aa, "iret", _A1(A_A), 00010, BR) /* IRET IP<-SRR0 */ +APUOP(M_IRET2, RR, 0x1aa, "iret", _A0(), 00010, BR) /* IRET IP<-SRR0 */ +APUOP(M_BISLED, RR, 0x1ab, "bisled", _A2(A_T,A_A), 00012, BR) /* BISLED RT,IP<-IP,RA_if(ext) */ +APUOP(M_HBR, LBTI, 0x1ac, "hbr", _A2(A_S11I,A_A), 00010, LS) /* HBR BTB[B9]<-M[Ra] */ +APUOP(M_FREST, RR, 0x1b8, "frest", _A2(A_T,A_A), 00012, SHUF) /* FREST RT<-recip(RA) */ +APUOP(M_FRSQEST, RR, 0x1b9, "frsqest", _A2(A_T,A_A), 00012, SHUF) /* FRSQEST RT<-rsqrt(RA) */ +APUOP(M_FSM, RR, 0x1b4, "fsm", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */ +APUOP(M_FSMH, RR, 0x1b5, "fsmh", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */ +APUOP(M_FSMB, RR, 0x1b6, "fsmb", _A2(A_T,A_A), 00012, SHUF) /* FormSelMask% RT<-expand(Ra) */ +APUOP(M_GB, RR, 0x1b0, "gb", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */ +APUOP(M_GBH, RR, 0x1b1, "gbh", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */ +APUOP(M_GBB, RR, 0x1b2, "gbb", _A2(A_T,A_A), 00012, SHUF) /* GatherBits% RT<-gather(RA) */ +APUOP(M_CBD, RI7, 0x1f4, "cbd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */ +APUOP(M_CHD, RI7, 0x1f5, "chd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */ +APUOP(M_CWD, RI7, 0x1f6, "cwd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */ +APUOP(M_CDD, RI7, 0x1f7, "cdd", _A4(A_T,A_U7,A_P,A_A), 00012, SHUF) /* genCtl%%insD RT<-sta(Ra+I4,siz) */ +APUOP(M_ROTQBII, RI7, 0x1f8, "rotqbii", _A3(A_T,A_A,A_U3), 00012, SHUF) /* ROTQBII RT<-RA<<I10) */ +APUOP(M_CGTHI, RI10, 0x268, "cgthi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CGT%I RT<-(RA>I10) */ +APUOP(M_CGTI, RI10, 0x260, "cgti", _A3(A_T,A_A,A_S10), 00012, FX2) /* CGT%I RT<-(RA>I10) */ +APUOP(M_CLGTBI, RI10, 0x2f0, "clgtbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CLGT%I RT<-(RA>I10) */ +APUOP(M_CLGTHI, RI10, 0x2e8, "clgthi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CLGT%I RT<-(RA>I10) */ +APUOP(M_CLGTI, RI10, 0x2e0, "clgti", _A3(A_T,A_A,A_S10), 00012, FX2) /* CLGT%I RT<-(RA>I10) */ +APUOP(M_CEQBI, RI10, 0x3f0, "ceqbi", _A3(A_T,A_A,A_S10B), 00012, FX2) /* CEQ%I RT<-(RA=I10) */ +APUOP(M_CEQHI, RI10, 0x3e8, "ceqhi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CEQ%I RT<-(RA=I10) */ +APUOP(M_CEQI, RI10, 0x3e0, "ceqi", _A3(A_T,A_A,A_S10), 00012, FX2) /* CEQ%I RT<-(RA=I10) */ +APUOP(M_HGTI, RI10, 0x278, "hgti", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltGTI halt_if(RA>I10) */ +APUOP(M_HGTI2, RI10, 0x278, "hgti", _A2(A_A,A_S10), 00010, FX2) /* HaltGTI halt_if(RA>I10) */ +APUOP(M_HLGTI, RI10, 0x2f8, "hlgti", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltLGTI halt_if(RA>I10) */ +APUOP(M_HLGTI2, RI10, 0x2f8, "hlgti", _A2(A_A,A_S10), 00010, FX2) /* HaltLGTI halt_if(RA>I10) */ +APUOP(M_HEQI, RI10, 0x3f8, "heqi", _A3(A_T,A_A,A_S10), 00010, FX2) /* HaltEQImm halt_if(RA=I10) */ +APUOP(M_HEQI2, RI10, 0x3f8, "heqi", _A2(A_A,A_S10), 00010, FX2) /* HaltEQImm halt_if(RA=I10) */ +APUOP(M_MPYI, RI10, 0x3a0, "mpyi", _A3(A_T,A_A,A_S10), 00012, FP7) /* MPYI RT<-RA*I10 */ +APUOP(M_MPYUI, RI10, 0x3a8, "mpyui", _A3(A_T,A_A,A_S10), 00012, FP7) /* MPYUI RT<-RA*I10 */ +APUOP(M_CFLTS, RI8, 0x3b0, "cflts", _A3(A_T,A_A,A_U7A), 00012, FP7) /* CFLTS RT<-int(RA,I8) */ +APUOP(M_CFLTU, RI8, 0x3b2, "cfltu", _A3(A_T,A_A,A_U7A), 00012, FP7) /* CFLTU RT<-int(RA,I8) */ +APUOP(M_CSFLT, RI8, 0x3b4, "csflt", _A3(A_T,A_A,A_U7B), 00012, FP7) /* CSFLT RT<-flt(RA,I8) */ +APUOP(M_CUFLT, RI8, 0x3b6, "cuflt", _A3(A_T,A_A,A_U7B), 00012, FP7) /* CUFLT RT<-flt(RA,I8) */ +APUOP(M_FESD, RR, 0x3b8, "fesd", _A2(A_T,A_A), 00012, FPD) /* FESD RT<-double(RA) */ +APUOP(M_FRDS, RR, 0x3b9, "frds", _A2(A_T,A_A), 00012, FPD) /* FRDS RT<-single(RA) */ +APUOP(M_FSCRRD, RR, 0x398, "fscrrd", _A1(A_T), 00002, FPD) /* FSCRRD RT<-FP_status */ +APUOP(M_FSCRWR, RR, 0x3ba, "fscrwr", _A2(A_T,A_A), 00010, FP7) /* FSCRWR FP_status<-RA */ +APUOP(M_FSCRWR2, RR, 0x3ba, "fscrwr", _A1(A_A), 00010, FP7) /* FSCRWR FP_status<-RA */ +APUOP(M_CLZ, RR, 0x2a5, "clz", _A2(A_T,A_A), 00012, FX2) /* CLZ RT<-clz(RA) */ +APUOP(M_CNTB, RR, 0x2b4, "cntb", _A2(A_T,A_A), 00012, FXB) /* CNT RT<-pop(RA) */ +APUOP(M_XSBH, RR, 0x2b6, "xsbh", _A2(A_T,A_A), 00012, FX2) /* eXtSignBtoH RT<-sign_ext(RA) */ +APUOP(M_XSHW, RR, 0x2ae, "xshw", _A2(A_T,A_A), 00012, FX2) /* eXtSignHtoW RT<-sign_ext(RA) */ +APUOP(M_XSWD, RR, 0x2a6, "xswd", _A2(A_T,A_A), 00012, FX2) /* eXtSignWtoD RT<-sign_ext(RA) */ +APUOP(M_ROTI, RI7, 0x078, "roti", _A3(A_T,A_A,A_S7N), 00012, FX3) /* ROT%I RT<-RA<<RB) */ +APUOP(M_CGTB, RR, 0x250, "cgtb", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */ +APUOP(M_CGTH, RR, 0x248, "cgth", _A3(A_T,A_A,A_B), 00112, FX2) /* CGT% RT<-(RA>RB) */ +APUOP(M_CLGT, RR, 0x2c0, "clgt", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */ +APUOP(M_CLGTB, RR, 0x2d0, "clgtb", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */ +APUOP(M_CLGTH, RR, 0x2c8, "clgth", _A3(A_T,A_A,A_B), 00112, FX2) /* CLGT% RT<-(RA>RB) */ +APUOP(M_CEQ, RR, 0x3c0, "ceq", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */ +APUOP(M_CEQB, RR, 0x3d0, "ceqb", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */ +APUOP(M_CEQH, RR, 0x3c8, "ceqh", _A3(A_T,A_A,A_B), 00112, FX2) /* CEQ% RT<-(RA=RB) */ +APUOP(M_HGT, RR, 0x258, "hgt", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltGT halt_if(RA>RB) */ +APUOP(M_HGT2, RR, 0x258, "hgt", _A2(A_A,A_B), 00110, FX2) /* HaltGT halt_if(RA>RB) */ +APUOP(M_HLGT, RR, 0x2d8, "hlgt", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltLGT halt_if(RA>RB) */ +APUOP(M_HLGT2, RR, 0x2d8, "hlgt", _A2(A_A,A_B), 00110, FX2) /* HaltLGT halt_if(RA>RB) */ +APUOP(M_HEQ, RR, 0x3d8, "heq", _A3(A_T,A_A,A_B), 00110, FX2) /* HaltEQ halt_if(RA=RB) */ +APUOP(M_HEQ2, RR, 0x3d8, "heq", _A2(A_A,A_B), 00110, FX2) /* HaltEQ halt_if(RA=RB) */ +APUOP(M_FCEQ, RR, 0x3c2, "fceq", _A3(A_T,A_A,A_B), 00112, FX2) /* FCEQ RT<-(RA=RB) */ +APUOP(M_FCMEQ, RR, 0x3ca, "fcmeq", _A3(A_T,A_A,A_B), 00112, FX2) /* FCMEQ RT<-(|RA|=|RB|) */ +APUOP(M_FCGT, RR, 0x2c2, "fcgt", _A3(A_T,A_A,A_B), 00112, FX2) /* FCGT RT<-(RA>16 */ +APUOP(M_MPYU, RR, 0x3cc, "mpyu", _A3(A_T,A_A,A_B), 00112, FP7) /* MPYU RT<-RA*RB */ +APUOP(M_FI, RR, 0x3d4, "fi", _A3(A_T,A_A,A_B), 00112, FP7) /* FInterpolate RT<-f(RA,RB) */ +APUOP(M_ROT, RR, 0x058, "rot", _A3(A_T,A_A,A_B), 00112, FX3) /* ROT% RT<-RA<<> (32-size)) +#define UNSIGNED_EXTRACT(insn,size,pos) (((insn) >> pos) & ((1 << size)-1)) + +#define DECODE_INSN_RT(insn) (insn & 0x7f) +#define DECODE_INSN_RA(insn) ((insn >> 7) & 0x7f) +#define DECODE_INSN_RB(insn) ((insn >> 14) & 0x7f) +#define DECODE_INSN_RC(insn) ((insn >> 21) & 0x7f) + +#define DECODE_INSN_I10(insn) SIGNED_EXTRACT(insn,10,14) +#define DECODE_INSN_U10(insn) UNSIGNED_EXTRACT(insn,10,14) + +/* For branching, immediate loads, hbr and lqa/stqa. */ +#define DECODE_INSN_I16(insn) SIGNED_EXTRACT(insn,16,7) +#define DECODE_INSN_U16(insn) UNSIGNED_EXTRACT(insn,16,7) + +/* for stop */ +#define DECODE_INSN_U14(insn) UNSIGNED_EXTRACT(insn,14,0) + +/* For ila */ +#define DECODE_INSN_I18(insn) SIGNED_EXTRACT(insn,18,7) +#define DECODE_INSN_U18(insn) UNSIGNED_EXTRACT(insn,18,7) + +/* For rotate and shift and generate control mask */ +#define DECODE_INSN_I7(insn) SIGNED_EXTRACT(insn,7,14) +#define DECODE_INSN_U7(insn) UNSIGNED_EXTRACT(insn,7,14) + +/* For float <-> int conversion */ +#define DECODE_INSN_I8(insn) SIGNED_EXTRACT(insn,8,14) +#define DECODE_INSN_U8(insn) UNSIGNED_EXTRACT(insn,8,14) + +/* For hbr */ +#define DECODE_INSN_I9a(insn) ((SIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0)) +#define DECODE_INSN_I9b(insn) ((SIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0)) +#define DECODE_INSN_U9a(insn) ((UNSIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0)) +#define DECODE_INSN_U9b(insn) ((UNSIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0)) + diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/Makefile.am binutils/ld/Makefile.am --- binutils-2.16.1/ld/Makefile.am 2005-01-20 20:37:49.000000000 +0100 +++ binutils/ld/Makefile.am 2006-03-30 01:23:21.000000000 +0200 @@ -151,6 +151,7 @@ eelf32_i860.o \ eelf32_sparc.o \ eelf32_sparc_vxworks.o \ + eelf32_spu.o \ eelf32b4300.o \ eelf32bfin.o \ eelf32bfinfd.o \ @@ -373,6 +374,7 @@ ez8002.o ALL_64_EMULATIONS = \ + eelf64_lv2.o \ eelf64_aix.o \ eelf64_ia64.o \ eelf64_ia64_fbsd.o \ @@ -654,6 +656,9 @@ $(srcdir)/emultempl/vxworks.em $(srcdir)/emultempl/elf32.em \ $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32_sparc_vxworks "$(tdir_elf32_sparc_vxworks)" +eelf32_spu.c: $(srcdir)/emulparams/elf32_spu.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32_spu "$(tdir_elf32_spu)" eelf32_i860.c: $(srcdir)/emulparams/elf32_i860.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32_i860 "$(tdir_elf32_i860)" @@ -797,6 +802,9 @@ $(srcdir)/emulparams/hppa64linux.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf64hppa "$(tdir_elf64hppa)" +eelf64_lv2.c: $(srcdir)/emulparams/elf64_lv2.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf64_lv2 "$(tdir_elf64_aix)" eelf64_aix.c: $(srcdir)/emulparams/elf64_aix.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf64_aix "$(tdir_elf64_aix)" diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/configure.tgt binutils/ld/configure.tgt --- binutils-2.16.1/ld/configure.tgt 2005-02-08 20:54:27.000000000 +0100 +++ binutils/ld/configure.tgt 2006-03-30 01:23:21.000000000 +0200 @@ -374,14 +374,14 @@ tdir_elf32ppcsim=`echo ${targ_alias} | sed -e 's/ppc/ppcsim/'` ;; powerpc*-*-linux*) case "${targ}" in *64*) targ_emul=elf64ppc - targ_extra_emuls="elf32ppclinux elf32ppc elf32ppcsim" + targ_extra_emuls="elf32ppclinux elf32ppc elf32ppcsim elf32_spu" targ_extra_libpath="elf32ppclinux elf32ppc" tdir_elf32ppc=`echo "${targ_alias}" | sed -e 's/64//'` tdir_elf32ppclinux=$tdir_elf32ppc tdir_elf32ppcsim=$tdir_elf32ppc ;; *) targ_emul=elf32ppclinux - targ_extra_emuls="elf32ppc elf32ppcsim" + targ_extra_emuls="elf32ppc elf32ppcsim elf32_spu" targ_extra_libpath=elf32ppc if test "${want64}" = "true"; then targ_extra_emuls="$targ_extra_emuls elf64ppc" @@ -427,6 +427,7 @@ powerpc-*-beos*) targ_emul=aixppc ;; powerpc-*-windiss*) targ_emul=elf32ppcwindiss ;; powerpc-*-lynxos*) targ_emul=ppclynx ;; +ppu-*-lv2) targ_emul=elf64_lv2 targ_extra_emuls="elf32_spu" ;; rs6000-*-aix5*) targ_emul=aix5rs6 ;; rs6000-*-aix*) targ_emul=aixrs6 ;; @@ -536,6 +537,9 @@ sparc*-wrs-vxworks*) targ_emul=sparcaout ;; sparc*-*-rtems*) targ_emul=elf32_sparc ;; +spu-*-lv2) targ_emul=elf32_spu ;; +spu-*-elf*) targ_emul=elf32_spu + ;; tic30-*-*aout*) targ_emul=tic30aout ;; tic30-*-*coff*) targ_emul=tic30coff ;; tic4x-*-* | c4x-*-*) targ_emul=tic4xcoff ; targ_extra_emuls="tic3xcoff tic3xcoff_onchip" ;; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/emulparams/elf32_spu.sh binutils/ld/emulparams/elf32_spu.sh --- binutils-2.16.1/ld/emulparams/elf32_spu.sh 1970-01-01 01:00:00.000000000 +0100 +++ binutils/ld/emulparams/elf32_spu.sh 2006-03-30 01:23:21.000000000 +0200 @@ -0,0 +1,14 @@ +SCRIPT_NAME=elf +TEMPLATE_NAME=elf32 +OUTPUT_FORMAT="elf32-spu" +ARCH=spu +MACHINE= +TEXT_START_ADDR=0x0000080 +ALIGNMENT=16 +OTHER_END_SYMBOLS='PROVIDE (__stack = 0x3fff0);' +NO_SMALL_DATA=true +EMBEDDED=true +MAXPAGESIZE=0x80 +DATA_ADDR="ALIGN(${MAXPAGESIZE})" +GENERATE_SHLIB_SCRIPT=yes +OTHER_GOT_SECTIONS=".toe ALIGN(128) : { *(.toe) } = 0" diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/emulparams/elf64_lv2.sh binutils/ld/emulparams/elf64_lv2.sh --- binutils-2.16.1/ld/emulparams/elf64_lv2.sh 1970-01-01 01:00:00.000000000 +0100 +++ binutils/ld/emulparams/elf64_lv2.sh 2004-10-26 06:22:56.000000000 +0200 @@ -0,0 +1,51 @@ +TEMPLATE_NAME=elf32 +EXTRA_EM_FILE=ppc64elf +ELFSIZE=64 +GENERATE_SHLIB_SCRIPT=yes +GENERATE_PIE_SCRIPT=yes +SCRIPT_NAME=elf +OUTPUT_FORMAT="elf64-powerpc" +TEXT_START_ADDR=0x10000 +#SEGMENT_SIZE=0x10000000 +MAXPAGESIZE=0x10000 +COMMONPAGESIZE=0x1000 +ARCH=powerpc:common64 +MACHINE= +NOP=0x60000000 +EXECUTABLE_SYMBOLS='PROVIDE (__stack = 0); PROVIDE (___stack = 0);' +OTHER_BSS_END_SYMBOLS='__end = .;' +CTOR_START='PROVIDE (__CTOR_LIST__ = .); PROVIDE (___CTOR_LIST__ = .);' +CTOR_END='PROVIDE (__CTOR_END__ = .); PROVIDE (___CTOR_END__ = .);' +DTOR_START='PROVIDE (__DTOR_LIST__ = .); PROVIDE (___DTOR_LIST__ = .);' +DTOR_END='PROVIDE (__DTOR_END__ = .); PROVIDE (___DTOR_END__ = .);' +OTHER_TEXT_SECTIONS="*(.sfpr .glink)" +BSS_PLT= +OTHER_BSS_SYMBOLS=" + .tocbss ${RELOCATING-0}${RELOCATING+ALIGN(8)} : { *(.tocbss)}" +OTHER_PLT_RELOC_SECTIONS=" + .rela.tocbss ${RELOCATING-0} : { *(.rela.tocbss) }" + +if test x${RELOCATING+set} = xset; then + GOT=" + .got ALIGN(8) : { *(.got .toc) }" +else + GOT=" + .got 0 : { *(.got) } + .toc 0 : { *(.toc) }" +fi +OTHER_GOT_RELOC_SECTIONS=" + .rela.toc ${RELOCATING-0} : { *(.rela.toc) }" +OTHER_READWRITE_SECTIONS=" + .toc1 ${RELOCATING-0}${RELOCATING+ALIGN(8)} : { *(.toc1) } + .opd ${RELOCATING-0}${RELOCATING+ALIGN(8)} : { KEEP (*(.opd)) }" + +# Treat a host that matches the target with the possible exception of "64" +# in the name as if it were native. +if test `echo "$host" | sed -e s/64//` = `echo "$target" | sed -e s/64//`; then + case " $EMULATION_LIBPATH " in + *" ${EMULATION_NAME} "*) + NATIVE=yes + ;; + esac +fi + diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/emulparams/elf64ppc.sh binutils/ld/emulparams/elf64ppc.sh --- binutils-2.16.1/ld/emulparams/elf64ppc.sh 2003-07-28 05:33:48.000000000 +0200 +++ binutils/ld/emulparams/elf64ppc.sh 2006-03-30 01:23:21.000000000 +0200 @@ -12,6 +12,12 @@ ARCH=powerpc:common64 MACHINE= NOP=0x60000000 +#EXECUTABLE_SYMBOLS='PROVIDE (__stack = 0); PROVIDE (___stack = 0);' +#OTHER_BSS_END_SYMBOLS='__end = .;' +#CTOR_START='PROVIDE (__CTOR_LIST__ = .); PROVIDE (___CTOR_LIST__ = .);' +#CTOR_END='PROVIDE (__CTOR_END__ = .); PROVIDE (___CTOR_END__ = .);' +#DTOR_START='PROVIDE (__DTOR_LIST__ = .); PROVIDE (___DTOR_LIST__ = .);' +#DTOR_END='PROVIDE (__DTOR_END__ = .); PROVIDE (___DTOR_END__ = .);' OTHER_TEXT_SECTIONS="*(.sfpr .glink)" BSS_PLT= OTHER_BSS_SYMBOLS=" diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/emultempl/elf32.em binutils/ld/emultempl/elf32.em --- binutils-2.16.1/ld/emultempl/elf32.em 2005-04-13 19:59:07.000000000 +0200 +++ binutils/ld/emultempl/elf32.em 2006-03-30 01:23:21.000000000 +0200 @@ -243,9 +243,16 @@ meaningful inode numbers will never set st_ino to zero, this is merely an optimization, so we do not need to worry about false negatives. */ +#ifndef __MINGW32__ if (st.st_dev == global_stat.st_dev && st.st_ino == global_stat.st_ino && st.st_ino != 0) +#else + if (st.st_dev == global_stat.st_dev + && st.st_ino == global_stat.st_ino + && st.st_size == global_stat.st_size + && strcmp (lbasename(s->the_bfd->filename), global_needed->name) != 0 ) +#endif { global_found = TRUE; return; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/ld.texinfo binutils/ld/ld.texinfo --- binutils-2.16.1/ld/ld.texinfo 2005-06-12 20:35:45.000000000 +0200 +++ binutils/ld/ld.texinfo 2006-03-30 01:23:21.000000000 +0200 @@ -1834,6 +1834,14 @@ symbols from, to ensure that they get linked in, just like a normal object file). +The @option{-shared} option creates a relocatable DLL. To convert a +relocatable DLL to a non-relocatable one, strip the @code{.reloc} section +using + +@smallexample +strip -R .reloc @var{foo.dll} +@end smallexample + In addition to the options common to all targets, the i386 PE linker support additional command line options that are specific to the i386 PE target. Options that take values may be separated from their diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/ldgram.y binutils/ld/ldgram.y --- binutils-2.16.1/ld/ldgram.y 2005-01-21 13:04:25.000000000 +0100 +++ binutils/ld/ldgram.y 2006-03-30 01:23:21.000000000 +0200 @@ -1079,6 +1079,11 @@ $$ = exp_intop (i); break; } +#if (defined(BPA)) + if (strcmp(s, "PT_SPU_INFO") == 0) + $$ = exp_intop(0x70000000); +#endif + if (i == sizeof phdr_types / sizeof phdr_types[0]) { if (strcmp (s, "PT_GNU_EH_FRAME") == 0) diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/ldmain.c binutils/ld/ldmain.c --- binutils-2.16.1/ld/ldmain.c 2005-03-03 12:51:58.000000000 +0100 +++ binutils/ld/ldmain.c 2006-03-30 01:23:21.000000000 +0200 @@ -195,6 +195,17 @@ program_name = argv[0]; xmalloc_set_program_name (program_name); + { + const char *response_file = expandargv (&argc, &argv); + if (response_file) + { + einfo (_("%X%P: can't set BFD default target to `%s': %E\n"), + response_file); + xexit (1); + } + } + + START_PROGRESS (program_name, 0); bfd_init (); @@ -313,6 +324,10 @@ link_info.need_relax_finalize = FALSE; link_info.warn_shared_textrel = FALSE; +#if defined(BPA) + link_info.spuplugin = FALSE; +#endif + ldfile_add_arch (""); config.make_executable = TRUE; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/lexsup.c binutils/ld/lexsup.c --- binutils-2.16.1/ld/lexsup.c 2005-03-03 12:52:00.000000000 +0100 +++ binutils/ld/lexsup.c 2006-03-30 01:23:21.000000000 +0200 @@ -153,6 +153,11 @@ OPTION_ERROR_UNRESOLVED_SYMBOLS, OPTION_WARN_SHARED_TEXTREL, OPTION_REDUCE_MEMORY_OVERHEADS +/* CELL LOCAL Begin */ +#if defined(BPA) + , OPTION_SPUPLUGIN +#endif +/* CELL LOCAL End */ }; /* The long options. This structure is used for both the option @@ -518,6 +523,10 @@ TWO_DASHES }, { {"wrap", required_argument, NULL, OPTION_WRAP}, '\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES }, +#if defined(BPA) + { {"plugin", no_argument, NULL, OPTION_SPUPLUGIN}, + '\0', NULL, N_("Make SPU Plugin"), ONE_DASH }, +#endif }; #define OPTION_COUNT ARRAY_SIZE (ld_options) @@ -1329,6 +1338,12 @@ link_info.fini_function = optarg; break; +#if defined(BPA) + case OPTION_SPUPLUGIN: + link_info.spuplugin = TRUE; + break; +#endif + case OPTION_REDUCE_MEMORY_OVERHEADS: command_line.reduce_memory_overheads = TRUE; if (config.hash_table_size == 0) diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/scripttempl/elf.sc binutils/ld/scripttempl/elf.sc --- binutils-2.16.1/ld/scripttempl/elf.sc 2005-03-22 16:32:43.000000000 +0100 +++ binutils/ld/scripttempl/elf.sc 2006-03-30 01:23:21.000000000 +0200 @@ -301,6 +301,7 @@ ${RELOCATING+${TEXT_START_SYMBOLS}} *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*}) KEEP (*(.text.*personality*)) + *(.spu.elf) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) ${RELOCATING+${OTHER_TEXT_SECTIONS}} diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/ld/scripttempl/pe.sc binutils/ld/scripttempl/pe.sc --- binutils-2.16.1/ld/scripttempl/pe.sc 2004-12-01 00:54:53.000000000 +0100 +++ binutils/ld/scripttempl/pe.sc 2006-03-30 01:23:21.000000000 +0200 @@ -65,10 +65,20 @@ ${R_TEXT} *(.glue_7t) *(.glue_7) - ${CONSTRUCTING+ ___CTOR_LIST__ = .; __CTOR_LIST__ = . ; - LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0); } - ${CONSTRUCTING+ ___DTOR_LIST__ = .; __DTOR_LIST__ = . ; - LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0); } + ${CONSTRUCTING+ ___CTOR_LIST__ = .; __CTOR_LIST__ = . ; + LONG (-1); + *(EXCLUDE_FILE (*crtend.o) .ctors); + *(.ctor); + *(SORT(.ctors.*)); + *crtend.o (.ctors); + LONG (0); } + ${CONSTRUCTING+ ___DTOR_LIST__ = .; __DTOR_LIST__ = . ; + LONG (-1); + *(EXCLUDE_FILE (*crtend.o) .dtors); + *(.dtor); + *(SORT(.dtors.*)); + *crtend.o (.dtors); + LONG (0); } ${RELOCATING+ *(.fini)} /* ??? Why is .gcc_exc here? */ ${RELOCATING+ *(.gcc_exc)} diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/opcodes/Makefile.am binutils/opcodes/Makefile.am --- binutils-2.16.1/opcodes/Makefile.am 2005-02-21 12:48:33.000000000 +0100 +++ binutils/opcodes/Makefile.am 2006-03-30 01:23:21.000000000 +0200 @@ -149,6 +149,8 @@ sh64-opc.c \ sparc-dis.c \ sparc-opc.c \ + spu-dis.c \ + spu-opc.c \ tic30-dis.c \ tic4x-dis.c \ tic54x-dis.c \ @@ -263,6 +265,8 @@ sh64-opc.lo \ sparc-dis.lo \ sparc-opc.lo \ + spu-dis.lo \ + spu-opc.lo \ tic30-dis.lo \ tic4x-dis.lo \ tic54x-dis.lo \ @@ -805,6 +809,12 @@ $(INCDIR)/symcat.h $(INCDIR)/libiberty.h opintl.h sparc-opc.lo: sparc-opc.c sysdep.h config.h $(INCDIR)/ansidecl.h \ $(INCDIR)/opcode/sparc.h +spu-dis.lo: spu-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/opcode/spu.h $(INCDIR)/dis-asm.h $(BFD_H) \ + $(INCDIR)/symcat.h $(INCDIR)/libiberty.h opintl.h \ + $(INCDIR)/opcode/spu-insns.h +spu-opc.lo: spu-opc.c sysdep.h config.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/opcode/spu.h tic30-dis.lo: tic30-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \ $(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/symcat.h $(INCDIR)/opcode/tic30.h tic4x-dis.lo: tic4x-dis.c $(INCDIR)/libiberty.h $(INCDIR)/ansidecl.h \ diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/opcodes/configure binutils/opcodes/configure --- binutils-2.16.1/opcodes/configure 2005-01-31 21:30:37.000000000 +0100 +++ binutils/opcodes/configure 2006-03-30 01:23:21.000000000 +0200 @@ -8655,6 +8655,7 @@ done ta="$ta sh-dis.lo" ;; bfd_sparc_arch) ta="$ta sparc-dis.lo sparc-opc.lo" ;; + bfd_spu_arch) ta="$ta spu-dis.lo spu-opc.lo" ;; bfd_tahoe_arch) ;; bfd_tic30_arch) ta="$ta tic30-dis.lo" ;; bfd_tic4x_arch) ta="$ta tic4x-dis.lo" ;; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/opcodes/configure.in binutils/opcodes/configure.in --- binutils-2.16.1/opcodes/configure.in 2004-11-08 14:17:37.000000000 +0100 +++ binutils/opcodes/configure.in 2006-03-30 01:23:21.000000000 +0200 @@ -232,6 +232,7 @@ done ta="$ta sh-dis.lo" ;; bfd_sparc_arch) ta="$ta sparc-dis.lo sparc-opc.lo" ;; + bfd_spu_arch) ta="$ta spu-dis.lo spu-opc.lo" ;; bfd_tahoe_arch) ;; bfd_tic30_arch) ta="$ta tic30-dis.lo" ;; bfd_tic4x_arch) ta="$ta tic4x-dis.lo" ;; diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/opcodes/disassemble.c binutils/opcodes/disassemble.c --- binutils-2.16.1/opcodes/disassemble.c 2005-03-03 12:49:48.000000000 +0100 +++ binutils/opcodes/disassemble.c 2006-03-30 01:23:21.000000000 +0200 @@ -25,6 +25,7 @@ #define ARCH_s390 #define ARCH_sh #define ARCH_sparc +#define ARCH_spu #define ARCH_tic30 #define ARCH_tic4x #define ARCH_tic54x @@ -120,6 +121,11 @@ disassemble = print_insn_avr; break; #endif +#ifdef ARCH_spu + case bfd_arch_spu: + disassemble = print_insn_spu; + break; +#endif #ifdef ARCH_cris case bfd_arch_cris: disassemble = cris_get_disassembler (abfd); diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/opcodes/ppc-dis.c binutils/opcodes/ppc-dis.c --- binutils-2.16.1/opcodes/ppc-dis.c 2005-03-22 16:31:19.000000000 +0100 +++ binutils/opcodes/ppc-dis.c 2006-03-30 01:23:21.000000000 +0200 @@ -81,6 +81,8 @@ dialect &= ~PPC_OPCODE_64; else if (strstr (info->disassembler_options, "64") != NULL) dialect |= PPC_OPCODE_64; + else if (strstr (info->disassembler_options, "cellppu") != NULL) + dialect |= PPC_OPCODE_CELLPPU; } ((struct dis_private *) &info->private_data)->dialect = dialect; @@ -158,6 +160,8 @@ int invalid; int need_comma; int need_paren; + int print_hex; + long hexval; table_op = PPC_OP (opcode->opcode); if (op < table_op) @@ -191,6 +195,7 @@ /* Now extract and print the operands. */ need_comma = 0; need_paren = 0; + print_hex = 0; for (opindex = opcode->operands; *opindex != 0; opindex++) { long value; @@ -236,12 +241,20 @@ else if ((operand->flags & PPC_OPERAND_VR) != 0) (*info->fprintf_func) (info->stream, "v%ld", value); else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) - (*info->print_address_func) (memaddr + value, info); + (*info->print_address_func) (memaddr + value, info); else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) - (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); + { + (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); + print_hex = 1; + hexval = value & 0xffffffff; + } else if ((operand->flags & PPC_OPERAND_CR) == 0 || (dialect & PPC_OPCODE_PPC) == 0) - (*info->fprintf_func) (info->stream, "%ld", value); + { + (*info->fprintf_func) (info->stream, "%ld", value); + print_hex = 1; + hexval = value; + } else { if (operand->bits == 3) @@ -275,6 +288,9 @@ } } + if (print_hex && (hexval > 16 || hexval < -1)) + (*info->fprintf_func) (info->stream, "\t\t# %lx", hexval); + /* We have found and printed an instruction; return. */ return 4; } diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/opcodes/ppc-opc.c binutils/opcodes/ppc-opc.c --- binutils-2.16.1/opcodes/ppc-opc.c 2005-04-19 19:09:56.000000000 +0200 +++ binutils/opcodes/ppc-opc.c 2006-03-30 01:23:21.000000000 +0200 @@ -560,6 +560,10 @@ }; +/* Version 2 of the PowerPC User ISA is compatible with POWER4. + Enable the POWER4 extensions by default, e.g., BO encoding. */ +#define POWER4_COMPAT(DIALECT) (((DIALECT) & PPC_OPCODE_NOPOWER4) == 0) + /* The functions used to insert and extract complicated operands. */ /* The BA field in an XL form instruction when it must be the same as @@ -651,7 +655,7 @@ int dialect, const char **errmsg ATTRIBUTE_UNUSED) { - if ((dialect & PPC_OPCODE_POWER4) == 0) + if (!POWER4_COMPAT (dialect)) { if ((value & 0x8000) != 0) insn |= 1 << 21; @@ -671,7 +675,7 @@ int dialect, int *invalid) { - if ((dialect & PPC_OPCODE_POWER4) == 0) + if (!POWER4_COMPAT (dialect)) { if (((insn & (1 << 21)) == 0) != ((insn & (1 << 15)) == 0)) *invalid = 1; @@ -696,7 +700,7 @@ int dialect, const char **errmsg ATTRIBUTE_UNUSED) { - if ((dialect & PPC_OPCODE_POWER4) == 0) + if (!POWER4_COMPAT (dialect)) { if ((value & 0x8000) == 0) insn |= 1 << 21; @@ -716,7 +720,7 @@ int dialect, int *invalid) { - if ((dialect & PPC_OPCODE_POWER4) == 0) + if (!POWER4_COMPAT (dialect)) { if (((insn & (1 << 21)) == 0) == ((insn & (1 << 15)) == 0)) *invalid = 1; @@ -736,7 +740,7 @@ static int valid_bo (long value, int dialect) { - if ((dialect & PPC_OPCODE_POWER4) == 0) + if (!POWER4_COMPAT (dialect)) { /* Certain encodings have bits that are required to be zero. These are (z must be zero, y may be anything): @@ -1796,6 +1800,7 @@ #define MFDEC2 PPC_OPCODE_PPC | PPC_OPCODE_601 | PPC_OPCODE_BOOKE #define BOOKE PPC_OPCODE_BOOKE #define BOOKE64 PPC_OPCODE_BOOKE64 +#define CELLPPU PPC_OPCODE_CELLPPU #define CLASSIC PPC_OPCODE_CLASSIC #define PPCSPE PPC_OPCODE_SPE #define PPCISEL PPC_OPCODE_ISEL @@ -1825,7 +1830,8 @@ sorted by major opcode. */ const struct powerpc_opcode powerpc_opcodes[] = { -{ "attn", X(0,256), X_MASK, POWER4, { 0 } }, +{ "attn", XRC(0,256,0), X_MASK, PPC64, { 0 }}, +{ "attn.", XRC(0,256,1), X_MASK, PPC64, { 0 }}, { "tdlgti", OPTO(2,TOLGT), OPTO_MASK, PPC64, { RA, SI } }, { "tdllti", OPTO(2,TOLLT), OPTO_MASK, PPC64, { RA, SI } }, { "tdeqi", OPTO(2,TOEQ), OPTO_MASK, PPC64, { RA, SI } }, @@ -2707,7 +2713,8 @@ { "bcla+", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDPA } }, { "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } }, -{ "sc", SC(17,1,0), SC_MASK, PPC, { LEV } }, +{ "scv", SC(17,0,1), SC_MASK, PPC64, { LEV } }, +{ "sc", SC(17,1,0), SC_MASK, PPC, { LEV } }, { "svc", SC(17,0,0), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } }, { "svcl", SC(17,0,1), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } }, { "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } }, @@ -2944,6 +2951,7 @@ { "bclrel", XLLK(19,17,1), XLBB_MASK, BOOKE64, { BO, BI } }, { "rfid", XL(19,18), 0xffffffff, PPC64, { 0 } }, +{ "hrfid", XL(19,274),0xffffffff, PPC64, { 0 } }, { "crnot", XL(19,33), XL_MASK, PPCCOM, { BT, BA, BBA } }, { "crnor", XL(19,33), XL_MASK, COM, { BT, BA, BB } }, @@ -2952,6 +2960,7 @@ { "rfi", XL(19,50), 0xffffffff, COM, { 0 } }, { "rfci", XL(19,51), 0xffffffff, PPC403 | BOOKE, { 0 } }, +{ "rfscv", XL(19,82), 0xffffffff, PPC64, { 0 } }, { "rfsvc", XL(19,82), 0xffffffff, POWER, { 0 } }, { "crandc", XL(19,129), XL_MASK, COM, { BT, BA, BB } }, @@ -3271,12 +3280,13 @@ { "isel", XISEL(31,15), XISEL_MASK, PPCISEL, { RT, RA, RB, CRB } }, { "mfocrf", XFXM(31,19,0,1), XFXFXM_MASK, COM, { RT, FXM } }, -{ "mfcr", X(31,19), XRARB_MASK, NOPOWER4, { RT } }, +{ "mfcr", XFXM(31,19,0,0), XRARB_MASK, NOPOWER4, { RT } }, { "mfcr", X(31,19), XFXFXM_MASK, POWER4, { RT, FXM4 } }, { "lwarx", X(31,20), X_MASK, PPC, { RT, RA0, RB } }, { "ldx", X(31,21), X_MASK, PPC64, { RT, RA0, RB } }, +{ "ldbrx", X(31,532), X_MASK, PPC64, { RT, RA0, RB } }, { "icbt", X(31,22), X_MASK, BOOKE, { CT, RA, RB } }, { "icbt", X(31,262), XRT_MASK, PPC403, { RA, RB } }, @@ -3433,6 +3443,7 @@ { "mtmsr", X(31,146), XRARB_MASK, COM, { RS } }, { "stdx", X(31,149), X_MASK, PPC64, { RS, RA0, RB } }, +{ "stdbrx", X(31,660), X_MASK, PPC64, { RS, RA0, RB } }, { "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA0, RB } }, @@ -3570,7 +3581,7 @@ { "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } }, { "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } }, -{ "dcbt", X(31,278), X_MASK, PPC, { CT, RA, RB } }, +{ "dcbt", X(31,278), X_MASK, PPC, { CT, RA, RB } }, { "lhzx", X(31,279), X_MASK, COM, { RT, RA0, RB } }, @@ -3827,6 +3838,7 @@ { "mfthrm3", XSPR(31,339,1022), XSPR_MASK, PPC750, { RT } }, { "mfpbu2", XSPR(31,339,1023), XSPR_MASK, PPC403, { RT } }, { "mfspr", X(31,339), X_MASK, COM, { RT, SPR } }, +{ "mfctrl", X(31,339), XSPR_MASK, PPC64, { RT } }, { "lwax", X(31,341), X_MASK, PPC64, { RT, RA0, RB } }, @@ -4109,6 +4121,7 @@ { "mtthrm3", XSPR(31,467,1022), XSPR_MASK, PPC750, { RS } }, { "mtpbu2", XSPR(31,467,1023), XSPR_MASK, PPC403, { RS } }, { "mtspr", X(31,467), X_MASK, COM, { SPR, RS } }, +{ "mtctrl", X(31,467), XSPR_MASK, PPC64, { RS } }, { "dcbi", X(31,470), XRT_MASK, PPC, { RA, RB } }, @@ -4613,6 +4626,15 @@ { "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } }, { "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } }, +{ "cctpl", 0x7c210b78, 0xffffffff, CELLPPU, { 0 }}, +{ "cctpm", 0x7c421378, 0xffffffff, CELLPPU, { 0 }}, +{ "cctph", 0x7c631b78, 0xffffffff, CELLPPU, { 0 }}, +{ "db8cyc", 0x7f9ce378, 0xffffffff, CELLPPU, { 0 }}, +{ "db10cyc", 0x7fbdeb78, 0xffffffff, CELLPPU, { 0 }}, +{ "db12cyc", 0x7fdef378, 0xffffffff, CELLPPU, { 0 }}, +{ "db16cyc", 0x7ffffb78, 0xffffffff, CELLPPU, { 0 }}, +/* Mambo simulator trap */ +{ "support", X(31,998), 0xffffffff, CELLPPU, { 0 }}, }; const int powerpc_num_opcodes = diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/opcodes/spu-dis.c binutils/opcodes/spu-dis.c --- binutils-2.16.1/opcodes/spu-dis.c 1970-01-01 01:00:00.000000000 +0100 +++ binutils/opcodes/spu-dis.c 2006-03-30 01:23:21.000000000 +0200 @@ -0,0 +1,258 @@ +/* spu-dis.c -- Disassemble Spu instructions */ + +/* (C) Copyright + Sony Computer Entertainment, Inc., + Toshiba Corporation, + International Business Machines Corporation, + 2001,2002,2003,2004,2005. + + 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 file 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 file; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include "sysdep.h" +#include "dis-asm.h" +#include "opcode/spu.h" + +/* This file provides a disassembler function which uses + the disassembler interface defined in dis-asm.h. */ + +static void init_spu_disassemble(void); + +extern const struct spu_opcode spu_opcodes[]; +extern const int spu_num_opcodes; + +static const struct spu_opcode *spu_disassemble_table[(1<<11)]; + +static void +init_spu_disassemble() +{ + int i; + /* If two instructions have the same opcode then we prefer the first + * one. In most cases it is just an alternate mnemonic. */ + for (i = 0; i < spu_num_opcodes; i++) + { + int o = spu_opcodes[i].opcode; + if (o >= (1 << 11)) + abort(); + if (spu_disassemble_table[o] == 0) + spu_disassemble_table[o] = &spu_opcodes[i]; + } +} + +/* Determine the instruction from the 10 least significant bits. */ +static const struct spu_opcode * +get_index_for_opcode(unsigned int insn) +{ + const struct spu_opcode *index; + unsigned int opcode = insn >> (32-11); + + /* Init the table. This assumes that element 0/opcode 0 (currently + * NOP) is always used */ + if (spu_disassemble_table[0] == 0) + init_spu_disassemble(); + + if ((index = spu_disassemble_table[opcode & 0x780]) != 0 + && index->insn_type == RRR) + return index; + + if ((index = spu_disassemble_table[opcode & 0x7f0]) != 0 + && (index->insn_type == RI18 || index->insn_type == LBT)) + return index; + + if ((index = spu_disassemble_table[opcode & 0x7f8]) != 0 + && index->insn_type == RI10) + return index; + + if ((index = spu_disassemble_table[opcode & 0x7fc]) != 0 + && (index->insn_type == RI16)) + return index; + + if ((index = spu_disassemble_table[opcode & 0x7fe]) != 0 + && (index->insn_type == RI8)) + return index; + + if ((index = spu_disassemble_table[opcode & 0x7ff]) != 0) + { + return index; + } + + return 0; +} + +/* Print a Spu instruction. */ + +int +print_insn_spu (memaddr, info) + bfd_vma memaddr; + struct disassemble_info *info; +{ + bfd_byte buffer[4]; + int value; + int hex_value; + int status; + unsigned int insn; + const struct spu_opcode *index; + enum spu_insns tag; + + status = (*info->read_memory_func) (memaddr, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + insn = bfd_getb32 (buffer); + + index = get_index_for_opcode(insn); + + if (index == 0) + { + (*info->fprintf_func) (info->stream, ".long 0x%x", insn); + } + else + { + int i; + int paren = 0; + tag = (enum spu_insns)(index - spu_opcodes); + (*info->fprintf_func) (info->stream, "%s", index->mnemonic); + if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED + || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ + || tag == M_SYNC || tag == M_HBR) + { + int fb = (insn >> (32-18)) & 0x7f; + if (fb & 0x40) + (*info->fprintf_func) (info->stream, tag == M_SYNC ? "c" : "p"); + if (fb & 0x20) + (*info->fprintf_func) (info->stream, "d"); + if (fb & 0x10) + (*info->fprintf_func) (info->stream, "e"); + } + if (index->arg[0] != 0) + (*info->fprintf_func) (info->stream, "\t"); + hex_value = 0; + for (i = 1; i <= index->arg[0]; i++) + { + int arg = index->arg[i]; + if (arg != A_P && !paren && i > 1) + (*info->fprintf_func) (info->stream, ","); + + switch (arg) + { + case A_T: + (*info->fprintf_func) (info->stream, "$%d", DECODE_INSN_RT(insn)); + break; + case A_A: + (*info->fprintf_func) (info->stream, "$%d", DECODE_INSN_RA(insn)); + break; + case A_B: + (*info->fprintf_func) (info->stream, "$%d", DECODE_INSN_RB(insn)); + break; + case A_C: + (*info->fprintf_func) (info->stream, "$%d", DECODE_INSN_RC(insn)); + break; + case A_S: + (*info->fprintf_func) (info->stream, "$sp%d", DECODE_INSN_RA(insn)); + break; + case A_H: + (*info->fprintf_func) (info->stream, "$ch%d", DECODE_INSN_RA(insn)); + break; + case A_P: + paren++; + (*info->fprintf_func) (info->stream, "("); + break; + case A_U7A: + (*info->fprintf_func) (info->stream, "%d", 173 - DECODE_INSN_U8(insn)); + break; + case A_U7B: + (*info->fprintf_func) (info->stream, "%d", 155 - DECODE_INSN_U8(insn)); + break; + case A_S3: + case A_S6: + case A_S7: + case A_S7N: + case A_U3: + case A_U5: + case A_U6: + case A_U7: + hex_value = DECODE_INSN_I7(insn); + (*info->fprintf_func) (info->stream, "%d", hex_value); + break; + case A_S11: + (*info->print_address_func) (memaddr + DECODE_INSN_I9a(insn) * 4, info); + break; + case A_S11I: + (*info->print_address_func) (memaddr + DECODE_INSN_I9b(insn) * 4, info); + break; + case A_S10: + case A_S10B: + hex_value = DECODE_INSN_I10(insn); + (*info->fprintf_func) (info->stream, "%d", hex_value); + break; + case A_S14: + hex_value = DECODE_INSN_I10(insn) * 16; + (*info->fprintf_func) (info->stream, "%d", hex_value); + break; + case A_S16: + hex_value = DECODE_INSN_I16(insn); + (*info->fprintf_func) (info->stream, "%d", hex_value); + break; + case A_X16: + hex_value = DECODE_INSN_U16(insn); + (*info->fprintf_func) (info->stream, "%u", hex_value); + break; + case A_R18: + value = DECODE_INSN_I16(insn) * 4; + if (value == 0) + (*info->fprintf_func) (info->stream, "%d", value); + else + { + hex_value = (int)(memaddr + value); + (*info->print_address_func) (hex_value & 0x3ffff, info); + } + break; + case A_S18: + value = DECODE_INSN_U16(insn) * 4; + if (value == 0) + (*info->fprintf_func) (info->stream, "%d", value); + else + (*info->print_address_func) (value, info); + break; + case A_U18: + value = DECODE_INSN_U18(insn); + if (value == 0 || !(*info->symbol_at_address_func)(0, info)) + { + hex_value = value; + (*info->fprintf_func) (info->stream, "%u", value); + } + else + (*info->print_address_func) (value, info); + break; + case A_U14: + hex_value = DECODE_INSN_U14(insn); + (*info->fprintf_func) (info->stream, "%u", hex_value); + break; + } + if (arg != A_P && paren) + { + (*info->fprintf_func) (info->stream, ")"); + paren--; + } + } + if (hex_value > 16) + (*info->fprintf_func) (info->stream, "\t# %x", hex_value); + } + return 4; +} diff --exclude '*.po' --exclude Makefile.in -ruN binutils-2.16.1/opcodes/spu-opc.c binutils/opcodes/spu-opc.c --- binutils-2.16.1/opcodes/spu-opc.c 1970-01-01 01:00:00.000000000 +0100 +++ binutils/opcodes/spu-opc.c 2006-03-30 01:23:21.000000000 +0200 @@ -0,0 +1,47 @@ +/* spu-opc.c -- Spu opcode list */ + +/* (C) Copyright + Sony Computer Entertainment, Inc., + Toshiba Corporation, + International Business Machines Corporation, + 2001,2002,2003,2004,2005. + + 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 file 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 file; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include "opcode/spu.h" + +/* This file holds the Spu opcode table */ + + +/* + Example contents of spu-insn.h + id_tag mode mode type opcode mnemonic asmtype dependency FPU L/S? branch? instruction + QUAD WORD (0,RC,RB,RA,RT) latency + APUOP(M_LQD, 1, 0, RI9, 0x1f8, "lqd", ASM_RI9IDX, 00012, FXU, 1, 0) Load Quadword d-form + */ + +const struct spu_opcode spu_opcodes[] = { +#define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \ + { MACFORMAT, OPCODE, MNEMONIC, ASMFORMAT }, +#define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \ + { MACFORMAT, OPCODE, MNEMONIC, ASMFORMAT }, +#include "opcode/spu-insns.h" +#undef APUOP +#undef APUOPFB +}; + +const int spu_num_opcodes = + sizeof (spu_opcodes) / sizeof (spu_opcodes[0]);