* 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.
+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
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.
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);
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[] = {
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;
}
}
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
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;
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;
}
}
+ 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;
}
#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
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;
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;
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))
{
Elf_Internal_Rela *internal_relocs;
bfd_vma r_type_mask;
int r_sym_shift;
+ int ret;
/* Get the swapped relocs. */
internal_relocs
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;
"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",
BFD_RELOC_SPU_LO16
ENUMX
BFD_RELOC_SPU_HI16
+ENUMX
+ BFD_RELOC_SPU_PPU32
+ENUMX
+ BFD_RELOC_SPU_PPU64
ENUMDOC
SPU Relocations.
+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.
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
}
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
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
# 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
$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
+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
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;
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},
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,
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);
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')
}
}
- 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. */
{
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;
}
#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)
} \
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. */
|| (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. */
+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
/* 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.
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 */