include/elf/
authorAlan Modra <amodra@gmail.com>
Fri, 11 May 2007 03:10:11 +0000 (03:10 +0000)
committerAlan Modra <amodra@gmail.com>
Fri, 11 May 2007 03:10:11 +0000 (03:10 +0000)
* spu.h (R_SPU_PPU32, R_SPU_PPU64): Define.
bfd/
* reloc.c (BFD_RELOC_SPU_PPU32, BFD_RELOC_SPU_PPU64): Define.
* elf-bfd.h (struct elf_backend_data): Change return type of
elf_backend_relocate_section to int.
* elf32-spu.c (elf_howto_table): Add howtos for R_SPU_PPU32 and
R_SPU_PPU64.
(spu_elf_bfd_to_reloc_type): Convert new relocs.
(spu_elf_count_relocs): New function.
(elf_backend_count_relocs): Define.
(spu_elf_relocate_section): Arrange to emit R_SPU_PPU32 and
R_SPU_PPU64 relocs.
* elflink.c (elf_link_input_bfd): Emit relocs if relocate_section
returns 2.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
gas/
* config/tc-spu.c (md_pseudo_table): Add int, long, quad.  Call
spu_cons for word.
(md_assemble): Tidy use of insn.flag.
(get_imm): Likewise.  Handle uppercase input too.
(spu_cons): New function.
* config/tc-spu.h (tc_fix_adjustable): Don't adjust SPU_PPU relocs.
(TC_FORCE_RELOCATION): Don't resolve them either.
binutils/
* embedspu.sh (find_prog): Prefer prog in same dir as embedspu
over one found on the users path.
(main): Generate .reloc for each R_SPU_PPU* reloc.

14 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf-bfd.h
bfd/elf32-spu.c
bfd/elflink.c
bfd/libbfd.h
bfd/reloc.c
binutils/ChangeLog
binutils/embedspu.sh
gas/ChangeLog
gas/config/tc-spu.c
gas/config/tc-spu.h
include/elf/ChangeLog
include/elf/spu.h

index b7f09eb64e97a88d68484eb7ada046d76dbe6881..71e7ef7f692b2feab46c27d14ff3273f59f3970e 100644 (file)
@@ -1,3 +1,20 @@
+2007-05-11  Alan Modra  <amodra@bigpond.net.au>
+
+       * reloc.c (BFD_RELOC_SPU_PPU32, BFD_RELOC_SPU_PPU64): Define.
+       * elf-bfd.h (struct elf_backend_data): Change return type of
+       elf_backend_relocate_section to int.
+       * elf32-spu.c (elf_howto_table): Add howtos for R_SPU_PPU32 and
+       R_SPU_PPU64.
+       (spu_elf_bfd_to_reloc_type): Convert new relocs.
+       (spu_elf_count_relocs): New function.
+       (elf_backend_count_relocs): Define.
+       (spu_elf_relocate_section): Arrange to emit R_SPU_PPU32 and
+       R_SPU_PPU64 relocs.
+       * elflink.c (elf_link_input_bfd): Emit relocs if relocate_section
+       returns 2.
+       * bfd-in2.h: Regenerate.
+       * libbfd.h: Regenerate.
+
 2007-05-10  Richard Sandiford  <richard@codesourcery.com>
 
        * elf32-arm.c (elf32_arm_check_relocs): Don't create PLT entries
index 81544353e462adf07026899df8f94b963344ebb6..e08dddf0595f4faa91fb3f9babd23f885a50a696 100644 (file)
@@ -2513,6 +2513,8 @@ relocation types already defined.  */
   BFD_RELOC_SPU_PCREL16,
   BFD_RELOC_SPU_LO16,
   BFD_RELOC_SPU_HI16,
+  BFD_RELOC_SPU_PPU32,
+  BFD_RELOC_SPU_PPU64,
 
 /* Alpha ECOFF and ELF relocations.  Some of these treat the symbol or
 "addend" in some special way.
index e9ee29b12c37cb8f413e002782e68651c30ff511..33ef61328e6b55db5b5a42507324598cc59a2637 100644 (file)
@@ -792,8 +792,11 @@ struct elf_backend_data
      STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
      going to be the section symbol corresponding to the output
      section, which means that the addend must be adjusted
-     accordingly.  */
-  bfd_boolean (*elf_backend_relocate_section)
+     accordingly.
+
+     Returns FALSE on error, TRUE on success, 2 if successful and
+     relocations should be written for this section.  */
+  int (*elf_backend_relocate_section)
     (bfd *output_bfd, 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);
index b6e5fbc88862b68d3f298304c1330b6d763aaa9f..865e1c0d1c4a4b95318eb96df861bfc895f53516 100644 (file)
@@ -78,6 +78,12 @@ static reloc_howto_type elf_howto_table[] = {
   HOWTO (R_SPU_REL32,   0, 2, 32, TRUE,  0, complain_overflow_dont,
         bfd_elf_generic_reloc, "SPU_REL32",
         FALSE, 0, 0xffffffff, TRUE),
+  HOWTO (R_SPU_PPU32,   0, 2, 32, FALSE,  0, complain_overflow_dont,
+        bfd_elf_generic_reloc, "SPU_PPU32",
+        FALSE, 0, 0xffffffff, FALSE),
+  HOWTO (R_SPU_PPU64,   0, 4, 64, FALSE,  0, complain_overflow_dont,
+        bfd_elf_generic_reloc, "SPU_PPU64",
+        FALSE, 0, -1, FALSE),
 };
 
 static struct bfd_elf_special_section const spu_elf_special_sections[] = {
@@ -120,6 +126,10 @@ spu_elf_bfd_to_reloc_type (bfd_reloc_code_real_type code)
       return R_SPU_ADDR32;
     case BFD_RELOC_32_PCREL:
       return R_SPU_REL32;
+    case BFD_RELOC_SPU_PPU32:
+      return R_SPU_PPU32;
+    case BFD_RELOC_SPU_PPU64:
+      return R_SPU_PPU64;
     }
 }
 
@@ -2627,6 +2637,26 @@ spu_elf_final_link (bfd *output_bfd, struct bfd_link_info *info)
   return bfd_elf_final_link (output_bfd, info);
 }
 
+/* Called when not normally emitting relocs, ie. !info->relocatable
+   and !info->emitrelocations.  Returns a count of special relocs
+   that need to be emitted.  */
+
+static unsigned int
+spu_elf_count_relocs (asection *sec, Elf_Internal_Rela *relocs)
+{
+  unsigned int count = 0;
+  Elf_Internal_Rela *relend = relocs + sec->reloc_count;
+
+  for (; relocs < relend; relocs++)
+    {
+      int r_type = ELF32_R_TYPE (relocs->r_info);
+      if (r_type == R_SPU_PPU32 || r_type == R_SPU_PPU64)
+       ++count;
+    }
+
+  return count;
+}
+
 /* Apply RELOCS to CONTENTS of INPUT_SECTION from INPUT_BFD.  */
 
 static bfd_boolean
@@ -2644,6 +2674,7 @@ spu_elf_relocate_section (bfd *output_bfd,
   Elf_Internal_Rela *rel, *relend;
   struct spu_link_hash_table *htab;
   bfd_boolean ret = TRUE;
+  bfd_boolean emit_these_relocs = FALSE;
 
   htab = spu_hash_table (info);
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
@@ -2669,10 +2700,15 @@ spu_elf_relocate_section (bfd *output_bfd,
 
       r_symndx = ELF32_R_SYM (rel->r_info);
       r_type = ELF32_R_TYPE (rel->r_info);
+      if (r_type == R_SPU_PPU32 || r_type == R_SPU_PPU64)
+       {
+         emit_these_relocs = TRUE;
+         continue;
+       }
+
       howto = elf_howto_table + r_type;
       unresolved_reloc = FALSE;
       warned = FALSE;
-
       h = NULL;
       sym = NULL;
       sec = NULL;
@@ -2796,6 +2832,31 @@ spu_elf_relocate_section (bfd *output_bfd,
        }
     }
 
+  if (ret
+      && emit_these_relocs
+      && !info->relocatable
+      && !info->emitrelocations)
+    {
+      Elf_Internal_Rela *wrel;
+      Elf_Internal_Shdr *rel_hdr;
+
+      wrel = rel = relocs;
+      relend = relocs + input_section->reloc_count;
+      for (; rel < relend; rel++)
+       {
+         int r_type;
+
+         r_type = ELF32_R_TYPE (rel->r_info);
+         if (r_type == R_SPU_PPU32 || r_type == R_SPU_PPU64)
+           *wrel++ = *rel;
+       }
+      input_section->reloc_count = wrel - relocs;
+      /* Backflips for _bfd_elf_link_output_relocs.  */
+      rel_hdr = &elf_section_data (input_section)->rel_hdr;
+      rel_hdr->sh_size = input_section->reloc_count * rel_hdr->sh_entsize;
+      ret = 2;
+    }
+
   return ret;
 }
 
@@ -3059,6 +3120,7 @@ spu_elf_modify_program_headers (bfd *abfd, struct bfd_link_info *info)
 #define bfd_elf32_bfd_reloc_type_lookup                spu_elf_reloc_type_lookup
 #define bfd_elf32_bfd_reloc_name_lookup        spu_elf_reloc_name_lookup
 #define elf_info_to_howto                      spu_elf_info_to_howto
+#define elf_backend_count_relocs               spu_elf_count_relocs
 #define elf_backend_relocate_section           spu_elf_relocate_section
 #define elf_backend_symbol_processing          spu_elf_backend_symbol_processing
 #define elf_backend_link_output_symbol_hook    spu_elf_output_symbol_hook
index e64819e3814c8cc7a91e15648c8fd70342418f05..41b518d8774e7c5e151abce47810fe084347cd2f 100644 (file)
@@ -8198,7 +8198,7 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info)
 static bfd_boolean
 elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
 {
-  bfd_boolean (*relocate_section)
+  int (*relocate_section)
     (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
      Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
   bfd *output_bfd;
@@ -8212,7 +8212,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
   asection **ppsection;
   asection *o;
   const struct elf_backend_data *bed;
-  bfd_boolean emit_relocs;
   struct elf_link_hash_entry **sym_hashes;
 
   output_bfd = finfo->output_bfd;
@@ -8225,9 +8224,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
   if ((input_bfd->flags & DYNAMIC) != 0)
     return TRUE;
 
-  emit_relocs = (finfo->info->relocatable
-                || finfo->info->emitrelocations);
-
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   if (elf_bad_symtab (input_bfd))
     {
@@ -8443,6 +8439,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
          Elf_Internal_Rela *internal_relocs;
          bfd_vma r_type_mask;
          int r_sym_shift;
+         int ret;
 
          /* Get the swapped relocs.  */
          internal_relocs
@@ -8580,14 +8577,17 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
             corresponding to the output section, which will require
             the addend to be adjusted.  */
 
-         if (! (*relocate_section) (output_bfd, finfo->info,
+         ret = (*relocate_section) (output_bfd, finfo->info,
                                     input_bfd, o, contents,
                                     internal_relocs,
                                     isymbuf,
-                                    finfo->sections))
+                                    finfo->sections);
+         if (!ret)
            return FALSE;
 
-         if (emit_relocs)
+         if (ret == 2
+             || finfo->info->relocatable
+             || finfo->info->emitrelocations)
            {
              Elf_Internal_Rela *irela;
              Elf_Internal_Rela *irelaend;
index 92bf14a4e182a55e910f44d5c2d74859ec6977ac..c9e3df2f97787be49c26a772c2d6c5045a7688c0 100644 (file)
@@ -919,6 +919,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_SPU_PCREL16",
   "BFD_RELOC_SPU_LO16",
   "BFD_RELOC_SPU_HI16",
+  "BFD_RELOC_SPU_PPU32",
+  "BFD_RELOC_SPU_PPU64",
   "BFD_RELOC_ALPHA_GPDISP_HI16",
   "BFD_RELOC_ALPHA_GPDISP_LO16",
   "BFD_RELOC_ALPHA_GPDISP",
index 2a169625d965414a40987cae3bb575d758f3a5d1..fa9c59d2c6b3aca0793de2a39d2b1221eaa7d9a4 100644 (file)
@@ -1972,6 +1972,10 @@ ENUMX
   BFD_RELOC_SPU_LO16
 ENUMX
   BFD_RELOC_SPU_HI16
+ENUMX
+  BFD_RELOC_SPU_PPU32
+ENUMX
+  BFD_RELOC_SPU_PPU64
 ENUMDOC
   SPU Relocations.
 
index 8e68263b12a2b7db0f968f7e8b09e2764772fa13..f5f0b58faf54c6706a39284ec7b890055d8b9443 100644 (file)
@@ -1,3 +1,9 @@
+2007-05-11  Alan Modra  <amodra@bigpond.net.au>
+
+       * embedspu.sh (find_prog): Prefer prog in same dir as embedspu
+       over one found on the users path.
+       (main): Generate .reloc for each R_SPU_PPU* reloc.
+
 2007-04-28  Alan Modra  <amodra@bigpond.net.au>
 
        * prdbg.c (tg_variable): Adjust for changed demangler.
index 3269ab8610753a932fb0a21f84ff15b62cc1baca..7a321589d1b8455f773b24be0494239045e5580e 100644 (file)
@@ -38,12 +38,12 @@ mydir=`dirname "$0"`
 find_prog ()
 {
   prog=`echo $1 | sed "$program_transform_name"`
-  which $prog > /dev/null 2> /dev/null && return 0
   prog="$mydir/$prog"
   test -x "$prog" && return 0
   prog="$mydir/$1"
   test -x "$prog" && return 0
   prog=`echo $1 | sed "$program_transform_name"`
+  which $prog > /dev/null 2> /dev/null && return 0
   return 1
 }
 
@@ -95,7 +95,7 @@ main ()
     CC="$prog"
   fi
 
-  # Find readelf.  Any old readelf should do.  We only want to read syms.
+  # Find readelf.  Any old readelf should do.
   find_prog readelf
   if test $? -ne 0; then
     if which readelf > /dev/null 2> /dev/null; then
@@ -119,8 +119,13 @@ main ()
   toe=`${READELF} -S ${INFILE} | sed -n -e 's, *\[ *\([0-9]*\)\] *\.toe *[PROGN]*BITS *\([0-9a-f]*\).*,\1 \2,p'`
   toe_addr=`echo $toe | sed -n -e 's,.* ,,p'`
   toe=`echo $toe | sed -n -e 's, .*,,p'`
+  # For loaded sections, pick off section number, address, and file offset
   sections=`${READELF} -S ${INFILE} | sed -n -e 's, *\[ *\([0-9]*\)\] *[^ ]* *PROGBITS *\([0-9a-f]*\) *\([0-9a-f]*\).*,\1 \2 \3,p'`
   sections=`echo ${sections}`
+  # For relocation sections, pick off file offset and info (points to
+  # section where relocs apply)
+  relas=`${READELF} -S ${INFILE} | sed -n -e 's, *\[ *[0-9]*\] *[^ ]* *RELA *[0-9a-f]* *0*\([0-9a-f][0-9a-f]*\) .*\([0-9a-f][0-9a-f]*\) *[0-9a-f][0-9a-f]*$,\1 \2,p'`
+  relas=`echo ${relas}`
 
   # Build embedded SPU image.
   # 1. The whole SPU ELF file is written to .rodata.speelf
@@ -135,8 +140,10 @@ main ()
   #    write the address of the corresponding PowerPC symbol in a table
   #    built in .data.spetoe.  For _EAE_ symbols not in .toe, create
   #    .reloc commands to relocate their location directly.
-  # 3. Write a struct spe_program_handle to .data.
-  # 4. Write a table of _SPUEAR_ symbols.
+  # 3. Look for R_SPU_PPU32 and R_SPU_PPU64 relocations in the SPU ELF image
+  #    and create .reloc commands for them.
+  # 4. Write a struct spe_program_handle to .data.
+  # 5. Write a table of _SPUEAR_ symbols.
   ${CC} ${FLAGS} -x assembler-with-cpp -nostartfiles -nostdlib \
        -Wa,-mbig -Wl,-r -Wl,-x -o ${OUTFILE} - <<EOF
  .section .rodata.speelf,"a",@progbits
@@ -178,6 +185,35 @@ $7 != "'${toe}'" && $7 in sec_off { \
 $7 != "'${toe}'" && ! $7 in sec_off { \
        print "#error Section not found for " $8; \
 } \
+'`
+`test -z "${relas}" || ${READELF} -r -W ${INFILE} | awk \
+'BEGIN { \
+       split ("'"${sections}"'", s, " "); \
+       for (i = 1; i in s; i += 3) { \
+           sec_off[s[i]] = strtonum ("0x" s[i+2]) - strtonum ("0x" s[i+1]); \
+       } \
+       split ("'"${relas}"'", s, " "); \
+       for (i = 1; i in s; i += 2) { \
+           rela[s[i]] = strtonum (s[i+1]); \
+       } \
+} \
+/^Relocation section/ { \
+       sec = substr($6, 3); \
+} \
+$3 ~ /R_SPU_PPU/ { \
+       print "#ifdef _LP64"; \
+       print " .reloc __speelf__+" strtonum ("0x" $1) + sec_off[rela[sec]] ", R_PPC64_ADDR" substr($3, 10) ", " $5 "+0x" $7; \
+       print "#else"; \
+       print " .reloc __speelf__+" strtonum ("0x" $1) + sec_off[rela[sec]] + (substr($3, 10) == "64" ? 4 : 0)", R_PPC_ADDR32, " $5 "+0x" $7; \
+       print "#endif"; \
+} \
+$3 ~ /unrecognized:/ { \
+       print "#ifdef _LP64"; \
+       print " .reloc __speelf__+" strtonum ("0x" $1) + sec_off[rela[sec]] ", R_PPC64_ADDR" ($4 == "f" ? "64" : "32") ", " $6 "+0x" $8; \
+       print "#else"; \
+       print " .reloc __speelf__+" strtonum ("0x" $1) + sec_off[rela[sec]] + ($4 == "f" ? 4 : 0)", R_PPC_ADDR32, " $6 "+0x" $8; \
+       print "#endif"; \
+} \
 '`
 
  .section .data,"aw",@progbits
index c3f7a3f23563cf0f9b5da613a87e77fbee091158..7f8834317560e1610394c8a23ec8bb7950d393c2 100644 (file)
@@ -1,3 +1,13 @@
+2007-05-11  Alan Modra  <amodra@bigpond.net.au>
+
+       * config/tc-spu.c (md_pseudo_table): Add int, long, quad.  Call
+       spu_cons for word.
+       (md_assemble): Tidy use of insn.flag.
+       (get_imm): Likewise.  Handle uppercase input too.
+       (spu_cons): New function.
+       * config/tc-spu.h (tc_fix_adjustable): Don't adjust SPU_PPU relocs.
+       (TC_FORCE_RELOCATION): Don't resolve them either.
+
 2007-05-05  Mark Shinwell  <shinwell@codesourcery.com>
  
        * config/tc-arm.c (md_apply_fix): Generate more accurate
index f4690fb6878de59917176fecd82b48a7173966bf..995a023df9ffdc427a34f0164edb09e78f5f8af7 100644 (file)
@@ -51,9 +51,9 @@ struct spu_insn
 static const char *get_imm (const char *param, struct spu_insn *insn, int arg);
 static const char *get_reg (const char *param, struct spu_insn *insn, int arg,
                            int accept_expr);
-
 static int calcop (struct spu_opcode *format, const char *param,
                   struct spu_insn *insn);
+static void spu_cons (int);
 
 extern char *myname;
 static struct hash_control *op_hash = NULL;
@@ -82,14 +82,17 @@ const char FLT_CHARS[] = "dDfF";
 const pseudo_typeS md_pseudo_table[] =
 {
   {"align", s_align_ptwo, 4},
+  {"bss", s_lcomm_bytes, 1},
   {"def", s_set, 0},
   {"dfloat", float_cons, 'd'},
   {"ffloat", float_cons, 'f'},
   {"global", s_globl, 0},
   {"half", cons, 2},
-  {"bss", s_lcomm_bytes, 1},
+  {"int", spu_cons, 4},
+  {"long", spu_cons, 4},
+  {"quad", spu_cons, 8},
   {"string", stringer, 1},
-  {"word", cons, 4},
+  {"word", spu_cons, 4},
   /* Force set to be treated as an instruction.  */
   {"set", NULL, 0},
   {".set", s_set, 0},
@@ -351,13 +354,14 @@ md_assemble (char *op)
         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)
+       if (insn.flag[i] == 1)
          reloc = BFD_RELOC_SPU_HI16;
-       else if (insn.flag[i] & 2)
+       else if (insn.flag[i] == 2)
          reloc = BFD_RELOC_SPU_LO16;
        fixP = fix_new_exp (frag_now,
                            thisfrag - frag_now->fr_literal,
@@ -585,30 +589,30 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
   int low = 0, high = 0;
   int reloc_i = insn->reloc_arg[0] >= 0 ? 1 : 0;
 
-  if (strncmp (param, "%lo(", 4) == 0)
+  if (strncasecmp (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)
+  else if (strncasecmp (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)
+  else if (strncasecmp (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.  */
+        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.  */
+        name, it's probably a mistake.  The only way to avoid this
+        warning is to rename the symbol.  */
       struct spu_insn tmp_insn;
       const char *np = get_reg (param, &tmp_insn, arg, 0);
 
@@ -623,7 +627,7 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
   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. */
+     handle we do it inlined here. */
   if (param[0] == '@' && !ISALNUM (param[2]) && param[2] != '@')
     {
       if (param[1] == 'h' || param[1] == 'H')
@@ -638,10 +642,10 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
        }
     }
 
-  val = insn->exp[reloc_i].X_add_number;
-
   if (insn->exp[reloc_i].X_op == O_constant)
     {
+      val = insn->exp[reloc_i].X_add_number;
+
       if (emulate_apuasm)
        {
          /* Convert the value to a format we expect. */ 
@@ -691,9 +695,9 @@ get_imm (const char *param, struct spu_insn *insn, int arg)
     {
       insn->reloc_arg[reloc_i] = arg;
       if (high)
-       insn->flag[reloc_i] |= 1;
-      if (low)
-       insn->flag[reloc_i] |= 2;
+       insn->flag[reloc_i] = 1;
+      else if (low)
+       insn->flag[reloc_i] = 2;
     }
 
   return param;
@@ -802,6 +806,52 @@ md_create_long_jump (char *ptr,
 }
 #endif
 
+/* Support @ppu on symbols referenced in .int/.long/.word/.quad.  */
+static void
+spu_cons (int nbytes)
+{
+  expressionS exp;
+
+  if (is_it_end_of_statement ())
+    {
+      demand_empty_rest_of_line ();
+      return;
+    }
+
+  do
+    {
+      expression (&exp);
+      if (exp.X_op == O_symbol
+         && strncasecmp (input_line_pointer, "@ppu", 4) == 0)
+       {
+         char *p = frag_more (nbytes);
+         enum bfd_reloc_code_real reloc;
+
+         /* Check for identifier@suffix+constant.  */
+         input_line_pointer += 4;
+         if (*input_line_pointer == '-' || *input_line_pointer == '+')
+           {
+             expressionS new_exp;
+
+             expression (&new_exp);
+             if (new_exp.X_op == O_constant)
+               exp.X_add_number += new_exp.X_add_number;
+           }
+
+         reloc = nbytes == 4 ? BFD_RELOC_SPU_PPU32 : BFD_RELOC_SPU_PPU64;
+         fix_new_exp (frag_now, p - frag_now->fr_literal, nbytes,
+                      &exp, 0, reloc);
+       }
+      else
+       emit_expr (&exp, nbytes);
+    }
+  while (*input_line_pointer++ == ',');
+
+  /* Put terminator back into stream.  */
+  input_line_pointer--;
+  demand_empty_rest_of_line ();
+}
+
 int
 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
                               segT segment_type ATTRIBUTE_UNUSED)
index 490177f39a29896be6e722a32d5398f6f8c6e8ea..4746764232295cf3bf56166ac761cf1a87334743 100644 (file)
@@ -61,8 +61,12 @@ struct tc_fix_info {
     }                                          \
   while (0)
 
-/* Don't reduce function symbols to section symbols.  */
-#define tc_fix_adjustable(FIXP) (!S_IS_FUNCTION ((FIXP)->fx_addsy))
+/* Don't reduce function symbols to section symbols, and don't adjust
+   references to PPU symbols.  */
+#define tc_fix_adjustable(FIXP) \
+  (!(S_IS_FUNCTION ((FIXP)->fx_addsy)                  \
+     || (FIXP)->fx_r_type == BFD_RELOC_SPU_PPU32       \
+     || (FIXP)->fx_r_type == BFD_RELOC_SPU_PPU64))
 
 /* Keep relocs on calls.  Branches to function symbols are tail or
    sibling calls.  */
@@ -73,6 +77,8 @@ struct tc_fix_info {
        || (FIXP)->tc_fix_data.insn_tag == M_BRA)       \
        && (FIXP)->fx_addsy != NULL                     \
        && S_IS_FUNCTION ((FIXP)->fx_addsy))            \
+   || (FIXP)->fx_r_type == BFD_RELOC_SPU_PPU32         \
+   || (FIXP)->fx_r_type == BFD_RELOC_SPU_PPU64         \
    || generic_force_reloc (FIXP))
 
 /* Values passed to md_apply_fix don't include symbol values.  */
index c214009738c12d0162547f8a225643cf51acb5e0..3169065b0f284afa70e7c74c0208bcf232f0daeb 100644 (file)
@@ -1,3 +1,7 @@
+2007-05-11  Alan Modra  <amodra@bigpond.net.au>
+
+       * spu.h (R_SPU_PPU32, R_SPU_PPU64): Define.
+
 2007-05-02  Alan Modra  <amodra@bigpond.net.au>
 
        * internal.h (ELF_IS_SECTION_IN_SEGMENT): Check both file offset
index 2e3f0500d1e1d8902e234f51a71ef8768ca5ed9b..2ae80c598f1fe4194f1c09a45708a8fbb7762434 100644 (file)
@@ -1,6 +1,6 @@
 /* SPU ELF support for BFD.
 
-   Copyright 2006 Free Software Foundation, Inc.
+   Copyright 2006, 2007 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -39,6 +39,8 @@ START_RELOC_NUMBERS (elf_spu_reloc_type)
      RELOC_NUMBER (R_SPU_ADDR10I,      11)
      RELOC_NUMBER (R_SPU_ADDR16I,      12)
      RELOC_NUMBER (R_SPU_REL32,                13)
+     RELOC_NUMBER (R_SPU_PPU32,                14)
+     RELOC_NUMBER (R_SPU_PPU64,                15)
 END_RELOC_NUMBERS (R_SPU_max)
 
 /* Program header extensions */