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.
This commit is contained in:
Alan Modra 2007-05-11 03:10:11 +00:00
parent 88b131f3ce
commit ece5ef6079
14 changed files with 239 additions and 35 deletions

View 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> 2007-05-10 Richard Sandiford <richard@codesourcery.com>
* elf32-arm.c (elf32_arm_check_relocs): Don't create PLT entries * elf32-arm.c (elf32_arm_check_relocs): Don't create PLT entries

View file

@ -2513,6 +2513,8 @@ relocation types already defined. */
BFD_RELOC_SPU_PCREL16, BFD_RELOC_SPU_PCREL16,
BFD_RELOC_SPU_LO16, BFD_RELOC_SPU_LO16,
BFD_RELOC_SPU_HI16, BFD_RELOC_SPU_HI16,
BFD_RELOC_SPU_PPU32,
BFD_RELOC_SPU_PPU64,
/* Alpha ECOFF and ELF relocations. Some of these treat the symbol or /* Alpha ECOFF and ELF relocations. Some of these treat the symbol or
"addend" in some special way. "addend" in some special way.

View file

@ -792,8 +792,11 @@ struct elf_backend_data
STB_LOCAL/STT_SECTION symbols specially. The output symbol is STB_LOCAL/STT_SECTION symbols specially. The output symbol is
going to be the section symbol corresponding to the output going to be the section symbol corresponding to the output
section, which means that the addend must be adjusted section, which means that the addend must be adjusted
accordingly. */ accordingly.
bfd_boolean (*elf_backend_relocate_section)
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, (bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd,
asection *input_section, bfd_byte *contents, Elf_Internal_Rela *relocs, asection *input_section, bfd_byte *contents, Elf_Internal_Rela *relocs,
Elf_Internal_Sym *local_syms, asection **local_sections); Elf_Internal_Sym *local_syms, asection **local_sections);

View file

@ -78,6 +78,12 @@ static reloc_howto_type elf_howto_table[] = {
HOWTO (R_SPU_REL32, 0, 2, 32, TRUE, 0, complain_overflow_dont, HOWTO (R_SPU_REL32, 0, 2, 32, TRUE, 0, complain_overflow_dont,
bfd_elf_generic_reloc, "SPU_REL32", bfd_elf_generic_reloc, "SPU_REL32",
FALSE, 0, 0xffffffff, TRUE), 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[] = { 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; return R_SPU_ADDR32;
case BFD_RELOC_32_PCREL: case BFD_RELOC_32_PCREL:
return R_SPU_REL32; 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); 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. */ /* Apply RELOCS to CONTENTS of INPUT_SECTION from INPUT_BFD. */
static bfd_boolean static bfd_boolean
@ -2644,6 +2674,7 @@ spu_elf_relocate_section (bfd *output_bfd,
Elf_Internal_Rela *rel, *relend; Elf_Internal_Rela *rel, *relend;
struct spu_link_hash_table *htab; struct spu_link_hash_table *htab;
bfd_boolean ret = TRUE; bfd_boolean ret = TRUE;
bfd_boolean emit_these_relocs = FALSE;
htab = spu_hash_table (info); htab = spu_hash_table (info);
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 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_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (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; howto = elf_howto_table + r_type;
unresolved_reloc = FALSE; unresolved_reloc = FALSE;
warned = FALSE; warned = FALSE;
h = NULL; h = NULL;
sym = NULL; sym = NULL;
sec = 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; 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_type_lookup spu_elf_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup spu_elf_reloc_name_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_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_relocate_section spu_elf_relocate_section
#define elf_backend_symbol_processing spu_elf_backend_symbol_processing #define elf_backend_symbol_processing spu_elf_backend_symbol_processing
#define elf_backend_link_output_symbol_hook spu_elf_output_symbol_hook #define elf_backend_link_output_symbol_hook spu_elf_output_symbol_hook

View file

@ -8198,7 +8198,7 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info)
static bfd_boolean static bfd_boolean
elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) 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 *, (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **); Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
bfd *output_bfd; bfd *output_bfd;
@ -8212,7 +8212,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
asection **ppsection; asection **ppsection;
asection *o; asection *o;
const struct elf_backend_data *bed; const struct elf_backend_data *bed;
bfd_boolean emit_relocs;
struct elf_link_hash_entry **sym_hashes; struct elf_link_hash_entry **sym_hashes;
output_bfd = finfo->output_bfd; 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) if ((input_bfd->flags & DYNAMIC) != 0)
return TRUE; return TRUE;
emit_relocs = (finfo->info->relocatable
|| finfo->info->emitrelocations);
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
if (elf_bad_symtab (input_bfd)) 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; Elf_Internal_Rela *internal_relocs;
bfd_vma r_type_mask; bfd_vma r_type_mask;
int r_sym_shift; int r_sym_shift;
int ret;
/* Get the swapped relocs. */ /* Get the swapped relocs. */
internal_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 corresponding to the output section, which will require
the addend to be adjusted. */ the addend to be adjusted. */
if (! (*relocate_section) (output_bfd, finfo->info, ret = (*relocate_section) (output_bfd, finfo->info,
input_bfd, o, contents, input_bfd, o, contents,
internal_relocs, internal_relocs,
isymbuf, isymbuf,
finfo->sections)) finfo->sections);
if (!ret)
return FALSE; return FALSE;
if (emit_relocs) if (ret == 2
|| finfo->info->relocatable
|| finfo->info->emitrelocations)
{ {
Elf_Internal_Rela *irela; Elf_Internal_Rela *irela;
Elf_Internal_Rela *irelaend; Elf_Internal_Rela *irelaend;

View file

@ -919,6 +919,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_SPU_PCREL16", "BFD_RELOC_SPU_PCREL16",
"BFD_RELOC_SPU_LO16", "BFD_RELOC_SPU_LO16",
"BFD_RELOC_SPU_HI16", "BFD_RELOC_SPU_HI16",
"BFD_RELOC_SPU_PPU32",
"BFD_RELOC_SPU_PPU64",
"BFD_RELOC_ALPHA_GPDISP_HI16", "BFD_RELOC_ALPHA_GPDISP_HI16",
"BFD_RELOC_ALPHA_GPDISP_LO16", "BFD_RELOC_ALPHA_GPDISP_LO16",
"BFD_RELOC_ALPHA_GPDISP", "BFD_RELOC_ALPHA_GPDISP",

View file

@ -1972,6 +1972,10 @@ ENUMX
BFD_RELOC_SPU_LO16 BFD_RELOC_SPU_LO16
ENUMX ENUMX
BFD_RELOC_SPU_HI16 BFD_RELOC_SPU_HI16
ENUMX
BFD_RELOC_SPU_PPU32
ENUMX
BFD_RELOC_SPU_PPU64
ENUMDOC ENUMDOC
SPU Relocations. SPU Relocations.

View 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> 2007-04-28 Alan Modra <amodra@bigpond.net.au>
* prdbg.c (tg_variable): Adjust for changed demangler. * prdbg.c (tg_variable): Adjust for changed demangler.

View file

@ -38,12 +38,12 @@ mydir=`dirname "$0"`
find_prog () find_prog ()
{ {
prog=`echo $1 | sed "$program_transform_name"` prog=`echo $1 | sed "$program_transform_name"`
which $prog > /dev/null 2> /dev/null && return 0
prog="$mydir/$prog" prog="$mydir/$prog"
test -x "$prog" && return 0 test -x "$prog" && return 0
prog="$mydir/$1" prog="$mydir/$1"
test -x "$prog" && return 0 test -x "$prog" && return 0
prog=`echo $1 | sed "$program_transform_name"` prog=`echo $1 | sed "$program_transform_name"`
which $prog > /dev/null 2> /dev/null && return 0
return 1 return 1
} }
@ -95,7 +95,7 @@ main ()
CC="$prog" CC="$prog"
fi fi
# Find readelf. Any old readelf should do. We only want to read syms. # Find readelf. Any old readelf should do.
find_prog readelf find_prog readelf
if test $? -ne 0; then if test $? -ne 0; then
if which readelf > /dev/null 2> /dev/null; 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=`${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_addr=`echo $toe | sed -n -e 's,.* ,,p'`
toe=`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=`${READELF} -S ${INFILE} | sed -n -e 's, *\[ *\([0-9]*\)\] *[^ ]* *PROGBITS *\([0-9a-f]*\) *\([0-9a-f]*\).*,\1 \2 \3,p'`
sections=`echo ${sections}` 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. # Build embedded SPU image.
# 1. The whole SPU ELF file is written to .rodata.speelf # 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 # write the address of the corresponding PowerPC symbol in a table
# built in .data.spetoe. For _EAE_ symbols not in .toe, create # built in .data.spetoe. For _EAE_ symbols not in .toe, create
# .reloc commands to relocate their location directly. # .reloc commands to relocate their location directly.
# 3. Write a struct spe_program_handle to .data. # 3. Look for R_SPU_PPU32 and R_SPU_PPU64 relocations in the SPU ELF image
# 4. Write a table of _SPUEAR_ symbols. # 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 \ ${CC} ${FLAGS} -x assembler-with-cpp -nostartfiles -nostdlib \
-Wa,-mbig -Wl,-r -Wl,-x -o ${OUTFILE} - <<EOF -Wa,-mbig -Wl,-r -Wl,-x -o ${OUTFILE} - <<EOF
.section .rodata.speelf,"a",@progbits .section .rodata.speelf,"a",@progbits
@ -178,6 +185,35 @@ $7 != "'${toe}'" && $7 in sec_off { \
$7 != "'${toe}'" && ! $7 in sec_off { \ $7 != "'${toe}'" && ! $7 in sec_off { \
print "#error Section not found for " $8; \ 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 .section .data,"aw",@progbits

View 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> 2007-05-05 Mark Shinwell <shinwell@codesourcery.com>
* config/tc-arm.c (md_apply_fix): Generate more accurate * config/tc-arm.c (md_apply_fix): Generate more accurate

View 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_imm (const char *param, struct spu_insn *insn, int arg);
static const char *get_reg (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); int accept_expr);
static int calcop (struct spu_opcode *format, const char *param, static int calcop (struct spu_opcode *format, const char *param,
struct spu_insn *insn); struct spu_insn *insn);
static void spu_cons (int);
extern char *myname; extern char *myname;
static struct hash_control *op_hash = NULL; static struct hash_control *op_hash = NULL;
@ -82,14 +82,17 @@ const char FLT_CHARS[] = "dDfF";
const pseudo_typeS md_pseudo_table[] = const pseudo_typeS md_pseudo_table[] =
{ {
{"align", s_align_ptwo, 4}, {"align", s_align_ptwo, 4},
{"bss", s_lcomm_bytes, 1},
{"def", s_set, 0}, {"def", s_set, 0},
{"dfloat", float_cons, 'd'}, {"dfloat", float_cons, 'd'},
{"ffloat", float_cons, 'f'}, {"ffloat", float_cons, 'f'},
{"global", s_globl, 0}, {"global", s_globl, 0},
{"half", cons, 2}, {"half", cons, 2},
{"bss", s_lcomm_bytes, 1}, {"int", spu_cons, 4},
{"long", spu_cons, 4},
{"quad", spu_cons, 8},
{"string", stringer, 1}, {"string", stringer, 1},
{"word", cons, 4}, {"word", spu_cons, 4},
/* Force set to be treated as an instruction. */ /* Force set to be treated as an instruction. */
{"set", NULL, 0}, {"set", NULL, 0},
{".set", s_set, 0}, {".set", s_set, 0},
@ -351,13 +354,14 @@ md_assemble (char *op)
fixS *fixP; fixS *fixP;
bfd_reloc_code_real_type reloc = arg_encode[insn.reloc_arg[i]].reloc; bfd_reloc_code_real_type reloc = arg_encode[insn.reloc_arg[i]].reloc;
int pcrel = 0; int pcrel = 0;
if (reloc == BFD_RELOC_SPU_PCREL9a if (reloc == BFD_RELOC_SPU_PCREL9a
|| reloc == BFD_RELOC_SPU_PCREL9b || reloc == BFD_RELOC_SPU_PCREL9b
|| reloc == BFD_RELOC_SPU_PCREL16) || reloc == BFD_RELOC_SPU_PCREL16)
pcrel = 1; pcrel = 1;
if (insn.flag[i] & 1) if (insn.flag[i] == 1)
reloc = BFD_RELOC_SPU_HI16; reloc = BFD_RELOC_SPU_HI16;
else if (insn.flag[i] & 2) else if (insn.flag[i] == 2)
reloc = BFD_RELOC_SPU_LO16; reloc = BFD_RELOC_SPU_LO16;
fixP = fix_new_exp (frag_now, fixP = fix_new_exp (frag_now,
thisfrag - frag_now->fr_literal, 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 low = 0, high = 0;
int reloc_i = insn->reloc_arg[0] >= 0 ? 1 : 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; param += 3;
low = 1; low = 1;
as_warn (_("Using old style, %%lo(expr), please change to PPC style, expr@l.")); 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; param += 3;
high = 1; high = 1;
as_warn (_("Using old style, %%hi(expr), please change to PPC style, expr@h.")); 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. /* 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; param += 4;
} }
if (*param == '$') if (*param == '$')
{ {
/* Symbols can start with $, but if this symbol matches a register /* Symbols can start with $, but if this symbol matches a register
* name, it's probably a mistake. The only way to avoid this name, it's probably a mistake. The only way to avoid this
* warning is to rename the symbol. */ warning is to rename the symbol. */
struct spu_insn tmp_insn; struct spu_insn tmp_insn;
const char *np = get_reg (param, &tmp_insn, arg, 0); 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; input_line_pointer = save_ptr;
/* Similar to ppc_elf_suffix in tc-ppc.c. We have so few cases to /* 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[0] == '@' && !ISALNUM (param[2]) && param[2] != '@')
{ {
if (param[1] == 'h' || param[1] == 'H') 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) if (insn->exp[reloc_i].X_op == O_constant)
{ {
val = insn->exp[reloc_i].X_add_number;
if (emulate_apuasm) if (emulate_apuasm)
{ {
/* Convert the value to a format we expect. */ /* 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; insn->reloc_arg[reloc_i] = arg;
if (high) if (high)
insn->flag[reloc_i] |= 1; insn->flag[reloc_i] = 1;
if (low) else if (low)
insn->flag[reloc_i] |= 2; insn->flag[reloc_i] = 2;
} }
return param; return param;
@ -802,6 +806,52 @@ md_create_long_jump (char *ptr,
} }
#endif #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 int
md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
segT segment_type ATTRIBUTE_UNUSED) segT segment_type ATTRIBUTE_UNUSED)

View file

@ -61,8 +61,12 @@ struct tc_fix_info {
} \ } \
while (0) while (0)
/* Don't reduce function symbols to section symbols. */ /* Don't reduce function symbols to section symbols, and don't adjust
#define tc_fix_adjustable(FIXP) (!S_IS_FUNCTION ((FIXP)->fx_addsy)) 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 /* Keep relocs on calls. Branches to function symbols are tail or
sibling calls. */ sibling calls. */
@ -73,6 +77,8 @@ struct tc_fix_info {
|| (FIXP)->tc_fix_data.insn_tag == M_BRA) \ || (FIXP)->tc_fix_data.insn_tag == M_BRA) \
&& (FIXP)->fx_addsy != NULL \ && (FIXP)->fx_addsy != NULL \
&& S_IS_FUNCTION ((FIXP)->fx_addsy)) \ && 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)) || generic_force_reloc (FIXP))
/* Values passed to md_apply_fix don't include symbol values. */ /* Values passed to md_apply_fix don't include symbol values. */

View 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> 2007-05-02 Alan Modra <amodra@bigpond.net.au>
* internal.h (ELF_IS_SECTION_IN_SEGMENT): Check both file offset * internal.h (ELF_IS_SECTION_IN_SEGMENT): Check both file offset

View file

@ -1,6 +1,6 @@
/* SPU ELF support for BFD. /* 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. 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_ADDR10I, 11)
RELOC_NUMBER (R_SPU_ADDR16I, 12) RELOC_NUMBER (R_SPU_ADDR16I, 12)
RELOC_NUMBER (R_SPU_REL32, 13) RELOC_NUMBER (R_SPU_REL32, 13)
RELOC_NUMBER (R_SPU_PPU32, 14)
RELOC_NUMBER (R_SPU_PPU64, 15)
END_RELOC_NUMBERS (R_SPU_max) END_RELOC_NUMBERS (R_SPU_max)
/* Program header extensions */ /* Program header extensions */