From d1bfdaad0087b4f2fe72d9c330db22cf798cf1bc Mon Sep 17 00:00:00 2001 From: miod Date: Mon, 25 May 2015 14:56:26 +0000 Subject: [PATCH] Port the ELF m88k work to binutils 2.17. Good enough to build a booting kernel, and hopefully userland as well. --- gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h | 2 + gnu/usr.bin/binutils-2.17/bfd/config.bfd | 10 +- gnu/usr.bin/binutils-2.17/bfd/elf32-m88k.c | 2142 ++++++++++++++++- gnu/usr.bin/binutils-2.17/bfd/libbfd.h | 2 + gnu/usr.bin/binutils-2.17/bfd/reloc.c | 4 + gnu/usr.bin/binutils-2.17/binutils/readelf.c | 12 + .../binutils-2.17/gas/config/aout_gnu.h | 1 + .../binutils-2.17/gas/config/m88k-opcode.h | 559 +++++ .../binutils-2.17/gas/config/tc-m88k.c | 1696 +++++++++++++ .../binutils-2.17/gas/config/tc-m88k.h | 136 ++ gnu/usr.bin/binutils-2.17/gas/configure.tgt | 2 + gnu/usr.bin/binutils-2.17/include/elf/m88k.h | 106 + gnu/usr.bin/binutils-2.17/ld/Makefile.am | 13 + gnu/usr.bin/binutils-2.17/ld/Makefile.in | 13 + gnu/usr.bin/binutils-2.17/ld/configure.tgt | 4 +- .../binutils-2.17/ld/emulparams/elf32m88k.sh | 11 + .../ld/emulparams/elf32m88k_obsd.sh | 6 + .../ld/emulparams/m88kopenbsd.sh | 6 + 18 files changed, 4696 insertions(+), 29 deletions(-) create mode 100644 gnu/usr.bin/binutils-2.17/gas/config/m88k-opcode.h create mode 100644 gnu/usr.bin/binutils-2.17/gas/config/tc-m88k.c create mode 100644 gnu/usr.bin/binutils-2.17/gas/config/tc-m88k.h create mode 100644 gnu/usr.bin/binutils-2.17/include/elf/m88k.h create mode 100644 gnu/usr.bin/binutils-2.17/ld/emulparams/elf32m88k.sh create mode 100644 gnu/usr.bin/binutils-2.17/ld/emulparams/elf32m88k_obsd.sh create mode 100644 gnu/usr.bin/binutils-2.17/ld/emulparams/m88kopenbsd.sh diff --git a/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h b/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h index 1f06496b2ef..eafad3dd507 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h +++ b/gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h @@ -2327,6 +2327,8 @@ displacement is used on the Alpha. */ BFD_RELOC_32_PCREL_S2, BFD_RELOC_16_PCREL_S2, BFD_RELOC_23_PCREL_S2, + BFD_RELOC_18_PCREL_S2, + BFD_RELOC_28_PCREL_S2, /* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of the target word. These are used on the SPARC. */ diff --git a/gnu/usr.bin/binutils-2.17/bfd/config.bfd b/gnu/usr.bin/binutils-2.17/bfd/config.bfd index 53d0f23fea1..33d7ac950a3 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/config.bfd +++ b/gnu/usr.bin/binutils-2.17/bfd/config.bfd @@ -810,10 +810,10 @@ case "${targ}" in targ_defvec=m88kmach3_vec targ_cflags=-DSTAT_FOR_EXEC ;; - m88*-*-openbsd*) - targ_defvec=m88kopenbsd_vec - targ_underscore=yes - ;; + m88k-*-openbsd*) + targ_defvec=bfd_elf32_m88k_vec + targ_selvecs="m88kopenbsd_vec m88kbcs_vec" + ;; m88*-*-*) targ_defvec=m88kbcs_vec targ_underscore=yes @@ -1374,7 +1374,7 @@ case "${targ}" in ;; vax-*-openbsd*) - targ_defvec=elf32_vax_vec + targ_defvec=bfd_elf32_vax_vec targ_selvecs=vaxnetbsd_vec ;; diff --git a/gnu/usr.bin/binutils-2.17/bfd/elf32-m88k.c b/gnu/usr.bin/binutils-2.17/bfd/elf32-m88k.c index 1554c23884c..ac436d4f15a 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/elf32-m88k.c +++ b/gnu/usr.bin/binutils-2.17/bfd/elf32-m88k.c @@ -1,36 +1,2132 @@ -/* Motorola 88k-specific support for 32-bit ELF - Copyright 1993, 1995, 1999 Free Software Foundation, Inc. +/* Motorola 88k series support for 32-bit ELF + Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, + 2004, 2005, 2006 Free Software Foundation, Inc. -This file is part of BFD, the Binary File Descriptor library. + 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 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. + 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "bfd.h" #include "sysdep.h" +#include "bfdlink.h" #include "libbfd.h" #include "elf-bfd.h" +#include "elf/m88k.h" -/* This does not include any relocations, but should be good enough - for GDB. */ +static reloc_howto_type *reloc_type_lookup (bfd *, bfd_reloc_code_real_type); +static void rtype_to_howto (bfd *, arelent *, Elf_Internal_Rela *); +static struct bfd_hash_entry *elf_m88k_link_hash_newfunc + (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); +static struct bfd_link_hash_table *elf_m88k_link_hash_table_create (bfd *); +static bfd_boolean elf_m88k_check_relocs + (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *); +static asection *elf_m88k_gc_mark_hook + (asection *, struct bfd_link_info *, Elf_Internal_Rela *, + struct elf_link_hash_entry *, Elf_Internal_Sym *); +static bfd_boolean elf_m88k_gc_sweep_hook + (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *); +static bfd_boolean elf_m88k_adjust_dynamic_symbol + (struct bfd_link_info *, struct elf_link_hash_entry *); +static bfd_boolean elf_m88k_size_dynamic_sections + (bfd *, struct bfd_link_info *); +static bfd_boolean elf_m88k_discard_copies + (struct elf_link_hash_entry *, PTR); +static bfd_boolean elf_m88k_relocate_section + (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, + Elf_Internal_Rela *, Elf_Internal_Sym *, asection **); +static bfd_boolean elf_m88k_finish_dynamic_symbol + (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, + Elf_Internal_Sym *); +static bfd_boolean elf_m88k_finish_dynamic_sections + (bfd *, struct bfd_link_info *); -#define TARGET_BIG_SYM bfd_elf32_m88k_vec -#define TARGET_BIG_NAME "elf32-m88k" -#define ELF_ARCH bfd_arch_m88k -#define ELF_MACHINE_CODE EM_88K -#define ELF_MAXPAGESIZE 1 /* FIXME: This number is wrong, It should be the page size in bytes. */ -#define bfd_elf32_bfd_reloc_type_lookup bfd_default_reloc_type_lookup -#define elf_info_to_howto _bfd_elf_no_info_to_howto +static bfd_boolean elf32_m88k_set_private_flags (bfd *, flagword); +static bfd_boolean elf32_m88k_merge_private_bfd_data (bfd *, bfd *); +static bfd_boolean elf32_m88k_print_private_bfd_data (bfd *, PTR); +static enum elf_reloc_type_class elf32_m88k_reloc_type_class + (const Elf_Internal_Rela *); + +#define UNHANDLED_HOWTO(C) \ + HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, __STRING(C), \ + FALSE, 0, 0, FALSE) +#define UNIMPLEMENTED_HOWTO \ + HOWTO (R_88K_UNIMPLEMENTED, 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \ + "R_88K_UNIMPLEMENTED", FALSE, 0, 0, FALSE) + +static reloc_howto_type howto_table[] = { + HOWTO (R_88K_NONE, 0, 0, 0, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_88K_NONE", FALSE, 0, 0x00000000,FALSE), + UNHANDLED_HOWTO (R_88K_COPY), + UNHANDLED_HOWTO (R_88K_GOTP_ENT), + UNIMPLEMENTED_HOWTO, + HOWTO (R_88K_8, 0, 0, 8, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_88K_8", FALSE, 0, 0x000000ff,FALSE), + UNHANDLED_HOWTO (R_88K_8S), + UNIMPLEMENTED_HOWTO, + UNHANDLED_HOWTO (R_88K_16S), + HOWTO (R_88K_DISP16, 2, 2,16, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_88K_DISP16", FALSE, 0, 0x0000ffff,TRUE), + UNIMPLEMENTED_HOWTO, + HOWTO (R_88K_DISP26, 2, 2,26, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_88K_DISP26", FALSE, 0, 0x03ffffff,TRUE), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + HOWTO (R_88K_PLT_DISP26, 2, 2,26, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_88K_PLT_DISP26", FALSE, 0, 0x03ffffff,TRUE), + UNIMPLEMENTED_HOWTO, + UNHANDLED_HOWTO (R_88K_BBASED_32), + UNHANDLED_HOWTO (R_88K_BBASED_32UA), + UNHANDLED_HOWTO (R_88K_BBASED_16H), + UNHANDLED_HOWTO (R_88K_BBASED_16L), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNHANDLED_HOWTO (R_88K_ABDIFF_32), + UNHANDLED_HOWTO (R_88K_ABDIFF_32UA), + HOWTO (R_88K_ABDIFF_16H, 16, 1,16, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_88K_ABDIFF_16H", FALSE, 0, 0x0000ffff,FALSE), + HOWTO (R_88K_ABDIFF_16L, 0, 1,16, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_88K_ABDIFF_16L", FALSE, 0, 0x0000ffff,FALSE), + UNHANDLED_HOWTO (R_88K_ABDIFF_16), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + HOWTO (R_88K_32, 0, 2,32, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_88K_32", FALSE, 0, 0xffffffff,FALSE), + UNHANDLED_HOWTO (R_88K_32UA), + HOWTO (R_88K_16H, 16, 1,16, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_88K_16H", FALSE, 0, 0x0000ffff,FALSE), + HOWTO (R_88K_16L, 0, 1,16, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_88K_16L", FALSE, 0, 0x0000ffff,FALSE), + HOWTO (R_88K_16, 0, 1,16, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_88K_16", FALSE, 0, 0x0000ffff,FALSE), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNHANDLED_HOWTO (R_88K_GOT_32), + UNHANDLED_HOWTO (R_88K_GOT_32UA), + HOWTO (R_88K_GOT_16H, 16, 1,16, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_88K_GOT_16H", FALSE, 0, 0x0000ffff,FALSE), + HOWTO (R_88K_GOT_16L, 0, 1,16, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_88K_GOT_16L", FALSE, 0, 0x0000ffff,FALSE), + UNHANDLED_HOWTO (R_88K_GOT_16), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNHANDLED_HOWTO (R_88K_GOTP_32), + UNHANDLED_HOWTO (R_88K_GOTP_32UA), + UNHANDLED_HOWTO (R_88K_GOTP_16H), + UNHANDLED_HOWTO (R_88K_GOTP_16L), + UNHANDLED_HOWTO (R_88K_GOTP_16), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + HOWTO (R_88K_PLT_32, 0, 2,32, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_88K_PLT_32", FALSE, 0, 0xffffffff,FALSE), + UNHANDLED_HOWTO (R_88K_PLT_32UA), + UNHANDLED_HOWTO (R_88K_PLT_16H), + UNHANDLED_HOWTO (R_88K_PLT_16L), + UNHANDLED_HOWTO (R_88K_PLT_16), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNHANDLED_HOWTO (R_88K_ABREL_32), + UNHANDLED_HOWTO (R_88K_ABREL_32UA), + UNHANDLED_HOWTO (R_88K_ABREL_16H), + UNHANDLED_HOWTO (R_88K_ABREL_16L), + UNHANDLED_HOWTO (R_88K_ABREL_16), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNHANDLED_HOWTO (R_88K_GOT_ABREL_32), + UNHANDLED_HOWTO (R_88K_GOT_ABREL_32UA), + UNHANDLED_HOWTO (R_88K_GOT_ABREL_16H), + UNHANDLED_HOWTO (R_88K_GOT_ABREL_16L), + UNHANDLED_HOWTO (R_88K_GOT_ABREL_16), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNHANDLED_HOWTO (R_88K_GOTP_ABREL_32), + UNHANDLED_HOWTO (R_88K_GOTP_ABREL_32UA), + UNHANDLED_HOWTO (R_88K_GOTP_ABREL_16H), + UNHANDLED_HOWTO (R_88K_GOTP_ABREL_16L), + UNHANDLED_HOWTO (R_88K_GOTP_ABREL_16), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNHANDLED_HOWTO (R_88K_PLT_ABREL_32), + UNHANDLED_HOWTO (R_88K_PLT_ABREL_32UA), + UNHANDLED_HOWTO (R_88K_PLT_ABREL_16H), + UNHANDLED_HOWTO (R_88K_PLT_ABREL_16L), + UNHANDLED_HOWTO (R_88K_PLT_ABREL_16), + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNIMPLEMENTED_HOWTO, + UNHANDLED_HOWTO (R_88K_SREL_32), + UNHANDLED_HOWTO (R_88K_SREL_32UA), + UNHANDLED_HOWTO (R_88K_SREL_16H), + UNHANDLED_HOWTO (R_88K_SREL_16L), + /* GNU extension to record C++ vtable hierarchy */ + HOWTO (R_88K_GNU_VTINHERIT,0,2,0, FALSE,0, complain_overflow_dont, NULL, "R_88K_GNU_VTINHERIT",FALSE,0,0, FALSE), + /* GNU extension to record C++ vtable member usage */ + HOWTO (R_88K_GNU_VTENTRY,0, 2, 0, FALSE,0, complain_overflow_dont, _bfd_elf_rel_vtable_reloc_fn,"R_88K_GNU_VTENTRY",FALSE,0,0, FALSE) +}; + +static void +rtype_to_howto (abfd, cache_ptr, dst) + bfd *abfd ATTRIBUTE_UNUSED; + arelent *cache_ptr; + Elf_Internal_Rela *dst; +{ + BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_88K_UNIMPLEMENTED); + cache_ptr->howto = &howto_table[ELF32_R_TYPE(dst->r_info)]; +} + +#define elf_info_to_howto rtype_to_howto + +static const struct +{ + bfd_reloc_code_real_type bfd_val; + int elf_val; +} reloc_map[] = { + { BFD_RELOC_NONE, R_88K_NONE }, + { BFD_RELOC_LO16, R_88K_16L }, + { BFD_RELOC_HI16, R_88K_16H }, + { BFD_RELOC_18_PCREL_S2, R_88K_DISP16 }, + { BFD_RELOC_28_PCREL_S2, R_88K_DISP26 }, + { BFD_RELOC_8, R_88K_8 }, + { BFD_RELOC_16, R_88K_16 }, + { BFD_RELOC_32, R_88K_32 }, + + { BFD_RELOC_LO16_BASEREL, R_88K_ABDIFF_16L }, + { BFD_RELOC_HI16_BASEREL, R_88K_ABDIFF_16H }, + { BFD_RELOC_LO16_GOTOFF, R_88K_GOT_16L }, + { BFD_RELOC_HI16_GOTOFF, R_88K_GOT_16H }, + { BFD_RELOC_32_PLTOFF, R_88K_PLT_32 }, + { BFD_RELOC_32_PLT_PCREL, R_88K_PLT_DISP26 }, + + { BFD_RELOC_VTABLE_INHERIT, R_88K_GNU_VTINHERIT }, + { BFD_RELOC_VTABLE_ENTRY, R_88K_GNU_VTENTRY } +}; + +static reloc_howto_type * +reloc_type_lookup (abfd, code) + bfd *abfd ATTRIBUTE_UNUSED; + bfd_reloc_code_real_type code; +{ + unsigned int i; + for (i = 0; i < sizeof (reloc_map) / sizeof (reloc_map[0]); i++) + { + if (reloc_map[i].bfd_val == code) + return &howto_table[reloc_map[i].elf_val]; + } + return 0; +} + +#define bfd_elf32_bfd_reloc_type_lookup reloc_type_lookup +#define ELF_ARCH bfd_arch_m88k + +/* Functions for the m88k ELF linker. */ + +/* The name of the dynamic interpreter. This is put in the .interp + section. */ + +#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" + +/* The size in bytes of an entry in the procedure linkage table. */ + +#define PLT_ENTRY_SIZE 24 + +/* The size in bytes of the first entry in the procedure linkage table. */ + +#define PLT_ENTRY0_SIZE (3 * PLT_ENTRY_SIZE) + +/* The first entry in a procedure linkage table looks like this. See + the SVR4 ABI m88k supplement to see how this works. */ + +static const bfd_byte elf_m88k_plt0_entry[PLT_ENTRY0_SIZE] = +{ + 0x67, 0xff, 0x00, 0x10, /* subu r31, r31, 0x10 */ + 0x24, 0x3f, 0x00, 0x0c, /* st r1, r31, 0x0c */ + 0x25, 0x7f, 0x00, 0x08, /* st r11, r31, 0x08 */ + 0xc8, 0x00, 0x00, 0x01, /* bsr 1f */ + 0x5d, 0x60, 0x00, 0x00, /* 1: or.u r11, r0, %hi16(1b#abdiff) */ + 0x59, 0x6b, 0x00, 0x00, /* or r11, r11, %lo16(1b#abdiff) */ + 0xf5, 0x6b, 0x60, 0x01, /* addu r11, r11, r1 */ + 0x14, 0x2b, 0x00, 0x04, /* ld r1, r11, 0x04 */ + 0x24, 0x3f, 0x00, 0x04, /* st r1, r31, 0x04 */ + 0x15, 0x6b, 0x00, 0x08, /* ld r11, r11, 0x08 */ + 0x24, 0x1f, 0x00, 0x00, /* st r0, r31, 0 */ + 0xf4, 0x00, 0xc8, 0x0b, /* jsr r11 */ + 0xf4, 0x00, 0x58, 0x00, /* nop */ + 0xf4, 0x00, 0x58, 0x00, /* nop */ + 0xf4, 0x00, 0x58, 0x00, /* nop */ + 0xf4, 0x00, 0x58, 0x00, /* nop */ + 0xf4, 0x00, 0x58, 0x00, /* nop */ + 0xf4, 0x00, 0x58, 0x00 /* nop */ +}; + +/* Subsequent entries in a procedure linkage table look like this. */ + +static const bfd_byte elf_m88k_plt_entry[PLT_ENTRY_SIZE] = +{ + 0x5d, 0x60, 0x00, 0x00, /* or.u r11, r0, %hi16(symbol#gotrel) */ + 0x15, 0x6b, 0x00, 0x00, /* ld r11, r11, %lo16(symbol#gotrel) */ + 0xf4, 0x00, 0xc0, 0x0b, /* jmp r11 */ + 0x5d, 0x60, 0x00, 0x00, /* 1: or.u r11, r0, %hi16(.rela offset) */ + 0x59, 0x6b, 0x00, 0x00, /* or r11, r11, %lo16(.rela offset) */ + 0xc0, 0x00, 0x00, 0x00 /* br resolver */ +}; + +/* The m88k linker needs to keep track of the number of relocs that it + decides to copy in check_relocs for each symbol. This is so that it + can discard PC relative relocs if it doesn't need them when linking + with -Bsymbolic. We store the information in a field extending the + regular ELF linker hash table. */ + +/* This structure keeps track of the number of PC relative relocs we have + copied for a given symbol. */ + +struct elf_m88k_pcrel_relocs_copied +{ + /* Next section. */ + struct elf_m88k_pcrel_relocs_copied *next; + /* A section in dynobj. */ + asection *section; + /* Number of relocs copied in this section. */ + bfd_size_type count; +}; + +/* m88k ELF linker hash entry. */ + +struct elf_m88k_link_hash_entry +{ + struct elf_link_hash_entry root; + + /* Number of PC relative relocs copied for this symbol. */ + struct elf_m88k_pcrel_relocs_copied *pcrel_relocs_copied; +}; + +#define elf_m88k_hash_entry(ent) ((struct elf_m88k_link_hash_entry *) (ent)) + +/* m88k ELF linker hash table. */ + +struct elf_m88k_link_hash_table +{ + struct elf_link_hash_table root; + + /* Small local sym to section mapping cache. */ + struct sym_sec_cache sym_sec; +}; + +/* Get the m88k ELF linker hash table from a link_info structure. */ + +#define elf_m88k_hash_table(p) \ + ((struct elf_m88k_link_hash_table *) (p)->hash) + +/* Create an entry in an m88k ELF linker hash table. */ + +static struct bfd_hash_entry * +elf_m88k_link_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct bfd_hash_entry *ret = entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == NULL) + ret = bfd_hash_allocate (table, + sizeof (struct elf_m88k_link_hash_entry)); + if (ret == NULL) + return ret; + + /* Call the allocation method of the superclass. */ + ret = _bfd_elf_link_hash_newfunc (ret, table, string); + if (ret != NULL) + elf_m88k_hash_entry (ret)->pcrel_relocs_copied = NULL; + + return ret; +} + +/* Create an m88k ELF linker hash table. */ + +static struct bfd_link_hash_table * +elf_m88k_link_hash_table_create (abfd) + bfd *abfd; +{ + struct elf_m88k_link_hash_table *ret; + bfd_size_type amt = sizeof (struct elf_m88k_link_hash_table); + + ret = (struct elf_m88k_link_hash_table *) bfd_alloc (abfd, amt); + if (ret == (struct elf_m88k_link_hash_table *) NULL) + return NULL; + + if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, + elf_m88k_link_hash_newfunc, + sizeof (struct elf_m88k_link_hash_entry))) + { + free (ret); + return NULL; + } + + ret->sym_sec.abfd = NULL; + + return &ret->root.root; +} + +/* Keep m88k-specific flags in the ELF header. */ +static bfd_boolean +elf32_m88k_set_private_flags (abfd, flags) + bfd *abfd; + flagword flags; +{ + elf_elfheader (abfd)->e_flags = flags; + elf_flags_init (abfd) = TRUE; + return TRUE; +} + +/* Merge backend specific data from an object file to the output + object file when linking. */ +static bfd_boolean +elf32_m88k_merge_private_bfd_data (ibfd, obfd) + bfd *ibfd; + bfd *obfd; +{ + flagword out_flags; + flagword in_flags; + + if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + return TRUE; + + in_flags = elf_elfheader (ibfd)->e_flags; + out_flags = elf_elfheader (obfd)->e_flags; + + if (!elf_flags_init (obfd)) + { + elf_flags_init (obfd) = TRUE; + elf_elfheader (obfd)->e_flags = in_flags; + } + + return TRUE; +} + +/* Display the flags field. */ +static bfd_boolean +elf32_m88k_print_private_bfd_data (abfd, ptr) + bfd *abfd; + PTR ptr; +{ + FILE *file = (FILE *) ptr; + flagword eflags; + + BFD_ASSERT (abfd != NULL && ptr != NULL); + + /* Print normal ELF private data. */ + _bfd_elf_print_private_bfd_data (abfd, ptr); + + eflags = elf_elfheader (abfd)->e_flags; + + /* xgettext:c-format */ + fprintf (file, _("private flags = %lx:"), (long) eflags); + + if (eflags & EF_NABI) + fprintf (file, _(" [not ABI]")); + + if (eflags & EF_M88110) + fprintf (file, _(" [m88110]")); + + fputc ('\n', file); + + return TRUE; +} + +/* Look through the relocs for a section during the first phase, and + allocate space in the global offset table or procedure linkage + table. */ + +static bfd_boolean +elf_m88k_check_relocs (abfd, info, sec, relocs) + bfd *abfd; + struct bfd_link_info *info; + asection *sec; + const Elf_Internal_Rela *relocs; +{ + bfd *dynobj; + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + bfd_signed_vma *local_got_refcounts; + const Elf_Internal_Rela *rel; + const Elf_Internal_Rela *rel_end; + asection *sgot; + asection *srelgot; + asection *sreloc; + + if (info->relocatable) + return TRUE; + + dynobj = elf_hash_table (info)->dynobj; + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (abfd); + local_got_refcounts = elf_local_got_refcounts (abfd); + + sgot = NULL; + srelgot = NULL; + sreloc = NULL; + + rel_end = relocs + sec->reloc_count; + for (rel = relocs; rel < rel_end; rel++) + { + unsigned long r_symndx; + struct elf_link_hash_entry *h; + + r_symndx = ELF32_R_SYM (rel->r_info); + + if (r_symndx < symtab_hdr->sh_info) + h = NULL; + else + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + } + + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_88K_GOT_16L: + case R_88K_GOT_16H: + /* This symbol requires a global offset table entry. */ + + if (dynobj == NULL) + { + /* Create the .got section. */ + elf_hash_table (info)->dynobj = dynobj = abfd; + if (!_bfd_elf_create_got_section (dynobj, info)) + return FALSE; + } + + if (sgot == NULL) + { + sgot = bfd_get_section_by_name (dynobj, ".got"); + BFD_ASSERT (sgot != NULL); + } + + if (srelgot == NULL + && (h != NULL || info->shared)) + { + srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); + if (srelgot == NULL) + { + srelgot = bfd_make_section_with_flags (dynobj, + ".rela.got", + (SEC_ALLOC + | SEC_LOAD + | SEC_HAS_CONTENTS + | SEC_IN_MEMORY + | SEC_LINKER_CREATED + | SEC_READONLY)); + if (srelgot == NULL + || !bfd_set_section_alignment (dynobj, srelgot, 2)) + return FALSE; + } + } + + if (h != NULL) + { + if (h->got.refcount == 0) + { + /* Make sure this symbol is output as a dynamic symbol. */ + if (h->dynindx == -1 + && !h->forced_local) + { + if (!bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + } + + /* Allocate space in the .got section. */ + sgot->size += 4; + /* Allocate relocation space. */ + srelgot->size += sizeof (Elf32_External_Rela); + } + h->got.refcount++; + } + else + { + /* This is a global offset table entry for a local symbol. */ + if (local_got_refcounts == NULL) + { + bfd_size_type size; + + size = symtab_hdr->sh_info; + size *= sizeof (bfd_signed_vma); + local_got_refcounts = ((bfd_signed_vma *) + bfd_zalloc (abfd, size)); + if (local_got_refcounts == NULL) + return FALSE; + elf_local_got_refcounts (abfd) = local_got_refcounts; + } + if (local_got_refcounts[r_symndx] == 0) + { + sgot->size += 4; + if (info->shared) + { + /* If we are generating a shared object, we need to + output a R_88K_BBASED reloc so that the dynamic + linker can adjust this GOT entry. */ + srelgot->size += sizeof (Elf32_External_Rela); + } + } + local_got_refcounts[r_symndx]++; + } + break; + + case R_88K_PLT_DISP26: + /* This symbol requires a procedure linkage table entry. We + actually build the entry in adjust_dynamic_symbol, + because this might be a case of linking PIC code which is + never referenced by a dynamic object, in which case we + don't need to generate a procedure linkage table entry + after all. */ + + /* If this is a local symbol, we resolve it directly without + creating a procedure linkage table entry. */ + if (h == NULL) + continue; + + h->needs_plt = 1; + h->plt.refcount++; + break; + + case R_88K_PLT_32: + /* This symbol requires a procedure linkage table entry. */ + + if (h == NULL) + { + /* It does not make sense to have this relocation for a + local symbol. FIXME: does it? How to handle it if + it does make sense? */ + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + /* Make sure this symbol is output as a dynamic symbol. */ + if (h->dynindx == -1 + && !h->forced_local) + { + if (!bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + } + + h->needs_plt = 1; + h->plt.refcount++; + break; + + case R_88K_DISP16: + case R_88K_DISP26: + /* If we are creating a shared library and this is not a local + symbol, we need to copy the reloc into the shared library. + However when linking with -Bsymbolic and this is a global + symbol which is defined in an object we are including in the + link (i.e., DEF_REGULAR is set), then we can resolve the + reloc directly. At this point we have not seen all the input + files, so it is possible that DEF_REGULAR is not set now but + will be set later (it is never cleared). We account for that + possibility below by storing information in the + pcrel_relocs_copied field of the hash table entry. */ + if (!(info->shared + && (sec->flags & SEC_ALLOC) != 0 + && h != NULL + && (!info->symbolic + || h->root.type == bfd_link_hash_defweak + || !h->def_regular))) + { + if (h != NULL) + { + /* Make sure a plt entry is created for this symbol if + it turns out to be a function defined by a dynamic + object. */ + h->plt.refcount++; + } + break; + } + /* Fall through. */ + case R_88K_32: + case R_88K_16L: + case R_88K_16H: + if (h != NULL) + { + /* Make sure a plt entry is created for this symbol if it + turns out to be a function defined by a dynamic object. */ + h->plt.refcount++; + } + + /* If we are creating a shared library, we need to copy the + reloc into the shared library. */ + if (info->shared + && (sec->flags & SEC_ALLOC) != 0) + { + /* When creating a shared object, we must copy these + reloc types into the output file. We create a reloc + section in dynobj and make room for this reloc. */ + if (sreloc == NULL) + { + const char *name; + + name = (bfd_elf_string_from_elf_section + (abfd, + elf_elfheader (abfd)->e_shstrndx, + elf_section_data (sec)->rel_hdr.sh_name)); + if (name == NULL) + return FALSE; + + BFD_ASSERT (strncmp (name, ".rela", 5) == 0 + && strcmp (bfd_get_section_name (abfd, sec), + name + 5) == 0); + + sreloc = bfd_get_section_by_name (dynobj, name); + if (sreloc == NULL) + { + sreloc = bfd_make_section_with_flags (dynobj, + name, + (SEC_ALLOC + | SEC_LOAD + | SEC_HAS_CONTENTS + | SEC_IN_MEMORY + | SEC_LINKER_CREATED + | SEC_READONLY)); + if (sreloc == NULL + || !bfd_set_section_alignment (dynobj, sreloc, 2)) + return FALSE; + } + elf_section_data (sec)->sreloc = sreloc; + } + + if (sec->flags & SEC_READONLY + /* Don't set DF_TEXTREL yet for PC relative + relocations, they might be discarded later. */ + && !(ELF32_R_TYPE (rel->r_info) == R_88K_DISP16 + || ELF32_R_TYPE (rel->r_info) == R_88K_DISP26)) + info->flags |= DF_TEXTREL; + + sreloc->size += sizeof (Elf32_External_Rela); + + /* We count the number of PC relative relocations we have + entered for this symbol, so that we can discard them + again if, in the -Bsymbolic case, the symbol is later + defined by a regular object, or, in the normal shared + case, the symbol is forced to be local. Note that this + function is only called if we are using an m88kelf linker + hash table, which means that h is really a pointer to an + elf_m88k_link_hash_entry. */ + if (ELF32_R_TYPE (rel->r_info) == R_88K_DISP16 + || ELF32_R_TYPE (rel->r_info) == R_88K_DISP26) + { + struct elf_m88k_pcrel_relocs_copied *p; + struct elf_m88k_pcrel_relocs_copied **head; + + if (h != NULL) + { + struct elf_m88k_link_hash_entry *eh + = elf_m88k_hash_entry (h); + head = &eh->pcrel_relocs_copied; + } + else + { + asection *s; + void *vpp; + + s = (bfd_section_from_r_symndx + (abfd, &elf_m88k_hash_table (info)->sym_sec, + sec, r_symndx)); + if (s == NULL) + return FALSE; + + vpp = &elf_section_data (s)->local_dynrel; + head = (struct elf_m88k_pcrel_relocs_copied **) vpp; + } + + for (p = *head; p != NULL; p = p->next) + if (p->section == sreloc) + break; + + if (p == NULL) + { + p = ((struct elf_m88k_pcrel_relocs_copied *) + bfd_alloc (dynobj, (bfd_size_type) sizeof *p)); + if (p == NULL) + return FALSE; + p->next = *head; + *head = p; + p->section = sreloc; + p->count = 0; + } + + ++p->count; + } + } + + break; + + /* This relocation describes the C++ object vtable hierarchy. + Reconstruct it for later use during GC. */ + case R_88K_GNU_VTINHERIT: + if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + return FALSE; + break; + + /* This relocation describes which C++ vtable entries are actually + used. Record for later use during GC. */ + case R_88K_GNU_VTENTRY: + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + return FALSE; + break; + + default: + break; + } + } + + return TRUE; +} + +/* Return the section that should be marked against GC for a given + relocation. */ + +static asection * +elf_m88k_gc_mark_hook (sec, info, rel, h, sym) + asection *sec; + struct bfd_link_info *info ATTRIBUTE_UNUSED; + Elf_Internal_Rela *rel; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; +{ + if (h != NULL) + { + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_88K_GNU_VTINHERIT: + case R_88K_GNU_VTENTRY: + break; + + default: + switch (h->root.type) + { + default: + break; + + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + return h->root.u.def.section; + + case bfd_link_hash_common: + return h->root.u.c.p->section; + } + } + } + else + return bfd_section_from_elf_index (sec->owner, sym->st_shndx); + + return NULL; +} + +/* Update the got entry reference counts for the section being removed. */ + +static bfd_boolean +elf_m88k_gc_sweep_hook (abfd, info, sec, relocs) + bfd *abfd; + struct bfd_link_info *info; + asection *sec; + const Elf_Internal_Rela *relocs; +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + bfd_signed_vma *local_got_refcounts; + const Elf_Internal_Rela *rel, *relend; + bfd *dynobj; + asection *sgot; + asection *srelgot; + + dynobj = elf_hash_table (info)->dynobj; + if (dynobj == NULL) + return TRUE; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (abfd); + local_got_refcounts = elf_local_got_refcounts (abfd); + + sgot = bfd_get_section_by_name (dynobj, ".got"); + srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); + + relend = relocs + sec->reloc_count; + for (rel = relocs; rel < relend; rel++) + { + unsigned long r_symndx; + struct elf_link_hash_entry *h = NULL; + + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + } + + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_88K_GOT_16L: + case R_88K_GOT_16H: + r_symndx = ELF32_R_SYM (rel->r_info); + if (h != NULL) + { + if (h->got.refcount > 0) + { + --h->got.refcount; + if (h->got.refcount == 0) + { + /* We don't need the .got entry any more. */ + sgot->size -= 4; + srelgot->size -= sizeof (Elf32_External_Rela); + } + } + } + else if (local_got_refcounts != NULL) + { + if (local_got_refcounts[r_symndx] > 0) + { + --local_got_refcounts[r_symndx]; + if (local_got_refcounts[r_symndx] == 0) + { + /* We don't need the .got entry any more. */ + sgot->size -= 4; + if (info->shared) + srelgot->size -= sizeof (Elf32_External_Rela); + } + } + } + break; + + case R_88K_PLT_DISP26: + case R_88K_PLT_32: + case R_88K_DISP16: + case R_88K_DISP26: + case R_88K_32: + case R_88K_16L: + case R_88K_16H: + if (h != NULL) + { + if (h->plt.refcount > 0) + --h->plt.refcount; + } + break; + + default: + break; + } + } + + return TRUE; +} + +/* Adjust a symbol defined by a dynamic object and referenced by a + regular object. The current definition is in some section of the + dynamic object, but we're not including those sections. We have to + change the definition to something the rest of the link can + understand. */ + +static bfd_boolean +elf_m88k_adjust_dynamic_symbol (info, h) + struct bfd_link_info *info; + struct elf_link_hash_entry *h; +{ + bfd *dynobj; + asection *s; + unsigned int power_of_two; + + dynobj = elf_hash_table (info)->dynobj; + + /* Make sure we know what is going on here. */ + BFD_ASSERT (dynobj != NULL + && (h->needs_plt + || h->u.weakdef != NULL + || (h->def_dynamic + && h->ref_regular + && !h->def_regular))); + + /* If this is a function, put it in the procedure linkage table. We + will fill in the contents of the procedure linkage table later, + when we know the address of the .got section. */ + if (h->type == STT_FUNC + || h->needs_plt) + { + if ((h->plt.refcount <= 0 + || SYMBOL_CALLS_LOCAL (info, h) + || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + && h->root.type == bfd_link_hash_undefweak)) + /* We must always create the plt entry if it was referenced + by a PLTxxO relocation. In this case we already recorded + it as a dynamic symbol. */ + && h->dynindx == -1) + { + /* This case can occur if we saw a PLTxx reloc in an input + file, but the symbol was never referred to by a dynamic + object, or if all references were garbage collected. In + such a case, we don't actually need to build a procedure + linkage table, and we can just do a PCxx reloc instead. */ + BFD_ASSERT (h->needs_plt); + h->plt.offset = (bfd_vma) -1; + h->needs_plt = 0; + return TRUE; + } + + /* Make sure this symbol is output as a dynamic symbol. */ + if (h->dynindx == -1 + && !h->forced_local) + { + if (! bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + } + + s = bfd_get_section_by_name (dynobj, ".plt"); + BFD_ASSERT (s != NULL); + + /* If this is the first .plt entry, make room for the special + first entry. */ + if (s->size == 0) + { + s->size += PLT_ENTRY0_SIZE; + } + + /* If this symbol is not defined in a regular file, and we are + not generating a shared library, then set the symbol to this + location in the .plt. This is required to make function + pointers compare as equal between the normal executable and + the shared library. */ + if (!info->shared + && !h->def_regular) + { + h->root.u.def.section = s; + h->root.u.def.value = s->size; + } + + h->plt.offset = s->size; + + /* Make room for this entry. */ + s->size += PLT_ENTRY_SIZE; + + /* We also need to make an entry in the .got.plt section, which + will be placed in the .got section by the linker script. */ + s = bfd_get_section_by_name (dynobj, ".got.plt"); + BFD_ASSERT (s != NULL); + s->size += 4; + + /* We also need to make an entry in the .rela.plt section. */ + s = bfd_get_section_by_name (dynobj, ".rela.plt"); + BFD_ASSERT (s != NULL); + s->size += sizeof (Elf32_External_Rela); + + return TRUE; + } + + /* Reinitialize the plt offset now that it is not used as a reference + count any more. */ + h->plt.offset = (bfd_vma) -1; + + /* If this is a weak symbol, and there is a real definition, the + processor independent code will have arranged for us to see the + real definition first, and we can just use the same value. */ + if (h->u.weakdef != NULL) + { + BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined + || h->u.weakdef->root.type == bfd_link_hash_defweak); + h->root.u.def.section = h->u.weakdef->root.u.def.section; + h->root.u.def.value = h->u.weakdef->root.u.def.value; + return TRUE; + } + + /* This is a reference to a symbol defined by a dynamic object which + is not a function. */ + + /* If we are creating a shared library, we must presume that the + only references to the symbol are via the global offset table. + For such cases we need not do anything here; the relocations will + be handled correctly by relocate_section. */ + if (info->shared) + return TRUE; + + if (h->size == 0) + { + (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"), + h->root.root.string); + return TRUE; + } + + /* We must allocate the symbol in our .dynbss section, which will + become part of the .bss section of the executable. There will be + an entry for this symbol in the .dynsym section. The dynamic + object will contain position independent code, so all references + from the dynamic object to this symbol will go through the global + offset table. The dynamic linker will use the .dynsym entry to + determine the address it must put in the global offset table, so + both the dynamic object and the regular object will refer to the + same memory location for the variable. */ + + s = bfd_get_section_by_name (dynobj, ".dynbss"); + BFD_ASSERT (s != NULL); + + /* We must generate a R_88K_COPY reloc to tell the dynamic linker to + copy the initial value out of the dynamic object and into the + runtime process image. We need to remember the offset into the + .rela.bss section we are going to use. */ + if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) + { + asection *srel; + + srel = bfd_get_section_by_name (dynobj, ".rela.bss"); + BFD_ASSERT (srel != NULL); + srel->size += sizeof (Elf32_External_Rela); + h->needs_copy = 1; + } + + /* We need to figure out the alignment required for this symbol. I + have no idea how other ELF linkers handle this. */ + power_of_two = bfd_log2 (h->size); + if (power_of_two > 3) + power_of_two = 3; + + /* Apply the required alignment. */ + s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); + if (power_of_two > bfd_get_section_alignment (dynobj, s)) + { + if (!bfd_set_section_alignment (dynobj, s, power_of_two)) + return FALSE; + } + + /* Define the symbol as being at this point in the section. */ + h->root.u.def.section = s; + h->root.u.def.value = s->size; + + /* Increment the section size to make room for the symbol. */ + s->size += h->size; + + return TRUE; +} + +/* Set the sizes of the dynamic sections. */ + +static bfd_boolean +elf_m88k_size_dynamic_sections (output_bfd, info) + bfd *output_bfd ATTRIBUTE_UNUSED; + struct bfd_link_info *info; +{ + bfd *dynobj; + asection *s; + bfd_boolean plt; + bfd_boolean relocs; + + dynobj = elf_hash_table (info)->dynobj; + BFD_ASSERT (dynobj != NULL); + + if (elf_hash_table (info)->dynamic_sections_created) + { + /* Set the contents of the .interp section to the interpreter. */ + if (info->executable && !info->static_link) + { + s = bfd_get_section_by_name (dynobj, ".interp"); + BFD_ASSERT (s != NULL); + s->size = sizeof ELF_DYNAMIC_INTERPRETER; + s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; + } + } + else + { + /* We may have created entries in the .rela.got section. + However, if we are not creating the dynamic sections, we will + not actually use these entries. Reset the size of .rela.got, + which will cause it to get stripped from the output file + below. */ + s = bfd_get_section_by_name (dynobj, ".rela.got"); + if (s != NULL) + s->size = 0; + } + + /* If this is a -Bsymbolic shared link, then we need to discard all + PC relative relocs against symbols defined in a regular object. + For the normal shared case we discard the PC relative relocs + against symbols that have become local due to visibility changes. + We allocated space for them in the check_relocs routine, but we + will not fill them in in the relocate_section routine. */ + if (info->shared) + elf_link_hash_traverse (elf_hash_table (info), + elf_m88k_discard_copies, + (PTR) info); + + /* The check_relocs and adjust_dynamic_symbol entry points have + determined the sizes of the various dynamic sections. Allocate + memory for them. */ + plt = FALSE; + relocs = FALSE; + for (s = dynobj->sections; s != NULL; s = s->next) + { + const char *name; + + if ((s->flags & SEC_LINKER_CREATED) == 0) + continue; + + /* It's OK to base decisions on the section name, because none + of the dynobj section names depend upon the input files. */ + name = bfd_get_section_name (dynobj, s); + + if (strcmp (name, ".plt") == 0) + { + /* Remember whether there is a PLT. */ + plt = s->size != 0; + } + else if (strncmp (name, ".rela", 5) == 0) + { + if (s->size != 0) + { + relocs = TRUE; + + /* We use the reloc_count field as a counter if we need + to copy relocs into the output file. */ + s->reloc_count = 0; + } + } + else if (strncmp (name, ".got", 4) != 0 + && strncmp (name, ".dynbss", 4) != 0) + { + /* It's not one of our sections, so don't allocate space. */ + continue; + } + + if (s->size == 0) + { + /* If we don't need this section, strip it from the + output file. This is mostly to handle .rela.bss and + .rela.plt. We must create both sections in + create_dynamic_sections, because they must be created + before the linker maps input sections to output + sections. The linker does that before + adjust_dynamic_symbol is called, and it is that + function which decides whether anything needs to go + into these sections. */ + s->flags |= SEC_EXCLUDE; + continue; + } + + if ((s->flags & SEC_HAS_CONTENTS) == 0) + continue; + + /* Allocate memory for the section contents. */ + /* FIXME: This should be a call to bfd_alloc not bfd_zalloc. + Unused entries should be reclaimed before the section's contents + are written out, but at the moment this does not happen. Thus in + order to prevent writing out garbage, we initialise the section's + contents to zero. */ + s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); + if (s->contents == NULL) + return FALSE; + } + + if (elf_hash_table (info)->dynamic_sections_created) + { + /* Add some entries to the .dynamic section. We fill in the + values later, in elf_m88k_finish_dynamic_sections, but we + must add the entries now so that we get the correct size for + the .dynamic section. The DT_DEBUG entry is filled in by the + dynamic linker and used by the debugger. */ +#define add_dynamic_entry(TAG, VAL) \ + _bfd_elf_add_dynamic_entry (info, TAG, VAL) + + if (!info->shared) + { + if (!add_dynamic_entry (DT_DEBUG, 0)) + return FALSE; + } + + if (plt) + { + if (!add_dynamic_entry (DT_PLTGOT, 0) + || !add_dynamic_entry (DT_PLTRELSZ, 0) + || !add_dynamic_entry (DT_PLTREL, DT_RELA) + || !add_dynamic_entry (DT_JMPREL, 0) + || !add_dynamic_entry (DT_88K_PLTSTART, 0) + || !add_dynamic_entry (DT_88K_PLTEND, 0)) + return FALSE; + } + + if (relocs) + { + if (!add_dynamic_entry (DT_RELA, 0) + || !add_dynamic_entry (DT_RELASZ, 0) + || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) + return FALSE; + } + + if ((info->flags & DF_TEXTREL) != 0) + { + if (!add_dynamic_entry (DT_TEXTREL, 0)) + return FALSE; + } + } +#undef add_dynamic_entry + + return TRUE; +} + +/* This function is called via elf_link_hash_traverse if we are + creating a shared object. In the -Bsymbolic case it discards the + space allocated to copy PC relative relocs against symbols which + are defined in regular objects. For the normal shared case, it + discards space for pc-relative relocs that have become local due to + symbol visibility changes. We allocated space for them in the + check_relocs routine, but we won't fill them in in the + relocate_section routine. + + We also check whether any of the remaining relocations apply + against a readonly section, and set the DF_TEXTREL flag in this + case. */ + +static bfd_boolean +elf_m88k_discard_copies (h, inf) + struct elf_link_hash_entry *h; + PTR inf; +{ + struct bfd_link_info *info = (struct bfd_link_info *) inf; + struct elf_m88k_pcrel_relocs_copied *s; + + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + if (!h->def_regular + || (!info->symbolic + && !h->forced_local)) + { + if ((info->flags & DF_TEXTREL) == 0) + { + /* Look for relocations against read-only sections. */ + for (s = elf_m88k_hash_entry (h)->pcrel_relocs_copied; + s != NULL; + s = s->next) + if ((s->section->flags & SEC_READONLY) != 0) + { + info->flags |= DF_TEXTREL; + break; + } + } + + return TRUE; + } + + for (s = elf_m88k_hash_entry (h)->pcrel_relocs_copied; + s != NULL; + s = s->next) + s->section->size -= s->count * sizeof (Elf32_External_Rela); + + return TRUE; +} + +/* Relocate an M88K ELF section. */ + +static bfd_boolean +elf_m88k_relocate_section (output_bfd, info, input_bfd, input_section, + contents, relocs, local_syms, local_sections) + bfd *output_bfd; + struct bfd_link_info *info; + bfd *input_bfd; + asection *input_section; + bfd_byte *contents; + Elf_Internal_Rela *relocs; + Elf_Internal_Sym *local_syms; + asection **local_sections; +{ + bfd *dynobj; + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + bfd_vma *local_got_offsets; + asection *sgot; + asection *splt; + asection *sreloc; + Elf_Internal_Rela *rel; + Elf_Internal_Rela *relend; + + if (info->relocatable) + return TRUE; + + dynobj = elf_hash_table (info)->dynobj; + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (input_bfd); + local_got_offsets = elf_local_got_offsets (input_bfd); + + sgot = NULL; + splt = NULL; + sreloc = NULL; + + rel = relocs; + relend = relocs + input_section->reloc_count; + for (; rel < relend; rel++) + { + int r_type; + const char *sym_name; + reloc_howto_type *howto; + unsigned long r_symndx; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; + asection *sec; + bfd_vma relocation; + bfd_boolean unresolved_reloc; + bfd_reloc_status_type r; + + r_type = ELF32_R_TYPE (rel->r_info); + if (r_type < 0 || r_type >= (int) R_88K_UNIMPLEMENTED) + { + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + howto = howto_table + r_type; + + r_symndx = ELF32_R_SYM (rel->r_info); + + h = NULL; + sym = NULL; + sec = NULL; + unresolved_reloc = FALSE; + + if (r_symndx < symtab_hdr->sh_info) + { + sym = local_syms + r_symndx; + sec = local_sections[r_symndx]; + + relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); + } + else + { + bfd_boolean warned; + + RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, + r_symndx, symtab_hdr, sym_hashes, + h, sec, relocation, + unresolved_reloc, warned); + } + + if (h != NULL) + { + sym_name = h->root.root.string; + } + else + { + sym_name = bfd_elf_string_from_elf_section (input_bfd, + symtab_hdr->sh_link, + sym->st_name); + if (sym_name != NULL && *sym_name == '\0') + sym_name = bfd_section_name (input_bfd, sec); + } + + switch (r_type) + { + case R_88K_GOT_16L: + case R_88K_GOT_16H: + /* Relocation is the offset of the entry for this symbol in + the global offset table. */ + { + bfd_vma off; + + if (sgot == NULL) + { + sgot = bfd_get_section_by_name (dynobj, ".got"); + BFD_ASSERT (sgot != NULL); + } + + if (h != NULL) + { + bfd_boolean dyn; + + off = h->got.offset; + BFD_ASSERT (off != (bfd_vma) -1); + + dyn = elf_hash_table (info)->dynamic_sections_created; + if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) + || (info->shared + && (info->symbolic + || h->dynindx == -1 + || h->forced_local) + && h->def_regular)) + { + /* This is actually a static link, or it is a + -Bsymbolic link and the symbol is defined + locally, or the symbol was forced to be local + because of a version file.. We must initialize + this entry in the global offset table. Since + the offset must always be a multiple of 4, we + use the least significant bit to record whether + we have initialized it already. + + When doing a dynamic link, we create a .rela.got + relocation entry to initialize the value. This + is done in the finish_dynamic_symbol routine. */ + if ((off & 1) != 0) + off &= ~1; + else + { + bfd_put_32 (output_bfd, relocation, + sgot->contents + off); + h->got.offset |= 1; + } + } + else + unresolved_reloc = FALSE; + } + else + { + BFD_ASSERT (local_got_offsets != NULL + && local_got_offsets[r_symndx] != (bfd_vma) -1); + + off = local_got_offsets[r_symndx]; + + /* The offset must always be a multiple of 4. We use + the least significant bit to record whether we have + already generated the necessary reloc. */ + if ((off & 1) != 0) + off &= ~1; + else + { + bfd_put_32 (output_bfd, relocation, sgot->contents + off); + + if (info->shared) + { + asection *s; + Elf_Internal_Rela outrel; + bfd_byte *loc; + + s = bfd_get_section_by_name (dynobj, ".rela.got"); + BFD_ASSERT (s != NULL); + + outrel.r_offset = (sgot->output_section->vma + + sgot->output_offset + + off); + outrel.r_info = ELF32_R_INFO (0, R_88K_BBASED_32); + outrel.r_addend = relocation; + loc = s->contents; + loc += s->reloc_count++ * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + } + + local_got_offsets[r_symndx] |= 1; + } + } + + /* Addends on got relocations don't make much sense. + x+off@got is actually x@got+off, and since the got is + generated by a hash table traversal, the value in the + got at entry m+n bears little relation to the entry m. */ + if (rel->r_addend != 0) + (*_bfd_error_handler) + (_("%B(%A+0x%lx): non-zero addend on %s reloc against `%s'"), + input_bfd, input_section, (long) rel->r_offset, howto->name, + sym_name); + + relocation = sgot->output_offset + off; + } + break; + + case R_88K_ABDIFF_16L: + case R_88K_ABDIFF_16H: + /* Relocation is the offset from this symbol to the address of + the global offset table. */ + + if (sgot == NULL) + { + sgot = bfd_get_section_by_name (dynobj, ".got"); + BFD_ASSERT (sgot != NULL); + } + + relocation = sgot->output_section->vma + - (input_section->output_section->vma + + input_section->output_offset + rel->r_addend); + rel->r_addend = 0; + unresolved_reloc = FALSE; + break; + + case R_88K_PLT_DISP26: + /* Relocation is to the entry for this symbol in the + procedure linkage table. */ + + /* Resolve a PLTxx reloc against a local symbol directly, + without using the procedure linkage table. */ + if (h == NULL) + break; + + if (h->plt.offset == (bfd_vma) -1 + || !elf_hash_table (info)->dynamic_sections_created) + { + /* We didn't make a PLT entry for this symbol. This + happens when statically linking PIC code, or when + using -Bsymbolic. */ + break; + } + + if (splt == NULL) + { + splt = bfd_get_section_by_name (dynobj, ".plt"); + BFD_ASSERT (splt != NULL); + } + + relocation = (splt->output_section->vma + + splt->output_offset + + h->plt.offset); + unresolved_reloc = FALSE; + break; + + case R_88K_PLT_32: + /* Relocation is the offset of the entry for this symbol in + the procedure linkage table. */ + BFD_ASSERT (h != NULL && h->plt.offset != (bfd_vma) -1); + + if (splt == NULL) + { + splt = bfd_get_section_by_name (dynobj, ".plt"); + BFD_ASSERT (splt != NULL); + } + + relocation = h->plt.offset; + unresolved_reloc = FALSE; + + /* This relocation does not use the addend. */ + rel->r_addend = 0; + + break; + + case R_88K_DISP16: + case R_88K_DISP26: + if (h == NULL + || (info->shared + && h->forced_local)) + break; + /* Fall through. */ + case R_88K_8: + case R_88K_16: + case R_88K_32: + case R_88K_16L: + case R_88K_16H: + if (info->shared + && r_symndx != 0 + && (input_section->flags & SEC_ALLOC) != 0 + && (h == NULL + || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak) + && ((r_type != R_88K_DISP16 + && r_type != R_88K_DISP26) + || (h != NULL + && h->dynindx != -1 + && (!info->symbolic + || !h->def_regular)))) + { + Elf_Internal_Rela outrel; + bfd_byte *loc; + bfd_boolean skip, relocate; + + /* When generating a shared object, these relocations + are copied into the output file to be resolved at run + time. */ + + skip = FALSE; + relocate = FALSE; + + outrel.r_offset = + _bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset); + if (outrel.r_offset == (bfd_vma) -1) + skip = TRUE; + else if (outrel.r_offset == (bfd_vma) -2) + skip = TRUE, relocate = TRUE; + outrel.r_offset += (input_section->output_section->vma + + input_section->output_offset); + + if (skip) + memset (&outrel, 0, sizeof outrel); + else if (h != NULL + && h->dynindx != -1 + && (r_type == R_88K_DISP16 + || r_type == R_88K_DISP26 + || !info->shared + || !info->symbolic + || !h->def_regular)) + { + outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); + outrel.r_addend = rel->r_addend; + } + else + { + /* This symbol is local, or marked to become local. */ + if (r_type == R_88K_32) + { + relocate = TRUE; + outrel.r_info = ELF32_R_INFO (0, R_88K_BBASED_32); + outrel.r_addend = relocation + rel->r_addend; + } + else + { + long indx; + + if (bfd_is_abs_section (sec)) + indx = 0; + else if (sec == NULL || sec->owner == NULL) + { + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + else + { + asection *osec; + + osec = sec->output_section; + indx = elf_section_data (osec)->dynindx; + BFD_ASSERT (indx > 0); + } + + outrel.r_info = ELF32_R_INFO (indx, r_type); + outrel.r_addend = relocation + rel->r_addend; + } + } + + sreloc = elf_section_data (input_section)->sreloc; + if (sreloc == NULL) + abort (); + + loc = sreloc->contents; + loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + + /* This reloc will be computed at runtime, so there's no + need to do anything now, except for R_88K_32 + relocations that have been turned into + R_88K_BBASED_32. */ + if (!relocate) + continue; + } + + break; + + case R_88K_GNU_VTINHERIT: + case R_88K_GNU_VTENTRY: + /* These are no-ops in the end. */ + continue; + + default: + break; + } + + /* Dynamic relocs are not propagated for SEC_DEBUGGING sections + because such sections are not SEC_ALLOC and thus ld.so will + not process them. */ + if (unresolved_reloc + && !((input_section->flags & SEC_DEBUGGING) != 0 + && h->def_dynamic)) + { + (*_bfd_error_handler) + (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), + input_bfd, input_section, (long) rel->r_offset, howto->name, + h->root.root.string); + return FALSE; + } + + r = _bfd_final_link_relocate (howto, input_bfd, input_section, + contents, rel->r_offset, + relocation, rel->r_addend); + + if (r != bfd_reloc_ok) + { + if (sym_name == NULL) + return FALSE; + + if (r == bfd_reloc_overflow) + { + if (!(info->callbacks->reloc_overflow + (info, (h ? &h->root : NULL), sym_name, howto->name, + (bfd_vma) 0, input_bfd, input_section, + rel->r_offset))) + return FALSE; + } + else + { + (*_bfd_error_handler) + (_("%B(%A+0x%lx): %s reloc against `%s': error %d"), + input_bfd, input_section, (long) rel->r_offset, howto->name, + sym_name, (int) r); + return FALSE; + } + } + } + + return TRUE; +} + +/* Finish up dynamic symbol handling. We set the contents of various + dynamic sections here. */ + +static bfd_boolean +elf_m88k_finish_dynamic_symbol (output_bfd, info, h, sym) + bfd *output_bfd; + struct bfd_link_info *info; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; +{ + bfd *dynobj; + + dynobj = elf_hash_table (info)->dynobj; + + if (h->plt.offset != (bfd_vma) -1) + { + asection *splt; + asection *sgot; + asection *srela; + bfd_vma plt_index; + bfd_vma got_offset; + bfd_vma dyn_offset; + Elf_Internal_Rela rela; + unsigned int br; + + /* This symbol has an entry in the procedure linkage table. Set + it up. */ + + BFD_ASSERT (h->dynindx != -1); + + splt = bfd_get_section_by_name (dynobj, ".plt"); + sgot = bfd_get_section_by_name (dynobj, ".got.plt"); + srela = bfd_get_section_by_name (dynobj, ".rela.plt"); + BFD_ASSERT (splt != NULL && sgot != NULL && srela != NULL); + + /* Get the index in the procedure linkage table which + corresponds to this symbol. This is the index of this symbol + in all the symbols for which we are making plt entries. The + first entry in the procedure linkage table, spanning three + regular entries, is reserved. */ + plt_index = (h->plt.offset - PLT_ENTRY0_SIZE) / PLT_ENTRY_SIZE; + + /* Get the offset into the .got table of the entry that + corresponds to this function. Each .got entry is 4 bytes. + The first three are reserved. */ + got_offset = (plt_index + 3) * 4; + + /* Fill in the entry in the procedure linkage table. */ + memcpy (splt->contents + h->plt.offset, elf_m88k_plt_entry, + PLT_ENTRY_SIZE); + + dyn_offset = sgot->output_section->vma + sgot->output_offset + got_offset; + bfd_put_16 (output_bfd, dyn_offset >> 16, + splt->contents + h->plt.offset + 2); + bfd_put_16 (output_bfd, dyn_offset & 0xffff, + splt->contents + h->plt.offset + 6); + + dyn_offset = plt_index * sizeof (Elf32_External_Rela); + bfd_put_16 (output_bfd, dyn_offset >> 16, + splt->contents + h->plt.offset + 14); + bfd_put_16 (output_bfd, dyn_offset & 0xffff, + splt->contents + h->plt.offset + 18); + + br = bfd_get_32 (output_bfd, splt->contents + h->plt.offset + 20); + br &= ~0x03ffffff; + br |= 0x04000000 - ((h->plt.offset + 20) >> 2); + bfd_put_32 (output_bfd, br, + splt->contents + h->plt.offset + 20); + + /* Fill in the entry in the global offset table. */ + bfd_put_32 (output_bfd, + splt->output_section->vma + + splt->output_offset + + h->plt.offset + + 12, + sgot->contents + got_offset); + + /* Fill in the entry in the .rela.plt section. */ + rela.r_offset = (sgot->output_section->vma + + sgot->output_offset + + got_offset); + rela.r_info = ELF32_R_INFO (h->dynindx, R_88K_GOTP_ENT); + rela.r_addend = splt->output_section->vma + h->plt.offset; + bfd_elf32_swap_reloca_out (output_bfd, &rela, + srela->contents + + plt_index * sizeof (Elf32_External_Rela)); + + if (!h->def_regular) + { + /* Mark the symbol as undefined, rather than as defined in + the .plt section. Leave the value alone. */ + sym->st_shndx = SHN_UNDEF; + } + } + + if (h->got.offset != (bfd_vma) -1) + { + asection *sgot; + asection *srela; + Elf_Internal_Rela rela; + bfd_byte *loc; + + /* This symbol has an entry in the global offset table. Set it + up. */ + + sgot = bfd_get_section_by_name (dynobj, ".got"); + srela = bfd_get_section_by_name (dynobj, ".rela.got"); + BFD_ASSERT (sgot != NULL && srela != NULL); + + rela.r_offset = (sgot->output_section->vma + + sgot->output_offset + + (h->got.offset &~ (bfd_vma) 1)); + + /* If this is a -Bsymbolic link, and the symbol is defined + locally, we just want to emit a BBASED reloc. Likewise if + the symbol was forced to be local because of a version file. + The entry in the global offset table will already have been + initialized in the relocate_section function. */ + if (info->shared + && (info->symbolic + || h->dynindx == -1 + || h->forced_local) + && h->def_regular) + { + rela.r_info = ELF32_R_INFO (0, R_88K_BBASED_32); + rela.r_addend = bfd_get_signed_32 (output_bfd, + (sgot->contents + + (h->got.offset &~ (bfd_vma) 1))); + } + else + { + bfd_put_32 (output_bfd, (bfd_vma) 0, + sgot->contents + (h->got.offset &~ (bfd_vma) 1)); + rela.r_info = ELF32_R_INFO (h->dynindx, R_88K_32); + rela.r_addend = 0; + } + + loc = srela->contents; + loc += srela->reloc_count++ * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + } + + if (h->needs_copy) + { + asection *s; + Elf_Internal_Rela rela; + bfd_byte *loc; + + /* This symbol needs a copy reloc. Set it up. */ + + BFD_ASSERT (h->dynindx != -1 + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak)); + + s = bfd_get_section_by_name (h->root.u.def.section->owner, + ".rela.bss"); + BFD_ASSERT (s != NULL); + + rela.r_offset = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + rela.r_info = ELF32_R_INFO (h->dynindx, R_88K_COPY); + rela.r_addend = 0; + loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); + } + + /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ + if (strcmp (h->root.root.string, "_DYNAMIC") == 0 + || h == elf_hash_table (info)->hgot) + sym->st_shndx = SHN_ABS; + + return TRUE; +} + +/* Finish up the dynamic sections. */ + +static bfd_boolean +elf_m88k_finish_dynamic_sections (output_bfd, info) + bfd *output_bfd; + struct bfd_link_info *info; +{ + bfd *dynobj; + asection *sgot; + asection *sdyn; + + dynobj = elf_hash_table (info)->dynobj; + + sgot = bfd_get_section_by_name (dynobj, ".got.plt"); + BFD_ASSERT (sgot != NULL); + sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + + if (elf_hash_table (info)->dynamic_sections_created) + { + asection *splt; + Elf32_External_Dyn *dyncon, *dynconend; + + splt = bfd_get_section_by_name (dynobj, ".plt"); + BFD_ASSERT (splt != NULL && sdyn != NULL); + + dyncon = (Elf32_External_Dyn *) sdyn->contents; + dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); + for (; dyncon < dynconend; dyncon++) + { + Elf_Internal_Dyn dyn; + const char *name; + asection *s; + + bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); + + switch (dyn.d_tag) + { + default: + break; + + case DT_PLTGOT: + name = ".got"; + goto get_vma; + case DT_JMPREL: + name = ".rela.plt"; + get_vma: + s = bfd_get_section_by_name (output_bfd, name); + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->vma; + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + break; + + case DT_PLTRELSZ: + s = bfd_get_section_by_name (output_bfd, ".rela.plt"); + BFD_ASSERT (s != NULL); + dyn.d_un.d_val = s->size; + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + break; + + case DT_RELASZ: + /* The procedure linkage table relocs (DT_JMPREL) should + not be included in the overall relocs (DT_RELA). + Therefore, we override the DT_RELASZ entry here to + make it not include the JMPREL relocs. Since the + linker script arranges for .rela.plt to follow all + other relocation sections, we don't have to worry + about changing the DT_RELA entry. */ + s = bfd_get_section_by_name (output_bfd, ".rela.plt"); + if (s != NULL) + dyn.d_un.d_val -= s->size; + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + break; + + case DT_88K_PLTSTART: + name = ".plt"; + goto get_vma; + case DT_88K_PLTEND: + s = bfd_get_section_by_name (output_bfd, ".plt"); + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->vma + s->size; + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + break; + } + } + + /* Fill in the first entry in the procedure linkage table. */ + if (splt->size > 0) + { + memcpy (splt->contents, elf_m88k_plt0_entry, PLT_ENTRY0_SIZE); + bfd_put_16 (output_bfd, + (sgot->output_section->vma + + sgot->output_offset + - (splt->output_section->vma + 16)) >> 16, + splt->contents + 18); + bfd_put_16 (output_bfd, + (sgot->output_section->vma + + sgot->output_offset + - (splt->output_section->vma + 16)) & 0xffff, + splt->contents + 22); + elf_section_data (splt->output_section)->this_hdr.sh_entsize + = PLT_ENTRY0_SIZE; + } + } + + /* Fill in the first three entries in the global offset table. */ + if (sgot->size > 0) + { + if (sdyn == NULL) + bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); + else + bfd_put_32 (output_bfd, + sdyn->output_section->vma + sdyn->output_offset, + sgot->contents); + bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4); + bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8); + } + + elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; + + return TRUE; +} + +static enum elf_reloc_type_class +elf32_m88k_reloc_type_class (rela) + const Elf_Internal_Rela *rela; +{ + switch ((int) ELF32_R_TYPE (rela->r_info)) + { + case R_88K_BBASED_32: + case R_88K_BBASED_16H: + case R_88K_BBASED_16L: + return reloc_class_relative; + case R_88K_GOTP_ENT: + return reloc_class_plt; + case R_88K_COPY: + return reloc_class_copy; + default: + return reloc_class_normal; + } +} + +/* Return address for Ith PLT stub in section PLT, for relocation REL + or (bfd_vma) -1 if it should not be included. */ +static bfd_vma +elf_m88k_plt_sym_val (bfd_vma i, const asection *plt, + const arelent *rel ATTRIBUTE_UNUSED) +{ + return plt->vma + PLT_ENTRY0_SIZE + i * PLT_ENTRY_SIZE; +} + +#define TARGET_BIG_SYM bfd_elf32_m88k_vec +#define TARGET_BIG_NAME "elf32-m88k" +#define ELF_MACHINE_CODE EM_88K +#define ELF_MAXPAGESIZE 0x1000 +#define elf_backend_create_dynamic_sections \ + _bfd_elf_create_dynamic_sections +#define bfd_elf32_bfd_link_hash_table_create \ + elf_m88k_link_hash_table_create +#define bfd_elf32_bfd_final_link bfd_elf_gc_common_final_link + +#define elf_backend_check_relocs elf_m88k_check_relocs +#define elf_backend_adjust_dynamic_symbol \ + elf_m88k_adjust_dynamic_symbol +#define elf_backend_size_dynamic_sections \ + elf_m88k_size_dynamic_sections +#define elf_backend_relocate_section elf_m88k_relocate_section +#define elf_backend_finish_dynamic_symbol \ + elf_m88k_finish_dynamic_symbol +#define elf_backend_finish_dynamic_sections \ + elf_m88k_finish_dynamic_sections +#define elf_backend_gc_mark_hook elf_m88k_gc_mark_hook +#define elf_backend_gc_sweep_hook elf_m88k_gc_sweep_hook +#define bfd_elf32_bfd_merge_private_bfd_data \ + elf32_m88k_merge_private_bfd_data +#define bfd_elf32_bfd_set_private_flags \ + elf32_m88k_set_private_flags +#define bfd_elf32_bfd_print_private_bfd_data \ + elf32_m88k_print_private_bfd_data +#define elf_backend_reloc_type_class elf32_m88k_reloc_type_class +#define elf_backend_plt_sym_val elf_m88k_plt_sym_val + +#define elf_backend_can_gc_sections 1 +#define elf_backend_can_refcount 1 +#define elf_backend_want_got_plt 1 +#define elf_backend_plt_readonly 1 +#define elf_backend_want_plt_sym 0 +#define elf_backend_got_header_size 12 +#define elf_backend_rela_normal 1 #include "elf32-target.h" diff --git a/gnu/usr.bin/binutils-2.17/bfd/libbfd.h b/gnu/usr.bin/binutils-2.17/bfd/libbfd.h index eccb42b047a..fb237440b29 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/libbfd.h +++ b/gnu/usr.bin/binutils-2.17/bfd/libbfd.h @@ -829,6 +829,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_32_PCREL_S2", "BFD_RELOC_16_PCREL_S2", "BFD_RELOC_23_PCREL_S2", + "BFD_RELOC_18_PCREL_S2", + "BFD_RELOC_28_PCREL_S2", "BFD_RELOC_HI22", "BFD_RELOC_LO10", "BFD_RELOC_GPREL16", diff --git a/gnu/usr.bin/binutils-2.17/bfd/reloc.c b/gnu/usr.bin/binutils-2.17/bfd/reloc.c index f1d09a5ab07..c80a0f9daea 100644 --- a/gnu/usr.bin/binutils-2.17/bfd/reloc.c +++ b/gnu/usr.bin/binutils-2.17/bfd/reloc.c @@ -1699,6 +1699,10 @@ ENUMX BFD_RELOC_16_PCREL_S2 ENUMX BFD_RELOC_23_PCREL_S2 +ENUMX + BFD_RELOC_18_PCREL_S2 +ENUMX + BFD_RELOC_28_PCREL_S2 ENUMDOC These PC-relative relocations are stored as word displacements -- i.e., byte displacements shifted right two bits. The 30-bit word diff --git a/gnu/usr.bin/binutils-2.17/binutils/readelf.c b/gnu/usr.bin/binutils-2.17/binutils/readelf.c index a82fe737e62..298bb6f0ab3 100644 --- a/gnu/usr.bin/binutils-2.17/binutils/readelf.c +++ b/gnu/usr.bin/binutils-2.17/binutils/readelf.c @@ -90,6 +90,7 @@ #include "elf/m32r.h" #include "elf/m68k.h" #include "elf/m68hc11.h" +#include "elf/m88k.h" #include "elf/mcore.h" #include "elf/mips.h" #include "elf/mmix.h" @@ -613,6 +614,7 @@ guess_is_rela (unsigned long e_machine) case EM_BLACKFIN: case EM_NIOS32: case EM_ALTERA_NIOS2: + case EM_88K: return TRUE; case EM_MMA: @@ -1133,6 +1135,9 @@ dump_relocations (FILE *file, rtype = elf_bfin_reloc_type (type); break; + case EM_88K: + rtype = elf_m88k_reloc_type (type); + break; } if (rtype == NULL) @@ -2235,6 +2240,13 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) if ((e_flags & EF_VAX_GFLOAT)) strcat (buf, ", G-Float"); break; + + case EM_88K: + if ((e_flags & EF_NABI)) + strcat (buf, ", not 88Open ABI compliant"); + if ((e_flags & EF_M88110)) + strcat (buf, ", m88110"); + break; } } diff --git a/gnu/usr.bin/binutils-2.17/gas/config/aout_gnu.h b/gnu/usr.bin/binutils-2.17/gas/config/aout_gnu.h index e17fda9465b..843233c6c9a 100644 --- a/gnu/usr.bin/binutils-2.17/gas/config/aout_gnu.h +++ b/gnu/usr.bin/binutils-2.17/gas/config/aout_gnu.h @@ -120,6 +120,7 @@ enum machine_type M_29K = 101, M_RS6000 = 102, /* IBM RS/6000 */ M_VAX4K_NETBSD = 150, + M_88K_OPENBSD = 153, /* HP/BSD formats */ M_HP200 = 200, /* hp200 (68010) BSD binary */ M_HP300 = 300, /* hp300 (68020+68881) BSD binary */ diff --git a/gnu/usr.bin/binutils-2.17/gas/config/m88k-opcode.h b/gnu/usr.bin/binutils-2.17/gas/config/m88k-opcode.h new file mode 100644 index 00000000000..8055b5e430e --- /dev/null +++ b/gnu/usr.bin/binutils-2.17/gas/config/m88k-opcode.h @@ -0,0 +1,559 @@ +/* m88k-opcode.h -- Instruction information for the Motorola 88000 + Contributed by Devon Bowen of Buffalo University + and Torbjorn Granlund of the Swedish Institute of Computer Science. + Copyright 1989, 1990, 1991, 1993, 2000 Free Software Foundation, Inc. + +This file is part of GAS, the GNU Assembler. + +GAS 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 1, or (at your option) +any later version. + +GAS 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 GAS; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if !defined(__STDC__) && !defined(const) +#define const +#endif + +/* + Character codes for op_spec field below. + Reserved for self-matching: [ ] , + + d = GRF Destination register (21:5) + x = XRF register prefix. Makes next d, 1, or 2, match an extended register. + 1 = Source register 1 (16:5) + 2 = Source register 2 (0:5) + 3 = Both source registers (same value) (0:5 and 16:5) + I = IMM16 (0:16) + b = bit field spec. (0:10) + p = 16 bit pc displ. (0:16) + P = 26 bit pc displ. (0:26) + B = bb0/bb1 condition (21:5) + M = bcnd condition (21:5) + f = fcr (5:6) + c = cr (5:6) + V = VEC9 (0:9) + o = O6 field of "prot" insn (10:7) + ? = Give warning for this insn/operand combination + */ + +/* instruction descriptor structure */ + +struct m88k_opcode +{ + unsigned int opcode; + char *name; + char *op_spec; +}; + +/* and introducing... the Motorola 88100 and 88110 instruction sets... */ + +/* By default, include the 88110 instructions. */ +#define MC88110 + +#if defined (MC88110) +#define _MC88100(OPCODE,MNEM,OP_SPEC) +#define _MC88110(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC}, +#else +#define _MC88100(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC}, +#define _MC88110(OPCODE,MNEM,OP_SPEC) +#endif + +#define _MC88xxx(OPCODE,MNEM,OP_SPEC) {OPCODE,MNEM,OP_SPEC}, + +/* Equal mnemonics must be adjacent. + More specific operand specification must go before more general. + For example, "d,1,2" must go before "d,1,I" as a register for s2 + would otherwise be considered a variable name. */ + +static struct m88k_opcode m88k_opcodes[] = +{ + /* Opcode Mnemonic Opspec */ + + _MC88xxx (0xf4007000, "add", "d,1,2") + _MC88xxx (0x70000000, "add", "d,1,I") + _MC88xxx (0xf4007200, "add.ci", "d,1,2") + _MC88xxx (0xf4007300, "add.cio", "d,1,2") + _MC88xxx (0xf4007100, "add.co", "d,1,2") + _MC88xxx (0xf4006000, "addu", "d,1,2") + _MC88xxx (0x60000000, "addu", "d,1,I") + _MC88xxx (0xf4006200, "addu.ci", "d,1,2") + _MC88xxx (0xf4006300, "addu.cio", "d,1,2") + _MC88xxx (0xf4006100, "addu.co", "d,1,2") + _MC88xxx (0xf4004000, "and", "d,1,2") + _MC88xxx (0x40000000, "and", "d,1,I") + _MC88xxx (0xf4004400, "and.c", "d,1,2") + _MC88xxx (0x44000000, "and.u", "d,1,I") + _MC88xxx (0xd0000000, "bb0", "B,1,p") + _MC88xxx (0xd4000000, "bb0.n", "B,1,p") + _MC88xxx (0xd8000000, "bb1", "B,1,p") + _MC88xxx (0xdc000000, "bb1.n", "B,1,p") + _MC88xxx (0xe8000000, "bcnd", "M,1,p") + _MC88xxx (0xec000000, "bcnd.n", "M,1,p") + _MC88xxx (0xc0000000, "br", "P") + _MC88xxx (0xc4000000, "br.n", "P") + _MC88xxx (0xc8000000, "bsr", "P") + _MC88xxx (0xcc000000, "bsr.n", "P") + _MC88xxx (0xf4008000, "clr", "d,1,2") + _MC88xxx (0xf0008000, "clr", "d,1,b") + _MC88xxx (0xf4007c00, "cmp", "d,1,2") + _MC88xxx (0x7c000000, "cmp", "d,1,I") + _MC88xxx (0xf4007800, "div", "d,1,2") + _MC88xxx (0x78000000, "div", "d,1,I") + _MC88xxx (0xf4007800, "divs", "d,1,2") + _MC88xxx (0x78000000, "divs", "d,1,I") + _MC88110 (0xf4006900, "divu.d", "d,1,2") + _MC88xxx (0xf4006800, "divu", "d,1,2") + _MC88xxx (0x68000000, "divu", "d,1,I") + _MC88xxx (0xf4009000, "ext", "d,1,2") + _MC88xxx (0xf0009000, "ext", "d,1,b") + _MC88xxx (0xf4009800, "extu", "d,1,2") + _MC88xxx (0xf0009800, "extu", "d,1,b") + _MC88xxx (0x84002800, "fadd.sss", "d,1,2") + _MC88110 (0x8400a800, "fadd.sss", "xd,x1,x2") + _MC88xxx (0x84002880, "fadd.ssd", "d,1,2") + _MC88110 (0x8400a820, "fadd.ssd", "xd,x1,x2") + _MC88110 (0x8400a840, "fadd.ssx", "xd,x1,x2") + _MC88xxx (0x84002a00, "fadd.sds", "d,1,2") + _MC88110 (0x8400a880, "fadd.sds", "xd,x1,x2") + _MC88xxx (0x84002a80, "fadd.sdd", "d,1,2") + _MC88110 (0x8400a8a0, "fadd.sdd", "xd,x1,x2") + _MC88110 (0x8400a8c0, "fadd.sdx", "xd,x1,x2") + _MC88110 (0x8400a900, "fadd.sxs", "xd,x1,x2") + _MC88110 (0x8400a920, "fadd.sxd", "xd,x1,x2") + _MC88110 (0x8400a940, "fadd.sxx", "xd,x1,x2") + _MC88xxx (0x84002820, "fadd.dss", "d,1,2") + _MC88110 (0x8400aa00, "fadd.dss", "xd,x1,x2") + _MC88xxx (0x840028a0, "fadd.dsd", "d,1,2") + _MC88110 (0x8400aa20, "fadd.dsd", "xd,x1,x2") + _MC88110 (0x8400aa40, "fadd.dsx", "xd,x1,x2") + _MC88xxx (0x84002a20, "fadd.dds", "d,1,2") + _MC88110 (0x8400aa80, "fadd.dds", "xd,x1,x2") + _MC88xxx (0x84002aa0, "fadd.ddd", "d,1,2") + _MC88110 (0x8400aaa0, "fadd.ddd", "xd,x1,x2") + _MC88110 (0x8400aac0, "fadd.ddx", "xd,x1,x2") + _MC88110 (0x8400ab00, "fadd.dxs", "xd,x1,x2") + _MC88110 (0x8400ab20, "fadd.dxd", "xd,x1,x2") + _MC88110 (0x8400ab40, "fadd.dxx", "xd,x1,x2") + _MC88110 (0x8400ac00, "fadd.xss", "xd,x1,x2") + _MC88110 (0x8400ac20, "fadd.xsd", "xd,x1,x2") + _MC88110 (0x8400ac40, "fadd.xsx", "xd,x1,x2") + _MC88110 (0x8400ac80, "fadd.xds", "xd,x1,x2") + _MC88110 (0x8400aca0, "fadd.xdd", "xd,x1,x2") + _MC88110 (0x8400acc0, "fadd.xdx", "xd,x1,x2") + _MC88110 (0x8400ad00, "fadd.xxs", "xd,x1,x2") + _MC88110 (0x8400ad20, "fadd.xxd", "xd,x1,x2") + _MC88110 (0x8400ad40, "fadd.xxx", "xd,x1,x2") + _MC88xxx (0x84003a80, "fcmp.sdd", "d,1,2") + _MC88110 (0x8400ba80, "fcmp.sdd", "d,x1,x2") + _MC88xxx (0x84003a00, "fcmp.sds", "d,1,2") + _MC88110 (0x8400ba00, "fcmp.sds", "d,x1,x2") + _MC88110 (0x8400bb00, "fcmp.sdx", "d,x1,x2") + _MC88xxx (0x84003880, "fcmp.ssd", "d,1,2") + _MC88110 (0x8400b880, "fcmp.ssd", "d,x1,x2") + _MC88xxx (0x84003800, "fcmp.sss", "d,1,2") + _MC88110 (0x8400b800, "fcmp.sss", "d,x1,x2") + _MC88110 (0x8400b900, "fcmp.ssx", "d,x1,x2") + _MC88110 (0x8400bc80, "fcmp.sxd", "d,x1,x2") + _MC88110 (0x8400bc00, "fcmp.sxs", "d,x1,x2") + _MC88110 (0x8400bd00, "fcmp.sxx", "d,x1,x2") + _MC88110 (0x84003aa0, "fcmpu.sdd", "d,1,2") + _MC88110 (0x8400baa0, "fcmpu.sdd", "d,x1,x2") + _MC88110 (0x84003a20, "fcmpu.sds", "d,1,2") + _MC88110 (0x8400ba20, "fcmpu.sds", "d,x1,x2") + _MC88110 (0x8400bb20, "fcmpu.sdx", "d,x1,x2") + _MC88110 (0x840038a0, "fcmpu.ssd", "d,1,2") + _MC88110 (0x8400b8a0, "fcmpu.ssd", "d,x1,x2") + _MC88110 (0x84003820, "fcmpu.sss", "d,1,2") + _MC88110 (0x8400b820, "fcmpu.sss", "d,x1,x2") + _MC88110 (0x8400b920, "fcmpu.ssx", "d,x1,x2") + _MC88110 (0x8400bca0, "fcmpu.sxd", "d,x1,x2") + _MC88110 (0x8400bc20, "fcmpu.sxs", "d,x1,x2") + _MC88110 (0x8400bd20, "fcmpu.sxx", "d,x1,x2") + _MC88110 (0x84000880, "fcvt.ds", "d,2") + _MC88110 (0x84008880, "fcvt.ds", "xd,x2") + _MC88110 (0x840088c0, "fcvt.dx", "xd,x2") + _MC88110 (0x84000820, "fcvt.sd", "d,2") + _MC88110 (0x84008820, "fcvt.sd", "xd,x2") + _MC88110 (0x84008840, "fcvt.sx", "xd,x2") + _MC88110 (0x84008920, "fcvt.xd", "xd,x2") + _MC88110 (0x84008900, "fcvt.xs", "xd,x2") + _MC88xxx (0x84007000, "fdiv.sss", "d,1,2") + _MC88110 (0x8400f000, "fdiv.sss", "xd,x1,x2") + _MC88xxx (0x84007080, "fdiv.ssd", "d,1,2") + _MC88110 (0x8400f020, "fdiv.ssd", "xd,x1,x2") + _MC88110 (0x8400f040, "fdiv.ssx", "xd,x1,x2") + _MC88xxx (0x84007200, "fdiv.sds", "d,1,2") + _MC88110 (0x8400f080, "fdiv.sds", "xd,x1,x2") + _MC88xxx (0x84007280, "fdiv.sdd", "d,1,2") + _MC88110 (0x8400f0a0, "fdiv.sdd", "xd,x1,x2") + _MC88110 (0x8400f0c0, "fdiv.sdx", "xd,x1,x2") + _MC88110 (0x8400f100, "fdiv.sxs", "xd,x1,x2") + _MC88110 (0x8400f120, "fdiv.sxd", "xd,x1,x2") + _MC88110 (0x8400f140, "fdiv.sxx", "xd,x1,x2") + _MC88xxx (0x84007020, "fdiv.dss", "d,1,2") + _MC88110 (0x8400f200, "fdiv.dss", "xd,x1,x2") + _MC88xxx (0x840070a0, "fdiv.dsd", "d,1,2") + _MC88110 (0x8400f220, "fdiv.dsd", "xd,x1,x2") + _MC88110 (0x8400f240, "fdiv.dsx", "xd,x1,x2") + _MC88xxx (0x84007220, "fdiv.dds", "d,1,2") + _MC88110 (0x8400f280, "fdiv.dds", "xd,x1,x2") + _MC88xxx (0x840072a0, "fdiv.ddd", "d,1,2") + _MC88110 (0x8400f2a0, "fdiv.ddd", "xd,x1,x2") + _MC88110 (0x8400f2c0, "fdiv.ddx", "xd,x1,x2") + _MC88110 (0x8400f300, "fdiv.dxs", "xd,x1,x2") + _MC88110 (0x8400f320, "fdiv.dxd", "xd,x1,x2") + _MC88110 (0x8400f340, "fdiv.dxx", "xd,x1,x2") + _MC88110 (0x8400f400, "fdiv.xss", "xd,x1,x2") + _MC88110 (0x8400f420, "fdiv.xsd", "xd,x1,x2") + _MC88110 (0x8400f440, "fdiv.xsx", "xd,x1,x2") + _MC88110 (0x8400f480, "fdiv.xds", "xd,x1,x2") + _MC88110 (0x8400f4a0, "fdiv.xdd", "xd,x1,x2") + _MC88110 (0x8400f4c0, "fdiv.xdx", "xd,x1,x2") + _MC88110 (0x8400f500, "fdiv.xxs", "xd,x1,x2") + _MC88110 (0x8400f520, "fdiv.xxd", "xd,x1,x2") + _MC88110 (0x8400f540, "fdiv.xxx", "xd,x1,x2") + _MC88xxx (0xf400ec00, "ff0", "d,2") + _MC88xxx (0xf400e800, "ff1", "d,2") + _MC88xxx (0x80004800, "fldcr", "d,f") + _MC88xxx (0x84002020, "flt.ds", "d,2") + _MC88110 (0x84002220, "flt.ds", "xd,2") + _MC88xxx (0x84002000, "flt.ss", "d,2") + _MC88110 (0x84002200, "flt.ss", "xd,2") + _MC88110 (0x84002240, "flt.xs", "xd,2") + _MC88xxx (0x84000000, "fmul.sss", "d,1,2") + _MC88110 (0x84008000, "fmul.sss", "xd,x1,x2") + _MC88xxx (0x84000080, "fmul.ssd", "d,1,2") + _MC88110 (0x84008020, "fmul.ssd", "xd,x1,x2") + _MC88110 (0x84008040, "fmul.ssx", "xd,x1,x2") + _MC88xxx (0x84000200, "fmul.sds", "d,1,2") + _MC88110 (0x84008080, "fmul.sds", "xd,x1,x2") + _MC88xxx (0x84000280, "fmul.sdd", "d,1,2") + _MC88110 (0x840080a0, "fmul.sdd", "xd,x1,x2") + _MC88110 (0x840080c0, "fmul.sdx", "xd,x1,x2") + _MC88110 (0x84008100, "fmul.sxs", "xd,x1,x2") + _MC88110 (0x84008120, "fmul.sxd", "xd,x1,x2") + _MC88110 (0x84008140, "fmul.sxx", "xd,x1,x2") + _MC88xxx (0x84000020, "fmul.dss", "d,1,2") + _MC88110 (0x84008200, "fmul.dss", "xd,x1,x2") + _MC88xxx (0x840000a0, "fmul.dsd", "d,1,2") + _MC88110 (0x84008220, "fmul.dsd", "xd,x1,x2") + _MC88110 (0x84008240, "fmul.dsx", "xd,x1,x2") + _MC88xxx (0x84000220, "fmul.dds", "d,1,2") + _MC88110 (0x84008280, "fmul.dds", "xd,x1,x2") + _MC88xxx (0x840002a0, "fmul.ddd", "d,1,2") + _MC88110 (0x840082a0, "fmul.ddd", "xd,x1,x2") + _MC88110 (0x840082c0, "fmul.ddx", "xd,x1,x2") + _MC88110 (0x84008300, "fmul.dxs", "xd,x1,x2") + _MC88110 (0x84008320, "fmul.dxd", "xd,x1,x2") + _MC88110 (0x84008340, "fmul.dxx", "xd,x1,x2") + _MC88110 (0x84008400, "fmul.xss", "xd,x1,x2") + _MC88110 (0x84008420, "fmul.xsd", "xd,x1,x2") + _MC88110 (0x84008440, "fmul.xsx", "xd,x1,x2") + _MC88110 (0x84008480, "fmul.xds", "xd,x1,x2") + _MC88110 (0x840084a0, "fmul.xdd", "xd,x1,x2") + _MC88110 (0x840084c0, "fmul.xdx", "xd,x1,x2") + _MC88110 (0x84008500, "fmul.xxs", "xd,x1,x2") + _MC88110 (0x84008520, "fmul.xxd", "xd,x1,x2") + _MC88110 (0x84008540, "fmul.xxx", "xd,x1,x2") + _MC88110 (0x840078a0, "fsqrt.dd", "d,2") + _MC88110 (0x8400f8a0, "fsqrt.dd", "xd,x2") + _MC88110 (0x84007880, "fsqrt.ds", "d,2") + _MC88110 (0x8400f880, "fsqrt.ds", "xd,x2") + _MC88110 (0x8400f8c0, "fsqrt.dx", "xd,x2") + _MC88110 (0x84007820, "fsqrt.sd", "d,2") + _MC88110 (0x8400f820, "fsqrt.sd", "xd,x2") + _MC88110 (0x84007800, "fsqrt.ss", "d,2") + _MC88110 (0x8400f800, "fsqrt.ss", "xd,x2") + _MC88110 (0x8400f840, "fsqrt.sx", "xd,x2") + _MC88110 (0x8400f920, "fsqrt.xd", "xd,x2") + _MC88110 (0x8400f900, "fsqrt.xs", "xd,x2") + _MC88110 (0x8400f940, "fsqrt.xx", "xd,x2") + _MC88xxx (0x80008800, "fstcr", "3,f") + _MC88xxx (0x84003000, "fsub.sss", "d,1,2") + _MC88110 (0x8400b000, "fsub.sss", "xd,x1,x2") + _MC88xxx (0x84003080, "fsub.ssd", "d,1,2") + _MC88110 (0x8400b020, "fsub.ssd", "xd,x1,x2") + _MC88110 (0x8400b040, "fsub.ssx", "xd,x1,x2") + _MC88xxx (0x84003200, "fsub.sds", "d,1,2") + _MC88110 (0x8400b080, "fsub.sds", "xd,x1,x2") + _MC88xxx (0x84003280, "fsub.sdd", "d,1,2") + _MC88110 (0x8400b0a0, "fsub.sdd", "xd,x1,x2") + _MC88110 (0x8400b0c0, "fsub.sdx", "xd,x1,x2") + _MC88110 (0x8400b100, "fsub.sxs", "xd,x1,x2") + _MC88110 (0x8400b120, "fsub.sxd", "xd,x1,x2") + _MC88110 (0x8400b140, "fsub.sxx", "xd,x1,x2") + _MC88xxx (0x84003020, "fsub.dss", "d,1,2") + _MC88110 (0x8400b200, "fsub.dss", "xd,x1,x2") + _MC88xxx (0x840030a0, "fsub.dsd", "d,1,2") + _MC88110 (0x8400b220, "fsub.dsd", "xd,x1,x2") + _MC88110 (0x8400b240, "fsub.dsx", "xd,x1,x2") + _MC88xxx (0x84003220, "fsub.dds", "d,1,2") + _MC88110 (0x8400b280, "fsub.dds", "xd,x1,x2") + _MC88xxx (0x840032a0, "fsub.ddd", "d,1,2") + _MC88110 (0x8400b2a0, "fsub.ddd", "xd,x1,x2") + _MC88110 (0x8400b2c0, "fsub.ddx", "xd,x1,x2") + _MC88110 (0x8400b300, "fsub.dxs", "xd,x1,x2") + _MC88110 (0x8400b320, "fsub.dxd", "xd,x1,x2") + _MC88110 (0x8400b340, "fsub.dxx", "xd,x1,x2") + _MC88110 (0x8400b400, "fsub.xss", "xd,x1,x2") + _MC88110 (0x8400b420, "fsub.xsd", "xd,x1,x2") + _MC88110 (0x8400b440, "fsub.xsx", "xd,x1,x2") + _MC88110 (0x8400b480, "fsub.xds", "xd,x1,x2") + _MC88110 (0x8400b4a0, "fsub.xdd", "xd,x1,x2") + _MC88110 (0x8400b4c0, "fsub.xdx", "xd,x1,x2") + _MC88110 (0x8400b500, "fsub.xxs", "xd,x1,x2") + _MC88110 (0x8400b520, "fsub.xxd", "xd,x1,x2") + _MC88110 (0x8400b540, "fsub.xxx", "xd,x1,x2") + _MC88xxx (0x8000c800, "fxcr", "d,3,f") + _MC88xxx (0x8400fc01, "illop1", "") + _MC88xxx (0x8400fc02, "illop2", "") + _MC88xxx (0x8400fc03, "illop3", "") + _MC88xxx (0x84004880, "int.sd", "d,2") + _MC88110 (0x8400c880, "int.sd", "d,x2") + _MC88xxx (0x84004800, "int.ss", "d,2") + _MC88110 (0x8400c800, "int.ss", "d,x2") + _MC88110 (0x8400c900, "int.sx", "d,x2") + _MC88xxx (0xf400c000, "jmp", "2") + _MC88xxx (0xf400c400, "jmp.n", "2") + _MC88xxx (0xf400c800, "jsr", "2") + _MC88xxx (0xf400cc00, "jsr.n", "2") + _MC88xxx (0xf4001400, "ld", "d,1,2") + _MC88xxx (0xf4001600, "ld", "d,1[2]") + _MC88xxx (0x14000000, "ld", "d,1,I") + _MC88110 (0xf0001600, "ld", "xd,1[2]") + _MC88110 (0xf0001400, "ld", "xd,1,2") + _MC88110 (0x04000000, "ld", "xd,1,I") + _MC88xxx (0xf4001e00, "ld.b", "d,1[2]") + _MC88xxx (0xf4001c00, "ld.b", "d,1,2") + _MC88xxx (0x1c000000, "ld.b", "d,1,I") + _MC88xxx (0xf4001d00, "ld.b.usr", "d,1,2") + _MC88xxx (0xf4001f00, "ld.b.usr", "d,1[2]") + _MC88xxx (0xf4000e00, "ld.bu", "d,1[2]") + _MC88xxx (0xf4000c00, "ld.bu", "d,1,2") + _MC88xxx (0x0c000000, "ld.bu", "d,1,I") + _MC88xxx (0xf4000d00, "ld.bu.usr", "d,1,2") + _MC88xxx (0xf4000f00, "ld.bu.usr", "d,1[2]") + _MC88xxx (0xf4001200, "ld.d", "d,1[2]") + _MC88xxx (0xf4001000, "ld.d", "d,1,2") + _MC88xxx (0x10000000, "ld.d", "d,1,I") + _MC88110 (0xf0001200, "ld.d", "xd,1[2]") + _MC88110 (0xf0001000, "ld.d", "xd,1,2") + _MC88110 (0x00000000, "ld.d", "xd,1,I") + _MC88xxx (0xf4001100, "ld.d.usr", "d,1,2") + _MC88xxx (0xf4001300, "ld.d.usr", "d,1[2]") + _MC88110 (0xf0001100, "ld.d.usr", "xd,1,2") + _MC88110 (0xf0001300, "ld.d.usr", "xd,1[2]") + _MC88xxx (0xf4001a00, "ld.h", "d,1[2]") + _MC88xxx (0xf4001800, "ld.h", "d,1,2") + _MC88xxx (0x18000000, "ld.h", "d,1,I") + _MC88xxx (0xf4001900, "ld.h.usr", "d,1,2") + _MC88xxx (0xf4001b00, "ld.h.usr", "d,1[2]") + _MC88xxx (0xf4000a00, "ld.hu", "d,1[2]") + _MC88xxx (0xf4000800, "ld.hu", "d,1,2") + _MC88xxx (0x08000000, "ld.hu", "d,1,I") + _MC88xxx (0xf4000900, "ld.hu.usr", "d,1,2") + _MC88xxx (0xf4000b00, "ld.hu.usr", "d,1[2]") + _MC88xxx (0xf4001500, "ld.usr", "d,1,2") + _MC88xxx (0xf4001700, "ld.usr", "d,1[2]") + _MC88110 (0xf0001500, "ld.usr", "xd,1,2") + _MC88110 (0xf0001700, "ld.usr", "xd,1[2]") + _MC88110 (0xf0001a00, "ld.x", "xd,1[2]") + _MC88110 (0xf0001800, "ld.x", "xd,1,2") + _MC88110 (0x3c000000, "ld.x", "xd,1,I") + _MC88110 (0xf0001900, "ld.x.usr", "xd,1,2") + _MC88110 (0xf0001b00, "ld.x.usr", "xd,1[2]") + _MC88xxx (0xf4003600, "lda", "d,1[2]") + _MC88xxx (0xf4006000, "lda", "?d,1,2") /* Output addu */ + _MC88xxx (0x60000000, "lda", "?d,1,I") /* Output addu */ + _MC88xxx (0xf4006000, "lda.b", "?d,1[2]") /* Output addu */ + _MC88xxx (0xf4006000, "lda.b", "?d,1,2") /* Output addu */ + _MC88xxx (0x60000000, "lda.b", "?d,1,I") /* Output addu */ + _MC88xxx (0xf4003200, "lda.d", "d,1[2]") + _MC88xxx (0xf4006000, "lda.d", "?d,1,2") /* Output addu */ + _MC88xxx (0x60000000, "lda.d", "?d,1,I") /* Output addu */ + _MC88110 (0xf4003e00, "lda.x", "d,1[2]") + _MC88xxx (0xf4003a00, "lda.h", "d,1[2]") + _MC88xxx (0xf4006000, "lda.h", "?d,1,2") /* Output addu */ + _MC88xxx (0x60000000, "lda.h", "?d,1,I") /* Output addu */ + _MC88xxx (0x80004000, "ldcr", "d,c") + _MC88xxx (0xf400a000, "mak", "d,1,2") + _MC88xxx (0xf000a000, "mak", "d,1,b") + _MC88xxx (0x48000000, "mask", "d,1,I") + _MC88xxx (0x4c000000, "mask.u", "d,1,I") + _MC88110 (0x8400c000, "mov.s", "d,x2") + _MC88110 (0x84004200, "mov.s", "xd,2") + _MC88110 (0x8400c080, "mov.d", "d,x2") + _MC88110 (0x84004280, "mov.d", "xd,2") + _MC88110 (0x8400c300, "mov", "xd,x2") + _MC88xxx (0xf4006c00, "mul", "d,1,2") + _MC88xxx (0x6c000000, "mul", "d,1,I") + _MC88xxx (0xf4006e00, "muls", "d,1,2") + _MC88xxx (0x6c000000, "muls", "d,1,I") + _MC88xxx (0xf4006c00, "mulu", "d,1,2") /* synonym for mul */ + _MC88xxx (0x6c000000, "mulu", "d,1,I") /* synonym for mul */ + _MC88110 (0xf4006d00, "mulu.d", "d,1,2") + _MC88xxx (0x84005080, "nint.sd", "d,2") + _MC88110 (0x8400d080, "nint.sd", "d,x2") + _MC88xxx (0x84005000, "nint.ss", "d,2") + _MC88110 (0x8400d000, "nint.ss", "d,x2") + _MC88110 (0x8400d100, "nint.sx", "d,x2") + _MC88xxx (0xf4005800, "or", "d,1,2") + _MC88xxx (0x58000000, "or", "d,1,I") + _MC88xxx (0xf4005c00, "or.c", "d,1,2") + _MC88xxx (0x5c000000, "or.u", "d,1,I") + _MC88110 (0x88002020, "padd.b", "d,1,2") + _MC88110 (0x88002040, "padd.h", "d,1,2") + _MC88110 (0x88002060, "padd", "d,1,2") + _MC88110 (0x880020a0, "padds.u.b", "d,1,2") + _MC88110 (0x880020c0, "padds.u.h", "d,1,2") + _MC88110 (0x880020e0, "padds.u", "d,1,2") + _MC88110 (0x88002120, "padds.us.b", "d,1,2") + _MC88110 (0x88002140, "padds.us.h", "d,1,2") + _MC88110 (0x88002160, "padds.us", "d,1,2") + _MC88110 (0x880021a0, "padds.s.b", "d,1,2") + _MC88110 (0x880021c0, "padds.s.h", "d,1,2") + _MC88110 (0x880021e0, "padds.s", "d,1,2") + _MC88110 (0x88003860, "pcmp", "d,1,2") + _MC88110 (0x88000000, "pmul", "d,1,2") + _MC88110 (0x88006420, "ppack.32.b", "d,1,2") + _MC88110 (0x88006240, "ppack.16.h", "d,1,2") + _MC88110 (0x88006440, "ppack.32.h", "d,1,2") + _MC88110 (0x88006160, "ppack.8", "d,1,2") + _MC88110 (0x88006260, "ppack.16", "d,1,2") + _MC88110 (0x88006460, "ppack.32", "d,1,2") + _MC88110 (0x88007800, "prot", "d,1,2") + _MC88110 (0x88007000, "prot", "d,1,o") + _MC88110 (0x88003020, "psub.b", "d,1,2") + _MC88110 (0x88003040, "psub.h", "d,1,2") + _MC88110 (0x88003060, "psub", "d,1,2") + _MC88110 (0x880030a0, "psubs.u.b", "d,1,2") + _MC88110 (0x880030c0, "psubs.u.h", "d,1,2") + _MC88110 (0x880030e0, "psubs.u", "d,1,2") + _MC88110 (0x88003120, "psubs.us.b", "d,1,2") + _MC88110 (0x88003140, "psubs.us.h", "d,1,2") + _MC88110 (0x88003160, "psubs.us", "d,1,2") + _MC88110 (0x880031a0, "psubs.s.b", "d,1,2") + _MC88110 (0x880031c0, "psubs.s.h", "d,1,2") + _MC88110 (0x880031e0, "psubs.s", "d,1,2") + _MC88110 (0x88006800, "punpk.n", "d,1") + _MC88110 (0x88006820, "punpk.b", "d,1") + _MC88110 (0x88006840, "punpk.h", "d,1") + _MC88xxx (0xf400a800, "rot", "d,1,2") + _MC88xxx (0xf000a800, "rot", "d,1,b") + _MC88xxx (0xf400fc00, "rte", "") + _MC88xxx (0xf4008800, "set", "d,1,2") + _MC88xxx (0xf0008800, "set", "d,1,b") + _MC88xxx (0xf4002600, "st", "d,1[2]") + _MC88xxx (0xf4002400, "st", "d,1,2") + _MC88xxx (0x24000000, "st", "d,1,I") + _MC88110 (0xf0002600, "st", "xd,1[2]") + _MC88110 (0xf0002400, "st", "xd,1,2") + _MC88110 (0x34000000, "st", "xd,1,I") + _MC88xxx (0xf4002e00, "st.b", "d,1[2]") + _MC88xxx (0xf4002c00, "st.b", "d,1,2") + _MC88xxx (0x2c000000, "st.b", "d,1,I") + _MC88xxx (0xf4002d00, "st.b.usr", "d,1,2") + _MC88xxx (0xf4002f00, "st.b.usr", "d,1[2]") + _MC88110 (0xf4002d80, "st.b.usr.wt", "d,1,2") + _MC88110 (0xf4002f80, "st.b.usr.wt", "d,1[2]") + _MC88110 (0xf4002c80, "st.b.wt", "d,1,2") + _MC88110 (0xf4002e80, "st.b.wt", "d,1[2]") + _MC88xxx (0xf4002200, "st.d", "d,1[2]") + _MC88xxx (0xf4002000, "st.d", "d,1,2") + _MC88xxx (0x20000000, "st.d", "d,1,I") + _MC88110 (0xf0002200, "st.d", "xd,1[2]") + _MC88110 (0xf0002000, "st.d", "xd,1,2") + _MC88110 (0x30000000, "st.d", "xd,1,I") + _MC88xxx (0xf4002100, "st.d.usr", "d,1,2") + _MC88xxx (0xf4002300, "st.d.usr", "d,1[2]") + _MC88110 (0xf0002100, "st.d.usr", "xd,1,2") + _MC88110 (0xf0002300, "st.d.usr", "xd,1[2]") + _MC88110 (0xf4002180, "st.d.usr.wt", "d,1,2") + _MC88110 (0xf4002380, "st.d.usr.wt", "d,1[2]") + _MC88110 (0xf0002180, "st.d.usr.wt", "xd,1,2") + _MC88110 (0xf0002380, "st.d.usr.wt", "xd,1[2]") + _MC88110 (0xf4002080, "st.d.wt", "d,1,2") + _MC88110 (0xf4002280, "st.d.wt", "d,1[2]") + _MC88110 (0xf0002080, "st.d.wt", "xd,1,2") + _MC88110 (0xf0002280, "st.d.wt", "xd,1[2]") + _MC88xxx (0xf4002a00, "st.h", "d,1[2]") + _MC88xxx (0xf4002800, "st.h", "d,1,2") + _MC88xxx (0x28000000, "st.h", "d,1,I") + _MC88xxx (0xf4002900, "st.h.usr", "d,1,2") + _MC88xxx (0xf4002b00, "st.h.usr", "d,1[2]") + _MC88110 (0xf4002980, "st.h.usr.wt", "d,1,2") + _MC88110 (0xf4002b80, "st.h.usr.wt", "d,1[2]") + _MC88110 (0xf4002880, "st.h.wt", "d,1,2") + _MC88110 (0xf4002a80, "st.h.wt", "d,1[2]") + _MC88xxx (0xf4002500, "st.usr", "d,1,2") + _MC88xxx (0xf4002700, "st.usr", "d,1[2]") + _MC88110 (0xf0002500, "st.usr", "xd,1,2") + _MC88110 (0xf0002700, "st.usr", "xd,1[2]") + _MC88110 (0xf4002580, "st.usr.wt", "d,1,2") + _MC88110 (0xf4002780, "st.usr.wt", "d,1[2]") + _MC88110 (0xf0002580, "st.usr.wt", "xd,1,2") + _MC88110 (0xf0002780, "st.usr.wt", "xd,1[2]") + _MC88110 (0xf4002480, "st.wt", "d,1,2") + _MC88110 (0xf4002680, "st.wt", "d,1[2]") + _MC88110 (0xf0002480, "st.wt", "xd,1,2") + _MC88110 (0xf0002680, "st.wt", "xd,1[2]") + _MC88110 (0xf0002a00, "st.x", "xd,1[2]") + _MC88110 (0xf0002800, "st.x", "xd,1,2") + _MC88110 (0x38000000, "st.x", "xd,1,I") + _MC88110 (0xf0002900, "st.x.usr", "xd,1,2") + _MC88110 (0xf0002b00, "st.x.usr", "xd,1[2]") + _MC88110 (0xf0002980, "st.x.usr.wt", "xd,1,2") + _MC88110 (0xf0002b80, "st.x.usr.wt", "xd,1[2]") + _MC88110 (0xf0002880, "st.x.wt", "xd,1,2") + _MC88110 (0xf0002a80, "st.x.wt", "xd,1[2]") + _MC88xxx (0x80008000, "stcr", "3,c") + _MC88xxx (0xf4007400, "sub", "d,1,2") + _MC88xxx (0x74000000, "sub", "d,1,I") + _MC88xxx (0xf4007600, "sub.ci", "d,1,2") + _MC88xxx (0xf4007700, "sub.cio", "d,1,2") + _MC88xxx (0xf4007500, "sub.co", "d,1,2") + _MC88xxx (0xf4006400, "subu", "d,1,2") + _MC88xxx (0x64000000, "subu", "d,1,I") + _MC88xxx (0xf4006600, "subu.ci", "d,1,2") + _MC88xxx (0xf4006700, "subu.cio", "d,1,2") + _MC88xxx (0xf4006500, "subu.co", "d,1,2") + _MC88xxx (0xf000d000, "tb0", "B,1,V") + _MC88xxx (0xf000d800, "tb1", "B,1,V") + _MC88xxx (0xf400f800, "tbnd", "1,2") + _MC88xxx (0xf8000000, "tbnd", "1,I") + _MC88xxx (0xf000e800, "tcnd", "M,1,V") + _MC88xxx (0x84005880, "trnc.sd", "d,2") + _MC88110 (0x8400d880, "trnc.sd", "d,x2") + _MC88xxx (0x84005800, "trnc.ss", "d,2") + _MC88110 (0x8400d800, "trnc.ss", "d,x2") + _MC88110 (0x8400d900, "trnc.sx", "d,x2") + _MC88xxx (0x8000c000, "xcr", "d,3,c") + _MC88xxx (0xf4000600, "xmem", "d,1[2]") + _MC88xxx (0xf4000400, "xmem", "d,1,2") + _MC88100 (0x04000000, "xmem", "?d,1,I") + _MC88xxx (0xf4000200, "xmem.bu", "d,1[2]") + _MC88xxx (0xf4000000, "xmem.bu", "d,1,2") + _MC88100 (0x00000000, "xmem.bu", "?d,1,I") + _MC88xxx (0xf4000300, "xmem.bu.usr", "d,1[2]") + _MC88xxx (0xf4000100, "xmem.bu.usr", "d,1,2") + _MC88100 (0x00000100, "xmem.bu.usr", "?d,1,I") + _MC88xxx (0xf4000700, "xmem.usr", "d,1[2]") + _MC88xxx (0xf4000500, "xmem.usr", "d,1,2") + _MC88100 (0x04000100, "xmem.usr", "?d,1,I") + _MC88xxx (0xf4005000, "xor", "d,1,2") + _MC88xxx (0x50000000, "xor", "d,1,I") + _MC88xxx (0xf4005400, "xor.c", "d,1,2") + _MC88xxx (0x54000000, "xor.u", "d,1,I") + _MC88xxx (0x00000000, "", 0) +}; + +#define NUMOPCODES ((sizeof m88k_opcodes)/(sizeof m88k_opcodes[0])) diff --git a/gnu/usr.bin/binutils-2.17/gas/config/tc-m88k.c b/gnu/usr.bin/binutils-2.17/gas/config/tc-m88k.c new file mode 100644 index 00000000000..6950cf803a3 --- /dev/null +++ b/gnu/usr.bin/binutils-2.17/gas/config/tc-m88k.c @@ -0,0 +1,1696 @@ +/* m88k.c -- Assembler for the Motorola 88000 + Contributed by Devon Bowen of Buffalo University + and Torbjorn Granlund of the Swedish Institute of Computer Science. + Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999, + 2000, 2001, 2002 + Free Software Foundation, Inc. + +This file is part of GAS, the GNU Assembler. + +GAS 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, or (at your option) +any later version. + +GAS 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 GAS; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + +#include "as.h" +#include "safe-ctype.h" +#include "subsegs.h" +#include "m88k-opcode.h" + +#if defined (OBJ_ELF) +#include "elf/m88k.h" +#endif + +#define RELOC_LO16 BFD_RELOC_LO16 +#define RELOC_HI16 BFD_RELOC_HI16 +#define RELOC_PC16 BFD_RELOC_18_PCREL_S2 +#define RELOC_PC26 BFD_RELOC_28_PCREL_S2 +#define RELOC_32 BFD_RELOC_32 +#define NO_RELOC BFD_RELOC_NONE + +struct field_val_assoc +{ + char *name; + unsigned val; +}; + +struct field_val_assoc m88100_cr_regs[] = +{ + {"PID", 0}, + {"PSR", 1}, + {"EPSR", 2}, + {"SSBR", 3}, + {"SXIP", 4}, + {"SNIP", 5}, + {"SFIP", 6}, + {"VBR", 7}, + {"DMT0", 8}, + {"DMD0", 9}, + {"DMA0", 10}, + {"DMT1", 11}, + {"DMD1", 12}, + {"DMA1", 13}, + {"DMT2", 14}, + {"DMD2", 15}, + {"DMA2", 16}, + {"SR0", 17}, + {"SR1", 18}, + {"SR2", 19}, + {"SR3", 20}, + + {NULL, 0}, +}; + +struct field_val_assoc m88110_cr_regs[] = +{ + {"PID", 0}, + {"PSR", 1}, + {"EPSR", 2}, + {"EXIP", 4}, + {"ENIP", 5}, + {"VBR", 7}, + {"SRX", 16}, + {"SR0", 17}, + {"SR1", 18}, + {"SR2", 19}, + {"SR3", 20}, + {"ICMD", 25}, + {"ICTL", 26}, + {"ISAR", 27}, + {"ISAP", 28}, + {"IUAP", 29}, + {"IIR", 30}, + {"IBP", 31}, + {"IPPU", 32}, + {"IPPL", 33}, + {"ISR", 34}, + {"ILAR", 35}, + {"IPAR", 36}, + {"DCMD", 40}, + {"DCTL", 41}, + {"DSAR", 42}, + {"DSAP", 43}, + {"DUAP", 44}, + {"DIR", 45}, + {"DBP", 46}, + {"DPPU", 47}, + {"DPPL", 48}, + {"DSR", 49}, + {"DLAR", 50}, + {"DPAR", 51}, + + {NULL, 0}, +}; + +struct field_val_assoc fcr_regs[] = +{ + {"FPECR", 0}, + {"FPHS1", 1}, + {"FPLS1", 2}, + {"FPHS2", 3}, + {"FPLS2", 4}, + {"FPPT", 5}, + {"FPRH", 6}, + {"FPRL", 7}, + {"FPIT", 8}, + + {"FPSR", 62}, + {"FPCR", 63}, + + {NULL, 0}, +}; + +struct field_val_assoc cmpslot[] = +{ +/* Integer Floating point */ + {"nc", 0}, + {"cp", 1}, + {"eq", 2}, + {"ne", 3}, + {"gt", 4}, + {"le", 5}, + {"lt", 6}, + {"ge", 7}, + {"hi", 8}, {"ou", 8}, + {"ls", 9}, {"ib", 9}, + {"lo", 10}, {"in", 10}, + {"hs", 11}, {"ob", 11}, + {"be", 12}, {"ue", 12}, + {"nb", 13}, {"lg", 13}, + {"he", 14}, {"ug", 14}, + {"nh", 15}, {"ule", 15}, + {"ul", 16}, + {"uge", 17}, + + {NULL, 0}, +}; + +struct field_val_assoc cndmsk[] = +{ + {"gt0", 1}, + {"eq0", 2}, + {"ge0", 3}, + {"lt0", 12}, + {"ne0", 13}, + {"le0", 14}, + + {NULL, 0}, +}; + +struct m88k_insn +{ + unsigned long opcode; + expressionS exp; + enum m88k_reloc_type reloc; +}; + +static char *get_bf (char *param, unsigned *valp); +static char *get_cmp (char *param, unsigned *valp); +static char *get_cnd (char *param, unsigned *valp); +static char *get_bf2 (char *param, int bc); +static char *get_bf_offset_expression (char *param, unsigned *offsetp); +static char *get_cr (char *param, unsigned *regnop); +static char *get_fcr (char *param, unsigned *regnop); +static char *get_imm16 (char *param, struct m88k_insn *insn); +static char *get_o6 (char *param, unsigned *valp); +static char *match_name (char *, struct field_val_assoc *, unsigned *); +static char *get_reg (char *param, unsigned *regnop, unsigned int reg_prefix); +static char *get_vec9 (char *param, unsigned *valp); +static char *getval (char *param, unsigned int *valp); +static char *get_pcr (char *param, struct m88k_insn *insn, + enum m88k_reloc_type reloc); + +static int calcop (struct m88k_opcode *format, + char *param, struct m88k_insn *insn); + +static void s_m88k_88110 (int); + +static struct hash_control *op_hash = NULL; + +/* Current cpu (either 88100 or 88110, or 0 if unspecified). Defaults to + zero, overriden with -m options or assembler pseudo-ops. */ +static int current_cpu = 0; + +/* These chars start a comment anywhere in a source file (except inside + another comment. */ +#if defined(OBJ_ELF) +const char comment_chars[] = "|"; +#elif defined(OBJ_AOUT) +const char comment_chars[] = "|#"; +#else +const char comment_chars[] = ";"; +#endif + +/* These chars only start a comment at the beginning of a line. */ +#if defined(OBJ_AOUT) +const char line_comment_chars[] = ";"; +#else +const char line_comment_chars[] = "#"; +#endif + +#if defined(OBJ_ELF) +const char line_separator_chars[] = ";"; +#else +const char line_separator_chars[] = ""; +#endif + +/* Chars that can be used to separate mant from exp in floating point nums */ +const char EXP_CHARS[] = "eE"; + +/* Chars that mean this number is a floating point constant */ +/* as in 0f123.456 */ +/* or 0H1.234E-12 (see exp chars above) */ +const char FLT_CHARS[] = "dDfF"; + +const pseudo_typeS md_pseudo_table[] = +{ +#ifndef OBJ_ELF + {"align", s_align_bytes, 4}, +#else + /* handled with s_align_ptwo in read.c potable[] */ +#endif + {"bss", s_lcomm, 1}, + {"def", s_set, 0}, + {"half", cons, 2}, + {"requires_88110", s_m88k_88110, 0}, + {"sbss", s_lcomm, 1}, +#if !defined(OBJ_ELF) || !defined(TE_OpenBSD) /* i.e. NO_PSEUDO_DOT == 1 */ + /* Force set to be treated as an instruction. */ + {"set", NULL, 0}, + {".set", s_set, 0}, +#endif + {"uahalf", cons, 2}, + {"uaword", cons, 4}, + {"word", cons, 4}, /* override potable[] which has word == short */ + {NULL, NULL, 0} +}; + +static void +s_m88k_88110(int i ATTRIBUTE_UNUSED) +{ + current_cpu = 88110; +} + +void +md_begin (void) +{ + const char *retval = NULL; + unsigned int i = 0; + + /* Initialize hash table. */ + op_hash = hash_new (); + + while (*m88k_opcodes[i].name) + { + char *name = m88k_opcodes[i].name; + + /* Hash each mnemonic and record its position. */ + retval = hash_insert (op_hash, name, &m88k_opcodes[i]); + + if (retval != NULL) + as_fatal (_("Can't hash instruction '%s':%s"), + m88k_opcodes[i].name, retval); + + /* Skip to next unique mnemonic or end of list. */ + for (i++; !strcmp (m88k_opcodes[i].name, name); i++) + ; + } + +#ifdef OBJ_ELF + record_alignment (text_section, 2); + record_alignment (data_section, 2); + record_alignment (bss_section, 2); + + bfd_set_private_flags (stdoutput, 0); +#endif +} + +const char *md_shortopts = "m:"; +struct option md_longopts[] = { + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof (md_longopts); + +int +md_parse_option (int c, char *arg) +{ + switch (c) + { + case 'm': + if (strcmp (arg, "88100") == 0) + current_cpu = 88100; + else if (strcmp (arg, "88110") == 0) + current_cpu = 88110; + else + as_bad (_("Option `%s' is not recognized."), arg); + break; + + default: + return 0; + } + + return 1; +} + +void +md_show_usage (FILE *stream) +{ + fputs (_("\ +M88k options:\n\ + -m88100 | -m88110 select processor type\n"), + stream); +} + +#ifdef OBJ_ELF +enum m88k_pic_reloc_type { + pic_reloc_none, + pic_reloc_abdiff, + pic_reloc_gotrel, + pic_reloc_plt +}; + +static bfd_reloc_code_real_type +m88k_get_reloc_code(struct m88k_insn *insn) +{ + switch (insn->exp.X_md) + { + default: + case pic_reloc_none: + return insn->reloc; + + case pic_reloc_abdiff: + if (insn->reloc == BFD_RELOC_LO16) + return BFD_RELOC_LO16_BASEREL; + if (insn->reloc == BFD_RELOC_HI16) + return BFD_RELOC_HI16_BASEREL; + break; + + case pic_reloc_gotrel: + if (insn->reloc == BFD_RELOC_LO16) + return BFD_RELOC_LO16_GOTOFF; + if (insn->reloc == BFD_RELOC_HI16) + return BFD_RELOC_HI16_GOTOFF; + break; + + case pic_reloc_plt: + if (insn->reloc == BFD_RELOC_32) + return BFD_RELOC_32_PLTOFF; + if (insn->reloc == BFD_RELOC_28_PCREL_S2) + return BFD_RELOC_32_PLT_PCREL; + break; + } + + as_bad ("Can't process pic type %d relocation type %d", + insn->exp.X_md, insn->reloc); + + return BFD_RELOC_NONE; +} +#else +#define m88k_get_reloc_code(insn) (insn).reloc +#endif + +void +md_assemble (char *op) +{ + char *param, *thisfrag; + char c; + struct m88k_opcode *format; + struct m88k_insn insn; + fixS *fixP; + + assert (op); + + /* Skip over instruction to find parameters. */ + for (param = op; *param != 0 && !ISSPACE (*param); param++) + ; + c = *param; + *param++ = '\0'; + + /* Try to find the instruction in the hash table. */ + /* XXX will not match XRF flavours of 88100 instructions on 88110 */ + if ((format = (struct m88k_opcode *) hash_find (op_hash, op)) == NULL) + { + as_bad (_("Invalid mnemonic '%s'"), op); + return; + } + + /* Try parsing this instruction into insn. */ + insn.exp.X_add_symbol = 0; + insn.exp.X_op_symbol = 0; + insn.exp.X_add_number = 0; + insn.exp.X_op = O_illegal; + insn.exp.X_md = pic_reloc_none; + insn.reloc = NO_RELOC; + + while (!calcop (format, param, &insn)) + { + /* If it doesn't parse try the next instruction. */ + if (!strcmp (format[0].name, format[1].name)) + format++; + else + { + as_fatal (_("Parameter syntax error")); + return; + } + } + + /* Grow the current frag and plop in the opcode. */ + thisfrag = frag_more (4); + md_number_to_chars (thisfrag, insn.opcode, 4); + + /* If this instruction requires labels mark it for later. */ + switch (insn.reloc) + { + case NO_RELOC: + break; + + case RELOC_LO16: + case RELOC_HI16: + fixP = fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal + 2, + 2, + &insn.exp, + 0, + m88k_get_reloc_code(&insn)); + fixP->fx_no_overflow = 1; + break; + +#ifdef M88KCOFF + case RELOC_IW16: + fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal, + 4, + &insn.exp, + 0, + m88k_get_reloc_code(&insn)); + break; +#endif + + case RELOC_PC16: +#ifdef OBJ_ELF + fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal , + 4, + &insn.exp, + 1, + m88k_get_reloc_code(&insn)); +#else + fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal + 2, + 2, + &insn.exp, + 1, + m88k_get_reloc_code(&insn)); +#endif + break; + + case RELOC_PC26: + fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal, + 4, + &insn.exp, + 1, + m88k_get_reloc_code(&insn)); + break; + + case RELOC_32: + fix_new_exp (frag_now, + thisfrag - frag_now->fr_literal, + 4, + &insn.exp, + 0, + m88k_get_reloc_code(&insn)); + break; + + default: + as_fatal (_("Unknown relocation type")); + break; + } +} + +static int +calcop (struct m88k_opcode *format, char *param, struct m88k_insn *insn) +{ + char *fmt = format->op_spec; + int f; + unsigned val; + unsigned opcode; + unsigned int reg_prefix = 'r'; + + insn->opcode = format->opcode; + opcode = 0; + + /* + * Instructions which have no arguments (such as rte) will get + * correctly reported only if param == "", although there could be + * whitespace following the instruction. + * Rather than eating whitespace here, let's assume everything is + * fine. If there were non-wanted arguments, they will be parsed as + * an incorrect opcode at the offending line, so that's not too bad. + * -- miod + */ + if (*fmt == '\0') + return 1; + + for (;;) + { + if (param == NULL) + return 0; + + f = *fmt++; + switch (f) + { + case 0: + insn->opcode |= opcode; + return (*param == 0 || *param == '\n'); + + default: + if (f != *param++) + return 0; + break; + + case 'd': + param = get_reg (param, &val, reg_prefix); + reg_prefix = 'r'; + opcode |= val << 21; + break; + + case 'o': + param = get_o6 (param, &val); + opcode |= ((val >> 2) << 7); + break; + + case 'x': + reg_prefix = 'x'; + break; + + case '1': + param = get_reg (param, &val, reg_prefix); + reg_prefix = 'r'; + opcode |= val << 16; + break; + + case '2': + param = get_reg (param, &val, reg_prefix); + reg_prefix = 'r'; + opcode |= val; + break; + + case '3': + param = get_reg (param, &val, 'r'); + opcode |= (val << 16) | val; + break; + + case 'I': + param = get_imm16 (param, insn); + break; + + case 'b': + param = get_bf (param, &val); + opcode |= val; + break; + + case 'p': + param = get_pcr (param, insn, RELOC_PC16); + break; + + case 'P': + param = get_pcr (param, insn, RELOC_PC26); + break; + + case 'B': + param = get_cmp (param, &val); + opcode |= val; + break; + + case 'M': + param = get_cnd (param, &val); + opcode |= val; + break; + + case 'c': + param = get_cr (param, &val); + opcode |= val << 5; + break; + + case 'f': + param = get_fcr (param, &val); + opcode |= val << 5; + break; + + case 'V': + param = get_vec9 (param, &val); + opcode |= val; + break; + + case '?': + /* Having this here repeats the warning sometimes. + But can't we stand that? */ + as_warn (_("Use of obsolete instruction")); + break; + } + } +} + +static char * +match_name (char *param, struct field_val_assoc *assoc_tab, unsigned *valp) +{ + int i; + char *name; + int name_len; + + for (i = 0;; i++) + { + name = assoc_tab[i].name; + if (name == NULL) + return NULL; + name_len = strlen (name); + if (!strncmp (param, name, name_len)) + { + *valp = assoc_tab[i].val; + return param + name_len; + } + } +} + +static char * +get_reg (char *param, unsigned *regnop, unsigned int reg_prefix) +{ + unsigned c; + unsigned regno; + +#ifdef REGISTER_PREFIX + c = *param++; + if (c != REGISTER_PREFIX) + return NULL; +#endif + + c = *param++; + if (c == reg_prefix) + { + regno = *param++ - '0'; + if (regno < 10) + { + if (regno == 0) + { + *regnop = 0; + return param; + } + c = *param - '0'; + if (c < 10) + { + regno = regno * 10 + c; + if (c < 32) + { + *regnop = regno; + return param + 1; + } + } + else + { + *regnop = regno; + return param; + } + } + return NULL; + } + else if (c == 's' && param[0] == 'p') + { + *regnop = 31; + return param + 1; + } + + return NULL; +} + +static char * +get_imm16 (char *param, struct m88k_insn *insn) +{ + enum m88k_reloc_type reloc = NO_RELOC; + unsigned int val; + char *save_ptr; +#ifdef REGISTER_PREFIX + int found_prefix = 0; +#endif + +#ifdef REGISTER_PREFIX + if (*param == REGISTER_PREFIX) + { + param++; + found_prefix = 1; + } +#endif + + if (!strncmp (param, "hi16", 4) && !ISALNUM (param[4])) + { + reloc = RELOC_HI16; + param += 4; + } + else if (!strncmp (param, "lo16", 4) && !ISALNUM (param[4])) + { + reloc = RELOC_LO16; + param += 4; + } +#ifdef M88KCOFF + else if (!strncmp (param, "iw16", 4) && !ISALNUM (param[4])) + { + reloc = RELOC_IW16; + param += 4; + } +#endif + +#ifdef REGISTER_PREFIX + if (found_prefix && reloc == NO_RELOC) + return NULL; +#endif + + save_ptr = input_line_pointer; + input_line_pointer = param; + expression (&insn->exp); + param = input_line_pointer; + input_line_pointer = save_ptr; + + val = insn->exp.X_add_number; + + if (insn->exp.X_op == O_constant) + { + /* Insert the value now, and reset reloc to NO_RELOC. */ + if (reloc == NO_RELOC) + { + /* Warn about too big expressions if not surrounded by xx16. */ + if (val > 0xffff) + as_warn (_("Expression truncated to 16 bits")); + } + + if (reloc == RELOC_HI16) + val >>= 16; + + insn->opcode |= val & 0xffff; + reloc = NO_RELOC; + } + else if (reloc == NO_RELOC) + /* We accept a symbol even without lo16, hi16, etc, and assume + lo16 was intended. */ + reloc = RELOC_LO16; + + insn->reloc = reloc; + + return param; +} + +static char * +get_pcr (char *param, struct m88k_insn *insn, enum m88k_reloc_type reloc) +{ + char *saveptr, *saveparam; + + saveptr = input_line_pointer; + input_line_pointer = param; + + expression (&insn->exp); + + saveparam = input_line_pointer; + input_line_pointer = saveptr; + + /* Botch: We should relocate now if O_constant. */ + insn->reloc = reloc; + + return saveparam; +} + +static char * +get_cmp (char *param, unsigned *valp) +{ + unsigned int val; + char *save_ptr; + + save_ptr = param; + +#ifdef REGISTER_PREFIX + /* SVR4 compiler prefixes condition codes with the register prefix */ + if (*param == REGISTER_PREFIX) + param++; +#endif + param = match_name (param, cmpslot, valp); + val = *valp; + + if (param == NULL) + { + param = save_ptr; + + save_ptr = input_line_pointer; + input_line_pointer = param; + val = get_absolute_expression (); + param = input_line_pointer; + input_line_pointer = save_ptr; + + if (val >= 32) + { + as_warn (_("Expression truncated to 5 bits")); + val %= 32; + } + } + + *valp = val << 21; + return param; +} + +static char * +get_cnd (char *param, unsigned *valp) +{ + unsigned int val; + + if (ISDIGIT (*param)) + { + param = getval (param, &val); + + if (val >= 32) + { + as_warn (_("Expression truncated to 5 bits")); + val %= 32; + } + } + else + { +#ifdef REGISTER_PREFIX + /* SVR4 compiler prefixes condition codes with the register prefix */ + if (*param == REGISTER_PREFIX) + param++; +#endif + + param[0] = TOLOWER (param[0]); + param[1] = TOLOWER (param[1]); + + param = match_name (param, cndmsk, valp); + + if (param == NULL) + return NULL; + + val = *valp; + } + + *valp = val << 21; + return param; +} + +static char * +get_bf2 (char *param, int bc) +{ + int depth = 0; + int c; + + for (;;) + { + c = *param; + if (c == 0) + return param; + else if (c == '(') + depth++; + else if (c == ')') + depth--; + else if (c == bc && depth <= 0) + return param; + param++; + } +} + +static char * +get_bf_offset_expression (char *param, unsigned *offsetp) +{ + unsigned offset; + +#ifdef REGISTER_PREFIX + /* SVR4 compiler prefixes condition codes with the register prefix */ + if (*param == REGISTER_PREFIX && ISALPHA (param[1])) + param++; +#endif + + if (ISALPHA (param[0])) + { + param[0] = TOLOWER (param[0]); + param[1] = TOLOWER (param[1]); + + param = match_name (param, cmpslot, offsetp); + + return param; + } + else + { + input_line_pointer = param; + offset = get_absolute_expression (); + param = input_line_pointer; + } + + *offsetp = offset; + return param; +} + +static char * +get_bf (char *param, unsigned *valp) +{ + unsigned offset = 0; + unsigned width = 0; + char *xp; + char *save_ptr; + + xp = get_bf2 (param, '<'); + + save_ptr = input_line_pointer; + input_line_pointer = param; + if (*xp == 0) + { + /* We did not find '<'. We have an offset (width implicitly 32). */ + param = get_bf_offset_expression (param, &offset); + input_line_pointer = save_ptr; + if (param == NULL) + return NULL; + } + else + { + *xp++ = 0; /* Overwrite the '<' */ + param = get_bf2 (xp, '>'); + if (*param == 0) + return NULL; + *param++ = 0; /* Overwrite the '>' */ + + width = get_absolute_expression (); + xp = get_bf_offset_expression (xp, &offset); + input_line_pointer = save_ptr; + + if (xp + 1 != param) + return NULL; + } + + *valp = ((width % 32) << 5) | (offset % 32); + + return param; +} + +static char * +get_cr (char *param, unsigned *regnop) +{ + unsigned regno; + unsigned c; + +#ifdef REGISTER_PREFIX + if (*param++ != REGISTER_PREFIX) + return NULL; +#endif + + if (!strncmp (param, "cr", 2)) + { + param += 2; + + regno = *param++ - '0'; + if (regno < 10) + { + if (regno == 0) + { + *regnop = 0; + return param; + } + c = *param - '0'; + if (c < 10) + { + regno = regno * 10 + c; + if (c < 64) + { + *regnop = regno; + return param + 1; + } + } + else + { + *regnop = regno; + return param; + } + } + return NULL; + } + + param = match_name (param, + current_cpu == 88110 ? m88110_cr_regs : m88100_cr_regs, + regnop); + + return param; +} + +static char * +get_fcr (char *param, unsigned *regnop) +{ + unsigned regno; + unsigned c; + +#ifdef REGISTER_PREFIX + if (*param++ != REGISTER_PREFIX) + return NULL; +#endif + + if (!strncmp (param, "fcr", 3)) + { + param += 3; + + regno = *param++ - '0'; + if (regno < 10) + { + if (regno == 0) + { + *regnop = 0; + return param; + } + c = *param - '0'; + if (c < 10) + { + regno = regno * 10 + c; + if (c < 64) + { + *regnop = regno; + return param + 1; + } + } + else + { + *regnop = regno; + return param; + } + } + return NULL; + } + + param = match_name (param, fcr_regs, regnop); + + return param; +} + +static char * +get_vec9 (char *param, unsigned *valp) +{ + unsigned val; + char *save_ptr; + + save_ptr = input_line_pointer; + input_line_pointer = param; + val = get_absolute_expression (); + param = input_line_pointer; + input_line_pointer = save_ptr; + + if (val >= 1 << 9) + as_warn (_("Expression truncated to 9 bits")); + + *valp = val % (1 << 9); + + return param; +} + +static char * +get_o6 (char *param, unsigned *valp) +{ + unsigned val; + char *save_ptr; + + save_ptr = input_line_pointer; + input_line_pointer = param; + val = get_absolute_expression (); + param = input_line_pointer; + input_line_pointer = save_ptr; + + if (val & 0x3) + as_warn (_("Removed lower 2 bits of expression")); + + *valp = val; + + return (param); +} + +#define hexval(z) \ + (ISDIGIT (z) ? (z) - '0' : \ + ISLOWER (z) ? (z) - 'a' + 10 : \ + ISUPPER (z) ? (z) - 'A' + 10 : (unsigned) -1) + +static char * +getval (char *param, unsigned int *valp) +{ + unsigned int val = 0; + unsigned int c; + + c = *param++; + if (c == '0') + { + c = *param++; + if (c == 'x' || c == 'X') + { + c = *param++; + c = hexval (c); + while (c < 16) + { + val = val * 16 + c; + c = *param++; + c = hexval (c); + } + } + else + { + c -= '0'; + while (c < 8) + { + val = val * 8 + c; + c = *param++ - '0'; + } + } + } + else + { + c -= '0'; + while (c < 10) + { + val = val * 10 + c; + c = *param++ - '0'; + } + } + + *valp = val; + return param - 1; +} + +void +md_number_to_chars (char *buf, valueT val, int nbytes) +{ + number_to_chars_bigendian (buf, val, nbytes); +} + +#define MAX_LITTLENUMS 6 + +/* Turn a string in input_line_pointer into a floating point constant of type + type, and store the appropriate bytes in *litP. The number of LITTLENUMS + emitted is stored in *sizeP . An error message is returned, or NULL on OK. + */ +char * +md_atof (int type, char *litP, int *sizeP) +{ + int prec; + LITTLENUM_TYPE words[MAX_LITTLENUMS]; + LITTLENUM_TYPE *wordP; + char *t; + + switch (type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + + case 'x': + case 'X': + prec = 6; + break; + + case 'p': + case 'P': + prec = 6; + break; + + default: + *sizeP = 0; + return _("Bad call to MD_ATOF()"); + } + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + + *sizeP = prec * sizeof (LITTLENUM_TYPE); + for (wordP = words; prec--;) + { + md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); + litP += sizeof (LITTLENUM_TYPE); + } + return 0; +} + +int md_short_jump_size = 4; +int md_long_jump_size = 4; + +void +md_create_short_jump (char *ptr, addressT from_addr ATTRIBUTE_UNUSED, + addressT to_addr ATTRIBUTE_UNUSED, fragS *frag, symbolS *to_symbol) +{ + /* Since all instructions have the same width, it does not make sense to + try and abuse a conditional instruction to get a short displacement + (such as bb1 0, %r0, address). */ + md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol); +} + +void +md_create_long_jump (char *ptr, addressT from_addr ATTRIBUTE_UNUSED, + addressT to_addr ATTRIBUTE_UNUSED, fragS *frag, symbolS *to_symbol) +{ + ptr[0] = (char) 0xc0; /* br to_addr */ + ptr[1] = 0x00; + ptr[2] = 0x00; + ptr[3] = 0x00; + fix_new (frag, + ptr - frag->fr_literal, + 4, + to_symbol, + (offsetT) 0, + 0, + RELOC_PC26); +} + +int +md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, + segT segment_type ATTRIBUTE_UNUSED) +{ + as_fatal (_("Relaxation should never occur")); + return (-1); +} + +#ifdef M88KCOFF + +/* These functions are needed if we are linking with obj-coffbfd.c. + That file may be replaced by a more BFD oriented version at some + point. If that happens, these functions should be reexamined. + + Ian Lance Taylor, Cygnus Support, 13 July 1993. */ + +/* Given a fixS structure (created by a call to fix_new, above), + return the BFD relocation type to use for it. */ + +short +tc_coff_fix2rtype (fixS *fixp) +{ + switch (fixp->fx_r_type) + { + case RELOC_LO16: + return R_LVRT16; + case RELOC_HI16: + return R_HVRT16; + case RELOC_PC16: + return R_PCR16L; + case RELOC_PC26: + return R_PCR26L; + case RELOC_32: + return R_VRT32; + case RELOC_IW16: + return R_VRT16; + default: + abort (); + } +} + +/* Apply a fixS to the object file. Since COFF does not use addends + in relocs, the addend is actually stored directly in the object + file itself. */ + +void +md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) +{ + long val = * (long *) valP; + char *buf; + + buf = fixP->fx_frag->fr_literal + fixP->fx_where; + fixP->fx_addnumber = val; + fixP->fx_offset = 0; + + switch (fixP->fx_r_type) + { + case RELOC_IW16: + fixP->fx_offset = val >> 16; + buf[2] = val >> 8; + buf[3] = val; + break; + + case RELOC_LO16: + fixP->fx_offset = val >> 16; + buf[0] = val >> 8; + buf[1] = val; + break; + + case RELOC_HI16: + buf[0] = val >> 24; + buf[1] = val >> 16; + break; + + case RELOC_PC16: + buf[0] = val >> 10; + buf[1] = val >> 2; + break; + + case RELOC_PC26: + buf[0] |= (val >> 26) & 0x03; + buf[1] = val >> 18; + buf[2] = val >> 10; + buf[3] = val >> 2; + break; + + case RELOC_32: + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val; + break; + + default: + abort (); + } + + if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) + fixP->fx_done = 1; +} + +#endif /* M88KCOFF */ + +/* Fill in rs_align_code fragments. */ + +void +m88k_handle_align (fragS *fragp) +{ + static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 }; + + int bytes; + char *p; + + if (fragp->fr_type != rs_align_code) + return; + + bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; + p = fragp->fr_literal + fragp->fr_fix; + + if (bytes & 3) + { + int fix = bytes & 3; + memset (p, 0, fix); + p += fix; + bytes -= fix; + fragp->fr_fix += fix; + } + + memcpy (p, nop_pattern, 4); + fragp->fr_var = 4; +} + +/* Where a PC relative offset is calculated from. On the m88k they + are calculated from just after the instruction. */ + +long +md_pcrel_from (fixS *fixp) +{ + switch (fixp->fx_r_type) + { + case RELOC_PC16: +#ifdef OBJ_ELF + /* FALLTHROUGH */ +#else + return fixp->fx_frag->fr_address + fixp->fx_where - 2; +#endif + case RELOC_PC26: +#ifdef OBJ_ELF + case BFD_RELOC_32_PLT_PCREL: +#endif + return fixp->fx_frag->fr_address + fixp->fx_where; + default: + abort (); + } + /*NOTREACHED*/ +} + +#ifdef OBJ_ELF + +valueT +md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) +{ + return size; +} + +/* Generate the BFD reloc to be stuck in the object file from the + fixup used internally in the assembler. */ + +arelent * +tc_gen_reloc (asection *sec ATTRIBUTE_UNUSED, fixS *fixp) +{ + arelent *reloc; + bfd_reloc_code_real_type code; + + reloc = (arelent *) xmalloc (sizeof (arelent)); + reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + + /* Make sure none of our internal relocations make it this far. + They'd better have been fully resolved by this point. */ + assert ((int) fixp->fx_r_type > 0); + + code = fixp->fx_r_type; + reloc->howto = bfd_reloc_type_lookup (stdoutput, code); + if (reloc->howto == NULL) + { + as_bad_where (fixp->fx_file, fixp->fx_line, + _("cannot represent `%s' relocation in object file"), + bfd_get_reloc_code_name (code)); + return NULL; + } + + if (!fixp->fx_pcrel != !reloc->howto->pc_relative) + { + as_fatal (_("internal error? cannot generate `%s' relocation"), + bfd_get_reloc_code_name (code)); + } + assert (!fixp->fx_pcrel == !reloc->howto->pc_relative); + + reloc->addend = fixp->fx_offset; + + return reloc; +} + +/* Apply a fixS to the object file. This is called for all the + fixups we generated by the call to fix_new_exp, above. In the call + above we used a reloc code which was the largest legal reloc code + plus the operand index. Here we undo that to recover the operand + index. At this point all symbol values should be fully resolved, + and we attempt to completely resolve the reloc. If we can not do + that, we determine the correct reloc code and put it back in the + fixup. + + This is the ELF version. +*/ + +void +md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) +{ + valueT val = * (valueT *) valP; + char *buf; + long insn; + + buf = fixP->fx_frag->fr_literal + fixP->fx_where; + + if (fixP->fx_subsy != NULL) + as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex")); + + if (fixP->fx_addsy) + { +#if 0 + /* can't empty 26-bit relocation values with memset() */ + if (fixP->fx_r_type == BFD_RELOC_28_PCREL_S2) + { + insn = bfd_getb32 ((unsigned char *) buf); + insn &= ~0x03ffffff; + bfd_putb32(insn, buf); + } + else + memset(buf, 0, fixP->fx_size); +#endif + + if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT + && !S_IS_DEFINED (fixP->fx_addsy) + && !S_IS_WEAK (fixP->fx_addsy)) + S_SET_WEAK (fixP->fx_addsy); + + return; + } + + switch (fixP->fx_r_type) + { + case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_VTABLE_ENTRY: + return; + + case BFD_RELOC_HI16_BASEREL: + case BFD_RELOC_LO16_BASEREL: + case BFD_RELOC_HI16_GOTOFF: + case BFD_RELOC_LO16_GOTOFF: + case BFD_RELOC_32_PLTOFF: + return; + + case BFD_RELOC_LO16: + case BFD_RELOC_HI16: + if (fixP->fx_pcrel) + abort (); + buf[0] = val >> 8; + buf[1] = val; + break; + + case BFD_RELOC_18_PCREL_S2: + if ((val & 0x03) != 0) + as_bad_where (fixP->fx_file, fixP->fx_line, + "Branch to unaligned address (%lx)", (long)val); + buf[2] = val >> 10; + buf[3] = val >> 2; + break; + + case BFD_RELOC_32_PLT_PCREL: + case BFD_RELOC_28_PCREL_S2: + if ((val & 0x03) != 0) + as_bad_where (fixP->fx_file, fixP->fx_line, + "Branch to unaligned address (%lx)", (long)val); + buf[0] |= (val >> 26) & 0x03; + buf[1] = val >> 18; + buf[2] = val >> 10; + buf[3] = val >> 2; + break; + + case BFD_RELOC_32: + insn = val; + bfd_putb32(insn, buf); + break; + + default: + abort (); + } + + if (/* fixP->fx_addsy == NULL && */ fixP->fx_pcrel == 0) + fixP->fx_done = 1; +} + +/* Set the ELF specific flags. */ +void +m88k_elf_final_processing (void) +{ + if (current_cpu == 88110) + elf_elfheader (stdoutput)->e_flags |= EF_M88110; +} + +inline static char * +m88k_end_of_name (char *suffix, const char *pattern, size_t patlen) +{ + if (strncmp (suffix, pattern, patlen) == 0 + && ! is_part_of_name (suffix[patlen])) + return suffix + patlen; + + return NULL; +} + +int +m88k_parse_name (const char *name, expressionS *expressionP, char *nextcharP) +{ + char *next = input_line_pointer; + char *next_end; + enum m88k_pic_reloc_type reloc_type = pic_reloc_none; + symbolS *symbolP; + segT segment; + + if (*nextcharP != '#') + return 0; + + if ((next_end = m88k_end_of_name (next + 1, "abdiff", 6)) != NULL) + { + reloc_type = pic_reloc_abdiff; + } + else if ((next_end = m88k_end_of_name (next + 1, "got_rel", 7)) != NULL) + { + reloc_type = pic_reloc_gotrel; + } + else if ((next_end = m88k_end_of_name (next + 1, "plt", 3)) != NULL) + { + reloc_type = pic_reloc_plt; + } + else + return 0; + + symbolP = symbol_find_or_make (name); + segment = S_GET_SEGMENT (symbolP); + if (segment == absolute_section) + { + expressionP->X_op = O_constant; + expressionP->X_add_number = S_GET_VALUE (symbolP); + } + else if (segment == reg_section) + { + expressionP->X_op = O_register; + expressionP->X_add_number = S_GET_VALUE (symbolP); + } + else + { + expressionP->X_op = O_symbol; + expressionP->X_add_symbol = symbolP; + expressionP->X_add_number = 0; + } + expressionP->X_md = reloc_type; + + *input_line_pointer = *nextcharP; + input_line_pointer = next_end; + *nextcharP = *input_line_pointer; + *input_line_pointer = '\0'; + + return 1; +} + +int +m88k_fix_adjustable (fixS *fix) +{ + return (fix->fx_r_type != BFD_RELOC_LO16_GOTOFF + && fix->fx_r_type != BFD_RELOC_HI16_GOTOFF + && fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT + && fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY + && (fix->fx_pcrel + || (fix->fx_subsy != NULL + && (S_GET_SEGMENT (fix->fx_subsy) + == S_GET_SEGMENT (fix->fx_addsy))) + || S_IS_LOCAL (fix->fx_addsy))); +} +#endif /* OBJ_ELF */ + +#ifdef OBJ_AOUT + +/* Round up a section size to the appropriate boundary. */ +valueT +md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) +{ + /* For a.out, force the section size to be aligned. If we don't do + this, BFD will align it for us, but it will not write out the + final bytes of the section. This may be a bug in BFD, but it is + easier to fix it here since that is how the other a.out targets + work. */ + int align; + + align = bfd_get_section_alignment (stdoutput, segment); + valueT mask = ((valueT) 1 << align) - 1; + + return (size + mask) & ~mask; +} + +const int md_reloc_size = 12; /* sizeof(struct relocation_info); */ + +void +tc_aout_fix_to_chars (char *where, fixS *fixP, + relax_addressT segment_address_in_file) +{ + long r_symbolnum; + long r_addend = 0; + long r_address; + + know (fixP->fx_addsy != NULL); + + r_address = fixP->fx_frag->fr_address + fixP->fx_where + - segment_address_in_file; + md_number_to_chars (where, r_address, 4); + + r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) + ? S_GET_TYPE (fixP->fx_addsy) + : fixP->fx_addsy->sy_number); + + where[4] = (r_symbolnum >> 16) & 0x0ff; + where[5] = (r_symbolnum >> 8) & 0x0ff; + where[6] = r_symbolnum & 0x0ff; + where[7] = ((((!S_IS_DEFINED (fixP->fx_addsy)) << 7) & 0x80) | (0 & 0x70) | + (fixP->fx_r_type & 0xf)); + + if (fixP->fx_addsy->sy_frag) { + r_addend = fixP->fx_addsy->sy_frag->fr_address; + } + + if (fixP->fx_pcrel) { + r_addend -= r_address; + } else { + r_addend = fixP->fx_addnumber; + } + + md_number_to_chars(&where[8], r_addend, 4); +} + +void +tc_headers_hook (object_headers *headers) +{ +#if defined(TE_NetBSD) || defined(TE_OpenBSD) + N_SET_INFO(headers->header, OMAGIC, M_88K_OPENBSD, 0); + headers->header.a_info = htonl(headers->header.a_info); +#endif +} + +#endif /* OBJ_AOUT */ diff --git a/gnu/usr.bin/binutils-2.17/gas/config/tc-m88k.h b/gnu/usr.bin/binutils-2.17/gas/config/tc-m88k.h new file mode 100644 index 00000000000..b266f492db9 --- /dev/null +++ b/gnu/usr.bin/binutils-2.17/gas/config/tc-m88k.h @@ -0,0 +1,136 @@ +/* m88k.h -- Assembler for the Motorola 88000 + Contributed by Devon Bowen of Buffalo University + and Torbjorn Granlund of the Swedish Institute of Computer Science. + Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000, + 2002 Free Software Foundation, Inc. + +This file is part of GAS, the GNU Assembler. + +GAS 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, or (at your option) +any later version. + +GAS 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 GAS; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + +#define TC_M88K + +#define TARGET_BYTES_BIG_ENDIAN 1 +#undef REGISTER_PREFIX + +#ifdef OBJ_AOUT +#ifdef TE_OpenBSD +#define TARGET_FORMAT "a.out-m88k-openbsd" +#endif +#endif + +#ifdef M88KCOFF +#define BFD_ARCH bfd_arch_m88k +#define COFF_MAGIC MC88OMAGIC +#define COFF_FLAGS F_AR32W +#endif + +#ifdef OBJ_ELF +#define BFD_ARCH bfd_arch_m88k +#define TARGET_ARCH bfd_arch_m88k +#define TARGET_FORMAT "elf32-m88k" +#if defined(TE_OpenBSD) +#define REGISTER_PREFIX '%' +#else +#define REGISTER_PREFIX '#' +#endif +#endif + +#define CUSTOM_RELOC_FORMAT + +/* different type of relocation available in the m88k */ + +#include "bfd.h" +#define m88k_reloc_type bfd_reloc_code_real + +#ifdef OBJ_ELF + +/* This is used to recognize #abdiff, #got_rel and #plt symbols. + The relocation type is stored in X_md. */ +extern int m88k_parse_name (const char *, expressionS *, char *); +#define md_parse_name(s, e, m, c) m88k_parse_name (s, e, c) + +/* This expression evaluates to true if the relocation is for a local + object for which we still want to do the relocation at runtime. + False if we are willing to perform this relocation while building + the .o file. Only concerns pcrel relocs. */ + +#define TC_FORCE_RELOCATION_LOCAL(FIX) \ + (!(FIX)->fx_pcrel \ + || (FIX)->fx_plt \ + || (FIX)->fx_r_type == BFD_RELOC_32_PLT_PCREL \ + || TC_FORCE_RELOCATION (FIX)) + +/* Keep relocations relative to the GOT, or non-PC relative. */ +#define tc_fix_adjustable(FIX) m88k_fix_adjustable (FIX) +extern int m88k_fix_adjustable (struct fix *); + +#endif /* OBJ_ELF */ + +#ifndef OBJ_ELF +/* The m88k uses '@' to start local labels, except on ELF. */ +#define LEX_AT (LEX_BEGIN_NAME | LEX_NAME) +#endif /* OBJ_ELF */ + +#if !defined(OBJ_ELF) || !defined(TE_OpenBSD) +/* The m88k uses pseudo-ops with no leading period, except on OpenBSD ELF. */ +#define NO_PSEUDO_DOT 1 +#endif + +/* Don't warn on word overflow; it happens on %hi relocs. */ +#undef WARN_SIGNED_OVERFLOW_WORD + +#define md_convert_frag(b,s,f) {as_fatal (_("m88k convert_frag\n"));} + +/* We don't need to do anything special for undefined symbols. */ +#define md_undefined_symbol(s) 0 + +/* We have no special operand handling. */ +#define md_operand(e) + +#define tc_aout_pre_write_hook(x) do { } while (0) +#define tc_crawl_symbol_chain(a) do { } while (0) + +#ifdef M88KCOFF + +/* Whether a reloc should be output. */ +#define TC_COUNT_RELOC(fixp) ((fixp)->fx_addsy != NULL) + +/* Get the BFD reloc type to use for a gas fixS structure. */ +#define TC_COFF_FIX2RTYPE(fixp) tc_coff_fix2rtype (fixp) + +/* No special hook needed for symbols. */ +#define tc_coff_symbol_emit_hook(s) + +/* Align sections to a four byte boundary. */ +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) max (section_alignment[(int) (SEG)], 4) + +#endif /* M88KCOFF */ + +/* Fill in rs_align_code fragments. */ +extern void m88k_handle_align (fragS *); +#define HANDLE_ALIGN(frag) m88k_handle_align (frag) + +#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4) + +#define elf_tc_final_processing m88k_elf_final_processing +extern void m88k_elf_final_processing (void); + +/* word pseudo outputs 32-bit values, no risk of ``broken words'' */ +#define WORKING_DOT_WORD diff --git a/gnu/usr.bin/binutils-2.17/gas/configure.tgt b/gnu/usr.bin/binutils-2.17/gas/configure.tgt index 80f3dbd5b6d..00b7ed4042b 100644 --- a/gnu/usr.bin/binutils-2.17/gas/configure.tgt +++ b/gnu/usr.bin/binutils-2.17/gas/configure.tgt @@ -254,6 +254,8 @@ case ${generic_target} in m68k-*-openbsd*) fmt=aout em=obsd bfd_gas=yes ;; m68k-*-psos*) fmt=elf em=psos;; + m88k-*-openbsd*) fmt=elf em=obsd ;; + maxq-*-coff) fmt=coff bfd_gas=yes ;; mcore-*-elf) fmt=elf ;; diff --git a/gnu/usr.bin/binutils-2.17/include/elf/m88k.h b/gnu/usr.bin/binutils-2.17/include/elf/m88k.h new file mode 100644 index 00000000000..b37f854b4f5 --- /dev/null +++ b/gnu/usr.bin/binutils-2.17/include/elf/m88k.h @@ -0,0 +1,106 @@ +/* MC88k ELF support for BFD. + Copyright 1998, 1999, 2000 Free Software Foundation, Inc. + + 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. */ + +#ifndef _ELF_M88K_H +#define _ELF_M88K_H + +#include "elf/reloc-macros.h" + +/* Relocation types. */ +START_RELOC_NUMBERS (elf_m88k_reloc_type) + RELOC_NUMBER (R_88K_NONE, 0) + RELOC_NUMBER (R_88K_COPY, 1) + RELOC_NUMBER (R_88K_GOTP_ENT, 2) + RELOC_NUMBER (R_88K_8, 4) + RELOC_NUMBER (R_88K_8S, 5) + RELOC_NUMBER (R_88K_16S, 7) + RELOC_NUMBER (R_88K_DISP16, 8) + RELOC_NUMBER (R_88K_DISP26, 10) + RELOC_NUMBER (R_88K_PLT_DISP26, 14) + RELOC_NUMBER (R_88K_BBASED_32, 16) + RELOC_NUMBER (R_88K_BBASED_32UA, 17) + RELOC_NUMBER (R_88K_BBASED_16H, 18) + RELOC_NUMBER (R_88K_BBASED_16L, 19) + RELOC_NUMBER (R_88K_ABDIFF_32, 24) + RELOC_NUMBER (R_88K_ABDIFF_32UA, 25) + RELOC_NUMBER (R_88K_ABDIFF_16H, 26) + RELOC_NUMBER (R_88K_ABDIFF_16L, 27) + RELOC_NUMBER (R_88K_ABDIFF_16, 28) + RELOC_NUMBER (R_88K_32, 32) + RELOC_NUMBER (R_88K_32UA, 33) + RELOC_NUMBER (R_88K_16H, 34) + RELOC_NUMBER (R_88K_16L, 35) + RELOC_NUMBER (R_88K_16, 36) + RELOC_NUMBER (R_88K_GOT_32, 40) + RELOC_NUMBER (R_88K_GOT_32UA, 41) + RELOC_NUMBER (R_88K_GOT_16H, 42) + RELOC_NUMBER (R_88K_GOT_16L, 43) + RELOC_NUMBER (R_88K_GOT_16, 44) + RELOC_NUMBER (R_88K_GOTP_32, 48) + RELOC_NUMBER (R_88K_GOTP_32UA, 49) + RELOC_NUMBER (R_88K_GOTP_16H, 50) + RELOC_NUMBER (R_88K_GOTP_16L, 51) + RELOC_NUMBER (R_88K_GOTP_16, 52) + RELOC_NUMBER (R_88K_PLT_32, 56) + RELOC_NUMBER (R_88K_PLT_32UA, 57) + RELOC_NUMBER (R_88K_PLT_16H, 58) + RELOC_NUMBER (R_88K_PLT_16L, 59) + RELOC_NUMBER (R_88K_PLT_16, 60) + RELOC_NUMBER (R_88K_ABREL_32, 64) + RELOC_NUMBER (R_88K_ABREL_32UA, 65) + RELOC_NUMBER (R_88K_ABREL_16H, 66) + RELOC_NUMBER (R_88K_ABREL_16L, 67) + RELOC_NUMBER (R_88K_ABREL_16, 68) + RELOC_NUMBER (R_88K_GOT_ABREL_32, 72) + RELOC_NUMBER (R_88K_GOT_ABREL_32UA, 73) + RELOC_NUMBER (R_88K_GOT_ABREL_16H, 74) + RELOC_NUMBER (R_88K_GOT_ABREL_16L, 75) + RELOC_NUMBER (R_88K_GOT_ABREL_16, 76) + RELOC_NUMBER (R_88K_GOTP_ABREL_32, 80) + RELOC_NUMBER (R_88K_GOTP_ABREL_32UA, 81) + RELOC_NUMBER (R_88K_GOTP_ABREL_16H, 82) + RELOC_NUMBER (R_88K_GOTP_ABREL_16L, 83) + RELOC_NUMBER (R_88K_GOTP_ABREL_16, 84) + RELOC_NUMBER (R_88K_PLT_ABREL_32, 88) + RELOC_NUMBER (R_88K_PLT_ABREL_32UA, 89) + RELOC_NUMBER (R_88K_PLT_ABREL_16H, 90) + RELOC_NUMBER (R_88K_PLT_ABREL_16L, 91) + RELOC_NUMBER (R_88K_PLT_ABREL_16, 92) + RELOC_NUMBER (R_88K_SREL_32, 96) + RELOC_NUMBER (R_88K_SREL_32UA, 97) + RELOC_NUMBER (R_88K_SREL_16H, 98) + RELOC_NUMBER (R_88K_SREL_16L, 99) + /* These are GNU extensions to enable C++ vtable garbage collection. */ + RELOC_NUMBER (R_88K_GNU_VTINHERIT, 100) + RELOC_NUMBER (R_88K_GNU_VTENTRY, 101) +END_RELOC_NUMBERS (R_88K_UNIMPLEMENTED) + +/* Processor specific flags for the ELF header e_flags field. */ + +#define EF_NABI 0x80000000 /* not ABI compliant */ +#define EF_M88110 0x00000004 /* used 88110-specific features */ + +/* Processor specific dynamic tag values. */ + +#define DT_88K_ADDRBASE 0x70000001 +#define DT_88K_PLTSTART 0x70000002 +#define DT_88K_PLTEND 0x70000003 +#define DT_88K_TDESC 0x70000004 + +#endif diff --git a/gnu/usr.bin/binutils-2.17/ld/Makefile.am b/gnu/usr.bin/binutils-2.17/ld/Makefile.am index 453f4cbf348..d0dbdc7944d 100644 --- a/gnu/usr.bin/binutils-2.17/ld/Makefile.am +++ b/gnu/usr.bin/binutils-2.17/ld/Makefile.am @@ -178,6 +178,8 @@ ALL_EMULATIONS = \ eelf32lppcnto.o \ eelf32lppcsim.o \ eelf32m32c.o \ + eelf32m88k.o \ + eelf32m88k_obsd.o \ eelf32mcore.o \ eelf32mipswindiss.o \ eelf32mt.o \ @@ -268,6 +270,7 @@ ALL_EMULATIONS = \ em68kobsd.o \ em68kpsos.o \ em88kbcs.o \ + em88kopenbsd.o \ emaxqcoff.o \ emcorepe.o \ emipsbig.o \ @@ -1193,6 +1196,9 @@ em68kpsos.c: $(srcdir)/emulparams/m68kpsos.sh \ em88kbcs.c: $(srcdir)/emulparams/m88kbcs.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/m88kbcs.sc ${GEN_DEPENDS} ${GENSCRIPTS} m88kbcs "$(tdir_m88kbcs)" +em88kopenbsd.c: $(srcdir)/emulparams/m88kopenbsd.sh \ + $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} + ${GENSCRIPTS} m88kopenbsd "$(tdir_m88kopenbsd)" emaxqcoff.c: $(srcdir)/emulparams/maxqcoff.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/maxqcoff.sc ${GEN_DEPENDS} ${GENSCRIPTS} maxqcoff "$(tdir_maxqcoff)" @@ -1687,6 +1693,13 @@ eelf32m32c.c: $(srcdir)/emulparams/elf32m32c.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/needrelax.em \ $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32m32c "$(tdir_m32c)" +eelf32m88k.c: $(srcdir)/emulparams/elf32m88k.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32m88k "$(tdir_elf32m88k)" +eelf32m88k_obsd.c: $(srcdir)/emulparams/elf32m88k_obsd.sh \ + $(srcdir)/emulparams/elf32m88k.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32m88k_obsd "$(tdir_elf32m88k_obsd)" eelf32mt.c: $(srcdir)/emulparams/elf32mt.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32mt "$(tdir_mt)" diff --git a/gnu/usr.bin/binutils-2.17/ld/Makefile.in b/gnu/usr.bin/binutils-2.17/ld/Makefile.in index 27a16e8f4f5..5436b9f2832 100644 --- a/gnu/usr.bin/binutils-2.17/ld/Makefile.in +++ b/gnu/usr.bin/binutils-2.17/ld/Makefile.in @@ -402,6 +402,8 @@ ALL_EMULATIONS = \ eelf32lppcnto.o \ eelf32lppcsim.o \ eelf32m32c.o \ + eelf32m88k.o \ + eelf32m88k_obsd.o \ eelf32mcore.o \ eelf32mipswindiss.o \ eelf32mt.o \ @@ -492,6 +494,7 @@ ALL_EMULATIONS = \ em68kobsd.o \ em68kpsos.o \ em88kbcs.o \ + em88kopenbsd.o \ emaxqcoff.o \ emcorepe.o \ emipsbig.o \ @@ -1990,6 +1993,9 @@ em68kpsos.c: $(srcdir)/emulparams/m68kpsos.sh \ em88kbcs.c: $(srcdir)/emulparams/m88kbcs.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/m88kbcs.sc ${GEN_DEPENDS} ${GENSCRIPTS} m88kbcs "$(tdir_m88kbcs)" +em88kopenbsd.c: $(srcdir)/emulparams/m88kopenbsd.sh \ + $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} + ${GENSCRIPTS} m88kopenbsd "$(tdir_m88kopenbsd)" emaxqcoff.c: $(srcdir)/emulparams/maxqcoff.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/maxqcoff.sc ${GEN_DEPENDS} ${GENSCRIPTS} maxqcoff "$(tdir_maxqcoff)" @@ -2484,6 +2490,13 @@ eelf32m32c.c: $(srcdir)/emulparams/elf32m32c.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/needrelax.em \ $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32m32c "$(tdir_m32c)" +eelf32m88k.c: $(srcdir)/emulparams/elf32m88k.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32m88k "$(tdir_elf32m88k)" +eelf32m88k_obsd.c: $(srcdir)/emulparams/elf32m88k_obsd.sh \ + $(srcdir)/emulparams/elf32m88k.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} elf32m88k_obsd "$(tdir_elf32m88k_obsd)" eelf32mt.c: $(srcdir)/emulparams/elf32mt.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32mt "$(tdir_mt)" diff --git a/gnu/usr.bin/binutils-2.17/ld/configure.tgt b/gnu/usr.bin/binutils-2.17/ld/configure.tgt index e25032179c4..cdfa4fb83e0 100644 --- a/gnu/usr.bin/binutils-2.17/ld/configure.tgt +++ b/gnu/usr.bin/binutils-2.17/ld/configure.tgt @@ -301,7 +301,9 @@ m68*-*-psos*) targ_emul=m68kpsos ;; m68*-*-rtemscoff*) targ_emul=m68kcoff ;; m68*-*-rtems*) targ_emul=m68kelf ;; -m8*-*-*) targ_emul=m88kbcs +m88*-*-openbsd*) targ_emul=elf32m88k_obsd + targ_extra_emul="m88kopenbsd m88kbcs" ;; +m88*-*-*) targ_emul=m88kbcs ;; maxq-*-coff) targ_emul=maxqcoff ;; diff --git a/gnu/usr.bin/binutils-2.17/ld/emulparams/elf32m88k.sh b/gnu/usr.bin/binutils-2.17/ld/emulparams/elf32m88k.sh new file mode 100644 index 00000000000..834168ccc27 --- /dev/null +++ b/gnu/usr.bin/binutils-2.17/ld/emulparams/elf32m88k.sh @@ -0,0 +1,11 @@ +SCRIPT_NAME=elf +OUTPUT_FORMAT="elf32-m88k" +TEXT_START_ADDR=0x1000 +MAXPAGESIZE=0x10000 +COMMONPAGESIZE=0x1000 +NONPAGED_TEXT_START_ADDR=0x1000 +ARCH=m88k +MACHINE= +NOP=0xf4005800 +TEMPLATE_NAME=elf32 +NO_SMALL_DATA=yes diff --git a/gnu/usr.bin/binutils-2.17/ld/emulparams/elf32m88k_obsd.sh b/gnu/usr.bin/binutils-2.17/ld/emulparams/elf32m88k_obsd.sh new file mode 100644 index 00000000000..9122e850390 --- /dev/null +++ b/gnu/usr.bin/binutils-2.17/ld/emulparams/elf32m88k_obsd.sh @@ -0,0 +1,6 @@ +. ${srcdir}/emulparams/elf32m88k.sh +# Force padding around .plt +DATA_PLT= +GENERATE_SHLIB_SCRIPT=yes +GENERATE_PIE_SCRIPT=no +. ${srcdir}/emulparams/elf_obsd.sh diff --git a/gnu/usr.bin/binutils-2.17/ld/emulparams/m88kopenbsd.sh b/gnu/usr.bin/binutils-2.17/ld/emulparams/m88kopenbsd.sh new file mode 100644 index 00000000000..ea637ce92d3 --- /dev/null +++ b/gnu/usr.bin/binutils-2.17/ld/emulparams/m88kopenbsd.sh @@ -0,0 +1,6 @@ +SCRIPT_NAME=aout +TEXT_START_ADDR=0x1020 +NONPAGED_TEXT_START_ADDR=0x1000 +OUTPUT_FORMAT="a.out-m88k-openbsd" +TARGET_PAGE_SIZE=0x1000 +ARCH=m88k -- 2.20.1