summaryrefslogtreecommitdiff
path: root/gas/config/tc-spu.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2009-01-12 00:23:58 +0000
committerAlan Modra <amodra@bigpond.net.au>2009-01-12 00:23:58 +0000
commitb707fe761140b54617889b083d873edfe5ca346e (patch)
tree6b23511fb081e5e0c2f143b9c51a91524934b177 /gas/config/tc-spu.c
parent2c9ef631d960b4047a3f973a79f39275e5516e73 (diff)
downloadbinutils-redhat-b707fe761140b54617889b083d873edfe5ca346e.tar.gz
bfd/
* elf32-spu.c (struct spu_link_hash_table): Add init, line_size_log2, num_lines_log2. (struct got_entry): Add br_addr. (struct call_info): Add priority. (struct function_info): Add lr_store and sp_adjust. (spu_elf_setup): Init line_size_log2 and num_lines_log2. (spu_elf_find_overlays): For soft-icache, mark any section within cache area as an overlay, and check that no other overlays exist. Look up icache overlay manager entry sym. (BRA_STUBS, BRA, BRASL): Define. (enum _stub_type): Replace ovl_stub with call_ovl_stub and br*_ovl_stub. (needs_ovl_stub): Adjust for soft-icache. Return priority encoded in branch insn. (count_stub, build_stub): Support soft-icache. (build_spuear_stubs, process_stubs): Adjust build_stub call. (spu_elf_size_stubs): Size soft-icache stubs. (overlay_index): New function. (spu_elf_build_stubs): Make static. Support soft-icache. (spu_elf_check_vma): Don't turn off auto_overlay if soft-icache. (find_function_stack_adjust): Save lr store and stack adjust insn offsets. (maybe_insert_function): Adjust find_function_stack_adjust call. (mark_functions_via_relocs): Retrieve priority. (remove_cycles): Only warn about pruned arcs when stack_analysis. (sort_calls): Sort by priority first. (mark_overlay_section): Ignore .ovl.init. (sum_stack): Only print when stack_analysis. (print_one_overlay_section): New function, extracted from.. (spu_elf_auto_overlay): ..here. Support soft-icache overlays. (spu_elf_stack_analysis): Only print when htab->stack_analysis. (spu_elf_final_link): Call spu_elf_stack_analysis for lrlive analysis. Call spu_elf_build_stubs. (spu_elf_relocate_section): For soft-icache encode overlay index into addresses. (spu_elf_output_symbol_hook): Support soft-icache. (spu_elf_modify_program_headers: Likewise. * elf32-spu.h (struct spu_elf_params): Add lrlive_analysis. Rename num_regions to num_lines. Add line_size and max_branch. (enum _ovly_flavour): Add ovly_soft_icache. (spu_elf_build_stubs): Delete. gas/ * config/tc-spu.c (md_pseudo_table): Add "brinfo". (brinfo): New var. (md_assemble): Poke brinfo into branch instructions. (spu_brinfo): New function. (md_apply_fix): Don't assume insn fields start off at zero, mask them to remove possible brinfo. ld/ * emultempl/spuelf.em (params): Init new fields. (num_lines_set, line_size_set, icache_mgr, icache_mgr_stream): New vars. (spu_place_special_section): Adjust placement for soft-icache. Pad soft-icache section to a fixed size. Clear addr_tree. (spu_elf_load_ovl_mgr): Support soft-icache. Map overlay manager sections a little more intelligently. (gld${EMULATION_NAME}_finish): Don't call spu_elf_build_stubs. (OPTION_SPU_NUM_LINES): Rename from OPTION_SPU_NUM_REGIONS. (OPTION_SPU_SOFT_ICACHE, OPTION_SPU_LINE_SIZE): Define. (OPTION_SPU_LRLIVE): Define. (PARSE_AND_LIST_LONGOPTS): Add new soft-icache options. (PARSE_AND_LIST_OPTIONS): Likewise. (PARSE_AND_LIST_ARGS_CASES): Handle them. * emultempl/spu_icache.S: Dummy file. * emultempl/spu_icache.o_c: Regenerate. * Makefile.am (eelf32_spu.c): Depend on spu_icache.o_c. (spu_icache.o_c): Add rule to build. (CLEANFILES): Zap temp files. (EXTRA_DIST): Add spu_icache.o_c. * Makefile.in: Regenerate. ld/testsuite/ * ld-spu/ovl.d: Allow for absolute branches in stubs. * ld-spu/ovl2.d: Likewise.
Diffstat (limited to 'gas/config/tc-spu.c')
-rw-r--r--gas/config/tc-spu.c165
1 files changed, 114 insertions, 51 deletions
diff --git a/gas/config/tc-spu.c b/gas/config/tc-spu.c
index e159e34f0b..0b40a562f1 100644
--- a/gas/config/tc-spu.c
+++ b/gas/config/tc-spu.c
@@ -1,6 +1,6 @@
/* spu.c -- Assembler for the IBM Synergistic Processing Unit (SPU)
- Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -53,6 +53,7 @@ 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_brinfo (int);
static void spu_cons (int);
extern char *myname;
@@ -82,6 +83,7 @@ const char FLT_CHARS[] = "dDfF";
const pseudo_typeS md_pseudo_table[] =
{
{"align", s_align_ptwo, 4},
+ {"brinfo", spu_brinfo, 0},
{"bss", s_lcomm_bytes, 1},
{"def", s_set, 0},
{"dfloat", float_cons, 'd'},
@@ -104,6 +106,9 @@ const pseudo_typeS md_pseudo_table[] =
{0,0,0}
};
+/* Bits plugged into branch instruction offset field. */
+unsigned int brinfo;
+
void
md_begin (void)
{
@@ -342,6 +347,16 @@ md_assemble (char *op)
as_warn (_("Treating '%-*s' as a symbol."), (int)(syntax_error_param - d), d);
}
+ if (brinfo != 0
+ && (insn.tag <= M_BRASL
+ || (insn.tag >= M_BRZ && insn.tag <= M_BRHNZ))
+ && (insn.opcode & 0x7ff80) == 0
+ && (insn.reloc_arg[0] == A_R18
+ || insn.reloc_arg[0] == A_S18
+ || insn.reloc_arg[1] == A_R18
+ || insn.reloc_arg[1] == A_S18))
+ insn.opcode |= brinfo << 7;
+
/* grow the current frag and plop in the opcode */
thisfrag = frag_more (4);
@@ -370,6 +385,9 @@ md_assemble (char *op)
fixP->tc_fix_data.insn_tag = insn.tag;
}
dwarf2_emit_insn (4);
+
+ /* .brinfo lasts exactly one instruction. */
+ brinfo = 0;
}
static int
@@ -752,6 +770,39 @@ md_create_long_jump (char *ptr,
}
#endif
+/* Handle .brinfo <priority>,<lrlive>. */
+static void
+spu_brinfo (int ignore ATTRIBUTE_UNUSED)
+{
+ addressT priority;
+ addressT lrlive;
+
+ priority = get_absolute_expression ();
+ SKIP_WHITESPACE ();
+
+ lrlive = 0;
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ lrlive = get_absolute_expression ();
+ }
+
+ if (priority > 0x1fff)
+ {
+ as_bad (_("invalid priority '%lu'"), (unsigned long) priority);
+ priority = 0;
+ }
+
+ if (lrlive > 7)
+ {
+ as_bad (_("invalid lrlive '%lu'"), (unsigned long) lrlive);
+ lrlive = 0;
+ }
+
+ brinfo = (lrlive << 13) | priority;
+ demand_empty_rest_of_line ();
+}
+
/* Support @ppu on symbols referenced in .int/.long/.word/.quad. */
static void
spu_cons (int nbytes)
@@ -898,6 +949,7 @@ void
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
unsigned int res;
+ unsigned int mask;
valueT val = *valP;
char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
@@ -944,6 +996,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
fixP->fx_done = 1;
res = 0;
+ mask = 0;
if (fixP->tc_fix_data.arg_format > A_P)
{
int hi = arg_encode[fixP->tc_fix_data.arg_format].hi;
@@ -955,84 +1008,94 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
}
switch (fixP->fx_r_type)
- {
- case BFD_RELOC_8:
+ {
+ case BFD_RELOC_8:
md_number_to_chars (place, val, 1);
return;
- case BFD_RELOC_16:
+ case BFD_RELOC_16:
md_number_to_chars (place, val, 2);
return;
- case BFD_RELOC_32:
+ case BFD_RELOC_32:
case BFD_RELOC_32_PCREL:
md_number_to_chars (place, val, 4);
return;
- case BFD_RELOC_64:
+ case BFD_RELOC_64:
md_number_to_chars (place, val, 8);
return;
- case BFD_RELOC_SPU_IMM7:
- res = (val & 0x7f) << 14;
- break;
+ case BFD_RELOC_SPU_IMM7:
+ res = val << 14;
+ mask = 0x7f << 14;
+ break;
- case BFD_RELOC_SPU_IMM8:
- res = (val & 0xff) << 14;
- break;
+ case BFD_RELOC_SPU_IMM8:
+ res = val << 14;
+ mask = 0xff << 14;
+ break;
- case BFD_RELOC_SPU_IMM10:
- res = (val & 0x3ff) << 14;
- break;
+ case BFD_RELOC_SPU_IMM10:
+ res = val << 14;
+ mask = 0x3ff << 14;
+ break;
- case BFD_RELOC_SPU_IMM10W:
- res = (val & 0x3ff0) << 10;
- break;
+ case BFD_RELOC_SPU_IMM10W:
+ res = val << 10;
+ mask = 0x3ff0 << 10;
+ break;
- case BFD_RELOC_SPU_IMM16:
- res = (val & 0xffff) << 7;
- break;
+ case BFD_RELOC_SPU_IMM16:
+ res = val << 7;
+ mask = 0xffff << 7;
+ break;
- case BFD_RELOC_SPU_IMM16W:
- res = (val & 0x3fffc) << 5;
- break;
+ case BFD_RELOC_SPU_IMM16W:
+ res = val << 5;
+ mask = 0x3fffc << 5;
+ break;
- case BFD_RELOC_SPU_IMM18:
- res = (val & 0x3ffff) << 7;
- break;
+ case BFD_RELOC_SPU_IMM18:
+ res = val << 7;
+ mask = 0x3ffff << 7;
+ break;
- case BFD_RELOC_SPU_PCREL9a:
- res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 14);
- break;
+ case BFD_RELOC_SPU_PCREL9a:
+ res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 14);
+ mask = (0x1fc >> 2) | (0x600 << 14);
+ break;
- case BFD_RELOC_SPU_PCREL9b:
- res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 5);
- break;
+ case BFD_RELOC_SPU_PCREL9b:
+ res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 5);
+ mask = (0x1fc >> 2) | (0x600 << 5);
+ break;
- case BFD_RELOC_SPU_PCREL16:
- res = (val & 0x3fffc) << 5;
- break;
+ case BFD_RELOC_SPU_PCREL16:
+ res = val << 5;
+ mask = 0x3fffc << 5;
+ break;
case BFD_RELOC_SPU_HI16:
- res = (val >> 9) & 0x7fff80;
+ res = val >> 9;
+ mask = 0xffff << 7;
break;
case BFD_RELOC_SPU_LO16:
- res = (val << 7) & 0x7fff80;
+ res = val << 7;
+ mask = 0xffff << 7;
break;
- default:
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("reloc %d not supported by object file format"),
- (int) fixP->fx_r_type);
- }
-
- if (res != 0)
- {
- place[0] |= (res >> 24) & 0xff;
- place[1] |= (res >> 16) & 0xff;
- place[2] |= (res >> 8) & 0xff;
- place[3] |= (res) & 0xff;
- }
+ default:
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("reloc %d not supported by object file format"),
+ (int) fixP->fx_r_type);
+ }
+
+ res &= mask;
+ place[0] = (place[0] & (~mask >> 24)) | ((res >> 24) & 0xff);
+ place[1] = (place[1] & (~mask >> 16)) | ((res >> 16) & 0xff);
+ place[2] = (place[2] & (~mask >> 8)) | ((res >> 8) & 0xff);
+ place[3] = (place[3] & ~mask) | (res & 0xff);
}
}