[02/21] Add new relocations for microMIPSR6

Message ID 20250402121759.1962001-3-jovan.dmitrovic@htecgroup.com
State New
Headers
Series Integrate MIPS-Specific Support |

Commit Message

Jovan Dmitrovic April 2, 2025, 12:18 p.m. UTC
  From: Matthew Fortune <matthew.fortune@imgtec.com>

Enabling support for advanced instructions and optimizations in
the microMIPS R6 architecture. New relocation types, such as PC21_S1
and PC26_S1, enhance memory management and branch efficiency for
PC-relative operations. These additions ensure proper functionality
of tools like linkers and assemblers with microMIPS R6 binaries.

Cherry-picked fe62e35
from https://github.com/MIPS/binutils-gdb

Signed-off-by: Matthew Fortune <matthew.fortune@mips.com>
Signed-off-by: Faraz Shahbazker <fshahbazker@wavecomp.com>
Signed-off-by: Milica Matic <milica.matic@htecgroup.com>

bfd/
  * bfd-in2.h (enum bfd_reloc_code_real): Add
  BFD_RELOC_MICROMIPS_21_PCREL_S1, BFD_RELOC_MICROMIPS_26_PCREL_S1,
  BFD_RELOC_MICROMIPS_18_PCREL_S3, BFD_RELOC_MICROMIPS_19_PCREL_S2,
  BFD_RELOC_MICROMIPS_HI16_S_PCREL, BFD_RELOC_MICROMIPS_LO16_PCREL.
  * libbfd.h (bfd_reloc_code_real_names): Add strings for the above.
  * reloc.c (DOCDD): Document the above.
  * elf32-mips.c (elf_micromips_howto_table_rel): Define HOWTO
  entries for the above.
  (micromips_reloc_map): Create mappings for the above.
  * elf64-mips.c (micromips_elf64_howto_table_rel): Define HOWTO
  entries for the above.
  (micromips_elf64_howto_table_rela): Likewise.
  (micromips_reloc_map): Create mappings for the above.
  * elfn32-mips.c (elf_micromips_howto_table_rel): Define HOWTO
  entries for the above.
  (elf_micromips_howto_table_rela): Likewise.
  (micromips_reloc_map): Create mappings for the above.

elfcpp/
  * mips.h (enum): Add R_MICROMIPS_PCHI16, R_MICROMIPS_PCLO16,
  R_MICROMIPS_PC21_S1, R_MICROMIPS_PC26_S1, R_MICROMIPS_PC18_S3,
  R_MICROMIPS_PC19_S2.

include/
  * elf/mips.h (elf_mips_reloc_type): Add R_MICROMIPS_PCHI16,
  R_MICROMIPS_PCLO16, R_MICROMIPS_PC21_S1, R_MICROMIPS_PC26_S1,
  R_MICROMIPS_PC18_S3, R_MICROMIPS_PC19_S2.
---
 bfd/bfd-in2.h      |   6 ++
 bfd/elf32-mips.c   |  93 ++++++++++++++++++++++-
 bfd/elf64-mips.c   | 181 +++++++++++++++++++++++++++++++++++++++++++-
 bfd/elfn32-mips.c  | 185 +++++++++++++++++++++++++++++++++++++++++++--
 bfd/libbfd.h       |   6 ++
 bfd/reloc.c        |  12 +++
 elfcpp/mips.h      |   6 ++
 include/elf/mips.h |   8 +-
 8 files changed, 484 insertions(+), 13 deletions(-)
  

Comments

Alan Modra April 7, 2025, 3:54 a.m. UTC | #1
On Wed, Apr 02, 2025 at 12:18:41PM +0000, Jovan Dmitrovic wrote:
> +  HOWTO (R_MICROMIPS_PCHI16,	/* type */
> +	 16,			/* rightshift */
> +	 2,			/* size (0 = byte, 1 = short, 2 = long) */

At the very least the comment here is wrong.  "size" in a reloc howto
is now just the number of bytes in the field being relocated.  See
commit 57698478b753.
  

Patch

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 8cc255b8354..b403b005a17 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3664,6 +3664,10 @@  enum bfd_reloc_code_real
   BFD_RELOC_MICROMIPS_7_PCREL_S1,
   BFD_RELOC_MICROMIPS_10_PCREL_S1,
   BFD_RELOC_MICROMIPS_16_PCREL_S1,
+  BFD_RELOC_MICROMIPS_21_PCREL_S1,
+  BFD_RELOC_MICROMIPS_26_PCREL_S1,
+  BFD_RELOC_MICROMIPS_18_PCREL_S3,
+  BFD_RELOC_MICROMIPS_19_PCREL_S2,
 
   /* MIPS16 PC-relative relocation.  */
   BFD_RELOC_MIPS16_16_PCREL_S1,
@@ -3679,6 +3683,8 @@  enum bfd_reloc_code_real
   BFD_RELOC_MICROMIPS_HI16,
   BFD_RELOC_MICROMIPS_HI16_S,
   BFD_RELOC_MICROMIPS_LO16,
+  BFD_RELOC_MICROMIPS_HI16_S_PCREL,
+  BFD_RELOC_MICROMIPS_LO16_PCREL,
 
   /* MIPS ELF relocations.  */
   BFD_RELOC_MIPS_GOT16,
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index bec7a207aa8..c62428c2857 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -1401,8 +1401,34 @@  static reloc_howto_type elf_micromips_howto_table_rel[] =
 	 0x0000ffff,		/* dst_mask */
 	 false),		/* pcrel_offset */
 
-  EMPTY_HOWTO (158),
-  EMPTY_HOWTO (159),
+  HOWTO (R_MICROMIPS_PCHI16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PCHI16",	/* name */
+	 true,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PCLO16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PCLO16",	/* name */
+	 true,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
   EMPTY_HOWTO (160),
   EMPTY_HOWTO (161),
 
@@ -1544,6 +1570,63 @@  static reloc_howto_type elf_micromips_howto_table_rel[] =
 	 0x007fffff,		/* src_mask */
 	 0x007fffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
+
+
+  HOWTO (R_MICROMIPS_PC21_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MICROMIPS_PC21_S1",	/* name */
+	 true,			/* partial_inplace */
+	 0x001fffff,		/* src_mask */
+	 0x001fffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC26_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MICROMIPS_PC26_S1",	/* name */
+	 true,			/* partial_inplace */
+	 0x03ffffff,		/* src_mask */
+	 0x03ffffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PC18_S3",	/* name */
+	 true,			/* partial_inplace */
+	 0x0003ffff,		/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PC19_S2",	/* name */
+	 true,			/* partial_inplace */
+	 0x0007ffff,		/* src_mask */
+	 0x0007ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
 };
 
 /* 16 bit offset for pc-relative branches.  */
@@ -2058,12 +2141,18 @@  static const struct elf_reloc_map micromips_reloc_map[] =
   { BFD_RELOC_MICROMIPS_JMP, R_MICROMIPS_26_S1 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_HI16_S, R_MICROMIPS_HI16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_LO16, R_MICROMIPS_LO16 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_HI16_S_PCREL, R_MICROMIPS_PCHI16 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_LO16_PCREL, R_MICROMIPS_PCLO16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GPREL16, R_MICROMIPS_GPREL16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_LITERAL, R_MICROMIPS_LITERAL - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GOT16, R_MICROMIPS_GOT16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_7_PCREL_S1, R_MICROMIPS_PC7_S1 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_10_PCREL_S1, R_MICROMIPS_PC10_S1 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_16_PCREL_S1, R_MICROMIPS_PC16_S1 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_21_PCREL_S1, R_MICROMIPS_PC21_S1 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_26_PCREL_S1, R_MICROMIPS_PC26_S1 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_18_PCREL_S3, R_MICROMIPS_PC18_S3 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_19_PCREL_S2, R_MICROMIPS_PC19_S2 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_CALL16, R_MICROMIPS_CALL16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GOT_DISP, R_MICROMIPS_GOT_DISP - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GOT_PAGE, R_MICROMIPS_GOT_PAGE - R_MICROMIPS_min },
diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c
index afd7b30f134..7d72aeedf62 100644
--- a/bfd/elf64-mips.c
+++ b/bfd/elf64-mips.c
@@ -2438,8 +2438,36 @@  static reloc_howto_type micromips_elf64_howto_table_rel[] =
 	 0x0000ffff,		/* dst_mask */
 	 false),		/* pcrel_offset */
 
-  EMPTY_HOWTO (158),
-  EMPTY_HOWTO (159),
+
+  HOWTO (R_MICROMIPS_PCHI16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PCHI16",	/* name */
+	 true,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PCLO16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PCLO16",	/* name */
+	 true,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+
   EMPTY_HOWTO (160),
   EMPTY_HOWTO (161),
 
@@ -2581,6 +2609,63 @@  static reloc_howto_type micromips_elf64_howto_table_rel[] =
 	 0x007fffff,		/* src_mask */
 	 0x007fffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
+
+ HOWTO (R_MICROMIPS_PC21_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MICROMIPS_PC21_S1",	/* name */
+	 true,			/* partial_inplace */
+	 0x001fffff,		/* src_mask */
+	 0x001fffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC26_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MICROMIPS_PC26_S1",	/* name */
+	 true,			/* partial_inplace */
+	 0x03ffffff,		/* src_mask */
+	 0x03ffffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PC18_S3",	/* name */
+	 true,			/* partial_inplace */
+	 0x0003ffff,		/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PC19_S2",	/* name */
+	 true,			/* partial_inplace */
+	 0x0007ffff,		/* src_mask */
+	 0x0007ffff,		/* dst_mask */
+	 true)			/* pcrel_offset */
+
 };
 
 static reloc_howto_type micromips_elf64_howto_table_rela[] =
@@ -2940,8 +3025,34 @@  static reloc_howto_type micromips_elf64_howto_table_rela[] =
 	 0x0000ffff,		/* dst_mask */
 	 false),		/* pcrel_offset */
 
-  EMPTY_HOWTO (158),
-  EMPTY_HOWTO (159),
+ HOWTO (R_MICROMIPS_PCHI16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "_MICROMIPS_PCHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PCLO16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PCLO16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
   EMPTY_HOWTO (160),
   EMPTY_HOWTO (161),
 
@@ -3083,6 +3194,62 @@  static reloc_howto_type micromips_elf64_howto_table_rela[] =
 	 0,			/* src_mask */
 	 0x007fffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC21_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MICROMIPS_PC21_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001fffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC26_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MICROMIPS_PC26_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x03ffffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PC18_S3",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PC19_S2",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0007ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
 };
 
 /* GNU extension to record C++ vtable hierarchy */
@@ -3771,12 +3938,18 @@  static const struct elf_reloc_map micromips_reloc_map[] =
   { BFD_RELOC_MICROMIPS_JMP, R_MICROMIPS_26_S1 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_HI16_S, R_MICROMIPS_HI16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_LO16, R_MICROMIPS_LO16 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_HI16_S_PCREL, R_MICROMIPS_PCHI16 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_LO16_PCREL, R_MICROMIPS_PCLO16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GPREL16, R_MICROMIPS_GPREL16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_LITERAL, R_MICROMIPS_LITERAL - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GOT16, R_MICROMIPS_GOT16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_7_PCREL_S1, R_MICROMIPS_PC7_S1 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_10_PCREL_S1, R_MICROMIPS_PC10_S1 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_16_PCREL_S1, R_MICROMIPS_PC16_S1 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_21_PCREL_S1, R_MICROMIPS_PC21_S1 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_26_PCREL_S1, R_MICROMIPS_PC26_S1 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_18_PCREL_S3, R_MICROMIPS_PC18_S3 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_19_PCREL_S2, R_MICROMIPS_PC19_S2 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_CALL16, R_MICROMIPS_CALL16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GOT_DISP, R_MICROMIPS_GOT_DISP - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GOT_PAGE, R_MICROMIPS_GOT_PAGE - R_MICROMIPS_min },
diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c
index e137204aff7..4f55be8ff78 100644
--- a/bfd/elfn32-mips.c
+++ b/bfd/elfn32-mips.c
@@ -2418,8 +2418,35 @@  static reloc_howto_type elf_micromips_howto_table_rel[] =
 	 0x0000ffff,		/* dst_mask */
 	 false),		/* pcrel_offset */
 
-  EMPTY_HOWTO (158),
-  EMPTY_HOWTO (159),
+
+ HOWTO (R_MICROMIPS_PCHI16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PCHI16",	/* name */
+	 true,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PCLO16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PCLO16",	/* name */
+	 true,			/* partial_inplace */
+	 0x0000ffff,		/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
   EMPTY_HOWTO (160),
   EMPTY_HOWTO (161),
 
@@ -2561,6 +2588,62 @@  static reloc_howto_type elf_micromips_howto_table_rel[] =
 	 0x007fffff,		/* src_mask */
 	 0x007fffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
+
+ HOWTO (R_MICROMIPS_PC21_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MICROMIPS_PC21_S1",	/* name */
+	 true,			/* partial_inplace */
+	 0x001fffff,		/* src_mask */
+	 0x001fffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC26_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MICROMIPS_PC26_S1",	/* name */
+	 true,			/* partial_inplace */
+	 0x03ffffff,		/* src_mask */
+	 0x03ffffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PC18_S3",	/* name */
+	 true,			/* partial_inplace */
+	 0x0003ffff,		/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PC19_S2",	/* name */
+	 true,			/* partial_inplace */
+	 0x0007ffff,		/* src_mask */
+	 0x0007ffff,		/* dst_mask */
+	 true)			/* pcrel_offset */
 };
 
 static reloc_howto_type elf_micromips_howto_table_rela[] =
@@ -2920,8 +3003,35 @@  static reloc_howto_type elf_micromips_howto_table_rela[] =
 	 0x0000ffff,		/* dst_mask */
 	 false),		/* pcrel_offset */
 
-  EMPTY_HOWTO (158),
-  EMPTY_HOWTO (159),
+
+ HOWTO (R_MICROMIPS_PCHI16,	/* type */
+	 16,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PCHI16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PCLO16,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PCLO16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
   EMPTY_HOWTO (160),
   EMPTY_HOWTO (161),
 
@@ -3063,6 +3173,63 @@  static reloc_howto_type elf_micromips_howto_table_rela[] =
 	 0,			/* src_mask */
 	 0x007fffff,		/* dst_mask */
 	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC21_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 21,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MICROMIPS_PC21_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001fffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC26_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 26,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc, /* special_function */
+	 "R_MICROMIPS_PC26_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x03ffffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PC18_S3",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_MICROMIPS_PC19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_mips_elf_generic_reloc,   /* special_function */
+	 "R_MICROMIPS_PC19_S2",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0007ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+	 
 };
 
 /* GNU extension to record C++ vtable hierarchy */
@@ -3195,7 +3362,7 @@  static reloc_howto_type elf_mips_eh_howto =
 	 false);		/* pcrel_offset */
 
 
-/* Set the GP value for OUTPUT_BFD.  Returns FALSE if this is a
+/* Set the GP value for OUTPUT_BFD.  Returns false if this is a
    dangerous relocation.  */
 
 static bool
@@ -3605,12 +3772,18 @@  static const struct elf_reloc_map micromips_reloc_map[] =
   { BFD_RELOC_MICROMIPS_JMP, R_MICROMIPS_26_S1 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_HI16_S, R_MICROMIPS_HI16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_LO16, R_MICROMIPS_LO16 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_HI16_S_PCREL, R_MICROMIPS_PCHI16 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_LO16_PCREL, R_MICROMIPS_PCLO16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GPREL16, R_MICROMIPS_GPREL16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_LITERAL, R_MICROMIPS_LITERAL - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GOT16, R_MICROMIPS_GOT16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_7_PCREL_S1, R_MICROMIPS_PC7_S1 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_10_PCREL_S1, R_MICROMIPS_PC10_S1 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_16_PCREL_S1, R_MICROMIPS_PC16_S1 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_21_PCREL_S1, R_MICROMIPS_PC21_S1 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_26_PCREL_S1, R_MICROMIPS_PC26_S1 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_18_PCREL_S3, R_MICROMIPS_PC18_S3 - R_MICROMIPS_min },
+  { BFD_RELOC_MICROMIPS_19_PCREL_S2, R_MICROMIPS_PC19_S2 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_CALL16, R_MICROMIPS_CALL16 - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GOT_DISP, R_MICROMIPS_GOT_DISP - R_MICROMIPS_min },
   { BFD_RELOC_MICROMIPS_GOT_PAGE, R_MICROMIPS_GOT_PAGE - R_MICROMIPS_min },
@@ -3858,7 +4031,7 @@  mips_elf_sym_is_global (bfd *abfd ATTRIBUTE_UNUSED, asymbol *sym)
 	    || bfd_is_com_section (bfd_asymbol_section (sym)));
 }
 
-/* Likewise, return TRUE if the symbol table split overall must be
+/* Likewise, return true if the symbol table split overall must be
    between section symbols and all other symbols.  */
 static bool
 mips_elf_n32_elfsym_local_is_section (bfd *abfd)
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 7d7ae1eaec9..a2d4ce2602c 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1314,6 +1314,10 @@  static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_MICROMIPS_7_PCREL_S1",
   "BFD_RELOC_MICROMIPS_10_PCREL_S1",
   "BFD_RELOC_MICROMIPS_16_PCREL_S1",
+  "BFD_RELOC_MICROMIPS_21_PCREL_S1",
+  "BFD_RELOC_MICROMIPS_26_PCREL_S1",
+  "BFD_RELOC_MICROMIPS_18_PCREL_S3",
+  "BFD_RELOC_MICROMIPS_19_PCREL_S2",
   "BFD_RELOC_MIPS16_16_PCREL_S1",
   "BFD_RELOC_MIPS_21_PCREL_S2",
   "BFD_RELOC_MIPS_26_PCREL_S2",
@@ -1323,6 +1327,8 @@  static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_MICROMIPS_HI16",
   "BFD_RELOC_MICROMIPS_HI16_S",
   "BFD_RELOC_MICROMIPS_LO16",
+  "BFD_RELOC_MICROMIPS_HI16_S_PCREL",
+  "BFD_RELOC_MICROMIPS_LO16_PCREL",
   "BFD_RELOC_MIPS_GOT16",
   "BFD_RELOC_MICROMIPS_GOT16",
   "BFD_RELOC_MIPS_CALL16",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index f60776299c8..437a77882c0 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2024,6 +2024,14 @@  ENUMX
   BFD_RELOC_MICROMIPS_10_PCREL_S1
 ENUMX
   BFD_RELOC_MICROMIPS_16_PCREL_S1
+ENUMX
+  BFD_RELOC_MICROMIPS_21_PCREL_S1
+ENUMX
+  BFD_RELOC_MICROMIPS_26_PCREL_S1
+ENUMX
+  BFD_RELOC_MICROMIPS_18_PCREL_S3
+ENUMX
+  BFD_RELOC_MICROMIPS_19_PCREL_S2
 ENUMDOC
   microMIPS PC-relative relocations.
 
@@ -2051,6 +2059,10 @@  ENUMX
   BFD_RELOC_MICROMIPS_HI16_S
 ENUMX
   BFD_RELOC_MICROMIPS_LO16
+ENUMX
+  BFD_RELOC_MICROMIPS_HI16_S_PCREL
+ENUMX
+  BFD_RELOC_MICROMIPS_LO16_PCREL
 ENUMDOC
   microMIPS versions of generic BFD relocs.
 
diff --git a/elfcpp/mips.h b/elfcpp/mips.h
index e8a8e2458e9..3539d1781b6 100644
--- a/elfcpp/mips.h
+++ b/elfcpp/mips.h
@@ -146,6 +146,8 @@  enum
   R_MICROMIPS_SCN_DISP = 155,
   R_MICROMIPS_JALR = 156,
   R_MICROMIPS_HI0_LO16 = 157,
+  R_MICROMIPS_PCHI16 = 158,
+  R_MICROMIPS_PCLO16 = 159,
   // TLS relocations.
   R_MICROMIPS_TLS_GD = 162,
   R_MICROMIPS_TLS_LDM = 163,
@@ -157,6 +159,10 @@  enum
   // microMIPS GP- and PC-relative relocations.
   R_MICROMIPS_GPREL7_S2 = 172,
   R_MICROMIPS_PC23_S2 = 173,
+  R_MICROMIPS_PC21_S1 = 174,
+  R_MICROMIPS_PC26_S1 = 175,
+  R_MICROMIPS_PC18_S3 = 176,
+  R_MICROMIPS_PC19_S2 = 177,
 
   // 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
diff --git a/include/elf/mips.h b/include/elf/mips.h
index fb3357666ec..2d390056374 100644
--- a/include/elf/mips.h
+++ b/include/elf/mips.h
@@ -148,6 +148,8 @@  START_RELOC_NUMBERS (elf_mips_reloc_type)
   RELOC_NUMBER (R_MICROMIPS_SCN_DISP, 155)
   RELOC_NUMBER (R_MICROMIPS_JALR, 156)
   RELOC_NUMBER (R_MICROMIPS_HI0_LO16, 157)
+  RELOC_NUMBER (R_MICROMIPS_PCHI16, 158)
+  RELOC_NUMBER (R_MICROMIPS_PCLO16, 159)
   /* TLS relocations.  */
   RELOC_NUMBER (R_MICROMIPS_TLS_GD, 162)
   RELOC_NUMBER (R_MICROMIPS_TLS_LDM, 163)
@@ -159,7 +161,11 @@  START_RELOC_NUMBERS (elf_mips_reloc_type)
   /* microMIPS GP- and PC-relative relocations. */
   RELOC_NUMBER (R_MICROMIPS_GPREL7_S2, 172)
   RELOC_NUMBER (R_MICROMIPS_PC23_S2, 173)
-  FAKE_RELOC (R_MICROMIPS_max, 174)
+  RELOC_NUMBER (R_MICROMIPS_PC21_S1, 174)
+  RELOC_NUMBER (R_MICROMIPS_PC26_S1, 175)
+  RELOC_NUMBER (R_MICROMIPS_PC18_S3, 176)
+  RELOC_NUMBER (R_MICROMIPS_PC19_S2, 177)
+  FAKE_RELOC (R_MICROMIPS_max, 178)
 
   /* 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