diff options
author | Alan Modra <amodra@gmail.com> | 2007-05-11 03:10:11 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2007-05-11 03:10:11 +0000 |
commit | ece5ef60797fafabe50aae16758ecb33b033871d (patch) | |
tree | 89aad076c5b14d568aec538ccf07e4d080b94443 | |
parent | 88b131f3cecc522396bf5c83c09ff76476ad56b9 (diff) | |
download | gdb-ece5ef60797fafabe50aae16758ecb33b033871d.zip gdb-ece5ef60797fafabe50aae16758ecb33b033871d.tar.gz gdb-ece5ef60797fafabe50aae16758ecb33b033871d.tar.bz2 |
include/elf/
* 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.
-rw-r--r-- | bfd/ChangeLog | 17 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 2 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 7 | ||||
-rw-r--r-- | bfd/elf32-spu.c | 64 | ||||
-rw-r--r-- | bfd/elflink.c | 16 | ||||
-rw-r--r-- | bfd/libbfd.h | 2 | ||||
-rw-r--r-- | bfd/reloc.c | 4 | ||||
-rw-r--r-- | binutils/ChangeLog | 6 | ||||
-rw-r--r-- | binutils/embedspu.sh | 44 | ||||
-rw-r--r-- | gas/ChangeLog | 10 | ||||
-rw-r--r-- | gas/config/tc-spu.c | 84 | ||||
-rw-r--r-- | gas/config/tc-spu.h | 10 | ||||
-rw-r--r-- | include/elf/ChangeLog | 4 | ||||
-rw-r--r-- | include/elf/spu.h | 4 |
14 files changed, 239 insertions, 35 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b7f09eb..71e7ef7 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 8154435..e08dddf 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -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. diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index e9ee29b..33ef613 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -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); diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c index b6e5fbc..865e1c0 100644 --- a/bfd/elf32-spu.c +++ b/bfd/elf32-spu.c @@ -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 diff --git a/bfd/elflink.c b/bfd/elflink.c index e64819e..41b518d 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -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; diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 92bf14a..c9e3df2 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -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", diff --git a/bfd/reloc.c b/bfd/reloc.c index 2a16962..fa9c59d 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -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. diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 8e68263..f5f0b58 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -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. diff --git a/binutils/embedspu.sh b/binutils/embedspu.sh index 3269ab8..7a32158 100644 --- a/binutils/embedspu.sh +++ b/binutils/embedspu.sh @@ -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 @@ -179,6 +186,35 @@ $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 .globl ${SYMBOL} diff --git a/gas/ChangeLog b/gas/ChangeLog index c3f7a3f..7f88343 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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 diff --git a/gas/config/tc-spu.c b/gas/config/tc-spu.c index f4690fb..995a023 100644 --- a/gas/config/tc-spu.c +++ b/gas/config/tc-spu.c @@ -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) diff --git a/gas/config/tc-spu.h b/gas/config/tc-spu.h index 490177f..4746764 100644 --- a/gas/config/tc-spu.h +++ b/gas/config/tc-spu.h @@ -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. */ diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index c214009..3169065 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -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 diff --git a/include/elf/spu.h b/include/elf/spu.h index 2e3f050..2ae80c5 100644 --- a/include/elf/spu.h +++ b/include/elf/spu.h @@ -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 */ |