diff options
author | Ian Lance Taylor <ian@airs.com> | 1997-05-23 00:26:58 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1997-05-23 00:26:58 +0000 |
commit | 8ac5f94028de75c52748f7ae4157ad12bb571b7c (patch) | |
tree | 2ababe9280b2e3907fbe15f64060b51f5bb7fa08 /bfd/coff-tic80.c | |
parent | 97cbfc2309a0e452c8ba3695348d4bf8e49d9f40 (diff) | |
download | gdb-8ac5f94028de75c52748f7ae4157ad12bb571b7c.zip gdb-8ac5f94028de75c52748f7ae4157ad12bb571b7c.tar.gz gdb-8ac5f94028de75c52748f7ae4157ad12bb571b7c.tar.bz2 |
* coff-tic80.c (tic80_howto_table): Add PP relocations. Change
name of R_RELLONG to "RELLONG". Set rightshift and complain for
M_PPCR.
(ppbase_reloc, glob15_reloc): New static functions.
(glob16_reloc, local16_reloc): New static functions.
(rtype2howto): Handle all relocation types.
(coff_tic80_relocate_section): New static function.
(coff_relocate_section): Define to coff_tic80_relocate_section.
* Makefile.in (coff-tic80.o): Depends upon include/coff/tic80.h.
Diffstat (limited to 'bfd/coff-tic80.c')
-rw-r--r-- | bfd/coff-tic80.c | 598 |
1 files changed, 587 insertions, 11 deletions
diff --git a/bfd/coff-tic80.c b/bfd/coff-tic80.c index b840de0..5f9d90e 100644 --- a/bfd/coff-tic80.c +++ b/bfd/coff-tic80.c @@ -23,6 +23,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "bfd.h" +#include "bfdlink.h" #include "sysdep.h" #include "libbfd.h" #include "coff/tic80.h" @@ -31,9 +32,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2) -#define coff_relocate_section _bfd_coff_generic_relocate_section - -static void rtype2howto PARAMS ((arelent *cache_ptr, struct internal_reloc *dst)); +static void rtype2howto + PARAMS ((arelent *cache_ptr, struct internal_reloc *dst)); +static bfd_reloc_status_type ppbase_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static bfd_reloc_status_type glob15_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static bfd_reloc_status_type glob16_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static bfd_reloc_status_type local16_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static boolean coff_tic80_relocate_section + PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, + struct internal_reloc *, struct internal_syment *, asection **)); static reloc_howto_type tic80_howto_table[] = { @@ -46,19 +57,19 @@ static reloc_howto_type tic80_howto_table[] = 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ NULL, /* special_function */ - "32", /* name */ + "RELLONG", /* name */ true, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ false), /* pcrel_offset */ HOWTO (R_MPPCR, /* type */ - 0, /* rightshift */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ + complain_overflow_signed, /* complain_on_overflow */ NULL, /* special_function */ "MPPCR", /* name */ true, /* partial_inplace */ @@ -79,8 +90,332 @@ static reloc_howto_type tic80_howto_table[] = 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ false), /* pcrel_offset */ + + HOWTO (R_PPBASE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + ppbase_reloc, /* special_function */ + "PPBASE", /* name */ + true, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPLBASE, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + ppbase_reloc, /* special_function */ + "PPLBASE", /* name */ + true, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PP15, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 6, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + glob15_reloc, /* special_function */ + "PP15", /* name */ + true, /* partial_inplace */ + 0x1ffc0, /* src_mask */ + 0x1ffc0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PP15W, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 6, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + glob15_reloc, /* special_function */ + "PP15W", /* name */ + true, /* partial_inplace */ + 0x1ffc0, /* src_mask */ + 0x1ffc0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PP15H, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 6, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + glob15_reloc, /* special_function */ + "PP15H", /* name */ + true, /* partial_inplace */ + 0x1ffc0, /* src_mask */ + 0x1ffc0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PP16B, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 6, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + glob16_reloc, /* special_function */ + "PP16B", /* name */ + true, /* partial_inplace */ + 0x3ffc0, /* src_mask */ + 0x3ffc0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPL15, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + NULL, /* special_function */ + "PPL15", /* name */ + true, /* partial_inplace */ + 0x7fff, /* src_mask */ + 0x7fff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPL15W, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + NULL, /* special_function */ + "PPL15W", /* name */ + true, /* partial_inplace */ + 0x7fff, /* src_mask */ + 0x7fff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPL15H, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + NULL, /* special_function */ + "PPL15H", /* name */ + true, /* partial_inplace */ + 0x7fff, /* src_mask */ + 0x7fff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPL16B, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + local16_reloc, /* special_function */ + "PPL16B", /* name */ + true, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPN15, /* type */ + 0, /* rightshift */ + -2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 6, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + glob15_reloc, /* special_function */ + "PPN15", /* name */ + true, /* partial_inplace */ + 0x1ffc0, /* src_mask */ + 0x1ffc0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPN15W, /* type */ + 2, /* rightshift */ + -2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 6, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + glob15_reloc, /* special_function */ + "PPN15W", /* name */ + true, /* partial_inplace */ + 0x1ffc0, /* src_mask */ + 0x1ffc0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPN15H, /* type */ + 1, /* rightshift */ + -2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 6, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + glob15_reloc, /* special_function */ + "PPN15H", /* name */ + true, /* partial_inplace */ + 0x1ffc0, /* src_mask */ + 0x1ffc0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPN16B, /* type */ + 0, /* rightshift */ + -2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 6, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + glob16_reloc, /* special_function */ + "PPN16B", /* name */ + true, /* partial_inplace */ + 0x3ffc0, /* src_mask */ + 0x3ffc0, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPLN15, /* type */ + 0, /* rightshift */ + -2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + NULL, /* special_function */ + "PPLN15", /* name */ + true, /* partial_inplace */ + 0x7fff, /* src_mask */ + 0x7fff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPLN15W, /* type */ + 2, /* rightshift */ + -2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + NULL, /* special_function */ + "PPLN15W", /* name */ + true, /* partial_inplace */ + 0x7fff, /* src_mask */ + 0x7fff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPLN15H, /* type */ + 1, /* rightshift */ + -2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + NULL, /* special_function */ + "PPLN15H", /* name */ + true, /* partial_inplace */ + 0x7fff, /* src_mask */ + 0x7fff, /* dst_mask */ + false), /* pcrel_offset */ + + HOWTO (R_PPLN16B, /* type */ + 0, /* rightshift */ + -2, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + local16_reloc, /* special_function */ + "PPLN16B", /* name */ + true, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + false) /* pcrel_offset */ }; + +/* Special relocation functions, used when the output file is not + itself a COFF TIc80 file. */ + +/* This special function is used for the base address type + relocations. */ + +static bfd_reloc_status_type +ppbase_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, + error_message) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol_in; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; +{ + /* FIXME. */ + abort (); +} + +/* This special function is used for the global 15 bit relocations. */ + +static bfd_reloc_status_type +glob15_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, + error_message) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol_in; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; +{ + /* FIXME. */ + abort (); +} + +/* This special function is used for the global 16 bit relocations. */ + +static bfd_reloc_status_type +glob16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, + error_message) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol_in; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; +{ + /* FIXME. */ + abort (); +} +/* This special function is used for the local 16 bit relocations. */ + +static bfd_reloc_status_type +local16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, + error_message) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol_in; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; +{ + /* FIXME. */ + abort (); +} + /* Code to turn an external r_type into a pointer to an entry in the howto_table. If passed an r_type we don't recognize the abort rather than silently failing to generate an output file. */ @@ -90,13 +425,20 @@ rtype2howto (cache_ptr, dst) arelent *cache_ptr; struct internal_reloc *dst; { - switch (dst -> r_type) + unsigned int i; + + for (i = 0; i < sizeof tic80_howto_table / sizeof tic80_howto_table[0]; i++) { - default: abort (); break; - case R_RELLONG: cache_ptr -> howto = tic80_howto_table + 0; break; - case R_MPPCR: cache_ptr -> howto = tic80_howto_table + 1; break; - case R_ABS: cache_ptr -> howto = tic80_howto_table + 2; break; + if (tic80_howto_table[i].type == dst->r_type) + { + cache_ptr->howto = tic80_howto_table + i; + return; + } } + + (*_bfd_error_handler) ("Unrecognized reloc type 0x%x", + (unsigned int) dst->r_type); + cache_ptr->howto = tic80_howto_table + 0; } #define RTYPE2HOWTO(cache_ptr, dst) rtype2howto (cache_ptr, dst) @@ -127,7 +469,241 @@ coff_tic80_rtype_to_howto (abfd, sec, rel, h, sym, addendp) #ifndef BADMAG #define BADMAG(x) TIC80BADMAG(x) #endif + +#define coff_relocate_section coff_tic80_relocate_section + +/* We need a special relocation routine to handle the PP relocs. Most + of this is a copy of _bfd_coff_generic_relocate_section. */ + +static boolean +coff_tic80_relocate_section (output_bfd, info, input_bfd, + input_section, contents, relocs, syms, + sections) + bfd *output_bfd; + struct bfd_link_info *info; + bfd *input_bfd; + asection *input_section; + bfd_byte *contents; + struct internal_reloc *relocs; + struct internal_syment *syms; + asection **sections; +{ + struct internal_reloc *rel; + struct internal_reloc *relend; + + rel = relocs; + relend = rel + input_section->reloc_count; + for (; rel < relend; rel++) + { + long symndx; + struct coff_link_hash_entry *h; + struct internal_syment *sym; + bfd_vma addend; + bfd_vma val; + reloc_howto_type *howto; + bfd_reloc_status_type rstat; + bfd_vma addr; + symndx = rel->r_symndx; + + if (symndx == -1) + { + h = NULL; + sym = NULL; + } + else + { + h = obj_coff_sym_hashes (input_bfd)[symndx]; + sym = syms + symndx; + } + + /* COFF treats common symbols in one of two ways. Either the + size of the symbol is included in the section contents, or it + is not. We assume that the size is not included, and force + the rtype_to_howto function to adjust the addend as needed. */ + + if (sym != NULL && sym->n_scnum != 0) + addend = - sym->n_value; + else + addend = 0; + + howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h, + sym, &addend); + if (howto == NULL) + return false; + + val = 0; + + if (h == NULL) + { + asection *sec; + + if (symndx == -1) + { + sec = bfd_abs_section_ptr; + val = 0; + } + else + { + sec = sections[symndx]; + val = (sec->output_section->vma + + sec->output_offset + + sym->n_value); + if (! obj_pe (output_bfd)) + val -= sec->vma; + } + } + else + { + if (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + { + asection *sec; + + sec = h->root.u.def.section; + val = (h->root.u.def.value + + sec->output_section->vma + + sec->output_offset); + } + + else if (! info->relocateable) + { + if (! ((*info->callbacks->undefined_symbol) + (info, h->root.root.string, input_bfd, input_section, + rel->r_vaddr - input_section->vma))) + return false; + } + } + + addr = rel->r_vaddr - input_section->vma; + + /* FIXME: This code assumes little endian, but the PP can + apparently be bi-endian. I don't know if the bi-endianness + applies to the instruction set or just to the data. */ + switch (howto->type) + { + default: + case R_ABS: + case R_RELLONGX: + case R_PPL15: + case R_PPL15W: + case R_PPL15H: + case R_PPLN15: + case R_PPLN15W: + case R_PPLN15H: + rstat = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents, addr, val, addend); + break; + + case R_PP15: + case R_PP15W: + case R_PP15H: + case R_PPN15: + case R_PPN15W: + case R_PPN15H: + /* Offset the address so that we can use 4 byte relocations. */ + rstat = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents + 2, addr, val, addend); + break; + + case R_PP16B: + case R_PPN16B: + { + /* The most significant bit is stored in bit 6. */ + bfd_byte hold; + + hold = contents[addr + 4]; + contents[addr + 4] &=~ 0x20; + contents[addr + 4] |= (contents[addr] >> 1) & 0x20; + rstat = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents + 2, addr, + val, addend); + contents[addr] &=~ 0x40; + contents[addr] |= (contents[addr + 4] << 1) & 0x40; + contents[addr + 4] &=~ 0x20; + contents[addr + 4] |= hold & 0x20; + break; + } + + case R_PPL16B: + case R_PPLN16B: + { + /* The most significant bit is stored in bit 28. */ + bfd_byte hold; + + hold = contents[addr + 1]; + contents[addr + 1] &=~ 0x80; + contents[addr + 1] |= (contents[addr + 3] << 3) & 0x80; + rstat = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents, addr, + val, addend); + contents[addr + 3] &= ~0x10; + contents[addr + 3] |= (contents[addr + 1] >> 3) & 0x10; + contents[addr + 1] &=~ 0x80; + contents[addr + 1] |= hold & 0x80; + break; + } + + case R_PPBASE: + /* Parameter RAM is from 0x1000000 to 0x1000800. */ + contents[addr] &=~ 0x3; + if (val >= 0x1000000 && val < 0x1000800) + contents[addr] |= 0x3; + else + contents[addr] |= 0x2; + rstat = bfd_reloc_ok; + break; + + case R_PPLBASE: + /* Parameter RAM is from 0x1000000 to 0x1000800. */ + contents[addr + 2] &= ~0xc0; + if (val >= 0x1000000 && val < 0x1000800) + contents[addr + 2] |= 0xc0; + else + contents[addr + 2] |= 0x80; + rstat = bfd_reloc_ok; + break; + } + + switch (rstat) + { + default: + abort (); + case bfd_reloc_ok: + break; + case bfd_reloc_outofrange: + (*_bfd_error_handler) + ("%s: bad reloc address 0x%lx in section `%s'", + bfd_get_filename (input_bfd), + (unsigned long) rel->r_vaddr, + bfd_get_section_name (input_bfd, input_section)); + return false; + case bfd_reloc_overflow: + { + const char *name; + char buf[SYMNMLEN + 1]; + + if (symndx == -1) + name = "*ABS*"; + else if (h != NULL) + name = h->root.root.string; + else + { + name = _bfd_coff_internal_syment_name (input_bfd, sym, buf); + if (name == NULL) + return false; + } + + if (! ((*info->callbacks->reloc_overflow) + (info, name, howto->name, (bfd_vma) 0, input_bfd, + input_section, rel->r_vaddr - input_section->vma))) + return false; + } + } + } + return true; +} + #define TIC80 1 /* Customize coffcode.h */ #include "coffcode.h" |