Adds code to the MSP430 linker to transform a 4-byte BR instruction into
[deliverable/binutils-gdb.git] / bfd / elf32-msp430.c
index 3d8d22f3776f02dd5e9f81518056d3c8f8f0b953..2157eb0c5d0eeb75089e4cd2a37d23810abd6fee 100644 (file)
@@ -1,5 +1,5 @@
 /*  MSP430-specific support for 32-bit ELF
-    Copyright (C) 2002-2013 Free Software Foundation, Inc.
+    Copyright (C) 2002-2015 Free Software Foundation, Inc.
     Contributed by Dmitry Diky <diwil@mail.ru>
 
     This file is part of BFD, the Binary File Descriptor library.
@@ -549,10 +549,10 @@ static const struct msp430_reloc_map msp430x_reloc_map[] =
 static inline bfd_boolean
 uses_msp430x_relocs (bfd * abfd)
 {
-  extern const bfd_target bfd_elf32_msp430_ti_vec;
+  extern const bfd_target msp430_elf32_ti_vec;
 
   return bfd_get_mach (abfd) == bfd_mach_msp430x
-    || abfd->xvec == & bfd_elf32_msp430_ti_vec;
+    || abfd->xvec == & msp430_elf32_ti_vec;
 }
 
 static reloc_howto_type *
@@ -617,12 +617,20 @@ msp430_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
 
   if (uses_msp430x_relocs (abfd))
     {
-      BFD_ASSERT (r_type < (unsigned int) R_MSP430x_max);
+      if (r_type >= (unsigned int) R_MSP430x_max)
+       {
+         _bfd_error_handler (_("%A: invalid MSP430X reloc number: %d"), abfd, r_type);
+         r_type = 0;
+       }
       cache_ptr->howto = elf_msp430x_howto_table + r_type;
       return;
     }
 
-  BFD_ASSERT (r_type < (unsigned int) R_MSP430_max);
+  if (r_type >= (unsigned int) R_MSP430_max)
+    {
+      _bfd_error_handler (_("%A: invalid MSP430 reloc number: %d"), abfd, r_type);
+      r_type = 0;
+    }
   cache_ptr->howto = &elf_msp430_howto_table[r_type];
 }
 
@@ -1582,14 +1590,15 @@ msp430_elf_relax_adjust_locals (bfd * abfd, asection * sec, bfd_vma addr,
   irelend = irel + sec->reloc_count;
   symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
   isym = (Elf_Internal_Sym *) symtab_hdr->contents;
-  
+
   for (;irel < irelend; irel++)
     {
-      int sidx = ELF32_R_SYM(irel->r_info);
+      unsigned int sidx = ELF32_R_SYM(irel->r_info);
       Elf_Internal_Sym *lsym = isym + sidx;
-      
+
       /* Adjust symbols referenced by .sec+0xXX */
-      if (irel->r_addend > addr && irel->r_addend < toaddr 
+      if (irel->r_addend > addr && irel->r_addend < toaddr
+         && sidx < symtab_hdr->sh_info
          && lsym->st_shndx == sec_shndx)
        irel->r_addend -= count;
     }
@@ -1759,7 +1768,6 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
   bfd_byte *          contents = NULL;
   Elf_Internal_Sym *  isymbuf = NULL;
 
-
   /* Assume nothing changes.  */
   *again = FALSE;
 
@@ -1957,10 +1965,6 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
       *again = TRUE;
     }
 
-  if (! uses_msp430x_relocs (abfd))
-    /* Now perform the relocations that shrink the code size.
-       We only do this for non msp430x as gas only generates the RL
-       reloc for the msp430.  */
     for (irel = internal_relocs; irel < irelend; irel++)
       {
        bfd_vma symval;
@@ -2039,7 +2043,8 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
        /* Try to turn a 16bit pc-relative branch into a 10bit pc-relative
           branch.  */
        /* Paranoia? paranoia...  */      
-       if (ELF32_R_TYPE (irel->r_info) == (int) R_MSP430_RL_PCREL)
+       if (! uses_msp430x_relocs (abfd)
+           && ELF32_R_TYPE (irel->r_info) == (int) R_MSP430_RL_PCREL)
          {
            bfd_vma value = symval;
 
@@ -2149,6 +2154,62 @@ msp430_elf_relax_section (bfd * abfd, asection * sec,
                *again = TRUE;
              }
          }
+
+       /* Try to turn a 16-bit absolute branch into a 10-bit pc-relative
+          branch.  */
+       if (uses_msp430x_relocs (abfd)
+           && ELF32_R_TYPE (irel->r_info) == R_MSP430X_ABS16)
+         {
+           bfd_vma value = symval;
+
+           value -= irel->r_offset;
+           value += irel->r_addend;
+          
+           /* See if the value will fit in 10 bits, note the high value is
+              1016 as the target will be two bytes closer if we are
+              able to relax.  */
+           if ((long) value < 1016 && (long) value > -1016)
+             {
+               int code2;
+
+               /* Get the opcode.  */
+               code2 = bfd_get_16 (abfd, contents + irel->r_offset - 2);
+               if (code2 != 0x4030)
+                 continue;
+               /* FIXME: check r4 and r3 ? */
+               /* FIXME: Handle 0x4010 as well ?  */
+
+               /* Note that we've changed the relocs, section contents, etc.  */
+               elf_section_data (sec)->relocs = internal_relocs;
+               elf_section_data (sec)->this_hdr.contents = contents;
+               symtab_hdr->contents = (unsigned char *) isymbuf;
+
+               /* Fix the relocation's type.  */
+               if (uses_msp430x_relocs (abfd))
+                 {
+                   irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+                                                R_MSP430X_10_PCREL);
+                 }
+               else
+                 {
+                   irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+                                                R_MSP430_10_PCREL);
+                 }
+
+               /* Fix the opcode right way.  */
+               bfd_put_16 (abfd, 0x3c00, contents + irel->r_offset - 2);
+               irel->r_offset -= 2;
+
+               /* Delete bytes.  */
+               if (!msp430_elf_relax_delete_bytes (abfd, sec,
+                                                   irel->r_offset + 2, 2))
+                 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;
+             }
+         }
       }
 
   if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
@@ -2436,7 +2497,7 @@ msp430_elf_is_target_special_symbol (bfd *abfd, asymbol *sym)
 #define ELF_MAXPAGESIZE                4
 #define        ELF_OSABI               ELFOSABI_STANDALONE
 
-#define TARGET_LITTLE_SYM       bfd_elf32_msp430_vec
+#define TARGET_LITTLE_SYM       msp430_elf32_vec
 #define TARGET_LITTLE_NAME     "elf32-msp430"
 
 #define elf_info_to_howto                   msp430_info_to_howto_rela
@@ -2446,7 +2507,6 @@ msp430_elf_is_target_special_symbol (bfd *abfd, asymbol *sym)
 #define elf_backend_can_gc_sections          1
 #define elf_backend_final_write_processing   bfd_elf_msp430_final_write_processing
 #define elf_backend_object_p                elf32_msp430_object_p
-#define elf_backend_post_process_headers     _bfd_elf_set_osabi
 #define bfd_elf32_bfd_relax_section         msp430_elf_relax_section
 #define bfd_elf32_bfd_is_target_special_symbol msp430_elf_is_target_special_symbol
 
@@ -2457,7 +2517,7 @@ msp430_elf_is_target_special_symbol (bfd *abfd, asymbol *sym)
 
 /* The TI compiler sets the OSABI field to ELFOSABI_NONE.  */
 #undef  TARGET_LITTLE_SYM
-#define TARGET_LITTLE_SYM       bfd_elf32_msp430_ti_vec
+#define TARGET_LITTLE_SYM       msp430_elf32_ti_vec
 
 #undef  elf32_bed
 #define elf32_bed              elf32_msp430_ti_bed
This page took 0.025685 seconds and 4 git commands to generate.