summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils/bfd/m88knetbsd.c
diff options
context:
space:
mode:
authorSteve Murphree <smurph@cvs.openbsd.org>1999-02-09 04:01:38 +0000
committerSteve Murphree <smurph@cvs.openbsd.org>1999-02-09 04:01:38 +0000
commit8122b924b37128798e866fa7acc34f843e9128d1 (patch)
tree10664a21cb4c5c13aa79c697b22e28e547e6a02d /gnu/usr.bin/binutils/bfd/m88knetbsd.c
parent7abfc1ed31eb7979e079708ca83bbf191e6e3789 (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.c572
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,
+};