public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v4 0/4] sim: Add support for MIPS32/64 revision 6
@ 2022-02-01 12:52 Dragan Mladjenovic
  2022-02-01 12:52 ` [PATCH v4 1/4] sim: Allow toggling of quiet NaN-bit semantics Dragan Mladjenovic
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Dragan Mladjenovic @ 2022-02-01 12:52 UTC (permalink / raw)
  To: gdb-patches; +Cc: Mike Frysinger, Maciej W . Rozycki, Chao-ying Fu

This is a refresh of the previous series by Faraz excluding GDB support.
Patches should be Werror clean now. The original summary is below:

We introduce partial support for IEEE 754-2008 in the common code including
NaN semantics for MIN/MAX/ABS/NEG operations and a CLASSIFY operation.
This can enabled by invoking sim_fpu_set_mode().

The multi-simulator model supports R6 in addition to previous
revisions and the engine picks the appropriate revision based on flags
in the ELF header where possible.

Faraz Shahbazker (4):
  sim: Allow toggling of quiet NaN-bit semantics
  sim: Factor out NaN handling in floating point operations
  sim: Add partial support for IEEE 754-2008
  sim: mips: Add simulator support for mips32r6/mips64r6

 sim/common/sim-bits.h              |    5 +
 sim/common/sim-fpu.c               |  321 ++++----
 sim/common/sim-fpu.h               |   61 +-
 sim/mips/Makefile.in               |    1 +
 sim/mips/configure                 |   22 +-
 sim/mips/configure.ac              |   20 +-
 sim/mips/cp1.c                     |  432 +++++++++-
 sim/mips/cp1.h                     |    6 +
 sim/mips/interp.c                  |    6 +-
 sim/mips/micromips.igen            |    4 +-
 sim/mips/mips.igen                 |  381 ++++++++-
 sim/mips/mips3264r2.igen           |   30 +
 sim/mips/mips3264r6.igen           | 1226 ++++++++++++++++++++++++++++
 sim/mips/sim-main.h                |   97 ++-
 sim/testsuite/mips/basic.exp       |   72 +-
 sim/testsuite/mips/hilo-hazard-3.s |    2 +-
 sim/testsuite/mips/r2-fpu.s        |   31 +
 sim/testsuite/mips/r6-64.s         |  157 ++++
 sim/testsuite/mips/r6-branch.s     |  291 +++++++
 sim/testsuite/mips/r6-forbidden.s  |   51 ++
 sim/testsuite/mips/r6-fpu.s        |  446 ++++++++++
 sim/testsuite/mips/r6-llsc-dp.s    |   57 ++
 sim/testsuite/mips/r6-llsc-wp.s    |   41 +
 sim/testsuite/mips/r6-removed.csv  |   68 ++
 sim/testsuite/mips/r6-removed.s    |   18 +
 sim/testsuite/mips/r6.s            |  163 ++++
 sim/testsuite/mips/testutils.inc   |   55 ++
 sim/testsuite/mips/utils-r6.inc    |  150 ++++
 28 files changed, 3963 insertions(+), 251 deletions(-)
 create mode 100644 sim/mips/mips3264r6.igen
 create mode 100644 sim/testsuite/mips/r2-fpu.s
 create mode 100644 sim/testsuite/mips/r6-64.s
 create mode 100644 sim/testsuite/mips/r6-branch.s
 create mode 100644 sim/testsuite/mips/r6-forbidden.s
 create mode 100644 sim/testsuite/mips/r6-fpu.s
 create mode 100644 sim/testsuite/mips/r6-llsc-dp.s
 create mode 100644 sim/testsuite/mips/r6-llsc-wp.s
 create mode 100644 sim/testsuite/mips/r6-removed.csv
 create mode 100644 sim/testsuite/mips/r6-removed.s
 create mode 100644 sim/testsuite/mips/r6.s
 create mode 100644 sim/testsuite/mips/utils-r6.inc

-- 
2.17.1


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

* [PATCH v4 1/4] sim: Allow toggling of quiet NaN-bit semantics
  2022-02-01 12:52 [PATCH v4 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
@ 2022-02-01 12:52 ` Dragan Mladjenovic
  2022-02-02  3:39   ` Mike Frysinger
  2022-02-01 12:53 ` [PATCH v4 2/4] sim: Factor out NaN handling in floating point operations Dragan Mladjenovic
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Dragan Mladjenovic @ 2022-02-01 12:52 UTC (permalink / raw)
  To: gdb-patches
  Cc: Mike Frysinger, Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

From: Faraz Shahbazker <fshahbazker@wavecomp.com>

IEEE754-1985 specifies the top bit of the mantissa as an indicator
of signalling vs. quiet NaN, but does not define the precise semantics.
Most architectures treat this bit as indicating quiet NaN, but legacy
(pre-R6) MIPS goes the other way and treats it as signalling NaN.

This used to be controlled by a macro that was only defined for MIPS.
This patch replaces the macro with a variable to track the current
semantics of the NaN bit and allows differentiation between older
(pre-R6) and and newer MIPS cores.

2022-02-01  Faraz Shahbazker  <fshahbazker@wavecomp.com>

sim/common/ChangeLog:
	* sim-fpu.c (_sim_fpu): New.
	(pack_fpu, unpack_fpu): Allow reversal of quiet NaN semantics.
	* sim-fpu.h (sim_fpu_state): New struct.
	(_sim_fpu): New extern.
	(sim_fpu_quiet_nan_inverted): New define.

sim/mips/ChangeLog:
	* cp1.h (fcsr_NAN2008_mask, fcsr_NAN2008_shift): New.
	* mips.igen (check_fpu): Select default quiet NaN mode
	for legacy MIPS.
	* sim-main.h (SIM_QUIET_NAN_NEGATED): Remove.
---
 sim/common/sim-fpu.c | 29 ++++++++++++++---------------
 sim/common/sim-fpu.h | 25 +++++++++++++++++++++++++
 sim/mips/cp1.h       |  4 ++++
 sim/mips/mips.igen   |  3 +++
 sim/mips/sim-main.h  |  3 ---
 5 files changed, 46 insertions(+), 18 deletions(-)

Changes from v3: Introduced sim_fpu_state struct.

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index a05c57897ff..78592b1f790 100644
--- a/sim/common/sim-fpu.c
+++ b/sim/common/sim-fpu.c
@@ -198,11 +198,10 @@ pack_fpu (const sim_fpu *src,
       /* Force fraction to correct class.  */
       fraction = src->fraction;
       fraction >>= NR_GUARDS;
-#ifdef SIM_QUIET_NAN_NEGATED
-      fraction |= QUIET_NAN - 1;
-#else
-      fraction |= QUIET_NAN;
-#endif
+      if (sim_fpu_quiet_nan_inverted)
+	fraction |= QUIET_NAN - 1;
+      else
+	fraction |= QUIET_NAN;
       break;
     case sim_fpu_class_snan:
       sign = src->sign;
@@ -210,11 +209,10 @@ pack_fpu (const sim_fpu *src,
       /* Force fraction to correct class.  */
       fraction = src->fraction;
       fraction >>= NR_GUARDS;
-#ifdef SIM_QUIET_NAN_NEGATED
-      fraction |= QUIET_NAN;
-#else
-      fraction &= ~QUIET_NAN;
-#endif
+      if (sim_fpu_quiet_nan_inverted)
+        fraction |= QUIET_NAN;
+      else
+	fraction &= ~QUIET_NAN;
       break;
     case sim_fpu_class_infinity:
       sign = src->sign;
@@ -372,11 +370,10 @@ unpack_fpu (sim_fpu *dst, uint64_t packed, int is_double)
 	  /* Non zero fraction, means NaN.  */
 	  dst->sign = sign;
 	  dst->fraction = (fraction << NR_GUARDS);
-#ifdef SIM_QUIET_NAN_NEGATED
-	  qnan = (fraction & QUIET_NAN) == 0;
-#else
-	  qnan = fraction >= QUIET_NAN;
-#endif
+	  if (sim_fpu_quiet_nan_inverted)
+	    qnan = (fraction & QUIET_NAN) == 0;
+	  else
+	    qnan = fraction >= QUIET_NAN;
 	  if (qnan)
 	    dst->class = sim_fpu_class_qnan;
 	  else
@@ -2512,6 +2509,8 @@ sim_fpu_gt (int *is,
 /* A number of useful constants */
 
 #if EXTERN_SIM_FPU_P
+sim_fpu_state _sim_fpu = { /* quiet_nan_inverted */ false };
+
 const sim_fpu sim_fpu_zero = {
   sim_fpu_class_zero, 0, 0, 0
 };
diff --git a/sim/common/sim-fpu.h b/sim/common/sim-fpu.h
index 447621b5d73..da67130d761 100644
--- a/sim/common/sim-fpu.h
+++ b/sim/common/sim-fpu.h
@@ -25,6 +25,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #define SIM_FPU_H
 
 
+#include <stdbool.h>
+
 
 /* The FPU intermediate type - this object, passed by reference,
    should be treated as opaque.
@@ -157,6 +159,17 @@ typedef enum
 
 
 
+/* State used by the FPU.
+
+   FIXME: This state is global, but should be moved to SIM_CPU .  */
+
+typedef struct _sim_fpu_state {
+  bool quiet_nan_inverted; /* Toggle quiet NaN semantics.  */
+} sim_fpu_state;
+
+
+
+
 /* Directly map between a 32/64 bit register and the sim_fpu internal
    type.
 
@@ -375,7 +388,19 @@ enum {
 INLINE_SIM_FPU (int) sim_fpu_is (const sim_fpu *l);
 INLINE_SIM_FPU (int) sim_fpu_cmp (const sim_fpu *l, const sim_fpu *r);
 
+/* Global FPU state.  */
+
+extern sim_fpu_state _sim_fpu;
+
+
+/* IEEE 754-1985 specifies the top bit of the mantissa as an indicator
+   of signalling vs. quiet NaN, but does not specify the semantics.
+   Most architectures treat this bit as quiet NaN, but legacy (pre-R6)
+   MIPS goes the other way and treats it as signalling.  This variable
+   tracks the current semantics of the NaN bit and allows differentiation
+   between pre-R6 and R6 MIPS cores.  */
 
+#define sim_fpu_quiet_nan_inverted _sim_fpu.quiet_nan_inverted
 
 /* A number of useful constants.  */
 
diff --git a/sim/mips/cp1.h b/sim/mips/cp1.h
index 96c51a7b736..d6d8a8874fd 100644
--- a/sim/mips/cp1.h
+++ b/sim/mips/cp1.h
@@ -40,6 +40,10 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #define fcsr_RM_mask       (0x00000003)
 #define fcsr_RM_shift      (0)
 
+/* FCSR bits for IEEE754-2008 compliance.  */
+#define fcsr_NAN2008_mask       (0x00040000)
+#define fcsr_NAN2008_shift      (18)
+
 #define fenr_FS            (0x00000004)
 
 /* Macros to update and retrieve the FCSR condition-code bits.  This
diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen
index c5db5c2304f..b0c5e5995af 100644
--- a/sim/mips/mips.igen
+++ b/sim/mips/mips.igen
@@ -5050,6 +5050,9 @@
 {
   if (! COP_Usable (1))
     SignalExceptionCoProcessorUnusable (1);
+
+  FCSR &= ~fcsr_NAN2008_mask;
+  sim_fpu_quiet_nan_inverted = true;
 }
 
 
diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h
index d724688a434..8e3e85f2585 100644
--- a/sim/mips/sim-main.h
+++ b/sim/mips/sim-main.h
@@ -20,9 +20,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifndef SIM_MAIN_H
 #define SIM_MAIN_H
 
-/* MIPS uses an unusual format for floating point quiet NaNs.  */
-#define SIM_QUIET_NAN_NEGATED
-
 #define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \
 mips_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ERROR))
 
-- 
2.17.1


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

* [PATCH v4 2/4] sim: Factor out NaN handling in floating point operations
  2022-02-01 12:52 [PATCH v4 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
  2022-02-01 12:52 ` [PATCH v4 1/4] sim: Allow toggling of quiet NaN-bit semantics Dragan Mladjenovic
@ 2022-02-01 12:53 ` Dragan Mladjenovic
  2022-02-01 12:53 ` [PATCH v4 3/4] sim: Add partial support for IEEE 754-2008 Dragan Mladjenovic
  2022-02-01 12:53 ` [PATCH v4 4/4] sim: mips: Add simulator support for mips32r6/mips64r6 Dragan Mladjenovic
  3 siblings, 0 replies; 8+ messages in thread
From: Dragan Mladjenovic @ 2022-02-01 12:53 UTC (permalink / raw)
  To: gdb-patches
  Cc: Mike Frysinger, Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

From: Faraz Shahbazker <fshahbazker@wavecomp.com>

2022-02-01  Faraz Shahbazker  <fshahbazker@wavecomp.com>

sim/common/ChangeLog:
	* sim-fpu.c (sim_fpu_op_nan): New.
	(sim_fpu_add): Factor out NaN operand handling with
	a call to sim_fpu_op_nan.
	(sim_fpu_sub, sim_fpu_mul, sim_fpu_div): Likewise.
	(sim_fpu_rem, sim_fpu_max, sim_fpu_min): Likewise.
	* sim-fpu.h (sim_fpu_op_nan): New declaration.
---
 sim/common/sim-fpu.c | 189 +++++++------------------------------------
 sim/common/sim-fpu.h |  10 +++
 2 files changed, 41 insertions(+), 158 deletions(-)

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index 78592b1f790..4d16a392dc9 100644
--- a/sim/common/sim-fpu.c
+++ b/sim/common/sim-fpu.c
@@ -986,7 +986,24 @@ sim_fpu_round_64 (sim_fpu *f,
   return do_round (f, 1, round, denorm);
 }
 
+/* NaN handling for binary operations.  */
 
+INLINE_SIM_FPU (int)
+sim_fpu_op_nan (sim_fpu *f, const sim_fpu *l, const sim_fpu *r)
+{
+  if (sim_fpu_is_snan (l) || sim_fpu_is_snan (r))
+    {
+      *f = sim_fpu_is_snan (l) ? *l : *r;
+      f->class = sim_fpu_class_qnan;
+      return sim_fpu_status_invalid_snan;
+    }
+   ASSERT (sim_fpu_is_nan (l) || sim_fpu_is_nan (r));
+   if (sim_fpu_is_qnan (l))
+     *f = *l;
+   else /* if (sim_fpu_is_qnan (r)) */
+     *f = *r;
+  return 0;
+}
 
 /* Arithmetic ops */
 
@@ -995,28 +1012,8 @@ sim_fpu_add (sim_fpu *f,
 	     const sim_fpu *l,
 	     const sim_fpu *r)
 {
-  if (sim_fpu_is_snan (l))
-    {
-      *f = *l;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_snan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_qnan (l))
-    {
-      *f = *l;
-      return 0;
-    }
-  if (sim_fpu_is_qnan (r))
-    {
-      *f = *r;
-      return 0;
-    }
+  if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
+    return sim_fpu_op_nan (f, l, r);
   if (sim_fpu_is_infinity (l))
     {
       if (sim_fpu_is_infinity (r)
@@ -1144,28 +1141,8 @@ sim_fpu_sub (sim_fpu *f,
 	     const sim_fpu *l,
 	     const sim_fpu *r)
 {
-  if (sim_fpu_is_snan (l))
-    {
-      *f = *l;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_snan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_qnan (l))
-    {
-      *f = *l;
-      return 0;
-    }
-  if (sim_fpu_is_qnan (r))
-    {
-      *f = *r;
-      return 0;
-    }
+  if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
+    return sim_fpu_op_nan (f, l, r);
   if (sim_fpu_is_infinity (l))
     {
       if (sim_fpu_is_infinity (r)
@@ -1298,28 +1275,8 @@ sim_fpu_mul (sim_fpu *f,
 	     const sim_fpu *l,
 	     const sim_fpu *r)
 {
-  if (sim_fpu_is_snan (l))
-    {
-      *f = *l;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_snan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_qnan (l))
-    {
-      *f = *l;
-      return 0;
-    }
-  if (sim_fpu_is_qnan (r))
-    {
-      *f = *r;
-      return 0;
-    }
+  if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
+    return sim_fpu_op_nan (f, l, r);
   if (sim_fpu_is_infinity (l))
     {
       if (sim_fpu_is_zero (r))
@@ -1423,30 +1380,8 @@ sim_fpu_div (sim_fpu *f,
 	     const sim_fpu *l,
 	     const sim_fpu *r)
 {
-  if (sim_fpu_is_snan (l))
-    {
-      *f = *l;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_snan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_qnan (l))
-    {
-      *f = *l;
-      f->class = sim_fpu_class_qnan;
-      return 0;
-    }
-  if (sim_fpu_is_qnan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return 0;
-    }
+  if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
+    return sim_fpu_op_nan (f, l, r);
   if (sim_fpu_is_infinity (l))
     {
       if (sim_fpu_is_infinity (r))
@@ -1556,30 +1491,8 @@ sim_fpu_rem (sim_fpu *f,
 	     const sim_fpu *l,
 	     const sim_fpu *r)
 {
-  if (sim_fpu_is_snan (l))
-    {
-      *f = *l;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_snan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_qnan (l))
-    {
-      *f = *l;
-      f->class = sim_fpu_class_qnan;
-      return 0;
-    }
-  if (sim_fpu_is_qnan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return 0;
-    }
+  if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
+    return sim_fpu_op_nan (f, l, r);
   if (sim_fpu_is_infinity (l))
     {
       *f = sim_fpu_qnan;
@@ -1639,28 +1552,8 @@ sim_fpu_max (sim_fpu *f,
 	     const sim_fpu *l,
 	     const sim_fpu *r)
 {
-  if (sim_fpu_is_snan (l))
-    {
-      *f = *l;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_snan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_qnan (l))
-    {
-      *f = *l;
-      return 0;
-    }
-  if (sim_fpu_is_qnan (r))
-    {
-      *f = *r;
-      return 0;
-    }
+  if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
+    return sim_fpu_op_nan (f, l, r);
   if (sim_fpu_is_infinity (l))
     {
       if (sim_fpu_is_infinity (r)
@@ -1722,28 +1615,8 @@ sim_fpu_min (sim_fpu *f,
 	     const sim_fpu *l,
 	     const sim_fpu *r)
 {
-  if (sim_fpu_is_snan (l))
-    {
-      *f = *l;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_snan (r))
-    {
-      *f = *r;
-      f->class = sim_fpu_class_qnan;
-      return sim_fpu_status_invalid_snan;
-    }
-  if (sim_fpu_is_qnan (l))
-    {
-      *f = *l;
-      return 0;
-    }
-  if (sim_fpu_is_qnan (r))
-    {
-      *f = *r;
-      return 0;
-    }
+  if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
+    return sim_fpu_op_nan (f, l, r);
   if (sim_fpu_is_infinity (l))
     {
       if (sim_fpu_is_infinity (r)
diff --git a/sim/common/sim-fpu.h b/sim/common/sim-fpu.h
index da67130d761..228d2c7e1d6 100644
--- a/sim/common/sim-fpu.h
+++ b/sim/common/sim-fpu.h
@@ -261,6 +261,16 @@ INLINE_SIM_FPU (int) sim_fpu_sqrt (sim_fpu *f,
 
 
 
+/* NaN handling.
+
+   Assuming that at least one of the inputs is NAN choose the correct
+   NAN result for the binary operation.  */
+
+INLINE_SIM_FPU (int) sim_fpu_op_nan (sim_fpu *f,
+				     const sim_fpu *l, const sim_fpu *r);
+
+
+
 /* Conversion of integer <-> floating point. */
 
 INLINE_SIM_FPU (int) sim_fpu_i32to (sim_fpu *f, int32_t i,
-- 
2.17.1


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

* [PATCH v4 3/4] sim: Add partial support for IEEE 754-2008
  2022-02-01 12:52 [PATCH v4 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
  2022-02-01 12:52 ` [PATCH v4 1/4] sim: Allow toggling of quiet NaN-bit semantics Dragan Mladjenovic
  2022-02-01 12:53 ` [PATCH v4 2/4] sim: Factor out NaN handling in floating point operations Dragan Mladjenovic
@ 2022-02-01 12:53 ` Dragan Mladjenovic
  2022-02-02  3:42   ` Mike Frysinger
  2022-02-01 12:53 ` [PATCH v4 4/4] sim: mips: Add simulator support for mips32r6/mips64r6 Dragan Mladjenovic
  3 siblings, 1 reply; 8+ messages in thread
From: Dragan Mladjenovic @ 2022-02-01 12:53 UTC (permalink / raw)
  To: gdb-patches
  Cc: Mike Frysinger, Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

From: Faraz Shahbazker <fshahbazker@wavecomp.com>

2022-02-01  Faraz Shahbazker  <fshahbazker@wavecomp.com>

sim/common/ChangeLog:
	* sim-fpu.c (sim_fpu_minmax_nan): New.
	(sim_fpu_max): Add variant behaviour for IEEE 754-2008.
	(sim_fpu_min): Likewise.
	(sim_fpu_is_un, sim_fpu_is_or): New.
	(sim_fpu_un, sim_fpu_or): New.
	(sim_fpu_is_ieee754_2008, sim_fpu_is_ieee754_1985): New.
	(sim_fpu_set_mode): New.
	(sim_fpu_classify): New.
	* sim-fpu.h (sim_fpu_minmax_nan): New declaration.
	(sim_fpu_un, sim_fpu_or): New declarations.
	(sim_fpu_is_un, sim_fpu_is_or): New declarations.
	(sim_fpu_mode): New enum.
	[sim_fpu_state](current_mode): New field.
	(sim_fpu_current_mode): New define.
	(sim_fpu_is_ieee754_2008): New declaration.
	(sim_fpu_is_ieee754_1985): New declaration.
	(sim_fpu_set_mode): New declaration.
	(sim_fpu_classify): New declaration.
---
 sim/common/sim-fpu.c | 111 +++++++++++++++++++++++++++++++++++++++++--
 sim/common/sim-fpu.h |  26 +++++++++-
 2 files changed, 131 insertions(+), 6 deletions(-)

Changes from v3: Moved current mode into sim_fpu_state.

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index 4d16a392dc9..c6f6622612c 100644
--- a/sim/common/sim-fpu.c
+++ b/sim/common/sim-fpu.c
@@ -1005,6 +1005,30 @@ sim_fpu_op_nan (sim_fpu *f, const sim_fpu *l, const sim_fpu *r)
   return 0;
 }
 
+/* NaN handling specific to min/max operations.  */
+
+INLINE_SIM_FPU (int)
+sim_fpu_minmax_nan (sim_fpu *f, const sim_fpu *l, const sim_fpu *r)
+{
+  if (sim_fpu_is_snan (l)
+      || sim_fpu_is_snan (r)
+      || sim_fpu_is_ieee754_1985 ())
+    return sim_fpu_op_nan (f, l, r);
+  else
+    /* if sim_fpu_is_ieee754_2008()
+       && ((sim_fpu_is_qnan (l) || sim_fpu_is_qnan (r))) */
+    {
+      /* In IEEE754-2008:
+       * "minNum/maxNum is ... the canonicalized number if one
+       * operand is a number and the other a quiet NaN." */
+      if (sim_fpu_is_qnan (l))
+	*f = *r;
+      else /* if (sim_fpu_is_qnan (r)) */
+	*f = *l;
+      return 0;
+    }
+}
+
 /* Arithmetic ops */
 
 INLINE_SIM_FPU (int)
@@ -1553,7 +1577,7 @@ sim_fpu_max (sim_fpu *f,
 	     const sim_fpu *r)
 {
   if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
-    return sim_fpu_op_nan (f, l, r);
+    return sim_fpu_minmax_nan (f, l, r);
   if (sim_fpu_is_infinity (l))
     {
       if (sim_fpu_is_infinity (r)
@@ -1616,7 +1640,7 @@ sim_fpu_min (sim_fpu *f,
 	     const sim_fpu *r)
 {
   if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
-    return sim_fpu_op_nan (f, l, r);
+    return sim_fpu_minmax_nan (f, l, r);
   if (sim_fpu_is_infinity (l))
     {
       if (sim_fpu_is_infinity (r)
@@ -1677,7 +1701,7 @@ INLINE_SIM_FPU (int)
 sim_fpu_neg (sim_fpu *f,
 	     const sim_fpu *r)
 {
-  if (sim_fpu_is_snan (r))
+  if (sim_fpu_is_ieee754_1985 () && sim_fpu_is_snan (r))
     {
       *f = *r;
       f->class = sim_fpu_class_qnan;
@@ -1700,7 +1724,7 @@ sim_fpu_abs (sim_fpu *f,
 {
   *f = *r;
   f->sign = 0;
-  if (sim_fpu_is_snan (r))
+  if (sim_fpu_is_ieee754_1985 () && sim_fpu_is_snan (r))
     {
       f->class = sim_fpu_class_qnan;
       return sim_fpu_status_invalid_snan;
@@ -2255,6 +2279,21 @@ sim_fpu_is_gt (const sim_fpu *l, const sim_fpu *r)
   return is;
 }
 
+INLINE_SIM_FPU (int)
+sim_fpu_is_un (const sim_fpu *l, const sim_fpu *r)
+{
+  int is;
+  sim_fpu_un (&is, l, r);
+  return is;
+}
+
+INLINE_SIM_FPU (int)
+sim_fpu_is_or (const sim_fpu *l, const sim_fpu *r)
+{
+  int is;
+  sim_fpu_or (&is, l, r);
+  return is;
+}
 
 /* Compare operators */
 
@@ -2378,11 +2417,55 @@ sim_fpu_gt (int *is,
   return sim_fpu_lt (is, r, l);
 }
 
+INLINE_SIM_FPU (int)
+sim_fpu_un (int *is, const sim_fpu *l, const sim_fpu *r)
+{
+  if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
+   {
+    *is = 1;
+    return 0;
+   }
+
+  *is = 0;
+  return 0;
+}
+
+INLINE_SIM_FPU (int)
+sim_fpu_or (int *is, const sim_fpu *l, const sim_fpu *r)
+{
+  sim_fpu_un (is, l, r);
+
+  /* Invert result.  */
+  *is = !*is;
+  return 0;
+}
+
+INLINE_SIM_FPU(int)
+sim_fpu_classify (const sim_fpu *f)
+{
+  switch (f->class)
+    {
+    case sim_fpu_class_snan: return SIM_FPU_IS_SNAN;
+    case sim_fpu_class_qnan: return SIM_FPU_IS_QNAN;
+    case sim_fpu_class_infinity:
+      return f->sign ? SIM_FPU_IS_NINF : SIM_FPU_IS_PINF;
+    case sim_fpu_class_zero:
+      return f->sign ? SIM_FPU_IS_NZERO : SIM_FPU_IS_PZERO;
+    case sim_fpu_class_number:
+      return f->sign ? SIM_FPU_IS_NNUMBER : SIM_FPU_IS_PNUMBER;
+    case sim_fpu_class_denorm:
+      return f->sign ? SIM_FPU_IS_NDENORM : SIM_FPU_IS_PDENORM;
+    default:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+  return 0;
+}
 
 /* A number of useful constants */
 
 #if EXTERN_SIM_FPU_P
-sim_fpu_state _sim_fpu = { /* quiet_nan_inverted */ false };
+sim_fpu_state _sim_fpu = { /* quiet_nan_inverted */ false, sim_fpu_ieee754_1985 };
 
 const sim_fpu sim_fpu_zero = {
   sim_fpu_class_zero, 0, 0, 0
@@ -2404,6 +2487,24 @@ const sim_fpu sim_fpu_max64 = {
 };
 #endif
 
+/* Specification swapping behaviour */
+INLINE_SIM_FPU (bool)
+sim_fpu_is_ieee754_1985 (void)
+{
+  return (sim_fpu_current_mode == sim_fpu_ieee754_1985);
+}
+
+INLINE_SIM_FPU (bool)
+sim_fpu_is_ieee754_2008 (void)
+{
+  return (sim_fpu_current_mode == sim_fpu_ieee754_2008);
+}
+
+INLINE_SIM_FPU (void)
+sim_fpu_set_mode (const sim_fpu_mode m)
+{
+  sim_fpu_current_mode = m;
+}
 
 /* For debugging */
 
diff --git a/sim/common/sim-fpu.h b/sim/common/sim-fpu.h
index 228d2c7e1d6..b192f2deaec 100644
--- a/sim/common/sim-fpu.h
+++ b/sim/common/sim-fpu.h
@@ -163,8 +163,15 @@ typedef enum
 
    FIXME: This state is global, but should be moved to SIM_CPU .  */
 
+typedef enum
+{
+  sim_fpu_ieee754_1985,
+  sim_fpu_ieee754_2008,
+} sim_fpu_mode;
+
 typedef struct _sim_fpu_state {
   bool quiet_nan_inverted; /* Toggle quiet NaN semantics.  */
+  sim_fpu_mode current_mode;
 } sim_fpu_state;
 
 
@@ -268,6 +275,8 @@ INLINE_SIM_FPU (int) sim_fpu_sqrt (sim_fpu *f,
 
 INLINE_SIM_FPU (int) sim_fpu_op_nan (sim_fpu *f,
 				     const sim_fpu *l, const sim_fpu *r);
+INLINE_SIM_FPU (int) sim_fpu_minmax_nan (sim_fpu *f,
+					 const sim_fpu *l, const sim_fpu *r);
 
 
 
@@ -318,7 +327,8 @@ INLINE_SIM_FPU (double) sim_fpu_2d (const sim_fpu *d);
 /* INLINE_SIM_FPU (void) sim_fpu_f2 (sim_fpu *f, float s); */
 INLINE_SIM_FPU (void) sim_fpu_d2 (sim_fpu *f, double d);
 
-
+/* IEEE754-2008 classifiction function.  */
+INLINE_SIM_FPU (int) sim_fpu_classify (const sim_fpu *f);
 
 /* Specific number classes.
 
@@ -367,7 +377,20 @@ INLINE_SIM_FPU (int) sim_fpu_is_ne (const sim_fpu *l, const sim_fpu *r);
 INLINE_SIM_FPU (int) sim_fpu_is_ge (const sim_fpu *l, const sim_fpu *r);
 INLINE_SIM_FPU (int) sim_fpu_is_gt (const sim_fpu *l, const sim_fpu *r);
 
+/* Unordered/ordered comparison operators */
+
+INLINE_SIM_FPU (int) sim_fpu_un (int *is, const sim_fpu *l, const sim_fpu *r);
+INLINE_SIM_FPU (int) sim_fpu_or (int *is, const sim_fpu *l, const sim_fpu *r);
+
+INLINE_SIM_FPU (int) sim_fpu_is_un (const sim_fpu *l, const sim_fpu *r);
+INLINE_SIM_FPU (int) sim_fpu_is_or (const sim_fpu *l, const sim_fpu *r);
+
+/* Changes the behaviour of the library to IEEE754-2008 or IEEE754-1985.
+ * The default for the library is IEEE754-1985. */
 
+INLINE_SIM_FPU (bool) sim_fpu_is_ieee754_1985 (void);
+INLINE_SIM_FPU (bool) sim_fpu_is_ieee754_2008 (void);
+INLINE_SIM_FPU (void) sim_fpu_set_mode (const sim_fpu_mode m);
 
 /* General number class and comparison operators.
 
@@ -411,6 +434,7 @@ extern sim_fpu_state _sim_fpu;
    between pre-R6 and R6 MIPS cores.  */
 
 #define sim_fpu_quiet_nan_inverted _sim_fpu.quiet_nan_inverted
+#define sim_fpu_current_mode _sim_fpu.current_mode
 
 /* A number of useful constants.  */
 
-- 
2.17.1


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

* [PATCH v4 4/4] sim: mips: Add simulator support for mips32r6/mips64r6
  2022-02-01 12:52 [PATCH v4 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
                   ` (2 preceding siblings ...)
  2022-02-01 12:53 ` [PATCH v4 3/4] sim: Add partial support for IEEE 754-2008 Dragan Mladjenovic
@ 2022-02-01 12:53 ` Dragan Mladjenovic
  2022-02-02  3:47   ` Mike Frysinger
  3 siblings, 1 reply; 8+ messages in thread
From: Dragan Mladjenovic @ 2022-02-01 12:53 UTC (permalink / raw)
  To: gdb-patches
  Cc: Mike Frysinger, Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

From: Faraz Shahbazker <fshahbazker@wavecomp.com>

2022-02-01  Ali Lown  <ali.lown@imgtec.com>
	    Andrew Bennett  <andrew.bennett@imgtec.com>
	    Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
	    Faraz Shahbazker  <fshahbazker@wavecomp.com>

sim/common/ChangeLog:
	* sim-bits.h (EXTEND9, EXTEND18 ,EXTEND19, EXTEND21,
	EXTEND26): New macros.

sim/mips/ChangeLog:
	* Makefile.in (IGEN_INCLUDE): Add mips3264r6.igen.
	* configure: Regenerate.
	* configure.ac: Support mipsisa32r6 and mipsisa64r6.
	(sim_engine_run): Pick simulator model from processor specified
	in e_flags.
	* cp1.c (value_fpr): Handle fmt_dc32.
	(fp_unary, fp_binary): Zero initialize locals.
	(update_fcsr, fp_classify, fp_rint, fp_r6_cmp, inner_fmac,
	fp_fmac, fp_min, fp_max, fp_mina, fp_maxa, fp_fmadd, fp_fmsub):
	New functions.
	(sim_fpu_class_mips_mapping): New.
	* cp1.h (fcsr_ABS2008_mask, fcsr_ABS2008_shift): New define.
	* interp.c (MIPSR6_P): New.
	(load_word): Allow unaligned memory access for MIPSR6.
	* micromips.igen (sc, scd): Adapt to new do_sc* helper signature.
	* mips.igen: Add *r6 models.
	(signal_if_cti, forbiddenslot32): New helpers.
	(delayslot32): Use signal_if_cti.
	(do_sc, do_scd); Add store_ll_bit parameter.
	(sc, scd): Adapt to previous change.
	(nal, beq, bal): New definitions for *r6.
	(sll): Split nop and ssnop cases into ...
	(nop, ssnop): New definitions.
	(loadstore_ea): Use the 32-bit compatibility adressing.
	(cache): Split logic into ...
	(do_cache): New helper.
	(check_fpu): Select IEEE 754-2008 mode for R6.
	(not_word_value, unpredictable, check_mt_hilo, check_mf_hilo,
	check_multi_hilo, check_div_hilo, check_u64, do_dmfc1b, add,
	li, addu, and, andi, bgez, bgtz, blez, bltz, bne, break, dadd,
	daddiu, daddu, dror, dror32, drorv, dsll, dsll32, dsllv, dsra,
	dsra32, dsrav, dsrl, dsrl32, dsub, dsubu, j, jal, jalr,
	jalr.hb, lb, lbu, ld, lh, lhu, lui, lw, lwu, nor, or, ori, ror,
	rorv, sb, sd, sh, sll, sllv, slt, slti, sltiu, sltu, sra, srav,
	srl, srlv, sub, subu, sw, sync, syscall, teq, tge, tgeu, tlt,
	tltu, tne, xor, xori, check_fmt_p, do_load_double,
	do_store_double, abs.FMT, add.FMT, ceil.l.FMT, ceil.w.FMT,
	cfc1, ctc1, cvt.d.FMT, cvt.l.FMT, cvt.w.FMT, div.FMT, dfmc1,
	dmtc1, floor.l.FMT, floor.w.FMT, ldc1, lwc1, mfc1, mov.FMT,
	mtc1, mul.FMT, recip.FMT, round.l.FMT, round.w.FMT, rsqrt.FMT,
	sdc1, sqrt.FMT, sub.FMT, swc1, trunc.l.FMT, trunc.w.FMT, bc0f,
	bc0fl, bc0t, bc0tl, dmfc0, dmtc0, eret, mfc0, mtc0, cop, tlbp,
	tlbr, tlbwi, tlbwr): Enable on *r6 models.
	* mips3264r2.igen (dext, dextm, dextu, di, dins, dinsm, dinsu,
	dsbh, dshd, ei, ext, mfhc1, mthc1, ins, seb, seh, synci, rdhwr,
	wsbh): Likewise.
	* mips3264r6.igen: New file.
	* sim-main.h (FP_formats): Add fmt_dc32.
	(FORBIDDEN_SLOT): New macros.
	(simFORBIDDENSLOT, FP_R6CMP_*, FP_R6CLASS_*): New defines.
	(fp_r6_cmp, fp_classify, fp_rint, fp_min, fp_max, fp_mina,
	fp_maxa, fp_fmadd, fp_fmsub): New declarations.
	(R6Compare, Classify, RoundToIntegralExact, Min, Max, MinA,
	MaxA, FusedMultiplyAdd, FusedMultiplySub): New macros. Wrapping
	previous declarations.

sim/testsuite/mips/ChangeLog:
	* basic.exp: Add r6-*.s tests.
	(run_r6_removed_test): New function.
	(run_endian_tests): New function.
	* hilo-hazard-3.s: Skip for mips*r6.
	* r2-fpu.s: New test.
	* r6-64.s: New test.
	* r6-branch.s: New test.
	* r6-forbidden.s: New test.
	* r6-fpu.s: New test.
	* r6-llsc-dp.s: New test.
	* r6-llsc-wp.s: New test.
	* r6-removed.csv: New test.
	* r6-removed.s: New test.
	* r6.s: New test.
	* utils-r6.inc: New inc.
---
 sim/common/sim-bits.h              |    5 +
 sim/mips/Makefile.in               |    1 +
 sim/mips/configure                 |   22 +-
 sim/mips/configure.ac              |   20 +-
 sim/mips/cp1.c                     |  432 +++++++++-
 sim/mips/cp1.h                     |    2 +
 sim/mips/interp.c                  |    6 +-
 sim/mips/micromips.igen            |    4 +-
 sim/mips/mips.igen                 |  380 ++++++++-
 sim/mips/mips3264r2.igen           |   30 +
 sim/mips/mips3264r6.igen           | 1226 ++++++++++++++++++++++++++++
 sim/mips/sim-main.h                |   94 ++-
 sim/testsuite/mips/basic.exp       |   72 +-
 sim/testsuite/mips/hilo-hazard-3.s |    2 +-
 sim/testsuite/mips/r2-fpu.s        |   31 +
 sim/testsuite/mips/r6-64.s         |  157 ++++
 sim/testsuite/mips/r6-branch.s     |  291 +++++++
 sim/testsuite/mips/r6-forbidden.s  |   51 ++
 sim/testsuite/mips/r6-fpu.s        |  446 ++++++++++
 sim/testsuite/mips/r6-llsc-dp.s    |   57 ++
 sim/testsuite/mips/r6-llsc-wp.s    |   41 +
 sim/testsuite/mips/r6-removed.csv  |   68 ++
 sim/testsuite/mips/r6-removed.s    |   18 +
 sim/testsuite/mips/r6.s            |  163 ++++
 sim/testsuite/mips/testutils.inc   |   55 ++
 sim/testsuite/mips/utils-r6.inc    |  150 ++++
 26 files changed, 3750 insertions(+), 74 deletions(-)
 create mode 100644 sim/mips/mips3264r6.igen
 create mode 100644 sim/testsuite/mips/r2-fpu.s
 create mode 100644 sim/testsuite/mips/r6-64.s
 create mode 100644 sim/testsuite/mips/r6-branch.s
 create mode 100644 sim/testsuite/mips/r6-forbidden.s
 create mode 100644 sim/testsuite/mips/r6-fpu.s
 create mode 100644 sim/testsuite/mips/r6-llsc-dp.s
 create mode 100644 sim/testsuite/mips/r6-llsc-wp.s
 create mode 100644 sim/testsuite/mips/r6-removed.csv
 create mode 100644 sim/testsuite/mips/r6-removed.s
 create mode 100644 sim/testsuite/mips/r6.s
 create mode 100644 sim/testsuite/mips/utils-r6.inc

Changes from v3: Use sim_io_error.

diff --git a/sim/common/sim-bits.h b/sim/common/sim-bits.h
index b1352d5a305..fab1dab478c 100644
--- a/sim/common/sim-bits.h
+++ b/sim/common/sim-bits.h
@@ -500,12 +500,17 @@ INLINE_SIM_BITS(unsigned_word) MSINSERTED (unsigned_word val, int start, int sto
 #define EXTEND5(X)  (LSSEXT ((X), 4))
 #define EXTEND6(X)  (LSSEXT ((X), 5))
 #define EXTEND8(X)  ((signed_word)(int8_t)(X))
+#define EXTEND9(X)  (LSSEXT ((X), 8))
 #define EXTEND11(X)  (LSSEXT ((X), 10))
 #define EXTEND12(X)  (LSSEXT ((X), 11))
 #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 EXTEND24(X)  (LSSEXT ((X), 23))
 #define EXTEND25(X)  (LSSEXT ((X), 24))
+#define EXTEND26(X)  (LSSEXT ((X), 25))
 #define EXTEND32(X) ((signed_word)(int32_t)(X))
 #define EXTEND64(X) ((signed_word)(int64_t)(X))
 
diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in
index 5c669279ae6..75438be5a18 100644
--- a/sim/mips/Makefile.in
+++ b/sim/mips/Makefile.in
@@ -98,6 +98,7 @@ IGEN_INCLUDE=\
 	$(srcdir)/dsp.igen \
 	$(srcdir)/dsp2.igen \
 	$(srcdir)/mips3264r2.igen \
+	$(srcdir)/mips3264r6.igen \
 
 # NB:	Since these can be built by a number of generators, care
 #	must be taken to ensure that they are only dependant on
diff --git a/sim/mips/configure b/sim/mips/configure
index 2521ce8638d..956b967a0b6 100755
--- a/sim/mips/configure
+++ b/sim/mips/configure
@@ -1871,7 +1871,8 @@ case "${target}" in
 			sim_gen=MULTI
 			sim_multi_configs="\
 			  micromips:micromips64,micromipsdsp:32,64,f:mips_micromips\
-			  mips64r2:mips64r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,64,f:mipsisa64r2"
+			  mipsisa64r2:mips64r2,mips16,mips16e,mdmx,dsp,dsp2,mips3d,smartmips:32,64,f:mipsisa32r2,mipsisa64r2,mipsisa32r5,mipsisa64r5\
+			  mipsisa64r6:mips64r6:32,64,f:mipsisa32r6,mipsisa64r6"
 			sim_multi_default=mipsisa64r2
 			;;
   mips64*-*-*)		sim_igen_filter="32,64,f"
@@ -1887,6 +1888,11 @@ case "${target}" in
 			  mips32r2:mips32r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,f:mipsisa32r2"
 			sim_multi_default=mipsisa32r2
 			;;
+  mipsisa32r6*-*-*)	sim_gen=IGEN
+			sim_igen_machine="-M mips32r6"
+			sim_igen_filter="32,f"
+			sim_mach_default="mipsisa32r6"
+			;;
   mipsisa32*-*-*)	sim_gen=M16
 			sim_igen_machine="-M mips32,mips16,mips16e,smartmips"
 			sim_m16_machine="-M mips16,mips16e,mips32"
@@ -1899,6 +1905,11 @@ case "${target}" in
 			sim_igen_filter="32,64,f"
 			sim_mach_default="mipsisa64r2"
 			;;
+  mipsisa64r6*-*-*)	sim_gen=IGEN
+			sim_igen_machine="-M mips64r6"
+			sim_igen_filter="32,64,f"
+			sim_mach_default="mipsisa64r6"
+			;;
   mipsisa64sb1*-*-*)	sim_gen=IGEN
 			sim_igen_machine="-M mips64,mips3d,sb1"
 			sim_igen_filter="32,64,f"
@@ -1963,7 +1974,7 @@ if test ${sim_gen} = MULTI; then
 
   cat << __EOF__ > multi-run.c
 /* Main entry point for MULTI simulators.
-   Copyright (C) 2003-2021 Free Software Foundation, Inc.
+   Copyright (C) 2003-2022 Free Software Foundation, Inc.
 
    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
@@ -1985,6 +1996,7 @@ if test ${sim_gen} = MULTI; then
 #include "sim-main.h"
 #include "multi-include.h"
 #include "elf-bfd.h"
+#include "elfxx-mips.h"
 #include "elf/mips.h"
 
 #define SD sd
@@ -2004,7 +2016,11 @@ sim_engine_run (SIM_DESC sd,
 	   & EF_MIPS_ARCH_ASE_MICROMIPS)
     mach = bfd_mach_mips_micromips;
   else
-    mach = STATE_ARCHITECTURE (SD)->mach;
+  {
+     mach = _bfd_elf_mips_mach (elf_elfheader (STATE_PROG_BFD (sd))->e_flags);
+     if (!mach)
+       mach = STATE_ARCHITECTURE (SD)->mach;
+  }
 
   switch (mach)
     {
diff --git a/sim/mips/configure.ac b/sim/mips/configure.ac
index 2ec9f0f9d4f..96806424958 100644
--- a/sim/mips/configure.ac
+++ b/sim/mips/configure.ac
@@ -102,7 +102,8 @@ case "${target}" in
 			sim_gen=MULTI
 			sim_multi_configs="\
 			  micromips:micromips64,micromipsdsp:32,64,f:mips_micromips\
-			  mips64r2:mips64r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,64,f:mipsisa64r2"
+			  mipsisa64r2:mips64r2,mips16,mips16e,mdmx,dsp,dsp2,mips3d,smartmips:32,64,f:mipsisa32r2,mipsisa64r2,mipsisa32r5,mipsisa64r5\
+			  mipsisa64r6:mips64r6:32,64,f:mipsisa32r6,mipsisa64r6"
 			sim_multi_default=mipsisa64r2
 			;;
   mips64*-*-*)		sim_igen_filter="32,64,f"
@@ -118,6 +119,11 @@ case "${target}" in
 			  mips32r2:mips32r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,f:mipsisa32r2"
 			sim_multi_default=mipsisa32r2
 			;;
+  mipsisa32r6*-*-*)	sim_gen=IGEN
+			sim_igen_machine="-M mips32r6"
+			sim_igen_filter="32,f"
+			sim_mach_default="mipsisa32r6"
+			;;
   mipsisa32*-*-*)	sim_gen=M16
 			sim_igen_machine="-M mips32,mips16,mips16e,smartmips"
 			sim_m16_machine="-M mips16,mips16e,mips32"
@@ -130,6 +136,11 @@ case "${target}" in
 			sim_igen_filter="32,64,f"
 			sim_mach_default="mipsisa64r2"
 			;;
+  mipsisa64r6*-*-*)	sim_gen=IGEN
+			sim_igen_machine="-M mips64r6"
+			sim_igen_filter="32,64,f"
+			sim_mach_default="mipsisa64r6"
+			;;
   mipsisa64sb1*-*-*)	sim_gen=IGEN
 			sim_igen_machine="-M mips64,mips3d,sb1"
 			sim_igen_filter="32,64,f"
@@ -216,6 +227,7 @@ if test ${sim_gen} = MULTI; then
 #include "sim-main.h"
 #include "multi-include.h"
 #include "elf-bfd.h"
+#include "elfxx-mips.h"
 #include "elf/mips.h"
 
 #define SD sd
@@ -235,7 +247,11 @@ sim_engine_run (SIM_DESC sd,
 	   & EF_MIPS_ARCH_ASE_MICROMIPS)
     mach = bfd_mach_mips_micromips;
   else
-    mach = STATE_ARCHITECTURE (SD)->mach;
+  {
+     mach = _bfd_elf_mips_mach (elf_elfheader (STATE_PROG_BFD (sd))->e_flags);
+     if (!mach)
+       mach = STATE_ARCHITECTURE (SD)->mach;
+  }
 
   switch (mach)
     {
diff --git a/sim/mips/cp1.c b/sim/mips/cp1.c
index a6d1b56fdb7..22d18ae8cf0 100644
--- a/sim/mips/cp1.c
+++ b/sim/mips/cp1.c
@@ -100,6 +100,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #define FPQNaN_LONG     (UNSIGNED64 (0x7FFFFFFFFFFFFFFF))
 #define FPQNaN_PS       (FP_PS_cat (FPQNaN_SINGLE, FPQNaN_SINGLE))
 
+static void update_fcsr (sim_cpu *, address_word , sim_fpu_status);
+
 static const char *fpu_format_name (FP_formats fmt);
 #ifdef DEBUG
 static const char *fpu_rounding_mode_name (int rm);
@@ -127,7 +129,7 @@ value_fpr (sim_cpu *cpu,
     }
 
   /* For values not yet accessed, set to the desired format.  */
-  if (fmt < fmt_uninterpreted)
+  if (fmt < fmt_uninterpreted && fmt != fmt_dc32)
     {
       if (FPR_STATE[fpr] == fmt_uninterpreted)
 	{
@@ -137,7 +139,10 @@ value_fpr (sim_cpu *cpu,
 		  fpu_format_name (fmt));
 #endif /* DEBUG */
 	}
-      else if (fmt != FPR_STATE[fpr])
+      else if (fmt != FPR_STATE[fpr]
+	       && !(fmt == fmt_single
+		    && FPR_STATE[fpr] == fmt_double
+		    && (FGR[fpr] == 0 || FGR[fpr] == 0xFFFFFFFF)))
 	{
 	  sim_io_eprintf (SD, "FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",
 			  fpr, fpu_format_name (FPR_STATE[fpr]),
@@ -166,6 +171,7 @@ value_fpr (sim_cpu *cpu,
 	case fmt_uninterpreted_32:
 	case fmt_single:
 	case fmt_word:
+	case fmt_dc32:
 	  value = (FGR[fpr] & 0xFFFFFFFF);
 	  break;
 
@@ -557,8 +563,8 @@ fp_test(uint64_t op1,
 
   if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
     {
-      if ((cond & (1 << 3)) ||
-	  sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
+      if ((cond & (1 << 3))
+	  || sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
 	status = sim_fpu_status_invalid_snan;
       less = 0;
       equal = 0;
@@ -581,6 +587,110 @@ fp_test(uint64_t op1,
   return status;
 }
 
+static const int sim_fpu_class_mips_mapping[] = {
+	FP_R6CLASS_SNAN, /* SIM_FPU_IS_SNAN = 1, Noisy not-a-number */
+	FP_R6CLASS_QNAN, /* SIM_FPU_IS_QNAN = 2, Quiet not-a-number */
+	FP_R6CLASS_NEGINF, /* SIM_FPU_IS_NINF = 3, -infinity */
+	FP_R6CLASS_POSINF, /* SIM_FPU_IS_PINF = 4, +infinity */
+	FP_R6CLASS_NEGNORM, /* SIM_FPU_IS_NNUMBER = 5, -num - [-MAX .. -MIN] */
+	FP_R6CLASS_POSNORM, /* SIM_FPU_IS_PNUMBER = 6, +num - [+MIN .. +MAX] */
+	FP_R6CLASS_NEGSUB, /* SIM_FPU_IS_NDENORM = 7, -denorm - (MIN .. 0) */
+	FP_R6CLASS_POSSUB, /* SIM_FPU_IS_PDENORM = 8, +denorm - (0 .. MIN) */
+	FP_R6CLASS_NEGZERO, /* SIM_FPU_IS_NZERO = 9, -0 */
+	FP_R6CLASS_POSZERO /* SIM_FPU_IS_PZERO = 10, +0 */
+};
+
+uint64_t
+fp_classify (sim_cpu *cpu,
+	     address_word cia,
+	     uint64_t op,
+	     FP_formats fmt)
+{
+  sim_fpu wop;
+
+  /* The format type has already been checked:  */
+  switch (fmt)
+    {
+    case fmt_single:
+      sim_fpu_32to (&wop, op);
+      break;
+    case fmt_double:
+      sim_fpu_64to (&wop, op);
+      break;
+    default:
+      sim_io_error (SD, "Bad switch\n");
+    }
+  return sim_fpu_class_mips_mapping[sim_fpu_classify (&wop) - 1];
+}
+
+int
+fp_rint (sim_cpu *cpu,
+	 address_word cia,
+	 uint64_t op,
+	 uint64_t *ans,
+	 FP_formats fmt)
+{
+  sim_fpu wop = {0}, wtemp = {0}, wmagic = {0}, wans = {0};
+  int64_t intermediate;
+  int status = 0;
+  sim_fpu_round round = rounding_mode (GETRM());
+
+  switch (fmt)
+    {
+    case fmt_single:
+      sim_fpu_32to (&wop, op);
+      sim_fpu_32to (&wmagic, 0x4b000000);
+      break;
+    case fmt_double:
+      sim_fpu_64to (&wop, op);
+      sim_fpu_64to (&wmagic, 0x4330000000000000);
+      break;
+    default:
+      sim_io_error (SD, "Bad switch\n");
+    }
+
+  if (sim_fpu_is_nan (&wop) || sim_fpu_is_infinity (&wop))
+    {
+      status = sim_fpu_status_invalid_cvi;
+      update_fcsr (cpu, cia, status);
+      return status;
+    }
+
+  switch (fmt)
+    {
+    case fmt_single:
+      if (sim_fpu_is_ge (&wop, &wmagic))
+	wans = wop;
+      else
+	{
+	  sim_fpu_add (&wtemp, &wop, &wmagic);
+	  sim_fpu_round_32 (&wtemp, round, sim_fpu_denorm_default);
+	  sim_fpu_sub (&wans, &wtemp, &wmagic);
+	}
+      sim_fpu_to32 ((uint32_t *) ans, &wans);
+      break;
+    case fmt_double:
+      if (sim_fpu_is_ge (&wop, &wmagic))
+	wans = wop;
+      else
+	{
+	  sim_fpu_add (&wtemp, &wop, &wmagic);
+	  sim_fpu_round_64 (&wtemp, round, sim_fpu_denorm_default);
+	  sim_fpu_sub (&wans, &wtemp, &wmagic);
+	}
+      sim_fpu_to64 (ans, &wans);
+      break;
+    default:
+      sim_io_error (SD, "Bad switch\n");
+    }
+
+  if (*ans != op && status == 0)
+    status = sim_fpu_status_inexact;
+
+  update_fcsr (cpu, cia, status);
+  return status;
+}
+
 void
 fp_cmp(sim_cpu *cpu,
        address_word cia,
@@ -620,11 +730,91 @@ fp_cmp(sim_cpu *cpu,
 	break;
       }
     default:
-      sim_io_eprintf (SD, "Bad switch\n");
-      abort ();
+      sim_io_error (SD, "Bad switch\n");
     }
 }
 
+uint64_t
+fp_r6_cmp (sim_cpu *cpu,
+	   address_word cia,
+	   uint64_t op1,
+	   uint64_t op2,
+	   FP_formats fmt,
+	   int cond)
+{
+  sim_fpu wop1, wop2;
+  int result = 0;
+  int signalling = cond & 0x8;
+
+  switch (fmt)
+    {
+    case fmt_single:
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      break;
+    case fmt_double:
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      break;
+    default:
+      sim_io_error (SD, "Bad switch\n");
+    }
+
+  switch (cond)
+    {
+    case FP_R6CMP_AF:
+      result = 0;
+      break;
+    case FP_R6CMP_UN:
+      result = sim_fpu_is_un (&wop1, &wop2);
+      break;
+    case FP_R6CMP_OR:
+      result = sim_fpu_is_or (&wop1, &wop2);
+      break;
+    case FP_R6CMP_EQ:
+      result = sim_fpu_is_eq (&wop1, &wop2);
+      break;
+    case FP_R6CMP_NE:
+      result = sim_fpu_is_ne (&wop1, &wop2);
+      break;
+    case FP_R6CMP_LT:
+      result = sim_fpu_is_lt (&wop1, &wop2);
+      break;
+    case FP_R6CMP_LE:
+      result = sim_fpu_is_le (&wop1, &wop2);
+      break;
+    case FP_R6CMP_UEQ:
+      result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_eq (&wop1, &wop2);
+      break;
+    case FP_R6CMP_UNE:
+      result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_ne (&wop1, &wop2);
+      break;
+    case FP_R6CMP_ULT:
+      result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_lt (&wop1, &wop2);
+      break;
+    case FP_R6CMP_ULE:
+      result = sim_fpu_is_un (&wop1, &wop2) || sim_fpu_is_le (&wop1, &wop2);
+      break;
+    default:
+      update_fcsr (cpu, cia, sim_fpu_status_invalid_cmp);
+      break;
+    }
+
+  if (result)
+    {
+      switch (fmt)
+	{
+	case fmt_single:
+	  return 0xFFFFFFFF;
+	case fmt_double:
+	  return 0xFFFFFFFFFFFFFFFF;
+	default:
+	  sim_io_error (SD, "Bad switch\n");
+	}
+     }
+   else
+     return 0;
+}
 
 /* Basic arithmetic operations.  */
 
@@ -635,7 +825,7 @@ fp_unary(sim_cpu *cpu,
 	 uint64_t op,
 	 FP_formats fmt)
 {
-  sim_fpu wop;
+  sim_fpu wop = {0};
   sim_fpu ans;
   sim_fpu_round round = rounding_mode (GETRM());
   sim_fpu_denorm denorm = denorm_mode (cpu);
@@ -680,8 +870,7 @@ fp_unary(sim_cpu *cpu,
 	break;
       }
     default:
-      sim_io_eprintf (SD, "Bad switch\n");
-      abort ();
+      sim_io_error (SD, "Bad switch\n");
     }
 
   update_fcsr (cpu, cia, status);
@@ -696,9 +885,9 @@ fp_binary(sim_cpu *cpu,
 	  uint64_t op2,
 	  FP_formats fmt)
 {
-  sim_fpu wop1;
-  sim_fpu wop2;
-  sim_fpu ans;
+  sim_fpu wop1 = {0};
+  sim_fpu wop2 = {0};
+  sim_fpu ans  = {0};
   sim_fpu_round round = rounding_mode (GETRM());
   sim_fpu_denorm denorm = denorm_mode (cpu);
   sim_fpu_status status = 0;
@@ -746,8 +935,7 @@ fp_binary(sim_cpu *cpu,
 	break;
       }
     default:
-      sim_io_eprintf (SD, "Bad switch\n");
-      abort ();
+      sim_io_error (SD, "Bad switch\n");
     }
 
   update_fcsr (cpu, cia, status);
@@ -786,7 +974,7 @@ inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
 	  ans.normal_exp += scale;
 	status |= sim_fpu_round_32 (&ans, round, denorm);
 	wop1 = ans;
-        op_status = 0;
+	op_status = 0;
 	sim_fpu_32to (&wop2, op3);
 	op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
 	op_status |= sim_fpu_round_32 (&ans, round, denorm);
@@ -812,7 +1000,7 @@ inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
 	  ans.normal_exp += scale;
 	status |= sim_fpu_round_64 (&ans, round, denorm);
 	wop1 = ans;
-        op_status = 0;
+	op_status = 0;
 	sim_fpu_64to (&wop2, op3);
 	op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2);
 	op_status |= sim_fpu_round_64 (&ans, round, denorm);
@@ -881,8 +1069,90 @@ fp_mac(sim_cpu *cpu,
 	break;
       }
     default:
-      sim_io_eprintf (SD, "Bad switch\n");
+      sim_io_error (SD, "Bad switch\n");
+    }
+
+  update_fcsr (cpu, cia, status);
+  return result;
+}
+
+/* Common FMAC code for .s, .d. Defers setting FCSR to caller. */
+static sim_fpu_status
+inner_fmac (int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),
+	    uint64_t op1,
+	    uint64_t op2,
+	    uint64_t op3,
+	    sim_fpu_round round,
+	    sim_fpu_denorm denorm,
+	    FP_formats fmt,
+	    uint64_t *result)
+{
+  sim_fpu wop1, wop2, ans;
+  sim_fpu_status status = 0;
+  sim_fpu_status op_status;
+  uint32_t t32 = 0;
+  uint64_t t64 = 0;
+
+  switch (fmt)
+    {
+    case fmt_single:
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      status |= sim_fpu_mul (&ans, &wop1, &wop2);
+      wop1 = ans;
+      op_status = 0;
+      sim_fpu_32to (&wop2, op3);
+      op_status |= (*sim_fpu_op) (&ans, &wop2, &wop1);
+      op_status |= sim_fpu_round_32 (&ans, round, denorm);
+      status |= op_status;
+      sim_fpu_to32 (&t32, &ans);
+      t64 = t32;
+      break;
+    case fmt_double:
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      status |= sim_fpu_mul (&ans, &wop1, &wop2);
+      wop1 = ans;
+      op_status = 0;
+      sim_fpu_64to (&wop2, op3);
+      op_status |= (*sim_fpu_op) (&ans, &wop2, &wop1);
+      op_status |= sim_fpu_round_64 (&ans, round, denorm);
+      status |= op_status;
+      sim_fpu_to64 (&t64, &ans);
+      break;
+    default:
+      fprintf (stderr, "Bad switch\n");
       abort ();
+      break;
+    }
+
+  *result = t64;
+  return status;
+}
+
+static uint64_t
+fp_fmac (sim_cpu *cpu,
+	 address_word cia,
+	 int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),
+	 uint64_t op1,
+	 uint64_t op2,
+	 uint64_t op3,
+	 FP_formats fmt)
+{
+  sim_fpu_round round = rounding_mode (GETRM());
+  sim_fpu_denorm denorm = denorm_mode (cpu);
+  sim_fpu_status status = 0;
+  uint64_t result = 0;
+
+  switch (fmt)
+    {
+    case fmt_single:
+    case fmt_double:
+      status = inner_fmac (sim_fpu_op, op1, op2, op3, round,
+			   denorm, fmt, &result);
+      break;
+    default:
+      sim_io_error (SD, "Bad switch\n");
     }
 
   update_fcsr (cpu, cia, status);
@@ -972,8 +1242,7 @@ fp_inv_sqrt(sim_cpu *cpu,
 	break;
       }
     default:
-      sim_io_eprintf (SD, "Bad switch\n");
-      abort ();
+      sim_io_error (SD, "Bad switch\n");
     }
 
   update_fcsr (cpu, cia, status);
@@ -1039,6 +1308,94 @@ fp_div(sim_cpu *cpu,
   return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
 }
 
+uint64_t
+fp_min (sim_cpu *cpu,
+	address_word cia,
+	uint64_t op1,
+	uint64_t op2,
+	FP_formats fmt)
+{
+  return fp_binary (cpu, cia, &sim_fpu_min, op1, op2, fmt);
+}
+
+uint64_t
+fp_max (sim_cpu *cpu,
+	address_word cia,
+	uint64_t op1,
+	uint64_t op2,
+	FP_formats fmt)
+{
+  return fp_binary (cpu, cia, &sim_fpu_max, op1, op2, fmt);
+}
+
+uint64_t
+fp_mina (sim_cpu *cpu,
+	 address_word cia,
+	 uint64_t op1,
+	 uint64_t op2,
+	 FP_formats fmt)
+{
+  uint64_t ret;
+  sim_fpu wop1 = {0}, wop2 = {0}, waop1, waop2, wans;
+  sim_fpu_status status = 0;
+
+  switch (fmt)
+    {
+    case fmt_single:
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      break;
+    case fmt_double:
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      break;
+    default:
+      sim_io_error (SD, "Bad switch\n");
+    }
+
+  status |= sim_fpu_abs (&waop1, &wop1);
+  status |= sim_fpu_abs (&waop2, &wop2);
+  status |= sim_fpu_min (&wans, &waop1, &waop2);
+  ret = (sim_fpu_is_eq (&wans, &waop1)) ? op1 : op2;
+
+  update_fcsr (cpu, cia, status);
+  return ret;
+}
+
+uint64_t
+fp_maxa (sim_cpu *cpu,
+	 address_word cia,
+	 uint64_t op1,
+	 uint64_t op2,
+	 FP_formats fmt)
+{
+  uint64_t ret;
+  sim_fpu wop1 = {0}, wop2 = {0}, waop1, waop2, wans;
+  sim_fpu_status status = 0;
+
+  switch (fmt)
+    {
+    case fmt_single:
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      break;
+    case fmt_double:
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      break;
+    default:
+      sim_io_error (SD, "Bad switch\n");
+    }
+
+  status |= sim_fpu_abs (&waop1, &wop1);
+  status |= sim_fpu_abs (&waop2, &wop2);
+  status |= sim_fpu_max (&wans, &waop1, &waop2);
+  ret = (sim_fpu_is_eq (&wans, &waop1)) ? op1 : op2;
+
+  update_fcsr (cpu, cia, status);
+  return ret;
+}
+
 uint64_t
 fp_recip(sim_cpu *cpu,
          address_word cia,
@@ -1088,6 +1445,28 @@ fp_msub(sim_cpu *cpu,
   return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 0, fmt);
 }
 
+uint64_t
+fp_fmadd (sim_cpu *cpu,
+          address_word cia,
+          uint64_t op1,
+          uint64_t op2,
+          uint64_t op3,
+          FP_formats fmt)
+{
+  return fp_fmac (cpu, cia, &sim_fpu_add, op1, op2, op3, fmt);
+}
+
+uint64_t
+fp_fmsub (sim_cpu *cpu,
+          address_word cia,
+          uint64_t op1,
+          uint64_t op2,
+          uint64_t op3,
+          FP_formats fmt)
+{
+  return fp_fmac (cpu, cia, &sim_fpu_sub, op1, op2, op3, fmt);
+}
+
 uint64_t
 fp_nmadd(sim_cpu *cpu,
          address_word cia,
@@ -1394,8 +1773,7 @@ convert (sim_cpu *cpu,
       status = sim_fpu_i64to (&wop, op, round);
       break;
     default:
-      sim_io_eprintf (SD, "Bad switch\n");
-      abort ();
+      sim_io_error (SD, "Bad switch\n");
     }
 
   /* Convert sim_fpu format into the output */
@@ -1430,8 +1808,7 @@ convert (sim_cpu *cpu,
       break;
     default:
       result64 = 0;
-      sim_io_eprintf (SD, "Bad switch\n");
-      abort ();
+      sim_io_error (SD, "Bad switch\n");
     }
 
   update_fcsr (cpu, cia, status);
@@ -1481,8 +1858,7 @@ pack_ps(sim_cpu *cpu,
 	break;
       }
     default:
-      sim_io_eprintf (SD, "Bad switch\n");
-      abort ();
+      sim_io_error (SD, "Bad switch\n");
     }
 
   return result;
@@ -1517,8 +1893,7 @@ convert_ps (sim_cpu *cpu,
       sim_fpu_32to (&wop_l, FP_PS_lower(op));
       break;
     default:
-      sim_io_eprintf (SD, "Bad switch\n");
-      abort ();
+      sim_io_error (SD, "Bad switch\n");
     }
 
   /* Convert sim_fpu format into the output */
@@ -1538,8 +1913,7 @@ convert_ps (sim_cpu *cpu,
       break;
     default:
       result = 0;
-      sim_io_eprintf (SD, "Bad switch\n");
-      abort ();
+      sim_io_error (SD, "Bad switch\n");
     }
 
   update_fcsr (cpu, cia, status_u | status_l);
diff --git a/sim/mips/cp1.h b/sim/mips/cp1.h
index d6d8a8874fd..5622b9384d9 100644
--- a/sim/mips/cp1.h
+++ b/sim/mips/cp1.h
@@ -43,6 +43,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 /* FCSR bits for IEEE754-2008 compliance.  */
 #define fcsr_NAN2008_mask       (0x00040000)
 #define fcsr_NAN2008_shift      (18)
+#define fcsr_ABS2008_mask       (0x00080000)
+#define fcsr_ABS2008_shift      (19)
 
 #define fenr_FS            (0x00000004)
 
diff --git a/sim/mips/interp.c b/sim/mips/interp.c
index 65015623ee5..c5d0901428b 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -1549,6 +1549,10 @@ store_word (SIM_DESC sd,
     }
 }
 
+#define MIPSR6_P(abfd) \
+  ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6 \
+    || (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_64R6)
+
 /* Load a word from memory.  */
 
 static signed_word
@@ -1557,7 +1561,7 @@ load_word (SIM_DESC sd,
 	   address_word cia,
 	   uword64 vaddr)
 {
-  if ((vaddr & 3) != 0)
+  if ((vaddr & 3) != 0 && !MIPSR6_P (STATE_PROG_BFD (sd)))
     {
       SIM_CORE_SIGNAL (SD, cpu, cia, read_map, AccessLength_WORD+1, vaddr, read_transfer, sim_core_unaligned_signal);
     }
diff --git a/sim/mips/micromips.igen b/sim/mips/micromips.igen
index acbff6f2db2..bb61b3f26e6 100644
--- a/sim/mips/micromips.igen
+++ b/sim/mips/micromips.igen
@@ -1761,7 +1761,7 @@
 *micromips32:
 *micromips64:
 {
-  do_sc (SD_, RT, EXTEND12 (IMMEDIATE), BASE, instruction_0);
+  do_sc (SD_, RT, EXTEND12 (IMMEDIATE), BASE, instruction_0, 1);
 }
 
 
@@ -3074,7 +3074,7 @@
 *micromips64:
 {
   check_u64 (SD_, instruction_0);
-  do_scd (SD_, RT, OFFSET, BASE);
+  do_scd (SD_, RT, OFFSET, BASE, 1);
 }
 
 110110,5.RT,5.BASE,16.OFFSET:MICROMIPS64:64::SD
diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen
index b0c5e5995af..dfad4227615 100644
--- a/sim/mips/mips.igen
+++ b/sim/mips/mips.igen
@@ -46,8 +46,10 @@
 :model:::mipsV:mipsisaV:
 :model:::mips32:mipsisa32:
 :model:::mips32r2:mipsisa32r2:
+:model:::mips32r6:mipsisa32r6:
 :model:::mips64:mipsisa64:
 :model:::mips64r2:mipsisa64r2:
+:model:::mips64r6:mipsisa64r6:
 
 //  Vendor ISAs:
 //
@@ -102,7 +104,28 @@
 
 
 
-// Helper:
+// Helpers:
+//
+// Check if given instruction is CTI, if so signal
+//
+:function:::void:signal_if_cti:instruction_word instr
+{
+  uint32_t maj = (instr & 0xfc000000) >> 26;
+  uint32_t special = instr & 0x3f;
+  if ((maj & 0x3e) == 0x06 /* Branch/Jump */
+      || ((maj & 0x38) == 0 && !((maj & 0x6) == 0))
+      || maj == 0x18
+      || (maj & 0x37) == 0x32
+      || (maj & 0x37) == 0x36
+      || ((maj == 0) && (special == 0x9))
+      /* DERET/ERET/WAIT */
+      || ((maj == 0x10) && (instr & 0x02000000)
+	  && (special == 0x1f || special == 0x18 || special == 0x20)))
+    {
+      SignalException (ReservedInstruction, instr);
+    }
+}
+
 //
 // Simulate a 32 bit delayslot instruction
 //
@@ -115,12 +138,34 @@
   CIA = CIA + 4; /* NOTE not mips16 */
   STATE |= simDELAYSLOT;
   delay_insn = IMEM32 (CIA); /* NOTE not mips16 */
+  signal_if_cti (SD_, delay_insn);
   ENGINE_ISSUE_PREFIX_HOOK();
   idecode_issue (CPU_, delay_insn, (CIA));
   STATE &= ~simDELAYSLOT;
   return target;
 }
 
+//
+// Simulate a 32 bit forbidden slot instruction
+//
+
+:function:::address_word:forbiddenslot32:
+*mips32r6:
+*mips64r6:
+{
+  instruction_word delay_insn;
+  sim_events_slip (SD, 1);
+  DSPC = CIA;
+  CIA = CIA + 4;
+  STATE |= simFORBIDDENSLOT;
+  delay_insn = IMEM32 (CIA);
+  signal_if_cti (SD_, delay_insn);
+  ENGINE_ISSUE_PREFIX_HOOK ();
+  idecode_issue (CPU_, delay_insn, (CIA));
+  STATE &= ~simFORBIDDENSLOT;
+  return CIA + 4;
+}
+
 :function:::address_word:nullify_next_insn32:
 {
   sim_events_slip (SD, 1);
@@ -142,6 +187,7 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -154,6 +200,7 @@
 *mips64:
 *mips64r2:
 *micromips64:
+*mips64r6:
 {
 #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
@@ -184,10 +231,12 @@
 *r3900:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
 *micromips32:
 *micromips64:
+*mips64r6:
 {
 #if WITH_TARGET_WORD_BITSIZE == 64
   return value != (((value & 0xffffffff) ^ 0x80000000) - 0x80000000);
@@ -219,10 +268,12 @@
 :function:::void:unpredictable:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
 *micromips32:
 *micromips64:
+*mips64r6:
 {
   unpredictable_action (CPU, CIA);
 }
@@ -311,8 +362,10 @@
 :function:::int:check_mt_hilo:hilo_history *history
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *r3900:
 *micromips32:
 *micromips64:
@@ -337,8 +390,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -411,8 +466,10 @@
 :function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *r3900:
 *micromips32:
 *micromips64:
@@ -468,10 +525,12 @@
 :function:::int:check_div_hilo:hilo_history *hi, hilo_history *lo
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
 *micromips32:
 *micromips64:
+*mips64r6:
 {
   int64_t time = sim_events_time (SD);
   hi->op.timestamp = time;
@@ -507,8 +566,10 @@
 *mips64r2:
 *mips32:
 *mips32r2:
+*mips32r6:
 *micromips64:
 *micromips32:
+*mips64r6:
 {
 #if 0 /* XXX FIXME: enable this only after some additional testing.  */
   if (UserMode && (SR & (status_UX|status_PX)) == 0)
@@ -1081,7 +1142,7 @@
   }
 }
 
-:function:::void:do_sc:int rt, int offsetarg, int basereg, address_word instruction_0
+:function:::void:do_sc:int rt, int offsetarg, int basereg, address_word instruction_0, int store_ll_bit
 {
   uint32_t instruction = instruction_0;
   address_word base = GPR[basereg];
@@ -1111,12 +1172,13 @@
 	if (LLBIT)
 	  StoreMemory (AccessLength_WORD, memval, memval1, paddr, vaddr,
 		        isREAL);
-	GPR[rt] = LLBIT;
+	if (store_ll_bit)
+	  GPR[rt] = LLBIT;
       }
   }
 }
 
-:function:::void:do_scd:int rt, int roffset, int rbase
+:function:::void:do_scd:int rt, int roffset, int rbase, int store_ll_bit
 {
   address_word base = GPR[rbase];
   address_word offset = EXTEND16 (roffset);
@@ -1137,7 +1199,8 @@
 	if (LLBIT)
 	  StoreMemory (AccessLength_DOUBLEWORD, memval, memval1, paddr, vaddr,
 		       isREAL);
-	GPR[rt] = LLBIT;
+	if (store_ll_bit)
+	  GPR[rt] = LLBIT;
       }
   }
 }
@@ -1376,6 +1439,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1633,6 +1697,7 @@
 *mipsII:
 *mips32:
 *mips32r2:
+*mips32r6:
 *micromips32:
 {
   check_fpu (SD_);
@@ -1763,8 +1828,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1812,8 +1879,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1841,8 +1910,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1868,8 +1939,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1888,8 +1961,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1922,6 +1997,17 @@
 }
 
 
+000100,5.RS,5.RT,16.OFFSET:R6:32::BEQ
+"beq r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  address_word offset = EXTEND16 (OFFSET) << 2;
+  if (GPR[RS] == GPR[RT])
+    DELAY_SLOT (NIA  + offset);
+  else
+    FORBIDDEN_SLOT ();
+}
 
 010100,5.RS,5.RT,16.OFFSET:NORMAL:32::BEQL
 "beql r<RS>, r<RT>, <OFFSET>"
@@ -1957,8 +2043,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1997,7 +2085,15 @@
     }
 }
 
-
+000001,00000,10001,16.OFFSET:REGIMM:32::BAL
+"bal <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  address_word offset = EXTEND16 (OFFSET) << 2;
+  RA = (CIA + 8);
+  DELAY_SLOT (NIA + offset);
+}
 
 000001,5.RS!31,10011,16.OFFSET:REGIMM:32::BGEZALL
 "bgezall r<RS>, <OFFSET>"
@@ -2063,8 +2159,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2114,8 +2212,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2165,8 +2265,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2209,6 +2311,18 @@
 
 
 
+000001,00000,10000,16.OFFSET:REGIMM:32::NAL
+"nal <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  address_word offset = EXTEND16 (OFFSET) << 2;
+  RA = (CIA + 8);
+  FORBIDDEN_SLOT ();
+}
+
+
+
 000001,5.RS!31,10010,16.OFFSET:REGIMM:32::BLTZALL
 "bltzall r<RS>, <OFFSET>"
 *mipsII:
@@ -2273,8 +2387,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2322,8 +2438,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2370,6 +2488,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2409,6 +2528,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2432,6 +2552,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2450,6 +2571,8 @@
   if (RT != RD)
     Unpredictable ();
   check_u64 (SD_, instruction_0);
+  if (RT != RD)
+    Unpredictable ();
   do_dclo (SD_, RD, RS);
 }
 
@@ -2464,6 +2587,8 @@
   if (RT != RD)
     Unpredictable ();
   check_u64 (SD_, instruction_0);
+  if (RT != RD)
+    Unpredictable ();
   do_dclz (SD_, RD, RS);
 }
 
@@ -2771,6 +2896,7 @@
 000000,00001,5.RT,5.RD,5.SHIFT,111010::64::DROR
 "dror r<RD>, r<RT>, <SHIFT>"
 *mips64r2:
+*mips64r6:
 *vr5400:
 *vr5500:
 {
@@ -2781,6 +2907,7 @@
 000000,00001,5.RT,5.RD,5.SHIFT,111110::64::DROR32
 "dror32 r<RD>, r<RT>, <SHIFT>"
 *mips64r2:
+*mips64r6:
 *vr5400:
 *vr5500:
 {
@@ -2791,6 +2918,7 @@
 000000,5.RS,5.RT,5.RD,00001,010110::64::DRORV
 "drorv r<RD>, r<RT>, r<RS>"
 *mips64r2:
+*mips64r6:
 *vr5400:
 *vr5500:
 {
@@ -2813,6 +2941,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2828,6 +2957,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2850,6 +2980,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2872,6 +3003,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2887,6 +3019,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2910,6 +3043,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2932,6 +3066,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2947,6 +3082,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2972,6 +3108,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2987,6 +3124,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3009,6 +3147,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3026,8 +3165,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3048,8 +3189,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3071,8 +3214,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3086,7 +3231,9 @@
 "jalr.hb r<RS>":RD == 31
 "jalr.hb r<RD>, r<RS>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   address_word temp = GPR[RS];
   GPR[RD] = CIA + 8;
@@ -3102,8 +3249,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3114,7 +3263,9 @@
 000000,5.RS,0000000000,10000,001000:SPECIAL:32::JR_HB
 "jr.hb r<RS>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   DELAY_SLOT (GPR[RS]);
 }
@@ -3232,8 +3383,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3251,8 +3404,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3268,6 +3423,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3335,8 +3491,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3354,8 +3512,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3405,8 +3565,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3424,8 +3586,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3498,6 +3662,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3882,8 +4047,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3908,8 +4075,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3935,8 +4104,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3973,7 +4144,9 @@
 000000,00001,5.RT,5.RD,5.SHIFT,000010::32::ROR
 "ror r<RD>, r<RT>, <SHIFT>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 *smartmips:
 *vr5400:
 *vr5500:
@@ -3984,7 +4157,9 @@
 000000,5.RS,5.RT,5.RD,00001,000110::32::RORV
 "rorv r<RD>, r<RT>, r<RS>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 *smartmips:
 *vr5400:
 *vr5500:
@@ -4086,8 +4261,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4109,7 +4286,7 @@
 *vr4100:
 *vr5000:
 {
-  do_sc (SD_, RT, OFFSET, BASE, instruction_0);
+  do_sc (SD_, RT, OFFSET, BASE, instruction_0, 1);
 }
 
 
@@ -4124,7 +4301,7 @@
 *vr5000:
 {
   check_u64 (SD_, instruction_0);
-  do_scd (SD_, RT, OFFSET, BASE);
+  do_scd (SD_, RT, OFFSET, BASE, 1);
 }
 
 
@@ -4135,6 +4312,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4200,8 +4378,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4239,16 +4419,16 @@
 000000,00000,5.RT,5.RD,5.SHIFT,000000:SPECIAL:32::SLLb
 "nop":RD == 0 && RT == 0 && SHIFT == 0
 "ssnop":RD == 0 && RT == 0 && SHIFT == 1
+"ehb":RD == 0 && RT == 0 && SHIFT == 3
 "sll r<RD>, r<RT>, <SHIFT>"
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
-  /* Skip shift for NOP and SSNOP, so that there won't be lots of
-     extraneous trace output.  */
-  if (RD != 0 || RT != 0 || (SHIFT != 0 && SHIFT != 1))
-    do_sll (SD_, RT, RD, SHIFT);
+  do_sll (SD_, RT, RD, SHIFT);
 }
 
 
@@ -4270,8 +4450,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4296,8 +4478,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4322,8 +4506,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4348,8 +4534,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4375,8 +4563,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4404,8 +4594,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4435,8 +4627,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4465,8 +4659,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4495,8 +4691,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4514,8 +4712,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4542,8 +4742,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4561,8 +4763,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *r3900:
 *vr5000:
@@ -4637,8 +4841,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4656,8 +4862,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4674,8 +4882,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4708,8 +4918,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4759,8 +4971,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4776,8 +4990,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4827,8 +5043,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4844,8 +5062,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4886,8 +5106,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4912,8 +5134,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4996,6 +5220,8 @@
 *mipsIII:
 *mipsIV:
 *mips32:
+*mips32r6:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5051,10 +5277,27 @@
   if (! COP_Usable (1))
     SignalExceptionCoProcessorUnusable (1);
 
-  FCSR &= ~fcsr_NAN2008_mask;
+  FCSR &= ~(fcsr_NAN2008_mask | fcsr_ABS2008_mask);
   sim_fpu_quiet_nan_inverted = true;
 }
 
+// Helper:
+//
+// Check that the FPU is currently usable, and signal a CoProcessorUnusable
+// exception if not.
+//
+
+:function:::void:check_fpu:
+*mips32r6:
+*mips64r6:
+{
+  if (! COP_Usable (1))
+    SignalExceptionCoProcessorUnusable (1);
+
+  FCSR |= (fcsr_NAN2008_mask | fcsr_ABS2008_mask);
+  sim_fpu_quiet_nan_inverted = 0;
+  sim_fpu_set_mode (sim_fpu_ieee754_2008);
+}
 
 // Helper:
 //
@@ -5067,6 +5310,7 @@
 *mipsII:
 *mips32:
 *mips32r2:
+*mips32r6:
 *micromips32:
 {
   int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian);
@@ -5102,6 +5346,7 @@
 *mips32:
 *mips32r2:
 *micromips32:
+ *mips32r6:
 {
   int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian);
   address_word vaddr;
@@ -5131,8 +5376,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5151,8 +5398,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5263,8 +5512,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5281,8 +5532,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5328,8 +5581,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   do_cfc1 (SD_, RT, FS);
 }
@@ -5365,8 +5620,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   do_ctc1 (SD_, RT, FS);
 }
@@ -5384,8 +5641,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5400,8 +5659,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5433,8 +5694,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5474,8 +5737,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5493,8 +5758,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5526,6 +5793,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5561,6 +5829,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5577,8 +5846,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5595,8 +5866,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5610,6 +5883,7 @@
 *mipsII:
 *mips32:
 *mips32r2:
+*mips32r6:
 {
   check_fpu (SD_);
   COP_LD (1, FT, do_load_double (SD_, GPR[BASE], EXTEND16 (OFFSET)));
@@ -5623,6 +5897,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5684,8 +5959,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5740,8 +6017,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5759,8 +6038,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5869,8 +6150,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5888,8 +6171,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5907,8 +6192,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6005,8 +6292,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr5000:
 {
   do_recip_fmt (SD_, FMT, FD, FS);
@@ -6019,8 +6308,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6037,8 +6328,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6052,8 +6345,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr5000:
 {
   do_rsqrt_fmt (SD_, FMT, FD, FS);
@@ -6065,6 +6360,7 @@
 *mipsII:
 *mips32:
 *mips32r2:
+*mips32r6:
 {
   do_sdc1 (SD_, FT, OFFSET, BASE);
 }
@@ -6077,6 +6373,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6088,7 +6385,7 @@
 
 010011,5.BASE,5.INDEX,5.FS,00000001001:COP1X:32,f::SDXC1
 "sdxc1 f<FS>, r<INDEX>(r<BASE>)"
-*mips32r2
+*mips32r2:
 {
   check_fpu (SD_);
   do_store_double (SD_, GPR[BASE], GPR[INDEX], COP_SD (1, FS));
@@ -6137,8 +6434,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6156,8 +6455,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6176,8 +6477,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6205,8 +6508,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6223,8 +6528,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6249,8 +6556,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6272,8 +6581,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6287,8 +6598,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 
 
@@ -6301,11 +6614,23 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
+:function:::void:do_cache:int op, int rbase, int roffset, address_word instruction_0
+{
+  address_word base = GPR[rbase];
+  address_word offset = EXTEND16 (roffset);
+  {
+    address_word vaddr = loadstore_ea (SD_, base, offset);
+    address_word paddr = vaddr;
+    CacheOp(op, vaddr, paddr, instruction_0);
+  }
+}
 
 101111,5.BASE,5.OP,16.OFFSET:NORMAL:32::CACHE
 "cache <OP>, <OFFSET>(r<BASE>)"
@@ -6320,13 +6645,7 @@
 *vr5000:
 *r3900:
 {
-  address_word base = GPR[BASE];
-  address_word offset = EXTEND16 (OFFSET);
-  {
-    address_word vaddr = loadstore_ea (SD_, base, offset);
-    address_word paddr = vaddr;
-    CacheOp(OP, vaddr, paddr, instruction_0);
-  }
+  do_cache (SD_, OP, BASE, OFFSET, instruction_0);
 }
 
 
@@ -6337,6 +6656,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   DecodeCoproc (instruction_0, 0, cp0_dmfc0, RT, RD, SEL);
@@ -6350,6 +6670,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   DecodeCoproc (instruction_0, 0, cp0_dmtc0, RT, RD, SEL);
@@ -6363,8 +6684,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -6392,8 +6715,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6412,8 +6737,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6446,8 +6773,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *r3900:
 {
@@ -6465,8 +6794,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6480,8 +6811,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6495,8 +6828,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6510,13 +6845,16 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
 
 :include:::mips3264r2.igen
+:include:::mips3264r6.igen
 :include:::m16.igen
 :include:::m16e.igen
 :include:::mdmx.igen
diff --git a/sim/mips/mips3264r2.igen b/sim/mips/mips3264r2.igen
index e0b838c4df2..a28d9897f79 100644
--- a/sim/mips/mips3264r2.igen
+++ b/sim/mips/mips3264r2.igen
@@ -193,6 +193,7 @@
 011111,5.RS,5.RT,5.SIZE,5.LSB,000011::64::DEXT
 "dext r<RT>, r<RS>, <LSB>, <SIZE+1>"
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   do_dext (SD_, RT, RS, LSB, SIZE);
@@ -201,6 +202,7 @@
 011111,5.RS,5.RT,5.SIZE,5.LSB,000001::64::DEXTM
 "dextm r<RT>, r<RS>, <LSB>, <SIZE+33>"
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   do_dextm (SD_, RT, RS, LSB, SIZE);
@@ -209,6 +211,7 @@
 011111,5.RS,5.RT,5.SIZE,5.LSB,000010::64::DEXTU
 "dextu r<RT>, r<RS>, <LSB+32>, <SIZE+1>"
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   do_dextu (SD_, RT, RS, LSB, SIZE);
@@ -219,7 +222,9 @@
 "di":RT == 0
 "di r<RT>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   do_di (SD_, RT);
 }
@@ -228,6 +233,7 @@
 011111,5.RS,5.RT,5.MSB,5.LSB,000111::64::DINS
 "dins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>"
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   do_dins (SD_, RT, RS, LSB, MSB);
@@ -236,6 +242,7 @@
 011111,5.RS,5.RT,5.MSB,5.LSB,000101::64::DINSM
 "dinsm r<RT>, r<RS>, <LSB>, <MSB+32-LSB+1>"
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   do_dinsm (SD_, RT, RS, LSB, MSB);
@@ -244,6 +251,7 @@
 011111,5.RS,5.RT,5.MSB,5.LSB,000110::64::DINSU
 "dinsu r<RT>, r<RS>, <LSB+32>, <MSB-LSB+1>"
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   do_dinsu (SD_, RT, RS, LSB, MSB);
@@ -253,6 +261,7 @@
 011111,00000,5.RT,5.RD,00010,100100::64::DSBH
 "dsbh r<RD>, r<RT>"
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   do_dsbh (SD_, RD, RT);
@@ -261,6 +270,7 @@
 011111,00000,5.RT,5.RD,00101,100100::64::DSHD
 "dshd r<RD>, r<RT>"
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   do_dshd (SD_, RD, RT);
@@ -270,7 +280,9 @@
 "ei":RT == 0
 "ei r<RT>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   do_ei (SD_, RT);
 }
@@ -279,7 +291,9 @@
 011111,5.RS,5.RT,5.SIZE,5.LSB,000000::32::EXT
 "ext r<RT>, r<RS>, <LSB>, <SIZE+1>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   do_ext (SD_, RT, RS, LSB, SIZE);
 }
@@ -288,7 +302,9 @@
 010001,00011,5.RT,5.FS,00000000000:COP1Sa:32,f::MFHC1
 "mfhc1 r<RT>, f<FS>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   do_mfhc1 (SD_, RT, FS);
 }
@@ -296,7 +312,9 @@
 010001,00111,5.RT,5.FS,00000000000:COP1Sa:32,f::MTHC1
 "mthc1 r<RT>, f<FS>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   do_mthc1 (SD_, RT, FS);
 }
@@ -305,7 +323,9 @@
 011111,5.RS,5.RT,5.MSB,5.LSB,000100::32::INS
 "ins r<RT>, r<RS>, <LSB>, <MSB-LSB+1>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   do_ins (SD_, RT, RS, LSB, MSB);
 }
@@ -314,7 +334,9 @@
 011111,00000,5.RT,5.RD,10000,100000::32::SEB
 "seb r<RD>, r<RT>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   do_seb (SD_, RD, RT);
 }
@@ -322,7 +344,9 @@
 011111,00000,5.RT,5.RD,11000,100000::32::SEH
 "seh r<RD>, r<RT>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   do_seh (SD_, RD, RT);
 }
@@ -331,7 +355,9 @@
 000001,5.BASE,11111,16.OFFSET::32::SYNCI
 "synci <OFFSET>(r<BASE>)"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   // sync i-cache - nothing to do currently
 }
@@ -340,7 +366,9 @@
 011111,00000,5.RT,5.RD,00000,111011::32::RDHWR
 "rdhwr r<RT>, r<RD>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   do_rdhwr (SD_, RT, RD);
 }
@@ -349,7 +377,9 @@
 011111,00000,5.RT,5.RD,00010,100000::32::WSBH
 "wsbh r<RD>, r<RT>"
 *mips32r2:
+*mips32r6:
 *mips64r2:
+*mips64r6:
 {
   do_wsbh (SD_, RD, RT);
 }
diff --git a/sim/mips/mips3264r6.igen b/sim/mips/mips3264r6.igen
new file mode 100644
index 00000000000..b83c3098077
--- /dev/null
+++ b/sim/mips/mips3264r6.igen
@@ -0,0 +1,1226 @@
+110010,26.OFFSET:POOL32X:32::BC
+"bc <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  NIA = CIA + (EXTEND26 (OFFSET) << 2) + 4;
+}
+
+111010,26.OFFSET:POOL32X:32::BALC
+"balc <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  RA = CIA + 4;
+  NIA = CIA + (EXTEND26 (OFFSET) << 2) + 4;
+}
+
+110110,5.RS!0,21.OFFSET:POOL32X:32::BEQZC
+"beqzc r<RS>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  if (GPR[RS] == 0)
+    NIA = CIA + (EXTEND21 (OFFSET) << 2) + 4;
+  else
+    FORBIDDEN_SLOT ();
+}
+
+110110,00000,5.RT,16.OFFSET:POOL32X:32::JIC
+"jic r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  NIA = GPR[RT] + (EXTEND16(OFFSET) << 2);
+}
+
+111110,5.RS!0,21.OFFSET:POOL32X:32::BNEZC
+"bnezc r<RS>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  if (GPR[RS] != 0)
+    NIA = CIA + (EXTEND21 (OFFSET) << 2) + 4;
+  else
+    FORBIDDEN_SLOT ();
+}
+
+111110,00000,5.RT,16.OFFSET:POOL32X:32::JIALC
+"jialc r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  RA = CIA + 4;
+  NIA = GPR[RT] + EXTEND16(OFFSET);
+}
+
+010110,5.RS,5.RT,16.OFFSET:POOL32X:32::B1xxC
+"blezc r<RT>, <OFFSET>": RS==0&&RT!=0
+"bgezc r<RT>, <OFFSET>":RS!=0&&RS==RT
+"bgec r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  if (RS == 0 && RT != 0)
+    {
+      //BLEZC
+      if ((signed_word)GPR[RT] <= 0)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else if (RS != 0 && RS == RT)
+    {
+      //BGEZC
+      if ((signed_word)GPR[RT] >= 0)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else
+    {
+      //BGEC
+      if ((signed_word) GPR[RS] >= (signed_word) GPR[RT])
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+}
+
+010111,5.RS,5.RT,16.OFFSET:POOL32X:32::B2xxC
+"bgtzc r<RT>, <OFFSET>":RS==0&&RT!=0
+"bltzc r<RT>, <OFFSET>":RS!=0&&RS==RT
+"bltc r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  if (RS == 0 && RT != 0)
+    {
+      //BGTZC
+      if ((signed_word)GPR[RT] > 0)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else if (RS != 0 && RS == RT)
+    {
+      //BLTZC
+      if ((signed_word)GPR[RT] < 0)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else
+    {
+      //BLTC
+      if ((signed_word) GPR[RS] < (signed_word) GPR[RT])
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+}
+
+000110,5.RS,5.RT!0,16.OFFSET:POOL32X:32::B3xxC
+"blezalc r<RT>, <OFFSET>":RS==0
+"bgezalc r<RT>, <OFFSET>":RS!=0&&RS==RT
+"bgeuc r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  if (RS == 0 && RT != 0)
+    {
+      //BLEZALC
+      RA = CIA + 4;
+      if ((signed_word)GPR[RT] <= 0)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else if (RS != 0 && RS == RT)
+    {
+      //BGEZALC
+      RA = CIA + 4;
+      if ((signed_word)GPR[RT] >= 0)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else
+    {
+      //BGEUC
+      if (GPR[RS] >= GPR[RT])
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+}
+
+000111,5.RS,5.RT!0,16.OFFSET:POOL32X:32::B4xxC
+"bgtzalc r<RT>, <OFFSET>":RS==0
+"bltzalc r<RT>, <OFFSET>":RS!=0&&RS==RT
+"bltuc r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  if (RS == 0 && RT != 0)
+    {
+      //BGTZALC
+      RA = CIA + 4;
+      if ((signed_word)GPR[RT] > 0)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else if (RS != 0 && RS == RT)
+    {
+      //BLTZALC
+      RA = CIA + 4;
+      if ((signed_word)GPR[RT] < 0)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else
+    {
+      //BLTUC
+      if (GPR[RS] < GPR[RT])
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+}
+
+001000,5.RS,5.RT,16.OFFSET:POOL32X:32::BxxxC
+"bovc r<RS>, r<RT>, <OFFSET>":RS>=RT
+"beqzalc r<RT>, <OFFSET>":RS==0&&RT>RS
+"beqc r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  if (RS >= RT)
+    {
+      //BOVC
+      ALU32_BEGIN (GPR[RS] & 0x0ffffffff);
+      ALU32_ADD (GPR[RT] & 0x0ffffffff);
+
+      if (ALU32_HAD_OVERFLOW)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else if (RS == 0)
+    {
+      RA = CIA + 4;
+      //BEQZALC
+      if (GPR[RT] == 0)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else
+    {
+      //BEQC
+      if (GPR[RS] == GPR[RT])
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+}
+
+011000,5.RS,5.RT,16.OFFSET:POOL32X:32::BNxxxC
+"bnvc r<RS>, r<RT>, <OFFSET>":RS>=RT
+"bnezalc r<RT>, <OFFSET>":RS==0&&RT>RS
+"bnec r<RS>, r<RT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  if (RS >= RT)
+    {
+      //BNVC
+      ALU32_BEGIN (GPR[RS] & 0x0ffffffff);
+      ALU32_ADD (GPR[RT] & 0x0ffffffff);
+
+      if (!ALU32_HAD_OVERFLOW)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else if (RS == 0 && RT > RS)
+    {
+      //BNEZALC
+      RA = CIA + 4;
+      if (GPR[RT] != 0)
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+  else
+    {
+      //BNEC
+      if (GPR[RT] != GPR[RS])
+	NIA = CIA + (EXTEND16 (OFFSET) << 2) + 4;
+      else
+	FORBIDDEN_SLOT ();
+    }
+}
+
+:%s::::R6COND:int r6cond
+{
+  switch (r6cond)
+    {
+    case FP_R6CMP_SAF:
+      return "SAF";
+    case FP_R6CMP_SUN:
+      return "SUN";
+    case FP_R6CMP_SOR:
+      return "SOR";
+    case FP_R6CMP_SEQ:
+      return "SEQ";
+    case FP_R6CMP_SUNE:
+      return "SUNE";
+    case FP_R6CMP_SUEQ:
+      return "SUEQ";
+    case FP_R6CMP_SNE:
+      return "SNE";
+    case FP_R6CMP_SLT:
+      return "SLT";
+    case FP_R6CMP_SULT:
+      return "SULT";
+    case FP_R6CMP_SLE:
+      return "SLE";
+    case FP_R6CMP_SULE:
+      return "SULE";
+    case FP_R6CMP_AF:
+      return "AF";
+    case FP_R6CMP_UN:
+      return "UN";
+    case FP_R6CMP_OR:
+      return "OR";
+    case FP_R6CMP_EQ:
+      return "EQ";
+    case FP_R6CMP_UNE:
+      return "UNE";
+    case FP_R6CMP_UEQ:
+      return "UEQ";
+    case FP_R6CMP_NE:
+      return "NE";
+    case FP_R6CMP_LT:
+      return "LT";
+    case FP_R6CMP_ULT:
+      return "ULT";
+    case FP_R6CMP_LE:
+      return "LE";
+    case FP_R6CMP_ULE:
+      return "ULE";
+    default:
+      abort ();
+    }
+}
+
+010001,1010,1.FMT,5.FT,5.FS,5.FD,0,5.R6COND:POOL32X:32,f::CMP.cond.fmt
+"cmp.%s<R6COND>.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+  uint64_t result;
+  check_fpu (SD_);
+  TRACE_ALU_INPUT2 (ValueFPR (FS, FMT), ValueFPR (FT, FMT));
+
+  result = R6Compare (ValueFPR (FS, FMT), ValueFPR (FT, FMT), FMT, R6COND);
+  StoreFPR (FD, FMT, result);
+  TRACE_ALU_RESULT (result);
+}
+
+010001,01001,5.FT,16.OFFSET:POOL32X:32,f::BC1EQZ
+"bc1eqz f<FT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  address_word offset = EXTEND16 (OFFSET) << 2;
+  check_fpu (SD_);
+  TRACE_ALU_INPUT1 (FGR[FT]);
+  if ((FGR[FT] & 0x01) == 0)
+    DELAY_SLOT (NIA + offset);
+}
+
+010001,01101,5.FT,16.OFFSET:POOL32X:32,f::BC1NEZ
+"bc1nez f<FT>, <OFFSET>"
+*mips32r6:
+*mips64r6:
+{
+  address_word offset = EXTEND16 (OFFSET) << 2;
+  check_fpu (SD_);
+  TRACE_ALU_INPUT1 (FGR[FT]);
+  if ((FGR[FT] & 0x01) != 0)
+    DELAY_SLOT (NIA + offset);
+}
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011000:POOLX:32,f::MADDF.fmt
+"maddf.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+  int fmt = FMT;
+  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]);
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011001:POOLX:32,f::MSUBF.fmt
+"msubf.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+  int fmt = FMT;
+  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]);
+}
+
+000000,5.RS,5.RT,5.RD,000,2.IMM,000101:SPECIAL:32::LSA
+"lsa r<RD>, r<RS>, r<RT>, <IMM + 1>"
+*mips32r6:
+*mips64r6:
+{
+  uint32_t t = GPR[RS] << (IMM + 1);
+  GPR[RD] = EXTEND32(GPR[RT] + t);
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,000,2.IMM,010101:SPECIAL:64::DLSA
+"dlsa r<RD>, r<RS>, r<RT>, <IMM + 1>"
+*mips64r6:
+{
+  uint64_t t = GPR[RS] << (IMM + 1);
+  GPR[RD] = GPR[RT] + t;
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+001111,5.RS!0,5.RT,16.IMMEDIATE:POOL32X:32::AUI
+"aui r<RS>, r<RT>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+  TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE);
+  GPR[RT] = EXTEND32 (GPR[RS] + (EXTEND16 (IMMEDIATE) << 16));
+  TRACE_ALU_RESULT (GPR[RT]);
+}
+
+011101,5.RS!0,5.RT,16.IMMEDIATE:POOL32X:64::DAUI
+"daui r<RS>, r<RT>, <IMMEDIATE>"
+*mips64r6:
+{
+  TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE);
+  GPR[RT] = GPR[RS] + (EXTEND16 (IMMEDIATE) << 16);
+  TRACE_ALU_RESULT (GPR[RT]);
+}
+
+000001,5.RS,00110,16.IMMEDIATE:POOL32X:64::DAHI
+"dahi r<RS>, <IMMEDIATE>"
+*mips64r6:
+{
+  TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE);
+  GPR[RS] = GPR[RS] + (EXTEND16 (IMMEDIATE) << 32);
+  TRACE_ALU_RESULT (GPR[RS]);
+}
+
+000001,5.RS,11110,16.IMMEDIATE:POOL32X:64::DATI
+"dati r<RS>, <IMMEDIATE>"
+*mips64r6:
+{
+  TRACE_ALU_INPUT2 (GPR[RS], IMMEDIATE);
+  GPR[RS] = GPR[RS] + (EXTEND16 (IMMEDIATE) << 48);
+  TRACE_ALU_RESULT (GPR[RS]);
+}
+
+011111,5.RS,5.RT,5.RD,010,2.IMMEDIATE,100000:POOL32X:32::ALIGN
+"align r<RD>, r<RS>, r<RT>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+  uint32_t rs = GPR[RS];
+  uint32_t rt = GPR[RT];
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  GPR[RD] = EXTEND32 (rs >> 8 * (4 - IMMEDIATE) | rt << 8 * IMMEDIATE);
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+011111,5.RS,5.RT,5.RD,01,3.IMMEDIATE,100100:POOL32X:64::DALIGN
+"dalign r<RD>, r<RS>, r<RT>, <IMMEDIATE>"
+*mips64r6:
+{
+  uint64_t rs = GPR[RS];
+  uint64_t rt = GPR[RT];
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  GPR[RD] = rs >> 8 * (8 - IMMEDIATE) | rt << 8 * IMMEDIATE;
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+011111,00000,5.RT,5.RD,00000,100000:POOL32X:32::BITSWAP
+"bitswap r<RD>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  /* Taken from: http://graphics.stanford.edu/~seander/bithacks.html */
+  uint32_t v = GPR[RT];
+
+  TRACE_ALU_INPUT1 (v);
+  v = ((v >> 1)  & 0x55555555) | ((v & 0x55555555) << 1);
+  v = ((v >> 2)  & 0x33333333) | ((v & 0x33333333) << 2);
+  v = ((v >> 4)  & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4);
+  GPR[RD] = EXTEND32 (v);
+  TRACE_ALU_RESULT(GPR[RD]);
+}
+
+011111,00000,5.RT,5.RD,00000,100100:POOL32X:64::DBITSWAP
+"dbitswap r<RD>, r<RT>"
+*mips64r6:
+{
+  /* Taken from: http://graphics.stanford.edu/~seander/bithacks.html */
+  uint64_t v = GPR[RT];
+
+  TRACE_ALU_INPUT1 (v);
+  v = ((v >> 1)  & 0x5555555555555555) | ((v & 0x5555555555555555) << 1);
+  v = ((v >> 2)  & 0x3333333333333333) | ((v & 0x3333333333333333) << 2);
+  v = ((v >> 4)  & 0x0F0F0F0F0F0F0F0F) | ((v & 0x0F0F0F0F0F0F0F0F) << 4);
+  TRACE_ALU_RESULT(v);
+  GPR[RD] = v;
+}
+
+111011,5.RS,00,19.IMMEDIATE:POOL32X:32::ADDIUPC
+"addiupc r<RS>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+  TRACE_ALU_INPUT1 (IMMEDIATE);
+  GPR[RS] = loadstore_ea (SD_, CIA, EXTEND19 (IMMEDIATE) << 2);
+  TRACE_ALU_RESULT (GPR[RS]);
+}
+
+111011,5.RS,11110,16.IMMEDIATE:POOL32X:32::AUIPC
+"auipc r<RS>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+  TRACE_ALU_INPUT1 (IMMEDIATE);
+  GPR[RS] = loadstore_ea (SD_, CIA, EXTEND32 (IMMEDIATE << 16));
+  TRACE_ALU_RESULT (GPR[RS]);
+}
+
+111011,5.RS,11111,16.IMMEDIATE:POOL32X:32::ALUIPC
+"aluipc r<RS>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+  TRACE_ALU_INPUT1 (IMMEDIATE);
+  GPR[RS] = ~0x0FFFF & loadstore_ea (SD_, CIA, EXTEND32 (IMMEDIATE << 16));
+  TRACE_ALU_RESULT (GPR[RS]);
+}
+
+111011,5.RS,01,19.IMMEDIATE:POOL32X:32::LWPC
+"lwpc r<RS>, <IMMEDIATE>"
+*mips32r6:
+*mips64r6:
+{
+  uint32_t offset = EXTEND19 (IMMEDIATE) << 2;
+  TRACE_ALU_INPUT1 (IMMEDIATE);
+  GPR[RS] = EXTEND32 (do_load (SD_, AccessLength_WORD, CIA, offset));
+  TRACE_ALU_RESULT (GPR[RS]);
+}
+
+111011,5.RS,10,19.IMMEDIATE:POOL32X:64::LWUPC
+"lwupc r<RS>, <IMMEDIATE>"
+*mips64r6:
+{
+  uint32_t offset = EXTEND19 (IMMEDIATE) << 2;
+  TRACE_ALU_INPUT1 (CIA + offset);
+  GPR[RS] = do_load (SD_, AccessLength_WORD, CIA, offset);
+  TRACE_ALU_RESULT (GPR[RS]);
+}
+
+111011,5.RS,110,18.IMMEDIATE:POOL32X:64::LDPC
+"ldpc r<RS>, <IMMEDIATE>"
+*mips64r6:
+{
+  uint32_t offset = EXTEND18 (IMMEDIATE) << 3;
+  TRACE_ALU_INPUT1 (IMMEDIATE);
+  GPR[RS] = do_load (SD_, AccessLength_DOUBLEWORD, CIA, offset);
+  TRACE_ALU_RESULT (GPR[RS]);
+}
+010001,1000,1.FMT,00000,5.FS,5.FD,011010::32,64,f::RINT.fmt
+"rint.%s<FMT> f<FD>, f<FS>"
+*mips32r6:
+*mips64r6:
+{
+  uint64_t result;
+  int fmt = FMT;
+  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]);
+}
+
+010001,1000,1.FMT,00000,5.FS,5.FD,011011::32,64,f::CLASS.fmt
+"class.%s<FMT> f<FD>, f<FS>"
+*mips32r6:
+*mips64r6:
+{
+  int fmt = FMT;
+  check_fpu (SD_);
+  check_u64 (SD_, instruction_0);
+  check_fmt_p (SD_, fmt, instruction_0);
+  StoreFPR (FD, fmt, Classify (ValueFPR (FS, fmt), fmt));
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011100::32,64,f::MIN.fmt
+"min.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+  int fmt = FMT;
+  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]);
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011110::32,64,f::MAX.fmt
+"max.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+  int fmt = FMT;
+  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]);
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011101::32,64,f::MINA.fmt
+"mina.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+  int fmt = FMT;
+  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]);
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,011111::32,64,f::MAXA.fmt
+"maxa.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+  int fmt = FMT;
+  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]);
+}
+000000,5.RS,5.RT,5.RD,00010,011000:POOL32X:32::MUL
+"mul r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  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 (VL4_8 (prod));
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011000:POOL32X:32::MUH
+"muh r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  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]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011001:POOL32X:32::MULU
+"mulu r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  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]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011001:POOL32X:32::MUHU
+"muhu r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  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]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011010:POOL32X:32::DIV
+"div r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  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]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011010:POOL32X:32::MOD
+"mod r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  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]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011011:POOL32X:32::DIVU
+"divu r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  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]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011011:POOL32X:32::MODU
+"modu r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  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]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011100:POOL32X:64::DMUL
+"dmul r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+  uint64_t lo;
+  uint64_t m00;
+  uint64_t m01;
+  uint64_t m10;
+  uint64_t mid;
+  int sign;
+  uint64_t op1 = GPR[RS];
+  uint64_t op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* make signed multiply unsigned */
+  sign = 0;
+  if ((int64_t) op1 < 0)
+    {
+      op1 = - op1;
+      ++sign;
+    }
+  if ((int64_t) op2 < 0)
+    {
+      op2 = - op2;
+      ++sign;
+    }
+  /* multiply out the sub products */
+  m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2));
+  m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2));
+  m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2));
+  /* add the products */
+  mid = ((uint64_t) VH4_8 (m00)
+	 + (uint64_t) VL4_8 (m10)
+	 + (uint64_t) VL4_8 (m01));
+  lo = U8_4 (mid, m00);
+  /* fix the sign */
+  if (sign & 1)
+    lo = -lo;
+
+  GPR[RD] = lo;
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011100:POOL32X:64::DMUH
+"dmuh r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+  uint64_t lo;
+  uint64_t hi;
+  uint64_t m00;
+  uint64_t m01;
+  uint64_t m10;
+  uint64_t m11;
+  uint64_t mid;
+  int sign;
+  uint64_t op1 = GPR[RS];
+  uint64_t op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* make signed multiply unsigned */
+  sign = 0;
+  if ((int64_t) op1 < 0)
+    {
+      op1 = - op1;
+      ++sign;
+    }
+  if ((int64_t) op2 < 0)
+    {
+      op2 = - op2;
+      ++sign;
+    }
+  /* multiply out the 4 sub products */
+  m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2));
+  m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2));
+  m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2));
+  m11 = ((uint64_t) VH4_8 (op1) * (uint64_t) VH4_8 (op2));
+  /* add the products */
+  mid = ((uint64_t) VH4_8 (m00)
+	 + (uint64_t) VL4_8 (m10)
+	 + (uint64_t) VL4_8 (m01));
+  lo = U8_4 (mid, m00);
+  hi = (m11
+	+ (uint64_t) VH4_8 (mid)
+	+ (uint64_t) VH4_8 (m01)
+	+ (uint64_t) VH4_8 (m10));
+  /* fix the sign */
+  if (sign & 1)
+    {
+      lo = -lo;
+      if (lo == 0)
+	hi = -hi;
+      else
+	hi = -hi - 1;
+    }
+
+  GPR[RD] = hi;
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011101:POOL32X:64::DMULU
+"dmulu r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+  uint64_t lo;
+  uint64_t m00;
+  uint64_t m01;
+  uint64_t m10;
+  uint64_t mid;
+  uint64_t op1 = GPR[RS];
+  uint64_t op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* multiply out the sub products */
+  m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2));
+  m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2));
+  m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2));
+  /* add the products */
+  mid = ((uint64_t) VH4_8 (m00)
+	 + (uint64_t) VL4_8 (m10)
+	 + (uint64_t) VL4_8 (m01));
+  lo = U8_4 (mid, m00);
+
+  GPR[RD] = lo;
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011101:POOL32X:64::DMUHU
+"dmuhu r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+  uint64_t lo;
+  uint64_t hi;
+  uint64_t m00;
+  uint64_t m01;
+  uint64_t m10;
+  uint64_t m11;
+  uint64_t mid;
+  uint64_t op1 = GPR[RS];
+  uint64_t op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* multiply out the 4 sub products */
+  m00 = ((uint64_t) VL4_8 (op1) * (uint64_t) VL4_8 (op2));
+  m10 = ((uint64_t) VH4_8 (op1) * (uint64_t) VL4_8 (op2));
+  m01 = ((uint64_t) VL4_8 (op1) * (uint64_t) VH4_8 (op2));
+  m11 = ((uint64_t) VH4_8 (op1) * (uint64_t) VH4_8 (op2));
+  /* add the products */
+  mid = ((uint64_t) VH4_8 (m00)
+	 + (uint64_t) VL4_8 (m10)
+	 + (uint64_t) VL4_8 (m01));
+  lo = U8_4 (mid, m00);
+  hi = (m11
+	+ (uint64_t) VH4_8 (mid)
+	+ (uint64_t) VH4_8 (m01)
+	+ (uint64_t) VH4_8 (m10));
+
+  GPR[RD] = hi;
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011110:POOL32X:64::DDIV
+"ddiv r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+  int64_t n = GPR[RS];
+  int64_t d = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (n, d);
+  if (d == 0)
+    GPR[RD] = SIGNED64 (0x8000000000000000);
+  else if (d == -1 && n == SIGNED64 (0x8000000000000000))
+    GPR[RD] = SIGNED64 (0x8000000000000000);
+  else
+    GPR[RD] = (n / d);
+
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011110:POOL32X:64::DMOD
+"dmod r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+  int64_t n = GPR[RS];
+  int64_t d = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (n, d);
+  if (d == 0 || (d == -1 && n == SIGNED64 (0x8000000000000000)))
+    GPR[RD] = SIGNED64 (0);
+  else
+    GPR[RD] = (n % d);
+
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00010,011111:POOL32X:64::DDIVU
+"ddivu r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+  uint64_t n = GPR[RS];
+  uint64_t d = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (n, d);
+  if (d == 0)
+    GPR[RD] = UNSIGNED64 (0x8000000000000000);
+  else
+    GPR[RD] = (n / d);
+
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00011,011111:POOL32X:64::DMODU
+"dmodu r<RD>, r<RS>, r<RT>"
+*mips64r6:
+{
+  uint64_t n = GPR[RS];
+  uint64_t d = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (n, d);
+  if (d == 0)
+    GPR[RD] = UNSIGNED64 (0);
+  else
+    GPR[RD] = (n % d);
+
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+011111,5.BASE,5.RT,9.OFFSET,0,110110:SPECIAL3:32::LL
+"ll r<RT>, <OFFSET>(r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+  do_ll (SD_, RT, EXTEND9 (OFFSET), BASE);
+}
+
+011111,5.BASE,5.RT,5.RD,0000,1,110110:SPECIAL3:32::LLWP
+"llwp r<RT>, r<RD>, (r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+  int first, second;
+  int offset;
+
+  if (RT == BASE)
+  {
+    first = RD;
+    second = RT;
+    offset = BigEndianCPU ? 0 : 4;
+  }
+  else
+  {
+    first = RT;
+    second = RD;
+    offset = BigEndianCPU ? 4 : 0;
+  }
+
+  do_ll (SD_, first, offset, BASE);
+  do_ll (SD_, second, offset ^ 4, BASE);
+}
+
+
+011111,5.BASE,5.RT,9.OFFSET,0,100110:SPECIAL3:32::SC
+"sc r<RT>, <OFFSET>(r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+  do_sc (SD_, RT, EXTEND9 (OFFSET), BASE, instruction_0, 1);
+}
+
+011111,5.BASE,5.RT,9.OFFSET,0,110111:SPECIAL3:64::LLD
+"lld r<RT>, <OFFSET>(r<BASE>)"
+*mips64r6:
+{
+  check_u64 (SD_, instruction_0);
+  do_lld (SD_, RT, EXTEND9 (OFFSET), BASE);
+}
+
+
+011111,5.BASE,5.RT,5.RD,0000,1,100110:SPECIAL3:32::SCWP
+"scwp r<RT>, r<RD>, (r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+  int offset = BigEndianCPU ? 0 : 4;
+
+  do_sc (SD_, RD, offset, BASE, instruction_0, 0);
+  do_sc (SD_, RT, offset ^ 4, BASE, instruction_0, 1);
+}
+
+011111,5.BASE,5.RT,5.RD,0000,1,110111:SPECIAL3:64::LLDP
+"lldp r<RT>, r<RD>, (r<BASE>)"
+*mips64r6:
+{
+  int first, second;
+  int offset;
+
+  check_u64 (SD_, instruction_0);
+
+  if (RT == BASE)
+  {
+    first = RD;
+    second = RT;
+    offset = BigEndianCPU ? 0 : 8;
+  }
+  else
+  {
+    first = RT;
+    second = RD;
+    offset = BigEndianCPU ? 8 : 0;
+  }
+
+  do_lld (SD_, first, offset, BASE);
+  do_lld (SD_, second, offset ^ 8, BASE);
+}
+
+011111,5.BASE,5.RT,9.OFFSET,0,100111:SPECIAL3:64::SCD
+"scd r<RT>, <OFFSET>(r<BASE>)"
+*mips64r6:
+{
+  check_u64 (SD_, instruction_0);
+  do_scd (SD_, RT, EXTEND9 (OFFSET), BASE, 1);
+}
+
+011111,5.BASE,5.RT,5.RD,0000,1,100111:SPECIAL3:64::SCDP
+"scdp r<RT>, r<RD>, (r<BASE>)"
+*mips64r6:
+{
+  int offset = BigEndianCPU ? 0 : 8;
+  check_u64 (SD_, instruction_0);
+
+  do_scd (SD_, RD, offset, BASE, 0);
+  do_scd (SD_, RT, offset ^ 8, BASE, 1);
+}
+
+011111,5.BASE,5.HINT,9.OFFSET,0,110101:SPECIAL3:32::PREF
+"pref <HINT>, <OFFSET>(r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+  do_pref (SD_, HINT, EXTEND9 (OFFSET), BASE);
+}
+
+011111,5.BASE,5.HINT,9.OFFSET,0,100101:SPECIAL3:32::CACHE
+"cache <HINT>, <OFFSET>(r<BASE>)"
+*mips32r6:
+*mips64r6:
+{
+  do_cache (SD_, HINT, BASE, EXTEND9 (OFFSET), instruction_0);
+}
+
+
+000000,5.RS,00000,5.RD,00001,010000:POOL32X:32::CLZ
+"clz r<RD>, r<RS>"
+*mips32r6:
+*mips64r6:
+{
+  do_clz (SD_, RD, RS);
+}
+
+000000,5.RS,00000,5.RD,00001,010001:POOL32X:32::CLO
+"clo r<RD>, r<RS>"
+*mips32r6:
+*mips64r6:
+{
+  do_clo (SD_, RD, RS);
+}
+
+000000,5.RS,00000,5.RD,00001,010010:POOL32X:64::DCLZ
+"dclz r<RD>, r<RS>"
+*mips64r6:
+{
+  check_u64 (SD_, instruction_0);
+  do_dclz (SD_, RD, RS);
+}
+
+000000,5.RS,00000,5.RD,00001,010011:POOL32X:64::DCLO
+"dclo r<RD>, r<RS>"
+*mips64r6:
+{
+  check_u64 (SD_, instruction_0);
+  do_dclo (SD_, RD, RS);
+}
+010001,1000,1.FMT,5.FT,5.FS,5.FD,010000:POOL32X:32,f::SEL.fmt
+"sel.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+  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));
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,010100:POOL32X:32,f::SELEQZ.fmt
+"seleqz.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+  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));
+}
+
+010001,1000,1.FMT,5.FT,5.FS,5.FD,010111:POOL32X:32,f::SELNEZ.fmt
+"selnez.%s<FMT> f<FD>, f<FS>, f<FT>"
+*mips32r6:
+*mips64r6:
+{
+  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, 0);
+  else
+    StoreFPR (FD, FMT, ValueFPR (FS, FMT));
+  TRACE_ALU_RESULT (ValueFPR(FD, FMT));
+}
+
+000000,5.RS,5.RT,5.RD,00000,110101:POOL32X:32::SELEQZ
+"seleqz r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  if (GPR[RT] != 0)
+    GPR[RD] = 0;
+  else
+    GPR[RD] = GPR[RS];
+  TRACE_ALU_RESULT (GPR[RD]);
+}
+
+000000,5.RS,5.RT,5.RD,00000,110111:POOL32X:32::SELNEZ
+"selnez r<RD>, r<RS>, r<RT>"
+*mips32r6:
+*mips64r6:
+{
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  if (GPR[RT] != 0)
+    GPR[RD] = GPR[RS];
+  else
+    GPR[RD] = 0;
+  TRACE_ALU_RESULT (GPR[RD]);
+}
diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h
index 8e3e85f2585..418c6599118 100644
--- a/sim/mips/sim-main.h
+++ b/sim/mips/sim-main.h
@@ -26,6 +26,8 @@ mips_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ER
 #include "sim-basics.h"
 #include "sim-base.h"
 #include "bfd.h"
+#include "elf-bfd.h"
+#include "elf/mips.h"
 
 /* Deprecated macros and types for manipulating 64bit values.  Use
    ../common/sim-bits.h and ../common/sim-endian.h macros instead. */
@@ -72,6 +74,9 @@ typedef enum {
  fmt_word    = 4,
  fmt_long    = 5,
  fmt_ps      = 6,
+ /* The following is a special case for FP conditions where only
+    the lower 32bits are considered.  This is a HACK.  */
+ fmt_dc32    = 7,
  /* The following are well outside the normal acceptable format
     range, and are used in the register status vector. */
  fmt_unknown       = 0x10000000,
@@ -261,6 +266,7 @@ struct _sim_cpu {
 #define DSPC ((CPU)->dspc)
 
 #define DELAY_SLOT(TARGET) NIA = delayslot32 (SD_, (TARGET))
+#define FORBIDDEN_SLOT() { NIA = forbiddenslot32 (SD_); }
 #define NULLIFY_NEXT_INSTRUCTION() NIA = nullify_next_insn32 (SD_)
 
 
@@ -271,15 +277,16 @@ struct _sim_cpu {
 #define DSSTATE ((CPU)->dsstate)
 
 /* Flags in the "state" variable: */
-#define simHALTEX       (1 << 2)  /* 0 = run; 1 = halt on exception */
-#define simHALTIN       (1 << 3)  /* 0 = run; 1 = halt on interrupt */
-#define simTRACE        (1 << 8)  /* 0 = do nothing; 1 = trace address activity */
-#define simPCOC0        (1 << 17) /* COC[1] from current */
-#define simPCOC1        (1 << 18) /* COC[1] from previous */
-#define simDELAYSLOT    (1 << 24) /* 0 = do nothing; 1 = delay slot entry exists */
-#define simSKIPNEXT     (1 << 25) /* 0 = do nothing; 1 = skip instruction */
-#define simSIGINT	(1 << 28)  /* 0 = do nothing; 1 = SIGINT has occured */
-#define simJALDELAYSLOT	(1 << 29) /* 1 = in jal delay slot */
+#define simHALTEX        (1 << 2)  /* 0 = run; 1 = halt on exception */
+#define simHALTIN        (1 << 3)  /* 0 = run; 1 = halt on interrupt */
+#define simTRACE         (1 << 8)  /* 1 = trace address activity */
+#define simPCOC0         (1 << 17) /* COC[1] from current */
+#define simPCOC1         (1 << 18) /* COC[1] from previous */
+#define simDELAYSLOT     (1 << 24) /* 1 = delay slot entry exists */
+#define simSKIPNEXT      (1 << 25) /* 0 = do nothing; 1 = skip instruction */
+#define simSIGINT        (1 << 28)  /* 0 = do nothing; 1 = SIGINT has occured */
+#define simJALDELAYSLOT  (1 << 29) /* 1 = in jal delay slot */
+#define simFORBIDDENSLOT (1 << 30) /* 1 = n forbidden slot */
 
 #ifndef ENGINE_ISSUE_PREFIX_HOOK
 #define ENGINE_ISSUE_PREFIX_HOOK() \
@@ -532,6 +539,10 @@ struct mips_sim_state {
 /* Bits reserved for implementations:  */
 #define status_SBX       (1 << 16)      /* Enable SiByte SB-1 extensions.  */
 
+/* From R6 onwards, some instructions (e.g. ADDIUPC) change behaviour based
+ * on the Status.UX bits to either sign extend, or act as full 64 bit. */
+#define status_optional_EXTEND32(x) ((SR & status_UX) ? x : EXTEND32(x))
+
 #define cause_BD ((unsigned)1 << 31)    /* L1 Exception in branch delay slot */
 #define cause_BD2         (1 << 30)     /* L2 Exception in branch delay slot */
 #define cause_CE_mask     0x30000000	/* Coprocessor exception */
@@ -719,8 +730,55 @@ void test_fcsr (SIM_STATE);
 
 
 /* FPU operations.  */
-void fp_cmp (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt, int abs, int cond, int cc);
-#define Compare(op1,op2,fmt,cond,cc) fp_cmp(SIM_ARGS, op1, op2, fmt, 0, cond, cc)
+/* Non-signalling */
+#define FP_R6CMP_AF  0x0
+#define FP_R6CMP_EQ  0x2
+#define FP_R6CMP_LE  0x6
+#define FP_R6CMP_LT  0x4
+#define FP_R6CMP_NE  0x13
+#define FP_R6CMP_OR  0x11
+#define FP_R6CMP_UEQ 0x3
+#define FP_R6CMP_ULE 0x7
+#define FP_R6CMP_ULT 0x5
+#define FP_R6CMP_UN  0x1
+#define FP_R6CMP_UNE 0x12
+
+/* Signalling */
+#define FP_R6CMP_SAF  0x8
+#define FP_R6CMP_SEQ  0xa
+#define FP_R6CMP_SLE  0xe
+#define FP_R6CMP_SLT  0xc
+#define FP_R6CMP_SNE  0x1b
+#define FP_R6CMP_SOR  0x19
+#define FP_R6CMP_SUEQ 0xb
+#define FP_R6CMP_SULE 0xf
+#define FP_R6CMP_SULT 0xd
+#define FP_R6CMP_SUN  0x9
+#define FP_R6CMP_SUNE 0x1a
+
+/* FPU Class */
+#define FP_R6CLASS_SNAN    (1<<0)
+#define FP_R6CLASS_QNAN    (1<<1)
+#define FP_R6CLASS_NEGINF  (1<<2)
+#define FP_R6CLASS_NEGNORM (1<<3)
+#define FP_R6CLASS_NEGSUB  (1<<4)
+#define FP_R6CLASS_NEGZERO (1<<5)
+#define FP_R6CLASS_POSINF  (1<<6)
+#define FP_R6CLASS_POSNORM (1<<7)
+#define FP_R6CLASS_POSSUB  (1<<8)
+#define FP_R6CLASS_POSZERO (1<<9)
+
+void fp_cmp (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt,
+	     int abs, int cond, int cc);
+#define Compare(op1,op2,fmt,cond,cc)  \
+  fp_cmp(SIM_ARGS, op1, op2, fmt, 0, cond, cc)
+uint64_t fp_r6_cmp (SIM_STATE, uint64_t op1, uint64_t op2,
+		      FP_formats fmt, int cond);
+#define R6Compare(op1,op2,fmt,cond) fp_r6_cmp(SIM_ARGS, op1, op2, fmt, cond)
+uint64_t fp_classify(SIM_STATE, uint64_t op, FP_formats fmt);
+#define Classify(op, fmt) fp_classify(SIM_ARGS, op, fmt)
+int fp_rint(SIM_STATE, uint64_t op, uint64_t *ans, FP_formats fmt);
+#define RoundToIntegralExact(op, ans, fmt) fp_rint(SIM_ARGS, op, ans, fmt)
 uint64_t fp_abs (SIM_STATE, uint64_t op, FP_formats fmt);
 #define AbsoluteValue(op,fmt) fp_abs(SIM_ARGS, op, fmt)
 uint64_t fp_neg (SIM_STATE, uint64_t op, FP_formats fmt);
@@ -733,6 +791,14 @@ uint64_t fp_mul (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
 #define Multiply(op1,op2,fmt) fp_mul(SIM_ARGS, op1, op2, fmt)
 uint64_t fp_div (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
 #define Divide(op1,op2,fmt) fp_div(SIM_ARGS, op1, op2, fmt)
+uint64_t fp_min (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
+#define Min(op1,op2,fmt) fp_min(SIM_ARGS, op1, op2, fmt)
+uint64_t fp_max (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
+#define Max(op1,op2,fmt) fp_max(SIM_ARGS, op1, op2, fmt)
+uint64_t fp_mina (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
+#define MinA(op1,op2,fmt) fp_mina(SIM_ARGS, op1, op2, fmt)
+uint64_t fp_maxa (SIM_STATE, uint64_t op1, uint64_t op2, FP_formats fmt);
+#define MaxA(op1,op2,fmt) fp_maxa(SIM_ARGS, op1, op2, fmt)
 uint64_t fp_recip (SIM_STATE, uint64_t op, FP_formats fmt);
 #define Recip(op,fmt) fp_recip(SIM_ARGS, op, fmt)
 uint64_t fp_sqrt (SIM_STATE, uint64_t op, FP_formats fmt);
@@ -741,6 +807,12 @@ uint64_t fp_rsqrt (SIM_STATE, uint64_t op, FP_formats fmt);
 #define RSquareRoot(op,fmt) fp_rsqrt(SIM_ARGS, op, fmt)
 uint64_t fp_madd (SIM_STATE, uint64_t op1, uint64_t op2,
 		    uint64_t op3, FP_formats fmt);
+#define FusedMultiplyAdd(op1,op2,op3,fmt) fp_fmadd(SIM_ARGS, op1, op2, op3, fmt)
+uint64_t fp_fmadd (SIM_STATE, uint64_t op1, uint64_t op2,
+		     uint64_t op3, FP_formats fmt);
+#define FusedMultiplySub(op1,op2,op3,fmt) fp_fmsub(SIM_ARGS, op1, op2, op3, fmt)
+uint64_t fp_fmsub (SIM_STATE, uint64_t op1, uint64_t op2,
+		     uint64_t op3, FP_formats fmt);
 #define MultiplyAdd(op1,op2,op3,fmt) fp_madd(SIM_ARGS, op1, op2, op3, fmt)
 uint64_t fp_msub (SIM_STATE, uint64_t op1, uint64_t op2,
 		    uint64_t op3, FP_formats fmt);
diff --git a/sim/testsuite/mips/basic.exp b/sim/testsuite/mips/basic.exp
index 81cce85a5b2..db297121e93 100644
--- a/sim/testsuite/mips/basic.exp
+++ b/sim/testsuite/mips/basic.exp
@@ -35,13 +35,61 @@ proc run_micromips_test { name requested_machs } {
     unset ASFLAGS_FOR_TARGET
 }
 
+# Runs endian tests
+proc run_endian_tests { name requested_machs } {
+    global ASFLAGS_FOR_TARGET
+    global LDFLAGS_FOR_TARGET
+    run_sim_test $name $requested_machs
+    set ASFLAGS_FOR_TARGET "-EL"
+    set LDFLAGS_FOR_TARGET "-EL"
+    run_sim_test $name $requested_machs
+    unset ASFLAGS_FOR_TARGET
+    unset LDFLAGS_FOR_TARGET
+}
+
 # Runs all specified tests
 proc run_sim_tests { name requested_machs { requested_micromips_machs "" } } {
     run_sim_test $name $requested_machs
     run_micromips_test $name $requested_micromips_machs
 }
 
+
+# Runs the combination of instructions removed in R6 through the testsuite
+proc run_r6_removed_test {testfile models} {
+    global subdir srcdir
+    set fd [open "$srcdir/$subdir/r6-removed.csv" r]
+    set file_data [read $fd]
+    close $fd
+    set data [split $file_data "\n"]
+    foreach line $data {
+        set line_contents [split $line ","]
+        set mnemonic [lindex $line_contents 0]
+        set insn [lindex $line_contents 1]
+
+        if {[string compare $insn ""] == 1} {
+
+            set contents ""
+            append contents ".macro removed_instr\n"
+            append contents ".word $insn\n"
+            append contents "nop\n"
+            append contents ".endm"
+
+            verbose -log "r6-removed test: $mnemonic\n$contents"
+            set file [open r6-removed.inc w]
+            puts $file $contents
+            close $file
+
+            run_sim_test $testfile $models
+        }
+    }
+}
+
+
 if {[istarget *]} {
+    # Used to locate the `run` program.
+    global arch
+    set arch "mips"
+
     set dspmodels ""
     set mdmxmodels ""
     set micromipsmodels ""
@@ -51,18 +99,24 @@ if {[istarget *]} {
 	set models "sb1"
 	set submodels "mips1 mips2 mips3 mips4 mips32 mips64"
 	append mdmxmodels " mips64"
+    } elseif {[istarget mipsisa64r6*-*-elf]} {
+        set models "mips32r6 mips64r6"
+        set submodels ""
     } elseif {[istarget mipsisa64*-*-elf]} {
 	set models "mips32 mips64 mips32r2 mips64r2"
 	set submodels "mips1 mips2 mips3 mips4"
 	append dspmodels " mips32r2 mips64r2"
 	append mdmxmodels " mips64 mips32r2 mips64r2"
     } elseif {[istarget mips*-sde-elf*] || [istarget mips*-mti-elf*]} {
-	set models "mips32 mips64 mips32r2 mips64r2"
+	set models "mips32 mips64 mips32r2 mips64r2 mips32r6 mips64r6"
 	set submodels ""
-	append dspmodels " mips32r2 mips64r2"
-	append mdmxmodels " mips64 mips32r2 mips64r2"
-	append micromipsmodels " mips32r2"
+	append dspmodels " mips32r2 mips64r2 mips32r6 mips64r6"
+	append mdmxmodels " mips64 mips32r2 mips64r2 mips32r6 mips64r6"
+	append micromipsmodels " mips32r2 mips64r2"
 	append micromipsdspmodels " mips32r2 mips64r2"
+    } elseif {[istarget mipsisa32r6*-*-elf]} {
+        set models "mips32r6"
+        set submodels ""
     } elseif {[istarget mipsisa32*-*-elf]} {
 	set models "mips32 mips32r2"
 	set submodels "mips1 mips2"
@@ -102,4 +156,14 @@ if {[istarget *]} {
     run_sim_tests mips32-dsp.s $dspmodels $micromipsdspmodels
     run_sim_tests mips32-dsp2.s $dspmodels $micromipsdspmodels
 
+    run_sim_test r2-fpu.s $models
+
+    run_sim_test r6-fpu.s $models
+    run_sim_test r6.s $models
+    run_sim_test r6-forbidden.s $models
+    run_r6_removed_test r6-removed.s $models
+    run_sim_test r6-64.s $models
+    run_sim_test r6-branch.s $models
+    run_endian_tests r6-llsc-wp.s $models
+    run_endian_tests r6-llsc-dp.s $models
 }
diff --git a/sim/testsuite/mips/hilo-hazard-3.s b/sim/testsuite/mips/hilo-hazard-3.s
index 1a0949db6e0..9d50da2a07d 100644
--- a/sim/testsuite/mips/hilo-hazard-3.s
+++ b/sim/testsuite/mips/hilo-hazard-3.s
@@ -1,6 +1,6 @@
 # Test for mf{hi,lo} -> mult/div/mt{hi,lo} with 2 nops inbetween.
 #
-# mach:		all
+# mach:		-mips32r6 -mips64r6 all
 # as:		-mabi=eabi
 # ld:		-N -Ttext=0x80010000
 # output:	pass\\n
diff --git a/sim/testsuite/mips/r2-fpu.s b/sim/testsuite/mips/r2-fpu.s
new file mode 100644
index 00000000000..1001f933c97
--- /dev/null
+++ b/sim/testsuite/mips/r2-fpu.s
@@ -0,0 +1,31 @@
+# mips r2 fpu tests
+# mach:   mips32r2 mips64r2
+# as:     -mabi=eabi
+# ld:     -N -Ttext=0x80010000
+# output: *\\npass\\n
+
+  .include "testutils.inc"
+
+  setup
+
+  .set noreorder
+
+  .ent DIAG
+
+DIAG:
+  writemsg "[1] Test qNaN format is 754-1985"
+  li $6, 0x7fbfffff
+  mtc1 $0, $f2
+  mtc1 $0, $f4
+  div.s $f6, $f2, $f4
+  mfc1 $8, $f6
+  beq $8, $6, L1
+  nop
+  fail
+
+  L1:
+  #TODO: More tests?
+
+  pass
+
+  .end DIAG
diff --git a/sim/testsuite/mips/r6-64.s b/sim/testsuite/mips/r6-64.s
new file mode 100644
index 00000000000..365f49f2f00
--- /dev/null
+++ b/sim/testsuite/mips/r6-64.s
@@ -0,0 +1,157 @@
+# mips64 specific r6 tests (non FPU)
+# mach:  mips64r6
+# as:    -mabi=eabi
+# ld:    -N -Ttext=0x80010000 -Tdata=0x80020000
+# output: *\\npass\\n
+
+  .include "testutils.inc"
+  .include "utils-r6.inc"
+
+  .data
+d0:   .dword 0
+dval: .dword 0xaa55bb66cc77dd88
+d1:   .dword 0xaaaabbbbccccdddd
+d2:   .dword 256
+dlo:  .dword 0xaabbbbccccdddd00
+dhi:  .dword 0xffffffffffffffaa
+dhiu: .dword 0x00000000000000aa
+d3:   .dword 0xffaaaabbbbccccde
+d4:   .dword 0xffffffffffffffdd
+d5:   .dword 0x00000000000000dd
+d6:   .dword 0x00aaaabbbbccccdd
+d7:   .dword 0xeeeeffff00001111
+d8:   .dword 0xbbccccddddeeeeff
+d9:   .dword 0x000000ddaaaabbbb
+d10:  .dword 0x5555dddd3333bbbb
+d11:  .dword 0x9999999999999999
+d12:  .dword 56
+d13:  .dword 8
+d14:  .dword 57
+d15:  .dword 0x000000ddaaaac98b
+d16:  .dword 0xffffffffdead00dd
+d17:  .dword 0xffffffffc0de0000
+d18:  .dword 0x0000123400000000
+d19:  .dword 0xffffabcddead00dd
+d20:  .dword 0xc0de000000000000
+d21:  .dword 0x8000abcddead00dd
+dmask:.dword 0xffffffffffff0000
+dval1: .word 0x1234abcd
+dval2: .word 0xffee0000
+dval3:	.dword 0xffffffffffffffff
+  .fill 240,1,0
+dval4:	.dword 0x5555555555555555
+  .fill  264,1,0
+dval5:	.dword 0xaaaaaaaaaaaaaaaa
+
+  .text
+
+  setup
+
+  .set noreorder
+
+  .ent DIAG
+DIAG:
+
+  writemsg "[1] Test DMUL"
+  r6ck_2r dmul, 6, 5, 30
+  r6ck_2r dmul, -7, 9, -63
+  r6ck_2r dmul, -1, 1, -1
+  r6ck_2dr dmul, d1, d2, dlo
+
+  writemsg "[2] Test DMUH"
+  r6ck_2r dmuh, 6, 5, 0
+  r6ck_2r dmuh, -7, 9, 0xffffffffffffffff
+  r6ck_2r dmuh, -1, 1, -1
+  r6ck_2dr dmuh, d1, d2, dhi
+
+  writemsg "[3] Test DMULU"
+  r6ck_2r dmulu, 12, 10, 120
+  r6ck_2r dmulu, -1, 1, -1
+  r6ck_2dr dmulu, d1, d2, dlo
+
+  writemsg "[4] Test DMUHU"
+  r6ck_2r dmuhu, 12, 10, 0
+  r6ck_2r dmuhu, -1, 1, 0
+  r6ck_2dr dmuhu, d1, d2, dhiu
+
+  writemsg "[5] Test DDIV"
+  r6ck_2r ddiv, 10001, 10, 1000
+  r6ck_2r ddiv, -123456, 560, -220
+  r6ck_2dr ddiv, d1, d2, d3
+
+  writemsg "[6] Test DMOD"
+  r6ck_2r dmod, 10001, 10, 1
+  r6ck_2r dmod, -123456, 560, 0xffffffffffffff00
+  r6ck_2dr dmod, d1, d2, d4
+
+  writemsg "[7] Test DDIVU"
+  r6ck_2r ddivu, 9, 100, 0
+  r6ck_2dr ddivu, d1, d2, d6
+
+  writemsg "[8] Test DMODU"
+  r6ck_2r dmodu, 9, 100, 9
+  r6ck_2dr dmodu, d1, d2, d5
+
+  writemsg "[9] Test DALIGN"
+  r6ck_2dr1i dalign, d7, d1, 3, d8
+  r6ck_2dr1i dalign, d1, d5, 4, d9
+
+  writemsg "[10] Test DBITSWAP"
+  r6ck_1dr dbitswap, d1, d10
+  r6ck_1dr dbitswap, d11, d11
+
+  writemsg "[11] Test DCLZ"
+  r6ck_1dr dclz, d5, d12
+  r6ck_1dr dclz, d6, d13
+
+  writemsg "[12] Test DCLO"
+  r6ck_1dr dclo, d5, d0
+  r6ck_1dr dclo, dhi, d14
+
+  writemsg "[13] Test DLSA"
+  r6ck_2r1i dlsa, 0x82, 0x2000068, 4, 0x2000888
+  r6ck_2dr1i dlsa, d5, d9, 4, d15
+
+  writemsg "[14] Test DAUI"
+  r6ck_1dr1i daui, d5, 0xdead, d16
+  r6ck_1dr1i daui, d0, 0xc0de, d17
+
+  writemsg "[15] Test DAHI"
+  r6ck_0dr1i dahi, d0, 0x1234, d18
+  r6ck_0dr1i dahi, d16, 0xabce, d19
+
+  writemsg "[16] Test DATI"
+  r6ck_0dr1i dati, d0, 0xc0de, d20
+  r6ck_0dr1i dati, d19, 0x8001, d21
+
+  writemsg "[17] Test LDPC"
+  ld $5, dval
+  nop
+  ldpc $4, dval
+  fp_assert $4, $5
+
+  writemsg "[18] Test LWUPC"
+  lwu $5, dval1
+  lwupc $4, dval1
+  fp_assert $4, $5
+  lwu $5, dval2
+  lwupc $4, dval2
+  fp_assert $4, $5
+
+  writemsg "[19] Test LLD"
+  ld $5, dval3
+  dla $3, dval4
+  lld $4, -248($3)
+  fp_assert $4, $5
+
+  writemsg "[20] Test SCD"
+  lld $4, -248($3)
+  dli $4, 0xafaf
+  scd $4, -248($3)
+  ld $5, dval3
+  dli $4, 0xafaf
+  fp_assert $4, $5
+
+  pass
+
+  .end DIAG
diff --git a/sim/testsuite/mips/r6-branch.s b/sim/testsuite/mips/r6-branch.s
new file mode 100644
index 00000000000..2d905ba97e6
--- /dev/null
+++ b/sim/testsuite/mips/r6-branch.s
@@ -0,0 +1,291 @@
+# mips r6 branch tests (non FPU)
+# mach: mips32r6 mips64r6
+# as:   -mabi=eabi
+# ld:   -N -Ttext=0x80010000
+# output: *\\npass\\n
+
+  .include "testutils.inc"
+  .include "utils-r6.inc"
+
+  setup
+
+  .set noreorder
+
+  .ent DIAG
+DIAG:
+  li $14, 0xffffffff
+  li $13, 0x123
+  li $12, 0x45
+  li $7, 0x45
+  li $8, 0xfffffffe
+  li $9, 2147483647
+  li $11, 0
+
+  writemsg "[1] Test BOVC"
+  bovc $12, $13, Lfail
+  nop
+  bovc $9, $13, L2
+  nop
+  fail
+
+L2:
+  writemsg "[2] Test BNVC"
+  bnvc $9, $13, Lfail
+  nop
+  bnvc $12, $13, L3
+  nop
+  fail
+
+L3:
+  writemsg "[3] Test BEQC"
+  beqc $12, $13, Lfail
+  nop
+  beqc $12, $7, L4
+  nop
+  fail
+
+L4:
+  writemsg "[4] Test BNEC"
+  bnec $12, $7, Lfail
+  nop
+  bnec $12, $13, L5
+  nop
+  fail
+
+L5:
+  writemsg "[5] Test BLTC"
+  bltc $13, $12, Lfail
+  nop
+  bltc $12, $13, L6
+  nop
+  fail
+
+L6:
+#  writemsg "[6] Test BLEC"
+#  blec $13, $12, Lfail
+#  nop
+#  blec $7, $12, L7
+#  nop
+#  fail
+
+L7:
+  writemsg "[7] Test BGEC"
+  bgec $12, $13, Lfail
+  nop
+  bgec $13, $12, L8
+  nop
+  fail
+
+L8:
+#  writemsg "[8] Test BGTC"
+#  bgtc $12, $13, Lfail
+#  nop
+#  bgtc $13, $12, L9
+#  nop
+#  fail
+
+
+L9:
+  writemsg "[9] Test BLTUC"
+  bltuc $14, $13, Lfail
+  nop
+  bltuc $8, $14, L10
+  nop
+  fail
+
+L10:
+#  writemsg "[10] Test BLEUC"
+#  bleuc $14, $13, Lfail
+#  nop
+#  bleuc $8, $14, L11
+#  nop
+#  fail
+
+L11:
+  writemsg "[11] Test BGEUC"
+  bgeuc $13, $14, Lfail
+  nop
+  bgeuc $14, $8, L12
+  nop
+  fail
+
+L12:
+#  writemsg "[12] Test BGTUC"
+#  bgtuc $13, $14, Lfail
+#  nop
+#  bgtuc $14, $8, L13
+#  nop
+#  fail
+
+L13:
+  writemsg "[13] Test BLTZC"
+  bltzc $13, Lfail
+  nop
+  bltzc $11, Lfail
+  nop
+  bltzc $14, L14
+  nop
+  fail
+
+L14:
+  writemsg "[14] Test BLEZC"
+  blezc $13, Lfail
+  nop
+  blezc $11, L145
+  nop
+  fail
+L145:
+  blezc $14, L15
+  nop
+  fail
+
+L15:
+  writemsg "[15] Test BGEZC"
+  bgezc $8, Lfail
+  nop
+  bgezc $11, L155
+  nop
+  fail
+L155:
+  bgezc $13, L16
+  nop
+  fail
+
+L16:
+  writemsg "[16] Test BGTZC"
+  bgtzc $8, Lfail
+  nop
+  bgtzc $11, Lfail
+  nop
+  bgtzc $13, L17
+  nop
+  fail
+
+  li $10, 0
+
+L17:
+  writemsg "[17] Test BLEZALC"
+  blezalc $12, Lfail
+  nop
+  blezalc $11, Lret
+  li $10, 1
+  beqzc $10, L175
+  nop
+  fail
+L175:
+  blezalc $14, Lret
+  li $10, 1
+  beqzc $10, L18
+  nop
+  fail
+
+L18:
+  writemsg "[18] Test BGEZALC"
+  bgezalc $14, Lfail
+  nop
+  bgezalc $11, Lret
+  li $10, 1
+  beqzc $10, L185
+  nop
+  fail
+L185:
+  bgezalc $12, Lret
+  li $10, 1
+  beqzc $10, L19
+  nop
+  fail
+
+L19:
+  writemsg "[19] Test BGTZALC"
+  bgtzalc $14, Lfail
+  nop
+  bgtzalc $11, Lfail
+  nop
+  bgtzalc $12, Lret
+  li $10, 1
+  beqzc $10, L20
+  nop
+  fail
+
+L20:
+  writemsg "[20] Test BLTZALC"
+  bltzalc $12, Lfail
+  nop
+  bltzalc $11, Lfail
+  nop
+  bltzalc $14, Lret
+  li $10, 1
+  beqzc $10, L21
+  nop
+  fail
+
+L21:
+  writemsg "[21] Test BC"
+  bc L22
+  fail
+
+L22:
+  writemsg "[22] Test BALC"
+  balc Lret
+  li $10, 1
+  beqzc $10, L23
+  nop
+  fail
+
+L23:
+  writemsg "[23] Test JIC"
+  jal GetPC
+  nop
+  jic $6, 4
+  nop
+  fail
+
+L24:
+  writemsg "[24] Test JIALC"
+  li $10, 1
+  jal GetPC
+  nop
+  jialc $6, 20
+  nop
+  beqzc $10, L25
+  nop
+  fail
+
+LJIALCRET:
+  li $10, 0
+  jr $ra
+  nop
+
+L25:
+  writemsg "[25] Test NAL"
+  jal GetPC
+  nop
+  move $11, $6
+  nal
+  nop
+  addiu $11, 12
+  beqc $11, $31, L26
+  nop
+  fail
+
+L26:
+  writemsg "[26] Test BAL"
+  balc Lret
+  li $10, 1
+  beqzc $10, Lend
+  nop
+  fail
+
+Lend:
+  pass
+
+Lfail:
+  fail
+
+  .end DIAG
+
+Lret:
+  li $10, 0
+  addiu $ra, 4
+  jr $ra
+  nop
diff --git a/sim/testsuite/mips/r6-forbidden.s b/sim/testsuite/mips/r6-forbidden.s
new file mode 100644
index 00000000000..6ce56d392d9
--- /dev/null
+++ b/sim/testsuite/mips/r6-forbidden.s
@@ -0,0 +1,51 @@
+# mips r6 test for forbidden slot behaviour
+# mach: mips32r6 mips64r6
+# as:   -mabi=eabi
+# ld:   -N -Ttext=0x80010000
+# output: *\\nReservedInstruction at PC = *\\nprogram stopped with signal 4 (Illegal instruction).\\n
+# xerror:
+
+  .include "testutils.inc"
+
+  setup
+
+  .set noreorder
+
+  .ent DIAG
+DIAG:
+
+  writemsg "[1] Test if FS is ignored when branch is taken"
+  li $4, 0
+  beqzalc $4, L1
+  bc L2
+
+L2:
+  fail
+
+L1:
+  writemsg "[2] Test if FS is used when branch is not taken"
+  li $4, 1
+  blezc $4, L3
+  addiu $4, $4, 1
+  li $2, 2
+  beq $4, $2, L4
+
+L3:
+  nop
+  fail
+
+L4:
+  writemsg "[3] Test if FS causes an error when it contains a branch"
+  li $4, 3
+  beqzalc $4, L6
+  bc L5
+
+L5:
+  nop
+  fail
+
+L6:
+  #There is no passing condition here, all routes to the end indicate failure
+  fail
+
+  .end DIAG
diff --git a/sim/testsuite/mips/r6-fpu.s b/sim/testsuite/mips/r6-fpu.s
new file mode 100644
index 00000000000..14a2ea58f83
--- /dev/null
+++ b/sim/testsuite/mips/r6-fpu.s
@@ -0,0 +1,446 @@
+# mips r6 fpu test for FMADD/FMSUB etc.
+# mach:  mips64r6
+# as:    -mabi=eabi
+# ld:    -N -Ttext=0x80010000
+# output: *\\npass\\n
+
+  .include "testutils.inc"
+  .include "utils-r6.inc"
+
+  setup
+
+  .set noreorder
+
+  .ent DIAG
+DIAG:
+
+  writemsg "[1] Test qNaN format is 754-2008"
+  li $4, 0x0
+  li $5, 0x0
+  li $6, 0x7fc00000
+  mtc1 $4, $f2
+  mtc1 $5, $f4
+  div.s $f6, $f2, $f4
+  mfc1 $8, $f6
+  fp_assert $6, $8
+
+  writemsg "[2] Test maddf.s"
+  r6ck_3s maddf.s, 0x0, 0x0, 0x0, 0x0
+  r6ck_3s maddf.s, 0x3f800000, 0x3f800000, 0x3f800000, 0x40000000
+  r6ck_3s maddf.s, 0xc0b1f5c3, 0x40490fd0, 0x402df854, 0x403e9f5d
+
+  writemsg "[3] Test maddf.d"
+  r6ck_3d maddf.d, 0x0, 0x0, 0x0, 0x0
+  r6ck_3d maddf.d, 0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000, 0x4000000000000000
+  r6ck_3d maddf.d, 0xc0163eb851eb851f, 0x400921f9f01b866e, 0x4005bf0a8b24919b,  0x4007d3ebc14f6cee
+
+  writemsg "[4] Test msubf.s"
+  r6ck_3s msubf.s, 0x0, 0x0, 0x0, 0x0
+  r6ck_3s msubf.s, 0x3f800000, 0x3f800000, 0x3f800000, 0x0
+  r6ck_3s msubf.s, 0xc0b1f5c3, 0x40490fd0, 0x402df854, 0xc1619d9a
+
+  writemsg "[5] Test msubf.d"
+  r6ck_3d msubf.d, 0x0, 0x0, 0x0, 0x0
+  r6ck_3d msubf.d, 0x3ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d msubf.d, 0xc0163eb851eb851f, 0x400921f9f01b866e, 0x4005bf0a8b24919b,  0xc02c33b3423f605b
+
+  writemsg "[6] Test CMP.af.s"
+  r6ck_3s cmp.af.s, 0x0, 0x3f800000, 0x3f800000, 0x0
+  r6ck_3s cmp.af.s, 0x0, 0x00000000, 0x3f800000, 0x0
+
+  writemsg "[7] Test CMP.af.d"
+  r6ck_3d cmp.af.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.af.d, 0x0, 0x0000000000000000, 0x3ff0000000000000, 0x0
+
+  writemsg "[8] Test CMP.eq.s"
+  r6ck_3s cmp.eq.s, 0x0, 0x3f800000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.eq.s, 0x0, 0x00000000, 0x3f800000, 0x0
+  r6ck_3s cmp.eq.s, 0x0, 0x80000000, 0x00000000, 0xffffffff
+  r6ck_3s cmp.eq.s, 0x0, 0x7fc00000, 0x7fc00000, 0x0
+  r6ck_3s cmp.eq.s, 0x0, 0x7fc00000, 0xffc00000, 0x0
+  r6ck_3s cmp.eq.s, 0x0, 0x7fa00000, 0x7fa00000, 0x0
+  r6ck_3s cmp.eq.s, 0x0, 0x7fa00000, 0x7fc00000, 0x0
+  r6ck_3s cmp.eq.s, 0x0, 0x7f800000, 0x7f800000, 0xffffffff
+  r6ck_3s cmp.eq.s, 0x0, 0xff800000, 0xff800000, 0xffffffff
+
+  writemsg "[9] Test CMP.eq.d"
+  r6ck_3d cmp.eq.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.eq.d, 0x0, 0x0000000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.eq.d, 0x0, 0x8000000000000000, 0x0000000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.eq.d, 0x0, 0x7ff8000000000000, 0x7ff8000000000000, 0x0
+  r6ck_3d cmp.eq.d, 0x0, 0x7ff8000000000000, 0xffc0000000000000, 0x0
+  r6ck_3d cmp.eq.d, 0x0, 0x7fa0000000000000, 0x7fa0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.eq.d, 0x0, 0x7fa0000000000000, 0x7ff8000000000000, 0x0
+  r6ck_3d cmp.eq.d, 0x0, 0x7ff0000000000000, 0x7ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.eq.d, 0x0, 0xfff0000000000000, 0xfff0000000000000, 0xffffffffffffffff
+
+  writemsg "[10] Test CMP.ne.s"
+  r6ck_3s cmp.ne.s, 0x0, 0x3f800000, 0x3f800000, 0x0
+  r6ck_3s cmp.ne.s, 0x0, 0x00000000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.ne.s, 0x0, 0x80000000, 0x00000000, 0x0
+  r6ck_3s cmp.ne.s, 0x0, 0x7fc00000, 0x7fc00000, 0x0
+  r6ck_3s cmp.ne.s, 0x0, 0x7fc00000, 0xffc00000, 0x0
+  r6ck_3s cmp.ne.s, 0x0, 0x7fa00000, 0x7fa00000, 0x0
+  r6ck_3s cmp.ne.s, 0x0, 0x7fa00000, 0x7fc00000, 0x0
+  r6ck_3s cmp.ne.s, 0x0, 0x7f800000, 0x7f800000, 0x0
+  r6ck_3s cmp.ne.s, 0x0, 0xff800000, 0xff800000, 0x0
+
+  writemsg "[11] Test CMP.ne.d"
+  r6ck_3d cmp.ne.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.ne.d, 0x0, 0x0000000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ne.d, 0x0, 0x8000000000000000, 0x0000000000000000, 0x0
+  r6ck_3d cmp.ne.d, 0x0, 0x7ff8000000000000, 0x7ff8000000000000, 0x0
+  r6ck_3d cmp.ne.d, 0x0, 0x7ff8000000000000, 0xffc0000000000000, 0x0
+  r6ck_3d cmp.ne.d, 0x0, 0x7fa0000000000000, 0x7fa0000000000000, 0x0
+  r6ck_3d cmp.ne.d, 0x0, 0x7fa0000000000000, 0x7ff8000000000000, 0x0
+  r6ck_3d cmp.ne.d, 0x0, 0x7ff0000000000000, 0x7ff0000000000000, 0x0
+  r6ck_3d cmp.ne.d, 0x0, 0xfff0000000000000, 0xfff0000000000000, 0x0
+  r6ck_3d cmp.ne.d, 0x0, 0xab19546120965720, 0x92452014f194abc3, 0xffffffffffffffff
+
+  writemsg "[12] Test CMP.lt.s"
+  r6ck_3s cmp.lt.s, 0x0, 0x3f800000, 0x3f800000, 0x0
+  r6ck_3s cmp.lt.s, 0x0, 0x00000000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.lt.s, 0x0, 0xbf800000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.lt.s, 0x0, 0x3f800000, 0xbf800000, 0x0
+  r6ck_3s cmp.lt.s, 0x0, 0xff800000, 0xbf800000, 0xffffffff
+  r6ck_3s cmp.lt.s, 0x0, 0xbf800000, 0x7f800000, 0xffffffff
+  r6ck_3s cmp.lt.s, 0x0, 0xbf800000, 0xff800000, 0x0
+  r6ck_3s cmp.lt.s, 0x0, 0x7f800000, 0xbf800000, 0x0
+
+  writemsg "[13] Test CMP.lt.d"
+  r6ck_3d cmp.lt.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.lt.d, 0x0, 0x0000000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.lt.d, 0x0, 0xbff0000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.lt.d, 0x0, 0x3ff0000000000000, 0xbff0000000000000, 0x0
+  r6ck_3d cmp.lt.d, 0x0, 0xfff0000000000000, 0xbff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.lt.d, 0x0, 0xbff0000000000000, 0x7ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.lt.d, 0x0, 0xbff0000000000000, 0xfff0000000000000, 0x0
+  r6ck_3d cmp.lt.d, 0x0, 0x7ff0000000000000, 0xbff0000000000000, 0x0
+
+  writemsg "[14] Test CMP.le.s"
+  r6ck_3s cmp.le.s, 0x0, 0x3f800000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.le.s, 0x0, 0x00000000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.le.s, 0x0, 0xbf800000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.le.s, 0x0, 0x3f800000, 0xbf800000, 0x0
+  r6ck_3s cmp.le.s, 0x0, 0xff800000, 0xbf800000, 0xffffffff
+  r6ck_3s cmp.le.s, 0x0, 0xbf800000, 0x7f800000, 0xffffffff
+  r6ck_3s cmp.le.s, 0x0, 0xbf800000, 0xff800000, 0x0
+  r6ck_3s cmp.le.s, 0x0, 0x7f800000, 0xbf800000, 0x0
+
+  writemsg "[15] Test CMP.le.d"
+  r6ck_3d cmp.le.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.le.d, 0x0, 0x0000000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.le.d, 0x0, 0xbff0000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.le.d, 0x0, 0x3ff0000000000000, 0xbff0000000000000, 0x0
+  r6ck_3d cmp.le.d, 0x0, 0xfff0000000000000, 0xbff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.le.d, 0x0, 0xbff0000000000000, 0x7ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.le.d, 0x0, 0xbff0000000000000, 0xfff0000000000000, 0x0
+  r6ck_3d cmp.le.d, 0x0, 0x7ff0000000000000, 0xbff0000000000000, 0x0
+
+  writemsg "[16] Test CMP.un.s"
+  r6ck_3s cmp.un.s, 0x0, 0x3f800000, 0x3f800000, 0x0
+  r6ck_3s cmp.un.s, 0x0, 0x3f800000, 0xbf800000, 0x0
+  r6ck_3s cmp.un.s, 0x0, 0x3f800000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.un.s, 0x0, 0x7fc01234, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.un.s, 0x0, 0x7fc00000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.un.s, 0x0, 0x3f800000, 0xff800000, 0x0
+  r6ck_3s cmp.un.s, 0x0, 0x3f800000, 0x7f800000, 0x0
+
+  writemsg "[17] Test CMP.un.d"
+  r6ck_3d cmp.un.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.un.d, 0x0, 0x3ff0000000000000, 0xbff0000000000000, 0x0
+  r6ck_3d cmp.un.d, 0x0, 0x3ff0000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.un.d, 0x0, 0x7fc0123400000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.un.d, 0x0, 0x7ff8000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.un.d, 0x0, 0x3ff0000000000000, 0xfff0000000000000, 0x0
+  r6ck_3d cmp.un.d, 0x0, 0x3ff0000000000000, 0x7ff0000000000000, 0x0
+
+  writemsg "[18] Test CMP.or.s"
+  r6ck_3s cmp.or.s, 0x0, 0x3f800000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.or.s, 0x0, 0xbf800000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.or.s, 0x0, 0x3f800000, 0x7fc00000, 0x0
+  r6ck_3s cmp.or.s, 0x0, 0x7fc00000, 0x3f800000, 0x0
+  r6ck_3s cmp.or.s, 0x0, 0xffc00000, 0x3f800000, 0x0
+  r6ck_3s cmp.or.s, 0x0, 0x7fc01234, 0x7fc00000, 0x0
+  r6ck_3s cmp.or.s, 0x0, 0xff800000, 0x00000000, 0xffffffff
+  r6ck_3s cmp.or.s, 0x0, 0x00000000, 0x7f800000, 0xffffffff
+  r6ck_3s cmp.or.s, 0x0, 0x00000000, 0xff800000, 0xffffffff
+  r6ck_3s cmp.or.s, 0x0, 0x7f800000, 0x00000000, 0xffffffff
+  r6ck_3s cmp.or.s, 0x0, 0x7f800000, 0x00000000, 0xffffffff
+
+  writemsg "[19] Test CMP.or.d"
+  r6ck_3d cmp.or.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.or.d, 0x0, 0xbff0000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.or.d, 0x0, 0x3ff0000000000000, 0x7ff8000000000000, 0x0
+  r6ck_3d cmp.or.d, 0x0, 0x7ff8000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.or.d, 0x0, 0xfff8000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.or.d, 0x0, 0x7ff8123492134352, 0x7ff8000000000000, 0x0
+  r6ck_3d cmp.or.d, 0x0, 0xfff0000000000000, 0x0000000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.or.d, 0x0, 0x0000000000000000, 0x7ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.or.d, 0x0, 0x0000000000000000, 0xfff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.or.d, 0x0, 0x7ff0000000000000, 0x0000000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.or.d, 0x0, 0x7ff0000000000000, 0x0000000000000000, 0xffffffffffffffff
+
+  writemsg "[20] Test CMP.ueq.s"
+  r6ck_3s cmp.ueq.s, 0x0, 0x3f800000, 0x00000000, 0x0
+  r6ck_3s cmp.ueq.s, 0x0, 0x3f800000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.ueq.s, 0x0, 0x7fc00000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.ueq.s, 0x0, 0x3f800000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.ueq.s, 0x0, 0x00000000, 0x3f800000, 0x0
+  r6ck_3s cmp.ueq.s, 0x0, 0x80000000, 0x00000000, 0xffffffff
+  r6ck_3s cmp.ueq.s, 0x0, 0x7f800000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.ueq.s, 0x0, 0xff800000, 0xff800000, 0xffffffff
+
+  writemsg "[21] Test CMP.ueq.d"
+  r6ck_3d cmp.ueq.d, 0x0, 0x3ff0000000000000, 0x0000000000000000, 0x0
+  r6ck_3d cmp.ueq.d, 0x0, 0x3ff0000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ueq.d, 0x0, 0x7ff8000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ueq.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ueq.d, 0x0, 0x0000000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.ueq.d, 0x0, 0x8000000000000000, 0x0000000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ueq.d, 0x0, 0x7ff0000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ueq.d, 0x0, 0xfff0000000000000, 0xfff0000000000000, 0xffffffffffffffff
+
+  writemsg "[22] Test CMP.une.s"
+  r6ck_3s cmp.une.s, 0x0, 0x3f800000, 0x3f800000, 0x0
+  r6ck_3s cmp.une.s, 0x0, 0x3f800000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.une.s, 0x0, 0x7fc00000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.une.s, 0x0, 0x3f800000, 0x3f800000, 0x0
+  r6ck_3s cmp.une.s, 0x0, 0x00000000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.une.s, 0x0, 0x80000000, 0x00000000, 0x0
+  r6ck_3s cmp.une.s, 0x0, 0x7f800000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.une.s, 0x0, 0xff800000, 0xff800000, 0x0
+
+  writemsg "[23] Test CMP.une.d"
+  r6ck_3d cmp.une.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.une.d, 0x0, 0x3ff0000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.une.d, 0x0, 0x7ff8000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.une.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.une.d, 0x0, 0x0000000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.une.d, 0x0, 0x8000000000000000, 0x0000000000000000, 0x0
+  r6ck_3d cmp.une.d, 0x0, 0x7ff0000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.une.d, 0x0, 0xfff0000000000000, 0xfff0000000000000, 0x0
+
+  writemsg "[24] Test CMP.ult.s"
+  r6ck_3s cmp.ult.s, 0x0, 0x3f800000, 0x3f800000, 0x0
+  r6ck_3s cmp.ult.s, 0x0, 0x3f800000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.ult.s, 0x0, 0x7fc00000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.ult.s, 0x0, 0x00000000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.ult.s, 0x0, 0xbf800000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.ult.s, 0x0, 0x3f800000, 0xbf800000, 0x0
+
+  writemsg "[25] Test CMP.ult.d"
+  r6ck_3d cmp.ult.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0x0
+  r6ck_3d cmp.ult.d, 0x0, 0x3ff0000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ult.d, 0x0, 0x7ff8000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ult.d, 0x0, 0x0000000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ult.d, 0x0, 0xbff0000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ult.d, 0x0, 0x3ff0000000000000, 0xbff0000000000000, 0x0
+
+  writemsg "[26] Test CMP.ule.s"
+  r6ck_3s cmp.ule.s, 0x0, 0x3f800000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.ule.s, 0x0, 0x7fc00000, 0x7fc00000, 0xffffffff
+  r6ck_3s cmp.ule.s, 0x0, 0x3f800000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.ule.s, 0x0, 0x00000000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.ule.s, 0x0, 0xbf800000, 0x3f800000, 0xffffffff
+  r6ck_3s cmp.ule.s, 0x0, 0x3f800000, 0xbf800000, 0x0
+  r6ck_3s cmp.ule.s, 0x0, 0x3f800000, 0xff800000, 0x0
+
+  writemsg "[27] Test CMP.ule.d"
+  r6ck_3d cmp.ule.d, 0x0, 0x3ff0000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ule.d, 0x0, 0x7ff8000000000000, 0x7ff8000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ule.d, 0x0, 0x3ff0000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ule.d, 0x0, 0x0000000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ule.d, 0x0, 0xbff0000000000000, 0x3ff0000000000000, 0xffffffffffffffff
+  r6ck_3d cmp.ule.d, 0x0, 0x3ff0000000000000, 0xbff0000000000000, 0x0
+  r6ck_3d cmp.ule.d, 0x0, 0x3ff0000000000000, 0xfff0000000000000, 0x0
+
+  writemsg "[28] Test rint.s"
+  r6ck_2s rint.s, 0x0, 0x3fbf10cb, 0x3f800000
+  r6ck_2s rint.s, 0x0, 0xb9011423, 0x0
+  r6ck_2s rint.s, 0x0, 0x43fa4687, 0x43fa8000
+  r6ck_2s rint.s, 0x0, 0x41380000, 0x41400000
+  r6ck_2s rint.s, 0x0, 0x3ff33333, 0x40000000
+
+  writemsg "[29] Test rint.d"
+  r6ck_2d rint.d, 0x0, 0x3ff1f9a6b50b0f28, 0x3ff0000000000000
+  r6ck_2d rint.d, 0x0, 0xbf543bf727136a40, 0x0
+  r6ck_2d rint.d, 0x0, 0x407f48d0e5604189, 0x407f500000000000
+  r6ck_2d rint.d, 0x0, 0x5b7c2d43b93b0a8c, 0x5b7c2d43b93b0a8c,
+
+  writemsg "[30] Test class.s"
+  r6ck_2s class.s, 0x0, 0x7f800010, 0x1
+  r6ck_2s class.s, 0x0, 0x7fc00000, 0x2
+  r6ck_2s class.s, 0x0, 0xff800000, 0x4
+  r6ck_2s class.s, 0x0, 0xbf800000, 0x8
+  r6ck_2s class.s, 0x0, 0x80000001, 0x10
+  r6ck_2s class.s, 0x0, 0x80000000, 0x20
+  r6ck_2s class.s, 0x0, 0x7f800000, 0x40
+  r6ck_2s class.s, 0x0, 0x3f800000, 0x80
+  r6ck_2s class.s, 0x0, 0x00000001, 0x100
+  r6ck_2s class.s, 0x0, 0x00000000, 0x200
+
+  writemsg "[31] Test class.d"
+  r6ck_2d class.d, 0x0, 0x7ff0000000000010, 0x1
+  r6ck_2d class.d, 0x0, 0x7ff8000000000000, 0x2
+  r6ck_2d class.d, 0x0, 0xfff0000000000000, 0x4
+  r6ck_2d class.d, 0x0, 0xbff0000000000000, 0x8
+  r6ck_2d class.d, 0x0, 0x8000000000000001, 0x10
+  r6ck_2d class.d, 0x0, 0x8000000000000000, 0x20
+  r6ck_2d class.d, 0x0, 0x7ff0000000000000, 0x40
+  r6ck_2d class.d, 0x0, 0x3ff0000000000000, 0x80
+  r6ck_2d class.d, 0x0, 0x0000000000000001, 0x100
+  r6ck_2d class.d, 0x0, 0x0000000000000000, 0x200
+
+  writemsg "[32] Test min.s"
+  r6ck_3s min.s, 0x0, 0x3f800000, 0x0, 0x0
+  r6ck_3s min.s, 0x0, 0x0, 0x3f800000, 0x0
+  r6ck_3s min.s, 0x0, 0x7f800000, 0x3f800000, 0x3f800000
+  r6ck_3s min.s, 0x0, 0x3f800000, 0x7f800000, 0x3f800000
+  r6ck_3s min.s, 0x0, 0xff800000, 0xbf800000, 0xff800000
+  r6ck_3s min.s, 0x0, 0xbf800000, 0xff800000, 0xff800000
+  r6ck_3s min.s, 0x0, 0x7fffffff, 0x3f800000, 0x3f800000
+  r6ck_3s min.s, 0x0, 0x3f800000, 0x7fffffff, 0x3f800000
+
+  writemsg "[33] Test min.d"
+  r6ck_3d min.d, 0x0, 0x3ff0000000000000, 0x0, 0x0
+  r6ck_3d min.d, 0x0, 0x0, 0x3ff0000000000000, 0x0
+  r6ck_3d min.d, 0x0, 0x7ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000
+  r6ck_3d min.d, 0x0, 0x3ff0000000000000, 0x7ff0000000000000, 0x3ff0000000000000
+  r6ck_3d min.d, 0x0, 0xfff0000000000000, 0xbff0000000000000, 0xfff0000000000000
+  r6ck_3d min.d, 0x0, 0xbff0000000000000, 0xfff0000000000000, 0xfff0000000000000
+  r6ck_3d min.d, 0x0, 0x7fffffffffffffff, 0x3ff0000000000000, 0x3ff0000000000000
+  r6ck_3d min.d, 0x0, 0x3ff0000000000000, 0x7fffffffffffffff, 0x3ff0000000000000
+
+  writemsg "[34] Test max.s"
+  r6ck_3s max.s, 0x0, 0x3f800000, 0x0, 0x3f800000
+  r6ck_3s max.s, 0x0, 0x0, 0x3f800000, 0x3f800000
+  r6ck_3s max.s, 0x0, 0x7f800000, 0x3f800000, 0x7f800000
+  r6ck_3s max.s, 0x0, 0x3f800000, 0x7f800000, 0x7f800000
+  r6ck_3s max.s, 0x0, 0xff800000, 0xbf800000, 0xbf800000
+  r6ck_3s max.s, 0x0, 0xbf800000, 0xff800000, 0xbf800000
+  r6ck_3s max.s, 0x0, 0x7fffffff, 0x3f800000, 0x3f800000
+  r6ck_3s max.s, 0x0, 0x3f800000, 0x7fffffff, 0x3f800000
+
+  writemsg "[35] Test max.d"
+  r6ck_3d max.d, 0x0, 0x3ff0000000000000, 0x0, 0x3ff0000000000000
+  r6ck_3d max.d, 0x0, 0x0, 0x3ff0000000000000, 0x3ff0000000000000
+  r6ck_3d max.d, 0x0, 0x7ff0000000000000, 0x3ff0000000000000, 0x7ff0000000000000
+  r6ck_3d max.d, 0x0, 0x3ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000
+  r6ck_3d max.d, 0x0, 0xfff0000000000000, 0xbff0000000000000, 0xbff0000000000000
+  r6ck_3d max.d, 0x0, 0xbff0000000000000, 0xfff0000000000000, 0xbff0000000000000
+  r6ck_3d max.d, 0x0, 0x7fffffffffffffff, 0x3ff0000000000000, 0x3ff0000000000000
+  r6ck_3d max.d, 0x0, 0x3ff0000000000000, 0x7fffffffffffffff, 0x3ff0000000000000
+
+  writemsg "[36] Test mina.s"
+  r6ck_3s mina.s, 0x0, 0x3f800000, 0x0, 0x0
+  r6ck_3s mina.s, 0x0, 0x0, 0x3f800000, 0x0
+  r6ck_3s mina.s, 0x0, 0x7f800000, 0x3f800000, 0x3f800000
+  r6ck_3s mina.s, 0x0, 0x3f800000, 0x7f800000, 0x3f800000
+  r6ck_3s mina.s, 0x0, 0xff800000, 0xbf800000, 0xbf800000
+  r6ck_3s mina.s, 0x0, 0xbf800000, 0xff800000, 0xbf800000
+  r6ck_3s mina.s, 0x0, 0x7fffffff, 0x3f800000, 0x3f800000
+  r6ck_3s mina.s, 0x0, 0x3f800000, 0x7fffffff, 0x3f800000
+  r6ck_3s mina.s, 0x0, 0xc0000000, 0x3f800000, 0x3f800000
+  r6ck_3s mina.s, 0x0, 0x3f800000, 0xc0000000, 0x3f800000
+
+  writemsg "[37] Test mina.d"
+  r6ck_3d mina.d, 0x0, 0x3ff0000000000000, 0x0, 0x0
+  r6ck_3d mina.d, 0x0, 0x0, 0x3ff0000000000000, 0x0
+  r6ck_3d mina.d, 0x0, 0x7ff0000000000000, 0x3ff0000000000000, 0x3ff0000000000000
+  r6ck_3d mina.d, 0x0, 0x3ff0000000000000, 0x7ff0000000000000, 0x3ff0000000000000
+  r6ck_3d mina.d, 0x0, 0xfff0000000000000, 0xbff0000000000000, 0xbff0000000000000
+  r6ck_3d mina.d, 0x0, 0xbff0000000000000, 0xfff0000000000000, 0xbff0000000000000
+  r6ck_3d mina.d, 0x0, 0x7fffffffffffffff, 0x3ff0000000000000, 0x3ff0000000000000
+  r6ck_3d mina.d, 0x0, 0x3ff0000000000000, 0x7fffffffffffffff, 0x3ff0000000000000
+  r6ck_3d mina.d, 0x0, 0xc000000000000000, 0x3ff0000000000000, 0x3ff0000000000000
+  r6ck_3d mina.d, 0x0, 0x3ff0000000000000, 0xc000000000000000, 0x3ff0000000000000
+
+  writemsg "[38] Test maxa.s"
+  r6ck_3s maxa.s, 0x0, 0x3f800000, 0x0, 0x3f800000
+  r6ck_3s maxa.s, 0x0, 0x0, 0x3f800000, 0x3f800000
+  r6ck_3s maxa.s, 0x0, 0x7f800000, 0x3f800000, 0x7f800000
+  r6ck_3s maxa.s, 0x0, 0x3f800000, 0x7f800000, 0x7f800000
+  r6ck_3s maxa.s, 0x0, 0xff800000, 0xbf800000, 0xff800000
+  r6ck_3s maxa.s, 0x0, 0xbf800000, 0xff800000, 0xff800000
+  r6ck_3s maxa.s, 0x0, 0x7fffffff, 0x3f800000, 0x3f800000
+  r6ck_3s maxa.s, 0x0, 0x3f800000, 0x7fffffff, 0x3f800000
+  r6ck_3s maxa.s, 0x0, 0xc0000000, 0x3f800000, 0xc0000000
+  r6ck_3s maxa.s, 0x0, 0x3f800000, 0xc0000000, 0xc0000000
+
+  writemsg "[39] Test maxa.d"
+  r6ck_3d maxa.d, 0x0, 0x3ff0000000000000, 0x0, 0x3ff0000000000000
+  r6ck_3d maxa.d, 0x0, 0x0, 0x3ff0000000000000, 0x3ff0000000000000
+  r6ck_3d maxa.d, 0x0, 0x7ff0000000000000, 0x3ff0000000000000, 0x7ff0000000000000
+  r6ck_3d maxa.d, 0x0, 0x3ff0000000000000, 0x7ff0000000000000, 0x7ff0000000000000
+  r6ck_3d maxa.d, 0x0, 0xfff0000000000000, 0xbff0000000000000, 0xfff0000000000000
+  r6ck_3d maxa.d, 0x0, 0xbff0000000000000, 0xfff0000000000000, 0xfff0000000000000
+  r6ck_3d maxa.d, 0x0, 0x7fffffffffffffff, 0x3ff0000000000000, 0x3ff0000000000000
+  r6ck_3d maxa.d, 0x0, 0x3ff0000000000000, 0x7fffffffffffffff, 0x3ff0000000000000
+  r6ck_3d maxa.d, 0x0, 0xc000000000000000, 0x3ff0000000000000, 0xc000000000000000
+  r6ck_3d maxa.d, 0x0, 0x3ff0000000000000, 0xc000000000000000, 0xc000000000000000
+
+  writemsg "[40] Test sel.s"
+  r6ck_3s sel.s, 0x0, 0xabcdef12, 0x12345678, 0xabcdef12
+  r6ck_3s sel.s, 0x1, 0xdeadbeef, 0xcafe1234, 0xcafe1234
+  r6ck_3s sel.s, 0xfffffffe, 0xbadcafe0, 0x12345678, 0xbadcafe0
+  r6ck_3s sel.s, 0xffffffff, 0xdeadbeef, 0xcadf00ab, 0xcadf00ab
+
+  writemsg "[41] Test sel.d"
+  r6ck_3d sel.d, 0x0, 0xabcdef123456789, 0x12345678abcdefa, 0xabcdef123456789
+  r6ck_3d sel.d, 0x1, 0xdeadbeef1534567, 0xcafe12340145279, 0xcafe12340145279
+  r6ck_3d sel.d, 0xfffffffffffffffe, 0xbadcafe00efacdab, 0x1234567887654321, 0xbadcafe00efacdab
+  r6ck_3d sel.d, 0xffffffffffffffff, 0xdeadbeeffeebdaed, 0xcadf00abba00fdac, 0xcadf00abba00fdac
+
+  writemsg "[42] Test seleqz.s"
+  r6ck_3s seleqz.s, 0x0, 0x1234abcd, 0x0, 0x1234abcd
+  r6ck_3s seleqz.s, 0x0, 0xabcdef01, 0x1, 0x0
+  r6ck_3s seleqz.s, 0x0, 0xffeebbcc, 0xfffffffe, 0xffeebbcc
+  r6ck_3s seleqz.s, 0x0, 0x12345678, 0xffffffff, 0
+
+  writemsg "[43] Test seleqz.d"
+  r6ck_3d seleqz.d, 0x0, 0x1234abcddcba4321, 0x0, 0x1234abcddcba4321
+  r6ck_3d seleqz.d, 0x0, 0xabcdef0110fedcba, 0x1, 0x0
+  r6ck_3d seleqz.d, 0x0, 0xffeebbccccbbeeff, 0xfffffffffffffffe, 0xffeebbccccbbeeff
+  r6ck_3d seleqz.d, 0x0, 0x1234567887654321, 0xffffffffffffffff, 0x0
+
+  writemsg "[44] Test selnez.s"
+  r6ck_3s selnez.s, 0x0, 0x1234abcd, 0x0, 0x0
+  r6ck_3s selnez.s, 0x0, 0xabcdef01, 0x1, 0xabcdef01
+  r6ck_3s selnez.s, 0x0, 0xffeebbcc, 0xfffffffe, 0x0
+  r6ck_3s selnez.s, 0x0, 0x12345678, 0xffffffff, 0x12345678
+
+  writemsg "[45] Test selnez.d"
+  r6ck_3d selnez.d, 0x0, 0x1234abcddcba4321, 0x0, 0x0
+  r6ck_3d selnez.d, 0x0, 0xabcdef0110fedcba, 0x1, 0xabcdef0110fedcba
+  r6ck_3d selnez.d, 0x0, 0xffeebbccccbbeeff, 0xfffffffffffffffe, 0x0
+  r6ck_3d selnez.d, 0x0, 0x1234567887654321, 0xffffffffffffffff, 0x1234567887654321
+
+  writemsg "[46] Test bc1eqz"
+  li $10, 0x01
+  mtc1 $10, $f2
+  mtc1 $0, $f4
+  bc1eqz $f2, L1
+  nop
+  bc1eqz $f4, L2
+  nop
+  fail
+
+L1:
+  fail
+
+L2:
+  writemsg "[47] Test bc1nez"
+  bc1nez $f4, L3
+  nop
+  bc1nez $f2, L4
+  nop
+  fail
+
+L3:
+  fail
+
+L4:
+  pass
+
+  .end DIAG
diff --git a/sim/testsuite/mips/r6-llsc-dp.s b/sim/testsuite/mips/r6-llsc-dp.s
new file mode 100644
index 00000000000..1eec3e4f056
--- /dev/null
+++ b/sim/testsuite/mips/r6-llsc-dp.s
@@ -0,0 +1,57 @@
+# mips64 specific r6 tests - paired LL/SC variants
+# mach:  mips64r6
+# as:    -mabi=eabi
+# ld:    -N -Ttext=0x80010000 -Tdata=0x80020000
+# output: *\\npass\\n
+
+  .include "testutils.inc"
+  .include "utils-r6.inc"
+
+  .data
+  .align 16
+test_data:
+	.word 0xaaaaaaaa
+	.word 0xbbbbbbbb
+	.word 0xcccccccc
+	.word 0xdddddddd
+end_check:
+	.byte 0
+	.byte 0
+	.byte 0
+	.byte 0x1
+
+  .text
+
+  setup
+
+  .ent DIAG
+DIAG:
+  writemsg "[1] Test LLWP"
+  llwp	$2, $3, test_data
+  checkpair_dword $2, $3, test_data, end_check
+
+  sll $2, $2, 1
+  srl $3, $3, 1
+  move  $s0, $2
+
+  scwp	$2, $3, test_data
+  check32 $2, 1
+  checkpair_dword $s0, $3, test_data, end_check
+  writemsg "[2] Test SCWP, done"
+
+  writemsg "[3] Test LLDP"
+  lldp	$2, $3, test_data
+  checkpair_qword $2, $3, test_data, end_check
+
+  dsll $2, $2, 1
+  dsrl $3, $3, 1
+  move	$s0, $2
+
+  scdp	$2, $3, test_data
+  check32 $2, 1
+  checkpair_qword $s0, $3, test_data, end_check
+  writemsg "[4] Test SCDP, done"
+
+  pass
+
+  .end DIAG
diff --git a/sim/testsuite/mips/r6-llsc-wp.s b/sim/testsuite/mips/r6-llsc-wp.s
new file mode 100644
index 00000000000..55ad9243fc8
--- /dev/null
+++ b/sim/testsuite/mips/r6-llsc-wp.s
@@ -0,0 +1,41 @@
+# mips32 specific r6 tests - paired LL/SC variants
+# mach:  mips32r6
+# as:    -mabi=eabi
+# ld:    -N -Ttext=0x80010000 -Tdata=0x80020000
+# output: *\\npass\\n
+
+  .include "testutils.inc"
+  .include "utils-r6.inc"
+
+  .data
+  .align 8
+test_data:
+	.word 0xaaaaaaaa
+	.word 0xbbbbbbbb
+end_check:
+	.byte 0
+	.byte 0
+	.byte 0
+	.byte 0x1
+  .text
+
+  setup
+
+  .ent DIAG
+DIAG:
+  writemsg "[1] Test LLWP"
+  llwp	$2, $3, test_data
+  checkpair_dword $2, $3, test_data, end_check
+
+  sll $2, $2, 1
+  srl $3, $3, 1
+  move  $s0, $2
+
+  scwp	$2, $3, test_data
+  check32 $2, 1
+  checkpair_dword $s0, $3, test_data, end_check
+  writemsg "[2] Test SCWP, done"
+
+pass
+
+  .end DIAG
diff --git a/sim/testsuite/mips/r6-removed.csv b/sim/testsuite/mips/r6-removed.csv
new file mode 100644
index 00000000000..5f2285c526e
--- /dev/null
+++ b/sim/testsuite/mips/r6-removed.csv
@@ -0,0 +1,68 @@
+BC1F,0x45000000
+BEQL,0x50000000
+BGEZAL,0x04310000
+BGEZALL,0x04130000
+BGEZL,0x04030000
+BLTZALL,0x04120000
+BLTZL,0x04020000
+BNEL,0x54000000
+C.DEQ.D,0x44000030
+CACHE,0xbc000000
+CVT.PS.S,0x46000026
+CVT.S.PL,0x46c00028
+CVT.S.PU,0x46c00020
+DCLO,0x70000025
+DCLZ,0x70000024
+LDL,0x68000000
+LDR,0x6c000000
+LDXC1,0x4c000001
+LL,0xc0000000
+LLD,0xd0000000
+LUXC1,0x4c000005
+LWL,0x88000000
+LWLE,0x7c000019
+LWR,0x98000000
+LWRE,0x7c00001a
+LWXC1,0x4c000000
+MADD,0x70000000
+MADD.D,0x4c000020
+MADDU,0x70000001
+MOVF,0x00000001
+MOVF.D,0x44000011
+MOVN.D,0x44000013
+MOVT,0x00010001
+MOVT.D,0x44010011
+MOVZ.D,0x44000012
+MSUB,0x70000004
+MSUB.D,0x4c000028
+MSUBU,0x70000005
+MUL,0x70000002
+NEG.S,0x44000007
+NMADD.D,0x4c000030
+NMSUB.D,0x4c000038
+PLL.PS,0x46c0002c
+PLU.PS,0x46c0002d
+PREF,0xcc000000
+PREFX,0x4c00000f
+PUL.PS,0x46c0005e
+PUU.PS,0x46c0002f
+RINT.fmt,0x4400001a
+SC,0xe0000000
+SCD,0xf0000000
+SDBBP,0x7000003f
+SDL,0xb0000000
+SDR,0xb4000000
+SDXC1,0x4c000009
+SUB.D,0x44000001
+SUXC1,0x4c00000d
+SWL,0xa8000000
+SWLE,0x7c000021
+SWR,0xb8000000
+SWRE,0x7c000022
+SWXC1,0x4c000008
+TEQI,0x040c0000
+TGEI,0x04080000
+TGEIU,0x04090000
+TLTI,0x040a0000
+TLTIU,0x040b0000
+TNEI,0x040c0000
diff --git a/sim/testsuite/mips/r6-removed.s b/sim/testsuite/mips/r6-removed.s
new file mode 100644
index 00000000000..4f2605fa6a7
--- /dev/null
+++ b/sim/testsuite/mips/r6-removed.s
@@ -0,0 +1,18 @@
+# Tests the instructions removed in R6 are correctly invalidated
+# mach: mips32r6 mips64r6
+# as:   -mabi=eabi
+# ld:   -N -Ttext=0x80010000
+# output: ReservedInstruction at PC = *\nprogram stopped with signal 4 (Illegal instruction).\n
+# xerror:
+
+  .include "testutils.inc"
+  .include "r6-removed.inc"
+
+  setup
+
+  .set noreorder
+  .ent DIAG
+DIAG:
+  removed_instr
+  fail
+  .end DIAG
diff --git a/sim/testsuite/mips/r6.s b/sim/testsuite/mips/r6.s
new file mode 100644
index 00000000000..d30ffffe137
--- /dev/null
+++ b/sim/testsuite/mips/r6.s
@@ -0,0 +1,163 @@
+# mips r6 tests (non FPU)
+# mach:  mips32r6 mips64r6
+# as:    -mabi=eabi
+# ld:    -N -Ttext=0x80010000
+# output: *\\npass\\n
+
+  .include "testutils.inc"
+  .include "utils-r6.inc"
+
+  setup
+
+  .data
+dval1:  .word 0xabcd1234
+dval2: .word 0x1234eeff
+  .fill 248,1,0
+dval3:	.word 0x55555555
+  .fill  260,1,0
+dval4:	.word 0xaaaaaaaa
+  .text
+
+  .set noreorder
+
+  .ent DIAG
+DIAG:
+
+  writemsg "[1] Test MUL"
+  r6ck_2r mul, 7, 9, 63
+  r6ck_2r mul, -7, -9, 63
+  r6ck_2r mul, 61, -11, -671
+  r6ck_2r mul, 1001, 1234, 1235234
+  r6ck_2r mul, 123456789, 999999, 0x7eb1e22b
+  r6ck_2r mul, 0xaaaabbbb, 0xccccdddd, 0x56787f6f
+
+  writemsg "[2] Test MUH"
+  r6ck_2r muh, 61, -11, 0xffffffff
+  r6ck_2r muh, 1001, 1234, 0
+  r6ck_2r muh, 123456789, 999999, 0x7048
+  r6ck_2r muh, 0xaaaabbbb, 0xccccdddd, 0x111107f7
+
+  writemsg "[3] Test MULU"
+  r6ck_2r mulu, 7, 9, 63
+  r6ck_2r mulu, -7, -9, 63
+  r6ck_2r mulu, 61, -11, -671
+  r6ck_2r mulu, 1001, 1234, 1235234
+  r6ck_2r mulu, 123456789, 999999, 0x7eb1e22b
+  r6ck_2r mulu, 0xaaaabbbb, 0xccccdddd, 0x56787f6f
+
+  writemsg "[4] Test MUHU"
+  r6ck_2r muhu, 1001, 1234, 0
+  r6ck_2r muhu, 123456789, 999999, 0x7048
+  r6ck_2r muhu, 0xaaaabbbb, 0xccccdddd, 0x8888a18f
+  r6ck_2r muhu, 0xaaaabbbb, 0xccccdddd, 0x8888a18f
+
+  writemsg "[5] Test DIV"
+  r6ck_2r div, 10001, 10, 1000
+  r6ck_2r div, -123456, 560, -220
+  r6ck_2r div, 9, 100, 0
+
+  writemsg "[6] Test MOD"
+  r6ck_2r mod, 10001, 10, 1
+  r6ck_2r mod, -123456, 560, 0xffffff00
+  r6ck_2r mod, 9, 100, 9
+
+  writemsg "[7] Test DIVU"
+  r6ck_2r divu, 10001, 10, 1000
+  r6ck_2r divu, -123456, 560, 0x750674
+  r6ck_2r divu, 9, 100, 0
+  r6ck_2r divu, 0xaaaabbbb, 3, 0x38e393e9
+
+  writemsg "[8] Test MODU"
+  r6ck_2r modu, 10001, 10, 1
+  r6ck_2r modu, -123456, 560, 0
+  r6ck_2r modu, 9, 100, 9
+  r6ck_2r modu, 0xaaaabbbb, 5, 4
+
+  writemsg "[9] Test LSA"
+  r6ck_2r1i lsa, 1, 2, 2, 6
+  r6ck_2r1i lsa, 0x8000, 0xa000, 1, 0x1a000
+  r6ck_2r1i lsa, 0x82, 0x2000068, 4, 0x2000888
+
+  writemsg "[10] Test AUI"
+  r6ck_1r1i aui, 0x0000c0de, 0xdead, 0xdeadc0de
+  r6ck_1r1i aui, 0x00005678, 0x1234, 0x12345678
+  r6ck_1r1i aui, 0x0000eeff, 0xabab, 0xababeeff
+
+  writemsg "[11] Test SELEQZ"
+  r6ck_2r seleqz, 0x1234, 0, 0x1234
+  r6ck_2r seleqz, 0x1234, 4, 0
+  r6ck_2r seleqz, 0x80010001, 0, 0x80010001
+
+  writemsg "[12] Test SELNEZ"
+  r6ck_2r selnez, 0x1234, 0, 0
+  r6ck_2r selnez, 0x1234, 1, 0x1234
+  r6ck_2r selnez, 0x80010001, 0xffffffff, 0x80010001
+
+  writemsg "[13] Test ALIGN"
+  r6ck_2r1i align, 0xaabbccdd, 0xeeff0011, 1, 0xff0011aa
+  r6ck_2r1i align, 0xaabbccdd, 0xeeff0011, 3, 0x11aabbcc
+
+  writemsg "[14] Test BITSWAP"
+  r6ck_1r bitswap, 0xaabbccdd, 0x55dd33bb
+  r6ck_1r bitswap, 0x11884422, 0x88112244
+
+  writemsg "[15] Test CLZ"
+  r6ck_1r clz, 0x00012340, 15
+  r6ck_1r clz, 0x80012340, 0
+  r6ck_1r clz, 0x40012340, 1
+
+  writemsg "[16] Test CLO"
+  r6ck_1r clo, 0x00123050, 0
+  r6ck_1r clo, 0xff123050, 8
+  r6ck_1r clo, 0x8f123050, 1
+
+  writemsg "[17] Test ADDIUPC"
+  jal GetPC
+  nop
+  addiu $4, $6, 8
+  addiupc $5, 4
+  fp_assert $4, $5
+
+  writemsg "[18] Test AUIPC"
+  jal GetPC
+  nop
+  addiu $4, $6, 8
+  aui $4, $4, 8
+  auipc $5, 8
+  fp_assert $4, $5
+
+  writemsg "[19] Test ALUIPC"
+  jal GetPC
+  nop
+  addiu $4, $6, 16
+  aui $4, $4, 8
+  li $7, 0xffff0000
+  and $4, $4, $7
+  aluipc $5, 8
+  fp_assert $4, $5
+
+  writemsg "[20] Test LWPC"
+  lw $5, dval1
+  lwpc $4, dval1
+  fp_assert $4, $5
+  lw $5, dval2
+  lwpc $4, dval2
+  fp_assert $4, $5
+
+  writemsg "[21] Test LL"
+  lw $5, dval2
+  la $3, dval3
+  ll $4, -252($3)
+  fp_assert $4, $5
+
+  writemsg "[22] Test SC"
+  ll $4, -252($3)
+  li $4, 0xafaf
+  sc $4, -252($3)
+  lw $5, dval2
+  li $4, 0xafaf
+  fp_assert $4, $5
+
+  pass
+
+  .end DIAG
diff --git a/sim/testsuite/mips/testutils.inc b/sim/testsuite/mips/testutils.inc
index 14d31e8ea55..1f64ba766aa 100644
--- a/sim/testsuite/mips/testutils.inc
+++ b/sim/testsuite/mips/testutils.inc
@@ -148,3 +148,58 @@ _dowrite:
 	checkreg \reg, $1
 	.set pop
 	.endm
+
+
+	# Check hi-lo register pair against data stored at base+o1 and base+o2
+	# Clobbers $1 - $5
+	.macro checkpair lo, hi, base, w, o1, o2
+	move  $2, \lo
+	move  $3, \hi
+	.set noat
+	la   $1, \base
+	l\w	$4, \o1($1)
+	l\w	$5, \o2($1)
+	.set at
+	checkreg  $2, $4
+	checkreg  $3, $5
+	.endm
+
+	.macro checkpair_le_d lo, hi, base
+	checkpair \lo, \hi, \base, w, 0, 4
+	.endm
+
+	.macro checkpair_be_d lo, hi, base
+	checkpair \lo, \hi, \base, w, 4, 0
+	.endm
+
+	.macro checkpair_le_q lo, hi, base
+	checkpair \lo, \hi, \base, d, 0, 8
+	.endm
+
+	.macro checkpair_be_q lo, hi, base
+	checkpair \lo, \hi, \base, d, 8, 0
+	.endm
+
+	# Endian-ness for comparison is determined by reading a word at ec
+	.macro checkpair_xendian lo, hi, base, ec, w
+	.set noat
+	lw   $1, \ec
+	andi $1, $1, 0x1
+	# check endianess
+	beqz  $1, 2f
+	.set at
+1: # big endian
+	checkpair_be_\w \lo, \hi, \base
+	b 3f
+2: # little endian
+	checkpair_le_\w \lo, \hi, \base
+3:
+	.endm
+
+	.macro checkpair_qword lo, hi, base, oe
+	checkpair_xendian \lo, \hi, \base, \oe, q
+	.endm
+
+	.macro checkpair_dword lo, hi, base, oe
+	checkpair_xendian \lo, \hi, \base, \oe, d
+	.endm
diff --git a/sim/testsuite/mips/utils-r6.inc b/sim/testsuite/mips/utils-r6.inc
new file mode 100644
index 00000000000..b5c88e54bc7
--- /dev/null
+++ b/sim/testsuite/mips/utils-r6.inc
@@ -0,0 +1,150 @@
+  .macro fp_assert a, b
+  beq \a, \b, 1f
+  nop
+  j _fail
+  nop
+1:
+  .endm
+
+  .macro r6ck_1r inst, a, ret
+  li $4, \a
+  li $6, \ret
+  \inst $7, $4
+  fp_assert $6, $7
+  .endm
+
+  .macro r6ck_1dr inst, a, ret
+  ld $4, \a
+  ld $6, \ret
+  \inst $7, $4
+  fp_assert $6, $7
+  .endm
+
+  .macro r6ck_2r inst, a, b, ret
+  li $4, \a
+  li $5, \b
+  li $6, \ret
+  \inst $7, $4, $5
+  fp_assert $6, $7
+  .endm
+
+  .macro r6ck_2dr inst, a, b, ret
+  ld $4, \a
+  ld $5, \b
+  ld $6, \ret
+  \inst $7, $4, $5
+  fp_assert $6, $7
+  .endm
+
+  .macro r6ck_2dr1i inst, a, b, imm, ret
+  ld $4, \a
+  ld $5, \b
+  ld $6, \ret
+  \inst $7, $4, $5, \imm
+  fp_assert $6, $7
+  .endm
+
+  .macro r6ck_1r1i inst, a, imm, ret
+  li $4, \a
+  li $6, \ret
+  \inst $7, $4, \imm
+  fp_assert $6, $7
+  .endm
+
+  .macro r6ck_1dr1i inst, a, imm, ret
+  ld $4, \a
+  ld $6, \ret
+  \inst $7, $4, \imm
+  fp_assert $6, $7
+  .endm
+
+  .macro r6ck_0dr1i inst, a, imm, ret
+  ld $4, \a
+  ld $6, \ret
+  \inst $4, $4, \imm
+  fp_assert $6, $4
+  .endm
+
+  .macro r6ck_2r1i inst, a, b, imm, ret
+  li $4, \a
+  li $5, \b
+  li $6, \ret
+  \inst $7, $4, $5, \imm
+  fp_assert $6, $7
+  .endm
+
+  .macro r6ck_3s inst, a, b, c, ret
+  li $4, \a
+  li $5, \b
+  li $6, \c
+  li $7, \ret
+  mtc1 $4, $f2
+  mtc1 $5, $f4
+  mtc1 $6, $f6
+  \inst $f2, $f4, $f6
+  mfc1 $8, $f2
+  fp_assert $7, $8
+  .endm
+
+  .macro r6ck_2s inst, a, b, ret
+  li $4, \a
+  li $5, \b
+  li $6, \ret
+  mtc1 $4, $f2
+  mtc1 $5, $f4
+  \inst $f2, $f4
+  mfc1 $7, $f2
+  fp_assert $6, $7
+  .endm
+
+  .macro r6ck_2d inst, a, b, ret
+  .data
+1: .dword \a
+2: .dword \b
+3: .dword \ret
+  .text
+  la $4, 1b
+  la $5, 2b
+  la $6, 3b
+  ldc1 $f2, 0($4)
+  ldc1 $f4, 0($5)
+  lw $7, 0($6)
+  lw $8, 4($6)
+  \inst $f2, $f4
+
+  #simulate dmfc1
+  mfhc1 $9, $f2
+  mfc1 $10, $f2
+  fp_assert $7, $9
+  fp_assert $8, $10
+  .endm
+
+  .macro r6ck_3d inst, a, b, c, ret
+  .data
+1: .dword \a
+2: .dword \b
+3: .dword \c
+4: .dword \ret
+  .text
+  la $4, 1b
+  la $5, 2b
+  la $6, 3b
+  la $2, 4b
+  ldc1 $f2, 0($4)
+  ldc1 $f4, 0($5)
+  ldc1 $f6, 0($6)
+  lw $7, 0($2)
+  lw $8, 4($2)
+  \inst $f2, $f4, $f6
+
+  #simulate dmfc1
+  mfhc1 $9, $f2
+  mfc1 $10, $f2
+  fp_assert $7, $9
+  fp_assert $8, $10
+  .endm
+
+.text
+GetPC:
+  move $6, $ra
+  jr $ra
-- 
2.17.1


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

* Re: [PATCH v4 1/4] sim: Allow toggling of quiet NaN-bit semantics
  2022-02-01 12:52 ` [PATCH v4 1/4] sim: Allow toggling of quiet NaN-bit semantics Dragan Mladjenovic
@ 2022-02-02  3:39   ` Mike Frysinger
  0 siblings, 0 replies; 8+ messages in thread
From: Mike Frysinger @ 2022-02-02  3:39 UTC (permalink / raw)
  To: Dragan Mladjenovic
  Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

[-- Attachment #1: Type: text/plain, Size: 365 bytes --]

On 01 Feb 2022 13:52, Dragan Mladjenovic wrote:
> +sim_fpu_state _sim_fpu = { /* quiet_nan_inverted */ false };

we require C11, so you can use designated initializers.
sim_fpu_state _sim_fpu = {
  .quiet_nan_inverted = false,
};

> +/* State used by the FPU.
> +
> +   FIXME: This state is global, but should be moved to SIM_CPU .  */

no space before the .
-mike

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 3/4] sim: Add partial support for IEEE 754-2008
  2022-02-01 12:53 ` [PATCH v4 3/4] sim: Add partial support for IEEE 754-2008 Dragan Mladjenovic
@ 2022-02-02  3:42   ` Mike Frysinger
  0 siblings, 0 replies; 8+ messages in thread
From: Mike Frysinger @ 2022-02-02  3:42 UTC (permalink / raw)
  To: Dragan Mladjenovic
  Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

[-- Attachment #1: Type: text/plain, Size: 562 bytes --]

On 01 Feb 2022 13:53, Dragan Mladjenovic wrote:
> +      /* In IEEE754-2008:
> +       * "minNum/maxNum is ... the canonicalized number if one
> +       * operand is a number and the other a quiet NaN." */

GNU style doesn't put * at the start of the wrapped line, and uses two
spaces before the closing */

> +/* Unordered/ordered comparison operators */

period at end

> +/* Changes the behaviour of the library to IEEE754-2008 or IEEE754-1985.
> + * The default for the library is IEEE754-1985. */

no leading * on wrapped lines and 2 spaces before */
-mike

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v4 4/4] sim: mips: Add simulator support for mips32r6/mips64r6
  2022-02-01 12:53 ` [PATCH v4 4/4] sim: mips: Add simulator support for mips32r6/mips64r6 Dragan Mladjenovic
@ 2022-02-02  3:47   ` Mike Frysinger
  0 siblings, 0 replies; 8+ messages in thread
From: Mike Frysinger @ 2022-02-02  3:47 UTC (permalink / raw)
  To: Dragan Mladjenovic
  Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

[-- Attachment #1: Type: text/plain, Size: 2400 bytes --]

On 01 Feb 2022 13:53, Dragan Mladjenovic wrote:
> +static void update_fcsr (sim_cpu *, address_word , sim_fpu_status);

no space before the ,

> +static const int sim_fpu_class_mips_mapping[] = {
> +	FP_R6CLASS_SNAN, /* SIM_FPU_IS_SNAN = 1, Noisy not-a-number */
> +	FP_R6CLASS_QNAN, /* SIM_FPU_IS_QNAN = 2, Quiet not-a-number */
> +	FP_R6CLASS_NEGINF, /* SIM_FPU_IS_NINF = 3, -infinity */
> +	FP_R6CLASS_POSINF, /* SIM_FPU_IS_PINF = 4, +infinity */
> +	FP_R6CLASS_NEGNORM, /* SIM_FPU_IS_NNUMBER = 5, -num - [-MAX .. -MIN] */
> +	FP_R6CLASS_POSNORM, /* SIM_FPU_IS_PNUMBER = 6, +num - [+MIN .. +MAX] */
> +	FP_R6CLASS_NEGSUB, /* SIM_FPU_IS_NDENORM = 7, -denorm - (MIN .. 0) */
> +	FP_R6CLASS_POSSUB, /* SIM_FPU_IS_PDENORM = 8, +denorm - (0 .. MIN) */
> +	FP_R6CLASS_NEGZERO, /* SIM_FPU_IS_NZERO = 9, -0 */
> +	FP_R6CLASS_POSZERO /* SIM_FPU_IS_PZERO = 10, +0 */
> +};

2 space indent, not tab

> +uint64_t
> +fp_classify (sim_cpu *cpu,
> +	     address_word cia,
> +	     uint64_t op,
> +	     FP_formats fmt)
> +{
> +  sim_fpu wop;
> +
> +  /* The format type has already been checked:  */
> +  switch (fmt)
> +    {
> +    case fmt_single:
> +      sim_fpu_32to (&wop, op);
> +      break;
> +    case fmt_double:
> +      sim_fpu_64to (&wop, op);
> +      break;
> +    default:
> +      sim_io_error (SD, "Bad switch\n");
> +    }

i don't understand what the comment is trying to say

> +/* Common FMAC code for .s, .d. Defers setting FCSR to caller. */

2 spaces after . at end of sentences

> +static sim_fpu_status
> +inner_fmac (int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),
> +	    uint64_t op1,
> +	    uint64_t op2,
> +	    uint64_t op3,
> +	    sim_fpu_round round,
> +	    sim_fpu_denorm denorm,
> +	    FP_formats fmt,
> +	    uint64_t *result)
> +{
> ...
> +    default:
> +      fprintf (stderr, "Bad switch\n");
>        abort ();
> +      break;
> +    }
> +
> +  *result = t64;
> +  return status;
> +}
> +
> +static uint64_t
> +fp_fmac (sim_cpu *cpu,
> +	 address_word cia,
> +	 int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),
> +	 uint64_t op1,
> +	 uint64_t op2,
> +	 uint64_t op3,
> +	 FP_formats fmt)
> +{
> ...
> +  switch (fmt)
> +    {
> +    case fmt_single:
> +    case fmt_double:
> +      status = inner_fmac (sim_fpu_op, op1, op2, op3, round,
> +			   denorm, fmt, &result);

pass |cpu| to inner_mac so it can use sim_io_error
-mike

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

end of thread, other threads:[~2022-02-02  3:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-01 12:52 [PATCH v4 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
2022-02-01 12:52 ` [PATCH v4 1/4] sim: Allow toggling of quiet NaN-bit semantics Dragan Mladjenovic
2022-02-02  3:39   ` Mike Frysinger
2022-02-01 12:53 ` [PATCH v4 2/4] sim: Factor out NaN handling in floating point operations Dragan Mladjenovic
2022-02-01 12:53 ` [PATCH v4 3/4] sim: Add partial support for IEEE 754-2008 Dragan Mladjenovic
2022-02-02  3:42   ` Mike Frysinger
2022-02-01 12:53 ` [PATCH v4 4/4] sim: mips: Add simulator support for mips32r6/mips64r6 Dragan Mladjenovic
2022-02-02  3:47   ` Mike Frysinger

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).