bfd/
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index ae553b4cb46df178a1b0231178727608953cdafa..9ec9c86dcb0547b1425d48546685e0dc1f4ed479 100644 (file)
@@ -3352,7 +3352,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       else
        {
          value = (_bfd_mips_elf_sign_extend (addend, 28) + symbol) >> 2;
-         overflowed_p = (value >> 26) != ((p + 4) >> 28);
+         if (h->root.root.type != bfd_link_hash_undefweak)
+           overflowed_p = (value >> 26) != ((p + 4) >> 28);
        }
       value &= howto->dst_mask;
       break;
@@ -3523,12 +3524,16 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       value &= howto->dst_mask;
       break;
 
-    case R_MIPS_PJUMP:
     case R_MIPS_JALR:
-      /* Both of these may be ignored.  R_MIPS_JALR is an optimization
-        hint; we could improve performance by honoring that hint.  */
-      return bfd_reloc_continue;
+      /* This relocation is only a hint.  In some cases, we optimize
+        it into a bal instruction.  But we don't try to optimize
+        branches to the PLT; that will wind up wasting time.  */
+      if (h != NULL && h->root.plt.offset != (bfd_vma) -1)
+       return bfd_reloc_continue;
+      value = symbol + addend;
+      break;
 
+    case R_MIPS_PJUMP:
     case R_MIPS_GNU_VTINHERIT:
     case R_MIPS_GNU_VTENTRY:
       /* We don't do anything with these at present.  */
@@ -3730,6 +3735,33 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
       x = (x & ~(0x3f << 26)) | (jalx_opcode << 26);
     }
 
+  /* On the RM9000, bal is faster than jal, because bal uses branch
+     prediction hardware.  If we are linking for the RM9000, and we
+     see jal, and bal fits, use it instead.  Note that this
+     transformation should be safe for all architectures.  */
+  if (bfd_get_mach (input_bfd) == bfd_mach_mips9000
+      && !info->relocatable
+      && !require_jalx
+      && ((r_type == R_MIPS_26 && (x >> 26) == 0x3)        /* jal addr */
+         || (r_type == R_MIPS_JALR && x == 0x0320f809)))   /* jalr t9 */
+    {
+      bfd_vma addr;
+      bfd_vma dest;
+      bfd_signed_vma off;
+
+      addr = (input_section->output_section->vma
+             + input_section->output_offset
+             + relocation->r_offset
+             + 4);
+      if (r_type == R_MIPS_26)
+       dest = (value << 2) | ((addr >> 28) << 28);
+      else
+       dest = value;
+      off = dest - addr;
+      if (off <= 0x1ffff && off >= -0x20000)
+       x = 0x04110000 | (((bfd_vma) off >> 2) & 0xffff);   /* bal addr */
+    }
+
   /* Swap the high- and low-order 16 bits on little-endian systems
      when doing a MIPS16 relocation.  */
   if ((r_type == R_MIPS16_GPREL || r_type == R_MIPS16_26)
@@ -4023,6 +4055,9 @@ _bfd_elf_mips_mach (flagword flags)
     case E_MIPS_MACH_5500:
       return bfd_mach_mips5500;
 
+    case E_MIPS_MACH_9000:
+      return bfd_mach_mips9000;
+
     case E_MIPS_MACH_SB1:
       return bfd_mach_mips_sb1;
 
@@ -7073,6 +7108,10 @@ mips_set_isa_flags (bfd *abfd)
       val = E_MIPS_ARCH_4 | E_MIPS_MACH_5500;
       break;
 
+    case bfd_mach_mips9000:
+      val = E_MIPS_ARCH_4 | E_MIPS_MACH_9000;
+      break;
+
     case bfd_mach_mips5000:
     case bfd_mach_mips7000:
     case bfd_mach_mips8000:
@@ -8803,6 +8842,7 @@ static const struct mips_mach_extension mips_mach_extensions[] = {
   { bfd_mach_mips10000, bfd_mach_mips8000 },
   { bfd_mach_mips5000, bfd_mach_mips8000 },
   { bfd_mach_mips7000, bfd_mach_mips8000 },
+  { bfd_mach_mips9000, bfd_mach_mips8000 },
 
   /* VR4100 extensions.  */
   { bfd_mach_mips4120, bfd_mach_mips4100 },
This page took 0.025401 seconds and 4 git commands to generate.