Ignore:
Timestamp:
Aug 16, 2003, 6:59:22 PM (22 years ago)
Author:
bird
Message:

binutils v2.14 - offical sources.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/GNU/src/binutils/bfd/elf32-m68hc11.c

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r608 r609  
    11/* Motorola 68HC11-specific support for 32-bit ELF
    2    Copyright 1999, 2000 Free Software Foundation, Inc.
    3    Contributed by Stephane Carrez (stcarrez@worldnet.fr)
     2   Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
     3   Contributed by Stephane Carrez (stcarrez@nerim.fr)
    44   (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
    55
     
    2222#include "bfd.h"
    2323#include "sysdep.h"
     24#include "bfdlink.h"
    2425#include "libbfd.h"
    2526#include "elf-bfd.h"
     27#include "elf32-m68hc1x.h"
    2628#include "elf/m68hc11.h"
    27 
     29#include "opcode/m68hc11.h"
     30
     31/* Relocation functions.  */
    2832static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
    29 PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
     33  PARAMS ((bfd *, bfd_reloc_code_real_type));
    3034static void m68hc11_info_to_howto_rel
    31 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
     35  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
     36
     37/* Trampoline generation.  */
     38static bfd_boolean m68hc11_elf_size_one_stub
     39  PARAMS((struct bfd_hash_entry *gen_entry, PTR in_arg));
     40static bfd_boolean m68hc11_elf_build_one_stub
     41  PARAMS((struct bfd_hash_entry *gen_entry, PTR in_arg));
     42static struct bfd_link_hash_table* m68hc11_elf_bfd_link_hash_table_create
     43  PARAMS ((bfd* abfd));
     44
     45/* Linker relaxation.  */
     46static bfd_boolean m68hc11_elf_relax_section
     47  PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
     48static void m68hc11_elf_relax_delete_bytes
     49  PARAMS ((bfd *, asection *, bfd_vma, int));
     50static void m68hc11_relax_group
     51  PARAMS ((bfd *, asection *, bfd_byte *, unsigned,
     52           unsigned long, unsigned long));
     53static int compare_reloc PARAMS ((const void *, const void *));
    3254
    3355/* Use REL instead of RELA to save space */
    34 #define USE_REL
    35 
    36 /* The Motorola 68HC11 microcontroler only addresses 64Kb.
     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.
    3760   We must handle 8 and 16-bit relocations.  The 32-bit relocation
    38    is defined but not used except by gas when -gstabs is used (which
    39    is wrong).
     61   are used for debugging sections (DWARF2) to represent a virtual
     62   address.
    4063   The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
    4164static reloc_howto_type elf_m68hc11_howto_table[] = {
     
    4568         2,                     /* size (0 = byte, 1 = short, 2 = long) */
    4669         32,                    /* bitsize */
    47          false,                 /* pc_relative */
    48          0,                     /* bitpos */
    49          complain_overflow_bitfield,    /* complain_on_overflow */
     70         FALSE,                 /* pc_relative */
     71         0,                     /* bitpos */
     72         complain_overflow_dont,/* complain_on_overflow */
    5073         bfd_elf_generic_reloc, /* special_function */
    5174         "R_M68HC11_NONE",      /* name */
    52          false,                 /* partial_inplace */
     75         FALSE,                 /* partial_inplace */
    5376         0,                     /* src_mask */
    5477         0,                     /* dst_mask */
    55          false),                /* pcrel_offset */
     78         FALSE),                /* pcrel_offset */
    5679
    5780  /* A 8 bit absolute relocation */
     
    6083         0,                     /* size (0 = byte, 1 = short, 2 = long) */
    6184         8,                     /* bitsize */
    62          false,                 /* pc_relative */
     85         FALSE,                 /* pc_relative */
    6386         0,                     /* bitpos */
    6487         complain_overflow_bitfield,    /* complain_on_overflow */
    6588         bfd_elf_generic_reloc, /* special_function */
    6689         "R_M68HC11_8",         /* name */
    67          false,                 /* partial_inplace */
     90         FALSE,                 /* partial_inplace */
    6891         0x00ff,                /* src_mask */
    6992         0x00ff,                /* dst_mask */
    70          false),                /* pcrel_offset */
     93         FALSE),                /* pcrel_offset */
    7194
    7295  /* A 8 bit absolute relocation (upper address) */
     
    7598         0,                     /* size (0 = byte, 1 = short, 2 = long) */
    7699         8,                     /* bitsize */
    77          false,                 /* pc_relative */
     100         FALSE,                 /* pc_relative */
    78101         0,                     /* bitpos */
    79102         complain_overflow_bitfield,    /* complain_on_overflow */
    80103         bfd_elf_generic_reloc, /* special_function */
    81104         "R_M68HC11_HI8",       /* name */
    82          false,                 /* partial_inplace */
     105         FALSE,                 /* partial_inplace */
    83106         0x00ff,                /* src_mask */
    84107         0x00ff,                /* dst_mask */
    85          false),                /* pcrel_offset */
     108         FALSE),                /* pcrel_offset */
    86109
    87110  /* A 8 bit absolute relocation (upper address) */
     
    90113         0,                     /* size (0 = byte, 1 = short, 2 = long) */
    91114         8,                     /* bitsize */
    92          false,                 /* pc_relative */
     115         FALSE,                 /* pc_relative */
    93116         0,                     /* bitpos */
    94117         complain_overflow_dont,        /* complain_on_overflow */
    95118         bfd_elf_generic_reloc, /* special_function */
    96119         "R_M68HC11_LO8",       /* name */
    97          false,                 /* partial_inplace */
     120         FALSE,                 /* partial_inplace */
    98121         0x00ff,                /* src_mask */
    99122         0x00ff,                /* dst_mask */
    100          false),                /* pcrel_offset */
     123         FALSE),                /* pcrel_offset */
    101124
    102125  /* A 8 bit PC-rel relocation */
     
    105128         0,                     /* size (0 = byte, 1 = short, 2 = long) */
    106129         8,                     /* bitsize */
    107          true,                  /* pc_relative */
     130         TRUE,                  /* pc_relative */
    108131         0,                     /* bitpos */
    109132         complain_overflow_bitfield,    /* complain_on_overflow */
    110133         bfd_elf_generic_reloc, /* special_function */
    111134         "R_M68HC11_PCREL_8",   /* name */
    112          false,                 /* partial_inplace */
    113          0x0,                   /* src_mask */
     135         FALSE,                 /* partial_inplace */
     136         0x00ff,                /* src_mask */
    114137         0x00ff,                /* dst_mask */
    115          false),                /* pcrel_offset */
     138         TRUE),                 /* pcrel_offset */
    116139
    117140  /* A 16 bit absolute relocation */
     
    120143         1,                     /* size (0 = byte, 1 = short, 2 = long) */
    121144         16,                    /* bitsize */
    122          false,                 /* pc_relative */
     145         FALSE,                 /* pc_relative */
    123146         0,                     /* bitpos */
    124147         complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
    125148         bfd_elf_generic_reloc, /* special_function */
    126149         "R_M68HC11_16",        /* name */
    127          false,                 /* partial_inplace */
     150         FALSE,                 /* partial_inplace */
    128151         0xffff,                /* src_mask */
    129152         0xffff,                /* dst_mask */
    130          false),                /* pcrel_offset */
     153         FALSE),                /* pcrel_offset */
    131154
    132155  /* A 32 bit absolute relocation.  This one is never used for the
     
    136159         2,                     /* size (0 = byte, 1 = short, 2 = long) */
    137160         32,                    /* bitsize */
    138          false,                 /* pc_relative */
     161         FALSE,                 /* pc_relative */
    139162         0,                     /* bitpos */
    140163         complain_overflow_bitfield,    /* complain_on_overflow */
    141164         bfd_elf_generic_reloc, /* special_function */
    142165         "R_M68HC11_32",        /* name */
    143          false,                 /* partial_inplace */
     166         FALSE,                 /* partial_inplace */
    144167         0xffffffff,            /* src_mask */
    145168         0xffffffff,            /* dst_mask */
    146          false),                /* pcrel_offset */
     169         FALSE),                /* pcrel_offset */
    147170
    148171  /* A 3 bit absolute relocation */
     
    151174         0,                     /* size (0 = byte, 1 = short, 2 = long) */
    152175         3,                     /* bitsize */
    153          false,                 /* pc_relative */
     176         FALSE,                 /* pc_relative */
    154177         0,                     /* bitpos */
    155178         complain_overflow_bitfield,    /* complain_on_overflow */
    156179         bfd_elf_generic_reloc, /* special_function */
    157180         "R_M68HC11_4B",        /* name */
    158          false,                 /* partial_inplace */
     181         FALSE,                 /* partial_inplace */
    159182         0x003,                 /* src_mask */
    160183         0x003,                 /* dst_mask */
    161          false),                /* pcrel_offset */
     184         FALSE),                /* pcrel_offset */
    162185
    163186  /* A 16 bit PC-rel relocation */
     
    166189         1,                     /* size (0 = byte, 1 = short, 2 = long) */
    167190         16,                    /* bitsize */
    168          true,                  /* pc_relative */
     191         TRUE,                  /* pc_relative */
    169192         0,                     /* bitpos */
    170193         complain_overflow_dont,        /* complain_on_overflow */
    171194         bfd_elf_generic_reloc, /* special_function */
    172195         "R_M68HC11_PCREL_16",  /* name */
    173          false,                 /* partial_inplace */
    174          0x0,                   /* src_mask */
     196         FALSE,                 /* partial_inplace */
     197         0xffff,                /* src_mask */
    175198         0xffff,                /* dst_mask */
    176          false),                /* pcrel_offset */
     199         TRUE),                 /* pcrel_offset */
    177200
    178201  /* GNU extension to record C++ vtable hierarchy */
     
    181204         1,                     /* size (0 = byte, 1 = short, 2 = long) */
    182205         0,                     /* bitsize */
    183          false,                 /* pc_relative */
     206         FALSE,                 /* pc_relative */
    184207         0,                     /* bitpos */
    185208         complain_overflow_dont,        /* complain_on_overflow */
    186209         NULL,                  /* special_function */
    187210         "R_M68HC11_GNU_VTINHERIT",     /* name */
    188          false,                 /* partial_inplace */
     211         FALSE,                 /* partial_inplace */
    189212         0,                     /* src_mask */
    190213         0,                     /* dst_mask */
    191          false),                /* pcrel_offset */
     214         FALSE),                /* pcrel_offset */
    192215
    193216  /* GNU extension to record C++ vtable member usage */
     
    196219         1,                     /* size (0 = byte, 1 = short, 2 = long) */
    197220         0,                     /* bitsize */
    198          false,                 /* pc_relative */
     221         FALSE,                 /* pc_relative */
    199222         0,                     /* bitpos */
    200223         complain_overflow_dont,        /* complain_on_overflow */
    201224         _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
    202225         "R_M68HC11_GNU_VTENTRY",       /* name */
    203          false,                 /* partial_inplace */
     226         FALSE,                 /* partial_inplace */
    204227         0,                     /* src_mask */
    205228         0,                     /* dst_mask */
    206          false),                /* pcrel_offset */
     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 */
    207312};
    208313
     
    226331  {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
    227332
    228   /* The following relocs are defined but they probably don't work yet.  */
    229333  {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
    230334  {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},
    231342};
    232343
     
    255366     bfd *abfd ATTRIBUTE_UNUSED;
    256367     arelent *cache_ptr;
    257      Elf32_Internal_Rel *dst;
     368     Elf_Internal_Rela *dst;
    258369{
    259370  unsigned int r_type;
     
    264375}
    265376
    266 /* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
    267    The Motorola spec says to use a different Elf machine code.  */
     377
     378
     379/* Far trampoline generation.  */
     380
     381/* Build a 68HC11 trampoline stub.  */
     382static bfd_boolean
     383m68hc11_elf_build_one_stub (gen_entry, in_arg)
     384     struct bfd_hash_entry *gen_entry;
     385     PTR in_arg;
     386{
     387  struct elf32_m68hc11_stub_hash_entry *stub_entry;
     388  struct bfd_link_info *info;
     389  struct m68hc11_elf_link_hash_table *htab;
     390  asection *stub_sec;
     391  bfd *stub_bfd;
     392  bfd_byte *loc;
     393  bfd_vma sym_value, phys_page, phys_addr;
     394
     395  /* Massage our args to the form they really have.  */
     396  stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
     397  info = (struct bfd_link_info *) in_arg;
     398
     399  htab = m68hc11_elf_hash_table (info);
     400
     401  stub_sec = stub_entry->stub_sec;
     402
     403  /* Make a note of the offset within the stubs for this entry.  */
     404  stub_entry->stub_offset = stub_sec->_raw_size;
     405  stub_sec->_raw_size += 10;
     406  loc = stub_sec->contents + stub_entry->stub_offset;
     407
     408  stub_bfd = stub_sec->owner;
     409
     410  /* Create the trampoline call stub:
     411
     412     pshb
     413     ldab #%page(symbol)
     414     ldy #%addr(symbol)
     415     jmp __trampoline
     416
     417  */
     418  sym_value = (stub_entry->target_value
     419               + stub_entry->target_section->output_offset
     420               + stub_entry->target_section->output_section->vma);
     421  phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
     422  phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
     423
     424  /* pshb; ldab #%page(sym) */
     425  bfd_put_8 (stub_bfd, 0x37, loc);
     426  bfd_put_8 (stub_bfd, 0xC6, loc + 1);
     427  bfd_put_8 (stub_bfd, phys_page, loc + 2);
     428  loc += 3;
     429
     430  /* ldy #%addr(sym)  */
     431  bfd_put_8 (stub_bfd, 0x18, loc);
     432  bfd_put_8 (stub_bfd, 0xCE, loc + 1);
     433  bfd_put_16 (stub_bfd, phys_addr, loc + 2);
     434  loc += 4;
     435
     436  /* jmp __trampoline  */
     437  bfd_put_8 (stub_bfd, 0x7E, loc);
     438  bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
     439
     440  return TRUE;
     441}
     442
     443/* As above, but don't actually build the stub.  Just bump offset so
     444   we know stub section sizes.  */
     445
     446static bfd_boolean
     447m68hc11_elf_size_one_stub (gen_entry, in_arg)
     448     struct bfd_hash_entry *gen_entry;
     449     PTR in_arg ATTRIBUTE_UNUSED;
     450{
     451  struct elf32_m68hc11_stub_hash_entry *stub_entry;
     452
     453  /* Massage our args to the form they really have.  */
     454  stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
     455
     456  stub_entry->stub_sec->_raw_size += 10;
     457  return TRUE;
     458}
     459
     460/* Create a 68HC11 ELF linker hash table.  */
     461
     462static struct bfd_link_hash_table *
     463m68hc11_elf_bfd_link_hash_table_create (abfd)
     464     bfd *abfd;
     465{
     466  struct m68hc11_elf_link_hash_table *ret;
     467
     468  ret = m68hc11_elf_hash_table_create (abfd);
     469  if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
     470    return NULL;
     471
     472  ret->size_one_stub = m68hc11_elf_size_one_stub;
     473  ret->build_one_stub = m68hc11_elf_build_one_stub;
     474
     475  return &ret->root.root;
     476}
     477
     478
     479
     480/* 68HC11 Linker Relaxation.  */
     481
     482struct m68hc11_direct_relax
     483{
     484  const char *name;
     485  unsigned char code;
     486  unsigned char direct_code;
     487} m68hc11_direct_relax_table[] = {
     488  { "adca", 0xB9, 0x99 },
     489  { "adcb", 0xF9, 0xD9 },
     490  { "adda", 0xBB, 0x9B },
     491  { "addb", 0xFB, 0xDB },
     492  { "addd", 0xF3, 0xD3 },
     493  { "anda", 0xB4, 0x94 },
     494  { "andb", 0xF4, 0xD4 },
     495  { "cmpa", 0xB1, 0x91 },
     496  { "cmpb", 0xF1, 0xD1 },
     497  { "cpd",  0xB3, 0x93 },
     498  { "cpxy", 0xBC, 0x9C },
     499/* { "cpy",  0xBC, 0x9C }, */
     500  { "eora", 0xB8, 0x98 },
     501  { "eorb", 0xF8, 0xD8 },
     502  { "jsr",  0xBD, 0x9D },
     503  { "ldaa", 0xB6, 0x96 },
     504  { "ldab", 0xF6, 0xD6 },
     505  { "ldd",  0xFC, 0xDC },
     506  { "lds",  0xBE, 0x9E },
     507  { "ldxy", 0xFE, 0xDE },
     508  /*  { "ldy",  0xFE, 0xDE },*/
     509  { "oraa", 0xBA, 0x9A },
     510  { "orab", 0xFA, 0xDA },
     511  { "sbca", 0xB2, 0x92 },
     512  { "sbcb", 0xF2, 0xD2 },
     513  { "staa", 0xB7, 0x97 },
     514  { "stab", 0xF7, 0xD7 },
     515  { "std",  0xFD, 0xDD },
     516  { "sts",  0xBF, 0x9F },
     517  { "stxy", 0xFF, 0xDF },
     518  /*  { "sty",  0xFF, 0xDF },*/
     519  { "suba", 0xB0, 0x90 },
     520  { "subb", 0xF0, 0xD0 },
     521  { "subd", 0xB3, 0x93 },
     522  { 0, 0, 0 }
     523};
     524
     525static struct m68hc11_direct_relax *
     526find_relaxable_insn (unsigned char code)
     527{
     528  int i;
     529
     530  for (i = 0; m68hc11_direct_relax_table[i].name; i++)
     531    if (m68hc11_direct_relax_table[i].code == code)
     532      return &m68hc11_direct_relax_table[i];
     533
     534  return 0;
     535}
     536
     537static int
     538compare_reloc (e1, e2)
     539     const void *e1;
     540     const void *e2;
     541{
     542  const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
     543  const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;
     544
     545  if (i1->r_offset == i2->r_offset)
     546    return 0;
     547  else
     548    return i1->r_offset < i2->r_offset ? -1 : 1;
     549}
     550
     551#define M6811_OP_LDX_IMMEDIATE (0xCE)
     552
     553static void
     554m68hc11_relax_group (abfd, sec, contents, value, offset, end_group)
     555     bfd *abfd;
     556     asection *sec;
     557     bfd_byte *contents;
     558     unsigned value;
     559     unsigned long offset;
     560     unsigned long end_group;
     561{
     562  unsigned char code;
     563  unsigned long start_offset;
     564  unsigned long ldx_offset = offset;
     565  unsigned long ldx_size;
     566  int can_delete_ldx;
     567  int relax_ldy = 0;
     568
     569  /* First instruction of the relax group must be a
     570     LDX #value or LDY #value.  If this is not the case,
     571     ignore the relax group.  */
     572  code = bfd_get_8 (abfd, contents + offset);
     573  if (code == 0x18)
     574    {
     575      relax_ldy++;
     576      offset++;
     577      code = bfd_get_8 (abfd, contents + offset);
     578    }
     579  ldx_size = offset - ldx_offset + 3;
     580  offset += 3;
     581  if (code != M6811_OP_LDX_IMMEDIATE || offset >= end_group)
     582    return;
     583
     584
     585  /* We can remove the LDX/LDY only when all bset/brclr instructions
     586     of the relax group have been converted to use direct addressing
     587     mode.  */
     588  can_delete_ldx = 1;
     589  while (offset < end_group)
     590    {
     591      unsigned isize;
     592      unsigned new_value;
     593      int bset_use_y;
     594
     595      bset_use_y = 0;
     596      start_offset = offset;
     597      code = bfd_get_8 (abfd, contents + offset);
     598      if (code == 0x18)
     599        {
     600          bset_use_y++;
     601          offset++;
     602          code = bfd_get_8 (abfd, contents + offset);
     603        }
     604
     605      /* Check the instruction and translate to use direct addressing mode.  */
     606      switch (code)
     607        {
     608          /* bset */
     609        case 0x1C:
     610          code = 0x14;
     611          isize = 3;
     612          break;
     613
     614          /* brclr */
     615        case 0x1F:
     616          code = 0x13;
     617          isize = 4;
     618          break;
     619
     620          /* brset */
     621        case 0x1E:
     622          code = 0x12;
     623          isize = 4;
     624          break;
     625
     626          /* bclr */
     627        case 0x1D:
     628          code = 0x15;
     629          isize = 3;
     630          break;
     631
     632          /* This instruction is not recognized and we are not
     633             at end of the relax group.  Ignore and don't remove
     634             the first LDX (we don't know what it is used for...).  */
     635        default:
     636          return;
     637        }
     638      new_value = (unsigned) bfd_get_8 (abfd, contents + offset + 1);
     639      new_value += value;
     640      if ((new_value & 0xff00) == 0 && bset_use_y == relax_ldy)
     641        {
     642          bfd_put_8 (abfd, code, contents + offset);
     643          bfd_put_8 (abfd, new_value, contents + offset + 1);
     644          if (start_offset != offset)
     645            {
     646              m68hc11_elf_relax_delete_bytes (abfd, sec, start_offset,
     647                                              offset - start_offset);
     648              end_group--;
     649            }
     650        }
     651      else
     652        {
     653          can_delete_ldx = 0;
     654        }
     655      offset = start_offset + isize;
     656    }
     657  if (can_delete_ldx)
     658    {
     659      /* Remove the move instruction (3 or 4 bytes win).  */
     660      m68hc11_elf_relax_delete_bytes (abfd, sec, ldx_offset, ldx_size);
     661    }
     662}
     663
     664/* This function handles relaxing for the 68HC11.
     665
     666
     667        and somewhat more difficult to support.  */
     668
     669static bfd_boolean
     670m68hc11_elf_relax_section (abfd, sec, link_info, again)
     671     bfd *abfd;
     672     asection *sec;
     673     struct bfd_link_info *link_info;
     674     bfd_boolean *again;
     675{
     676  Elf_Internal_Shdr *symtab_hdr;
     677  Elf_Internal_Shdr *shndx_hdr;
     678  Elf_Internal_Rela *internal_relocs;
     679  Elf_Internal_Rela *free_relocs = NULL;
     680  Elf_Internal_Rela *irel, *irelend;
     681  bfd_byte *contents = NULL;
     682  bfd_byte *free_contents = NULL;
     683  Elf32_External_Sym *free_extsyms = NULL;
     684  Elf_Internal_Rela *prev_insn_branch = NULL;
     685  Elf_Internal_Rela *prev_insn_group = NULL;
     686  unsigned insn_group_value = 0;
     687  Elf_Internal_Sym *isymbuf = NULL;
     688
     689  /* Assume nothing changes.  */
     690  *again = FALSE;
     691
     692  /* We don't have to do anything for a relocateable link, if
     693     this section does not have relocs, or if this is not a
     694     code section.  */
     695  if (link_info->relocateable
     696      || (sec->flags & SEC_RELOC) == 0
     697      || sec->reloc_count == 0
     698      || (sec->flags & SEC_CODE) == 0)
     699    return TRUE;
     700
     701  /* If this is the first time we have been called for this section,
     702     initialize the cooked size.  */
     703  if (sec->_cooked_size == 0)
     704    sec->_cooked_size = sec->_raw_size;
     705
     706  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
     707  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
     708
     709  /* Get a copy of the native relocations.  */
     710  internal_relocs = (_bfd_elf32_link_read_relocs
     711                     (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
     712                      link_info->keep_memory));
     713  if (internal_relocs == NULL)
     714    goto error_return;
     715  if (! link_info->keep_memory)
     716    free_relocs = internal_relocs;
     717
     718  /* Checking for branch relaxation relies on the relocations to
     719     be sorted on 'r_offset'.  This is not guaranteed so we must sort.  */
     720  qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
     721         compare_reloc);
     722
     723  /* Walk through them looking for relaxing opportunities.  */
     724  irelend = internal_relocs + sec->reloc_count;
     725  for (irel = internal_relocs; irel < irelend; irel++)
     726    {
     727      bfd_vma symval;
     728      bfd_vma value;
     729      Elf_Internal_Sym *isym;
     730      asection *sym_sec;
     731      int is_far = 0;
     732
     733      /* If this isn't something that can be relaxed, then ignore
     734         this reloc.  */
     735      if (ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_16
     736          && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_JUMP
     737          && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_GROUP)
     738        {
     739          prev_insn_branch = 0;
     740          prev_insn_group = 0;
     741          continue;
     742        }
     743
     744      /* Get the section contents if we haven't done so already.  */
     745      if (contents == NULL)
     746        {
     747          /* Get cached copy if it exists.  */
     748          if (elf_section_data (sec)->this_hdr.contents != NULL)
     749            contents = elf_section_data (sec)->this_hdr.contents;
     750          else
     751            {
     752              /* Go get them off disk.  */
     753              contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
     754              if (contents == NULL)
     755                goto error_return;
     756              free_contents = contents;
     757
     758              if (! bfd_get_section_contents (abfd, sec, contents,
     759                                              (file_ptr) 0, sec->_raw_size))
     760                goto error_return;
     761            }
     762        }
     763
     764      /* Try to eliminate an unconditional 8 bit pc-relative branch
     765         which immediately follows a conditional 8 bit pc-relative
     766         branch around the unconditional branch.
     767
     768            original:           new:
     769            bCC lab1            bCC' lab2
     770            bra lab2
     771           lab1:               lab1:
     772
     773         This happens when the bCC can't reach lab2 at assembly time,
     774         but due to other relaxations it can reach at link time.  */
     775      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_JUMP)
     776        {
     777          Elf_Internal_Rela *nrel;
     778          unsigned char code;
     779          unsigned char roffset;
     780
     781          prev_insn_branch = 0;
     782          prev_insn_group = 0;
     783
     784          /* Do nothing if this reloc is the last byte in the section.  */
     785          if (irel->r_offset + 2 >= sec->_cooked_size)
     786            continue;
     787
     788          /* See if the next instruction is an unconditional pc-relative
     789             branch, more often than not this test will fail, so we
     790             test it first to speed things up.  */
     791          code = bfd_get_8 (abfd, contents + irel->r_offset + 2);
     792          if (code != 0x7e)
     793            continue;
     794
     795          /* Also make sure the next relocation applies to the next
     796             instruction and that it's a pc-relative 8 bit branch.  */
     797          nrel = irel + 1;
     798          if (nrel == irelend
     799              || irel->r_offset + 3 != nrel->r_offset
     800              || ELF32_R_TYPE (nrel->r_info) != (int) R_M68HC11_16)
     801            continue;
     802
     803          /* Make sure our destination immediately follows the
     804             unconditional branch.  */
     805          roffset = bfd_get_8 (abfd, contents + irel->r_offset + 1);
     806          if (roffset != 3)
     807            continue;
     808
     809          prev_insn_branch = irel;
     810          prev_insn_group = 0;
     811          continue;
     812        }
     813
     814      /* Read this BFD's symbols if we haven't done so already.  */
     815      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
     816        {
     817          isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
     818          if (isymbuf == NULL)
     819            isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
     820                                            symtab_hdr->sh_info, 0,
     821                                            NULL, NULL, NULL);
     822          if (isymbuf == NULL)
     823            goto error_return;
     824        }
     825
     826      /* Get the value of the symbol referred to by the reloc.  */
     827      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
     828        {
     829          /* A local symbol.  */
     830          isym = isymbuf + ELF32_R_SYM (irel->r_info);
     831          is_far = isym->st_other & STO_M68HC12_FAR;
     832          sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
     833          symval = (isym->st_value
     834                    + sym_sec->output_section->vma
     835                    + sym_sec->output_offset);
     836        }
     837      else
     838        {
     839          unsigned long indx;
     840          struct elf_link_hash_entry *h;
     841
     842          /* An external symbol.  */
     843          indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
     844          h = elf_sym_hashes (abfd)[indx];
     845          BFD_ASSERT (h != NULL);
     846          if (h->root.type != bfd_link_hash_defined
     847              && h->root.type != bfd_link_hash_defweak)
     848            {
     849              /* This appears to be a reference to an undefined
     850                 symbol.  Just ignore it--it will be caught by the
     851                 regular reloc processing.  */
     852              prev_insn_branch = 0;
     853              prev_insn_group = 0;
     854              continue;
     855            }
     856
     857          is_far = h->other & STO_M68HC12_FAR;
     858          isym = 0;
     859          sym_sec = h->root.u.def.section;
     860          symval = (h->root.u.def.value
     861                    + sym_sec->output_section->vma
     862                    + sym_sec->output_offset);
     863        }
     864
     865      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
     866        {
     867          prev_insn_branch = 0;
     868          prev_insn_group = 0;
     869
     870          /* Do nothing if this reloc is the last byte in the section.  */
     871          if (irel->r_offset == sec->_cooked_size)
     872            continue;
     873
     874          prev_insn_group = irel;
     875          insn_group_value = isym->st_value;
     876          continue;
     877        }
     878
     879      /* When we relax some bytes, the size of our section changes.
     880         This affects the layout of next input sections that go in our
     881         output section.  When the symbol is part of another section that
     882         will go in the same output section as the current one, it's
     883         final address may now be incorrect (too far).  We must let the
     884         linker re-compute all section offsets before processing this
     885         reloc.  Code example:
     886
     887                                Initial             Final
     888         .sect .text            section size = 6    section size = 4
     889         jmp foo
     890         jmp bar
     891         .sect .text.foo_bar    output_offset = 6   output_offset = 4
     892         foo: rts
     893         bar: rts
     894
     895         If we process the reloc now, the jmp bar is replaced by a
     896         relative branch to the initial bar address (output_offset 6).  */
     897      if (*again && sym_sec != sec
     898          && sym_sec->output_section == sec->output_section)
     899        {
     900          prev_insn_group = 0;
     901          prev_insn_branch = 0;
     902          continue;
     903        }
     904
     905      value = symval;
     906      /* Try to turn a far branch to a near branch.  */
     907      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
     908          && prev_insn_branch)
     909        {
     910          bfd_vma offset;
     911          unsigned char code;
     912
     913          offset = value - (prev_insn_branch->r_offset
     914                            + sec->output_section->vma
     915                            + sec->output_offset + 2);
     916
     917          /* If the offset is still out of -128..+127 range,
     918             leave that far branch unchanged.  */
     919          if ((offset & 0xff80) != 0 && (offset & 0xff80) != 0xff80)
     920            {
     921              prev_insn_branch = 0;
     922              continue;
     923            }
     924
     925          /* Shrink the branch.  */
     926          code = bfd_get_8 (abfd, contents + prev_insn_branch->r_offset);
     927          if (code == 0x7e)
     928            {
     929              code = 0x20;
     930              bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
     931              bfd_put_8 (abfd, 0xff,
     932                         contents + prev_insn_branch->r_offset + 1);
     933              irel->r_offset = prev_insn_branch->r_offset + 1;
     934              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
     935                                           R_M68HC11_PCREL_8);
     936              m68hc11_elf_relax_delete_bytes (abfd, sec,
     937                                              irel->r_offset + 1, 1);
     938            }
     939          else
     940            {
     941              code ^= 0x1;
     942              bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
     943              bfd_put_8 (abfd, 0xff,
     944                         contents + prev_insn_branch->r_offset + 1);
     945              irel->r_offset = prev_insn_branch->r_offset + 1;
     946              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
     947                                           R_M68HC11_PCREL_8);
     948              m68hc11_elf_relax_delete_bytes (abfd, sec,
     949                                              irel->r_offset + 1, 3);
     950            }
     951          prev_insn_branch = 0;
     952          *again = TRUE;
     953        }
     954
     955      /* Try to turn a 16 bit address into a 8 bit page0 address.  */
     956      else if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
     957               && (value & 0xff00) == 0)
     958        {
     959          unsigned char code;
     960          unsigned short offset;
     961          struct m68hc11_direct_relax *rinfo;
     962
     963          prev_insn_branch = 0;
     964          offset = bfd_get_16 (abfd, contents + irel->r_offset);
     965          offset += value;
     966          if ((offset & 0xff00) != 0)
     967            {
     968              prev_insn_group = 0;
     969              continue;
     970            }
     971
     972          if (prev_insn_group)
     973            {
     974              unsigned long old_sec_size = sec->_cooked_size;
     975
     976              /* Note that we've changed the reldection contents, etc.  */
     977              elf_section_data (sec)->relocs = internal_relocs;
     978              free_relocs = NULL;
     979
     980              elf_section_data (sec)->this_hdr.contents = contents;
     981              free_contents = NULL;
     982
     983              symtab_hdr->contents = (bfd_byte *) isymbuf;
     984              free_extsyms = NULL;
     985
     986              m68hc11_relax_group (abfd, sec, contents, offset,
     987                                   prev_insn_group->r_offset,
     988                                   insn_group_value);
     989              irel = prev_insn_group;
     990              prev_insn_group = 0;
     991              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
     992                                           R_M68HC11_NONE);
     993              if (sec->_cooked_size != old_sec_size)
     994                *again = TRUE;
     995              continue;
     996            }
     997
     998          /* Get the opcode.  */
     999          code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
     1000          rinfo = find_relaxable_insn (code);
     1001          if (rinfo == 0)
     1002            {
     1003              prev_insn_group = 0;
     1004              continue;
     1005            }
     1006
     1007          /* Note that we've changed the reldection contents, etc.  */
     1008          elf_section_data (sec)->relocs = internal_relocs;
     1009          free_relocs = NULL;
     1010
     1011          elf_section_data (sec)->this_hdr.contents = contents;
     1012          free_contents = NULL;
     1013
     1014          symtab_hdr->contents = (bfd_byte *) isymbuf;
     1015          free_extsyms = NULL;
     1016
     1017          /* Fix the opcode.  */
     1018          /* printf ("A relaxable case : 0x%02x (%s)\n",
     1019             code, rinfo->name); */
     1020          bfd_put_8 (abfd, rinfo->direct_code,
     1021                     contents + irel->r_offset - 1);
     1022
     1023          /* Delete one byte of data (upper byte of address).  */
     1024          m68hc11_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 1);
     1025
     1026          /* Fix the relocation's type.  */
     1027          irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
     1028                                       R_M68HC11_8);
     1029
     1030          /* That will change things, so, we should relax again.  */
     1031          *again = TRUE;
     1032        }
     1033      else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16 && !is_far)
     1034        {
     1035          unsigned char code;
     1036          bfd_vma offset;
     1037
     1038          prev_insn_branch = 0;
     1039          code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
     1040          if (code == 0x7e || code == 0xbd)
     1041            {
     1042              offset = value - (irel->r_offset
     1043                                + sec->output_section->vma
     1044                                + sec->output_offset + 1);
     1045              offset += bfd_get_16 (abfd, contents + irel->r_offset);
     1046
     1047              /* If the offset is still out of -128..+127 range,
     1048                 leave that far branch unchanged.  */
     1049              if ((offset & 0xff80) == 0 || (offset & 0xff80) == 0xff80)
     1050                {
     1051
     1052                  /* Note that we've changed the reldection contents, etc.  */
     1053                  elf_section_data (sec)->relocs = internal_relocs;
     1054                  free_relocs = NULL;
     1055
     1056                  elf_section_data (sec)->this_hdr.contents = contents;
     1057                  free_contents = NULL;
     1058
     1059                  symtab_hdr->contents = (bfd_byte *) isymbuf;
     1060                  free_extsyms = NULL;
     1061
     1062                  /* Shrink the branch.  */
     1063                  code = (code == 0x7e) ? 0x20 : 0x8d;
     1064                  bfd_put_8 (abfd, code,
     1065                             contents + irel->r_offset - 1);
     1066                  bfd_put_8 (abfd, 0xff,
     1067                             contents + irel->r_offset);
     1068                  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
     1069                                               R_M68HC11_PCREL_8);
     1070                  m68hc11_elf_relax_delete_bytes (abfd, sec,
     1071                                                  irel->r_offset + 1, 1);
     1072                  /* That will change things, so, we should relax again.  */
     1073                  *again = TRUE;
     1074                }
     1075            }
     1076        }
     1077      prev_insn_branch = 0;
     1078      prev_insn_group = 0;
     1079    }
     1080
     1081  if (free_relocs != NULL)
     1082    {
     1083      free (free_relocs);
     1084      free_relocs = NULL;
     1085    }
     1086
     1087  if (free_contents != NULL)
     1088    {
     1089      if (! link_info->keep_memory)
     1090        free (free_contents);
     1091      else
     1092        {
     1093          /* Cache the section contents for elf_link_input_bfd.  */
     1094          elf_section_data (sec)->this_hdr.contents = contents;
     1095        }
     1096      free_contents = NULL;
     1097    }
     1098
     1099  if (free_extsyms != NULL)
     1100    {
     1101      if (! link_info->keep_memory)
     1102        free (free_extsyms);
     1103      else
     1104        {
     1105          /* Cache the symbols for elf_link_input_bfd.  */
     1106          symtab_hdr->contents = (unsigned char *) isymbuf;
     1107        }
     1108      free_extsyms = NULL;
     1109    }
     1110
     1111  return TRUE;
     1112
     1113 error_return:
     1114  if (free_relocs != NULL)
     1115    free (free_relocs);
     1116  if (free_contents != NULL)
     1117    free (free_contents);
     1118  if (free_extsyms != NULL)
     1119    free (free_extsyms);
     1120  return FALSE;
     1121}
     1122
     1123/* Delete some bytes from a section while relaxing.  */
     1124
     1125static void
     1126m68hc11_elf_relax_delete_bytes (abfd, sec, addr, count)
     1127     bfd *abfd;
     1128     asection *sec;
     1129     bfd_vma addr;
     1130     int count;
     1131{
     1132  Elf_Internal_Shdr *symtab_hdr;
     1133  unsigned int sec_shndx;
     1134  bfd_byte *contents;
     1135  Elf_Internal_Rela *irel, *irelend;
     1136  bfd_vma toaddr;
     1137  Elf_Internal_Sym *isymbuf, *isym, *isymend;
     1138  struct elf_link_hash_entry **sym_hashes;
     1139  struct elf_link_hash_entry **end_hashes;
     1140  unsigned int symcount;
     1141
     1142  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
     1143  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
     1144
     1145  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
     1146
     1147  contents = elf_section_data (sec)->this_hdr.contents;
     1148
     1149  toaddr = sec->_cooked_size;
     1150
     1151  irel = elf_section_data (sec)->relocs;
     1152  irelend = irel + sec->reloc_count;
     1153
     1154  /* Actually delete the bytes.  */
     1155  memmove (contents + addr, contents + addr + count,
     1156           (size_t) (toaddr - addr - count));
     1157
     1158  sec->_cooked_size -= count;
     1159
     1160  /* Adjust all the relocs.  */
     1161  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
     1162    {
     1163      unsigned char code;
     1164      unsigned char offset;
     1165      unsigned short raddr;
     1166      unsigned long old_offset;
     1167      int branch_pos;
     1168
     1169      old_offset = irel->r_offset;
     1170
     1171      /* See if this reloc was for the bytes we have deleted, in which
     1172         case we no longer care about it.  Don't delete relocs which
     1173         represent addresses, though.  */
     1174      if (ELF32_R_TYPE (irel->r_info) != R_M68HC11_RL_JUMP
     1175          && irel->r_offset >= addr && irel->r_offset < addr + count)
     1176        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
     1177                                     R_M68HC11_NONE);
     1178
     1179      if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_NONE)
     1180        continue;
     1181
     1182      /* Get the new reloc address.  */
     1183      if ((irel->r_offset > addr
     1184           && irel->r_offset < toaddr))
     1185        irel->r_offset -= count;
     1186
     1187      /* If this is a PC relative reloc, see if the range it covers
     1188         includes the bytes we have deleted.  */
     1189      switch (ELF32_R_TYPE (irel->r_info))
     1190        {
     1191        default:
     1192          break;
     1193
     1194        case R_M68HC11_RL_JUMP:
     1195          code = bfd_get_8 (abfd, contents + irel->r_offset);
     1196          switch (code)
     1197            {
     1198              /* jsr and jmp instruction are also marked with RL_JUMP
     1199                 relocs but no adjustment must be made.  */
     1200            case 0x7e:
     1201            case 0x9d:
     1202            case 0xbd:
     1203              continue;
     1204
     1205            case 0x12:
     1206            case 0x13:
     1207              branch_pos = 3;
     1208              raddr = 4;
     1209
     1210              /* Special case when we translate a brclr N,y into brclr *<addr>
     1211                 In this case, the 0x18 page2 prefix is removed.
     1212                 The reloc offset is not modified but the instruction
     1213                 size is reduced by 1.  */
     1214              if (old_offset == addr)
     1215                raddr++;
     1216              break;
     1217
     1218            case 0x1e:
     1219            case 0x1f:
     1220              branch_pos = 3;
     1221              raddr = 4;
     1222              break;
     1223
     1224            case 0x18:
     1225              branch_pos = 4;
     1226              raddr = 5;
     1227              break;
     1228
     1229            default:
     1230              branch_pos = 1;
     1231              raddr = 2;
     1232              break;
     1233            }
     1234          offset = bfd_get_8 (abfd, contents + irel->r_offset + branch_pos);
     1235          raddr += old_offset;
     1236          raddr += ((unsigned short) offset | ((offset & 0x80) ? 0xff00 : 0));
     1237          if (irel->r_offset < addr && raddr > addr)
     1238            {
     1239              offset -= count;
     1240              bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
     1241            }
     1242          else if (irel->r_offset >= addr && raddr <= addr)
     1243            {
     1244              offset += count;
     1245              bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
     1246            }
     1247          else
     1248            {
     1249              /*printf ("Not adjusted 0x%04x [0x%4x 0x%4x]\n", raddr,
     1250                irel->r_offset, addr);*/
     1251            }
     1252
     1253          break;
     1254        }
     1255    }
     1256
     1257  /* Adjust the local symbols defined in this section.  */
     1258  isymend = isymbuf + symtab_hdr->sh_info;
     1259  for (isym = isymbuf; isym < isymend; isym++)
     1260    {
     1261      if (isym->st_shndx == sec_shndx
     1262          && isym->st_value > addr
     1263          && isym->st_value <= toaddr)
     1264        isym->st_value -= count;
     1265    }
     1266
     1267  /* Now adjust the global symbols defined in this section.  */
     1268  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
     1269              - symtab_hdr->sh_info);
     1270  sym_hashes = elf_sym_hashes (abfd);
     1271  end_hashes = sym_hashes + symcount;
     1272  for (; sym_hashes < end_hashes; sym_hashes++)
     1273    {
     1274      struct elf_link_hash_entry *sym_hash = *sym_hashes;
     1275      if ((sym_hash->root.type == bfd_link_hash_defined
     1276           || sym_hash->root.type == bfd_link_hash_defweak)
     1277          && sym_hash->root.u.def.section == sec
     1278          && sym_hash->root.u.def.value > addr
     1279          && sym_hash->root.u.def.value <= toaddr)
     1280        {
     1281          sym_hash->root.u.def.value -= count;
     1282        }
     1283    }
     1284}
     1285
     1286
     1287
    2681288#define ELF_ARCH                bfd_arch_m68hc11
    2691289#define ELF_MACHINE_CODE        EM_68HC11
     
    2751295#define elf_info_to_howto       0
    2761296#define elf_info_to_howto_rel   m68hc11_info_to_howto_rel
     1297#define bfd_elf32_bfd_relax_section  m68hc11_elf_relax_section
     1298#define elf_backend_gc_mark_hook     elf32_m68hc11_gc_mark_hook
     1299#define elf_backend_gc_sweep_hook    elf32_m68hc11_gc_sweep_hook
     1300#define elf_backend_check_relocs     elf32_m68hc11_check_relocs
     1301#define elf_backend_relocate_section elf32_m68hc11_relocate_section
     1302#define elf_backend_add_symbol_hook  elf32_m68hc11_add_symbol_hook
    2771303#define elf_backend_object_p    0
    2781304#define elf_backend_final_write_processing      0
     1305#define elf_backend_can_gc_sections             1
     1306
     1307#define bfd_elf32_bfd_link_hash_table_create \
     1308                                m68hc11_elf_bfd_link_hash_table_create
     1309#define bfd_elf32_bfd_link_hash_table_free \
     1310                                m68hc11_elf_bfd_link_hash_table_free
     1311#define bfd_elf32_bfd_merge_private_bfd_data \
     1312                                        _bfd_m68hc11_elf_merge_private_bfd_data
     1313#define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
     1314#define bfd_elf32_bfd_print_private_bfd_data \
     1315                                        _bfd_m68hc11_elf_print_private_bfd_data
    2791316
    2801317#include "elf32-target.h"
Note: See TracChangeset for help on using the changeset viewer.