Delete duplicate target short-cuts to dynamic sections
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index b4438765d156c010573c51ac8daf8a6e475b20db..029ea1c80d25d0eeedd1ba82c80169a9506a1a5a 100644 (file)
@@ -1,5 +1,5 @@
 /* MIPS-specific support for ELF
-   Copyright 1993-2013 Free Software Foundation, Inc.
+   Copyright (C) 1993-2016 Free Software Foundation, Inc.
 
    Most of the information added by Ian Lance Taylor, Cygnus Support,
    <ian@cygnus.com>.
@@ -36,6 +36,7 @@
 #include "elfxx-mips.h"
 #include "elf/mips.h"
 #include "elf-vxworks.h"
+#include "dwarf2.h"
 
 /* Get the ECOFF swapping routines.  */
 #include "coff/sym.h"
@@ -168,8 +169,10 @@ struct mips_got_info
   unsigned int page_gotno;
   /* The number of relocations needed for the GOT entries.  */
   unsigned int relocs;
-  /* The number of local .got entries we have used.  */
-  unsigned int assigned_gotno;
+  /* The first unused local .got entry.  */
+  unsigned int assigned_low_gotno;
+  /* The last unused local .got entry.  */
+  unsigned int assigned_high_gotno;
   /* A hash table holding members of the got.  */
   struct htab *got_entries;
   /* A hash table holding mips_got_page_ref structures.  */
@@ -450,12 +453,8 @@ struct mips_elf_link_hash_table
      being used.  */
   asection *srelbss;
   asection *sdynbss;
-  asection *srelplt;
   asection *srelplt2;
-  asection *sgotplt;
-  asection *splt;
   asection *sstubs;
-  asection *sgot;
 
   /* The master GOT information.  */
   struct mips_got_info *got_info;
@@ -542,6 +541,13 @@ struct mips_elf_obj_tdata
   /* Input BFD providing Tag_GNU_MIPS_ABI_FP attribute for output.  */
   bfd *abi_fp_bfd;
 
+  /* Input BFD providing Tag_GNU_MIPS_ABI_MSA attribute for output.  */
+  bfd *abi_msa_bfd;
+
+  /* The abiflags for this object.  */
+  Elf_Internal_ABIFlags_v0 abiflags;
+  bfd_boolean abiflags_valid;
+
   /* The GOT requirements of input bfds.  */
   struct mips_got_info *got;
 
@@ -771,6 +777,10 @@ static bfd *reldyn_sorting_bfd;
 #define PIC_OBJECT_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_PIC) != 0)
 
+/* Nonzero if ABFD is using the O32 ABI.  */
+#define ABI_O32_P(abfd) \
+  ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI) == E_MIPS_ABI_O32)
+
 /* Nonzero if ABFD is using the N32 ABI.  */
 #define ABI_N32_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
@@ -786,6 +796,11 @@ static bfd *reldyn_sorting_bfd;
 #define MICROMIPS_P(abfd) \
   ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0)
 
+/* Nonzero if ABFD is MIPS R6.  */
+#define MIPSR6_P(abfd) \
+  ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6 \
+    || (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R6)
+
 /* The IRIX compatibility level we are striving for.  */
 #define IRIX_COMPAT(abfd) \
   (get_elf_backend_data (abfd)->elf_backend_mips_irix_compat (abfd))
@@ -803,6 +818,10 @@ static bfd *reldyn_sorting_bfd;
 #define MIPS_ELF_OPTIONS_SECTION_NAME_P(NAME) \
   (strcmp (NAME, ".MIPS.options") == 0 || strcmp (NAME, ".options") == 0)
 
+/* True if NAME is the recognized name of any SHT_MIPS_ABIFLAGS section.  */
+#define MIPS_ELF_ABIFLAGS_SECTION_NAME_P(NAME) \
+  (strcmp (NAME, ".MIPS.abiflags") == 0)
+
 /* Whether the section is readonly.  */
 #define MIPS_ELF_READONLY_SECTION(sec) \
   ((sec->flags & (SEC_ALLOC | SEC_LOAD | SEC_READONLY))                \
@@ -888,12 +907,9 @@ static bfd *reldyn_sorting_bfd;
   ((ABI_64_P (abfd)                                                    \
     ? 0xdf998010                               /* ld t9,0x8010(gp) */  \
     : 0x8f998010))                             /* lw t9,0x8010(gp) */
-#define STUB_MOVE(abfd)                                                        \
-   ((ABI_64_P (abfd)                                                   \
-     ? 0x03e0782d                              /* daddu t7,ra */       \
-     : 0x03e07821))                            /* addu t7,ra */
+#define STUB_MOVE 0x03e07825                   /* or t7,ra,zero */
 #define STUB_LUI(VAL) (0x3c180000 + (VAL))     /* lui t8,VAL */
-#define STUB_JALR 0x0320f809                   /* jalr t9,ra */
+#define STUB_JALR 0x0320f809                   /* jalr ra,t9 */
 #define STUB_ORI(VAL) (0x37180000 + (VAL))     /* ori t8,t8,VAL */
 #define STUB_LI16U(VAL) (0x34180000 + (VAL))   /* ori t8,zero,VAL unsigned */
 #define STUB_LI16S(abfd, VAL)                                          \
@@ -907,10 +923,7 @@ static bfd *reldyn_sorting_bfd;
    ? 0xdf3c8010                                        /* ld t9,0x8010(gp) */  \
    : 0xff3c8010)                               /* lw t9,0x8010(gp) */
 #define STUB_MOVE_MICROMIPS 0x0dff             /* move t7,ra */
-#define STUB_MOVE32_MICROMIPS(abfd)                                    \
-   (ABI_64_P (abfd)                                                    \
-    ? 0x581f7950                               /* daddu t7,ra,zero */  \
-    : 0x001f7950)                              /* addu t7,ra,zero */
+#define STUB_MOVE32_MICROMIPS 0x001f7a90       /* or t7,ra,zero */
 #define STUB_LUI_MICROMIPS(VAL)                                                \
    (0x41b80000 + (VAL))                                /* lui t8,VAL */
 #define STUB_JALR_MICROMIPS 0x45d9             /* jalr t9 */
@@ -1007,7 +1020,7 @@ static const bfd_vma mips_o32_exec_plt0_entry[] =
   0x8f990000,  /* lw $25, %lo(&GOTPLT[0])($28)                         */
   0x279c0000,  /* addiu $28, $28, %lo(&GOTPLT[0])                      */
   0x031cc023,  /* subu $24, $24, $28                                   */
-  0x03e07821,  /* move $15, $31        # 32-bit move (addu)            */
+  0x03e07825,  /* or t7, ra, zero                                      */
   0x0018c082,  /* srl $24, $24, 2                                      */
   0x0320f809,  /* jalr $25                                             */
   0x2718fffe   /* subu $24, $24, 2                                     */
@@ -1021,7 +1034,7 @@ static const bfd_vma mips_n32_exec_plt0_entry[] =
   0x8dd90000,  /* lw $25, %lo(&GOTPLT[0])($14)                         */
   0x25ce0000,  /* addiu $14, $14, %lo(&GOTPLT[0])                      */
   0x030ec023,  /* subu $24, $24, $14                                   */
-  0x03e07821,  /* move $15, $31        # 32-bit move (addu)            */
+  0x03e07825,  /* or t7, ra, zero                                      */
   0x0018c082,  /* srl $24, $24, 2                                      */
   0x0320f809,  /* jalr $25                                             */
   0x2718fffe   /* subu $24, $24, 2                                     */
@@ -1035,7 +1048,7 @@ static const bfd_vma mips_n64_exec_plt0_entry[] =
   0xddd90000,  /* ld $25, %lo(&GOTPLT[0])($14)                         */
   0x25ce0000,  /* addiu $14, $14, %lo(&GOTPLT[0])                      */
   0x030ec023,  /* subu $24, $24, $14                                   */
-  0x03e0782d,  /* move $15, $31        # 64-bit move (daddu)           */
+  0x03e07825,  /* or t7, ra, zero                                      */
   0x0018c0c2,  /* srl $24, $24, 3                                      */
   0x0320f809,  /* jalr $25                                             */
   0x2718fffe   /* subu $24, $24, 2                                     */
@@ -1068,7 +1081,7 @@ static const bfd_vma micromips_insn32_o32_exec_plt0_entry[] =
   0xff3c, 0x0000,      /* lw $25, %lo(&GOTPLT[0])($28)                 */
   0x339c, 0x0000,      /* addiu $28, $28, %lo(&GOTPLT[0])              */
   0x0398, 0xc1d0,      /* subu $24, $24, $28                           */
-  0x001f, 0x7950,      /* move $15, $31                                */
+  0x001f, 0x7a90,      /* or $15, $31, zero                            */
   0x0318, 0x1040,      /* srl $24, $24, 2                              */
   0x03f9, 0x0f3c,      /* jalr $25                                     */
   0x3318, 0xfffe       /* subu $24, $24, 2                             */
@@ -1083,6 +1096,17 @@ static const bfd_vma mips_exec_plt_entry[] =
   0x03200008   /* jr $25                                       */
 };
 
+/* In the following PLT entry the JR and ADDIU instructions will
+   be swapped in _bfd_mips_elf_finish_dynamic_symbol because
+   LOAD_INTERLOCKS_P will be true for MIPS R6.  */
+static const bfd_vma mipsr6_exec_plt_entry[] =
+{
+  0x3c0f0000,  /* lui $15, %hi(.got.plt entry)                 */
+  0x01f90000,  /* l[wd] $25, %lo(.got.plt entry)($15)          */
+  0x25f80000,  /* addiu $24, $15, %lo(.got.plt entry)          */
+  0x03200009   /* jr $25                                       */
+};
+
 /* The format of subsequent MIPS16 o32 PLT entries.  We use v0 ($2)
    and v1 ($3) as temporaries because t8 ($24) and t9 ($25) are not
    directly addressable.  */
@@ -1550,19 +1574,23 @@ mips_elf_create_stub_symbol (struct bfd_link_info *info,
                             const char *prefix, asection *s, bfd_vma value,
                             bfd_vma size)
 {
+  bfd_boolean micromips_p = ELF_ST_IS_MICROMIPS (h->root.other);
   struct bfd_link_hash_entry *bh;
   struct elf_link_hash_entry *elfh;
-  const char *name;
+  char *name;
+  bfd_boolean res;
 
-  if (ELF_ST_IS_MICROMIPS (h->root.other))
+  if (micromips_p)
     value |= 1;
 
   /* Create a new symbol.  */
-  name = ACONCAT ((prefix, h->root.root.root.string, NULL));
+  name = concat (prefix, h->root.root.root.string, NULL);
   bh = NULL;
-  if (!_bfd_generic_link_add_one_symbol (info, s->owner, name,
-                                        BSF_LOCAL, s, value, NULL,
-                                        TRUE, FALSE, &bh))
+  res = _bfd_generic_link_add_one_symbol (info, s->owner, name,
+                                         BSF_LOCAL, s, value, NULL,
+                                         TRUE, FALSE, &bh);
+  free (name);
+  if (! res)
     return FALSE;
 
   /* Make it a local function.  */
@@ -1570,6 +1598,8 @@ mips_elf_create_stub_symbol (struct bfd_link_info *info,
   elfh->type = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
   elfh->size = size;
   elfh->forced_local = 1;
+  if (micromips_p)
+    elfh->other = ELF_ST_SET_MICROMIPS (elfh->other);
   return TRUE;
 }
 
@@ -1584,9 +1614,10 @@ mips_elf_create_shadow_symbol (struct bfd_link_info *info,
 {
   struct bfd_link_hash_entry *bh;
   struct elf_link_hash_entry *elfh;
-  const char *name;
+  char *name;
   asection *s;
   bfd_vma value;
+  bfd_boolean res;
 
   /* Read the symbol's value.  */
   BFD_ASSERT (h->root.root.type == bfd_link_hash_defined
@@ -1595,11 +1626,13 @@ mips_elf_create_shadow_symbol (struct bfd_link_info *info,
   value = h->root.root.u.def.value;
 
   /* Create a new symbol.  */
-  name = ACONCAT ((prefix, h->root.root.root.string, NULL));
+  name = concat (prefix, h->root.root.root.string, NULL);
   bh = NULL;
-  if (!_bfd_generic_link_add_one_symbol (info, s->owner, name,
-                                        BSF_LOCAL, s, value, NULL,
-                                        TRUE, FALSE, &bh))
+  res = _bfd_generic_link_add_one_symbol (info, s->owner, name,
+                                         BSF_LOCAL, s, value, NULL,
+                                         TRUE, FALSE, &bh);
+  free (name);
+  if (! res)
     return FALSE;
 
   /* Make it local and copy the other attributes from H.  */
@@ -1679,6 +1712,7 @@ mips_elf_check_mips16_stubs (struct bfd_link_info *info,
       h->fn_stub->flags &= ~SEC_RELOC;
       h->fn_stub->reloc_count = 0;
       h->fn_stub->flags |= SEC_EXCLUDE;
+      h->fn_stub->output_section = bfd_abs_section_ptr;
     }
 
   if (h->call_stub != NULL
@@ -1691,6 +1725,7 @@ mips_elf_check_mips16_stubs (struct bfd_link_info *info,
       h->call_stub->flags &= ~SEC_RELOC;
       h->call_stub->reloc_count = 0;
       h->call_stub->flags |= SEC_EXCLUDE;
+      h->call_stub->output_section = bfd_abs_section_ptr;
     }
 
   if (h->call_fp_stub != NULL
@@ -1703,6 +1738,7 @@ mips_elf_check_mips16_stubs (struct bfd_link_info *info,
       h->call_fp_stub->flags &= ~SEC_RELOC;
       h->call_fp_stub->reloc_count = 0;
       h->call_fp_stub->flags |= SEC_EXCLUDE;
+      h->call_fp_stub->output_section = bfd_abs_section_ptr;
     }
 }
 
@@ -1768,6 +1804,7 @@ mips_elf_local_pic_function_p (struct mips_elf_link_hash_entry *h)
           || h->root.root.type == bfd_link_hash_defweak)
          && h->root.def_regular
          && !bfd_is_abs_section (h->root.root.u.def.section)
+         && !bfd_is_und_section (h->root.root.u.def.section)
          && (!ELF_ST_IS_MIPS16 (h->root.other)
              || (h->fn_stub && h->need_fn_stub))
          && (PIC_OBJECT_P (h->root.root.u.def.section->owner)
@@ -1924,6 +1961,8 @@ mips_elf_add_la25_stub (struct bfd_link_info *info,
   /* Prefer to use LUI/ADDIU stubs if the function is at the beginning
      of the section and if we would need no more than 2 nops.  */
   value = mips_elf_get_la25_target (stub, &s);
+  if (ELF_ST_IS_MICROMIPS (stub->h->root.other))
+    value &= ~1;
   use_trampoline_p = (value != 0 || s->alignment_power > 4);
 
   h->la25_stub = stub;
@@ -1941,7 +1980,7 @@ mips_elf_check_symbols (struct mips_elf_link_hash_entry *h, void *data)
   struct mips_htab_traverse_info *hti;
 
   hti = (struct mips_htab_traverse_info *) data;
-  if (!hti->info->relocatable)
+  if (!bfd_link_relocatable (hti->info))
     mips_elf_check_mips16_stubs (hti->info, h);
 
   if (mips_elf_local_pic_function_p (h))
@@ -1956,7 +1995,7 @@ mips_elf_check_symbols (struct mips_elf_link_hash_entry *h, void *data)
         being PIC.  If we're creating a non-relocatable object with
         non-PIC branches and jumps to H, make sure that H has an la25
         stub.  */
-      if (hti->info->relocatable)
+      if (bfd_link_relocatable (hti->info))
        {
          if (!PIC_OBJECT_P (hti->output_bfd))
            h->root.other = ELF_ST_SET_MIPS_PIC (h->root.other);
@@ -2053,7 +2092,11 @@ mips_elf_check_symbols (struct mips_elf_link_hash_entry *h, void *data)
 
    All we need to do here is shuffle the bits appropriately.
    As above, the two 16-bit halves must be swapped on a
-   little-endian system.  */
+   little-endian system.
+
+   Finally R_MIPS16_PC16_S1 corresponds to R_MIPS_PC16, however the
+   relocatable field is shifted by 1 rather than 2 and the same bit
+   shuffling is done as with the relocations above.  */
 
 static inline bfd_boolean
 mips16_reloc_p (int r_type)
@@ -2073,6 +2116,7 @@ mips16_reloc_p (int r_type)
     case R_MIPS16_TLS_GOTTPREL:
     case R_MIPS16_TLS_TPREL_HI16:
     case R_MIPS16_TLS_TPREL_LO16:
+    case R_MIPS16_PC16_S1:
       return TRUE;
 
     default:
@@ -2128,18 +2172,6 @@ got_page_reloc_p (unsigned int r_type)
   return r_type == R_MIPS_GOT_PAGE || r_type == R_MICROMIPS_GOT_PAGE;
 }
 
-static inline bfd_boolean
-got_ofst_reloc_p (unsigned int r_type)
-{
-  return r_type == R_MIPS_GOT_OFST || r_type == R_MICROMIPS_GOT_OFST;
-}
-
-static inline bfd_boolean
-got_hi16_reloc_p (unsigned int r_type)
-{
-  return r_type == R_MIPS_GOT_HI16 || r_type == R_MICROMIPS_GOT_HI16;
-}
-
 static inline bfd_boolean
 got_lo16_reloc_p (unsigned int r_type)
 {
@@ -2163,7 +2195,8 @@ hi16_reloc_p (int r_type)
 {
   return (r_type == R_MIPS_HI16
          || r_type == R_MIPS16_HI16
-         || r_type == R_MICROMIPS_HI16);
+         || r_type == R_MICROMIPS_HI16
+         || r_type == R_MIPS_PCHI16);
 }
 
 static inline bfd_boolean
@@ -2171,7 +2204,8 @@ lo16_reloc_p (int r_type)
 {
   return (r_type == R_MIPS_LO16
          || r_type == R_MIPS16_LO16
-         || r_type == R_MICROMIPS_LO16);
+         || r_type == R_MICROMIPS_LO16
+         || r_type == R_MIPS_PCLO16);
 }
 
 static inline bfd_boolean
@@ -2188,6 +2222,43 @@ jal_reloc_p (int r_type)
          || r_type == R_MICROMIPS_26_S1);
 }
 
+static inline bfd_boolean
+b_reloc_p (int r_type)
+{
+  return (r_type == R_MIPS_PC26_S2
+         || r_type == R_MIPS_PC21_S2
+         || r_type == R_MIPS_PC16
+         || r_type == R_MIPS_GNU_REL16_S2
+         || r_type == R_MIPS16_PC16_S1
+         || r_type == R_MICROMIPS_PC16_S1
+         || r_type == R_MICROMIPS_PC10_S1
+         || r_type == R_MICROMIPS_PC7_S1);
+}
+
+static inline bfd_boolean
+aligned_pcrel_reloc_p (int r_type)
+{
+  return (r_type == R_MIPS_PC18_S3
+         || r_type == R_MIPS_PC19_S2);
+}
+
+static inline bfd_boolean
+branch_reloc_p (int r_type)
+{
+  return (r_type == R_MIPS_26
+         || r_type == R_MIPS_PC26_S2
+         || r_type == R_MIPS_PC21_S2
+         || r_type == R_MIPS_PC16
+         || r_type == R_MIPS_GNU_REL16_S2);
+}
+
+static inline bfd_boolean
+mips16_branch_reloc_p (int r_type)
+{
+  return (r_type == R_MIPS16_26
+         || r_type == R_MIPS16_PC16_S1);
+}
+
 static inline bfd_boolean
 micromips_branch_reloc_p (int r_type)
 {
@@ -2659,6 +2730,46 @@ bfd_mips_elf_swap_options_out (bfd *abfd, const Elf_Internal_Options *in,
   H_PUT_16 (abfd, in->section, ex->section);
   H_PUT_32 (abfd, in->info, ex->info);
 }
+
+/* Swap in an abiflags structure.  */
+
+void
+bfd_mips_elf_swap_abiflags_v0_in (bfd *abfd,
+                                 const Elf_External_ABIFlags_v0 *ex,
+                                 Elf_Internal_ABIFlags_v0 *in)
+{
+  in->version = H_GET_16 (abfd, ex->version);
+  in->isa_level = H_GET_8 (abfd, ex->isa_level);
+  in->isa_rev = H_GET_8 (abfd, ex->isa_rev);
+  in->gpr_size = H_GET_8 (abfd, ex->gpr_size);
+  in->cpr1_size = H_GET_8 (abfd, ex->cpr1_size);
+  in->cpr2_size = H_GET_8 (abfd, ex->cpr2_size);
+  in->fp_abi = H_GET_8 (abfd, ex->fp_abi);
+  in->isa_ext = H_GET_32 (abfd, ex->isa_ext);
+  in->ases = H_GET_32 (abfd, ex->ases);
+  in->flags1 = H_GET_32 (abfd, ex->flags1);
+  in->flags2 = H_GET_32 (abfd, ex->flags2);
+}
+
+/* Swap out an abiflags structure.  */
+
+void
+bfd_mips_elf_swap_abiflags_v0_out (bfd *abfd,
+                                  const Elf_Internal_ABIFlags_v0 *in,
+                                  Elf_External_ABIFlags_v0 *ex)
+{
+  H_PUT_16 (abfd, in->version, ex->version);
+  H_PUT_8 (abfd, in->isa_level, ex->isa_level);
+  H_PUT_8 (abfd, in->isa_rev, ex->isa_rev);
+  H_PUT_8 (abfd, in->gpr_size, ex->gpr_size);
+  H_PUT_8 (abfd, in->cpr1_size, ex->cpr1_size);
+  H_PUT_8 (abfd, in->cpr2_size, ex->cpr2_size);
+  H_PUT_8 (abfd, in->fp_abi, ex->fp_abi);
+  H_PUT_32 (abfd, in->isa_ext, ex->isa_ext);
+  H_PUT_32 (abfd, in->ases, ex->ases);
+  H_PUT_32 (abfd, in->flags1, ex->flags1);
+  H_PUT_32 (abfd, in->flags2, ex->flags2);
+}
 \f
 /* This function is called via qsort() to sort the dynamic relocation
    entries by increasing r_symndx value.  */
@@ -3142,11 +3253,11 @@ mips_tls_got_relocs (struct bfd_link_info *info, unsigned char tls_type,
   bfd_boolean need_relocs = FALSE;
   bfd_boolean dyn = elf_hash_table (info)->dynamic_sections_created;
 
-  if (h && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
-      && (!info->shared || !SYMBOL_REFERENCES_LOCAL (info, h)))
+  if (h && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)
+      && (!bfd_link_pic (info) || !SYMBOL_REFERENCES_LOCAL (info, h)))
     indx = h->dynindx;
 
-  if ((info->shared || indx != 0)
+  if ((bfd_link_pic (info) || indx != 0)
       && (h == NULL
          || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
          || h->root.type != bfd_link_hash_undefweak))
@@ -3164,7 +3275,7 @@ mips_tls_got_relocs (struct bfd_link_info *info, unsigned char tls_type,
       return 1;
 
     case GOT_TLS_LDM:
-      return info->shared ? 1 : 0;
+      return bfd_link_pic (info) ? 1 : 0;
 
     default:
       return 0;
@@ -3241,22 +3352,24 @@ mips_elf_initialize_tls_slots (bfd *abfd, struct bfd_link_info *info,
   if (htab == NULL)
     return;
 
-  sgot = htab->sgot;
+  sgot = htab->root.sgot;
 
   indx = 0;
   if (h != NULL)
     {
       bfd_boolean dyn = elf_hash_table (info)->dynamic_sections_created;
 
-      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, &h->root)
-         && (!info->shared || !SYMBOL_REFERENCES_LOCAL (info, &h->root)))
+      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info),
+                                          &h->root)
+         && (!bfd_link_pic (info)
+             || !SYMBOL_REFERENCES_LOCAL (info, &h->root)))
        indx = h->root.dynindx;
     }
 
   if (entry->tls_initialized)
     return;
 
-  if ((info->shared || indx != 0)
+  if ((bfd_link_pic (info) || indx != 0)
       && (h == NULL
          || ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT
          || h->root.type != bfd_link_hash_undefweak))
@@ -3331,7 +3444,7 @@ mips_elf_initialize_tls_slots (bfd *abfd, struct bfd_link_info *info,
                         sgot->contents + got_offset
                         + MIPS_ELF_GOT_SIZE (abfd));
 
-      if (!info->shared)
+      if (!bfd_link_pic (info))
        MIPS_ELF_PUT_WORD (abfd, 1,
                           sgot->contents + got_offset);
       else
@@ -3366,8 +3479,8 @@ mips_elf_gotplt_index (struct bfd_link_info *info,
   BFD_ASSERT (h->plt.plist->gotplt_index != MINUS_ONE);
 
   /* Calculate the address of the associated .got.plt entry.  */
-  got_address = (htab->sgotplt->output_section->vma
-                + htab->sgotplt->output_offset
+  got_address = (htab->root.sgotplt->output_section->vma
+                + htab->root.sgotplt->output_offset
                 + (h->plt.plist->gotplt_index
                    * MIPS_ELF_GOT_SIZE (info->output_bfd)));
 
@@ -3431,7 +3544,7 @@ mips_elf_primary_global_got_index (bfd *obfd, struct bfd_link_info *info,
   g = mips_elf_bfd_got (obfd, FALSE);
   got_index = ((h->dynindx - global_got_dynindx + g->local_gotno)
               * MIPS_ELF_GOT_SIZE (obfd));
-  BFD_ASSERT (got_index < htab->sgot->size);
+  BFD_ASSERT (got_index < htab->root.sgot->size);
 
   return got_index;
 }
@@ -3465,7 +3578,7 @@ mips_elf_global_got_index (bfd *obfd, struct bfd_link_info *info, bfd *ibfd,
   BFD_ASSERT (entry);
 
   gotidx = entry->gotidx;
-  BFD_ASSERT (gotidx > 0 && gotidx < htab->sgot->size);
+  BFD_ASSERT (gotidx > 0 && gotidx < htab->root.sgot->size);
 
   if (lookup.tls_type)
     {
@@ -3553,7 +3666,7 @@ mips_elf_got_offset_from_index (struct bfd_link_info *info, bfd *output_bfd,
   htab = mips_elf_hash_table (info);
   BFD_ASSERT (htab != NULL);
 
-  sgot = htab->sgot;
+  sgot = htab->root.sgot;
   gp = _bfd_get_gp_value (output_bfd)
     + mips_elf_adjust_gp (output_bfd, htab->got_info, input_bfd);
 
@@ -3616,7 +3729,7 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
       BFD_ASSERT (entry);
 
       gotidx = entry->gotidx;
-      BFD_ASSERT (gotidx > 0 && gotidx < htab->sgot->size);
+      BFD_ASSERT (gotidx > 0 && gotidx < htab->root.sgot->size);
 
       return entry;
     }
@@ -3632,10 +3745,10 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
   if (entry)
     return entry;
 
-  if (g->assigned_gotno >= g->local_gotno)
+  if (g->assigned_low_gotno > g->assigned_high_gotno)
     {
       /* We didn't allocate enough space in the GOT.  */
-      (*_bfd_error_handler)
+      _bfd_error_handler
        (_("not enough GOT space for local GOT entries"));
       bfd_set_error (bfd_error_bad_value);
       return NULL;
@@ -3645,11 +3758,18 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
   if (!entry)
     return NULL;
 
-  lookup.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_gotno++;
+  if (got16_reloc_p (r_type)
+      || call16_reloc_p (r_type)
+      || got_page_reloc_p (r_type)
+      || got_disp_reloc_p (r_type))
+    lookup.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_low_gotno++;
+  else
+    lookup.gotidx = MIPS_ELF_GOT_SIZE (abfd) * g->assigned_high_gotno--;
+
   *entry = lookup;
   *loc = entry;
 
-  MIPS_ELF_PUT_WORD (abfd, value, htab->sgot->contents + entry->gotidx);
+  MIPS_ELF_PUT_WORD (abfd, value, htab->root.sgot->contents + entry->gotidx);
 
   /* These GOT entries need a dynamic relocation on VxWorks.  */
   if (htab->is_vxworks)
@@ -3660,8 +3780,8 @@ mips_elf_create_local_got_entry (bfd *abfd, struct bfd_link_info *info,
       bfd_vma got_address;
 
       s = mips_elf_rel_dyn_section (info, FALSE);
-      got_address = (htab->sgot->output_section->vma
-                    + htab->sgot->output_offset
+      got_address = (htab->root.sgot->output_section->vma
+                    + htab->root.sgot->output_offset
                     + entry->gotidx);
 
       rloc = s->contents + (s->reloc_count++ * sizeof (Elf32_External_Rela));
@@ -3685,7 +3805,8 @@ count_section_dynsyms (bfd *output_bfd, struct bfd_link_info *info)
   bfd_size_type count;
 
   count = 0;
-  if (info->shared || elf_hash_table (info)->is_relocatable_executable)
+  if (bfd_link_pic (info)
+      || elf_hash_table (info)->is_relocatable_executable)
     {
       asection *p;
       const struct elf_backend_data *bed;
@@ -4086,9 +4207,10 @@ mips_elf_pages_for_range (const struct mips_got_page_range *range)
 /* Record that G requires a page entry that can reach SEC + ADDEND.  */
 
 static bfd_boolean
-mips_elf_record_got_page_entry (struct mips_got_info *g,
+mips_elf_record_got_page_entry (struct mips_elf_traverse_got_arg *arg,
                                asection *sec, bfd_signed_vma addend)
 {
+  struct mips_got_info *g = arg->g;
   struct mips_got_page_entry lookup, *entry;
   struct mips_got_page_range **range_ptr, *range;
   bfd_vma old_pages, new_pages;
@@ -4105,7 +4227,7 @@ mips_elf_record_got_page_entry (struct mips_got_info *g,
   entry = (struct mips_got_page_entry *) *loc;
   if (!entry)
     {
-      entry = bfd_zalloc (sec->owner, sizeof (*entry));
+      entry = bfd_zalloc (arg->info->output_bfd, sizeof (*entry));
       if (!entry)
        return FALSE;
 
@@ -4125,7 +4247,7 @@ mips_elf_record_got_page_entry (struct mips_got_info *g,
   range = *range_ptr;
   if (!range || addend < range->min_addend - 0xffff)
     {
-      range = bfd_zalloc (sec->owner, sizeof (*range));
+      range = bfd_zalloc (arg->info->output_bfd, sizeof (*range));
       if (!range)
        return FALSE;
 
@@ -4245,7 +4367,7 @@ mips_elf_resolve_got_page_ref (void **refp, void *data)
       else
        addend = isym->st_value + ref->addend;
     }
-  if (!mips_elf_record_got_page_entry (arg->g, sec, addend))
+  if (!mips_elf_record_got_page_entry (arg, sec, addend))
     {
       arg->g = NULL;
       return 0;
@@ -4323,7 +4445,7 @@ mips_use_local_got_p (struct bfd_link_info *info,
   /* If this is an executable that must provide a definition of the symbol,
      either though PLTs or copy relocations, then that address should go in
      the local rather than global GOT.  */
-  if (info->executable && h->has_static_relocs)
+  if (bfd_link_executable (info) && h->has_static_relocs)
     return TRUE;
 
   return FALSE;
@@ -4624,14 +4746,14 @@ mips_elf_set_global_gotidx (void **entryp, void *data)
       && entry->symndx == -1
       && entry->d.h->global_got_area != GGA_NONE)
     {
-      if (!mips_elf_set_gotidx (entryp, arg->value * arg->g->assigned_gotno))
+      if (!mips_elf_set_gotidx (entryp, arg->value * arg->g->assigned_low_gotno))
        {
          arg->g = NULL;
          return 0;
        }
-      arg->g->assigned_gotno += 1;
+      arg->g->assigned_low_gotno += 1;
 
-      if (arg->info->shared
+      if (bfd_link_pic (arg->info)
          || (elf_hash_table (arg->info)->dynamic_sections_created
              && entry->d.h->root.def_dynamic
              && !entry->d.h->root.def_regular))
@@ -4724,7 +4846,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
   /* Try to merge the GOTs of input bfds together, as long as they
      don't seem to exceed the maximum GOT size, choosing one of them
      to be the primary GOT.  */
-  for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next)
     {
       gg = mips_elf_bfd_got (ibfd, FALSE);
       if (gg && !mips_elf_merge_got (ibfd, gg, &got_per_bfd_arg))
@@ -4762,7 +4884,7 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
   htab_traverse (g->got_entries, mips_elf_set_global_got_area, &tga);
 
   /* Now go through the GOTs assigning them offset ranges.
-     [assigned_gotno, local_gotno[ will be set to the range of local
+     [assigned_low_gotno, local_gotno[ will be set to the range of local
      entries in each GOT.  We can then compute the end of a GOT by
      adding local_gotno to global_gotno.  We reverse the list and make
      it circular since then we'll be able to quickly compute the
@@ -4785,9 +4907,10 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
       struct mips_got_info *gn;
 
       assign += htab->reserved_gotno;
-      g->assigned_gotno = assign;
+      g->assigned_low_gotno = assign;
       g->local_gotno += assign;
       g->local_gotno += (pages < g->page_gotno ? pages : g->page_gotno);
+      g->assigned_high_gotno = g->local_gotno - 1;
       assign = g->local_gotno + g->global_gotno + g->tls_gotno;
 
       /* Take g out of the direct list, and push it onto the reversed
@@ -4826,21 +4949,21 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
 
       /* Assign offsets to global GOT entries and count how many
         relocations they need.  */
-      save_assign = g->assigned_gotno;
-      g->assigned_gotno = g->local_gotno;
+      save_assign = g->assigned_low_gotno;
+      g->assigned_low_gotno = g->local_gotno;
       tga.info = info;
       tga.value = MIPS_ELF_GOT_SIZE (abfd);
       tga.g = g;
       htab_traverse (g->got_entries, mips_elf_set_global_gotidx, &tga);
       if (!tga.g)
        return FALSE;
-      BFD_ASSERT (g->assigned_gotno == g->local_gotno + g->global_gotno);
-      g->assigned_gotno = save_assign;
+      BFD_ASSERT (g->assigned_low_gotno == g->local_gotno + g->global_gotno);
+      g->assigned_low_gotno = save_assign;
 
-      if (info->shared)
+      if (bfd_link_pic (info))
        {
-         g->relocs += g->local_gotno - g->assigned_gotno;
-         BFD_ASSERT (g->assigned_gotno == g->next->local_gotno
+         g->relocs += g->local_gotno - g->assigned_low_gotno;
+         BFD_ASSERT (g->assigned_low_gotno == g->next->local_gotno
                      + g->next->global_gotno
                      + g->next->tls_gotno
                      + htab->reserved_gotno);
@@ -5010,7 +5133,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   BFD_ASSERT (htab != NULL);
 
   /* This function may be called more than once.  */
-  if (htab->sgot)
+  if (htab->root.sgot)
     return TRUE;
 
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
@@ -5022,7 +5145,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   if (s == NULL
       || ! bfd_set_section_alignment (abfd, s, 4))
     return FALSE;
-  htab->sgot = s;
+  htab->root.sgot = s;
 
   /* Define the symbol _GLOBAL_OFFSET_TABLE_.  We don't do this in the
      linker script because we don't want to define the symbol if we
@@ -5040,7 +5163,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
   elf_hash_table (info)->hgot = h;
 
-  if (info->shared
+  if (bfd_link_pic (info)
       && ! bfd_elf_link_record_dynamic_symbol (info, h))
     return FALSE;
 
@@ -5056,7 +5179,7 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
                                          | SEC_LINKER_CREATED);
   if (s == NULL)
     return FALSE;
-  htab->sgotplt = s;
+  htab->root.sgotplt = s;
 
   return TRUE;
 }
@@ -5069,7 +5192,7 @@ static bfd_boolean
 is_gott_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h)
 {
   return (mips_elf_hash_table (info)->is_vxworks
-         && info->shared
+         && bfd_link_pic (info)
          && (strcmp (h->root.root.string, "__GOTT_BASE__") == 0
              || strcmp (h->root.root.string, "__GOTT_INDEX__") == 0));
 }
@@ -5095,6 +5218,8 @@ mips_elf_relocation_needs_la25_stub (bfd *input_bfd, int r_type,
     {
     case R_MIPS_26:
     case R_MIPS_PC16:
+    case R_MIPS_PC21_S2:
+    case R_MIPS_PC26_S2:
     case R_MICROMIPS_26_S1:
     case R_MICROMIPS_PC7_S1:
     case R_MICROMIPS_PC10_S1:
@@ -5159,6 +5284,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
   /* TRUE if the symbol referred to by this relocation is a local
      symbol.  */
   bfd_boolean local_p, was_local_p;
+  /* TRUE if the symbol referred to by this relocation is a section
+     symbol.  */
+  bfd_boolean section_p = FALSE;
   /* TRUE if the symbol referred to by this relocation is "_gp_disp".  */
   bfd_boolean gp_disp_p = FALSE;
   /* TRUE if the symbol referred to by this relocation is
@@ -5209,17 +5337,18 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
   /* Figure out the value of the symbol.  */
   if (local_p)
     {
+      bfd_boolean micromips_p = MICROMIPS_P (abfd);
       Elf_Internal_Sym *sym;
 
       sym = local_syms + r_symndx;
       sec = local_sections[r_symndx];
 
+      section_p = ELF_ST_TYPE (sym->st_info) == STT_SECTION;
+
       symbol = sec->output_section->vma + sec->output_offset;
-      if (ELF_ST_TYPE (sym->st_info) != STT_SECTION
-         || (sec->flags & SEC_MERGE))
+      if (!section_p || (sec->flags & SEC_MERGE))
        symbol += sym->st_value;
-      if ((sec->flags & SEC_MERGE)
-         && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+      if ((sec->flags & SEC_MERGE) && section_p)
        {
          addend = _bfd_elf_rel_local_sym (abfd, sym, &sec, addend);
          addend -= symbol;
@@ -5234,11 +5363,29 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       *namep = bfd_elf_string_from_elf_section (input_bfd,
                                                symtab_hdr->sh_link,
                                                sym->st_name);
-      if (*namep == '\0')
+      if (*namep == NULL || **namep == '\0')
        *namep = bfd_section_name (input_bfd, sec);
 
-      target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (sym->st_other);
-      target_is_micromips_code_p = ELF_ST_IS_MICROMIPS (sym->st_other);
+      /* For relocations against a section symbol and ones against no
+         symbol (absolute relocations) infer the ISA mode from the addend.  */
+      if (section_p || r_symndx == STN_UNDEF)
+       {
+         target_is_16_bit_code_p = (addend & 1) && !micromips_p;
+         target_is_micromips_code_p = (addend & 1) && micromips_p;
+       }
+      /* For relocations against an absolute symbol infer the ISA mode
+         from the value of the symbol plus addend.  */
+      else if (bfd_is_abs_section (sec))
+       {
+         target_is_16_bit_code_p = ((symbol + addend) & 1) && !micromips_p;
+         target_is_micromips_code_p = ((symbol + addend) & 1) && micromips_p;
+       }
+      /* Otherwise just use the regular symbol annotation available.  */
+      else
+       {
+         target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (sym->st_other);
+         target_is_micromips_code_p = ELF_ST_IS_MICROMIPS (sym->st_other);
+       }
     }
   else
     {
@@ -5307,7 +5454,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
             Otherwise, we should define the symbol with a value of 0.
             FIXME: It should probably get into the symbol table
             somehow as well.  */
-         BFD_ASSERT (! info->shared);
+         BFD_ASSERT (! bfd_link_pic (info));
          BFD_ASSERT (bfd_get_section_by_name (abfd, ".dynamic") == NULL);
          symbol = 0;
        }
@@ -5322,17 +5469,14 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
             http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf  */
          symbol = 0;
        }
-      else if ((*info->callbacks->undefined_symbol)
-              (info, h->root.root.root.string, input_bfd,
-               input_section, relocation->r_offset,
-               (info->unresolved_syms_in_objects == RM_GENERATE_ERROR)
-                || ELF_ST_VISIBILITY (h->root.other)))
-       {
-         return bfd_reloc_undefined;
-       }
       else
        {
-         return bfd_reloc_notsupported;
+         (*info->callbacks->undefined_symbol)
+           (info, h->root.root.root.string, input_bfd,
+            input_section, relocation->r_offset,
+            (info->unresolved_syms_in_objects == RM_GENERATE_ERROR)
+            || ELF_ST_VISIBILITY (h->root.other));
+         return bfd_reloc_undefined;
        }
 
       target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (h->root.other);
@@ -5349,7 +5493,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
 
      (c) the section allows direct references to MIPS16 functions.  */
   if (r_type != R_MIPS16_26
-      && !info->relocatable
+      && !bfd_link_relocatable (info)
       && ((h != NULL
           && h->fn_stub != NULL
           && (r_type != R_MIPS16_CALL16 || h->need_fn_stub))
@@ -5391,7 +5535,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
      to a standard MIPS function, we need to redirect the call to the stub.
      Note that we specifically exclude R_MIPS16_CALL16 from this behavior;
      indirect calls should use an indirect stub instead.  */
-  else if (r_type == R_MIPS16_26 && !info->relocatable
+  else if (r_type == R_MIPS16_26 && !bfd_link_relocatable (info)
           && ((h != NULL && (h->call_stub != NULL || h->call_fp_stub != NULL))
               || (local_p
                   && mips_elf_tdata (input_bfd)->local_call_stubs != NULL
@@ -5435,16 +5579,21 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
   else if (h != NULL && h->la25_stub
           && mips_elf_relocation_needs_la25_stub (input_bfd, r_type,
                                                   target_is_16_bit_code_p))
-    symbol = (h->la25_stub->stub_section->output_section->vma
-             + h->la25_stub->stub_section->output_offset
-             + h->la25_stub->offset);
+    {
+       symbol = (h->la25_stub->stub_section->output_section->vma
+                 + h->la25_stub->stub_section->output_offset
+                 + h->la25_stub->offset);
+       if (ELF_ST_IS_MICROMIPS (h->root.other))
+         symbol |= 1;
+    }
   /* For direct MIPS16 and microMIPS calls make sure the compressed PLT
      entry is used if a standard PLT entry has also been made.  In this
      case the symbol will have been set by mips_elf_set_plt_sym_value
      to point to the standard PLT entry, so redirect to the compressed
      one.  */
-  else if ((r_type == R_MIPS16_26 || r_type == R_MICROMIPS_26_S1)
-          && !info->relocatable
+  else if ((mips16_branch_reloc_p (r_type)
+           || micromips_branch_reloc_p (r_type))
+          && !bfd_link_relocatable (info)
           && h != NULL
           && h->use_plt_entry
           && h->root.plt.plist->comp_offset != MINUS_ONE
@@ -5452,7 +5601,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
     {
       bfd_boolean micromips_p = MICROMIPS_P (abfd);
 
-      sec = htab->splt;
+      sec = htab->root.splt;
       symbol = (sec->output_section->vma
                + sec->output_offset
                + htab->plt_header_size
@@ -5465,10 +5614,10 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
     }
 
   /* Make sure MIPS16 and microMIPS are not used together.  */
-  if ((r_type == R_MIPS16_26 && target_is_micromips_code_p)
+  if ((mips16_branch_reloc_p (r_type) && target_is_micromips_code_p)
       || (micromips_branch_reloc_p (r_type) && target_is_16_bit_code_p))
    {
-      (*_bfd_error_handler)
+      _bfd_error_handler
        (_("MIPS16 and microMIPS functions cannot call each other"));
       return bfd_reloc_notsupported;
    }
@@ -5479,12 +5628,14 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
      because the assembly writer may have "known" that any definition of the
      symbol would be 16-bit code, and that direct jumps were therefore
      acceptable.  */
-  *cross_mode_jump_p = (!info->relocatable
+  *cross_mode_jump_p = (!bfd_link_relocatable (info)
                        && !(h && h->root.root.type == bfd_link_hash_undefweak)
-                       && ((r_type == R_MIPS16_26 && !target_is_16_bit_code_p)
-                           || (r_type == R_MICROMIPS_26_S1
+                       && ((mips16_branch_reloc_p (r_type)
+                            && !target_is_16_bit_code_p)
+                           || (micromips_branch_reloc_p (r_type)
                                && !target_is_micromips_code_p)
-                           || ((r_type == R_MIPS_26 || r_type == R_MIPS_JALR)
+                           || ((branch_reloc_p (r_type)
+                                || r_type == R_MIPS_JALR)
                                && (target_is_16_bit_code_p
                                    || target_is_micromips_code_p))));
 
@@ -5566,7 +5717,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
              if (!TLS_RELOC_P (r_type)
                  && !elf_hash_table (info)->dynamic_sections_created)
                /* This is a static link.  We must initialize the GOT entry.  */
-               MIPS_ELF_PUT_WORD (dynobj, symbol, htab->sgot->contents + g);
+               MIPS_ELF_PUT_WORD (dynobj, symbol, htab->root.sgot->contents + g);
            }
        }
       else if (!htab->is_vxworks
@@ -5621,14 +5772,16 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       return bfd_reloc_continue;
 
     case R_MIPS_16:
-      value = symbol + _bfd_mips_elf_sign_extend (addend, 16);
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 16);
+      value = symbol + addend;
       overflowed_p = mips_elf_overflow_p (value, 16);
       break;
 
     case R_MIPS_32:
     case R_MIPS_REL32:
     case R_MIPS_64:
-      if ((info->shared
+      if ((bfd_link_pic (info)
           || (htab->root.dynamic_sections_created
               && h != NULL
               && h->root.def_dynamic
@@ -5683,20 +5836,26 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
       {
        unsigned int shift;
 
-       /* Make sure the target of JALX is word-aligned.  Bit 0 must be
-          the correct ISA mode selector and bit 1 must be 0.  */
-       if (*cross_mode_jump_p && (symbol & 3) != (r_type == R_MIPS_26))
-         return bfd_reloc_outofrange;
-
        /* Shift is 2, unusually, for microMIPS JALX.  */
        shift = (!*cross_mode_jump_p && r_type == R_MICROMIPS_26_S1) ? 1 : 2;
 
-       if (was_local_p)
-         value = addend | ((p + 4) & (0xfc000000 << shift));
-       else
+       if (howto->partial_inplace && !section_p)
          value = _bfd_mips_elf_sign_extend (addend, 26 + shift);
-       value = (value + symbol) >> shift;
-       if (!was_local_p && h->root.root.type != bfd_link_hash_undefweak)
+       else
+         value = addend;
+       value += symbol;
+
+       /* Make sure the target of a jump is suitably aligned.  Bit 0 must
+          be the correct ISA mode selector except for weak undefined
+          symbols.  */
+       if ((was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+           && (*cross_mode_jump_p
+               ? (value & 3) != (r_type == R_MIPS_26)
+               : (value & ((1 << shift) - 1)) != (r_type != R_MIPS_26)))
+         return bfd_reloc_outofrange;
+
+       value >>= shift;
+       if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
          overflowed_p = (value >> 26) != ((p + 4) >> (26 + shift));
        value &= howto->dst_mask;
       }
@@ -5831,7 +5990,8 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
         to them before.  */
       if (was_local_p)
        value += gp0;
-      overflowed_p = mips_elf_overflow_p (value, 16);
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 16);
       break;
 
     case R_MIPS16_GOT16:
@@ -5879,36 +6039,168 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
 
     case R_MIPS_PC16:
     case R_MIPS_GNU_REL16_S2:
-      value = symbol + _bfd_mips_elf_sign_extend (addend, 18) - p;
-      overflowed_p = mips_elf_overflow_p (value, 18);
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 18);
+
+      /* No need to exclude weak undefined symbols here as they resolve
+         to 0 and never set `*cross_mode_jump_p', so this alignment check
+         will never trigger for them.  */
+      if (*cross_mode_jump_p
+         ? ((symbol + addend) & 3) != 1
+         : ((symbol + addend) & 3) != 0)
+       return bfd_reloc_outofrange;
+
+      value = symbol + addend - p;
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 18);
+      value >>= howto->rightshift;
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS16_PC16_S1:
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 17);
+
+      if ((was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+         && (*cross_mode_jump_p
+             ? ((symbol + addend) & 3) != 0
+             : ((symbol + addend) & 1) == 0))
+       return bfd_reloc_outofrange;
+
+      value = symbol + addend - p;
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 17);
+      value >>= howto->rightshift;
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_PC21_S2:
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 23);
+
+      if ((symbol + addend) & 3)
+       return bfd_reloc_outofrange;
+
+      value = symbol + addend - p;
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 23);
+      value >>= howto->rightshift;
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_PC26_S2:
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 28);
+
+      if ((symbol + addend) & 3)
+       return bfd_reloc_outofrange;
+
+      value = symbol + addend - p;
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 28);
+      value >>= howto->rightshift;
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_PC18_S3:
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 21);
+
+      if ((symbol + addend) & 7)
+       return bfd_reloc_outofrange;
+
+      value = symbol + addend - ((p | 7) ^ 7);
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 21);
+      value >>= howto->rightshift;
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_PC19_S2:
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 21);
+
+      if ((symbol + addend) & 3)
+       return bfd_reloc_outofrange;
+
+      value = symbol + addend - p;
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 21);
       value >>= howto->rightshift;
       value &= howto->dst_mask;
       break;
 
+    case R_MIPS_PCHI16:
+      value = mips_elf_high (symbol + addend - p);
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 16);
+      value &= howto->dst_mask;
+      break;
+
+    case R_MIPS_PCLO16:
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 16);
+      value = symbol + addend - p;
+      value &= howto->dst_mask;
+      break;
+
     case R_MICROMIPS_PC7_S1:
-      value = symbol + _bfd_mips_elf_sign_extend (addend, 8) - p;
-      overflowed_p = mips_elf_overflow_p (value, 8);
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 8);
+
+      if ((was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+         && (*cross_mode_jump_p
+             ? ((symbol + addend + 2) & 3) != 0
+             : ((symbol + addend + 2) & 1) == 0))
+       return bfd_reloc_outofrange;
+
+      value = symbol + addend - p;
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 8);
       value >>= howto->rightshift;
       value &= howto->dst_mask;
       break;
 
     case R_MICROMIPS_PC10_S1:
-      value = symbol + _bfd_mips_elf_sign_extend (addend, 11) - p;
-      overflowed_p = mips_elf_overflow_p (value, 11);
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 11);
+
+      if ((was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+         && (*cross_mode_jump_p
+             ? ((symbol + addend + 2) & 3) != 0
+             : ((symbol + addend + 2) & 1) == 0))
+       return bfd_reloc_outofrange;
+
+      value = symbol + addend - p;
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 11);
       value >>= howto->rightshift;
       value &= howto->dst_mask;
       break;
 
     case R_MICROMIPS_PC16_S1:
-      value = symbol + _bfd_mips_elf_sign_extend (addend, 17) - p;
-      overflowed_p = mips_elf_overflow_p (value, 17);
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 17);
+
+      if ((was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+         && (*cross_mode_jump_p
+             ? ((symbol + addend) & 3) != 0
+             : ((symbol + addend) & 1) == 0))
+       return bfd_reloc_outofrange;
+
+      value = symbol + addend - p;
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 17);
       value >>= howto->rightshift;
       value &= howto->dst_mask;
       break;
 
     case R_MICROMIPS_PC23_S2:
-      value = symbol + _bfd_mips_elf_sign_extend (addend, 25) - ((p | 3) ^ 3);
-      overflowed_p = mips_elf_overflow_p (value, 25);
+      if (howto->partial_inplace)
+       addend = _bfd_mips_elf_sign_extend (addend, 25);
+      value = symbol + addend - ((p | 3) ^ 3);
+      if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
+       overflowed_p = mips_elf_overflow_p (value, 25);
       value >>= howto->rightshift;
       value &= howto->dst_mask;
       break;
@@ -6007,11 +6299,13 @@ mips_elf_obtain_contents (reloc_howto_type *howto,
                          const Elf_Internal_Rela *relocation,
                          bfd *input_bfd, bfd_byte *contents)
 {
-  bfd_vma x;
+  bfd_vma x = 0;
   bfd_byte *location = contents + relocation->r_offset;
+  unsigned int size = bfd_get_reloc_size (howto);
 
   /* Obtain the bytes.  */
-  x = bfd_get ((8 * bfd_get_reloc_size (howto)), input_bfd, location);
+  if (size != 0)
+    x = bfd_get (8 * size, input_bfd, location);
 
   return x;
 }
@@ -6036,6 +6330,7 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
   bfd_vma x;
   bfd_byte *location;
   int r_type = ELF_R_TYPE (input_bfd, relocation->r_info);
+  unsigned int size;
 
   /* Figure out where the relocation is occurring.  */
   location = contents + relocation->r_offset;
@@ -6051,7 +6346,21 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
   /* Set the field.  */
   x |= (value & howto->dst_mask);
 
-  /* If required, turn JAL into JALX.  */
+  /* Detect incorrect JALX usage.  If required, turn JAL or BAL into JALX.  */
+  if (!cross_mode_jump_p && jal_reloc_p (r_type))
+    {
+      bfd_vma opcode = x >> 26;
+
+      if (r_type == R_MIPS16_26 ? opcode == 0x7
+         : r_type == R_MICROMIPS_26_S1 ? opcode == 0x3c
+         : opcode == 0x1d)
+       {
+         info->callbacks->einfo
+           (_("%X%H: Unsupported JALX to the same ISA mode\n"),
+            input_bfd, input_section, relocation->r_offset);
+         return TRUE;
+       }
+    }
   if (cross_mode_jump_p && jal_reloc_p (r_type))
     {
       bfd_boolean ok;
@@ -6079,22 +6388,67 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
          convert J or JALS to JALX.  */
       if (!ok)
        {
-         (*_bfd_error_handler)
-           (_("%B: %A+0x%lx: Unsupported jump between ISA modes; consider recompiling with interlinking enabled."),
-            input_bfd,
-            input_section,
-            (unsigned long) relocation->r_offset);
-         bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         info->callbacks->einfo
+           (_("%X%H: Unsupported jump between ISA modes; "
+              "consider recompiling with interlinking enabled\n"),
+            input_bfd, input_section, relocation->r_offset);
+         return TRUE;
        }
 
       /* Make this the JALX opcode.  */
       x = (x & ~(0x3f << 26)) | (jalx_opcode << 26);
     }
+  else if (cross_mode_jump_p && b_reloc_p (r_type))
+    {
+      bfd_boolean ok = FALSE;
+      bfd_vma opcode = x >> 16;
+      bfd_vma jalx_opcode = 0;
+      bfd_vma addr;
+      bfd_vma dest;
+
+      if (r_type == R_MICROMIPS_PC16_S1)
+       {
+         ok = opcode == 0x4060;
+         jalx_opcode = 0x3c;
+         value <<= 1;
+       }
+      else if (r_type == R_MIPS_PC16 || r_type == R_MIPS_GNU_REL16_S2)
+       {
+         ok = opcode == 0x411;
+         jalx_opcode = 0x1d;
+         value <<= 2;
+       }
+
+      if (bfd_link_pic (info) || !ok)
+       {
+         info->callbacks->einfo
+           (_("%X%H: Unsupported branch between ISA modes\n"),
+            input_bfd, input_section, relocation->r_offset);
+         return TRUE;
+       }
+
+      addr = (input_section->output_section->vma
+             + input_section->output_offset
+             + relocation->r_offset
+             + 4);
+      dest = addr + (((value & 0x3ffff) ^ 0x20000) - 0x20000);
+
+      if ((addr >> 28) << 28 != (dest >> 28) << 28)
+       {
+         info->callbacks->einfo
+           (_("%X%H: Cannot convert branch between ISA modes "
+              "to JALX: relocation out of range\n"),
+            input_bfd, input_section, relocation->r_offset);
+         return TRUE;
+       }
+
+      /* Make this the JALX opcode.  */
+      x = ((dest >> 2) & 0x3ffffff) | jalx_opcode << 26;
+    }
 
   /* Try converting JAL to BAL and J(AL)R to B(AL), if the target is in
      range.  */
-  if (!info->relocatable
+  if (!bfd_link_relocatable (info)
       && !cross_mode_jump_p
       && ((JAL_TO_BAL_P (input_bfd)
           && r_type == R_MIPS_26
@@ -6129,9 +6483,11 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
     }
 
   /* Put the value into the output.  */
-  bfd_put (8 * bfd_get_reloc_size (howto), input_bfd, x, location);
+  size = bfd_get_reloc_size (howto);
+  if (size != 0)
+    bfd_put (8 * size, input_bfd, x, location);
 
-  _bfd_mips_elf_reloc_shuffle (input_bfd, r_type, !info->relocatable,
+  _bfd_mips_elf_reloc_shuffle (input_bfd, r_type, !bfd_link_relocatable (info),
                               location);
 
   return TRUE;
@@ -6412,6 +6768,9 @@ _bfd_elf_mips_mach (flagword flags)
     case E_MIPS_MACH_LS3A:
       return bfd_mach_mips_loongson_3a;
 
+    case E_MIPS_MACH_OCTEON3:
+      return bfd_mach_mips_octeon3;
+
     case E_MIPS_MACH_OCTEON2:
       return bfd_mach_mips_octeon2;
 
@@ -6451,6 +6810,12 @@ _bfd_elf_mips_mach (flagword flags)
 
        case E_MIPS_ARCH_64R2:
          return bfd_mach_mipsisa64r2;
+
+       case E_MIPS_ARCH_32R6:
+         return bfd_mach_mipsisa32r6;
+
+       case E_MIPS_ARCH_64R6:
+         return bfd_mach_mipsisa64r6;
        }
     }
 
@@ -6748,7 +7113,8 @@ _bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr)
                                        &intopt);
          if (intopt.size < sizeof (Elf_External_Options))
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B: Warning: bad `%s' option size %u smaller than its header"),
                abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size);
              break;
@@ -6801,20 +7167,11 @@ _bfd_mips_elf_section_processing (bfd *abfd, Elf_Internal_Shdr *hdr)
       if (strcmp (name, ".sdata") == 0
          || strcmp (name, ".lit8") == 0
          || strcmp (name, ".lit4") == 0)
-       {
-         hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
-         hdr->sh_type = SHT_PROGBITS;
-       }
+       hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
       else if (strcmp (name, ".srdata") == 0)
-       {
-         hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
-         hdr->sh_type = SHT_PROGBITS;
-       }
+       hdr->sh_flags |= SHF_ALLOC | SHF_MIPS_GPREL;
       else if (strcmp (name, ".compact_rel") == 0)
-       {
-         hdr->sh_flags = 0;
-         hdr->sh_type = SHT_PROGBITS;
-       }
+       hdr->sh_flags = 0;
       else if (strcmp (name, ".rtproc") == 0)
        {
          if (hdr->sh_addralign != 0 && hdr->sh_entsize == 0)
@@ -6896,6 +7253,11 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd,
       if (!MIPS_ELF_OPTIONS_SECTION_NAME_P (name))
        return FALSE;
       break;
+    case SHT_MIPS_ABIFLAGS:
+      if (!MIPS_ELF_ABIFLAGS_SECTION_NAME_P (name))
+       return FALSE;
+      flags = (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_SIZE);
+      break;
     case SHT_MIPS_DWARF:
       if (! CONST_STRNEQ (name, ".debug_")
           && ! CONST_STRNEQ (name, ".zdebug_"))
@@ -6926,6 +7288,20 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd,
        return FALSE;
     }
 
+  if (hdr->sh_type == SHT_MIPS_ABIFLAGS)
+    {
+      Elf_External_ABIFlags_v0 ext;
+
+      if (! bfd_get_section_contents (abfd, hdr->bfd_section,
+                                     &ext, 0, sizeof ext))
+       return FALSE;
+      bfd_mips_elf_swap_abiflags_v0_in (abfd, &ext,
+                                       &mips_elf_tdata (abfd)->abiflags);
+      if (mips_elf_tdata (abfd)->abiflags.version != 0)
+       return FALSE;
+      mips_elf_tdata (abfd)->abiflags_valid = TRUE;
+    }
+
   /* FIXME: We should record sh_info for a .gptab section.  */
 
   /* For a .reginfo section, set the gp value in the tdata information
@@ -6971,7 +7347,8 @@ _bfd_mips_elf_section_from_shdr (bfd *abfd,
                                        &intopt);
          if (intopt.size < sizeof (Elf_External_Options))
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B: Warning: bad `%s' option size %u smaller than its header"),
                abfd, MIPS_ELF_OPTIONS_SECTION_NAME (abfd), intopt.size);
              break;
@@ -7092,6 +7469,11 @@ _bfd_mips_elf_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec)
       hdr->sh_entsize = 1;
       hdr->sh_flags |= SHF_MIPS_NOSTRIP;
     }
+  else if (CONST_STRNEQ (name, ".MIPS.abiflags"))
+    {
+      hdr->sh_type = SHT_MIPS_ABIFLAGS;
+      hdr->sh_entsize = sizeof (Elf_External_ABIFlags_v0);
+    }
   else if (CONST_STRNEQ (name, ".debug_")
            || CONST_STRNEQ (name, ".zdebug_"))
     {
@@ -7237,7 +7619,7 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
          elf_text_symbol->section = elf_text_section;
        }
       /* This code used to do *secp = bfd_und_section_ptr if
-         info->shared.  I don't know why, and that doesn't make sense,
+         bfd_link_pic (info).  I don't know why, and that doesn't make sense,
          so I took it out.  */
       *secp = mips_elf_tdata (abfd)->elf_text_section;
       break;
@@ -7278,7 +7660,7 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
          elf_data_symbol->section = elf_data_section;
        }
       /* This code used to do *secp = bfd_und_section_ptr if
-         info->shared.  I don't know why, and that doesn't make sense,
+         bfd_link_pic (info).  I don't know why, and that doesn't make sense,
          so I took it out.  */
       *secp = mips_elf_tdata (abfd)->elf_data_section;
       break;
@@ -7289,7 +7671,7 @@ _bfd_mips_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
     }
 
   if (SGI_COMPAT (abfd)
-      && ! info->shared
+      && ! bfd_link_pic (info)
       && info->output_bfd->xvec == abfd->xvec
       && strcmp (*namep, "__rld_obj_head") == 0)
     {
@@ -7397,7 +7779,7 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   htab->sstubs = s;
 
   if (!mips_elf_hash_table (info)->use_rld_obj_head
-      && !info->shared
+      && bfd_link_executable (info)
       && bfd_get_linker_section (abfd, ".rld_map") == NULL)
     {
       s = bfd_make_section_anyway_with_flags (abfd, ".rld_map",
@@ -7461,7 +7843,7 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
        (void) bfd_set_section_alignment (abfd, s, MIPS_ELF_LOG_FILE_ALIGN (abfd));
     }
 
-  if (!info->shared)
+  if (bfd_link_executable (info))
     {
       const char *name;
 
@@ -7513,19 +7895,13 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
     return FALSE;
 
   /* Cache the sections created above.  */
-  htab->splt = bfd_get_linker_section (abfd, ".plt");
   htab->sdynbss = bfd_get_linker_section (abfd, ".dynbss");
   if (htab->is_vxworks)
-    {
-      htab->srelbss = bfd_get_linker_section (abfd, ".rela.bss");
-      htab->srelplt = bfd_get_linker_section (abfd, ".rela.plt");
-    }
-  else
-    htab->srelplt = bfd_get_linker_section (abfd, ".rel.plt");
+    htab->srelbss = bfd_get_linker_section (abfd, ".rela.bss");
   if (!htab->sdynbss
-      || (htab->is_vxworks && !htab->srelbss && !info->shared)
-      || !htab->srelplt
-      || !htab->splt)
+      || (htab->is_vxworks && !htab->srelbss && !bfd_link_pic (info))
+      || !htab->root.srelplt
+      || !htab->root.splt)
     abort ();
 
   /* Do the usual VxWorks handling.  */
@@ -7569,16 +7945,24 @@ mips_elf_read_rel_addend (bfd *abfd, const Elf_Internal_Rela *rel,
   bfd_byte *location;
   unsigned int r_type;
   bfd_vma addend;
+  bfd_vma bytes;
 
   r_type = ELF_R_TYPE (abfd, rel->r_info);
   location = contents + rel->r_offset;
 
   /* Get the addend, which is stored in the input file.  */
   _bfd_mips_elf_reloc_unshuffle (abfd, r_type, FALSE, location);
-  addend = mips_elf_obtain_contents (howto, rel, abfd, contents);
+  bytes = mips_elf_obtain_contents (howto, rel, abfd, contents);
   _bfd_mips_elf_reloc_shuffle (abfd, r_type, FALSE, location);
 
-  return addend & howto->src_mask;
+  addend = bytes & howto->src_mask;
+
+  /* Shift is 2, unusually, for microMIPS JALX.  Adjust the addend
+     accordingly.  */
+  if (r_type == R_MICROMIPS_26_S1 && (bytes >> 26) == 0x3c)
+    addend <<= 1;
+
+  return addend;
 }
 
 /* REL is a relocation in ABFD that needs a partnering LO16 relocation
@@ -7603,6 +7987,8 @@ mips_elf_add_lo16_rel_addend (bfd *abfd,
     lo16_type = R_MIPS16_LO16;
   else if (micromips_reloc_p (r_type))
     lo16_type = R_MICROMIPS_LO16;
+  else if (r_type == R_MIPS_PCHI16)
+    lo16_type = R_MIPS_PCLO16;
   else
     lo16_type = R_MIPS_LO16;
 
@@ -7699,7 +8085,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
   bfd_vma addend;
   reloc_howto_type *howto;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   htab = mips_elf_hash_table (info);
@@ -7726,7 +8112,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       r_symndx = mips16_stub_symndx (bed, sec, relocs, rel_end);
       if (r_symndx == 0)
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: Warning: cannot determine the target function for"
               " stub section `%s'"),
             abfd, name);
@@ -7851,7 +8238,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       r_symndx = mips16_stub_symndx (bed, sec, relocs, rel_end);
       if (r_symndx == 0)
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: Warning: cannot determine the target function for"
               " stub section `%s'"),
             abfd, name);
@@ -7982,7 +8370,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        h = NULL;
       else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr))
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: Malformed reloc detected for section %s"),
             abfd, name);
          bfd_set_error (bfd_error_bad_value);
@@ -8055,9 +8444,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            elf_hash_table (info)->dynobj = dynobj = abfd;
          if (!mips_elf_create_got_section (dynobj, info))
            return FALSE;
-         if (htab->is_vxworks && !info->shared)
+         if (htab->is_vxworks && !bfd_link_pic (info))
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B: GOT reloc at 0x%lx not expected in executables"),
                 abfd, (unsigned long) rel->r_offset);
              bfd_set_error (bfd_error_bad_value);
@@ -8098,7 +8488,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
             one or using copy relocations or PLT entries.  It is
             usually better to do the former, unless the relocation is
             against a read-only section.  */
-         if ((info->shared
+         if ((bfd_link_pic (info)
               || (h != NULL
                   && !htab->is_vxworks
                   && strcmp (h->root.root.string, "__gnu_local_gp") != 0
@@ -8115,7 +8505,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
        case R_MIPS_26:
        case R_MIPS_PC16:
+       case R_MIPS_PC21_S2:
+       case R_MIPS_PC26_S2:
        case R_MIPS16_26:
+       case R_MIPS16_PC16_S1:
        case R_MICROMIPS_26_S1:
        case R_MICROMIPS_PC7_S1:
        case R_MICROMIPS_PC10_S1:
@@ -8191,7 +8584,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_MICROMIPS_CALL16:
          if (h == NULL)
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B: CALL16 reloc at 0x%lx not against global symbol"),
                 abfd, (unsigned long) rel->r_offset);
              bfd_set_error (bfd_error_bad_value);
@@ -8261,7 +8655,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
                  /* This symbol is definitely not overridable.  */
                  if (hmips->root.def_regular
-                     && ! (info->shared && ! info->symbolic
+                     && ! (bfd_link_pic (info) && ! info->symbolic
                            && ! hmips->root.forced_local))
                    h = NULL;
                }
@@ -8280,7 +8674,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_MIPS_TLS_GOTTPREL:
        case R_MIPS16_TLS_GOTTPREL:
        case R_MICROMIPS_TLS_GOTTPREL:
-         if (info->shared)
+         if (bfd_link_pic (info))
            info->flags |= DF_STATIC_TLS;
          /* Fall through */
 
@@ -8328,7 +8722,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                  if (sreloc == NULL)
                    return FALSE;
                }
-             if (info->shared && h == NULL)
+             if (bfd_link_pic (info) && h == NULL)
                {
                  /* When creating a shared object, we must copy these
                     reloc types into the output file as R_MIPS_REL32
@@ -8409,7 +8803,9 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          a PLT entry is not created because the symbol is satisfied
          locally.  */
       if (h != NULL
-         && jal_reloc_p (r_type)
+         && (branch_reloc_p (r_type)
+             || mips16_branch_reloc_p (r_type)
+             || micromips_branch_reloc_p (r_type))
          && !SYMBOL_CALLS_LOCAL (info, h))
        {
          if (h->plt.plist == NULL)
@@ -8417,7 +8813,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          if (h->plt.plist == NULL)
            return FALSE;
 
-         if (r_type == R_MIPS_26)
+         if (branch_reloc_p (r_type))
            h->plt.plist->need_mips = TRUE;
          else
            h->plt.plist->need_comp = TRUE;
@@ -8442,7 +8838,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
         not PIC, but we can create dynamic relocations and the result
         will be fine.  Also do not refuse R_MIPS_LO16, which can be
         combined with R_MIPS_GOT16.  */
-      if (info->shared)
+      if (bfd_link_pic (info))
        {
          switch (r_type)
            {
@@ -8474,7 +8870,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            case R_MIPS_26:
            case R_MICROMIPS_26_S1:
              howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, r_type, FALSE);
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"),
                 abfd, howto->name,
                 (h) ? h->root.root.string : "a local symbol");
@@ -8506,7 +8903,7 @@ _bfd_mips_relax_section (bfd *abfd, asection *sec,
   /* We are not currently changing any sizes, so only one pass.  */
   *again = FALSE;
 
-  if (link_info->relocatable)
+  if (bfd_link_relocatable (link_info))
     return TRUE;
 
   internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
@@ -8552,7 +8949,7 @@ _bfd_mips_relax_section (bfd *abfd, asection *sec,
          if (! ((h->root.root.type == bfd_link_hash_defined
                  || h->root.root.type == bfd_link_hash_defweak)
                 && h->root.root.u.def.section)
-             || (link_info->shared && ! link_info->symbolic
+             || (bfd_link_pic (link_info) && ! link_info->symbolic
                  && !h->root.forced_local))
            continue;
 
@@ -8668,7 +9065,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
   /* VxWorks executables are handled elsewhere; we only need to
      allocate relocations in shared objects.  */
-  if (htab->is_vxworks && !info->shared)
+  if (htab->is_vxworks && !bfd_link_pic (info))
     return TRUE;
 
   /* Ignore indirect symbols.  All relocations against such symbols
@@ -8679,11 +9076,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   /* If this symbol is defined in a dynamic object, or we are creating
      a shared library, we will need to copy any R_MIPS_32 or
      R_MIPS_REL32 relocs against it into the output file.  */
-  if (! info->relocatable
+  if (! bfd_link_relocatable (info)
       && hmips->possibly_dynamic_relocs != 0
       && (h->root.type == bfd_link_hash_defweak
          || (!h->def_regular && !ELF_COMMON_DEF_P (h))
-         || info->shared))
+         || bfd_link_pic (info)))
     {
       bfd_boolean do_copy = TRUE;
 
@@ -8811,7 +9208,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
          for PLT offset calculations.  */
       if (htab->plt_mips_offset + htab->plt_comp_offset == 0)
        {
-         BFD_ASSERT (htab->sgotplt->size == 0);
+         BFD_ASSERT (htab->root.sgotplt->size == 0);
          BFD_ASSERT (htab->plt_got_index == 0);
 
          /* If we're using the PLT additions to the psABI, each PLT
@@ -8819,12 +9216,12 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
             Encourage better cache usage by aligning.  We do this
             lazily to avoid pessimizing traditional objects.  */
          if (!htab->is_vxworks
-             && !bfd_set_section_alignment (dynobj, htab->splt, 5))
+             && !bfd_set_section_alignment (dynobj, htab->root.splt, 5))
            return FALSE;
 
          /* Make sure that .got.plt is word-aligned.  We do this lazily
             for the same reason as above.  */
-         if (!bfd_set_section_alignment (dynobj, htab->sgotplt,
+         if (!bfd_set_section_alignment (dynobj, htab->root.sgotplt,
                                          MIPS_ELF_LOG_FILE_ALIGN (dynobj)))
            return FALSE;
 
@@ -8837,11 +9234,11 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
          /* On VxWorks, also allocate room for the header's
             .rela.plt.unloaded entries.  */
-         if (htab->is_vxworks && !info->shared)
+         if (htab->is_vxworks && !bfd_link_pic (info))
            htab->srelplt2->size += 2 * sizeof (Elf32_External_Rela);
 
          /* Now work out the sizes of individual PLT entries.  */
-         if (htab->is_vxworks && info->shared)
+         if (htab->is_vxworks && bfd_link_pic (info))
            htab->plt_mips_entry_size
              = 4 * ARRAY_SIZE (mips_vxworks_shared_plt_entry);
          else if (htab->is_vxworks)
@@ -8925,16 +9322,16 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
       /* If the output file has no definition of the symbol, set the
         symbol's value to the address of the stub.  */
-      if (!info->shared && !h->def_regular)
+      if (!bfd_link_pic (info) && !h->def_regular)
        hmips->use_plt_entry = TRUE;
 
       /* Make room for the R_MIPS_JUMP_SLOT relocation.  */
-      htab->srelplt->size += (htab->is_vxworks
-                             ? MIPS_ELF_RELA_SIZE (dynobj)
-                             : MIPS_ELF_REL_SIZE (dynobj));
+      htab->root.srelplt->size += (htab->is_vxworks
+                                  ? MIPS_ELF_RELA_SIZE (dynobj)
+                                  : MIPS_ELF_REL_SIZE (dynobj));
 
       /* Make room for the .rela.plt.unloaded relocations.  */
-      if (htab->is_vxworks && !info->shared)
+      if (htab->is_vxworks && !bfd_link_pic (info))
        htab->srelplt2->size += 3 * sizeof (Elf32_External_Rela);
 
       /* All relocations against this symbol that could have been made
@@ -8968,11 +9365,11 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   /* We're now relying on copy relocations.  Complain if we have
      some that we can't convert.  */
-  if (!htab->use_plts_and_copy_relocs || info->shared)
+  if (!htab->use_plts_and_copy_relocs || bfd_link_pic (info))
     {
-      (*_bfd_error_handler) (_("non-dynamic relocations refer to "
-                              "dynamic symbol %s"),
-                            h->root.root.string);
+      _bfd_error_handler (_("non-dynamic relocations refer to "
+                           "dynamic symbol %s"),
+                         h->root.root.string);
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
     }
@@ -9000,7 +9397,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
      dynamic will now refer to the local copy instead.  */
   hmips->possibly_dynamic_relocs = 0;
 
-  return _bfd_elf_adjust_dynamic_copy (h, htab->sdynbss);
+  return _bfd_elf_adjust_dynamic_copy (info, h, htab->sdynbss);
 }
 \f
 /* This function is called after all the input files have been read,
@@ -9011,7 +9408,7 @@ bfd_boolean
 _bfd_mips_elf_always_size_sections (bfd *output_bfd,
                                    struct bfd_link_info *info)
 {
-  asection *ri;
+  asection *sect;
   struct mips_elf_link_hash_table *htab;
   struct mips_htab_traverse_info hti;
 
@@ -9019,9 +9416,14 @@ _bfd_mips_elf_always_size_sections (bfd *output_bfd,
   BFD_ASSERT (htab != NULL);
 
   /* The .reginfo section has a fixed size.  */
-  ri = bfd_get_section_by_name (output_bfd, ".reginfo");
-  if (ri != NULL)
-    bfd_set_section_size (output_bfd, ri, sizeof (Elf32_External_RegInfo));
+  sect = bfd_get_section_by_name (output_bfd, ".reginfo");
+  if (sect != NULL)
+    bfd_set_section_size (output_bfd, sect, sizeof (Elf32_External_RegInfo));
+
+  /* The .MIPS.abiflags section has a fixed size.  */
+  sect = bfd_get_section_by_name (output_bfd, ".MIPS.abiflags");
+  if (sect != NULL)
+    bfd_set_section_size (output_bfd, sect, sizeof (Elf_External_ABIFlags_v0));
 
   hti.info = info;
   hti.output_bfd = output_bfd;
@@ -9051,7 +9453,7 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
   htab = mips_elf_hash_table (info);
   BFD_ASSERT (htab != NULL);
 
-  s = htab->sgot;
+  s = htab->root.sgot;
   if (s == NULL)
     return TRUE;
 
@@ -9060,13 +9462,13 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
 
   /* Allocate room for the reserved entries.  VxWorks always reserves
      3 entries; other objects only reserve 2 entries.  */
-  BFD_ASSERT (g->assigned_gotno == 0);
+  BFD_ASSERT (g->assigned_low_gotno == 0);
   if (htab->is_vxworks)
     htab->reserved_gotno = 3;
   else
     htab->reserved_gotno = 2;
   g->local_gotno += htab->reserved_gotno;
-  g->assigned_gotno = htab->reserved_gotno;
+  g->assigned_low_gotno = htab->reserved_gotno;
 
   /* Decide which symbols need to go in the global part of the GOT and
      count the number of reloc-only GOT symbols.  */
@@ -9078,7 +9480,7 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
   /* Calculate the total loadable size of the output.  That
      will give us the maximum number of GOT_PAGE entries
      required.  */
-  for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next)
     {
       asection *subsection;
 
@@ -9109,6 +9511,7 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
     page_gotno = g->page_gotno;
 
   g->local_gotno += page_gotno;
+  g->assigned_high_gotno = g->local_gotno - 1;
 
   s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
   s->size += g->global_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
@@ -9126,7 +9529,7 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
     {
       /* Record that all bfds use G.  This also has the effect of freeing
         the per-bfd GOTs, which we no longer need.  */
-      for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link_next)
+      for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next)
        if (mips_elf_bfd_got (ibfd, FALSE))
          mips_elf_replace_bfd_got (ibfd, g);
       mips_elf_replace_bfd_got (output_bfd, g);
@@ -9143,7 +9546,7 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
                  == g->global_gotno + g->local_gotno + g->tls_gotno);
 
       /* Each VxWorks GOT entry needs an explicit relocation.  */
-      if (htab->is_vxworks && info->shared)
+      if (htab->is_vxworks && bfd_link_pic (info))
        g->relocs += g->global_gotno + g->local_gotno - htab->reserved_gotno;
 
       /* Allocate room for the TLS relocations.  */
@@ -9328,7 +9731,7 @@ mips_elf_set_plt_sym_value (struct mips_elf_link_hash_entry *h, void *data)
       if (htab->is_vxworks)
        val += 8;
 
-      h->root.root.u.def.section = htab->splt;
+      h->root.root.u.def.section = htab->root.splt;
       h->root.root.u.def.value = val;
       h->root.other = other;
     }
@@ -9355,7 +9758,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (info->executable)
+      if (bfd_link_executable (info) && !info->nointerp)
        {
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
@@ -9377,7 +9780,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
 
          Also create the _PROCEDURE_LINKAGE_TABLE_ symbol if we
          haven't already in _bfd_elf_create_dynamic_sections.  */
-      if (htab->splt && htab->plt_mips_offset + htab->plt_comp_offset != 0)
+      if (htab->root.splt && htab->plt_mips_offset + htab->plt_comp_offset != 0)
        {
          bfd_boolean micromips_p = (MICROMIPS_P (output_bfd)
                                     && !htab->plt_mips_offset);
@@ -9387,10 +9790,10 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
          bfd_vma size;
 
          BFD_ASSERT (htab->use_plts_and_copy_relocs);
-         BFD_ASSERT (htab->sgotplt->size == 0);
-         BFD_ASSERT (htab->splt->size == 0);
+         BFD_ASSERT (htab->root.sgotplt->size == 0);
+         BFD_ASSERT (htab->root.splt->size == 0);
 
-         if (htab->is_vxworks && info->shared)
+         if (htab->is_vxworks && bfd_link_pic (info))
            size = 4 * ARRAY_SIZE (mips_vxworks_shared_plt0_entry);
          else if (htab->is_vxworks)
            size = 4 * ARRAY_SIZE (mips_vxworks_exec_plt0_entry);
@@ -9407,17 +9810,17 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
 
          htab->plt_header_is_comp = micromips_p;
          htab->plt_header_size = size;
-         htab->splt->size = (size
-                             + htab->plt_mips_offset
-                             + htab->plt_comp_offset);
-         htab->sgotplt->size = (htab->plt_got_index
-                                * MIPS_ELF_GOT_SIZE (dynobj));
+         htab->root.splt->size = (size
+                                  + htab->plt_mips_offset
+                                  + htab->plt_comp_offset);
+         htab->root.sgotplt->size = (htab->plt_got_index
+                                     * MIPS_ELF_GOT_SIZE (dynobj));
 
          mips_elf_link_hash_traverse (htab, mips_elf_set_plt_sym_value, info);
 
          if (htab->root.hplt == NULL)
            {
-             h = _bfd_elf_define_linkage_sym (dynobj, info, htab->splt,
+             h = _bfd_elf_define_linkage_sym (dynobj, info, htab->root.splt,
                                               "_PROCEDURE_LINKAGE_TABLE_");
              htab->root.hplt = h;
              if (h == NULL)
@@ -9492,7 +9895,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
              info->combreloc = 0;
            }
        }
-      else if (! info->shared
+      else if (bfd_link_executable (info)
               && ! mips_elf_hash_table (info)->use_rld_obj_head
               && CONST_STRNEQ (name, ".rld_map"))
        {
@@ -9503,7 +9906,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
       else if (SGI_COMPAT (output_bfd)
               && CONST_STRNEQ (name, ".compact_rel"))
        s->size += mips_elf_hash_table (info)->compact_rel_size;
-      else if (s == htab->splt)
+      else if (s == htab->root.splt)
        {
          /* If the last PLT entry has a branch delay slot, allocate
             room for an extra nop to fill the delay slot.  This is
@@ -9513,8 +9916,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
            s->size += 4;
        }
       else if (! CONST_STRNEQ (name, ".init")
-              && s != htab->sgot
-              && s != htab->sgotplt
+              && s != htab->root.sgot
+              && s != htab->root.sgotplt
               && s != htab->sstubs
               && s != htab->sdynbss)
        {
@@ -9551,13 +9954,17 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
         DT_MIPS_RLD_MAP entry.  This must come first because glibc
         only fills in DT_MIPS_RLD_MAP (not DT_DEBUG) and some tools
         may only look at the first one they see.  */
-      if (!info->shared
+      if (!bfd_link_pic (info)
          && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_MAP, 0))
        return FALSE;
 
+      if (bfd_link_executable (info)
+         && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RLD_MAP_REL, 0))
+       return FALSE;
+
       /* The DT_DEBUG entry may be filled in by the dynamic linker and
         used by the debugger.  */
-      if (info->executable
+      if (bfd_link_executable (info)
          && !SGI_COMPAT (output_bfd)
          && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0))
        return FALSE;
@@ -9642,7 +10049,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
              && !MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_OPTIONS, 0))
            return FALSE;
        }
-      if (htab->splt->size > 0)
+      if (htab->root.splt->size > 0)
        {
          if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTREL, 0))
            return FALSE;
@@ -9693,7 +10100,7 @@ mips_elf_adjust_addend (bfd *output_bfd, struct bfd_link_info *info,
       sym = local_syms + r_symndx;
 
       /* Adjust REL's addend to account for section merging.  */
-      if (!info->relocatable)
+      if (!bfd_link_relocatable (info))
        {
          sec = local_sections[r_symndx];
          _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
@@ -9869,7 +10276,8 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                        name = bfd_elf_sym_name (input_bfd, symtab_hdr,
                                                 local_syms + r_symndx,
                                                 sec);
-                     (*_bfd_error_handler)
+                     _bfd_error_handler
+                       /* xgettext:c-format */
                        (_("%B: Can't find matching LO16 reloc against `%s' for %s at 0x%lx in section `%A'"),
                         input_bfd, input_section, name, howto->name,
                         rel->r_offset);
@@ -9884,7 +10292,7 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                                  local_syms, local_sections, rel);
        }
 
-      if (info->relocatable)
+      if (bfd_link_relocatable (info))
        {
          if (r_type == R_MIPS_64 && ! NEWABI_P (output_bfd)
              && bfd_big_endian (input_bfd))
@@ -10015,10 +10423,9 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                  htab->small_data_overflow_reported = TRUE;
                  (*info->callbacks->einfo) ("%P: %s\n", msg);
                }
-             if (! ((*info->callbacks->reloc_overflow)
-                    (info, NULL, name, howto->name, (bfd_vma) 0,
-                     input_bfd, input_section, rel->r_offset)))
-               return FALSE;
+             (*info->callbacks->reloc_overflow)
+               (info, NULL, name, howto->name, (bfd_vma) 0,
+                input_bfd, input_section, rel->r_offset);
            }
          break;
 
@@ -10026,12 +10433,26 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          break;
 
        case bfd_reloc_outofrange:
+         msg = NULL;
          if (jal_reloc_p (howto->type))
+           msg = (cross_mode_jump_p
+                  ? _("Cannot convert a jump to JALX "
+                      "for a non-word-aligned address")
+                  : (howto->type == R_MIPS16_26
+                     ? _("Jump to a non-word-aligned address")
+                     : _("Jump to a non-instruction-aligned address")));
+         else if (b_reloc_p (howto->type))
+           msg = (cross_mode_jump_p
+                  ? _("Cannot convert a branch to JALX "
+                      "for a non-word-aligned address")
+                  : _("Branch to a non-instruction-aligned address"));
+         else if (aligned_pcrel_reloc_p (howto->type))
+           msg = _("PC-relative load from unaligned address");
+         if (msg)
            {
-             msg = _("JALX to a non-word-aligned address");
-             info->callbacks->warning
-               (info, msg, name, input_bfd, input_section, rel->r_offset);
-             return FALSE;
+             info->callbacks->einfo
+               ("%X%H: %s\n", input_bfd, input_section, rel->r_offset, msg);
+             break;
            }
          /* Fall through.  */
 
@@ -10280,25 +10701,25 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
 
       BFD_ASSERT (htab->use_plts_and_copy_relocs);
       BFD_ASSERT (h->dynindx != -1);
-      BFD_ASSERT (htab->splt != NULL);
+      BFD_ASSERT (htab->root.splt != NULL);
       BFD_ASSERT (got_index != MINUS_ONE);
       BFD_ASSERT (!h->def_regular);
 
       /* Calculate the address of the PLT header.  */
       isa_bit = htab->plt_header_is_comp;
-      header_address = (htab->splt->output_section->vma
-                       + htab->splt->output_offset + isa_bit);
+      header_address = (htab->root.splt->output_section->vma
+                       + htab->root.splt->output_offset + isa_bit);
 
       /* Calculate the address of the .got.plt entry.  */
-      got_address = (htab->sgotplt->output_section->vma
-                    + htab->sgotplt->output_offset
+      got_address = (htab->root.sgotplt->output_section->vma
+                    + htab->root.sgotplt->output_offset
                     + got_index * MIPS_ELF_GOT_SIZE (dynobj));
 
       got_address_high = ((got_address + 0x8000) >> 16) & 0xffff;
       got_address_low = got_address & 0xffff;
 
       /* Initially point the .got.plt entry at the PLT header.  */
-      loc = (htab->sgotplt->contents + got_index * MIPS_ELF_GOT_SIZE (dynobj));
+      loc = (htab->root.sgotplt->contents + got_index * MIPS_ELF_GOT_SIZE (dynobj));
       if (ABI_64_P (output_bfd))
        bfd_put_64 (output_bfd, header_address, loc);
       else
@@ -10313,16 +10734,20 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
 
          plt_offset = htab->plt_header_size + h->plt.plist->mips_offset;
 
-         BFD_ASSERT (plt_offset <= htab->splt->size);
+         BFD_ASSERT (plt_offset <= htab->root.splt->size);
 
          /* Find out where the .plt entry should go.  */
-         loc = htab->splt->contents + plt_offset;
+         loc = htab->root.splt->contents + plt_offset;
 
          /* Pick the load opcode.  */
          load = MIPS_ELF_LOAD_WORD (output_bfd);
 
          /* Fill in the PLT entry itself.  */
-         plt_entry = mips_exec_plt_entry;
+
+         if (MIPSR6_P (output_bfd))
+           plt_entry = mipsr6_exec_plt_entry;
+         else
+           plt_entry = mips_exec_plt_entry;
          bfd_put_32 (output_bfd, plt_entry[0] | got_address_high, loc);
          bfd_put_32 (output_bfd, plt_entry[1] | got_address_low | load,
                      loc + 4);
@@ -10348,10 +10773,10 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
          plt_offset = (htab->plt_header_size + htab->plt_mips_offset
                        + h->plt.plist->comp_offset);
 
-         BFD_ASSERT (plt_offset <= htab->splt->size);
+         BFD_ASSERT (plt_offset <= htab->root.splt->size);
 
          /* Find out where the .plt entry should go.  */
-         loc = htab->splt->contents + plt_offset;
+         loc = htab->root.splt->contents + plt_offset;
 
          /* Fill in the PLT entry itself.  */
          if (!MICROMIPS_P (output_bfd))
@@ -10387,19 +10812,20 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
 
              BFD_ASSERT (got_address % 4 == 0);
 
-             loc_address = (htab->splt->output_section->vma
-                            + htab->splt->output_offset + plt_offset);
+             loc_address = (htab->root.splt->output_section->vma
+                            + htab->root.splt->output_offset + plt_offset);
              gotpc_offset = got_address - ((loc_address | 3) ^ 3);
 
              /* ADDIUPC has a span of +/-16MB, check we're in range.  */
              if (gotpc_offset + 0x1000000 >= 0x2000000)
                {
-                 (*_bfd_error_handler)
+                 _bfd_error_handler
+                   /* xgettext:c-format */
                    (_("%B: `%A' offset of %ld from `%A' "
                       "beyond the range of ADDIUPC"),
                     output_bfd,
-                    htab->sgotplt->output_section,
-                    htab->splt->output_section,
+                    htab->root.sgotplt->output_section,
+                    htab->root.splt->output_section,
                     (long) gotpc_offset);
                  bfd_set_error (bfd_error_no_error);
                  return FALSE;
@@ -10415,7 +10841,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
        }
 
       /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry.  */
-      mips_elf_output_dynamic_relocation (output_bfd, htab->srelplt,
+      mips_elf_output_dynamic_relocation (output_bfd, htab->root.srelplt,
                                          got_index - 2, h->dynindx,
                                          R_MIPS_JUMP_SLOT, got_address);
 
@@ -10472,8 +10898,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
          if (htab->insn32)
            {
              bfd_put_micromips_32 (output_bfd,
-                                   STUB_MOVE32_MICROMIPS (output_bfd),
-                                   stub + idx);
+                                   STUB_MOVE32_MICROMIPS, stub + idx);
              idx += 4;
            }
          else
@@ -10523,7 +10948,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
          idx = 0;
          bfd_put_32 (output_bfd, STUB_LW (output_bfd), stub + idx);
          idx += 4;
-         bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + idx);
+         bfd_put_32 (output_bfd, STUB_MOVE, stub + idx);
          idx += 4;
          if (stub_size == stub_big_size)
            {
@@ -10580,7 +11005,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
   BFD_ASSERT (h->dynindx != -1
              || h->forced_local);
 
-  sgot = htab->sgot;
+  sgot = htab->root.sgot;
   g = htab->got_info;
   BFD_ASSERT (g != NULL);
 
@@ -10616,8 +11041,8 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
                                                           &e)))
            {
              offset = p->gotidx;
-             BFD_ASSERT (offset > 0 && offset < htab->sgot->size);
-             if (info->shared
+             BFD_ASSERT (offset > 0 && offset < htab->root.sgot->size);
+             if (bfd_link_pic (info)
                  || (elf_hash_table (info)->dynamic_sections_created
                      && p->d.h != NULL
                      && p->d.h->root.def_dynamic
@@ -10763,18 +11188,18 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
       gotplt_index = h->plt.plist->gotplt_index;
 
       BFD_ASSERT (h->dynindx != -1);
-      BFD_ASSERT (htab->splt != NULL);
+      BFD_ASSERT (htab->root.splt != NULL);
       BFD_ASSERT (gotplt_index != MINUS_ONE);
-      BFD_ASSERT (plt_offset <= htab->splt->size);
+      BFD_ASSERT (plt_offset <= htab->root.splt->size);
 
       /* Calculate the address of the .plt entry.  */
-      plt_address = (htab->splt->output_section->vma
-                    + htab->splt->output_offset
+      plt_address = (htab->root.splt->output_section->vma
+                    + htab->root.splt->output_offset
                     + plt_offset);
 
       /* Calculate the address of the .got.plt entry.  */
-      got_address = (htab->sgotplt->output_section->vma
-                    + htab->sgotplt->output_offset
+      got_address = (htab->root.sgotplt->output_section->vma
+                    + htab->root.sgotplt->output_offset
                     + gotplt_index * MIPS_ELF_GOT_SIZE (output_bfd));
 
       /* Calculate the offset of the .got.plt entry from
@@ -10787,13 +11212,13 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
 
       /* Fill in the initial value of the .got.plt entry.  */
       bfd_put_32 (output_bfd, plt_address,
-                 (htab->sgotplt->contents
+                 (htab->root.sgotplt->contents
                   + gotplt_index * MIPS_ELF_GOT_SIZE (output_bfd)));
 
       /* Find out where the .plt entry should go.  */
-      loc = htab->splt->contents + plt_offset;
+      loc = htab->root.splt->contents + plt_offset;
 
-      if (info->shared)
+      if (bfd_link_pic (info))
        {
          plt_entry = mips_vxworks_shared_plt_entry;
          bfd_put_32 (output_bfd, plt_entry[0] | branch_offset, loc);
@@ -10840,7 +11265,7 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
        }
 
       /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry.  */
-      loc = (htab->srelplt->contents
+      loc = (htab->root.srelplt->contents
             + gotplt_index * sizeof (Elf32_External_Rela));
       rel.r_offset = got_address;
       rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_JUMP_SLOT);
@@ -10853,7 +11278,7 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
 
   BFD_ASSERT (h->dynindx != -1 || h->forced_local);
 
-  sgot = htab->sgot;
+  sgot = htab->root.sgot;
   g = htab->got_info;
   BFD_ASSERT (g != NULL);
 
@@ -10931,8 +11356,8 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
     plt_entry = micromips_o32_exec_plt0_entry;
 
   /* Calculate the value of .got.plt.  */
-  gotplt_value = (htab->sgotplt->output_section->vma
-                 + htab->sgotplt->output_offset);
+  gotplt_value = (htab->root.sgotplt->output_section->vma
+                 + htab->root.sgotplt->output_offset);
   gotplt_value_high = ((gotplt_value + 0x8000) >> 16) & 0xffff;
   gotplt_value_low = gotplt_value & 0xffff;
 
@@ -10942,7 +11367,7 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
              || ~(gotplt_value | 0x7fffffff) == 0);
 
   /* Install the PLT header.  */
-  loc = htab->splt->contents;
+  loc = htab->root.splt->contents;
   if (plt_entry == micromips_o32_exec_plt0_entry)
     {
       bfd_vma gotpc_offset;
@@ -10951,18 +11376,19 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
 
       BFD_ASSERT (gotplt_value % 4 == 0);
 
-      loc_address = (htab->splt->output_section->vma
-                    + htab->splt->output_offset);
+      loc_address = (htab->root.splt->output_section->vma
+                    + htab->root.splt->output_offset);
       gotpc_offset = gotplt_value - ((loc_address | 3) ^ 3);
 
       /* ADDIUPC has a span of +/-16MB, check we're in range.  */
       if (gotpc_offset + 0x1000000 >= 0x2000000)
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: `%A' offset of %ld from `%A' beyond the range of ADDIUPC"),
             output_bfd,
-            htab->sgotplt->output_section,
-            htab->splt->output_section,
+            htab->root.sgotplt->output_section,
+            htab->root.splt->output_section,
             (long) gotpc_offset);
          bfd_set_error (bfd_error_no_error);
          return FALSE;
@@ -11027,10 +11453,11 @@ mips_vxworks_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
   got_value_low = got_value & 0xffff;
 
   /* Calculate the address of the PLT header.  */
-  plt_address = htab->splt->output_section->vma + htab->splt->output_offset;
+  plt_address = (htab->root.splt->output_section->vma
+                + htab->root.splt->output_offset);
 
   /* Install the PLT header.  */
-  loc = htab->splt->contents;
+  loc = htab->root.splt->contents;
   bfd_put_32 (output_bfd, plt_entry[0] | got_value_high, loc);
   bfd_put_32 (output_bfd, plt_entry[1] | got_value_low, loc + 4);
   bfd_put_32 (output_bfd, plt_entry[2], loc + 8);
@@ -11091,7 +11518,7 @@ mips_vxworks_finish_shared_plt (bfd *output_bfd, struct bfd_link_info *info)
   /* We just need to copy the entry byte-by-byte.  */
   for (i = 0; i < ARRAY_SIZE (mips_vxworks_shared_plt0_entry); i++)
     bfd_put_32 (output_bfd, mips_vxworks_shared_plt0_entry[i],
-               htab->splt->contents + i * 4);
+               htab->root.splt->contents + i * 4);
 }
 
 /* Finish up the dynamic sections.  */
@@ -11113,7 +11540,7 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
 
   sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
-  sgot = htab->sgot;
+  sgot = htab->root.sgot;
   gg = htab->got_info;
 
   if (elf_hash_table (info)->dynamic_sections_created)
@@ -11161,12 +11588,12 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_PLTGOT:
-             s = htab->sgot;
+             s = htab->root.sgot;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
            case DT_MIPS_PLTGOT:
-             s = htab->sgotplt;
+             s = htab->root.sgotplt;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
 
@@ -11221,15 +11648,18 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
                }
              /* In case if we don't have global got symbols we default
                 to setting DT_MIPS_GOTSYM to the same value as
-                DT_MIPS_SYMTABNO, so we just fall through.  */
+                DT_MIPS_SYMTABNO.  */
+             /* Fall through.  */
 
            case DT_MIPS_SYMTABNO:
              name = ".dynsym";
              elemsize = MIPS_ELF_SYM_SIZE (output_bfd);
-             s = bfd_get_section_by_name (output_bfd, name);
-             BFD_ASSERT (s != NULL);
+             s = bfd_get_linker_section (dynobj, name);
 
-             dyn.d_un.d_val = s->size / elemsize;
+             if (s != NULL)
+               dyn.d_un.d_val = s->size / elemsize;
+             else
+               dyn.d_un.d_val = 0;
              break;
 
            case DT_MIPS_HIPAGENO:
@@ -11247,11 +11677,37 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
                    break;
                  }
                s = h->root.u.def.section;
+
+               /* The MIPS_RLD_MAP tag stores the absolute address of the
+                  debug pointer.  */
                dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset
                                  + h->root.u.def.value);
              }
              break;
 
+           case DT_MIPS_RLD_MAP_REL:
+             {
+               struct elf_link_hash_entry *h;
+               bfd_vma dt_addr, rld_addr;
+               h = mips_elf_hash_table (info)->rld_symbol;
+               if (!h)
+                 {
+                   dyn_to_skip = MIPS_ELF_DYN_SIZE (dynobj);
+                   swap_out_p = FALSE;
+                   break;
+                 }
+               s = h->root.u.def.section;
+
+               /* The MIPS_RLD_MAP_REL tag stores the offset to the debug
+                  pointer, relative to the address of the tag.  */
+               dt_addr = (sdyn->output_section->vma + sdyn->output_offset
+                          + (b - sdyn->contents));
+               rld_addr = (s->output_section->vma + s->output_offset
+                           + h->root.u.def.value);
+               dyn.d_un.d_ptr = rld_addr - dt_addr;
+             }
+             break;
+
            case DT_MIPS_OPTIONS:
              s = (bfd_get_section_by_name
                   (output_bfd, MIPS_ELF_OPTIONS_SECTION_NAME (output_bfd)));
@@ -11261,8 +11717,8 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
            case DT_RELASZ:
              BFD_ASSERT (htab->is_vxworks);
              /* The count does not include the JUMP_SLOT relocations.  */
-             if (htab->srelplt)
-               dyn.d_un.d_val -= htab->srelplt->size;
+             if (htab->root.srelplt)
+               dyn.d_un.d_val -= htab->root.srelplt->size;
              break;
 
            case DT_PLTREL:
@@ -11275,13 +11731,13 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
 
            case DT_PLTRELSZ:
              BFD_ASSERT (htab->use_plts_and_copy_relocs);
-             dyn.d_un.d_val = htab->srelplt->size;
+             dyn.d_un.d_val = htab->root.srelplt->size;
              break;
 
            case DT_JMPREL:
              BFD_ASSERT (htab->use_plts_and_copy_relocs);
-             dyn.d_un.d_ptr = (htab->srelplt->output_section->vma
-                               + htab->srelplt->output_offset);
+             dyn.d_un.d_ptr = (htab->root.srelplt->output_section->vma
+                               + htab->root.srelplt->output_offset);
              break;
 
            case DT_TEXTREL:
@@ -11380,13 +11836,17 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
                             sgot->contents
                             + got_index++ * MIPS_ELF_GOT_SIZE (output_bfd));
 
-         if (! info->shared)
+         if (! bfd_link_pic (info))
            continue;
 
-         while (got_index < g->assigned_gotno)
+         for (; got_index < g->local_gotno; got_index++)
            {
+             if (got_index >= g->assigned_low_gotno
+                 && got_index <= g->assigned_high_gotno)
+               continue;
+
              rel[0].r_offset = rel[1].r_offset = rel[2].r_offset
-               = got_index++ * MIPS_ELF_GOT_SIZE (output_bfd);
+               = got_index * MIPS_ELF_GOT_SIZE (output_bfd);
              if (!(mips_elf_create_dynamic_relocation
                    (output_bfd, info, rel, NULL,
                     bfd_abs_section_ptr,
@@ -11508,18 +11968,18 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
       }
   }
 
-  if (htab->splt && htab->splt->size > 0)
+  if (htab->root.splt && htab->root.splt->size > 0)
     {
       if (htab->is_vxworks)
        {
-         if (info->shared)
+         if (bfd_link_pic (info))
            mips_vxworks_finish_shared_plt (output_bfd, info);
          else
            mips_vxworks_finish_exec_plt (output_bfd, info);
        }
       else
        {
-         BFD_ASSERT (!info->shared);
+         BFD_ASSERT (!bfd_link_pic (info));
          if (!mips_finish_exec_plt (output_bfd, info))
            return FALSE;
        }
@@ -11620,7 +12080,7 @@ mips_set_isa_flags (bfd *abfd)
       break;
 
     case bfd_mach_mips_loongson_3a:
-      val = E_MIPS_ARCH_64 | E_MIPS_MACH_LS3A;
+      val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_LS3A;
       break;
 
     case bfd_mach_mips_octeon:
@@ -11628,6 +12088,10 @@ mips_set_isa_flags (bfd *abfd)
       val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON;
       break;
 
+    case bfd_mach_mips_octeon3:
+      val = E_MIPS_ARCH_64R2 | E_MIPS_MACH_OCTEON3;
+      break;
+
     case bfd_mach_mips_xlr:
       val = E_MIPS_ARCH_64 | E_MIPS_MACH_XLR;
       break;
@@ -11645,16 +12109,40 @@ mips_set_isa_flags (bfd *abfd)
       break;
 
     case bfd_mach_mipsisa32r2:
+    case bfd_mach_mipsisa32r3:
+    case bfd_mach_mipsisa32r5:
       val = E_MIPS_ARCH_32R2;
       break;
 
     case bfd_mach_mipsisa64r2:
+    case bfd_mach_mipsisa64r3:
+    case bfd_mach_mipsisa64r5:
       val = E_MIPS_ARCH_64R2;
       break;
-    }
-  elf_elfheader (abfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
-  elf_elfheader (abfd)->e_flags |= val;
 
+    case bfd_mach_mipsisa32r6:
+      val = E_MIPS_ARCH_32R6;
+      break;
+
+    case bfd_mach_mipsisa64r6:
+      val = E_MIPS_ARCH_64R6;
+      break;
+    }
+  elf_elfheader (abfd)->e_flags &= ~(EF_MIPS_ARCH | EF_MIPS_MACH);
+  elf_elfheader (abfd)->e_flags |= val;
+
+}
+
+
+/* Whether to sort relocs output by ld -r or ld --emit-relocs, by r_offset.
+   Don't do so for code sections.  We want to keep ordering of HI16/LO16
+   as is.  On the other hand, elf-eh-frame.c processing requires .eh_frame
+   relocs to be sorted.  */
+
+bfd_boolean
+_bfd_mips_elf_sort_relocs_p (asection *sec)
+{
+  return (sec->flags & SEC_CODE) == 0;
 }
 
 
@@ -11759,6 +12247,10 @@ _bfd_mips_elf_additional_program_headers (bfd *abfd,
   if (s && (s->flags & SEC_LOAD))
     ++ret;
 
+  /* See if we need a PT_MIPS_ABIFLAGS segment.  */
+  if (bfd_get_section_by_name (abfd, ".MIPS.abiflags"))
+    ++ret;
+
   /* See if we need a PT_MIPS_OPTIONS segment.  */
   if (IRIX_COMPAT (abfd) == ict_irix6
       && bfd_get_section_by_name (abfd,
@@ -11821,6 +12313,37 @@ _bfd_mips_elf_modify_segment_map (bfd *abfd,
        }
     }
 
+  /* If there is a .MIPS.abiflags section, we need a PT_MIPS_ABIFLAGS
+     segment.  */
+  s = bfd_get_section_by_name (abfd, ".MIPS.abiflags");
+  if (s != NULL && (s->flags & SEC_LOAD) != 0)
+    {
+      for (m = elf_seg_map (abfd); m != NULL; m = m->next)
+       if (m->p_type == PT_MIPS_ABIFLAGS)
+         break;
+      if (m == NULL)
+       {
+         amt = sizeof *m;
+         m = bfd_zalloc (abfd, amt);
+         if (m == NULL)
+           return FALSE;
+
+         m->p_type = PT_MIPS_ABIFLAGS;
+         m->count = 1;
+         m->sections[0] = s;
+
+         /* We want to put it after the PHDR and INTERP segments.  */
+         pm = &elf_seg_map (abfd);
+         while (*pm != NULL
+                && ((*pm)->p_type == PT_PHDR
+                    || (*pm)->p_type == PT_INTERP))
+           pm = &(*pm)->next;
+
+         m->next = *pm;
+         *pm = m;
+       }
+    }
+
   /* For IRIX 6, we don't have .mdebug sections, nor does anything but
      .dynamic end up in PT_DYNAMIC.  However, we do have to insert a
      PT_MIPS_OPTIONS segment immediately following the program header
@@ -11915,18 +12438,6 @@ _bfd_mips_elf_modify_segment_map (bfd *abfd,
        if ((*pm)->p_type == PT_DYNAMIC)
          break;
       m = *pm;
-      if (m != NULL && IRIX_COMPAT (abfd) == ict_none)
-       {
-         /* For a normal mips executable the permissions for the PT_DYNAMIC
-            segment are read, write and execute. We do that here since
-            the code in elf.c sets only the read permission. This matters
-            sometimes for the dynamic linker.  */
-         if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
-           {
-             m->p_flags = PF_R | PF_W | PF_X;
-             m->p_flags_valid = 1;
-           }
-       }
       /* GNU/Linux binaries do not need the extended PT_DYNAMIC section.
         glibc's dynamic linker has traditionally derived the number of
         tags from the p_filesz field, and sometimes allocates stack
@@ -12073,7 +12584,7 @@ _bfd_mips_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
   unsigned long r_symndx;
   struct elf_link_hash_entry *h;
 
-  if (info->relocatable)
+  if (bfd_link_relocatable (info))
     return TRUE;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -12116,6 +12627,36 @@ _bfd_mips_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
 
   return TRUE;
 }
+
+/* Prevent .MIPS.abiflags from being discarded with --gc-sections.  */
+
+bfd_boolean
+_bfd_mips_elf_gc_mark_extra_sections (struct bfd_link_info *info,
+                                     elf_gc_mark_hook_fn gc_mark_hook)
+{
+  bfd *sub;
+
+  _bfd_elf_gc_mark_extra_sections (info, gc_mark_hook);
+
+  for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
+    {
+      asection *o;
+
+      if (! is_mips_elf (sub))
+       continue;
+
+      for (o = sub->sections; o != NULL; o = o->next)
+       if (!o->gc_mark
+           && MIPS_ELF_ABIFLAGS_SECTION_NAME_P
+                (bfd_get_section_name (sub, o)))
+         {
+           if (!_bfd_elf_gc_mark (info, o, gc_mark_hook))
+             return FALSE;
+         }
+    }
+
+  return TRUE;
+}
 \f
 /* Copy data from a MIPS ELF indirect symbol to its direct symbol,
    hiding the old indirect symbol.  Process additional relocation
@@ -12223,6 +12764,8 @@ _bfd_mips_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie,
   if (skip != 0)
     {
       mips_elf_section_data (o)->u.tdata = tdata;
+      if (o->rawsize == 0)
+       o->rawsize = o->size;
       o->size -= skip * PDR_SIZE;
       ret = TRUE;
     }
@@ -12293,24 +12836,26 @@ struct mips_elf_find_line
 };
 
 bfd_boolean
-_bfd_mips_elf_find_nearest_line (bfd *abfd, asection *section,
-                                asymbol **symbols, bfd_vma offset,
+_bfd_mips_elf_find_nearest_line (bfd *abfd, asymbol **symbols,
+                                asection *section, bfd_vma offset,
                                 const char **filename_ptr,
                                 const char **functionname_ptr,
-                                unsigned int *line_ptr)
+                                unsigned int *line_ptr,
+                                unsigned int *discriminator_ptr)
 {
   asection *msec;
 
-  if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
+  if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr))
+                                    line_ptr, discriminator_ptr,
+                                    dwarf_debug_sections,
+                                    ABI_64_P (abfd) ? 8 : 0,
+                                    &elf_tdata (abfd)->dwarf2_find_line_info))
     return TRUE;
 
-  if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
-                                     section, symbols, offset,
+  if (_bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr, NULL, ABI_64_P (abfd) ? 8 : 0,
-                                    &elf_tdata (abfd)->dwarf2_find_line_info))
+                                    line_ptr))
     return TRUE;
 
   msec = bfd_get_section_by_name (abfd, ".mdebug");
@@ -12389,9 +12934,9 @@ _bfd_mips_elf_find_nearest_line (bfd *abfd, asection *section,
 
   /* Fall back on the generic ELF find_nearest_line routine.  */
 
-  return _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
+  return _bfd_elf_find_nearest_line (abfd, symbols, section, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr);
+                                    line_ptr, discriminator_ptr);
 }
 
 bfd_boolean
@@ -12570,25 +13115,22 @@ _bfd_elf_mips_get_relocated_section_contents
              switch (r)
                {
                case bfd_reloc_undefined:
-                 if (!((*link_info->callbacks->undefined_symbol)
-                       (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
-                        input_bfd, input_section, (*parent)->address, TRUE)))
-                   goto error_return;
+                 (*link_info->callbacks->undefined_symbol)
+                   (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
+                    input_bfd, input_section, (*parent)->address, TRUE);
                  break;
                case bfd_reloc_dangerous:
                  BFD_ASSERT (error_message != NULL);
-                 if (!((*link_info->callbacks->reloc_dangerous)
-                       (link_info, error_message, input_bfd, input_section,
-                        (*parent)->address)))
-                   goto error_return;
+                 (*link_info->callbacks->reloc_dangerous)
+                   (link_info, error_message,
+                    input_bfd, input_section, (*parent)->address);
                  break;
                case bfd_reloc_overflow:
-                 if (!((*link_info->callbacks->reloc_overflow)
-                       (link_info, NULL,
-                        bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
-                        (*parent)->howto->name, (*parent)->addend,
-                        input_bfd, input_section, (*parent)->address)))
-                   goto error_return;
+                 (*link_info->callbacks->reloc_overflow)
+                   (link_info, NULL,
+                    bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
+                    (*parent)->howto->name, (*parent)->addend,
+                    input_bfd, input_section, (*parent)->address);
                  break;
                case bfd_reloc_outofrange:
                default:
@@ -12764,9 +13306,8 @@ static const struct opcode_descriptor bz_insns_16[] = {
 
 /* Switch between a 5-bit register index and its 3-bit shorthand.  */
 
-#define BZ16_REG(opcode) ((((((opcode) >> 7) & 7) + 0x1e) & 0x17) + 2)
-#define BZ16_REG_FIELD(r) \
-  (((2 <= (r) && (r) <= 7) ? (r) : ((r) - 16)) << 7)
+#define BZ16_REG(opcode) ((((((opcode) >> 7) & 7) + 0x1e) & 0xf) + 2)
+#define BZ16_REG_FIELD(r) (((r) & 7) << 7)
 
 
 /* 32-bit instructions with a delay slot.  */
@@ -12865,8 +13406,8 @@ static const struct opcode_descriptor addiupc_insn =
 #define MOVE16_RS_FIELD(r) (((r) & 0x1f)     )
 
 static const struct opcode_descriptor move_insns_32[] = {
-  { /* "move", "d,s",          */ 0x00000150, 0xffe007ff }, /* addu d,s,$0 */
   { /* "move", "d,s",          */ 0x00000290, 0xffe007ff }, /* or   d,s,$0 */
+  { /* "move", "d,s",          */ 0x00000150, 0xffe007ff }, /* addu d,s,$0 */
   { 0, 0 }  /* End marker for find_match().  */
 };
 
@@ -13053,7 +13594,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
      this section does not have relocs, or if this is not a
      code section.  */
 
-  if (link_info->relocatable
+  if (bfd_link_relocatable (link_info)
       || (sec->flags & SEC_RELOC) == 0
       || sec->reloc_count == 0
       || (sec->flags & SEC_CODE) == 0)
@@ -13566,6 +14107,277 @@ _bfd_mips_elf_insn32 (struct bfd_link_info *info, bfd_boolean on)
   mips_elf_hash_table (info)->insn32 = on;
 }
 \f
+/* Structure for saying that BFD machine EXTENSION extends BASE.  */
+
+struct mips_mach_extension
+{
+  unsigned long extension, base;
+};
+
+
+/* An array describing how BFD machines relate to one another.  The entries
+   are ordered topologically with MIPS I extensions listed last.  */
+
+static const struct mips_mach_extension mips_mach_extensions[] =
+{
+  /* MIPS64r2 extensions.  */
+  { bfd_mach_mips_octeon3, bfd_mach_mips_octeon2 },
+  { bfd_mach_mips_octeon2, bfd_mach_mips_octeonp },
+  { bfd_mach_mips_octeonp, bfd_mach_mips_octeon },
+  { bfd_mach_mips_octeon, bfd_mach_mipsisa64r2 },
+  { bfd_mach_mips_loongson_3a, bfd_mach_mipsisa64r2 },
+
+  /* MIPS64 extensions.  */
+  { bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
+  { bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
+  { bfd_mach_mips_xlr, bfd_mach_mipsisa64 },
+
+  /* MIPS V extensions.  */
+  { bfd_mach_mipsisa64, bfd_mach_mips5 },
+
+  /* R10000 extensions.  */
+  { bfd_mach_mips12000, bfd_mach_mips10000 },
+  { bfd_mach_mips14000, bfd_mach_mips10000 },
+  { bfd_mach_mips16000, bfd_mach_mips10000 },
+
+  /* R5000 extensions.  Note: the vr5500 ISA is an extension of the core
+     vr5400 ISA, but doesn't include the multimedia stuff.  It seems
+     better to allow vr5400 and vr5500 code to be merged anyway, since
+     many libraries will just use the core ISA.  Perhaps we could add
+     some sort of ASE flag if this ever proves a problem.  */
+  { bfd_mach_mips5500, bfd_mach_mips5400 },
+  { bfd_mach_mips5400, bfd_mach_mips5000 },
+
+  /* MIPS IV extensions.  */
+  { bfd_mach_mips5, bfd_mach_mips8000 },
+  { 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 },
+  { bfd_mach_mips4111, bfd_mach_mips4100 },
+
+  /* MIPS III extensions.  */
+  { bfd_mach_mips_loongson_2e, bfd_mach_mips4000 },
+  { bfd_mach_mips_loongson_2f, bfd_mach_mips4000 },
+  { bfd_mach_mips8000, bfd_mach_mips4000 },
+  { bfd_mach_mips4650, bfd_mach_mips4000 },
+  { bfd_mach_mips4600, bfd_mach_mips4000 },
+  { bfd_mach_mips4400, bfd_mach_mips4000 },
+  { bfd_mach_mips4300, bfd_mach_mips4000 },
+  { bfd_mach_mips4100, bfd_mach_mips4000 },
+  { bfd_mach_mips4010, bfd_mach_mips4000 },
+  { bfd_mach_mips5900, bfd_mach_mips4000 },
+
+  /* MIPS32 extensions.  */
+  { bfd_mach_mipsisa32r2, bfd_mach_mipsisa32 },
+
+  /* MIPS II extensions.  */
+  { bfd_mach_mips4000, bfd_mach_mips6000 },
+  { bfd_mach_mipsisa32, bfd_mach_mips6000 },
+
+  /* MIPS I extensions.  */
+  { bfd_mach_mips6000, bfd_mach_mips3000 },
+  { bfd_mach_mips3900, bfd_mach_mips3000 }
+};
+
+/* Return true if bfd machine EXTENSION is an extension of machine BASE.  */
+
+static bfd_boolean
+mips_mach_extends_p (unsigned long base, unsigned long extension)
+{
+  size_t i;
+
+  if (extension == base)
+    return TRUE;
+
+  if (base == bfd_mach_mipsisa32
+      && mips_mach_extends_p (bfd_mach_mipsisa64, extension))
+    return TRUE;
+
+  if (base == bfd_mach_mipsisa32r2
+      && mips_mach_extends_p (bfd_mach_mipsisa64r2, extension))
+    return TRUE;
+
+  for (i = 0; i < ARRAY_SIZE (mips_mach_extensions); i++)
+    if (extension == mips_mach_extensions[i].extension)
+      {
+       extension = mips_mach_extensions[i].base;
+       if (extension == base)
+         return TRUE;
+      }
+
+  return FALSE;
+}
+
+/* Return the BFD mach for each .MIPS.abiflags ISA Extension.  */
+
+static unsigned long
+bfd_mips_isa_ext_mach (unsigned int isa_ext)
+{
+  switch (isa_ext)
+    {
+    case AFL_EXT_3900:        return bfd_mach_mips3900;
+    case AFL_EXT_4010:        return bfd_mach_mips4010;
+    case AFL_EXT_4100:        return bfd_mach_mips4100;
+    case AFL_EXT_4111:        return bfd_mach_mips4111;
+    case AFL_EXT_4120:        return bfd_mach_mips4120;
+    case AFL_EXT_4650:        return bfd_mach_mips4650;
+    case AFL_EXT_5400:        return bfd_mach_mips5400;
+    case AFL_EXT_5500:        return bfd_mach_mips5500;
+    case AFL_EXT_5900:        return bfd_mach_mips5900;
+    case AFL_EXT_10000:       return bfd_mach_mips10000;
+    case AFL_EXT_LOONGSON_2E: return bfd_mach_mips_loongson_2e;
+    case AFL_EXT_LOONGSON_2F: return bfd_mach_mips_loongson_2f;
+    case AFL_EXT_LOONGSON_3A: return bfd_mach_mips_loongson_3a;
+    case AFL_EXT_SB1:         return bfd_mach_mips_sb1;
+    case AFL_EXT_OCTEON:      return bfd_mach_mips_octeon;
+    case AFL_EXT_OCTEONP:     return bfd_mach_mips_octeonp;
+    case AFL_EXT_OCTEON2:     return bfd_mach_mips_octeon2;
+    case AFL_EXT_XLR:         return bfd_mach_mips_xlr;
+    default:                  return bfd_mach_mips3000;
+    }
+}
+
+/* Return the .MIPS.abiflags value representing each ISA Extension.  */
+
+unsigned int
+bfd_mips_isa_ext (bfd *abfd)
+{
+  switch (bfd_get_mach (abfd))
+    {
+    case bfd_mach_mips3900:         return AFL_EXT_3900;
+    case bfd_mach_mips4010:         return AFL_EXT_4010;
+    case bfd_mach_mips4100:         return AFL_EXT_4100;
+    case bfd_mach_mips4111:         return AFL_EXT_4111;
+    case bfd_mach_mips4120:         return AFL_EXT_4120;
+    case bfd_mach_mips4650:         return AFL_EXT_4650;
+    case bfd_mach_mips5400:         return AFL_EXT_5400;
+    case bfd_mach_mips5500:         return AFL_EXT_5500;
+    case bfd_mach_mips5900:         return AFL_EXT_5900;
+    case bfd_mach_mips10000:        return AFL_EXT_10000;
+    case bfd_mach_mips_loongson_2e: return AFL_EXT_LOONGSON_2E;
+    case bfd_mach_mips_loongson_2f: return AFL_EXT_LOONGSON_2F;
+    case bfd_mach_mips_loongson_3a: return AFL_EXT_LOONGSON_3A;
+    case bfd_mach_mips_sb1:         return AFL_EXT_SB1;
+    case bfd_mach_mips_octeon:      return AFL_EXT_OCTEON;
+    case bfd_mach_mips_octeonp:     return AFL_EXT_OCTEONP;
+    case bfd_mach_mips_octeon3:     return AFL_EXT_OCTEON3;
+    case bfd_mach_mips_octeon2:     return AFL_EXT_OCTEON2;
+    case bfd_mach_mips_xlr:         return AFL_EXT_XLR;
+    default:                        return 0;
+    }
+}
+
+/* Encode ISA level and revision as a single value.  */
+#define LEVEL_REV(LEV,REV) ((LEV) << 3 | (REV))
+
+/* Decode a single value into level and revision.  */
+#define ISA_LEVEL(LEVREV)  ((LEVREV) >> 3)
+#define ISA_REV(LEVREV)    ((LEVREV) & 0x7)
+
+/* Update the isa_level, isa_rev, isa_ext fields of abiflags.  */
+
+static void
+update_mips_abiflags_isa (bfd *abfd, Elf_Internal_ABIFlags_v0 *abiflags)
+{
+  int new_isa = 0;
+  switch (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH)
+    {
+    case E_MIPS_ARCH_1:    new_isa = LEVEL_REV (1, 0); break;
+    case E_MIPS_ARCH_2:    new_isa = LEVEL_REV (2, 0); break;
+    case E_MIPS_ARCH_3:    new_isa = LEVEL_REV (3, 0); break;
+    case E_MIPS_ARCH_4:    new_isa = LEVEL_REV (4, 0); break;
+    case E_MIPS_ARCH_5:    new_isa = LEVEL_REV (5, 0); break;
+    case E_MIPS_ARCH_32:   new_isa = LEVEL_REV (32, 1); break;
+    case E_MIPS_ARCH_32R2: new_isa = LEVEL_REV (32, 2); break;
+    case E_MIPS_ARCH_32R6: new_isa = LEVEL_REV (32, 6); break;
+    case E_MIPS_ARCH_64:   new_isa = LEVEL_REV (64, 1); break;
+    case E_MIPS_ARCH_64R2: new_isa = LEVEL_REV (64, 2); break;
+    case E_MIPS_ARCH_64R6: new_isa = LEVEL_REV (64, 6); break;
+    default:
+      _bfd_error_handler
+       /* xgettext:c-format */
+       (_("%B: Unknown architecture %s"),
+        abfd, bfd_printable_name (abfd));
+    }
+
+  if (new_isa > LEVEL_REV (abiflags->isa_level, abiflags->isa_rev))
+    {
+      abiflags->isa_level = ISA_LEVEL (new_isa);
+      abiflags->isa_rev = ISA_REV (new_isa);
+    }
+
+  /* Update the isa_ext if ABFD describes a further extension.  */
+  if (mips_mach_extends_p (bfd_mips_isa_ext_mach (abiflags->isa_ext),
+                          bfd_get_mach (abfd)))
+    abiflags->isa_ext = bfd_mips_isa_ext (abfd);
+}
+
+/* Return true if the given ELF header flags describe a 32-bit binary.  */
+
+static bfd_boolean
+mips_32bit_flags_p (flagword flags)
+{
+  return ((flags & EF_MIPS_32BITMODE) != 0
+         || (flags & EF_MIPS_ABI) == E_MIPS_ABI_O32
+         || (flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI32
+         || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1
+         || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2
+         || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32
+         || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2
+         || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6);
+}
+
+/* Infer the content of the ABI flags based on the elf header.  */
+
+static void
+infer_mips_abiflags (bfd *abfd, Elf_Internal_ABIFlags_v0* abiflags)
+{
+  obj_attribute *in_attr;
+
+  memset (abiflags, 0, sizeof (Elf_Internal_ABIFlags_v0));
+  update_mips_abiflags_isa (abfd, abiflags);
+
+  if (mips_32bit_flags_p (elf_elfheader (abfd)->e_flags))
+    abiflags->gpr_size = AFL_REG_32;
+  else
+    abiflags->gpr_size = AFL_REG_64;
+
+  abiflags->cpr1_size = AFL_REG_NONE;
+
+  in_attr = elf_known_obj_attributes (abfd)[OBJ_ATTR_GNU];
+  abiflags->fp_abi = in_attr[Tag_GNU_MIPS_ABI_FP].i;
+
+  if (abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_SINGLE
+      || abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_XX
+      || (abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_DOUBLE
+         && abiflags->gpr_size == AFL_REG_32))
+    abiflags->cpr1_size = AFL_REG_32;
+  else if (abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_DOUBLE
+          || abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_64
+          || abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_64A)
+    abiflags->cpr1_size = AFL_REG_64;
+
+  abiflags->cpr2_size = AFL_REG_NONE;
+
+  if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MDMX)
+    abiflags->ases |= AFL_ASE_MDMX;
+  if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_M16)
+    abiflags->ases |= AFL_ASE_MIPS16;
+  if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS)
+    abiflags->ases |= AFL_ASE_MICROMIPS;
+
+  if (abiflags->fp_abi != Val_GNU_MIPS_ABI_FP_ANY
+      && abiflags->fp_abi != Val_GNU_MIPS_ABI_FP_SOFT
+      && abiflags->fp_abi != Val_GNU_MIPS_ABI_FP_64A
+      && abiflags->isa_level >= 32
+      && abiflags->isa_ext != AFL_EXT_LOONGSON_3A)
+    abiflags->flags1 |= AFL_FLAGS1_ODDSPREG;
+}
+
 /* We need to use a special link routine to handle the .reginfo and
    the .mdebug sections.  We need to merge all instances of these
    sections together, not write them all out sequentially.  */
@@ -13576,7 +14388,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   asection *o;
   struct bfd_link_order *p;
   asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec;
-  asection *rtproc_sec;
+  asection *rtproc_sec, *abiflags_sec;
   Elf32_RegInfo reginfo;
   struct ecoff_debug_info debug;
   struct mips_htab_traverse_info hti;
@@ -13635,7 +14447,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        elf_gp (abfd) = (h->u.def.section->output_section->vma
                         + h->u.def.section->output_offset
                         + h->u.def.value);
-      else if (info->relocatable)
+      else if (bfd_link_relocatable (info))
        {
          bfd_vma lo = MINUS_ONE;
 
@@ -13658,12 +14470,46 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   /* Go through the sections and collect the .reginfo and .mdebug
      information.  */
+  abiflags_sec = NULL;
   reginfo_sec = NULL;
   mdebug_sec = NULL;
   gptab_data_sec = NULL;
   gptab_bss_sec = NULL;
   for (o = abfd->sections; o != NULL; o = o->next)
     {
+      if (strcmp (o->name, ".MIPS.abiflags") == 0)
+       {
+         /* We have found the .MIPS.abiflags section in the output file.
+            Look through all the link_orders comprising it and remove them.
+            The data is merged in _bfd_mips_elf_merge_private_bfd_data.  */
+         for (p = o->map_head.link_order; p != NULL; p = p->next)
+           {
+             asection *input_section;
+
+             if (p->type != bfd_indirect_link_order)
+               {
+                 if (p->type == bfd_data_link_order)
+                   continue;
+                 abort ();
+               }
+
+             input_section = p->u.indirect.section;
+
+             /* Hack: reset the SEC_HAS_CONTENTS flag so that
+                elf_link_input_bfd ignores this section.  */
+             input_section->flags &= ~SEC_HAS_CONTENTS;
+           }
+
+         /* Size has been set in _bfd_mips_elf_always_size_sections.  */
+         BFD_ASSERT(o->size == sizeof (Elf_External_ABIFlags_v0));
+
+         /* Skip this section later on (I don't think this currently
+            matters, but someday it might).  */
+         o->map_head.link_order = NULL;
+
+         abiflags_sec = o;
+       }
+
       if (strcmp (o->name, ".reginfo") == 0)
        {
          memset (&reginfo, 0, sizeof reginfo);
@@ -13887,7 +14733,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              input_section->flags &= ~SEC_HAS_CONTENTS;
            }
 
-         if (SGI_COMPAT (abfd) && info->shared)
+         if (SGI_COMPAT (abfd) && bfd_link_pic (info))
            {
              /* Create .rtproc section.  */
              rtproc_sec = bfd_get_linker_section (abfd, ".rtproc");
@@ -13943,7 +14789,7 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
             information describing how the small data area would
             change depending upon the -G switch.  These sections
             not used in executables files.  */
-         if (! info->relocatable)
+         if (! bfd_link_relocatable (info))
            {
              for (p = o->map_head.link_order; p != NULL; p = p->next)
                {
@@ -13982,7 +14828,8 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            gptab_bss_sec = o;
          else
            {
-             (*_bfd_error_handler)
+             _bfd_error_handler
+               /* xgettext:c-format */
                (_("%s: illegal section name `%s'"),
                 bfd_get_filename (abfd), o->name);
              bfd_set_error (bfd_error_nonrepresentable_section);
@@ -14148,6 +14995,24 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   /* Now write out the computed sections.  */
 
+  if (abiflags_sec != NULL)
+    {
+      Elf_External_ABIFlags_v0 ext;
+      Elf_Internal_ABIFlags_v0 *abiflags;
+
+      abiflags = &mips_elf_tdata (abfd)->abiflags;
+
+      /* Set up the abiflags if no valid input sections were found.  */
+      if (!mips_elf_tdata (abfd)->abiflags_valid)
+       {
+         infer_mips_abiflags (abfd, abiflags);
+         mips_elf_tdata (abfd)->abiflags_valid = TRUE;
+       }
+      bfd_mips_elf_swap_abiflags_v0_out (abfd, abiflags, &ext);
+      if (! bfd_set_section_contents (abfd, abiflags_sec, &ext, 0, sizeof ext))
+       return FALSE;
+    }
+
   if (reginfo_sec != NULL)
     {
       Elf32_External_RegInfo ext;
@@ -14199,395 +15064,22 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   return TRUE;
 }
 \f
-/* Structure for saying that BFD machine EXTENSION extends BASE.  */
-
-struct mips_mach_extension
-{
-  unsigned long extension, base;
-};
-
-
-/* An array describing how BFD machines relate to one another.  The entries
-   are ordered topologically with MIPS I extensions listed last.  */
-
-static const struct mips_mach_extension mips_mach_extensions[] =
-{
-  /* MIPS64r2 extensions.  */
-  { bfd_mach_mips_octeon2, bfd_mach_mips_octeonp },
-  { bfd_mach_mips_octeonp, bfd_mach_mips_octeon },
-  { bfd_mach_mips_octeon, bfd_mach_mipsisa64r2 },
-
-  /* MIPS64 extensions.  */
-  { bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
-  { bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
-  { bfd_mach_mips_xlr, bfd_mach_mipsisa64 },
-  { bfd_mach_mips_loongson_3a, bfd_mach_mipsisa64 },
-
-  /* MIPS V extensions.  */
-  { bfd_mach_mipsisa64, bfd_mach_mips5 },
-
-  /* R10000 extensions.  */
-  { bfd_mach_mips12000, bfd_mach_mips10000 },
-  { bfd_mach_mips14000, bfd_mach_mips10000 },
-  { bfd_mach_mips16000, bfd_mach_mips10000 },
-
-  /* R5000 extensions.  Note: the vr5500 ISA is an extension of the core
-     vr5400 ISA, but doesn't include the multimedia stuff.  It seems
-     better to allow vr5400 and vr5500 code to be merged anyway, since
-     many libraries will just use the core ISA.  Perhaps we could add
-     some sort of ASE flag if this ever proves a problem.  */
-  { bfd_mach_mips5500, bfd_mach_mips5400 },
-  { bfd_mach_mips5400, bfd_mach_mips5000 },
-
-  /* MIPS IV extensions.  */
-  { bfd_mach_mips5, bfd_mach_mips8000 },
-  { 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 },
-  { bfd_mach_mips4111, bfd_mach_mips4100 },
-
-  /* MIPS III extensions.  */
-  { bfd_mach_mips_loongson_2e, bfd_mach_mips4000 },
-  { bfd_mach_mips_loongson_2f, bfd_mach_mips4000 },
-  { bfd_mach_mips8000, bfd_mach_mips4000 },
-  { bfd_mach_mips4650, bfd_mach_mips4000 },
-  { bfd_mach_mips4600, bfd_mach_mips4000 },
-  { bfd_mach_mips4400, bfd_mach_mips4000 },
-  { bfd_mach_mips4300, bfd_mach_mips4000 },
-  { bfd_mach_mips4100, bfd_mach_mips4000 },
-  { bfd_mach_mips4010, bfd_mach_mips4000 },
-  { bfd_mach_mips5900, bfd_mach_mips4000 },
-
-  /* MIPS32 extensions.  */
-  { bfd_mach_mipsisa32r2, bfd_mach_mipsisa32 },
-
-  /* MIPS II extensions.  */
-  { bfd_mach_mips4000, bfd_mach_mips6000 },
-  { bfd_mach_mipsisa32, bfd_mach_mips6000 },
-
-  /* MIPS I extensions.  */
-  { bfd_mach_mips6000, bfd_mach_mips3000 },
-  { bfd_mach_mips3900, bfd_mach_mips3000 }
-};
-
-
-/* Return true if bfd machine EXTENSION is an extension of machine BASE.  */
-
-static bfd_boolean
-mips_mach_extends_p (unsigned long base, unsigned long extension)
-{
-  size_t i;
-
-  if (extension == base)
-    return TRUE;
-
-  if (base == bfd_mach_mipsisa32
-      && mips_mach_extends_p (bfd_mach_mipsisa64, extension))
-    return TRUE;
-
-  if (base == bfd_mach_mipsisa32r2
-      && mips_mach_extends_p (bfd_mach_mipsisa64r2, extension))
-    return TRUE;
-
-  for (i = 0; i < ARRAY_SIZE (mips_mach_extensions); i++)
-    if (extension == mips_mach_extensions[i].extension)
-      {
-       extension = mips_mach_extensions[i].base;
-       if (extension == base)
-         return TRUE;
-      }
-
-  return FALSE;
-}
-
-
-/* Return true if the given ELF header flags describe a 32-bit binary.  */
+/* Merge object file header flags from IBFD into OBFD.  Raise an error
+   if there are conflicting settings.  */
 
 static bfd_boolean
-mips_32bit_flags_p (flagword flags)
-{
-  return ((flags & EF_MIPS_32BITMODE) != 0
-         || (flags & EF_MIPS_ABI) == E_MIPS_ABI_O32
-         || (flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI32
-         || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1
-         || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2
-         || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32
-         || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2);
-}
-
-
-/* Merge object attributes from IBFD into OBFD.  Raise an error if
-   there are conflicting attributes.  */
-static bfd_boolean
-mips_elf_merge_obj_attributes (bfd *ibfd, bfd *obfd)
-{
-  obj_attribute *in_attr;
-  obj_attribute *out_attr;
-  bfd *abi_fp_bfd;
-
-  abi_fp_bfd = mips_elf_tdata (obfd)->abi_fp_bfd;
-  in_attr = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
-  if (!abi_fp_bfd && in_attr[Tag_GNU_MIPS_ABI_FP].i != Val_GNU_MIPS_ABI_FP_ANY)
-    mips_elf_tdata (obfd)->abi_fp_bfd = ibfd;
-
-  if (!elf_known_obj_attributes_proc (obfd)[0].i)
-    {
-      /* This is the first object.  Copy the attributes.  */
-      _bfd_elf_copy_obj_attributes (ibfd, obfd);
-
-      /* Use the Tag_null value to indicate the attributes have been
-        initialized.  */
-      elf_known_obj_attributes_proc (obfd)[0].i = 1;
-
-      return TRUE;
-    }
-
-  /* Check for conflicting Tag_GNU_MIPS_ABI_FP attributes and merge
-     non-conflicting ones.  */
-  out_attr = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
-  if (in_attr[Tag_GNU_MIPS_ABI_FP].i != out_attr[Tag_GNU_MIPS_ABI_FP].i)
-    {
-      out_attr[Tag_GNU_MIPS_ABI_FP].type = 1;
-      if (out_attr[Tag_GNU_MIPS_ABI_FP].i == Val_GNU_MIPS_ABI_FP_ANY)
-       out_attr[Tag_GNU_MIPS_ABI_FP].i = in_attr[Tag_GNU_MIPS_ABI_FP].i;
-      else if (in_attr[Tag_GNU_MIPS_ABI_FP].i != Val_GNU_MIPS_ABI_FP_ANY)
-       switch (out_attr[Tag_GNU_MIPS_ABI_FP].i)
-         {
-         case Val_GNU_MIPS_ABI_FP_DOUBLE:
-           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
-             {
-             case Val_GNU_MIPS_ABI_FP_SINGLE:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd, "-mdouble-float", "-msingle-float");
-               break;
-
-             case Val_GNU_MIPS_ABI_FP_SOFT:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd, "-mhard-float", "-msoft-float");
-               break;
-
-             case Val_GNU_MIPS_ABI_FP_64:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd,
-                  "-mdouble-float", "-mips32r2 -mfp64");
-               break;
-
-             default:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), "
-                    "%B uses unknown floating point ABI %d"),
-                  obfd, abi_fp_bfd, ibfd,
-                  "-mdouble-float", in_attr[Tag_GNU_MIPS_ABI_FP].i);
-               break;
-             }
-           break;
-
-         case Val_GNU_MIPS_ABI_FP_SINGLE:
-           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
-             {
-             case Val_GNU_MIPS_ABI_FP_DOUBLE:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd, "-msingle-float", "-mdouble-float");
-               break;
-
-             case Val_GNU_MIPS_ABI_FP_SOFT:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd, "-mhard-float", "-msoft-float");
-               break;
-
-             case Val_GNU_MIPS_ABI_FP_64:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd,
-                  "-msingle-float", "-mips32r2 -mfp64");
-               break;
-
-             default:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), "
-                    "%B uses unknown floating point ABI %d"),
-                  obfd, abi_fp_bfd, ibfd,
-                  "-msingle-float", in_attr[Tag_GNU_MIPS_ABI_FP].i);
-               break;
-             }
-           break;
-
-         case Val_GNU_MIPS_ABI_FP_SOFT:
-           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
-             {
-             case Val_GNU_MIPS_ABI_FP_DOUBLE:
-             case Val_GNU_MIPS_ABI_FP_SINGLE:
-             case Val_GNU_MIPS_ABI_FP_64:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd, "-msoft-float", "-mhard-float");
-               break;
-
-             default:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), "
-                    "%B uses unknown floating point ABI %d"),
-                  obfd, abi_fp_bfd, ibfd,
-                  "-msoft-float", in_attr[Tag_GNU_MIPS_ABI_FP].i);
-               break;
-             }
-           break;
-
-         case Val_GNU_MIPS_ABI_FP_64:
-           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
-             {
-             case Val_GNU_MIPS_ABI_FP_DOUBLE:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd,
-                  "-mips32r2 -mfp64", "-mdouble-float");
-               break;
-
-             case Val_GNU_MIPS_ABI_FP_SINGLE:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd,
-                  "-mips32r2 -mfp64", "-msingle-float");
-               break;
-
-             case Val_GNU_MIPS_ABI_FP_SOFT:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd, "-mhard-float", "-msoft-float");
-               break;
-
-             default:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), "
-                    "%B uses unknown floating point ABI %d"),
-                  obfd, abi_fp_bfd, ibfd,
-                  "-mips32r2 -mfp64", in_attr[Tag_GNU_MIPS_ABI_FP].i);
-               break;
-             }
-           break;
-
-         default:
-           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
-             {
-             case Val_GNU_MIPS_ABI_FP_DOUBLE:
-               _bfd_error_handler
-                 (_("Warning: %B uses unknown floating point ABI %d "
-                    "(set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd,
-                  out_attr[Tag_GNU_MIPS_ABI_FP].i, "-mdouble-float");
-               break;
-
-             case Val_GNU_MIPS_ABI_FP_SINGLE:
-               _bfd_error_handler
-                 (_("Warning: %B uses unknown floating point ABI %d "
-                    "(set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd,
-                  out_attr[Tag_GNU_MIPS_ABI_FP].i, "-msingle-float");
-               break;
-
-             case Val_GNU_MIPS_ABI_FP_SOFT:
-               _bfd_error_handler
-                 (_("Warning: %B uses unknown floating point ABI %d "
-                    "(set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd,
-                  out_attr[Tag_GNU_MIPS_ABI_FP].i, "-msoft-float");
-               break;
-
-             case Val_GNU_MIPS_ABI_FP_64:
-               _bfd_error_handler
-                 (_("Warning: %B uses unknown floating point ABI %d "
-                    "(set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd,
-                  out_attr[Tag_GNU_MIPS_ABI_FP].i, "-mips32r2 -mfp64");
-               break;
-
-             default:
-               _bfd_error_handler
-                 (_("Warning: %B uses unknown floating point ABI %d "
-                    "(set by %B), %B uses unknown floating point ABI %d"),
-                  obfd, abi_fp_bfd, ibfd,
-                  out_attr[Tag_GNU_MIPS_ABI_FP].i,
-                  in_attr[Tag_GNU_MIPS_ABI_FP].i);
-               break;
-             }
-           break;
-         }
-    }
-
-  /* Merge Tag_compatibility attributes and any common GNU ones.  */
-  _bfd_elf_merge_object_attributes (ibfd, obfd);
-
-  return TRUE;
-}
-
-/* Merge backend specific data from an object file to the output
-   object file when linking.  */
-
-bfd_boolean
-_bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+mips_elf_merge_obj_e_flags (bfd *ibfd, struct bfd_link_info *info)
 {
+  bfd *obfd = info->output_bfd;
+  struct mips_elf_obj_tdata *out_tdata = mips_elf_tdata (obfd);
   flagword old_flags;
   flagword new_flags;
   bfd_boolean ok;
-  bfd_boolean null_input_bfd = TRUE;
-  asection *sec;
-
-  /* Check if we have the same endianness.  */
-  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
-    {
-      (*_bfd_error_handler)
-       (_("%B: endianness incompatible with that of the selected emulation"),
-        ibfd);
-      return FALSE;
-    }
-
-  if (!is_mips_elf (ibfd) || !is_mips_elf (obfd))
-    return TRUE;
-
-  if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
-    {
-      (*_bfd_error_handler)
-       (_("%B: ABI is incompatible with that of the selected emulation"),
-        ibfd);
-      return FALSE;
-    }
-
-  if (!mips_elf_merge_obj_attributes (ibfd, obfd))
-    return FALSE;
 
   new_flags = elf_elfheader (ibfd)->e_flags;
   elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
   old_flags = elf_elfheader (obfd)->e_flags;
 
-  if (! elf_flags_init (obfd))
-    {
-      elf_flags_init (obfd) = TRUE;
-      elf_elfheader (obfd)->e_flags = new_flags;
-      elf_elfheader (obfd)->e_ident[EI_CLASS]
-       = elf_elfheader (ibfd)->e_ident[EI_CLASS];
-
-      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
-         && (bfd_get_arch_info (obfd)->the_default
-             || mips_mach_extends_p (bfd_get_mach (obfd),
-                                     bfd_get_mach (ibfd))))
-       {
-         if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
-                                  bfd_get_mach (ibfd)))
-           return FALSE;
-       }
-
-      return TRUE;
-    }
-
   /* Check flag compatibility.  */
 
   new_flags &= ~EF_MIPS_NOREORDER;
@@ -14610,36 +15102,12 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
   if (new_flags == old_flags)
     return TRUE;
 
-  /* Check to see if the input BFD actually contains any sections.
-     If not, its flags may not have been initialised either, but it cannot
-     actually cause any incompatibility.  */
-  for (sec = ibfd->sections; sec != NULL; sec = sec->next)
-    {
-      /* Ignore synthetic sections and empty .text, .data and .bss sections
-        which are automatically generated by gas.  Also ignore fake
-        (s)common sections, since merely defining a common symbol does
-        not affect compatibility.  */
-      if ((sec->flags & SEC_IS_COMMON) == 0
-         && strcmp (sec->name, ".reginfo")
-         && strcmp (sec->name, ".mdebug")
-         && (sec->size != 0
-             || (strcmp (sec->name, ".text")
-                 && strcmp (sec->name, ".data")
-                 && strcmp (sec->name, ".bss"))))
-       {
-         null_input_bfd = FALSE;
-         break;
-       }
-    }
-  if (null_input_bfd)
-    return TRUE;
-
   ok = TRUE;
 
   if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)
       != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0))
     {
-      (*_bfd_error_handler)
+      _bfd_error_handler
        (_("%B: warning: linking abicalls files with non-abicalls files"),
         ibfd);
       ok = TRUE;
@@ -14656,7 +15124,7 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
   /* Compare the ISAs.  */
   if (mips_32bit_flags_p (old_flags) != mips_32bit_flags_p (new_flags))
     {
-      (*_bfd_error_handler)
+      _bfd_error_handler
        (_("%B: linking 32-bit code with 64-bit code"),
         ibfd);
       ok = FALSE;
@@ -14674,6 +15142,9 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
          elf_elfheader (obfd)->e_flags
            |= new_flags & (EF_MIPS_ARCH | EF_MIPS_MACH | EF_MIPS_32BITMODE);
 
+         /* Update the ABI flags isa_level, isa_rev, isa_ext fields.  */
+         update_mips_abiflags_isa (obfd, &out_tdata->abiflags);
+
          /* Copy across the ABI flags if OBFD doesn't use them
             and if that was what caused us to treat IBFD as 32-bit.  */
          if ((old_flags & EF_MIPS_ABI) == 0
@@ -14684,7 +15155,8 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
       else
        {
          /* The ISAs aren't compatible.  */
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: linking %s module with previous %s modules"),
             ibfd,
             bfd_printable_name (ibfd),
@@ -14707,7 +15179,8 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
          || (elf_elfheader (ibfd)->e_ident[EI_CLASS]
              != elf_elfheader (obfd)->e_ident[EI_CLASS]))
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: ABI mismatch: linking %s module with previous %s modules"),
             ibfd,
             elf_mips_abi_name (ibfd),
@@ -14731,7 +15204,8 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
 
       if (m16_mis || micro_mis)
        {
-         (*_bfd_error_handler)
+         _bfd_error_handler
+           /* xgettext:c-format */
            (_("%B: ASE mismatch: linking %s module with previous %s modules"),
             ibfd,
             m16_mis ? "MIPS16" : "microMIPS",
@@ -14748,6 +15222,7 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
   /* Compare NaN encodings.  */
   if ((new_flags & EF_MIPS_NAN2008) != (old_flags & EF_MIPS_NAN2008))
     {
+      /* xgettext:c-format */
       _bfd_error_handler (_("%B: linking %s module with previous %s modules"),
                          ibfd,
                          (new_flags & EF_MIPS_NAN2008
@@ -14759,17 +15234,375 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
       old_flags &= ~EF_MIPS_NAN2008;
     }
 
+  /* Compare FP64 state.  */
+  if ((new_flags & EF_MIPS_FP64) != (old_flags & EF_MIPS_FP64))
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%B: linking %s module with previous %s modules"),
+                         ibfd,
+                         (new_flags & EF_MIPS_FP64
+                          ? "-mfp64" : "-mfp32"),
+                         (old_flags & EF_MIPS_FP64
+                          ? "-mfp64" : "-mfp32"));
+      ok = FALSE;
+      new_flags &= ~EF_MIPS_FP64;
+      old_flags &= ~EF_MIPS_FP64;
+    }
+
   /* Warn about any other mismatches */
   if (new_flags != old_flags)
     {
-      (*_bfd_error_handler)
-       (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
+      /* xgettext:c-format */
+      _bfd_error_handler
+       (_("%B: uses different e_flags (0x%lx) fields than previous modules "
+          "(0x%lx)"),
         ibfd, (unsigned long) new_flags,
         (unsigned long) old_flags);
       ok = FALSE;
     }
 
-  if (! ok)
+  return ok;
+}
+
+/* Merge object attributes from IBFD into OBFD.  Raise an error if
+   there are conflicting attributes.  */
+static bfd_boolean
+mips_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info)
+{
+  bfd *obfd = info->output_bfd;
+  obj_attribute *in_attr;
+  obj_attribute *out_attr;
+  bfd *abi_fp_bfd;
+  bfd *abi_msa_bfd;
+
+  abi_fp_bfd = mips_elf_tdata (obfd)->abi_fp_bfd;
+  in_attr = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
+  if (!abi_fp_bfd && in_attr[Tag_GNU_MIPS_ABI_FP].i != Val_GNU_MIPS_ABI_FP_ANY)
+    mips_elf_tdata (obfd)->abi_fp_bfd = ibfd;
+
+  abi_msa_bfd = mips_elf_tdata (obfd)->abi_msa_bfd;
+  if (!abi_msa_bfd
+      && in_attr[Tag_GNU_MIPS_ABI_MSA].i != Val_GNU_MIPS_ABI_MSA_ANY)
+    mips_elf_tdata (obfd)->abi_msa_bfd = ibfd;
+
+  if (!elf_known_obj_attributes_proc (obfd)[0].i)
+    {
+      /* This is the first object.  Copy the attributes.  */
+      _bfd_elf_copy_obj_attributes (ibfd, obfd);
+
+      /* Use the Tag_null value to indicate the attributes have been
+        initialized.  */
+      elf_known_obj_attributes_proc (obfd)[0].i = 1;
+
+      return TRUE;
+    }
+
+  /* Check for conflicting Tag_GNU_MIPS_ABI_FP attributes and merge
+     non-conflicting ones.  */
+  out_attr = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
+  if (in_attr[Tag_GNU_MIPS_ABI_FP].i != out_attr[Tag_GNU_MIPS_ABI_FP].i)
+    {
+      int out_fp, in_fp;
+
+      out_fp = out_attr[Tag_GNU_MIPS_ABI_FP].i;
+      in_fp = in_attr[Tag_GNU_MIPS_ABI_FP].i;
+      out_attr[Tag_GNU_MIPS_ABI_FP].type = 1;
+      if (out_fp == Val_GNU_MIPS_ABI_FP_ANY)
+       out_attr[Tag_GNU_MIPS_ABI_FP].i = in_fp;
+      else if (out_fp == Val_GNU_MIPS_ABI_FP_XX
+              && (in_fp == Val_GNU_MIPS_ABI_FP_DOUBLE
+                  || in_fp == Val_GNU_MIPS_ABI_FP_64
+                  || in_fp == Val_GNU_MIPS_ABI_FP_64A))
+       {
+         mips_elf_tdata (obfd)->abi_fp_bfd = ibfd;
+         out_attr[Tag_GNU_MIPS_ABI_FP].i = in_attr[Tag_GNU_MIPS_ABI_FP].i;
+       }
+      else if (in_fp == Val_GNU_MIPS_ABI_FP_XX
+              && (out_fp == Val_GNU_MIPS_ABI_FP_DOUBLE
+                  || out_fp == Val_GNU_MIPS_ABI_FP_64
+                  || out_fp == Val_GNU_MIPS_ABI_FP_64A))
+       /* Keep the current setting.  */;
+      else if (out_fp == Val_GNU_MIPS_ABI_FP_64A
+              && in_fp == Val_GNU_MIPS_ABI_FP_64)
+       {
+         mips_elf_tdata (obfd)->abi_fp_bfd = ibfd;
+         out_attr[Tag_GNU_MIPS_ABI_FP].i = in_attr[Tag_GNU_MIPS_ABI_FP].i;
+       }
+      else if (in_fp == Val_GNU_MIPS_ABI_FP_64A
+              && out_fp == Val_GNU_MIPS_ABI_FP_64)
+       /* Keep the current setting.  */;
+      else if (in_fp != Val_GNU_MIPS_ABI_FP_ANY)
+       {
+         const char *out_string, *in_string;
+
+         out_string = _bfd_mips_fp_abi_string (out_fp);
+         in_string = _bfd_mips_fp_abi_string (in_fp);
+         /* First warn about cases involving unrecognised ABIs.  */
+         if (!out_string && !in_string)
+           /* xgettext:c-format */
+           _bfd_error_handler
+             (_("Warning: %B uses unknown floating point ABI %d "
+                "(set by %B), %B uses unknown floating point ABI %d"),
+              obfd, abi_fp_bfd, ibfd, out_fp, in_fp);
+         else if (!out_string)
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("Warning: %B uses unknown floating point ABI %d "
+                "(set by %B), %B uses %s"),
+              obfd, abi_fp_bfd, ibfd, out_fp, in_string);
+         else if (!in_string)
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("Warning: %B uses %s (set by %B), "
+                "%B uses unknown floating point ABI %d"),
+              obfd, abi_fp_bfd, ibfd, out_string, in_fp);
+         else
+           {
+             /* If one of the bfds is soft-float, the other must be
+                hard-float.  The exact choice of hard-float ABI isn't
+                really relevant to the error message.  */
+             if (in_fp == Val_GNU_MIPS_ABI_FP_SOFT)
+               out_string = "-mhard-float";
+             else if (out_fp == Val_GNU_MIPS_ABI_FP_SOFT)
+               in_string = "-mhard-float";
+             _bfd_error_handler
+               /* xgettext:c-format */
+               (_("Warning: %B uses %s (set by %B), %B uses %s"),
+                obfd, abi_fp_bfd, ibfd, out_string, in_string);
+           }
+       }
+    }
+
+  /* Check for conflicting Tag_GNU_MIPS_ABI_MSA attributes and merge
+     non-conflicting ones.  */
+  if (in_attr[Tag_GNU_MIPS_ABI_MSA].i != out_attr[Tag_GNU_MIPS_ABI_MSA].i)
+    {
+      out_attr[Tag_GNU_MIPS_ABI_MSA].type = 1;
+      if (out_attr[Tag_GNU_MIPS_ABI_MSA].i == Val_GNU_MIPS_ABI_MSA_ANY)
+       out_attr[Tag_GNU_MIPS_ABI_MSA].i = in_attr[Tag_GNU_MIPS_ABI_MSA].i;
+      else if (in_attr[Tag_GNU_MIPS_ABI_MSA].i != Val_GNU_MIPS_ABI_MSA_ANY)
+       switch (out_attr[Tag_GNU_MIPS_ABI_MSA].i)
+         {
+         case Val_GNU_MIPS_ABI_MSA_128:
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("Warning: %B uses %s (set by %B), "
+                "%B uses unknown MSA ABI %d"),
+              obfd, abi_msa_bfd, ibfd,
+              "-mmsa", in_attr[Tag_GNU_MIPS_ABI_MSA].i);
+           break;
+
+         default:
+           switch (in_attr[Tag_GNU_MIPS_ABI_MSA].i)
+             {
+             case Val_GNU_MIPS_ABI_MSA_128:
+               _bfd_error_handler
+                 /* xgettext:c-format */
+                 (_("Warning: %B uses unknown MSA ABI %d "
+                    "(set by %B), %B uses %s"),
+                    obfd, abi_msa_bfd, ibfd,
+                    out_attr[Tag_GNU_MIPS_ABI_MSA].i, "-mmsa");
+                 break;
+
+             default:
+               _bfd_error_handler
+                 /* xgettext:c-format */
+                 (_("Warning: %B uses unknown MSA ABI %d "
+                    "(set by %B), %B uses unknown MSA ABI %d"),
+                  obfd, abi_msa_bfd, ibfd,
+                  out_attr[Tag_GNU_MIPS_ABI_MSA].i,
+                  in_attr[Tag_GNU_MIPS_ABI_MSA].i);
+               break;
+             }
+         }
+    }
+
+  /* Merge Tag_compatibility attributes and any common GNU ones.  */
+  return _bfd_elf_merge_object_attributes (ibfd, info);
+}
+
+/* Merge object ABI flags from IBFD into OBFD.  Raise an error if
+   there are conflicting settings.  */
+
+static bfd_boolean
+mips_elf_merge_obj_abiflags (bfd *ibfd, bfd *obfd)
+{
+  obj_attribute *out_attr = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU];
+  struct mips_elf_obj_tdata *out_tdata = mips_elf_tdata (obfd);
+  struct mips_elf_obj_tdata *in_tdata = mips_elf_tdata (ibfd);
+
+  /* Update the output abiflags fp_abi using the computed fp_abi.  */
+  out_tdata->abiflags.fp_abi = out_attr[Tag_GNU_MIPS_ABI_FP].i;
+
+#define max(a, b) ((a) > (b) ? (a) : (b))
+  /* Merge abiflags.  */
+  out_tdata->abiflags.isa_level = max (out_tdata->abiflags.isa_level,
+                                      in_tdata->abiflags.isa_level);
+  out_tdata->abiflags.isa_rev = max (out_tdata->abiflags.isa_rev,
+                                    in_tdata->abiflags.isa_rev);
+  out_tdata->abiflags.gpr_size = max (out_tdata->abiflags.gpr_size,
+                                     in_tdata->abiflags.gpr_size);
+  out_tdata->abiflags.cpr1_size = max (out_tdata->abiflags.cpr1_size,
+                                      in_tdata->abiflags.cpr1_size);
+  out_tdata->abiflags.cpr2_size = max (out_tdata->abiflags.cpr2_size,
+                                      in_tdata->abiflags.cpr2_size);
+#undef max
+  out_tdata->abiflags.ases |= in_tdata->abiflags.ases;
+  out_tdata->abiflags.flags1 |= in_tdata->abiflags.flags1;
+
+  return TRUE;
+}
+
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+bfd_boolean
+_bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
+{
+  bfd *obfd = info->output_bfd;
+  struct mips_elf_obj_tdata *out_tdata;
+  struct mips_elf_obj_tdata *in_tdata;
+  bfd_boolean null_input_bfd = TRUE;
+  asection *sec;
+  bfd_boolean ok;
+
+  /* Check if we have the same endianness.  */
+  if (! _bfd_generic_verify_endian_match (ibfd, info))
+    {
+      _bfd_error_handler
+       (_("%B: endianness incompatible with that of the selected emulation"),
+        ibfd);
+      return FALSE;
+    }
+
+  if (!is_mips_elf (ibfd) || !is_mips_elf (obfd))
+    return TRUE;
+
+  in_tdata = mips_elf_tdata (ibfd);
+  out_tdata = mips_elf_tdata (obfd);
+
+  if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
+    {
+      _bfd_error_handler
+       (_("%B: ABI is incompatible with that of the selected emulation"),
+        ibfd);
+      return FALSE;
+    }
+
+  /* Check to see if the input BFD actually contains any sections.  If not,
+     then it has no attributes, and its flags may not have been initialized
+     either, but it cannot actually cause any incompatibility.  */
+  for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+    {
+      /* Ignore synthetic sections and empty .text, .data and .bss sections
+        which are automatically generated by gas.  Also ignore fake
+        (s)common sections, since merely defining a common symbol does
+        not affect compatibility.  */
+      if ((sec->flags & SEC_IS_COMMON) == 0
+         && strcmp (sec->name, ".reginfo")
+         && strcmp (sec->name, ".mdebug")
+         && (sec->size != 0
+             || (strcmp (sec->name, ".text")
+                 && strcmp (sec->name, ".data")
+                 && strcmp (sec->name, ".bss"))))
+       {
+         null_input_bfd = FALSE;
+         break;
+       }
+    }
+  if (null_input_bfd)
+    return TRUE;
+
+  /* Populate abiflags using existing information.  */
+  if (in_tdata->abiflags_valid)
+    {
+      obj_attribute *in_attr = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU];
+      Elf_Internal_ABIFlags_v0 in_abiflags;
+      Elf_Internal_ABIFlags_v0 abiflags;
+
+      /* Set up the FP ABI attribute from the abiflags if it is not already
+         set.  */
+      if (in_attr[Tag_GNU_MIPS_ABI_FP].i == Val_GNU_MIPS_ABI_FP_ANY)
+        in_attr[Tag_GNU_MIPS_ABI_FP].i = in_tdata->abiflags.fp_abi;
+
+      infer_mips_abiflags (ibfd, &abiflags);
+      in_abiflags = in_tdata->abiflags;
+
+      /* It is not possible to infer the correct ISA revision
+         for R3 or R5 so drop down to R2 for the checks.  */
+      if (in_abiflags.isa_rev == 3 || in_abiflags.isa_rev == 5)
+       in_abiflags.isa_rev = 2;
+
+      if (LEVEL_REV (in_abiflags.isa_level, in_abiflags.isa_rev)
+         < LEVEL_REV (abiflags.isa_level, abiflags.isa_rev))
+       _bfd_error_handler
+         (_("%B: warning: Inconsistent ISA between e_flags and "
+            ".MIPS.abiflags"), ibfd);
+      if (abiflags.fp_abi != Val_GNU_MIPS_ABI_FP_ANY
+         && in_abiflags.fp_abi != abiflags.fp_abi)
+       _bfd_error_handler
+         (_("%B: warning: Inconsistent FP ABI between .gnu.attributes and "
+            ".MIPS.abiflags"), ibfd);
+      if ((in_abiflags.ases & abiflags.ases) != abiflags.ases)
+       _bfd_error_handler
+         (_("%B: warning: Inconsistent ASEs between e_flags and "
+            ".MIPS.abiflags"), ibfd);
+      /* The isa_ext is allowed to be an extension of what can be inferred
+        from e_flags.  */
+      if (!mips_mach_extends_p (bfd_mips_isa_ext_mach (abiflags.isa_ext),
+                               bfd_mips_isa_ext_mach (in_abiflags.isa_ext)))
+       _bfd_error_handler
+         (_("%B: warning: Inconsistent ISA extensions between e_flags and "
+            ".MIPS.abiflags"), ibfd);
+      if (in_abiflags.flags2 != 0)
+       _bfd_error_handler
+         (_("%B: warning: Unexpected flag in the flags2 field of "
+            ".MIPS.abiflags (0x%lx)"), ibfd,
+          (unsigned long) in_abiflags.flags2);
+    }
+  else
+    {
+      infer_mips_abiflags (ibfd, &in_tdata->abiflags);
+      in_tdata->abiflags_valid = TRUE;
+    }
+
+  if (!out_tdata->abiflags_valid)
+    {
+      /* Copy input abiflags if output abiflags are not already valid.  */
+      out_tdata->abiflags = in_tdata->abiflags;
+      out_tdata->abiflags_valid = TRUE;
+    }
+
+  if (! elf_flags_init (obfd))
+    {
+      elf_flags_init (obfd) = TRUE;
+      elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
+      elf_elfheader (obfd)->e_ident[EI_CLASS]
+       = elf_elfheader (ibfd)->e_ident[EI_CLASS];
+
+      if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
+         && (bfd_get_arch_info (obfd)->the_default
+             || mips_mach_extends_p (bfd_get_mach (obfd),
+                                     bfd_get_mach (ibfd))))
+       {
+         if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
+                                  bfd_get_mach (ibfd)))
+           return FALSE;
+
+         /* Update the ABI flags isa_level, isa_rev and isa_ext fields.  */
+         update_mips_abiflags_isa (obfd, &out_tdata->abiflags);
+       }
+
+      ok = TRUE;
+    }
+  else
+    ok = mips_elf_merge_obj_e_flags (ibfd, info);
+
+  ok = mips_elf_merge_obj_attributes (ibfd, info) && ok;
+
+  ok = mips_elf_merge_obj_abiflags (ibfd, obfd) && ok;
+
+  if (!ok)
     {
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
@@ -14831,6 +15664,8 @@ _bfd_mips_elf_get_target_dtag (bfd_vma dtag)
       return "MIPS_HIPAGENO";
     case DT_MIPS_RLD_MAP:
       return "MIPS_RLD_MAP";
+    case DT_MIPS_RLD_MAP_REL:
+      return "MIPS_RLD_MAP_REL";
     case DT_MIPS_DELTA_CLASS:
       return "MIPS_DELTA_CLASS";
     case DT_MIPS_DELTA_CLASS_NO:
@@ -14890,6 +15725,195 @@ _bfd_mips_elf_get_target_dtag (bfd_vma dtag)
     }
 }
 
+/* Return the meaning of Tag_GNU_MIPS_ABI_FP value FP, or null if
+   not known.  */
+
+const char *
+_bfd_mips_fp_abi_string (int fp)
+{
+  switch (fp)
+    {
+      /* These strings aren't translated because they're simply
+        option lists.  */
+    case Val_GNU_MIPS_ABI_FP_DOUBLE:
+      return "-mdouble-float";
+
+    case Val_GNU_MIPS_ABI_FP_SINGLE:
+      return "-msingle-float";
+
+    case Val_GNU_MIPS_ABI_FP_SOFT:
+      return "-msoft-float";
+
+    case Val_GNU_MIPS_ABI_FP_OLD_64:
+      return _("-mips32r2 -mfp64 (12 callee-saved)");
+
+    case Val_GNU_MIPS_ABI_FP_XX:
+      return "-mfpxx";
+
+    case Val_GNU_MIPS_ABI_FP_64:
+      return "-mgp32 -mfp64";
+
+    case Val_GNU_MIPS_ABI_FP_64A:
+      return "-mgp32 -mfp64 -mno-odd-spreg";
+
+    default:
+      return 0;
+    }
+}
+
+static void
+print_mips_ases (FILE *file, unsigned int mask)
+{
+  if (mask & AFL_ASE_DSP)
+    fputs ("\n\tDSP ASE", file);
+  if (mask & AFL_ASE_DSPR2)
+    fputs ("\n\tDSP R2 ASE", file);
+  if (mask & AFL_ASE_DSPR3)
+    fputs ("\n\tDSP R3 ASE", file);
+  if (mask & AFL_ASE_EVA)
+    fputs ("\n\tEnhanced VA Scheme", file);
+  if (mask & AFL_ASE_MCU)
+    fputs ("\n\tMCU (MicroController) ASE", file);
+  if (mask & AFL_ASE_MDMX)
+    fputs ("\n\tMDMX ASE", file);
+  if (mask & AFL_ASE_MIPS3D)
+    fputs ("\n\tMIPS-3D ASE", file);
+  if (mask & AFL_ASE_MT)
+    fputs ("\n\tMT ASE", file);
+  if (mask & AFL_ASE_SMARTMIPS)
+    fputs ("\n\tSmartMIPS ASE", file);
+  if (mask & AFL_ASE_VIRT)
+    fputs ("\n\tVZ ASE", file);
+  if (mask & AFL_ASE_MSA)
+    fputs ("\n\tMSA ASE", file);
+  if (mask & AFL_ASE_MIPS16)
+    fputs ("\n\tMIPS16 ASE", file);
+  if (mask & AFL_ASE_MICROMIPS)
+    fputs ("\n\tMICROMIPS ASE", file);
+  if (mask & AFL_ASE_XPA)
+    fputs ("\n\tXPA ASE", file);
+  if (mask == 0)
+    fprintf (file, "\n\t%s", _("None"));
+  else if ((mask & ~AFL_ASE_MASK) != 0)
+    fprintf (stdout, "\n\t%s (%x)", _("Unknown"), mask & ~AFL_ASE_MASK);
+}
+
+static void
+print_mips_isa_ext (FILE *file, unsigned int isa_ext)
+{
+  switch (isa_ext)
+    {
+    case 0:
+      fputs (_("None"), file);
+      break;
+    case AFL_EXT_XLR:
+      fputs ("RMI XLR", file);
+      break;
+    case AFL_EXT_OCTEON3:
+      fputs ("Cavium Networks Octeon3", file);
+      break;
+    case AFL_EXT_OCTEON2:
+      fputs ("Cavium Networks Octeon2", file);
+      break;
+    case AFL_EXT_OCTEONP:
+      fputs ("Cavium Networks OcteonP", file);
+      break;
+    case AFL_EXT_LOONGSON_3A:
+      fputs ("Loongson 3A", file);
+      break;
+    case AFL_EXT_OCTEON:
+      fputs ("Cavium Networks Octeon", file);
+      break;
+    case AFL_EXT_5900:
+      fputs ("Toshiba R5900", file);
+      break;
+    case AFL_EXT_4650:
+      fputs ("MIPS R4650", file);
+      break;
+    case AFL_EXT_4010:
+      fputs ("LSI R4010", file);
+      break;
+    case AFL_EXT_4100:
+      fputs ("NEC VR4100", file);
+      break;
+    case AFL_EXT_3900:
+      fputs ("Toshiba R3900", file);
+      break;
+    case AFL_EXT_10000:
+      fputs ("MIPS R10000", file);
+      break;
+    case AFL_EXT_SB1:
+      fputs ("Broadcom SB-1", file);
+      break;
+    case AFL_EXT_4111:
+      fputs ("NEC VR4111/VR4181", file);
+      break;
+    case AFL_EXT_4120:
+      fputs ("NEC VR4120", file);
+      break;
+    case AFL_EXT_5400:
+      fputs ("NEC VR5400", file);
+      break;
+    case AFL_EXT_5500:
+      fputs ("NEC VR5500", file);
+      break;
+    case AFL_EXT_LOONGSON_2E:
+      fputs ("ST Microelectronics Loongson 2E", file);
+      break;
+    case AFL_EXT_LOONGSON_2F:
+      fputs ("ST Microelectronics Loongson 2F", file);
+      break;
+    default:
+      fprintf (file, "%s (%d)", _("Unknown"), isa_ext);
+      break;
+    }
+}
+
+static void
+print_mips_fp_abi_value (FILE *file, int val)
+{
+  switch (val)
+    {
+    case Val_GNU_MIPS_ABI_FP_ANY:
+      fprintf (file, _("Hard or soft float\n"));
+      break;
+    case Val_GNU_MIPS_ABI_FP_DOUBLE:
+      fprintf (file, _("Hard float (double precision)\n"));
+      break;
+    case Val_GNU_MIPS_ABI_FP_SINGLE:
+      fprintf (file, _("Hard float (single precision)\n"));
+      break;
+    case Val_GNU_MIPS_ABI_FP_SOFT:
+      fprintf (file, _("Soft float\n"));
+      break;
+    case Val_GNU_MIPS_ABI_FP_OLD_64:
+      fprintf (file, _("Hard float (MIPS32r2 64-bit FPU 12 callee-saved)\n"));
+      break;
+    case Val_GNU_MIPS_ABI_FP_XX:
+      fprintf (file, _("Hard float (32-bit CPU, Any FPU)\n"));
+      break;
+    case Val_GNU_MIPS_ABI_FP_64:
+      fprintf (file, _("Hard float (32-bit CPU, 64-bit FPU)\n"));
+      break;
+    case Val_GNU_MIPS_ABI_FP_64A:
+      fprintf (file, _("Hard float compat (32-bit CPU, 64-bit FPU)\n"));
+      break;
+    default:
+      fprintf (file, "??? (%d)\n", val);
+      break;
+    }
+}
+
+static int
+get_mips_reg_size (int reg_size)
+{
+  return (reg_size == AFL_REG_NONE) ? 0
+        : (reg_size == AFL_REG_32) ? 32
+        : (reg_size == AFL_REG_64) ? 64
+        : (reg_size == AFL_REG_128) ? 128
+        : -1;
+}
+
 bfd_boolean
 _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
 {
@@ -14938,6 +15962,10 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
     fprintf (file, " [mips32r2]");
   else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R2)
     fprintf (file, " [mips64r2]");
+  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6)
+    fprintf (file, " [mips32r6]");
+  else if ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R6)
+    fprintf (file, " [mips64r6]");
   else
     fprintf (file, _(" [unknown ISA]"));
 
@@ -14954,7 +15982,7 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
     fprintf (file, " [nan2008]");
 
   if (elf_elfheader (abfd)->e_flags & EF_MIPS_FP64)
-    fprintf (file, " [fp64]");
+    fprintf (file, " [old fp64]");
 
   if (elf_elfheader (abfd)->e_flags & EF_MIPS_32BITMODE)
     fprintf (file, " [32bitmode]");
@@ -14978,6 +16006,30 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
 
   fputc ('\n', file);
 
+  if (mips_elf_tdata (abfd)->abiflags_valid)
+    {
+      Elf_Internal_ABIFlags_v0 *abiflags = &mips_elf_tdata (abfd)->abiflags;
+      fprintf (file, "\nMIPS ABI Flags Version: %d\n", abiflags->version);
+      fprintf (file, "\nISA: MIPS%d", abiflags->isa_level);
+      if (abiflags->isa_rev > 1)
+       fprintf (file, "r%d", abiflags->isa_rev);
+      fprintf (file, "\nGPR size: %d",
+              get_mips_reg_size (abiflags->gpr_size));
+      fprintf (file, "\nCPR1 size: %d",
+              get_mips_reg_size (abiflags->cpr1_size));
+      fprintf (file, "\nCPR2 size: %d",
+              get_mips_reg_size (abiflags->cpr2_size));
+      fputs ("\nFP ABI: ", file);
+      print_mips_fp_abi_value (file, abiflags->fp_abi);
+      fputs ("ISA Extension: ", file);
+      print_mips_isa_ext (file, abiflags->isa_ext);
+      fputs ("\nASEs:", file);
+      print_mips_ases (file, abiflags->ases);
+      fprintf (file, "\nFLAGS 1: %8.8lx", abiflags->flags1);
+      fprintf (file, "\nFLAGS 2: %8.8lx", abiflags->flags2);
+      fputc ('\n', file);
+    }
+
   return TRUE;
 }
 
@@ -15298,4 +16350,27 @@ _bfd_mips_post_process_headers (bfd *abfd, struct bfd_link_info *link_info)
       if (htab->use_plts_and_copy_relocs && !htab->is_vxworks)
        i_ehdrp->e_ident[EI_ABIVERSION] = 1;
     }
+
+  _bfd_elf_post_process_headers (abfd, link_info);
+
+  if (mips_elf_tdata (abfd)->abiflags.fp_abi == Val_GNU_MIPS_ABI_FP_64
+      || mips_elf_tdata (abfd)->abiflags.fp_abi == Val_GNU_MIPS_ABI_FP_64A)
+    i_ehdrp->e_ident[EI_ABIVERSION] = 3;
+
+  if (elf_stack_flags (abfd) && !(elf_stack_flags (abfd) & PF_X))
+    i_ehdrp->e_ident[EI_ABIVERSION] = 5;
+}
+
+int
+_bfd_mips_elf_compact_eh_encoding (struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
+{
+  return DW_EH_PE_pcrel | DW_EH_PE_sdata4;
+}
+
+/* Return the opcode for can't unwind.  */
+
+int
+_bfd_mips_elf_cant_unwind_opcode (struct bfd_link_info *link_info ATTRIBUTE_UNUSED)
+{
+  return COMPACT_EH_CANT_UNWIND_OPCODE;
 }
This page took 0.080626 seconds and 4 git commands to generate.