Line 1... |
Line 1... |
/* BFD back-end for Renesas H8/300 ELF binaries.
|
/* BFD back-end for Renesas H8/300 ELF binaries.
|
Copyright 1993, 1995, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006,
|
Copyright 1993, 1995, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006,
|
2007 Free Software Foundation, Inc.
|
2007, 2009 Free Software Foundation, Inc.
|
|
|
This file is part of BFD, the Binary File Descriptor library.
|
This file is part of BFD, the Binary File Descriptor library.
|
|
|
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
Line 720... |
Line 720... |
irelend = internal_relocs + sec->reloc_count;
|
irelend = internal_relocs + sec->reloc_count;
|
for (irel = internal_relocs; irel < irelend; irel++)
|
for (irel = internal_relocs; irel < irelend; irel++)
|
{
|
{
|
bfd_vma symval;
|
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
|
/* Keep track of the previous reloc so that we can delete
|
some long jumps created by the compiler. */
|
some long jumps created by the compiler. */
|
if (irel != internal_relocs)
|
if (irel != internal_relocs)
|
last_reloc = irel - 1;
|
last_reloc = irel - 1;
|
|
|
Line 992... |
Line 999... |
}
|
}
|
else if (code == 0x5c)
|
else if (code == 0x5c)
|
/* This is bsr. */
|
/* This is bsr. */
|
bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 2);
|
bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 2);
|
else
|
else
|
abort ();
|
/* Might be MOVSD. */
|
|
break;
|
|
|
/* Fix the relocation's type. */
|
/* Fix the relocation's type. */
|
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
R_H8_PCREL8);
|
R_H8_PCREL8);
|
irel->r_offset--;
|
irel->r_offset--;
|
Line 1205... |
Line 1213... |
|
|
value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
|
value = bfd_h8300_pad_address (abfd, symval + irel->r_addend);
|
if (value <= 0x7fff || value >= 0xffff8000u)
|
if (value <= 0x7fff || value >= 0xffff8000u)
|
{
|
{
|
unsigned char code;
|
unsigned char code;
|
|
unsigned char op0, op1, op2, op3;
|
|
unsigned char *op_ptr;
|
|
|
/* Note that we've changed the relocs, section contents,
|
/* Note that we've changed the relocs, section contents,
|
etc. */
|
etc. */
|
elf_section_data (sec)->relocs = internal_relocs;
|
elf_section_data (sec)->relocs = internal_relocs;
|
elf_section_data (sec)->this_hdr.contents = contents;
|
elf_section_data (sec)->this_hdr.contents = contents;
|
symtab_hdr->contents = (unsigned char *) isymbuf;
|
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. */
|
/* Get the opcode. */
|
code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
|
code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
|
|
|
/* Fix the opcode. For all the instructions that
|
/* Fix the opcode. For all the instructions that
|
belong to this relaxation, we simply need to turn
|
belong to this relaxation, we simply need to turn
|
off bit 0x20 in the previous byte. */
|
off bit 0x20 in the previous byte. */
|
code &= ~0x20;
|
code &= ~0x20;
|
|
|
bfd_put_8 (abfd, code, contents + irel->r_offset - 1);
|
bfd_put_8 (abfd, code, contents + irel->r_offset - 1);
|
|
|
|
r_h8_dir32a16_common:
|
/* Fix the relocation's type. */
|
/* Fix the relocation's type. */
|
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
R_H8_DIR16);
|
R_H8_DIR16);
|
|
|
/* Delete two bytes of data. */
|
/* Delete two bytes of data. */
|