aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-spu.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2007-05-11 03:10:11 +0000
committerAlan Modra <amodra@gmail.com>2007-05-11 03:10:11 +0000
commitece5ef60797fafabe50aae16758ecb33b033871d (patch)
tree89aad076c5b14d568aec538ccf07e4d080b94443 /gas/config/tc-spu.c
parent88b131f3cecc522396bf5c83c09ff76476ad56b9 (diff)
downloadgdb-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.
Diffstat (limited to 'gas/config/tc-spu.c')
-rw-r--r--gas/config/tc-spu.c84
1 files changed, 67 insertions, 17 deletions
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)