/* BFD back-end for Renesas H8/300 ELF binaries.
- Copyright 1993, 1995, 1998, 1999, 2001, 2002, 2003
- Free Software Foundation, Inc.
+ Copyright 1993, 1995, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2007 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/h8.h"
static reloc_howto_type *elf32_h8_reloc_type_lookup
- PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+ (bfd *abfd, bfd_reloc_code_real_type code);
static void elf32_h8_info_to_howto
- PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
+ (bfd *, arelent *, Elf_Internal_Rela *);
static void elf32_h8_info_to_howto_rel
- PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
-static unsigned long elf32_h8_mach
- PARAMS ((flagword));
-static void elf32_h8_final_write_processing
- PARAMS ((bfd *, bfd_boolean));
-static bfd_boolean elf32_h8_object_p
- PARAMS ((bfd *));
-static bfd_boolean elf32_h8_merge_private_bfd_data
- PARAMS ((bfd *, bfd *));
+ (bfd *, arelent *, Elf_Internal_Rela *);
+static unsigned long elf32_h8_mach (flagword);
+static void elf32_h8_final_write_processing (bfd *, bfd_boolean);
+static bfd_boolean elf32_h8_object_p (bfd *);
+static bfd_boolean elf32_h8_merge_private_bfd_data (bfd *, bfd *);
static bfd_boolean elf32_h8_relax_section
- PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
+ (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
static bfd_boolean elf32_h8_relax_delete_bytes
- PARAMS ((bfd *, asection *, bfd_vma, int));
-static bfd_boolean elf32_h8_symbol_address_p
- PARAMS ((bfd *, asection *, bfd_vma));
+ (bfd *, asection *, bfd_vma, int);
+static bfd_boolean elf32_h8_symbol_address_p (bfd *, asection *, bfd_vma);
static bfd_byte *elf32_h8_get_relocated_section_contents
- PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
- bfd_byte *, bfd_boolean, asymbol **));
+ (bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, bfd_boolean, asymbol **);
static bfd_reloc_status_type elf32_h8_final_link_relocate
- PARAMS ((unsigned long, bfd *, bfd *, asection *,
- bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
- struct bfd_link_info *, asection *, int));
+ (unsigned long, bfd *, bfd *, asection *,
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma,
+ struct bfd_link_info *, asection *, int);
static bfd_boolean elf32_h8_relocate_section
- PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
- bfd_byte *, Elf_Internal_Rela *,
- Elf_Internal_Sym *, asection **));
+ (bfd *, struct bfd_link_info *, bfd *, asection *,
+ bfd_byte *, Elf_Internal_Rela *,
+ Elf_Internal_Sym *, asection **);
static bfd_reloc_status_type special
- PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+ (bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
/* This does not include any relocation information, but should be
good enough for GDB or objdump to read the file. */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
special, /* special_function */
- "R_H8_DIR32", /* name */
+ "R_H8_DIR32A16", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
unsigned char howto_index;
};
-/* An array mapping BFD reloc codes to SH ELF relocs. */
+/* An array mapping BFD reloc codes to H8 ELF relocs. */
static const struct elf_reloc_map h8_reloc_map[] = {
{ BFD_RELOC_NONE, R_H8_NONE_X },
static reloc_howto_type *
-elf32_h8_reloc_type_lookup (abfd, code)
- bfd *abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type code;
+elf32_h8_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ bfd_reloc_code_real_type code)
{
unsigned int i;
return NULL;
}
+static reloc_howto_type *
+elf32_h8_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (h8_elf_howto_table) / sizeof (h8_elf_howto_table[0]);
+ i++)
+ if (h8_elf_howto_table[i].name != NULL
+ && strcasecmp (h8_elf_howto_table[i].name, r_name) == 0)
+ return &h8_elf_howto_table[i];
+
+ return NULL;
+}
+
static void
-elf32_h8_info_to_howto (abfd, bfd_reloc, elf_reloc)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *bfd_reloc;
- Elf_Internal_Rela *elf_reloc;
+elf32_h8_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc,
+ Elf_Internal_Rela *elf_reloc)
{
unsigned int r;
unsigned int i;
}
static void
-elf32_h8_info_to_howto_rel (abfd, bfd_reloc, elf_reloc)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *bfd_reloc;
- Elf_Internal_Rela *elf_reloc ATTRIBUTE_UNUSED;
+elf32_h8_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc,
+ Elf_Internal_Rela *elf_reloc ATTRIBUTE_UNUSED)
{
unsigned int r;
When doing -r, we can't do any arithmetic for the pcrel stuff, because
we support relaxing on the H8/300 series chips. */
static bfd_reloc_status_type
-special (abfd, reloc_entry, symbol, data, input_section, output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry ATTRIBUTE_UNUSED;
- asymbol *symbol ATTRIBUTE_UNUSED;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section ATTRIBUTE_UNUSED;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
+special (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *reloc_entry ATTRIBUTE_UNUSED,
+ asymbol *symbol ATTRIBUTE_UNUSED,
+ PTR data ATTRIBUTE_UNUSED,
+ asection *input_section ATTRIBUTE_UNUSED,
+ bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
{
if (output_bfd == (bfd *) NULL)
return bfd_reloc_continue;
/* Perform a relocation as part of a final link. */
static bfd_reloc_status_type
-elf32_h8_final_link_relocate (r_type, input_bfd, output_bfd,
- input_section, contents, offset, value,
- addend, info, sym_sec, is_local)
- unsigned long r_type;
- bfd *input_bfd;
- bfd *output_bfd ATTRIBUTE_UNUSED;
- asection *input_section ATTRIBUTE_UNUSED;
- bfd_byte *contents;
- bfd_vma offset;
- bfd_vma value;
- bfd_vma addend;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- asection *sym_sec ATTRIBUTE_UNUSED;
- int is_local ATTRIBUTE_UNUSED;
+elf32_h8_final_link_relocate (unsigned long r_type, bfd *input_bfd,
+ bfd *output_bfd ATTRIBUTE_UNUSED,
+ asection *input_section ATTRIBUTE_UNUSED,
+ bfd_byte *contents, bfd_vma offset,
+ bfd_vma value, bfd_vma addend,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ asection *sym_sec ATTRIBUTE_UNUSED,
+ int is_local ATTRIBUTE_UNUSED)
{
bfd_byte *hit_data = contents + offset;
switch (r_type)
{
-
case R_H8_NONE:
return bfd_reloc_ok;
value += addend;
/* HIT_DATA is the address for the first byte for the relocated
- value. Subtract 1 so that we can manipulate the data in 32bit
+ value. Subtract 1 so that we can manipulate the data in 32-bit
hunks. */
hit_data--;
/* Retrieve the type byte for value from the section contents. */
value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
- /* Now scribble it out in one 32bit hunk. */
+ /* Now scribble it out in one 32-bit hunk. */
bfd_put_32 (input_bfd, value, hit_data);
return bfd_reloc_ok;
\f
/* Relocate an H8 ELF section. */
static bfd_boolean
-elf32_h8_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, relocs, local_syms, local_sections)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- Elf_Internal_Rela *relocs;
- Elf_Internal_Sym *local_syms;
- asection **local_sections;
+elf32_h8_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
+ bfd *input_bfd, asection *input_section,
+ bfd_byte *contents, Elf_Internal_Rela *relocs,
+ Elf_Internal_Sym *local_syms,
+ asection **local_sections)
{
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
Elf_Internal_Rela *rel, *relend;
- if (info->relocateable)
- return TRUE;
-
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
struct elf_link_hash_entry *h;
bfd_vma relocation;
bfd_reloc_status_type r;
+ arelent bfd_reloc;
+ reloc_howto_type *howto;
+
+ elf32_h8_info_to_howto (input_bfd, &bfd_reloc, rel);
+ howto = bfd_reloc.howto;
- /* This is a final link. */
r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
h = NULL;
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
- relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
}
else
{
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- {
- sec = h->root.u.def.section;
- relocation = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
- }
- else if (h->root.type == bfd_link_hash_undefweak)
- relocation = 0;
- else
- {
- if (! ((*info->callbacks->undefined_symbol)
- (info, h->root.root.string, input_bfd,
- input_section, rel->r_offset, TRUE)))
- return FALSE;
- relocation = 0;
- }
+ bfd_boolean unresolved_reloc, warned;
+
+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+ r_symndx, symtab_hdr, sym_hashes,
+ h, sec, relocation,
+ unresolved_reloc, warned);
+ }
+
+ if (sec != NULL && elf_discarded_section (sec))
+ {
+ /* For relocs against symbols from removed linkonce sections,
+ or sections discarded by a linker script, we just want the
+ section contents zeroed. Avoid any special processing. */
+ _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+ rel->r_info = 0;
+ rel->r_addend = 0;
+ continue;
}
+ if (info->relocatable)
+ continue;
+
r = elf32_h8_final_link_relocate (r_type, input_bfd, output_bfd,
input_section,
contents, rel->r_offset,
{
const char *name;
const char *msg = (const char *) 0;
- arelent bfd_reloc;
- reloc_howto_type *howto;
-
- elf32_h8_info_to_howto (input_bfd, &bfd_reloc, rel);
- howto = bfd_reloc.howto;
if (h != NULL)
name = h->root.root.string;
{
case bfd_reloc_overflow:
if (! ((*info->callbacks->reloc_overflow)
- (info, name, howto->name, (bfd_vma) 0,
- input_bfd, input_section, rel->r_offset)))
+ (info, (h ? &h->root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section,
+ rel->r_offset)))
return FALSE;
break;
Examine that field and return the proper BFD machine type for
the object file. */
static unsigned long
-elf32_h8_mach (flags)
- flagword flags;
+elf32_h8_mach (flagword flags)
{
switch (flags & EF_H8_MACH)
{
case E_H8_MACH_H8300SN:
return bfd_mach_h8300sn;
+
+ case E_H8_MACH_H8300SX:
+ return bfd_mach_h8300sx;
+
+ case E_H8_MACH_H8300SXN:
+ return bfd_mach_h8300sxn;
}
}
into the flags field in the object file. */
static void
-elf32_h8_final_write_processing (abfd, linker)
- bfd *abfd;
- bfd_boolean linker ATTRIBUTE_UNUSED;
+elf32_h8_final_write_processing (bfd *abfd,
+ bfd_boolean linker ATTRIBUTE_UNUSED)
{
unsigned long val;
case bfd_mach_h8300sn:
val = E_H8_MACH_H8300SN;
break;
+
+ case bfd_mach_h8300sx:
+ val = E_H8_MACH_H8300SX;
+ break;
+
+ case bfd_mach_h8300sxn:
+ val = E_H8_MACH_H8300SXN;
+ break;
}
elf_elfheader (abfd)->e_flags &= ~ (EF_H8_MACH);
record the encoded machine type found in the ELF flags. */
static bfd_boolean
-elf32_h8_object_p (abfd)
- bfd *abfd;
+elf32_h8_object_p (bfd *abfd)
{
bfd_default_set_arch_mach (abfd, bfd_arch_h8300,
elf32_h8_mach (elf_elfheader (abfd)->e_flags));
time is the architecture/machine information. */
static bfd_boolean
-elf32_h8_merge_private_bfd_data (ibfd, obfd)
- bfd *ibfd;
- bfd *obfd;
+elf32_h8_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
{
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
&& bfd_get_mach (obfd) < bfd_get_mach (ibfd))
{
if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
- bfd_get_mach (ibfd)))
- return FALSE;
+ bfd_get_mach (ibfd)))
+ return FALSE;
}
return TRUE;
/* This function handles relaxing for the H8..
- There's a few relaxing opportunites available on the H8:
+ There are a few relaxing opportunities available on the H8:
jmp/jsr:24 -> bra/bsr:8 2 bytes
The jmp may be completely eliminated if the previous insn is a
bCC:16 -> bCC:8 2 bytes
bsr:16 -> bsr:8 2 bytes
+ bset:16 -> bset:8 2 bytes
+ bset:24/32 -> bset:8 4 bytes
+ (also applicable to other bit manipulation instructions)
+
mov.b:16 -> mov.b:8 2 bytes
mov.b:24/32 -> mov.b:8 4 bytes
+ bset:24/32 -> bset:16 2 bytes
+ (also applicable to other bit manipulation instructions)
+
mov.[bwl]:24/32 -> mov.[bwl]:16 2 bytes */
static bfd_boolean
-elf32_h8_relax_section (abfd, sec, link_info, again)
- bfd *abfd;
- asection *sec;
- struct bfd_link_info *link_info;
- bfd_boolean *again;
+elf32_h8_relax_section (bfd *abfd, asection *sec,
+ struct bfd_link_info *link_info, bfd_boolean *again)
{
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *internal_relocs;
/* Assume nothing changes. */
*again = FALSE;
- /* We don't have to do anything for a relocateable link, if
+ /* 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->relocateable
+ if (link_info->relocatable
|| (sec->flags & SEC_RELOC) == 0
|| sec->reloc_count == 0
|| (sec->flags & SEC_CODE) == 0)
return TRUE;
- /* If this is the first time we have been called for this section,
- initialize the cooked size. */
- if (sec->_cooked_size == 0)
- sec->_cooked_size = sec->_raw_size;
-
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
/* Get a copy of the native relocations. */
{
bfd_vma symval;
+ {
+ arelent bfd_reloc;
+ reloc_howto_type *h;
+
+ elf32_h8_info_to_howto (abfd, &bfd_reloc, irel);
+ h = bfd_reloc.howto;
+ }
/* Keep track of the previous reloc so that we can delete
some long jumps created by the compiler. */
if (irel != internal_relocs)
else
{
/* Go get them off disk. */
- contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
- if (contents == NULL)
- goto error_return;
-
- if (! bfd_get_section_contents (abfd, sec, contents,
- (file_ptr) 0, sec->_raw_size))
+ if (!bfd_malloc_and_get_section (abfd, sec, &contents))
goto error_return;
}
}
the linker is run. */
switch (ELF32_R_TYPE (irel->r_info))
{
- /* Try to turn a 24 bit absolute branch/call into an 8 bit
+ /* Try to turn a 24-bit absolute branch/call into an 8-bit
pc-relative branch/call. */
case R_H8_DIR24R8:
{
}
if (code == 0x5e)
+ /* This is jsr. */
bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 1);
else if (code == 0x5a)
+ /* This is jmp. */
bfd_put_8 (abfd, 0x40, contents + irel->r_offset - 1);
else
abort ();
break;
}
- /* Try to turn a 16bit pc-relative branch into a 8bit pc-relative
+ /* Try to turn a 16-bit pc-relative branch into a 8-bit pc-relative
branch. */
case R_H8_PCREL16:
{
if (code == 0x58)
{
/* bCC:16 -> bCC:8 */
- /* Get the condition code from the original insn. */
+ /* Get the second byte of the original insn, which
+ contains the condition code. */
code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
+
+ /* Compute the fisrt byte of the relaxed
+ instruction. The original sequence 0x58 0xX0
+ is relaxed to 0x4X, where X represents the
+ condition code. */
code &= 0xf0;
code >>= 4;
code |= 0x40;
bfd_put_8 (abfd, code, contents + irel->r_offset - 2);
}
else if (code == 0x5c)
+ /* This is bsr. */
bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 2);
else
- abort ();
+ /* Might be MOVSD. */
+ break;
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
break;
}
- /* This is a 16 bit absolute address in a "mov.b" insn, which may
- become an 8 bit absolute address if its in the right range. */
+ /* This is a 16-bit absolute address in one of the following
+ instructions:
+
+ "band", "bclr", "biand", "bild", "bior", "bist", "bixor",
+ "bld", "bnot", "bor", "bset", "bst", "btst", "bxor", and
+ "mov.b"
+
+ We may relax this into an 8-bit absolute address if it's in
+ the right range. */
case R_H8_DIR16A8:
{
- bfd_vma value = symval + irel->r_addend;
+ bfd_vma value;
- if ((bfd_get_mach (abfd) == bfd_mach_h8300
- && value >= 0xff00
- && value <= 0xffff)
- || ((bfd_get_mach (abfd) == bfd_mach_h8300h
- || bfd_get_mach (abfd) == bfd_mach_h8300s)
- && value >= 0xffff00
- && value <= 0xffffff))
+ value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
+ if (value >= 0xffffff00u)
{
unsigned char code;
+ unsigned char temp_code;
/* Note that we've changed the relocs, section contents,
etc. */
/* Get the opcode. */
code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
- /* Sanity check. */
+ /* All instructions with R_H8_DIR16A8 start with
+ 0x6a. */
if (code != 0x6a)
abort ();
- code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
+ temp_code = code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
+ /* If this is a mov.b instruction, clear the lower
+ nibble, which contains the source/destination
+ register number. */
+ if ((temp_code & 0x10) != 0x10)
+ temp_code &= 0xf0;
- if ((code & 0xf0) == 0x00)
- bfd_put_8 (abfd,
- (code & 0xf) | 0x20,
- contents + irel->r_offset - 2);
- else if ((code & 0xf0) == 0x80)
- bfd_put_8 (abfd,
- (code & 0xf) | 0x30,
- contents + irel->r_offset - 2);
- else
- abort ();
+ switch (temp_code)
+ {
+ case 0x00:
+ /* This is mov.b @aa:16,Rd. */
+ bfd_put_8 (abfd, (code & 0xf) | 0x20,
+ contents + irel->r_offset - 2);
+ break;
+ case 0x80:
+ /* This is mov.b Rs,@aa:16. */
+ bfd_put_8 (abfd, (code & 0xf) | 0x30,
+ contents + irel->r_offset - 2);
+ break;
+ case 0x18:
+ /* This is a bit-maniputation instruction that
+ stores one bit into memory, one of "bclr",
+ "bist", "bnot", "bset", and "bst". */
+ bfd_put_8 (abfd, 0x7f, contents + irel->r_offset - 2);
+ break;
+ case 0x10:
+ /* This is a bit-maniputation instruction that
+ loads one bit from memory, one of "band",
+ "biand", "bild", "bior", "bixor", "bld", "bor",
+ "btst", and "bxor". */
+ bfd_put_8 (abfd, 0x7e, contents + irel->r_offset - 2);
+ break;
+ default:
+ abort ();
+ }
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_H8_DIR8);
+ /* Move the relocation. */
+ irel->r_offset--;
+
/* Delete two bytes of data. */
if (!elf32_h8_relax_delete_bytes (abfd, sec,
irel->r_offset + 1, 2))
break;
}
- /* This is a 24 bit absolute address in a "mov.b" insn, which may
- become an 8 bit absolute address if its in the right range. */
+ /* This is a 24-bit absolute address in one of the following
+ instructions:
+
+ "band", "bclr", "biand", "bild", "bior", "bist", "bixor",
+ "bld", "bnot", "bor", "bset", "bst", "btst", "bxor", and
+ "mov.b"
+
+ We may relax this into an 8-bit absolute address if it's in
+ the right range. */
case R_H8_DIR24A8:
{
- bfd_vma value = symval + irel->r_addend;
+ bfd_vma value;
- if ((bfd_get_mach (abfd) == bfd_mach_h8300
- && value >= 0xff00
- && value <= 0xffff)
- || ((bfd_get_mach (abfd) == bfd_mach_h8300h
- || bfd_get_mach (abfd) == bfd_mach_h8300s)
- && value >= 0xffff00
- && value <= 0xffffff))
+ value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
+ if (value >= 0xffffff00u)
{
- bfd_boolean skip = FALSE;
unsigned char code;
+ unsigned char temp_code;
/* Note that we've changed the relocs, section contents,
etc. */
/* Get the opcode. */
code = bfd_get_8 (abfd, contents + irel->r_offset - 2);
- /* Sanity check. */
+ /* All instructions with R_H8_DIR24A8 start with
+ 0x6a. */
if (code != 0x6a)
abort ();
- code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
+ temp_code = code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
+
+ /* If this is a mov.b instruction, clear the lower
+ nibble, which contains the source/destination
+ register number. */
+ if ((temp_code & 0x30) != 0x30)
+ temp_code &= 0xf0;
- switch (code & 0xf0)
+ switch (temp_code)
{
- case 0x00:
+ case 0x20:
+ /* This is mov.b @aa:24/32,Rd. */
bfd_put_8 (abfd, (code & 0xf) | 0x20,
contents + irel->r_offset - 2);
break;
- case 0x80:
+ case 0xa0:
+ /* This is mov.b Rs,@aa:24/32. */
bfd_put_8 (abfd, (code & 0xf) | 0x30,
contents + irel->r_offset - 2);
break;
- case 0x20:
- case 0xa0:
- /* Skip 32bit versions. */
- skip = TRUE;
+ case 0x38:
+ /* This is a bit-maniputation instruction that
+ stores one bit into memory, one of "bclr",
+ "bist", "bnot", "bset", and "bst". */
+ bfd_put_8 (abfd, 0x7f, contents + irel->r_offset - 2);
+ break;
+ case 0x30:
+ /* This is a bit-maniputation instruction that
+ loads one bit from memory, one of "band",
+ "biand", "bild", "bior", "bixor", "bld", "bor",
+ "btst", and "bxor". */
+ bfd_put_8 (abfd, 0x7e, contents + irel->r_offset - 2);
break;
default:
- abort ();
+ abort();
}
- if (skip)
- break;
-
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
R_H8_DIR8);
+ irel->r_offset--;
/* Delete two bytes of data. */
- if (!elf32_h8_relax_delete_bytes (abfd, sec, irel->r_offset, 2))
+ if (!elf32_h8_relax_delete_bytes (abfd, sec,
+ irel->r_offset + 1, 4))
goto error_return;
/* That will change things, so, we should relax again.
Note that this is not required, and it may be slow. */
*again = TRUE;
+ break;
}
}
- /* FALLTHRU */
+ /* Fall through. */
+
+ /* This is a 24-/32-bit absolute address in one of the
+ following instructions:
- /* This is a 24/32bit absolute address in a "mov" insn, which may
- become a 16bit absoulte address if it is in the right range. */
+ "band", "bclr", "biand", "bild", "bior", "bist",
+ "bixor", "bld", "bnot", "bor", "bset", "bst", "btst",
+ "bxor", "ldc.w", "stc.w" and "mov.[bwl]"
+
+ We may relax this into an 16-bit absolute address if it's
+ in the right range. */
case R_H8_DIR32A16:
{
- bfd_vma value = symval + irel->r_addend;
+ bfd_vma value;
- if (value <= 0x7fff || value >= 0xff8000)
+ value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
+ if (value <= 0x7fff || value >= 0xffff8000u)
{
unsigned char code;
+ unsigned char op0, op1, op2, op3;
+ unsigned char *op_ptr;
/* Note that we've changed the relocs, section contents,
etc. */
elf_section_data (sec)->this_hdr.contents = contents;
symtab_hdr->contents = (unsigned char *) isymbuf;
+ if (irel->r_offset >= 4)
+ {
+ /* Check for 4-byte MOVA relaxation. */
+ int second_reloc = 0;
+
+ op_ptr = contents + irel->r_offset - 4;
+
+ if (last_reloc)
+ {
+ arelent bfd_reloc;
+ reloc_howto_type *h;
+ bfd_vma last_reloc_size;
+
+ elf32_h8_info_to_howto (abfd, &bfd_reloc, last_reloc);
+ h = bfd_reloc.howto;
+ last_reloc_size = 1 << h->size;
+ if (last_reloc->r_offset + last_reloc_size
+ == irel->r_offset)
+ {
+ op_ptr -= last_reloc_size;
+ second_reloc = 1;
+ }
+ }
+ if (irel < irelend)
+ {
+ Elf_Internal_Rela *next_reloc = irel + 1;
+ arelent bfd_reloc;
+ reloc_howto_type *h;
+ bfd_vma next_reloc_size;
+
+ elf32_h8_info_to_howto (abfd, &bfd_reloc, next_reloc);
+ h = bfd_reloc.howto;
+ next_reloc_size = 1 << h->size;
+ if (next_reloc->r_offset + next_reloc_size
+ == irel->r_offset)
+ {
+ op_ptr -= next_reloc_size;
+ second_reloc = 1;
+ }
+ }
+
+ op0 = bfd_get_8 (abfd, op_ptr + 0);
+ op1 = bfd_get_8 (abfd, op_ptr + 1);
+ op2 = bfd_get_8 (abfd, op_ptr + 2);
+ op3 = bfd_get_8 (abfd, op_ptr + 3);
+
+ if (op0 == 0x01
+ && (op1 & 0xdf) == 0x5f
+ && (op2 & 0x40) == 0x40
+ && (op3 & 0x80) == 0x80)
+ {
+ if ((op2 & 0x08) == 0)
+ second_reloc = 1;
+
+ if (second_reloc)
+ {
+ op3 &= ~0x08;
+ bfd_put_8 (abfd, op3, op_ptr + 3);
+ }
+ else
+ {
+ op2 &= ~0x08;
+ bfd_put_8 (abfd, op2, op_ptr + 2);
+ }
+ goto r_h8_dir32a16_common;
+ }
+ }
+
+ /* Now check for short version of MOVA. */
+ op_ptr = contents + irel->r_offset - 2;
+ op0 = bfd_get_8 (abfd, op_ptr + 0);
+ op1 = bfd_get_8 (abfd, op_ptr + 1);
+
+ if (op0 == 0x7a
+ && (op1 & 0x88) == 0x80)
+ {
+ op1 |= 0x08;
+ bfd_put_8 (abfd, op1, op_ptr + 1);
+ goto r_h8_dir32a16_common;
+ }
+
/* Get the opcode. */
code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
- /* We just need to turn off bit 0x20. */
+ /* Fix the opcode. For all the instructions that
+ belong to this relaxation, we simply need to turn
+ off bit 0x20 in the previous byte. */
code &= ~0x20;
bfd_put_8 (abfd, code, contents + irel->r_offset - 1);
+ r_h8_dir32a16_common:
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
- R_H8_DIR16A8);
+ R_H8_DIR16);
/* Delete two bytes of data. */
if (!elf32_h8_relax_delete_bytes (abfd, sec,
/* Delete some bytes from a section while relaxing. */
static bfd_boolean
-elf32_h8_relax_delete_bytes (abfd, sec, addr, count)
- bfd *abfd;
- asection *sec;
- bfd_vma addr;
- int count;
+elf32_h8_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, int count)
{
Elf_Internal_Shdr *symtab_hdr;
unsigned int sec_shndx;
power larger than the number of bytes we are deleting. */
irelalign = NULL;
- toaddr = sec->_cooked_size;
+ 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->_cooked_size -= count;
+ sec->size -= count;
/* Adjust all the relocs. */
for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
/* Return TRUE if a symbol exists at the given address, else return
FALSE. */
static bfd_boolean
-elf32_h8_symbol_address_p (abfd, sec, addr)
- bfd *abfd;
- asection *sec;
- bfd_vma addr;
+elf32_h8_symbol_address_p (bfd *abfd, asection *sec, bfd_vma addr)
{
Elf_Internal_Shdr *symtab_hdr;
unsigned int sec_shndx;
which uses elf32_h8_relocate_section. */
static bfd_byte *
-elf32_h8_get_relocated_section_contents (output_bfd, link_info, link_order,
- data, relocateable, symbols)
- bfd *output_bfd;
- struct bfd_link_info *link_info;
- struct bfd_link_order *link_order;
- bfd_byte *data;
- bfd_boolean relocateable;
- asymbol **symbols;
+elf32_h8_get_relocated_section_contents (bfd *output_bfd,
+ struct bfd_link_info *link_info,
+ struct bfd_link_order *link_order,
+ bfd_byte *data,
+ bfd_boolean relocatable,
+ asymbol **symbols)
{
Elf_Internal_Shdr *symtab_hdr;
asection *input_section = link_order->u.indirect.section;
/* We only need to handle the case of relaxing, or of having a
particular set of section contents, specially. */
- if (relocateable
+ if (relocatable
|| elf_section_data (input_section)->this_hdr.contents == NULL)
return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
link_order, data,
- relocateable,
+ relocatable,
symbols);
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
memcpy (data, elf_section_data (input_section)->this_hdr.contents,
- (size_t) input_section->_raw_size);
+ (size_t) input_section->size);
if ((input_section->flags & SEC_RELOC) != 0
&& input_section->reloc_count > 0)
#define ELF_MACHINE_CODE EM_H8_300
#define ELF_MAXPAGESIZE 0x1
#define bfd_elf32_bfd_reloc_type_lookup elf32_h8_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup elf32_h8_reloc_name_lookup
#define elf_info_to_howto elf32_h8_info_to_howto
#define elf_info_to_howto_rel elf32_h8_info_to_howto_rel
/* ??? when elf_backend_relocate_section is not defined, elf32-target.h
defaults to using _bfd_generic_link_hash_table_create, but
- elflink.h:bfd_elf32_size_dynamic_sections uses
+ bfd_elf_size_dynamic_sections uses
dynobj = elf_hash_table (info)->dynobj;
and thus requires an elf hash table. */
#define bfd_elf32_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
/* Use an H8 specific linker, not the ELF generic linker. */
#define elf_backend_relocate_section elf32_h8_relocate_section
#define elf_backend_rela_normal 1
+#define elf_backend_can_gc_sections 1
/* And relaxing stuff. */
#define bfd_elf32_bfd_relax_section elf32_h8_relax_section