diff options
author | Steve Murphree <smurph@cvs.openbsd.org> | 1999-02-09 04:01:38 +0000 |
---|---|---|
committer | Steve Murphree <smurph@cvs.openbsd.org> | 1999-02-09 04:01:38 +0000 |
commit | 8122b924b37128798e866fa7acc34f843e9128d1 (patch) | |
tree | 10664a21cb4c5c13aa79c697b22e28e547e6a02d /gnu/usr.bin/binutils/bfd/m88knetbsd.c | |
parent | 7abfc1ed31eb7979e079708ca83bbf191e6e3789 (diff) |
Adding support for Motorola mvme88k
Diffstat (limited to 'gnu/usr.bin/binutils/bfd/m88knetbsd.c')
-rw-r--r-- | gnu/usr.bin/binutils/bfd/m88knetbsd.c | 572 |
1 files changed, 572 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils/bfd/m88knetbsd.c b/gnu/usr.bin/binutils/bfd/m88knetbsd.c new file mode 100644 index 00000000000..58fedb6e24f --- /dev/null +++ b/gnu/usr.bin/binutils/bfd/m88knetbsd.c @@ -0,0 +1,572 @@ +/* BFD backend for MIPS BSD (a.out) binaries. + Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + Written by Ralph Campbell. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* NetBSD fits its header into the start of its text segment */ +#define BYTES_IN_WORD 4 +#define TARGET_IS_BIG_ENDIAN_P + +#define TARGET_PAGE_SIZE 8192 +#define SEGMENT_SIZE 0x20000 + +#define DEFAULT_ARCH bfd_arch_m88k +#define MACHTYPE_OK(mtype) \ + ((mtype) == M_88K_NETBSD || (mtype) == M_UNKNOWN || (mtype) == 151) + +#define N_HEADER_IN_TEXT(x) 1 +#define TEXT_START_ADDR 4128 + +#define N_MACHTYPE(exec) \ + ((enum machine_type)(((exec).a_info >> 16) & 0x03ff)) +#define N_FLAGS(exec) \ + (((exec).a_info >> 26) & 0x3f) + +#define N_SET_INFO(exec, magic, type, flags) \ + ((exec).a_info = ((magic) & 0xffff) \ + | (((int)(type) & 0x3ff) << 16) \ + | (((flags) & 0x3f) << 24)) +#define N_SET_MACHTYPE(exec, machtype) \ + ((exec).a_info = \ + ((exec).a_info & 0xfb00ffff) | ((((int)(machtype))&0x3ff) << 16)) +#define N_SET_FLAGS(exec, flags) \ + ((exec).a_info = \ + ((exec).a_info & 0x03ffffff) | ((flags & 0x03f) << 26)) + +#define N_SHARED_LIB(x) 0 + +#define MY(OP) CAT(m88knetbsd_,OP) + +#define TARGETNAME "a.out-m88k-netbsd" + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" +#include "libaout.h" + +#define SET_ARCH_MACH(ABFD, EXEC) \ + MY(set_arch_mach)(ABFD, N_MACHTYPE (EXEC)); \ + MY(choose_reloc_size)(ABFD); + +#if 0 + MY(fix_howto_table); +#endif + +void MY(set_arch_mach) PARAMS ((bfd *abfd, int machtype)); +static void MY(choose_reloc_size) PARAMS ((bfd *abfd)); +static void MY(fix_howto_table) PARAMS ((void)); + +/* On NetBSD, the magic number is always in ntohl's "network" (big-endian) + format. */ +#define SWAP_MAGIC(ext) bfd_getb32 (ext) + +#define MY_write_object_contents MY(write_object_contents) +static boolean MY(write_object_contents) PARAMS ((bfd *abfd)); +#define MY_text_includes_header 1 + +/* We can't use MY(x) here because it leads to a recursive call to CAT + when expanded inside JUMP_TABLE. */ +#define MY_bfd_reloc_type_lookup m88knetbsd_bfd_reloc_type_lookup +#define MY_canonicalize_reloc m88knetbsd_canonicalize_reloc + +#if 1 +#define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create +#define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols +#define MY_final_link_callback unused +#define MY_bfd_final_link _bfd_generic_final_link +#endif + +/*#define MY_bfd_final_link m88knetbsd_bfd_final_link*/ +#define howto_table_ext m88k_howto_table_ext +#define MY_BFD_TARGET + +#include "aout-target.h" + +void +MY(set_arch_mach) (abfd, machtype) + bfd *abfd; + int machtype; +{ + enum bfd_architecture arch; + long machine; + + /* Determine the architecture and machine type of the object file. */ + switch (machtype) { + + case M_88K_NETBSD: + arch = bfd_arch_m88k; + machine = 88100; + break; + + default: + arch = bfd_arch_obscure; + machine = 0; + break; + } + bfd_set_arch_mach(abfd, arch, machine); +} + +/* Determine the size of a relocation entry, based on the architecture */ +static void +MY(choose_reloc_size) (abfd) + bfd *abfd; +{ + switch (bfd_get_arch(abfd)) { + case bfd_arch_sparc: + case bfd_arch_m88k: + case bfd_arch_a29k: + case bfd_arch_mips: + obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE; + break; + default: + obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; + break; + } +} + +/* Write an object file. + Section contents have already been written. We write the + file header, symbols, and relocation. */ + +static boolean +MY(write_object_contents) (abfd) + bfd *abfd; +{ + struct external_exec exec_bytes; + struct internal_exec *execp = exec_hdr (abfd); + + /* We must make certain that the magic number has been set. This + will normally have been done by set_section_contents, but only if + there actually are some section contents. */ + if (! abfd->output_has_begun) + { + bfd_size_type text_size; + file_ptr text_end; + + NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); + } + + MY(choose_reloc_size) (abfd); + + /* Magic number, maestro, please! */ + switch (bfd_get_arch(abfd)) { + case bfd_arch_m88k: + N_SET_MACHTYPE(*execp, M_88K_NETBSD); + break; + default: + N_SET_MACHTYPE(*execp, M_UNKNOWN); + break; + } + + /* The NetBSD magic number is always big-endian */ +#ifndef TARGET_IS_BIG_ENDIAN_P + /* XXX aren't there any macro to change byteorder of a word independent of + the host's or target's endianesses? */ + execp->a_info + = (execp->a_info & 0xff) << 24 | (execp->a_info & 0xff00) << 8 + | (execp->a_info & 0xff0000) >> 8 | (execp->a_info & 0xff000000) >> 24; +#endif + + WRITE_HEADERS(abfd, execp); + + return true; +} + +/* + * m88k relocation types. + */ + +enum m88k_reloc_type { + R_88K_LO16, /* lo16(sym) */ + R_88K_HI16, /* hi16(sym) */ + R_88K_PC16, /* bb0, bb1, bcnd */ + R_88K_PC26, /* br, bsr */ + R_88K_32, /* jump tables, etc */ + R_88K_IW16, /* global access through linker regs 28 */ + R_88K_NONE, + R_88K_GLOB_DAT, + R_88K_JMP_SLOT, + R_88K_RELATIVE, + R_88K__max +}; + +static bfd_reloc_status_type m88k_special_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); + +static bfd_reloc_status_type +m88k_special_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; +{ + reloc_howto_type *howto = reloc_entry->howto; + switch (howto->type) + { + case R_88K_LO16: /* lo16(sym) */ + case R_88K_HI16: /* hi16(sym) */ + if (output_bfd != (bfd *) NULL) + { + /* This is a partial relocation, and we want to apply the + relocation to the reloc entry rather than the raw data. + Modify the reloc inplace to reflect what we now know. */ + + reloc_entry->address += input_section->output_offset; + } + else + { + bfd_vma output_base = 0; + bfd_vma addr = reloc_entry->address; + bfd_vma x = bfd_get_16 (abfd, (bfd_byte *) data + addr); + asection *reloc_target_output_section; + long relocation = 0; + + /* Work out which section the relocation is targetted at and the + initial relocation command value. */ + + /* Get symbol value. (Common symbols are special.) */ + if (bfd_is_com_section (symbol->section)) + relocation = 0; + else + relocation = symbol->value; + + reloc_target_output_section = symbol->section->output_section; + + /* Convert input-section-relative symbol value to absolute. */ + if (output_bfd) + output_base = 0; + else + output_base = reloc_target_output_section->vma; + + relocation += output_base + symbol->section->output_offset; + + /* Add in supplied addend. */ + relocation += ((reloc_entry->addend << howto->bitsize) + x); + + reloc_entry->addend = 0; + + relocation >>= (bfd_vma) howto->rightshift; + + /* Shift everything up to where it's going to be used */ + + relocation <<= (bfd_vma) howto->bitpos; + + if (relocation) + bfd_put_16 (abfd, relocation, (unsigned char *) data + addr); + } + + return bfd_reloc_ok; + break; + + default: + if (output_bfd != (bfd *) NULL) + { + /* This is a partial relocation, and we want to apply the + relocation to the reloc entry rather than the raw data. + Modify the reloc inplace to reflect what we now know. */ + + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + break; + } + + if (output_bfd == (bfd *) NULL) + return bfd_reloc_continue; + + return bfd_reloc_ok; +} + +static reloc_howto_type m88k_howto_table_ext[] = { + HOWTO (R_88K_LO16, /* type */ + 00, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + m88k_special_reloc, /* special_function */ + "R_88K_LO16", /* name */ + false, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + true), /* pcrel_offset */ + + HOWTO (R_88K_HI16, /* type */ + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + m88k_special_reloc, /* special_function */ + "R_88K_HI16", /* name */ + false, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + true), /* pcrel_offset */ + + HOWTO (R_88K_PC16, /* type */ + 02, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + m88k_special_reloc, /* special_function */ + "R_88K_PC16", /* name */ + false, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + true), /* pcrel_offset */ + + HOWTO (R_88K_PC26, /* type */ + 02, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 26, /* bitsize */ + true, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + m88k_special_reloc, /* special_function */ + "R_88K_PC26", /* name */ + false, /* partial_inplace */ + 0x03ffffff, /* src_mask */ + 0x03ffffff, /* dst_mask */ + true), /* pcrel_offset */ + + HOWTO (R_88K_32, /* type */ + 00, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + m88k_special_reloc, /* special_function */ + "R_88K_32", /* name */ + false, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + true), /* pcrel_offset */ + + {-1}, /* R_88K_IW16 */ + + HOWTO (R_88K_NONE, + 00, + 0, + 0, + false, + 0, + complain_overflow_dont, + m88k_special_reloc, + "R_88K_NONE", + false, + 0, + 0x00000000, + false), + + HOWTO (R_88K_GLOB_DAT, /* type */ + 00, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + false, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + m88k_special_reloc, /* special_function */ + "R_88K_GLOB_DAT", /* name */ + false, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + true), /* pcrel_offset */ + {-1}, /* R_88K_JMP_SLOT */ + {-1}, /* R_88K_RELATIVE */ + +}; + +#define CTOR_TABLE_RELOC_HOWTO(BFD) (MY(howto_table) + 4) + +/* Translate internal representation of relocation info to target format. + Total len is 12 bytes + On m88k: first 4 bytes are normal unsigned long address, + next three bytes are index, most sig. byte first. + Byte 7 is broken up with bit 7 as external, + bits 6, 5, & 4 unused, and the lower four bits as relocation + type. + Next 4 bytes are long addend. + + struct reloc_ext_external { + bfd_byte r_address[BYTES_IN_WORD]; offset of of data to relocate + bfd_byte r_index[3]; symbol table index of symbol + bfd_byte r_type[1]; relocation type + bfd_byte r_addend[BYTES_IN_WORD]; datum addend + }; +*/ + +static const struct { unsigned char bfd_val, aout_val; } reloc_map[] = { + { BFD_RELOC_NONE, R_88K_NONE }, + { BFD_RELOC_32, R_88K_32 }, + { BFD_RELOC_88K_32, R_88K_32 }, + { BFD_RELOC_88K_LO16, R_88K_LO16 }, + { BFD_RELOC_LO16, R_88K_LO16 }, + { BFD_RELOC_88K_HI16, R_88K_HI16 }, + { BFD_RELOC_HI16, R_88K_HI16 }, + { BFD_RELOC_88K_IW16, R_88K_IW16 }, + { BFD_RELOC_88K_16_PCREL, R_88K_PC16 }, + { BFD_RELOC_88K_26_PCREL, R_88K_PC26 }, + { BFD_RELOC_88K_GLOB_DAT, R_88K_GLOB_DAT }, + { BFD_RELOC_88K_JMP_SLOT, R_88K_JMP_SLOT }, + { BFD_RELOC_88K_RELATIVE, R_88K_RELATIVE }, + { BFD_RELOC_CTOR, R_88K_32 }, +}; + +static reloc_howto_type * +MY(bfd_reloc_type_lookup)(abfd,code) + bfd *abfd; + bfd_reloc_code_real_type code; +{ + unsigned int i; +/* printf("In MY_bfd_reloc_type_lookup\n");*/ + for (i = 0; i < sizeof (reloc_map) / sizeof (reloc_map[0]); i++) + { + if (reloc_map[i].bfd_val == code){ + return &m88k_howto_table_ext[(int) reloc_map[i].aout_val]; + } + } + return 0; +} + +#if 0 +static void +MY(fix_howto_table)(void) +{ + extern reloc_howto_type NAME(aout,ext_howto_table)[]; + memcpy(&NAME(aout,ext_howto_table), m88k_howto_table_ext, + sizeof(m88k_howto_table_ext)); +} +static int Init = 0; +#endif +#if 0 +static boolean +MY(bfd_final_link) (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + unsigned int i; + extern reloc_howto_type NAME(aout,ext_howto_table)[]; + + for (i = 0; i < sizeof (m88k_howto_table_ext) / sizeof (reloc_howto_type); i++) + { + memcpy(&NAME(aout,ext_howto_table)[i], &m88k_howto_table_ext[i], + sizeof (reloc_howto_type)); + } +/* memcpy(&aout_32_ext_howto_table, &m88k_howto_table_ext, + sizeof(m88k_howto_table_ext));*/ + return NAME(aout,final_link) (abfd, info, MY_final_link_callback); +} +#endif +/* + * This is just like the standard aoutx.h version but we need to do our + * own mapping of external reloc type values to howto entries. + */ +long +MY(canonicalize_reloc)(abfd, section, relptr, symbols) + bfd *abfd; + sec_ptr section; + arelent **relptr; + asymbol **symbols; +{ + arelent *tblptr = section->relocation; + unsigned int count, c; + extern reloc_howto_type NAME(aout,ext_howto_table)[]; + + /* If we have already read in the relocation table, return the values. */ + if (section->flags & SEC_CONSTRUCTOR) { + arelent_chain *chain = section->constructor_chain; + + for (count = 0; count < section->reloc_count; count++) { + *relptr++ = &chain->relent; + chain = chain->next; + } + *relptr = 0; + return section->reloc_count; + } + if (tblptr && section->reloc_count) { + for (count = 0; count++ < section->reloc_count;) + *relptr++ = tblptr++; + *relptr = 0; + return section->reloc_count; + } + + if (!NAME(aout,slurp_reloc_table)(abfd, section, symbols)) + return -1; + tblptr = section->relocation; + + /* fix up howto entries */ + for (count = 0; count++ < section->reloc_count;) + { + c = tblptr->howto - NAME(aout,ext_howto_table); + tblptr->howto = &m88k_howto_table_ext[c]; + + *relptr++ = tblptr++; + } + *relptr = 0; + return section->reloc_count; +} + +const bfd_target MY(vec) = +{ + TARGETNAME, /* name */ + bfd_target_aout_flavour, + BFD_ENDIAN_BIG, /* target byte order (big) */ + BFD_ENDIAN_BIG, /* target headers byte order (big) */ + (HAS_RELOC | EXEC_P | /* object flags */ + HAS_LINENO | HAS_DEBUG | + HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ + MY_symbol_leading_char, + ' ', /* ar_pad_char */ + 15, /* ar_max_namelen */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ + bfd_getb64, bfd_getb_signed_64, bfd_putb64, + bfd_getb32, bfd_getb_signed_32, bfd_putb32, + bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ + + {_bfd_dummy_target, MY_object_p, /* bfd_check_format */ + bfd_generic_archive_p, MY_core_file_p}, + {bfd_false, MY_mkobject, /* bfd_set_format */ + _bfd_generic_mkarchive, bfd_false}, + {bfd_false, MY_write_object_contents, /* bfd_write_contents */ + _bfd_write_archive_contents, bfd_false}, + + BFD_JUMP_TABLE_GENERIC (MY), + BFD_JUMP_TABLE_COPY (MY), + BFD_JUMP_TABLE_CORE (MY), + BFD_JUMP_TABLE_ARCHIVE (MY), + BFD_JUMP_TABLE_SYMBOLS (MY), + BFD_JUMP_TABLE_RELOCS (MY), + BFD_JUMP_TABLE_WRITE (MY), + BFD_JUMP_TABLE_LINK (MY), + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + + (PTR) MY_backend_data, +}; |