X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-h8300.c;h=ea54112a11e85e9f7083e1e440f8f659617a2eb0;hb=e9e0a58e87c33963dda1800900c0e43b7c0213c0;hp=17e8e30f68dff0391f0a31da0e509bb27f2a4f9b;hpb=3db64b009284dda3a1ce10a91beb1297475e60a7;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-h8300.c b/bfd/elf32-h8300.c index 17e8e30f68..ea54112a11 100644 --- a/bfd/elf32-h8300.c +++ b/bfd/elf32-h8300.c @@ -6,7 +6,7 @@ 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, @@ -16,7 +16,8 @@ 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ #include "sysdep.h" #include "bfd.h" @@ -721,6 +722,13 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, { 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) @@ -993,7 +1001,8 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, /* 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), @@ -1206,6 +1215,8 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, 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. */ @@ -1213,6 +1224,87 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, 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); @@ -1223,6 +1315,7 @@ elf32_h8_relax_section (bfd *abfd, asection *sec, 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_DIR16);