]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
MIPS: Add o32 RELA relocations for VxWorks targets
authorMaciej W. Rozycki <macro@orcam.me.uk>
Thu, 30 Oct 2025 14:24:23 +0000 (14:24 +0000)
committerMaciej W. Rozycki <macro@orcam.me.uk>
Thu, 30 Oct 2025 14:24:23 +0000 (14:24 +0000)
MIPS/VxWorks targets have an unusual arrangement in that they use RELA
relocations with the o32 ABI, unlike any other MIPS target.  Due to an
inconsistency in BFD however "hybrid" relocations are produced by GAS,
where despite the relocations being of the RELA type the field to be
relocated also holds an in-place addend to be applied at link time.

For example:

$ cat vxworks-rela.s
.text
foo:
la $2, bar + 0x12345678
$ mips-vxworks-as -o vxworks-rela.o vxworks-rela.s
$ mips-vxworks-objdump -dr vxworks-rela.o

vxworks-rela.o:     file format elf32-bigmips-vxworks

Disassembly of section .text:

00000000 <foo>:
   0: 3c021234  lui v0,0x1234
0: R_MIPS_HI16 bar+0x12345678
   4: 24425678  addiu v0,v0,22136
4: R_MIPS_LO16 bar+0x12345678
$

This is due to the BFD backend being strapped for RELA relocations:

#undef elf_backend_may_use_rel_p
#define elf_backend_may_use_rel_p 0
#undef elf_backend_may_use_rela_p
#define elf_backend_may_use_rela_p 1
#undef elf_backend_default_use_rela_p
#define elf_backend_default_use_rela_p 1

but the howtos in use requesting an in-place addend, e.g.:

  /* High 16 bits of symbol value.  */
  HOWTO (R_MIPS_HI16, /* type */
 16, /* rightshift */
 4, /* size */
 16, /* bitsize */
 false, /* pc_relative */
 0, /* bitpos */
 complain_overflow_dont, /* complain_on_overflow */
 _bfd_mips_elf_hi16_reloc, /* special_function */
 "R_MIPS_HI16", /* name */
 true, /* partial_inplace */
 0x0000ffff, /* src_mask */
 0x0000ffff, /* dst_mask */
 false), /* pcrel_offset */

  /* Low 16 bits of symbol value.  */
  HOWTO (R_MIPS_LO16, /* type */
 0, /* rightshift */
 4, /* size */
 16, /* bitsize */
 false, /* pc_relative */
 0, /* bitpos */
 complain_overflow_dont, /* complain_on_overflow */
 _bfd_mips_elf_lo16_reloc, /* special_function */
 "R_MIPS_LO16", /* name */
 true, /* partial_inplace */
 0x0000ffff, /* src_mask */
 0x0000ffff, /* dst_mask */
 false), /* pcrel_offset */

This arrangement nevertheless happens to produce correct ELF executables
owing to the ELF linker avoiding the use of howtos and doing relocation
calculations using its own knowledge of relocation semantics embedded
directly in `mips_elf_calculate_relocation' code.

Beyond producing questionable link object files it however breaks badly
with the generic linker, such as when output is srec.

Fix the problem by providing a set of o32 RELA howtos and making VxWorks
targets use it.  Complement it with a set of test cases for GAS and LD;
we expect link object files to be essentially the same as n32 ones for
other MIPS targets sans the ABI2 ELF file header flag, and machine code
produced to be the same between SREC and ELF executables.

bfd/elf32-mips.c
bfd/elfxx-mips.c
gas/config/tc-mips.c
gas/testsuite/gas/mips/mips.exp
gas/testsuite/gas/mips/vxworks-micromips-hilo.d [new file with mode: 0644]
gas/testsuite/gas/mips/vxworks-mips-hilo.d [new file with mode: 0644]
gas/testsuite/gas/mips/vxworks-mips16-hilo.d [new file with mode: 0644]
gas/testsuite/gas/mips/vxworks-mips16e2-hilo.d [new file with mode: 0644]
gas/testsuite/gas/mips/vxworks-pcrel-hilo.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/mips-elf.exp

index 5871fb75e8a204e102fb0c77ad39519790bc4cec..939debda2236058041a6c6a05de0fddca4ea8fb5 100644 (file)
@@ -33,6 +33,7 @@
 #include "sysdep.h"
 #include "bfd.h"
 #include "libbfd.h"
+#include "libiberty.h"
 #include "bfdlink.h"
 #include "genlink.h"
 #include "elf-bfd.h"
@@ -55,8 +56,6 @@ static bfd_reloc_status_type mips_elf_gprel32_reloc
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
 static bfd_reloc_status_type mips32_64bit_reloc
   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
-static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
-  (bfd *, bfd_reloc_code_real_type);
 static bool mips_info_to_howto_rel
   (bfd *, arelent *, Elf_Internal_Rela *);
 static bool mips_info_to_howto_rela
@@ -811,75 +810,1386 @@ static reloc_howto_type elf_mips_howto_table_rel[] =
         true),                 /* pcrel_offset */
 };
 
-/* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link.  This
-   is a hack to make the linker think that we need 64 bit values.  */
-static reloc_howto_type elf_mips_ctor64_howto =
+/* The relocation table used for SHT_RELA sections.  */
+
+static reloc_howto_type elf_mips_howto_table_rela[] =
+{
+  /* No relocation.  */
+  HOWTO (R_MIPS_NONE,          /* type */
+        0,                     /* rightshift */
+        0,                     /* size */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_NONE",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 16 bit relocation.  */
+  HOWTO (R_MIPS_16,            /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_16",           /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 32 bit relocation.  */
+  HOWTO (R_MIPS_32,            /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_32",           /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 32 bit symbol relative relocation.  */
+  HOWTO (R_MIPS_REL32,         /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_REL32",        /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 26 bit jump address.  */
+  HOWTO (R_MIPS_26,            /* type */
+        2,                     /* rightshift */
+        4,                     /* size */
+        26,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+                               /* This needs complex overflow
+                                  detection, because the upper four
+                                  bits must match the PC + 4.  */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_26",           /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x03ffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of symbol value.  */
+  HOWTO (R_MIPS_HI16,          /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_HI16",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of symbol value.  */
+  HOWTO (R_MIPS_LO16,          /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_LO16",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* GP relative reference.  */
+  HOWTO (R_MIPS_GPREL16,       /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf32_gprel16_reloc, /* special_function */
+        "R_MIPS_GPREL16",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Reference to literal section.  */
+  HOWTO (R_MIPS_LITERAL,       /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf32_gprel16_reloc, /* special_function */
+        "R_MIPS_LITERAL",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Reference to global offset table.  */
+  HOWTO (R_MIPS_GOT16,         /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT16",        /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 16 bit PC relative reference.  Note that the ABI document has a typo
+     and claims R_MIPS_PC16 to be not rightshifted, rendering it useless.
+     We do the right thing here.  */
+  HOWTO (R_MIPS_PC16,          /* type */
+        2,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_PC16",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* 16 bit call through global offset table.  */
+  HOWTO (R_MIPS_CALL16,                /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_CALL16",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 32 bit GP relative reference.  */
+  HOWTO (R_MIPS_GPREL32,       /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        mips_elf_gprel32_reloc, /* special_function */
+        "R_MIPS_GPREL32",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  EMPTY_HOWTO (13),
+  EMPTY_HOWTO (14),
+  EMPTY_HOWTO (15),
+
+  /* A 5 bit shift field.  */
+  HOWTO (R_MIPS_SHIFT5,                /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        5,                     /* bitsize */
+        false,                 /* pc_relative */
+        6,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_SHIFT5",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x000007c0,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* A 6 bit shift field.  */
+  /* FIXME: This is not handled correctly; a special function is
+     needed to put the most significant bit in the right place.  */
+  HOWTO (R_MIPS_SHIFT6,                /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        6,                     /* bitsize */
+        false,                 /* pc_relative */
+        6,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_SHIFT6",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x000007c4,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* A 64 bit relocation.  */
   HOWTO (R_MIPS_64,            /* type */
         0,                     /* rightshift */
-        8,                     /* size */
-        32,                    /* bitsize */
+        8,                     /* size */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        mips32_64bit_reloc,    /* special_function */
+        "R_MIPS_64",           /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Displacement in the global offset table.  */
+  HOWTO (R_MIPS_GOT_DISP,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_DISP",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Displacement to page pointer in the global offset table.  */
+  HOWTO (R_MIPS_GOT_PAGE,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_PAGE",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Offset from page pointer in the global offset table.  */
+  HOWTO (R_MIPS_GOT_OFST,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_OFST",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of displacement in global offset table.  */
+  HOWTO (R_MIPS_GOT_HI16,      /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_HI16",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of displacement in global offset table.  */
+  HOWTO (R_MIPS_GOT_LO16,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_GOT_LO16",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 64 bit subtraction.  Used in the N32 ABI.  */
+  HOWTO (R_MIPS_SUB,           /* type */
+        0,                     /* rightshift */
+        8,                     /* size */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_SUB",          /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Used to cause the linker to insert and delete instructions?  */
+  EMPTY_HOWTO (R_MIPS_INSERT_A),
+  EMPTY_HOWTO (R_MIPS_INSERT_B),
+  EMPTY_HOWTO (R_MIPS_DELETE),
+
+  /* Get the higher value of a 64 bit addend.  */
+  HOWTO (R_MIPS_HIGHER,                /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_HIGHER",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Get the highest value of a 64 bit addend.  */
+  HOWTO (R_MIPS_HIGHEST,       /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_HIGHEST",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of displacement in global offset table.  */
+  HOWTO (R_MIPS_CALL_HI16,     /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_CALL_HI16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of displacement in global offset table.  */
+  HOWTO (R_MIPS_CALL_LO16,     /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_CALL_LO16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Section displacement.  */
+  HOWTO (R_MIPS_SCN_DISP,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_SCN_DISP",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  EMPTY_HOWTO (R_MIPS_REL16),
+  EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE),
+  EMPTY_HOWTO (R_MIPS_PJUMP),
+  EMPTY_HOWTO (R_MIPS_RELGOT),
+
+  /* Protected jump conversion.  This is an optimization hint.  No
+     relocation is required for correctness.  */
+  HOWTO (R_MIPS_JALR,          /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_JALR",         /* name */
+        false,                 /* partial_inplace */
+        0x00000000,            /* src_mask */
+        0x00000000,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* TLS GD/LD dynamic relocations.  */
+  HOWTO (R_MIPS_TLS_DTPMOD32,  /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_TLS_DTPMOD32", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_MIPS_TLS_DTPREL32,  /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_TLS_DTPREL32", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  EMPTY_HOWTO (R_MIPS_TLS_DTPMOD64),
+  EMPTY_HOWTO (R_MIPS_TLS_DTPREL64),
+
+  /* TLS general dynamic variable reference.  */
+  HOWTO (R_MIPS_TLS_GD,                /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_TLS_GD",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* TLS local dynamic variable reference.  */
+  HOWTO (R_MIPS_TLS_LDM,       /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_TLS_LDM",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* TLS local dynamic offset.  */
+  HOWTO (R_MIPS_TLS_DTPREL_HI16,       /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_TLS_DTPREL_HI16",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* TLS local dynamic offset.  */
+  HOWTO (R_MIPS_TLS_DTPREL_LO16,       /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_TLS_DTPREL_LO16",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* TLS thread pointer offset.  */
+  HOWTO (R_MIPS_TLS_GOTTPREL,  /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_TLS_GOTTPREL", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* TLS IE dynamic relocations.  */
+  HOWTO (R_MIPS_TLS_TPREL32,   /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_TLS_TPREL32",  /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  EMPTY_HOWTO (R_MIPS_TLS_TPREL64),
+
+  /* TLS thread pointer offset.  */
+  HOWTO (R_MIPS_TLS_TPREL_HI16,        /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_TLS_TPREL_HI16", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* TLS thread pointer offset.  */
+  HOWTO (R_MIPS_TLS_TPREL_LO16,        /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_TLS_TPREL_LO16", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 32 bit relocation with no addend.  */
+  HOWTO (R_MIPS_GLOB_DAT,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_GLOB_DAT",     /* name */
+        false,                 /* partial_inplace */
+        0x0,                   /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  EMPTY_HOWTO (52),
+  EMPTY_HOWTO (53),
+  EMPTY_HOWTO (54),
+  EMPTY_HOWTO (55),
+  EMPTY_HOWTO (56),
+  EMPTY_HOWTO (57),
+  EMPTY_HOWTO (58),
+  EMPTY_HOWTO (59),
+
+  HOWTO (R_MIPS_PC21_S2,       /* type */
+        2,                     /* rightshift */
+        4,                     /* size */
+        21,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_PC21_S2",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x001fffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  HOWTO (R_MIPS_PC26_S2,       /* type */
+        2,                     /* rightshift */
+        4,                     /* size */
+        26,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_PC26_S2",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x03ffffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  HOWTO (R_MIPS_PC18_S3,       /* type */
+        3,                     /* rightshift */
+        4,                     /* size */
+        18,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc,   /* special_function */
+        "R_MIPS_PC18_S3",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0003ffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  HOWTO (R_MIPS_PC19_S2,       /* type */
+        2,                     /* rightshift */
+        4,                     /* size */
+        19,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc,   /* special_function */
+        "R_MIPS_PC19_S2",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0007ffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  HOWTO (R_MIPS_PCHI16,                /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc,   /* special_function */
+        "R_MIPS_PCHI16",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  HOWTO (R_MIPS_PCLO16,                /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc,   /* special_function */
+        "R_MIPS_PCLO16",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+};
+
+/* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link.  This
+   is a hack to make the linker think that we need 64 bit values.  */
+static reloc_howto_type elf_mips_ctor64_howto =
+  HOWTO (R_MIPS_64,            /* type */
+        0,                     /* rightshift */
+        8,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        mips32_64bit_reloc,    /* special_function */
+        "R_MIPS_64",           /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false);                /* pcrel_offset */
+
+static reloc_howto_type elf_mips16_howto_table_rel[] =
+{
+  /* The reloc used for the mips16 jump instruction.  */
+  HOWTO (R_MIPS16_26,          /* type */
+        2,                     /* rightshift */
+        4,                     /* size */
+        26,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+                               /* This needs complex overflow
+                                  detection, because the upper four
+                                  bits must match the PC.  */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_26",         /* name */
+        true,                  /* partial_inplace */
+        0x3ffffff,             /* src_mask */
+        0x3ffffff,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* The reloc used for the mips16 gprel instruction.  */
+  HOWTO (R_MIPS16_GPREL,       /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        mips16_gprel_reloc,    /* special_function */
+        "R_MIPS16_GPREL",      /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* A MIPS16 reference to the global offset table.  */
+  HOWTO (R_MIPS16_GOT16,       /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_got16_reloc, /* special_function */
+        "R_MIPS16_GOT16",      /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* A MIPS16 call through the global offset table.  */
+  HOWTO (R_MIPS16_CALL16,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_CALL16",     /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 high 16 bits of symbol value.  */
+  HOWTO (R_MIPS16_HI16,                /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_hi16_reloc, /* special_function */
+        "R_MIPS16_HI16",       /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 low 16 bits of symbol value.  */
+  HOWTO (R_MIPS16_LO16,                /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_lo16_reloc, /* special_function */
+        "R_MIPS16_LO16",       /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS general dynamic variable reference.  */
+  HOWTO (R_MIPS16_TLS_GD,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_TLS_GD",     /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS local dynamic variable reference.  */
+  HOWTO (R_MIPS16_TLS_LDM,     /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_TLS_LDM",    /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS local dynamic offset.  */
+  HOWTO (R_MIPS16_TLS_DTPREL_HI16,     /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_hi16_reloc, /* special_function */
+        "R_MIPS16_TLS_DTPREL_HI16",    /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS local dynamic offset.  */
+  HOWTO (R_MIPS16_TLS_DTPREL_LO16,     /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_lo16_reloc, /* special_function */
+        "R_MIPS16_TLS_DTPREL_LO16",    /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS thread pointer offset.  */
+  HOWTO (R_MIPS16_TLS_GOTTPREL,        /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_TLS_GOTTPREL",       /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS thread pointer offset.  */
+  HOWTO (R_MIPS16_TLS_TPREL_HI16,      /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_hi16_reloc, /* special_function */
+        "R_MIPS16_TLS_TPREL_HI16", /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS thread pointer offset.  */
+  HOWTO (R_MIPS16_TLS_TPREL_LO16,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_lo16_reloc, /* special_function */
+        "R_MIPS16_TLS_TPREL_LO16", /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 16-bit PC-relative branch offset.  */
+  HOWTO (R_MIPS16_PC16_S1,     /* type */
+        1,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_PC16_S1",    /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+};
+
+static reloc_howto_type elf_mips16_howto_table_rela[] =
+{
+  /* The reloc used for the mips16 jump instruction.  */
+  HOWTO (R_MIPS16_26,          /* type */
+        2,                     /* rightshift */
+        4,                     /* size */
+        26,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+                               /* This needs complex overflow
+                                  detection, because the upper four
+                                  bits must match the PC.  */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_26",         /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x3ffffff,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* The reloc used for the mips16 gprel instruction.  */
+  HOWTO (R_MIPS16_GPREL,       /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        mips16_gprel_reloc,    /* special_function */
+        "R_MIPS16_GPREL",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* A MIPS16 reference to the global offset table.  */
+  HOWTO (R_MIPS16_GOT16,       /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_GOT16",      /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* A MIPS16 call through the global offset table.  */
+  HOWTO (R_MIPS16_CALL16,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_CALL16",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 high 16 bits of symbol value.  */
+  HOWTO (R_MIPS16_HI16,                /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_HI16",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 low 16 bits of symbol value.  */
+  HOWTO (R_MIPS16_LO16,                /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_LO16",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS general dynamic variable reference.  */
+  HOWTO (R_MIPS16_TLS_GD,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_TLS_GD",     /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS local dynamic variable reference.  */
+  HOWTO (R_MIPS16_TLS_LDM,     /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_TLS_LDM",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS local dynamic offset.  */
+  HOWTO (R_MIPS16_TLS_DTPREL_HI16,     /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_TLS_DTPREL_HI16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS local dynamic offset.  */
+  HOWTO (R_MIPS16_TLS_DTPREL_LO16,     /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_TLS_DTPREL_LO16",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS thread pointer offset.  */
+  HOWTO (R_MIPS16_TLS_GOTTPREL,        /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_TLS_GOTTPREL",       /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS thread pointer offset.  */
+  HOWTO (R_MIPS16_TLS_TPREL_HI16,      /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_TLS_TPREL_HI16", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 TLS thread pointer offset.  */
+  HOWTO (R_MIPS16_TLS_TPREL_LO16,      /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_TLS_TPREL_LO16", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* MIPS16 16-bit PC-relative branch offset.  */
+  HOWTO (R_MIPS16_PC16_S1,     /* type */
+        1,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS16_PC16_S1",    /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+};
+
+static reloc_howto_type elf_micromips_howto_table_rel[] =
+{
+  EMPTY_HOWTO (130),
+  EMPTY_HOWTO (131),
+  EMPTY_HOWTO (132),
+
+  /* 26 bit jump address.  */
+  HOWTO (R_MICROMIPS_26_S1,    /* type */
+        1,                     /* rightshift */
+        4,                     /* size */
+        26,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+                               /* This needs complex overflow
+                                  detection, because the upper four
+                                  bits must match the PC.  */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_26_S1",   /* name */
+        true,                  /* partial_inplace */
+        0x3ffffff,             /* src_mask */
+        0x3ffffff,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of symbol value.  */
+  HOWTO (R_MICROMIPS_HI16,     /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_hi16_reloc, /* special_function */
+        "R_MICROMIPS_HI16",    /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of symbol value.  */
+  HOWTO (R_MICROMIPS_LO16,     /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_lo16_reloc, /* special_function */
+        "R_MICROMIPS_LO16",    /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* GP relative reference.  */
+  HOWTO (R_MICROMIPS_GPREL16,  /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf32_gprel16_reloc, /* special_function */
+        "R_MICROMIPS_GPREL16", /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Reference to literal section.  */
+  HOWTO (R_MICROMIPS_LITERAL,  /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf32_gprel16_reloc, /* special_function */
+        "R_MICROMIPS_LITERAL", /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Reference to global offset table.  */
+  HOWTO (R_MICROMIPS_GOT16,    /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        mips32_64bit_reloc,    /* special_function */
-        "R_MIPS_64",           /* name */
+        _bfd_mips_elf_got16_reloc, /* special_function */
+        "R_MICROMIPS_GOT16",   /* name */
         true,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
-        0xffffffff,            /* dst_mask */
-        false);                /* pcrel_offset */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
 
-static reloc_howto_type elf_mips16_howto_table_rel[] =
-{
-  /* The reloc used for the mips16 jump instruction.  */
-  HOWTO (R_MIPS16_26,          /* type */
-        2,                     /* rightshift */
+  /* This is for microMIPS branches.  */
+  HOWTO (R_MICROMIPS_PC7_S1,   /* type */
+        1,                     /* rightshift */
+        2,                     /* size */
+        7,                     /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_PC7_S1",  /* name */
+        true,                  /* partial_inplace */
+        0x0000007f,            /* src_mask */
+        0x0000007f,            /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC10_S1,  /* type */
+        1,                     /* rightshift */
+        2,                     /* size */
+        10,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_PC10_S1", /* name */
+        true,                  /* partial_inplace */
+        0x000003ff,            /* src_mask */
+        0x000003ff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC16_S1,  /* type */
+        1,                     /* rightshift */
         4,                     /* size */
-        26,                    /* bitsize */
+        16,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_PC16_S1", /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        true),                 /* pcrel_offset */
+
+  /* 16 bit call through global offset table.  */
+  HOWTO (R_MICROMIPS_CALL16,   /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_dont, /* complain_on_overflow */
-                               /* This needs complex overflow
-                                  detection, because the upper four
-                                  bits must match the PC.  */
+        complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
-        "R_MIPS16_26",         /* name */
+        "R_MICROMIPS_CALL16",  /* name */
         true,                  /* partial_inplace */
-        0x3ffffff,             /* src_mask */
-        0x3ffffff,             /* dst_mask */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* The reloc used for the mips16 gprel instruction.  */
-  HOWTO (R_MIPS16_GPREL,       /* type */
+  EMPTY_HOWTO (143),
+  EMPTY_HOWTO (144),
+
+  /* Displacement in the global offset table.  */
+  HOWTO (R_MICROMIPS_GOT_DISP, /* type */
         0,                     /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        mips16_gprel_reloc,    /* special_function */
-        "R_MIPS16_GPREL",      /* name */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_GOT_DISP",/* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* A MIPS16 reference to the global offset table.  */
-  HOWTO (R_MIPS16_GOT16,       /* type */
+  /* Displacement to page pointer in the global offset table.  */
+  HOWTO (R_MICROMIPS_GOT_PAGE, /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_GOT_PAGE",/* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Offset from page pointer in the global offset table.  */
+  HOWTO (R_MICROMIPS_GOT_OFST, /* type */
         0,                     /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_GOT_OFST",/* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of displacement in global offset table.  */
+  HOWTO (R_MICROMIPS_GOT_HI16, /* type */
+        16,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_got16_reloc, /* special_function */
-        "R_MIPS16_GOT16",      /* name */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_GOT_HI16",/* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* A MIPS16 call through the global offset table.  */
-  HOWTO (R_MIPS16_CALL16,      /* type */
+  /* Low 16 bits of displacement in global offset table.  */
+  HOWTO (R_MICROMIPS_GOT_LO16, /* type */
         0,                     /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
@@ -887,44 +2197,141 @@ static reloc_howto_type elf_mips16_howto_table_rel[] =
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
-        "R_MIPS16_CALL16",     /* name */
+        "R_MICROMIPS_GOT_LO16",/* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* MIPS16 high 16 bits of symbol value.  */
-  HOWTO (R_MIPS16_HI16,                /* type */
+  /* 64 bit subtraction.  Used in the N32 ABI.  */
+  HOWTO (R_MICROMIPS_SUB,      /* type */
+        0,                     /* rightshift */
+        8,                     /* size */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_SUB",     /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Get the higher value of a 64 bit addend.  */
+  HOWTO (R_MICROMIPS_HIGHER,   /* type */
+        32,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_HIGHER",  /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Get the highest value of a 64 bit addend.  */
+  HOWTO (R_MICROMIPS_HIGHEST,  /* type */
+        48,                    /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_HIGHEST", /* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* High 16 bits of displacement in global offset table.  */
+  HOWTO (R_MICROMIPS_CALL_HI16,        /* type */
         16,                    /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_hi16_reloc, /* special_function */
-        "R_MIPS16_HI16",       /* name */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_CALL_HI16",/* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* MIPS16 low 16 bits of symbol value.  */
-  HOWTO (R_MIPS16_LO16,                /* type */
+  /* Low 16 bits of displacement in global offset table.  */
+  HOWTO (R_MICROMIPS_CALL_LO16,        /* type */
         0,                     /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_lo16_reloc, /* special_function */
-        "R_MIPS16_LO16",       /* name */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_CALL_LO16",/* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* MIPS16 TLS general dynamic variable reference.  */
-  HOWTO (R_MIPS16_TLS_GD,      /* type */
+  /* Section displacement.  */
+  HOWTO (R_MICROMIPS_SCN_DISP,  /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_SCN_DISP",/* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Protected jump conversion.  This is an optimization hint.  No
+     relocation is required for correctness.  */
+  HOWTO (R_MICROMIPS_JALR,     /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_JALR",    /* name */
+        false,                 /* partial_inplace */
+        0x00000000,            /* src_mask */
+        0x00000000,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* Low 16 bits of symbol value.  Note that the high 16 bits of symbol values
+     must be zero.  This is used for relaxation.  */
+  HOWTO (R_MICROMIPS_HI0_LO16, /* type */
+        0,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MICROMIPS_HI0_LO16",/* name */
+        true,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  EMPTY_HOWTO (158),
+  EMPTY_HOWTO (159),
+  EMPTY_HOWTO (160),
+  EMPTY_HOWTO (161),
+
+  /* TLS general dynamic variable reference.  */
+  HOWTO (R_MICROMIPS_TLS_GD,           /* type */
         0,                     /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
@@ -932,14 +2339,14 @@ static reloc_howto_type elf_mips16_howto_table_rel[] =
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
-        "R_MIPS16_TLS_GD",     /* name */
+        "R_MICROMIPS_TLS_GD",  /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* MIPS16 TLS local dynamic variable reference.  */
-  HOWTO (R_MIPS16_TLS_LDM,     /* type */
+  /* TLS local dynamic variable reference.  */
+  HOWTO (R_MICROMIPS_TLS_LDM,  /* type */
         0,                     /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
@@ -947,14 +2354,14 @@ static reloc_howto_type elf_mips16_howto_table_rel[] =
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
-        "R_MIPS16_TLS_LDM",    /* name */
+        "R_MICROMIPS_TLS_LDM", /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* MIPS16 TLS local dynamic offset.  */
-  HOWTO (R_MIPS16_TLS_DTPREL_HI16,     /* type */
+  /* TLS local dynamic offset.  */
+  HOWTO (R_MICROMIPS_TLS_DTPREL_HI16,  /* type */
         16,                    /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
@@ -962,14 +2369,14 @@ static reloc_howto_type elf_mips16_howto_table_rel[] =
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_hi16_reloc, /* special_function */
-        "R_MIPS16_TLS_DTPREL_HI16",    /* name */
+        "R_MICROMIPS_TLS_DTPREL_HI16", /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* MIPS16 TLS local dynamic offset.  */
-  HOWTO (R_MIPS16_TLS_DTPREL_LO16,     /* type */
+  /* TLS local dynamic offset.  */
+  HOWTO (R_MICROMIPS_TLS_DTPREL_LO16,  /* type */
         0,                     /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
@@ -977,14 +2384,14 @@ static reloc_howto_type elf_mips16_howto_table_rel[] =
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_lo16_reloc, /* special_function */
-        "R_MIPS16_TLS_DTPREL_LO16",    /* name */
+        "R_MICROMIPS_TLS_DTPREL_LO16", /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* MIPS16 TLS thread pointer offset.  */
-  HOWTO (R_MIPS16_TLS_GOTTPREL,        /* type */
+  /* TLS thread pointer offset.  */
+  HOWTO (R_MICROMIPS_TLS_GOTTPREL,     /* type */
         0,                     /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
@@ -992,14 +2399,17 @@ static reloc_howto_type elf_mips16_howto_table_rel[] =
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
-        "R_MIPS16_TLS_GOTTPREL",       /* name */
+        "R_MICROMIPS_TLS_GOTTPREL",    /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* MIPS16 TLS thread pointer offset.  */
-  HOWTO (R_MIPS16_TLS_TPREL_HI16,      /* type */
+  EMPTY_HOWTO (167),
+  EMPTY_HOWTO (168),
+
+  /* TLS thread pointer offset.  */
+  HOWTO (R_MICROMIPS_TLS_TPREL_HI16,   /* type */
         16,                    /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
@@ -1007,14 +2417,14 @@ static reloc_howto_type elf_mips16_howto_table_rel[] =
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_hi16_reloc, /* special_function */
-        "R_MIPS16_TLS_TPREL_HI16", /* name */
+        "R_MICROMIPS_TLS_TPREL_HI16", /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* MIPS16 TLS thread pointer offset.  */
-  HOWTO (R_MIPS16_TLS_TPREL_LO16,      /* type */
+  /* TLS thread pointer offset.  */
+  HOWTO (R_MICROMIPS_TLS_TPREL_LO16,   /* type */
         0,                     /* rightshift */
         4,                     /* size */
         16,                    /* bitsize */
@@ -1022,29 +2432,45 @@ static reloc_howto_type elf_mips16_howto_table_rel[] =
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_lo16_reloc, /* special_function */
-        "R_MIPS16_TLS_TPREL_LO16", /* name */
+        "R_MICROMIPS_TLS_TPREL_LO16", /* name */
         true,                  /* partial_inplace */
         0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
-  /* MIPS16 16-bit PC-relative branch offset.  */
-  HOWTO (R_MIPS16_PC16_S1,     /* type */
-        1,                     /* rightshift */
+  EMPTY_HOWTO (171),
+
+  /* GP- and PC-relative relocations.  */
+  HOWTO (R_MICROMIPS_GPREL7_S2,        /* type */
+        2,                     /* rightshift */
+        2,                     /* size */
+        7,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf32_gprel16_reloc, /* special_function */
+        "R_MICROMIPS_GPREL7_S2",       /* name */
+        true,                  /* partial_inplace */
+        0x0000007f,            /* src_mask */
+        0x0000007f,            /* dst_mask */
+        false),                /* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC23_S2,  /* type */
+        2,                     /* rightshift */
         4,                     /* size */
-        16,                    /* bitsize */
+        23,                    /* bitsize */
         true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
-        "R_MIPS16_PC16_S1",    /* name */
+        "R_MICROMIPS_PC23_S2", /* name */
         true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
-        0x0000ffff,            /* dst_mask */
+        0x007fffff,            /* src_mask */
+        0x007fffff,            /* dst_mask */
         true),                 /* pcrel_offset */
 };
 
-static reloc_howto_type elf_micromips_howto_table_rel[] =
+static reloc_howto_type elf_micromips_howto_table_rela[] =
 {
   EMPTY_HOWTO (130),
   EMPTY_HOWTO (131),
@@ -1063,8 +2489,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
                                   bits must match the PC.  */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_26_S1",   /* name */
-        true,                  /* partial_inplace */
-        0x3ffffff,             /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x3ffffff,             /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1076,10 +2502,10 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_hi16_reloc, /* special_function */
+        _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_HI16",    /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1091,10 +2517,10 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_lo16_reloc, /* special_function */
+        _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_LO16",    /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1108,8 +2534,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf32_gprel16_reloc, /* special_function */
         "R_MICROMIPS_GPREL16", /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1123,8 +2549,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf32_gprel16_reloc, /* special_function */
         "R_MICROMIPS_LITERAL", /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1136,10 +2562,10 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_got16_reloc, /* special_function */
+        _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_GOT16",   /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1153,8 +2579,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_PC7_S1",  /* name */
-        true,                  /* partial_inplace */
-        0x0000007f,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000007f,            /* dst_mask */
         true),                 /* pcrel_offset */
 
@@ -1167,8 +2593,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_PC10_S1", /* name */
-        true,                  /* partial_inplace */
-        0x000003ff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x000003ff,            /* dst_mask */
         true),                 /* pcrel_offset */
 
@@ -1181,8 +2607,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_PC16_S1", /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         true),                 /* pcrel_offset */
 
@@ -1196,8 +2622,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_CALL16",  /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1214,8 +2640,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_GOT_DISP",/* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1229,8 +2655,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_GOT_PAGE",/* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1244,8 +2670,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_GOT_OFST",/* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1259,8 +2685,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_GOT_HI16",/* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1274,8 +2700,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_GOT_LO16",/* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1289,8 +2715,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_SUB",     /* name */
-        true,                  /* partial_inplace */
-        MINUS_ONE,             /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         MINUS_ONE,             /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1304,8 +2730,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_HIGHER",  /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1319,8 +2745,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_HIGHEST", /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1334,8 +2760,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_CALL_HI16",/* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1349,8 +2775,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_CALL_LO16",/* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1363,9 +2789,9 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
-        "R_MICROMIPS_SCN_DISP",/* name */
-        true,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
+        "R_MICROMIPS_SCN_DISP", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0xffffffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1381,7 +2807,7 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_JALR",    /* name */
         false,                 /* partial_inplace */
-        0x00000000,            /* src_mask */
+        0,                     /* src_mask */
         0x00000000,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1396,8 +2822,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_dont, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_HI0_LO16",/* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1416,8 +2842,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_TLS_GD",  /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1431,8 +2857,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_TLS_LDM", /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1444,10 +2870,10 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_hi16_reloc, /* special_function */
+        _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_TLS_DTPREL_HI16", /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1459,10 +2885,10 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_lo16_reloc, /* special_function */
+        _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_TLS_DTPREL_LO16", /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1476,8 +2902,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_TLS_GOTTPREL",    /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1492,10 +2918,10 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        _bfd_mips_elf_hi16_reloc, /* special_function */
+        _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_TLS_TPREL_HI16", /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1507,10 +2933,10 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        _bfd_mips_elf_lo16_reloc, /* special_function */
+        _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_TLS_TPREL_LO16", /* name */
-        true,                  /* partial_inplace */
-        0x0000ffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000ffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1526,8 +2952,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf32_gprel16_reloc, /* special_function */
         "R_MICROMIPS_GPREL7_S2",       /* name */
-        true,                  /* partial_inplace */
-        0x0000007f,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x0000007f,            /* dst_mask */
         false),                /* pcrel_offset */
 
@@ -1540,8 +2966,8 @@ static reloc_howto_type elf_micromips_howto_table_rel[] =
         complain_overflow_signed, /* complain_on_overflow */
         _bfd_mips_elf_generic_reloc, /* special_function */
         "R_MICROMIPS_PC23_S2", /* name */
-        true,                  /* partial_inplace */
-        0x007fffff,            /* src_mask */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
         0x007fffff,            /* dst_mask */
         true),                 /* pcrel_offset */
 };
@@ -1562,6 +2988,22 @@ static reloc_howto_type elf_mips_gnu_rel16_s2 =
         0xffff,                /* dst_mask */
         true);                 /* pcrel_offset */
 
+/* 16 bit offset for pc-relative branches.  */
+static reloc_howto_type elf_mips_gnu_rela16_s2 =
+  HOWTO (R_MIPS_GNU_REL16_S2,  /* type */
+        2,                     /* rightshift */
+        4,                     /* size */
+        16,                    /* bitsize */
+        true,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_signed, /* complain_on_overflow */
+        _bfd_mips_elf_generic_reloc, /* special_function */
+        "R_MIPS_GNU_REL16_S2", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0x0000ffff,            /* dst_mask */
+        true);                 /* pcrel_offset */
+
 /* 32 bit pc-relative.  This was a GNU extension used by embedded-PIC.
    It was co-opted by mips-linux for exception-handling data.  GCC stopped
    using it in May, 2004, then started using it again for compact unwind
@@ -2097,12 +3539,12 @@ static const struct elf_reloc_map micromips_reloc_map[] =
 /* Given a BFD reloc type, return a howto structure.  */
 
 static reloc_howto_type *
-bfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
+mips_elf32_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code,
+                             reloc_howto_type *howto_table,
+                             reloc_howto_type *howto16_table,
+                             reloc_howto_type *howto_micromips_table)
 {
   unsigned int i;
-  reloc_howto_type *howto_table = elf_mips_howto_table_rel;
-  reloc_howto_type *howto16_table = elf_mips16_howto_table_rel;
-  reloc_howto_type *howto_micromips_table = elf_micromips_howto_table_rel;
 
   for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map);
        i++)
@@ -2156,35 +3598,55 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code)
     }
 }
 
+/* Given a BFD reloc type, return a howto structure; REL wrapper.  */
+
+static reloc_howto_type *
+mips_elf32_reloc_type_lookup_rel (bfd *abfd, bfd_reloc_code_real_type code)
+{
+  return mips_elf32_reloc_type_lookup (abfd, code,
+                                      elf_mips_howto_table_rel,
+                                      elf_mips16_howto_table_rel,
+                                      elf_micromips_howto_table_rel);
+}
+
+/* Given a BFD reloc type, return a howto structure; RELA wrapper.  */
+
+static reloc_howto_type *
+mips_elf32_reloc_type_lookup_rela (bfd *abfd, bfd_reloc_code_real_type code)
+{
+  return mips_elf32_reloc_type_lookup (abfd, code,
+                                      elf_mips_howto_table_rela,
+                                      elf_mips16_howto_table_rela,
+                                      elf_micromips_howto_table_rela);
+}
+
+/* Given an ELF reloc name, return a howto structure.  */
+
 static reloc_howto_type *
-bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
-                                const char *r_name)
+mips_elf32_reloc_name_lookup (const char *r_name,
+                             reloc_howto_type *howto_table,
+                             size_t howto_table_size,
+                             reloc_howto_type *howto16_table,
+                             size_t howto16_table_size,
+                             reloc_howto_type *howto_micromips_table,
+                             size_t howto_micromips_table_size)
 {
   unsigned int i;
 
-  for (i = 0;
-       i < (sizeof (elf_mips_howto_table_rel)
-           / sizeof (elf_mips_howto_table_rel[0]));
-       i++)
-    if (elf_mips_howto_table_rel[i].name != NULL
-       && strcasecmp (elf_mips_howto_table_rel[i].name, r_name) == 0)
-      return &elf_mips_howto_table_rel[i];
+  for (i = 0; i < howto_table_size; i++)
+    if (howto_table[i].name != NULL
+       && strcasecmp (howto_table[i].name, r_name) == 0)
+      return &howto_table[i];
 
-  for (i = 0;
-       i < (sizeof (elf_mips16_howto_table_rel)
-           / sizeof (elf_mips16_howto_table_rel[0]));
-       i++)
-    if (elf_mips16_howto_table_rel[i].name != NULL
-       && strcasecmp (elf_mips16_howto_table_rel[i].name, r_name) == 0)
-      return &elf_mips16_howto_table_rel[i];
+  for (i = 0; i < howto16_table_size; i++)
+    if (howto16_table[i].name != NULL
+       && strcasecmp (howto16_table[i].name, r_name) == 0)
+      return &howto16_table[i];
 
-  for (i = 0;
-       i < (sizeof (elf_micromips_howto_table_rel)
-           / sizeof (elf_micromips_howto_table_rel[0]));
-       i++)
-    if (elf_micromips_howto_table_rel[i].name != NULL
-       && strcasecmp (elf_micromips_howto_table_rel[i].name, r_name) == 0)
-      return &elf_micromips_howto_table_rel[i];
+  for (i = 0; i < howto_micromips_table_size; i++)
+    if (howto_micromips_table[i].name != NULL
+       && strcasecmp (howto_micromips_table[i].name, r_name) == 0)
+      return &howto_micromips_table[i];
 
   if (strcasecmp (elf_mips_gnu_pcrel32.name, r_name) == 0)
     return &elf_mips_gnu_pcrel32;
@@ -2204,12 +3666,42 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return NULL;
 }
 
-/* Given a MIPS Elf_Internal_Rel, fill in an arelent structure.  */
+/* Given an ELF reloc name, return a howto structure; REL wrapper.  */
+
+static reloc_howto_type *
+mips_elf32_reloc_name_lookup_rel (bfd *abfd ATTRIBUTE_UNUSED,
+                                 const char *r_name)
+{
+  return
+    mips_elf32_reloc_name_lookup (r_name,
+                                 elf_mips_howto_table_rel,
+                                 ARRAY_SIZE (elf_mips_howto_table_rel),
+                                 elf_mips16_howto_table_rel,
+                                 ARRAY_SIZE (elf_mips16_howto_table_rel),
+                                 elf_micromips_howto_table_rel,
+                                 ARRAY_SIZE (elf_micromips_howto_table_rel));
+}
+
+/* Given an ELF reloc name, return a howto structure; RELA wrapper.  */
+
+static reloc_howto_type *
+mips_elf32_reloc_name_lookup_rela (bfd *abfd ATTRIBUTE_UNUSED,
+                                  const char *r_name)
+{
+  return
+    mips_elf32_reloc_name_lookup (r_name,
+                                 elf_mips_howto_table_rela,
+                                 ARRAY_SIZE (elf_mips_howto_table_rela),
+                                 elf_mips16_howto_table_rela,
+                                 ARRAY_SIZE (elf_mips16_howto_table_rela),
+                                 elf_micromips_howto_table_rela,
+                                 ARRAY_SIZE (elf_micromips_howto_table_rela));
+}
+
+/* Given an ELF reloc type, return a howto structure.  */
 
 static reloc_howto_type *
-mips_elf32_rtype_to_howto (bfd *abfd,
-                          unsigned int r_type,
-                          bool rela_p ATTRIBUTE_UNUSED)
+mips_elf32_rtype_to_howto (bfd *abfd, unsigned int r_type, bool rela_p)
 {
   reloc_howto_type *howto = NULL;
 
@@ -2220,7 +3712,7 @@ mips_elf32_rtype_to_howto (bfd *abfd,
     case R_MIPS_GNU_VTENTRY:
       return &elf_mips_gnu_vtentry_howto;
     case R_MIPS_GNU_REL16_S2:
-      return &elf_mips_gnu_rel16_s2;
+      return rela_p ? &elf_mips_gnu_rela16_s2 : &elf_mips_gnu_rel16_s2;
     case R_MIPS_PC32:
       return &elf_mips_gnu_pcrel32;
     case R_MIPS_COPY:
@@ -2231,11 +3723,17 @@ mips_elf32_rtype_to_howto (bfd *abfd,
       return &elf_mips_eh_howto;
     default:
       if (r_type >= R_MICROMIPS_min && r_type < R_MICROMIPS_max)
-       howto = &elf_micromips_howto_table_rel[r_type - R_MICROMIPS_min];
+       howto = (rela_p
+                ? &elf_micromips_howto_table_rela[r_type - R_MICROMIPS_min]
+                : &elf_micromips_howto_table_rel[r_type - R_MICROMIPS_min]);
       if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max)
-       howto = &elf_mips16_howto_table_rel[r_type - R_MIPS16_min];
+       howto = (rela_p
+                ? &elf_mips16_howto_table_rela[r_type - R_MIPS16_min]
+                : &elf_mips16_howto_table_rel[r_type - R_MIPS16_min]);
       if (r_type < R_MIPS_max)
-       howto = &elf_mips_howto_table_rel[r_type];
+       howto = (rela_p
+                ? &elf_mips_howto_table_rela[r_type]
+                : &elf_mips_howto_table_rel[r_type]);
       if (howto != NULL && howto->name != NULL)
        return howto;
 
@@ -2246,15 +3744,16 @@ mips_elf32_rtype_to_howto (bfd *abfd,
     }
 }
 
-/* Given a MIPS Elf_Internal_Rel, fill in an arelent structure.  */
+/* Given a MIPS Elf_Internal_Rela, fill in an arelent structure.  */
 
 static bool
-mips_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
+mips_info_to_howto (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst,
+                   bool rela_p)
 {
   unsigned int r_type;
 
   r_type = ELF32_R_TYPE (dst->r_info);
-  cache_ptr->howto = mips_elf32_rtype_to_howto (abfd, r_type, false);
+  cache_ptr->howto = mips_elf32_rtype_to_howto (abfd, r_type, rela_p);
 
   if (cache_ptr->howto == NULL)
     return false;
@@ -2270,15 +3769,22 @@ mips_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
   return true;
 }
 
-/* Given a MIPS Elf_Internal_Rela, fill in an arelent structure.  */
+/* Given a MIPS Elf_Internal_Rela, fill in an arelent structure;
+   REL wrapper.  */
 
 static bool
-mips_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
+mips_info_to_howto_rel (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
 {
-  return mips_info_to_howto_rel (abfd, cache_ptr, dst);
+  return mips_info_to_howto (abfd, cache_ptr, dst, false);
+}
 
-  /* If we ever need to do any extra processing with dst->r_addend
-     (the field omitted in an Elf_Internal_Rel) we can do it here.  */
+/* Given a MIPS Elf_Internal_Rela, fill in an arelent structure;
+   RELA wrapper.  */
+
+static bool
+mips_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, Elf_Internal_Rela *dst)
+{
+  return mips_info_to_howto (abfd, cache_ptr, dst, true);
 }
 \f
 /* Determine whether a symbol is global for the purposes of splitting
@@ -2578,6 +4084,8 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
 
 #define bfd_elf32_bfd_is_local_label_name \
                                        mips_elf_is_local_label_name
+#define bfd_elf32_bfd_reloc_type_lookup        mips_elf32_reloc_type_lookup_rel
+#define bfd_elf32_bfd_reloc_name_lookup        mips_elf32_reloc_name_lookup_rel
 #define bfd_elf32_bfd_is_target_special_symbol \
                                        _bfd_mips_elf_is_target_special_symbol
 #define bfd_elf32_get_synthetic_symtab _bfd_mips_elf_get_synthetic_symtab
@@ -2714,6 +4222,12 @@ mips_vxworks_final_write_processing (bfd *abfd)
 #undef elf_backend_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_symbol \
   _bfd_mips_vxworks_finish_dynamic_symbol
+#undef bfd_elf32_bfd_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_type_lookup        \
+  mips_elf32_reloc_type_lookup_rela
+#undef bfd_elf32_bfd_reloc_name_lookup
+#define bfd_elf32_bfd_reloc_name_lookup        \
+  mips_elf32_reloc_name_lookup_rela
 #undef bfd_elf32_bfd_link_hash_table_create
 #define bfd_elf32_bfd_link_hash_table_create \
   _bfd_mips_vxworks_link_hash_table_create
index 5fbfbc6c2dd645f17d69a2f5dd3400d300222853..80e7e08308aaf5cd2a85de8de454a8e1b6c49eaf 100644 (file)
@@ -10524,9 +10524,8 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       struct elf_link_hash_entry *h;
       bool rel_reloc;
 
-      rel_reloc = (NEWABI_P (input_bfd)
-                  && mips_elf_rel_relocation_p (input_bfd, input_section,
-                                                relocs, rel));
+      rel_reloc = mips_elf_rel_relocation_p (input_bfd, input_section,
+                                            relocs, rel);
       /* Find the relocation howto for this relocation.  */
       howto = MIPS_ELF_RTYPE_TO_HOWTO (input_bfd, r_type, !rel_reloc);
 
index 5f1099da96cd7383e4eeb5d79372cdf1c831ad4a..1f85b81da45cec26f3936a5a030213bc40169b6a 100644 (file)
@@ -492,7 +492,11 @@ static int mips_32bitmode = 0;
 #define HAVE_64BIT_OBJECTS (mips_abi == N64_ABI)
 
 /* True if relocations are stored in-place.  */
+#ifdef TE_VXWORKS
+#define HAVE_IN_PLACE_ADDENDS 0
+#else
 #define HAVE_IN_PLACE_ADDENDS (!HAVE_NEWABI)
+#endif
 
 /* The ABI-derived address size.  */
 #define HAVE_64BIT_ADDRESSES \
index 85820c27b5accbc1890d59adce47cf07f0de6e41..48b1fe7bf46ec40d413127bafeac5ee611181ca5 100644 (file)
@@ -573,6 +573,12 @@ if { [istarget mips*-*-vxworks*] } {
        "MIPS invalid PIC option in VxWorks PIC"
     run_list_test "option-pic-vxworks-2" "-mvxworks-pic" \
        "MIPS invalid switch to SVR4 PIC from VxWorks PIC"
+
+    run_dump_test "vxworks-mips-hilo"
+    run_dump_test "vxworks-mips16-hilo"
+    run_dump_test "vxworks-mips16e2-hilo"
+    run_dump_test "vxworks-micromips-hilo"
+    run_dump_test "vxworks-pcrel-hilo"
 } elseif { [istarget mips*-*-*] } {
     set addr32 [expr [istarget mipstx39*-*-*] || [istarget mips-*-linux*] || [istarget mipsel-*-linux*] \
                     || [istarget mipsisa32*-*-linux*]]
diff --git a/gas/testsuite/gas/mips/vxworks-micromips-hilo.d b/gas/testsuite/gas/mips/vxworks-micromips-hilo.d
new file mode 100644 (file)
index 0000000..b62134b
--- /dev/null
@@ -0,0 +1,5 @@
+#objdump: -dr
+#name: VxWorks microMIPS lui/addiu
+#as: -mabi=32 -march=mips32r2 -mmicromips
+#source: mips-hilo.s
+#dump: micromips-hilo-n32.d
diff --git a/gas/testsuite/gas/mips/vxworks-mips-hilo.d b/gas/testsuite/gas/mips/vxworks-mips-hilo.d
new file mode 100644 (file)
index 0000000..64f576a
--- /dev/null
@@ -0,0 +1,5 @@
+#objdump: -dr
+#name: VxWorks MIPS lui/addiu
+#as: -mabi=32 -march=mips32r2
+#source: mips-hilo.s
+#dump: mips-hilo-n32.d
diff --git a/gas/testsuite/gas/mips/vxworks-mips16-hilo.d b/gas/testsuite/gas/mips/vxworks-mips16-hilo.d
new file mode 100644 (file)
index 0000000..6c5f7c1
--- /dev/null
@@ -0,0 +1,5 @@
+#objdump: -dr
+#name: VxWorks MIPS16 lui/addi
+#as: -mips16 -mabi=32 -march=mips32
+#source: mips16-hilo.s
+#dump: mips16-hilo-n32.d
diff --git a/gas/testsuite/gas/mips/vxworks-mips16e2-hilo.d b/gas/testsuite/gas/mips/vxworks-mips16e2-hilo.d
new file mode 100644 (file)
index 0000000..9fc371d
--- /dev/null
@@ -0,0 +1,5 @@
+#objdump: -dr
+#name: VxWorks MIPS16e2 lui/addi
+#as: -mips16 -mabi=32 -march=mips32r2 -mmips16e2
+#source: mips-hilo.s
+#dump: mips16e2-hilo-n32.d
diff --git a/gas/testsuite/gas/mips/vxworks-pcrel-hilo.d b/gas/testsuite/gas/mips/vxworks-pcrel-hilo.d
new file mode 100644 (file)
index 0000000..368e3b7
--- /dev/null
@@ -0,0 +1,5 @@
+#readelf: -r
+#name: VxWorks MIPSr6 PCHI16/PCLO16 relocations
+#as: -mabi=32 -march=mips32r6 -mno-pdr
+#source: pcrel-hilo.s
+#dump: pcrel-hilo-n32.d
index da6bed9b4ced1d79985170c41096f17e9e62ff60..6350b2432f93794a28b4b1765fde8b344d3c5e2c 100644 (file)
@@ -47,10 +47,20 @@ if {[istarget "mips*-*-vxworks"]} {
     run_dump_test "vxworks-forced-local-1"
 
     run_dump_test "mips-hilo"
+    run_dump_test "mips-hilo-srec" \
+       [list [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
     run_dump_test "mips16-hilo"
+    run_dump_test "mips16-hilo-srec" \
+       [list [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
     run_dump_test "mips16e2-hilo"
+    run_dump_test "mips16e2-hilo-srec" \
+       [list [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
     run_dump_test "micromips-hilo"
+    run_dump_test "micromips-hilo-srec" \
+       [list [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
     run_dump_test "pcrel-hilo"
+    run_dump_test "pcrel-hilo-srec" \
+       [list [list objdump [expr { [istarget *el-*-*] ? "-EL" : "-EB" }]]]
     return
 }