diff options
author | Alan Modra <amodra@gmail.com> | 2009-01-12 00:23:58 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2009-01-12 00:23:58 +0000 |
commit | cd4a7468c909dc8135cdf6198d596869defcdabe (patch) | |
tree | 71d35b68ba5984de4d54c75253ff12e97a6c710f /gas/config/tc-spu.c | |
parent | 2c0fbbe09e6b2dec0e8fa68f133773e0970bda89 (diff) | |
download | gdb-cd4a7468c909dc8135cdf6198d596869defcdabe.zip gdb-cd4a7468c909dc8135cdf6198d596869defcdabe.tar.gz gdb-cd4a7468c909dc8135cdf6198d596869defcdabe.tar.bz2 |
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.c | 165 |
1 files changed, 114 insertions, 51 deletions
diff --git a/gas/config/tc-spu.c b/gas/config/tc-spu.c index e159e34..0b40a56 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); } } |