Port the ELF m88k work to binutils 2.17. Good enough to build a booting
authormiod <miod@openbsd.org>
Mon, 25 May 2015 14:56:26 +0000 (14:56 +0000)
committermiod <miod@openbsd.org>
Mon, 25 May 2015 14:56:26 +0000 (14:56 +0000)
kernel, and hopefully userland as well.

18 files changed:
gnu/usr.bin/binutils-2.17/bfd/bfd-in2.h
gnu/usr.bin/binutils-2.17/bfd/config.bfd
gnu/usr.bin/binutils-2.17/bfd/elf32-m88k.c
gnu/usr.bin/binutils-2.17/bfd/libbfd.h
gnu/usr.bin/binutils-2.17/bfd/reloc.c
gnu/usr.bin/binutils-2.17/binutils/readelf.c
gnu/usr.bin/binutils-2.17/gas/config/aout_gnu.h
gnu/usr.bin/binutils-2.17/gas/config/m88k-opcode.h [new file with mode: 0644]
gnu/usr.bin/binutils-2.17/gas/config/tc-m88k.c [new file with mode: 0644]
gnu/usr.bin/binutils-2.17/gas/config/tc-m88k.h [new file with mode: 0644]
gnu/usr.bin/binutils-2.17/gas/configure.tgt
gnu/usr.bin/binutils-2.17/include/elf/m88k.h [new file with mode: 0644]
gnu/usr.bin/binutils-2.17/ld/Makefile.am
gnu/usr.bin/binutils-2.17/ld/Makefile.in
gnu/usr.bin/binutils-2.17/ld/configure.tgt
gnu/usr.bin/binutils-2.17/ld/emulparams/elf32m88k.sh [new file with mode: 0644]
gnu/usr.bin/binutils-2.17/ld/emulparams/elf32m88k_obsd.sh [new file with mode: 0644]
gnu/usr.bin/binutils-2.17/ld/emulparams/m88kopenbsd.sh [new file with mode: 0644]

index 1f06496..eafad3d 100644 (file)
@@ -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.  */
index 53d0f23..33d7ac9 100644 (file)
@@ -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
     ;;
 
index 1554c23..ac436d4 100644 (file)
-/* 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
+\f
+/* 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"
index eccb42b..fb23744 100644 (file)
@@ -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",
index f1d09a5..c80a0f9 100644 (file)
@@ -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
index a82fe73..298bb6f 100644 (file)
@@ -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;
        }
     }
 
index e17fda9..843233c 100644 (file)
@@ -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 (file)
index 0000000..8055b5e
--- /dev/null
@@ -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 (file)
index 0000000..6950cf8
--- /dev/null
@@ -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<cpu> 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
+}
+\f
+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
+\f
+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;
+}
+\f
+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 (file)
index 0000000..b266f49
--- /dev/null
@@ -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
index 80f3dbd..00b7ed4 100644 (file)
@@ -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 (file)
index 0000000..b37f854
--- /dev/null
@@ -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
index 453f4cb..d0dbdc7 100644 (file)
@@ -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)"
index 27a16e8..5436b9f 100644 (file)
@@ -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)"
index e250321..cdfa4fb 100644 (file)
@@ -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 (file)
index 0000000..834168c
--- /dev/null
@@ -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 (file)
index 0000000..9122e85
--- /dev/null
@@ -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 (file)
index 0000000..ea637ce
--- /dev/null
@@ -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