public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v2 1/2] sim: Add nanoMIPS port
@ 2022-05-31 11:35 Aleksandar Rikalo
  2022-05-31 11:35 ` [PATCH v2 2/2] gdb: " Aleksandar Rikalo
  0 siblings, 1 reply; 3+ messages in thread
From: Aleksandar Rikalo @ 2022-05-31 11:35 UTC (permalink / raw)
  To: gdb-patches

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>
---
 sim/common/sim-bits.h     |    4 +
 sim/configure             |    2 +-
 sim/configure.ac          |    2 +-
 sim/mips/Makefile.in      |   28 +
 sim/mips/configure        |   28 +
 sim/mips/configure.ac     |   28 +
 sim/mips/interp.c         |   21 +-
 sim/mips/micromips16.dc   |    3 +
 sim/mips/mips.igen        |  193 ++-
 sim/mips/nanomipsdsp.igen | 1115 +++++++++++++++
 sim/mips/nanomipsr6.igen  | 2744 +++++++++++++++++++++++++++++++++++++
 sim/mips/nanomipsrun.c    |  109 ++
 sim/mips/nms.c            |   44 +
 sim/mips/sim-main.h       |   61 +-
 14 files changed, 4358 insertions(+), 24 deletions(-)
 create mode 100644 sim/mips/nanomipsdsp.igen
 create mode 100644 sim/mips/nanomipsr6.igen
 create mode 100644 sim/mips/nanomipsrun.c
 create mode 100644 sim/mips/nms.c

diff --git a/sim/common/sim-bits.h b/sim/common/sim-bits.h
index fab1dab478c..8799916de26 100644
--- a/sim/common/sim-bits.h
+++ b/sim/common/sim-bits.h
@@ -499,15 +499,19 @@ INLINE_SIM_BITS(unsigned_word) MSINSERTED (unsigned_word val, int start, int sto
 #define EXTEND4(X)  (LSSEXT ((X), 3))
 #define EXTEND5(X)  (LSSEXT ((X), 4))
 #define EXTEND6(X)  (LSSEXT ((X), 5))
+#define EXTEND7(X)  (LSSEXT ((X), 6))
 #define EXTEND8(X)  ((signed_word)(int8_t)(X))
 #define EXTEND9(X)  (LSSEXT ((X), 8))
+#define EXTEND10(X)  (LSSEXT ((X), 9))
 #define EXTEND11(X)  (LSSEXT ((X), 10))
 #define EXTEND12(X)  (LSSEXT ((X), 11))
+#define EXTEND14(X)  (LSSEXT ((X), 13))
 #define EXTEND15(X)  (LSSEXT ((X), 14))
 #define EXTEND16(X) ((signed_word)(int16_t)(X))
 #define EXTEND18(X)  (LSSEXT ((X), 17))
 #define EXTEND19(X)  (LSSEXT ((X), 18))
 #define EXTEND21(X)  (LSSEXT ((X), 20))
+#define EXTEND22(X)  (LSSEXT ((X), 21))
 #define EXTEND24(X)  (LSSEXT ((X), 23))
 #define EXTEND25(X)  (LSSEXT ((X), 24))
 #define EXTEND26(X)  (LSSEXT ((X), 25))
diff --git a/sim/configure b/sim/configure
index b31c2f5d8f3..2977061d458 100755
--- a/sim/configure
+++ b/sim/configure
@@ -15285,7 +15285,7 @@ fi
 
       sim_enable_arch_mips=false
   case "${targ}" in
-    all|mips*-*-*)
+    all|mips*-*-*|nanomips*-*-*)
       if test "${targ}" = "${target}"; then
         SIM_PRIMARY_TARGET=mips
       fi
diff --git a/sim/configure.ac b/sim/configure.ac
index 66a1020efe0..ff8da89a9ab 100644
--- a/sim/configure.ac
+++ b/sim/configure.ac
@@ -137,7 +137,7 @@ if test "${enable_sim}" != no; then
     SIM_TARGET([m68hc11-*-*|m6811-*-*], [m68hc11])
     SIM_TARGET([mcore-*-*], [mcore])
     SIM_TARGET([microblaze*-*-*], [microblaze])
-    SIM_TARGET([mips*-*-*], [mips], [true], [sim_igen=yes])
+    SIM_TARGET([mips*-*-*|nanomips*-*-*], [mips], [true], [sim_igen=yes])
     SIM_TARGET([mn10300*-*-*], [mn10300], [true], [sim_igen=yes])
     SIM_TARGET([moxie-*-*], [moxie])
     SIM_TARGET([msp430*-*-*], [msp430])
diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in
index 75438be5a18..8637b46b186 100644
--- a/sim/mips/Makefile.in
+++ b/sim/mips/Makefile.in
@@ -61,6 +61,7 @@ SIM_OBJS = \
 	cp1.o \
 	mdmx.o \
 	dsp.o \
+	nms.o \
 	sim-main.o \
 	sim-resume.o \
 
@@ -99,6 +100,8 @@ IGEN_INCLUDE=\
 	$(srcdir)/dsp2.igen \
 	$(srcdir)/mips3264r2.igen \
 	$(srcdir)/mips3264r6.igen \
+	$(srcdir)/nanomipsdsp.igen \
+	$(srcdir)/nanomipsr6.igen
 
 # NB:	Since these can be built by a number of generators, care
 #	must be taken to ensure that they are only dependant on
@@ -463,8 +466,11 @@ tmp-mach-multi: $(IGEN_INSN) $(IGEN_DC) $(IGEN) $(IGEN_INCLUDE)
 	  f=`echo $${t} | sed -e 's/.*://'` ; \
 	  case $${p} in \
 	    micromips16*) e="-B 16 -H 15 -o $(MICROMIPS16_DC) -F 16" ;; \
+	    nanomips16*) e="-B 16 -H 15 -o $(MICROMIPS16_DC) -F 16" ;; \
 	    micromips32* | micromips64*) \
 		e="-B 32 -H 31 -o $(MICROMIPS32_DC) -F $${f}" ;; \
+	    nanomips32* | nanomips64*) \
+		e="-B 32 -H 31 -o $(MICROMIPS32_DC) -F $${f}" ;; \
 	    micromips_m32*) \
 		e="-B 32 -H 31 -o $(IGEN_DC) -F $${f}"; \
 		m="mips32r2,mips3d,mdmx,dsp,dsp2,smartmips" ;; \
@@ -579,6 +585,28 @@ tmp-run-multi: $(srcdir)/m16run.c $(srcdir)/micromipsrun.c
 	      $(SHELL) $(srcdir)/../../move-if-change tmp-run \
 						      micromips$${m}_run.c ; \
              ;;\
+	    nanomips32*) \
+	      m=`echo $${t} | sed -e 's/^nanomips32//' -e 's/:.*//'`; \
+	      sed <  $(srcdir)/nanomipsrun.c > tmp-run \
+		    -e "s/^sim_/nanomips32$${m}_/" \
+		    -e "s/nanomips_instruction_decode/nanomips32$${m}_instruction_decode/g" \
+		    -e "s/nanomips16_/nanomips16$${m}_/" \
+		    -e "s/nanomips32_/nanomips32$${m}_/" \
+		    -e "s/m32_/m32$${m}_/" ; \
+	      $(SHELL) $(srcdir)/../../move-if-change tmp-run \
+						      nanomips$${m}_run.c ; \
+             ;;\
+	    nanomips64*) \
+	      m=`echo $${t} | sed -e 's/^nanomips64//' -e 's/:.*//'`; \
+	      sed <  $(srcdir)/nanomipsrun.c > tmp-run \
+		    -e "s/^sim_/nanomips64$${m}_/" \
+		    -e "s/nanomips_instruction_decode/nanomips64$${m}_instruction_decode/g" \
+		    -e "s/nanomips16_/nanomips16$${m}_/" \
+		    -e "s/nanomips32_/nanomips64$${m}_/" \
+		    -e "s/m32_/m64$${m}_/" ; \
+	      $(SHELL) $(srcdir)/../../move-if-change tmp-run \
+						      nanomips$${m}_run.c ; \
+             ;;\
 	  esac \
 	done
 	$(SILENCE) touch $@
diff --git a/sim/mips/configure b/sim/mips/configure
index 2f635a50e10..ab0079a7f35 100755
--- a/sim/mips/configure
+++ b/sim/mips/configure
@@ -1874,6 +1874,12 @@ case "${target}" in
 			  mipsisa64r6:mips64r6:32,64,f:mipsisa32r6,mipsisa64r6"
 			sim_multi_default=mipsisa64r2
 			;;
+  nanomips*-elf*)
+			sim_gen=MULTI
+			sim_multi_configs="\
+			  nanor6sim:nanomips64r6,nanomipsdsp:32,64,f:nanomipsisa64r6,nanomipsisa32r6"
+			sim_multi_default=nanomipsisa32r6
+			;;
   mips64*-*-*)		sim_igen_filter="32,64,f"
 			sim_gen=IGEN
 			;;
@@ -2072,6 +2078,17 @@ __EOF__
 	sim_multi_obj="${sim_multi_obj} micromips${name}_run.o"
 	sim_multi_flags="${sim_multi_flags} -F 16,32"
 	;;
+      *:*nanomips32*)
+	# Run igen twice, once for nanomips32 and once for nanomips16.
+	ws="nanomips16 nanomips32"
+
+	# The top-level function for the micromips simulator is
+	# in a file micromips${name}_run.c, generated by the
+	# tmp-run-multi Makefile rule.
+	sim_multi_src="${sim_multi_src} nanomips${name}_run.c"
+	sim_multi_obj="${sim_multi_obj} nanomips${name}_run.o"
+	sim_multi_flags="${sim_multi_flags} -F 16,32"
+	;;
       *:*micromips64*:*)
 	# Run igen thrice, once for micromips64, once for micromips16,
 	# and once for m64.
@@ -2084,6 +2101,17 @@ __EOF__
 	sim_multi_obj="${sim_multi_obj} micromips${name}_run.o"
 	sim_multi_flags="${sim_multi_flags} -F 16,32,64"
 	;;
+      *:*nanomips64*)
+	# Run igen twice, once for nanomips64 and once for nanomips16.
+	ws="nanomips16 nanomips64"
+
+	# The top-level function for the micromips simulator is
+	# in a file micromips${name}_run.c, generated by the
+	# tmp-run-multi Makefile rule.
+	sim_multi_src="${sim_multi_src} nanomips${name}_run.c"
+	sim_multi_obj="${sim_multi_obj} nanomips${name}_run.o"
+	sim_multi_flags="${sim_multi_flags} -F 16,32,64"
+	;;
       *)
 	ws=m32
 	;;
diff --git a/sim/mips/configure.ac b/sim/mips/configure.ac
index 96806424958..0d48b9630d9 100644
--- a/sim/mips/configure.ac
+++ b/sim/mips/configure.ac
@@ -106,6 +106,12 @@ case "${target}" in
 			  mipsisa64r6:mips64r6:32,64,f:mipsisa32r6,mipsisa64r6"
 			sim_multi_default=mipsisa64r2
 			;;
+  nanomips*-*-elf*)
+			sim_gen=MULTI
+			sim_multi_configs="\
+			  nanor6sim:nanomips64r6,nanomipsdsp:32,64,f:nanomipsisa64r6,nanomipsisa32r6"
+			sim_multi_default=nanomipsisa64r6
+			;;
   mips64*-*-*)		sim_igen_filter="32,64,f"
 			sim_gen=IGEN
 			;;
@@ -304,6 +310,17 @@ __EOF__
 	sim_multi_obj="${sim_multi_obj} micromips${name}_run.o"
 	sim_multi_flags="${sim_multi_flags} -F 16,32"
 	;;
+      *:*nanomips32*)
+	# Run igen twice, once for nanomips32 and once for nanomips16.
+	ws="nanomips16 nanomips32"
+
+	# The top-level function for the micromips simulator is
+	# in a file micromips${name}_run.c, generated by the
+	# tmp-run-multi Makefile rule.
+	sim_multi_src="${sim_multi_src} nanomips${name}_run.c"
+	sim_multi_obj="${sim_multi_obj} nanomips${name}_run.o"
+	sim_multi_flags="${sim_multi_flags} -F 16,32"
+	;;
       *:*micromips64*:*)
 	# Run igen thrice, once for micromips64, once for micromips16,
 	# and once for m64.
@@ -316,6 +333,17 @@ __EOF__
 	sim_multi_obj="${sim_multi_obj} micromips${name}_run.o"
 	sim_multi_flags="${sim_multi_flags} -F 16,32,64"
 	;;
+      *:*nanomips64*)
+	# Run igen twice, once for nanomips64 and once for nanomips16.
+	ws="nanomips16 nanomips64"
+
+	# The top-level function for the micromips simulator is
+	# in a file micromips${name}_run.c, generated by the
+	# tmp-run-multi Makefile rule.
+	sim_multi_src="${sim_multi_src} nanomips${name}_run.c"
+	sim_multi_obj="${sim_multi_obj} nanomips${name}_run.o"
+	sim_multi_flags="${sim_multi_flags} -F 16,32,64"
+	;;
       *)
 	ws=m32
 	;;
diff --git a/sim/mips/interp.c b/sim/mips/interp.c
index e46e817eed9..a4c6cee800a 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -356,6 +356,8 @@ sim_open (SIM_OPEN_KIND kind, host_callback *cb,
 
   cpu = STATE_CPU (sd, 0); /* FIXME */
 
+  IS_NANOMIPS = 0;
+
   /* FIXME: watchpoints code shouldn't need this */
   STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event;
 
@@ -672,10 +674,13 @@ sim_open (SIM_OPEN_KIND kind, host_callback *cb,
 	  cpu->register_widths[rn] = WITH_TARGET_FLOATING_POINT_BITSIZE;
 	else if ((rn >= 33) && (rn <= 37))
 	  cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
+	else if ((rn >= 70) && (rn <= 78))
+	  cpu->register_widths[rn] = WITH_TARGET_WORD_BITSIZE;
 	else if ((rn == SRIDX)
 		 || (rn == FCR0IDX)
 		 || (rn == FCR31IDX)
-		 || ((rn >= 72) && (rn <= 89)))
+		 || (rn == DSPCRIDX)
+		 || ((rn >= 80) && (rn <= 89)))
 	  cpu->register_widths[rn] = 32;
 	else
 	  cpu->register_widths[rn] = 0;
@@ -1200,7 +1205,7 @@ sim_monitor (SIM_DESC sd,
     case 6: /* int open(char *path,int flags) */
       {
 	char *path = fetch_str (sd, A0);
-	V0 = sim_io_open (sd, path, (int)A1);
+	SET_RV0 (sim_io_open (sd, path, (int)A1));
 	free (path);
 	break;
       }
@@ -1210,7 +1215,7 @@ sim_monitor (SIM_DESC sd,
 	int fd = A0;
 	int nr = A2;
 	char *buf = zalloc (nr);
-	V0 = sim_io_read (sd, fd, buf, nr);
+	SET_RV0 (sim_io_read (sd, fd, buf, nr));
 	sim_write (sd, A1, (unsigned char *)buf, nr);
 	free (buf);
       }
@@ -1222,7 +1227,7 @@ sim_monitor (SIM_DESC sd,
 	int nr = A2;
 	char *buf = zalloc (nr);
 	sim_read (sd, A1, (unsigned char *)buf, nr);
-	V0 = sim_io_write (sd, fd, buf, nr);
+	SET_RV0 (sim_io_write (sd, fd, buf, nr));
 	if (fd == 1)
 	    sim_io_flush_stdout (sd);
 	else if (fd == 2)
@@ -1233,14 +1238,14 @@ sim_monitor (SIM_DESC sd,
 
     case 10: /* int close(int file) */
       {
-	V0 = sim_io_close (sd, (int)A0);
+	SET_RV0 (sim_io_close (sd, (int)A0));
 	break;
       }
 
     case 2:  /* Densan monitor: char inbyte(int waitflag) */
       {
 	if (A0 == 0)	/* waitflag == NOWAIT */
-	  V0 = (unsigned_word)-1;
+	    SET_RV0 ((unsigned_word)-1);
       }
      /* Drop through to case 11 */
 
@@ -1252,10 +1257,10 @@ sim_monitor (SIM_DESC sd,
         if (sim_io_read_stdin (sd, &tmp, sizeof(char)) != sizeof(char))
 	  {
 	    sim_io_error(sd,"Invalid return from character read");
-	    V0 = (unsigned_word)-1;
+	    SET_RV0 ((unsigned_word)-1);
 	  }
         else
-	  V0 = (unsigned_word)tmp;
+	    SET_RV0 ((unsigned_word)tmp);
 	break;
       }
 
diff --git a/sim/mips/micromips16.dc b/sim/mips/micromips16.dc
index a1cd9a0ea89..ace9bb94fad 100644
--- a/sim/mips/micromips16.dc
+++ b/sim/mips/micromips16.dc
@@ -8,4 +8,7 @@
 
   switch,combine        :  9 :    6 :    :    :    :      :      :
   switch,combine        :  9 :    5 :    :    :    :      :      :
+  switch,combine        :  3 :    0 :    :    :    :      :      :
+  switch,combine        :  2 :    0 :    :    :    :      :      :
+  switch,combine        :  5 :    3 :    :    :    :      :      :
   switch,combine        :  0 :    0 :    :    :    :      :      :
diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen
index dfad4227615..95366daa371 100644
--- a/sim/mips/mips.igen
+++ b/sim/mips/mips.igen
@@ -79,6 +79,9 @@
 :model:::micromips32:micromips64:	// micromips.igen
 :model:::micromips64:micromips64:	// micromips.igen
 :model:::micromipsdsp:micromipsdsp:	// micromipsdsp.igen
+:model:::nanomips32r6:nanomips32r6: // nanomipsr6.igen
+:model:::nanomips64r6:nanomips64r6: // nanomipsr6.igen
+:model:::nanomipsdsp:nanomipsdsp: // nanompsdsp.igen
 
 //  Vendor Extensions
 //
@@ -98,6 +101,33 @@
 // For grep - RSVD_INSTRUCTION, RSVD_INSTRUCTION_MASK
 000000,5.*,5.*,5.*,5.OP,111001:SPECIAL:32::RSVD
 "rsvd <OP>"
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr4120:
+*vr5000:
+*vr5400:
+*vr5500:
+*r3900:
+*mips16:
+*mips16e:
+*mips3d:
+*mdmx:
+*dsp:
+*dsp2:
+*smartmips:
+*micromips32:
+*micromips64:
+*micromipsdsp:
 {
   SignalException (ReservedInstruction, instruction_0);
 }
@@ -192,6 +222,7 @@
 *vr5000:
 *r3900:
 *micromips32:
+*nanomips32r6:
 {
   return base + offset;
 }
@@ -201,6 +232,7 @@
 *mips64r2:
 *micromips64:
 *mips64r6:
+*nanomips64r6:
 {
 #if 0 /* XXX FIXME: enable this only after some additional testing.  */
   /* If in user mode and UX is not set, use 32-bit compatibility effective
@@ -237,6 +269,8 @@
 *micromips32:
 *micromips64:
 *mips64r6:
+*nanomips32r6:
+*nanomips64r6:
 {
 #if WITH_TARGET_WORD_BITSIZE == 64
   return value != (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
@@ -274,6 +308,8 @@
 *micromips32:
 *micromips64:
 *mips64r6:
+*nanomips32r6:
+*nanomips64r6:
 {
   unpredictable_action (CPU, CIA);
 }
@@ -369,6 +405,7 @@
 *r3900:
 *micromips32:
 *micromips64:
+*nanomipsdsp:
 {
   int64_t time = sim_events_time (SD);
   history->mt.timestamp = time;
@@ -399,6 +436,7 @@
 *r3900:
 *micromips32:
 *micromips64:
+*nanomipsdsp:
 {
   int64_t time = sim_events_time (SD);
   int ok = 1;
@@ -473,6 +511,7 @@
 *r3900:
 *micromips32:
 *micromips64:
+*nanomipsdsp:
 {
   /* FIXME: could record the fact that a stall occured if we want */
   int64_t time = sim_events_time (SD);
@@ -570,6 +609,8 @@
 *micromips64:
 *micromips32:
 *mips64r6:
+*nanomips32r6:
+*nanomips64r6:
 {
 #if 0 /* XXX FIXME: enable this only after some additional testing.  */
   if (UserMode && (SR & (status_UX|status_PX)) == 0)
@@ -781,12 +822,44 @@
 }
 
 :function:::void:do_lb:int rt, int offset, int base
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips32:
+*micromips64:
 {
   GPR[rt] = EXTEND8 (do_load (SD_, AccessLength_BYTE, GPR[base],
 			      EXTEND16 (offset)));
 }
 
 :function:::void:do_lh:int rt, int offset, int base
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips32:
+*micromips64:
 {
   GPR[rt] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[base],
 			       EXTEND16 (offset)));
@@ -811,6 +884,22 @@
 }
 
 :function:::void:do_lw:int rt, int offset, int base
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips32:
+*micromips64:
 {
   GPR[rt] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[base],
 			       EXTEND16 (offset)));
@@ -823,6 +912,22 @@
 }
 
 :function:::void:do_lhu:int rt, int offset, int base
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips32:
+*micromips64:
 {
   GPR[rt] = do_load (SD_, AccessLength_HALFWORD, GPR[base], EXTEND16 (offset));
 }
@@ -1861,7 +1966,23 @@
 
 
 
-:function:::void:do_addiu:int rs, int rt, uint16_t immediate
+:function:::void:do_addiu:int rs, int rt, int immediate
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips32:
+*micromips64:
 {
   if (NotWordValue (GPR[rs]))
     Unpredictable ();
@@ -2595,6 +2716,14 @@
 
 
 :function:::void:do_ddiv:int rs, int rt
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips64:
+*mips64r2:
+*micromips64:
+*vr4100:
+*vr5000:
 {
   check_div_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
@@ -2641,6 +2770,14 @@
 
 
 :function:::void:do_ddivu:int rs, int rt
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips64:
+*mips64r2:
+*micromips64:
+*vr4100:
+*vr5000:
 {
   check_div_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
@@ -2680,6 +2817,20 @@
 }
 
 :function:::void:do_div:int rs, int rt
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*micromips32:
+*mips64:
+*mips64r2:
+*micromips64:
+*vr4100:
+*vr5000:
+*r3900:
 {
   check_div_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
@@ -2726,6 +2877,20 @@
 
 
 :function:::void:do_divu:int rs, int rt
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*mips32:
+*mips32r2:
+*micromips32:
+*mips64:
+*mips64r2:
+*micromips64:
+*vr4100:
+*vr5000:
+*r3900:
 {
   check_div_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
@@ -3714,6 +3879,25 @@
 
 
 :function:::void:do_mfhi:int rd
+*mipsI:
+*mipsII:
+*mipsIII:
+*mipsIV:
+*mipsV:
+*vr4100:
+*vr5000:
+*r3900:
+*mips32:
+*mips64:
+*mips32r2:
+*mips32r6:
+*mips64r2:
+*mips64r6:
+*dsp:
+*micromips32:
+*micromips64:
+*micromipsdsp:
+*nanomipsdsp:
 {
   check_mf_hilo (SD_, HIHISTORY, LOHISTORY);
   TRACE_ALU_INPUT1 (HI);
@@ -5225,6 +5409,8 @@
 *vr4100:
 *vr5000:
 *r3900:
+*nanomips32r6:
+*nanomips64r6:
 {
   /* None of these ISAs support Paired Single, so just fall back to
      the single/double check.  */
@@ -5273,6 +5459,8 @@
 *r3900:
 *micromips32:
 *micromips64:
+*nanomips32r6:
+*nanomips64r6:
 {
   if (! COP_Usable (1))
     SignalExceptionCoProcessorUnusable (1);
@@ -6867,4 +7055,5 @@
 :include:::smartmips.igen
 :include:::micromips.igen
 :include:::micromipsdsp.igen
-
+:include:::nanomipsr6.igen
+:include:::nanomipsdsp.igen
diff --git a/sim/mips/nanomipsdsp.igen b/sim/mips/nanomipsdsp.igen
new file mode 100644
index 00000000000..07fd26b6ad0
--- /dev/null
+++ b/sim/mips/nanomipsdsp.igen
@@ -0,0 +1,1115 @@
+// Simulator definition for the micromips ASE.
+// Copyright (C) 2018-2022 Free Software Foundation, Inc.
+// Contributed by Imagination Technologies, Ltd.
+// Written by Ali Lown <ali.lown@imgtec.com>
+//
+// This file is part of GDB, the GNU debugger.
+//
+// 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, see <http://www.gnu.org/licenses/>.
+
+001000,5.RT,5.RS,0001000100111111:POOL32A:32::ABSQ_S.PH
+"absq_s.ph r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_ph_s_absq (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,0000000100111111:POOL32A:32::ABSQ_S.QB
+"absq_s.qb r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_s_absq (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,0010000100111111:POOL32A:32::ABSQ_S.W
+"absq_s.w r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_w_s_absq (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,5.RD,00000001101:POOL32A:32::ADDQ.PH
+"addq.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10000001101:POOL32A:32::ADDQ_S.PH
+"addq_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1100000101:POOL32A:32::ADDQ_S.W
+"addq_s.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_w_op (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,00001001101:POOL32A:32::ADDQH.PH
+"addqh.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qh_ph_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10001001101:POOL32A:32::ADDQH_R.PH
+"addqh_r.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qh_ph_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,00010001101:POOL32A:32::ADDQH.W
+"addqh.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qh_w_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10010001101:POOL32A:32::ADDQH_R.W
+"addqh_r.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qh_w_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1110000101:POOL32A:32::ADDSC
+"addsc r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_addsc (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,00100001101:POOL32A:32::ADDU.PH
+"addu.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_u_ph_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10100001101:POOL32A:32::ADDU_S.PH
+"addu_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_u_ph_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,00011001101:POOL32A:32::ADDU.QB
+"addu.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10011001101:POOL32A:32::ADDU_S.QB
+"addu_s.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1111000101:POOL32A:32::ADDWC
+"addwc r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_addwc (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,00101001101:POOL32A:32::ADDUH.QB
+"adduh.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_uh_qb_op (SD_, RD, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10101001101:POOL32A:32::ADDUH_R.QB
+"adduh_r.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_uh_qb_op (SD_, RD, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,5.SA,1.X,1000010101:POOL32A:32::APPEND
+"append r<RT>, r<RS>, <SA>"
+*nanomipsdsp:
+{
+  do_append (SD_, RT, RS, SA);
+}
+
+001000,5.RT,5.RS,2.BP,00100010111111:POOL32A:32::BALIGN
+"balign r<RT>, r<RS>, <BP>"
+*nanomipsdsp:
+{
+  do_balign (SD_, RT, RS, BP);
+}
+
+001000,5.RT,5.RS,0011000100111111:POOL32A:32::BITREV
+"bitrev r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_bitrev (SD_, RT, RS);
+}
+
+100010,5.X,0010001,13.S1,1.S2:POOL32I:32::BPOSGE32C
+"bposge32c <ADDRESS15>"
+*nanomipsdsp:
+{
+  uint32_t pos = (DSPCR >> DSPCR_POS_SHIFT) & DSPCR_POS_MASK;
+  if (pos >= 32)
+    NIA = ADDRESS15;
+}
+
+001000,5.RT,5.RS,6.X,0000000101:POOL32A:32::CMP.EQ.PH
+"cmp.eq.ph r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_cmpu (SD_, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,0000000001,000101:POOL32A:32::CMP.LT.PH
+"cmp.lt.ph r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_cmpu (SD_, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,0000000010,000101:POOL32A:32::CMP.LE.PH
+"cmp.le.ph r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_cmpu (SD_, RS, RT, 2);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0110000101:POOL32A:32::CMPGDU.EQ.QB
+"cmpgdu.eq.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_cmpgdu (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0111000101:POOL32A:32::CMPGDU.LT.QB
+"cmpgdu.lt.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_cmpgdu (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1000000101:POOL32A:32::CMPGDU.LE.QB
+"cmpgdu.le.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_cmpgdu (SD_, RD, RS, RT, 2);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0011000101:POOL32A:32::CMPGU.EQ.QB
+"cmpgu.eq.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_cmpgu (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0100000101:POOL32A:32::CMPGU.LT.QB
+"cmpgu.lt.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_cmpgu (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0101000101:POOL32A:32::CMPGU.LE.QB
+"cmpgu.le.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_cmpgu (SD_, RD, RS, RT, 2);
+}
+
+001000,5.RT,5.RS,5.X1,1.X2,1001000101:POOL32A:32::CMPU.EQ.QB
+"cmpu.eq.qb r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_cmpu (SD_, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.X1,1.X2,1010000101:POOL32A:32::CMPU.LT.QB
+"cmpu.lt.qb r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_cmpu (SD_, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.X1,1.X2,1011000101:POOL32A:32::CMPU.LE.QB
+"cmpu.le.qb r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_cmpu (SD_, RS, RT, 2);
+}
+
+001000,5.RT,5.RS,2.AC,00000010111111:POOL32A:32::DPA.W.PH
+"dpa.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_w_ph_dot_product (SD_, AC, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,2.AC,00001010111111:POOL32A:32::DPAQ_S.W.PH
+"dpaq_s.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_dot_product (SD_, AC, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,2.AC,01001010111111:POOL32A:32::DPAQ_SA.L.W
+"dpaq_sa.l.w ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_w_dot_product (SD_, AC, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,2.AC,10001010111111:POOL32A:32::DPAQX_S.W.PH
+"dpaqx_s.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qx_w_ph_dot_product (SD_, AC, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,2.AC,11001010111111:POOL32A:32::DPAQX_SA.W.PH
+"dpaqx_sa.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qx_w_ph_dot_product (SD_, AC, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10000010111111:POOL32A:32::DPAU.H.QBL
+"dpau.h.qbl ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_dot_product (SD_, AC, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,2.AC,11000010111111:POOL32A:32::DPAU.H.QBR
+"dpau.h.qbr ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_dot_product (SD_, AC, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,2.AC,01000010111111:POOL32A:32::DPAX.W.PH
+"dpax.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_x_w_ph_dot_product (SD_, AC, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,2.AC,00010010111111:POOL32A:32::DPS.W.PH
+"dps.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_w_ph_dot_product (SD_, AC, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,2.AC,00011010111111:POOL32A:32::DPSQ_S.W.PH
+"dpsq_s.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_dot_product (SD_, AC, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,2.AC,01011010111111:POOL32A:32::DPSQ_SA.L.W
+"dpsq_sa.l.w ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_w_dot_product (SD_, AC, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10011010111111:POOL32A:32::DPSQX_S.W.PH
+"dpsqx_s.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qx_w_ph_dot_product (SD_, AC, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,2.AC,11011010111111:POOL32A:32::DPSQX_SA.W.PH
+"dpsqx_sa.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qx_w_ph_dot_product (SD_, AC, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10010010111111:POOL32A:32::DPSU.H.QBL
+"dpsu.h.qbl ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_dot_product (SD_, AC, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,2.AC,11010010111111:POOL32A:32::DPSU.H.QBR
+"dpsu.h.qbr ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_dot_product (SD_, AC, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,2.AC,01010010111111:POOL32A:32::DPSX.W.PH
+"dpsx.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_x_w_ph_dot_product (SD_, AC, RS, RT, 1);
+}
+
+001000,5.RT,5.SIZE,2.AC,10011001111111:POOL32A:32::EXTP
+"extp r<RT>, ac<AC>, <SIZE>"
+*nanomipsdsp:
+{
+  do_extp (SD_, RT, AC, SIZE, 0);
+}
+
+001000,5.RT,5.SIZE,2.AC,11011001111111:POOL32A:32::EXTPDP
+"extpdp r<RT>, ac<AC>, <SIZE>"
+*nanomipsdsp:
+{
+  do_extp (SD_, RT, AC, SIZE, 1);
+}
+
+001000,5.RT,5.RS,2.AC,11100010111111:POOL32A:32::EXTPDPV
+"extpdpv r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+  do_extpv (SD_, RT, AC, RS, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10100010111111:POOL32A:32::EXTPV
+"extpv r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+  do_extpv (SD_, RT, AC, RS, 0);
+}
+
+001000,5.RT,5.SHIFT,2.AC,00111001111111:POOL32A:32::EXTR.W
+"extr.w r<RT>, ac<AC>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_w_extr (SD_, RT, AC, SHIFT, 0);
+}
+
+001000,5.RT,5.SHIFT,2.AC,01111001111111:POOL32A:32::EXTR_R.W
+"extr_r.w r<RT>, ac<AC>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_w_extr (SD_, RT, AC, SHIFT, 1);
+}
+
+001000,5.RT,5.SHIFT,2.AC,10111001111111:POOL32A:32::EXTR_RS.W
+"extr_rs.w r<RT>, ac<AC>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_w_extr (SD_, RT, AC, SHIFT, 2);
+}
+
+001000,5.RT,5.SHIFT,2.AC,11111001111111:POOL32A:32::EXTR_S.H
+"extr_s.h r<RT>, ac<AC>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_h_extr (SD_, RT, AC, SHIFT);
+}
+
+001000,5.RT,5.RS,2.AC,00111010111111:POOL32A:32::EXTRV.W
+"extrv.w r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+  do_extrv (SD_, RT, AC, RS, 0);
+}
+
+001000,5.RT,5.RS,2.AC,01111010111111:POOL32A:32::EXTRV_R.W
+"extrv_r.w r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+  do_extrv (SD_, RT, AC, RS, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10111010111111:POOL32A:32::EXTRV_RS.W
+"extrv_rs.w r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+  do_extrv (SD_, RT, AC, RS, 2);
+}
+
+001000,5.RT,5.RS,2.AC,11111010111111:POOL32A:32::EXTRV_S.H
+"extrv_s.h r<RT>, ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+  do_extrv_s_h (SD_, RT, AC, RS);
+}
+
+001000,5.RT,5.RS,0100000100111111:POOL32A:32::INSV
+"insv r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_insv (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,2.AC,00101010111111:POOL32A:32::MADD_DSP
+"madd ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_dsp_madd (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,01101010111111:POOL32A:32::MADDU_DSP
+"maddu ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_dsp_maddu (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,01101001111111:POOL32A:32::MAQ_S.W.PHL
+"maq_s.w.phl ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_maq (SD_, AC, RS, RT, 0, 0);
+}
+
+001000,5.RT,5.RS,2.AC,11101001111111:POOL32A:32::MAQ_SA.W.PHL
+"maq_sa.w.phl ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_maq (SD_, AC, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,2.AC,00101001111111:POOL32A:32::MAQ_S.W.PHR
+"maq_s.w.phr ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_maq (SD_, AC, RS, RT, 0, 1);
+}
+
+001000,5.RT,5.RS,2.AC,10101001111111:POOL32A:32::MAQ_SA.W.PHR
+"maq_sa.w.phr ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_maq (SD_, AC, RS, RT, 1, 1);
+}
+
+001000,5.RS,5.X,2.AC,00000001111111:POOL32A:32::MFHI_DSP
+"mfhi r<RS>, ac<AC>"
+*nanomipsdsp:
+{
+  do_dsp_mfhi (SD_, AC, RS);
+}
+
+001000,5.RS,5.X,2.AC,01000001111111:POOL32A:32::MFLO_DSP
+"mflo r<RS>, ac<AC>"
+*nanomipsdsp:
+{
+  do_dsp_mflo (SD_, AC, RS);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1010010101:POOL32A:32::MODSUB
+"modsub r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_modsub (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,10101010111111:POOL32A:32::MSUB_DSP
+"msub ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_dsp_msub (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,11101010111111:POOL32A:32::MSUBU_DSP
+"msubu ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_dsp_msubu (SD_, AC, RS, RT);
+}
+
+001000,00000,5.RS,2.AC,10000001111111:POOL32A:32::MTHI_DSP
+"mthi r<RS>, ac<AC>"
+*nanomipsdsp:
+{
+  do_dsp_mthi (SD_, AC, RS);
+}
+
+001000,00000,5.RS,2.AC,00001001111111:POOL32A:32::MTHLIP
+"mthlip r<RS>, ac<AC>"
+*nanomipsdsp:
+{
+  do_mthlip (SD_, RS, AC);
+}
+
+001000,00000,5.RS,2.AC,11000001111111:POOL32A:32::MTLO_DSP
+"mtlo r<RS>, ac<AC>"
+*nanomipsdsp:
+{
+  do_dsp_mtlo (SD_, AC, RS);
+}
+
+001000,5.RT,5.RS,5.RD,00000101101:POOL32A:32::MUL.PH
+"mul.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_op (SD_, RD, RS, RT, 2, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10000101101:POOL32A:32::MUL_S.PH
+"mul_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_op (SD_, RD, RS, RT, 2, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0000100101:POOL32A:32::MULEQ_S.W.PHL
+"muleq_s.w.phl r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_muleq (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0001100101:POOL32A:32::MULEQ_S.W.PHR
+"muleq_s.w.phr r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_muleq (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0010010101:POOL32A:32::MULEU_S.PH.QBL
+"muleu_s.ph.qbl r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_muleu (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0011010101:POOL32A:32::MULEU_S.PH.QBR
+"muleu_s.ph.qbr r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_muleu (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0100010101:POOL32A:32::MULQ_RS.PH
+"mulq_rs.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_mulq (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0110010101:POOL32A:32::MULQ_RS.W
+"mulq_rs.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_w_mulq (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0101010101:POOL32A:32::MULQ_S.PH
+"mulq_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_mulq (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0111010101:POOL32A:32::MULQ_S.W
+"mulq_s.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_w_mulq (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,2.AC,10110010111111:POOL32A:32::MULSA.W.PH
+"mulsa.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_w_mulsa (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,11110010111111:POOL32A:32::MULSAQ_S.W.PH
+"mulsaq_s.w.ph ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_mulsaq_s_w_ph (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,00110010111111:POOL32A:32::MULT_DSP
+"mult ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_dsp_mult (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,2.AC,01110010111111:POOL32A:32::MULTU_DSP
+"multu ac<AC>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_dsp_multu (SD_, AC, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0110101101:POOL32A:32::PACKRL.PH
+"packrl.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_packrl (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1000101101:POOL32A:32::PICK.PH
+"pick.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_pick (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0111101101:POOL32A:32::PICK.QB
+"pick.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_pick (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,0101000100111111:POOL32A:32::PRECEQ.W.PHL
+"preceq.w.phl r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_w_preceq (SD_, RT, RS, 0);
+}
+
+001000,5.RT,5.RS,0110000100111111:POOL32A:32::PRECEQ.W.PHR
+"preceq.w.phr r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_w_preceq (SD_, RT, RS, 1);
+}
+
+001000,5.RT,5.RS,0111000100111111:POOL32A:32::PRECEQU.PH.QBL
+"precequ.ph.qbl r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_ph_precequ (SD_, RT, RS, 2);
+}
+
+001000,5.RT,5.RS,0111001100111111:POOL32A:32::PRECEQU.PH.QBLA
+"precequ.ph.qbla r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_ph_precequ (SD_, RT, RS, 3);
+}
+
+001000,5.RT,5.RS,1001000100111111:POOL32A:32::PRECEQU.PH.QBR
+"precequ.ph.qbr r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_ph_precequ (SD_, RT, RS, 0);
+}
+
+001000,5.RT,5.RS,1001001100111111:POOL32A:32::PRECEQU.PH.QBRA
+"precequ.ph.qbra r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_ph_precequ (SD_, RT, RS, 1);
+}
+
+001000,5.RT,5.RS,1011000100111111:POOL32A:32::PRECEU.PH.QBL
+"preceu.ph.qbl r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_ph_preceu (SD_, RT, RS, 2);
+}
+
+001000,5.RT,5.RS,1011001100111111:POOL32A:32::PRECEU.PH.QBLA
+"preceu.ph.qbla r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_ph_preceu (SD_, RT, RS, 3);
+}
+
+001000,5.RT,5.RS,1101000100111111:POOL32A:32::PRECEU.PH.QBR
+"preceu.ph.qbr r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_ph_preceu (SD_, RT, RS, 0);
+}
+
+001000,5.RT,5.RS,1101001100111111:POOL32A:32::PRECEU.PH.QBRA
+"preceu.ph.qbra r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_ph_preceu (SD_, RT, RS, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0001101101:POOL32A:32::PRECR.QB.PH
+"precr.qb.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_qb_precr (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.SA,01111001101:POOL32A:32::PRECR_SRA.PH.W
+"precr_sra.ph.w r<RT>, r<RS>, <SA>"
+*nanomipsdsp:
+{
+  do_precr_sra (SD_, RT, RS, SA, 0);
+}
+
+001000,5.RT,5.RS,5.SA,11111001101:POOL32A:32::PRECR_SRA_R.PH.W
+"precr_sra_r.ph.w r<RT>, r<RS>, <SA>"
+*nanomipsdsp:
+{
+  do_precr_sra (SD_, RT, RS, SA, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0011101101:POOL32A:32::PRECRQ.PH.W
+"precrq.ph.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_w_ph_precrq (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0010101101:POOL32A:32::PRECRQ.QB.PH
+"precrq.qb.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_qb_precrq (SD_, RD, RS, RT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0101101101:POOL32A:32::PRECRQU_S.QB.PH
+"precrqu_s.qb.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_qb_precrq (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0100101101:POOL32A:32::PRECRQ_RS.PH.W
+"precrq_rs.ph.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_w_ph_rs_precrq (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.SA,1.X,1001010101:POOL32A:32::PREPEND
+"prepend r<RT>, r<RS>, <SA>"
+*nanomipsdsp:
+{
+  do_prepend (SD_, RT, RS, SA);
+}
+
+001000,5.RT,5.RS,1111000100111111:POOL32A:32::RADDU.W.QB
+"raddu.w.qb r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_w_raddu (SD_, RT, RS);
+}
+
+001000,5.RT,7.CONTROL_MASK,00011001111111:POOL32A:32::RDDSP
+"rddsp r<RT>":CONTROL_MASK == 1111111111
+"rddsp r<RT>, <CONTROL_MASK>"
+*nanomipsdsp:
+{
+  do_rddsp (SD_, RT, CONTROL_MASK);
+}
+
+001000,5.RT,10.IMMEDIATE,1.X,0000111101:POOL32A:32::REPL.PH
+"repl.ph r<RT>, <IMMEDIATE>"
+*nanomipsdsp:
+{
+  do_repl (SD_, RT, IMMEDIATE, 2);
+}
+
+001000,5.RT,8.IMMEDIATE,1.X,010111111111:POOL32A:32::REPL.QB
+"repl.qb r<RT>, <IMMEDIATE>"
+*nanomipsdsp:
+{
+  do_repl (SD_, RT, IMMEDIATE, 0);
+}
+
+001000,5.RT,5.RS,0000001100111111:POOL32A:32::REPLV.PH
+"replv.ph r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_repl (SD_, RT, RS, 3);
+}
+
+001000,5.RT,5.RS,0001001100111111:POOL32A:32::REPLV.QB
+"replv.qb r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_repl (SD_, RT, RS, 1);
+}
+
+001000,0000,6.IMMEDIATE,2.AC,00000000011101:POOL32A:32::SHILO
+"shilo ac<AC>, <IMMEDIATE>"
+*nanomipsdsp:
+{
+  do_shilo (SD_, AC, IMMEDIATE);
+}
+
+001000,00000,5.RS,2.AC,01001001111111:POOL32A:32::SHILOV
+"shilov ac<AC>, r<RS>"
+*nanomipsdsp:
+{
+  do_shilov (SD_, AC, RS);
+}
+
+001000,5.RT,5.RS,4.SHIFT,001110110101:POOL32A:32::SHLL.PH
+"shll.ph r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_ph_shift (SD_, RT, RS, SHIFT, 0, 0);
+}
+
+001000,5.RT,5.RS,4.SHIFT,101110110101:POOL32A:32::SHLL_S.PH
+"shll_s.ph r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_ph_shift (SD_, RT, RS, SHIFT, 0, 1);
+}
+
+001000,5.RT,5.RS,3.SHIFT,0100001111111:POOL32A:32::SHLL.QB
+"shll.qb r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_qb_shift (SD_, RT, RS, SHIFT, 0);
+}
+
+001000,5.RT,5.RS,5.RD,01110001101:POOL32A:32::SHLLV.PH
+"shllv.ph r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_ph_shl (SD_, RD, RT, RS, 0, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11110001101:POOL32A:32::SHLLV_S.PH
+"shllv_s.ph r<RD>, r<RD>, r<RS>"
+*nanomipsdsp:
+{
+  do_ph_shl (SD_, RD, RT, RS, 0, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1110010101:POOL32A:32::SHLLV.QB
+"shllv.qb r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_shl (SD_, RD, RT, RS, 0);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1111010101:POOL32A:32::SHLLV_S.W
+"shllv_s.w r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_w_s_shllv (SD_, RD, RT, RS);
+}
+
+001000,5.RT,5.RS,5.SHIFT,1.X,1111110101:POOL32A:32::SHLL_S.W
+"shll_s.w r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_w_shll (SD_, RT, RS, SHIFT);
+}
+
+001000,5.RT,5.RS,3.SHIFT,0000111111111:POOL32A:32::SHRA.QB
+"shra.qb r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_qb_shra (SD_, RT, RS, SHIFT, 0);
+}
+
+001000,5.RT,5.RS,3.SHIFT,1000111111111:POOL32A:32::SHRA_R.QB
+"shra_r.qb r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_qb_shra (SD_, RT, RS, SHIFT, 1);
+}
+
+001000,5.RT,5.RS,4.SHIFT,1.X,01100110101:POOL32A:32::SHRA.PH
+"shra.ph r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_ph_shift (SD_, RT, RS, SHIFT, 1, 0);
+}
+
+001000,5.RT,5.RS,4.SHIFT,1.X,11100110101:POOL32A:32::SHRA_R.PH
+"shra_r.ph r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_ph_shift (SD_, RT, RS, SHIFT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,00110001101:POOL32A:32::SHRAV.PH
+"shrav.ph r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_ph_shl (SD_, RD, RT, RS, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10110001101:POOL32A:32::SHRAV_R.PH
+"shrav_r.ph r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_ph_shl (SD_, RD, RT, RS, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,00111001101:POOL32A:32::SHRAV.QB
+"shrav.qb r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_shrav (SD_, RD, RT, RS, 0);
+}
+
+001000,5.RT,5.RS,5.RD,10111001101:POOL32A:32::SHRAV_R.QB
+"shrav_r.qb r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_shrav (SD_, RD, RT, RS, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1011010101:POOL32A:32::SHRAV_R.W
+"shrav_r.w r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_w_r_shrav (SD_, RD, RT, RS);
+}
+
+001000,5.RT,5.RS,5.SHIFT,1.X,1011110101:POOL32A:32::SHRA_R.W
+"shra_r.w r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_w_shra (SD_, RT, RS, SHIFT);
+}
+
+001000,5.RT,5.RS,4.SHIFT,001111111111:POOL32A:32::SHRL.PH
+"shrl.ph r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_ph_shrl (SD_, RT, RS, SHIFT);
+}
+
+001000,5.RT,5.RS,3.SHIFT,1100001111111:POOL32A:32::SHRL.QB
+"shrl.qb r<RT>, r<RS>, <SHIFT>"
+*nanomipsdsp:
+{
+  do_qb_shift (SD_, RT, RS, SHIFT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1100010101:POOL32A:32::SHRLV.PH
+"shrlv.ph r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_ph_shrlv (SD_, RD, RT, RS);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1101010101:POOL32A:32::SHRLV.QB
+"shrlv.qb r<RD>, r<RT>, r<RS>"
+*nanomipsdsp:
+{
+  do_qb_shl (SD_, RD, RT, RS, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01000001101:POOL32A:32::SUBQ.PH
+"subq.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11000001101:POOL32A:32::SUBQ_S.PH
+"subq_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_ph_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1101000101:POOL32A:32::SUBQ_S.W
+"subq_s.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_w_op (SD_, RD, RS, RT, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01001001101:POOL32A:32::SUBQH.PH
+"subqh.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qh_ph_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11001001101:POOL32A:32::SUBQH_R.PH
+"subqh_r.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qh_ph_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01010001101:POOL32A:32::SUBQH.W
+"subqh.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qh_w_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11010001101:POOL32A:32::SUBQH_R.W
+"subqh_r.w r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qh_w_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01100001101:POOL32A:32::SUBU.PH
+"subu.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_u_ph_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11100001101:POOL32A:32::SUBU_S.PH
+"subu_s.ph r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_u_ph_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01011001101:POOL32A:32::SUBU.QB
+"subu.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11011001101:POOL32A:32::SUBU_S.QB
+"subu_s.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_qb_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,5.RS,5.RD,01101001101:POOL32A:32::SUBUH.QB
+"subuh.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_uh_qb_op (SD_, RD, RS, RT, 1, 0);
+}
+
+001000,5.RT,5.RS,5.RD,11101001101:POOL32A:32::SUBUH_R.QB
+"subuh_r.qb r<RD>, r<RS>, r<RT>"
+*nanomipsdsp:
+{
+  do_uh_qb_op (SD_, RD, RS, RT, 1, 1);
+}
+
+001000,5.RT,7.CONTROL_MASK,01011001111111:POOL32A:32::WRDSP
+"wrdsp r<RT>":CONTROL_MASK == 1111111111
+"wrdsp r<RT>, <CONTROL_MASK>"
+*nanomipsdsp:
+{
+  do_wrdsp (SD_, RT, CONTROL_MASK);
+}
diff --git a/sim/mips/nanomipsr6.igen b/sim/mips/nanomipsr6.igen
new file mode 100644
index 00000000000..bef5c04c3b3
--- /dev/null
+++ b/sim/mips/nanomipsr6.igen
@@ -0,0 +1,2744 @@
+// Simulator definition for the nanoMIPS.
+// Copyright (C) 2018-2022 Free Software Foundation, Inc.
+// Contributed by Imagination Technologies, Ltd.
+// Written by Ali Lown <ali.lown@imgtec.com>
+//
+// This file is part of GDB, the GNU debugger.
+//
+// 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, see <http://www.gnu.org/licenses/>.
+
+:compute:::int:U_SHIFT_1BIT:U:(U << 1)
+:compute:::int:U_SHIFT_2BIT:U:(U << 2)
+:compute:::int:U_SHIFT_3BIT:U:(U << 3)
+:compute:::int:U_SHIFT_4BIT:U:(U << 4)
+:compute:::int:EU_127:EU:((EU == 127) ? -1 \: EU)
+:compute:::int:U_LW4X4:U2,U3:((U3 << 3) | (U2 << 2))
+:compute:::int:AXUIPC_S_LO:S1,S2,S3:((EXTEND32((S3 << 31) | (S2 << 21) | (S1 << 12))) & 0x0000ffff)
+:compute:::int:AXUIPC_S_HI:S1,S2,S3:((EXTEND32((S3 << 31) | (S2 << 21) | (S1 << 12))) & 0xffff0000)
+:compute:::int:AXUIPC_S:S1,S2,S3:(EXTEND32((S3 << 31) | (S2 << 21) | (S1 << 12)))
+:compute:::int:TRD2:RD20,RD21:(compute_gpr2_dest1_reg (SD_, (RD21 << 1 | RD20)))
+:compute:::int:TRE2:RD20,RD21:(compute_gpr2_dest2_reg (SD_, (RD21 << 1 | RD20)))
+:compute:::int:TRS2:RS4,RS2_0:(compute_gpr4_zero (SD_, (RS4 << 3 | RS2_0)))
+:compute:::int:TRT2:RT4,RT2_0:(compute_gpr4_zero (SD_, (RT4 << 3 | RT2_0)))
+:compute:::int:TRD2_REV:RD4,RD2_0:(compute_gpr4 (SD_, (RD4 << 3) | RD2_0))
+:compute:::int:TRE2_REV:RE4,RE2_0:(compute_gpr4 (SD_, (RE4 << 3) | RE2_0))
+:compute:::int:TRS2_REV:RS20,RS21:(compute_gpr2_dest1_reg (SD_, (RS21 << 1 | RS20)))
+:compute:::int:TRT2_REV:RS20,RS21:(compute_gpr2_dest2_reg (SD_, (RS21 << 1 | RS20)))
+:compute:::address_word:ADDRESS8:S1,S2:(nia + EXTEND8((S2 << 7) | (S1 << 1)))
+:compute:::address_word:ADDRESS11:S1,S2:(nia + EXTEND11((S2 << 10) | (S1 << 1)))
+:compute:::address_word:ADDRESS15:S1,S2:(nia + EXTEND15((S2 << 14) | (S1 << 1)))
+:compute:::address_word:ADDRESS21:S1,S2:(nia + EXTEND21((S2 << 20) | (S1 << 1)))
+:compute:::address_word:ADDRESS22:S1,S2:(nia + EXTEND22((S2 << 21) | (S1 << 1)))
+:compute:::address_word:ADDRESS26:S1,S2:(nia + EXTEND26((S2 << 25) | (S1 << 1)))
+:compute:::int:INS_POS:LSB:(LSB)
+:compute:::int:INS_SIZE:LSB,MSBD:(1 + MSBD - LSB)
+:compute:::address_word:ADDRESS12:S1,S2:(nia + EXTEND12(S2 << 11 | S1 << 1))
+:compute:::int:S_14_BIT:S1,S2:(EXTEND14 ((S1 << 13) | S2))
+:compute:::int:S_4_BIT:S1,S2:(EXTEND4((S1 << 3) | S2))
+:compute:::int:S_9_BIT:S1,S2:(EXTEND9((S1 << 8) | S2))
+:compute:::int:S_9_BIT_LLSC:S1,S2:(EXTEND9((S1 << 8) | (S2 << 2)))
+:compute:::int:RD1:RD:(compute_gpr1_dest_reg (SD_, RD))
+:compute:::int:RT_5_BIT_NM_Z:RT1,RT2:(compute_gpr4_zero (SD_, (RT1 << 3) | RT2))
+:compute:::int:RT_5_BIT_NM:RT1,RT2:(compute_gpr4 (SD_, (RT1 << 3) | RT2))
+:compute:::int:RS_5_BIT_NM:RS1,RS2:(compute_gpr4 (SD_, (RS1 << 3) | RS2))
+:compute:::int:TRTZ:RTZ:((RTZ >= 1 && RTZ <= 3) ? (16 + RTZ) \: RTZ)
+:compute:::int:EU_12_13:EU:((EU == 12) ? 255 \: ((EU == 13) ? 65535 \: EU))
+:compute:::int:RS_MOVE:RS1,RS_CODE_1,RS_CODE_2:((RS1 << 3) | (RS_CODE_1 << 2) | RS_CODE_2)
+:compute:::int:CODE_BREAK:RS_CODE_1,RS_CODE_2:((RS_CODE_1 << 2) | RS_CODE_2)
+:compute:::int:TRD_NM:RD:((RD < 4) ? (16 + RD) \: RD)
+:compute:::int:TRS_NM:RS:((RS < 4) ? (16 + RS) \: RS)
+:compute:::int:TRT_NM:RT:((RT < 4) ? (16 + RT) \: RT)
+:compute:::int:COUNT:COUNT3:(COUNT3 == 0 ? 8 \: COUNT3)
+:compute:::int:SHIFTX_1BIT:SHIFTX:(SHIFTX << 1)
+
+:function:::void:do_msubf:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  check_fmt_p (SD_, fmt, instruction_0);
+  TRACE_ALU_INPUT3 (FGR[fd], FGR[fs], FGR[ft]);
+  StoreFPR (fd, fmt, FusedMultiplySub (ValueFPR (fs, fmt),
+               ValueFPR (ft, fmt),
+               ValueFPR (fd, fmt), fmt));
+  TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_maddf:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  check_fmt_p (SD_, fmt, instruction_0);
+  TRACE_ALU_INPUT3 (FGR[fd], FGR[fs], FGR[ft]);
+  StoreFPR (fd, fmt, FusedMultiplyAdd (ValueFPR (fs, fmt),
+               ValueFPR (ft, fmt),
+               ValueFPR (fd, fmt), fmt));
+  TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_rint:int fd, int fs, int fmt, instruction_word instruction_0
+{
+  uint64_t result = 0;
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  check_fmt_p (SD_, fmt, instruction_0);
+  TRACE_ALU_INPUT1 (FGR[fs]);
+  RoundToIntegralExact (ValueFPR (fs, fmt), &result, fmt);
+  StoreFPR (fd, fmt, result);
+  TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_class:int fd, int fs, int fmt, instruction_word instruction_0
+{
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  check_fmt_p (SD_, fmt, instruction_0);
+  StoreFPR (fd, fmt, Classify (ValueFPR (fs, fmt), fmt));
+}
+
+:function:::void:do_seleqzf:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+  check_fpu (SD_);
+  check_fmt_p (SD_, fmt, instruction_0);
+  TRACE_ALU_INPUT2 (ValueFPR(fs, fmt), FGR[ft]);
+  if ((FGR[ft] & 0x01) == 0)
+    StoreFPR (fd, fmt, ValueFPR (fs, fmt));
+  else
+    StoreFPR (fd, fmt, 0);
+  TRACE_ALU_RESULT (ValueFPR(fd, fmt));
+}
+
+:function:::void:do_selnezf:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+  check_fpu (SD_);
+  check_fmt_p (SD_, fmt, instruction_0);
+  TRACE_ALU_INPUT2 (ValueFPR(fs, fmt), FGR[ft]);
+  if ((FGR[ft] & 0x01) == 0x1)
+    StoreFPR (fd, fmt, ValueFPR (fs, fmt));
+  else
+    StoreFPR (fd, fmt, 0);
+  TRACE_ALU_RESULT (ValueFPR(fd, fmt));
+}
+
+:function:::void:do_self:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+  check_fpu (SD_);
+  check_fmt_p (SD_, fmt, instruction_0);
+  TRACE_ALU_INPUT3 (FGR[fd], ValueFPR(fs, fmt), ValueFPR(ft, fmt));
+  if ((FGR[fd] & 0x01) != 0)
+    StoreFPR (fd, fmt, ValueFPR (ft, fmt));
+  else
+    StoreFPR (fd, fmt, ValueFPR (fs, fmt));
+  TRACE_ALU_RESULT (ValueFPR(fd, fmt));
+}
+
+:function:::void:do_mina:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  check_fmt_p (SD_, fmt, instruction_0);
+  TRACE_ALU_INPUT2 (FGR[fs], FGR[ft]);
+  StoreFPR (fd, fmt, MinA (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+  TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_maxa:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  check_fmt_p (SD_, fmt, instruction_0);
+  TRACE_ALU_INPUT2 (FGR[fs], FGR[ft]);
+  StoreFPR (fd, fmt, MaxA (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+  TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_max:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  check_fmt_p (SD_, fmt, instruction_0);
+  TRACE_ALU_INPUT2 (FGR[fs], FGR[ft]);
+  StoreFPR (fd, fmt, Max (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+  TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_min:int fd, int fs, int ft, int fmt, instruction_word instruction_0
+{
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  check_fmt_p (SD_, fmt, instruction_0);
+  TRACE_ALU_INPUT2 (FGR[fs], FGR[ft]);
+  StoreFPR (fd, fmt, Min (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+  TRACE_ALU_RESULT (FGR[fd]);
+}
+
+:function:::void:do_cmp:int fd, int fs, int ft, int fmt, int condition
+{
+  uint64_t result;
+  check_fpu (SD_);
+  TRACE_ALU_INPUT2 (ValueFPR (fs, fmt), ValueFPR (ft, fmt));
+  result = R6Compare (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt, condition);
+  StoreFPR (fd, fmt, result);
+  TRACE_ALU_RESULT (result);
+}
+
+:function:::void:do_modu:int rd, int rs, int rt
+{
+  uint32_t n = GPR[rs];
+  uint32_t d = GPR[rt];
+  TRACE_ALU_INPUT2 (n,d);
+  if (d == 0)
+    GPR[rd] = EXTEND32 (0);
+  else
+    GPR[rd] = EXTEND32 (n % d);
+
+  TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_mod:int rd, int rs, int rt
+{
+  int32_t n = GPR[rs];
+  int32_t d = GPR[rt];
+  TRACE_ALU_INPUT2 (n,d);
+  if (d == 0 || (n == SIGNED32 (0x80000000) && d == -1))
+    GPR[rd] = EXTEND32 (0);
+  else
+    GPR[rd] = EXTEND32 (n % d);
+
+  TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_muhu:int rd, int rs, int rt
+{
+  uint64_t prod;
+  if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+  prod = ((uint64_t)(uint32_t) GPR[rs])
+    * ((uint64_t)(uint32_t) GPR[rt]);
+  GPR[rd] = EXTEND32 (VH4_8 (prod));
+  TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_mulu:int rd, int rs, int rt
+{
+  uint64_t prod;
+  if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+  prod = ((uint64_t)(uint32_t) GPR[rs])
+    * ((uint64_t)(uint32_t) GPR[rt]);
+  GPR[rd] = EXTEND32 (VL4_8 (prod));
+  TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_muh:int rd, int rs, int rt
+{
+  int64_t prod;
+  if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+  prod = ((int64_t)(int32_t) GPR[rs])
+    * ((int64_t)(int32_t) GPR[rt]);
+  GPR[rd] = EXTEND32 (VH4_8 (prod));
+  TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_lsa:int rd, int rs, int rt, unsigned immediate
+{
+  uint32_t t = GPR[rs] << immediate;
+  GPR[rd] = EXTEND32(GPR[rt] + t);
+  TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_divu:int rd, int rs, int rt
+*nanomips32r6:
+*nanomips64r6:
+{
+  uint32_t n = GPR[rs];
+  uint32_t d = GPR[rt];
+  TRACE_ALU_INPUT2 (n,d);
+  if (d == 0)
+    GPR[rd] = EXTEND32 (0x80000000);
+  else
+    GPR[rd] = EXTEND32 (n / d);
+
+  TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_div:int rd, int rs, int rt
+*nanomips32r6:
+*nanomips64r6:
+{
+  int32_t n = GPR[rs];
+  int32_t d = GPR[rt];
+  TRACE_ALU_INPUT2 (n,d);
+  if (d == 0)
+    GPR[rd] = EXTEND32 (0x80000000);
+  else if (n == SIGNED32 (0x80000000) && d == -1)
+    GPR[rd] = EXTEND32 (0x80000000);
+  else
+    GPR[rd] = EXTEND32 (n / d);
+
+  TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_llwp:int rt, int ru, int roffset, int rbase
+{
+  address_word base = GPR[rbase];
+  address_word offset = EXTEND16 (roffset);
+  {
+    address_word vaddr = loadstore_ea (SD_, base, offset);
+    address_word paddr = vaddr;
+    int uncached;
+    if ((vaddr & 7) != 0)
+      {
+  SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, read_transfer,
+    sim_core_unaligned_signal);
+      }
+    else
+      {
+      uint64_t memval = 0;
+      uint64_t memval1 = 0;
+      uint64_t data = memval;
+
+      LoadMemory (&memval, &memval1, AccessLength_DOUBLEWORD, paddr,
+            vaddr, isDATA, isREAL);
+
+      GPR[rt] = EXTEND32 (data & 0xFFFFFFFF);
+      GPR[ru] = EXTEND32 (data >> 32);
+
+      LLBIT = 1;
+      COP0_COUNT++;
+      }
+  }
+}
+
+:function:::void:do_rotx:int rt, int rs, int shift, int shiftx, int stripe
+{
+  int i;
+  uint64_t tmp0 = ((uint64_t)GPR[rs] << 32) | (GPR[rs] & 0xFFFFFFFF);
+  uint64_t tmp1, tmp2, tmp3, tmp4, tmp5;
+
+  tmp1 = tmp0;
+  for (i = 0; i <=46; i++) {
+    int s;
+
+    if (i & 0x8)
+      s = shift;
+    else
+      s = shiftx;
+
+    if (stripe != 0 && !(i & 0x4))
+      s = ~s;
+
+    if (s & 0x10) {
+      if (tmp0 & (1LL << (i + 16)))
+        tmp1 |= 1LL << i;
+      else
+        tmp1 &= ~(1LL << i);
+    }
+  }
+
+  tmp2 = tmp1;
+  for (i = 0; i <=38; i++) {
+    int s;
+
+    if (i & 0x4)
+      s = shift;
+    else
+      s = shiftx;
+
+    if (s & 0x8) {
+      if (tmp1 & (1LL << (i + 8)))
+        tmp2 |= 1LL << i;
+      else
+        tmp2 &= ~(1LL << i);
+    }
+  }
+
+  tmp3 = tmp2;
+  for (i = 0; i <=34; i++) {
+    int s;
+
+    if (i & 0x2)
+      s = shift;
+    else
+      s = shiftx;
+
+    if (s & 0x4) {
+      if (tmp2 & (1LL << (i + 4)))
+        tmp3 |= 1LL << i;
+      else
+        tmp3 &= ~(1LL << i);
+    }
+  }
+
+  tmp4 = tmp3;
+  for (i = 0; i <=32; i++) {
+    int s;
+
+    if (i & 0x1)
+      s = shift;
+    else
+      s = shiftx;
+
+    if (s & 0x2) {
+      if (tmp3 & (1LL << (i + 2)))
+        tmp4 |= 1LL << i;
+      else
+        tmp4 &= ~(1LL << i);
+    }
+  }
+
+  tmp5 = tmp4;
+  for (i = 0; i <=31; i++) {
+    int s;
+
+    s = shift;
+
+    if (s & 0x1) {
+      if (tmp4 & (1LL << (i + 1)))
+        tmp5 |= 1LL << i;
+      else
+        tmp5 &= ~(1LL << i);
+    }
+  }
+
+  GPR[rt] = EXTEND32 (tmp5);
+}
+
+:function:::void:do_lwc1xs:int ft, int rbase, int roffset
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_fpu (SD_);
+  COP_LW (1, ft, do_load (SD_, AccessLength_WORD, GPR[rbase] << 2,
+        GPR[roffset]));
+}
+
+:function:::void:do_lwpc_nanomips:int rt, uint32_t offset, address_word nia
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_fpu (SD_);
+  GPR[rt] = EXTEND32 (do_load (SD_, AccessLength_WORD, nia, offset));
+}
+
+:function:::void:check_nms_flag:
+*nanomips32r6:
+*nanomips64r6:
+{
+  if(nms_flag == 0)
+    sim_engine_abort (SD, CPU, CIA, "Error: NMS instruction generated\
+  (nanoMIPS Subset is disabled - use -march=32r6s option)\n");
+}
+
+:function:::uint32_t:compute_gpr2_dest1_reg:int reg
+*nanomips32r6:
+*nanomips64r6:
+{
+  switch(reg)
+    {
+    case 0: return 4;
+    case 1: return 5;
+    case 2: return 6;
+    case 3: return 7;
+    default: return 4;
+    }
+}
+
+:function:::uint32_t:compute_gpr4_zero:int reg
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (reg == 3) return 0;
+  else if (reg >=4 && reg <= 7) return reg;
+  else return reg + 8;
+}
+
+:function:::uint32_t:compute_gpr4:int reg
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (reg >=4 && reg <= 7) return reg;
+  else return reg + 8;
+}
+
+:function:::uint32_t:compute_gpr2_dest2_reg:int reg
+*nanomips32r6:
+*nanomips64r6:
+{
+  switch(reg)
+    {
+    case 0: return 5;
+    case 1: return 6;
+    case 2: return 7;
+    case 3: return 8;
+    default: return 5;
+    }
+}
+
+:function:::uint32_t:compute_gpr1_dest_reg:int reg
+*nanomips32r6:
+*nanomips64r6:
+{
+  switch(reg)
+    {
+    case 0: return 4;
+    case 1: return 5;
+    default: return 4;
+    }
+}
+
+:function:::unsigned:zero_extend:signed_word value, uint32_t from_nbits
+{
+  uint32_t low_bits_mask = (1 << from_nbits) - 1;
+  return value & low_bits_mask;
+}
+
+:function:::void:do_save_gprs_to_stack_and_adjust_sp: int first_gpr, int count, int gp, int u
+*nanomips32r6:
+*nanomips64r6:
+{
+  int counter = 0;
+
+  while (counter != count) {
+    int gpr = (first_gpr & 0x10) | ((first_gpr + counter) & 0x1F);
+    int offset = - ( (counter + 1) << 2 );
+
+    if ( gp && (counter == count - 1))
+      gpr = 28;
+
+    do_store (SD_, AccessLength_WORD, GPR[SPIDX], offset, GPR[gpr]);
+
+    counter++;
+    COP0_COUNT++;
+  }
+
+  GPR[SPIDX] -= u;
+}
+
+:function:::void:do_restore_gprs_from_stack_and_adjust_sp: int first_gpr, int count, int gp, int u
+*nanomips32r6:
+*nanomips64r6:
+{
+  int counter = 0;
+
+  while (counter != count) {
+    int gpr = (first_gpr & 0x10) | ((first_gpr + counter) & 0x1F);
+    int offset;
+
+    if (gpr == 29)
+      Unpredictable();
+
+    offset = u - ((counter + 1) << 2);
+
+    if ( gp && (counter == count - 1))
+      gpr = 28;
+
+    GPR[gpr] = EXTEND32 (do_load(SD_, AccessLength_WORD, GPR[SPIDX], offset));
+
+    counter++;
+    COP0_COUNT++;
+  }
+
+  GPR[SPIDX] += u;
+}
+
+:function:::address_word:do_eret:int nc, address_word nia
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (SR & status_ERL)
+    {
+      /* Oops, not yet available */
+      sim_io_printf (SD, "Warning: ERET when SR[ERL] set not supported");
+      nia = EPC;
+      SR &= ~status_ERL;
+    }
+  else
+    {
+      nia = EPC;
+      SR &= ~status_EXL;
+      //if ( SRSCtl.HSS > 0 && Status.BEV == 0)
+      //  SRSCtl.CSS = SRSCtl.PSS
+  }
+
+  if (!nc)
+    LLBIT = 0;
+
+  //TODO: ClearHazards()
+  return nia;
+}
+
+:%s::::GPR_LIST_SAVE:int count
+*nanomips32r6:
+*nanomips64r6:
+{
+  int i;
+  static char gpr_list[100];
+
+  gpr_list[0] = '\0';
+
+  i = 0;
+
+  while (i<count)
+    {
+      char str1[32];
+      if (i == 0 || i==count-1) {
+        sprintf(str1, "%d", i);
+        strcat (gpr_list,"s");
+        strcat (gpr_list,str1);
+        if(i==0 && count > 1)
+          strcat (gpr_list,"-");
+      }
+      i++;
+    }
+  return (gpr_list);
+}
+
+:function:::void:do_break_nanomips:address_word instruction_0
+{
+  /* Check for some break instruction which are reserved for use by the
+     simulator.  */
+  unsigned int break_code = instruction_0 & HALT_INSTRUCTION_MASK_NANOMIPS;
+  if (break_code == (HALT_INSTRUCTION_NANOMIPS & HALT_INSTRUCTION_MASK_NANOMIPS))
+    {
+      sim_engine_halt (SD, CPU, NULL, cia,
+           sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
+    }
+  else if (break_code == (BREAKPOINT_INSTRUCTION_NANOMIPS & HALT_INSTRUCTION_MASK_NANOMIPS))
+    {
+      PC = cia;
+      SignalException (BreakPoint, instruction_0);
+    }
+
+  else
+    {
+    /* If we get this far, we're not an instruction reserved by the sim. Raise
+       the exception. */
+      SignalException (BreakPoint, instruction_0);
+    }
+}
+
+:%s::::GP_SAVE:int gp
+*nanomips32r6:
+*nanomips64r6:
+{
+  return (gp > 0) ? "gp" : "";
+}
+
+:%s::::FP_SAVE:int fp
+*nanomips32r6:
+*nanomips64r6:
+{
+  return (fp > 0) ? "fp" : "";
+}
+
+11111111111111111111111111111111:R6DUMMY:32,f::DUMMY0.fmt
+"dummy 0"
+*nanomips32r6:
+*nanomips64r6:
+{
+  /* Just needed so GNUSIM builds */
+}
+
+011100,3.RT,1,6.U:R6P16A1:16::ADDIUR1SP
+"addiu r<TRT_NM>, SP, <U_SHIFT_2BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_addiu (SD_, SPIDX, TRT_NM, U_SHIFT_2BIT);
+}
+
+100100,3.RT,3.RS,0,3.U:R6P16A2:16::ADDIUR2
+"addiu r<TRT_NM>, r<TRS_NM>, <U_SHIFT_2BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_addiu (SD_, TRS_NM, TRT_NM, U_SHIFT_2BIT);
+}
+
+100100,5.RT,1.S1,1,3.S2:R6P16ADDIURS5:16::ADDIURS5
+"nop":RT==0
+"addiu r<RT>, <S_4_BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (RT != 0)
+    do_addiu (SD_, RT, RT, S_4_BIT);
+}
+
+000001,5.RT,20.S1,1.S2:R6P32:32::ADDIUPC
+"addiu r<RT>, <ADDRESS22>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  GPR[RT] = ADDRESS22;
+}
+
+011000,5.RT,00011,16.IMM48:R6POOL48I:32::ADDIUPC48
+"addiu r<RT>, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  uint16_t U2;
+  uint32_t total;
+  check_nms_flag (SD_);
+  U2 = do_load (SD_, AccessLength_HALFWORD, CIA + 4, 0);
+  total = U2 << 16 | IMM48;
+  TRACE_ALU_INPUT2(GPR[RT], total);
+  GPR[RT] = CIA + 6 + EXTEND32(total);
+  TRACE_ALU_RESULT(GPR[RT]);
+  NIA = CIA + 6;
+}
+
+101100,3.RT,3.RS,3.RD,0:R6P16ADDU:16::ADDU16
+"addu r<TRD_NM>, r<TRS_NM>, r<TRT_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_addu (SD_, TRS_NM, TRT_NM, TRD_NM);
+}
+
+001111,1.RT1,0,3.RT2,1.RS1,0,3.RS2:R6P164X4:16::ADDU4X4
+"addu r<RT_5_BIT_NM>, r<RS_5_BIT_NM>, r<RT_5_BIT_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_addu (SD_, RS_5_BIT_NM, RT_5_BIT_NM, RT_5_BIT_NM);
+}
+
+010100,3.RT,3.RS,10,0,0:R6POOL16C00:16::AND16
+"and r<TRT_NM>, r<TRS_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_and (SD_, TRS_NM, TRT_NM, TRT_NM);
+}
+
+111100,3.RT,3.RS,4.EU:R6P16:16::ANDI16
+"andi r<TRT_NM>, r<TRS_NM>, <EU_12_13>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_andi (SD_, TRS_NM, TRT_NM, EU_12_13);
+}
+
+001110,9.S1,1.S2:R6P16:16::BALC16
+"balc <ADDRESS11>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT1(RA);
+  RA = NIA;
+  NIA = ADDRESS11;
+  TRACE_ALU_RESULT(RA);
+
+  // For cycle counting
+  COP0_COUNT++;
+}
+
+000110,9.S1,1.S2:R6P16:16::BC16
+"bc <ADDRESS11>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  NIA = ADDRESS11;
+}
+
+110110,3.RT,3.RS,4.U!0:R6P16BR1:16::BxxC16
+"beqc r<TRS_NM>, r<TRT_NM>, <U_SHIFT_1BIT>":RS<RT
+"bnec r<TRS_NM>, r<TRT_NM>, <U_SHIFT_1BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  TRACE_ALU_INPUT2(GPR[TRS_NM], GPR[TRT_NM]);
+  if (RS < RT && GPR[TRS_NM] == GPR[TRT_NM])
+    NIA = NIA + U_SHIFT_1BIT; //BEQC
+  else if (RS >= RT && GPR[TRS_NM] != GPR[TRT_NM])
+    NIA = NIA + U_SHIFT_1BIT; //BNEC
+}
+
+100110,3.RT,6.S1,1.S2:R6P16:16::BEQZC16
+"beqzc r<TRT_NM>, <ADDRESS8>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT1(GPR[TRT_NM]);
+  if(GPR[TRT_NM] == 0)
+    NIA = ADDRESS8;
+}
+
+101110,3.RT,6.S1,1.S2:R6P16:16::BNEZC16
+"bnezc r<TRT_NM>, <ADDRESS8>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT1(GPR[TRT_NM]);
+  if(GPR[TRT_NM] != 0)
+    NIA = ADDRESS8;
+}
+
+110110,5.RT,1,0000:R6P16JRC:16::JALRC16
+"jalrc r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RT], RA);
+  RA = NIA;
+  NIA = GPR[RT];
+  TRACE_ALU_RESULT(RA);
+
+  // For cycle counting
+  COP0_COUNT++;
+}
+
+110110,5.RT,0,0000:R6P16JRC:16::JRC16
+"jrc r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT1(GPR[RT]);
+  NIA = GPR[RT];
+}
+
+010111,3.RT,3.RS,00,2.U:R6P16LB:16::LB16
+"lb r<TRT_NM>, <U>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lb (SD_, TRT_NM, U, TRS_NM);
+}
+
+010111,3.RT,3.RS,10,2.U:R6P16LB:16::LBU16
+"lbu r<TRT_NM>, <U>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2 (U, GPR[TRS_NM]);
+  do_lbu (SD_, TRT_NM, U, TRS_NM);
+  TRACE_ALU_RESULT (GPR[TRT_NM]);
+}
+
+011111,3.RT,3.RS,0,2.U,0:R6P16LH:16::LH16
+"lh r<TRT_NM>, <U_SHIFT_1BIT>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lh (SD_, TRT_NM, U_SHIFT_1BIT, TRS_NM);
+}
+
+011111,3.RT,3.RS,1,2.U,0:R6P16LH:16::LHU16
+"lhu r<TRT_NM>, <U_SHIFT_1BIT>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lhu (SD_, TRT_NM, U_SHIFT_1BIT, TRS_NM);
+}
+
+110100,3.RT,7.EU:R6P16:16::LI16
+"li r<TRT_NM>, <EU_127>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT1(GPR[TRT_NM]);
+  GPR[TRT_NM] = EU_127;
+  TRACE_ALU_RESULT(GPR[TRT_NM]);
+}
+
+011101,1.RT1,1.U2,3.RT2,1.RS1,1.U3,3.RS2:R6P16:16::LW4X4
+"lw r<RT_5_BIT_NM>, <U_LW4X4>(r<RS_5_BIT_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_lw (SD_, RT_5_BIT_NM, U_LW4X4, RS_5_BIT_NM);
+}
+
+000101,3.RT,3.RS,4.U:R6P16:16::LW16
+"lw r<TRT_NM>, <U_SHIFT_2BIT>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lw (SD_, TRT_NM, U_SHIFT_2BIT, TRS_NM);
+}
+
+010101,3.RT,7.U:R6P16:16::LWGP16
+"lw r<TRT_NM>, <U_SHIFT_2BIT>(gp)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lw (SD_, TRT_NM, U_SHIFT_2BIT, GPIDX);
+}
+
+001101,5.RT,5.U:R6P16:16::LWSP
+"lw r<RT>, <U_SHIFT_2BIT>(sp)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lw (SD_, RT, U_SHIFT_2BIT, SPIDX);
+}
+
+010100,3.RT,3.RS,3.RD,1:R6P16C:16::LWXS16
+"lwxs r<TRD_NM>, r<TRS_NM>(r<TRT_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lw (SD_, TRD_NM, GPR[TRS_NM] << 2, TRT_NM);
+}
+
+// These four instructions are grouped together because of a bug in GNUSIM
+// pattern recognition
+000100,5.RT,2.RS1,1.RS_CODE_1,2.RS_CODE_2:R6P16MOVE:16::P16MOVE_P16RI
+"move r<RT>, r<RS_MOVE>": RT != 0
+"syscall <RS_CODE_2>": RS1 == 1
+"sdbbp <CODE_BREAK>": RS1 == 3
+"break <CODE_BREAK>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (RT == 0) {
+    if (RS1 == 1)
+      SignalException (SystemCall, instruction_0);
+    else if (RS1 == 3)
+      SignalException (DebugBreakPoint, instruction_0);
+    else
+      do_break_nanomips (SD_, instruction_0);
+  }
+  else {
+    TRACE_ALU_INPUT2 (GPR[RT], GPR[RS_MOVE]);
+    GPR[RT] = GPR[RS_MOVE];
+    TRACE_ALU_RESULT2 (GPR[RT], GPR[RS_MOVE]);
+  }
+}
+
+101111,1.RT4,1.RD20,3.RT2_0,1.RS4,1.RD21,3.RS2_0:R6P16:16::MOVEP
+"movep r<TRD2>, r<TRE2>, r<TRS2>, r<TRT2>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  TRACE_ALU_INPUT4 (GPR[TRD2], GPR[TRE2], GPR[TRS2], GPR[TRT2]);
+  GPR[TRD2] = GPR[TRS2];
+  GPR[TRE2] = GPR[TRT2];
+  TRACE_ALU_RESULT2 (GPR[TRD2], GPR[TRE2]);
+
+  // For cycle counting
+  COP0_COUNT++;
+}
+
+111111,1.RE4,1.RS20,3.RE2_0,1.RD4,1.RS21,3.RD2_0:R6P16:16::MOVEPREV
+"movep r<TRD2_REV>, r<TRE2_REV>, r<TRS2_REV>, r<TRT2_REV>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  TRACE_ALU_INPUT4 (GPR[TRD2_REV], GPR[TRE2_REV], GPR[TRS2_REV], GPR[TRT2_REV]);
+  GPR[TRD2_REV] = GPR[TRS2_REV];
+  GPR[TRE2_REV] = GPR[TRT2_REV];
+  TRACE_ALU_RESULT2 (GPR[TRD2_REV], GPR[TRE2_REV]);
+
+  // For cycle counting
+  COP0_COUNT++;
+}
+
+010100,3.RT,3.RS,00,0,0:R6POOL16C00:16::NOT16
+"not r<TRT_NM>, r<TRS_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_nor (SD_, 0, TRS_NM, TRT_NM);
+}
+
+010100,3.RT,3.RS,11,0,0:R6POOL16C00:16::OR16
+"or r<TRT_NM>, r<TRS_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_or (SD_, TRS_NM, TRT_NM, TRT_NM);
+}
+
+000111,1.RT1,1,4.U,4.GPR_LIST_SAVE:R6P16SR:16::RESTORE.JRC16
+"restore.jrc <U_SHIFT_4BIT>":GPR_LIST_SAVE==15
+"restore.jrc <U_SHIFT_4BIT>, ra, %s<GPR_LIST_SAVE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (RT1 == 0)
+    do_restore_gprs_from_stack_and_adjust_sp(SD_, 30, GPR_LIST_SAVE, 0,
+                                             U_SHIFT_4BIT);
+  else
+    do_restore_gprs_from_stack_and_adjust_sp(SD_, 31, GPR_LIST_SAVE, 0,
+                                             U_SHIFT_4BIT);
+  NIA = RA;
+}
+
+000111,1.RT1,0,4.U,4.GPR_LIST_SAVE:R6P16SR:16::SAVE16
+"save <U_SHIFT_4BIT>, ra": GPR_LIST_SAVE == 0
+"save <U_SHIFT_4BIT>, ra, %s<GPR_LIST_SAVE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (RT1 == 0)
+    do_save_gprs_to_stack_and_adjust_sp(SD_, 30, GPR_LIST_SAVE, 0, U_SHIFT_4BIT);
+  else
+    do_save_gprs_to_stack_and_adjust_sp(SD_, 31, GPR_LIST_SAVE, 0, U_SHIFT_4BIT);
+
+}
+
+010111,3.RTZ,3.RS,01,2.U:R6P16LB:16::SB16
+"sb r<TRTZ>, <U>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_BYTE, GPR[TRS_NM], U, GPR[TRTZ]);
+}
+
+011111,3.RTZ,3.RS,0,2.U,1:R6P16LH:16::SH16
+"sh r<TRTZ>, <U_SHIFT_1BIT>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_HALFWORD, GPR[TRS_NM], U_SHIFT_1BIT, GPR[TRTZ]);
+}
+
+001100,3.RT,3.RS,0,3.SHIFT:R6P16SHIFT:16::SLL16
+"sll r<TRT_NM>, r<TRS_NM>, <SHIFT_DEC>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_sll (SD_, TRS_NM, TRT_NM, SHIFT_DEC);
+}
+
+001100,3.RT,3.RS,1,3.SHIFT:R6P16SHIFT:16::SRL16
+"srl r<TRT_NM>, r<TRS_NM>, <SHIFT_DEC>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_srl (SD_, TRS_NM, TRT_NM, SHIFT_DEC);
+}
+
+101100,3.RT,3.RS,3.RD,1:R6P16ADDU:16::SUBU16
+"subu r<TRD_NM>, r<TRS_NM>, r<TRT_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_subu (SD_, TRS_NM, TRT_NM, TRD_NM);
+}
+
+100101,3.RTZ,3.RS,4.U:R6P16:16::SW16
+"sw r<TRTZ>, <U_SHIFT_2BIT>(r<TRS_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_WORD, GPR[TRS_NM], U_SHIFT_2BIT, GPR[TRTZ]);
+}
+
+101101,5.RT,5.U:R6P16:16::SWSP
+"sw r<RT>, <U_SHIFT_2BIT>(sp)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_WORD, SP, U_SHIFT_2BIT, GPR[RT]);
+}
+
+010100,3.RT,3.RS,01,0,0:R6POOL16C00:16::XOR16
+"xor r<TRT_NM>, r<TRS_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_xor (SD_, TRT_NM, TRS_NM, TRT_NM);
+}
+
+// 32-bit instructions
+
+001000,5.RT,5.RS,5.RD,1.X,0100010,000:R6POOL32A0:32::ADD
+"add r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_add (SD_, RS, RT, RD);
+}
+
+000000,5.RT!0,5.RS,16.U:R6PPADDIU:32::ADDIU
+"addiu r<RT>, r<RS>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_addiu (SD_, RS, RT, U);
+}
+
+010001,5.RT,011,18.U:R6PGPBH:32::ADDIUGPB
+"addiu r<RT>, GP, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_addiu (SD_, GPIDX, RT, U);
+}
+
+010000,5.RT,19.U,00:R6PGPW:32::ADDIUGPW
+"addiu r<RT>, GP, <U_SHIFT_2BIT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_addiu (SD_, GPIDX, RT, U_SHIFT_2BIT);
+}
+
+111000,5.RT,9.S1,10.S2,1,1.S3:R6PLUI:32::ALUIPC
+"aluipc r<RT>, <AXUIPC_S_HI>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  address_word address = NIA + AXUIPC_S;
+
+  TRACE_ALU_INPUT2(GPR[RT], address);
+  GPR[RT] = address & ~0xfff;
+  TRACE_ALU_RESULT(GPR[RT]);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0101010,000:R6POOL32A0:32::ADDU
+"addu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_addu (SD_, RS, RT, RD);
+}
+
+001000,5.RT,5.RS,5.RD,5.IMMEDIATE,011,111:R6POOL32A0:32::EXTW
+"prepend r<RT>, r<RS>, <IMMEDIATE>": RD == RS
+"align r<RD>, r<RS>, r<RT>, <IMMEDIATE>": IMMEDIATE != 0
+"extw r<RD>, r<RS>, r<RT>, <IMMEDIATE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (IMMEDIATE != 0) {
+    uint64_t tmp = ((uint64_t)GPR[RT] << 32) | (0xffffffff & GPR[RS]);
+    TRACE_ALU_INPUT4 (GPR[RD], GPR[RS], GPR[RT], tmp);
+    GPR[RD] = EXTEND32 (tmp >> IMMEDIATE);
+    TRACE_ALU_RESULT (GPR[RD]);
+  } else {
+    TRACE_ALU_INPUT2 (GPR[RD], GPR[RT]);
+    GPR[RD] = GPR[RT];
+    TRACE_ALU_RESULT (GPR[RD]);
+  }
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1001010,000:R6POOL32A0:32::AND
+"and r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_and (SD_, RS, RT, RD);
+}
+
+100000,5.RT,5.RS,0010,12.U:R6PU12:32::ANDI
+"andi r<RT>, r<RS>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_andi (SD_, RS, RT, U);
+}
+
+001010,1,24.S1,1.S2:R6PBAL:32::BALC
+"balc <ADDRESS26>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT1(RA);
+  RA = NIA;
+  NIA = ADDRESS26;
+  TRACE_ALU_RESULT(RA);
+
+  // For cycle counting
+  COP0_COUNT++;
+}
+
+001010,0,24.S1,1.S2:R6PBAL:32::BC
+"bc <ADDRESS26>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  NIA = ADDRESS26;
+}
+
+100010,5.RT,5.RS,00,13.S1,1.S2:R6PBR1:32::BEQC
+"beqc r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+  if (GPR[RS] == GPR[RT])
+    NIA = ADDRESS15;
+}
+
+110010,5.RT,000,7.U,10.S1,1.S2:P7PBRI:32::BEQIC
+"beqic r<RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RT], U);
+  if (GPR[RT] == U) {
+    NIA = ADDRESS12;
+  }
+}
+
+100010,5.RT,5.RS,10,13.S1,1.S2:P7PBR1:32::BGEC
+"bgec r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+  if ((signed_word) GPR[RS] >= (signed_word) GPR[RT])
+    NIA = ADDRESS15;
+}
+
+110010,5.RT,010,7.U,10.S1,1.S2:P7PBRI:32::BGEIC
+"bgeic r<RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RT], U);
+  if ((signed_word) GPR[RT] >= U) {
+    NIA = ADDRESS12;
+  }
+}
+
+100010,5.RT,5.RS,11,13.S1,1.S2:P7PBR2:32::BGEUC
+"bgeuc r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+  if ((unsigned_word) (GPR[RS]) >= (unsigned_word)(GPR[RT])) {
+    NIA = ADDRESS15;
+  }
+}
+
+110010,5.RT,011,7.U,10.S1,1.S2:P7PBRI:32::BGEUIC
+"bgeuic r<RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RT], U);
+  if ((unsigned_word) GPR[RT] >= U) {
+    NIA = ADDRESS12;
+  }
+}
+
+101010,5.RT,5.RS,10,13.S1,1.S2:P7PBR2:32::BLTC
+"bltc r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+  if ((signed_word) GPR[RS] < (signed_word) GPR[RT])
+    NIA = ADDRESS15;
+}
+
+110010,5.RT,110,7.U,10.S1,1.S2:P7PBRI:32::BLTIC
+"bltic r<RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RT], U);
+  if ((signed_word) GPR[RT] < U) {
+    NIA = ADDRESS12;
+  }
+}
+
+101010,5.RT,5.RS,11,13.S1,1.S2:P7PBR2:32::BLTUC
+"bltuc r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+  if ((unsigned_word) GPR[RS] < (unsigned_word) GPR[RT]) {
+    NIA = ADDRESS15;
+  }
+}
+
+110010,5.RT,111,7.U,10.S1,1.S2:P7PBRI:32::BLTIUC
+"bltiuc <RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RT], U);
+  if ((unsigned_word) GPR[RT] < U) {
+    NIA = ADDRESS12;
+  }
+}
+
+101010,5.RT,5.RS,00,13.S1,1.S2:R6PBR2:32::BNEC
+"bnec r<RS>, r<RT>, <ADDRESS15>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+  if (GPR[RS] != GPR[RT])
+    NIA = ADDRESS15;
+}
+
+110010,5.RT,100,7.U,10.S1,1.S2:R6PBRI:32::BNEIC
+"bneic r<RT>, <U>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RT], U);
+  if (GPR[RT] != U) {
+    NIA = ADDRESS12;
+  }
+}
+
+000000,00000,10,19.CODE:R6PRI:32::BREAK
+"break %#lx<CODE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_break_nanomips (SD_, instruction_0);
+}
+
+101001,5.OP,5.RS,1.S1,0111,0,01,8.S2:R6PLSS1:32::CACHE
+"cache <OP>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_cache (SD_, OP, RS, S_9_BIT, instruction_0);
+}
+
+001000,5.RT,5.RS,0100101,100,111,111:R6POOL32AXF4:32::CLO
+"clo r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_clo (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,0101101,100,111,111:R6POOL32AXF4:32::CLZ
+"clz r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_clz (SD_, RT, RS);
+}
+
+001000,5.RT,5.X,01,00011,101,111,111:R6POOL32AXF5GROUP1:32::DI
+"di":RT == 0
+"di r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_di (SD_, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0100011,000:R6POOL32A0:32::DIV
+"div r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_div (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0110011,000:R6POOL32A0:32::DIVU
+"divu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_divu (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.X,01,01011,101,111,111:R6POOL32AXF5GROUP1:32::EI
+"ei":RT == 0
+"ei r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_ei (SD_, RT);
+}
+
+001000,9.X,0,11,11001,101,111,111:R6ERETX:32::ERET
+"eret"
+*nanomips32r6:
+*nanomips64r6:
+{
+  NIA = do_eret(SD_, 0, NIA);
+}
+
+001000,9.X,1,11,11001,101,111,111:R6ERETX:32::ERETNC
+"eretnc"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  SignalException (ReservedInstruction, instruction_0);
+  NIA = do_eret(SD_, 1, NIA);
+}
+
+100000,5.RT,5.RS,1111,0,5.MSBD,0,5.LSB:R6PEXT:32::EXT
+"ext r<RT>, r<RS>, <LSB>, <MSBD+1>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  if (LSB + MSBD + 1 > 32)
+    Unpredictable ();
+
+  do_ext (SD_, RT, RS, LSB, MSBD);
+}
+
+100000,5.RT,5.RS,1110,0,5.MSBD,0,5.LSB:R6PINS:32::INS
+"ins r<RT>, r<RS>, <INS_POS>, <INS_SIZE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  if ((1 + MSBD - LSB) < 1)
+    Unpredictable ();
+  do_ins (SD_, RT, RS, LSB, MSBD);
+}
+
+100000,5.RT,5.RS,1101,0,4.SHIFTX,1.STRIPE,0,5.SHIFT:R6PROTX:32::ROTX
+"bitrev r<RT>, r<RS>": SHIFT == 31 && SHIFTX_1BIT == 0
+"bitswap r<RT>, r<RS>": SHIFT == 7 && SHIFTX_1BIT == 8 && STRIPE == 1
+"bitswap.h r<RT>, r<RS>": SHIFT == 15 && SHIFTX_1BIT == 16
+"byteswap r<RT>, r<RS>": SHIFT == 24 && SHIFTX_1BIT == 8
+"wsbh r<RT>, r<RS>": SHIFT == 8 && SHIFTX_1BIT == 24
+"rotx r<RT>, r<RS>, <SHIFT>, <SHIFTX_1BIT>": STRIPE == 0
+"rotx r<RT>, r<RS>, <SHIFT>, <SHIFTX_1BIT>, <STRIPE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+
+  TRACE_ALU_INPUT4 (GPR[RT], GPR[RS], SHIFT, SHIFTX_1BIT);
+  do_rotx (SD_, RT, RS, SHIFT, SHIFTX_1BIT, STRIPE);
+  TRACE_ALU_RESULT (GPR[RT]);
+}
+
+010010,5.RT,5.RS,0000,12.X:R6PJ:32::JALRC
+"jalrc r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  unsigned_word address;
+  TRACE_ALU_INPUT3(GPR[RT], GPR[RS], RA);
+  GPR[RT] = NIA;
+  address = GPR[RS];
+  NIA = address;
+
+  // For cycle counting
+  COP0_COUNT++;
+  TRACE_ALU_RESULT(NIA);
+
+}
+
+010010,5.RT,5.RS,0001,12.X:R6PJ:32::JALRC.HB
+"jalrc.hb r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  unsigned_word address;
+  GPR[RT] = NIA;
+  address = GPR[RS];
+  NIA = address;
+
+  // For cycle counting
+  COP0_COUNT++;
+}
+
+100001,5.RT,5.RS,0000,12.U:R6PLSU12:32::LB
+"lb r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lb (SD_, RT, U, RS);
+}
+
+010001,5.RT,000,18.U:R6PLSGP:32::LBGP
+"lb r<RT>, <U>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lb (SD_, RT, U, GPIDX);
+}
+
+101001,5.RT,5.RS,1.S1,0000,0,00,8.S2:R6PLSS0:32::LBS9
+"lb r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lb (SD_, RT, S_9_BIT, RS);
+}
+
+100001,5.RT,5.RS,0010,12.U:R6PLSU12:32::LBU
+"lbu r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lbu (SD_, RT, U, RS);
+}
+
+010001,5.RT,010,18.U:R6GPBH:32::LBUGP
+"lbu r<RT>, <U>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2 (U, GP);
+  do_lbu (SD_, RT, U, GPIDX);
+  TRACE_ALU_RESULT (GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,0010,0,00,8.S2:R6PLSS0:32::LBUS9
+"lbu r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lbu (SD_, RT, S_9_BIT, RS);
+}
+
+001000,5.RT,5.RS,5.RD,0010,0,000,111:R6PPLSX:32::LBUX
+"lbux r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lbu (SD_, RD, GPR[RS], RT);
+}
+
+001000,5.RT,5.RS,5.RD,0000,0,000,111:R6PPLSX:32::LBX
+"lbx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lb (SD_, RD, GPR[RS], RT);
+}
+
+100001,5.RT,5.RS,0100,12.U:R6PLSU12:32::LH
+"lh r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lh (SD_, RT, U, RS);
+}
+
+010001,5.RT,100,17.U,0:R6PGPLH:32::LHGP
+"lh r<RT>, <U_SHIFT_1BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lh (SD_, RT, U_SHIFT_1BIT, GPIDX);
+}
+
+101001,5.RT,5.RS,1.S1,0100,0,00,8.S2:R6PLSS0:32::LHS9
+"lh r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lh (SD_, RT, S_9_BIT, RS);
+}
+
+100001,5.RT,5.RS,0110,12.U:R6PLSU12:32::LHU
+"lhu r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lhu (SD_, RT, U, RS);
+}
+
+010001,5.RT,100,17.U,1:R6PLSGP:32::LHUGP
+"lhu r<RT>, <U_SHIFT_1BIT>(gp)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lhu (SD_, RT, U_SHIFT_1BIT, GPIDX);
+}
+
+101001,5.RT,5.RS,1.S1,0110,0,00,8.S2:R6PLSS0:32::LHUS9
+"lhu r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lhu (SD_, RT, S_9_BIT, RS);
+}
+
+001000,5.RT,5.RS,5.RD,0110,0,000,111:R6PPLSX:32::LHUX
+"lhux r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lhu (SD_, RD, GPR[RS], RT);
+}
+
+001000,5.RT,5.RS,5.RD,0110,1,000,111:R6PPLSXS:32::LHUXS
+"lhux r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lhu (SD_, RD, GPR[RS] << 1, RT);
+}
+
+001000,5.RT,5.RS,5.RD,0100,0,000,111:R6PPLSX:32::LHX
+"lhx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lh (SD_, RD, GPR[RS], RT);
+}
+
+001000,5.RT,5.RS,5.RD,0100,1,000,111:R6PPLSXS:32::LHXS
+"lhxs r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lh (SD_, RD, GPR[RS] << 1, RT);
+}
+
+101001,5.RT,5.RS,1.S1,1010,0,01,6.S2,00:R6PLL:32::LL
+"ll r<RT>, <S_9_BIT_LLSC>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT3(GPR[RT], S_9_BIT_LLSC, GPR[RS]);
+  do_ll (SD_, RT, S_9_BIT_LLSC, RS);
+  TRACE_ALU_RESULT(GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.X1,1010,0,01,5.RU,1.X2,01:R6PLL:32::LLWP
+"llwp r<RT>, r<RU>, (r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_llwp (SD_, RT, RU, 0, RS);
+}
+
+001000,5.RT,5.RS,5.RD,2.U,3.X,001,111:R6POOL32A7:32::LSA
+"lsa r<RD>, r<RS>, r<RT>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lsa (SD_, RD, RS, RT, U);
+}
+
+111000,5.RT,9.S1,10.S2,0,1.S3:R6PLUI:32::LUI
+"lui r<RT>, <AXUIPC_S_HI>, <AXUIPC_S_LO>":AXUIPC_S_LO != 0
+"lui r<RT>, <AXUIPC_S_HI>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2 (GPR[RT], AXUIPC_S);
+  GPR[RT] = AXUIPC_S;
+  TRACE_ALU_RESULT (GPR[RT]);
+}
+
+100001,5.RT,5.RS,1000,12.U:R6PLSU12:32::LW
+"lw r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT3 (GPR[RT], U, GPR[RS]);
+  do_lw (SD_, RT, U, RS);
+  TRACE_ALU_RESULT (GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,1000000,8.S2:R6PLSS0:32::LWS9
+"lw r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lw (SD_, RT, S_9_BIT, RS);
+}
+
+101001,5.RT,5.RS,1.S1,3.COUNT3,0,1,00,8.S2:R6PLSWM:32::LWM
+"lwm r<RT>, <S_9_BIT>(r<RS>), <COUNT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  int counter = 0;
+  int dest;
+  int this_offset;
+
+  check_nms_flag (SD_);
+
+  while (counter != COUNT)
+  {
+    dest = (RT & 0x10) | ((RT + counter) & 0x1F);
+
+    if ((dest == RS) && (counter != (COUNT - 1)))
+      Unpredictable ();
+
+    this_offset = S_9_BIT + (counter << 2);
+
+    do_lw (SD_, dest, this_offset, RS);
+
+    counter++;
+    if (counter != 0)
+      COP0_COUNT++;
+  }
+}
+
+010000,5.RT,19.U,10:R6PGPW:32::LWGP
+"lw r<RT>, <U_SHIFT_2BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RT], GPR[RT]);
+  do_lw (SD_, RT, U_SHIFT_2BIT, GPIDX);
+  TRACE_ALU_RESULT(GPR[RT]);
+}
+
+011000,5.RT,01011,16.IMM48:R6POOL48I:32::LWPC48
+"lwpc r<RT>, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  uint16_t S2;
+  uint32_t total;
+  check_nms_flag (SD_);
+  S2 = do_load(SD_, AccessLength_HALFWORD, CIA + 4, 0);
+  total = S2 << 16 | IMM48;
+
+  do_lwpc_nanomips (SD_, RT, total, CIA + 6);
+  NIA = CIA + 6;
+}
+
+001000,5.RT,5.RS,5.RD,1000,0,000,111:R6PPLSX:32::LWX
+"lwx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lw (SD_, RD, GPR[RS], RT);
+}
+
+001000,5.RT,5.RS,5.RD,1000,1,000,111:R6PPLSXS:32::LWXS
+"lwxs r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_lw (SD_, RD, GPR[RS] << 2, RT);
+}
+
+001000,5.RT,5.C0S,5.SEL,1.X,0000110,000:R6POOL32A0:32::MFC0
+"mfc0 r<RT>, r<C0S>, <SEL>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  DecodeCoproc (instruction_0, 0, cp0_mfc0, RT, C0S, SEL);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0101011,000:R6POOL32A0:32::MOD
+"mod r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_mod (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0111011,000:R6POOL32A0:32::MODU
+"modu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_modu (SD_, RD, RS, RT);
+}
+
+000010,1.RT1,1.RD,3.RT2,20.S1,1.S2:R6MOVEBALC:32::MOVE.BALC
+"move.balc r<RD1>, r<RT_5_BIT_NM_Z>, <ADDRESS22>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  TRACE_ALU_INPUT2(GPR[RD1], GPR[RT_5_BIT_NM_Z]);
+  GPR[RD1] = GPR[RT_5_BIT_NM_Z];
+  RA = NIA;
+  NIA = ADDRESS22;
+  TRACE_ALU_RESULT(GPR[RD1]);
+
+  // For cycle counting
+  COP0_COUNT += 2;
+}
+
+001000,5.RT,5.RS,5.RD,1,1000010,000:R6PCMOVE:32::MOVN
+"movn r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT2(GPR[RS], GPR[RT]);
+  do_movn (SD_, RD, RS, RT);
+  TRACE_ALU_RESULT(GPR[RD]);
+}
+
+001000,5.RT,5.RS,5.RD,0,1000010,000:R6PCMOVE:32::MOVZ
+"movz r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_movz (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.C0S,5.SEL,1.X,0001110,000:R6POOL32A0:32::MTC0
+"mtc0 r<RT>, r<C0S>, <SEL>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  DecodeCoproc (instruction_0, 0, cp0_mtc0, RT, C0S, SEL);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0001011,000:R6POOL32A0:32::MUH
+"muh r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_muh (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0011011,000:R6POOL32A0:32::MUHU
+"muhu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_muhu (SD_, RD, RS, RT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0000011,000:R6POOL32A0:32::MUL32
+"mul r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_mul (SD_, RD, RS, RT);
+}
+
+001111,1.RT1,0,3.RT2,1.RS1,1,3.RS2:R6P164X4:16::MUL4X4
+"mul r<RT_5_BIT_NM>, r<RS_5_BIT_NM>, r<RT_5_BIT_NM>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_mul (SD_, RT_5_BIT_NM, RS_5_BIT_NM, RT_5_BIT_NM);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0010011,000:R6POOL32A0:32::MULU
+"mulu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_mulu (SD_, RD, RS, RT);
+}
+
+100000,00000,5.X1,1100,3.X2,0000,00000:R6PSLL:32::NOP32
+"nop"
+*nanomips32r6:
+*nanomips64r6:
+{
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1011010,000:R6POOL32A0:32::NOR
+"nor r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_nor (SD_, RS, RT, RD);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1010010,000:R6POOL32A0:32::OR32
+"or r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_or (SD_, RS, RT, RD);
+}
+
+100000,5.RT,5.RS,0000,12.U:R6PU12:32::ORI
+"ori r<RT>, r<RS>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_ori (SD_, RS, RT, U);
+}
+
+100000,00000,5.X1,1100,3.X2,0000,00101:R6PSLL:32::PAUSE
+"pause"
+*nanomips32r6:
+*nanomips64r6:
+{
+  sim_io_printf (SD, "Not implemented");
+}
+
+101001,5.HINT!31,5.RS,1.S1,0011,0,00,8.S2:R6PPREFS9:32::PREFS9
+"pref <HINT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_pref (SD_, HINT, S_9_BIT, RS);
+}
+
+100001,5.HINT,5.RS,0011,12.U:R6PLSU12:32::PREFU12
+"pref <HINT>, <U>(r<RS>)": HINT != 31
+"synci <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (HINT != 31)
+   do_pref (SD_, HINT, U, RS);
+  else
+  {
+    // synci - nothing to do currently
+    sim_io_printf (SD, "Not implemented");
+  }
+}
+
+100000,5.RT,0,4.GPR_LIST_SAVE,0011,9.U,1.GP_SAVE,10:R6PPSR:32::RESTORE
+"restore <U_SHIFT_3BIT>, r<RT>": GPR_LIST_SAVE == 0
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GPR_LIST_SAVE>": !GP_SAVE && GPR_LIST_SAVE != 0
+"restore <U_SHIFT_3BIT>, r<RT>": !GP_SAVE && GPR_LIST_SAVE < 2
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GPR_LIST_SAVE>" : !GP_SAVE && GPR_LIST_SAVE >=2
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 2
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>" : GP_SAVE && GPR_LIST_SAVE >=2
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 3
+"restore <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_restore_gprs_from_stack_and_adjust_sp(SD_, RT, GPR_LIST_SAVE,
+                                           GP_SAVE, U_SHIFT_3BIT);
+}
+
+100000,5.RT,0,4.GPR_LIST_SAVE,0011,9.U,1.GP_SAVE,11:R6PPSR:32::RESTORE.JRC
+"restore.jrc <U_SHIFT_3BIT>, r<RT>": GPR_LIST_SAVE == 0
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GPR_LIST_SAVE>": !GP_SAVE && GPR_LIST_SAVE != 0
+"restore.jrc <U_SHIFT_3BIT>, r<RT>": !GP_SAVE && GPR_LIST_SAVE < 2
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GPR_LIST_SAVE>" : !GP_SAVE && GPR_LIST_SAVE >=2
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 2
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>" : GP_SAVE && GPR_LIST_SAVE >=2
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 3
+"restore.jrc <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_restore_gprs_from_stack_and_adjust_sp(SD_, RT, GPR_LIST_SAVE,
+                                           GP_SAVE, U_SHIFT_3BIT);
+
+  NIA = GPR[RAIDX];
+}
+
+100000,5.RT,5.RS,1100,3.X,0110,5.SHIFT:R6PSHIFT:32::ROTR
+"rotr r<RT>, r<RS>, <SHIFT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  GPR[RT] = do_ror (SD_, GPR[RS], SHIFT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0011010,000:R6POOL32A0:32::ROTRV
+"rotrv r<RD>, r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  uint32_t shift = GPR[RT] & 0x1f;
+  GPR[RD] = do_ror (SD_, GPR[RS], shift);
+}
+
+001000,5.RT,5.RS,5.RD,0,1100010,000:R6POOL32A0:32::XOR
+"xor r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_xor (SD_, RS, RT, RD);
+}
+
+100000,5.RT,5.RS,0001,12.U:R6PU12:32::XORI
+"xori r<RT>, r<RS>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_xori (SD_, RS, RT, U);
+}
+
+100000,5.RT,0,4.GPR_LIST_SAVE,0011,9.U,1.GP_SAVE,00:R6PPSR:32::SAVE
+"save <U_SHIFT_3BIT>, r<RT>": GPR_LIST_SAVE == 0
+"save <U_SHIFT_3BIT>, r<RT>, %s<GPR_LIST_SAVE>":  !GP_SAVE && GPR_LIST_SAVE != 0
+"save <U_SHIFT_3BIT>, r<RT>": !GP_SAVE && GPR_LIST_SAVE < 2
+"save <U_SHIFT_3BIT>, r<RT> %s<GPR_LIST_SAVE>" : !GP_SAVE && GPR_LIST_SAVE >=2
+"save <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 2
+"save <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>" : GP_SAVE && GPR_LIST_SAVE >=2
+"save <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>": GP_SAVE && GPR_LIST_SAVE < 3
+"save <U_SHIFT_3BIT>, r<RT>, %s<GP_SAVE>, %s<GPR_LIST_SAVE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_save_gprs_to_stack_and_adjust_sp(SD_, RT, GPR_LIST_SAVE,
+                                      GP_SAVE, U_SHIFT_3BIT);
+}
+
+100001,5.RT,5.RS,0001,12.U:R6PLSU12:32::SBU12
+"sb r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_BYTE, GPR[RS], U, GPR[RT]);
+}
+
+010001,5.RT,001,18.U:R6PGPBH:32::SBGP
+"sb r<RT>, <U>(gp)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_BYTE, GP, U, GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,0001,0,00,8.S2:R6PLSS0:32::SBS9
+"sb r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_BYTE, GPR[RS], S_9_BIT, GPR[RT]);
+}
+
+001000,5.RT,5.RS,5.RD,0001,0,000,111:R6PPLSX:32::SBX
+"sbx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_store (SD_, AccessLength_BYTE, GPR[RT], GPR[RS], GPR[RD]);
+}
+
+101001,5.RT,5.RS,1.S1,1011,0,01,6.S2,00:R6PSC:32::SC
+"sc r<RT>, <S_9_BIT_LLSC>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_sc (SD_, RT, S_9_BIT_LLSC, RS, instruction_0, 1);
+}
+
+101001,5.RT,5.RS,1.X1,1011,0,01,5.RU,1.X,01:R6PSC:32::SCWP
+"scwp r<RT>, r<RU>, (r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  int offset = BigEndianCPU ? 0 : 4;
+
+  do_sc (SD_, RU, offset, RS, instruction_0, 0);
+  do_sc (SD_, RT, offset ^ 4, RS, instruction_0, 1);
+}
+
+001000,5.RT,5.RS,6.X,0000001,000:R6POOL32A0:32::SEB
+"seb r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_seb (SD_, RT, RS);
+}
+
+001000,5.RT,5.RS,6.X,0001001,000:R6POOL32A0:32::SEH
+"seh r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_seh (SD_, RT, RS);
+}
+
+100000,5.RT,5.RS,0110,12.IMMEDIATE:R6PU12:32::SEQI
+"seqi r<RT>, r<RS>, <IMMEDIATE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  TRACE_ALU_INPUT3(GPR[RT], GPR[RS], IMMEDIATE);
+  GPR[RT] = (GPR[RS] == IMMEDIATE) ? 1 : 0;
+  TRACE_ALU_RESULT(GPR[RT]);
+}
+
+100001,5.RT,5.RS,0101,12.U:R6PLSU12:32::SHU12
+"sh r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_HALFWORD, GPR[RS], U, GPR[RT]);
+}
+
+010001,5.RT,101,17.U,0:R6PGPSH:32::SHGP
+"sh r<RT>, <U_SHIFT_1BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_HALFWORD, GP, U_SHIFT_1BIT, GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,0101,0,00,8.S2:R6PLSS0:32::SHS9
+"sh r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_HALFWORD, GPR[RS], S_9_BIT, GPR[RT]);
+}
+
+001000,5.RT,5.RS,5.RD,0101,0,000,111:R6PPLSX:32::SHX
+"shx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_store (SD_, AccessLength_HALFWORD, GPR[RT], GPR[RS], GPR[RD]);
+}
+
+001000,5.RT,5.RS,5.RD,0101,1,000,111:R6PPLSXS:32::SHXS
+"shxs r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_store (SD_, AccessLength_HALFWORD, GPR[RT], GPR[RS] << 1, GPR[RD]);
+}
+
+000000,00000,00,19.CODE:R6PRI:32::SIGRIE
+"sigrie %#lx<CODE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  SignalException (ReservedInstruction, instruction_0);
+}
+
+100000,5.RT!0,5.RS,1100,3.X,0000,5.SHIFT:R6PSLL:32::SLL32
+"sll r<RT>, r<RS>, <SHIFT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_sll (SD_, RS, RT, SHIFT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0000010,000:R6POOL32A0:32::SLLV
+"sllv r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_sllv (SD_, RT, RS, RD);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1101010,000:R6POOL32A0:32::SLT
+"slt r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_slt (SD_, RS, RT, RD);
+}
+
+100000,5.RT,5.RS,0100,12.IMMEDIATE:R6PU12:32::SLTI
+"slti r<RT>, r<RS>, <IMMEDIATE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_slti (SD_, RS, RT, EXTEND12(IMMEDIATE));
+}
+
+100000,5.RT,5.RS,0101,12.U:R6PU12:32::SLTIU
+"sltiu r<RT>, r<RS>, <U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_sltiu (SD_, RS, RT, EXTEND12(U));
+}
+
+001000,5.RT,5.RS,5.RD!0,1.X,1110010,000:R6PSLTU:32::SLTU
+"sltu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_sltu (SD_, RS, RT, RD);
+}
+
+100000,5.RT,5.RS,1100,3.X,0100,5.SHIFT:R6PSHIFT:32::SRA
+"sra r<RT>, r<RS>, <SHIFT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_sra (SD_, RS, RT, SHIFT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0010010,000:R6POOL32A0:32::SRAV
+"srav r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_srav (SD_, RT, RS, RD);
+}
+
+100000,5.RT,5.RS,1100,3.X,0010,5.SHIFT:R6PSHIFT:32::SRL32
+"srl r<RT>, r<RS>, <SHIFT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_srl (SD_, RS, RT, SHIFT);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0001010,000:R6POOL32A0:32::SRLV
+"srlv r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_srlv (SD_, RT, RS, RD);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0110010,000:R6POOL32A0:32::SUB
+"sub r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_sub (SD_, RS, RT, RD);
+}
+
+001000,5.RT,5.RS,5.RD,1.X,0111010,000:R6POOL32A0:32::SUBU32
+"subu r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_subu (SD_, RS, RT, RD);
+}
+
+100001,5.RT,5.RS,1001,12.U:R6PLSU12:32::SWU12
+"sw r<RT>, <U>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_WORD, GPR[RS], U, GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,1001,0,00,8.S2:R6PLS0:32::SWS9
+"sw r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_WORD, GPR[RS], S_9_BIT, GPR[RT]);
+}
+
+010000,5.RT,19.U,11:R6PGPW:32::SWGP
+"sw r<RT>, <U_SHIFT_2BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_WORD, GP, U_SHIFT_2BIT, GPR[RT]);
+}
+
+011000,5.RT,01111,16.IMM48:R6POOL48I:32::SWPC48
+"swpc r<RT>, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  uint16_t U2;
+  uint32_t total;
+  check_nms_flag (SD_);
+  U2 = do_load (SD_, AccessLength_HALFWORD, CIA + 4, 0);
+  total = U2 << 16 | IMM48;
+  TRACE_ALU_INPUT2(GPR[RT], total);
+  do_store(SD_, AccessLength_WORD, CIA + 6, total, GPR[RT]);
+  TRACE_ALU_RESULT(GPR[RT]);
+  NIA = CIA + 6;
+}
+
+
+110101,3.RTZ,7.U:R6P16:16::SWGP16
+"sw r<TRTZ>, <U_SHIFT_2BIT>(GP)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_store (SD_, AccessLength_WORD, GP, U_SHIFT_2BIT, GPR[TRTZ]);
+}
+
+001000,5.RT,5.RS,5.RD,1001,0,000,111:R6PPLSX:32::SWX
+"swx r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_store (SD_, AccessLength_WORD, GPR[RT], GPR[RS], GPR[RD]);
+}
+
+001000,5.RT,5.RS,5.RD,1001,1,000,111:R6PPLSXS:32::SWXS
+"swxs r<RD>, r<RS>(r<RT>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_store (SD_, AccessLength_WORD, GPR[RT], GPR[RS] << 2, GPR[RD]);
+}
+
+111101,1.RT1,1.U2,3.RT2,1.RS1,1.U3,3.RS2:R6P16:16::SW4X4
+"sw r<RT_5_BIT_NM_Z>, <U_LW4X4>(r<RS_5_BIT_NM>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_store (SD_, AccessLength_WORD, GPR[RS_5_BIT_NM], U_LW4X4, GPR[RT_5_BIT_NM_Z]);
+}
+
+101001,5.RT,5.RS,1.S1,3.COUNT3,1,1,00,8.S2:R6PLSWM:32::SWM
+"swm r<RT>, <S_9_BIT>(r<RS>), <COUNT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  int counter = 0;
+  int source;
+  int offsetm;
+
+  check_nms_flag (SD_);
+
+  while (counter != COUNT)
+  {
+    if (RT == 0)
+      source = 0;
+    else
+      source = (RT & 0x10) | ((RT + counter) & 0x1F);
+
+    offsetm = S_9_BIT + (counter << 2);
+
+    do_sw (SD_, source, offsetm, RS);
+
+    counter++;
+
+    if (counter != 0)
+      COP0_COUNT++;
+  }
+}
+
+100000,00000,5.STYPE,1100,3.X,0000,00110:R6PHB:32::SYNC
+"sync":STYPE==0
+"sync <STYPE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  SyncOperation (STYPE);
+}
+
+101001,11111,5.RS,1.S1,0011,0,00,8.S2:R6PPREFS:32::SYNCI
+"synci <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // sync i-cache - nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+000000,00000,11,19.CODE:R6PRI:32::SDBBP32
+"sdbbp %#lx<CODE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  SignalException (DebugBreakPoint, instruction_0);
+}
+
+001000,10.X,00,00001,101,111,111:R6POOL32AXF5GROUP0:32::TLBP
+"tlbp"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+001000,10.X,00,10001,101,111,111:R6POOL32AXF5GROUP0:32::TLBWI
+"tlbwi"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+001000,10.X,00,11001,101,111,111:R6POOL32AXF5GROUP0:32::TLBWR
+"tlbwr"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+
+001000,0000000000,01,00001,101,111,111:R6POOL32AXF5GROUP1:32::TLBINV
+"tlbinv"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // invalidate a set of TLB entries based on ASID and Index match - nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+001000,0000000000,01,01001,101,111,111:R6POOL32AXF5GROUP1:32::TLBINVF
+"tlbinvf"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // invalidate a set of TLB entries based on Index match - nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+001000,10.CODE,10,00101,101,111,111:R6PSYSCALL:32::SYSCALL
+"syscall %#lx<CODE>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  SignalException (SystemCall, instruction_0);
+}
+
+100000,00000,5.X1,1100,3.X2,0000,00011:R6PHB:32::EHB
+"ehb"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // Do nothing, there are no hazards to clear
+}
+
+001000,5.RT,5.RS,5.X,0,0000000,000:R6PTRAP:32::TEQ
+"teq r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+
+  if (GPR[RS] == GPR[RT])
+    SignalException(Trap, instruction_0);
+}
+
+001000,5.RT,5.RS,5.X,1,0000000,000:R6PTRAP:32::TNE
+"tne r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+
+  if (GPR[RS] != GPR[RT])
+    SignalException(Trap, instruction_0);
+}
+
+101001,5.RT,5.RS,1.S1,0100,0,01,8.S2:R6PLSS1:32::UALH
+"ualh r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+
+  TRACE_ALU_INPUT3(GPR[RT], S_9_BIT, GPR[RS]);
+  do_lh (SD_, RT, S_9_BIT, RS);
+  TRACE_ALU_RESULT(GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,3.COUNT3,0,1,01,8.S2:R6PLSUAWM:32::UALWM
+"ualwm r<RT>, <S_9_BIT>(r<RS>), <COUNT>":COUNT != 1
+"ualw r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  int i;
+  int dest;
+  int this_offset;
+
+  address_word base = GPR[RS];
+  for(i = 0; i< COUNT; i++)
+  {
+    dest = (RT & 0x10) | ((RT + i) & 0x1F);
+
+    if (dest == RS && i != COUNT - 1)
+      Unpredictable ();
+
+    this_offset = S_9_BIT + (i << 2);
+
+    if(BigEndianCPU) {
+      GPR[dest] = EXTEND32 (do_load_left (SD_, AccessLength_WORD, base,
+         EXTEND16 (this_offset), GPR[dest]));
+      GPR[dest] = EXTEND32 (do_load_right (SD_, AccessLength_WORD, base,
+         EXTEND16 (this_offset + AccessLength_WORD), GPR[dest]));
+    } else {
+      GPR[dest] = EXTEND32 (do_load_right (SD_, AccessLength_WORD, base,
+         EXTEND16 (this_offset), GPR[dest]));
+      GPR[dest] = EXTEND32 (do_load_left (SD_, AccessLength_WORD, base,
+         EXTEND16 (this_offset + AccessLength_WORD), GPR[dest]));
+    }
+
+    if (i != 0)
+      COP0_COUNT++;
+  }
+}
+
+101001,5.RT,5.RS,1.S1,0101,0,01,8.S2:R6PLSS1:32::UASH
+"uash r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+
+  do_store (SD_, AccessLength_HALFWORD, GPR[RS], S_9_BIT, GPR[RT]);
+}
+
+101001,5.RT,5.RS,1.S1,3.COUNT3,1,1,01,8.S2:R6PLSUAWM:32::UASWM
+"uaswm r<RT>, <S_9_BIT>(r<RS>), <COUNT>":COUNT != 1
+"uasw r<RT>, <S_9_BIT>(r<RS>)"
+*nanomips32r6:
+*nanomips64r6:
+{
+
+  int i;
+  int source;
+  int offsetm;
+
+  for(i = 0; i< COUNT; i++)
+   {
+    if (RT == 0)
+      source = 0;
+    else
+      source = (RT & 0x10) | ((RT + i) & 0x1F);
+
+    offsetm = S_9_BIT + (i << 2);
+
+    if(BigEndianCPU) {
+      do_store_left (SD_, AccessLength_WORD, GPR[RS], EXTEND16 (offsetm), GPR[source]);
+      do_store_right (SD_, AccessLength_WORD, GPR[RS],
+                          EXTEND16 (offsetm + AccessLength_WORD), GPR[source]);
+    } else {
+      do_store_right (SD_, AccessLength_WORD, GPR[RS], EXTEND16 (offsetm), GPR[source]);
+      do_store_left (SD_, AccessLength_WORD, GPR[RS],
+                          EXTEND16 (offsetm + AccessLength_WORD), GPR[source]);
+    }
+
+    if (i != 0)
+      COP0_COUNT++;
+  }
+}
+
+001000,5.RT,5.X,00000,0,1110010,000:R6PDVP:32::DVP
+"dvp r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+
+001000,5.RT,5.HS,2.X1,3.SEL,1.X2,0111000,000:R6POOL32A0:32::RDHWR
+"rdhwr r<HS>, r<RT>, <SEL>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  check_nms_flag (SD_);
+  do_rdhwr (SD_, RT, HS);
+}
+
+001000,5.RT,5.RS,11,10000,101,111,111:R6POOL32AXF5GROUP3:32::RDPGPR
+"rdpgpr r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+001000,5.RT,5.RS,11,11000,101,111,111:R6POOL32AXF5GROUP3:32::WRPGPR
+"wrpgpr r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+001000,5.RT,5.RS,5.RD,1.X,1111010,000:R6POOL32A0:32::SOV
+"SOV r<RD>, r<RS>, r<RT>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  {
+    ALU32_BEGIN (GPR[RS]);
+    ALU32_ADD (GPR[RT]);
+    if (ALU32_HAD_OVERFLOW)
+      GPR[RD] = 1;
+    else
+      GPR[RD] = 0;
+  }
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+001000,10.X,11,10001,101,111,111:R6POOL32A0:32::DERET
+"deret"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+001000,5.RT,5.X,00000,1,1110010,000:R6PDVP:32::EVP
+"evp r<RT>" : RT!=0
+"evp"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+001000,10.CODE,110000110,1111111:R6POOL32AXF5GROUP2:32::WAIT
+"wait"
+*nanomips32r6:
+*nanomips64r6:
+{
+  // nothing to do currently
+  sim_io_printf (SD, "Not implemented");
+}
+
+011000,5.RT,00000,16.IMM48:R6POOL48I:32::LI48
+"li r<RT>, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  uint16_t U2;
+  uint32_t total;
+  check_nms_flag (SD_);
+  U2 = do_load (SD_, AccessLength_HALFWORD, CIA + 4, 0);
+  total = U2 << 16 | IMM48;
+  TRACE_ALU_INPUT2(GPR[RT], total);
+  GPR[RT] = EXTEND32(total);
+  TRACE_ALU_RESULT(GPR[RT]);
+  NIA = CIA + 6;
+}
+
+011000,5.RT,00001,16.IMM48:R6POOL48I:32::ADDIU48
+"addiu r<RT>, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  uint16_t S2;
+  uint32_t total;
+  check_nms_flag (SD_);
+  S2 = do_load(SD_, AccessLength_HALFWORD, CIA + 4, 0);
+  total = S2 << 16 | IMM48;
+  do_addiu(SD_, RT, RT, total);
+  NIA = CIA + 6;
+}
+
+100000,5.RT,5.RS,1000,12.U:R6PU12:32::ADDIUNEG
+"addiu r<RT>, r<RS>, -<U>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  do_addiu (SD_, RS, RT, -U);
+}
+
+011000,5.RT,00010,16.IMM48:R6POOL48I:32::ADDIUGP48
+"addiu r<RT>, GP, <IMM48>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  uint16_t S2;
+  uint32_t total;
+  check_nms_flag (SD_);
+  S2 = do_load(SD_, AccessLength_HALFWORD, CIA + 4, 0);
+  total = S2 << 16 | IMM48;
+  do_addiu (SD_, GPIDX, RT, total);
+  NIA = CIA + 6;
+}
+
+010010,00000,5.RS,1000,12.X:R6BALRSC:32::BRSC
+"brsc r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  unsigned_word address = NIA + (GPR[RS] << 1);
+  NIA = address;
+}
+
+010010,5.RT!0,5.RS,1000,12.X:R6PBALRSC:32::BALRSC
+"balrsc r<RT>, r<RS>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  unsigned_word address = NIA + (GPR[RS] << 1);
+
+  GPR[RT] = NIA;
+  NIA = address;
+
+  // For cycle counting
+  COP0_COUNT++;
+}
+
+110010,5.RT,001,1.X,6.BIT,10.S1,1.S2:R6PBRI:32::BBEQZC
+"bbeqzc r<RT>, <BIT>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  int testbit = (GPR[RT] >> BIT) & 1;
+
+  check_nms_flag (SD_);
+
+  if (testbit == 0)
+      NIA = ADDRESS12;
+}
+
+110010,5.RT,101,1.X,6.BIT,10.S1,1.S2:R6PBRI:32::BBNEZC
+"bbnezc r<RT>, <BIT>, <ADDRESS12>"
+*nanomips32r6:
+*nanomips64r6:
+{
+  int testbit = (GPR[RT] >> BIT) & 1;
+
+  check_nms_flag (SD_);
+
+  if (testbit == 1)
+      NIA = ADDRESS12;
+}
+
+:function:::void:do_lb:int rt, int offset, int base
+*nanomips32r6:
+*nanomips64r6:
+{
+  GPR[rt] = EXTEND8 (do_load (SD_, AccessLength_BYTE, GPR[base], offset));
+}
+
+:function:::void:do_lh:int rt, int offset, int base
+*nanomips32r6:
+*nanomips64r6:
+{
+  GPR[rt] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[base], offset));
+}
+
+:function:::void:do_lw:int rt, int offset, int base
+*nanomips32r6:
+*nanomips64r6:
+{
+  GPR[rt] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[base], offset));
+}
+
+:function:::void:do_lhu:int rt, int offset, int base
+*nanomips32r6:
+*nanomips64r6:
+{
+  GPR[rt] = do_load (SD_, AccessLength_HALFWORD, GPR[base], offset);
+}
+
+:function:::void:do_addiu:int rs, int rt, int immediate
+*nanomips32r6:
+*nanomips64r6:
+{
+  if (NotWordValue (GPR[rs]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[rs], immediate);
+  GPR[rt] = EXTEND32 (GPR[rs] + immediate);
+  TRACE_ALU_RESULT (GPR[rt]);
+}
diff --git a/sim/mips/nanomipsrun.c b/sim/mips/nanomipsrun.c
new file mode 100644
index 00000000000..8698726a9fa
--- /dev/null
+++ b/sim/mips/nanomipsrun.c
@@ -0,0 +1,109 @@
+/*  Run function for the nanomips simulator
+
+    Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+    Written by Andrew Bennett <andrew.bennett@imgtec.com>.
+
+    This file is part of GDB, the GNU debugger.
+
+    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, see <http://www.gnu.org/licenses/>.  */
+
+#include "sim-main.h"
+#include "nanomips16_idecode.h"
+#include "nanomips32_idecode.h"
+#include "bfd.h"
+
+
+#define SD sd
+#define CPU cpu
+#define SIM_MONITOR_ADDRESS 0xBFC00000
+
+void
+sim_engine_run (SIM_DESC sd, int next_cpu_nr, int nr_cpus, int signal);
+
+address_word
+nanomips_instruction_decode (SIM_DESC sd, sim_cpu * cpu,
+            address_word cia,
+            int instruction_size);
+
+address_word
+nanomips_instruction_decode (SIM_DESC sd, sim_cpu * cpu,
+			      address_word cia,
+			      int instruction_size)
+{
+
+  nanomips16_instruction_word instruction_0 = IMEM16_NANOMIPS (cia);
+
+  if((cia & 0xFFF00000) == SIM_MONITOR_ADDRESS) {
+    nanomips32_instruction_word instruction_0 = IMEM32 (cia);
+    return nanomips32_idecode_issue (sd, instruction_0, cia);
+  } else if ((STATE_ARCHITECTURE (sd)->mach == bfd_mach_nanomipsisa32r6
+	  || STATE_ARCHITECTURE (sd)->mach == bfd_mach_nanomipsisa64r6)
+	     && (NANOMIPS_MAJOR_OPCODE_3_5 (instruction_0) & 0x4) == 4)
+	return nanomips16_idecode_issue (sd, instruction_0, cia);
+      else
+	{
+	  nanomips32_instruction_word instruction_0 = IMEM32_NANOMIPS (cia);
+	  return nanomips32_idecode_issue (sd, instruction_0, cia);
+	}
+}
+
+void
+sim_engine_run (SIM_DESC sd, int next_cpu_nr, int nr_cpus,
+		int signal)
+{
+  nanomips32_instruction_word instruction_0;
+  sim_cpu *cpu = STATE_CPU (sd, next_cpu_nr);
+  nanomips32_instruction_address cia = CPU_PC_GET (cpu);
+  unsigned long bfdmach;
+  IS_NANOMIPS = 1;
+
+  bfdmach = STATE_ARCHITECTURE(SD)->mach;
+
+  if (is_nms_flag_set == 0 && (bfdmach == bfd_mach_nanomipsisa64r6
+      || bfdmach == bfd_mach_nanomipsisa32r6))
+    set_nms_flag (sd);
+
+  while (1)
+    {
+      nanomips32_instruction_address nia;
+
+	    cia = cia & ~0x1;
+
+#if defined (ENGINE_ISSUE_PREFIX_HOOK)
+      ENGINE_ISSUE_PREFIX_HOOK ();
+#endif
+
+    nia =
+      nanomips_instruction_decode (sd, cpu, cia,
+            MICROMIPS_DELAYSLOT_SIZE_ANY);
+
+#if defined (ENGINE_ISSUE_POSTFIX_HOOK)
+      ENGINE_ISSUE_POSTFIX_HOOK ();
+#endif
+      // Cycle counting
+      COP0_COUNT++;
+
+      /* Update the instruction address */
+      cia = nia;
+
+      /* process any events */
+      if (sim_events_tick (sd))
+	{
+	  CPU_PC_SET (CPU, cia);
+	  sim_events_process (sd);
+	  cia = CPU_PC_GET (CPU);
+	}
+    }
+}
diff --git a/sim/mips/nms.c b/sim/mips/nms.c
new file mode 100644
index 00000000000..fd957d69e8b
--- /dev/null
+++ b/sim/mips/nms.c
@@ -0,0 +1,44 @@
+/*  Run function for the nanomips simulator
+
+    Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+    Written by Andrew Bennett <andrew.bennett@imgtec.com>.
+
+    This file is part of GDB, the GNU debugger.
+
+    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, see <http://www.gnu.org/licenses/>.  */
+
+#include "sim-main.h"
+#include "elf/mips-common.h"
+#include "elf/nanomips.h"
+
+/* NMS Flag */
+int nms_flag = -1;
+
+int is_nms_flag_set = 0;
+
+void
+set_nms_flag (SIM_DESC sd)
+{
+  Elf_Internal_ABIFlags_v0 *abiflags;
+  abiflags = bfd_nanomips_elf_get_abiflags (STATE_PROG_BFD(sd));
+
+  nms_flag = 0;
+
+  if (abiflags != NULL
+      && ((abiflags->ases & NANOMIPS_ASE_xNMS) != 0))
+    nms_flag = 1;
+
+  is_nms_flag_set = 1;
+}
diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h
index 418c6599118..e6b2b47ede7 100644
--- a/sim/mips/sim-main.h
+++ b/sim/mips/sim-main.h
@@ -318,9 +318,9 @@ struct _sim_cpu {
 #define LAST_EMBED_REGNUM (96)
 #define NUM_REGS (LAST_EMBED_REGNUM + 1)
 
-#define FP0_REGNUM 38           /* Floating point register 0 (single float) */
-#define FCRCS_REGNUM 70         /* FP control/status */
-#define FCRIR_REGNUM 71         /* FP implementation/revision */
+#define FP0_REGNUM ((CPU)->is_nanomips ? 36 : 38)           /* Floating point register 0 (single float) */
+#define FCRCS_REGNUM ((CPU)->is_nanomips ? 68 : 70)         /* FP control/status */
+#define FCRIR_REGNUM ((CPU)->is_nanomips ? 69 : 71)         /* FP implementation/revision */
 #endif
 
 
@@ -336,16 +336,19 @@ struct _sim_cpu {
 #define GPR     (&REGISTERS[0])
 #define GPR_SET(N,VAL) (REGISTERS[(N)] = (VAL))
 
-#define LO      (REGISTERS[33])
-#define HI      (REGISTERS[34])
-#define PCIDX	37
+#define HIIDX   ((CPU)->is_nanomips ? 70 : 33)
+#define LOIDX   ((CPU)->is_nanomips ? 71 : 34)
+#define HI      (REGISTERS[HIIDX])
+#define LO      (REGISTERS[LOIDX])
+#define PCIDX	  ((CPU)->is_nanomips ? 32 : 37)
 #define PC      (REGISTERS[PCIDX])
-#define CAUSE   (REGISTERS[36])
+#define COUSEIDX ((CPU)->is_nanomips ? 34 : 36)
+#define CAUSE   (REGISTERS[COUSEIDX])
 #define SRIDX   (32)
 #define SR      (REGISTERS[SRIDX])      /* CPU status register */
-#define FCR0IDX  (71)
+#define FCR0IDX  ((CPU)->is_nanomips ? 69 : 71)
 #define FCR0    (REGISTERS[FCR0IDX])    /* really a 32bit register */
-#define FCR31IDX (70)
+#define FCR31IDX ((CPU)->is_nanomips ? 68 : 70)
 #define FCR31   (REGISTERS[FCR31IDX])   /* really a 32bit register */
 #define FCSR    (FCR31)
 #define Debug	(REGISTERS[86])
@@ -362,10 +365,10 @@ struct _sim_cpu {
 #define AC3LOIDX	(94)
 #define AC3HIIDX	(95)
 
-#define DSPLO(N)	(REGISTERS[DSPLO_REGNUM[N]])
-#define DSPHI(N)	(REGISTERS[DSPHI_REGNUM[N]])
+#define DSPLO(N)	(REGISTERS[((CPU)->is_nanomips ? (LOIDX + 2 * N) : DSPLO_REGNUM[N])])
+#define DSPHI(N)	(REGISTERS[((CPU)->is_nanomips ? (HIIDX + 2 * N) : DSPHI_REGNUM[N])])
 
-#define DSPCRIDX	(96)	/* DSP control register */
+#define DSPCRIDX	((CPU)->is_nanomips ? 79 : 96)	/* DSP control register */
 #define DSPCR		(REGISTERS[DSPCRIDX])
 
 #define DSPCR_POS_SHIFT		(0)
@@ -420,6 +423,8 @@ struct _sim_cpu {
 #define A3      (REGISTERS[7])
 #define T8IDX   24
 #define T8	(REGISTERS[T8IDX])
+#define GPIDX   28
+#define GP      (REGISTERS[GPIDX])
 #define SPIDX   29
 #define SP      (REGISTERS[SPIDX])
 #define RAIDX   31
@@ -433,6 +438,7 @@ struct _sim_cpu {
   unsigned_word cop0_gpr[NR_COP0_GPR];
 #define COP0_GPR	((CPU)->cop0_gpr)
 #define COP0_BADVADDR	(COP0_GPR[8])
+#define COP0_COUNT (COP0_GPR[9])
 
   /* While space is allocated for the floating point registers in the
      main registers array, they are stored separatly.  This is because
@@ -472,10 +478,21 @@ struct _sim_cpu {
   hilo_history lo_history;
 #define LOHISTORY (&(CPU)->lo_history)
 
+  int is_nanomips;
+#define IS_NANOMIPS ((CPU)->is_nanomips)
 
   sim_cpu_base base;
 };
 
+#define SET_RV0(VAL)        \
+  do {                      \
+    if ((CPU)->is_nanomips) \
+      A0 = VAL;             \
+    else                    \
+      V0 = VAL;             \
+  } while (0)
+
+
 extern void mips_sim_close (SIM_DESC sd, int quitting);
 #define SIM_CLOSE_HOOK(...) mips_sim_close (__VA_ARGS__)
 
@@ -643,13 +660,16 @@ enum ExceptionCause {
    is used by gdb for break-points.  NOTE: Care must be taken, since
    this value may be used in later revisions of the MIPS ISA. */
 #define HALT_INSTRUCTION_MASK   (0x03FFFFC0)
+#define HALT_INSTRUCTION_MASK_NANOMIPS (0x0007FFFF)
 
 #define HALT_INSTRUCTION        (0x03ff000d)
 #define HALT_INSTRUCTION2       (0x0000ffcd)
+#define HALT_INSTRUCTION_NANOMIPS      (0x001003FF)
 
 
 #define BREAKPOINT_INSTRUCTION  (0x0005000d)
 #define BREAKPOINT_INSTRUCTION2 (0x0000014d)
+#define BREAKPOINT_INSTRUCTION_NANOMIPS  (0x00101400)
 
 
 
@@ -1022,6 +1042,16 @@ INLINE_SIM_MAIN (uint16_t) ifetch16 (SIM_DESC sd, sim_cpu *cpu, address_word cia
 #define MICROMIPS_DELAYSLOT_SIZE_16 2
 #define MICROMIPS_DELAYSLOT_SIZE_32 4
 
+#define IMEM32_NANOMIPS(CIA) \
+  (ifetch16 (SD, CPU, (CIA), (CIA)) << 16 | ifetch16 (SD, CPU, (CIA + 2), \
+                  (CIA + 2)))
+#define IMEM16_NANOMIPS(CIA) ifetch16 (SD, CPU, (CIA), ((CIA)))
+
+
+#define NANOMIPS_MAJOR_OPCODE_3_5(INSN) ((INSN & 0x1c00) >> 10)
+
+#define NANOMIPS_DELAYSLOT_SIZE_ANY 0
+
 extern int isa_mode;
 
 #define ISA_MODE_MIPS32 0
@@ -1041,6 +1071,13 @@ extern FILE *tracefh;
 extern int DSPLO_REGNUM[4];
 extern int DSPHI_REGNUM[4];
 
+/* NMS Flag */
+extern int nms_flag;
+extern int is_nms_flag_set;
+
+void
+set_nms_flag (SIM_DESC sd);
+
 INLINE_SIM_MAIN (void) pending_tick (SIM_DESC sd, sim_cpu *cpu, address_word cia);
 extern SIM_CORE_SIGNAL_FN mips_core_signal;
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v2 2/2] gdb: Add nanoMIPS port
  2022-05-31 11:35 [PATCH v2 1/2] sim: Add nanoMIPS port Aleksandar Rikalo
@ 2022-05-31 11:35 ` Aleksandar Rikalo
  2022-05-31 11:56   ` Eli Zaretskii
  0 siblings, 1 reply; 3+ messages in thread
From: Aleksandar Rikalo @ 2022-05-31 11:35 UTC (permalink / raw)
  To: gdb-patches

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>
---
 config.sub                                    |    1 +
 configure                                     |    3 +
 configure.ac                                  |    3 +
 gdb/Makefile.in                               |    2 +
 gdb/NEWS                                      |    1 +
 gdb/configure.host                            |    1 +
 gdb/configure.tgt                             |   11 +
 gdb/features/Makefile                         |    4 +
 gdb/features/nanomips-cp0.xml                 |   13 +
 gdb/features/nanomips-cpu.xml                 |   44 +
 gdb/features/nanomips-dsp.xml                 |   20 +
 gdb/features/nanomips-fpu.xml                 |   45 +
 gdb/features/nanomips.c                       |   54 +
 gdb/features/nanomips.xml                     |   12 +
 gdb/features/nanomips64-cp0.xml               |   13 +
 gdb/features/nanomips64-cpu.xml               |   44 +
 gdb/features/nanomips64-dsp.xml               |   20 +
 gdb/nanomips-tdep.c                           | 3410 +++++++++++++++++
 gdb/nanomips-tdep.h                           |  144 +
 gdb/testsuite/gdb.asm/asm-source.exp          |    9 +-
 gdb/testsuite/gdb.asm/nanomips.inc            |   49 +
 .../gdb.base/catch-gdb-caused-signals.c       |    3 +
 gdb/testsuite/gdb.base/float.exp              |    2 +-
 gdb/testsuite/gdb.trace/trace-common.h        |    2 +-
 gdb/testsuite/lib/gdb.exp                     |    1 +
 25 files changed, 3908 insertions(+), 3 deletions(-)
 create mode 100644 gdb/features/nanomips-cp0.xml
 create mode 100644 gdb/features/nanomips-cpu.xml
 create mode 100644 gdb/features/nanomips-dsp.xml
 create mode 100644 gdb/features/nanomips-fpu.xml
 create mode 100644 gdb/features/nanomips.c
 create mode 100644 gdb/features/nanomips.xml
 create mode 100644 gdb/features/nanomips64-cp0.xml
 create mode 100644 gdb/features/nanomips64-cpu.xml
 create mode 100644 gdb/features/nanomips64-dsp.xml
 create mode 100644 gdb/nanomips-tdep.c
 create mode 100644 gdb/nanomips-tdep.h
 create mode 100644 gdb/testsuite/gdb.asm/nanomips.inc

diff --git a/config.sub b/config.sub
index dba16e84c77..b562e37aa09 100755
--- a/config.sub
+++ b/config.sub
@@ -1243,6 +1243,7 @@ case $cpu-$vendor in
 			| moxie \
 			| mt \
 			| msp430 \
+			| nanomips | nanomipseb \
 			| nds32 | nds32le | nds32be \
 			| nfp \
 			| nios | nios2 | nios2eb | nios2el \
diff --git a/configure b/configure
index 1badcb314f8..c297043dcab 100755
--- a/configure
+++ b/configure
@@ -3908,6 +3908,9 @@ case "${target}" in
   mips*-*-*)
     noconfigdirs="$noconfigdirs gprof"
     ;;
+  nanomips*-*-elf*)
+    noconfigdirs="$noconfigdirs gas binutils ld gprof"
+    ;;
   nvptx*-*-*)
     noconfigdirs="$noconfigdirs target-libssp target-libstdc++-v3 target-libobjc"
     ;;
diff --git a/configure.ac b/configure.ac
index 5b6e2048514..f02e0357b4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1186,6 +1186,9 @@ case "${target}" in
   mips*-*-*)
     noconfigdirs="$noconfigdirs gprof"
     ;;
+  nanomips*-*-elf*)
+    noconfigdirs="$noconfigdirs gas binutils ld gprof"
+    ;;
   nvptx*-*-*)
     noconfigdirs="$noconfigdirs target-libssp target-libstdc++-v3 target-libobjc"
     ;;
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index d80087749de..30676bae9d9 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -817,6 +817,7 @@ ALL_TARGET_OBS = \
 	mn10300-tdep.o \
 	moxie-tdep.o \
 	msp430-tdep.o \
+	nanomips-tdep.o \
 	netbsd-tdep.o \
 	nds32-tdep.o \
 	nios2-linux-tdep.o \
@@ -1386,6 +1387,7 @@ HFILES_NO_SRCDIR = \
 	mips-tdep.h \
 	mn10300-tdep.h \
 	moxie-tdep.h \
+	nanomips-tdep.h \
 	netbsd-nat.h \
 	netbsd-tdep.h \
 	nds32-tdep.h \
diff --git a/gdb/NEWS b/gdb/NEWS
index dac6dabfa42..e03f87f607b 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -256,6 +256,7 @@ winheight
 
 * New targets
 
+GNU/ELF/nanoMIPS      nanomips*-*-*
 GNU/Linux/LoongArch		loongarch*-*-linux*
 
 * Removed targets
diff --git a/gdb/configure.host b/gdb/configure.host
index da71675b201..3a9799ee56e 100644
--- a/gdb/configure.host
+++ b/gdb/configure.host
@@ -61,6 +61,7 @@ i[34567]86*)		gdb_host_cpu=i386 ;;
 loongarch*)		gdb_host_cpu=loongarch ;;
 m68*)			gdb_host_cpu=m68k ;;
 mips*)			gdb_host_cpu=mips ;;
+nanomips*)		gdb_host_cpu=nanomips ;;
 powerpc* | rs6000)	gdb_host_cpu=powerpc ;;
 sparcv9 | sparc64)	gdb_host_cpu=sparc ;;
 s390*)			gdb_host_cpu=s390 ;;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 0705ccf32b8..e0ff7ec7cca 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -447,6 +447,16 @@ msp430-*-elf*)
 	gdb_target_obs="msp430-tdep.o"
 	;;
 
+mt-*-*)
+	# Target: Morpho Technologies ms1 processor
+	gdb_target_obs="mt-tdep.o"
+	;;
+
+nanomips*-*-*)
+	# Target: nanomips ELF
+	gdb_target_obs="nanomips-tdep.o"
+	;;
+
 nds32*-*-elf)
 	# Target: AndesTech NDS32 core
 	gdb_target_obs="nds32-tdep.o"
@@ -765,6 +775,7 @@ m32r-*-*)		gdb_sim=m32r ;;
 m68hc11-*-*|m6811-*-*)	gdb_sim=m68hc11 ;;
 microblaze*-*-*)	gdb_sim=microblaze ;;
 mips*-*-*)		gdb_sim=mips ;;
+nanomips*-*-*)	gdb_sim=mips ;;
 mn10300*-*-*)		gdb_sim=mn10300 ;;
 moxie-*-*)		gdb_sim=moxie ;;
 msp430*-*-*)		gdb_sim=msp430 ;;
diff --git a/gdb/features/Makefile b/gdb/features/Makefile
index 15d623c2681..631d7adee64 100644
--- a/gdb/features/Makefile
+++ b/gdb/features/Makefile
@@ -46,6 +46,7 @@
 # List of .dat files to create in ../regformats/
 WHICH = mips-linux mips-dsp-linux \
 	mips64-linux mips64-dsp-linux \
+	nanomips \
 	nios2-linux \
 	or1k-linux \
 	rs6000/powerpc-32 \
@@ -73,6 +74,8 @@ mips-expedite = r29,pc
 mips-dsp-expedite = r29,pc
 mips64-expedite = r29,pc
 mips64-dsp-expedite = r29,pc
+microblaze-expedite = r1,rpc
+nanomips-expedite = r29,pc
 nios2-linux-expedite = sp,pc
 powerpc-expedite = r1,pc
 s390-linux32-expedite = r14,r15,pswa
@@ -105,6 +108,7 @@ XMLTOC = \
 	mips-linux.xml \
 	mips64-dsp-linux.xml \
 	mips64-linux.xml \
+	nanomips.xml \
 	nds32.xml \
 	nios2.xml \
 	or1k.xml \
diff --git a/gdb/features/nanomips-cp0.xml b/gdb/features/nanomips-cp0.xml
new file mode 100644
index 00000000000..7a3995f0fd7
--- /dev/null
+++ b/gdb/features/nanomips-cp0.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nanomips.cp0">
+  <reg name="status" bitsize="32"/>
+  <reg name="badvaddr" bitsize="32"/>
+  <reg name="cause" bitsize="32"/>
+</feature>
diff --git a/gdb/features/nanomips-cpu.xml b/gdb/features/nanomips-cpu.xml
new file mode 100644
index 00000000000..bb04a24d6f6
--- /dev/null
+++ b/gdb/features/nanomips-cpu.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nanomips.cpu">
+  <reg name="r0" bitsize="32"/>
+  <reg name="r1" bitsize="32"/>
+  <reg name="r2" bitsize="32"/>
+  <reg name="r3" bitsize="32"/>
+  <reg name="r4" bitsize="32"/>
+  <reg name="r5" bitsize="32"/>
+  <reg name="r6" bitsize="32"/>
+  <reg name="r7" bitsize="32"/>
+  <reg name="r8" bitsize="32"/>
+  <reg name="r9" bitsize="32"/>
+  <reg name="r10" bitsize="32"/>
+  <reg name="r11" bitsize="32"/>
+  <reg name="r12" bitsize="32"/>
+  <reg name="r13" bitsize="32"/>
+  <reg name="r14" bitsize="32"/>
+  <reg name="r15" bitsize="32"/>
+  <reg name="r16" bitsize="32"/>
+  <reg name="r17" bitsize="32"/>
+  <reg name="r18" bitsize="32"/>
+  <reg name="r19" bitsize="32"/>
+  <reg name="r20" bitsize="32"/>
+  <reg name="r21" bitsize="32"/>
+  <reg name="r22" bitsize="32"/>
+  <reg name="r23" bitsize="32"/>
+  <reg name="r24" bitsize="32"/>
+  <reg name="r25" bitsize="32"/>
+  <reg name="r26" bitsize="32"/>
+  <reg name="r27" bitsize="32"/>
+  <reg name="r28" bitsize="32"/>
+  <reg name="r29" bitsize="32"/>
+  <reg name="r30" bitsize="32"/>
+  <reg name="r31" bitsize="32"/>
+
+  <reg name="pc" bitsize="32"/>
+</feature>
diff --git a/gdb/features/nanomips-dsp.xml b/gdb/features/nanomips-dsp.xml
new file mode 100644
index 00000000000..659fc3850c2
--- /dev/null
+++ b/gdb/features/nanomips-dsp.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nanomips.dsp">
+  <reg name="hi0" bitsize="32"/>
+  <reg name="lo0" bitsize="32"/>
+  <reg name="hi1" bitsize="32"/>
+  <reg name="lo1" bitsize="32"/>
+  <reg name="hi2" bitsize="32"/>
+  <reg name="lo2" bitsize="32"/>
+  <reg name="hi3" bitsize="32"/>
+  <reg name="lo3" bitsize="32"/>
+
+  <reg name="dspctl" bitsize="32"/>
+</feature>
diff --git a/gdb/features/nanomips-fpu.xml b/gdb/features/nanomips-fpu.xml
new file mode 100644
index 00000000000..cac1d51f2ac
--- /dev/null
+++ b/gdb/features/nanomips-fpu.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nanomips.fpu">
+  <reg name="f0" bitsize="64" type="ieee_double"/>
+  <reg name="f1" bitsize="64" type="ieee_double"/>
+  <reg name="f2" bitsize="64" type="ieee_double"/>
+  <reg name="f3" bitsize="64" type="ieee_double"/>
+  <reg name="f4" bitsize="64" type="ieee_double"/>
+  <reg name="f5" bitsize="64" type="ieee_double"/>
+  <reg name="f6" bitsize="64" type="ieee_double"/>
+  <reg name="f7" bitsize="64" type="ieee_double"/>
+  <reg name="f8" bitsize="64" type="ieee_double"/>
+  <reg name="f9" bitsize="64" type="ieee_double"/>
+  <reg name="f10" bitsize="64" type="ieee_double"/>
+  <reg name="f11" bitsize="64" type="ieee_double"/>
+  <reg name="f12" bitsize="64" type="ieee_double"/>
+  <reg name="f13" bitsize="64" type="ieee_double"/>
+  <reg name="f14" bitsize="64" type="ieee_double"/>
+  <reg name="f15" bitsize="64" type="ieee_double"/>
+  <reg name="f16" bitsize="64" type="ieee_double"/>
+  <reg name="f17" bitsize="64" type="ieee_double"/>
+  <reg name="f18" bitsize="64" type="ieee_double"/>
+  <reg name="f19" bitsize="64" type="ieee_double"/>
+  <reg name="f20" bitsize="64" type="ieee_double"/>
+  <reg name="f21" bitsize="64" type="ieee_double"/>
+  <reg name="f22" bitsize="64" type="ieee_double"/>
+  <reg name="f23" bitsize="64" type="ieee_double"/>
+  <reg name="f24" bitsize="64" type="ieee_double"/>
+  <reg name="f25" bitsize="64" type="ieee_double"/>
+  <reg name="f26" bitsize="64" type="ieee_double"/>
+  <reg name="f27" bitsize="64" type="ieee_double"/>
+  <reg name="f28" bitsize="64" type="ieee_double"/>
+  <reg name="f29" bitsize="64" type="ieee_double"/>
+  <reg name="f30" bitsize="64" type="ieee_double"/>
+  <reg name="f31" bitsize="64" type="ieee_double"/>
+
+  <reg name="fcsr" bitsize="32" group="float"/>
+  <reg name="fir" bitsize="32" group="float"/>
+</feature>
diff --git a/gdb/features/nanomips.c b/gdb/features/nanomips.c
new file mode 100644
index 00000000000..43cdc8a95d5
--- /dev/null
+++ b/gdb/features/nanomips.c
@@ -0,0 +1,54 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: nanomips.xml */
+
+#include "defs.h"
+#include "osabi.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_nanomips;
+static void
+initialize_tdesc_nanomips (void)
+{
+  struct target_desc *result;
+  result = allocate_target_description ().release();
+  struct tdesc_feature *feature;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("nanomips"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.nanomips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 32, 1, NULL, 32, "int");
+
+  tdesc_nanomips = result;
+}
diff --git a/gdb/features/nanomips.xml b/gdb/features/nanomips.xml
new file mode 100644
index 00000000000..ae05a91e935
--- /dev/null
+++ b/gdb/features/nanomips.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>nanomips</architecture>
+  <xi:include href="nanomips-cpu.xml"/>
+</target>
diff --git a/gdb/features/nanomips64-cp0.xml b/gdb/features/nanomips64-cp0.xml
new file mode 100644
index 00000000000..6af2e2c369d
--- /dev/null
+++ b/gdb/features/nanomips64-cp0.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nanomips.cp0">
+  <reg name="status" bitsize="32"/>
+  <reg name="badvaddr" bitsize="64"/>
+  <reg name="cause" bitsize="32"/>
+</feature>
diff --git a/gdb/features/nanomips64-cpu.xml b/gdb/features/nanomips64-cpu.xml
new file mode 100644
index 00000000000..30a237050a6
--- /dev/null
+++ b/gdb/features/nanomips64-cpu.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nanomips.cpu">
+  <reg name="r0" bitsize="64"/>
+  <reg name="r1" bitsize="64"/>
+  <reg name="r2" bitsize="64"/>
+  <reg name="r3" bitsize="64"/>
+  <reg name="r4" bitsize="64"/>
+  <reg name="r5" bitsize="64"/>
+  <reg name="r6" bitsize="64"/>
+  <reg name="r7" bitsize="64"/>
+  <reg name="r8" bitsize="64"/>
+  <reg name="r9" bitsize="64"/>
+  <reg name="r10" bitsize="64"/>
+  <reg name="r11" bitsize="64"/>
+  <reg name="r12" bitsize="64"/>
+  <reg name="r13" bitsize="64"/>
+  <reg name="r14" bitsize="64"/>
+  <reg name="r15" bitsize="64"/>
+  <reg name="r16" bitsize="64"/>
+  <reg name="r17" bitsize="64"/>
+  <reg name="r18" bitsize="64"/>
+  <reg name="r19" bitsize="64"/>
+  <reg name="r20" bitsize="64"/>
+  <reg name="r21" bitsize="64"/>
+  <reg name="r22" bitsize="64"/>
+  <reg name="r23" bitsize="64"/>
+  <reg name="r24" bitsize="64"/>
+  <reg name="r25" bitsize="64"/>
+  <reg name="r26" bitsize="64"/>
+  <reg name="r27" bitsize="64"/>
+  <reg name="r28" bitsize="64"/>
+  <reg name="r29" bitsize="64"/>
+  <reg name="r30" bitsize="64"/>
+  <reg name="r31" bitsize="64"/>
+
+  <reg name="pc" bitsize="64"/>
+</feature>
diff --git a/gdb/features/nanomips64-dsp.xml b/gdb/features/nanomips64-dsp.xml
new file mode 100644
index 00000000000..84bf7b06cc6
--- /dev/null
+++ b/gdb/features/nanomips64-dsp.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.nanomips.dsp">
+  <reg name="hi0" bitsize="64"/>
+  <reg name="lo0" bitsize="64"/>
+  <reg name="hi1" bitsize="64"/>
+  <reg name="lo1" bitsize="64"/>
+  <reg name="hi2" bitsize="64"/>
+  <reg name="lo2" bitsize="64"/>
+  <reg name="hi3" bitsize="64"/>
+  <reg name="lo3" bitsize="64"/>
+
+  <reg name="dspctl" bitsize="32"/>
+</feature>
diff --git a/gdb/nanomips-tdep.c b/gdb/nanomips-tdep.c
new file mode 100644
index 00000000000..b26ba72bc80
--- /dev/null
+++ b/gdb/nanomips-tdep.c
@@ -0,0 +1,3410 @@
+/* Target-dependent code for the nanoMIPS architecture, for GDB,
+   the GNU Debugger.
+
+   Copyright (C) 2017-2022 Free Software Foundation, Inc.
+   Contributed by:
+    Jaydeep Patil <jaydeep.patil@imgtec.com>
+    Matthew Fortune <matthew.fortune@imgtec.com>
+    Maciej W. Rozycki <macro@mips.com>
+    Stefan Markovic <stefan.markovic@mips.com>
+    Sara Popadic <sara.popadic@imgtec.com>
+    Dragan Mladjenovic <dragan.mladjenovic@syrmia.com>
+    Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
+
+   This file is part of GDB.
+
+   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, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "gdbcore.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbtypes.h"
+#include "target.h"
+#include "arch-utils.h"
+#include "regcache.h"
+#include "osabi.h"
+#include "nanomips-tdep.h"
+#include "block.h"
+#include "reggroups.h"
+#include "opcode/nanomips.h"
+#include "elf/mips-common.h"
+#include "elf/nanomips.h"
+#include "elf-bfd.h"
+#include "symcat.h"
+#include "sim-regno.h"
+#include "dis-asm.h"
+#include "disasm.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "trad-frame.h"
+#include "infcall.h"
+#include "floatformat.h"
+#include "remote.h"
+#include "target-descriptions.h"
+#include "dwarf2/frame.h"
+#include "user-regs.h"
+#include "valprint.h"
+#include "ax.h"
+#include "target-float.h"
+#include <algorithm>
+
+#include "features/nanomips.c"
+
+static const struct objfile_data *nanomips_pdr_data;
+
+/* The sizes of registers.  */
+
+enum
+{
+  NANOMIPS32_REGSIZE = 4,
+  NANOMIPS64_REGSIZE = 8
+};
+
+static const char *const nanomips_abi_strings[] = {
+  "auto",
+  "p32",
+  "p64",
+  NULL
+};
+
+/* Enum describing the different kinds of breakpoints.  */
+
+enum nanomips_breakpoint_kind
+{
+  /* 16-bit breakpoint.  */
+  NANOMIPS_BP_KIND_16 = 3,
+
+  /* 32-bit breakpoint.  */
+  NANOMIPS_BP_KIND_32 = 5,
+};
+
+/* The standard register names, and all the valid aliases for them.  */
+struct register_alias
+{
+  const char *name;
+  int regnum;
+};
+
+
+static unsigned int nanomips_debug = 0;
+
+const struct nanomips_regnum *
+nanomips_regnum (struct gdbarch *gdbarch)
+{
+  return ((struct nanomips_gdbarch_tdep*) gdbarch_tdep (gdbarch))->regnum;
+}
+
+static int
+nanomips_fp_arg_regnum (struct gdbarch *gdbarch)
+{
+  gdb_assert (nanomips_regnum (gdbarch)->fpr != -1);
+
+  return nanomips_regnum (gdbarch)->fpr + NANOMIPS_FP0_REGNUM;
+}
+
+/* Return 1 if REGNUM refers to a floating-point general register, raw
+   or cooked.  Otherwise return 0.  */
+
+static int
+nanomips_float_register_p (struct gdbarch *gdbarch, int regnum)
+{
+  int rawnum = regnum % gdbarch_num_regs (gdbarch);
+  int fprnum = nanomips_regnum (gdbarch)->fpr;
+
+  return (fprnum != -1
+	  && rawnum >= fprnum + NANOMIPS_FP0_REGNUM
+	  && rawnum < fprnum + NANOMIPS_FCSR_REGNUM);
+}
+
+/* Return 1 if REGNUM refers to a floating-point control register, raw
+   or cooked.  Otherwise return 0.  */
+
+static int
+nanomips_float_control_register_p (struct gdbarch *gdbarch, int regnum)
+{
+  int rawnum = regnum % gdbarch_num_regs (gdbarch);
+  int fprnum = nanomips_regnum (gdbarch)->fpr;
+
+  return (fprnum != -1
+	  && (rawnum == fprnum + NANOMIPS_FCSR_REGNUM
+	      || rawnum == fprnum + NANOMIPS_FIR_REGNUM));
+}
+
+/* Return 1 if REGNUM refers to a DSP accumulator register, raw or cooked.
+   Otherwise return 0.  */
+
+static int
+nanomips_dspacc_register_p (struct gdbarch *gdbarch, int regnum)
+{
+  int rawnum = regnum % gdbarch_num_regs (gdbarch);
+  int dspnum = nanomips_regnum (gdbarch)->dsp;
+
+  return (dspnum != -1
+	  && rawnum >= dspnum + NANOMIPS_DSPHI0_REGNUM
+	  && rawnum < dspnum + NANOMIPS_DSPCTL_REGNUM);
+}
+
+#define FPU_TYPE(gdbarch) (((struct nanomips_gdbarch_tdep*) gdbarch_tdep (gdbarch))->fpu_type)
+
+/* Return the nanoMIPS ABI associated with GDBARCH.  */
+enum nanomips_abi
+nanomips_abi (struct gdbarch *gdbarch)
+{
+  return ((struct nanomips_gdbarch_tdep*) gdbarch_tdep (gdbarch))->nanomips_abi;
+}
+
+int
+nanomips_isa_regsize (struct gdbarch *gdbarch)
+{
+  return ((struct nanomips_gdbarch_tdep*) gdbarch_tdep (gdbarch))->register_size;
+}
+
+/* Return the currently configured (or set) saved register size.  */
+
+unsigned int
+nanomips_abi_regsize (struct gdbarch *gdbarch)
+{
+  switch (nanomips_abi (gdbarch))
+    {
+    case NANOMIPS_ABI_P32:
+      return 4;
+    case NANOMIPS_ABI_P64:
+      return 8;
+    case NANOMIPS_ABI_UNKNOWN:
+    default:
+      internal_error (__FILE__, __LINE__, _("bad switch"));
+    }
+}
+
+static void
+nanomips_xfer_register (struct gdbarch *gdbarch, struct regcache *regcache,
+        int reg_num, int length,
+        enum bfd_endian endian, gdb_byte *in,
+        const gdb_byte *out, int buf_offset)
+{
+  int reg_offset = 0;
+
+  gdb_assert (reg_num >= gdbarch_num_regs (gdbarch));
+  /* Need to transfer the left or right part of the register, based on
+     the targets byte order.  */
+  switch (endian)
+    {
+    case BFD_ENDIAN_BIG:
+      reg_offset = register_size (gdbarch, reg_num) - length;
+      break;
+    case BFD_ENDIAN_LITTLE:
+      reg_offset = 0;
+      break;
+    case BFD_ENDIAN_UNKNOWN:  /* Indicates no alignment.  */
+      reg_offset = 0;
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, _("bad switch"));
+    }
+  if (nanomips_debug)
+    gdb_printf (gdb_stderr,
+      "xfer $%d, reg offset %d, buf offset %d, length %d, ",
+      reg_num, reg_offset, buf_offset, length);
+  if (nanomips_debug && out != NULL)
+    {
+      int i;
+      gdb_printf (gdb_stdlog, "out ");
+      for (i = 0; i < length; i++)
+  gdb_printf (gdb_stdlog, "%02x", out[buf_offset + i]);
+    }
+  if (in != NULL)
+    regcache->cooked_read_part (reg_num, reg_offset, length, in + buf_offset);
+  if (out != NULL)
+    regcache->cooked_write_part (reg_num, reg_offset, length, out + buf_offset);
+  if (nanomips_debug && in != NULL)
+    {
+      int i;
+      gdb_printf (gdb_stdlog, "in ");
+      for (i = 0; i < length; i++)
+  gdb_printf (gdb_stdlog, "%02x", in[buf_offset + i]);
+    }
+  if (nanomips_debug)
+    gdb_printf (gdb_stdlog, "\n");
+}
+
+#define VM_MIN_ADDRESS (CORE_ADDR)0x400000
+
+static CORE_ADDR heuristic_proc_start (struct gdbarch *, CORE_ADDR);
+
+static void reinit_frame_cache_sfunc (const char *, int, struct cmd_list_element *);
+
+/* The list of available "set nanomips " and "show nanomips " commands.  */
+
+static struct cmd_list_element *setnanomipscmdlist = NULL;
+static struct cmd_list_element *shownanomipscmdlist = NULL;
+
+/* Return the name of the register corresponding to REGNO.  */
+
+static const char *
+nanomips_register_name (struct gdbarch *gdbarch, int regno)
+{
+  /* GPR names for p32 and p64 ABIs.  */
+  static const char *const gpr_names[]  = {
+    "zero", "at", "t4", "t5", "a0", "a1", "a2", "a3",
+    "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
+    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+    "t8", "t9", "k0", "k1", "gp", "sp", "raw_fp", "ra"
+  };
+
+  const char *name;
+  /* Map [gdbarch_num_regs .. 2*gdbarch_num_regs) onto the raw registers,
+     but then don't make the raw register names visible.  This (upper)
+     range of user visible register numbers are the pseudo-registers.
+
+     This approach was adopted accommodate the following scenario:
+     It is possible to debug a 64-bit device using a 32-bit
+     programming model.  In such instances, the raw registers are
+     configured to be 64-bits wide, while the pseudo registers are
+     configured to be 32-bits wide.  The registers that the user
+     sees - the pseudo registers - match the users expectations
+     given the programming model being used.  */
+  int rawnum = regno % gdbarch_num_regs (gdbarch);
+  if (regno < gdbarch_num_regs (gdbarch))
+    return "";
+
+  name = tdesc_register_name (gdbarch, rawnum);
+
+  if (rawnum >= 0 && rawnum < 32)
+    {
+      gdb_assert (name != NULL && name[0] != 0);
+      gdb_assert ((sizeof (gpr_names) / sizeof (gpr_names[0])) == 32);
+      return gpr_names[rawnum];
+    }
+
+  return name;
+}
+
+/* Return the groups that a nanoMIPS register can be categorised into.  */
+
+static int
+nanomips_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+			      const struct reggroup *reggroup)
+{
+  int vector_p;
+  int float_p;
+  int raw_p;
+  int rawnum = regnum % gdbarch_num_regs (gdbarch);
+  int pseudo = regnum / gdbarch_num_regs (gdbarch);
+  if (reggroup == all_reggroup)
+    return pseudo;
+  vector_p = (register_type (gdbarch, regnum))->is_vector ();
+  float_p = (nanomips_float_register_p (gdbarch, rawnum)
+	     || nanomips_float_control_register_p (gdbarch, rawnum));
+  /* FIXME: cagney/2003-04-13: Can't yet use gdbarch_num_regs
+     (gdbarch), as not all architectures are multi-arch.  */
+  raw_p = rawnum < gdbarch_num_regs (gdbarch);
+  if (gdbarch_register_name (gdbarch, regnum) == NULL
+      || gdbarch_register_name (gdbarch, regnum)[0] == '\0')
+    return 0;
+  if (reggroup == float_reggroup)
+    return float_p && pseudo;
+  if (reggroup == vector_reggroup)
+    return vector_p && pseudo;
+  if (reggroup == general_reggroup)
+    return (!vector_p && !float_p) && pseudo;
+  /* Save the pseudo registers.  Need to make certain that any code
+     extracting register values from a saved register cache also uses
+     pseudo registers.  */
+  if (reggroup == save_reggroup)
+    return raw_p && pseudo;
+  /* Restore the same pseudo register.  */
+  if (reggroup == restore_reggroup)
+    return raw_p && pseudo;
+  return 0;
+}
+
+/* Return the groups that a nanoMIPS register can be categorised into.
+   This version is only used if we have a target description which
+   describes real registers (and their groups).  */
+
+static int
+nanomips_tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+				    const struct reggroup *reggroup)
+{
+  int rawnum = regnum % gdbarch_num_regs (gdbarch);
+  int pseudo = regnum / gdbarch_num_regs (gdbarch);
+  int ret;
+
+  /* Only save, restore, and display the pseudo registers.  Need to
+     make certain that any code extracting register values from a
+     saved register cache also uses pseudo registers.
+
+     Note: saving and restoring the pseudo registers is slightly
+     strange; if we have 64 bits, we should save and restore all
+     64 bits.  But this is hard and has little benefit.  */
+  if (!pseudo)
+    return 0;
+
+  ret = tdesc_register_in_reggroup_p (gdbarch, rawnum, reggroup);
+  if (ret != -1)
+    return ret;
+
+  return nanomips_register_reggroup_p (gdbarch, regnum, reggroup);
+}
+
+/* Map the symbol table registers which live in the range [1 *
+   gdbarch_num_regs .. 2 * gdbarch_num_regs) back onto the corresponding raw
+   registers.  Take care of alignment and size problems.  */
+
+static enum register_status
+nanomips_pseudo_register_read (struct gdbarch *gdbarch,
+			       struct readable_regcache *regcache,
+			       int cookednum, gdb_byte *buf)
+{
+  int rawnum = cookednum % gdbarch_num_regs (gdbarch);
+  gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
+	      && cookednum < 2 * gdbarch_num_regs (gdbarch));
+  if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
+    return regcache->raw_read (rawnum, buf);
+  else if (register_size (gdbarch, rawnum) >
+	   register_size (gdbarch, cookednum))
+    {
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      LONGEST regval;
+      enum register_status status;
+
+      status = regcache->raw_read (rawnum, &regval);
+      if (status == REG_VALID)
+        store_signed_integer (buf, 4, byte_order, regval);
+      return status;
+    }
+  else
+    internal_error (__FILE__, __LINE__, _("bad register size"));
+}
+
+static void
+nanomips_pseudo_register_write (struct gdbarch *gdbarch,
+				struct regcache *regcache, int cookednum,
+				const gdb_byte *buf)
+{
+  int rawnum = cookednum % gdbarch_num_regs (gdbarch);
+  gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
+	      && cookednum < 2 * gdbarch_num_regs (gdbarch));
+  if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
+    regcache->raw_write (rawnum, buf);
+  else if (register_size (gdbarch, rawnum) >
+	   register_size (gdbarch, cookednum))
+    {
+      /* Sign extend the shortened version of the register prior
+         to placing it in the raw register.  This is required for
+         some mips64 parts in order to avoid unpredictable behavior.  */
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      LONGEST regval = extract_signed_integer (buf, 4, byte_order);
+      regcache_raw_write_signed (regcache, rawnum, regval);
+    }
+  else
+    internal_error (__FILE__, __LINE__, _("bad register size"));
+}
+
+static int
+nanomips_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+				     struct agent_expr *ax, int reg)
+{
+  int rawnum = reg % gdbarch_num_regs (gdbarch);
+  gdb_assert (reg >= gdbarch_num_regs (gdbarch)
+	      && reg < 2 * gdbarch_num_regs (gdbarch));
+
+  ax_reg_mask (ax, rawnum);
+
+  return 0;
+}
+
+static int
+nanomips_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
+				    struct agent_expr *ax, int reg)
+{
+  int rawnum = reg % gdbarch_num_regs (gdbarch);
+  gdb_assert (reg >= gdbarch_num_regs (gdbarch)
+	      && reg < 2 * gdbarch_num_regs (gdbarch));
+  if (register_size (gdbarch, rawnum) >= register_size (gdbarch, reg))
+    {
+      ax_reg (ax, rawnum);
+
+      if (register_size (gdbarch, rawnum) > register_size (gdbarch, reg))
+        {
+	  if (gdbarch_byte_order (gdbarch) != BFD_ENDIAN_BIG)
+	    {
+	      ax_const_l (ax, 32);
+	      ax_simple (ax, aop_lsh);
+	    }
+	  ax_const_l (ax, 32);
+	  ax_simple (ax, aop_rsh_signed);
+	}
+    }
+  else
+    internal_error (__FILE__, __LINE__, _("bad register size"));
+
+  return 0;
+}
+
+/* Table to translate nanomips 3-bit register field to
+   actual register number.  */
+static const signed char reg3_to_reg[8] = { 16, 17, 18, 19, 4, 5, 6, 7 };
+
+/* Heuristic_proc_start may hunt through the text section for a long
+   time across a 2400 baud serial line.  Allows the user to limit this
+   search.  */
+
+static int heuristic_fence_post = 0;
+
+/* Convert to/from a register and the corresponding memory value.  */
+
+/* This predicate tests for the case of a 4 byte floating point
+   value that is being transferred to or from a floating point
+   register which is 8 bytes wide.  */
+
+static int
+nanomips_convert_register_float_case_p (struct gdbarch *gdbarch, int regnum,
+					struct type *type)
+{
+  return (register_size (gdbarch, regnum) == 8
+	  && nanomips_float_register_p (gdbarch, regnum)
+	  && type->code () == TYPE_CODE_FLT && TYPE_LENGTH (type) == 4);
+}
+
+/* This predicate tests for the case of a value of less than 8
+   bytes in width that is being transfered to or from an 8 byte
+   general purpose register.  */
+static int
+nanomips_convert_register_gpreg_case_p (struct gdbarch *gdbarch, int regnum,
+					struct type *type)
+{
+  int num_regs = gdbarch_num_regs (gdbarch);
+
+  return (register_size (gdbarch, regnum) == 8
+          && regnum % num_regs > 0 && regnum % num_regs < 32
+          && TYPE_LENGTH (type) < 8);
+}
+
+static int
+nanomips_convert_register_p (struct gdbarch *gdbarch,
+			     int regnum, struct type *type)
+{
+  return (nanomips_convert_register_float_case_p (gdbarch, regnum, type)
+	  || nanomips_convert_register_gpreg_case_p (gdbarch, regnum, type));
+}
+
+static int
+nanomips_register_to_value (struct frame_info *frame, int regnum,
+			    struct type *type, gdb_byte *to,
+			    int *optimizedp, int *unavailablep)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  if (nanomips_convert_register_float_case_p (gdbarch, regnum, type))
+    {
+      /* single comes from low half of 64-bit register */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	{
+	  if (!get_frame_register_bytes (frame, regnum, 4, {to + 0, 4},
+					 optimizedp, unavailablep))
+	    return 0;
+	}
+      else
+	{
+	  if (!get_frame_register_bytes (frame, regnum, 0, {to + 0, 4},
+					 optimizedp, unavailablep))
+	    return 0;
+	}
+      *optimizedp = *unavailablep = 0;
+      return 1;
+    }
+  else if (nanomips_convert_register_gpreg_case_p (gdbarch, regnum, type))
+    {
+      int len = TYPE_LENGTH (type);
+      CORE_ADDR offset;
+
+      offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 - len : 0;
+      if (!get_frame_register_bytes (frame, regnum, offset, {to, (size_t)len},
+				     optimizedp, unavailablep))
+	return 0;
+
+      *optimizedp = *unavailablep = 0;
+      return 1;
+    }
+  else
+    {
+      internal_error (__FILE__, __LINE__,
+                      _("nanomips_register_to_value: unrecognized case"));
+    }
+}
+
+static void
+nanomips_value_to_register (struct frame_info *frame, int regnum,
+			    struct type *type, const gdb_byte *from)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  if (nanomips_convert_register_float_case_p (gdbarch, regnum, type))
+    {
+      /* single goes in low half of 64-bit register */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	put_frame_register_bytes (frame, regnum, 4, {from, 4});
+      else
+	put_frame_register_bytes (frame, regnum, 0, {from, 4});
+    }
+  else if (nanomips_convert_register_gpreg_case_p (gdbarch, regnum, type))
+    {
+      gdb_byte fill[8];
+      int len = TYPE_LENGTH (type);
+
+      /* Sign extend values, irrespective of type, that are stored to
+         a 64-bit general purpose register.  (32-bit unsigned values
+	 are stored as signed quantities within a 64-bit register.
+	 When performing an operation, in compiled code, that combines
+	 a 32-bit unsigned value with a signed 64-bit value, a type
+	 conversion is first performed that zeroes out the high 32 bits.)  */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	{
+	  if (from[0] & 0x80)
+	    store_signed_integer (fill, 8, BFD_ENDIAN_BIG, -1);
+	  else
+	    store_signed_integer (fill, 8, BFD_ENDIAN_BIG, 0);
+	  put_frame_register_bytes (frame, regnum, 0, {fill, (size_t)(8 - len)});
+	  put_frame_register_bytes (frame, regnum, 8 - len, {from, (size_t)len});
+	}
+      else
+	{
+	  if (from[len-1] & 0x80)
+	    store_signed_integer (fill, 8, BFD_ENDIAN_LITTLE, -1);
+	  else
+	    store_signed_integer (fill, 8, BFD_ENDIAN_LITTLE, 0);
+	  put_frame_register_bytes (frame, regnum, 0, {from, (size_t)len});
+	  put_frame_register_bytes (frame, regnum, len, {fill, (size_t)(8 - len)});
+	}
+    }
+  else
+    {
+      internal_error (__FILE__, __LINE__,
+                      _("nanomips_value_to_register: unrecognized case"));
+    }
+}
+
+/* Return the GDB type for the pseudo register REGNUM, which is the
+   ABI-level view.  This function is only called if there is a target
+   description which includes registers, so we know precisely the
+   types of hardware registers.  */
+
+static struct type *
+nanomips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
+{
+  const int num_regs = gdbarch_num_regs (gdbarch);
+  int rawnum = regnum % num_regs;
+  struct type *rawtype;
+
+  gdb_assert (regnum >= num_regs && regnum < 2 * num_regs);
+
+  /* Absent registers are still absent.  */
+  rawtype = gdbarch_register_type (gdbarch, rawnum);
+  if (TYPE_LENGTH (rawtype) == 0)
+    return rawtype;
+
+  /* Present the floating point registers however the hardware did;
+     do not try to convert between FPU layouts.  */
+  if (nanomips_float_register_p (gdbarch, rawnum))
+    return rawtype;
+
+  /* Floating-point control registers are always 32-bit even though for
+     backwards compatibility reasons 64-bit targets will transfer them
+     as 64-bit quantities even if using XML descriptions.  */
+  if (nanomips_float_control_register_p (gdbarch, rawnum))
+    return builtin_type (gdbarch)->builtin_int32;
+
+  /* Use pointer types for registers if we can.  For n32 we can not,
+     since we do not have a 64-bit pointer type.  */
+  if (nanomips_abi_regsize (gdbarch)
+      == TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr))
+    {
+      if (rawnum == NANOMIPS_SP_REGNUM
+	  || rawnum == nanomips_regnum (gdbarch)->badvaddr)
+	return builtin_type (gdbarch)->builtin_data_ptr;
+      else if (rawnum == NANOMIPS_PC_REGNUM)
+	return builtin_type (gdbarch)->builtin_func_ptr;
+    }
+
+  if (nanomips_abi_regsize (gdbarch) == 4 && TYPE_LENGTH (rawtype) == 8
+      && ((rawnum >= NANOMIPS_ZERO_REGNUM && rawnum <= NANOMIPS_PC_REGNUM)
+	  || rawnum == nanomips_regnum (gdbarch)->badvaddr
+	  || rawnum == nanomips_regnum (gdbarch)->status
+	  || rawnum == nanomips_regnum (gdbarch)->cause
+	  || nanomips_dspacc_register_p (gdbarch, rawnum)))
+    return builtin_type (gdbarch)->builtin_int32;
+
+  /* For all other registers, pass through the hardware type.  */
+  return rawtype;
+}
+
+/* Should the upper word of 64-bit addresses be zeroed?  */
+static enum auto_boolean mask_address_var = AUTO_BOOLEAN_AUTO;
+
+static int
+nanomips_mask_address_p (struct nanomips_gdbarch_tdep *tdep)
+{
+  switch (mask_address_var)
+    {
+    case AUTO_BOOLEAN_TRUE:
+      return 1;
+    case AUTO_BOOLEAN_FALSE:
+      return 0;
+      break;
+    case AUTO_BOOLEAN_AUTO:
+      return tdep->default_mask_address_p;
+    default:
+      internal_error (__FILE__, __LINE__,
+		      _("nanomips_mask_address_p: bad switch"));
+      return -1;
+    }
+}
+
+static void
+show_mask_address (struct ui_file *file, int from_tty,
+		   struct cmd_list_element *c, const char *value)
+{
+  struct nanomips_gdbarch_tdep *tdep = (struct nanomips_gdbarch_tdep*) gdbarch_tdep (target_gdbarch ());
+
+  deprecated_show_value_hack (file, from_tty, c, value);
+  switch (mask_address_var)
+    {
+    case AUTO_BOOLEAN_TRUE:
+      gdb_printf ("The 32 bit nanomips address mask is enabled\n");
+      break;
+    case AUTO_BOOLEAN_FALSE:
+      gdb_printf ("The 32 bit nanomips address mask is disabled\n");
+      break;
+    case AUTO_BOOLEAN_AUTO:
+      gdb_printf
+	("The 32 bit address mask is set automatically.  Currently %s\n",
+	 nanomips_mask_address_p (tdep) ? "enabled" : "disabled");
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, _("show_mask_address: bad switch"));
+      break;
+    }
+}
+
+/* nanoMIPS believes that the PC has a sign extended value.  Perhaps
+   all registers should be sign extended for simplicity?  */
+
+static CORE_ADDR
+nanomips_read_pc (struct readable_regcache *regcache)
+{
+  int regnum = gdbarch_pc_regnum (regcache->arch ());
+  LONGEST pc;
+
+  regcache->cooked_read (regnum, &pc);
+  return pc;
+}
+
+static CORE_ADDR
+nanomips_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  return frame_unwind_register_signed
+	   (next_frame, gdbarch_pc_regnum (gdbarch));
+}
+
+static CORE_ADDR
+nanomips_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  return frame_unwind_register_signed
+	   (next_frame, gdbarch_num_regs (gdbarch) + NANOMIPS_SP_REGNUM);
+}
+
+/* Assuming THIS_FRAME is a dummy, return the frame ID of that
+   dummy frame.  The frame ID's base needs to match the TOS value
+   saved by save_dummy_frame_tos(), and the PC match the dummy frame's
+   breakpoint.  */
+
+static struct frame_id
+nanomips_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+  return frame_id_build
+	   (get_frame_register_signed (this_frame,
+				       gdbarch_num_regs (gdbarch)
+				       + NANOMIPS_SP_REGNUM),
+	    get_frame_pc (this_frame));
+}
+
+/* Implement the "write_pc" gdbarch method.  */
+
+void
+nanomips_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  int regnum = gdbarch_pc_regnum (regcache->arch ());
+  regcache_cooked_write_unsigned (regcache, regnum, pc);
+}
+
+/* Fetch and return 16-bit instruction from the specified location.  */
+
+static ULONGEST
+nanomips_fetch_stack_slot (struct gdbarch *gdbarch, CORE_ADDR sp, int offset)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  return read_memory_unsigned_integer (sp + offset, 4, byte_order);
+}
+
+static ULONGEST
+nanomips_fetch_instruction (struct gdbarch *gdbarch,
+			    CORE_ADDR addr, int *errp)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  gdb_byte buf[INSN16_SIZE];
+  int err;
+
+  err = target_read_memory (addr, buf, INSN16_SIZE);
+  if (errp != NULL)
+    *errp = err;
+  if (err != 0)
+    {
+      if (errp == NULL)
+	memory_error (TARGET_XFER_E_IO, addr);
+      return 0;
+    }
+  return extract_unsigned_integer (buf, INSN16_SIZE, byte_order);
+}
+
+/* MicroMIPS instruction fields.  */
+#define micromips_op(x) ((x) >> 10)
+
+/* 16-bit/32-bit-high-part instruction formats, B and S refer to the lowest
+   bit and the size respectively of the field extracted.  */
+#define b0s4_imm(x) ((x) & 0xf)
+#define b0s5_imm(x) ((x) & 0x1f)
+#define b0s5_reg(x) ((x) & 0x1f)
+#define b0s7_imm(x) ((x) & 0x7f)
+#define b0s8_imm(x) ((x) & 0xff)
+#define b0s10_imm(x) ((x) & 0x3ff)
+#define b0u13_15s1_imm(x) (((x) & 0x1fff) | (((x) & 0x8000) >> 2))
+#define b1s4_imm(x) (((x) >> 1) & 0xf)
+#define b1s9_imm(x) (((x) >> 1) & 0x1ff)
+#define b2s1_op(x) (((x) >> 2) & 0x1)
+#define b2s3_cc(x) (((x) >> 2) & 0x7)
+#define b3s2_op(x) (((x) >> 3) & 0x3)
+#define b3s9_imm(x) (((x) >> 3) & 0x1ff)
+#define b4s2_regl(x) (((x) >> 4) & 0x3)
+#define b4s3_reg(x) (((x) >> 4) & 0x7)
+#define b4s4_imm(x) (((x) >> 4) & 0xf)
+#define b5s5_op(x) (((x) >> 5) & 0x1f)
+#define b5s5_reg(x) (((x) >> 5) & 0x1f)
+#define b6s4_op(x) (((x) >> 6) & 0xf)
+#define b7s3_reg(x) (((x) >> 7) & 0x7)
+#define b8s2_regl(x) (((x) >> 8) & 0x3)
+#define b8s7_op(x) (((x) >> 8) & 0x7f)
+
+/* 32-bit instruction formats, B and S refer to the lowest bit and the size
+   respectively of the field extracted.  */
+#define b0s6_op(x) ((x) & 0x3f)
+#define b0s10_op(x) ((x) & 0x3ff)
+#define b0s11_op(x) ((x) & 0x7ff)
+#define b0s12_imm(x) ((x) & 0xfff)
+#define b0u16_imm(x) ((x) & 0xffff)
+#define b0s21_imm(x) ((x) & 0x1fffff)
+#define b0s26_imm(x) ((x) & 0x3ffffff)
+#define b6s10_ext(x) (((x) >> 6) & 0x3ff)
+#define b9s3_op(x) (((x) >> 9) & 0x7)
+#define b11s5_reg(x) (((x) >> 11) & 0x1f)
+#define b16s5_reg(x) (((x) >> 16) & 0x1f)
+#define b21s5_reg(x) (((x) >> 21) & 0x1f)
+#define b11s7_imm(x) (((x) >> 11) & 0x7f)
+#define b12s4_op(x) (((x) >> 12) & 0xf)
+#define b12s5_op(x) (((x) >> 12) & 0x1f)
+#define b14s2_op(x) (((x) >> 14) & 0x3)
+#define b16s4_imm(x) (((x) >> 16) & 0xf)
+
+/* Return the size in bytes of the instruction INSN encoded in the ISA
+   instruction set.  */
+
+static int
+nanomips_insn_size (ULONGEST insn)
+{
+  if (micromips_op (insn) == 0x18)
+    return 3 * INSN16_SIZE;
+  else if ((micromips_op (insn) & 0x4) == 0x0)
+    return 2 * INSN16_SIZE;
+  else
+    return INSN16_SIZE;
+}
+
+/* Calculate the address of the next nanoMIPS instruction to execute
+   after the instruction at the address PC.  The nanomips_next_pc
+   function supports single_step when the remote target monitor or stub
+   is not developed enough to do a single_step.  It works by decoding the
+   current instruction and predicting where a branch will go.  This isn't
+   hard because all the data is available.  */
+
+static CORE_ADDR
+nanomips_next_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  ULONGEST insn;
+  CORE_ADDR offset, sp, ra;
+  int op, sreg, treg, uimm, count;
+  LONGEST val_rs, val_rt;
+
+  insn = nanomips_fetch_instruction (gdbarch, pc, NULL);
+  pc += INSN16_SIZE;
+  switch (nanomips_insn_size (insn))
+    {
+    /* 48-bit instructions.  */
+    case 3 * INSN16_SIZE:
+      /* No branch or jump instructions in this category.  */
+      pc += 2 * INSN16_SIZE;
+      break;
+
+    /* 32-bit instructions.  */
+    case 2 * INSN16_SIZE:
+      insn <<= 16;
+      insn |= nanomips_fetch_instruction (gdbarch, pc, NULL);
+      pc += INSN16_SIZE;
+      switch (micromips_op (insn >> 16))
+	{
+	case 0x0: /* P32 */
+	  op = b5s5_op (insn >> 16);
+	  switch (op)
+	    {
+	    case 0x0: /* P.RI */
+	      switch (b3s2_op (insn >> 16))
+		{
+		case 0x1: /* SYSCALL */
+		  if (b2s1_op (insn >> 16) == 0)
+		    {
+		      struct nanomips_gdbarch_tdep *tdep;
+
+		      tdep = (struct nanomips_gdbarch_tdep*) gdbarch_tdep (gdbarch);
+		      if (tdep->syscall_next_pc != NULL)
+			pc = tdep->syscall_next_pc (get_current_frame (), pc);
+		    }
+		  break;
+		}
+	      break;
+	    }
+	  break;
+
+	case 0x2: /* MOVE.BALC */
+	  offset = ((insn & 1) << 20 | ((insn >> 1) & 0xfffff)) << 1;
+	  offset = (offset ^ 0x200000) - 0x200000;
+	  pc += offset;
+	  break;
+
+	case 0xa: /* BALC, BC */
+	  offset = ((insn & 1) << 24 | ((insn >> 1) & 0xffffff)) << 1;
+	  offset = (offset ^ 0x2000000) - 0x2000000;
+	  pc += offset;
+	  break;
+
+	case 0x12: /* P.J P.BREG P.BALRC P.BALRSC */
+	  op = b12s4_op (insn);
+	  sreg = b0s5_reg (insn >> 16);
+	  treg = b5s5_reg (insn >> 16);
+	  if (op == 0x8) /* BALRSC, BRSC */
+	    {
+	      val_rs = regcache_raw_get_signed (regcache, sreg);
+	      pc += (val_rs << 1);
+	    }
+	  else if (op == 0 || op == 1) /* JALRC JALRC.HB */
+	    pc = regcache_raw_get_signed (regcache, sreg);
+	  break;
+
+	case 0x20: /* PP.SR */
+	  if ((b12s4_op (insn) == 0x3) && ((insn & 3) == 3)) /* RESTORE.JRC */
+	   {
+             sp = regcache_raw_get_signed (regcache, NANOMIPS_SP_REGNUM);
+             ra = regcache_raw_get_signed (regcache, NANOMIPS_RA_REGNUM);
+             sp += (((insn >> 3) & 0x1ff) << 3);
+             count = ((insn >> 16) & 0xf);
+             treg = b5s5_reg(insn >> 16);
+             if (count != 0 && treg <= 31 && (treg + count) > 31)
+               ra = nanomips_fetch_stack_slot (gdbarch, sp, -(31 - treg + 1) * 4);
+             pc = ra;
+           }
+	  break;
+
+	case 0x22: /* P.BR1 */
+	  op = b14s2_op (insn);
+	  sreg = b0s5_reg (insn >> 16);
+	  treg = b5s5_reg (insn >> 16);
+	  val_rs = regcache_raw_get_signed (regcache, sreg);
+	  val_rt = regcache_raw_get_signed (regcache, treg);
+	  offset = ((insn & 1) << 13 | ((insn >> 1) & 0x1fff)) << 1;
+	  offset = (offset ^ 0x4000) - 0x4000;
+	  if ((op == 0 && val_rs == val_rt) /* BEQC */
+	      || (op == 2 && val_rs >= val_rt) /* BGEC */
+	      || (op == 3
+		  && (ULONGEST) val_rs >= (ULONGEST) val_rt)) /* BGEUC */
+	    pc += offset;
+	  break;
+
+	case 0x2a: /* P.BR2 */
+	  op = b14s2_op (insn);
+	  sreg = b0s5_reg (insn >> 16);
+	  treg = b5s5_reg (insn >> 16);
+	  val_rs = regcache_raw_get_signed (regcache, sreg);
+	  val_rt = regcache_raw_get_signed (regcache, treg);
+	  offset = ((insn & 1) << 13 | ((insn >> 1) & 0x1fff)) << 1;
+	  offset = (offset ^ 0x4000) - 0x4000;
+	  if ((op == 0 && val_rs != val_rt) /* BNEC */
+	      || (op == 2 && val_rs < val_rt) /* BLTC */
+	      || (op == 3
+		  && (ULONGEST) val_rs < (ULONGEST) val_rt)) /* BLTUC */
+	    pc += offset;
+	  break;
+
+	case 0x32: /* P.BRI */
+	  op = b2s3_cc (insn >> 16);
+	  treg = b5s5_reg (insn >> 16);
+	  val_rt = regcache_raw_get_signed (regcache, treg);
+	  offset = ((insn & 1) << 10 | ((insn >> 1) & 0x3ff)) << 1;
+	  offset = (offset ^ 0x800) - 0x800;
+	  uimm = b11s7_imm (insn);
+	  if ((op == 0 && val_rt == uimm) /* BEQIC */
+              || (op == 1 && ((val_rt &  (1 << uimm)) == 0)) /* BBEQZC */
+	      || (op == 2 && val_rt >= uimm) /* BGEIC */
+	      || (op == 3 && (ULONGEST) val_rt >= uimm) /* BGEIUC */
+	      || (op == 4 && val_rt != uimm) /* BNEIC */
+              || (op == 5 && ((val_rt &  (1 << uimm)) != 0)) /* BBNEZC */
+	      || (op == 6 && val_rt < uimm) /* BLTIC */
+	      || (op == 7 && (ULONGEST) val_rt < uimm)) /* BLTIUC */
+	    pc += offset;
+	  break;
+
+	case 0x3a: /* P.BZ */
+	  op = (insn & 0x80000); /* 20th bit */
+	  treg = b5s5_reg (insn >> 16);
+	  val_rt = regcache_raw_get_signed (regcache, treg);
+	  offset = ((insn & 1) << 19 | ((insn >> 1) & 0x7ffff)) << 1;
+	  offset = (offset ^ 0x100000) - 0x100000;
+	  if ((op == 0 && val_rt == 0) /* BEQZC */
+	      || (op != 0 && val_rt != 0)) /* BNEZC */
+	    pc += offset;
+	  break;
+
+	default:
+	  break;
+	}
+
+    /* 16-bit instructions.  */
+    case INSN16_SIZE:
+      switch (micromips_op (insn))
+	{
+	case 0x4: /* P16 */
+	  op = b5s5_op (insn);
+	  switch (op)
+	    {
+	    case 0x0: /* P16.RI */
+	      switch (b3s2_op (insn))
+		{
+		case 0x1: /* SYSCALL[16] */
+		  if (b2s1_op (insn) == 0)
+		    {
+		      struct nanomips_gdbarch_tdep *tdep;
+
+		      tdep = (struct nanomips_gdbarch_tdep*) gdbarch_tdep (gdbarch);
+		      if (tdep->syscall_next_pc != NULL)
+			pc = tdep->syscall_next_pc (get_current_frame (), pc);
+		    }
+		  break;
+		}
+	      break;
+	    }
+	  break;
+
+	case 0x6: /* BC[16] */
+	case 0xe: /* BALC[16] */
+	  offset = ((insn & 1) << 9 | ((insn >> 1) & 0x1ff)) << 1;
+	  offset = (offset ^ 0x400) - 0x400;
+	  pc += offset;
+	  break;
+
+	case 0x7: /* RESTORE.JRC[16] */
+	  if ((insn & 1) == 0 && (insn & 0x20) == 0x20 && ((insn >> 8) & 1) == 1)
+          {
+            sp = regcache_raw_get_signed (regcache, NANOMIPS_SP_REGNUM);
+	    ra = regcache_raw_get_signed (regcache, NANOMIPS_RA_REGNUM);
+            sp += (((insn >> 4) & 0xf) << 4);
+            count = insn & 0xf;
+            treg = ((insn >> 9) & 0x1) ? NANOMIPS_RA_REGNUM : NANOMIPS_FP_REGNUM;
+            if (count != 0 && treg + count > 31) {
+                ra = nanomips_fetch_stack_slot (gdbarch, sp, -(31 - treg + 1) * 4);
+            }
+            pc = ra;
+          }
+	  break;
+
+	case 0x26: /* BEQZC[16] */
+	  treg = reg3_to_reg[b7s3_reg (insn)];
+	  val_rt = regcache_raw_get_signed (regcache, treg);
+	  offset = ((insn & 1) << 6 | ((insn >> 1) & 0x3f)) << 1;
+	  offset = (offset ^ 0x80) - 0x80;
+	  if (val_rt == 0)
+	    pc += offset;
+	  break;
+
+	case 0x2e: /* BNEZC[16] */
+	  treg = reg3_to_reg[b7s3_reg (insn)];
+	  val_rt = regcache_raw_get_signed (regcache, treg);
+	  offset = ((insn & 1) << 6 | ((insn >> 1) & 0x3f)) << 1;
+	  offset = (offset ^ 0x80) - 0x80;
+	  if (val_rt != 0)
+	    pc += offset;
+	  break;
+
+	case 0x36: /* P16.BR P16.JRC */
+	  sreg = b4s3_reg (insn);
+	  treg = b7s3_reg (insn);
+	  val_rs = regcache_raw_get_signed (regcache, reg3_to_reg[sreg]);
+	  val_rt = regcache_raw_get_signed (regcache, reg3_to_reg[treg]);
+	  offset = insn & 0xf;
+	  /* BEQC[16] BEQC[16] */
+	  if ((sreg < treg && offset != 0 && val_rs == val_rt)
+	      || (sreg >= treg && offset != 0 && val_rs != val_rt))
+	    pc += (offset << 1);
+	  else if (offset == 0) /* JALRC[16] JRC */
+	    pc = regcache_raw_get_signed (regcache, b5s5_reg(insn));
+	  break;
+
+	default:
+	  break;
+	}
+      break;
+
+    default:
+      break;
+    }
+  return pc;
+}
+
+struct nanomips_frame_cache
+{
+  CORE_ADDR base;
+  struct trad_frame_saved_reg *saved_regs;
+};
+
+/* Set a register's saved stack address in temp_saved_regs.  If an
+   address has already been set for this register, do nothing; this
+   way we will only recognize the first save of a given register in a
+   function prologue.
+
+   For simplicity, save the address in both [0 .. gdbarch_num_regs) and
+   [gdbarch_num_regs .. 2*gdbarch_num_regs).
+   Strictly speaking, only the second range is used as it is only second
+   range (the ABI instead of ISA registers) that comes into play when finding
+   saved registers in a frame.  */
+
+static void
+set_reg_offset (struct gdbarch *gdbarch, struct nanomips_frame_cache *this_cache,
+		int regnum, CORE_ADDR offset)
+{
+  if (this_cache != NULL
+      && this_cache->saved_regs[regnum].addr() == -1)
+    {
+      this_cache->saved_regs[regnum + 0 * gdbarch_num_regs (gdbarch)].set_addr(
+        offset);
+      this_cache->saved_regs[regnum + 1 * gdbarch_num_regs (gdbarch)].set_addr(
+        offset);
+    }
+}
+
+/* Analyze the function prologue from START_PC to LIMIT_PC.  Return
+   the address of the first instruction past the prologue.  */
+
+static CORE_ADDR
+nanomips_scan_prologue (struct gdbarch *gdbarch,
+			CORE_ADDR start_pc, CORE_ADDR limit_pc,
+			struct frame_info *this_frame,
+			struct nanomips_frame_cache *this_cache)
+{
+  CORE_ADDR end_prologue_addr;
+  int prev_non_prologue_insn = 0;
+  int frame_reg = NANOMIPS_SP_REGNUM;
+  int this_non_prologue_insn;
+  int non_prologue_insns = 0;
+  long frame_offset = 0;	/* Size of stack frame.  */
+  long frame_adjust = 0;	/* Offset of FP from SP.  */
+  CORE_ADDR prev_pc;
+  CORE_ADDR cur_pc;
+  ULONGEST insn;		/* current instruction */
+  CORE_ADDR sp;
+  long offset;
+  long sp_adj;
+  long v1_off = 0;		/* The assumption is LUI will replace it.  */
+  int breg;
+  int dreg;
+  int sreg;
+  int treg;
+  int loc;
+  int op;
+
+  /* Can be called when there's no process, and hence when there's no
+     THIS_FRAME.  */
+  if (this_frame != NULL)
+    sp = get_frame_register_signed (this_frame,
+				    gdbarch_num_regs (gdbarch)
+				    + NANOMIPS_SP_REGNUM);
+  else
+    sp = 0;
+
+  if (limit_pc > start_pc + 200)
+    limit_pc = start_pc + 200;
+  prev_pc = start_pc;
+
+  /* Permit at most one non-prologue non-control-transfer instruction
+     in the middle which may have been reordered by the compiler for
+     optimisation.  */
+  for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += loc)
+    {
+      this_non_prologue_insn = 0;
+      sp_adj = 0;
+      loc = 0;
+      insn = nanomips_fetch_instruction (gdbarch, cur_pc, NULL);
+      loc += INSN16_SIZE;
+      switch (nanomips_insn_size (insn))
+	{
+	/* 48-bit instructions.  */
+	case 3 * INSN16_SIZE:
+	  if (micromips_op (insn) == 0x18)
+	    {
+	      op = b0s5_imm (insn);
+	      treg = b5s5_reg (insn);
+	      offset = nanomips_fetch_instruction (gdbarch, cur_pc + 2, NULL);
+	      offset <<= 16;
+	      offset |= nanomips_fetch_instruction (gdbarch, cur_pc + 4, NULL);
+	      if (op == 0x0 && treg == 3) /* LI48 $v1, imm32 */
+		v1_off = offset;
+	      else if (op == 0x1 /* ADDIU48 $sp, imm32 */
+		       && treg == NANOMIPS_SP_REGNUM)
+		sp_adj = offset;
+	      else
+		this_non_prologue_insn = 1;
+	    }
+	      else
+		this_non_prologue_insn = 1;
+	  break;
+
+	/* 32-bit instructions.  */
+	case 2 * INSN16_SIZE:
+	  insn <<= 16;
+	  insn |= nanomips_fetch_instruction (gdbarch,
+					  cur_pc + loc, NULL);
+	  loc += INSN16_SIZE;
+
+	  switch (micromips_op (insn >> 16))
+	    {
+	    case 0x0: /* PP.ADDIU bits 000000 */
+	      sreg = b0s5_reg (insn >> 16);
+	      treg = b5s5_reg (insn >> 16);
+	      offset = b0u16_imm (insn);
+	      if (sreg == treg
+		  && treg == NANOMIPS_SP_REGNUM) /* ADDIU $sp, $sp, imm */
+		sp_adj = offset;
+	      else if (sreg == NANOMIPS_SP_REGNUM
+		       && treg == NANOMIPS_FP_REGNUM) /* ADDIU $fp, $sp, imm */
+		{
+		  frame_adjust = offset;
+		  frame_reg = NANOMIPS_FP_REGNUM;
+		}
+	      else if (sreg != NANOMIPS_GP_REGNUM
+		       || treg != NANOMIPS_GP_REGNUM)
+		this_non_prologue_insn = 1;
+	      break;
+
+	    case 0x8: /* P32A: bits 001000 */
+	      op = b0s10_op (insn);
+	      sreg = b0s5_reg (insn >> 16);
+	      treg = b5s5_reg (insn >> 16);
+	      dreg = b11s5_reg (insn);
+	      if (op == 0x1d0	/* SUBU: bits 001000 0111010000 */
+		  && dreg == NANOMIPS_SP_REGNUM && sreg == NANOMIPS_SP_REGNUM
+		  && treg == 3)	/* SUBU $sp, $v1 */
+		sp_adj = v1_off;
+	      else
+		this_non_prologue_insn = 1;
+	      break;
+
+	    case 0x20: /* P.U12 bits 100000 */
+	      /* SAVE: bits 100000 rt 0 count 0011 */
+	      if (b12s4_op (insn) == 0x3)
+		{
+		  int rt, this_rt, gp, use_gp;
+		  int counter = 0, count = b16s4_imm (insn);
+		  long this_offset;
+		  offset = b3s9_imm (insn) << 3;
+		  rt = b21s5_reg (insn);
+		  sp_adj = -offset;
+		  gp = (insn >> 2) & 1;
+		  while (counter != count)
+		    {
+		      use_gp = gp & (counter == count - 1);
+		      if (use_gp)
+			this_rt = NANOMIPS_GP_REGNUM;
+		      else
+			this_rt = (((rt >> 4) & 1) << 4) | (rt + counter);
+		      this_offset = (counter + 1) << 2;
+		      set_reg_offset (gdbarch, this_cache, this_rt,
+				      sp + offset - this_offset);
+		      counter++;
+		    }
+		}
+	      else if (b12s4_op (insn) == 8) /* ADDIU[NEG]: bits 100000 1000 */
+		{
+		  sreg = b0s5_reg (insn >> 16);
+		  treg = b5s5_reg (insn >> 16);
+		  if (sreg == treg && sreg == NANOMIPS_SP_REGNUM)
+			  /* ADDIU[NEG] $sp, $sp, imm */
+		    {
+		      offset = b0s11_op (insn);
+		      sp_adj = -offset;
+		    }
+		}
+	      else if (b12s4_op (insn) == 0) /* ORI: bits 100000 0000 */
+		{
+		  sreg = b0s5_reg (insn >> 16);
+		  treg = b5s5_reg (insn >> 16);
+		  if (sreg == treg && treg == 3) /* ORI $v1, $v1, imm */
+		    v1_off |= b0s11_op (insn);
+		  else
+		    this_non_prologue_insn = 1;
+		}
+		else
+		  this_non_prologue_insn = 1;
+	      break;
+
+	    case 0x21: /* P.LS.U12 bits 100001 */
+	      if (b12s4_op (insn) == 0x9) /* SW 100001 1001 */
+		{
+		  breg = b0s5_reg (insn >> 16);
+		  sreg = b5s5_reg (insn >> 16);
+		  offset = b0s12_imm (insn);
+		  if (breg == NANOMIPS_SP_REGNUM) /* SW reg,offset($sp) */
+		    set_reg_offset (gdbarch, this_cache, sreg, sp + offset);
+		  else
+		    this_non_prologue_insn = 1;
+		}
+	      break;
+
+	    case 0x29: /* P.LS.S9 bits 101001 */
+	      if (b8s7_op (insn) == 0x48) /* SW[S9] 101001 1001 0 00 */
+		{
+		  breg = b0s5_reg (insn >> 16);
+		  sreg = b5s5_reg (insn >> 16);
+		  offset = (((insn >> 15) & 1) << 8) | b0s8_imm (insn);
+		  offset = (offset ^ 0x100) - 0x100;
+		  if (breg == NANOMIPS_SP_REGNUM) /* SW[S9] reg,offset($sp) */
+		    set_reg_offset (gdbarch, this_cache, sreg, sp + offset);
+		  else
+		    this_non_prologue_insn = 1;
+		}
+	      break;
+
+	    case 0x38: /* P.LUI bits 111000 */
+	      treg = b5s5_reg (insn >> 16);
+	      if ((insn & 2) == 0 /* LU20I bits 111000 0 */
+		  && treg == 3) /* LU20I $v1, imm */
+		{
+		  v1_off = ((insn & 1) << 19)
+			    | (((insn >> 2) & 0x3ff) << 9)
+			    | (((insn >> 12) & 0x1ff));
+		  v1_off = v1_off << 12;
+		}
+	      else
+		this_non_prologue_insn = 1;
+	      break;
+
+	   default:
+	     this_non_prologue_insn = 1;
+	     break;
+	   }
+
+	  insn >>= 16;
+	  break;
+
+	/* 16-bit instructions.  */
+	case INSN16_SIZE:
+	  switch (micromips_op (insn))
+	    {
+	    case 0x4: /* MOVE: bits 000100 */
+	      sreg = b0s5_reg (insn);
+	      dreg = b5s5_reg (insn);
+	      if (sreg == NANOMIPS_SP_REGNUM && dreg == NANOMIPS_FP_REGNUM)
+				/* MOVE  $fp, $sp */
+		frame_reg = NANOMIPS_FP_REGNUM;
+	      else
+		this_non_prologue_insn = 1;
+	      break;
+
+	    case 0x7: /* SAVE: bits 000111 */
+	      {
+		int rt, rt1, this_rt;
+		int counter = 0, count = b0s4_imm (insn);
+		long this_offset;
+		offset = b4s4_imm (insn) << 4;
+		rt1 = (insn >> 9) & 1;
+		rt = 30 | rt1;
+		sp_adj = -offset;
+		while (counter != count)
+		  {
+		    this_rt = (((rt >> 4) & 1) << 4) | (rt + counter);
+		    this_offset = (counter + 1) << 2;
+		    set_reg_offset (gdbarch, this_cache, this_rt,
+				    sp + offset - this_offset);
+		    counter++;
+		  }
+		break;
+	      }
+
+	    case 0x35: /* SW[SP]: bits 110101 */
+	      treg = b5s5_reg (insn);
+	      offset = b0s5_imm (insn);
+	      set_reg_offset (gdbarch, this_cache, treg, sp + offset);
+	      break;
+
+	    default:
+	      this_non_prologue_insn = 1;
+	      break;
+	    }
+	  break;
+	}
+
+      if (sp_adj < 0)
+	frame_offset -= sp_adj;
+
+      non_prologue_insns += this_non_prologue_insn;
+
+      if (non_prologue_insns > 1 || sp_adj > 0)
+  break;
+
+      prev_non_prologue_insn = this_non_prologue_insn;
+      prev_pc = cur_pc;
+    }
+
+  if (this_cache != NULL)
+    {
+      this_cache->base =
+	(get_frame_register_signed (this_frame,
+				    gdbarch_num_regs (gdbarch) + frame_reg)
+	 + frame_offset - frame_adjust);
+      /* FIXME: brobecker/2004-10-10: Just as in the mips32 case, we should
+	 be able to get rid of the assignment below, evetually. But it's
+	 still needed for now.  */
+      this_cache->saved_regs[gdbarch_num_regs (gdbarch) + NANOMIPS_PC_REGNUM]
+	= this_cache->saved_regs[gdbarch_num_regs (gdbarch)
+				 + NANOMIPS_RA_REGNUM];
+    }
+
+  /* Set end_prologue_addr to the address of the instruction immediately
+     after the last one we scanned.  Unless the last one looked like a
+     non-prologue instruction (and we looked ahead), in which case use
+     its address instead.  */
+  end_prologue_addr
+    = prev_non_prologue_insn ? prev_pc : cur_pc;
+
+  return end_prologue_addr;
+}
+
+/* Heuristic unwinder for procedures using nanoMIPS instructions.
+   Procedures that use the 32-bit instruction set are handled by the
+   mips_insn32 unwinder.  Likewise MIPS16 and the mips_insn16 unwinder. */
+
+static struct nanomips_frame_cache *
+nanomips_frame_cache (struct frame_info *this_frame, void **this_cache)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct nanomips_frame_cache *cache;
+
+  if ((*this_cache) != NULL)
+    return (struct nanomips_frame_cache *) (*this_cache);
+
+  cache = FRAME_OBSTACK_ZALLOC (struct nanomips_frame_cache);
+  (*this_cache) = cache;
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+  /* Analyze the function prologue.  */
+  {
+    const CORE_ADDR pc = get_frame_address_in_block (this_frame);
+    CORE_ADDR start_addr;
+
+    find_pc_partial_function (pc, NULL, &start_addr, NULL);
+    if (start_addr == 0)
+      start_addr = heuristic_proc_start (get_frame_arch (this_frame), pc);
+    /* We can't analyze the prologue if we couldn't find the begining
+       of the function.  */
+    if (start_addr == 0)
+      return cache;
+
+    nanomips_scan_prologue (gdbarch, start_addr, pc, this_frame,
+			    (struct nanomips_frame_cache *) *this_cache);
+  }
+
+  /* gdbarch_sp_regnum contains the value and not the address.  */
+  cache->saved_regs[gdbarch_num_regs (gdbarch)
+        + NANOMIPS_SP_REGNUM].set_value (cache->base);
+
+  return (struct nanomips_frame_cache *) (*this_cache);
+}
+
+static void
+nanomips_frame_this_id (struct frame_info *this_frame, void **this_cache,
+			struct frame_id *this_id)
+{
+  struct nanomips_frame_cache *info = nanomips_frame_cache (this_frame,
+							    this_cache);
+  /* This marks the outermost frame.  */
+  if (info->base == 0)
+    return;
+  (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
+}
+
+static struct value *
+nanomips_frame_prev_register (struct frame_info *this_frame,
+			      void **this_cache, int regnum)
+{
+  struct nanomips_frame_cache *info = nanomips_frame_cache (this_frame,
+							    this_cache);
+  return trad_frame_get_prev_register (this_frame, info->saved_regs, regnum);
+}
+
+static int
+nanomips_frame_sniffer (const struct frame_unwind *self,
+			struct frame_info *this_frame, void **this_cache)
+{
+  return 1;
+}
+
+static const struct frame_unwind nanomips_frame_unwind =
+{
+  "nanoMIPS insn prologue",
+  NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
+  nanomips_frame_this_id,
+  nanomips_frame_prev_register,
+  NULL,
+  nanomips_frame_sniffer
+};
+
+static CORE_ADDR
+nanomips_frame_base_address (struct frame_info *this_frame,
+			     void **this_cache)
+{
+  struct nanomips_frame_cache *info = nanomips_frame_cache (this_frame,
+							    this_cache);
+  return info->base;
+}
+
+static const struct frame_base nanomips_frame_base =
+{
+  &nanomips_frame_unwind,
+  nanomips_frame_base_address,
+  nanomips_frame_base_address,
+  nanomips_frame_base_address
+};
+
+static const struct frame_base *
+nanomips_frame_base_sniffer (struct frame_info *this_frame)
+{
+  return &nanomips_frame_base;
+}
+
+/* nanomips_addr_bits_remove - remove useless address bits  */
+
+static CORE_ADDR
+nanomips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  struct nanomips_gdbarch_tdep *tdep = (struct nanomips_gdbarch_tdep*) gdbarch_tdep (gdbarch);
+
+  if (nanomips_mask_address_p (tdep)
+      && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
+    /* This hack is a work-around for existing boards using PMON, the
+       simulator, and any other 64-bit targets that doesn't have true
+       64-bit addressing.  On these targets, the upper 32 bits of
+       addresses are ignored by the hardware.  Thus, the PC or SP are
+       likely to have been sign extended to all 1s by instruction
+       sequences that load 32-bit addresses.  For example, a typical
+       piece of code that loads an address is this:
+
+       lui $r2, <upper 16 bits>
+       ori $r2, <lower 16 bits>
+
+       But the lui sign-extends the value such that the upper 32 bits
+       may be all 1s.  The workaround is simply to mask off these
+       bits.  In the future, gcc may be changed to support true 64-bit
+       addressing, and this masking will have to be disabled.  */
+    return addr &= 0xffffffffUL;
+  else
+    return addr;
+}
+
+
+/* Checks for an atomic sequence of instructions beginning with a LL/LLD
+   instruction and ending with a SC/SCD instruction.  If such a sequence
+   is found, attempt to step through it.  A breakpoint is placed at the end of
+   the sequence.  */
+
+static std::vector<CORE_ADDR>
+nanomips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
+				    CORE_ADDR pc)
+{
+  const int atomic_sequence_length = 16; /* Instruction sequence length.  */
+  int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */
+  CORE_ADDR breaks[2] = {CORE_ADDR_MAX, CORE_ADDR_MAX};
+  CORE_ADDR branch_bp = 0; /* Breakpoint at branch instruction's
+			      destination.  */
+  CORE_ADDR loc = pc;
+  int sc_found = 0;
+  ULONGEST insn;
+  int insn_count;
+  int index;
+
+  /* Assume all atomic sequences start with a ll/lld instruction.  */
+  insn = nanomips_fetch_instruction (gdbarch, loc, NULL);
+  if (micromips_op (insn) != 0x29)	/* P.LL: bits 101001 */
+    return {};
+  loc += INSN16_SIZE;
+  insn <<= 16;
+  insn |= nanomips_fetch_instruction (gdbarch, loc, NULL);
+  if (b8s7_op (insn) != 0x51)	/* LL: bits 101001 1010 0 01 */
+    return {};
+  loc += INSN16_SIZE;
+
+  /* Assume all atomic sequences end with an sc/scd instruction.  Assume
+     that no atomic sequence is longer than "atomic_sequence_length"
+     instructions.  */
+  for (insn_count = 0;
+       !sc_found && insn_count < atomic_sequence_length;
+       ++insn_count)
+    {
+      int is_branch = 0, op;
+      CORE_ADDR offset;
+
+      insn = nanomips_fetch_instruction (gdbarch, loc, NULL);
+      loc += INSN16_SIZE;
+
+      /* Assume that there is at most one conditional branch in the
+         atomic sequence.  If a branch is found, put a breakpoint in
+         its destination address.  */
+      switch (nanomips_insn_size (insn))
+	{
+	/* 32-bit instructions.  */
+	case 2 * INSN16_SIZE:
+	  insn <<= 16;
+	  insn |= nanomips_fetch_instruction (gdbarch, loc, NULL);
+	  loc += INSN16_SIZE;
+
+	  switch (micromips_op (insn >> 16))
+	    {
+	    case 0xa: /* BALC, BC */
+	      offset = ((insn & 1) << 24 | ((insn >> 1) & 0xffffff)) << 1;
+	      offset = (offset ^ 0x2000000) - 0x2000000;
+	      branch_bp = loc + offset;
+	      is_branch = 1;
+	      break;
+
+	    case 0x12:
+	      op = b12s4_op (insn);
+	      if (op == 0x8) /* BALRC, BALRSC */
+		return {}; /* Fall back to the standard single-step code. */
+	      else if (op == 0 || op == 1) /* JALRC JALRC.HB */
+		return {}; /* Fall back to the standard single-step code. */
+	      break;
+
+	    case 0x20: /* PP.SR */
+	      if (b12s5_op (insn) == 0x13) /* RESTORE.JRC */
+		return {}; /* Fall back to the standard single-step code. */
+	      break;
+
+	    case 0x22: /* P.BR1 */
+	    case 0x2a: /* P.BR2 */
+	      op = b14s2_op (insn);
+	      offset = ((insn & 1) << 13 | ((insn >> 1) & 0x1fff)) << 1;
+	      offset = (offset ^ 0x4000) - 0x4000;
+	      if (op == 0 /* BEQC, BNEC */
+		  || op == 2 /* BGEC, BLTC */
+		  || op == 3) /* BGEUC, BLTUC */
+		{
+		  branch_bp = loc + offset;
+		  is_branch = 1;
+		}
+	      break;
+
+	    case 0x32: /* P.BRI */
+	      op = b2s3_cc (insn >> 16);
+	      offset = ((insn & 1) << 10 | ((insn >> 1) & 0x3ff)) << 1;
+	      offset = (offset ^ 0x800) - 0x800;
+	      if (op == 0 /* BEQIC */
+		  || op == 2 /* BGEIC */
+		  || op == 3 /* BGEIUC */
+		  || op == 4 /* BNEIC */
+		  || op == 6 /* BLTIC */
+		  || op == 7 ) /* BLTIUC */
+		{
+		  branch_bp = loc + offset;
+		  is_branch = 1;
+		}
+	      break;
+
+	    case 0x3a: /* P.BZ */
+	      op = (insn & 0x80000); /* 20th bit */
+	      offset = ((insn & 1) << 19 | ((insn >> 1) & 0x7ffff)) << 1;
+	      offset = (offset ^ 0x100000) - 0x100000;
+	      if (op == 0 /* BEQZC */
+	          || op != 0 ) /* BNEZC */
+		{
+		  branch_bp = loc + offset;
+		  is_branch = 1;
+		}
+	      break;
+
+	    case 0x29: /* P.SC: bits 101001 */
+	      if (b8s7_op (insn) == 0x59) /* SC: bits 101001 1011 0 01 */
+		sc_found = 1;
+	      break;
+	    }
+	  break;
+
+	/* 16-bit instructions.  */
+	case INSN16_SIZE:
+	  switch (micromips_op (insn))
+	    {
+	    case 0x6: /* BC[16] */
+	    case 0xe: /* BALC[16] */
+	      offset = ((insn & 1) << 9 | ((insn >> 1) & 0x1ff)) << 1;
+	      offset = (offset ^ 0x400) - 0x400;
+	      branch_bp = loc + offset;
+	      is_branch = 1;
+	      break;
+
+	    case 0x7: /* RESTORE.JRC[16] */
+	      if ((insn & 1) == 0 && (insn & 0x20) == 0x20)
+		return {}; /* Fall back to the standard single-step code. */
+	      break;
+
+	    case 0x26: /* BEQZC[16] */
+	    case 0x2e: /* BNEZC[16] */
+	      offset = ((insn & 1) << 6 | ((insn >> 1) & 0x3f)) << 1;
+	      offset = (offset ^ 0x80) - 0x80;
+	      branch_bp = loc + offset;
+	      is_branch = 1;
+	      break;
+
+	    case 0x36: /* P16.BR P16.JRC */
+	      offset = insn & 0xf;
+	      /* BEQC[16] BEQC[16] */
+	      if (offset != 0)
+		{
+		  branch_bp = loc + offset;
+		  is_branch = 1;
+		}
+	      else if (offset == 0) /* JALRC[16] JRC */
+		return {}; /* Fall back to the standard single-step code. */
+	      break;
+	    }
+	  break;
+	}
+
+      if (is_branch)
+	{
+	  if (last_breakpoint >= 1)
+	    return {}; /* More than one branch found, fallback to the
+			 standard single-step code.  */
+	  breaks[1] = branch_bp;
+	  last_breakpoint++;
+	}
+    }
+  if (!sc_found)
+    return {};
+
+  /* Insert a breakpoint right after the end of the atomic sequence.  */
+  breaks[0] = loc;
+
+  /* Check for duplicated breakpoints.  Check also for a breakpoint
+     placed (branch instruction's destination) in the atomic sequence */
+  if (last_breakpoint && pc <= breaks[1] && breaks[1] <= breaks[0])
+    last_breakpoint = 0;
+
+  std::vector<CORE_ADDR> next_pcs;
+
+  /* Effectively inserts the breakpoints.  */
+  for (index = 0; index <= last_breakpoint; index++)
+    next_pcs.push_back (breaks[index]);
+
+  return next_pcs;
+}
+
+/* nanomips_software_single_step() is called just before we want to resume
+   the inferior, if we want to single-step it but there is no hardware
+   or kernel single-step support (nanoMIPS on GNU/Linux for example).  We find
+   the target of the coming instruction and breakpoint it.  */
+
+std::vector<CORE_ADDR>
+nanomips_software_single_step (struct regcache *regcache)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  CORE_ADDR pc, next_pc;
+
+  pc = regcache_read_pc (regcache);
+  std::vector<CORE_ADDR> next_pcs =
+			nanomips_deal_with_atomic_sequence (gdbarch, pc);
+
+  if (!next_pcs.empty ())
+    return next_pcs;
+
+  next_pc = nanomips_next_pc (regcache, pc);
+
+  return {next_pc};
+}
+
+/* This fencepost looks highly suspicious to me.  Removing it also
+   seems suspicious as it could affect remote debugging across serial
+   lines.  */
+
+static CORE_ADDR
+heuristic_proc_start (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  CORE_ADDR start_pc;
+  CORE_ADDR fence;
+  int instlen;
+  struct inferior *inf;
+
+  pc = gdbarch_addr_bits_remove (gdbarch, pc);
+  start_pc = pc;
+  fence = start_pc - heuristic_fence_post;
+  if (start_pc == 0)
+    return 0;
+
+  if (heuristic_fence_post == -1 || fence < VM_MIN_ADDRESS)
+    fence = VM_MIN_ADDRESS;
+
+  instlen = INSN16_SIZE;
+
+  inf = current_inferior ();
+
+  /* Search back for previous return.  */
+  for (start_pc -= instlen;; start_pc -= instlen)
+    if (start_pc < fence)
+      {
+	/* It's not clear to me why we reach this point when
+	   stop_soon, but with this test, at least we
+	   don't print out warnings for every child forked (eg, on
+	   decstation).  22apr93 rich@cygnus.com.  */
+	if (inf->control.stop_soon == NO_STOP_QUIETLY)
+	  {
+	    static int blurb_printed = 0;
+
+	    warning (_("GDB can't find the start of the function at %s."),
+		     paddress (gdbarch, pc));
+
+	    if (!blurb_printed)
+	      {
+		/* This actually happens frequently in embedded
+		   development, when you first connect to a board
+		   and your stack pointer and pc are nowhere in
+		   particular.  This message needs to give people
+		   in that situation enough information to
+		   determine that it's no big deal.  */
+		gdb_printf ("\n\
+    GDB is unable to find the start of the function at %s\n\
+and thus can't determine the size of that function's stack frame.\n\
+This means that GDB may be unable to access that stack frame, or\n\
+the frames below it.\n\
+    This problem is most likely caused by an invalid program counter or\n\
+stack pointer.\n\
+    However, if you think GDB should simply search farther back\n\
+from %s for code which looks like the beginning of a\n\
+function, you can increase the range of the search using the `set\n\
+heuristic-fence-post' command.\n",
+			paddress (gdbarch, pc), paddress (gdbarch, pc));
+		blurb_printed = 1;
+	      }
+	  }
+
+	return 0;
+      }
+    else
+      {
+	ULONGEST insn;
+	int size;
+
+	/* On nanomips, SAVE is likely to be the start of a function.  */
+	insn = nanomips_fetch_instruction (gdbarch, pc, NULL);
+	size = nanomips_insn_size (insn);
+	if ((size == 2 && micromips_op (insn) == 0x7) ||
+	    (size == 4 && micromips_op (insn) == 0x20))
+	    break;
+      }
+
+  return start_pc;
+}
+
+/* On p32, argument passing in GPRs depends on the alignment of the type being
+   passed.  Return 1 if this type must be aligned to a doubleword boundary.  */
+
+static int
+type_needs_double_align (struct type *type)
+{
+  enum type_code typecode = type->code ();
+
+  if ((typecode == TYPE_CODE_FLT || typecode == TYPE_CODE_INT)
+      && TYPE_LENGTH (type) == 8)
+    return 1;
+  else if (typecode == TYPE_CODE_STRUCT)
+    {
+      if (type->num_fields () > 1)
+	return 0;
+      return type_needs_double_align (type->field (0).type ());
+    }
+  else if (typecode == TYPE_CODE_UNION)
+    {
+      int i, n;
+
+      n = type->num_fields ();
+      for (i = 0; i < n; i++)
+	if (type_needs_double_align (type->field (i).type ()))
+	  return 1;
+      return 0;
+    }
+  return 0;
+}
+
+/* Adjust the address downward (direction of stack growth) so that it
+   is correctly aligned for a new stack frame.  */
+static CORE_ADDR
+nanomips_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  return align_down (addr, 16);
+}
+
+/* Implement the "push_dummy_code" gdbarch method.  */
+
+static CORE_ADDR
+nanomips_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
+			  CORE_ADDR funaddr, struct value **args,
+			  int nargs, struct type *value_type,
+			  CORE_ADDR *real_pc, CORE_ADDR *bp_addr,
+			  struct regcache *regcache)
+{
+  /* Reserve enough room on the stack for our breakpoint instruction.  */
+  sp = sp - 4;
+  *bp_addr = sp;
+
+  /* Inferior resumes at the function entry point.  */
+  *real_pc = funaddr;
+
+  return sp;
+}
+
+/* p32, p64 ABI stuff.  */
+
+#define MAX_REG_ARGS	8	/* Maximum 8 arguments in registers */
+
+static CORE_ADDR
+nanomips_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+			  struct regcache *regcache, CORE_ADDR bp_addr,
+			  int nargs, struct value **args, CORE_ADDR sp,
+			  function_call_return_method return_method, CORE_ADDR struct_addr)
+{
+  int arg_gpr = 0, arg_fpr = 0;
+  int argnum;
+  int stack_offset = 0, stack_size = 0;
+  int seen_on_stack = 0;
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int regsize = nanomips_abi_regsize (gdbarch);
+
+  /* Set the return address register to point to the entry point of
+     the program, where a breakpoint lies in wait.  */
+  regcache_cooked_write_signed (regcache, NANOMIPS_RA_REGNUM, bp_addr);
+
+  /* First ensure that the stack and structure return address (if any)
+     are properly aligned.  The stack has to be at least 64-bit
+     aligned even on 32-bit machines, because doubles must be 64-bit
+     aligned.  */
+
+  sp = align_down (sp, 16);
+  struct_addr = align_down (struct_addr, 16);
+
+  /* Calculate space required on the stack for the args.  */
+  for (argnum = 0; argnum < nargs; argnum++)
+    {
+      struct type *arg_type = check_typedef (value_type (args[argnum]));
+
+      /* Align to double-word if necessary.  */
+      if (type_needs_double_align (arg_type))
+	stack_size = align_up (stack_size, NANOMIPS32_REGSIZE * 2);
+
+      /* Allocate space on the stack.  */
+      stack_size += align_up (TYPE_LENGTH (arg_type), NANOMIPS32_REGSIZE);
+    }
+  stack_size = align_up (stack_size, 16);
+
+  if (nanomips_debug)
+    gdb_printf (gdb_stdlog, "nanomips_push_dummy_call (stack_size=%d)\n", stack_size);
+
+  /* The struct_return pointer occupies the first parameter-passing reg.  */
+  if (return_method == return_method_struct)
+    {
+      if (nanomips_debug)
+	gdb_printf (gdb_stdlog,
+			    "  struct_return reg=%d %s\n",
+			    arg_gpr + NANOMIPS_A0_REGNUM,
+			    paddress (gdbarch, struct_addr));
+
+      regcache_cooked_write_unsigned (regcache, arg_gpr + NANOMIPS_A0_REGNUM,
+				      struct_addr);
+
+      /* occupy first argument reg */
+      arg_gpr++;
+    }
+
+  /* Now load as many as possible of the first arguments into
+     registers, and push the rest onto the stack.  Loop thru args
+     from first to last.  */
+  for (argnum = 0; argnum < nargs; argnum++)
+    {
+      const gdb_byte *val;
+      gdb_byte valbuf[NANOMIPS64_REGSIZE];
+      struct value *arg = args[argnum];
+      struct type *arg_type = check_typedef (value_type (arg));
+      int len = TYPE_LENGTH (arg_type);
+      enum type_code typecode = arg_type->code ();
+
+      if (typecode == TYPE_CODE_STRUCT && arg_type->num_fields () == 1)
+      {
+          if ((arg_type->field (0).type ())->code () == TYPE_CODE_TYPEDEF)
+            {
+              struct type *type = check_typedef (arg_type->field (0).type ());
+              typecode = type->code ();
+              len = TYPE_LENGTH (arg_type);
+            }
+          else if ((arg_type->field (0).type ())->code () == TYPE_CODE_FLT)
+            {
+              typecode = TYPE_CODE_FLT;
+            }
+      }
+
+      /* The P32 ABI passes structures larger than 8 bytes by reference. */
+      if ((typecode == TYPE_CODE_ARRAY || typecode == TYPE_CODE_STRUCT
+          || typecode == TYPE_CODE_UNION || typecode == TYPE_CODE_COMPLEX)
+          && len > regsize * 2)
+        {
+          store_unsigned_integer (valbuf, regsize, byte_order,
+                value_address (arg));
+          typecode = TYPE_CODE_PTR;
+          len = 4;
+          val = valbuf;
+
+          if (nanomips_debug)
+            gdb_printf (gdb_stdlog, " push");
+        }
+          else
+        val = value_contents (arg).data ();
+
+
+      while (len > 0)
+	{
+	  int partial_len = (len < NANOMIPS32_REGSIZE ? len : NANOMIPS32_REGSIZE);
+	  LONGEST regval;
+	  int use_stack = 0;
+
+	  /* Align the argument register for double and long long types.  */
+	  if ((arg_gpr < MAX_REG_ARGS) && (arg_gpr & 1) && (len == 8)
+        && ((typecode == TYPE_CODE_FLT
+        && FPU_TYPE(gdbarch) == NANOMIPS_FPU_SOFT)
+        || typecode == TYPE_CODE_INT))
+	    {
+	      arg_gpr++;
+	      stack_offset += 4;
+	    }
+
+    if (typecode == TYPE_CODE_STRUCT && (len <= 8 && len > 4) && arg_gpr == 7)
+      arg_gpr ++;
+
+	  /* double type occupies only one register.  */
+	  if (typecode == TYPE_CODE_FLT && len == 8)
+	    partial_len = (FPU_TYPE(gdbarch) == NANOMIPS_FPU_HARD ? 8 : 4);
+
+	  regval = extract_unsigned_integer (val, partial_len, byte_order);
+
+	  /* Check if any argument register is available.  */
+	  if (typecode == TYPE_CODE_FLT && FPU_TYPE(gdbarch) == NANOMIPS_FPU_HARD)
+	    {
+        if(arg_fpr < MAX_REG_ARGS)
+          {
+            if (nanomips_debug)
+              {
+                int r_num = arg_fpr + nanomips_fp_arg_regnum (gdbarch)
+                  + gdbarch_num_regs (gdbarch);
+                const char *r = nanomips_register_name (gdbarch, r_num);
+                gdb_printf (gdb_stdlog,
+                        "  argnum=%d,reg=%s,len=%d,val=%ld\n",
+                        argnum + 1, r, partial_len, regval);
+              }
+
+           /* Update the register with specified value.  */
+           regcache_cooked_write_unsigned (regcache,
+                    arg_fpr + nanomips_fp_arg_regnum (gdbarch),
+                    regval);
+            arg_fpr++;
+          }
+        else
+          use_stack = 1;
+	    }
+	  else
+	    {
+		    if (arg_gpr < MAX_REG_ARGS)
+          {
+            if (nanomips_debug)
+              {
+                int r_num = arg_gpr + NANOMIPS_A0_REGNUM
+                  + gdbarch_num_regs (gdbarch);
+                const char *r = nanomips_register_name (gdbarch, r_num);
+                gdb_printf (gdb_stdlog,
+                        "  argnum=%d,reg=%s,len=%d,val=%ld\n",
+                        argnum + 1, r, partial_len, regval);
+              }
+
+            /* Update the register with specified value.  */
+            regcache_cooked_write_unsigned (regcache,
+                     arg_gpr + NANOMIPS_A0_REGNUM, regval);
+            arg_gpr++;
+
+	        }
+	      else
+	        use_stack = 1;
+
+	    }
+
+	  if (use_stack)
+	    {
+	      CORE_ADDR addr;
+
+	      if (nanomips_debug)
+		{
+		  LONGEST valreg = extract_unsigned_integer (val, len,
+							     byte_order);
+		  gdb_printf (gdb_stdlog,
+				      "  argnum=%d,off=%d,len=%d,val=%ld\n",
+				      argnum + 1, stack_offset, partial_len,
+				      valreg);
+		}
+
+	      addr = (sp - stack_size) + stack_offset;
+	      write_memory (addr, val, partial_len);
+
+	      seen_on_stack = 1;
+	      stack_offset += (partial_len <= NANOMIPS32_REGSIZE)
+                            ? NANOMIPS32_REGSIZE : partial_len;
+	      use_stack = 0;
+	    } /* argument on stack */
+
+	  val += partial_len;
+	  len -= partial_len;
+	}
+    }
+
+  if (seen_on_stack)
+    sp -= stack_size;
+
+  regcache_cooked_write_signed (regcache, NANOMIPS_SP_REGNUM, sp);
+
+  /* Return adjusted stack pointer.  */
+  return sp;
+}
+
+static enum return_value_convention
+nanomips_return_value (struct gdbarch *gdbarch, struct value *function,
+           struct type *type, struct regcache *regcache,
+           gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+  if ((type->code () == TYPE_CODE_ARRAY
+      || type->code () == TYPE_CODE_STRUCT
+      || type->code () == TYPE_CODE_COMPLEX)
+      && TYPE_LENGTH (type) > 2 * NANOMIPS32_REGSIZE)
+    return RETURN_VALUE_STRUCT_CONVENTION;
+
+  else if (type->code () == TYPE_CODE_COMPLEX
+     && FPU_TYPE(gdbarch) == NANOMIPS_FPU_HARD)
+    {
+      gdb_assert (nanomips_regnum (gdbarch)->fpr != -1);
+
+      nanomips_xfer_register (gdbarch, regcache,
+			      (gdbarch_num_regs (gdbarch)
+			       + nanomips_regnum (gdbarch)->fpr
+			       + NANOMIPS_FP0_REGNUM),
+			      4, gdbarch_byte_order (gdbarch),
+			      readbuf, writebuf, 0);
+      nanomips_xfer_register (gdbarch, regcache,
+			      (gdbarch_num_regs (gdbarch)
+			       + nanomips_regnum (gdbarch)->fpr
+			       + NANOMIPS_FP0_REGNUM + 1),
+			      4, gdbarch_byte_order (gdbarch),
+			      readbuf, writebuf, 4);
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  else if (type->code () == TYPE_CODE_FLT
+     && FPU_TYPE(gdbarch) == NANOMIPS_FPU_HARD)
+    {
+      gdb_assert (nanomips_regnum (gdbarch)->fpr != -1);
+
+      nanomips_xfer_register (gdbarch, regcache,
+			      (gdbarch_num_regs (gdbarch)
+			       + nanomips_regnum (gdbarch)->fpr
+			       + NANOMIPS_FP0_REGNUM),
+			      TYPE_LENGTH (type), gdbarch_byte_order (gdbarch),
+			      readbuf, writebuf, 0);
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  else
+    {
+      int offset;
+      int regnum;
+      for (offset = 0, regnum = NANOMIPS_A0_REGNUM;
+     offset < TYPE_LENGTH (type);
+     offset += NANOMIPS32_REGSIZE, regnum++)
+  {
+    int xfer = NANOMIPS32_REGSIZE;
+    if (offset + xfer > TYPE_LENGTH (type))
+      xfer = TYPE_LENGTH (type) - offset;
+    if (nanomips_debug)
+      gdb_printf (gdb_stderr, "Return scalar+%d:%d in $%d\n",
+        offset, xfer, regnum);
+    nanomips_xfer_register (gdbarch, regcache,
+            gdbarch_num_regs (gdbarch) + regnum, xfer,
+            gdbarch_byte_order (gdbarch),
+            readbuf, writebuf, offset);
+  }
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+}
+
+/* Copy a 32-bit single-precision value from the current frame
+   into rare_buffer.  */
+
+static void
+read_fp_register_single (struct frame_info *frame, int regno,
+			 gdb_byte *rare_buffer)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  int raw_size = register_size (gdbarch, regno);
+  int offset;
+  gdb_byte *raw_buffer = (gdb_byte *) alloca (raw_size);
+
+  if (!deprecated_frame_register_read (frame, regno, raw_buffer))
+    error (_("can't read register %d (%s)"),
+	   regno, gdbarch_register_name (gdbarch, regno));
+
+  /* We have a 64-bit value for this register.  Find the low-order 32 bits.  */
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+    offset = 4;
+  else
+    offset = 0;
+
+  memcpy (rare_buffer, raw_buffer + offset, 4);
+}
+
+/* Copy a 64-bit double-precision value from the current frame into
+   rare_buffer.  */
+
+static void
+read_fp_register_double (struct frame_info *frame, int regno,
+			 gdb_byte *rare_buffer)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  /* We have a 64-bit value for this register, use all 64 bits.  */
+  if (!deprecated_frame_register_read (frame, regno, rare_buffer))
+      error (_("can't read register %d (%s)"),
+	     regno, gdbarch_register_name (gdbarch, regno));
+}
+
+static void
+print_fp_register (struct ui_file *file, struct frame_info *frame,
+		   int regnum)
+{		/* Do values for FP (float) regs.  */
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  gdb_byte *raw_buffer;
+  std::string flt_str, dbl_str;
+  struct value_print_options opts;
+
+  const struct type *flt_type = builtin_type (gdbarch)->builtin_float;
+  const struct type *dbl_type = builtin_type (gdbarch)->builtin_double;
+
+  gdb_assert (nanomips_regnum (gdbarch)->fpr != -1);
+
+  raw_buffer
+    = ((gdb_byte *)
+       alloca (2 * register_size (gdbarch,
+				  (nanomips_regnum (gdbarch)->fpr
+				   + NANOMIPS_FP0_REGNUM))));
+
+  gdb_printf (file, "%s:", gdbarch_register_name (gdbarch, regnum));
+  gdb_printf (file, "%*s",
+		    4 - (int) strlen (gdbarch_register_name (gdbarch, regnum)),
+		    "");
+
+  /* Eight byte registers: print each one as hex, float and double.  */
+  read_fp_register_single (frame, regnum, raw_buffer);
+  flt_str = target_float_to_string (raw_buffer, flt_type, "%-17.9g");
+
+  read_fp_register_double (frame, regnum, raw_buffer);
+  dbl_str = target_float_to_string (raw_buffer, dbl_type, "%-24.17g");
+
+  get_formatted_print_options (&opts, 'x');
+  print_scalar_formatted (raw_buffer,
+			  builtin_type (gdbarch)->builtin_uint64,
+			  &opts, 'g', file);
+
+  gdb_printf (file, " flt: %s", flt_str.c_str ());
+
+  gdb_printf (file, " dbl: %s", dbl_str.c_str ());
+}
+
+static void
+nanomips_print_register (struct ui_file *file, struct frame_info *frame,
+			 int regnum)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct value_print_options opts;
+  struct value *val;
+
+  if (nanomips_float_register_p (gdbarch, regnum))
+    {
+      print_fp_register (file, frame, regnum);
+      return;
+    }
+
+  val = get_frame_register_value (frame, regnum);
+
+  gdb_puts (gdbarch_register_name (gdbarch, regnum), file);
+
+  /* The problem with printing numeric register names (r26, etc.) is that
+     the user can't use them on input.  Probably the best solution is to
+     fix it so that either the numeric or the funky (a2, etc.) names
+     are accepted on input.  */
+  if (regnum < NUMREGS)
+    gdb_printf (file, "(r%d): ", regnum);
+  else
+    gdb_printf (file, ": ");
+
+  get_formatted_print_options (&opts, 'x');
+  value_print_scalar_formatted (val, &opts, 0, file);
+}
+
+/* Print IEEE exception condition bits in FLAGS.  */
+
+static void
+print_fpu_flags (struct ui_file *file, int flags)
+{
+  if (flags & (1 << 0))
+    gdb_puts (" inexact", file);
+  if (flags & (1 << 1))
+    gdb_puts (" uflow", file);
+  if (flags & (1 << 2))
+    gdb_puts (" oflow", file);
+  if (flags & (1 << 3))
+    gdb_puts (" div0", file);
+  if (flags & (1 << 4))
+    gdb_puts (" inval", file);
+  if (flags & (1 << 5))
+    gdb_puts (" unimp", file);
+  gdb_putc ('\n', file);
+}
+
+/* Print interesting information about the floating point processor
+   (if present) or emulator.  */
+
+static void
+nanomips_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
+			   struct frame_info *frame, const char *args)
+{
+  int fcsr = nanomips_regnum (gdbarch)->fpr + NANOMIPS_FCSR_REGNUM;
+  enum fpu_type type = FPU_TYPE (gdbarch);
+  ULONGEST fcs = 0;
+  int i;
+
+  if (nanomips_regnum (gdbarch)->fpr == -1
+      || !read_frame_register_unsigned (frame, fcsr, &fcs))
+    type = NANOMIPS_FPU_NONE;
+
+  gdb_printf (file, "fpu type: %s\n",
+		    type == NANOMIPS_FPU_HARD ? "64bit hardware floating point"
+		    : type == NANOMIPS_FPU_SOFT ? "Software floating point"
+		    : "none / unused");
+
+  if (type == NANOMIPS_FPU_NONE)
+    return;
+
+  gdb_printf (file, "reg size: %d bits\n",
+		    register_size (gdbarch,
+				   (nanomips_regnum (gdbarch)->fpr
+				    + NANOMIPS_FP0_REGNUM)) * 8);
+
+  gdb_puts ("cond    :", file);
+  if (fcs & (1 << 23))
+    gdb_puts (" 0", file);
+  for (i = 1; i <= 7; i++)
+    if (fcs & (1 << (24 + i)))
+      gdb_printf (file, " %d", i);
+  gdb_putc ('\n', file);
+
+  gdb_puts ("cause   :", file);
+  print_fpu_flags (file, (fcs >> 12) & 0x3f);
+  fputs ("mask    :", stdout);
+  print_fpu_flags (file, (fcs >> 7) & 0x1f);
+  fputs ("flags   :", stdout);
+  print_fpu_flags (file, (fcs >> 2) & 0x1f);
+
+  gdb_puts ("rounding: ", file);
+  switch (fcs & 3)
+    {
+    case 0: gdb_puts ("nearest\n", file); break;
+    case 1: gdb_puts ("zero\n", file); break;
+    case 2: gdb_puts ("+inf\n", file); break;
+    case 3: gdb_puts ("-inf\n", file); break;
+    }
+
+  gdb_puts ("flush   :", file);
+  if (fcs & (1 << 21))
+    gdb_puts (" nearest", file);
+  if (fcs & (1 << 22))
+    gdb_puts (" override", file);
+  if (fcs & (1 << 24))
+    gdb_puts (" zero", file);
+  if ((fcs & (0xb << 21)) == 0)
+    gdb_puts (" no", file);
+  gdb_putc ('\n', file);
+
+  gdb_printf (file, "nan2008 : %s\n", fcs & (1 << 18) ? "yes" : "no");
+  gdb_printf (file, "abs2008 : %s\n", fcs & (1 << 19) ? "yes" : "no");
+  gdb_putc ('\n', file);
+
+  default_print_float_info (gdbarch, file, frame, args);
+}
+
+/* Replacement for generic do_registers_info.
+   Print regs in pretty columns.  */
+
+static int
+print_fp_register_row (struct ui_file *file, struct frame_info *frame,
+		       int regnum)
+{
+  gdb_printf (file, " ");
+  print_fp_register (file, frame, regnum);
+  gdb_printf (file, "\n");
+  return regnum + 1;
+}
+
+
+/* Print a row's worth of GP (int) registers, with name labels above.  */
+
+static int
+print_gp_register_row (struct ui_file *file, struct frame_info *frame,
+		       int start_regnum)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  /* Do values for GP (int) regs.  */
+  gdb_byte raw_buffer[NANOMIPS64_REGSIZE];
+  int ncols = (nanomips_abi_regsize (gdbarch) == 8 ? 4 : 8);    /* display cols
+							       per row.  */
+  int col, byte;
+  int regnum;
+
+  /* For GP registers, we print a separate row of names above the vals.  */
+  for (col = 0, regnum = start_regnum;
+       col < ncols && regnum < gdbarch_num_regs (gdbarch)
+			       + gdbarch_num_pseudo_regs (gdbarch);
+       regnum++)
+    {
+      if (*gdbarch_register_name (gdbarch, regnum) == '\0')
+	continue;		/* unused register */
+      if (nanomips_float_register_p (gdbarch, regnum))
+	break;			/* End the row: reached FP register.  */
+      /* Large registers are handled separately.  */
+      if (register_size (gdbarch, regnum) > nanomips_abi_regsize (gdbarch))
+	{
+	  if (col > 0)
+	    break;		/* End the row before this register.  */
+
+	  /* Print this register on a row by itself.  */
+	  nanomips_print_register (file, frame, regnum);
+	  gdb_printf (file, "\n");
+	  return regnum + 1;
+	}
+      if (col == 0)
+	gdb_printf (file, "     ");
+      gdb_printf (file,
+			nanomips_abi_regsize (gdbarch) == 8 ? "%17s" : "%9s",
+			gdbarch_register_name (gdbarch, regnum));
+      col++;
+    }
+
+  if (col == 0)
+    return regnum;
+
+  /* Print the R0 to R31 names.  */
+  if ((start_regnum % gdbarch_num_regs (gdbarch)) < NUMREGS)
+    gdb_printf (file, "\n R%-4d",
+		      start_regnum % gdbarch_num_regs (gdbarch));
+  else
+    gdb_printf (file, "\n      ");
+
+  /* Now print the values in hex, 4 or 8 to the row.  */
+  for (col = 0, regnum = start_regnum;
+       col < ncols && regnum < gdbarch_num_regs (gdbarch)
+			       + gdbarch_num_pseudo_regs (gdbarch);
+       regnum++)
+    {
+      if (*gdbarch_register_name (gdbarch, regnum) == '\0')
+	continue;		/* unused register */
+      if (nanomips_float_register_p (gdbarch, regnum))
+	break;			/* End row: reached FP register.  */
+      if (register_size (gdbarch, regnum) > nanomips_abi_regsize (gdbarch))
+	break;			/* End row: large register.  */
+
+      /* OK: get the data in raw format.  */
+      if (!deprecated_frame_register_read (frame, regnum, raw_buffer))
+	error (_("can't read register %d (%s)"),
+	       regnum, gdbarch_register_name (gdbarch, regnum));
+      /* pad small registers */
+      for (byte = 0;
+	   byte < (nanomips_abi_regsize (gdbarch)
+		   - register_size (gdbarch, regnum)); byte++)
+	gdb_printf ("  ");
+      /* Now print the register value in hex, endian order.  */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+	for (byte =
+	     register_size (gdbarch, regnum) - register_size (gdbarch, regnum);
+	     byte < register_size (gdbarch, regnum); byte++)
+	  gdb_printf (file, "%02x", raw_buffer[byte]);
+      else
+	for (byte = register_size (gdbarch, regnum) - 1;
+	     byte >= 0; byte--)
+	  gdb_printf (file, "%02x", raw_buffer[byte]);
+      gdb_printf (file, " ");
+      col++;
+    }
+  if (col > 0)			/* ie. if we actually printed anything...  */
+    gdb_printf (file, "\n");
+
+  return regnum;
+}
+
+/* MIPS_DO_REGISTERS_INFO(): called by "info register" command.  */
+
+static void
+nanomips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
+			       struct frame_info *frame, int regnum, int all)
+{
+  if (regnum != -1)		/* Do one specified register.  */
+    {
+      gdb_assert (regnum >= gdbarch_num_regs (gdbarch));
+      if (*(gdbarch_register_name (gdbarch, regnum)) == '\0')
+	error (_("Not a valid register for the current processor type"));
+
+      nanomips_print_register (file, frame, regnum);
+      gdb_printf (file, "\n");
+    }
+  else
+    /* Do all (or most) registers.  */
+    {
+      regnum = gdbarch_num_regs (gdbarch);
+      while (regnum < gdbarch_num_regs (gdbarch)
+		      + gdbarch_num_pseudo_regs (gdbarch))
+	{
+	  if (nanomips_float_register_p (gdbarch, regnum))
+	    {
+	      if (all)		/* True for "INFO ALL-REGISTERS" command.  */
+		regnum = print_fp_register_row (file, frame, regnum);
+	      else
+		regnum += NUMREGS;	/* Skip floating point regs.  */
+	    }
+	  else
+	    regnum = print_gp_register_row (file, frame, regnum);
+	}
+    }
+}
+
+/* To skip prologues, I use this predicate.  Returns either PC itself
+   if the code at PC does not look like a function prologue; otherwise
+   returns an address that (if we're lucky) follows the prologue.  If
+   LENIENT, then we must skip everything which is involved in setting
+   up the frame (it's OK to skip more, just so long as we don't skip
+   anything which might clobber the registers which are being saved.
+   We must skip more in the case where part of the prologue is in the
+   delay slot of a non-prologue instruction).  */
+
+static CORE_ADDR
+nanomips_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  CORE_ADDR limit_pc;
+  CORE_ADDR func_addr;
+
+  /* See if we can determine the end of the prologue via the symbol table.
+     If so, then return either PC, or the PC after the prologue, whichever
+     is greater.  */
+  if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
+    {
+      CORE_ADDR post_prologue_pc
+	= skip_prologue_using_sal (gdbarch, func_addr);
+      if (post_prologue_pc != 0)
+	return std::max (pc, post_prologue_pc);
+    }
+
+  /* Can't determine prologue from the symbol table, need to examine
+     instructions.  */
+
+  /* Find an upper limit on the function prologue using the debug
+     information.  If the debug information could not be used to provide
+     that bound, then use an arbitrary large number as the upper bound.  */
+  limit_pc = skip_prologue_using_sal (gdbarch, pc);
+  if (limit_pc == 0)
+    limit_pc = pc + 100;          /* Magic.  */
+
+  return nanomips_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL);
+}
+
+/* Implement the stack_frame_destroyed_p gdbarch method (nanoMIPS version).
+   This is a helper function for mips_stack_frame_destroyed_p.  */
+
+static int
+nanomips_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  CORE_ADDR func_addr = 0;
+  CORE_ADDR func_end = 0;
+  CORE_ADDR addr;
+  ULONGEST insn;
+  int dreg;
+  int sreg;
+  int treg, op;
+  int loc;
+
+  if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+    return 0;
+
+  /* The nanoMIPS epilogue is max. 12 bytes long.  */
+  addr = func_end - 12;
+
+  if (addr < func_addr + 2)
+    addr = func_addr + 2;
+  if (pc < addr)
+    return 0;
+
+  for (; pc < func_end; pc += loc)
+    {
+      loc = 0;
+      insn = nanomips_fetch_instruction (gdbarch, pc, NULL);
+      loc += INSN16_SIZE;
+      switch (nanomips_insn_size (insn))
+	{
+	/* 48-bit instructions.  */
+	case 3 * INSN16_SIZE:
+	  if (micromips_op (insn) == 0x18)
+	    {
+	      op = b0s5_imm (insn);
+	      treg = b5s5_reg (insn);
+	      if (op == 0x0) /* LI48 xx, imm32 */
+		break; /* continue scan */
+	      else if (op == 0x1 /* ADDIU48 $sp, imm32 */
+		       && treg == NANOMIPS_SP_REGNUM)
+		return 1;
+	    }
+	  return 0;
+
+	/* 32-bit instructions.  */
+	case 2 * INSN16_SIZE:
+	  insn <<= 16;
+	  insn |= nanomips_fetch_instruction (gdbarch, pc + loc, NULL);
+	  loc += INSN16_SIZE;
+
+	  switch (micromips_op (insn >> 16))
+	    {
+	    case 0x0: /* PP.ADDIU bits 000000 */
+	      treg = b5s5_reg (insn >> 16);
+	      sreg = b0s5_reg (insn >> 16);
+	      if (sreg == treg
+		  && treg == NANOMIPS_SP_REGNUM) /* ADDIU $sp, $sp, imm */
+		return 1;
+	      else if (sreg == NANOMIPS_SP_REGNUM && treg == 30)
+		break; /* continue scan */
+	      return 0;
+
+	    case 0x8: /* _POOL32A0 */
+	      if ((insn & 0x1ff) == 0x150) /* ADDU */
+		{
+		  dreg = b11s5_reg (insn);
+		  sreg = b0s5_reg (insn >> 16);
+		  if ((dreg == sreg && sreg == NANOMIPS_SP_REGNUM)
+		      /* ADDU $sp, $sp, xx */
+		      || (dreg == NANOMIPS_SP_REGNUM && sreg == 30))
+		      /* ADDU $sp, $fp, xx */
+		    break; /* continue scan */
+		}
+	      else if (((insn & 0xffff) == 0xE37F) /* DERET */
+		       || ((insn & 0x1ffff) == 0xF37F) /* ERET */
+		       || ((insn & 0x1ffff) == 0x1F37F)) /* ERETNC */
+		return 1;
+	      return 0;
+
+	    case 0x20: /* P.U12 bits 100000 */
+	      if (b12s4_op (insn) == 0) /* ORI: bits 100000 0000 */
+		{
+		  sreg = b0s5_reg (insn >> 16);
+		  treg = b5s5_reg (insn >> 16);
+		  if (sreg == treg && treg == 3) /* ORI $v1, $v1, imm */
+		    break; /* continue scan */
+		}
+	      else if (b12s5_op (insn) == 0x13) /* RESTORE, RESTORE.JRC */
+		return 1;
+	      return 0;
+
+	    case 0x38: /* P.LUI bits 111000 */
+	      treg = b5s5_reg (insn >> 16);
+	      if ((insn & 2) == 0 /* LU20I bits 111000 0 */
+		  && treg == 3) /* LU20I $v1, imm */
+		break; /* continue scan */
+	      return 0;
+
+	    default:
+	      return 0;
+	    }
+	  break;
+
+	/* 16-bit instructions.  */
+	case INSN16_SIZE:
+	  switch (micromips_op (insn))
+	    {
+	    case 0x4: /* MOVE: bits 000100 */
+	      sreg = b0s5_reg (insn);
+	      dreg = b5s5_reg (insn);
+	      if (sreg == NANOMIPS_SP_REGNUM && dreg == 30)
+			/* MOVE  $fp, $sp */
+		return 1;
+	      return 0;
+
+	    case 0x7: /* RESTORE[16], RESTORE.JRC[16] */
+	      if ((insn & 0x20) == 0x20)
+		return 1;
+	      return 0;
+
+	    case 0x36: /* JRC[16] $31 */
+	      if ((insn & 0x1f) == 0 && b5s5_reg (insn) == 31)
+		return 1;
+	      return 0;
+
+	    default:
+		return 0;
+	    }
+	  break;
+	}
+    }
+
+  return 1;
+}
+
+/* Root of all "set nanomips "/"show nanomips " commands.  This will eventually be
+   used for all nanoMIPS-specific commands.  */
+
+static void
+show_nanomips_command (const char *args, int from_tty)
+{
+  help_list (shownanomipscmdlist, "show nanomips ", all_commands, gdb_stdout);
+}
+
+static void
+set_nanomips_command (const char *args, int from_tty)
+{
+  printf_unfiltered
+    ("\"set nanomips\" must be followed by an appropriate subcommand.\n");
+  help_list (setnanomipscmdlist, "set nanomips ", all_commands, gdb_stdout);
+}
+
+/* Just like reinit_frame_cache, but with the right arguments to be
+   callable as an sfunc.  */
+
+static void
+reinit_frame_cache_sfunc (const char *args, int from_tty,
+			  struct cmd_list_element *c)
+{
+  reinit_frame_cache ();
+}
+
+static int
+gdb_print_insn_nanomips_p32 (bfd_vma memaddr, struct disassemble_info *info)
+{
+  info->mach = bfd_mach_nanomipsisa32r6;
+  info->flavour = bfd_target_elf_flavour;
+  info->disassembler_options = "gpr-names=p32";
+
+  return print_insn_nanomips (memaddr, info);
+}
+
+static int
+gdb_print_insn_nanomips_p64 (bfd_vma memaddr, struct disassemble_info *info)
+{
+  info->mach = bfd_mach_nanomipsisa64r6;
+  info->flavour = bfd_target_elf_flavour;
+  info->disassembler_options = "gpr-names=p64";
+
+  return print_insn_nanomips (memaddr, info);
+}
+
+/* Implement the breakpoint_kind_from_pc gdbarch method.  */
+
+static int
+nanomips_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+  CORE_ADDR pc = *pcptr;
+  ULONGEST insn;
+  int status;
+
+  insn = nanomips_fetch_instruction (gdbarch, pc, &status);
+  if (status || (nanomips_insn_size (insn) == 2))
+    return NANOMIPS_BP_KIND_16;
+  else
+    return NANOMIPS_BP_KIND_32;
+}
+
+/* Implement the sw_breakpoint_from_kind gdbarch method.  */
+
+static const gdb_byte *
+nanomips_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+
+  switch (kind)
+    {
+    case NANOMIPS_BP_KIND_16:
+      {
+	static gdb_byte be16_break[] = { 0x10, 0x10 };
+	static gdb_byte le16_break[] = { 0x10, 0x10 };
+
+	*size = 2;
+
+	if (byte_order_for_code == BFD_ENDIAN_BIG)
+	  return be16_break;
+	else
+	  return le16_break;
+      }
+    case NANOMIPS_BP_KIND_32:
+      {
+	static gdb_byte be32_break[] = { 0, 0x10, 0, 0 };
+	static gdb_byte le32_break[] = { 0x10, 0, 0, 0 };
+
+	*size = 4;
+	if (byte_order_for_code == BFD_ENDIAN_BIG)
+	  return be32_break;
+	else
+	  return le32_break;
+      }
+    default:
+      gdb_assert_not_reached ("unexpected nanomips breakpoint kind");
+    };
+}
+
+/* Convert a dbx stab register number (from `r' declaration) to a GDB
+   [1 * gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM.  */
+
+static int
+nanomips_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
+{
+  int regnum;
+  if (num >= 0 && num < 32)
+    regnum = num;
+  else if (nanomips_regnum (gdbarch)->fpr != -1 && num >= 36 && num < 70)
+    regnum = num + nanomips_regnum (gdbarch)->fpr + NANOMIPS_FP0_REGNUM - 36;
+  else if (nanomips_regnum (gdbarch)->dsp != -1 && num >= 70 && num < 78)
+    regnum
+      = num + nanomips_regnum (gdbarch)->dsp + NANOMIPS_DSPHI0_REGNUM - 70;
+  else
+    return -1;
+  return gdbarch_num_regs (gdbarch) + regnum;
+}
+
+
+/* Convert a dwarf, dwarf2, or ecoff register number to a GDB [1 *
+   gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM.  */
+
+static int
+nanomips_dwarf_dwarf2_ecoff_reg_to_regnum (struct gdbarch *gdbarch, int num)
+{
+  int regnum;
+  if (num >= 0 && num < 32)
+    regnum = num;
+  else if (nanomips_regnum (gdbarch)->fpr != -1 && num >= 32 && num < 64)
+    regnum = num + nanomips_regnum (gdbarch)->fpr + NANOMIPS_FP0_REGNUM - 32;
+  else if (nanomips_regnum (gdbarch)->dsp != -1 && num >= 64 && num < 72)
+    regnum
+      = num + nanomips_regnum (gdbarch)->dsp + NANOMIPS_DSPHI0_REGNUM - 64;
+  else
+    return -1;
+  return gdbarch_num_regs (gdbarch) + regnum;
+}
+
+static int
+nanomips_register_sim_regno (struct gdbarch *gdbarch, int regnum)
+{
+  /* Only makes sense to supply raw registers.  */
+  gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch));
+  /* FIXME: cagney/2002-05-13: Need to look at the pseudo register to
+     decide if it is valid.  Should instead define a standard sim/gdb
+     register numbering scheme.  */
+  if (gdbarch_register_name (gdbarch,
+			     gdbarch_num_regs (gdbarch) + regnum) != NULL
+      && gdbarch_register_name (gdbarch,
+			        gdbarch_num_regs (gdbarch)
+				+ regnum)[0] != '\0')
+    return regnum;
+  else
+    return LEGACY_SIM_REGNO_IGNORE;
+}
+
+
+/* Convert an integer into an address.  Extracting the value signed
+   guarantees a correctly sign extended address.  */
+
+static CORE_ADDR
+nanomips_integer_to_address (struct gdbarch *gdbarch,
+			     struct type *type, const gdb_byte *buf)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  return extract_signed_integer (buf, TYPE_LENGTH (type), byte_order);
+}
+
+/* Dummy virtual frame pointer method.  This is no more or less accurate
+   than most other architectures; we just need to be explicit about it,
+   because the pseudo-register gdbarch_sp_regnum will otherwise lead to
+   an assertion failure.  */
+
+static void
+nanomips_virtual_frame_pointer (struct gdbarch *gdbarch,
+				CORE_ADDR pc, int *reg, LONGEST *offset)
+{
+  *reg = NANOMIPS_SP_REGNUM;
+  *offset = 0;
+}
+
+static struct gdbarch *
+nanomips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+  static const char *const mips_gprs[] = {
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+    "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+    "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
+  };
+  static const char *const mips_fprs[] = {
+    "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+    "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+    "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+    "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
+  };
+  static const char *const mips_dsprs[] = {
+    "hi0", "lo0", "hi1", "lo1", "hi2", "lo2", "hi3", "lo3"
+  };
+  const struct tdesc_feature *feature;
+  struct gdbarch *gdbarch;
+  struct nanomips_gdbarch_tdep *tdep;
+  int elf_flags;
+  enum nanomips_abi nanomips_abi, found_abi;
+  int i, num_regs;
+  enum fpu_type fpu_type;
+  tdesc_arch_data_up tdesc_data;
+  const struct target_desc *tdesc = info.target_desc;
+  int elf_fpu_type = Val_GNU_NANOMIPS_ABI_FP_ANY;
+  struct nanomips_regnum nanomips_regnum, *regnum;
+  int register_size;
+  int valid_p;
+
+  num_regs = 0;
+
+  nanomips_regnum.cause = -1;
+  nanomips_regnum.status = -1;
+  nanomips_regnum.badvaddr = -1;
+  nanomips_regnum.fpr = -1;
+  nanomips_regnum.dsp = -1;
+  nanomips_regnum.restart = -1;
+
+  /* If there's no target description, then use the default.  */
+  if (!tdesc_has_registers (tdesc))
+    tdesc = tdesc_nanomips;
+
+  /* The CPU feature and the registers within are mandatory.  */
+  feature = tdesc_find_feature (tdesc, "org.gnu.gdb.nanomips.cpu");
+  if (feature == NULL)
+    return NULL;
+
+  tdesc_data = tdesc_data_alloc ();
+
+  valid_p = 1;
+  for (i = 0; i < 32; i++, num_regs++)
+    valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), num_regs,
+					mips_gprs[i]);
+  valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), num_regs++, "pc");
+  if (!valid_p)
+      return NULL;
+  register_size = tdesc_register_bitsize (feature, "r0") / 8;
+
+  /* All the remaining target description features are optional.  */
+
+  /* Check for and assign a number to the syscall restart PC register.  */
+  feature = tdesc_find_feature (tdesc, "org.gnu.gdb.nanomips.linux");
+  if (feature != NULL)
+    {
+      if (tdesc_numbered_register (feature, tdesc_data.get (), num_regs, "restart"))
+	nanomips_regnum.restart = num_regs++;
+
+      /* Check for and assign numbers to particular CP0 registers.
+	 These are only special and need known numbers with Linux
+	 targets, due to the use in signal frames, etc.  Bare metal
+	 stubs can simply include them along with other CP0 registers.  */
+      feature = tdesc_find_feature (tdesc, "org.gnu.gdb.nanomips.cp0");
+      if (feature != NULL)
+	{
+	  if (tdesc_numbered_register (feature, tdesc_data.get (), num_regs,
+				       "badvaddr"))
+	    nanomips_regnum.badvaddr = num_regs++;
+	  if (tdesc_numbered_register (feature, tdesc_data.get (), num_regs,
+				       "status"))
+	    nanomips_regnum.status = num_regs++;
+	  if (tdesc_numbered_register (feature, tdesc_data.get (), num_regs,
+				       "cause"))
+	    nanomips_regnum.cause = num_regs++;
+	}
+    }
+
+  /* Check for and assign numbers to FPU registers.  */
+  feature = tdesc_find_feature (tdesc, "org.gnu.gdb.nanomips.fpu");
+  if (feature != NULL)
+    {
+      nanomips_regnum.fpr = num_regs;
+      for (i = 0; i < 32; i++, num_regs++)
+	valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), num_regs,
+					    mips_fprs[i]);
+      valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), num_regs++,
+					  "fcsr");
+      valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), num_regs++,
+					  "fir");
+      if (!valid_p)
+      return NULL;
+    }
+
+  /* Check for and assign numbers to DSP registers.  */
+  feature = tdesc_find_feature (tdesc, "org.gnu.gdb.nanomips.dsp");
+  if (feature != NULL)
+    {
+      nanomips_regnum.dsp = num_regs;
+      for (i = 0; i < 8; i++, num_regs++)
+	valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), num_regs,
+					    mips_dsprs[i]);
+      valid_p &= tdesc_numbered_register (feature, tdesc_data.get (), num_regs++,
+					  "dspctl");
+      if (!valid_p)
+        return NULL;
+    }
+
+  /* First of all, extract the elf_flags, if available.  */
+  if (info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
+    elf_flags = elf_elfheader (info.abfd)->e_flags;
+  else if (arches != NULL)
+    elf_flags = ((struct nanomips_gdbarch_tdep*) gdbarch_tdep (arches->gdbarch))->elf_flags;
+  else
+    elf_flags = 0;
+
+  if (gdbarch_debug)
+    gdb_printf (gdb_stdlog,
+			"nanomips_gdbarch_init: elf_flags = 0x%08x\n",
+			elf_flags);
+
+  /* Check ELF_FLAGS to see if it specifies the ABI being used.  */
+  switch ((elf_flags & EF_NANOMIPS_ABI))
+    {
+    case E_NANOMIPS_ABI_P32:
+      found_abi = NANOMIPS_ABI_P32;
+      break;
+    case E_NANOMIPS_ABI_P64:
+      found_abi = NANOMIPS_ABI_P64;
+      break;
+    default:
+      found_abi = NANOMIPS_ABI_UNKNOWN;
+      break;
+    }
+
+  /* If we have no useful BFD information, use the ABI from the last
+     nanoMIPS architecture (if there is one).  */
+  if (found_abi == NANOMIPS_ABI_UNKNOWN && info.abfd == NULL && arches != NULL)
+    found_abi = ((struct nanomips_gdbarch_tdep*) gdbarch_tdep (arches->gdbarch))->found_abi;
+
+  /* Try the architecture for any hint of the correct ABI.  */
+  if (found_abi == NANOMIPS_ABI_UNKNOWN
+      && info.bfd_arch_info != NULL
+      && info.bfd_arch_info->arch == bfd_arch_nanomips)
+    {
+      switch (info.bfd_arch_info->mach)
+	{
+	case bfd_mach_nanomipsisa32r6:
+	  found_abi = NANOMIPS_ABI_P32;
+	  break;
+	case bfd_mach_nanomipsisa64r6:
+	  found_abi = NANOMIPS_ABI_P64;
+	  break;
+	}
+    }
+
+  /* Default 64-bit objects to P64 instead of P32.  */
+  if (found_abi == NANOMIPS_ABI_UNKNOWN
+      && info.abfd != NULL
+      && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour
+      && elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64)
+    found_abi = NANOMIPS_ABI_P64;
+
+  if (gdbarch_debug)
+    gdb_printf (gdb_stdlog, "nanomips_gdbarch_init: found_abi = %d\n",
+			found_abi);
+
+  /* Now that we have found what the ABI for this binary would be,
+     check whether the user is overriding it.  */
+  if (found_abi != NANOMIPS_ABI_UNKNOWN)
+    nanomips_abi = found_abi;
+  else
+    nanomips_abi = NANOMIPS_ABI_P32;
+  if (gdbarch_debug)
+    gdb_printf (gdb_stdlog,
+			"nanomips_gdbarch_init: nanomips_abi = %d\n",
+			nanomips_abi);
+
+  /* Determine the nanoMIPS FPU type.  */
+  if (info.abfd
+      && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
+    {
+      Elf_Internal_ABIFlags_v0 *abiflags;
+      abiflags = bfd_nanomips_elf_get_abiflags (info.abfd);
+      if (abiflags != NULL)
+	elf_fpu_type = abiflags->fp_abi;
+    }
+
+  if (elf_fpu_type != Val_GNU_NANOMIPS_ABI_FP_ANY)
+    {
+      switch (elf_fpu_type)
+	{
+	case Val_GNU_NANOMIPS_ABI_FP_SOFT:
+	  fpu_type = NANOMIPS_FPU_SOFT;
+	  break;
+	default:
+	  fpu_type = NANOMIPS_FPU_HARD;
+	  break;
+	}
+    }
+  else if (arches != NULL)
+    fpu_type = ((struct nanomips_gdbarch_tdep*) gdbarch_tdep (arches->gdbarch))->fpu_type;
+  else
+    fpu_type = NANOMIPS_FPU_HARD;
+
+  if (gdbarch_debug)
+    gdb_printf (gdb_stdlog,
+			"nanomips_gdbarch_init: fpu_type = %d\n", fpu_type);
+
+  /* Check for blatant incompatibilities.  */
+
+  /* If we have only 32-bit registers, then we can't debug a 64-bit ABI.  */
+  if (register_size == 4 && nanomips_abi != NANOMIPS_ABI_P32)
+    {
+      return NULL;
+    }
+
+  /* Try to find a pre-existing architecture.  */
+  for (arches = gdbarch_list_lookup_by_info (arches, &info);
+       arches != NULL;
+       arches = gdbarch_list_lookup_by_info (arches->next, &info))
+    {
+      /* nanoMIPS needs to be pedantic about which ABI and the compressed
+         ISA variation the object is using.  */
+      if (((struct nanomips_gdbarch_tdep*) gdbarch_tdep (arches->gdbarch))->elf_flags != elf_flags)
+	continue;
+      if (((struct nanomips_gdbarch_tdep*) gdbarch_tdep (arches->gdbarch))->nanomips_abi != nanomips_abi)
+	continue;
+      /* Be pedantic about which FPU is selected.  */
+      if (((struct nanomips_gdbarch_tdep*) gdbarch_tdep (arches->gdbarch))->fpu_type != fpu_type)
+	continue;
+
+      return arches->gdbarch;
+    }
+
+  /* Need a new architecture.  Fill in a target specific vector.  */
+  tdep = XNEW (struct nanomips_gdbarch_tdep);
+  gdbarch = gdbarch_alloc (&info, tdep);
+  tdep->elf_flags = elf_flags;
+  tdep->found_abi = found_abi;
+  tdep->nanomips_abi = nanomips_abi;
+  tdep->fpu_type = fpu_type;
+  tdep->register_size = register_size;
+
+  /* Initially set everything according to the default ABI/ISA.  */
+  set_gdbarch_short_bit (gdbarch, 16);
+  set_gdbarch_int_bit (gdbarch, 32);
+  set_gdbarch_float_bit (gdbarch, 32);
+  set_gdbarch_double_bit (gdbarch, 64);
+  set_gdbarch_long_double_bit (gdbarch, 64);
+  set_gdbarch_register_reggroup_p (gdbarch, nanomips_register_reggroup_p);
+  set_gdbarch_pseudo_register_read (gdbarch, nanomips_pseudo_register_read);
+  set_gdbarch_pseudo_register_write (gdbarch, nanomips_pseudo_register_write);
+  set_gdbarch_ax_pseudo_register_collect (gdbarch,
+					  nanomips_ax_pseudo_register_collect);
+  set_gdbarch_ax_pseudo_register_push_stack
+      (gdbarch, nanomips_ax_pseudo_register_push_stack);
+
+  tdep->default_mask_address_p = 0;
+
+  set_gdbarch_push_dummy_call (gdbarch, nanomips_push_dummy_call);
+  set_gdbarch_return_value (gdbarch, nanomips_return_value);
+
+  switch (nanomips_abi)
+    {
+    case NANOMIPS_ABI_P32:
+      set_gdbarch_long_bit (gdbarch, 32);
+      set_gdbarch_ptr_bit (gdbarch, 32);
+      set_gdbarch_long_long_bit (gdbarch, 64);
+      break;
+    case NANOMIPS_ABI_P64:
+      set_gdbarch_long_bit (gdbarch, 64);
+      set_gdbarch_ptr_bit (gdbarch, 64);
+      set_gdbarch_long_long_bit (gdbarch, 64);
+      set_gdbarch_long_double_bit (gdbarch, 128);
+      set_gdbarch_long_double_format (gdbarch, floatformats_ibm_long_double);
+      break;
+    default:
+      internal_error (__FILE__, __LINE__, _("unknown ABI in switch"));
+    }
+
+  set_gdbarch_read_pc (gdbarch, nanomips_read_pc);
+  set_gdbarch_write_pc (gdbarch, nanomips_write_pc);
+
+  /* Add/remove bits from an address.  The nanoMIPS needs be careful to
+     ensure that all 32 bit addresses are sign extended to 64 bits.  */
+  set_gdbarch_addr_bits_remove (gdbarch, nanomips_addr_bits_remove);
+
+  /* Unwind the frame.  */
+  set_gdbarch_unwind_pc (gdbarch, nanomips_unwind_pc);
+  set_gdbarch_unwind_sp (gdbarch, nanomips_unwind_sp);
+  set_gdbarch_dummy_id (gdbarch, nanomips_dummy_id);
+
+  /* Map debug register numbers onto internal register numbers.  */
+  set_gdbarch_stab_reg_to_regnum (gdbarch, nanomips_stab_reg_to_regnum);
+  set_gdbarch_ecoff_reg_to_regnum (gdbarch,
+				   nanomips_dwarf_dwarf2_ecoff_reg_to_regnum);
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch,
+				    nanomips_dwarf_dwarf2_ecoff_reg_to_regnum);
+  set_gdbarch_register_sim_regno (gdbarch, nanomips_register_sim_regno);
+
+  /* nanoMIPS version of CALL_DUMMY.  */
+
+  set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
+  set_gdbarch_push_dummy_code (gdbarch, nanomips_push_dummy_code);
+  set_gdbarch_frame_align (gdbarch, nanomips_frame_align);
+
+  set_gdbarch_print_float_info (gdbarch, nanomips_print_float_info);
+
+  set_gdbarch_convert_register_p (gdbarch, nanomips_convert_register_p);
+  set_gdbarch_register_to_value (gdbarch, nanomips_register_to_value);
+  set_gdbarch_value_to_register (gdbarch, nanomips_value_to_register);
+
+  set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+  set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+				       nanomips_breakpoint_kind_from_pc);
+  set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+				       nanomips_sw_breakpoint_from_kind);
+
+  set_gdbarch_skip_prologue (gdbarch, nanomips_skip_prologue);
+
+  set_gdbarch_stack_frame_destroyed_p (gdbarch,
+				       nanomips_stack_frame_destroyed_p);
+
+  set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address);
+  set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);
+  set_gdbarch_integer_to_address (gdbarch, nanomips_integer_to_address);
+
+  set_gdbarch_print_registers_info (gdbarch, nanomips_print_registers_info);
+
+  if (nanomips_abi == NANOMIPS_ABI_P64)
+    set_gdbarch_print_insn (gdbarch, gdb_print_insn_nanomips_p64);
+  else
+    set_gdbarch_print_insn (gdbarch, gdb_print_insn_nanomips_p32);
+
+  /* FIXME: cagney/2003-08-29: The macros target_have_steppable_watchpoint,
+     HAVE_NONSTEPPABLE_WATCHPOINT, and target_have_continuable_watchpoint
+     need to all be folded into the target vector.  Since they are
+     being used as guards for target_stopped_by_watchpoint, why not have
+     target_stopped_by_watchpoint return the type of watchpoint that the code
+     is sitting on?  */
+  set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
+
+  /* Virtual tables.  */
+  set_gdbarch_vbit_in_delta (gdbarch, 0);
+
+  /* Hook in OS ABI-specific overrides, if they have been registered.  */
+  info.target_desc = tdesc;
+  info.tdesc_data = tdesc_data.get ();
+  gdbarch_init_osabi (info, gdbarch);
+
+  /* Unwind the frame.  */
+  dwarf2_append_unwinders (gdbarch);
+  frame_unwind_append_unwinder (gdbarch, &nanomips_frame_unwind);
+  frame_base_append_sniffer (gdbarch, dwarf2_frame_base_sniffer);
+  frame_base_append_sniffer (gdbarch, nanomips_frame_base_sniffer);
+
+  regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct nanomips_regnum);
+  *regnum = nanomips_regnum;
+  tdep->regnum = regnum;
+
+  set_gdbarch_num_regs (gdbarch, num_regs);
+  set_tdesc_pseudo_register_type (gdbarch, nanomips_pseudo_register_type);
+  tdesc_use_registers (gdbarch, info.target_desc, std::move (tdesc_data));
+
+  /* Override the normal target description methods to handle our
+     dual real and pseudo registers.  */
+  set_gdbarch_register_name (gdbarch, nanomips_register_name);
+  set_gdbarch_register_reggroup_p (gdbarch,
+				   nanomips_tdesc_register_reggroup_p);
+
+  /* The target description may have adjusted num_regs, fetch the final
+     value and set pc_regnum and sp_regnum now that it has been fixed.  */
+  num_regs = gdbarch_num_regs (gdbarch);
+  set_gdbarch_num_pseudo_regs (gdbarch, num_regs);
+  set_gdbarch_pc_regnum (gdbarch, NANOMIPS_PC_REGNUM + num_regs);
+  set_gdbarch_sp_regnum (gdbarch, NANOMIPS_SP_REGNUM + num_regs);
+  if (regnum->fpr != -1)
+    set_gdbarch_fp0_regnum (gdbarch, regnum->fpr + NANOMIPS_FP0_REGNUM);
+  set_gdbarch_virtual_frame_pointer (gdbarch, nanomips_virtual_frame_pointer);
+
+  return gdbarch;
+}
+
+static void
+nanomips_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
+{
+  struct nanomips_gdbarch_tdep *tdep = (struct nanomips_gdbarch_tdep*) gdbarch_tdep (gdbarch);
+  if (tdep != NULL)
+    {
+      int ef_mips_arch;
+      int ef_mips_32bitmode;
+      /* Determine the ISA.  */
+      switch (tdep->elf_flags & EF_NANOMIPS_ARCH)
+	{
+	case E_NANOMIPS_ARCH_32R6:
+	  ef_mips_arch = 1;
+	  break;
+	case E_NANOMIPS_ARCH_64R6:
+	  ef_mips_arch = 2;
+	  break;
+	default:
+	  ef_mips_arch = 0;
+	  break;
+	}
+      /* Determine the size of a pointer.  */
+      ef_mips_32bitmode = (tdep->elf_flags & EF_NANOMIPS_32BITMODE);
+      gdb_printf (file,
+			  "nanomips_dump_tdep: tdep->elf_flags = 0x%x\n",
+			  tdep->elf_flags);
+      gdb_printf (file,
+			  "nanomips_dump_tdep: ef_mips_32bitmode = %d\n",
+			  ef_mips_32bitmode);
+      gdb_printf (file,
+			  "nanomips_dump_tdep: ef_mips_arch = %d\n",
+			  ef_mips_arch);
+      gdb_printf (file,
+			  "nanomips_dump_tdep: tdep->nanomips_abi = %d (%s)\n",
+			  tdep->nanomips_abi,
+			  nanomips_abi_strings[tdep->nanomips_abi]);
+      gdb_printf (file,
+			  "nanomips_dump_tdep: "
+			  "nanomips_mask_address_p() %d (default %d)\n",
+			  nanomips_mask_address_p (tdep),
+			  tdep->default_mask_address_p);
+    }
+
+  gdb_printf (file,
+		      "nanomips_dump_tdep: FPU_TYPE = %d (%s)\n",
+		      FPU_TYPE (gdbarch),
+		      (FPU_TYPE (gdbarch) == NANOMIPS_FPU_NONE ? "unknown"
+		       : FPU_TYPE (gdbarch) == NANOMIPS_FPU_HARD ?
+						"64bit hardware floating point"
+		       : FPU_TYPE (gdbarch) == NANOMIPS_FPU_SOFT ?
+						"Software floating point"
+		       : "???"));
+}
+
+void _initialize_nanomips_tdep(); /* -Wmissing-prototypes */
+
+void
+_initialize_nanomips_tdep ()
+{
+  gdbarch_register (bfd_arch_nanomips, nanomips_gdbarch_init,
+		    nanomips_dump_tdep);
+
+  initialize_tdesc_nanomips ();
+
+  nanomips_pdr_data = register_objfile_data ();
+
+  /* Add root prefix command for all "set/show nanomips" commands.  */
+  add_prefix_cmd ("nanomips", no_class, set_nanomips_command,
+		  _("Various nanoMIPS specific commands."),
+		  &setnanomipscmdlist, 0, &setlist);
+
+  add_prefix_cmd ("nanomips", no_class, show_nanomips_command,
+		  _("Various nanoMIPS specific commands."),
+		  &shownanomipscmdlist, 0, &showlist);
+
+  /* We really would like to have both "0" and "unlimited" work, but
+     command.c doesn't deal with that.  So make it a var_zinteger
+     because the user can always use "999999" or some such for unlimited.  */
+  add_setshow_zinteger_cmd ("heuristic-fence-post", class_support,
+			    &heuristic_fence_post, _("\
+Set the distance searched for the start of a function."), _("\
+Show the distance searched for the start of a function."), _("\
+If you are debugging a stripped executable, GDB needs to search through the\n\
+program for the start of a function.  This command sets the distance of the\n\
+search.  The only need to set it is when debugging a stripped executable."),
+			    reinit_frame_cache_sfunc,
+			    NULL, /* FIXME: i18n: The distance searched for
+				     the start of a function is %s.  */
+			    &setlist, &showlist);
+
+  /* Allow the user to control whether the upper bits of 64-bit
+     addresses should be zeroed.  */
+  add_setshow_auto_boolean_cmd ("mask-address", no_class,
+				&mask_address_var, _("\
+Set zeroing of upper 32 bits of 64-bit addresses."), _("\
+Show zeroing of upper 32 bits of 64-bit addresses."), _("\
+Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to\n\
+allow GDB to determine the correct value."),
+				NULL, show_mask_address,
+				&setnanomipscmdlist, &shownanomipscmdlist);
+
+  /* Debug this files internals.  */
+  add_setshow_zuinteger_cmd ("nanomips", class_maintenance,
+			     &nanomips_debug, _("\
+Set nanomips debugging."), _("\
+Show nanomips debugging."), _("\
+When non-zero, nanomips specific debugging is enabled."),
+			     NULL,
+			     NULL, /* FIXME: i18n: Mips debugging is
+				      currently %s.  */
+			     &setdebuglist, &showdebuglist);
+}
diff --git a/gdb/nanomips-tdep.h b/gdb/nanomips-tdep.h
new file mode 100644
index 00000000000..6bced514e85
--- /dev/null
+++ b/gdb/nanomips-tdep.h
@@ -0,0 +1,144 @@
+/* Target-dependent header for the nanoMIPS architecture, for GDB,
+   the GNU Debugger.
+
+   Copyright (C) 2002-2022 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef NANOMIPS_TDEP_H
+#define NANOMIPS_TDEP_H
+
+#include "objfiles.h"
+
+struct gdbarch;
+
+/* All the possible nanoMIPS ABIs.  */
+enum nanomips_abi
+  {
+    NANOMIPS_ABI_UNKNOWN = 0,
+    NANOMIPS_ABI_P32,
+    NANOMIPS_ABI_P64,
+  };
+
+/* Return the nanoMIPS ABI associated with GDBARCH.  */
+enum nanomips_abi nanomips_abi (struct gdbarch *gdbarch);
+
+/* Return the current index for various nanoMIPS registers.  */
+struct nanomips_regnum
+{
+  int fpr;		/* Floating-point unit registers.  */
+  int badvaddr;		/* Bad vaddr for addressing exception.  */
+  int status;		/* Status register.  */
+  int cause;		/* Describes last exception.  */
+  int dsp;		/* DSP registers.  */
+  int restart;		/* Linux syscall restart flag.  */
+};
+
+extern const struct nanomips_regnum *nanomips_regnum (struct gdbarch *gdbarch);
+
+/* nanoMIPS floating-point operations.  */
+
+enum fpu_type
+{
+  NANOMIPS_FPU_NONE,	/* Unknown floating point.  */
+  NANOMIPS_FPU_HARD,	/* Double precision floating point.  */
+  NANOMIPS_FPU_SOFT	/* Software floating point.  */
+};
+
+/* nanoMIPS specific per-architecture information.  */
+struct nanomips_gdbarch_tdep : gdbarch_tdep
+{
+  /* from the elf header */
+  int elf_flags;
+
+  /* nanomips options */
+  enum nanomips_abi nanomips_abi;
+  enum nanomips_abi found_abi;
+  enum fpu_type fpu_type;
+  int mips_last_arg_regnum;
+  int default_mask_address_p;
+
+  /* Indexes for various registers determined dynamically at run time.
+     This contains the "public" fields.  Don't add any that do not need
+     to be public.  */
+  struct nanomips_regnum *regnum;
+
+  /* The size of register data available from the target.  */
+  int register_size;
+
+  /* Return the expected next PC if FRAME is stopped at a syscall
+     instruction.  */
+  CORE_ADDR (*syscall_next_pc) (struct frame_info *frame, CORE_ADDR pc);
+};
+
+/* Register numbers of various important registers from the fixed
+   GPR+PC register set that is always present.  The rest is determined
+   dynamically at run time and held in `gdbarch_tdep->regnum'.  */
+
+enum
+{
+  NANOMIPS_ZERO_REGNUM = 0,
+  NANOMIPS_AT_REGNUM = 1,
+  NANOMIPS_T4_REGNUM = 2,
+  NANOMIPS_A0_REGNUM = 4,
+  NANOMIPS_GP_REGNUM = 28,
+  NANOMIPS_SP_REGNUM = 29,
+  NANOMIPS_FP_REGNUM = 30,
+  NANOMIPS_RA_REGNUM = 31,
+  NANOMIPS_PC_REGNUM = 32
+};
+
+/* Floating-point register offsets relative to `gdbarch_tdep->regnum->fpr'.  */
+
+enum
+{
+  NANOMIPS_FP0_REGNUM = 0,
+  NANOMIPS_FCSR_REGNUM = 32,
+  NANOMIPS_FIR_REGNUM = 33
+};
+
+/* DSP register offsets, relative to `gdbarch_tdep->regnum->dsp'.  */
+
+enum
+{
+  NANOMIPS_DSPHI0_REGNUM = 0,
+  NANOMIPS_DSPLO0_REGNUM = 1,
+  NANOMIPS_DSPCTL_REGNUM = 8
+};
+
+/* Instruction sizes and other useful constants.  */
+enum
+{
+  INSN16_SIZE = 2,
+  INSN32_SIZE = 4,
+  /* The number of floating-point or integer registers.  */
+  NUMREGS = 32
+};
+
+/* Single step based on where the current instruction will take us.  */
+extern std::vector<CORE_ADDR>
+nanomips_software_single_step (struct regcache *regcache);
+
+/* Return the currently determined ISA register size.  */
+extern int nanomips_isa_regsize (struct gdbarch *gdbarch);
+
+/* Return the currently configured (or set) saved register size.  */
+extern unsigned int nanomips_abi_regsize (struct gdbarch *gdbarch);
+
+/* Make PC the address of the next instruction to execute.  */
+extern void nanomips_write_pc (struct regcache *regcache, CORE_ADDR pc);
+
+#endif /* NANOMIPS_TDEP_H */
diff --git a/gdb/testsuite/gdb.asm/asm-source.exp b/gdb/testsuite/gdb.asm/asm-source.exp
index d56a5076b44..c2ec299a81f 100644
--- a/gdb/testsuite/gdb.asm/asm-source.exp
+++ b/gdb/testsuite/gdb.asm/asm-source.exp
@@ -100,6 +100,13 @@ switch -glob -- [istarget] {
     "mips*-*" {
         set asm-arch mips
     }
+    "nanomips*-elf" {
+        set asm-arch nanomips
+	append link-flags " -Ttext 0x80020000 -Tdata 0x80030000"
+	set board [target_info name]
+	set old_ldscript [board_info $board ldscript]
+	set_board_info ldscript ""
+    }
     "powerpc64le-*" {
         set asm-arch powerpc64le
         set asm-flags "-a64 -I${srcdir}/${subdir} $obj_include"
@@ -260,7 +267,7 @@ if {[target_link [list $asm1obj $asm2obj] "${binfile}" ${link-flags}] != "" } th
 }
 
 # Restore the target board linker script for HC11/HC12.
-if { [istarget "m6811-*-*"] || [istarget "m6812-*-*"] } {
+if { [istarget "m6811-*-*"] || [istarget "m6812-*-*"] || [istarget "nanomips*-elf"] } {
     set_board_info ldscript $old_ldscript
 }
 
diff --git a/gdb/testsuite/gdb.asm/nanomips.inc b/gdb/testsuite/gdb.asm/nanomips.inc
new file mode 100644
index 00000000000..6e2ead15d2c
--- /dev/null
+++ b/gdb/testsuite/gdb.asm/nanomips.inc
@@ -0,0 +1,49 @@
+	comment "subroutine declare"
+	.purgem gdbasm_declare
+	.macro gdbasm_declare name
+	.align	1
+	.ent	\name
+	.type	\name,@function
+\name:
+	.endm
+
+	comment "subroutine prologue"
+	.macro gdbasm_enter
+	save 32, $fp, $ra
+	addiu $fp, $sp, -4080
+	.endm
+
+	comment "subroutine epilogue"
+	.macro gdbasm_leave
+	restore.jrc 32, $fp, $ra
+	.endm
+
+	comment "subroutine end"
+	.purgem gdbasm_end
+	.macro gdbasm_end name
+	.end	\name
+	.endm
+
+	.macro gdbasm_call subr
+        li     $t9, \subr
+        jalrc  $ra, $t9
+	.endm
+
+	.macro gdbasm_several_nops
+	nop
+	nop
+	nop
+	nop
+	.endm
+
+	comment "exit (0)"
+	.macro gdbasm_exit0
+	comment "Don't know how to exit, but this will certainly halt..."
+	lw 	$a3, 0($zero)
+	.endm
+
+	comment "crt0 startup"
+	.macro gdbasm_startup
+	li $sp, 0x8007fff0
+	li $fp, 0
+	.endm
diff --git a/gdb/testsuite/gdb.base/catch-gdb-caused-signals.c b/gdb/testsuite/gdb.base/catch-gdb-caused-signals.c
index e9923814b01..a2064b3bb2e 100644
--- a/gdb/testsuite/gdb.base/catch-gdb-caused-signals.c
+++ b/gdb/testsuite/gdb.base/catch-gdb-caused-signals.c
@@ -27,6 +27,9 @@ main (void)
 {
   int i = 0;
 
+  /* Ensure printf function is available.  */
+  printf ("printf available %d\n", i);
+
   gdb_unbuffer_output ();
 
   i++; /* set dprintf here */
diff --git a/gdb/testsuite/gdb.base/float.exp b/gdb/testsuite/gdb.base/float.exp
index 62e8346928b..002a4829acb 100644
--- a/gdb/testsuite/gdb.base/float.exp
+++ b/gdb/testsuite/gdb.base/float.exp
@@ -67,7 +67,7 @@ if { [is_aarch64_target] } then {
             pass "info float (without FPU)"
 	}
     }
-} elseif [istarget "mips*-*-*"] then {
+} elseif { [istarget "mips*-*-*"] || [istarget "nanomips*-*-*"] } then {
     gdb_test_multiple "info float" "info float" {
 	-re "fpu type: none / unused\r\n$gdb_prompt $" {
 	      pass "info float (without FPU)"
diff --git a/gdb/testsuite/gdb.trace/trace-common.h b/gdb/testsuite/gdb.trace/trace-common.h
index f8cd654ba2b..6dfab081f1e 100644
--- a/gdb/testsuite/gdb.trace/trace-common.h
+++ b/gdb/testsuite/gdb.trace/trace-common.h
@@ -43,7 +43,7 @@ x86_trace_dummy ()
        "    call " SYMBOL(x86_trace_dummy) "\n" \
        )
 
-#elif (defined __aarch64__) || (defined __powerpc__)
+#elif (defined __aarch64__) || (defined __powerpc__) || (__nanomips__)
 
 #define FAST_TRACEPOINT_LABEL(name) \
   asm ("    .global " SYMBOL(name) "\n" \
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index b04fbb89e4e..64401ab480b 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -2995,6 +2995,7 @@ gdb_caching_proc supports_memtag {
 proc can_hardware_single_step {} {
 
     if { [istarget "arm*-*-*"] || [istarget "mips*-*-*"]
+	 || [istarget "nanomips*-*-*"]
 	 || [istarget "tic6x-*-*"] || [istarget "sparc*-*-linux*"]
 	 || [istarget "nios2-*-*"] || [istarget "riscv*-*-linux*"] } {
 	return 0
-- 
2.25.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2 2/2] gdb: Add nanoMIPS port
  2022-05-31 11:35 ` [PATCH v2 2/2] gdb: " Aleksandar Rikalo
@ 2022-05-31 11:56   ` Eli Zaretskii
  0 siblings, 0 replies; 3+ messages in thread
From: Eli Zaretskii @ 2022-05-31 11:56 UTC (permalink / raw)
  To: Aleksandar Rikalo; +Cc: gdb-patches

> From: Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>
> Date: Tue, 31 May 2022 13:35:06 +0200
> 
>  config.sub                                    |    1 +
>  configure                                     |    3 +
>  configure.ac                                  |    3 +
>  gdb/Makefile.in                               |    2 +
>  gdb/NEWS                                      |    1 +
>  gdb/configure.host                            |    1 +
>  gdb/configure.tgt                             |   11 +
>  gdb/features/Makefile                         |    4 +
>  gdb/features/nanomips-cp0.xml                 |   13 +
>  gdb/features/nanomips-cpu.xml                 |   44 +
>  gdb/features/nanomips-dsp.xml                 |   20 +
>  gdb/features/nanomips-fpu.xml                 |   45 +
>  gdb/features/nanomips.c                       |   54 +
>  gdb/features/nanomips.xml                     |   12 +
>  gdb/features/nanomips64-cp0.xml               |   13 +
>  gdb/features/nanomips64-cpu.xml               |   44 +
>  gdb/features/nanomips64-dsp.xml               |   20 +
>  gdb/nanomips-tdep.c                           | 3410 +++++++++++++++++
>  gdb/nanomips-tdep.h                           |  144 +
>  gdb/testsuite/gdb.asm/asm-source.exp          |    9 +-
>  gdb/testsuite/gdb.asm/nanomips.inc            |   49 +
>  .../gdb.base/catch-gdb-caused-signals.c       |    3 +
>  gdb/testsuite/gdb.base/float.exp              |    2 +-
>  gdb/testsuite/gdb.trace/trace-common.h        |    2 +-
>  gdb/testsuite/lib/gdb.exp                     |    1 +
>  25 files changed, 3908 insertions(+), 3 deletions(-)
>  create mode 100644 gdb/features/nanomips-cp0.xml
>  create mode 100644 gdb/features/nanomips-cpu.xml
>  create mode 100644 gdb/features/nanomips-dsp.xml
>  create mode 100644 gdb/features/nanomips-fpu.xml
>  create mode 100644 gdb/features/nanomips.c
>  create mode 100644 gdb/features/nanomips.xml
>  create mode 100644 gdb/features/nanomips64-cp0.xml
>  create mode 100644 gdb/features/nanomips64-cpu.xml
>  create mode 100644 gdb/features/nanomips64-dsp.xml
>  create mode 100644 gdb/nanomips-tdep.c
>  create mode 100644 gdb/nanomips-tdep.h
>  create mode 100644 gdb/testsuite/gdb.asm/nanomips.inc

Thanks, the addition to NEWS is okay.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-05-31 11:56 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-31 11:35 [PATCH v2 1/2] sim: Add nanoMIPS port Aleksandar Rikalo
2022-05-31 11:35 ` [PATCH v2 2/2] gdb: " Aleksandar Rikalo
2022-05-31 11:56   ` Eli Zaretskii

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).