Home | History | Annotate | Line # | Download | only in bfd
elf32-m68hc11.c revision 1.1.1.7
      1 /* Motorola 68HC11-specific support for 32-bit ELF
      2    Copyright (C) 1999-2020 Free Software Foundation, Inc.
      3    Contributed by Stephane Carrez (stcarrez (at) nerim.fr)
      4    (Heavily copied from the D10V port by Martin Hunt (hunt (at) cygnus.com))
      5 
      6    This file is part of BFD, the Binary File Descriptor library.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, write to the Free Software
     20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21    MA 02110-1301, USA.  */
     22 
     23 #include "sysdep.h"
     24 #include "bfd.h"
     25 #include "bfdlink.h"
     26 #include "libbfd.h"
     27 #include "elf-bfd.h"
     28 #include "elf32-m68hc1x.h"
     29 #include "elf/m68hc11.h"
     30 #include "opcode/m68hc11.h"
     31 
     32 /* Relocation functions.  */
     33 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
     34   (bfd *, bfd_reloc_code_real_type);
     35 static bfd_boolean m68hc11_info_to_howto_rel
     36   (bfd *, arelent *, Elf_Internal_Rela *);
     37 
     38 /* Trampoline generation.  */
     39 static bfd_boolean m68hc11_elf_size_one_stub
     40   (struct bfd_hash_entry *gen_entry, void *in_arg);
     41 static bfd_boolean m68hc11_elf_build_one_stub
     42   (struct bfd_hash_entry *gen_entry, void *in_arg);
     43 static struct bfd_link_hash_table* m68hc11_elf_bfd_link_hash_table_create
     44   (bfd* abfd);
     45 
     46 /* Linker relaxation.  */
     47 static bfd_boolean m68hc11_elf_relax_section
     48   (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
     49 static void m68hc11_elf_relax_delete_bytes
     50   (bfd *, asection *, bfd_vma, int);
     51 static void m68hc11_relax_group
     52   (bfd *, asection *, bfd_byte *, unsigned, unsigned long, unsigned long);
     53 static int compare_reloc (const void *, const void *);
     54 
     55 /* Use REL instead of RELA to save space */
     56 #define USE_REL	1
     57 
     58 /* The Motorola 68HC11 microcontroller only addresses 64Kb but we also
     59    support a memory bank switching mechanism similar to 68HC12.
     60    We must handle 8 and 16-bit relocations.  The 32-bit relocation
     61    are used for debugging sections (DWARF2) to represent a virtual
     62    address.
     63    The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
     64 static reloc_howto_type elf_m68hc11_howto_table[] = {
     65   /* This reloc does nothing.  */
     66   HOWTO (R_M68HC11_NONE,	/* type */
     67 	 0,			/* rightshift */
     68 	 3,			/* size (0 = byte, 1 = short, 2 = long) */
     69 	 0,			/* bitsize */
     70 	 FALSE,			/* pc_relative */
     71 	 0,			/* bitpos */
     72 	 complain_overflow_dont,/* complain_on_overflow */
     73 	 bfd_elf_generic_reloc,	/* special_function */
     74 	 "R_M68HC11_NONE",	/* name */
     75 	 FALSE,			/* partial_inplace */
     76 	 0,			/* src_mask */
     77 	 0,			/* dst_mask */
     78 	 FALSE),		/* pcrel_offset */
     79 
     80   /* A 8 bit absolute relocation */
     81   HOWTO (R_M68HC11_8,		/* type */
     82 	 0,			/* rightshift */
     83 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
     84 	 8,			/* bitsize */
     85 	 FALSE,			/* pc_relative */
     86 	 0,			/* bitpos */
     87 	 complain_overflow_bitfield,	/* complain_on_overflow */
     88 	 bfd_elf_generic_reloc,	/* special_function */
     89 	 "R_M68HC11_8",		/* name */
     90 	 FALSE,			/* partial_inplace */
     91 	 0x00ff,		/* src_mask */
     92 	 0x00ff,		/* dst_mask */
     93 	 FALSE),		/* pcrel_offset */
     94 
     95   /* A 8 bit absolute relocation (upper address) */
     96   HOWTO (R_M68HC11_HI8,		/* type */
     97 	 8,			/* rightshift */
     98 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
     99 	 8,			/* bitsize */
    100 	 FALSE,			/* pc_relative */
    101 	 0,			/* bitpos */
    102 	 complain_overflow_bitfield,	/* complain_on_overflow */
    103 	 bfd_elf_generic_reloc,	/* special_function */
    104 	 "R_M68HC11_HI8",	/* name */
    105 	 FALSE,			/* partial_inplace */
    106 	 0x00ff,		/* src_mask */
    107 	 0x00ff,		/* dst_mask */
    108 	 FALSE),		/* pcrel_offset */
    109 
    110   /* A 8 bit absolute relocation (upper address) */
    111   HOWTO (R_M68HC11_LO8,		/* type */
    112 	 0,			/* rightshift */
    113 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
    114 	 8,			/* bitsize */
    115 	 FALSE,			/* pc_relative */
    116 	 0,			/* bitpos */
    117 	 complain_overflow_dont,	/* complain_on_overflow */
    118 	 bfd_elf_generic_reloc,	/* special_function */
    119 	 "R_M68HC11_LO8",	/* name */
    120 	 FALSE,			/* partial_inplace */
    121 	 0x00ff,		/* src_mask */
    122 	 0x00ff,		/* dst_mask */
    123 	 FALSE),		/* pcrel_offset */
    124 
    125   /* A 8 bit PC-rel relocation */
    126   HOWTO (R_M68HC11_PCREL_8,	/* type */
    127 	 0,			/* rightshift */
    128 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
    129 	 8,			/* bitsize */
    130 	 TRUE,			/* pc_relative */
    131 	 0,			/* bitpos */
    132 	 complain_overflow_bitfield,	/* complain_on_overflow */
    133 	 bfd_elf_generic_reloc,	/* special_function */
    134 	 "R_M68HC11_PCREL_8",	/* name */
    135 	 FALSE,			/* partial_inplace */
    136 	 0x00ff,		/* src_mask */
    137 	 0x00ff,		/* dst_mask */
    138 	 TRUE),			/* pcrel_offset */
    139 
    140   /* A 16 bit absolute relocation */
    141   HOWTO (R_M68HC11_16,		/* type */
    142 	 0,			/* rightshift */
    143 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    144 	 16,			/* bitsize */
    145 	 FALSE,			/* pc_relative */
    146 	 0,			/* bitpos */
    147 	 complain_overflow_dont /*bitfield */ ,	/* complain_on_overflow */
    148 	 bfd_elf_generic_reloc,	/* special_function */
    149 	 "R_M68HC11_16",	/* name */
    150 	 FALSE,			/* partial_inplace */
    151 	 0xffff,		/* src_mask */
    152 	 0xffff,		/* dst_mask */
    153 	 FALSE),		/* pcrel_offset */
    154 
    155   /* A 32 bit absolute relocation.  This one is never used for the
    156      code relocation.  It's used by gas for -gstabs generation.  */
    157   HOWTO (R_M68HC11_32,		/* type */
    158 	 0,			/* rightshift */
    159 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    160 	 32,			/* bitsize */
    161 	 FALSE,			/* pc_relative */
    162 	 0,			/* bitpos */
    163 	 complain_overflow_bitfield,	/* complain_on_overflow */
    164 	 bfd_elf_generic_reloc,	/* special_function */
    165 	 "R_M68HC11_32",	/* name */
    166 	 FALSE,			/* partial_inplace */
    167 	 0xffffffff,		/* src_mask */
    168 	 0xffffffff,		/* dst_mask */
    169 	 FALSE),		/* pcrel_offset */
    170 
    171   /* A 3 bit absolute relocation */
    172   HOWTO (R_M68HC11_3B,		/* type */
    173 	 0,			/* rightshift */
    174 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
    175 	 3,			/* bitsize */
    176 	 FALSE,			/* pc_relative */
    177 	 0,			/* bitpos */
    178 	 complain_overflow_bitfield,	/* complain_on_overflow */
    179 	 bfd_elf_generic_reloc,	/* special_function */
    180 	 "R_M68HC11_4B",	/* name */
    181 	 FALSE,			/* partial_inplace */
    182 	 0x003,			/* src_mask */
    183 	 0x003,			/* dst_mask */
    184 	 FALSE),		/* pcrel_offset */
    185 
    186   /* A 16 bit PC-rel relocation */
    187   HOWTO (R_M68HC11_PCREL_16,	/* type */
    188 	 0,			/* rightshift */
    189 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    190 	 16,			/* bitsize */
    191 	 TRUE,			/* pc_relative */
    192 	 0,			/* bitpos */
    193 	 complain_overflow_dont,	/* complain_on_overflow */
    194 	 bfd_elf_generic_reloc,	/* special_function */
    195 	 "R_M68HC11_PCREL_16",	/* name */
    196 	 FALSE,			/* partial_inplace */
    197 	 0xffff,		/* src_mask */
    198 	 0xffff,		/* dst_mask */
    199 	 TRUE),			/* pcrel_offset */
    200 
    201   /* GNU extension to record C++ vtable hierarchy */
    202   HOWTO (R_M68HC11_GNU_VTINHERIT,	/* type */
    203 	 0,			/* rightshift */
    204 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    205 	 0,			/* bitsize */
    206 	 FALSE,			/* pc_relative */
    207 	 0,			/* bitpos */
    208 	 complain_overflow_dont,	/* complain_on_overflow */
    209 	 NULL,			/* special_function */
    210 	 "R_M68HC11_GNU_VTINHERIT",	/* name */
    211 	 FALSE,			/* partial_inplace */
    212 	 0,			/* src_mask */
    213 	 0,			/* dst_mask */
    214 	 FALSE),		/* pcrel_offset */
    215 
    216   /* GNU extension to record C++ vtable member usage */
    217   HOWTO (R_M68HC11_GNU_VTENTRY,	/* type */
    218 	 0,			/* rightshift */
    219 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    220 	 0,			/* bitsize */
    221 	 FALSE,			/* pc_relative */
    222 	 0,			/* bitpos */
    223 	 complain_overflow_dont,	/* complain_on_overflow */
    224 	 _bfd_elf_rel_vtable_reloc_fn,	/* special_function */
    225 	 "R_M68HC11_GNU_VTENTRY",	/* name */
    226 	 FALSE,			/* partial_inplace */
    227 	 0,			/* src_mask */
    228 	 0,			/* dst_mask */
    229 	 FALSE),		/* pcrel_offset */
    230 
    231   /* A 24 bit relocation */
    232   HOWTO (R_M68HC11_24,		/* type */
    233 	 0,			/* rightshift */
    234 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    235 	 24,			/* bitsize */
    236 	 FALSE,			/* pc_relative */
    237 	 0,			/* bitpos */
    238 	 complain_overflow_bitfield,	/* complain_on_overflow */
    239 	 bfd_elf_generic_reloc,	/* special_function */
    240 	 "R_M68HC11_24",	/* name */
    241 	 FALSE,			/* partial_inplace */
    242 	 0xffffff,		/* src_mask */
    243 	 0xffffff,		/* dst_mask */
    244 	 FALSE),		/* pcrel_offset */
    245 
    246   /* A 16-bit low relocation */
    247   HOWTO (R_M68HC11_LO16,	/* type */
    248 	 0,			/* rightshift */
    249 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    250 	 16,			/* bitsize */
    251 	 FALSE,			/* pc_relative */
    252 	 0,			/* bitpos */
    253 	 complain_overflow_bitfield,	/* complain_on_overflow */
    254 	 bfd_elf_generic_reloc,	/* special_function */
    255 	 "R_M68HC11_LO16",	/* name */
    256 	 FALSE,			/* partial_inplace */
    257 	 0xffff,		/* src_mask */
    258 	 0xffff,		/* dst_mask */
    259 	 FALSE),		/* pcrel_offset */
    260 
    261   /* A page relocation */
    262   HOWTO (R_M68HC11_PAGE,	/* type */
    263 	 0,			/* rightshift */
    264 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
    265 	 8,			/* bitsize */
    266 	 FALSE,			/* pc_relative */
    267 	 0,			/* bitpos */
    268 	 complain_overflow_bitfield,	/* complain_on_overflow */
    269 	 bfd_elf_generic_reloc,	/* special_function */
    270 	 "R_M68HC11_PAGE",	/* name */
    271 	 FALSE,			/* partial_inplace */
    272 	 0x00ff,		/* src_mask */
    273 	 0x00ff,		/* dst_mask */
    274 	 FALSE),		/* pcrel_offset */
    275 
    276   EMPTY_HOWTO (14),
    277   EMPTY_HOWTO (15),
    278   EMPTY_HOWTO (16),
    279   EMPTY_HOWTO (17),
    280   EMPTY_HOWTO (18),
    281   EMPTY_HOWTO (19),
    282 
    283   /* Mark beginning of a jump instruction (any form).  */
    284   HOWTO (R_M68HC11_RL_JUMP,	/* type */
    285 	 0,			/* rightshift */
    286 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    287 	 0,			/* bitsize */
    288 	 FALSE,			/* pc_relative */
    289 	 0,			/* bitpos */
    290 	 complain_overflow_dont,	/* complain_on_overflow */
    291 	 m68hc11_elf_ignore_reloc,	/* special_function */
    292 	 "R_M68HC11_RL_JUMP",	/* name */
    293 	 TRUE,			/* partial_inplace */
    294 	 0,			/* src_mask */
    295 	 0,			/* dst_mask */
    296 	 TRUE),			/* pcrel_offset */
    297 
    298   /* Mark beginning of Gcc relaxation group instruction.  */
    299   HOWTO (R_M68HC11_RL_GROUP,	/* type */
    300 	 0,			/* rightshift */
    301 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    302 	 0,			/* bitsize */
    303 	 FALSE,			/* pc_relative */
    304 	 0,			/* bitpos */
    305 	 complain_overflow_dont,	/* complain_on_overflow */
    306 	 m68hc11_elf_ignore_reloc,	/* special_function */
    307 	 "R_M68HC11_RL_GROUP",	/* name */
    308 	 TRUE,			/* partial_inplace */
    309 	 0,			/* src_mask */
    310 	 0,			/* dst_mask */
    311 	 TRUE),			/* pcrel_offset */
    312 };
    313 
    314 /* Map BFD reloc types to M68HC11 ELF reloc types.  */
    315 
    316 struct m68hc11_reloc_map
    317 {
    318   bfd_reloc_code_real_type bfd_reloc_val;
    319   unsigned char elf_reloc_val;
    320 };
    321 
    322 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
    323   {BFD_RELOC_NONE, R_M68HC11_NONE,},
    324   {BFD_RELOC_8, R_M68HC11_8},
    325   {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
    326   {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
    327   {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
    328   {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
    329   {BFD_RELOC_16, R_M68HC11_16},
    330   {BFD_RELOC_32, R_M68HC11_32},
    331   {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
    332 
    333   {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
    334   {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
    335 
    336   {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
    337   {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
    338   {BFD_RELOC_M68HC11_24, R_M68HC11_24},
    339 
    340   {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
    341   {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
    342 };
    343 
    344 static reloc_howto_type *
    345 bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    346 				 bfd_reloc_code_real_type code)
    347 {
    348   unsigned int i;
    349 
    350   for (i = 0;
    351        i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
    352        i++)
    353     {
    354       if (m68hc11_reloc_map[i].bfd_reloc_val == code)
    355 	return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
    356     }
    357 
    358   return NULL;
    359 }
    360 
    361 static reloc_howto_type *
    362 bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    363 				 const char *r_name)
    364 {
    365   unsigned int i;
    366 
    367   for (i = 0;
    368        i < (sizeof (elf_m68hc11_howto_table)
    369 	    / sizeof (elf_m68hc11_howto_table[0]));
    370        i++)
    371     if (elf_m68hc11_howto_table[i].name != NULL
    372 	&& strcasecmp (elf_m68hc11_howto_table[i].name, r_name) == 0)
    373       return &elf_m68hc11_howto_table[i];
    374 
    375   return NULL;
    376 }
    377 
    378 /* Set the howto pointer for an M68HC11 ELF reloc.  */
    379 
    380 static bfd_boolean
    381 m68hc11_info_to_howto_rel (bfd *abfd,
    382 			   arelent *cache_ptr, Elf_Internal_Rela *dst)
    383 {
    384   unsigned int r_type;
    385 
    386   r_type = ELF32_R_TYPE (dst->r_info);
    387   if (r_type >= (unsigned int) R_M68HC11_max)
    388     {
    389       /* xgettext:c-format */
    390       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
    391 			  abfd, r_type);
    392       bfd_set_error (bfd_error_bad_value);
    393       return FALSE;
    394     }
    395   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
    396   return TRUE;
    397 }
    398 
    399 
    400 /* Far trampoline generation.  */
    402 
    403 /* Build a 68HC11 trampoline stub.  */
    404 static bfd_boolean
    405 m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
    406 {
    407   struct elf32_m68hc11_stub_hash_entry *stub_entry;
    408   struct bfd_link_info *info;
    409   struct m68hc11_elf_link_hash_table *htab;
    410   asection *stub_sec;
    411   bfd *stub_bfd;
    412   bfd_byte *loc;
    413   bfd_vma sym_value, phys_page, phys_addr;
    414 
    415   /* Massage our args to the form they really have.  */
    416   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
    417   info = (struct bfd_link_info *) in_arg;
    418 
    419   /* Fail if the target section could not be assigned to an output
    420      section.  The user should fix his linker script.  */
    421   if (stub_entry->target_section->output_section == NULL
    422       && info->non_contiguous_regions)
    423     info->callbacks->einfo (_("%F%P: Could not assign '%pA' to an output section. "
    424 			      "Retry without --enable-non-contiguous-regions.\n"),
    425 			    stub_entry->target_section);
    426 
    427   htab = m68hc11_elf_hash_table (info);
    428   if (htab == NULL)
    429     return FALSE;
    430 
    431   stub_sec = stub_entry->stub_sec;
    432 
    433   /* Make a note of the offset within the stubs for this entry.  */
    434   stub_entry->stub_offset = stub_sec->size;
    435   stub_sec->size += 10;
    436   loc = stub_sec->contents + stub_entry->stub_offset;
    437 
    438   stub_bfd = stub_sec->owner;
    439 
    440   /* Create the trampoline call stub:
    441 
    442      pshb
    443      ldab #%page(symbol)
    444      ldy #%addr(symbol)
    445      jmp __trampoline
    446 
    447   */
    448   sym_value = (stub_entry->target_value
    449 	       + stub_entry->target_section->output_offset
    450 	       + stub_entry->target_section->output_section->vma);
    451   phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
    452   phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
    453 
    454   /* pshb; ldab #%page(sym) */
    455   bfd_put_8 (stub_bfd, 0x37, loc);
    456   bfd_put_8 (stub_bfd, 0xC6, loc + 1);
    457   bfd_put_8 (stub_bfd, phys_page, loc + 2);
    458   loc += 3;
    459 
    460   /* ldy #%addr(sym)  */
    461   bfd_put_8 (stub_bfd, 0x18, loc);
    462   bfd_put_8 (stub_bfd, 0xCE, loc + 1);
    463   bfd_put_16 (stub_bfd, phys_addr, loc + 2);
    464   loc += 4;
    465 
    466   /* jmp __trampoline  */
    467   bfd_put_8 (stub_bfd, 0x7E, loc);
    468   bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
    469 
    470   return TRUE;
    471 }
    472 
    473 /* As above, but don't actually build the stub.  Just bump offset so
    474    we know stub section sizes.  */
    475 
    476 static bfd_boolean
    477 m68hc11_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
    478 			   void *in_arg ATTRIBUTE_UNUSED)
    479 {
    480   struct elf32_m68hc11_stub_hash_entry *stub_entry;
    481 
    482   /* Massage our args to the form they really have.  */
    483   stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
    484 
    485   stub_entry->stub_sec->size += 10;
    486   return TRUE;
    487 }
    488 
    489 /* Create a 68HC11 ELF linker hash table.  */
    490 
    491 static struct bfd_link_hash_table *
    492 m68hc11_elf_bfd_link_hash_table_create (bfd *abfd)
    493 {
    494   struct m68hc11_elf_link_hash_table *ret;
    495 
    496   ret = m68hc11_elf_hash_table_create (abfd);
    497   if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
    498     return NULL;
    499 
    500   ret->size_one_stub = m68hc11_elf_size_one_stub;
    501   ret->build_one_stub = m68hc11_elf_build_one_stub;
    502 
    503   return &ret->root.root;
    504 }
    505 
    506 
    507 /* 68HC11 Linker Relaxation.  */
    509 
    510 struct m68hc11_direct_relax
    511 {
    512   const char *name;
    513   unsigned char code;
    514   unsigned char direct_code;
    515 } m68hc11_direct_relax_table[] = {
    516   { "adca", 0xB9, 0x99 },
    517   { "adcb", 0xF9, 0xD9 },
    518   { "adda", 0xBB, 0x9B },
    519   { "addb", 0xFB, 0xDB },
    520   { "addd", 0xF3, 0xD3 },
    521   { "anda", 0xB4, 0x94 },
    522   { "andb", 0xF4, 0xD4 },
    523   { "cmpa", 0xB1, 0x91 },
    524   { "cmpb", 0xF1, 0xD1 },
    525   { "cpd",  0xB3, 0x93 },
    526   { "cpxy", 0xBC, 0x9C },
    527 /* { "cpy",  0xBC, 0x9C }, */
    528   { "eora", 0xB8, 0x98 },
    529   { "eorb", 0xF8, 0xD8 },
    530   { "jsr",  0xBD, 0x9D },
    531   { "ldaa", 0xB6, 0x96 },
    532   { "ldab", 0xF6, 0xD6 },
    533   { "ldd",  0xFC, 0xDC },
    534   { "lds",  0xBE, 0x9E },
    535   { "ldxy", 0xFE, 0xDE },
    536   /*  { "ldy",  0xFE, 0xDE },*/
    537   { "oraa", 0xBA, 0x9A },
    538   { "orab", 0xFA, 0xDA },
    539   { "sbca", 0xB2, 0x92 },
    540   { "sbcb", 0xF2, 0xD2 },
    541   { "staa", 0xB7, 0x97 },
    542   { "stab", 0xF7, 0xD7 },
    543   { "std",  0xFD, 0xDD },
    544   { "sts",  0xBF, 0x9F },
    545   { "stxy", 0xFF, 0xDF },
    546   /*  { "sty",  0xFF, 0xDF },*/
    547   { "suba", 0xB0, 0x90 },
    548   { "subb", 0xF0, 0xD0 },
    549   { "subd", 0xB3, 0x93 },
    550   { 0, 0, 0 }
    551 };
    552 
    553 static struct m68hc11_direct_relax *
    554 find_relaxable_insn (unsigned char code)
    555 {
    556   int i;
    557 
    558   for (i = 0; m68hc11_direct_relax_table[i].name; i++)
    559     if (m68hc11_direct_relax_table[i].code == code)
    560       return &m68hc11_direct_relax_table[i];
    561 
    562   return 0;
    563 }
    564 
    565 static int
    566 compare_reloc (const void *e1, const void *e2)
    567 {
    568   const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
    569   const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;
    570 
    571   if (i1->r_offset == i2->r_offset)
    572     return 0;
    573   else
    574     return i1->r_offset < i2->r_offset ? -1 : 1;
    575 }
    576 
    577 #define M6811_OP_LDX_IMMEDIATE (0xCE)
    578 
    579 static void
    580 m68hc11_relax_group (bfd *abfd, asection *sec, bfd_byte *contents,
    581 		     unsigned value, unsigned long offset,
    582 		     unsigned long end_group)
    583 {
    584   unsigned char code;
    585   unsigned long start_offset;
    586   unsigned long ldx_offset = offset;
    587   unsigned long ldx_size;
    588   int can_delete_ldx;
    589   int relax_ldy = 0;
    590 
    591   /* First instruction of the relax group must be a
    592      LDX #value or LDY #value.  If this is not the case,
    593      ignore the relax group.  */
    594   code = bfd_get_8 (abfd, contents + offset);
    595   if (code == 0x18)
    596     {
    597       relax_ldy++;
    598       offset++;
    599       code = bfd_get_8 (abfd, contents + offset);
    600     }
    601   ldx_size = offset - ldx_offset + 3;
    602   offset += 3;
    603   if (code != M6811_OP_LDX_IMMEDIATE || offset >= end_group)
    604     return;
    605 
    606 
    607   /* We can remove the LDX/LDY only when all bset/brclr instructions
    608      of the relax group have been converted to use direct addressing
    609      mode.  */
    610   can_delete_ldx = 1;
    611   while (offset < end_group)
    612     {
    613       unsigned isize;
    614       unsigned new_value;
    615       int bset_use_y;
    616 
    617       bset_use_y = 0;
    618       start_offset = offset;
    619       code = bfd_get_8 (abfd, contents + offset);
    620       if (code == 0x18)
    621 	{
    622 	  bset_use_y++;
    623 	  offset++;
    624 	  code = bfd_get_8 (abfd, contents + offset);
    625 	}
    626 
    627       /* Check the instruction and translate to use direct addressing mode.  */
    628       switch (code)
    629 	{
    630 	  /* bset */
    631 	case 0x1C:
    632 	  code = 0x14;
    633 	  isize = 3;
    634 	  break;
    635 
    636 	  /* brclr */
    637 	case 0x1F:
    638 	  code = 0x13;
    639 	  isize = 4;
    640 	  break;
    641 
    642 	  /* brset */
    643 	case 0x1E:
    644 	  code = 0x12;
    645 	  isize = 4;
    646 	  break;
    647 
    648 	  /* bclr */
    649 	case 0x1D:
    650 	  code = 0x15;
    651 	  isize = 3;
    652 	  break;
    653 
    654 	  /* This instruction is not recognized and we are not
    655 	     at end of the relax group.  Ignore and don't remove
    656 	     the first LDX (we don't know what it is used for...).  */
    657 	default:
    658 	  return;
    659 	}
    660       new_value = (unsigned) bfd_get_8 (abfd, contents + offset + 1);
    661       new_value += value;
    662       if ((new_value & 0xff00) == 0 && bset_use_y == relax_ldy)
    663 	{
    664 	  bfd_put_8 (abfd, code, contents + offset);
    665 	  bfd_put_8 (abfd, new_value, contents + offset + 1);
    666 	  if (start_offset != offset)
    667 	    {
    668 	      m68hc11_elf_relax_delete_bytes (abfd, sec, start_offset,
    669 					      offset - start_offset);
    670 	      end_group--;
    671 	    }
    672 	}
    673       else
    674 	{
    675 	  can_delete_ldx = 0;
    676 	}
    677       offset = start_offset + isize;
    678     }
    679   if (can_delete_ldx)
    680     {
    681       /* Remove the move instruction (3 or 4 bytes win).  */
    682       m68hc11_elf_relax_delete_bytes (abfd, sec, ldx_offset, ldx_size);
    683     }
    684 }
    685 
    686 /* This function handles relaxing for the 68HC11.
    687 
    688 
    689 	and somewhat more difficult to support.  */
    690 
    691 static bfd_boolean
    692 m68hc11_elf_relax_section (bfd *abfd, asection *sec,
    693 			   struct bfd_link_info *link_info, bfd_boolean *again)
    694 {
    695   Elf_Internal_Shdr *symtab_hdr;
    696   Elf_Internal_Rela *internal_relocs;
    697   Elf_Internal_Rela *free_relocs = NULL;
    698   Elf_Internal_Rela *irel, *irelend;
    699   bfd_byte *contents = NULL;
    700   bfd_byte *free_contents = NULL;
    701   Elf32_External_Sym *free_extsyms = NULL;
    702   Elf_Internal_Rela *prev_insn_branch = NULL;
    703   Elf_Internal_Rela *prev_insn_group = NULL;
    704   unsigned insn_group_value = 0;
    705   Elf_Internal_Sym *isymbuf = NULL;
    706 
    707   /* Assume nothing changes.  */
    708   *again = FALSE;
    709 
    710   /* We don't have to do anything for a relocatable link, if
    711      this section does not have relocs, or if this is not a
    712      code section.  */
    713   if (bfd_link_relocatable (link_info)
    714       || (sec->flags & SEC_RELOC) == 0
    715       || sec->reloc_count == 0
    716       || (sec->flags & SEC_CODE) == 0)
    717     return TRUE;
    718 
    719   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
    720 
    721   /* Get a copy of the native relocations.  */
    722   internal_relocs = (_bfd_elf_link_read_relocs
    723 		     (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
    724 		      link_info->keep_memory));
    725   if (internal_relocs == NULL)
    726     goto error_return;
    727   if (! link_info->keep_memory)
    728     free_relocs = internal_relocs;
    729 
    730   /* Checking for branch relaxation relies on the relocations to
    731      be sorted on 'r_offset'.  This is not guaranteed so we must sort.  */
    732   qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
    733 	 compare_reloc);
    734 
    735   /* Walk through them looking for relaxing opportunities.  */
    736   irelend = internal_relocs + sec->reloc_count;
    737   for (irel = internal_relocs; irel < irelend; irel++)
    738     {
    739       bfd_vma symval;
    740       bfd_vma value;
    741       Elf_Internal_Sym *isym;
    742       asection *sym_sec;
    743       int is_far = 0;
    744 
    745       /* If this isn't something that can be relaxed, then ignore
    746 	 this reloc.  */
    747       if (ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_16
    748 	  && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_JUMP
    749 	  && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_GROUP)
    750 	{
    751 	  prev_insn_branch = 0;
    752 	  prev_insn_group = 0;
    753 	  continue;
    754 	}
    755 
    756       /* Get the section contents if we haven't done so already.  */
    757       if (contents == NULL)
    758 	{
    759 	  /* Get cached copy if it exists.  */
    760 	  if (elf_section_data (sec)->this_hdr.contents != NULL)
    761 	    contents = elf_section_data (sec)->this_hdr.contents;
    762 	  else
    763 	    {
    764 	      /* Go get them off disk.  */
    765 	      if (!bfd_malloc_and_get_section (abfd, sec, &contents))
    766 		goto error_return;
    767 	    }
    768 	}
    769 
    770       /* Try to eliminate an unconditional 8 bit pc-relative branch
    771 	 which immediately follows a conditional 8 bit pc-relative
    772 	 branch around the unconditional branch.
    773 
    774 	    original:		new:
    775 	    bCC lab1		bCC' lab2
    776 	    bra lab2
    777 	   lab1:	       lab1:
    778 
    779 	 This happens when the bCC can't reach lab2 at assembly time,
    780 	 but due to other relaxations it can reach at link time.  */
    781       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_JUMP)
    782 	{
    783 	  Elf_Internal_Rela *nrel;
    784 	  unsigned char code;
    785 	  unsigned char roffset;
    786 
    787 	  prev_insn_branch = 0;
    788 	  prev_insn_group = 0;
    789 
    790 	  /* Do nothing if this reloc is the last byte in the section.  */
    791 	  if (irel->r_offset + 2 >= sec->size)
    792 	    continue;
    793 
    794 	  /* See if the next instruction is an unconditional pc-relative
    795 	     branch, more often than not this test will fail, so we
    796 	     test it first to speed things up.  */
    797 	  code = bfd_get_8 (abfd, contents + irel->r_offset + 2);
    798 	  if (code != 0x7e)
    799 	    continue;
    800 
    801 	  /* Also make sure the next relocation applies to the next
    802 	     instruction and that it's a pc-relative 8 bit branch.  */
    803 	  nrel = irel + 1;
    804 	  if (nrel == irelend
    805 	      || irel->r_offset + 3 != nrel->r_offset
    806 	      || ELF32_R_TYPE (nrel->r_info) != (int) R_M68HC11_16)
    807 	    continue;
    808 
    809 	  /* Make sure our destination immediately follows the
    810 	     unconditional branch.  */
    811 	  roffset = bfd_get_8 (abfd, contents + irel->r_offset + 1);
    812 	  if (roffset != 3)
    813 	    continue;
    814 
    815 	  prev_insn_branch = irel;
    816 	  prev_insn_group = 0;
    817 	  continue;
    818 	}
    819 
    820       /* Read this BFD's symbols if we haven't done so already.  */
    821       if (isymbuf == NULL && symtab_hdr->sh_info != 0)
    822 	{
    823 	  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
    824 	  if (isymbuf == NULL)
    825 	    isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
    826 					    symtab_hdr->sh_info, 0,
    827 					    NULL, NULL, NULL);
    828 	  if (isymbuf == NULL)
    829 	    goto error_return;
    830 	}
    831 
    832       /* Get the value of the symbol referred to by the reloc.  */
    833       if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
    834 	{
    835 	  /* A local symbol.  */
    836 	  isym = isymbuf + ELF32_R_SYM (irel->r_info);
    837 	  is_far = isym->st_other & STO_M68HC12_FAR;
    838 	  sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
    839 	  symval = (isym->st_value
    840 		    + sym_sec->output_section->vma
    841 		    + sym_sec->output_offset);
    842 	}
    843       else
    844 	{
    845 	  unsigned long indx;
    846 	  struct elf_link_hash_entry *h;
    847 
    848 	  /* An external symbol.  */
    849 	  indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
    850 	  h = elf_sym_hashes (abfd)[indx];
    851 	  BFD_ASSERT (h != NULL);
    852 	  if (h->root.type != bfd_link_hash_defined
    853 	      && h->root.type != bfd_link_hash_defweak)
    854 	    {
    855 	      /* This appears to be a reference to an undefined
    856 		 symbol.  Just ignore it--it will be caught by the
    857 		 regular reloc processing.  */
    858 	      prev_insn_branch = 0;
    859 	      prev_insn_group = 0;
    860 	      continue;
    861 	    }
    862 
    863 	  is_far = h->other & STO_M68HC12_FAR;
    864 	  isym = 0;
    865 	  sym_sec = h->root.u.def.section;
    866 	  symval = (h->root.u.def.value
    867 		    + sym_sec->output_section->vma
    868 		    + sym_sec->output_offset);
    869 	}
    870 
    871       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
    872 	{
    873 	  prev_insn_branch = 0;
    874 	  prev_insn_group = 0;
    875 
    876 	  /* Do nothing if this reloc is the last byte in the section.  */
    877 	  if (irel->r_offset == sec->size)
    878 	    continue;
    879 
    880 	  prev_insn_group = irel;
    881 	  insn_group_value = isym->st_value;
    882 	  continue;
    883 	}
    884 
    885       /* When we relax some bytes, the size of our section changes.
    886 	 This affects the layout of next input sections that go in our
    887 	 output section.  When the symbol is part of another section that
    888 	 will go in the same output section as the current one, it's
    889 	 final address may now be incorrect (too far).  We must let the
    890 	 linker re-compute all section offsets before processing this
    891 	 reloc.  Code example:
    892 
    893 				Initial		    Final
    894 	 .sect .text		section size = 6    section size = 4
    895 	 jmp foo
    896 	 jmp bar
    897 	 .sect .text.foo_bar	output_offset = 6   output_offset = 4
    898 	 foo: rts
    899 	 bar: rts
    900 
    901 	 If we process the reloc now, the jmp bar is replaced by a
    902 	 relative branch to the initial bar address (output_offset 6).  */
    903       if (*again && sym_sec != sec
    904 	  && sym_sec->output_section == sec->output_section)
    905 	{
    906 	  prev_insn_group = 0;
    907 	  prev_insn_branch = 0;
    908 	  continue;
    909 	}
    910 
    911       value = symval;
    912       /* Try to turn a far branch to a near branch.  */
    913       if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
    914 	  && prev_insn_branch)
    915 	{
    916 	  bfd_vma offset;
    917 	  unsigned char code;
    918 
    919 	  offset = value - (prev_insn_branch->r_offset
    920 			    + sec->output_section->vma
    921 			    + sec->output_offset + 2);
    922 
    923 	  /* If the offset is still out of -128..+127 range,
    924 	     leave that far branch unchanged.  */
    925 	  if ((offset & 0xff80) != 0 && (offset & 0xff80) != 0xff80)
    926 	    {
    927 	      prev_insn_branch = 0;
    928 	      continue;
    929 	    }
    930 
    931 	  /* Shrink the branch.  */
    932 	  code = bfd_get_8 (abfd, contents + prev_insn_branch->r_offset);
    933 	  if (code == 0x7e)
    934 	    {
    935 	      code = 0x20;
    936 	      bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
    937 	      bfd_put_8 (abfd, 0xff,
    938 			 contents + prev_insn_branch->r_offset + 1);
    939 	      irel->r_offset = prev_insn_branch->r_offset + 1;
    940 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
    941 					   R_M68HC11_PCREL_8);
    942 	      m68hc11_elf_relax_delete_bytes (abfd, sec,
    943 					      irel->r_offset + 1, 1);
    944 	    }
    945 	  else
    946 	    {
    947 	      code ^= 0x1;
    948 	      bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
    949 	      bfd_put_8 (abfd, 0xff,
    950 			 contents + prev_insn_branch->r_offset + 1);
    951 	      irel->r_offset = prev_insn_branch->r_offset + 1;
    952 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
    953 					   R_M68HC11_PCREL_8);
    954 	      m68hc11_elf_relax_delete_bytes (abfd, sec,
    955 					      irel->r_offset + 1, 3);
    956 	    }
    957 	  prev_insn_branch = 0;
    958 	  *again = TRUE;
    959 	}
    960 
    961       /* Try to turn a 16 bit address into a 8 bit page0 address.  */
    962       else if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
    963 	       && (value & 0xff00) == 0)
    964 	{
    965 	  unsigned char code;
    966 	  unsigned short offset;
    967 	  struct m68hc11_direct_relax *rinfo;
    968 
    969 	  prev_insn_branch = 0;
    970 	  offset = bfd_get_16 (abfd, contents + irel->r_offset);
    971 	  offset += value;
    972 	  if ((offset & 0xff00) != 0)
    973 	    {
    974 	      prev_insn_group = 0;
    975 	      continue;
    976 	    }
    977 
    978 	  if (prev_insn_group)
    979 	    {
    980 	      unsigned long old_sec_size = sec->size;
    981 
    982 	      /* Note that we've changed the relocation contents, etc.  */
    983 	      elf_section_data (sec)->relocs = internal_relocs;
    984 	      free_relocs = NULL;
    985 
    986 	      elf_section_data (sec)->this_hdr.contents = contents;
    987 	      free_contents = NULL;
    988 
    989 	      symtab_hdr->contents = (bfd_byte *) isymbuf;
    990 	      free_extsyms = NULL;
    991 
    992 	      m68hc11_relax_group (abfd, sec, contents, offset,
    993 				   prev_insn_group->r_offset,
    994 				   insn_group_value);
    995 	      irel = prev_insn_group;
    996 	      prev_insn_group = 0;
    997 	      irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
    998 					   R_M68HC11_NONE);
    999 	      if (sec->size != old_sec_size)
   1000 		*again = TRUE;
   1001 	      continue;
   1002 	    }
   1003 
   1004 	  /* Get the opcode.  */
   1005 	  code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
   1006 	  rinfo = find_relaxable_insn (code);
   1007 	  if (rinfo == 0)
   1008 	    {
   1009 	      prev_insn_group = 0;
   1010 	      continue;
   1011 	    }
   1012 
   1013 	  /* Note that we've changed the relocation contents, etc.  */
   1014 	  elf_section_data (sec)->relocs = internal_relocs;
   1015 	  free_relocs = NULL;
   1016 
   1017 	  elf_section_data (sec)->this_hdr.contents = contents;
   1018 	  free_contents = NULL;
   1019 
   1020 	  symtab_hdr->contents = (bfd_byte *) isymbuf;
   1021 	  free_extsyms = NULL;
   1022 
   1023 	  /* Fix the opcode.  */
   1024 	  /* printf ("A relaxable case : 0x%02x (%s)\n",
   1025 	     code, rinfo->name); */
   1026 	  bfd_put_8 (abfd, rinfo->direct_code,
   1027 		     contents + irel->r_offset - 1);
   1028 
   1029 	  /* Delete one byte of data (upper byte of address).  */
   1030 	  m68hc11_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 1);
   1031 
   1032 	  /* Fix the relocation's type.  */
   1033 	  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
   1034 				       R_M68HC11_8);
   1035 
   1036 	  /* That will change things, so, we should relax again.  */
   1037 	  *again = TRUE;
   1038 	}
   1039       else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16 && !is_far)
   1040 	{
   1041 	  unsigned char code;
   1042 	  bfd_vma offset;
   1043 
   1044 	  prev_insn_branch = 0;
   1045 	  code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
   1046 	  if (code == 0x7e || code == 0xbd)
   1047 	    {
   1048 	      offset = value - (irel->r_offset
   1049 				+ sec->output_section->vma
   1050 				+ sec->output_offset + 1);
   1051 	      offset += bfd_get_16 (abfd, contents + irel->r_offset);
   1052 
   1053 	      /* If the offset is still out of -128..+127 range,
   1054 		 leave that far branch unchanged.  */
   1055 	      if ((offset & 0xff80) == 0 || (offset & 0xff80) == 0xff80)
   1056 		{
   1057 
   1058 		  /* Note that we've changed the relocation contents, etc.  */
   1059 		  elf_section_data (sec)->relocs = internal_relocs;
   1060 		  free_relocs = NULL;
   1061 
   1062 		  elf_section_data (sec)->this_hdr.contents = contents;
   1063 		  free_contents = NULL;
   1064 
   1065 		  symtab_hdr->contents = (bfd_byte *) isymbuf;
   1066 		  free_extsyms = NULL;
   1067 
   1068 		  /* Shrink the branch.  */
   1069 		  code = (code == 0x7e) ? 0x20 : 0x8d;
   1070 		  bfd_put_8 (abfd, code,
   1071 			     contents + irel->r_offset - 1);
   1072 		  bfd_put_8 (abfd, 0xff,
   1073 			     contents + irel->r_offset);
   1074 		  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
   1075 					       R_M68HC11_PCREL_8);
   1076 		  m68hc11_elf_relax_delete_bytes (abfd, sec,
   1077 						  irel->r_offset + 1, 1);
   1078 		  /* That will change things, so, we should relax again.  */
   1079 		  *again = TRUE;
   1080 		}
   1081 	    }
   1082 	}
   1083       prev_insn_branch = 0;
   1084       prev_insn_group = 0;
   1085     }
   1086 
   1087   free (free_relocs);
   1088   free_relocs = NULL;
   1089 
   1090   if (free_contents != NULL)
   1091     {
   1092       if (! link_info->keep_memory)
   1093 	free (free_contents);
   1094       else
   1095 	{
   1096 	  /* Cache the section contents for elf_link_input_bfd.  */
   1097 	  elf_section_data (sec)->this_hdr.contents = contents;
   1098 	}
   1099       free_contents = NULL;
   1100     }
   1101 
   1102   if (free_extsyms != NULL)
   1103     {
   1104       if (! link_info->keep_memory)
   1105 	free (free_extsyms);
   1106       else
   1107 	{
   1108 	  /* Cache the symbols for elf_link_input_bfd.  */
   1109 	  symtab_hdr->contents = (unsigned char *) isymbuf;
   1110 	}
   1111       free_extsyms = NULL;
   1112     }
   1113 
   1114   return TRUE;
   1115 
   1116  error_return:
   1117   free (free_relocs);
   1118   free (free_contents);
   1119   free (free_extsyms);
   1120   return FALSE;
   1121 }
   1122 
   1123 /* Delete some bytes from a section while relaxing.  */
   1124 
   1125 static void
   1126 m68hc11_elf_relax_delete_bytes (bfd *abfd, asection *sec,
   1127 				bfd_vma addr, int count)
   1128 {
   1129   Elf_Internal_Shdr *symtab_hdr;
   1130   unsigned int sec_shndx;
   1131   bfd_byte *contents;
   1132   Elf_Internal_Rela *irel, *irelend;
   1133   bfd_vma toaddr;
   1134   Elf_Internal_Sym *isymbuf, *isym, *isymend;
   1135   struct elf_link_hash_entry **sym_hashes;
   1136   struct elf_link_hash_entry **end_hashes;
   1137   unsigned int symcount;
   1138 
   1139   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   1140   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   1141 
   1142   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
   1143 
   1144   contents = elf_section_data (sec)->this_hdr.contents;
   1145 
   1146   toaddr = sec->size;
   1147 
   1148   irel = elf_section_data (sec)->relocs;
   1149   irelend = irel + sec->reloc_count;
   1150 
   1151   /* Actually delete the bytes.  */
   1152   memmove (contents + addr, contents + addr + count,
   1153 	   (size_t) (toaddr - addr - count));
   1154 
   1155   sec->size -= count;
   1156 
   1157   /* Adjust all the relocs.  */
   1158   for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
   1159     {
   1160       unsigned char code;
   1161       unsigned char offset;
   1162       unsigned short raddr;
   1163       unsigned long old_offset;
   1164       int branch_pos;
   1165 
   1166       old_offset = irel->r_offset;
   1167 
   1168       /* See if this reloc was for the bytes we have deleted, in which
   1169 	 case we no longer care about it.  Don't delete relocs which
   1170 	 represent addresses, though.  */
   1171       if (ELF32_R_TYPE (irel->r_info) != R_M68HC11_RL_JUMP
   1172 	  && irel->r_offset >= addr && irel->r_offset < addr + count)
   1173 	irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
   1174 				     R_M68HC11_NONE);
   1175 
   1176       if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_NONE)
   1177 	continue;
   1178 
   1179       /* Get the new reloc address.  */
   1180       if ((irel->r_offset > addr
   1181 	   && irel->r_offset < toaddr))
   1182 	irel->r_offset -= count;
   1183 
   1184       /* If this is a PC relative reloc, see if the range it covers
   1185 	 includes the bytes we have deleted.  */
   1186       switch (ELF32_R_TYPE (irel->r_info))
   1187 	{
   1188 	default:
   1189 	  break;
   1190 
   1191 	case R_M68HC11_RL_JUMP:
   1192 	  code = bfd_get_8 (abfd, contents + irel->r_offset);
   1193 	  switch (code)
   1194 	    {
   1195 	      /* jsr and jmp instruction are also marked with RL_JUMP
   1196 		 relocs but no adjustment must be made.  */
   1197 	    case 0x7e:
   1198 	    case 0x9d:
   1199 	    case 0xbd:
   1200 	      continue;
   1201 
   1202 	    case 0x12:
   1203 	    case 0x13:
   1204 	      branch_pos = 3;
   1205 	      raddr = 4;
   1206 
   1207 	      /* Special case when we translate a brclr N,y into brclr *<addr>
   1208 		 In this case, the 0x18 page2 prefix is removed.
   1209 		 The reloc offset is not modified but the instruction
   1210 		 size is reduced by 1.  */
   1211 	      if (old_offset == addr)
   1212 		raddr++;
   1213 	      break;
   1214 
   1215 	    case 0x1e:
   1216 	    case 0x1f:
   1217 	      branch_pos = 3;
   1218 	      raddr = 4;
   1219 	      break;
   1220 
   1221 	    case 0x18:
   1222 	      branch_pos = 4;
   1223 	      raddr = 5;
   1224 	      break;
   1225 
   1226 	    default:
   1227 	      branch_pos = 1;
   1228 	      raddr = 2;
   1229 	      break;
   1230 	    }
   1231 	  offset = bfd_get_8 (abfd, contents + irel->r_offset + branch_pos);
   1232 	  raddr += old_offset;
   1233 	  raddr += ((unsigned short) offset | ((offset & 0x80) ? 0xff00 : 0));
   1234 	  if (irel->r_offset < addr && raddr > addr)
   1235 	    {
   1236 	      offset -= count;
   1237 	      bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
   1238 	    }
   1239 	  else if (irel->r_offset >= addr && raddr <= addr)
   1240 	    {
   1241 	      offset += count;
   1242 	      bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
   1243 	    }
   1244 	  else
   1245 	    {
   1246 	      /*printf ("Not adjusted 0x%04x [0x%4x 0x%4x]\n", raddr,
   1247 		irel->r_offset, addr);*/
   1248 	    }
   1249 
   1250 	  break;
   1251 	}
   1252     }
   1253 
   1254   /* Adjust the local symbols defined in this section.  */
   1255   isymend = isymbuf + symtab_hdr->sh_info;
   1256   for (isym = isymbuf; isym < isymend; isym++)
   1257     {
   1258       if (isym->st_shndx == sec_shndx
   1259 	  && isym->st_value > addr
   1260 	  && isym->st_value <= toaddr)
   1261 	isym->st_value -= count;
   1262     }
   1263 
   1264   /* Now adjust the global symbols defined in this section.  */
   1265   symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
   1266 	      - symtab_hdr->sh_info);
   1267   sym_hashes = elf_sym_hashes (abfd);
   1268   end_hashes = sym_hashes + symcount;
   1269   for (; sym_hashes < end_hashes; sym_hashes++)
   1270     {
   1271       struct elf_link_hash_entry *sym_hash = *sym_hashes;
   1272       if ((sym_hash->root.type == bfd_link_hash_defined
   1273 	   || sym_hash->root.type == bfd_link_hash_defweak)
   1274 	  && sym_hash->root.u.def.section == sec
   1275 	  && sym_hash->root.u.def.value > addr
   1276 	  && sym_hash->root.u.def.value <= toaddr)
   1277 	{
   1278 	  sym_hash->root.u.def.value -= count;
   1279 	}
   1280     }
   1281 }
   1282 
   1283 /* Specific sections:
   1284    - The .page0 is a data section that is mapped in [0x0000..0x00FF].
   1285      Page0 accesses are faster on the M68HC11. Soft registers used by GCC-m6811
   1286      are located in .page0.
   1287    - The .vectors is the section that represents the interrupt
   1288      vectors.  */
   1289 static const struct bfd_elf_special_section elf32_m68hc11_special_sections[] =
   1290 {
   1291   { STRING_COMMA_LEN (".eeprom"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   1292   { STRING_COMMA_LEN (".page0"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   1293   { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
   1294   { STRING_COMMA_LEN (".vectors"),  0, SHT_PROGBITS, SHF_ALLOC },
   1295   { NULL,			0,  0, 0,	     0 }
   1296 };
   1297 
   1298 #define ELF_ARCH		bfd_arch_m68hc11
   1300 #define ELF_TARGET_ID		M68HC11_ELF_DATA
   1301 #define ELF_MACHINE_CODE	EM_68HC11
   1302 #define ELF_MAXPAGESIZE		0x1000
   1303 
   1304 #define TARGET_BIG_SYM		m68hc11_elf32_vec
   1305 #define TARGET_BIG_NAME		"elf32-m68hc11"
   1306 
   1307 #define elf_info_to_howto	NULL
   1308 #define elf_info_to_howto_rel	m68hc11_info_to_howto_rel
   1309 #define bfd_elf32_bfd_relax_section  m68hc11_elf_relax_section
   1310 #define elf_backend_check_relocs     elf32_m68hc11_check_relocs
   1311 #define elf_backend_relocate_section elf32_m68hc11_relocate_section
   1312 #define elf_backend_add_symbol_hook  elf32_m68hc11_add_symbol_hook
   1313 #define elf_backend_object_p	0
   1314 #define elf_backend_can_gc_sections		1
   1315 #define elf_backend_special_sections  elf32_m68hc11_special_sections
   1316 #define elf_backend_merge_symbol_attribute elf32_m68hc11_merge_symbol_attribute
   1317 
   1318 #define bfd_elf32_bfd_link_hash_table_create \
   1319 				m68hc11_elf_bfd_link_hash_table_create
   1320 #define bfd_elf32_bfd_merge_private_bfd_data \
   1321 					_bfd_m68hc11_elf_merge_private_bfd_data
   1322 #define bfd_elf32_bfd_set_private_flags	_bfd_m68hc11_elf_set_private_flags
   1323 #define bfd_elf32_bfd_print_private_bfd_data \
   1324 					_bfd_m68hc11_elf_print_private_bfd_data
   1325 
   1326 #include "elf32-target.h"
   1327