Back to index

cell-binutils  2.17cvs20070401
Classes | Defines | Functions | Variables
elf32-m68hc11.c File Reference
#include "bfd.h"
#include "sysdep.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf32-m68hc1x.h"
#include "elf/m68hc11.h"
#include "opcode/m68hc11.h"
#include "elf32-target.h"

Go to the source code of this file.

Classes

struct  m68hc11_reloc_map
struct  m68hc11_direct_relax

Defines

#define USE_REL   1
#define M6811_OP_LDX_IMMEDIATE   (0xCE)
#define ELF_ARCH   bfd_arch_m68hc11
#define ELF_MACHINE_CODE   EM_68HC11
#define ELF_MAXPAGESIZE   0x1000
#define TARGET_BIG_SYM   bfd_elf32_m68hc11_vec
#define TARGET_BIG_NAME   "elf32-m68hc11"
#define elf_info_to_howto   0
#define elf_info_to_howto_rel   m68hc11_info_to_howto_rel
#define bfd_elf32_bfd_relax_section   m68hc11_elf_relax_section
#define elf_backend_check_relocs   elf32_m68hc11_check_relocs
#define elf_backend_relocate_section   elf32_m68hc11_relocate_section
#define elf_backend_add_symbol_hook   elf32_m68hc11_add_symbol_hook
#define elf_backend_object_p   0
#define elf_backend_final_write_processing   0
#define elf_backend_can_gc_sections   1
#define elf_backend_special_sections   elf32_m68hc11_special_sections
#define bfd_elf32_bfd_link_hash_table_create   m68hc11_elf_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_free   m68hc11_elf_bfd_link_hash_table_free
#define bfd_elf32_bfd_merge_private_bfd_data   _bfd_m68hc11_elf_merge_private_bfd_data
#define bfd_elf32_bfd_set_private_flags   _bfd_m68hc11_elf_set_private_flags
#define bfd_elf32_bfd_print_private_bfd_data   _bfd_m68hc11_elf_print_private_bfd_data

Functions

static reloc_howto_type * bfd_elf32_bfd_reloc_type_lookup (bfd *, bfd_reloc_code_real_type)
static void m68hc11_info_to_howto_rel (bfd *, arelent *, Elf_Internal_Rela *)
static bfd_boolean m68hc11_elf_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
static bfd_boolean m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
static struct bfd_link_hash_tablem68hc11_elf_bfd_link_hash_table_create (bfd *abfd)
static bfd_boolean m68hc11_elf_relax_section (bfd *, asection *, struct bfd_link_info *, bfd_boolean *)
static void m68hc11_elf_relax_delete_bytes (bfd *, asection *, bfd_vma, int)
static void m68hc11_relax_group (bfd *, asection *, bfd_byte *, unsigned, unsigned long, unsigned long)
static int compare_reloc (const void *, const void *)
static reloc_howto_type * bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
static reloc_howto_type * bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
static void m68hc11_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, Elf_Internal_Rela *dst)
static bfd_boolean m68hc11_elf_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_UNUSED)
static struct
m68hc11_direct_relax
find_relaxable_insn (unsigned char code)

Variables

static reloc_howto_type elf_m68hc11_howto_table []
static struct m68hc11_reloc_map []
struct m68hc11_direct_relax m68hc11_direct_relax_table []
static struct bfd_elf_special_section []

Class Documentation

struct m68hc11_reloc_map

Definition at line 316 of file elf32-m68hc11.c.

Class Members
bfd_reloc_code_real_type bfd_reloc_val
unsigned char elf_reloc_val
struct m68hc11_direct_relax

Definition at line 490 of file elf32-m68hc11.c.

Class Members
unsigned char code
unsigned char direct_code
const char * name

Define Documentation

Definition at line 1304 of file elf32-m68hc11.c.

Definition at line 1306 of file elf32-m68hc11.c.

Definition at line 1308 of file elf32-m68hc11.c.

Definition at line 1311 of file elf32-m68hc11.c.

Definition at line 1295 of file elf32-m68hc11.c.

Definition at line 1310 of file elf32-m68hc11.c.

#define ELF_ARCH   bfd_arch_m68hc11

Definition at line 1286 of file elf32-m68hc11.c.

Definition at line 1298 of file elf32-m68hc11.c.

Definition at line 1301 of file elf32-m68hc11.c.

Definition at line 1296 of file elf32-m68hc11.c.

Definition at line 1300 of file elf32-m68hc11.c.

#define elf_backend_object_p   0

Definition at line 1299 of file elf32-m68hc11.c.

Definition at line 1297 of file elf32-m68hc11.c.

#define elf_backend_special_sections   elf32_m68hc11_special_sections

Definition at line 1302 of file elf32-m68hc11.c.

#define elf_info_to_howto   0

Definition at line 1293 of file elf32-m68hc11.c.

Definition at line 1294 of file elf32-m68hc11.c.

Definition at line 1287 of file elf32-m68hc11.c.

#define ELF_MAXPAGESIZE   0x1000

Definition at line 1288 of file elf32-m68hc11.c.

#define M6811_OP_LDX_IMMEDIATE   (0xCE)

Definition at line 557 of file elf32-m68hc11.c.

#define TARGET_BIG_NAME   "elf32-m68hc11"

Definition at line 1291 of file elf32-m68hc11.c.

Definition at line 1290 of file elf32-m68hc11.c.

#define USE_REL   1

Definition at line 56 of file elf32-m68hc11.c.


Function Documentation

static reloc_howto_type* bfd_elf32_bfd_reloc_name_lookup ( bfd *abfd  ATTRIBUTE_UNUSED,
const char *  r_name 
) [static]

Definition at line 362 of file elf32-m68hc11.c.

{
  unsigned int i;

  for (i = 0;
       i < (sizeof (elf_m68hc11_howto_table)
           / sizeof (elf_m68hc11_howto_table[0]));
       i++)
    if (elf_m68hc11_howto_table[i].name != NULL
       && strcasecmp (elf_m68hc11_howto_table[i].name, r_name) == 0)
      return &elf_m68hc11_howto_table[i];

  return NULL;
}

Here is the call graph for this function:

static reloc_howto_type* bfd_elf32_bfd_reloc_type_lookup ( bfd ,
bfd_reloc_code_real_type   
) [static]
static reloc_howto_type* bfd_elf32_bfd_reloc_type_lookup ( bfd *abfd  ATTRIBUTE_UNUSED,
bfd_reloc_code_real_type  code 
) [static]

Definition at line 345 of file elf32-m68hc11.c.

{
  unsigned int i;

  for (i = 0;
       i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
       i++)
    {
      if (m68hc11_reloc_map[i].bfd_reloc_val == code)
       return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
    }

  return NULL;
}
static int compare_reloc ( const void *  e1,
const void *  e2 
) [static]

Definition at line 546 of file elf32-m68hc11.c.

{
  const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
  const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;

  if (i1->r_offset == i2->r_offset)
    return 0;
  else
    return i1->r_offset < i2->r_offset ? -1 : 1;
}

Here is the caller graph for this function:

static struct m68hc11_direct_relax* find_relaxable_insn ( unsigned char  code) [static, read]

Definition at line 534 of file elf32-m68hc11.c.

{
  int i;

  for (i = 0; m68hc11_direct_relax_table[i].name; i++)
    if (m68hc11_direct_relax_table[i].code == code)
      return &m68hc11_direct_relax_table[i];

  return 0;
}

Here is the caller graph for this function:

Definition at line 473 of file elf32-m68hc11.c.

{
  struct m68hc11_elf_link_hash_table *ret;

  ret = m68hc11_elf_hash_table_create (abfd);
  if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
    return NULL;

  ret->size_one_stub = m68hc11_elf_size_one_stub;
  ret->build_one_stub = m68hc11_elf_build_one_stub;

  return &ret->root.root;
}

Here is the call graph for this function:

static bfd_boolean m68hc11_elf_build_one_stub ( struct bfd_hash_entry gen_entry,
void *  in_arg 
) [static]

Definition at line 396 of file elf32-m68hc11.c.

{
  struct elf32_m68hc11_stub_hash_entry *stub_entry;
  struct bfd_link_info *info;
  struct m68hc11_elf_link_hash_table *htab;
  asection *stub_sec;
  bfd *stub_bfd;
  bfd_byte *loc;
  bfd_vma sym_value, phys_page, phys_addr;

  /* Massage our args to the form they really have.  */
  stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
  info = (struct bfd_link_info *) in_arg;

  htab = m68hc11_elf_hash_table (info);

  stub_sec = stub_entry->stub_sec;

  /* Make a note of the offset within the stubs for this entry.  */
  stub_entry->stub_offset = stub_sec->size;
  stub_sec->size += 10;
  loc = stub_sec->contents + stub_entry->stub_offset;

  stub_bfd = stub_sec->owner;

  /* Create the trampoline call stub:

     pshb
     ldab #%page(symbol)
     ldy #%addr(symbol)
     jmp __trampoline

  */
  sym_value = (stub_entry->target_value
               + stub_entry->target_section->output_offset
               + stub_entry->target_section->output_section->vma);
  phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
  phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);

  /* pshb; ldab #%page(sym) */
  bfd_put_8 (stub_bfd, 0x37, loc);
  bfd_put_8 (stub_bfd, 0xC6, loc + 1);
  bfd_put_8 (stub_bfd, phys_page, loc + 2);
  loc += 3;

  /* ldy #%addr(sym)  */
  bfd_put_8 (stub_bfd, 0x18, loc);
  bfd_put_8 (stub_bfd, 0xCE, loc + 1);
  bfd_put_16 (stub_bfd, phys_addr, loc + 2);
  loc += 4;

  /* jmp __trampoline  */
  bfd_put_8 (stub_bfd, 0x7E, loc);
  bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);

  return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void m68hc11_elf_relax_delete_bytes ( bfd abfd,
asection sec,
bfd_vma  addr,
int  count 
) [static]

Definition at line 1114 of file elf32-m68hc11.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  unsigned int sec_shndx;
  bfd_byte *contents;
  Elf_Internal_Rela *irel, *irelend;
  bfd_vma toaddr;
  Elf_Internal_Sym *isymbuf, *isym, *isymend;
  struct elf_link_hash_entry **sym_hashes;
  struct elf_link_hash_entry **end_hashes;
  unsigned int symcount;

  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;

  sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);

  contents = elf_section_data (sec)->this_hdr.contents;

  toaddr = sec->size;

  irel = elf_section_data (sec)->relocs;
  irelend = irel + sec->reloc_count;

  /* Actually delete the bytes.  */
  memmove (contents + addr, contents + addr + count,
          (size_t) (toaddr - addr - count));

  sec->size -= count;

  /* Adjust all the relocs.  */
  for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
    {
      unsigned char code;
      unsigned char offset;
      unsigned short raddr;
      unsigned long old_offset;
      int branch_pos;

      old_offset = irel->r_offset;

      /* See if this reloc was for the bytes we have deleted, in which
        case we no longer care about it.  Don't delete relocs which
        represent addresses, though.  */
      if (ELF32_R_TYPE (irel->r_info) != R_M68HC11_RL_JUMP
          && irel->r_offset >= addr && irel->r_offset < addr + count)
        irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                     R_M68HC11_NONE);

      if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_NONE)
        continue;

      /* Get the new reloc address.  */
      if ((irel->r_offset > addr
          && irel->r_offset < toaddr))
       irel->r_offset -= count;

      /* If this is a PC relative reloc, see if the range it covers
         includes the bytes we have deleted.  */
      switch (ELF32_R_TYPE (irel->r_info))
       {
       default:
         break;

       case R_M68HC11_RL_JUMP:
          code = bfd_get_8 (abfd, contents + irel->r_offset);
          switch (code)
            {
              /* jsr and jmp instruction are also marked with RL_JUMP
                 relocs but no adjustment must be made.  */
            case 0x7e:
            case 0x9d:
            case 0xbd:
              continue;

            case 0x12:
            case 0x13:
              branch_pos = 3;
              raddr = 4;

              /* Special case when we translate a brclr N,y into brclr *<addr>
                 In this case, the 0x18 page2 prefix is removed.
                 The reloc offset is not modified but the instruction
                 size is reduced by 1.  */
              if (old_offset == addr)
                raddr++;
              break;

            case 0x1e:
            case 0x1f:
              branch_pos = 3;
              raddr = 4;
              break;

            case 0x18:
              branch_pos = 4;
              raddr = 5;
              break;

            default:
              branch_pos = 1;
              raddr = 2;
              break;
            }
          offset = bfd_get_8 (abfd, contents + irel->r_offset + branch_pos);
          raddr += old_offset;
          raddr += ((unsigned short) offset | ((offset & 0x80) ? 0xff00 : 0));
          if (irel->r_offset < addr && raddr > addr)
            {
              offset -= count;
              bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
            }
          else if (irel->r_offset >= addr && raddr <= addr)
            {
              offset += count;
              bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
            }
          else
            {
              /*printf ("Not adjusted 0x%04x [0x%4x 0x%4x]\n", raddr,
                irel->r_offset, addr);*/
            }

          break;
       }
    }

  /* Adjust the local symbols defined in this section.  */
  isymend = isymbuf + symtab_hdr->sh_info;
  for (isym = isymbuf; isym < isymend; isym++)
    {
      if (isym->st_shndx == sec_shndx
         && isym->st_value > addr
         && isym->st_value <= toaddr)
       isym->st_value -= count;
    }

  /* Now adjust the global symbols defined in this section.  */
  symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
             - symtab_hdr->sh_info);
  sym_hashes = elf_sym_hashes (abfd);
  end_hashes = sym_hashes + symcount;
  for (; sym_hashes < end_hashes; sym_hashes++)
    {
      struct elf_link_hash_entry *sym_hash = *sym_hashes;
      if ((sym_hash->root.type == bfd_link_hash_defined
          || sym_hash->root.type == bfd_link_hash_defweak)
         && sym_hash->root.u.def.section == sec
         && sym_hash->root.u.def.value > addr
         && sym_hash->root.u.def.value <= toaddr)
       {
         sym_hash->root.u.def.value -= count;
       }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static bfd_boolean m68hc11_elf_relax_section ( bfd abfd,
asection sec,
struct bfd_link_info link_info,
bfd_boolean again 
) [static]

Definition at line 672 of file elf32-m68hc11.c.

{
  Elf_Internal_Shdr *symtab_hdr;
  Elf_Internal_Shdr *shndx_hdr;
  Elf_Internal_Rela *internal_relocs;
  Elf_Internal_Rela *free_relocs = NULL;
  Elf_Internal_Rela *irel, *irelend;
  bfd_byte *contents = NULL;
  bfd_byte *free_contents = NULL;
  Elf32_External_Sym *free_extsyms = NULL;
  Elf_Internal_Rela *prev_insn_branch = NULL;
  Elf_Internal_Rela *prev_insn_group = NULL;
  unsigned insn_group_value = 0;
  Elf_Internal_Sym *isymbuf = NULL;

  /* Assume nothing changes.  */
  *again = FALSE;

  /* We don't have to do anything for a relocatable link, if
     this section does not have relocs, or if this is not a
     code section.  */
  if (link_info->relocatable
      || (sec->flags & SEC_RELOC) == 0
      || sec->reloc_count == 0
      || (sec->flags & SEC_CODE) == 0)
    return TRUE;

  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
  shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;

  /* Get a copy of the native relocations.  */
  internal_relocs = (_bfd_elf_link_read_relocs
                   (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
                    link_info->keep_memory));
  if (internal_relocs == NULL)
    goto error_return;
  if (! link_info->keep_memory)
    free_relocs = internal_relocs;

  /* Checking for branch relaxation relies on the relocations to
     be sorted on 'r_offset'.  This is not guaranteed so we must sort.  */
  qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
         compare_reloc);

  /* Walk through them looking for relaxing opportunities.  */
  irelend = internal_relocs + sec->reloc_count;
  for (irel = internal_relocs; irel < irelend; irel++)
    {
      bfd_vma symval;
      bfd_vma value;
      Elf_Internal_Sym *isym;
      asection *sym_sec;
      int is_far = 0;

      /* If this isn't something that can be relaxed, then ignore
        this reloc.  */
      if (ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_16
          && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_JUMP
          && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_GROUP)
        {
          prev_insn_branch = 0;
          prev_insn_group = 0;
          continue;
        }

      /* Get the section contents if we haven't done so already.  */
      if (contents == NULL)
       {
         /* Get cached copy if it exists.  */
         if (elf_section_data (sec)->this_hdr.contents != NULL)
           contents = elf_section_data (sec)->this_hdr.contents;
         else
           {
             /* Go get them off disk.  */
             if (!bfd_malloc_and_get_section (abfd, sec, &contents))
              goto error_return;
           }
       }

      /* Try to eliminate an unconditional 8 bit pc-relative branch
        which immediately follows a conditional 8 bit pc-relative
        branch around the unconditional branch.

           original:        new:
           bCC lab1         bCC' lab2
           bra lab2
          lab1:             lab1:

        This happens when the bCC can't reach lab2 at assembly time,
        but due to other relaxations it can reach at link time.  */
      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_JUMP)
       {
         Elf_Internal_Rela *nrel;
         unsigned char code;
          unsigned char roffset;

          prev_insn_branch = 0;
          prev_insn_group = 0;

         /* Do nothing if this reloc is the last byte in the section.  */
         if (irel->r_offset + 2 >= sec->size)
           continue;

         /* See if the next instruction is an unconditional pc-relative
            branch, more often than not this test will fail, so we
            test it first to speed things up.  */
         code = bfd_get_8 (abfd, contents + irel->r_offset + 2);
         if (code != 0x7e)
           continue;

         /* Also make sure the next relocation applies to the next
            instruction and that it's a pc-relative 8 bit branch.  */
         nrel = irel + 1;
         if (nrel == irelend
             || irel->r_offset + 3 != nrel->r_offset
             || ELF32_R_TYPE (nrel->r_info) != (int) R_M68HC11_16)
           continue;

         /* Make sure our destination immediately follows the
            unconditional branch.  */
          roffset = bfd_get_8 (abfd, contents + irel->r_offset + 1);
          if (roffset != 3)
            continue;

          prev_insn_branch = irel;
          prev_insn_group = 0;
          continue;
        }

      /* Read this BFD's symbols if we haven't done so already.  */
      if (isymbuf == NULL && symtab_hdr->sh_info != 0)
       {
         isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
         if (isymbuf == NULL)
           isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
                                       symtab_hdr->sh_info, 0,
                                       NULL, NULL, NULL);
         if (isymbuf == NULL)
           goto error_return;
       }

      /* Get the value of the symbol referred to by the reloc.  */
      if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
       {
         /* A local symbol.  */
         isym = isymbuf + ELF32_R_SYM (irel->r_info);
          is_far = isym->st_other & STO_M68HC12_FAR;
          sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
         symval = (isym->st_value
                  + sym_sec->output_section->vma
                  + sym_sec->output_offset);
       }
      else
       {
         unsigned long indx;
         struct elf_link_hash_entry *h;

         /* An external symbol.  */
         indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
         h = elf_sym_hashes (abfd)[indx];
         BFD_ASSERT (h != NULL);
         if (h->root.type != bfd_link_hash_defined
             && h->root.type != bfd_link_hash_defweak)
           {
             /* This appears to be a reference to an undefined
                 symbol.  Just ignore it--it will be caught by the
                 regular reloc processing.  */
              prev_insn_branch = 0;
              prev_insn_group = 0;
             continue;
           }

          is_far = h->other & STO_M68HC12_FAR;
          isym = 0;
          sym_sec = h->root.u.def.section;
         symval = (h->root.u.def.value
                  + sym_sec->output_section->vma
                  + sym_sec->output_offset);
       }

      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
       {
          prev_insn_branch = 0;
          prev_insn_group = 0;

         /* Do nothing if this reloc is the last byte in the section.  */
         if (irel->r_offset == sec->size)
           continue;

          prev_insn_group = irel;
          insn_group_value = isym->st_value;
          continue;
        }

      /* When we relax some bytes, the size of our section changes.
         This affects the layout of next input sections that go in our
         output section.  When the symbol is part of another section that
         will go in the same output section as the current one, it's
         final address may now be incorrect (too far).  We must let the
         linker re-compute all section offsets before processing this
         reloc.  Code example:

                                Initial             Final
         .sect .text            section size = 6    section size = 4
         jmp foo
         jmp bar
         .sect .text.foo_bar    output_offset = 6   output_offset = 4
         foo: rts
         bar: rts

         If we process the reloc now, the jmp bar is replaced by a
         relative branch to the initial bar address (output_offset 6).  */
      if (*again && sym_sec != sec
          && sym_sec->output_section == sec->output_section)
        {
          prev_insn_group = 0;
          prev_insn_branch = 0;
          continue;
        }

      value = symval;
      /* Try to turn a far branch to a near branch.  */
      if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
          && prev_insn_branch)
        {
          bfd_vma offset;
          unsigned char code;

          offset = value - (prev_insn_branch->r_offset
                            + sec->output_section->vma
                            + sec->output_offset + 2);

          /* If the offset is still out of -128..+127 range,
             leave that far branch unchanged.  */
          if ((offset & 0xff80) != 0 && (offset & 0xff80) != 0xff80)
            {
              prev_insn_branch = 0;
              continue;
            }

          /* Shrink the branch.  */
          code = bfd_get_8 (abfd, contents + prev_insn_branch->r_offset);
          if (code == 0x7e)
            {
              code = 0x20;
              bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
              bfd_put_8 (abfd, 0xff,
                         contents + prev_insn_branch->r_offset + 1);
              irel->r_offset = prev_insn_branch->r_offset + 1;
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                           R_M68HC11_PCREL_8);
              m68hc11_elf_relax_delete_bytes (abfd, sec,
                                              irel->r_offset + 1, 1);
            }
          else
            {
              code ^= 0x1;
              bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
              bfd_put_8 (abfd, 0xff,
                         contents + prev_insn_branch->r_offset + 1);
              irel->r_offset = prev_insn_branch->r_offset + 1;
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                           R_M68HC11_PCREL_8);
              m68hc11_elf_relax_delete_bytes (abfd, sec,
                                              irel->r_offset + 1, 3);
            }
          prev_insn_branch = 0;
          *again = TRUE;
        }

      /* Try to turn a 16 bit address into a 8 bit page0 address.  */
      else if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
               && (value & 0xff00) == 0)
       {
          unsigned char code;
          unsigned short offset;
          struct m68hc11_direct_relax *rinfo;

          prev_insn_branch = 0;
          offset = bfd_get_16 (abfd, contents + irel->r_offset);
          offset += value;
          if ((offset & 0xff00) != 0)
            {
              prev_insn_group = 0;
              continue;
            }

          if (prev_insn_group)
            {
              unsigned long old_sec_size = sec->size;

              /* Note that we've changed the relocation contents, etc.  */
              elf_section_data (sec)->relocs = internal_relocs;
              free_relocs = NULL;

              elf_section_data (sec)->this_hdr.contents = contents;
              free_contents = NULL;

              symtab_hdr->contents = (bfd_byte *) isymbuf;
              free_extsyms = NULL;

              m68hc11_relax_group (abfd, sec, contents, offset,
                                   prev_insn_group->r_offset,
                                   insn_group_value);
              irel = prev_insn_group;
              prev_insn_group = 0;
              irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                           R_M68HC11_NONE);
              if (sec->size != old_sec_size)
                *again = TRUE;
              continue;
            }

          /* Get the opcode.  */
          code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
          rinfo = find_relaxable_insn (code);
          if (rinfo == 0)
            {
              prev_insn_group = 0;
              continue;
            }

          /* Note that we've changed the relocation contents, etc.  */
          elf_section_data (sec)->relocs = internal_relocs;
          free_relocs = NULL;

          elf_section_data (sec)->this_hdr.contents = contents;
          free_contents = NULL;

          symtab_hdr->contents = (bfd_byte *) isymbuf;
          free_extsyms = NULL;

          /* Fix the opcode.  */
          /* printf ("A relaxable case : 0x%02x (%s)\n",
             code, rinfo->name); */
          bfd_put_8 (abfd, rinfo->direct_code,
                     contents + irel->r_offset - 1);

          /* Delete one byte of data (upper byte of address).  */
          m68hc11_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 1);

          /* Fix the relocation's type.  */
          irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                       R_M68HC11_8);

          /* That will change things, so, we should relax again.  */
          *again = TRUE;
        }
      else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16 && !is_far)
        {
          unsigned char code;
          bfd_vma offset;

          prev_insn_branch = 0;
          code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
          if (code == 0x7e || code == 0xbd)
            {
              offset = value - (irel->r_offset
                                + sec->output_section->vma
                                + sec->output_offset + 1);
              offset += bfd_get_16 (abfd, contents + irel->r_offset);

              /* If the offset is still out of -128..+127 range,
                 leave that far branch unchanged.  */
              if ((offset & 0xff80) == 0 || (offset & 0xff80) == 0xff80)
                {

                  /* Note that we've changed the relocation contents, etc.  */
                  elf_section_data (sec)->relocs = internal_relocs;
                  free_relocs = NULL;

                  elf_section_data (sec)->this_hdr.contents = contents;
                  free_contents = NULL;

                  symtab_hdr->contents = (bfd_byte *) isymbuf;
                  free_extsyms = NULL;

                  /* Shrink the branch.  */
                  code = (code == 0x7e) ? 0x20 : 0x8d;
                  bfd_put_8 (abfd, code,
                             contents + irel->r_offset - 1);
                  bfd_put_8 (abfd, 0xff,
                             contents + irel->r_offset);
                  irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
                                               R_M68HC11_PCREL_8);
                  m68hc11_elf_relax_delete_bytes (abfd, sec,
                                                  irel->r_offset + 1, 1);
                  /* That will change things, so, we should relax again.  */
                  *again = TRUE;
                }
            }
        }
      prev_insn_branch = 0;
      prev_insn_group = 0;
    }

  if (free_relocs != NULL)
    {
      free (free_relocs);
      free_relocs = NULL;
    }

  if (free_contents != NULL)
    {
      if (! link_info->keep_memory)
       free (free_contents);
      else
       {
         /* Cache the section contents for elf_link_input_bfd.  */
         elf_section_data (sec)->this_hdr.contents = contents;
       }
      free_contents = NULL;
    }

  if (free_extsyms != NULL)
    {
      if (! link_info->keep_memory)
       free (free_extsyms);
      else
       {
         /* Cache the symbols for elf_link_input_bfd.  */
         symtab_hdr->contents = (unsigned char *) isymbuf;
       }
      free_extsyms = NULL;
    }

  return TRUE;

 error_return:
  if (free_relocs != NULL)
    free (free_relocs);
  if (free_contents != NULL)
    free (free_contents);
  if (free_extsyms != NULL)
    free (free_extsyms);
  return FALSE;
}

Here is the call graph for this function:

static bfd_boolean m68hc11_elf_size_one_stub ( struct bfd_hash_entry gen_entry,
void *  in_arg 
) [static]

Here is the caller graph for this function:

static bfd_boolean m68hc11_elf_size_one_stub ( struct bfd_hash_entry gen_entry,
void *in_arg  ATTRIBUTE_UNUSED 
) [static]

Definition at line 458 of file elf32-m68hc11.c.

{
  struct elf32_m68hc11_stub_hash_entry *stub_entry;

  /* Massage our args to the form they really have.  */
  stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;

  stub_entry->stub_sec->size += 10;
  return TRUE;
}
static void m68hc11_info_to_howto_rel ( bfd ,
arelent ,
Elf_Internal_Rela  
) [static]
static void m68hc11_info_to_howto_rel ( bfd *abfd  ATTRIBUTE_UNUSED,
arelent cache_ptr,
Elf_Internal_Rela dst 
) [static]

Definition at line 381 of file elf32-m68hc11.c.

{
  unsigned int r_type;

  r_type = ELF32_R_TYPE (dst->r_info);
  BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
  cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
}
static void m68hc11_relax_group ( bfd abfd,
asection sec,
bfd_byte contents,
unsigned  value,
unsigned long  offset,
unsigned long  end_group 
) [static]

Definition at line 560 of file elf32-m68hc11.c.

{
  unsigned char code;
  unsigned long start_offset;
  unsigned long ldx_offset = offset;
  unsigned long ldx_size;
  int can_delete_ldx;
  int relax_ldy = 0;

  /* First instruction of the relax group must be a
     LDX #value or LDY #value.  If this is not the case,
     ignore the relax group.  */
  code = bfd_get_8 (abfd, contents + offset);
  if (code == 0x18)
    {
      relax_ldy++;
      offset++;
      code = bfd_get_8 (abfd, contents + offset);
    }
  ldx_size = offset - ldx_offset + 3;
  offset += 3;
  if (code != M6811_OP_LDX_IMMEDIATE || offset >= end_group)
    return;


  /* We can remove the LDX/LDY only when all bset/brclr instructions
     of the relax group have been converted to use direct addressing
     mode.  */
  can_delete_ldx = 1;
  while (offset < end_group)
    {
      unsigned isize;
      unsigned new_value;
      int bset_use_y;

      bset_use_y = 0;
      start_offset = offset;
      code = bfd_get_8 (abfd, contents + offset);
      if (code == 0x18)
        {
          bset_use_y++;
          offset++;
          code = bfd_get_8 (abfd, contents + offset);
        }

      /* Check the instruction and translate to use direct addressing mode.  */
      switch (code)
        {
          /* bset */
        case 0x1C:
          code = 0x14;
          isize = 3;
          break;

          /* brclr */
        case 0x1F:
          code = 0x13;
          isize = 4;
          break;

          /* brset */
        case 0x1E:
          code = 0x12;
          isize = 4;
          break;

          /* bclr */
        case 0x1D:
          code = 0x15;
          isize = 3;
          break;

          /* This instruction is not recognized and we are not
             at end of the relax group.  Ignore and don't remove
             the first LDX (we don't know what it is used for...).  */
        default:
          return;
        }
      new_value = (unsigned) bfd_get_8 (abfd, contents + offset + 1);
      new_value += value;
      if ((new_value & 0xff00) == 0 && bset_use_y == relax_ldy)
        {
          bfd_put_8 (abfd, code, contents + offset);
          bfd_put_8 (abfd, new_value, contents + offset + 1);
          if (start_offset != offset)
            {
              m68hc11_elf_relax_delete_bytes (abfd, sec, start_offset,
                                              offset - start_offset);
              end_group--;
            }
        }
      else
        {
          can_delete_ldx = 0;
        }
      offset = start_offset + isize;
    }
  if (can_delete_ldx)
    {
      /* Remove the move instruction (3 or 4 bytes win).  */
      m68hc11_elf_relax_delete_bytes (abfd, sec, ldx_offset, ldx_size);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Initial value:
{
  { STRING_COMMA_LEN (".eeprom"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
  { STRING_COMMA_LEN (".page0"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
  { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
  { STRING_COMMA_LEN (".vectors"),  0, SHT_PROGBITS, SHF_ALLOC },
  { NULL,                       0,  0, 0,            0 }
}

Definition at line 1277 of file elf32-m68hc11.c.

reloc_howto_type elf_m68hc11_howto_table[] [static]

Definition at line 64 of file elf32-m68hc11.c.

Initial value:
 {
  {BFD_RELOC_NONE, R_M68HC11_NONE,},
  {BFD_RELOC_8, R_M68HC11_8},
  {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
  {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
  {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
  {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
  {BFD_RELOC_16, R_M68HC11_16},
  {BFD_RELOC_32, R_M68HC11_32},
  {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},

  {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
  {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},

  {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
  {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
  {BFD_RELOC_M68HC11_24, R_M68HC11_24},

  {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
  {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
}

Definition at line 322 of file elf32-m68hc11.c.