Remove use of alloca.
[deliverable/binutils-gdb.git] / bfd / elfxx-mips.c
index dd61049a17ec424b02aab21ddad47030d0843ef7..a46b2f56b92609946d26a2e84784b46466968c8e 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.  */
@@ -437,6 +440,9 @@ struct mips_elf_link_hash_table
   /* True if we can generate copy relocs and PLTs.  */
   bfd_boolean use_plts_and_copy_relocs;
 
+  /* True if we can only use 32-bit microMIPS instructions.  */
+  bfd_boolean insn32;
+
   /* True if we're generating code for VxWorks.  */
   bfd_boolean is_vxworks;
 
@@ -539,6 +545,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;
 
@@ -768,6 +781,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)
@@ -783,6 +800,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))
@@ -800,6 +822,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))                \
@@ -885,10 +911,7 @@ 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_ORI(VAL) (0x37180000 + (VAL))     /* ori t8,t8,VAL */
@@ -904,9 +927,11 @@ 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 0x001f7a90       /* or t7,ra,zero */
 #define STUB_LUI_MICROMIPS(VAL)                                                \
    (0x41b80000 + (VAL))                                /* lui t8,VAL */
 #define STUB_JALR_MICROMIPS 0x45d9             /* jalr t9 */
+#define STUB_JALR32_MICROMIPS 0x03f90f3c       /* jalr ra,t9 */
 #define STUB_ORI_MICROMIPS(VAL)                                                \
   (0x53180000 + (VAL))                         /* ori t8,t8,VAL */
 #define STUB_LI16U_MICROMIPS(VAL)                                      \
@@ -920,6 +945,8 @@ static bfd *reldyn_sorting_bfd;
 #define MIPS_FUNCTION_STUB_BIG_SIZE 20
 #define MICROMIPS_FUNCTION_STUB_NORMAL_SIZE 12
 #define MICROMIPS_FUNCTION_STUB_BIG_SIZE 16
+#define MICROMIPS_INSN32_FUNCTION_STUB_NORMAL_SIZE 16
+#define MICROMIPS_INSN32_FUNCTION_STUB_BIG_SIZE 20
 
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
@@ -997,7 +1024,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                                     */
@@ -1011,7 +1038,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                                     */
@@ -1025,7 +1052,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                                     */
@@ -1050,6 +1077,20 @@ static const bfd_vma micromips_o32_exec_plt0_entry[] =
   0x0c00               /* nop                                          */
 };
 
+/* The format of the microMIPS first PLT entry in an O32 executable
+   in the insn32 mode.  */
+static const bfd_vma micromips_insn32_o32_exec_plt0_entry[] =
+{
+  0x41bc, 0x0000,      /* lui $28, %hi(&GOTPLT[0])                     */
+  0xff3c, 0x0000,      /* lw $25, %lo(&GOTPLT[0])($28)                 */
+  0x339c, 0x0000,      /* addiu $28, $28, %lo(&GOTPLT[0])              */
+  0x0398, 0xc1d0,      /* subu $24, $24, $28                           */
+  0x001f, 0x7a90,      /* or $15, $31, zero                            */
+  0x0318, 0x1040,      /* srl $24, $24, 2                              */
+  0x03f9, 0x0f3c,      /* jalr $25                                     */
+  0x3318, 0xfffe       /* subu $24, $24, 2                             */
+};
+
 /* The format of subsequent standard PLT entries.  */
 static const bfd_vma mips_exec_plt_entry[] =
 {
@@ -1059,6 +1100,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.  */
@@ -1083,6 +1135,15 @@ static const bfd_vma micromips_o32_exec_plt_entry[] =
   0x0f02               /* move $24, $2                         */
 };
 
+/* The format of subsequent microMIPS o32 PLT entries in the insn32 mode.  */
+static const bfd_vma micromips_insn32_o32_exec_plt_entry[] =
+{
+  0x41af, 0x0000,      /* lui $15, %hi(.got.plt entry)         */
+  0xff2f, 0x0000,      /* lw $25, %lo(.got.plt entry)($15)     */
+  0x0019, 0x0f3c,      /* jr $25                               */
+  0x330f, 0x0000       /* addiu $24, $15, %lo(.got.plt entry)  */
+};
+
 /* The format of the first PLT entry in a VxWorks executable.  */
 static const bfd_vma mips_vxworks_exec_plt0_entry[] =
 {
@@ -1519,17 +1580,20 @@ mips_elf_create_stub_symbol (struct bfd_link_info *info,
 {
   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))
     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.  */
@@ -1551,9 +1615,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
@@ -1562,11 +1627,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.  */
@@ -1646,6 +1713,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
@@ -1658,6 +1726,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
@@ -1670,6 +1739,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;
     }
 }
 
@@ -1908,7 +1978,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))
@@ -1923,7 +1993,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);
@@ -2095,18 +2165,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)
 {
@@ -2130,7 +2188,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
@@ -2138,7 +2197,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
@@ -2155,6 +2215,13 @@ jal_reloc_p (int r_type)
          || r_type == R_MICROMIPS_26_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
 micromips_branch_reloc_p (int r_type)
 {
@@ -2626,6 +2693,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.  */
@@ -3109,11 +3216,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))
@@ -3131,7 +3238,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;
@@ -3215,15 +3322,17 @@ mips_elf_initialize_tls_slots (bfd *abfd, struct bfd_link_info *info,
     {
       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))
@@ -3298,7 +3407,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
@@ -3599,7 +3708,7 @@ 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)
@@ -3612,7 +3721,14 @@ 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;
 
@@ -3652,7 +3768,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;
@@ -4053,9 +4170,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;
@@ -4072,7 +4190,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;
 
@@ -4092,7 +4210,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;
 
@@ -4212,7 +4330,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;
@@ -4266,6 +4384,36 @@ mips_elf_resolve_final_got_entries (struct bfd_link_info *info,
   return TRUE;
 }
 
+/* Return true if a GOT entry for H should live in the local rather than
+   global GOT area.  */
+
+static bfd_boolean
+mips_use_local_got_p (struct bfd_link_info *info,
+                     struct mips_elf_link_hash_entry *h)
+{
+  /* Symbols that aren't in the dynamic symbol table must live in the
+     local GOT.  This includes symbols that are completely undefined
+     and which therefore don't bind locally.  We'll report undefined
+     symbols later if appropriate.  */
+  if (h->root.dynindx == -1)
+    return TRUE;
+
+  /* Symbols that bind locally can (and in the case of forced-local
+     symbols, must) live in the local GOT.  */
+  if (h->got_only_for_calls
+      ? SYMBOL_CALLS_LOCAL (info, &h->root)
+      : SYMBOL_REFERENCES_LOCAL (info, &h->root))
+    return TRUE;
+
+  /* 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 (bfd_link_executable (info) && h->has_static_relocs)
+    return TRUE;
+
+  return FALSE;
+}
+
 /* A mips_elf_link_hash_traverse callback for which DATA points to the
    link_info structure.  Decide whether the hash entry needs an entry in
    the global part of the primary GOT, setting global_got_area accordingly.
@@ -4285,18 +4433,8 @@ mips_elf_count_got_symbols (struct mips_elf_link_hash_entry *h, void *data)
   if (h->global_got_area != GGA_NONE)
     {
       /* Make a final decision about whether the symbol belongs in the
-        local or global GOT.  Symbols that bind locally can (and in the
-        case of forced-local symbols, must) live in the local GOT.
-        Those that are aren't in the dynamic symbol table must also
-        live in the local GOT.
-
-        Note that the former condition does not always imply the
-        latter: symbols do not bind locally if they are completely
-        undefined.  We'll report undefined symbols later if appropriate.  */
-      if (h->root.dynindx == -1
-         || (h->got_only_for_calls
-             ? SYMBOL_CALLS_LOCAL (info, &h->root)
-             : SYMBOL_REFERENCES_LOCAL (info, &h->root)))
+        local or global GOT.  */
+      if (mips_use_local_got_p (info, h))
        /* The symbol belongs in the local GOT.  We no longer need this
           entry if it was only used for relocations; those relocations
           will be against the null or section symbol instead of H.  */
@@ -4571,14 +4709,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))
@@ -4671,7 +4809,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))
@@ -4709,7 +4847,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
@@ -4732,9 +4870,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
@@ -4773,21 +4912,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);
@@ -4984,9 +5123,10 @@ mips_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
   h->non_elf = 0;
   h->def_regular = 1;
   h->type = STT_OBJECT;
+  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;
 
@@ -5015,7 +5155,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));
 }
@@ -5041,6 +5181,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:
@@ -5253,7 +5395,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;
        }
@@ -5295,7 +5437,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))
@@ -5337,7 +5479,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
@@ -5390,7 +5532,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
      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
+          && !bfd_link_relocatable (info)
           && h != NULL
           && h->use_plt_entry
           && h->root.plt.plist->comp_offset != MINUS_ONE
@@ -5425,7 +5567,7 @@ 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
@@ -5434,10 +5576,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
                                && (target_is_16_bit_code_p
                                    || target_is_micromips_code_p))));
 
-  local_p = (h == NULL
-            || (h->got_only_for_calls
-                ? SYMBOL_CALLS_LOCAL (info, &h->root)
-                : SYMBOL_REFERENCES_LOCAL (info, &h->root)));
+  local_p = (h == NULL || mips_use_local_got_p (info, h));
 
   gp0 = _bfd_get_gp_value (input_bfd);
   gp = _bfd_get_gp_value (abfd);
@@ -5570,14 +5709,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
@@ -5642,8 +5783,10 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
 
        if (was_local_p)
          value = addend | ((p + 4) & (0xfc000000 << shift));
-       else
+       else if (howto->partial_inplace)
          value = _bfd_mips_elf_sign_extend (addend, 26 + shift);
+       else
+         value = addend;
        value = (value + symbol) >> shift;
        if (!was_local_p && h->root.root.type != bfd_link_hash_undefweak)
          overflowed_p = (value >> 26) != ((p + 4) >> (26 + shift));
@@ -5780,7 +5923,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:
@@ -5828,36 +5972,125 @@ 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);
+
+      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, 18);
+      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);
+      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);
+      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);
+      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;
@@ -5956,11 +6189,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;
 }
@@ -5985,6 +6220,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;
@@ -6043,7 +6279,7 @@ mips_elf_perform_relocation (struct bfd_link_info *info,
 
   /* 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
@@ -6078,9 +6314,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;
@@ -6361,6 +6599,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;
 
@@ -6400,6 +6641,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;
        }
     }
 
@@ -6750,20 +6997,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)
@@ -6845,6 +7083,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_"))
@@ -6875,6 +7118,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
@@ -7041,6 +7298,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_"))
     {
@@ -7186,7 +7448,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;
@@ -7227,7 +7489,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;
@@ -7238,7 +7500,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)
     {
@@ -7346,7 +7608,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",
@@ -7410,7 +7672,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;
 
@@ -7472,7 +7734,7 @@ _bfd_mips_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   else
     htab->srelplt = bfd_get_linker_section (abfd, ".rel.plt");
   if (!htab->sdynbss
-      || (htab->is_vxworks && !htab->srelbss && !info->shared)
+      || (htab->is_vxworks && !htab->srelbss && !bfd_link_pic (info))
       || !htab->srelplt
       || !htab->splt)
     abort ();
@@ -7552,6 +7814,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;
 
@@ -7648,7 +7912,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);
@@ -7921,6 +8185,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       unsigned int r_type;
       struct elf_link_hash_entry *h;
       bfd_boolean can_make_dynamic_p;
+      bfd_boolean call_reloc_p;
+      bfd_boolean constrain_symbol_p;
 
       r_symndx = ELF_R_SYM (abfd, rel->r_info);
       r_type = ELF_R_TYPE (abfd, rel->r_info);
@@ -7953,12 +8219,30 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       /* Set CAN_MAKE_DYNAMIC_P to true if we can convert this
         relocation into a dynamic one.  */
       can_make_dynamic_p = FALSE;
+
+      /* Set CALL_RELOC_P to true if the relocation is for a call,
+        and if pointer equality therefore doesn't matter.  */
+      call_reloc_p = FALSE;
+
+      /* Set CONSTRAIN_SYMBOL_P if we need to take the relocation
+        into account when deciding how to define the symbol.
+        Relocations in nonallocatable sections such as .pdr and
+        .debug* should have no effect.  */
+      constrain_symbol_p = ((sec->flags & SEC_ALLOC) != 0);
+
       switch (r_type)
        {
-       case R_MIPS_GOT16:
        case R_MIPS_CALL16:
        case R_MIPS_CALL_HI16:
        case R_MIPS_CALL_LO16:
+       case R_MIPS16_CALL16:
+       case R_MICROMIPS_CALL16:
+       case R_MICROMIPS_CALL_HI16:
+       case R_MICROMIPS_CALL_LO16:
+         call_reloc_p = TRUE;
+         /* Fall through.  */
+
+       case R_MIPS_GOT16:
        case R_MIPS_GOT_HI16:
        case R_MIPS_GOT_LO16:
        case R_MIPS_GOT_PAGE:
@@ -7968,14 +8252,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_MIPS_TLS_GD:
        case R_MIPS_TLS_LDM:
        case R_MIPS16_GOT16:
-       case R_MIPS16_CALL16:
        case R_MIPS16_TLS_GOTTPREL:
        case R_MIPS16_TLS_GD:
        case R_MIPS16_TLS_LDM:
        case R_MICROMIPS_GOT16:
-       case R_MICROMIPS_CALL16:
-       case R_MICROMIPS_CALL_HI16:
-       case R_MICROMIPS_CALL_LO16:
        case R_MICROMIPS_GOT_HI16:
        case R_MICROMIPS_GOT_LO16:
        case R_MICROMIPS_GOT_PAGE:
@@ -7988,7 +8268,7 @@ _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)
                (_("%B: GOT reloc at 0x%lx not expected in executables"),
@@ -7996,12 +8276,27 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
            }
+         can_make_dynamic_p = TRUE;
          break;
 
-         /* This is just a hint; it can safely be ignored.  Don't set
-            has_static_relocs for the corresponding symbol.  */
+       case R_MIPS_NONE:
        case R_MIPS_JALR:
        case R_MICROMIPS_JALR:
+         /* These relocations have empty fields and are purely there to
+            provide link information.  The symbol value doesn't matter.  */
+         constrain_symbol_p = FALSE;
+         break;
+
+       case R_MIPS_GPREL16:
+       case R_MIPS_GPREL32:
+       case R_MIPS16_GPREL:
+       case R_MICROMIPS_GPREL16:
+         /* GP-relative relocations always resolve to a definition in a
+            regular input file, ignoring the one-definition rule.  This is
+            important for the GP setup sequence in NewABI code, which
+            always resolves to a local function even if other relocations
+            against the symbol wouldn't.  */
+         constrain_symbol_p = FALSE;
          break;
 
        case R_MIPS_32:
@@ -8016,7 +8311,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
@@ -8028,51 +8323,41 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
              can_make_dynamic_p = TRUE;
              if (dynobj == NULL)
                elf_hash_table (info)->dynobj = dynobj = abfd;
-             break;
            }
-         /* For sections that are not SEC_ALLOC a copy reloc would be
-            output if possible (implying questionable semantics for
-            read-only data objects) or otherwise the final link would
-            fail as ld.so will not process them and could not therefore
-            handle any outstanding dynamic relocations.
-
-            For such sections that are also SEC_DEBUGGING, we can avoid
-            these problems by simply ignoring any relocs as these
-            sections have a predefined use and we know it is safe to do
-            so.
-
-            This is needed in cases such as a global symbol definition
-            in a shared library causing a common symbol from an object
-            file to be converted to an undefined reference.  If that
-            happens, then all the relocations against this symbol from
-            SEC_DEBUGGING sections in the object file will resolve to
-            nil.  */
-         if ((sec->flags & SEC_DEBUGGING) != 0)
-           break;
-         /* Fall through.  */
-
-       default:
-         /* Most static relocations require pointer equality, except
-            for branches.  */
-         if (h)
-           h->pointer_equality_needed = TRUE;
-         /* Fall through.  */
+         break;
 
        case R_MIPS_26:
        case R_MIPS_PC16:
+       case R_MIPS_PC21_S2:
+       case R_MIPS_PC26_S2:
        case R_MIPS16_26:
        case R_MICROMIPS_26_S1:
        case R_MICROMIPS_PC7_S1:
        case R_MICROMIPS_PC10_S1:
        case R_MICROMIPS_PC16_S1:
        case R_MICROMIPS_PC23_S2:
-         if (h)
-           ((struct mips_elf_link_hash_entry *) h)->has_static_relocs = TRUE;
+         call_reloc_p = TRUE;
          break;
        }
 
       if (h)
        {
+         if (constrain_symbol_p)
+           {
+             if (!can_make_dynamic_p)
+               ((struct mips_elf_link_hash_entry *) h)->has_static_relocs = 1;
+
+             if (!call_reloc_p)
+               h->pointer_equality_needed = 1;
+
+             /* We must not create a stub for a symbol that has
+                relocations related to taking the function's address.
+                This doesn't apply to VxWorks, where CALL relocs refer
+                to a .got.plt entry instead of a normal .got entry.  */
+             if (!htab->is_vxworks && (!can_make_dynamic_p || !call_reloc_p))
+               ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE;
+           }
+
          /* Relocations against the special VxWorks __GOTT_BASE__ and
             __GOTT_INDEX__ symbols must be left to the loader.  Allocate
             room for them in .rela.dyn.  */
@@ -8191,7 +8476,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;
                }
@@ -8210,7 +8495,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 */
 
@@ -8258,7 +8543,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
@@ -8353,28 +8638,6 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
            h->plt.plist->need_comp = TRUE;
        }
 
-      /* We must not create a stub for a symbol that has relocations
-        related to taking the function's address.  This doesn't apply to
-        VxWorks, where CALL relocs refer to a .got.plt entry instead of
-        a normal .got entry.  */
-      if (!htab->is_vxworks && h != NULL)
-       switch (r_type)
-         {
-         default:
-           ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE;
-           break;
-         case R_MIPS16_CALL16:
-         case R_MIPS_CALL16:
-         case R_MIPS_CALL_HI16:
-         case R_MIPS_CALL_LO16:
-         case R_MIPS_JALR:
-         case R_MICROMIPS_CALL16:
-         case R_MICROMIPS_CALL_HI16:
-         case R_MICROMIPS_CALL_LO16:
-         case R_MICROMIPS_JALR:
-           break;
-         }
-
       /* See if this reloc would need to refer to a MIPS16 hard-float stub,
         if there is one.  We only need to handle global symbols here;
         we decide whether to keep or delete stubs for local symbols
@@ -8394,7 +8657,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)
            {
@@ -8458,7 +8721,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,
@@ -8504,7 +8767,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;
 
@@ -8620,7 +8883,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
@@ -8631,11 +8894,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;
 
@@ -8789,11 +9052,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)
@@ -8802,19 +9065,26 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
          else if (newabi_p)
            htab->plt_mips_entry_size
              = 4 * ARRAY_SIZE (mips_exec_plt_entry);
-         else if (micromips_p)
+         else if (!micromips_p)
            {
              htab->plt_mips_entry_size
                = 4 * ARRAY_SIZE (mips_exec_plt_entry);
              htab->plt_comp_entry_size
-               = 2 * ARRAY_SIZE (micromips_o32_exec_plt_entry);
+               = 2 * ARRAY_SIZE (mips16_o32_exec_plt_entry);
+           }
+         else if (htab->insn32)
+           {
+             htab->plt_mips_entry_size
+               = 4 * ARRAY_SIZE (mips_exec_plt_entry);
+             htab->plt_comp_entry_size
+               = 2 * ARRAY_SIZE (micromips_insn32_o32_exec_plt_entry);
            }
          else
            {
              htab->plt_mips_entry_size
                = 4 * ARRAY_SIZE (mips_exec_plt_entry);
              htab->plt_comp_entry_size
-               = 2 * ARRAY_SIZE (mips16_o32_exec_plt_entry);
+               = 2 * ARRAY_SIZE (micromips_o32_exec_plt_entry);
            }
        }
 
@@ -8870,7 +9140,7 @@ _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.  */
@@ -8879,7 +9149,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
                              : 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
@@ -8913,7 +9183,7 @@ _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"),
@@ -8945,7 +9215,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,
@@ -8956,7 +9226,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;
 
@@ -8964,9 +9234,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;
@@ -9005,13 +9280,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.  */
@@ -9023,7 +9298,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;
 
@@ -9054,6 +9329,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);
@@ -9071,7 +9347,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);
@@ -9088,7 +9364,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.  */
@@ -9128,15 +9404,19 @@ mips_elf_estimate_stub_size (bfd *output_bfd, struct bfd_link_info *info)
      from using microMIPS code here, so for the sake of pure-microMIPS
      binaries we prefer it whenever there's any microMIPS code in
      output produced at all.  This has a benefit of stubs being
-     shorter by 4 bytes each too.  */
-  if (MICROMIPS_P (output_bfd))
-    htab->function_stub_size = (dynsymcount > 0x10000
-                               ? MICROMIPS_FUNCTION_STUB_BIG_SIZE
-                               : MICROMIPS_FUNCTION_STUB_NORMAL_SIZE);
-  else
+     shorter by 4 bytes each too, unless in the insn32 mode.  */
+  if (!MICROMIPS_P (output_bfd))
     htab->function_stub_size = (dynsymcount > 0x10000
                                ? MIPS_FUNCTION_STUB_BIG_SIZE
                                : MIPS_FUNCTION_STUB_NORMAL_SIZE);
+  else if (htab->insn32)
+    htab->function_stub_size = (dynsymcount > 0x10000
+                               ? MICROMIPS_INSN32_FUNCTION_STUB_BIG_SIZE
+                               : MICROMIPS_INSN32_FUNCTION_STUB_NORMAL_SIZE);
+  else
+    htab->function_stub_size = (dynsymcount > 0x10000
+                               ? MICROMIPS_FUNCTION_STUB_BIG_SIZE
+                               : MICROMIPS_FUNCTION_STUB_NORMAL_SIZE);
 
   htab->sstubs->size = htab->lazy_stub_count * htab->function_stub_size;
 }
@@ -9296,7 +9576,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);
@@ -9331,7 +9611,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
          BFD_ASSERT (htab->sgotplt->size == 0);
          BFD_ASSERT (htab->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);
@@ -9341,6 +9621,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
            size = 4 * ARRAY_SIZE (mips_n32_exec_plt0_entry);
          else if (!micromips_p)
            size = 4 * ARRAY_SIZE (mips_o32_exec_plt0_entry);
+         else if (htab->insn32)
+           size = 2 * ARRAY_SIZE (micromips_insn32_o32_exec_plt0_entry);
          else
            size = 2 * ARRAY_SIZE (micromips_o32_exec_plt0_entry);
 
@@ -9431,7 +9713,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"))
        {
@@ -9490,13 +9772,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;
@@ -9632,7 +9918,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);
@@ -9823,7 +10109,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))
@@ -9972,6 +10258,13 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                (info, msg, name, input_bfd, input_section, rel->r_offset);
              return FALSE;
            }
+         if (aligned_pcrel_reloc_p (howto->type))
+           {
+             msg = _("PC-relative load from unaligned address");
+             info->callbacks->warning
+               (info, msg, name, input_bfd, input_section, rel->r_offset);
+             return FALSE;
+           }
          /* Fall through.  */
 
        default:
@@ -10261,7 +10554,11 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
          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);
@@ -10293,7 +10590,32 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
          loc = htab->splt->contents + plt_offset;
 
          /* Fill in the PLT entry itself.  */
-         if (MICROMIPS_P (output_bfd))
+         if (!MICROMIPS_P (output_bfd))
+           {
+             const bfd_vma *plt_entry = mips16_o32_exec_plt_entry;
+
+             bfd_put_16 (output_bfd, plt_entry[0], loc);
+             bfd_put_16 (output_bfd, plt_entry[1], loc + 2);
+             bfd_put_16 (output_bfd, plt_entry[2], loc + 4);
+             bfd_put_16 (output_bfd, plt_entry[3], loc + 6);
+             bfd_put_16 (output_bfd, plt_entry[4], loc + 8);
+             bfd_put_16 (output_bfd, plt_entry[5], loc + 10);
+             bfd_put_32 (output_bfd, got_address, loc + 12);
+           }
+         else if (htab->insn32)
+           {
+             const bfd_vma *plt_entry = micromips_insn32_o32_exec_plt_entry;
+
+             bfd_put_16 (output_bfd, plt_entry[0], loc);
+             bfd_put_16 (output_bfd, got_address_high, loc + 2);
+             bfd_put_16 (output_bfd, plt_entry[2], loc + 4);
+             bfd_put_16 (output_bfd, got_address_low, loc + 6);
+             bfd_put_16 (output_bfd, plt_entry[4], loc + 8);
+             bfd_put_16 (output_bfd, plt_entry[5], loc + 10);
+             bfd_put_16 (output_bfd, plt_entry[6], loc + 12);
+             bfd_put_16 (output_bfd, got_address_low, loc + 14);
+           }
+         else
            {
              const bfd_vma *plt_entry = micromips_o32_exec_plt_entry;
              bfd_signed_vma gotpc_offset;
@@ -10326,18 +10648,6 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
              bfd_put_16 (output_bfd, plt_entry[4], loc + 8);
              bfd_put_16 (output_bfd, plt_entry[5], loc + 10);
            }
-         else
-           {
-             const bfd_vma *plt_entry = mips16_o32_exec_plt_entry;
-
-             bfd_put_16 (output_bfd, plt_entry[0], loc);
-             bfd_put_16 (output_bfd, plt_entry[1], loc + 2);
-             bfd_put_16 (output_bfd, plt_entry[2], loc + 4);
-             bfd_put_16 (output_bfd, plt_entry[3], loc + 6);
-             bfd_put_16 (output_bfd, plt_entry[4], loc + 8);
-             bfd_put_16 (output_bfd, plt_entry[5], loc + 10);
-             bfd_put_32 (output_bfd, got_address, loc + 12);
-           }
        }
 
       /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry.  */
@@ -10369,10 +10679,12 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
       bfd_vma isa_bit = micromips_p;
       bfd_vma stub_big_size;
 
-      if (micromips_p)
-       stub_big_size = MICROMIPS_FUNCTION_STUB_BIG_SIZE;
-      else
+      if (!micromips_p)
        stub_big_size = MIPS_FUNCTION_STUB_BIG_SIZE;
+      else if (htab->insn32)
+       stub_big_size = MICROMIPS_INSN32_FUNCTION_STUB_BIG_SIZE;
+      else
+       stub_big_size = MICROMIPS_FUNCTION_STUB_BIG_SIZE;
 
       /* This symbol has a stub.  Set it up.  */
 
@@ -10393,8 +10705,17 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
          bfd_put_micromips_32 (output_bfd, STUB_LW_MICROMIPS (output_bfd),
                                stub + idx);
          idx += 4;
-         bfd_put_16 (output_bfd, STUB_MOVE_MICROMIPS, stub + idx);
-         idx += 2;
+         if (htab->insn32)
+           {
+             bfd_put_micromips_32 (output_bfd,
+                                   STUB_MOVE32_MICROMIPS, stub + idx);
+             idx += 4;
+           }
+         else
+           {
+             bfd_put_16 (output_bfd, STUB_MOVE_MICROMIPS, stub + idx);
+             idx += 2;
+           }
          if (stub_size == stub_big_size)
            {
              long dynindx_hi = (h->dynindx >> 16) & 0x7fff;
@@ -10404,11 +10725,20 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
                                    stub + idx);
              idx += 4;
            }
-         bfd_put_16 (output_bfd, STUB_JALR_MICROMIPS, stub + idx);
-         idx += 2;
-
-         /* If a large stub is not required and sign extension is not a
-            problem, then use legacy code in the stub.  */
+         if (htab->insn32)
+           {
+             bfd_put_micromips_32 (output_bfd, STUB_JALR32_MICROMIPS,
+                                   stub + idx);
+             idx += 4;
+           }
+         else
+           {
+             bfd_put_16 (output_bfd, STUB_JALR_MICROMIPS, stub + idx);
+             idx += 2;
+           }
+
+         /* If a large stub is not required and sign extension is not a
+            problem, then use legacy code in the stub.  */
          if (stub_size == stub_big_size)
            bfd_put_micromips_32 (output_bfd,
                                  STUB_ORI_MICROMIPS (h->dynindx & 0xffff),
@@ -10428,7 +10758,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)
            {
@@ -10522,7 +10852,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd,
            {
              offset = p->gotidx;
              BFD_ASSERT (offset > 0 && offset < htab->sgot->size);
-             if (info->shared
+             if (bfd_link_pic (info)
                  || (elf_hash_table (info)->dynamic_sections_created
                      && p->d.h != NULL
                      && p->d.h->root.def_dynamic
@@ -10698,7 +11028,7 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
       /* Find out where the .plt entry should go.  */
       loc = htab->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);
@@ -10828,10 +11158,12 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
     plt_entry = mips_n64_exec_plt0_entry;
   else if (ABI_N32_P (output_bfd))
     plt_entry = mips_n32_exec_plt0_entry;
-  else if (htab->plt_header_is_comp)
-    plt_entry = micromips_o32_exec_plt0_entry;
-  else
+  else if (!htab->plt_header_is_comp)
     plt_entry = mips_o32_exec_plt0_entry;
+  else if (htab->insn32)
+    plt_entry = micromips_insn32_o32_exec_plt0_entry;
+  else
+    plt_entry = micromips_o32_exec_plt0_entry;
 
   /* Calculate the value of .got.plt.  */
   gotplt_value = (htab->sgotplt->output_section->vma
@@ -10876,6 +11208,19 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info)
       for (i = 2; i < ARRAY_SIZE (micromips_o32_exec_plt0_entry); i++)
        bfd_put_16 (output_bfd, plt_entry[i], loc + (i * 2));
     }
+  else if (plt_entry == micromips_insn32_o32_exec_plt0_entry)
+    {
+      size_t i;
+
+      bfd_put_16 (output_bfd, plt_entry[0], loc);
+      bfd_put_16 (output_bfd, gotplt_value_high, loc + 2);
+      bfd_put_16 (output_bfd, plt_entry[2], loc + 4);
+      bfd_put_16 (output_bfd, gotplt_value_low, loc + 6);
+      bfd_put_16 (output_bfd, plt_entry[4], loc + 8);
+      bfd_put_16 (output_bfd, gotplt_value_low, loc + 10);
+      for (i = 6; i < ARRAY_SIZE (micromips_insn32_o32_exec_plt0_entry); i++)
+       bfd_put_16 (output_bfd, plt_entry[i], loc + (i * 2));
+    }
   else
     {
       bfd_put_32 (output_bfd, plt_entry[0] | gotplt_value_high, loc);
@@ -11117,9 +11462,11 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
              name = ".dynsym";
              elemsize = MIPS_ELF_SYM_SIZE (output_bfd);
              s = bfd_get_section_by_name (output_bfd, name);
-             BFD_ASSERT (s != NULL);
 
-             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:
@@ -11137,11 +11484,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)));
@@ -11270,13 +11643,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,
@@ -11402,14 +11779,14 @@ _bfd_mips_elf_finish_dynamic_sections (bfd *output_bfd,
     {
       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;
        }
@@ -11510,7 +11887,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:
@@ -11518,6 +11895,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;
@@ -11535,12 +11916,24 @@ 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;
+
+    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;
@@ -11548,6 +11941,18 @@ mips_set_isa_flags (bfd *abfd)
 }
 
 
+/* 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;
+}
+
+
 /* The final processing done just before writing out a MIPS ELF object
    file.  This gets the MIPS architecture right based on the machine
    number.  This is used by both the 32-bit and the 64-bit ABI.  */
@@ -11649,6 +12054,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,
@@ -11711,6 +12120,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
@@ -11805,18 +12245,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
@@ -11963,7 +12391,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;
@@ -12006,6 +12434,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
@@ -12113,6 +12571,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;
     }
@@ -12183,24 +12643,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");
@@ -12279,9 +12741,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
@@ -12654,9 +13116,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.  */
@@ -12755,8 +13216,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().  */
 };
 
@@ -12929,6 +13390,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
                             struct bfd_link_info *link_info,
                             bfd_boolean *again)
 {
+  bfd_boolean insn32 = mips_elf_hash_table (link_info)->insn32;
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Rela *internal_relocs;
   Elf_Internal_Rela *irel, *irelend;
@@ -12942,7 +13404,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)
@@ -13211,7 +13673,13 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
               && irel->r_offset + 5 < sec->size
               && ((fndopc = find_match (opcode, bz_rs_insns_32)) >= 0
                   || (fndopc = find_match (opcode, bz_rt_insns_32)) >= 0)
-              && MATCH (bfd_get_16 (abfd, ptr + 4), nop_insn_16))
+              && ((!insn32
+                   && (delcnt = MATCH (bfd_get_16 (abfd, ptr + 4),
+                                       nop_insn_16) ? 2 : 0))
+                  || (irel->r_offset + 7 < sec->size
+                      && (delcnt = MATCH (bfd_get_micromips_32 (abfd,
+                                                                ptr + 4),
+                                          nop_insn_32) ? 4 : 0))))
        {
          unsigned long reg;
 
@@ -13224,15 +13692,15 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
 
          bfd_put_micromips_32 (abfd, opcode, ptr);
 
-         /* Delete the 16-bit delay slot NOP: two bytes from
-            irel->offset + 4.  */
-         delcnt = 2;
+         /* Delete the delay slot NOP: two or four bytes from
+            irel->offset + 4; delcnt has already been set above.  */
          deloff = 4;
        }
 
       /* R_MICROMIPS_PC16_S1 relaxation to R_MICROMIPS_PC10_S1.  We need
          to check the distance from the next instruction, so subtract 2.  */
-      else if (r_type == R_MICROMIPS_PC16_S1
+      else if (!insn32
+              && r_type == R_MICROMIPS_PC16_S1
               && IS_BITSIZE (pcrval - 2, 11)
               && find_match (opcode, b_insns_32) >= 0)
        {
@@ -13252,7 +13720,8 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
 
       /* R_MICROMIPS_PC16_S1 relaxation to R_MICROMIPS_PC7_S1.  We need
          to check the distance from the next instruction, so subtract 2.  */
-      else if (r_type == R_MICROMIPS_PC16_S1
+      else if (!insn32
+              && r_type == R_MICROMIPS_PC16_S1
               && IS_BITSIZE (pcrval - 2, 8)
               && (((fndopc = find_match (opcode, bz_rs_insns_32)) >= 0
                    && OP16_VALID_REG (OP32_SREG (opcode)))
@@ -13279,7 +13748,8 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
        }
 
       /* R_MICROMIPS_26_S1 -- JAL to JALS relaxation for microMIPS targets.  */
-      else if (r_type == R_MICROMIPS_26_S1
+      else if (!insn32
+              && r_type == R_MICROMIPS_26_S1
               && target_is_micromips_code_p
               && irel->r_offset + 7 < sec->size
               && MATCH (opcode, jal_insn_32_bd32))
@@ -13437,123 +13907,436 @@ _bfd_mips_elf_use_plts_and_copy_relocs (struct bfd_link_info *info)
 {
   mips_elf_hash_table (info)->use_plts_and_copy_relocs = TRUE;
 }
-\f
-/* 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.  */
 
-bfd_boolean
-_bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
+/* A function that the linker calls to select between all or only
+   32-bit microMIPS instructions.  */
+
+void
+_bfd_mips_elf_insn32 (struct bfd_link_info *info, bfd_boolean on)
 {
-  asection *o;
-  struct bfd_link_order *p;
-  asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec;
-  asection *rtproc_sec;
-  Elf32_RegInfo reginfo;
-  struct ecoff_debug_info debug;
-  struct mips_htab_traverse_info hti;
-  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  const struct ecoff_debug_swap *swap = bed->elf_backend_ecoff_debug_swap;
-  HDRR *symhdr = &debug.symbolic_header;
-  void *mdebug_handle = NULL;
-  asection *s;
-  EXTR esym;
-  unsigned int i;
-  bfd_size_type amt;
-  struct mips_elf_link_hash_table *htab;
+  mips_elf_hash_table (info)->insn32 = on;
+}
+\f
+/* Structure for saying that BFD machine EXTENSION extends BASE.  */
 
-  static const char * const secname[] =
-  {
-    ".text", ".init", ".fini", ".data",
-    ".rodata", ".sdata", ".sbss", ".bss"
-  };
-  static const int sc[] =
-  {
-    scText, scInit, scFini, scData,
-    scRData, scSData, scSBss, scBss
-  };
+struct mips_mach_extension
+{
+  unsigned long extension, base;
+};
 
-  /* Sort the dynamic symbols so that those with GOT entries come after
-     those without.  */
-  htab = mips_elf_hash_table (info);
-  BFD_ASSERT (htab != NULL);
 
-  if (!mips_elf_sort_hash_table (abfd, info))
-    return FALSE;
+/* An array describing how BFD machines relate to one another.  The entries
+   are ordered topologically with MIPS I extensions listed last.  */
 
-  /* Create any scheduled LA25 stubs.  */
-  hti.info = info;
-  hti.output_bfd = abfd;
-  hti.error = FALSE;
-  htab_traverse (htab->la25_stubs, mips_elf_create_la25_stub, &hti);
-  if (hti.error)
-    return FALSE;
+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 },
 
-  /* Get a value for the GP register.  */
-  if (elf_gp (abfd) == 0)
-    {
-      struct bfd_link_hash_entry *h;
+  /* MIPS64 extensions.  */
+  { bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
+  { bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
+  { bfd_mach_mips_xlr, bfd_mach_mipsisa64 },
 
-      h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
-      if (h != NULL && h->type == bfd_link_hash_defined)
-       elf_gp (abfd) = (h->u.def.value
-                        + h->u.def.section->output_section->vma
-                        + h->u.def.section->output_offset);
-      else if (htab->is_vxworks
-              && (h = bfd_link_hash_lookup (info->hash,
-                                            "_GLOBAL_OFFSET_TABLE_",
-                                            FALSE, FALSE, TRUE))
-              && h->type == bfd_link_hash_defined)
-       elf_gp (abfd) = (h->u.def.section->output_section->vma
-                        + h->u.def.section->output_offset
-                        + h->u.def.value);
-      else if (info->relocatable)
-       {
-         bfd_vma lo = MINUS_ONE;
+  /* MIPS V extensions.  */
+  { bfd_mach_mipsisa64, bfd_mach_mips5 },
 
-         /* Find the GP-relative section with the lowest offset.  */
-         for (o = abfd->sections; o != NULL; o = o->next)
-           if (o->vma < lo
-               && (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
-             lo = o->vma;
+  /* R10000 extensions.  */
+  { bfd_mach_mips12000, bfd_mach_mips10000 },
+  { bfd_mach_mips14000, bfd_mach_mips10000 },
+  { bfd_mach_mips16000, bfd_mach_mips10000 },
 
-         /* And calculate GP relative to that.  */
-         elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (info);
-       }
-      else
-       {
-         /* If the relocate_section function needs to do a reloc
-            involving the GP value, it should make a reloc_dangerous
-            callback to warn that GP is not defined.  */
-       }
-    }
+  /* 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 },
 
-  /* Go through the sections and collect the .reginfo and .mdebug
-     information.  */
-  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, ".reginfo") == 0)
-       {
-         memset (&reginfo, 0, sizeof reginfo);
+  /* 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 },
 
-         /* We have found the .reginfo section in the output file.
-            Look through all the link_orders comprising it and merge
-            the information together.  */
-         for (p = o->map_head.link_order; p != NULL; p = p->next)
-           {
-             asection *input_section;
-             bfd *input_bfd;
-             Elf32_External_RegInfo ext;
-             Elf32_RegInfo sub;
+  /* VR4100 extensions.  */
+  { bfd_mach_mips4120, bfd_mach_mips4100 },
+  { bfd_mach_mips4111, bfd_mach_mips4100 },
 
-             if (p->type != bfd_indirect_link_order)
-               {
-                 if (p->type == bfd_data_link_order)
-                   continue;
+  /* 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)
+       (_("%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.  */
+
+bfd_boolean
+_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, *abiflags_sec;
+  Elf32_RegInfo reginfo;
+  struct ecoff_debug_info debug;
+  struct mips_htab_traverse_info hti;
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  const struct ecoff_debug_swap *swap = bed->elf_backend_ecoff_debug_swap;
+  HDRR *symhdr = &debug.symbolic_header;
+  void *mdebug_handle = NULL;
+  asection *s;
+  EXTR esym;
+  unsigned int i;
+  bfd_size_type amt;
+  struct mips_elf_link_hash_table *htab;
+
+  static const char * const secname[] =
+  {
+    ".text", ".init", ".fini", ".data",
+    ".rodata", ".sdata", ".sbss", ".bss"
+  };
+  static const int sc[] =
+  {
+    scText, scInit, scFini, scData,
+    scRData, scSData, scSBss, scBss
+  };
+
+  /* Sort the dynamic symbols so that those with GOT entries come after
+     those without.  */
+  htab = mips_elf_hash_table (info);
+  BFD_ASSERT (htab != NULL);
+
+  if (!mips_elf_sort_hash_table (abfd, info))
+    return FALSE;
+
+  /* Create any scheduled LA25 stubs.  */
+  hti.info = info;
+  hti.output_bfd = abfd;
+  hti.error = FALSE;
+  htab_traverse (htab->la25_stubs, mips_elf_create_la25_stub, &hti);
+  if (hti.error)
+    return FALSE;
+
+  /* Get a value for the GP register.  */
+  if (elf_gp (abfd) == 0)
+    {
+      struct bfd_link_hash_entry *h;
+
+      h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
+      if (h != NULL && h->type == bfd_link_hash_defined)
+       elf_gp (abfd) = (h->u.def.value
+                        + h->u.def.section->output_section->vma
+                        + h->u.def.section->output_offset);
+      else if (htab->is_vxworks
+              && (h = bfd_link_hash_lookup (info->hash,
+                                            "_GLOBAL_OFFSET_TABLE_",
+                                            FALSE, FALSE, TRUE))
+              && h->type == bfd_link_hash_defined)
+       elf_gp (abfd) = (h->u.def.section->output_section->vma
+                        + h->u.def.section->output_offset
+                        + h->u.def.value);
+      else if (bfd_link_relocatable (info))
+       {
+         bfd_vma lo = MINUS_ONE;
+
+         /* Find the GP-relative section with the lowest offset.  */
+         for (o = abfd->sections; o != NULL; o = o->next)
+           if (o->vma < lo
+               && (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
+             lo = o->vma;
+
+         /* And calculate GP relative to that.  */
+         elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (info);
+       }
+      else
+       {
+         /* If the relocate_section function needs to do a reloc
+            involving the GP value, it should make a reloc_dangerous
+            callback to warn that GP is not defined.  */
+       }
+    }
+
+  /* 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);
+
+         /* We have found the .reginfo section in the output file.
+            Look through all the link_orders comprising it and merge
+            the information together.  */
+         for (p = o->map_head.link_order; p != NULL; p = p->next)
+           {
+             asection *input_section;
+             bfd *input_bfd;
+             Elf32_External_RegInfo ext;
+             Elf32_RegInfo sub;
+
+             if (p->type != bfd_indirect_link_order)
+               {
+                 if (p->type == bfd_data_link_order)
+                   continue;
                  abort ();
                }
 
@@ -13759,7 +14542,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");
@@ -13815,7 +14598,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)
                {
@@ -14020,6 +14803,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;
@@ -14071,395 +14872,21 @@ _bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   return TRUE;
 }
 \f
-/* Structure for saying that BFD machine EXTENSION extends BASE.  */
+/* Merge object file header flags from IBFD into OBFD.  Raise an error
+   if there are conflicting settings.  */
 
-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.  */
-
-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 != 0)
-    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 == 0)
-       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 != 0)
-       switch (out_attr[Tag_GNU_MIPS_ABI_FP].i)
-         {
-         case 1:
-           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
-             {
-             case 2:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd, "-mdouble-float", "-msingle-float");
-               break;
-
-             case 3:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd, "-mhard-float", "-msoft-float");
-               break;
-
-             case 4:
-               _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 2:
-           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
-             {
-             case 1:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd, "-msingle-float", "-mdouble-float");
-               break;
-
-             case 3:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd, "-mhard-float", "-msoft-float");
-               break;
-
-             case 4:
-               _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 3:
-           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
-             {
-             case 1:
-             case 2:
-             case 4:
-               _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 4:
-           switch (in_attr[Tag_GNU_MIPS_ABI_FP].i)
-             {
-             case 1:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd,
-                  "-mips32r2 -mfp64", "-mdouble-float");
-               break;
-
-             case 2:
-               _bfd_error_handler
-                 (_("Warning: %B uses %s (set by %B), %B uses %s"),
-                  obfd, abi_fp_bfd, ibfd,
-                  "-mips32r2 -mfp64", "-msingle-float");
-               break;
-
-             case 3:
-               _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 1:
-               _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 2:
-               _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 3:
-               _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 4:
-               _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)
+static bfd_boolean
+mips_elf_merge_obj_e_flags (bfd *ibfd, bfd *obfd)
 {
+  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;
@@ -14482,30 +14909,6 @@ _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)
@@ -14546,6 +14949,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
@@ -14617,17 +15023,378 @@ _bfd_mips_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
       old_flags &= ~ EF_MIPS_ARCH_ASE;
     }
 
+  /* Compare NaN encodings.  */
+  if ((new_flags & EF_MIPS_NAN2008) != (old_flags & EF_MIPS_NAN2008))
+    {
+      _bfd_error_handler (_("%B: linking %s module with previous %s modules"),
+                         ibfd,
+                         (new_flags & EF_MIPS_NAN2008
+                          ? "-mnan=2008" : "-mnan=legacy"),
+                         (old_flags & EF_MIPS_NAN2008
+                          ? "-mnan=2008" : "-mnan=legacy"));
+      ok = FALSE;
+      new_flags &= ~EF_MIPS_NAN2008;
+      old_flags &= ~EF_MIPS_NAN2008;
+    }
+
+  /* Compare FP64 state.  */
+  if ((new_flags & EF_MIPS_FP64) != (old_flags & EF_MIPS_FP64))
+    {
+      _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)"),
+       (_("%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, bfd *obfd)
+{
+  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)
+           _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
+             (_("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
+             (_("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
+               (_("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
+             (_("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
+                 (_("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
+                 (_("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, obfd);
+}
+
+/* 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, bfd *obfd)
+{
+  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, 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;
+
+  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, obfd);
+
+  ok = mips_elf_merge_obj_attributes (ibfd, obfd) && ok;
+
+  ok = mips_elf_merge_obj_abiflags (ibfd, obfd) && ok;
+
+  if (!ok)
     {
       bfd_set_error (bfd_error_bad_value);
       return FALSE;
@@ -14689,6 +15456,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:
@@ -14748,6 +15517,193 @@ _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_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)
 {
@@ -14796,6 +15752,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]"));
 
@@ -14808,6 +15768,12 @@ _bfd_mips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
   if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS)
     fprintf (file, " [micromips]");
 
+  if (elf_elfheader (abfd)->e_flags & EF_MIPS_NAN2008)
+    fprintf (file, " [nan2008]");
+
+  if (elf_elfheader (abfd)->e_flags & EF_MIPS_FP64)
+    fprintf (file, " [old fp64]");
+
   if (elf_elfheader (abfd)->e_flags & EF_MIPS_32BITMODE)
     fprintf (file, " [32bitmode]");
   else
@@ -14830,6 +15796,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;
 }
 
@@ -14999,6 +15989,13 @@ _bfd_mips_elf_get_synthetic_symtab (bfd *abfd,
       plt0_size = 2 * ARRAY_SIZE (micromips_o32_exec_plt0_entry);
       other = STO_MICROMIPS;
     }
+  else if (opcode == 0x0398c1d0)
+    {
+      if (!micromips_p)
+       return -1;
+      plt0_size = 2 * ARRAY_SIZE (micromips_insn32_o32_exec_plt0_entry);
+      other = STO_MICROMIPS;
+    }
   else
     {
       plt0_size = 4 * ARRAY_SIZE (mips_o32_exec_plt0_entry);
@@ -15042,7 +16039,7 @@ _bfd_mips_elf_get_synthetic_symtab (bfd *abfd,
          suffix = m16suffix;
          other = STO_MIPS16;
        }
-      /* Likewise the expected microMIPS instruction.  */
+      /* Likewise the expected microMIPS instruction (no insn32 mode).  */
       else if (opcode == 0xff220000)
        {
          if (!micromips_p)
@@ -15058,6 +16055,19 @@ _bfd_mips_elf_get_synthetic_symtab (bfd *abfd,
          suffix = microsuffix;
          other = STO_MICROMIPS;
        }
+      /* Likewise the expected microMIPS instruction (insn32 mode).  */
+      else if ((opcode & 0xffff0000) == 0xff2f0000)
+       {
+         gotplt_hi = bfd_get_16 (abfd, plt_data + plt_offset + 2) & 0xffff;
+         gotplt_lo = bfd_get_16 (abfd, plt_data + plt_offset + 6) & 0xffff;
+         gotplt_hi = ((gotplt_hi ^ 0x8000) - 0x8000) << 16;
+         gotplt_lo = (gotplt_lo ^ 0x8000) - 0x8000;
+         gotplt_addr = gotplt_hi + gotplt_lo;
+         entry_size = 2 * ARRAY_SIZE (micromips_insn32_o32_exec_plt_entry);
+         suffixlen = sizeof (microsuffix);
+         suffix = microsuffix;
+         other = STO_MICROMIPS;
+       }
       /* Otherwise assume standard MIPS code.  */
       else
        {
@@ -15130,4 +16140,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.115905 seconds and 4 git commands to generate.