[v6,1/3] BFD changes for nanoMIPS support

Message ID 20230510141829.2748105-2-aleksandar.rikalo@syrmia.com
State Accepted
Headers
Series Add support for nanoMIPS architecture |

Checks

Context Check Description
snail/binutils-gdb-check success Github commit url

Commit Message

Aleksandar Rikalo May 10, 2023, 2:18 p.m. UTC
  Add a subset of the functionality required for GDB.

Co-Authored-By: Jaydeep Patil <jaydeep.patil@imgtec.com>
Co-Authored-By: Matthew Fortune <matthew.fortune@imgtec.com>
Co-Authored-By: Maciej W. Rozycki <macro@mips.com>
Co-Authored-By: Stefan Markovic <stefan.markovic@mips.com>
Co-Authored-By: Sara Graovac <sara.graovac@syrmia.com>
Co-Authored-By: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
---
 bfd/Makefile.am        |   19 +
 bfd/Makefile.in        |   22 +
 bfd/archures.c         |    5 +
 bfd/bfd-in2.h          |   74 +++
 bfd/config.bfd         |    6 +
 bfd/configure          |    4 +
 bfd/configure.ac       |    4 +
 bfd/cpu-nanomips.c     |   61 ++
 bfd/elf-bfd.h          |    1 +
 bfd/elfnn-nanomips.c   | 1423 ++++++++++++++++++++++++++++++++++++++++
 bfd/elfxx-mips.h       |    5 +
 bfd/elfxx-nanomips.c   |  794 ++++++++++++++++++++++
 bfd/elfxx-nanomips.h   |   54 ++
 bfd/libbfd.h           |   69 ++
 bfd/reloc.c            |  140 ++++
 bfd/targets.c          |   11 +
 binutils/readelf.c     |    2 +-
 include/elf/common.h   |    2 +-
 include/elf/nanomips.h |  262 ++++++++
 19 files changed, 2956 insertions(+), 2 deletions(-)
 create mode 100644 bfd/cpu-nanomips.c
 create mode 100644 bfd/elfnn-nanomips.c
 create mode 100644 bfd/elfxx-nanomips.c
 create mode 100644 bfd/elfxx-nanomips.h
 create mode 100644 include/elf/nanomips.h
  

Comments

Hans-Peter Nilsson May 11, 2023, 12:42 a.m. UTC | #1
On Wed, 10 May 2023, Aleksandar Rikalo wrote:
> Add a subset of the functionality required for GDB.
> 
> Co-Authored-By: Jaydeep Patil <jaydeep.patil@imgtec.com>
> Co-Authored-By: Matthew Fortune <matthew.fortune@imgtec.com>
> Co-Authored-By: Maciej W. Rozycki <macro@mips.com>
> Co-Authored-By: Stefan Markovic <stefan.markovic@mips.com>
> Co-Authored-By: Sara Graovac <sara.graovac@syrmia.com>
> Co-Authored-By: Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>

Random spotting: I see a "Written by ..." note at the top of 
several files with a name not in the above co-authored-by list.
If the person quit, me thinks attribution in the list is still 
in order.

brgds, H-P
  
Aleksandar Rikalo May 12, 2023, 5:01 p.m. UTC | #2
> Random spotting: I see a "Written by ..." note at the top of
> several files with a name not in the above co-authored-by list.
> If the person quit, me thinks attribution in the list is still
> in order.

> brgds, H-P

Will be fixed. Thank You for noticing that.

--Aleksandar
  
Maciej W. Rozycki May 19, 2023, 10:25 p.m. UTC | #3
On Fri, 12 May 2023, Aleksandar Rikalo wrote:

> > Random spotting: I see a "Written by ..." note at the top of
> > several files with a name not in the above co-authored-by list.
> > If the person quit, me thinks attribution in the list is still
> > in order.
> 
> Will be fixed. Thank You for noticing that.

 Right, Faraz was the big contributor to this port, and may well deserve 
to be named the author of the changes in this series (via a `From:' tag).

  Maciej
  

Patch

diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index 5c5fdefd3b8..8f452f856f7 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -142,6 +142,7 @@  ALL_MACHINES = \
 	cpu-moxie.lo \
 	cpu-msp430.lo \
 	cpu-mt.lo \
+	cpu-nanomips.lo \
 	cpu-nds32.lo \
 	cpu-nfp.lo \
 	cpu-nios2.lo \
@@ -547,6 +548,7 @@  BFD64_BACKENDS = \
 	coff64-rs6000.lo \
 	elf32-ia64.lo \
 	elf32-mips.lo \
+	elf32-nanomips.lo \
 	elf32-score.lo \
 	elf32-score7.lo \
 	elf64-alpha.lo \
@@ -564,6 +566,8 @@  BFD64_BACKENDS = \
 	elfxx-mips.lo \
 	elf64-mmix.lo \
 	elf64-nfp.lo \
+	elf64-nanomips.lo \
+	elfxx-nanomips.lo \
 	elf64-ppc.lo \
 	elf32-riscv.lo \
 	elf64-riscv.lo \
@@ -607,6 +611,7 @@  BFD64_BACKENDS_CFILES = \
 	elf64-mips.c \
 	elf64-mmix.c \
 	elf64-nfp.c \
+	elf64-nanomips.c \
 	elf64-ppc.c \
 	elf64-s390.c \
 	elf64-sparc.c \
@@ -620,6 +625,7 @@  BFD64_BACKENDS_CFILES = \
 	elfxx-ia64.c \
 	elfxx-loongarch.c \
 	elfxx-mips.c \
+	elfxx-nanomips.c \
 	elfxx-riscv.c \
 	mach-o-aarch64.c \
 	mach-o-x86-64.c \
@@ -684,6 +690,7 @@  BUILD_CFILES = \
 	elf32-ia64.c elf64-ia64.c \
 	elf32-loongarch.c elf64-loongarch.c \
 	elf32-riscv.c elf64-riscv.c \
+	elf32-nanomips.c elf64-nanomips.c \
 	peigen.c pepigen.c pex64igen.c pe-aarch64igen.c pe-loongarch64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
@@ -886,6 +893,18 @@  pe-loongarch64igen.c: peXXigen.c
 	$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
 	$(AM_V_GEN)$(SED) -e s/XX/peLoongArch64/g < $< >> $@
 
+elf32-nanomips.c : elfnn-nanomips.c
+	rm -f elf32-nanomips.c
+	echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf32-nanomips.new
+	sed -e s/NN/32/g < $(srcdir)/elfnn-nanomips.c >> elf32-nanomips.new
+	mv -f elf32-nanomips.new elf32-nanomips.c
+
+elf64-nanomips.c : elfnn-nanomips.c
+	rm -f elf64-nanomips.c
+	echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf64-nanomips.new
+	sed -e s/NN/64/g < $(srcdir)/elfnn-nanomips.c >> elf64-nanomips.new
+	mv -f elf64-nanomips.new elf64-nanomips.c
+
 host-aout.lo: Makefile
 
 # The following program can be used to generate a simple config file
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index 4edfedee924..64ff01733fd 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -597,6 +597,7 @@  ALL_MACHINES = \
 	cpu-moxie.lo \
 	cpu-msp430.lo \
 	cpu-mt.lo \
+	cpu-nanomips.lo \
 	cpu-nds32.lo \
 	cpu-nfp.lo \
 	cpu-nios2.lo \
@@ -1004,6 +1005,7 @@  BFD64_BACKENDS = \
 	coff64-rs6000.lo \
 	elf32-ia64.lo \
 	elf32-mips.lo \
+	elf32-nanomips.lo \
 	elf32-score.lo \
 	elf32-score7.lo \
 	elf64-alpha.lo \
@@ -1021,6 +1023,8 @@  BFD64_BACKENDS = \
 	elfxx-mips.lo \
 	elf64-mmix.lo \
 	elf64-nfp.lo \
+	elf64-nanomips.lo \
+	elfxx-nanomips.lo \
 	elf64-ppc.lo \
 	elf32-riscv.lo \
 	elf64-riscv.lo \
@@ -1064,6 +1068,7 @@  BFD64_BACKENDS_CFILES = \
 	elf64-mips.c \
 	elf64-mmix.c \
 	elf64-nfp.c \
+	elf64-nanomips.c \
 	elf64-ppc.c \
 	elf64-s390.c \
 	elf64-sparc.c \
@@ -1077,6 +1082,7 @@  BFD64_BACKENDS_CFILES = \
 	elfxx-ia64.c \
 	elfxx-loongarch.c \
 	elfxx-mips.c \
+	elfxx-nanomips.c \
 	elfxx-riscv.c \
 	mach-o-aarch64.c \
 	mach-o-x86-64.c \
@@ -1140,6 +1146,7 @@  BUILD_CFILES = \
 	elf32-ia64.c elf64-ia64.c \
 	elf32-loongarch.c elf64-loongarch.c \
 	elf32-riscv.c elf64-riscv.c \
+	elf32-nanomips.c elf64-nanomips.c \
 	peigen.c pepigen.c pex64igen.c pe-aarch64igen.c pe-loongarch64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
@@ -1593,6 +1600,7 @@  distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-moxie.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-msp430.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-mt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-nanomips.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-nds32.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-nios2.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-or1k.Plo@am__quote@
@@ -1633,6 +1641,7 @@  distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mips.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mmix.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-nfp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-nanomips.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ppc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-riscv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-s390.Plo@am__quote@
@@ -1646,6 +1655,7 @@  distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-ia64.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-loongarch.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-mips.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-nanomips.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-riscv.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-sparc.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-tilegx.Plo@am__quote@
@@ -2384,6 +2394,18 @@  pe-loongarch64igen.c: peXXigen.c
 	$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
 	$(AM_V_GEN)$(SED) -e s/XX/peLoongArch64/g < $< >> $@
 
+elf32-nanomips.c : elfnn-nanomips.c
+	rm -f elf32-nanomips.c
+	echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf32-nanomips.new
+	sed -e s/NN/32/g < $(srcdir)/elfnn-nanomips.c >> elf32-nanomips.new
+	mv -f elf32-nanomips.new elf32-nanomips.c
+
+elf64-nanomips.c : elfnn-nanomips.c
+	rm -f elf64-nanomips.c
+	echo "#line 1 \"$(srcdir)/elfnn-nanomips.c\"" > elf64-nanomips.new
+	sed -e s/NN/64/g < $(srcdir)/elfnn-nanomips.c >> elf64-nanomips.new
+	mv -f elf64-nanomips.new elf64-nanomips.c
+
 host-aout.lo: Makefile
 
 # The following program can be used to generate a simple config file
diff --git a/bfd/archures.c b/bfd/archures.c
index 6fe8701b412..5e5fd28e71d 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -563,6 +563,9 @@  DESCRIPTION
 .#define bfd_mach_amdgcn_gfx1030 0x036
 .#define bfd_mach_amdgcn_gfx1031 0x037
 .#define bfd_mach_amdgcn_gfx1032 0x038
+.  bfd_arch_nanomips,      {* nanoMIPS.  *}
+.#define bfd_mach_nanomipsisa32r6       32
+.#define bfd_mach_nanomipsisa64r6       64
 .  bfd_arch_last
 .  };
 */
@@ -663,6 +666,7 @@  extern const bfd_arch_info_type bfd_moxie_arch;
 extern const bfd_arch_info_type bfd_ft32_arch;
 extern const bfd_arch_info_type bfd_msp430_arch;
 extern const bfd_arch_info_type bfd_mt_arch;
+extern const bfd_arch_info_type bfd_nanomips_arch;
 extern const bfd_arch_info_type bfd_nds32_arch;
 extern const bfd_arch_info_type bfd_nfp_arch;
 extern const bfd_arch_info_type bfd_nios2_arch;
@@ -751,6 +755,7 @@  static const bfd_arch_info_type * const bfd_archures_list[] =
     &bfd_ft32_arch,
     &bfd_msp430_arch,
     &bfd_mt_arch,
+    &bfd_nanomips_arch,
     &bfd_nds32_arch,
     &bfd_nfp_arch,
     &bfd_nios2_arch,
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 7be18db20a8..98fd0bf2d8f 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1816,6 +1816,9 @@  enum bfd_architecture
 #define bfd_mach_amdgcn_gfx1030 0x036
 #define bfd_mach_amdgcn_gfx1031 0x037
 #define bfd_mach_amdgcn_gfx1032 0x038
+  bfd_arch_nanomips,      /* nanoMIPS.  */
+#define bfd_mach_nanomipsisa32r6       32
+#define bfd_mach_nanomipsisa64r6       64
   bfd_arch_last
   };
 
@@ -3663,6 +3666,77 @@  to compensate for the borrow when the low bits are added.  */
   BFD_RELOC_MIPS_JUMP_SLOT,
 
 
+/* nanoMIPS relocations  */
+  BFD_RELOC_NANOMIPS_HI20,
+  BFD_RELOC_NANOMIPS_LO12,
+  BFD_RELOC_NANOMIPS_LO4_S2,
+  BFD_RELOC_NANOMIPS_IMM16,
+  BFD_RELOC_NANOMIPS_NEG12,
+  BFD_RELOC_NANOMIPS_GPREL7_S2,
+  BFD_RELOC_NANOMIPS_GPREL18,
+  BFD_RELOC_NANOMIPS_GPREL19_S2,
+  BFD_RELOC_NANOMIPS_GPREL16_S2,
+  BFD_RELOC_NANOMIPS_GPREL18_S3,
+  BFD_RELOC_NANOMIPS_4_PCREL_S1,
+  BFD_RELOC_NANOMIPS_7_PCREL_S1,
+  BFD_RELOC_NANOMIPS_10_PCREL_S1,
+  BFD_RELOC_NANOMIPS_11_PCREL_S1,
+  BFD_RELOC_NANOMIPS_14_PCREL_S1,
+  BFD_RELOC_NANOMIPS_21_PCREL_S1,
+  BFD_RELOC_NANOMIPS_25_PCREL_S1,
+  BFD_RELOC_NANOMIPS_PCREL_HI20,
+  BFD_RELOC_NANOMIPS_GOT_CALL,
+  BFD_RELOC_NANOMIPS_GOTPC_HI20,
+  BFD_RELOC_NANOMIPS_GOTPC_I32,
+  BFD_RELOC_NANOMIPS_GOT_LO12,
+  BFD_RELOC_NANOMIPS_GOT_DISP,
+  BFD_RELOC_NANOMIPS_GOT_PAGE,
+  BFD_RELOC_NANOMIPS_GOT_OFST,
+  BFD_RELOC_NANOMIPS_I32,
+  BFD_RELOC_NANOMIPS_GPREL_HI20,
+  BFD_RELOC_NANOMIPS_GPREL_LO12,
+  BFD_RELOC_NANOMIPS_TLS_GD,
+  BFD_RELOC_NANOMIPS_TLS_GD_I32,
+  BFD_RELOC_NANOMIPS_TLS_LD,
+  BFD_RELOC_NANOMIPS_TLS_LD_I32,
+  BFD_RELOC_NANOMIPS_TLS_DTPREL12,
+  BFD_RELOC_NANOMIPS_TLS_DTPREL16,
+  BFD_RELOC_NANOMIPS_TLS_DTPREL_I32,
+  BFD_RELOC_NANOMIPS_TLS_GOTTPREL,
+  BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32,
+  BFD_RELOC_NANOMIPS_TLS_TPREL12,
+  BFD_RELOC_NANOMIPS_TLS_TPREL16,
+  BFD_RELOC_NANOMIPS_TLS_TPREL_I32,
+  BFD_RELOC_NANOMIPS_TLS_DTPMOD,
+  BFD_RELOC_NANOMIPS_TLS_DTPREL,
+  BFD_RELOC_NANOMIPS_TLS_TPREL,
+  BFD_RELOC_NANOMIPS_PC_I32,
+  BFD_RELOC_NANOMIPS_GPREL_I32,
+  BFD_RELOC_NANOMIPS_GPREL17_S1,
+  BFD_RELOC_NANOMIPS_NEG,
+  BFD_RELOC_NANOMIPS_ASHIFTR_1,
+  BFD_RELOC_NANOMIPS_UNSIGNED_8,
+  BFD_RELOC_NANOMIPS_UNSIGNED_16,
+  BFD_RELOC_NANOMIPS_SIGNED_8,
+  BFD_RELOC_NANOMIPS_SIGNED_16,
+  BFD_RELOC_NANOMIPS_EH,
+  BFD_RELOC_NANOMIPS_JUMP_SLOT,
+  BFD_RELOC_NANOMIPS_ALIGN,
+  BFD_RELOC_NANOMIPS_FILL,
+  BFD_RELOC_NANOMIPS_MAX,
+  BFD_RELOC_NANOMIPS_INSN32,
+  BFD_RELOC_NANOMIPS_INSN16,
+  BFD_RELOC_NANOMIPS_FIXED,
+  BFD_RELOC_NANOMIPS_RELAX,
+  BFD_RELOC_NANOMIPS_NORELAX,
+  BFD_RELOC_NANOMIPS_SAVERESTORE,
+  BFD_RELOC_NANOMIPS_JALR16,
+  BFD_RELOC_NANOMIPS_JALR32,
+  BFD_RELOC_NANOMIPS_COPY,
+  BFD_RELOC_NANOMIPS_SIGNED_9,
+  BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD,
+
+
 /* Moxie ELF relocations.  */
   BFD_RELOC_MOXIE_10_PCREL,
 
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 954837033c8..6f9324f89a8 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -202,6 +202,7 @@  m6812*|m68hc12*) targ_archs="bfd_m68hc12_arch bfd_m68hc11_arch bfd_m9s12x_arch b
 m68*)		 targ_archs=bfd_m68k_arch ;;
 microblaze*)	 targ_archs=bfd_microblaze_arch ;;
 mips*)		 targ_archs=bfd_mips_arch ;;
+nanomips*)	 targ_archs=bfd_nanomips_arch ;;
 nds32*)		 targ_archs=bfd_nds32_arch ;;
 nios2*)          targ_archs=bfd_nios2_arch ;;
 or1k*|or1knd*)	 targ_archs=bfd_or1k_arch ;;
@@ -1020,6 +1021,11 @@  case "${targ}" in
     targ_selvecs=msp430_elf32_ti_vec
     ;;
 
+  nanomips*-*-elf*)
+    targ_defvec=nanomips_elf32_le_vec
+    targ_selvecs="nanomips_elf32_be_vec nanomips_elf64_be_vec nanomips_elf64_le_vec"
+    ;;
+
   nds32*le-*-linux*)
     targ_defvec=nds32_elf32_linux_le_vec
     targ_selvecs=nds32_elf32_linux_be_vec
diff --git a/bfd/configure b/bfd/configure
index 41d280ef461..81cb3cfec49 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -13988,6 +13988,10 @@  do
     msp430_elf32_vec)		 tb="$tb elf32-msp430.lo elf32.lo $elf" ;;
     msp430_elf32_ti_vec)	 tb="$tb elf32-msp430.lo elf32.lo $elf" ;;
     mt_elf32_vec)		 tb="$tb elf32-mt.lo elf32.lo $elf" ;;
+    nanomips_elf32_be_vec)	 tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;;
+    nanomips_elf32_le_vec)	 tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;;
+    nanomips_elf64_be_vec)	 tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+    nanomips_elf64_le_vec)	 tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
     nds32_elf32_be_vec)		 tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
     nds32_elf32_le_vec)		 tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
     nds32_elf32_linux_be_vec)	 tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
diff --git a/bfd/configure.ac b/bfd/configure.ac
index f044616f4d9..b2c54704d48 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -555,6 +555,10 @@  do
     msp430_elf32_vec)		 tb="$tb elf32-msp430.lo elf32.lo $elf" ;;
     msp430_elf32_ti_vec)	 tb="$tb elf32-msp430.lo elf32.lo $elf" ;;
     mt_elf32_vec)		 tb="$tb elf32-mt.lo elf32.lo $elf" ;;
+    nanomips_elf32_be_vec)	 tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;;
+    nanomips_elf32_le_vec)	 tb="$tb elf32-nanomips.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo" ;;
+    nanomips_elf64_be_vec)	 tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
+    nanomips_elf64_le_vec)	 tb="$tb elf64-nanomips.lo elf64.lo elfxx-nanomips.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
     nds32_elf32_be_vec)		 tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
     nds32_elf32_le_vec)		 tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
     nds32_elf32_linux_be_vec)	 tb="$tb elf32-nds32.lo elf32.lo $elf" ;;
diff --git a/bfd/cpu-nanomips.c b/bfd/cpu-nanomips.c
new file mode 100644
index 00000000000..2cd66786cfe
--- /dev/null
+++ b/bfd/cpu-nanomips.c
@@ -0,0 +1,61 @@ 
+/* bfd back-end for nanomips support
+   Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+   Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT)     \
+  {                                                               \
+    BITS_WORD, /*  bits in a word */                              \
+    BITS_ADDR, /* bits in an address */                           \
+    8,         /* 8 bits in a byte */                             \
+    bfd_arch_nanomips,                                            \
+    NUMBER,                                                       \
+    "nanomips",                                                   \
+    PRINT,                                                        \
+    3,                                                            \
+    DEFAULT,                                                      \
+    bfd_default_compatible,                                       \
+    bfd_default_scan,                                             \
+    bfd_arch_default_fill,                                        \
+    NEXT,                                                         \
+    0 /* Maximum offset of a reloc from the start of an insn.  */ \
+  }
+
+enum
+{
+  I_nanomipsisa32r6,
+  I_nanomipsisa64r6,
+};
+
+#define NN(index) (&arch_info_struct[(index) + 1])
+
+static const bfd_arch_info_type arch_info_struct[] = {
+  N (32, 32, bfd_mach_nanomipsisa32r6, "nanomips:isa32r6", false,
+     NN (I_nanomipsisa32r6)),
+  N (64, 64, bfd_mach_nanomipsisa64r6, "nanomips:isa64r6", false,
+     0),
+};
+
+const bfd_arch_info_type bfd_nanomips_arch =
+N (32, 32, 0, "nanomips", true, &arch_info_struct[0]);
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 2a64a1e6a03..cbdc0d61758 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -554,6 +554,7 @@  enum elf_target_id
   MICROBLAZE_ELF_DATA,
   MIPS_ELF_DATA,
   MN10300_ELF_DATA,
+  NANOMIPS_ELF_DATA,
   NDS32_ELF_DATA,
   NIOS2_ELF_DATA,
   OR1K_ELF_DATA,
diff --git a/bfd/elfnn-nanomips.c b/bfd/elfnn-nanomips.c
new file mode 100644
index 00000000000..e134a51c5ee
--- /dev/null
+++ b/bfd/elfnn-nanomips.c
@@ -0,0 +1,1423 @@ 
+/* nanoMIPS-specific support for 32-bit ELF
+   Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+   Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+
+/* This file handles nanoMIPS ELF targets.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elfxx-nanomips.h"
+#include "elf/nanomips.h"
+
+#define ARCH_SIZE	NN
+
+#if ARCH_SIZE == 32
+/* Nonzero if ABFD is using the P32 ABI.  */
+#define ABI_P32_P(abfd) \
+  ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) != E_NANOMIPS_ABI_P64)
+#else /* ARCH_SIZE != 32 */
+/* Nonzero if ABFD is using the P64 ABI.  */
+#define ABI_P64_P(abfd) \
+  ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) != E_NANOMIPS_ABI_P32)
+#endif /* ARCH_SIZE == 32 */
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
+   from smaller values.  Start with zero, widen, *then* decrement.  */
+#define MINUS_ONE	(((bfd_vma)0) - 1)
+
+/* The relocation table used for SHT_RELA sections.  */
+
+static reloc_howto_type elfNN_nanomips_howto_table_rela[] = {
+  /* No relocation.  */
+  HOWTO (R_NANOMIPS_NONE,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_NONE",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* 32 bit relocation.  */
+  HOWTO (R_NANOMIPS_32,		/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_32",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* 64 bit relocation.  */
+  HOWTO (R_NANOMIPS_64, 	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_64",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 MINUS_ONE,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Symbol address negation, can be composed for label differences.  */
+  HOWTO (R_NANOMIPS_NEG,	/* type */
+	 0,			/* rightshift */
+	 4,			/* size (0 = byte, 1 = short, 2 = long) */
+	 64,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_negative_reloc, /* special_function */
+	 "R_NANOMIPS_NEG",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* A 5 bit shift field.  */
+  HOWTO (R_NANOMIPS_ASHIFTR_1,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_ASHIFTR_1", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_UNSIGNED_8, /* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 8,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_UNSIGNED_8", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xff,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_SIGNED_8,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 8,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_SIGNED_8",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xff,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_UNSIGNED_16, /* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_UNSIGNED_16", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_SIGNED_16,	/* type */
+	 0,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_SIGNED_16", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  EMPTY_HOWTO (R_NANOMIPS_RELATIVE),
+  EMPTY_HOWTO (R_NANOMIPS_GLOBAL),
+
+  /* Lazy resolver jump slot.  */
+  HOWTO (R_NANOMIPS_JUMP_SLOT,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_JUMP_SLOT", /* name */
+	 false,			/* partial_inplace */
+	 0x0,         		/* src_mask */
+	 0x0,		        /* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Reserved for IFUNC support.  */
+  EMPTY_HOWTO (R_NANOMIPS_IRELATIVE),
+
+  HOWTO (R_NANOMIPS_PC25_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 25,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_PC25_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x01ffffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_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_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_PC21_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0001ffff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_PC14_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 14,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_PC14_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x00003fff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_PC11_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 11,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_PC11_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x000007ff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_PC10_S1,	/* type */
+	 1,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 10,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_PC10_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x000003ff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* This is for nanoMIPS branches.  */
+  HOWTO (R_NANOMIPS_PC7_S1,	/* type */
+	 1,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 7,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_PC7_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000007f,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_PC4_S1,	/* type */
+	 1,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 4,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_PC4_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000000f,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* GP relative reference.  */
+  HOWTO (R_NANOMIPS_GPREL19_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 false,			/* pc_relative */
+	 2,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GPREL19_S2",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001ffffc,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* GP relative reference.  */
+  HOWTO (R_NANOMIPS_GPREL18_S3,	/* type */
+	 3,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 false,			/* pc_relative */
+	 3,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GPREL18_S3",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001ffff8,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* GP relative reference.  */
+  HOWTO (R_NANOMIPS_GPREL18,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 18,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GPREL18",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0003ffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* GP relative reference.  */
+  HOWTO (R_NANOMIPS_GPREL17_S1,	/* type */
+	 1,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 17,			/* bitsize */
+	 false,			/* pc_relative */
+	 1,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GPREL17_S1",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0001fffe,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* GP relative reference.  */
+  HOWTO (R_NANOMIPS_GPREL16_S2,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 2,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GPREL16_S2",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0003fffc,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* GP- and PC-relative relocations.  */
+  HOWTO (R_NANOMIPS_GPREL7_S2,	/* type */
+	 2,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 7,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GPREL7_S2", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000007f,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* High 20 bits of GP relative reference.  */
+  HOWTO (R_NANOMIPS_GPREL_HI20,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 20,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GPREL_HI20", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001ffffd,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_PCHI20,	/* type */
+	 12,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 20,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_PCHI20", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001ffffd,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* High 20 bits of symbol value.  */
+  HOWTO (R_NANOMIPS_HI20,	/* type */
+	 12,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 20,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_HI20",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001ffffd,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Low 12 bits of symbol value.  */
+  HOWTO (R_NANOMIPS_LO12,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_LO12",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x00000fff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* High 32 bits of 64-bit address.  */
+  HOWTO (R_NANOMIPS_GPREL_I32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GPREL_I32", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* High 32 bits of 64-bit address.  */
+  HOWTO (R_NANOMIPS_PC_I32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_PC_I32",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Refers to low 32-bits of 48-bit instruction. The 32-bit value
+     is encoded as nanoMIPS instruction stream - so it will be
+     half-word swapped on little endian targets.  */
+  HOWTO (R_NANOMIPS_I32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_I32",	/* name */
+	 false,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Displacement in the global offset table.  */
+  HOWTO (R_NANOMIPS_GOT_DISP,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 false,			/* pc_relative */
+	 2,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GOT_DISP", /* name */
+	 false,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x001ffffc,		/* dst_mask */
+	 false),		/* pcrel_offset */
+  /* High 32 bits of 64-bit address.  */
+  HOWTO (R_NANOMIPS_GOTPC_I32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GOTPC_I32", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* High 20 bits of PC-relative GOT offset.  */
+  HOWTO (R_NANOMIPS_GOTPC_HI20,	/* type */
+	 12,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 20,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GOTPC_HI20", /* name */
+	 false,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x001ffffd,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* Low 12 bits of displacement in global offset table.  */
+  HOWTO (R_NANOMIPS_GOT_LO12,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 2,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GOT_LO12", /* name */
+	 false,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x00000fff,		/* dst_mask */
+	 true),			/* pcrel_offset */
+
+  /* 19 bit call through global offset table.  */
+  HOWTO (R_NANOMIPS_GOT_CALL,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GOT_CALL",	/* name */
+	 false,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x001ffffc,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Displacement to page pointer in the global offset table.  */
+  HOWTO (R_NANOMIPS_GOT_PAGE,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GOT_PAGE", /* name */
+	 false,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x001ffffc,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Offset from page pointer in the global offset table.  */
+  HOWTO (R_NANOMIPS_GOT_OFST,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GOT_OFST", /* name */
+	 false,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x00000fff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Low 4 bits of symbol value.  */
+  HOWTO (R_NANOMIPS_LO4_S2,	/* type */
+	 2,			/* rightshift */
+	 1,			/* size (0 = byte, 1 = short, 2 = long) */
+	 4,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_LO4_S2",	/* name */
+	 false,			/* partial_inplace */
+	 0x0000000f,		/* src_mask */
+	 0x0000000f,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Reserved for 64-bit ABI, HI32 relocation.  */
+  EMPTY_HOWTO (R_NANOMIPS_RESERVED1),
+
+  /* Low 12 bits of GP-relative displacement.  */
+  HOWTO (R_NANOMIPS_GPREL_LO12,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_GPREL_LO12", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x00000fff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Section displacement.  */
+  HOWTO (R_NANOMIPS_SCN_DISP,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_SCN_DISP",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Copy relocation.  */
+  HOWTO (R_NANOMIPS_COPY,	/* type */
+	 0,			/* rightshift */
+	 0,			/* this one is variable size */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_bitfield, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_COPY",	/* name */
+	 false,			/* partial_inplace */
+	 0x0,			/* src_mask */
+	 0x0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  EMPTY_HOWTO (45),
+  EMPTY_HOWTO (46),
+  EMPTY_HOWTO (47),
+  EMPTY_HOWTO (48),
+  EMPTY_HOWTO (49),
+  EMPTY_HOWTO (50),
+  EMPTY_HOWTO (51),
+  EMPTY_HOWTO (52),
+  EMPTY_HOWTO (53),
+  EMPTY_HOWTO (54),
+  EMPTY_HOWTO (55),
+  EMPTY_HOWTO (56),
+  EMPTY_HOWTO (57),
+  EMPTY_HOWTO (58),
+  EMPTY_HOWTO (59),
+  EMPTY_HOWTO (60),
+  EMPTY_HOWTO (61),
+  EMPTY_HOWTO (62),
+  EMPTY_HOWTO (63),
+
+  /* Place-holder for code alignment.  */
+  HOWTO (R_NANOMIPS_ALIGN,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special handler.  */
+	 "R_NANOMIPS_ALIGN",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Fill value for code alignment.  */
+  HOWTO (R_NANOMIPS_FILL,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special handler.  */
+	 "R_NANOMIPS_FILL",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Maximum padding bytes for code alignment.  */
+  HOWTO (R_NANOMIPS_MAX,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special handler.  */
+	 "R_NANOMIPS_MAX",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Place-holder to enforce 32-bit instruction encoding.  */
+  HOWTO (R_NANOMIPS_INSN32,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special handler.  */
+	 "R_NANOMIPS_INSN32",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Place-holder to inhibit relaxation on one instruction.  */
+  HOWTO (R_NANOMIPS_FIXED,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special handler.  */
+	 "R_NANOMIPS_FIXED",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Marker to inhibit linker relaxation.  */
+  HOWTO (R_NANOMIPS_NORELAX,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false, 		/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special handler.  */
+	 "R_NANOMIPS_NORELAX",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Marker to enable linker relaxation.  */
+  HOWTO (R_NANOMIPS_RELAX,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special handler.  */
+	 "R_NANOMIPS_RELAX",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Place-holder for relaxation of save/restore instructions.  */
+  HOWTO (R_NANOMIPS_SAVERESTORE, /* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special handler.  */
+	 "R_NANOMIPS_SAVERESTORE", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Place-holder to enforce 16-bit instruction encoding.  */
+  HOWTO (R_NANOMIPS_INSN16,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc,	/* special handler.  */
+	 "R_NANOMIPS_INSN16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Place-holder to enforce 32-bit JALR encoding.  */
+  HOWTO (R_NANOMIPS_JALR32,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc, /* special handler.  */
+	 "R_NANOMIPS_JALR32",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Place-holder to enforce 16-bit JALR encoding.  */
+  HOWTO (R_NANOMIPS_JALR16,	/* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc, /* special handler.  */
+	 "R_NANOMIPS_JALR16",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Place-holder for compressed jump-table load instructions.  */
+  HOWTO (R_NANOMIPS_JUMPTABLE_LOAD, /* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc, /* special handler */
+	 "R_NANOMIPS_JUMPTABLE_LOAD", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* Place-holder for relaxing frame-register information.  */
+  HOWTO (R_NANOMIPS_FRAME_REG, /* type */
+	 0,			/* rightshift */
+	 0,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 bfd_elf_generic_reloc, /* special handler */
+	 "R_NANOMIPS_FRAME_REG", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false),		/* pcrel_offset */
+
+
+  EMPTY_HOWTO (77),
+  EMPTY_HOWTO (78),
+  EMPTY_HOWTO (79),
+
+  /* TLS GD/LD dynamic relocations.  */
+  HOWTO (R_NANOMIPS_TLS_DTPMOD, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_DTPMOD", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_TLS_DTPREL, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_DTPREL", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* TLS IE dynamic relocations.  */
+  HOWTO (R_NANOMIPS_TLS_TPREL, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_TPREL", /* name */
+	 false,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* TLS general dynamic variable reference.  */
+  HOWTO (R_NANOMIPS_TLS_GD,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 false,			/* pc_relative */
+	 2,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_GD",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001ffffc,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_TLS_GD_I32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_GD_I32", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* TLS local dynamic variable reference.  */
+  HOWTO (R_NANOMIPS_TLS_LD,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 false,			/* pc_relative */
+	 2,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_LD",	/* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001ffffc,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  HOWTO (R_NANOMIPS_TLS_LD_I32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_LD_I32", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* TLS local dynamic 12-bit offset.  */
+  HOWTO (R_NANOMIPS_TLS_DTPREL12, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_DTPREL12", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x00000fff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* TLS local dynamic 16-bit offset.  */
+  HOWTO (R_NANOMIPS_TLS_DTPREL16, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_DTPREL16", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* TLS local dynamic 32-bit offset.  */
+  HOWTO (R_NANOMIPS_TLS_DTPREL_I32, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_DTPREL_I32", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* TLS thread pointer 21-bit GOT offset.  */
+  HOWTO (R_NANOMIPS_TLS_GOTTPREL,	/* type */
+	 2,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 19,			/* bitsize */
+	 false,			/* pc_relative */
+	 2,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_GOTTPREL", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x001ffffc,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* TLS thread pointer 32-bit GOT offset.  */
+  HOWTO (R_NANOMIPS_TLS_GOTTPREL_PC_I32, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_GOTTPREL_PC_I32", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 true), 		/* pcrel_offset */
+
+  /* TLS thread pointer 12-bit offset.  */
+  HOWTO (R_NANOMIPS_TLS_TPREL12, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 12,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_TPREL12", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x00000fff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* TLS thread pointer 16-bit offset.  */
+  HOWTO (R_NANOMIPS_TLS_TPREL16, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 16,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_unsigned, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_TPREL16", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0x0000ffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+
+  /* TLS thread pointer 32-bit offset.  */
+  HOWTO (R_NANOMIPS_TLS_TPREL_I32, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_TLS_TPREL_I32", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 false),		/* pcrel_offset */
+};
+
+/* GNU extension to record C++ vtable hierarchy */
+static reloc_howto_type elf_nanomips_gnu_vtinherit_howto =
+  HOWTO (R_NANOMIPS_GNU_VTINHERIT, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false, 		/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 NULL,			/* special_function */
+	 "R_NANOMIPS_GNU_VTINHERIT", /* name */
+	 false, 		/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false);		/* pcrel_offset */
+
+/* GNU extension to record C++ vtable member usage */
+static reloc_howto_type elf_nanomips_gnu_vtentry_howto =
+  HOWTO (R_NANOMIPS_GNU_VTENTRY, /* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 0,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_dont, /* complain_on_overflow */
+	 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
+	 "R_NANOMIPS_GNU_VTENTRY", /* name */
+	 false,			/* partial_inplace */
+	 0,			/* src_mask */
+	 0,			/* dst_mask */
+	 false);		/* pcrel_offset */
+
+/* 32 bit pc-relative.  */
+static reloc_howto_type elf_nanomips_gnu_pcrel32 =
+  HOWTO (R_NANOMIPS_PC32,	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 true,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_PC32",	/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,		/* dst_mask */
+	 true);			/* pcrel_offset */
+
+/* Used in EH tables.  */
+static reloc_howto_type elf_nanomips_eh_howto =
+  HOWTO (R_NANOMIPS_EH, 	/* type */
+	 0,			/* rightshift */
+	 2,			/* size (0 = byte, 1 = short, 2 = long) */
+	 32,			/* bitsize */
+	 false,			/* pc_relative */
+	 0,			/* bitpos */
+	 complain_overflow_signed, /* complain_on_overflow */
+	 _bfd_nanomips_elf_generic_reloc, /* special_function */
+	 "R_NANOMIPS_EH",	/* name */
+	 true,			/* partial_inplace */
+	 0xffffffff,		/* src_mask */
+	 0xffffffff,	        /* dst_mask */
+	 false);		/* pcrel_offset */
+
+/* A mapping from BFD reloc types to nanoMIPS ELF reloc types.  */
+
+struct elf_reloc_map
+{
+  bfd_reloc_code_real_type bfd_val;
+  enum elf_nanomips_reloc_type elf_val;
+};
+
+static const struct elf_reloc_map nanomips_reloc_map[] = {
+  { BFD_RELOC_NONE, R_NANOMIPS_NONE },
+  { BFD_RELOC_32, R_NANOMIPS_32 },
+  { BFD_RELOC_64, R_NANOMIPS_64 },
+  { BFD_RELOC_NANOMIPS_NEG, R_NANOMIPS_NEG },
+  { BFD_RELOC_NANOMIPS_ASHIFTR_1, R_NANOMIPS_ASHIFTR_1 },
+  { BFD_RELOC_NANOMIPS_UNSIGNED_8, R_NANOMIPS_UNSIGNED_8 },
+  { BFD_RELOC_NANOMIPS_SIGNED_8, R_NANOMIPS_SIGNED_8 },
+  { BFD_RELOC_NANOMIPS_UNSIGNED_16, R_NANOMIPS_UNSIGNED_16 },
+  { BFD_RELOC_16, R_NANOMIPS_UNSIGNED_16 },
+  { BFD_RELOC_NANOMIPS_SIGNED_16, R_NANOMIPS_SIGNED_16 },
+  { BFD_RELOC_NANOMIPS_HI20, R_NANOMIPS_HI20 },
+  { BFD_RELOC_NANOMIPS_LO12, R_NANOMIPS_LO12 },
+  { BFD_RELOC_NANOMIPS_IMM16, R_NANOMIPS_LO12 },
+  { BFD_RELOC_NANOMIPS_25_PCREL_S1, R_NANOMIPS_PC25_S1 },
+  { BFD_RELOC_NANOMIPS_21_PCREL_S1, R_NANOMIPS_PC21_S1 },
+  { BFD_RELOC_NANOMIPS_14_PCREL_S1, R_NANOMIPS_PC14_S1 },
+  { BFD_RELOC_NANOMIPS_11_PCREL_S1, R_NANOMIPS_PC11_S1 },
+  { BFD_RELOC_NANOMIPS_10_PCREL_S1, R_NANOMIPS_PC10_S1 },
+  { BFD_RELOC_NANOMIPS_7_PCREL_S1, R_NANOMIPS_PC7_S1 },
+  { BFD_RELOC_NANOMIPS_GPREL7_S2, R_NANOMIPS_GPREL7_S2 },
+  { BFD_RELOC_NANOMIPS_GPREL18, R_NANOMIPS_GPREL18 },
+  { BFD_RELOC_NANOMIPS_GPREL19_S2, R_NANOMIPS_GPREL19_S2 },
+  { BFD_RELOC_NANOMIPS_4_PCREL_S1,R_NANOMIPS_PC4_S1 },
+  { BFD_RELOC_NANOMIPS_PCREL_HI20, R_NANOMIPS_PCHI20 },
+  { BFD_RELOC_NANOMIPS_GPREL16_S2, R_NANOMIPS_GPREL16_S2 },
+  { BFD_RELOC_NANOMIPS_GPREL18_S3, R_NANOMIPS_GPREL18_S3 },
+  { BFD_RELOC_NANOMIPS_GOT_CALL, R_NANOMIPS_GOT_CALL },
+  { BFD_RELOC_NANOMIPS_GOT_DISP, R_NANOMIPS_GOT_DISP },
+  { BFD_RELOC_NANOMIPS_GOT_PAGE, R_NANOMIPS_GOT_PAGE },
+  { BFD_RELOC_NANOMIPS_GOT_OFST, R_NANOMIPS_GOT_OFST },
+  { BFD_RELOC_NANOMIPS_GOTPC_HI20, R_NANOMIPS_GOTPC_HI20 },
+  { BFD_RELOC_NANOMIPS_GOT_LO12, R_NANOMIPS_GOT_LO12 },
+  { BFD_RELOC_NANOMIPS_GOTPC_I32, R_NANOMIPS_GOTPC_I32 },
+  { BFD_RELOC_NANOMIPS_I32, R_NANOMIPS_I32 },
+  { BFD_RELOC_NANOMIPS_GPREL_HI20, R_NANOMIPS_GPREL_HI20 },
+  { BFD_RELOC_NANOMIPS_PC_I32, R_NANOMIPS_PC_I32 },
+  { BFD_RELOC_NANOMIPS_GPREL_I32, R_NANOMIPS_GPREL_I32 },
+  { BFD_RELOC_NANOMIPS_GPREL17_S1, R_NANOMIPS_GPREL17_S1 },
+  { BFD_RELOC_NANOMIPS_GPREL_LO12, R_NANOMIPS_GPREL_LO12 },
+  { BFD_RELOC_NANOMIPS_LO4_S2, R_NANOMIPS_LO4_S2 },
+  { BFD_RELOC_NANOMIPS_COPY, R_NANOMIPS_COPY },
+
+  { BFD_RELOC_NANOMIPS_ALIGN, R_NANOMIPS_ALIGN },
+  { BFD_RELOC_NANOMIPS_FILL, R_NANOMIPS_FILL },
+  { BFD_RELOC_NANOMIPS_MAX, R_NANOMIPS_MAX },
+  { BFD_RELOC_NANOMIPS_INSN32, R_NANOMIPS_INSN32 },
+  { BFD_RELOC_NANOMIPS_INSN16, R_NANOMIPS_INSN16 },
+  { BFD_RELOC_NANOMIPS_FIXED, R_NANOMIPS_FIXED },
+  { BFD_RELOC_NANOMIPS_RELAX, R_NANOMIPS_RELAX },
+  { BFD_RELOC_NANOMIPS_NORELAX, R_NANOMIPS_NORELAX },
+  { BFD_RELOC_NANOMIPS_SAVERESTORE, R_NANOMIPS_SAVERESTORE },
+  { BFD_RELOC_NANOMIPS_JALR32, R_NANOMIPS_JALR32 },
+  { BFD_RELOC_NANOMIPS_JALR16, R_NANOMIPS_JALR16 },
+  { BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD, R_NANOMIPS_JUMPTABLE_LOAD },
+
+  { BFD_RELOC_NANOMIPS_TLS_GD, R_NANOMIPS_TLS_GD },
+  { BFD_RELOC_NANOMIPS_TLS_GD_I32, R_NANOMIPS_TLS_GD_I32 },
+  { BFD_RELOC_NANOMIPS_TLS_LD, R_NANOMIPS_TLS_LD },
+  { BFD_RELOC_NANOMIPS_TLS_LD_I32, R_NANOMIPS_TLS_LD_I32 },
+  { BFD_RELOC_NANOMIPS_TLS_DTPREL12, R_NANOMIPS_TLS_DTPREL12 },
+  { BFD_RELOC_NANOMIPS_TLS_DTPREL16, R_NANOMIPS_TLS_DTPREL16 },
+  { BFD_RELOC_NANOMIPS_TLS_DTPREL_I32, R_NANOMIPS_TLS_DTPREL_I32 },
+  { BFD_RELOC_NANOMIPS_TLS_GOTTPREL, R_NANOMIPS_TLS_GOTTPREL },
+  { BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32, R_NANOMIPS_TLS_GOTTPREL_PC_I32 },
+  { BFD_RELOC_NANOMIPS_TLS_TPREL12, R_NANOMIPS_TLS_TPREL12 },
+  { BFD_RELOC_NANOMIPS_TLS_TPREL16, R_NANOMIPS_TLS_TPREL16 },
+  { BFD_RELOC_NANOMIPS_TLS_TPREL_I32, R_NANOMIPS_TLS_TPREL_I32 },
+  { BFD_RELOC_NANOMIPS_TLS_DTPMOD, R_NANOMIPS_TLS_DTPMOD },
+  { BFD_RELOC_NANOMIPS_TLS_DTPREL, R_NANOMIPS_TLS_DTPREL },
+  { BFD_RELOC_NANOMIPS_TLS_TPREL, R_NANOMIPS_TLS_TPREL },
+};
+
+/* Given a BFD reloc type, return a howto structure.  */
+
+static reloc_howto_type *
+bfd_elfNN_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+				 bfd_reloc_code_real_type code)
+{
+  unsigned int i;
+  reloc_howto_type *howto_nanomips_table;
+
+  howto_nanomips_table = elfNN_nanomips_howto_table_rela;
+
+  for (i = 0; i < sizeof (nanomips_reloc_map) / sizeof (struct elf_reloc_map);
+       i++)
+    {
+      if (nanomips_reloc_map[i].bfd_val == code)
+	return &howto_nanomips_table[(int) nanomips_reloc_map[i].elf_val];
+    }
+
+  switch (code)
+    {
+    default:
+      bfd_set_error (bfd_error_bad_value);
+      return NULL;
+
+    case BFD_RELOC_CTOR:
+      return &howto_nanomips_table[(int) R_NANOMIPS_32];
+
+    case BFD_RELOC_VTABLE_INHERIT:
+      return &elf_nanomips_gnu_vtinherit_howto;
+    case BFD_RELOC_VTABLE_ENTRY:
+      return &elf_nanomips_gnu_vtentry_howto;
+    case BFD_RELOC_NANOMIPS_EH:
+      return &elf_nanomips_eh_howto;
+    case BFD_RELOC_32_PCREL:
+      return &elf_nanomips_gnu_pcrel32;
+    }
+}
+
+/* Map a BFD relocation to its display name.  */
+
+static reloc_howto_type *
+bfd_elfNN_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+				 const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < (sizeof (elfNN_nanomips_howto_table_rela)
+	    / sizeof (elfNN_nanomips_howto_table_rela[0])); i++)
+    if (elfNN_nanomips_howto_table_rela[i].name != NULL
+	&& strcasecmp (elfNN_nanomips_howto_table_rela[i].name, r_name) == 0)
+      return &elfNN_nanomips_howto_table_rela[i];
+
+  if (strcasecmp (elf_nanomips_gnu_vtinherit_howto.name, r_name) == 0)
+    return &elf_nanomips_gnu_vtinherit_howto;
+  if (strcasecmp (elf_nanomips_gnu_vtentry_howto.name, r_name) == 0)
+    return &elf_nanomips_gnu_vtentry_howto;
+  if (strcasecmp (elf_nanomips_eh_howto.name, r_name) == 0)
+    return &elf_nanomips_eh_howto;
+
+  return NULL;
+}
+
+/* Given a nanoMIPS Elf_Internal_Rel, fill in an arelent structure.  */
+
+static reloc_howto_type *
+nanomips_elfNN_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+			       unsigned int r_type,
+			       bool rela_p ATTRIBUTE_UNUSED)
+{
+  switch (r_type)
+    {
+    case R_NANOMIPS_GNU_VTINHERIT:
+      return &elf_nanomips_gnu_vtinherit_howto;
+    case R_NANOMIPS_GNU_VTENTRY:
+      return &elf_nanomips_gnu_vtentry_howto;
+    case R_NANOMIPS_EH:
+      return &elf_nanomips_eh_howto;
+    case R_NANOMIPS_PC32:
+      return &elf_nanomips_gnu_pcrel32;
+    default:
+      return &elfNN_nanomips_howto_table_rela[r_type];
+    }
+}
+
+/* Given a nanoMIPS Elf_Internal_Rela, fill in an arelent structure.  */
+
+static bool
+nanomips_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
+			     Elf_Internal_Rela *dst)
+{
+  const struct elf_backend_data *bed;
+  unsigned int r_type;
+
+  r_type = ELFNN_R_TYPE (dst->r_info);
+  bed = get_elf_backend_data (abfd);
+  cache_ptr->howto = bed->elf_backend_mips_rtype_to_howto (abfd, r_type, true);
+  cache_ptr->addend = dst->r_addend;
+  return true;
+}
+
+/* nanoMIPS ELF local labels start with '$'.  */
+
+static bool
+nanomips_elf_is_local_label_name (bfd *abfd, const char *name)
+{
+  if (name[0] == '$')
+    return true;
+
+  /* Fall back to the generic ELF local label syntax.  */
+  return _bfd_elf_is_local_label_name (abfd, name);
+}
+
+/* Set the right machine number for a nanoMIPS ELF file.  */
+
+static bool
+nanomips_elfNN_object_p (bfd *abfd)
+{
+  unsigned long mach;
+
+  if (!ABI_PNN_P (abfd))
+    return false;
+
+  mach = _bfd_elf_nanomips_mach (elf_elfheader (abfd)->e_flags);
+  bfd_default_set_arch_mach (abfd, bfd_arch_nanomips, mach);
+  return true;
+}
+
+#define ELF_ARCH			bfd_arch_nanomips
+#define ELF_TARGET_ID			NANOMIPS_ELF_DATA
+#define ELF_MACHINE_CODE		EM_NANOMIPS
+
+#define elf_backend_collect		true
+#define elf_backend_type_change_ok	true
+#define elf_info_to_howto		nanomips_info_to_howto_rela
+#define elf_backend_object_p		nanomips_elfNN_object_p
+#define elf_backend_section_processing	_bfd_nanomips_elf_section_processing
+#define elf_backend_section_from_shdr	_bfd_nanomips_elf_section_from_shdr
+#define elf_backend_fake_sections	_bfd_nanomips_elf_fake_sections
+#define elf_backend_final_write_processing \
+					_bfd_nanomips_elf_final_write_processing
+
+#define elf_backend_may_use_rela_p	1
+#define elf_backend_default_use_rela_p	1
+#define elf_backend_sign_extend_vma	true
+#define elf_backend_plt_readonly	1
+
+#define bfd_elfNN_bfd_get_relocated_section_contents \
+			_bfd_elf_nanomips_get_relocated_section_contents
+#define elf_backend_mips_rtype_to_howto	nanomips_elfNN_rtype_to_howto
+#define bfd_elfNN_bfd_print_private_bfd_data \
+					_bfd_nanomips_elf_print_private_bfd_data
+#define bfd_elfNN_mkobject		_bfd_nanomips_elf_mkobject
+#define bfd_elfNN_bfd_is_local_label_name \
+					nanomips_elf_is_local_label_name
+
+#define ELF_MAXPAGESIZE    0x1000
+#define ELF_COMMONPAGESIZE 0x1000
+
+/* Support for nanomipsNN target.  */
+
+#define TARGET_LITTLE_SYM               nanomips_elfNN_le_vec
+#define TARGET_LITTLE_NAME              "elfNN-littlenanomips"
+#define TARGET_BIG_SYM                  nanomips_elfNN_be_vec
+#define TARGET_BIG_NAME                 "elfNN-bignanomips"
+
+#define elfNN_bed                       elfNN_nanomips_bed
+
+/* Include the target file for this target.  */
+#include "elfNN-target.h"
diff --git a/bfd/elfxx-mips.h b/bfd/elfxx-mips.h
index 2c790ed5ed6..a24c30f5d55 100644
--- a/bfd/elfxx-mips.h
+++ b/bfd/elfxx-mips.h
@@ -65,6 +65,8 @@  extern bool _bfd_mips_elf_create_dynamic_sections
   (bfd *, struct bfd_link_info *);
 extern bool _bfd_mips_elf_check_relocs
   (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
+extern bool _bfd_mips_relax_section
+  (bfd *, asection *, struct bfd_link_info *, bool *again);
 extern bool _bfd_mips_elf_adjust_dynamic_symbol
   (struct bfd_link_info *, struct elf_link_hash_entry *);
 extern bool _bfd_mips_elf_always_size_sections
@@ -133,6 +135,8 @@  extern const char * _bfd_mips_fp_abi_string
   (int);
 extern bool _bfd_mips_elf_print_private_bfd_data
   (bfd *, void *);
+extern bool _bfd_nanomips_elf_print_private_bfd_data
+  (bfd *, void *);
 extern bool _bfd_mips_elf_discard_info
   (bfd *, struct elf_reloc_cookie *, struct bfd_link_info *);
 extern bool _bfd_mips_elf_write_section
@@ -165,6 +169,7 @@  extern bfd_vma _bfd_mips_elf_sign_extend
 extern void _bfd_mips_elf_merge_symbol_attribute
   (struct elf_link_hash_entry *, unsigned int, bool, bool);
 extern char *_bfd_mips_elf_get_target_dtag (bfd_vma);
+extern char *_bfd_nanomips_elf_get_target_dtag (bfd_vma);
 extern bool _bfd_mips_elf_ignore_undef_symbol
   (struct elf_link_hash_entry *);
 extern void _bfd_mips_elf_use_plts_and_copy_relocs
diff --git a/bfd/elfxx-nanomips.c b/bfd/elfxx-nanomips.c
new file mode 100644
index 00000000000..8405fe09c34
--- /dev/null
+++ b/bfd/elfxx-nanomips.c
@@ -0,0 +1,794 @@ 
+/* nanoMIPS-specific support for ELF
+   Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+   Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+
+/* This file handles functionality common to nanoMIPS ABIs.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elfxx-nanomips.h"
+#include "elf/nanomips.h"
+
+/* nanoMIPS ELF private object data.  */
+
+struct nanomips_elf_obj_tdata
+{
+  /* Generic ELF private object data.  */
+  struct elf_obj_tdata root;
+
+  /* Input BFD providing Tag_GNU_NANOMIPS_ABI_FP attribute for output.  */
+  bfd *abi_fp_bfd;
+
+  /* Input BFD providing Tag_GNU_NANOMIPS_ABI_MSA attribute for output.  */
+  bfd *abi_msa_bfd;
+
+  /* The abiflags for this object.  */
+  Elf_Internal_ABIFlags_v0 abiflags;
+  bool abiflags_valid;
+
+  bfd_signed_vma sdata_section[1000];
+};
+
+/* Get nanoMIPS ELF private object data from BFD's tdata.  */
+
+#define nanomips_elf_tdata(bfd) \
+  ((struct nanomips_elf_obj_tdata *) (bfd)->tdata.any)
+
+/* True if NAME is the recognized name of any SHT_NANOMIPS_ABIFLAGS section.  */
+
+#define NANOMIPS_ELF_ABIFLAGS_SECTION_NAME_P(NAME) \
+  (strcmp (NAME, ".nanoMIPS.abiflags") == 0)
+
+/* Allocate nanoMIPS ELF private object data.  */
+
+bool
+_bfd_nanomips_elf_mkobject (bfd *abfd)
+{
+  return bfd_elf_allocate_object (abfd,
+				  sizeof (struct nanomips_elf_obj_tdata),
+				  NANOMIPS_ELF_DATA);
+}
+
+/* A generic howto special_function.  This calculates and installs the
+   relocation itself, thus avoiding the oft-discussed problems in
+   bfd_perform_relocation and bfd_install_relocation.  */
+
+bfd_reloc_status_type
+_bfd_nanomips_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+				 arelent *reloc_entry, asymbol *symbol,
+				 void *data ATTRIBUTE_UNUSED,
+				 asection *input_section, bfd *output_bfd,
+				 char **error_message ATTRIBUTE_UNUSED)
+{
+  bfd_signed_vma val;
+  bfd_reloc_status_type status;
+  bool relocatable;
+
+  relocatable = (output_bfd != NULL);
+
+  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+    return bfd_reloc_outofrange;
+
+  /* Build up the field adjustment in VAL.  */
+  val = 0;
+  if (!relocatable || (symbol->flags & BSF_SECTION_SYM) != 0)
+    {
+      /* Either we're calculating the final field value or we have a
+         relocation against a section symbol.  Add in the section's
+         offset or address.  */
+      val += symbol->section->output_section->vma;
+      val += symbol->section->output_offset;
+    }
+
+  if (!relocatable)
+    {
+      /* We're calculating the final field value.  Add in the symbol's value
+         and, if pc-relative, subtract the address of the field itself.  */
+      val += symbol->value;
+      if (reloc_entry->howto->pc_relative)
+	{
+	  val -= input_section->output_section->vma;
+	  val -= input_section->output_offset;
+	  val -= reloc_entry->address;
+	}
+    }
+
+  /* VAL is now the final adjustment.  If we're keeping this relocation
+     in the output file, and if the relocation uses a separate addend,
+     we just need to add VAL to that addend.  Otherwise we need to add
+     VAL to the relocation field itself.  */
+  if (relocatable && !reloc_entry->howto->partial_inplace)
+    reloc_entry->addend += val;
+  else
+    {
+      bfd_byte *location = (bfd_byte *) data + reloc_entry->address;
+
+      /* Add in the separate addend, if any.  */
+      val += reloc_entry->addend;
+
+      /* Add VAL to the relocation field.  */
+      status = _bfd_relocate_contents (reloc_entry->howto, abfd, val,
+				       location);
+      if (status != bfd_reloc_ok)
+	return status;
+    }
+
+  if (relocatable)
+    reloc_entry->address += input_section->output_offset;
+
+  return bfd_reloc_ok;
+}
+
+/* A negation howto special_function.  */
+
+bfd_reloc_status_type
+_bfd_nanomips_elf_negative_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+				  arelent *reloc_entry, asymbol *symbol,
+				  void *data ATTRIBUTE_UNUSED,
+				  asection *input_section, bfd *output_bfd,
+				  char **error_message ATTRIBUTE_UNUSED)
+{
+  bfd_signed_vma val;
+  bool relocatable;
+
+  relocatable = (output_bfd != NULL);
+
+  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+    return bfd_reloc_outofrange;
+
+  /* Calculate the value of the symbol S.  */
+  val = symbol->section->output_section->vma;
+  val += symbol->section->output_offset;
+  val += symbol->value;
+
+  /* Add negated value to addend: (-S + A).  */
+  if (! relocatable )
+    reloc_entry->addend = -val + reloc_entry->addend;
+
+  if (relocatable)
+    reloc_entry->address += input_section->output_offset;
+
+  return bfd_reloc_ok;
+}
+
+/* Swap in an abiflags structure.  */
+
+void
+bfd_nanomips_elf_swap_abiflags_v0_in (bfd *abfd,
+				      const Elf_External_ABIFlags_v0 *ex,
+				      Elf_Internal_ABIFlags_v0 *in)
+{
+  in->version = H_GET_16 (abfd, ex->version);
+  in->isa_level = H_GET_8 (abfd, ex->isa_level);
+  in->isa_rev = H_GET_8 (abfd, ex->isa_rev);
+  in->gpr_size = H_GET_8 (abfd, ex->gpr_size);
+  in->cpr1_size = H_GET_8 (abfd, ex->cpr1_size);
+  in->cpr2_size = H_GET_8 (abfd, ex->cpr2_size);
+  in->fp_abi = H_GET_8 (abfd, ex->fp_abi);
+  in->isa_ext = H_GET_32 (abfd, ex->isa_ext);
+  in->ases = H_GET_32 (abfd, ex->ases);
+  in->flags1 = H_GET_32 (abfd, ex->flags1);
+  in->flags2 = H_GET_32 (abfd, ex->flags2);
+}
+
+/* Swap out an abiflags structure.  */
+
+void
+bfd_nanomips_elf_swap_abiflags_v0_out (bfd *abfd,
+				       const Elf_Internal_ABIFlags_v0 *in,
+				       Elf_External_ABIFlags_v0 *ex)
+{
+  H_PUT_16 (abfd, in->version, ex->version);
+  H_PUT_8 (abfd, in->isa_level, ex->isa_level);
+  H_PUT_8 (abfd, in->isa_rev, ex->isa_rev);
+  H_PUT_8 (abfd, in->gpr_size, ex->gpr_size);
+  H_PUT_8 (abfd, in->cpr1_size, ex->cpr1_size);
+  H_PUT_8 (abfd, in->cpr2_size, ex->cpr2_size);
+  H_PUT_8 (abfd, in->fp_abi, ex->fp_abi);
+  H_PUT_32 (abfd, in->isa_ext, ex->isa_ext);
+  H_PUT_32 (abfd, in->ases, ex->ases);
+  H_PUT_32 (abfd, in->flags1, ex->flags1);
+  H_PUT_32 (abfd, in->flags2, ex->flags2);
+}
+
+/* Map flag bits to BFD architecture.  */
+
+unsigned long
+_bfd_elf_nanomips_mach (flagword flags)
+{
+  switch (flags & EF_NANOMIPS_ARCH)
+    {
+    default:
+    case E_NANOMIPS_ARCH_32R6:
+      return bfd_mach_nanomipsisa32r6;
+
+    case E_NANOMIPS_ARCH_64R6:
+      return bfd_mach_nanomipsisa64r6;
+    }
+
+  return 0;
+}
+
+/* Work over a section just before writing it out.  This routine is
+   used by both the 32-bit and the 64-bit ABI.  */
+
+bool
+_bfd_nanomips_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED,
+				      Elf_Internal_Shdr *hdr)
+{
+  if (hdr->bfd_section != NULL)
+    {
+      const char *name = bfd_section_name (hdr->bfd_section);
+
+      /* .sbss is not handled specially here because the GNU/Linux
+         prelinker can convert .sbss from NOBITS to PROGBITS and
+         changing it back to NOBITS breaks the binary.  The entry in
+         _bfd_nanomips_elf_special_sections will ensure the correct flags
+         are set on .sbss if BFD creates it without reading it from an
+         input file, and without special handling here the flags set
+         on it in an input file will be followed.  */
+      if (strcmp (name, ".sdata") == 0
+	  || strcmp (name, ".lit8") == 0
+	  || strcmp (name, ".lit4") == 0
+	  || strncmp (name, ".sdata_", 7) == 0)
+	{
+	  hdr->sh_flags |= SHF_ALLOC | SHF_WRITE;
+	  hdr->sh_type = SHT_PROGBITS;
+	}
+      else if (strcmp (name, ".srdata") == 0)
+	{
+	  hdr->sh_flags |= SHF_ALLOC;
+	  hdr->sh_type = SHT_PROGBITS;
+	}
+      else if (strcmp (name, ".compact_rel") == 0)
+	{
+	  hdr->sh_flags = 0;
+	  hdr->sh_type = SHT_PROGBITS;
+	}
+      else if (strcmp (name, ".rtproc") == 0)
+	{
+	  if (hdr->sh_addralign != 0 && hdr->sh_entsize == 0)
+	    {
+	      unsigned int adjust;
+
+	      adjust = hdr->sh_size % hdr->sh_addralign;
+	      if (adjust != 0)
+		hdr->sh_size += hdr->sh_addralign - adjust;
+	    }
+	}
+    }
+
+  return true;
+}
+
+/* Handle a nanoMIPS specific section when reading an object file.
+   This is called when elfcode.h finds a section with an unknown type.
+   This routine supports both the 32-bit and 64-bit ELF ABI.  */
+
+bool
+_bfd_nanomips_elf_section_from_shdr (bfd *abfd, Elf_Internal_Shdr *hdr,
+				     const char *name, int shindex)
+{
+  flagword flags = 0;
+
+  /* There ought to be a place to keep ELF backend specific flags, but
+     at the moment there isn't one.  We just keep track of the
+     sections by their name, instead.   */
+  switch (hdr->sh_type)
+    {
+    case SHT_NANOMIPS_ABIFLAGS:
+      if (!NANOMIPS_ELF_ABIFLAGS_SECTION_NAME_P (name))
+	return false;
+      flags = (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_SIZE);
+      break;
+    default:
+      break;
+    }
+
+  if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
+    return false;
+
+  if (flags)
+    {
+      if (!bfd_set_section_flags (hdr->bfd_section,
+				  (bfd_section_flags (hdr->bfd_section)
+				   | flags)))
+	return false;
+    }
+
+  if (hdr->sh_type == SHT_NANOMIPS_ABIFLAGS)
+    {
+      Elf_External_ABIFlags_v0 ext;
+
+      if (! bfd_get_section_contents (abfd, hdr->bfd_section, &ext,
+				      0, sizeof ext))
+	return false;
+      bfd_nanomips_elf_swap_abiflags_v0_in
+	(abfd, &ext, &nanomips_elf_tdata (abfd)->abiflags);
+      if (nanomips_elf_tdata (abfd)->abiflags.version != 0)
+	return false;
+      nanomips_elf_tdata (abfd)->abiflags_valid = true;
+    }
+
+  return true;
+}
+
+/* Set the correct type for a nanoMIPS ELF section.  We do this by the
+   section name, which is a hack, but ought to work.  This routine is
+   used by both the 32-bit and the 64-bit ABI.  */
+
+bool
+_bfd_nanomips_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
+				 Elf_Internal_Shdr *hdr,
+				 asection *sec)
+{
+  const char *name = bfd_section_name (sec);
+
+  if (startswith (name, ".nanoMIPS.abiflags"))
+    {
+      hdr->sh_type = SHT_NANOMIPS_ABIFLAGS;
+      hdr->sh_entsize = sizeof (Elf_External_ABIFlags_v0);
+    }
+
+  /* The generic elf_fake_sections will set up REL_HDR using the default
+     kind of relocations.  */
+  return true;
+}
+
+/* Functions for the dynamic linker.  */
+
+/* Set ABFD's EF_NANOMIPS_ARCH and EF_NANOMIPS_MACH flags.  */
+
+static void
+nanomips_set_isa_flags (bfd *abfd)
+{
+  flagword val = 0;
+
+  switch (bfd_get_mach (abfd))
+    {
+    case bfd_mach_nanomipsisa32r6:
+      val = E_NANOMIPS_ARCH_32R6;
+      break;
+
+    case bfd_mach_nanomipsisa64r6:
+      val = E_NANOMIPS_ARCH_64R6;
+      break;
+    default:
+      break;
+    }
+
+  elf_elfheader (abfd)->e_flags &= ~(EF_NANOMIPS_ARCH | EF_NANOMIPS_MACH);
+  elf_elfheader (abfd)->e_flags |= val;
+}
+
+/* The final processing done just before writing out a nanoMIPS ELF
+   object file.  This gets the nanoMIPS architecture right based on the
+   machine number.  This is used by both the 32-bit and the 64-bit ABI.  */
+
+bool
+_bfd_nanomips_elf_final_write_processing (bfd *abfd)
+{
+  nanomips_set_isa_flags (abfd);
+  return _bfd_elf_final_write_processing (abfd);
+}
+
+/* Return the meaning of Tag_GNU_NANOMIPS_ABI_FP value FP, or null if
+   not known.  */
+
+const char *
+_bfd_nanomips_fp_abi_string (int fp)
+{
+  switch (fp)
+    {
+      /* These strings aren't translated because they're simply
+         option lists.  */
+    case Val_GNU_NANOMIPS_ABI_FP_DOUBLE:
+      return "-mdouble-float";
+
+    case Val_GNU_NANOMIPS_ABI_FP_SINGLE:
+      return "-msingle-float";
+
+    case Val_GNU_NANOMIPS_ABI_FP_SOFT:
+      return "-msoft-float";
+
+    default:
+      return 0;
+    }
+}
+
+/* Print the name of an ASE.  */
+
+static void
+print_nanomips_ases (FILE *file, unsigned int mask)
+{
+  if (mask & NANOMIPS_ASE_DSPR3)
+    fputs ("\n\tDSP R3 ASE", file);
+  if (mask & NANOMIPS_ASE_EVA)
+    fputs ("\n\tEnhanced VA Scheme", file);
+  if (mask & NANOMIPS_ASE_MCU)
+    fputs ("\n\tMCU (MicroController) ASE", file);
+  if (mask & NANOMIPS_ASE_MT)
+    fputs ("\n\tMT ASE", file);
+  if (mask & NANOMIPS_ASE_VIRT)
+    fputs ("\n\tVZ ASE", file);
+  if (mask & NANOMIPS_ASE_MSA)
+    fputs ("\n\tMSA ASE", file);
+  if (mask & NANOMIPS_ASE_TLB)
+    fputs ("\n\tTLB ASE", file);
+  if (mask & NANOMIPS_ASE_CRC)
+    fputs ("\n\tCRC ASE", file);
+  if ((mask & NANOMIPS_ASE_xNMS) == 0)
+    fputs ("\n\tnanoMIPS subset", file);
+  else if (mask == 0)
+    fprintf (file, "\n\t%s", _("None"));
+  else if ((mask & ~NANOMIPS_ASE_MASK) != 0)
+    fprintf (stdout, "\n\t%s (%x)", _("Unknown"), mask & ~NANOMIPS_ASE_MASK);
+}
+
+/* Print the name of an ISA extension.  None yet for nanoMIPS.  */
+
+static void
+print_nanomips_isa_ext (FILE *file, unsigned int isa_ext)
+{
+  switch (isa_ext)
+    {
+    case 0:
+      fputs (_("None"), file);
+      break;
+    default:
+      fprintf (file, "%s (%d)", _("Unknown"), isa_ext);
+      break;
+    }
+}
+
+/* Decode and print the FP ABI mode.  */
+
+static void
+print_nanomips_fp_abi_value (FILE *file, int val)
+{
+  switch (val)
+    {
+    case Val_GNU_NANOMIPS_ABI_FP_ANY:
+      fprintf (file, _("Hard or soft float\n"));
+      break;
+    case Val_GNU_NANOMIPS_ABI_FP_DOUBLE:
+      fprintf (file, _("Hard float (double precision)\n"));
+      break;
+    case Val_GNU_NANOMIPS_ABI_FP_SINGLE:
+      fprintf (file, _("Hard float (single precision)\n"));
+      break;
+    case Val_GNU_NANOMIPS_ABI_FP_SOFT:
+      fprintf (file, _("Soft float\n"));
+      break;
+    default:
+      fprintf (file, "??? (%d)\n", val);
+      break;
+    }
+}
+
+/* Map register type to size.  */
+
+static int
+get_nanomips_reg_size (int reg_size)
+{
+  return ((reg_size == AFL_REG_NONE) ? 0
+	  : (reg_size == AFL_REG_32) ? 32
+	  : (reg_size == AFL_REG_64) ? 64
+	  : (reg_size == AFL_REG_128) ? 128
+	  : -1);
+}
+
+/* Print nanoMIPS-specific ELF data.  */
+
+bool
+_bfd_nanomips_elf_print_private_bfd_data (bfd *abfd, void *ptr)
+{
+  FILE *file = ptr;
+
+  BFD_ASSERT (abfd != NULL && ptr != NULL);
+
+  /* Print normal ELF private data.  */
+  _bfd_elf_print_private_bfd_data (abfd, ptr);
+
+  /* xgettext:c-format */
+  fprintf (file, _("private flags = %08lx:"), elf_elfheader (abfd)->e_flags);
+
+  if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) == E_NANOMIPS_ABI_P32)
+    fprintf (file, _(" [abi=P32]"));
+  else if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ABI) ==
+	   E_NANOMIPS_ABI_P64)
+    fprintf (file, _(" [abi=P64]"));
+  else
+    fprintf (file, _(" [no abi set]"));
+
+  if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ARCH)
+      == E_NANOMIPS_ARCH_32R6)
+    fprintf (file, " [nanomips32r6]");
+  else if ((elf_elfheader (abfd)->e_flags & EF_NANOMIPS_ARCH)
+	   == E_NANOMIPS_ARCH_64R6)
+    fprintf (file, " [nanomips64r6]");
+  else
+    fprintf (file, _(" [unknown ISA]"));
+
+  if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_32BITMODE)
+    fprintf (file, " [32bitmode]");
+  else
+    fprintf (file, _(" [not 32bitmode]"));
+
+  if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_LINKRELAX)
+    fprintf (file, " [RELAXABLE]");
+
+  if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_PIC)
+    fprintf (file, " [PIC]");
+
+  if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_PID)
+    fprintf (file, " [PID]");
+
+  if (elf_elfheader (abfd)->e_flags & EF_NANOMIPS_PCREL)
+    fprintf (file, " [PCREL]");
+
+  fputc ('\n', file);
+
+  if (nanomips_elf_tdata (abfd)->abiflags_valid)
+    {
+      Elf_Internal_ABIFlags_v0 *abiflags =
+	&nanomips_elf_tdata (abfd)->abiflags;
+      fprintf (file, "\nnanoMIPS ABI Flags Version: %d\n", abiflags->version);
+      fprintf (file, "\nISA: nanoMIPS%d", abiflags->isa_level);
+      if (abiflags->isa_rev > 1)
+	fprintf (file, "r%d", abiflags->isa_rev);
+      fprintf (file, "\nGPR size: %d",
+	       get_nanomips_reg_size (abiflags->gpr_size));
+      fprintf (file, "\nCPR1 size: %d",
+	       get_nanomips_reg_size (abiflags->cpr1_size));
+      fprintf (file, "\nCPR2 size: %d",
+	       get_nanomips_reg_size (abiflags->cpr2_size));
+      fputs ("\nFP ABI: ", file);
+      print_nanomips_fp_abi_value (file, abiflags->fp_abi);
+      fputs ("ISA Extension: ", file);
+      print_nanomips_isa_ext (file, abiflags->isa_ext);
+      fputs ("\nASEs:", file);
+      print_nanomips_ases (file, abiflags->ases);
+      fprintf (file, "\nFLAGS 1: %8.8lx", abiflags->flags1);
+      fprintf (file, "\nFLAGS 2: %8.8lx", abiflags->flags2);
+      fputc ('\n', file);
+    }
+
+  return true;
+}
+
+const struct bfd_elf_special_section _bfd_nanomips_elf_special_sections[] = {
+  { STRING_COMMA_LEN (".lit4"),   0, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE},
+  { STRING_COMMA_LEN (".lit8"),   0, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE},
+  { STRING_COMMA_LEN (".sbss"),  -2, SHT_NOBITS,     SHF_ALLOC + SHF_WRITE},
+  { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS,   SHF_ALLOC + SHF_WRITE},
+  { NULL,                     0,  0, 0,              0 }
+};
+
+/* Merge non visibility st_other attributes.  Ensure that the
+   STO_OPTIONAL flag is copied into h->other, even if this is not a
+   definiton of the symbol.  */
+
+void
+_bfd_nanomips_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
+					  unsigned int st_other,
+					  bool definition,
+					  bool dynamic
+					  ATTRIBUTE_UNUSED)
+{
+  if ((st_other & ~ELF_ST_VISIBILITY (-1)) != 0)
+    {
+      unsigned char other;
+
+      other = (definition ? st_other : h->other);
+      other &= ~ELF_ST_VISIBILITY (-1);
+      h->other = other | ELF_ST_VISIBILITY (h->other);
+    }
+}
+
+/* Get ABI flags for a nanoMIPS BFD arch.  */
+
+Elf_Internal_ABIFlags_v0 *
+bfd_nanomips_elf_get_abiflags (bfd *abfd)
+{
+  struct nanomips_elf_obj_tdata *tdata = nanomips_elf_tdata (abfd);
+
+  return tdata->abiflags_valid ? &tdata->abiflags : NULL;
+}
+
+/* Relocate a section.  Tools like readelf/binutils needed to perform a static
+   relocation on objects to make sense debug information that contains label
+   difference relocations.  The only difference between this and the generic
+   ELF version is that correct handling of composite relocations according to
+   gABI spec.  */
+
+bfd_byte *
+_bfd_elf_nanomips_get_relocated_section_contents (bfd *abfd,
+						  struct bfd_link_info *link_info,
+						  struct bfd_link_order *link_order,
+						  bfd_byte *data,
+						  bool relocatable,
+						  asymbol **symbols)
+{
+  bfd *input_bfd = link_order->u.indirect.section->owner;
+  asection *input_section = link_order->u.indirect.section;
+  long reloc_size;
+  arelent **reloc_vector;
+  long reloc_count;
+
+  reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
+  if (reloc_size < 0)
+    return NULL;
+
+  /* Read in the section.  */
+  if (!bfd_get_full_section_contents (input_bfd, input_section, &data))
+    return NULL;
+
+  if (data == NULL)
+    return NULL;
+
+  if (reloc_size == 0)
+    return data;
+
+  reloc_vector = (arelent **) bfd_malloc (reloc_size);
+  if (reloc_vector == NULL)
+    return NULL;
+
+  reloc_count = bfd_canonicalize_reloc (input_bfd, input_section,
+					reloc_vector, symbols);
+
+  if (reloc_count < 0)
+    goto error_return;
+
+  if (reloc_count > 0)
+    {
+      arelent **parent;
+      /* offset in section of previous relocation  */
+      bfd_size_type last_address = 0;
+      /* saved result of previous relocation.  */
+      bfd_vma saved_addend = 0;
+
+      for (parent = reloc_vector; *parent != NULL; parent++)
+	{
+	  char *error_message = NULL;
+	  asymbol *symbol;
+	  bfd_reloc_status_type r;
+
+	  symbol = *(*parent)->sym_ptr_ptr;
+	  /* PR ld/19628: A specially crafted input file
+	     can result in a NULL symbol pointer here.  */
+	  if (symbol == NULL)
+	    {
+	      link_info->callbacks->einfo
+		/* xgettext:c-format */
+		(_("%X%P: %B(%A): error: relocation for offset %V has no value\n"),
+		 abfd, input_section, (* parent)->address);
+	      goto error_return;
+	    }
+
+	  if (symbol->section && discarded_section (symbol->section))
+	    {
+	      bfd_vma off;
+	      static reloc_howto_type none_howto
+		= HOWTO (0, 0, 0, 0, false, 0, complain_overflow_dont, NULL,
+			 "unused", false, 0, 0, false);
+
+	      off = (*parent)->address * bfd_octets_per_byte (input_bfd, input_section);
+	      _bfd_clear_contents ((*parent)->howto, input_bfd, input_section,
+				   data, off);
+	      (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+	      (*parent)->addend = 0;
+	      (*parent)->howto = &none_howto;
+	      r = bfd_reloc_ok;
+	    }
+	  else
+	    {
+	      if (last_address != 0 && (*parent)->address == last_address)
+		(*parent)->addend = saved_addend;
+	      else
+		saved_addend = 0;
+
+	      r = bfd_perform_relocation (input_bfd,
+					  *parent,
+					  data,
+					  input_section,
+					  relocatable ? abfd : NULL,
+					  &error_message);
+	      saved_addend = (*parent)->addend;
+	    }
+
+	  if (relocatable)
+	    {
+	      asection *os = input_section->output_section;
+
+	      /* A partial link, so keep the relocs.  */
+	      os->orelocation[os->reloc_count] = *parent;
+	      os->reloc_count++;
+	    }
+
+	  if (r != bfd_reloc_ok)
+	    {
+	      switch (r)
+		{
+		case bfd_reloc_undefined:
+		  (*link_info->callbacks->undefined_symbol)
+		    (link_info, bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
+		     input_bfd, input_section, (*parent)->address, true);
+		  break;
+		case bfd_reloc_dangerous:
+		  BFD_ASSERT (error_message != NULL);
+		  (*link_info->callbacks->reloc_dangerous)
+		    (link_info, error_message,
+		     input_bfd, input_section, (*parent)->address);
+		  break;
+		case bfd_reloc_overflow:
+		  (*link_info->callbacks->reloc_overflow)
+		    (link_info, NULL,
+		     bfd_asymbol_name (*(*parent)->sym_ptr_ptr),
+		     (*parent)->howto->name, (*parent)->addend,
+		     input_bfd, input_section, (*parent)->address);
+		  break;
+		case bfd_reloc_outofrange:
+		  /* PR ld/13730:
+		     This error can result when processing some partially
+		     complete binaries.  Do not abort, but issue an error
+		     message instead.  */
+		  link_info->callbacks->einfo
+		    /* xgettext:c-format */
+		    (_("%X%P: %B(%A): relocation \"%R\" goes out of range\n"),
+		     abfd, input_section, *parent);
+		  goto error_return;
+
+		case bfd_reloc_notsupported:
+		  /* PR ld/17512
+		     This error can result when processing a corrupt binary.
+		     Do not abort.  Issue an error message instead.  */
+		  link_info->callbacks->einfo
+		    /* xgettext:c-format */
+		    (_("%X%P: %B(%A): relocation \"%R\" is not supported\n"),
+		     abfd, input_section, *parent);
+		  goto error_return;
+
+		default:
+		  /* PR 17512; file: 90c2a92e.
+		     Report unexpected results, without aborting.  */
+		  link_info->callbacks->einfo
+		    /* xgettext:c-format */
+		    (_("%X%P: %B(%A): relocation \"%R\" returns an unrecognized value %x\n"),
+		     abfd, input_section, *parent, r);
+		  break;
+		}
+
+	    }
+	  last_address = (*parent)->address;
+	}
+    }
+
+  free (reloc_vector);
+  return data;
+
+error_return:
+  free (reloc_vector);
+  return NULL;
+}
diff --git a/bfd/elfxx-nanomips.h b/bfd/elfxx-nanomips.h
new file mode 100644
index 00000000000..6566db550cb
--- /dev/null
+++ b/bfd/elfxx-nanomips.h
@@ -0,0 +1,54 @@ 
+/* nanoMIPS ELF specific backend routines.
+   Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+   Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "elf/nanomips.h"
+
+extern bool _bfd_nanomips_elf_mkobject (bfd *);
+extern bool _bfd_nanomips_elf_section_processing
+  (bfd *, Elf_Internal_Shdr *);
+extern bool _bfd_nanomips_elf_section_from_shdr
+  (bfd *, Elf_Internal_Shdr *, const char *, int);
+extern bool _bfd_nanomips_elf_fake_sections
+  (bfd *, Elf_Internal_Shdr *, asection *);
+extern bool _bfd_nanomips_elf_final_write_processing (bfd *);
+extern const char *_bfd_nanomips_fp_abi_string (int);
+extern bool _bfd_nanomips_elf_print_private_bfd_data (bfd *, void *);
+
+extern bfd_reloc_status_type _bfd_nanomips_elf_generic_reloc
+  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+extern bfd_reloc_status_type _bfd_nanomips_elf_negative_reloc
+  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+
+extern unsigned long _bfd_elf_nanomips_mach (flagword);
+extern void _bfd_nanomips_elf_merge_symbol_attribute
+  (struct elf_link_hash_entry *, unsigned int, bool, bool);
+
+extern const struct bfd_elf_special_section
+  _bfd_nanomips_elf_special_sections[];
+
+extern bfd_byte *_bfd_elf_nanomips_get_relocated_section_contents
+  (bfd *, struct bfd_link_info *, struct bfd_link_order *,
+   bfd_byte *, bool, asymbol **);
+
+#define elf_backend_special_sections _bfd_nanomips_elf_special_sections
+#define elf_backend_merge_symbol_attribute	\
+  _bfd_nanomips_elf_merge_symbol_attribute
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 05508c986ad..c48f85ea582 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1330,6 +1330,75 @@  static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_MIPS_COPY",
   "BFD_RELOC_MIPS_JUMP_SLOT",
 
+  "BFD_RELOC_NANOMIPS_HI20",
+  "BFD_RELOC_NANOMIPS_LO12",
+  "BFD_RELOC_NANOMIPS_LO4_S2",
+  "BFD_RELOC_NANOMIPS_IMM16",
+  "BFD_RELOC_NANOMIPS_NEG12",
+  "BFD_RELOC_NANOMIPS_GPREL7_S2",
+  "BFD_RELOC_NANOMIPS_GPREL18",
+  "BFD_RELOC_NANOMIPS_GPREL19_S2",
+  "BFD_RELOC_NANOMIPS_GPREL16_S2",
+  "BFD_RELOC_NANOMIPS_GPREL18_S3",
+  "BFD_RELOC_NANOMIPS_4_PCREL_S1",
+  "BFD_RELOC_NANOMIPS_7_PCREL_S1",
+  "BFD_RELOC_NANOMIPS_10_PCREL_S1",
+  "BFD_RELOC_NANOMIPS_11_PCREL_S1",
+  "BFD_RELOC_NANOMIPS_14_PCREL_S1",
+  "BFD_RELOC_NANOMIPS_21_PCREL_S1",
+  "BFD_RELOC_NANOMIPS_25_PCREL_S1",
+  "BFD_RELOC_NANOMIPS_PCREL_HI20",
+  "BFD_RELOC_NANOMIPS_GOT_CALL",
+  "BFD_RELOC_NANOMIPS_GOTPC_HI20",
+  "BFD_RELOC_NANOMIPS_GOTPC_I32",
+  "BFD_RELOC_NANOMIPS_GOT_LO12",
+  "BFD_RELOC_NANOMIPS_GOT_DISP",
+  "BFD_RELOC_NANOMIPS_GOT_PAGE",
+  "BFD_RELOC_NANOMIPS_GOT_OFST",
+  "BFD_RELOC_NANOMIPS_I32",
+  "BFD_RELOC_NANOMIPS_GPREL_HI20",
+  "BFD_RELOC_NANOMIPS_GPREL_LO12",
+  "BFD_RELOC_NANOMIPS_TLS_GD",
+  "BFD_RELOC_NANOMIPS_TLS_GD_I32",
+  "BFD_RELOC_NANOMIPS_TLS_LD",
+  "BFD_RELOC_NANOMIPS_TLS_LD_I32",
+  "BFD_RELOC_NANOMIPS_TLS_DTPREL12",
+  "BFD_RELOC_NANOMIPS_TLS_DTPREL16",
+  "BFD_RELOC_NANOMIPS_TLS_DTPREL_I32",
+  "BFD_RELOC_NANOMIPS_TLS_GOTTPREL",
+  "BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32",
+  "BFD_RELOC_NANOMIPS_TLS_TPREL12",
+  "BFD_RELOC_NANOMIPS_TLS_TPREL16",
+  "BFD_RELOC_NANOMIPS_TLS_TPREL_I32",
+  "BFD_RELOC_NANOMIPS_TLS_DTPMOD",
+  "BFD_RELOC_NANOMIPS_TLS_DTPREL",
+  "BFD_RELOC_NANOMIPS_TLS_TPREL",
+  "BFD_RELOC_NANOMIPS_PC_I32",
+  "BFD_RELOC_NANOMIPS_GPREL_I32",
+  "BFD_RELOC_NANOMIPS_GPREL17_S1",
+  "BFD_RELOC_NANOMIPS_NEG",
+  "BFD_RELOC_NANOMIPS_ASHIFTR_1",
+  "BFD_RELOC_NANOMIPS_UNSIGNED_8",
+  "BFD_RELOC_NANOMIPS_UNSIGNED_16",
+  "BFD_RELOC_NANOMIPS_SIGNED_8",
+  "BFD_RELOC_NANOMIPS_SIGNED_16",
+  "BFD_RELOC_NANOMIPS_EH",
+  "BFD_RELOC_NANOMIPS_JUMP_SLOT",
+  "BFD_RELOC_NANOMIPS_ALIGN",
+  "BFD_RELOC_NANOMIPS_FILL",
+  "BFD_RELOC_NANOMIPS_MAX",
+  "BFD_RELOC_NANOMIPS_INSN32",
+  "BFD_RELOC_NANOMIPS_INSN16",
+  "BFD_RELOC_NANOMIPS_FIXED",
+  "BFD_RELOC_NANOMIPS_RELAX",
+  "BFD_RELOC_NANOMIPS_NORELAX",
+  "BFD_RELOC_NANOMIPS_SAVERESTORE",
+  "BFD_RELOC_NANOMIPS_JALR16",
+  "BFD_RELOC_NANOMIPS_JALR32",
+  "BFD_RELOC_NANOMIPS_COPY",
+  "BFD_RELOC_NANOMIPS_SIGNED_9",
+  "BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD",
+
   "BFD_RELOC_MOXIE_10_PCREL",
 
   "BFD_RELOC_FT32_10",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index aab5d49bdb3..bc422fef840 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2177,6 +2177,146 @@  ENUMDOC
   MIPS ELF relocations (VxWorks and PLT extensions).
 COMMENT
 
+ENUM
+  BFD_RELOC_NANOMIPS_HI20
+ENUMX
+  BFD_RELOC_NANOMIPS_LO12
+ENUMX
+  BFD_RELOC_NANOMIPS_LO4_S2
+ENUMX
+  BFD_RELOC_NANOMIPS_IMM16
+ENUMX
+  BFD_RELOC_NANOMIPS_NEG12
+ENUMX
+  BFD_RELOC_NANOMIPS_GPREL7_S2
+ENUMX
+  BFD_RELOC_NANOMIPS_GPREL18
+ENUMX
+  BFD_RELOC_NANOMIPS_GPREL19_S2
+ENUMX
+  BFD_RELOC_NANOMIPS_GPREL16_S2
+ENUMX
+  BFD_RELOC_NANOMIPS_GPREL18_S3
+ENUMX
+  BFD_RELOC_NANOMIPS_4_PCREL_S1
+ENUMX
+  BFD_RELOC_NANOMIPS_7_PCREL_S1
+ENUMX
+  BFD_RELOC_NANOMIPS_10_PCREL_S1
+ENUMX
+  BFD_RELOC_NANOMIPS_11_PCREL_S1
+ENUMX
+  BFD_RELOC_NANOMIPS_14_PCREL_S1
+ENUMX
+  BFD_RELOC_NANOMIPS_21_PCREL_S1
+ENUMX
+  BFD_RELOC_NANOMIPS_25_PCREL_S1
+ENUMX
+  BFD_RELOC_NANOMIPS_PCREL_HI20
+ENUMX
+  BFD_RELOC_NANOMIPS_GOT_CALL
+ENUMX
+  BFD_RELOC_NANOMIPS_GOTPC_HI20
+ENUMX
+  BFD_RELOC_NANOMIPS_GOTPC_I32
+ENUMX
+  BFD_RELOC_NANOMIPS_GOT_LO12
+ENUMX
+  BFD_RELOC_NANOMIPS_GOT_DISP
+ENUMX
+  BFD_RELOC_NANOMIPS_GOT_PAGE
+ENUMX
+  BFD_RELOC_NANOMIPS_GOT_OFST
+ENUMX
+  BFD_RELOC_NANOMIPS_I32
+ENUMX
+  BFD_RELOC_NANOMIPS_GPREL_HI20
+ENUMX
+  BFD_RELOC_NANOMIPS_GPREL_LO12
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_GD
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_GD_I32
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_LD
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_LD_I32
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_DTPREL12
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_DTPREL16
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_DTPREL_I32
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_GOTTPREL
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_GOTTPREL_PC_I32
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_TPREL12
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_TPREL16
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_TPREL_I32
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_DTPMOD
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_DTPREL
+ENUMX
+  BFD_RELOC_NANOMIPS_TLS_TPREL
+ENUMX
+  BFD_RELOC_NANOMIPS_PC_I32
+ENUMX
+  BFD_RELOC_NANOMIPS_GPREL_I32
+ENUMX
+  BFD_RELOC_NANOMIPS_GPREL17_S1
+ENUMX
+  BFD_RELOC_NANOMIPS_NEG
+ENUMX
+  BFD_RELOC_NANOMIPS_ASHIFTR_1
+ENUMX
+  BFD_RELOC_NANOMIPS_UNSIGNED_8
+ENUMX
+  BFD_RELOC_NANOMIPS_UNSIGNED_16
+ENUMX
+  BFD_RELOC_NANOMIPS_SIGNED_8
+ENUMX
+  BFD_RELOC_NANOMIPS_SIGNED_16
+ENUMX
+  BFD_RELOC_NANOMIPS_EH
+ENUMX
+  BFD_RELOC_NANOMIPS_JUMP_SLOT
+ENUMX
+  BFD_RELOC_NANOMIPS_ALIGN
+ENUMX
+  BFD_RELOC_NANOMIPS_FILL
+ENUMX
+  BFD_RELOC_NANOMIPS_MAX
+ENUMX
+  BFD_RELOC_NANOMIPS_INSN32
+ENUMX
+  BFD_RELOC_NANOMIPS_INSN16
+ENUMX
+  BFD_RELOC_NANOMIPS_FIXED
+ENUMX
+  BFD_RELOC_NANOMIPS_RELAX
+ENUMX
+  BFD_RELOC_NANOMIPS_NORELAX
+ENUMX
+  BFD_RELOC_NANOMIPS_SAVERESTORE
+ENUMX
+  BFD_RELOC_NANOMIPS_JALR16
+ENUMX
+  BFD_RELOC_NANOMIPS_JALR32
+ENUMX
+  BFD_RELOC_NANOMIPS_COPY
+ENUMX
+  BFD_RELOC_NANOMIPS_SIGNED_9
+ENUMX
+  BFD_RELOC_NANOMIPS_JUMPTABLE_LOAD
+ENUMDOC
+  nanoMIPS relocations
+COMMENT
+
 ENUM
   BFD_RELOC_MOXIE_10_PCREL
 ENUMDOC
diff --git a/bfd/targets.c b/bfd/targets.c
index 3dbcd088966..264933a83eb 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -829,6 +829,10 @@  extern const bfd_target moxie_elf32_le_vec;
 extern const bfd_target msp430_elf32_vec;
 extern const bfd_target msp430_elf32_ti_vec;
 extern const bfd_target mt_elf32_vec;
+extern const bfd_target nanomips_elf32_be_vec;
+extern const bfd_target nanomips_elf32_le_vec;
+extern const bfd_target nanomips_elf64_le_vec;
+extern const bfd_target nanomips_elf64_be_vec;
 extern const bfd_target nds32_elf32_be_vec;
 extern const bfd_target nds32_elf32_le_vec;
 extern const bfd_target nds32_elf32_linux_be_vec;
@@ -1203,6 +1207,13 @@  static const bfd_target * const _bfd_target_vector[] =
 
 	&mt_elf32_vec,
 
+	&nanomips_elf32_be_vec,
+	&nanomips_elf32_le_vec,
+#ifdef BFD64
+	&nanomips_elf64_be_vec,
+	&nanomips_elf64_le_vec,
+#endif
+
 	&nds32_elf32_be_vec,
 	&nds32_elf32_le_vec,
 	&nds32_elf32_linux_be_vec,
diff --git a/binutils/readelf.c b/binutils/readelf.c
index b872876a8b6..140337d7bec 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -2963,7 +2963,7 @@  get_machine_name (unsigned e_machine)
     case EM_CEVA_X2:		return "CEVA X2 Processor Family";
     case EM_BPF:		return "Linux BPF";
     case EM_GRAPHCORE_IPU:	return "Graphcore Intelligent Processing Unit";
-    case EM_IMG1:		return "Imagination Technologies";
+    case EM_NANOMIPS:		return "nanoMIPS";
       /* 250 */
     case EM_NFP:		return "Netronome Flow Processor";
     case EM_VE:			return "NEC Vector Engine";
diff --git a/include/elf/common.h b/include/elf/common.h
index 6f64f05890c..253200fa652 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -346,7 +346,7 @@ 
 #define EM_CEVA_X2	246	/* CEVA X2 Processor Family */
 #define EM_BPF		247	/* Linux BPF – in-kernel virtual machine.  */
 #define EM_GRAPHCORE_IPU 248	/* Graphcore Intelligent Processing Unit */
-#define EM_IMG1		249	/* Imagination Technologies */
+#define EM_NANOMIPS		249	/* nanoMIPS */
 #define EM_NFP		250	/* Netronome Flow Processor.  */
 #define EM_VE		251	/* NEC Vector Engine */
 #define EM_CSKY		252	/* C-SKY processor family.  */
diff --git a/include/elf/nanomips.h b/include/elf/nanomips.h
new file mode 100644
index 00000000000..b04c7343af2
--- /dev/null
+++ b/include/elf/nanomips.h
@@ -0,0 +1,262 @@ 
+/* nanoMIPS ELF support for BFD.
+   Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+   Written by Faraz Shahbazker <faraz.shahbazker@mips.com>
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+/* This file holds definitions specific to the nanoMIPS ELF ABI.  */
+
+#ifndef _ELF_NANOMIPS_H
+#define _ELF_NANOMIPS_H
+
+#include "elf/reloc-macros.h"
+#include "elf/mips.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Values for the xxx_size bytes of an ABI flags structure.  */
+
+#define AFL_REG_NONE     0x00 /* No registers.  */
+#define AFL_REG_32       0x01 /* 32-bit registers.  */
+#define AFL_REG_64       0x02 /* 64-bit registers.  */
+#define AFL_REG_128      0x03 /* 128-bit registers.  */
+
+START_RELOC_NUMBERS (elf_nanomips_reloc_type)
+  RELOC_NUMBER (R_NANOMIPS_NONE, 0)
+  RELOC_NUMBER (R_NANOMIPS_32, 1)
+  RELOC_NUMBER (R_NANOMIPS_64, 2)
+  RELOC_NUMBER (R_NANOMIPS_NEG, 3)
+  RELOC_NUMBER (R_NANOMIPS_ASHIFTR_1, 4)
+  RELOC_NUMBER (R_NANOMIPS_UNSIGNED_8, 5)
+  RELOC_NUMBER (R_NANOMIPS_SIGNED_8, 6)
+  RELOC_NUMBER (R_NANOMIPS_UNSIGNED_16, 7)
+  RELOC_NUMBER (R_NANOMIPS_SIGNED_16, 8)
+  RELOC_NUMBER (R_NANOMIPS_RELATIVE, 9)
+  RELOC_NUMBER (R_NANOMIPS_GLOBAL, 10)
+  RELOC_NUMBER (R_NANOMIPS_JUMP_SLOT, 11)
+  RELOC_NUMBER (R_NANOMIPS_IRELATIVE, 12)
+
+  RELOC_NUMBER (R_NANOMIPS_PC25_S1, 13)
+  RELOC_NUMBER (R_NANOMIPS_PC21_S1, 14)
+  RELOC_NUMBER (R_NANOMIPS_PC14_S1, 15)
+  RELOC_NUMBER (R_NANOMIPS_PC11_S1, 16)
+  RELOC_NUMBER (R_NANOMIPS_PC10_S1, 17)
+  RELOC_NUMBER (R_NANOMIPS_PC7_S1, 18)
+  RELOC_NUMBER (R_NANOMIPS_PC4_S1, 19)
+
+  RELOC_NUMBER (R_NANOMIPS_GPREL19_S2, 20)
+  RELOC_NUMBER (R_NANOMIPS_GPREL18_S3, 21)
+  RELOC_NUMBER (R_NANOMIPS_GPREL18, 22)
+  RELOC_NUMBER (R_NANOMIPS_GPREL17_S1, 23)
+  RELOC_NUMBER (R_NANOMIPS_GPREL16_S2, 24)
+  RELOC_NUMBER (R_NANOMIPS_GPREL7_S2, 25)
+  RELOC_NUMBER (R_NANOMIPS_GPREL_HI20, 26)
+  RELOC_NUMBER (R_NANOMIPS_PCHI20, 27)
+
+  RELOC_NUMBER (R_NANOMIPS_HI20, 28)
+  RELOC_NUMBER (R_NANOMIPS_LO12, 29)
+  RELOC_NUMBER (R_NANOMIPS_GPREL_I32, 30)
+  RELOC_NUMBER (R_NANOMIPS_PC_I32, 31)
+  RELOC_NUMBER (R_NANOMIPS_I32, 32)
+  RELOC_NUMBER (R_NANOMIPS_GOT_DISP, 33)
+  RELOC_NUMBER (R_NANOMIPS_GOTPC_I32, 34)
+  RELOC_NUMBER (R_NANOMIPS_GOTPC_HI20, 35)
+  RELOC_NUMBER (R_NANOMIPS_GOT_LO12, 36)
+  RELOC_NUMBER (R_NANOMIPS_GOT_CALL, 37)
+  RELOC_NUMBER (R_NANOMIPS_GOT_PAGE, 38)
+  RELOC_NUMBER (R_NANOMIPS_GOT_OFST, 39)
+  RELOC_NUMBER (R_NANOMIPS_LO4_S2, 40)
+  /* Reserved for 64-bit ABI. */
+  RELOC_NUMBER (R_NANOMIPS_RESERVED1, 41)
+  RELOC_NUMBER (R_NANOMIPS_GPREL_LO12, 42)
+  RELOC_NUMBER (R_NANOMIPS_SCN_DISP, 43)
+  RELOC_NUMBER (R_NANOMIPS_COPY, 44)
+
+  RELOC_NUMBER (R_NANOMIPS_ALIGN, 64)
+  RELOC_NUMBER (R_NANOMIPS_FILL, 65)
+  RELOC_NUMBER (R_NANOMIPS_MAX, 66)
+  RELOC_NUMBER (R_NANOMIPS_INSN32, 67)
+  RELOC_NUMBER (R_NANOMIPS_FIXED, 68)
+  RELOC_NUMBER (R_NANOMIPS_NORELAX, 69)
+  RELOC_NUMBER (R_NANOMIPS_RELAX, 70)
+  RELOC_NUMBER (R_NANOMIPS_SAVERESTORE, 71)
+  RELOC_NUMBER (R_NANOMIPS_INSN16, 72)
+  RELOC_NUMBER (R_NANOMIPS_JALR32, 73)
+  RELOC_NUMBER (R_NANOMIPS_JALR16, 74)
+  RELOC_NUMBER (R_NANOMIPS_JUMPTABLE_LOAD, 75)
+  RELOC_NUMBER (R_NANOMIPS_FRAME_REG, 76)
+
+  /* TLS relocations.  */
+  RELOC_NUMBER (R_NANOMIPS_TLS_DTPMOD, 80)
+  RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL, 81)
+  RELOC_NUMBER (R_NANOMIPS_TLS_TPREL, 82)
+  RELOC_NUMBER (R_NANOMIPS_TLS_GD, 83)
+  RELOC_NUMBER (R_NANOMIPS_TLS_GD_I32, 84)
+  RELOC_NUMBER (R_NANOMIPS_TLS_LD, 85)
+  RELOC_NUMBER (R_NANOMIPS_TLS_LD_I32, 86)
+  RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL12, 87)
+  RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL16, 88)
+  RELOC_NUMBER (R_NANOMIPS_TLS_DTPREL_I32, 89)
+  RELOC_NUMBER (R_NANOMIPS_TLS_GOTTPREL, 90)
+  RELOC_NUMBER (R_NANOMIPS_TLS_GOTTPREL_PC_I32, 91)
+  RELOC_NUMBER (R_NANOMIPS_TLS_TPREL12, 92)
+  RELOC_NUMBER (R_NANOMIPS_TLS_TPREL16, 93)
+  RELOC_NUMBER (R_NANOMIPS_TLS_TPREL_I32, 94)
+
+  FAKE_RELOC (R_NANOMIPS_max, 94)
+  /* May be used for compact unwind tables in the future.  */
+  RELOC_NUMBER (R_NANOMIPS_PC32, 248)
+  RELOC_NUMBER (R_NANOMIPS_EH, 249)
+  /* These are GNU extensions to enable C++ vtable garbage collection.  */
+  RELOC_NUMBER (R_NANOMIPS_GNU_VTINHERIT, 253)
+  RELOC_NUMBER (R_NANOMIPS_GNU_VTENTRY, 254)
+END_RELOC_NUMBERS (R_NANOMIPS_maxext)
+
+/* Processor specific flags for the ELF header e_flags field.  */
+
+/* File may be relaxed by the linker.  */
+#define EF_NANOMIPS_LINKRELAX   0x00000001
+
+/* File contains position independent code.  */
+#define EF_NANOMIPS_PIC         0x00000002
+
+/* Indicates code compiled for a 64-bit machine in 32-bit mode
+   (regs are 32-bits wide).  */
+#define EF_NANOMIPS_32BITMODE   0x00000004
+
+/* File contains position independent code.  */
+#define EF_NANOMIPS_PID         0x00000008
+
+/* File contains pure PC-relative code.  */
+#define EF_NANOMIPS_PCREL       0x00000010
+
+/* Four bit nanoMIPS architecture field.  */
+#define EF_NANOMIPS_ARCH        0xf0000000
+
+/* -march=32r6[s] code.  */
+#define E_NANOMIPS_ARCH_32R6    0x00000000
+
+/* -march=64r6 code.  */
+#define E_NANOMIPS_ARCH_64R6    0x10000000
+
+/* The ABI of the file.  */
+#define EF_NANOMIPS_ABI         0x0000F000
+
+/* nanoMIPS ABI in 32 bit mode.  */
+#define E_NANOMIPS_ABI_P32      0x00001000
+
+/* nanoMIPS ABI in 64 bit mode.  */
+#define E_NANOMIPS_ABI_P64      0x00002000
+
+/* Machine variant if we know it.  This field was invented at Cygnus
+   for MIPS.  It may be used similarly for nanoMIPS.  */
+
+#define EF_NANOMIPS_MACH        0x00FF0000
+
+/* Processor specific section types.  */
+
+/* ABI related flags section.  */
+#define SHT_NANOMIPS_ABIFLAGS   0x70000000
+
+/* Processor specific program header types.  */
+
+/* Records ABI related flags.  */
+#define PT_NANOMIPS_ABIFLAGS    0x70000000
+
+/* Object attribute tags.  */
+enum
+{
+  /* 0-3 are generic.  */
+
+  /* Floating-point ABI used by this object file.  */
+  Tag_GNU_NANOMIPS_ABI_FP = 4,
+
+  /* MSA ABI used by this object file.  */
+  Tag_GNU_NANOMIPS_ABI_MSA = 8,
+};
+
+/* Object attribute values.  */
+enum
+{
+  /* Values defined for Tag_GNU_NANOMIPS_ABI_FP.  */
+
+  /* Not tagged or not using any ABIs affected by the differences.  */
+  Val_GNU_NANOMIPS_ABI_FP_ANY = 0,
+
+  /* Using hard-float -mdouble-float.  */
+  Val_GNU_NANOMIPS_ABI_FP_DOUBLE = 1,
+
+  /* Using hard-float -msingle-float.  */
+  Val_GNU_NANOMIPS_ABI_FP_SINGLE = 2,
+
+  /* Using soft-float.  */
+  Val_GNU_NANOMIPS_ABI_FP_SOFT = 3,
+
+  /* Not tagged or not using any ABIs affected by the differences.  */
+  Val_GNU_NANOMIPS_ABI_MSA_ANY = 0,
+
+  /* Using 128-bit MSA.  */
+  Val_GNU_NANOMIPS_ABI_MSA_128 = 1,
+};
+
+/* Masks for the ases word of an ABI flags structure.
+
+   Unfortunate decisions in early development transitioning from MIPS
+   to nanoMIPS, left this horifically fragmented.  Bits marked as
+   UNUSED may be cannibalized for future ASEs;  bits marked as RESERVED
+   are intended to remain blocked.  If MIPS history is anything to go
+   by, nanoMIPS will eventually spawn enough ASEs to fill up the gaps!
+*/
+
+#define NANOMIPS_ASE_TLB          0x00000001 /* TLB control ASE.  */
+#define NANOMIPS_ASE_UNUSED1      0x00000002 /* was DSP R2 ASE.  */
+#define NANOMIPS_ASE_EVA          0x00000004 /* Enhanced VA Scheme.  */
+#define NANOMIPS_ASE_MCU          0x00000008 /* MCU (MicroController) ASE.  */
+#define NANOMIPS_ASE_UNUSED2      0x00000010 /* was MDMX ASE.  */
+#define NANOMIPS_ASE_UNUSED3      0x00000020 /* was MIPS-3D ASE.  */
+#define NANOMIPS_ASE_MT           0x00000040 /* MT ASE.  */
+#define NANOMIPS_ASE_UNUSED4      0x00000080 /* was SmartMIPS ASE.  */
+#define NANOMIPS_ASE_VIRT         0x00000100 /* VZ ASE.  */
+#define NANOMIPS_ASE_MSA          0x00000200 /* MSA ASE.  */
+#define NANOMIPS_ASE_RESERVED1    0x00000400 /* was MIPS16 ASE.  */
+#define NANOMIPS_ASE_RESERVED2    0x00000800 /* was MICROMIPS ASE.  */
+#define NANOMIPS_ASE_UNUSED6      0x00001000 /* was XPA.  */
+#define NANOMIPS_ASE_DSPR3        0x00002000 /* DSP R3 ASE.  */
+#define NANOMIPS_ASE_UNUSED5      0x00004000 /* was MIPS16 E2 Extension.  */
+#define NANOMIPS_ASE_CRC          0x00008000 /* CRC extension.  */
+#define NANOMIPS_ASE_CRYPTO       0x00010000 /* Cryptography extension.  */
+#define NANOMIPS_ASE_GINV         0x00020000 /* GINV ASE.  */
+#define NANOMIPS_ASE_xNMS         0x00040000 /* not nanoMIPS Subset.  */
+#define NANOMIPS_ASE_MASK         0x0007af4d /* All valid ASEs.  */
+
+/* nanoMIPS ELF flags routines.  */
+extern Elf_Internal_ABIFlags_v0 * bfd_nanomips_elf_get_abiflags (bfd *);
+
+extern void bfd_nanomips_elf_swap_abiflags_v0_in
+  (bfd *, const Elf_External_ABIFlags_v0 *, Elf_Internal_ABIFlags_v0 *);
+extern void bfd_nanomips_elf_swap_abiflags_v0_out
+  (bfd *, const Elf_Internal_ABIFlags_v0 *, Elf_External_ABIFlags_v0 *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ELF_NANOMIPS_H */