Back to index

cell-binutils  2.17cvs20070401
elf32-m68hc11.c
Go to the documentation of this file.
00001 /* Motorola 68HC11-specific support for 32-bit ELF
00002    Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
00003    Free Software Foundation, Inc.
00004    Contributed by Stephane Carrez (stcarrez@nerim.fr)
00005    (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
00006 
00007 This file is part of BFD, the Binary File Descriptor library.
00008 
00009 This program is free software; you can redistribute it and/or modify
00010 it under the terms of the GNU General Public License as published by
00011 the Free Software Foundation; either version 2 of the License, or
00012 (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00022 
00023 #include "bfd.h"
00024 #include "sysdep.h"
00025 #include "bfdlink.h"
00026 #include "libbfd.h"
00027 #include "elf-bfd.h"
00028 #include "elf32-m68hc1x.h"
00029 #include "elf/m68hc11.h"
00030 #include "opcode/m68hc11.h"
00031 
00032 /* Relocation functions.  */
00033 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
00034   (bfd *, bfd_reloc_code_real_type);
00035 static void m68hc11_info_to_howto_rel
00036   (bfd *, arelent *, Elf_Internal_Rela *);
00037 
00038 /* Trampoline generation.  */
00039 static bfd_boolean m68hc11_elf_size_one_stub
00040   (struct bfd_hash_entry *gen_entry, void *in_arg);
00041 static bfd_boolean m68hc11_elf_build_one_stub
00042   (struct bfd_hash_entry *gen_entry, void *in_arg);
00043 static struct bfd_link_hash_table* m68hc11_elf_bfd_link_hash_table_create
00044   (bfd* abfd);
00045 
00046 /* Linker relaxation.  */
00047 static bfd_boolean m68hc11_elf_relax_section
00048   (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
00049 static void m68hc11_elf_relax_delete_bytes
00050   (bfd *, asection *, bfd_vma, int);
00051 static void m68hc11_relax_group
00052   (bfd *, asection *, bfd_byte *, unsigned, unsigned long, unsigned long);
00053 static int compare_reloc (const void *, const void *);
00054 
00055 /* Use REL instead of RELA to save space */
00056 #define USE_REL      1
00057 
00058 /* The Motorola 68HC11 microcontroller only addresses 64Kb but we also
00059    support a memory bank switching mechanism similar to 68HC12.
00060    We must handle 8 and 16-bit relocations.  The 32-bit relocation
00061    are used for debugging sections (DWARF2) to represent a virtual
00062    address.
00063    The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
00064 static reloc_howto_type elf_m68hc11_howto_table[] = {
00065   /* This reloc does nothing.  */
00066   HOWTO (R_M68HC11_NONE,    /* type */
00067         0,                  /* rightshift */
00068         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00069         32,                 /* bitsize */
00070         FALSE,                     /* pc_relative */
00071         0,                  /* bitpos */
00072         complain_overflow_dont,/* complain_on_overflow */
00073         bfd_elf_generic_reloc,     /* special_function */
00074         "R_M68HC11_NONE",   /* name */
00075         FALSE,                     /* partial_inplace */
00076         0,                  /* src_mask */
00077         0,                  /* dst_mask */
00078         FALSE),             /* pcrel_offset */
00079 
00080   /* A 8 bit absolute relocation */
00081   HOWTO (R_M68HC11_8,              /* type */
00082         0,                  /* rightshift */
00083         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00084         8,                  /* bitsize */
00085         FALSE,                     /* pc_relative */
00086         0,                  /* bitpos */
00087         complain_overflow_bitfield,       /* complain_on_overflow */
00088         bfd_elf_generic_reloc,     /* special_function */
00089         "R_M68HC11_8",             /* name */
00090         FALSE,                     /* partial_inplace */
00091         0x00ff,             /* src_mask */
00092         0x00ff,             /* dst_mask */
00093         FALSE),             /* pcrel_offset */
00094 
00095   /* A 8 bit absolute relocation (upper address) */
00096   HOWTO (R_M68HC11_HI8,            /* type */
00097         8,                  /* rightshift */
00098         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00099         8,                  /* bitsize */
00100         FALSE,                     /* pc_relative */
00101         0,                  /* bitpos */
00102         complain_overflow_bitfield,       /* complain_on_overflow */
00103         bfd_elf_generic_reloc,     /* special_function */
00104         "R_M68HC11_HI8",    /* name */
00105         FALSE,                     /* partial_inplace */
00106         0x00ff,             /* src_mask */
00107         0x00ff,             /* dst_mask */
00108         FALSE),             /* pcrel_offset */
00109 
00110   /* A 8 bit absolute relocation (upper address) */
00111   HOWTO (R_M68HC11_LO8,            /* type */
00112         0,                  /* rightshift */
00113         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00114         8,                  /* bitsize */
00115         FALSE,                     /* pc_relative */
00116         0,                  /* bitpos */
00117         complain_overflow_dont,    /* complain_on_overflow */
00118         bfd_elf_generic_reloc,     /* special_function */
00119         "R_M68HC11_LO8",    /* name */
00120         FALSE,                     /* partial_inplace */
00121         0x00ff,             /* src_mask */
00122         0x00ff,             /* dst_mask */
00123         FALSE),             /* pcrel_offset */
00124 
00125   /* A 8 bit PC-rel relocation */
00126   HOWTO (R_M68HC11_PCREL_8, /* type */
00127         0,                  /* rightshift */
00128         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00129         8,                  /* bitsize */
00130         TRUE,               /* pc_relative */
00131         0,                  /* bitpos */
00132         complain_overflow_bitfield,       /* complain_on_overflow */
00133         bfd_elf_generic_reloc,     /* special_function */
00134         "R_M68HC11_PCREL_8",       /* name */
00135         FALSE,                     /* partial_inplace */
00136         0x00ff,             /* src_mask */
00137         0x00ff,             /* dst_mask */
00138         TRUE),                 /* pcrel_offset */
00139 
00140   /* A 16 bit absolute relocation */
00141   HOWTO (R_M68HC11_16,             /* type */
00142         0,                  /* rightshift */
00143         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00144         16,                 /* bitsize */
00145         FALSE,                     /* pc_relative */
00146         0,                  /* bitpos */
00147         complain_overflow_dont /*bitfield */ ,   /* complain_on_overflow */
00148         bfd_elf_generic_reloc,     /* special_function */
00149         "R_M68HC11_16",     /* name */
00150         FALSE,                     /* partial_inplace */
00151         0xffff,             /* src_mask */
00152         0xffff,             /* dst_mask */
00153         FALSE),             /* pcrel_offset */
00154 
00155   /* A 32 bit absolute relocation.  This one is never used for the
00156      code relocation.  It's used by gas for -gstabs generation.  */
00157   HOWTO (R_M68HC11_32,             /* type */
00158         0,                  /* rightshift */
00159         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00160         32,                 /* bitsize */
00161         FALSE,                     /* pc_relative */
00162         0,                  /* bitpos */
00163         complain_overflow_bitfield,       /* complain_on_overflow */
00164         bfd_elf_generic_reloc,     /* special_function */
00165         "R_M68HC11_32",     /* name */
00166         FALSE,                     /* partial_inplace */
00167         0xffffffff,         /* src_mask */
00168         0xffffffff,         /* dst_mask */
00169         FALSE),             /* pcrel_offset */
00170 
00171   /* A 3 bit absolute relocation */
00172   HOWTO (R_M68HC11_3B,             /* type */
00173         0,                  /* rightshift */
00174         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00175         3,                  /* bitsize */
00176         FALSE,                     /* pc_relative */
00177         0,                  /* bitpos */
00178         complain_overflow_bitfield,       /* complain_on_overflow */
00179         bfd_elf_generic_reloc,     /* special_function */
00180         "R_M68HC11_4B",     /* name */
00181         FALSE,                     /* partial_inplace */
00182         0x003,                     /* src_mask */
00183         0x003,                     /* dst_mask */
00184         FALSE),             /* pcrel_offset */
00185 
00186   /* A 16 bit PC-rel relocation */
00187   HOWTO (R_M68HC11_PCREL_16,       /* type */
00188         0,                  /* rightshift */
00189         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00190         16,                 /* bitsize */
00191         TRUE,               /* pc_relative */
00192         0,                  /* bitpos */
00193         complain_overflow_dont,    /* complain_on_overflow */
00194         bfd_elf_generic_reloc,     /* special_function */
00195         "R_M68HC11_PCREL_16",      /* name */
00196         FALSE,                     /* partial_inplace */
00197         0xffff,             /* src_mask */
00198         0xffff,             /* dst_mask */
00199         TRUE),                 /* pcrel_offset */
00200 
00201   /* GNU extension to record C++ vtable hierarchy */
00202   HOWTO (R_M68HC11_GNU_VTINHERIT,  /* type */
00203         0,                  /* rightshift */
00204         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00205         0,                  /* bitsize */
00206         FALSE,                     /* pc_relative */
00207         0,                  /* bitpos */
00208         complain_overflow_dont,    /* complain_on_overflow */
00209         NULL,               /* special_function */
00210         "R_M68HC11_GNU_VTINHERIT", /* name */
00211         FALSE,                     /* partial_inplace */
00212         0,                  /* src_mask */
00213         0,                  /* dst_mask */
00214         FALSE),             /* pcrel_offset */
00215 
00216   /* GNU extension to record C++ vtable member usage */
00217   HOWTO (R_M68HC11_GNU_VTENTRY,    /* type */
00218         0,                  /* rightshift */
00219         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00220         0,                  /* bitsize */
00221         FALSE,                     /* pc_relative */
00222         0,                  /* bitpos */
00223         complain_overflow_dont,    /* complain_on_overflow */
00224         _bfd_elf_rel_vtable_reloc_fn,     /* special_function */
00225         "R_M68HC11_GNU_VTENTRY",   /* name */
00226         FALSE,                     /* partial_inplace */
00227         0,                  /* src_mask */
00228         0,                  /* dst_mask */
00229         FALSE),             /* pcrel_offset */
00230 
00231   /* A 24 bit relocation */
00232   HOWTO (R_M68HC11_24,              /* type */
00233         0,                  /* rightshift */
00234         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00235         24,                 /* bitsize */
00236         FALSE,                     /* pc_relative */
00237         0,                  /* bitpos */
00238         complain_overflow_bitfield,       /* complain_on_overflow */
00239         bfd_elf_generic_reloc,     /* special_function */
00240         "R_M68HC11_24",     /* name */
00241         FALSE,                     /* partial_inplace */
00242         0xffffff,           /* src_mask */
00243         0xffffff,           /* dst_mask */
00244         FALSE),             /* pcrel_offset */
00245 
00246   /* A 16-bit low relocation */
00247   HOWTO (R_M68HC11_LO16,        /* type */
00248         0,                  /* rightshift */
00249         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00250         16,                 /* bitsize */
00251         FALSE,                     /* pc_relative */
00252         0,                  /* bitpos */
00253         complain_overflow_bitfield,       /* complain_on_overflow */
00254         bfd_elf_generic_reloc,     /* special_function */
00255         "R_M68HC11_LO16",   /* name */
00256         FALSE,                     /* partial_inplace */
00257         0xffff,             /* src_mask */
00258         0xffff,             /* dst_mask */
00259         FALSE),             /* pcrel_offset */
00260 
00261   /* A page relocation */
00262   HOWTO (R_M68HC11_PAGE,        /* type */
00263         0,                  /* rightshift */
00264         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00265         8,                  /* bitsize */
00266         FALSE,                     /* pc_relative */
00267         0,                  /* bitpos */
00268         complain_overflow_bitfield,       /* complain_on_overflow */
00269         bfd_elf_generic_reloc,     /* special_function */
00270         "R_M68HC11_PAGE",   /* name */
00271         FALSE,                     /* partial_inplace */
00272         0x00ff,             /* src_mask */
00273         0x00ff,             /* dst_mask */
00274         FALSE),             /* pcrel_offset */
00275 
00276   EMPTY_HOWTO (14),
00277   EMPTY_HOWTO (15),
00278   EMPTY_HOWTO (16),
00279   EMPTY_HOWTO (17),
00280   EMPTY_HOWTO (18),
00281   EMPTY_HOWTO (19),
00282 
00283   /* Mark beginning of a jump instruction (any form).  */
00284   HOWTO (R_M68HC11_RL_JUMP, /* type */
00285         0,                  /* rightshift */
00286         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00287         0,                  /* bitsize */
00288         FALSE,                     /* pc_relative */
00289         0,                  /* bitpos */
00290         complain_overflow_dont,    /* complain_on_overflow */
00291         m68hc11_elf_ignore_reloc,  /* special_function */
00292         "R_M68HC11_RL_JUMP",       /* name */
00293         TRUE,               /* partial_inplace */
00294         0,                  /* src_mask */
00295         0,                  /* dst_mask */
00296         TRUE),                 /* pcrel_offset */
00297 
00298   /* Mark beginning of Gcc relaxation group instruction.  */
00299   HOWTO (R_M68HC11_RL_GROUP,       /* type */
00300         0,                  /* rightshift */
00301         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00302         0,                  /* bitsize */
00303         FALSE,                     /* pc_relative */
00304         0,                  /* bitpos */
00305         complain_overflow_dont,    /* complain_on_overflow */
00306         m68hc11_elf_ignore_reloc,  /* special_function */
00307         "R_M68HC11_RL_GROUP",      /* name */
00308         TRUE,               /* partial_inplace */
00309         0,                  /* src_mask */
00310         0,                  /* dst_mask */
00311         TRUE),                 /* pcrel_offset */
00312 };
00313 
00314 /* Map BFD reloc types to M68HC11 ELF reloc types.  */
00315 
00316 struct m68hc11_reloc_map
00317 {
00318   bfd_reloc_code_real_type bfd_reloc_val;
00319   unsigned char elf_reloc_val;
00320 };
00321 
00322 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
00323   {BFD_RELOC_NONE, R_M68HC11_NONE,},
00324   {BFD_RELOC_8, R_M68HC11_8},
00325   {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
00326   {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
00327   {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
00328   {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
00329   {BFD_RELOC_16, R_M68HC11_16},
00330   {BFD_RELOC_32, R_M68HC11_32},
00331   {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
00332 
00333   {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
00334   {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
00335 
00336   {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
00337   {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
00338   {BFD_RELOC_M68HC11_24, R_M68HC11_24},
00339 
00340   {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
00341   {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
00342 };
00343 
00344 static reloc_howto_type *
00345 bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00346                                  bfd_reloc_code_real_type code)
00347 {
00348   unsigned int i;
00349 
00350   for (i = 0;
00351        i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
00352        i++)
00353     {
00354       if (m68hc11_reloc_map[i].bfd_reloc_val == code)
00355        return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
00356     }
00357 
00358   return NULL;
00359 }
00360 
00361 static reloc_howto_type *
00362 bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00363                              const char *r_name)
00364 {
00365   unsigned int i;
00366 
00367   for (i = 0;
00368        i < (sizeof (elf_m68hc11_howto_table)
00369            / sizeof (elf_m68hc11_howto_table[0]));
00370        i++)
00371     if (elf_m68hc11_howto_table[i].name != NULL
00372        && strcasecmp (elf_m68hc11_howto_table[i].name, r_name) == 0)
00373       return &elf_m68hc11_howto_table[i];
00374 
00375   return NULL;
00376 }
00377 
00378 /* Set the howto pointer for an M68HC11 ELF reloc.  */
00379 
00380 static void
00381 m68hc11_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
00382                            arelent *cache_ptr, Elf_Internal_Rela *dst)
00383 {
00384   unsigned int r_type;
00385 
00386   r_type = ELF32_R_TYPE (dst->r_info);
00387   BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
00388   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
00389 }
00390 
00391 
00392 /* Far trampoline generation.  */
00393 
00394 /* Build a 68HC11 trampoline stub.  */
00395 static bfd_boolean
00396 m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
00397 {
00398   struct elf32_m68hc11_stub_hash_entry *stub_entry;
00399   struct bfd_link_info *info;
00400   struct m68hc11_elf_link_hash_table *htab;
00401   asection *stub_sec;
00402   bfd *stub_bfd;
00403   bfd_byte *loc;
00404   bfd_vma sym_value, phys_page, phys_addr;
00405 
00406   /* Massage our args to the form they really have.  */
00407   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
00408   info = (struct bfd_link_info *) in_arg;
00409 
00410   htab = m68hc11_elf_hash_table (info);
00411 
00412   stub_sec = stub_entry->stub_sec;
00413 
00414   /* Make a note of the offset within the stubs for this entry.  */
00415   stub_entry->stub_offset = stub_sec->size;
00416   stub_sec->size += 10;
00417   loc = stub_sec->contents + stub_entry->stub_offset;
00418 
00419   stub_bfd = stub_sec->owner;
00420 
00421   /* Create the trampoline call stub:
00422 
00423      pshb
00424      ldab #%page(symbol)
00425      ldy #%addr(symbol)
00426      jmp __trampoline
00427 
00428   */
00429   sym_value = (stub_entry->target_value
00430                + stub_entry->target_section->output_offset
00431                + stub_entry->target_section->output_section->vma);
00432   phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
00433   phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
00434 
00435   /* pshb; ldab #%page(sym) */
00436   bfd_put_8 (stub_bfd, 0x37, loc);
00437   bfd_put_8 (stub_bfd, 0xC6, loc + 1);
00438   bfd_put_8 (stub_bfd, phys_page, loc + 2);
00439   loc += 3;
00440 
00441   /* ldy #%addr(sym)  */
00442   bfd_put_8 (stub_bfd, 0x18, loc);
00443   bfd_put_8 (stub_bfd, 0xCE, loc + 1);
00444   bfd_put_16 (stub_bfd, phys_addr, loc + 2);
00445   loc += 4;
00446 
00447   /* jmp __trampoline  */
00448   bfd_put_8 (stub_bfd, 0x7E, loc);
00449   bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
00450 
00451   return TRUE;
00452 }
00453 
00454 /* As above, but don't actually build the stub.  Just bump offset so
00455    we know stub section sizes.  */
00456 
00457 static bfd_boolean
00458 m68hc11_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
00459                            void *in_arg ATTRIBUTE_UNUSED)
00460 {
00461   struct elf32_m68hc11_stub_hash_entry *stub_entry;
00462 
00463   /* Massage our args to the form they really have.  */
00464   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
00465 
00466   stub_entry->stub_sec->size += 10;
00467   return TRUE;
00468 }
00469 
00470 /* Create a 68HC11 ELF linker hash table.  */
00471 
00472 static struct bfd_link_hash_table *
00473 m68hc11_elf_bfd_link_hash_table_create (bfd *abfd)
00474 {
00475   struct m68hc11_elf_link_hash_table *ret;
00476 
00477   ret = m68hc11_elf_hash_table_create (abfd);
00478   if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
00479     return NULL;
00480 
00481   ret->size_one_stub = m68hc11_elf_size_one_stub;
00482   ret->build_one_stub = m68hc11_elf_build_one_stub;
00483 
00484   return &ret->root.root;
00485 }
00486 
00487 
00488 /* 68HC11 Linker Relaxation.  */
00489 
00490 struct m68hc11_direct_relax
00491 {
00492   const char *name;
00493   unsigned char code;
00494   unsigned char direct_code;
00495 } m68hc11_direct_relax_table[] = {
00496   { "adca", 0xB9, 0x99 },
00497   { "adcb", 0xF9, 0xD9 },
00498   { "adda", 0xBB, 0x9B },
00499   { "addb", 0xFB, 0xDB },
00500   { "addd", 0xF3, 0xD3 },
00501   { "anda", 0xB4, 0x94 },
00502   { "andb", 0xF4, 0xD4 },
00503   { "cmpa", 0xB1, 0x91 },
00504   { "cmpb", 0xF1, 0xD1 },
00505   { "cpd",  0xB3, 0x93 },
00506   { "cpxy", 0xBC, 0x9C },
00507 /* { "cpy",  0xBC, 0x9C }, */
00508   { "eora", 0xB8, 0x98 },
00509   { "eorb", 0xF8, 0xD8 },
00510   { "jsr",  0xBD, 0x9D },
00511   { "ldaa", 0xB6, 0x96 },
00512   { "ldab", 0xF6, 0xD6 },
00513   { "ldd",  0xFC, 0xDC },
00514   { "lds",  0xBE, 0x9E },
00515   { "ldxy", 0xFE, 0xDE },
00516   /*  { "ldy",  0xFE, 0xDE },*/
00517   { "oraa", 0xBA, 0x9A },
00518   { "orab", 0xFA, 0xDA },
00519   { "sbca", 0xB2, 0x92 },
00520   { "sbcb", 0xF2, 0xD2 },
00521   { "staa", 0xB7, 0x97 },
00522   { "stab", 0xF7, 0xD7 },
00523   { "std",  0xFD, 0xDD },
00524   { "sts",  0xBF, 0x9F },
00525   { "stxy", 0xFF, 0xDF },
00526   /*  { "sty",  0xFF, 0xDF },*/
00527   { "suba", 0xB0, 0x90 },
00528   { "subb", 0xF0, 0xD0 },
00529   { "subd", 0xB3, 0x93 },
00530   { 0, 0, 0 }
00531 };
00532 
00533 static struct m68hc11_direct_relax *
00534 find_relaxable_insn (unsigned char code)
00535 {
00536   int i;
00537 
00538   for (i = 0; m68hc11_direct_relax_table[i].name; i++)
00539     if (m68hc11_direct_relax_table[i].code == code)
00540       return &m68hc11_direct_relax_table[i];
00541 
00542   return 0;
00543 }
00544 
00545 static int
00546 compare_reloc (const void *e1, const void *e2)
00547 {
00548   const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
00549   const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;
00550 
00551   if (i1->r_offset == i2->r_offset)
00552     return 0;
00553   else
00554     return i1->r_offset < i2->r_offset ? -1 : 1;
00555 }
00556 
00557 #define M6811_OP_LDX_IMMEDIATE (0xCE)
00558 
00559 static void
00560 m68hc11_relax_group (bfd *abfd, asection *sec, bfd_byte *contents,
00561                      unsigned value, unsigned long offset,
00562                      unsigned long end_group)
00563 {
00564   unsigned char code;
00565   unsigned long start_offset;
00566   unsigned long ldx_offset = offset;
00567   unsigned long ldx_size;
00568   int can_delete_ldx;
00569   int relax_ldy = 0;
00570 
00571   /* First instruction of the relax group must be a
00572      LDX #value or LDY #value.  If this is not the case,
00573      ignore the relax group.  */
00574   code = bfd_get_8 (abfd, contents + offset);
00575   if (code == 0x18)
00576     {
00577       relax_ldy++;
00578       offset++;
00579       code = bfd_get_8 (abfd, contents + offset);
00580     }
00581   ldx_size = offset - ldx_offset + 3;
00582   offset += 3;
00583   if (code != M6811_OP_LDX_IMMEDIATE || offset >= end_group)
00584     return;
00585 
00586 
00587   /* We can remove the LDX/LDY only when all bset/brclr instructions
00588      of the relax group have been converted to use direct addressing
00589      mode.  */
00590   can_delete_ldx = 1;
00591   while (offset < end_group)
00592     {
00593       unsigned isize;
00594       unsigned new_value;
00595       int bset_use_y;
00596 
00597       bset_use_y = 0;
00598       start_offset = offset;
00599       code = bfd_get_8 (abfd, contents + offset);
00600       if (code == 0x18)
00601         {
00602           bset_use_y++;
00603           offset++;
00604           code = bfd_get_8 (abfd, contents + offset);
00605         }
00606 
00607       /* Check the instruction and translate to use direct addressing mode.  */
00608       switch (code)
00609         {
00610           /* bset */
00611         case 0x1C:
00612           code = 0x14;
00613           isize = 3;
00614           break;
00615 
00616           /* brclr */
00617         case 0x1F:
00618           code = 0x13;
00619           isize = 4;
00620           break;
00621 
00622           /* brset */
00623         case 0x1E:
00624           code = 0x12;
00625           isize = 4;
00626           break;
00627 
00628           /* bclr */
00629         case 0x1D:
00630           code = 0x15;
00631           isize = 3;
00632           break;
00633 
00634           /* This instruction is not recognized and we are not
00635              at end of the relax group.  Ignore and don't remove
00636              the first LDX (we don't know what it is used for...).  */
00637         default:
00638           return;
00639         }
00640       new_value = (unsigned) bfd_get_8 (abfd, contents + offset + 1);
00641       new_value += value;
00642       if ((new_value & 0xff00) == 0 && bset_use_y == relax_ldy)
00643         {
00644           bfd_put_8 (abfd, code, contents + offset);
00645           bfd_put_8 (abfd, new_value, contents + offset + 1);
00646           if (start_offset != offset)
00647             {
00648               m68hc11_elf_relax_delete_bytes (abfd, sec, start_offset,
00649                                               offset - start_offset);
00650               end_group--;
00651             }
00652         }
00653       else
00654         {
00655           can_delete_ldx = 0;
00656         }
00657       offset = start_offset + isize;
00658     }
00659   if (can_delete_ldx)
00660     {
00661       /* Remove the move instruction (3 or 4 bytes win).  */
00662       m68hc11_elf_relax_delete_bytes (abfd, sec, ldx_offset, ldx_size);
00663     }
00664 }
00665 
00666 /* This function handles relaxing for the 68HC11.
00667 
00668 
00669        and somewhat more difficult to support.  */
00670 
00671 static bfd_boolean
00672 m68hc11_elf_relax_section (bfd *abfd, asection *sec,
00673                            struct bfd_link_info *link_info, bfd_boolean *again)
00674 {
00675   Elf_Internal_Shdr *symtab_hdr;
00676   Elf_Internal_Shdr *shndx_hdr;
00677   Elf_Internal_Rela *internal_relocs;
00678   Elf_Internal_Rela *free_relocs = NULL;
00679   Elf_Internal_Rela *irel, *irelend;
00680   bfd_byte *contents = NULL;
00681   bfd_byte *free_contents = NULL;
00682   Elf32_External_Sym *free_extsyms = NULL;
00683   Elf_Internal_Rela *prev_insn_branch = NULL;
00684   Elf_Internal_Rela *prev_insn_group = NULL;
00685   unsigned insn_group_value = 0;
00686   Elf_Internal_Sym *isymbuf = NULL;
00687 
00688   /* Assume nothing changes.  */
00689   *again = FALSE;
00690 
00691   /* We don't have to do anything for a relocatable link, if
00692      this section does not have relocs, or if this is not a
00693      code section.  */
00694   if (link_info->relocatable
00695       || (sec->flags & SEC_RELOC) == 0
00696       || sec->reloc_count == 0
00697       || (sec->flags & SEC_CODE) == 0)
00698     return TRUE;
00699 
00700   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00701   shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
00702 
00703   /* Get a copy of the native relocations.  */
00704   internal_relocs = (_bfd_elf_link_read_relocs
00705                    (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
00706                     link_info->keep_memory));
00707   if (internal_relocs == NULL)
00708     goto error_return;
00709   if (! link_info->keep_memory)
00710     free_relocs = internal_relocs;
00711 
00712   /* Checking for branch relaxation relies on the relocations to
00713      be sorted on 'r_offset'.  This is not guaranteed so we must sort.  */
00714   qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
00715          compare_reloc);
00716 
00717   /* Walk through them looking for relaxing opportunities.  */
00718   irelend = internal_relocs + sec->reloc_count;
00719   for (irel = internal_relocs; irel < irelend; irel++)
00720     {
00721       bfd_vma symval;
00722       bfd_vma value;
00723       Elf_Internal_Sym *isym;
00724       asection *sym_sec;
00725       int is_far = 0;
00726 
00727       /* If this isn't something that can be relaxed, then ignore
00728         this reloc.  */
00729       if (ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_16
00730           && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_JUMP
00731           && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_GROUP)
00732         {
00733           prev_insn_branch = 0;
00734           prev_insn_group = 0;
00735           continue;
00736         }
00737 
00738       /* Get the section contents if we haven't done so already.  */
00739       if (contents == NULL)
00740        {
00741          /* Get cached copy if it exists.  */
00742          if (elf_section_data (sec)->this_hdr.contents != NULL)
00743            contents = elf_section_data (sec)->this_hdr.contents;
00744          else
00745            {
00746              /* Go get them off disk.  */
00747              if (!bfd_malloc_and_get_section (abfd, sec, &contents))
00748               goto error_return;
00749            }
00750        }
00751 
00752       /* Try to eliminate an unconditional 8 bit pc-relative branch
00753         which immediately follows a conditional 8 bit pc-relative
00754         branch around the unconditional branch.
00755 
00756            original:        new:
00757            bCC lab1         bCC' lab2
00758            bra lab2
00759           lab1:             lab1:
00760 
00761         This happens when the bCC can't reach lab2 at assembly time,
00762         but due to other relaxations it can reach at link time.  */
00763       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_JUMP)
00764        {
00765          Elf_Internal_Rela *nrel;
00766          unsigned char code;
00767           unsigned char roffset;
00768 
00769           prev_insn_branch = 0;
00770           prev_insn_group = 0;
00771 
00772          /* Do nothing if this reloc is the last byte in the section.  */
00773          if (irel->r_offset + 2 >= sec->size)
00774            continue;
00775 
00776          /* See if the next instruction is an unconditional pc-relative
00777             branch, more often than not this test will fail, so we
00778             test it first to speed things up.  */
00779          code = bfd_get_8 (abfd, contents + irel->r_offset + 2);
00780          if (code != 0x7e)
00781            continue;
00782 
00783          /* Also make sure the next relocation applies to the next
00784             instruction and that it's a pc-relative 8 bit branch.  */
00785          nrel = irel + 1;
00786          if (nrel == irelend
00787              || irel->r_offset + 3 != nrel->r_offset
00788              || ELF32_R_TYPE (nrel->r_info) != (int) R_M68HC11_16)
00789            continue;
00790 
00791          /* Make sure our destination immediately follows the
00792             unconditional branch.  */
00793           roffset = bfd_get_8 (abfd, contents + irel->r_offset + 1);
00794           if (roffset != 3)
00795             continue;
00796 
00797           prev_insn_branch = irel;
00798           prev_insn_group = 0;
00799           continue;
00800         }
00801 
00802       /* Read this BFD's symbols if we haven't done so already.  */
00803       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
00804        {
00805          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
00806          if (isymbuf == NULL)
00807            isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
00808                                        symtab_hdr->sh_info, 0,
00809                                        NULL, NULL, NULL);
00810          if (isymbuf == NULL)
00811            goto error_return;
00812        }
00813 
00814       /* Get the value of the symbol referred to by the reloc.  */
00815       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
00816        {
00817          /* A local symbol.  */
00818          isym = isymbuf + ELF32_R_SYM (irel->r_info);
00819           is_far = isym->st_other & STO_M68HC12_FAR;
00820           sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
00821          symval = (isym->st_value
00822                   + sym_sec->output_section->vma
00823                   + sym_sec->output_offset);
00824        }
00825       else
00826        {
00827          unsigned long indx;
00828          struct elf_link_hash_entry *h;
00829 
00830          /* An external symbol.  */
00831          indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
00832          h = elf_sym_hashes (abfd)[indx];
00833          BFD_ASSERT (h != NULL);
00834          if (h->root.type != bfd_link_hash_defined
00835              && h->root.type != bfd_link_hash_defweak)
00836            {
00837              /* This appears to be a reference to an undefined
00838                  symbol.  Just ignore it--it will be caught by the
00839                  regular reloc processing.  */
00840               prev_insn_branch = 0;
00841               prev_insn_group = 0;
00842              continue;
00843            }
00844 
00845           is_far = h->other & STO_M68HC12_FAR;
00846           isym = 0;
00847           sym_sec = h->root.u.def.section;
00848          symval = (h->root.u.def.value
00849                   + sym_sec->output_section->vma
00850                   + sym_sec->output_offset);
00851        }
00852 
00853       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
00854        {
00855           prev_insn_branch = 0;
00856           prev_insn_group = 0;
00857 
00858          /* Do nothing if this reloc is the last byte in the section.  */
00859          if (irel->r_offset == sec->size)
00860            continue;
00861 
00862           prev_insn_group = irel;
00863           insn_group_value = isym->st_value;
00864           continue;
00865         }
00866 
00867       /* When we relax some bytes, the size of our section changes.
00868          This affects the layout of next input sections that go in our
00869          output section.  When the symbol is part of another section that
00870          will go in the same output section as the current one, it's
00871          final address may now be incorrect (too far).  We must let the
00872          linker re-compute all section offsets before processing this
00873          reloc.  Code example:
00874 
00875                                 Initial             Final
00876          .sect .text            section size = 6    section size = 4
00877          jmp foo
00878          jmp bar
00879          .sect .text.foo_bar    output_offset = 6   output_offset = 4
00880          foo: rts
00881          bar: rts
00882 
00883          If we process the reloc now, the jmp bar is replaced by a
00884          relative branch to the initial bar address (output_offset 6).  */
00885       if (*again && sym_sec != sec
00886           && sym_sec->output_section == sec->output_section)
00887         {
00888           prev_insn_group = 0;
00889           prev_insn_branch = 0;
00890           continue;
00891         }
00892 
00893       value = symval;
00894       /* Try to turn a far branch to a near branch.  */
00895       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
00896           && prev_insn_branch)
00897         {
00898           bfd_vma offset;
00899           unsigned char code;
00900 
00901           offset = value - (prev_insn_branch->r_offset
00902                             + sec->output_section->vma
00903                             + sec->output_offset + 2);
00904 
00905           /* If the offset is still out of -128..+127 range,
00906              leave that far branch unchanged.  */
00907           if ((offset & 0xff80) != 0 && (offset & 0xff80) != 0xff80)
00908             {
00909               prev_insn_branch = 0;
00910               continue;
00911             }
00912 
00913           /* Shrink the branch.  */
00914           code = bfd_get_8 (abfd, contents + prev_insn_branch->r_offset);
00915           if (code == 0x7e)
00916             {
00917               code = 0x20;
00918               bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
00919               bfd_put_8 (abfd, 0xff,
00920                          contents + prev_insn_branch->r_offset + 1);
00921               irel->r_offset = prev_insn_branch->r_offset + 1;
00922               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
00923                                            R_M68HC11_PCREL_8);
00924               m68hc11_elf_relax_delete_bytes (abfd, sec,
00925                                               irel->r_offset + 1, 1);
00926             }
00927           else
00928             {
00929               code ^= 0x1;
00930               bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
00931               bfd_put_8 (abfd, 0xff,
00932                          contents + prev_insn_branch->r_offset + 1);
00933               irel->r_offset = prev_insn_branch->r_offset + 1;
00934               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
00935                                            R_M68HC11_PCREL_8);
00936               m68hc11_elf_relax_delete_bytes (abfd, sec,
00937                                               irel->r_offset + 1, 3);
00938             }
00939           prev_insn_branch = 0;
00940           *again = TRUE;
00941         }
00942 
00943       /* Try to turn a 16 bit address into a 8 bit page0 address.  */
00944       else if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
00945                && (value & 0xff00) == 0)
00946        {
00947           unsigned char code;
00948           unsigned short offset;
00949           struct m68hc11_direct_relax *rinfo;
00950 
00951           prev_insn_branch = 0;
00952           offset = bfd_get_16 (abfd, contents + irel->r_offset);
00953           offset += value;
00954           if ((offset & 0xff00) != 0)
00955             {
00956               prev_insn_group = 0;
00957               continue;
00958             }
00959 
00960           if (prev_insn_group)
00961             {
00962               unsigned long old_sec_size = sec->size;
00963 
00964               /* Note that we've changed the relocation contents, etc.  */
00965               elf_section_data (sec)->relocs = internal_relocs;
00966               free_relocs = NULL;
00967 
00968               elf_section_data (sec)->this_hdr.contents = contents;
00969               free_contents = NULL;
00970 
00971               symtab_hdr->contents = (bfd_byte *) isymbuf;
00972               free_extsyms = NULL;
00973 
00974               m68hc11_relax_group (abfd, sec, contents, offset,
00975                                    prev_insn_group->r_offset,
00976                                    insn_group_value);
00977               irel = prev_insn_group;
00978               prev_insn_group = 0;
00979               irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
00980                                            R_M68HC11_NONE);
00981               if (sec->size != old_sec_size)
00982                 *again = TRUE;
00983               continue;
00984             }
00985 
00986           /* Get the opcode.  */
00987           code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
00988           rinfo = find_relaxable_insn (code);
00989           if (rinfo == 0)
00990             {
00991               prev_insn_group = 0;
00992               continue;
00993             }
00994 
00995           /* Note that we've changed the relocation contents, etc.  */
00996           elf_section_data (sec)->relocs = internal_relocs;
00997           free_relocs = NULL;
00998 
00999           elf_section_data (sec)->this_hdr.contents = contents;
01000           free_contents = NULL;
01001 
01002           symtab_hdr->contents = (bfd_byte *) isymbuf;
01003           free_extsyms = NULL;
01004 
01005           /* Fix the opcode.  */
01006           /* printf ("A relaxable case : 0x%02x (%s)\n",
01007              code, rinfo->name); */
01008           bfd_put_8 (abfd, rinfo->direct_code,
01009                      contents + irel->r_offset - 1);
01010 
01011           /* Delete one byte of data (upper byte of address).  */
01012           m68hc11_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 1);
01013 
01014           /* Fix the relocation's type.  */
01015           irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
01016                                        R_M68HC11_8);
01017 
01018           /* That will change things, so, we should relax again.  */
01019           *again = TRUE;
01020         }
01021       else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16 && !is_far)
01022         {
01023           unsigned char code;
01024           bfd_vma offset;
01025 
01026           prev_insn_branch = 0;
01027           code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
01028           if (code == 0x7e || code == 0xbd)
01029             {
01030               offset = value - (irel->r_offset
01031                                 + sec->output_section->vma
01032                                 + sec->output_offset + 1);
01033               offset += bfd_get_16 (abfd, contents + irel->r_offset);
01034 
01035               /* If the offset is still out of -128..+127 range,
01036                  leave that far branch unchanged.  */
01037               if ((offset & 0xff80) == 0 || (offset & 0xff80) == 0xff80)
01038                 {
01039 
01040                   /* Note that we've changed the relocation contents, etc.  */
01041                   elf_section_data (sec)->relocs = internal_relocs;
01042                   free_relocs = NULL;
01043 
01044                   elf_section_data (sec)->this_hdr.contents = contents;
01045                   free_contents = NULL;
01046 
01047                   symtab_hdr->contents = (bfd_byte *) isymbuf;
01048                   free_extsyms = NULL;
01049 
01050                   /* Shrink the branch.  */
01051                   code = (code == 0x7e) ? 0x20 : 0x8d;
01052                   bfd_put_8 (abfd, code,
01053                              contents + irel->r_offset - 1);
01054                   bfd_put_8 (abfd, 0xff,
01055                              contents + irel->r_offset);
01056                   irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
01057                                                R_M68HC11_PCREL_8);
01058                   m68hc11_elf_relax_delete_bytes (abfd, sec,
01059                                                   irel->r_offset + 1, 1);
01060                   /* That will change things, so, we should relax again.  */
01061                   *again = TRUE;
01062                 }
01063             }
01064         }
01065       prev_insn_branch = 0;
01066       prev_insn_group = 0;
01067     }
01068 
01069   if (free_relocs != NULL)
01070     {
01071       free (free_relocs);
01072       free_relocs = NULL;
01073     }
01074 
01075   if (free_contents != NULL)
01076     {
01077       if (! link_info->keep_memory)
01078        free (free_contents);
01079       else
01080        {
01081          /* Cache the section contents for elf_link_input_bfd.  */
01082          elf_section_data (sec)->this_hdr.contents = contents;
01083        }
01084       free_contents = NULL;
01085     }
01086 
01087   if (free_extsyms != NULL)
01088     {
01089       if (! link_info->keep_memory)
01090        free (free_extsyms);
01091       else
01092        {
01093          /* Cache the symbols for elf_link_input_bfd.  */
01094          symtab_hdr->contents = (unsigned char *) isymbuf;
01095        }
01096       free_extsyms = NULL;
01097     }
01098 
01099   return TRUE;
01100 
01101  error_return:
01102   if (free_relocs != NULL)
01103     free (free_relocs);
01104   if (free_contents != NULL)
01105     free (free_contents);
01106   if (free_extsyms != NULL)
01107     free (free_extsyms);
01108   return FALSE;
01109 }
01110 
01111 /* Delete some bytes from a section while relaxing.  */
01112 
01113 static void
01114 m68hc11_elf_relax_delete_bytes (bfd *abfd, asection *sec,
01115                                 bfd_vma addr, int count)
01116 {
01117   Elf_Internal_Shdr *symtab_hdr;
01118   unsigned int sec_shndx;
01119   bfd_byte *contents;
01120   Elf_Internal_Rela *irel, *irelend;
01121   bfd_vma toaddr;
01122   Elf_Internal_Sym *isymbuf, *isym, *isymend;
01123   struct elf_link_hash_entry **sym_hashes;
01124   struct elf_link_hash_entry **end_hashes;
01125   unsigned int symcount;
01126 
01127   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
01128   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
01129 
01130   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
01131 
01132   contents = elf_section_data (sec)->this_hdr.contents;
01133 
01134   toaddr = sec->size;
01135 
01136   irel = elf_section_data (sec)->relocs;
01137   irelend = irel + sec->reloc_count;
01138 
01139   /* Actually delete the bytes.  */
01140   memmove (contents + addr, contents + addr + count,
01141           (size_t) (toaddr - addr - count));
01142 
01143   sec->size -= count;
01144 
01145   /* Adjust all the relocs.  */
01146   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
01147     {
01148       unsigned char code;
01149       unsigned char offset;
01150       unsigned short raddr;
01151       unsigned long old_offset;
01152       int branch_pos;
01153 
01154       old_offset = irel->r_offset;
01155 
01156       /* See if this reloc was for the bytes we have deleted, in which
01157         case we no longer care about it.  Don't delete relocs which
01158         represent addresses, though.  */
01159       if (ELF32_R_TYPE (irel->r_info) != R_M68HC11_RL_JUMP
01160           && irel->r_offset >= addr && irel->r_offset < addr + count)
01161         irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
01162                                      R_M68HC11_NONE);
01163 
01164       if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_NONE)
01165         continue;
01166 
01167       /* Get the new reloc address.  */
01168       if ((irel->r_offset > addr
01169           && irel->r_offset < toaddr))
01170        irel->r_offset -= count;
01171 
01172       /* If this is a PC relative reloc, see if the range it covers
01173          includes the bytes we have deleted.  */
01174       switch (ELF32_R_TYPE (irel->r_info))
01175        {
01176        default:
01177          break;
01178 
01179        case R_M68HC11_RL_JUMP:
01180           code = bfd_get_8 (abfd, contents + irel->r_offset);
01181           switch (code)
01182             {
01183               /* jsr and jmp instruction are also marked with RL_JUMP
01184                  relocs but no adjustment must be made.  */
01185             case 0x7e:
01186             case 0x9d:
01187             case 0xbd:
01188               continue;
01189 
01190             case 0x12:
01191             case 0x13:
01192               branch_pos = 3;
01193               raddr = 4;
01194 
01195               /* Special case when we translate a brclr N,y into brclr *<addr>
01196                  In this case, the 0x18 page2 prefix is removed.
01197                  The reloc offset is not modified but the instruction
01198                  size is reduced by 1.  */
01199               if (old_offset == addr)
01200                 raddr++;
01201               break;
01202 
01203             case 0x1e:
01204             case 0x1f:
01205               branch_pos = 3;
01206               raddr = 4;
01207               break;
01208 
01209             case 0x18:
01210               branch_pos = 4;
01211               raddr = 5;
01212               break;
01213 
01214             default:
01215               branch_pos = 1;
01216               raddr = 2;
01217               break;
01218             }
01219           offset = bfd_get_8 (abfd, contents + irel->r_offset + branch_pos);
01220           raddr += old_offset;
01221           raddr += ((unsigned short) offset | ((offset & 0x80) ? 0xff00 : 0));
01222           if (irel->r_offset < addr && raddr > addr)
01223             {
01224               offset -= count;
01225               bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
01226             }
01227           else if (irel->r_offset >= addr && raddr <= addr)
01228             {
01229               offset += count;
01230               bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
01231             }
01232           else
01233             {
01234               /*printf ("Not adjusted 0x%04x [0x%4x 0x%4x]\n", raddr,
01235                 irel->r_offset, addr);*/
01236             }
01237 
01238           break;
01239        }
01240     }
01241 
01242   /* Adjust the local symbols defined in this section.  */
01243   isymend = isymbuf + symtab_hdr->sh_info;
01244   for (isym = isymbuf; isym < isymend; isym++)
01245     {
01246       if (isym->st_shndx == sec_shndx
01247          && isym->st_value > addr
01248          && isym->st_value <= toaddr)
01249        isym->st_value -= count;
01250     }
01251 
01252   /* Now adjust the global symbols defined in this section.  */
01253   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
01254              - symtab_hdr->sh_info);
01255   sym_hashes = elf_sym_hashes (abfd);
01256   end_hashes = sym_hashes + symcount;
01257   for (; sym_hashes < end_hashes; sym_hashes++)
01258     {
01259       struct elf_link_hash_entry *sym_hash = *sym_hashes;
01260       if ((sym_hash->root.type == bfd_link_hash_defined
01261           || sym_hash->root.type == bfd_link_hash_defweak)
01262          && sym_hash->root.u.def.section == sec
01263          && sym_hash->root.u.def.value > addr
01264          && sym_hash->root.u.def.value <= toaddr)
01265        {
01266          sym_hash->root.u.def.value -= count;
01267        }
01268     }
01269 }
01270 
01271 /* Specific sections:
01272    - The .page0 is a data section that is mapped in [0x0000..0x00FF].
01273      Page0 accesses are faster on the M68HC11. Soft registers used by GCC-m6811
01274      are located in .page0.
01275    - The .vectors is the section that represents the interrupt
01276      vectors.  */
01277 static const struct bfd_elf_special_section elf32_m68hc11_special_sections[] =
01278 {
01279   { STRING_COMMA_LEN (".eeprom"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
01280   { STRING_COMMA_LEN (".page0"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
01281   { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
01282   { STRING_COMMA_LEN (".vectors"),  0, SHT_PROGBITS, SHF_ALLOC },
01283   { NULL,                       0,  0, 0,            0 }
01284 };
01285 
01286 #define ELF_ARCH            bfd_arch_m68hc11
01287 #define ELF_MACHINE_CODE    EM_68HC11
01288 #define ELF_MAXPAGESIZE            0x1000
01289 
01290 #define TARGET_BIG_SYM          bfd_elf32_m68hc11_vec
01291 #define TARGET_BIG_NAME            "elf32-m68hc11"
01292 
01293 #define elf_info_to_howto   0
01294 #define elf_info_to_howto_rel      m68hc11_info_to_howto_rel
01295 #define bfd_elf32_bfd_relax_section  m68hc11_elf_relax_section
01296 #define elf_backend_check_relocs     elf32_m68hc11_check_relocs
01297 #define elf_backend_relocate_section elf32_m68hc11_relocate_section
01298 #define elf_backend_add_symbol_hook  elf32_m68hc11_add_symbol_hook
01299 #define elf_backend_object_p       0
01300 #define elf_backend_final_write_processing       0
01301 #define elf_backend_can_gc_sections              1
01302 #define elf_backend_special_sections  elf32_m68hc11_special_sections
01303 
01304 #define bfd_elf32_bfd_link_hash_table_create \
01305                                 m68hc11_elf_bfd_link_hash_table_create
01306 #define bfd_elf32_bfd_link_hash_table_free \
01307                             m68hc11_elf_bfd_link_hash_table_free
01308 #define bfd_elf32_bfd_merge_private_bfd_data \
01309                                    _bfd_m68hc11_elf_merge_private_bfd_data
01310 #define bfd_elf32_bfd_set_private_flags   _bfd_m68hc11_elf_set_private_flags
01311 #define bfd_elf32_bfd_print_private_bfd_data \
01312                                    _bfd_m68hc11_elf_print_private_bfd_data
01313 
01314 #include "elf32-target.h"