public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Add support for MIPS32/64 revision 6
@ 2021-05-20  7:45 Faraz Shahbazker
  2021-05-20  7:45 ` [PATCH 1/5] sim: Allow toggling of quiet NaN-bit semantics Faraz Shahbazker
                   ` (5 more replies)
  0 siblings, 6 replies; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-20  7:45 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger
  Cc: Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

This series adds support to GDB and simulator for MIPSR6.  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 (5):
  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
  gdb: mips: Add MIPSR6 support

 gdb/mips-tdep.c                    |  525 +++++++++++-
 sim/common/sim-bits.h              |    5 +
 sim/common/sim-fpu.c               |  346 ++++----
 sim/common/sim-fpu.h               |   17 +-
 sim/mips/Makefile.in               |    1 +
 sim/mips/configure                 |   21 +-
 sim/mips/configure.ac              |   15 +-
 sim/mips/cp1.c                     |  417 +++++++++-
 sim/mips/cp1.h                     |    6 +
 sim/mips/interp.c                  |    5 +-
 sim/mips/micromips.igen            |    4 +-
 sim/mips/mips.igen                 |  378 ++++++++-
 sim/mips/mips3264r2.igen           |   30 +
 sim/mips/mips3264r6.igen           | 1226 ++++++++++++++++++++++++++++
 sim/mips/sim-main.h                |  110 ++-
 sim/testsuite/mips/basic.exp       |   66 +-
 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     |  290 +++++++
 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 ++++
 sim/testsuite/mips/utils-r6.s      |    0
 30 files changed, 4423 insertions(+), 278 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
 create mode 100644 sim/testsuite/mips/utils-r6.s

-- 
2.25.1


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

* [PATCH 1/5] sim: Allow toggling of quiet NaN-bit semantics
  2021-05-20  7:45 [PATCH 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
@ 2021-05-20  7:45 ` Faraz Shahbazker
  2021-05-22  1:16   ` Mike Frysinger
  2021-05-20  7:45 ` [PATCH 2/5] sim: Factor out NaN handling in floating point operations Faraz Shahbazker
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-20  7:45 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger
  Cc: Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

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.

2021-05-19  Faraz Shahbazker  <fshahbazker@wavecomp.com>

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

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 | 35 ++++++++++++++++++++---------------
 sim/common/sim-fpu.h |  2 ++
 sim/mips/cp1.h       |  4 ++++
 sim/mips/mips.igen   |  3 +++
 sim/mips/sim-main.h  |  3 ---
 5 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index fe8ecf8a3ce..b5e96b9a324 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, unsigned64 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
@@ -2530,6 +2527,14 @@ const sim_fpu sim_fpu_max32 = {
 const sim_fpu sim_fpu_max64 = {
   sim_fpu_class_number, 0, LSMASK64 (NR_FRAC_GUARD, NR_GUARDS64), NORMAL_EXPMAX64
 };
+
+/* 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.  */
+int sim_fpu_quiet_nan_inverted = 0;
 #endif
 
 
diff --git a/sim/common/sim-fpu.h b/sim/common/sim-fpu.h
index 89e6de7e35f..1eb5cae6c08 100644
--- a/sim/common/sim-fpu.h
+++ b/sim/common/sim-fpu.h
@@ -375,7 +375,9 @@ 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);
 
+/* Toggle quiet NaN semantics.  */
 
+extern int sim_fpu_quiet_nan_inverted;
 
 /* A number of useful constants.  */
 
diff --git a/sim/mips/cp1.h b/sim/mips/cp1.h
index 3a78bf4c6b3..0babdc28eca 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 522cad6fe45..8240a859bfd 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 = 1;
 }
 
 
diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h
index 8c9abfa0b0b..e8531405ebc 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.25.1


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

* [PATCH 2/5] sim: Factor out NaN handling in floating point operations
  2021-05-20  7:45 [PATCH 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
  2021-05-20  7:45 ` [PATCH 1/5] sim: Allow toggling of quiet NaN-bit semantics Faraz Shahbazker
@ 2021-05-20  7:45 ` Faraz Shahbazker
  2021-05-22  1:25   ` Mike Frysinger
  2021-05-20  7:45 ` [PATCH 3/5] sim: Add partial support for IEEE 754-2008 Faraz Shahbazker
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-20  7:45 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger
  Cc: Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

2021-05-19  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/common/sim-fpu.c | 189 +++++++------------------------------------
 1 file changed, 31 insertions(+), 158 deletions(-)

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index b5e96b9a324..7a2f5c4a605 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);x
   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)
-- 
2.25.1


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

* [PATCH 3/5] sim: Add partial support for IEEE 754-2008
  2021-05-20  7:45 [PATCH 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
  2021-05-20  7:45 ` [PATCH 1/5] sim: Allow toggling of quiet NaN-bit semantics Faraz Shahbazker
  2021-05-20  7:45 ` [PATCH 2/5] sim: Factor out NaN handling in floating point operations Faraz Shahbazker
@ 2021-05-20  7:45 ` Faraz Shahbazker
  2021-05-22  1:34   ` Mike Frysinger
  2021-05-20  7:45 ` [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6 Faraz Shahbazker
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-20  7:45 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger
  Cc: Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

2021-05-19  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_current_mode, sim_fpu_set_mode): New.
	(sim_fpu_is_ieee754_2008, sim_fpu_is_ieee754_1985): New.
	(sim_fpu_classify): New.
	* sim-fpu.h (sim_fpu_is_un, sim_fpu_is_or): New declarations.
	(sim_fpu_current_mode, sim_fpu_set_mode): New.
	(sim_fpu_is_ieee754_2008): New declaration.
	(sim_fpu_is_ieee754_1985): New declaration.
	(sim_fpu_classify): New declaration.
---
 sim/common/sim-fpu.c | 126 +++++++++++++++++++++++++++++++++++++++++--
 sim/common/sim-fpu.h |  15 +++++-
 2 files changed, 137 insertions(+), 4 deletions(-)

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index 7a2f5c4a605..1cc12d6d831 100644
--- a/sim/common/sim-fpu.c
+++ b/sim/common/sim-fpu.c
@@ -1005,6 +1005,29 @@ 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;
+    }
+}
+
 /* Arithmetic ops */
 
 INLINE_SIM_FPU (int)
@@ -1553,7 +1576,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 +1639,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)
@@ -1700,7 +1723,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 +2278,23 @@ 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,10 +2418,72 @@ 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) ? 0 : 1;
+  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:
+      if (!f->sign)
+        return SIM_FPU_IS_PINF;
+      else
+        return SIM_FPU_IS_NINF;
+    case sim_fpu_class_zero:
+      if (!f->sign)
+        return SIM_FPU_IS_PZERO;
+      else
+        return SIM_FPU_IS_NZERO;
+    case sim_fpu_class_number:
+      if (!f->sign)
+        return SIM_FPU_IS_PNUMBER;
+      else
+        return SIM_FPU_IS_NNUMBER;
+    case sim_fpu_class_denorm:
+      if (!f->sign)
+        return SIM_FPU_IS_PDENORM;
+      else
+        return SIM_FPU_IS_NDENORM;
+    default:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+  return 0;
+}
 
 /* A number of useful constants */
 
 #if EXTERN_SIM_FPU_P
+static sim_fpu_mode sim_fpu_current_mode = sim_fpu_ieee754_1985;
+
 const sim_fpu sim_fpu_zero = {
   sim_fpu_class_zero, 0, 0, 0
 };
@@ -2410,6 +2512,24 @@ const sim_fpu sim_fpu_max64 = {
 int sim_fpu_quiet_nan_inverted = 0;
 #endif
 
+/* Specification swapping behaviour */
+INLINE_SIM_FPU (int)
+sim_fpu_is_ieee754_1985 (void)
+{
+  return (sim_fpu_current_mode == sim_fpu_ieee754_1985);
+}
+
+INLINE_SIM_FPU (int)
+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 1eb5cae6c08..511338aa923 100644
--- a/sim/common/sim-fpu.h
+++ b/sim/common/sim-fpu.h
@@ -295,7 +295,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.
 
@@ -343,8 +344,20 @@ INLINE_SIM_FPU (int) sim_fpu_is_eq (const sim_fpu *l, const sim_fpu *r);
 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);
+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. */
+typedef enum
+{
+  sim_fpu_ieee754_1985,
+  sim_fpu_ieee754_2008,
+} sim_fpu_mode;
 
+INLINE_SIM_FPU (int) sim_fpu_is_ieee754_1985 (void);
+INLINE_SIM_FPU (int) 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.
 
-- 
2.25.1


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

* [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-05-20  7:45 [PATCH 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
                   ` (2 preceding siblings ...)
  2021-05-20  7:45 ` [PATCH 3/5] sim: Add partial support for IEEE 754-2008 Faraz Shahbazker
@ 2021-05-20  7:45 ` Faraz Shahbazker
  2021-05-22  1:46   ` Mike Frysinger
  2021-05-20  7:45 ` [PATCH " Faraz Shahbazker
  2022-02-02 10:17 ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
  5 siblings, 1 reply; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-20  7:45 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger
  Cc: Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

2021-05-19  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.
	* 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_fpu_class_mips_mapping): New.

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                 |   21 +-
 sim/mips/configure.ac              |   15 +-
 sim/mips/cp1.c                     |  417 +++++++++-
 sim/mips/cp1.h                     |    2 +
 sim/mips/interp.c                  |    5 +-
 sim/mips/micromips.igen            |    4 +-
 sim/mips/mips.igen                 |  377 ++++++++-
 sim/mips/mips3264r2.igen           |   30 +
 sim/mips/mips3264r6.igen           | 1226 ++++++++++++++++++++++++++++
 sim/mips/sim-main.h                |  107 ++-
 sim/testsuite/mips/basic.exp       |   66 +-
 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     |  290 +++++++
 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 ++++
 sim/testsuite/mips/utils-r6.s      |    0
 27 files changed, 3744 insertions(+), 61 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
 create mode 100644 sim/testsuite/mips/utils-r6.s

diff --git a/sim/common/sim-bits.h b/sim/common/sim-bits.h
index f8c2563e5bd..1caf0f705a6 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)(signed8)(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)(signed16)(X))
+#define EXTEND18(X)  (LSSEXT ((X), 18))
+#define EXTEND19(X)  (LSSEXT ((X), 19))
+#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)(signed32)(X))
 #define EXTEND64(X) ((signed_word)(signed64)(X))
 
diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in
index d8eba877fb8..26ec3789829 100644
--- a/sim/mips/Makefile.in
+++ b/sim/mips/Makefile.in
@@ -103,6 +103,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 1560b0a48ac..f606640f370 100755
--- a/sim/mips/configure
+++ b/sim/mips/configure
@@ -12297,7 +12297,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"
@@ -12313,6 +12314,12 @@ case "${target}" in
 			  mips32r2:mips32r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,f:mipsisa32r2"
 			sim_multi_default=mipsisa32r2
 			;;
+  mipsisa32r6*-*-*)	sim_gen=M16
+			sim_igen_machine="-M mips32r6,mips16,mips16e,mdmx,dsp,dsp2,smartmips"
+			sim_m16_machine="-M mips16,mips16e,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"
@@ -12325,6 +12332,12 @@ case "${target}" in
 			sim_igen_filter="32,64,f"
 			sim_mach_default="mipsisa64r2"
 			;;
+  mipsisa64r6*-*-*)	sim_gen=M16
+			sim_igen_machine="-M mips64r6,mips16,mips16e,mdmx,dsp,dsp2"
+			sim_m16_machine="-M mips16,mips16e,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"
@@ -12430,7 +12443,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 == NULL)
+       mach = STATE_ARCHITECTURE (SD)->mach;
+  }
 
   switch (mach)
     {
diff --git a/sim/mips/configure.ac b/sim/mips/configure.ac
index fee3816b57a..f9e793ae2a4 100644
--- a/sim/mips/configure.ac
+++ b/sim/mips/configure.ac
@@ -129,7 +129,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"
@@ -145,6 +146,12 @@ case "${target}" in
 			  mips32r2:mips32r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,f:mipsisa32r2"
 			sim_multi_default=mipsisa32r2
 			;;
+  mipsisa32r6*-*-*)	sim_gen=M16
+			sim_igen_machine="-M mips32r6,mips16,mips16e,mdmx,dsp,dsp2,smartmips"
+			sim_m16_machine="-M mips16,mips16e,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"
@@ -157,6 +164,12 @@ case "${target}" in
 			sim_igen_filter="32,64,f"
 			sim_mach_default="mipsisa64r2"
 			;;
+  mipsisa64r6*-*-*)	sim_gen=M16
+			sim_igen_machine="-M mips64r6,mips16,mips16e,mdmx,dsp,dsp2"
+			sim_m16_machine="-M mips16,mips16e,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"
diff --git a/sim/mips/cp1.c b/sim/mips/cp1.c
index 03ed0c0558f..bd3d7a74892 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(unsigned64 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,101 @@ fp_test(unsigned64 op1,
   return status;
 }
 
+unsigned64
+fp_classify(sim_cpu *cpu,
+	    address_word cia,
+	    unsigned64 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:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+  return sim_fpu_class_mips_mapping[sim_fpu_classify (&wop) - 1];
+}
+
+int
+fp_rint(sim_cpu *cpu,
+	address_word cia,
+	unsigned64 op,
+	unsigned64 *ans,
+	FP_formats fmt)
+{
+  sim_fpu wop = {0}, wtemp = {0}, wmagic = {0}, wans = {0};
+  signed64 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:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+
+  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 ((unsigned32 *) 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:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+
+  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,
@@ -625,6 +726,90 @@ fp_cmp(sim_cpu *cpu,
     }
 }
 
+unsigned64
+fp_r6_cmp (sim_cpu *cpu,
+	   address_word cia,
+	   unsigned64 op1,
+	   unsigned64 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:
+      abort ();
+      break;
+    }
+
+  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:
+	  fprintf (stderr, "Bad switch\n");
+	  abort();
+	  break;
+	}
+     }
+   else
+     return 0;
+}
 
 /* Basic arithmetic operations.  */
 
@@ -635,7 +820,7 @@ fp_unary(sim_cpu *cpu,
 	 unsigned64 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);
@@ -696,9 +881,9 @@ fp_binary(sim_cpu *cpu,
 	  unsigned64 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;
@@ -889,6 +1074,90 @@ fp_mac(sim_cpu *cpu,
   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 *),
+	   unsigned64 op1,
+	   unsigned64 op2,
+	   unsigned64 op3,
+	   sim_fpu_round round,
+	   sim_fpu_denorm denorm,
+	   FP_formats fmt,
+	   unsigned64 *result)
+{
+  sim_fpu wop1, wop2, ans;
+  sim_fpu_status status = 0;
+  sim_fpu_status op_status;
+  unsigned32 t32 = 0;
+  unsigned64 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 unsigned64
+fp_fmac (sim_cpu *cpu,
+	 address_word cia,
+	 int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *),
+	 unsigned64 op1,
+	 unsigned64 op2,
+	 unsigned64 op3,
+	 FP_formats fmt)
+{
+  sim_fpu_round round = rounding_mode (GETRM());
+  sim_fpu_denorm denorm = denorm_mode (cpu);
+  sim_fpu_status status = 0;
+  unsigned64 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_eprintf (SD, "Bad switch\n");
+      abort();
+  }
+
+  update_fcsr (cpu, cia, status);
+  return result;
+}
+
 /* Common rsqrt code for single operands (.s or .d), intermediate rounding.  */
 static sim_fpu_status
 inner_rsqrt(unsigned64 op1,
@@ -1039,6 +1308,96 @@ fp_div(sim_cpu *cpu,
   return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
 }
 
+unsigned64
+fp_min(sim_cpu *cpu,
+       address_word cia,
+       unsigned64 op1,
+       unsigned64 op2,
+       FP_formats fmt)
+{
+  return fp_binary(cpu, cia, &sim_fpu_min, op1, op2, fmt);
+}
+
+unsigned64
+fp_max(sim_cpu *cpu,
+       address_word cia,
+       unsigned64 op1,
+       unsigned64 op2,
+       FP_formats fmt)
+{
+  return fp_binary(cpu, cia, &sim_fpu_max, op1, op2, fmt);
+}
+
+unsigned64
+fp_mina(sim_cpu *cpu,
+	address_word cia,
+	unsigned64 op1,
+	unsigned64 op2,
+	FP_formats fmt)
+{
+  unsigned64 ret = 0;
+  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:
+      fprintf (stderr, "Invalid fmt.\n");
+      abort();
+    }
+
+  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;
+}
+
+unsigned64
+fp_maxa(sim_cpu *cpu,
+	address_word cia,
+	unsigned64 op1,
+	unsigned64 op2,
+	FP_formats fmt)
+{
+  unsigned64 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:
+      fprintf (stderr, "Invalid fmt.\n");
+      abort();
+    }
+
+  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;
+}
+
 unsigned64
 fp_recip(sim_cpu *cpu,
          address_word cia,
@@ -1068,26 +1427,48 @@ fp_rsqrt(sim_cpu *cpu,
 
 unsigned64
 fp_madd(sim_cpu *cpu,
-        address_word cia,
-        unsigned64 op1,
-        unsigned64 op2,
-        unsigned64 op3,
-        FP_formats fmt)
+	address_word cia,
+	unsigned64 op1,
+	unsigned64 op2,
+	unsigned64 op3,
+	FP_formats fmt)
 {
   return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 0, fmt);
 }
 
 unsigned64
 fp_msub(sim_cpu *cpu,
-        address_word cia,
-        unsigned64 op1,
-        unsigned64 op2,
-        unsigned64 op3,
-        FP_formats fmt)
+	address_word cia,
+	unsigned64 op1,
+	unsigned64 op2,
+	unsigned64 op3,
+	FP_formats fmt)
 {
   return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 0, fmt);
 }
 
+unsigned64
+fp_fmadd (sim_cpu* cpu,
+          address_word cia,
+          unsigned64 op1,
+          unsigned64 op2,
+          unsigned64 op3,
+          FP_formats fmt)
+{
+  return fp_fmac (cpu, cia, &sim_fpu_add, op1, op2, op3, fmt);
+}
+
+unsigned64
+fp_fmsub (sim_cpu* cpu,
+          address_word cia,
+          unsigned64 op1,
+          unsigned64 op2,
+          unsigned64 op3,
+          FP_formats fmt)
+{
+  return fp_fmac (cpu, cia, &sim_fpu_sub, op1, op2, op3, fmt);
+}
+
 unsigned64
 fp_nmadd(sim_cpu *cpu,
          address_word cia,
diff --git a/sim/mips/cp1.h b/sim/mips/cp1.h
index 0babdc28eca..9e6b9153e42 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 2839715959c..b41c1a0d77b 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -1517,6 +1517,9 @@ store_word (SIM_DESC sd,
 }
 
 /* Load a word from memory.  */
+#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)
 
 static signed_word
 load_word (SIM_DESC sd,
@@ -1524,7 +1527,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 08c5bb7a2dc..b41411cd887 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 8240a859bfd..a8c0e8cfe93 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
+{
+  unsigned32 maj = (instr & 0xfc000000) >> 26;
+  unsigned32 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:
 {
   signed64 time = sim_events_time (SD);
   hi->op.timestamp = time;
@@ -509,6 +568,7 @@
 *mips32r2:
 *micromips64:
 *micromips32:
+*mips64r6:
 {
 #if 0 /* XXX FIXME: enable this only after some additional testing.  */
   if (UserMode && (SR & (status_UX|status_PX)) == 0)
@@ -1081,7 +1141,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
 {
   unsigned32 instruction = instruction_0;
   address_word base = GPR[basereg];
@@ -1111,12 +1171,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 +1198,8 @@
 	if (LLBIT)
 	  StoreMemory (AccessLength_DOUBLEWORD, memval, memval1, paddr, vaddr,
 		       isREAL);
-	GPR[rt] = LLBIT;
+	if (store_ll_bit)
+	  GPR[rt] = LLBIT;
       }
   }
 }
@@ -1376,6 +1438,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1763,8 +1826,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1812,8 +1877,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1841,8 +1908,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1868,8 +1937,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1888,8 +1959,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1922,6 +1995,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 +2041,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1997,7 +2083,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 +2157,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2114,8 +2210,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2165,8 +2263,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2209,6 +2309,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 +2385,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2322,8 +2436,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2370,6 +2486,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2409,6 +2526,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2432,6 +2550,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2450,6 +2569,8 @@
   if (RT != RD)
     Unpredictable ();
   check_u64 (SD_, instruction_0);
+  if (RT != RD)
+    Unpredictable ();
   do_dclo (SD_, RD, RS);
 }
 
@@ -2464,6 +2585,8 @@
   if (RT != RD)
     Unpredictable ();
   check_u64 (SD_, instruction_0);
+  if (RT != RD)
+    Unpredictable ();
   do_dclz (SD_, RD, RS);
 }
 
@@ -2771,6 +2894,7 @@
 000000,00001,5.RT,5.RD,5.SHIFT,111010::64::DROR
 "dror r<RD>, r<RT>, <SHIFT>"
 *mips64r2:
+*mips64r6:
 *vr5400:
 *vr5500:
 {
@@ -2781,6 +2905,7 @@
 000000,00001,5.RT,5.RD,5.SHIFT,111110::64::DROR32
 "dror32 r<RD>, r<RT>, <SHIFT>"
 *mips64r2:
+*mips64r6:
 *vr5400:
 *vr5500:
 {
@@ -2791,6 +2916,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 +2939,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2828,6 +2955,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2850,6 +2978,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2872,6 +3001,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2887,6 +3017,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2910,6 +3041,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2932,6 +3064,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2947,6 +3080,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2972,6 +3106,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2987,6 +3122,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3009,6 +3145,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3026,8 +3163,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3048,8 +3187,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3071,8 +3212,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3086,7 +3229,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 +3247,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3114,7 +3261,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 +3381,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3251,8 +3402,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3268,6 +3421,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3335,8 +3489,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3354,8 +3510,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3405,8 +3563,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3424,8 +3584,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3498,6 +3660,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3882,8 +4045,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3908,8 +4073,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3935,8 +4102,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3973,7 +4142,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 +4155,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 +4259,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4109,7 +4284,7 @@
 *vr4100:
 *vr5000:
 {
-  do_sc (SD_, RT, OFFSET, BASE, instruction_0);
+  do_sc (SD_, RT, OFFSET, BASE, instruction_0, 1);
 }
 
 
@@ -4124,7 +4299,7 @@
 *vr5000:
 {
   check_u64 (SD_, instruction_0);
-  do_scd (SD_, RT, OFFSET, BASE);
+  do_scd (SD_, RT, OFFSET, BASE, 1);
 }
 
 
@@ -4135,6 +4310,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4200,8 +4376,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4239,16 +4417,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 +4448,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4296,8 +4476,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4322,8 +4504,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4348,8 +4532,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4375,8 +4561,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4404,8 +4592,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4435,8 +4625,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4465,8 +4657,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4495,8 +4689,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4514,8 +4710,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4542,8 +4740,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4561,8 +4761,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *r3900:
 *vr5000:
@@ -4637,8 +4839,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4656,8 +4860,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4674,8 +4880,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4708,8 +4916,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4759,8 +4969,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4776,8 +4988,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4827,8 +5041,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4844,8 +5060,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4886,8 +5104,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4912,8 +5132,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4996,6 +5218,8 @@
 *mipsIII:
 *mipsIV:
 *mips32:
+*mips32r6:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5051,10 +5275,27 @@
   if (! COP_Usable (1))
     SignalExceptionCoProcessorUnusable (1);
 
-  FCSR &= ~fcsr_NAN2008_mask;
+  FCSR &= ~(fcsr_NAN2008_mask | fcsr_ABS2008_mask);
   sim_fpu_quiet_nan_inverted = 1;
 }
 
+// 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:
 //
@@ -5102,6 +5343,7 @@
 *mips32:
 *mips32r2:
 *micromips32:
+ *mips32r6:
 {
   int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian);
   address_word vaddr;
@@ -5131,8 +5373,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5151,8 +5395,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5263,8 +5509,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5281,8 +5529,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5328,8 +5578,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   do_cfc1 (SD_, RT, FS);
 }
@@ -5365,8 +5617,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   do_ctc1 (SD_, RT, FS);
 }
@@ -5384,8 +5638,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5400,8 +5656,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5433,8 +5691,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5474,8 +5734,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5493,8 +5755,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5526,6 +5790,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5561,6 +5826,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5577,8 +5843,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5595,8 +5863,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5610,6 +5880,7 @@
 *mipsII:
 *mips32:
 *mips32r2:
+*mips32r6:
 {
   check_fpu (SD_);
   COP_LD (1, FT, do_load_double (SD_, GPR[BASE], EXTEND16 (OFFSET)));
@@ -5623,6 +5894,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5684,8 +5956,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5740,8 +6014,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5759,8 +6035,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5869,8 +6147,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5888,8 +6168,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5907,8 +6189,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6005,8 +6289,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr5000:
 {
   do_recip_fmt (SD_, FMT, FD, FS);
@@ -6019,8 +6305,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6037,8 +6325,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6052,8 +6342,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr5000:
 {
   do_rsqrt_fmt (SD_, FMT, FD, FS);
@@ -6065,6 +6357,7 @@
 *mipsII:
 *mips32:
 *mips32r2:
+*mips32r6:
 {
   do_sdc1 (SD_, FT, OFFSET, BASE);
 }
@@ -6077,6 +6370,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6088,7 +6382,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 +6431,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6156,8 +6452,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6176,8 +6474,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6205,8 +6505,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6223,8 +6525,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6249,8 +6553,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6272,8 +6578,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6287,8 +6595,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 
 
@@ -6301,11 +6611,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 +6642,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 +6653,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   DecodeCoproc (instruction_0, 0, cp0_dmfc0, RT, RD, SEL);
@@ -6350,6 +6667,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   DecodeCoproc (instruction_0, 0, cp0_dmtc0, RT, RD, SEL);
@@ -6363,8 +6681,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -6392,8 +6712,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6412,8 +6734,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6446,8 +6770,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *r3900:
 {
@@ -6465,8 +6791,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6480,8 +6808,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6495,8 +6825,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6510,13 +6842,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 2c1e7195733..c844fe3a703 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..60a8c910416
--- /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:
+{
+  unsigned64 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:
+{
+  unsigned32 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:
+{
+  unsigned64 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:
+{
+  unsigned32 rs = GPR[RS];
+  unsigned32 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:
+{
+  unsigned64 rs = GPR[RS];
+  unsigned64 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 */
+  unsigned32 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 */
+  unsigned64 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:
+{
+  unsigned32 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:
+{
+  unsigned32 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:
+{
+  unsigned32 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:
+{
+  unsigned64 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:
+{
+  signed64 prod;
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  prod = ((signed64)(signed32) GPR[RS])
+    * ((signed64)(signed32) 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:
+{
+  signed64 prod;
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  prod = ((signed64)(signed32) GPR[RS])
+    * ((signed64)(signed32) 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:
+{
+  unsigned64 prod;
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  prod = ((unsigned64)(unsigned32) GPR[RS])
+    * ((unsigned64)(unsigned32) 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:
+{
+  unsigned64 prod;
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  prod = ((unsigned64)(unsigned32) GPR[RS])
+    * ((unsigned64)(unsigned32) 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:
+{
+  signed32 n = GPR[RS];
+  signed32 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:
+{
+  signed32 n = GPR[RS];
+  signed32 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:
+{
+  unsigned32 n = GPR[RS];
+  unsigned32 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:
+{
+  unsigned32 n = GPR[RS];
+  unsigned32 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:
+{
+  unsigned64 lo;
+  unsigned64 m00;
+  unsigned64 m01;
+  unsigned64 m10;
+  unsigned64 mid;
+  int sign;
+  unsigned64 op1 = GPR[RS];
+  unsigned64 op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* make signed multiply unsigned */
+  sign = 0;
+  if ((signed64) op1 < 0)
+    {
+      op1 = - op1;
+      ++sign;
+    }
+  if ((signed64) op2 < 0)
+    {
+      op2 = - op2;
+      ++sign;
+    }
+  /* multiply out the sub products */
+  m00 = ((unsigned64) VL4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m10 = ((unsigned64) VH4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m01 = ((unsigned64) VL4_8 (op1) * (unsigned64) VH4_8 (op2));
+  /* add the products */
+  mid = ((unsigned64) VH4_8 (m00)
+	 + (unsigned64) VL4_8 (m10)
+	 + (unsigned64) 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:
+{
+  unsigned64 lo;
+  unsigned64 hi;
+  unsigned64 m00;
+  unsigned64 m01;
+  unsigned64 m10;
+  unsigned64 m11;
+  unsigned64 mid;
+  int sign;
+  unsigned64 op1 = GPR[RS];
+  unsigned64 op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* make signed multiply unsigned */
+  sign = 0;
+  if ((signed64) op1 < 0)
+    {
+      op1 = - op1;
+      ++sign;
+    }
+  if ((signed64) op2 < 0)
+    {
+      op2 = - op2;
+      ++sign;
+    }
+  /* multiply out the 4 sub products */
+  m00 = ((unsigned64) VL4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m10 = ((unsigned64) VH4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m01 = ((unsigned64) VL4_8 (op1) * (unsigned64) VH4_8 (op2));
+  m11 = ((unsigned64) VH4_8 (op1) * (unsigned64) VH4_8 (op2));
+  /* add the products */
+  mid = ((unsigned64) VH4_8 (m00)
+	 + (unsigned64) VL4_8 (m10)
+	 + (unsigned64) VL4_8 (m01));
+  lo = U8_4 (mid, m00);
+  hi = (m11
+	+ (unsigned64) VH4_8 (mid)
+	+ (unsigned64) VH4_8 (m01)
+	+ (unsigned64) 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:
+{
+  unsigned64 lo;
+  unsigned64 m00;
+  unsigned64 m01;
+  unsigned64 m10;
+  unsigned64 mid;
+  unsigned64 op1 = GPR[RS];
+  unsigned64 op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* multiply out the sub products */
+  m00 = ((unsigned64) VL4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m10 = ((unsigned64) VH4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m01 = ((unsigned64) VL4_8 (op1) * (unsigned64) VH4_8 (op2));
+  /* add the products */
+  mid = ((unsigned64) VH4_8 (m00)
+	 + (unsigned64) VL4_8 (m10)
+	 + (unsigned64) 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:
+{
+  unsigned64 lo;
+  unsigned64 hi;
+  unsigned64 m00;
+  unsigned64 m01;
+  unsigned64 m10;
+  unsigned64 m11;
+  unsigned64 mid;
+  unsigned64 op1 = GPR[RS];
+  unsigned64 op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* multiply out the 4 sub products */
+  m00 = ((unsigned64) VL4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m10 = ((unsigned64) VH4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m01 = ((unsigned64) VL4_8 (op1) * (unsigned64) VH4_8 (op2));
+  m11 = ((unsigned64) VH4_8 (op1) * (unsigned64) VH4_8 (op2));
+  /* add the products */
+  mid = ((unsigned64) VH4_8 (m00)
+	 + (unsigned64) VL4_8 (m10)
+	 + (unsigned64) VL4_8 (m01));
+  lo = U8_4 (mid, m00);
+  hi = (m11
+	+ (unsigned64) VH4_8 (mid)
+	+ (unsigned64) VH4_8 (m01)
+	+ (unsigned64) 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:
+{
+  signed64 n = GPR[RS];
+  signed64 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:
+{
+  signed64 n = GPR[RS];
+  signed64 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:
+{
+  unsigned64 n = GPR[RS];
+  unsigned64 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:
+{
+  unsigned64 n = GPR[RS];
+  unsigned64 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 e8531405ebc..bc6f3c78e3d 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,68 @@ void test_fcsr (SIM_STATE);
 
 
 /* FPU operations.  */
-void fp_cmp (SIM_STATE, unsigned64 op1, unsigned64 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)
+
+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 */
+};
+
+void fp_cmp (SIM_STATE, unsigned64 op1, unsigned64 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)
+unsigned64 fp_r6_cmp (SIM_STATE, unsigned64 op1, unsigned64 op2,
+		      FP_formats fmt, int cond);
+#define R6Compare(op1,op2,fmt,cond) fp_r6_cmp(SIM_ARGS, op1, op2, fmt, cond)
+unsigned64 fp_classify(SIM_STATE, unsigned64 op, FP_formats fmt);
+#define Classify(op, fmt) fp_classify(SIM_ARGS, op, fmt)
+int fp_rint(SIM_STATE, unsigned64 op, unsigned64 *ans, FP_formats fmt);
+#define RoundToIntegralExact(op, ans, fmt) fp_rint(SIM_ARGS, op, ans, fmt)
 unsigned64 fp_abs (SIM_STATE, unsigned64 op, FP_formats fmt);
 #define AbsoluteValue(op,fmt) fp_abs(SIM_ARGS, op, fmt)
 unsigned64 fp_neg (SIM_STATE, unsigned64 op, FP_formats fmt);
@@ -733,6 +804,14 @@ unsigned64 fp_mul (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
 #define Multiply(op1,op2,fmt) fp_mul(SIM_ARGS, op1, op2, fmt)
 unsigned64 fp_div (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
 #define Divide(op1,op2,fmt) fp_div(SIM_ARGS, op1, op2, fmt)
+unsigned64 fp_min (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
+#define Min(op1,op2,fmt) fp_min(SIM_ARGS, op1, op2, fmt)
+unsigned64 fp_max (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
+#define Max(op1,op2,fmt) fp_max(SIM_ARGS, op1, op2, fmt)
+unsigned64 fp_mina (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
+#define MinA(op1,op2,fmt) fp_mina(SIM_ARGS, op1, op2, fmt)
+unsigned64 fp_maxa (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
+#define MaxA(op1,op2,fmt) fp_maxa(SIM_ARGS, op1, op2, fmt)
 unsigned64 fp_recip (SIM_STATE, unsigned64 op, FP_formats fmt);
 #define Recip(op,fmt) fp_recip(SIM_ARGS, op, fmt)
 unsigned64 fp_sqrt (SIM_STATE, unsigned64 op, FP_formats fmt);
@@ -741,6 +820,12 @@ unsigned64 fp_rsqrt (SIM_STATE, unsigned64 op, FP_formats fmt);
 #define RSquareRoot(op,fmt) fp_rsqrt(SIM_ARGS, op, fmt)
 unsigned64 fp_madd (SIM_STATE, unsigned64 op1, unsigned64 op2,
 		    unsigned64 op3, FP_formats fmt);
+#define FusedMultiplyAdd(op1,op2,op3,fmt) fp_fmadd(SIM_ARGS, op1, op2, op3, fmt)
+unsigned64 fp_fmadd (SIM_STATE, unsigned64 op1, unsigned64 op2,
+		     unsigned64 op3, FP_formats fmt);
+#define FusedMultiplySub(op1,op2,op3,fmt) fp_fmsub(SIM_ARGS, op1, op2, op3, fmt)
+unsigned64 fp_fmsub (SIM_STATE, unsigned64 op1, unsigned64 op2,
+		     unsigned64 op3, FP_formats fmt);
 #define MultiplyAdd(op1,op2,op3,fmt) fp_madd(SIM_ARGS, op1, op2, op3, fmt)
 unsigned64 fp_msub (SIM_STATE, unsigned64 op1, unsigned64 op2,
 		    unsigned64 op3, FP_formats fmt);
diff --git a/sim/testsuite/mips/basic.exp b/sim/testsuite/mips/basic.exp
index 352b3b4e719..89cc35512db 100644
--- a/sim/testsuite/mips/basic.exp
+++ b/sim/testsuite/mips/basic.exp
@@ -34,14 +34,62 @@ proc run_micromips_test { name requested_machs } {
     set global_as_options $gas_old
 }
 
+# Runs endian tests
+proc run_endian_tests { name requested_machs } {
+    global global_as_options;
+    global global_ld_options;
+    run_sim_test $name $requested_machs
+    set gas_old $global_as_options;
+    set ld_old $global_ld_options;
+    append global_as_options " -EL "
+    append global_ld_options " -EL "
+    run_sim_test $name $requested_machs
+    set global_as_options $gas_old
+    set global_ld_options $ld_old
+}
+
 # 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
+        }
+    }
+}
+
 # Only test mips*-*-elf (e.g., no mips*-*-linux)
 if {[istarget mips*-*-elf]} {
+    # Used to locate the `run` program.
+    global arch
+    set arch "mips"
+
     set dspmodels ""
     set mdmxmodels ""
     set micromipsmodels ""
@@ -57,11 +105,11 @@ if {[istarget mips*-*-elf]} {
 	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 mipsisa32*-*-elf]} {
 	set models "mips32 mips32r2"
@@ -102,4 +150,14 @@ if {[istarget mips*-*-elf]} {
     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 "mips32r6"
+    run_endian_tests r6-llsc-dp.s "mips64r6"
 }
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..bd5c339134d
--- /dev/null
+++ b/sim/testsuite/mips/r6-branch.s
@@ -0,0 +1,290 @@
+# 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
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..32d4e58e7dc
--- /dev/null
+++ b/sim/testsuite/mips/r6-fpu.s
@@ -0,0 +1,446 @@
+# mips r6 fpu test for FMADD/FMSUB etc.
+# 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:
+
+  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 a0fcd0a7f08..f23ea643e02 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
diff --git a/sim/testsuite/mips/utils-r6.s b/sim/testsuite/mips/utils-r6.s
new file mode 100644
index 00000000000..e69de29bb2d
-- 
2.25.1


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

* [PATCH 5/5] gdb: mips: Add MIPSR6 support
  2021-05-20  7:45 [PATCH 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
                   ` (3 preceding siblings ...)
  2021-05-20  7:45 ` [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6 Faraz Shahbazker
@ 2021-05-20  7:45 ` Faraz Shahbazker
  2022-02-02 10:17 ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
  5 siblings, 0 replies; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-20  7:45 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger
  Cc: Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

2021-05-19  Andrew Bennett  <andrew.bennett@imgtec.com>
	    Matthew Fortune  <matthew.fortune@mips.com>
	    Faraz Shahbazker  <fshahbazker@wavecomp.com>

gdb/ChangeLog:
	* mips-tdep.c (is_mipsr6_isa): New.
	(b0s21_imm): New define.
	(mips32_relative_offset21, mips32_relative_offset26): New.
	(is_add32bit_overflow, is_add64bit_overflow): New.
	(mips32_next_pc): Handle r6 compact and fpu coprocessor branches.
	Move handling of BLEZ, BGTZ opcode into ...
	(mips32_blez_pc): New.
	(mips32_instruction_is_compact_branch): New.
	(mips32_insn_at_pc_has_forbidden_slot):  New.
	(mips32_scan_prologue): Ignore pre-r6 addi encoding on r6.
	Stop at compact branch also.
	(LLSC_R6_OPCODE,LL_R6_FUNCT,LLE_FUNCT,
	LLD_R6_FUNCT,SC_R6_FUNCT,SCE_FUNCT,
	SCD_R6_FUNCT: New defines.
	(is_ll_insn, is_sc_insn): New.
	(mips_deal_with_atomic_sequence): Use is_ll_insn/is_sc_insn.
	Handle compact branches.
	(mips_about_to_return): Handle jrc and macro jr.
	(mips32_stack_frame_destroyed_p): Likewise.
	(mips32_instruction_has_delay_slot): Don't handle JALX no r6.
	Handle compact branches and coprocessor branches.
	(mips_adjust_breakpoint_address): Skip forbidden slot for
	compact branches.
---
 gdb/mips-tdep.c | 525 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 485 insertions(+), 40 deletions(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 2fe83324738..504dee83bbf 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -76,6 +76,9 @@ static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
 static void mips_print_float_info (struct gdbarch *, struct ui_file *,
 				   struct frame_info *, const char *);
 
+static void mips_read_fp_register_single (struct frame_info *, int,
+					  gdb_byte *);
+
 /* A useful bit in the CP0 status register (MIPS_PS_REGNUM).  */
 /* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip.  */
 #define ST0_FR (1 << 26)
@@ -1471,6 +1474,17 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
   return extract_unsigned_integer (buf, instlen, byte_order);
 }
 
+/* Return one if the gdbarch is based on MIPS Release 6.  */
+
+static int
+is_mipsr6_isa (struct gdbarch *gdbarch)
+{
+  const struct bfd_arch_info *info = gdbarch_bfd_arch_info (gdbarch);
+
+  return (info->mach == bfd_mach_mipsisa32r6
+	  || info->mach == bfd_mach_mipsisa64r6);
+}
+
 /* These are the fields of 32 bit mips instructions.  */
 #define mips32_op(x) (x >> 26)
 #define itype_op(x) (x >> 26)
@@ -1513,6 +1527,7 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
 #define b0s11_op(x) ((x) & 0x7ff)
 #define b0s12_imm(x) ((x) & 0xfff)
 #define b0s16_imm(x) ((x) & 0xffff)
+#define b0s21_imm(x) ((x) & 0x1fffff)
 #define b0s26_imm(x) ((x) & 0x3ffffff)
 #define b6s10_ext(x) (((x) >> 6) & 0x3ff)
 #define b11s5_reg(x) (((x) >> 11) & 0x1f)
@@ -1549,6 +1564,18 @@ mips32_relative_offset (ULONGEST inst)
   return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2;
 }
 
+static LONGEST
+mips32_relative_offset21 (ULONGEST insn)
+{
+  return ((b0s21_imm (insn) ^ 0x100000) - 0x100000) << 2;
+}
+
+static LONGEST
+mips32_relative_offset26 (ULONGEST insn)
+{
+  return ((b0s26_imm (insn) ^ 0x2000000) - 0x2000000) << 2;
+}
+
 /* Determine the address of the next instruction executed after the INST
    floating condition branch instruction at PC.  COUNT specifies the
    number of the floating condition bits tested by the branch.  */
@@ -1607,6 +1634,73 @@ is_octeon_bbit_op (int op, struct gdbarch *gdbarch)
   return 0;
 }
 
+static int
+is_add32bit_overflow (int32_t a, int32_t b)
+{
+  int32_t r = (uint32_t) a + (uint32_t) b;
+  return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
+}
+
+static int
+is_add64bit_overflow (int64_t a, int64_t b)
+{
+  if (a != (int32_t)a)
+    return 1;
+  if (b != (int32_t)b)
+    return 1;
+  return is_add32bit_overflow ((int32_t)a, (int32_t)b);
+}
+
+/* Calculate address of next instruction after BLEZ.  */
+
+static CORE_ADDR
+mips32_blez_pc (struct gdbarch *gdbarch, struct regcache *regcache,
+		ULONGEST inst, CORE_ADDR pc, int invert)
+{
+  int rs = itype_rs (inst);
+  int rt = itype_rt (inst);
+  LONGEST val_rs = regcache_raw_get_signed (regcache, rs);
+  LONGEST val_rt = regcache_raw_get_signed (regcache, rt);
+  ULONGEST uval_rs = regcache_raw_get_unsigned (regcache, rs);
+  ULONGEST uval_rt = regcache_raw_get_unsigned (regcache, rt);
+  int taken = 0;
+  int delay_slot_size = 4;
+
+  /* BLEZ, BLEZL, BGTZ, BGTZL */
+  if (rt == 0)
+    {
+      taken = (val_rs <= 0);
+    }
+  else if (is_mipsr6_isa (gdbarch))
+    {
+      /* BLEZALC, BGTZALC */
+      if (rs == 0 && rt != 0)
+	taken = (val_rt <= 0);
+      /* BGEZALC, BLTZALC */
+      else if (rs == rt && rt != 0)
+	taken = (val_rt >= 0);
+      /* BGEUC, BLTUC */
+      else if (rs != rt && rs != 0 && rt != 0)
+	taken = (uval_rs >= uval_rt);
+
+      /* Step through the forbidden slot to avoid repeated exceptions we do
+	 not currently have access to the BD bit when hitting a breakpoint
+	 and therefore cannot tell if the breakpoint hit on the branch or the
+	 forbidden slot.  */
+      /* delay_slot_size = 0; */
+    }
+
+  if (invert)
+    taken = !taken;
+
+  /* Calculate branch target */
+  if (taken)
+    pc += mips32_relative_offset (inst);
+  else
+    pc += delay_slot_size;
+
+  return pc;
+}
 
 /* Determine where to set a single step breakpoint while considering
    branch prediction.  */
@@ -1617,12 +1711,17 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
   struct gdbarch *gdbarch = regcache->arch ();
   unsigned long inst;
   int op;
+  int mips64bitreg = 0;
+
+  if (mips_isa_regsize (gdbarch) == 8)
+    mips64bitreg = 1;
+
   inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
   op = itype_op (inst);
   if ((inst & 0xe0000000) != 0)		/* Not a special, jump or branch
 					   instruction.  */
     {
-      if (op >> 2 == 5)
+      if (op >> 2 == 5 && ((op & 0x02) == 0 || itype_rt (inst) == 0))
 	/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
 	{
 	  switch (op & 0x03)
@@ -1632,7 +1731,7 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	    case 1:		/* BNEL */
 	      goto neq_branch;
 	    case 2:		/* BLEZL */
-	      goto less_branch;
+	      goto lez_branch;
 	    case 3:		/* BGTZL */
 	      goto greater_branch;
 	    default:
@@ -1642,15 +1741,19 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
       else if (op == 17 && itype_rs (inst) == 8)
 	/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
 	pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 1);
-      else if (op == 17 && itype_rs (inst) == 9
+      else if (!is_mipsr6_isa (gdbarch)
+	       && op == 17
+	       && itype_rs (inst) == 9
 	       && (itype_rt (inst) & 2) == 0)
 	/* BC1ANY2F, BC1ANY2T: 010001 01001 xxx0x */
 	pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 2);
-      else if (op == 17 && itype_rs (inst) == 10
+      else if (!is_mipsr6_isa (gdbarch)
+               && op == 17
+               && itype_rs (inst) == 10
 	       && (itype_rt (inst) & 2) == 0)
 	/* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
 	pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 4);
-      else if (op == 29)
+      else if (!is_mipsr6_isa (gdbarch) && op == 29)
 	/* JALX: 011101 */
 	/* The new PC will be alternate mode.  */
 	{
@@ -1678,7 +1781,128 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	  else
 	    pc += 8;        /* After the delay slot.  */
 	}
+      else if (is_mipsr6_isa (gdbarch))
+	{
+	  /* BOVC, BEQZALC, BEQC and BNVC, BNEZALC, BNEC */
+	  if (op == 8 || op == 24)
+	    {
+	      int rs = rtype_rs (inst);
+	      int rt = rtype_rt (inst);
+	      LONGEST val_rs = regcache_raw_get_signed (regcache, rs);
+	      LONGEST val_rt = regcache_raw_get_signed (regcache, rt);
+	      int taken = 0;
+	      /* BOVC (BNVC) */
+	      if (rs >= rt)
+		{
+		  if (mips64bitreg == 1)
+		    taken = is_add64bit_overflow (val_rs, val_rt);
+		  else
+		    taken = is_add32bit_overflow (val_rs, val_rt);
+		}
+	      /* BEQZALC (BNEZALC) */
+	      else if (rs < rt && rs == 0)
+		taken = (val_rt == 0);
+	      /* BEQC (BNEC) */
+	      else
+		taken = (val_rs == val_rt);
+
+	      /* BNVC, BNEZALC, BNEC */
+	      if (op == 24)
+		taken = !taken;
+
+	      if (taken)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
+	    }
+	  /* BC1EQZ, BC1NEZ */
+	  else if (op == 17 && (itype_rs (inst) == 9 || itype_rs (inst) == 13))
+	    {
+	      gdb_byte status;
+	      gdb_byte true_val = 0;
+	      unsigned int fp = gdbarch_num_regs (gdbarch) +
+		mips_regnum (gdbarch)->fp0 +
+		itype_rt (inst);
+	      struct frame_info *frame = get_current_frame ();
+	      gdb_byte *raw_buffer = (gdb_byte *) alloca (sizeof (gdb_byte) * 4);
+	      mips_read_fp_register_single (frame, fp, raw_buffer);
+
+	      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+		status = *(raw_buffer + 3);
+	      else
+		status = *(raw_buffer);
 
+	      if (itype_rs (inst) == 13)
+		true_val = 1;
+
+	      if ((status & 0x1) == true_val)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		pc += 8;
+	    }
+	  else if (op == 22 || op == 23)
+	  /* BLEZC, BGEZC, BGEC, BGTZC, BLTZC, BLTC */
+	    {
+	      int rs = rtype_rs (inst);
+	      int rt = rtype_rt (inst);
+	      LONGEST val_rs = regcache_raw_get_signed (regcache, rs);
+	      LONGEST val_rt = regcache_raw_get_signed (regcache, rt);
+	      int taken = 0;
+	      /* The R5 rt == 0 case is handled above so we treat it as
+		 an unknown instruction here for future ISA usage.  */
+	      if (rs == 0 && rt != 0)
+		taken = (val_rt <= 0);
+	      else if (rs == rt && rt != 0)
+		taken = (val_rt >= 0);
+	      else if (rs != rt && rs != 0 && rt != 0)
+		taken = (val_rs >= val_rt);
+
+	      if (op == 23)
+		taken = !taken;
+
+	      if (taken)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
+	    }
+	  else if (op == 50 || op == 58)
+	  /* BC, BALC */
+	    pc += mips32_relative_offset26 (inst) + 4;
+	  else if ((op == 54 || op == 62)
+		   && rtype_rs (inst) == 0)
+	  /* JIC, JIALC */
+	    {
+	      pc = regcache_raw_get_signed (regcache, itype_rt (inst));
+	      pc += (itype_immediate (inst) ^ 0x8000) - 0x8000;
+	    }
+	  else if (op == 54 || op == 62)
+	  /* BEQZC, BNEZC */
+	    {
+	      int rs = itype_rs (inst);
+	      LONGEST rs_val = regcache_raw_get_signed (regcache, rs);
+	      int taken = (rs_val == 0);
+	      if (op == 62)
+		taken = !taken;
+	      if (taken)
+		pc += mips32_relative_offset21 (inst) + 4;
+	      else
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
+	    }
+	  else
+	    pc += 4;		/* Not a branch, next instruction is easy.  */
+	}
       else
 	pc += 4;		/* Not a branch, next instruction is easy.  */
     }
@@ -1722,7 +1946,6 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	      case 2:		/* BLTZL */
 	      case 16:		/* BLTZAL */
 	      case 18:		/* BLTZALL */
-	      less_branch:
 		if (regcache_raw_get_signed (regcache, itype_rs (inst)) < 0)
 		  pc += mips32_relative_offset (inst) + 4;
 		else
@@ -1738,22 +1961,38 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 		  pc += 8;	/* after the delay slot */
 		break;
 	      case 0x1c:	/* BPOSGE32 */
+	      case 0x1d:	/* BPOSGE32C */
 	      case 0x1e:	/* BPOSGE64 */
 		pc += 4;
 		if (itype_rs (inst) == 0)
 		  {
 		    unsigned int pos = (op & 2) ? 64 : 32;
 		    int dspctl = mips_regnum (gdbarch)->dspctl;
+		    int delay_slot_size = 4;
 
 		    if (dspctl == -1)
 		      /* No way to handle; it'll most likely trap anyway.  */
 		      break;
 
+		    /* BPOSGE32C */
+		    if (op == 0x1d)
+		      {
+			if (!is_mipsr6_isa (gdbarch))
+			  break;
+
+			/* Step through the forbidden slot to avoid repeated
+			   exceptions we do not currently have access to the BD
+			   bit when hitting a breakpoint and therefore cannot
+			   tell if the breakpoint hit on the branch or the
+			   forbidden slot.  */
+			/* delay_slot_size = 0; */
+		      }
+
 		    if ((regcache_raw_get_unsigned (regcache,
 						    dspctl) & 0x7f) >= pos)
 		      pc += mips32_relative_offset (inst);
 		    else
-		      pc += 4;
+		      pc += delay_slot_size;
 		  }
 		break;
 		/* All of the other instructions in the REGIMM category */
@@ -1787,19 +2026,14 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	  else
 	    pc += 8;
 	  break;
-	case 6:		/* BLEZ, BLEZL */
-	  if (regcache_raw_get_signed (regcache, itype_rs (inst)) <= 0)
-	    pc += mips32_relative_offset (inst) + 4;
-	  else
-	    pc += 8;
+	case 6:		/* BLEZ, BLEZL, BLEZALC, BGEZALC, BGEUC */
+	lez_branch:
+	  pc = mips32_blez_pc (gdbarch, regcache, inst, pc + 4, 0);
 	  break;
 	case 7:
 	default:
-	greater_branch:	/* BGTZ, BGTZL */
-	  if (regcache_raw_get_signed (regcache, itype_rs (inst)) > 0)
-	    pc += mips32_relative_offset (inst) + 4;
-	  else
-	    pc += 8;
+	greater_branch:	/* BGTZ, BGTZL, BGTZALC, BLTZALC, BLTUC */
+	  pc = mips32_blez_pc (gdbarch, regcache, inst, pc + 4, 1);
 	  break;
 	}			/* switch */
     }				/* else */
@@ -2422,6 +2656,74 @@ micromips_instruction_is_compact_branch (unsigned short insn)
     }
 }
 
+/* Return non-zero if the MIPS instruction INSN is a compact branch
+   or jump.  A value of 1 indicates an unconditional compact branch
+   and a value of 2 indicates a conditional compact branch.  */
+
+static int
+mips32_instruction_is_compact_branch (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  switch (itype_op (insn))
+    {
+    /* BC */
+    case 50:
+    /* BALC */
+    case 58:
+      if (is_mipsr6_isa (gdbarch))
+	return 1;
+      break;
+    /* BOVC, BEQZALC, BEQC */
+    case 8:
+    /* BNVC, BNEZALC, BNEC */
+    case 24:
+      if (is_mipsr6_isa (gdbarch))
+	return 2;
+      break;
+    /* BEQZC, JIC */
+    case 54:
+    /* BNEZC, JIALC */
+    case 62:
+      if (is_mipsr6_isa (gdbarch))
+	/* JIC, JIALC are unconditional */
+	return (itype_rs (insn) == 0) ? 1 : 2;
+      break;
+    /* BLEZC, BGEZC, BGEC */
+    case 22:
+    /* BGTZC, BLTZC, BLTC */
+    case 23:
+    /* BLEZALC, BGEZALC, BGEUC */
+    case 6:
+    /* BGTZALC, BLTZALC, BLTUC */
+    case 7:
+      if (is_mipsr6_isa (gdbarch)
+	  && itype_rt (insn) != 0)
+	return 2;
+      break;
+    /* BPOSGE32C */
+    case 1:
+      if (is_mipsr6_isa (gdbarch)
+	  && itype_rt (insn) == 0x1d && itype_rs (insn) == 0)
+	return 2;
+    }
+  return 0;
+}
+
+/* Return non-zero if a standard MIPS instruction at ADDR has a branch
+   forbidden slot (i.e. it is a conditional compact branch instruction).  */
+
+static int
+mips32_insn_at_pc_has_forbidden_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  ULONGEST insn;
+  int status;
+
+  insn = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
+  if (status)
+    return 0;
+
+  return mips32_instruction_is_compact_branch (gdbarch, insn) == 2;
+}
+
 struct mips_frame_cache
 {
   CORE_ADDR base;
@@ -3463,7 +3765,8 @@ mips32_scan_prologue (struct gdbarch *gdbarch,
       reg = high_word & 0x1f;
 
       if (high_word == 0x27bd		/* addiu $sp,$sp,-i */
-	  || high_word == 0x23bd	/* addi $sp,$sp,-i */
+	  || (high_word == 0x23bd	/* addi $sp,$sp,-i */
+	      && !is_mipsr6_isa (gdbarch))
 	  || high_word == 0x67bd)	/* daddiu $sp,$sp,-i */
 	{
 	  if (offset < 0)		/* Negative stack adjustment?  */
@@ -3596,9 +3899,12 @@ mips32_scan_prologue (struct gdbarch *gdbarch,
 
       non_prologue_insns += this_non_prologue_insn;
 
+
       /* A jump or branch, or enough non-prologue insns seen?  If so,
 	 then we must have reached the end of the prologue by now.  */
-      if (prev_delay_slot || non_prologue_insns > 1)
+      if (prev_delay_slot
+	  || non_prologue_insns > 1
+	  || mips32_instruction_is_compact_branch (gdbarch, inst))
 	break;
 
       prev_non_prologue_insn = this_non_prologue_insn;
@@ -3902,6 +4208,59 @@ mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
 #define LLD_OPCODE 0x34
 #define SC_OPCODE 0x38
 #define SCD_OPCODE 0x3c
+#define LLSC_R6_OPCODE 0x1f
+#define LL_R6_FUNCT 0x36
+#define LLE_FUNCT 0x2e
+#define LLD_R6_FUNCT 0x37
+#define SC_R6_FUNCT 0x26
+#define SCE_FUNCT 0x1e
+#define SCD_R6_FUNCT 0x27
+
+static int
+is_ll_insn (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  if (itype_op (insn) == LL_OPCODE
+      || itype_op (insn) == LLD_OPCODE)
+    return 1;
+
+  if (rtype_op (insn) == LLSC_R6_OPCODE
+      && rtype_funct (insn) == LLE_FUNCT
+      && (insn & 0x40) == 0)
+    return 1;
+
+  /* Handle LL and LLP varieties.  */
+  if (is_mipsr6_isa (gdbarch)
+      && rtype_op (insn) == LLSC_R6_OPCODE
+      && (rtype_funct (insn) == LL_R6_FUNCT
+	  || rtype_funct (insn) == LLD_R6_FUNCT
+	  || rtype_funct (insn) == LLE_FUNCT))
+    return 1;
+
+  return 0;
+}
+
+static int
+is_sc_insn (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  if (itype_op (insn) == SC_OPCODE
+      || itype_op (insn) == SCD_OPCODE)
+    return 1;
+
+  if (rtype_op (insn) == LLSC_R6_OPCODE
+      && rtype_funct (insn) == SCE_FUNCT
+      && (insn & 0x40) == 0)
+    return 1;
+
+  /* Handle SC and SCP varieties.  */
+  if (is_mipsr6_isa (gdbarch)
+      && rtype_op (insn) == LLSC_R6_OPCODE
+      && (rtype_funct (insn) == SC_R6_FUNCT
+	  || rtype_funct (insn) == SCD_R6_FUNCT
+	  || rtype_funct (insn) == SCE_FUNCT))
+    return 1;
+
+  return 0;
+}
 
 static std::vector<CORE_ADDR>
 mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
@@ -3914,10 +4273,11 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
   int index;
   int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */  
   const int atomic_sequence_length = 16; /* Instruction sequence length.  */
+  int is_mipsr6 = is_mipsr6_isa (gdbarch);
 
   insn = mips_fetch_instruction (gdbarch, ISA_MIPS, loc, NULL);
   /* Assume all atomic sequences start with a ll/lld instruction.  */
-  if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE)
+  if (!is_ll_insn (gdbarch, insn))
     return {};
 
   /* Assume that no atomic sequence is longer than "atomic_sequence_length" 
@@ -3947,28 +4307,72 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
 	  return {}; /* fallback to the standard single-step code.  */
 	case 4: /* BEQ */
 	case 5: /* BNE */
-	case 6: /* BLEZ */
-	case 7: /* BGTZ */
 	case 20: /* BEQL */
 	case 21: /* BNEL */
-	case 22: /* BLEZL */
-	case 23: /* BGTTL */
+	case 22: /* BLEZL (BLEZC, BGEZC, BGEC) */
+	case 23: /* BGTZL (BGTZC, BLTZC, BLTC) */
 	  is_branch = 1;
 	  break;
+	case 6: /* BLEZ (BLEZALC, BGEZALC, BGEUC) */
+	case 7: /* BGTZ (BGTZALC, BLTZALC, BLTUC) */
+	  if (is_mipsr6)
+	    {
+	      /* BLEZALC, BGTZALC */
+	      if (itype_rs (insn) == 0 && itype_rt (insn) != 0)
+		return {}; /* fallback to the standard single-step code.  */
+	      /* BGEZALC, BLTZALC */
+	      else if (itype_rs (insn) == itype_rt (insn)
+		  && itype_rt (insn) != 0)
+		return {}; /* fallback to the standard single-step code.  */
+	    }
+	  is_branch = 1;
+	  break;
+	case 8: /* BOVC, BEQZALC, BEQC */
+	case 24: /* BNVC, BNEZALC, BNEC */
+	  if (is_mipsr6)
+	    is_branch = 1;
+	  break;
+	case 50: /* BC */
+	case 58: /* BALC */
+	  if (is_mipsr6)
+	    return {}; /* fallback to the standard single-step code.  */
+	  break;
+	case 54: /* BEQZC, JIC */
+	case 62: /* BNEZC, JIALC */
+	  if (is_mipsr6)
+	    {
+	      if (itype_rs (insn) == 0) /* JIC, JIALC */
+		return {}; /* fallback to the standard single-step code.  */
+	      else
+		is_branch = 2; /* Marker for branches with a 21-bit offset */
+	    }
+	  break;
 	case 17: /* COP1 */
-	  is_branch = ((itype_rs (insn) == 9 || itype_rs (insn) == 10)
-		       && (itype_rt (insn) & 0x2) == 0);
+	  is_branch = ((!is_mipsr6
+		       && (itype_rs (insn) == 9 || itype_rs (insn) == 10)
+		       && (itype_rt (insn) & 0x2) == 0)
+				/* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+		       || (itype_rs (insn) & 0x18) == 0x18);
+				/* BZ.df:  010001 110xx */
 	  if (is_branch) /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
 	    break;
 	/* Fall through.  */
 	case 18: /* COP2 */
 	case 19: /* COP3 */
-	  is_branch = (itype_rs (insn) == 8); /* BCzF, BCzFL, BCzT, BCzTL */
+	  /* BCzF, BCzFL, BCzT, BCzTL, BC*EQZ, BC*NEZ */
+	  is_branch = (itype_rs (insn) == 8)
+		       || (is_mipsr6
+			   && (itype_rs (insn) == 9
+			       || itype_rs (insn) == 13));
 	  break;
 	}
       if (is_branch)
 	{
-	  branch_bp = loc + mips32_relative_offset (insn) + 4;
+	  /* Is this a special PC21_S2 branch? */
+	  if (is_branch == 2)
+	    branch_bp = loc + mips32_relative_offset21 (insn) + 4;
+	  else
+	    branch_bp = loc + mips32_relative_offset (insn) + 4;
 	  if (last_breakpoint >= 1)
 	    return {}; /* More than one branch found, fallback to the
 			  standard single-step code.  */
@@ -3976,12 +4380,12 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
 	  last_breakpoint++;
 	}
 
-      if (itype_op (insn) == SC_OPCODE || itype_op (insn) == SCD_OPCODE)
+      if (is_sc_insn (gdbarch, insn))
 	break;
     }
 
   /* Assume that the atomic sequence ends with a sc/scd instruction.  */
-  if (itype_op (insn) != SC_OPCODE && itype_op (insn) != SCD_OPCODE)
+  if (!is_sc_insn (gdbarch, insn))
     return {};
 
   loc += MIPS_INSN32_SIZE;
@@ -4206,8 +4610,14 @@ mips_about_to_return (struct gdbarch *gdbarch, CORE_ADDR pc)
   gdb_assert (mips_pc_is_mips (pc));
 
   insn = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
-  hint = 0x7c0;
-  return (insn & ~hint) == 0x3e00008;			/* jr(.hb) $ra */
+  /* Mask the hint and the jalr/jr bit */
+  hint = 0x7c1;
+
+  if (is_mipsr6_isa (gdbarch) && insn == 0xd81f0000) /* jrc $31 */
+    return 1;
+
+  /* jr(.hb) $ra and "jalr(.hb) $ra" */
+  return ((insn & ~hint) == 0x3e00008);
 }
 
 
@@ -6711,7 +7121,9 @@ mips32_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 
 	  if (high_word != 0x27bd	/* addiu $sp,$sp,offset */
 	      && high_word != 0x67bd	/* daddiu $sp,$sp,offset */
-	      && inst != 0x03e00008	/* jr $ra */
+	      && (inst & ~0x1) != 0x03e00008 /* jr $31 or jalr $0, $31 */
+	      && (!is_mipsr6_isa (gdbarch)
+		  || inst != 0xd81f0000) /* jrc $31 */
 	      && inst != 0x00000000)	/* nop */
 	    return 0;
 	}
@@ -7092,22 +7504,31 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
   int op;
   int rs;
   int rt;
+  int is_mipsr6 = is_mipsr6_isa (gdbarch);
 
   op = itype_op (inst);
   if ((inst & 0xe0000000) != 0)
     {
       rs = itype_rs (inst);
       rt = itype_rt (inst);
-      return (is_octeon_bbit_op (op, gdbarch) 
-	      || op >> 2 == 5	/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx  */
-	      || op == 29	/* JALX: bits 011101  */
+      return (is_octeon_bbit_op (op, gdbarch)
+	      || (op >> 1 == 10) /* BEQL, BNEL: bits 01010x  */
+	      || (op >> 1 == 11 && rt == 0) /* BLEZL, BGTZL: bits 01011x  */
+	      || (!is_mipsr6 && op == 29)	/* JALX: bits 011101  */
 	      || (op == 17
 		  && (rs == 8
 				/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000  */
-		      || (rs == 9 && (rt & 0x2) == 0)
+		      || (!is_mipsr6 && rs == 9 && (rt & 0x2) == 0)
 				/* BC1ANY2F, BC1ANY2T: bits 010001 01001  */
-		      || (rs == 10 && (rt & 0x2) == 0))));
+		      || (!is_mipsr6 && rs == 10 && (rt & 0x2) == 0)))
 				/* BC1ANY4F, BC1ANY4T: bits 010001 01010  */
+	      || (is_mipsr6
+		  && ((op == 17
+		       && (rs == 9  /* BC1EQZ: 010001 01001  */
+			   || rs == 13 /* BC1NEZ: 010001 01101  */ ))
+		      || (op == 18
+			  && (rs == 9 /* BC2EQZ: 010010 01001  */
+			      || rs == 13 /* BC2NEZ: 010010 01101  */ )))));
     }
   else
     switch (op & 0x07)		/* extract bits 28,27,26  */
@@ -7126,7 +7547,11 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
 		|| ((rt & 0x1e) == 0x1c && rs == 0));
 				/* BPOSGE32, BPOSGE64: bits 1110x  */
 	break;			/* end REGIMM  */
-      default:			/* J, JAL, BEQ, BNE, BLEZ, BGTZ  */
+	case 6:			/* BLEZ  */
+	case 7:			/* BGTZ  */
+	 return (itype_rt (inst) == 0);
+	 break;
+      default:			/* J, JAL, BEQ, BNE  */
 	return 1;
 	break;
       }
@@ -7338,7 +7763,18 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
 
      So, we'll use the second solution.  To do this we need to know if
      the instruction we're trying to set the breakpoint on is in the
-     branch delay slot.  */
+     branch delay slot.
+
+     A similar problem occurs for breakpoints on forbidden slots where
+     the trap will be reported for the branch with the BD bit set.
+     In this case it would be ideal to recover using solution 1 from
+     above as there is no problem with the branch being skipped
+     (since the forbidden slot only exists on not-taken branches).
+     However, the BD bit is not available in all scenarios currently
+     so instead we move the breakpoint on to the next instruction.
+     This means that it is not possible to stop on an instruction
+     that can be in a forbidden slot even if that instruction is
+     jumped to directly.  */
 
   boundary = mips_segment_boundary (bpaddr);
 
@@ -7360,6 +7796,13 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
       prev_addr = bpaddr - 4;
       if (mips32_insn_at_pc_has_delay_slot (gdbarch, prev_addr))
 	bpaddr = prev_addr;
+      /* If the previous instruction has a forbidden slot, we have to
+	 move the breakpoint to the following instruction to prevent
+	 breakpoints in forbidden slots being reported as unknown
+	 traps.  */
+      else if (mips32_insn_at_pc_has_forbidden_slot (gdbarch, prev_addr))
+
+	bpaddr += 4;
     }
   else
     {
@@ -7772,6 +8215,8 @@ mips_in_return_stub (struct gdbarch *gdbarch, CORE_ADDR pc, const char *name)
    PC of the stub target.  The stub just loads $t9 and jumps to it,
    so that $t9 has the correct value at function entry.  */
 
+/* TODO: Update for compact jump trampoline */
+
 static CORE_ADDR
 mips_skip_pic_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 {
-- 
2.25.1


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

* Re: [PATCH 1/5] sim: Allow toggling of quiet NaN-bit semantics
  2021-05-20  7:45 ` [PATCH 1/5] sim: Allow toggling of quiet NaN-bit semantics Faraz Shahbazker
@ 2021-05-22  1:16   ` Mike Frysinger
  0 siblings, 0 replies; 50+ messages in thread
From: Mike Frysinger @ 2021-05-22  1:16 UTC (permalink / raw)
  To: Faraz Shahbazker; +Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu

On 20 May 2021 13:15, Faraz Shahbazker wrote:
> 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.

looks good ... minor style nits

> --- a/sim/common/sim-fpu.c
> +++ b/sim/common/sim-fpu.c
> 
> +/* 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.  */
> +int sim_fpu_quiet_nan_inverted = 0;

we're C11 now, so we can assume stdbool.h.  so switch to bool/true/false.

> --- a/sim/common/sim-fpu.h
> +++ b/sim/common/sim-fpu.h
>  
> +/* Toggle quiet NaN semantics.  */
>  
> +extern int sim_fpu_quiet_nan_inverted;

omit the blank line between the two lines
-mike

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

* Re: [PATCH 2/5] sim: Factor out NaN handling in floating point operations
  2021-05-20  7:45 ` [PATCH 2/5] sim: Factor out NaN handling in floating point operations Faraz Shahbazker
@ 2021-05-22  1:25   ` Mike Frysinger
  2021-05-23  6:32     ` [EXTERNAL]Re: " Faraz Shahbazker
  0 siblings, 1 reply; 50+ messages in thread
From: Mike Frysinger @ 2021-05-22  1:25 UTC (permalink / raw)
  To: Faraz Shahbazker; +Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu

On 20 May 2021 13:15, Faraz Shahbazker wrote:
> --- a/sim/common/sim-fpu.c
> +++ b/sim/common/sim-fpu.c
>  
> +/* 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));

indent style of this func needs fixing as it's all over the place

> +   if (sim_fpu_is_qnan (l))
> +	*f = *l;
> +   else /* if (sim_fpu_is_qnan (r)) */
> +    *f = *r;

so some of the logic you replaced below do:
	if (sim_fpu_is_qnan (l))
	  {
	    *f = *l;
	    return 0;
	  }
	if (sim_fpu_is_qnan (r))
	  {
	    *f = *r;
	    return 0;
	  }

but others do:
	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;
	  }

it seems like we should have been consistently doing the latter ?
so it's a good time to fix with your new helper.

> +    return sim_fpu_op_nan (f, l, r);x

looks like you have a typo in there.  might want to do a compile test.
-mike

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

* Re: [PATCH 3/5] sim: Add partial support for IEEE 754-2008
  2021-05-20  7:45 ` [PATCH 3/5] sim: Add partial support for IEEE 754-2008 Faraz Shahbazker
@ 2021-05-22  1:34   ` Mike Frysinger
  0 siblings, 0 replies; 50+ messages in thread
From: Mike Frysinger @ 2021-05-22  1:34 UTC (permalink / raw)
  To: Faraz Shahbazker; +Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu

On 20 May 2021 13:15, Faraz Shahbazker wrote:

just nits

> --- a/sim/common/sim-fpu.c
> +++ b/sim/common/sim-fpu.c
>  
> +/* 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))) */

i know it's a comment, but we want the correct style either way

    /* 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." */

don't want the leading * in multiline comment blocks.
two spaces before the trailing */.

> +      if (sim_fpu_is_qnan (l))
> +	*f = *r;
> +      else if (sim_fpu_is_qnan (r))
> +	*f = *l;

should the else be a comment too ?

> +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)
>
> +INLINE_SIM_FPU (int)
> +sim_fpu_un (int *is,
> +             const sim_fpu *l,
> +             const sim_fpu *r)

bad indentation on these.  you could just unwrap them.

> +{
> +  if (sim_fpu_is_nan (l) || sim_fpu_is_nan (r))
> +  {
> +    *is = 1;
> +    return 0;
> +  }

bad indentation

> +  /* Invert result */

period & two spaces at the end

> +  *is = (*is) ? 0 : 1;

simpler ?
	*is = !*is;

> +INLINE_SIM_FPU(int)
> +sim_fpu_classify(const sim_fpu *f)

space before the (
-mike

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

* Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-05-20  7:45 ` [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6 Faraz Shahbazker
@ 2021-05-22  1:46   ` Mike Frysinger
  2021-05-22  6:20     ` Eli Zaretskii
                       ` (2 more replies)
  0 siblings, 3 replies; 50+ messages in thread
From: Mike Frysinger @ 2021-05-22  1:46 UTC (permalink / raw)
  To: Faraz Shahbazker; +Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu

On 20 May 2021 13:15, Faraz Shahbazker wrote:
> 2021-05-19  Ali Lown  <ali.lown@imgtec.com>
> 	    Andrew Bennett  <andrew.bennett@imgtec.com>
> 	    Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
> 	    Faraz Shahbazker  <fshahbazker@wavecomp.com>

i assume everyone has FSF papers in place ?

i can't provide too much substantive review on the ISA stuff here.

> --- a/sim/mips/cp1.c
> +++ b/sim/mips/cp1.c
>
> +unsigned64
> +fp_classify(sim_cpu *cpu,
>
> +int
> +fp_rint(sim_cpu *cpu,
>
> +unsigned64
> +fp_min(sim_cpu *cpu,
>
> +unsigned64
> +fp_max(sim_cpu *cpu,
>
> +unsigned64
> +fp_mina(sim_cpu *cpu,
>
> +unsigned64
> +fp_maxa(sim_cpu *cpu,
>
>  unsigned64
>  fp_madd(sim_cpu *cpu,
>
>  unsigned64
>  fp_msub(sim_cpu *cpu,

missing space before the (

should these (and others in this file) be static ?  they aren't namespaced.

> +unsigned64
> +fp_fmsub (sim_cpu* cpu,

shoul be "sim_cpu *cpu".  comes up a few times in here.

> --- a/sim/mips/interp.c
> +++ b/sim/mips/interp.c
>  
>  /* Load a word from memory.  */
> +#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)

define should be before the comment

> --- a/sim/mips/mips.igen
> +++ b/sim/mips/mips.igen
>
> +:function:::void:signal_if_cti:instruction_word instr
> +{
> +  unsigned32 maj = (instr & 0xfc000000) >> 26;
> +  unsigned32 special = instr & 0x3f;
> +  if((maj & 0x3e) == 0x06 /* Branch/Jump */

space after "if"

> --- a/sim/mips/sim-main.h
> +++ b/sim/mips/sim-main.h
>
> +static const int sim_fpu_class_mips_mapping[] = {

shouldn't put these in the header

> diff --git a/sim/testsuite/mips/utils-r6.s b/sim/testsuite/mips/utils-r6.s
> new file mode 100644
> index 00000000000..e69de29bb2d

it's an empty file ?
-mike

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

* Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-05-22  1:46   ` Mike Frysinger
@ 2021-05-22  6:20     ` Eli Zaretskii
  2021-06-27 19:25       ` [EXTERNAL]Re: " Faraz Shahbazker
  2021-05-22  6:44     ` Faraz Shahbazker
  2021-05-24 17:57     ` [PATCH v2 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
  2 siblings, 1 reply; 50+ messages in thread
From: Eli Zaretskii @ 2021-05-22  6:20 UTC (permalink / raw)
  To: Mike Frysinger; +Cc: fshahbazker, gdb-patches, macro, cfu

> Date: Fri, 21 May 2021 21:46:33 -0400
> From: Mike Frysinger via Gdb-patches <gdb-patches@sourceware.org>
> Cc: Chao-ying Fu <cfu@wavecomp.com>, gdb-patches@sourceware.org,
>  "Maciej W . Rozycki" <macro@orcam.me.uk>
> 
> On 20 May 2021 13:15, Faraz Shahbazker wrote:
> > 2021-05-19  Ali Lown  <ali.lown@imgtec.com>
> > 	    Andrew Bennett  <andrew.bennett@imgtec.com>
> > 	    Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
> > 	    Faraz Shahbazker  <fshahbazker@wavecomp.com>
> 
> i assume everyone has FSF papers in place ?

Not that I could see, no.

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

* Re: [EXTERNAL]Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-05-22  1:46   ` Mike Frysinger
  2021-05-22  6:20     ` Eli Zaretskii
@ 2021-05-22  6:44     ` Faraz Shahbazker
  2021-05-24 17:57     ` [PATCH v2 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
  2 siblings, 0 replies; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-22  6:44 UTC (permalink / raw)
  To: gdb-patches, Maciej W . Rozycki, Chao-ying Fu

On 5/22/21 7:16 AM, Mike Frysinger wrote:
> On 20 May 2021 13:15, Faraz Shahbazker wrote:
>> 2021-05-19  Ali Lown  <ali.lown@imgtec.com>
>> 	    Andrew Bennett  <andrew.bennett@imgtec.com>
>> 	    Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
>> 	    Faraz Shahbazker  <fshahbazker@wavecomp.com>
> 
> i assume everyone has FSF papers in place ?
> 

Its complicated! Most of this code was written way back (2013-15). 
Imgtec went through multiple splits and acquisitions since then. I know 
for a fact that Wave Computing today has the the ownership rights to 
publish/license this code, so thats the only one that really matters.

One could put @wavecomp.com for the initial authors, but those addresses 
have never existed. I've discussed this with Maciej at one point and his 
suggestion was to use historically accurate e-mail addresses.

- Faraz

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

* Re: [EXTERNAL]Re: [PATCH 2/5] sim: Factor out NaN handling in floating point operations
  2021-05-22  1:25   ` Mike Frysinger
@ 2021-05-23  6:32     ` Faraz Shahbazker
  2021-05-24  1:26       ` Mike Frysinger
  0 siblings, 1 reply; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-23  6:32 UTC (permalink / raw)
  To: gdb-patches, Maciej W . Rozycki, Chao-ying Fu

On 5/22/21 6:55 AM, Mike Frysinger wrote:
> so some of the logic you replaced below do:
> 	if (sim_fpu_is_qnan (l))
> 	  {
> 	    *f = *l;
> 	    return 0;
> 	  }
> 	if (sim_fpu_is_qnan (r))
> 	  {
> 	    *f = *r;
> 	    return 0;
> 	  }
> 
> but others do:
> 	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;
> 	  }
> 
> it seems like we should have been consistently doing the latter ?

Isn't the extra assignment redundant? If sim_fpu_is_qnan(l), then 
l->class == sim_fpu_class_qnan, and so *f = *l is sufficient.

Only sNaN-handling needs the extra assignment because it has to be 
downgraded to qNaN.

- Faraz

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

* Re: [EXTERNAL]Re: [PATCH 2/5] sim: Factor out NaN handling in floating point operations
  2021-05-23  6:32     ` [EXTERNAL]Re: " Faraz Shahbazker
@ 2021-05-24  1:26       ` Mike Frysinger
  0 siblings, 0 replies; 50+ messages in thread
From: Mike Frysinger @ 2021-05-24  1:26 UTC (permalink / raw)
  To: Faraz Shahbazker; +Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu

On 23 May 2021 12:02, Faraz Shahbazker wrote:
> On 5/22/21 6:55 AM, Mike Frysinger wrote:
> > so some of the logic you replaced below do:
> > 	if (sim_fpu_is_qnan (l))
> > 	  {
> > 	    *f = *l;
> > 	    return 0;
> > 	  }
> > 	if (sim_fpu_is_qnan (r))
> > 	  {
> > 	    *f = *r;
> > 	    return 0;
> > 	  }
> > 
> > but others do:
> > 	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;
> > 	  }
> > 
> > it seems like we should have been consistently doing the latter ?
> 
> Isn't the extra assignment redundant? If sim_fpu_is_qnan(l), then 
> l->class == sim_fpu_class_qnan, and so *f = *l is sufficient.
> 
> Only sNaN-handling needs the extra assignment because it has to be 
> downgraded to qNaN.

gotcha, sounds good.  so the old code that was assigning the class didn't
need to, and you're cleaning that up.
-mike

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

* [PATCH v2 0/5] Add support for MIPS32/64 revision 6
  2021-05-22  1:46   ` Mike Frysinger
  2021-05-22  6:20     ` Eli Zaretskii
  2021-05-22  6:44     ` Faraz Shahbazker
@ 2021-05-24 17:57     ` Faraz Shahbazker
  2021-05-24 17:57       ` [PATCH v2 1/5] sim: Allow toggling of quiet NaN-bit semantics Faraz Shahbazker
                         ` (4 more replies)
  2 siblings, 5 replies; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-24 17:57 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger; +Cc: Chao-ying Fu, Faraz Shahbazker

Changes from v1: style and indentation fixes from previous review.

This series adds support to GDB and simulator for MIPSR6.  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 (5):
  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
  gdb: mips: Add MIPSR6 support

 gdb/mips-tdep.c                    |  518 +++++++++++-
 sim/common/sim-bits.h              |    5 +
 sim/common/sim-fpu.c               |  344 ++++----
 sim/common/sim-fpu.h               |   17 +-
 sim/mips/Makefile.in               |    1 +
 sim/mips/configure                 |   21 +-
 sim/mips/configure.ac              |   15 +-
 sim/mips/cp1.c                     |  409 +++++++++-
 sim/mips/cp1.h                     |    6 +
 sim/mips/interp.c                  |    6 +-
 sim/mips/micromips.igen            |    4 +-
 sim/mips/mips.igen                 |  378 ++++++++-
 sim/mips/mips3264r2.igen           |   30 +
 sim/mips/mips3264r6.igen           | 1226 ++++++++++++++++++++++++++++
 sim/mips/sim-main.h                |   97 ++-
 sim/testsuite/mips/basic.exp       |   66 +-
 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     |  290 +++++++
 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 ++++
 29 files changed, 4402 insertions(+), 270 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.25.1


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

* [PATCH v2 1/5] sim: Allow toggling of quiet NaN-bit semantics
  2021-05-24 17:57     ` [PATCH v2 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
@ 2021-05-24 17:57       ` Faraz Shahbazker
  2021-05-24 17:57       ` [PATCH v2 2/5] sim: Factor out NaN handling in floating point operations Faraz Shahbazker
                         ` (3 subsequent siblings)
  4 siblings, 0 replies; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-24 17:57 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger; +Cc: Chao-ying Fu, Faraz Shahbazker

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.

2021-05-24  Faraz Shahbazker  <fshahbazker@wavecomp.com>

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

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

Notes:
    Changes from v1:
      Use bool/true/false for sim_fpu_quiet_nan_inverted flag.
      White space changes

 sim/common/sim-fpu.c | 35 ++++++++++++++++++++---------------
 sim/common/sim-fpu.h |  2 ++
 sim/mips/cp1.h       |  4 ++++
 sim/mips/mips.igen   |  3 +++
 sim/mips/sim-main.h  |  3 ---
 5 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index fe8ecf8a3ce..4edd651fd52 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, unsigned64 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
@@ -2530,6 +2527,14 @@ const sim_fpu sim_fpu_max32 = {
 const sim_fpu sim_fpu_max64 = {
   sim_fpu_class_number, 0, LSMASK64 (NR_FRAC_GUARD, NR_GUARDS64), NORMAL_EXPMAX64
 };
+
+/* 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.  */
+bool sim_fpu_quiet_nan_inverted = false;
 #endif
 
 
diff --git a/sim/common/sim-fpu.h b/sim/common/sim-fpu.h
index 89e6de7e35f..51bb7d2be92 100644
--- a/sim/common/sim-fpu.h
+++ b/sim/common/sim-fpu.h
@@ -375,7 +375,9 @@ 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);
 
+/* Toggle quiet NaN semantics.  */
 
+extern bool sim_fpu_quiet_nan_inverted;
 
 /* A number of useful constants.  */
 
diff --git a/sim/mips/cp1.h b/sim/mips/cp1.h
index 3a78bf4c6b3..0babdc28eca 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 522cad6fe45..160ca2a8c45 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 8c9abfa0b0b..e8531405ebc 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.25.1


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

* [PATCH v2 2/5] sim: Factor out NaN handling in floating point operations
  2021-05-24 17:57     ` [PATCH v2 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
  2021-05-24 17:57       ` [PATCH v2 1/5] sim: Allow toggling of quiet NaN-bit semantics Faraz Shahbazker
@ 2021-05-24 17:57       ` Faraz Shahbazker
  2021-05-24 17:58       ` [PATCH v2 3/5] sim: Add partial support for IEEE 754-2008 Faraz Shahbazker
                         ` (2 subsequent siblings)
  4 siblings, 0 replies; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-24 17:57 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger; +Cc: Chao-ying Fu, Faraz Shahbazker

2021-05-24  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.
---

Notes:
    Changes from v1:
      - indentation fixes
      - remove spurious character typo

 sim/common/sim-fpu.c | 189 +++++++------------------------------------
 1 file changed, 31 insertions(+), 158 deletions(-)

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index 4edd651fd52..96b1776e986 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)
-- 
2.25.1


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

* [PATCH v2 3/5] sim: Add partial support for IEEE 754-2008
  2021-05-24 17:57     ` [PATCH v2 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
  2021-05-24 17:57       ` [PATCH v2 1/5] sim: Allow toggling of quiet NaN-bit semantics Faraz Shahbazker
  2021-05-24 17:57       ` [PATCH v2 2/5] sim: Factor out NaN handling in floating point operations Faraz Shahbazker
@ 2021-05-24 17:58       ` Faraz Shahbazker
  2021-05-24 17:58       ` [PATCH v2 4/5] sim: mips: Add simulator support for mips32r6/mips64r6 Faraz Shahbazker
  2021-05-24 17:58       ` [PATCH v2 5/5] gdb: mips: Add MIPSR6 support Faraz Shahbazker
  4 siblings, 0 replies; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-24 17:58 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger; +Cc: Chao-ying Fu, Faraz Shahbazker

2021-05-24  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_current_mode): 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_is_un, sim_fpu_is_or): New declarations.
	(sim_fpu_mode): New.
	(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.
---

Notes:
    Changes from v1:
      - whitespace and style fixes only

 sim/common/sim-fpu.c | 124 +++++++++++++++++++++++++++++++++++++++++--
 sim/common/sim-fpu.h |  15 +++++-
 2 files changed, 134 insertions(+), 5 deletions(-)

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index 96b1776e986..26ada87c154 100644
--- a/sim/common/sim-fpu.c
+++ b/sim/common/sim-fpu.c
@@ -1005,6 +1005,29 @@ 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;
+    }
+}
+
 /* Arithmetic ops */
 
 INLINE_SIM_FPU (int)
@@ -1553,7 +1576,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 +1639,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 +1700,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 +1723,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 +2278,23 @@ 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,10 +2418,68 @@ 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:
+      if (!f->sign)
+	return SIM_FPU_IS_PINF;
+      else
+	return SIM_FPU_IS_NINF;
+    case sim_fpu_class_zero:
+      if (!f->sign)
+	return SIM_FPU_IS_PZERO;
+      else
+	return SIM_FPU_IS_NZERO;
+    case sim_fpu_class_number:
+      if (!f->sign)
+	return SIM_FPU_IS_PNUMBER;
+      else
+	return SIM_FPU_IS_NNUMBER;
+    case sim_fpu_class_denorm:
+      if (!f->sign)
+	return SIM_FPU_IS_PDENORM;
+      else
+	return SIM_FPU_IS_NDENORM;
+    default:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+  return 0;
+}
 
 /* A number of useful constants */
 
 #if EXTERN_SIM_FPU_P
+static sim_fpu_mode sim_fpu_current_mode = sim_fpu_ieee754_1985;
+
 const sim_fpu sim_fpu_zero = {
   sim_fpu_class_zero, 0, 0, 0
 };
@@ -2410,6 +2508,24 @@ const sim_fpu sim_fpu_max64 = {
 bool sim_fpu_quiet_nan_inverted = false;
 #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 51bb7d2be92..e4abe6ac96f 100644
--- a/sim/common/sim-fpu.h
+++ b/sim/common/sim-fpu.h
@@ -295,7 +295,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.
 
@@ -343,8 +344,20 @@ INLINE_SIM_FPU (int) sim_fpu_is_eq (const sim_fpu *l, const sim_fpu *r);
 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);
+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. */
+typedef enum
+{
+  sim_fpu_ieee754_1985,
+  sim_fpu_ieee754_2008,
+} sim_fpu_mode;
 
+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.
 
-- 
2.25.1


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

* [PATCH v2 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-05-24 17:57     ` [PATCH v2 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
                         ` (2 preceding siblings ...)
  2021-05-24 17:58       ` [PATCH v2 3/5] sim: Add partial support for IEEE 754-2008 Faraz Shahbazker
@ 2021-05-24 17:58       ` Faraz Shahbazker
  2021-05-24 17:58       ` [PATCH v2 5/5] gdb: mips: Add MIPSR6 support Faraz Shahbazker
  4 siblings, 0 replies; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-24 17:58 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger; +Cc: Chao-ying Fu, Faraz Shahbazker

2021-05-24  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.
---

Notes:
    Changes from v1:
      - whitespace fixes
      - remove empty sim/testsuite/mips/utils-r6.s

 sim/common/sim-bits.h              |    5 +
 sim/mips/Makefile.in               |    1 +
 sim/mips/configure                 |   21 +-
 sim/mips/configure.ac              |   15 +-
 sim/mips/cp1.c                     |  409 +++++++++-
 sim/mips/cp1.h                     |    2 +
 sim/mips/interp.c                  |    6 +-
 sim/mips/micromips.igen            |    4 +-
 sim/mips/mips.igen                 |  377 ++++++++-
 sim/mips/mips3264r2.igen           |   30 +
 sim/mips/mips3264r6.igen           | 1226 ++++++++++++++++++++++++++++
 sim/mips/sim-main.h                |   94 ++-
 sim/testsuite/mips/basic.exp       |   66 +-
 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     |  290 +++++++
 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, 3734 insertions(+), 51 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

diff --git a/sim/common/sim-bits.h b/sim/common/sim-bits.h
index f8c2563e5bd..1caf0f705a6 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)(signed8)(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)(signed16)(X))
+#define EXTEND18(X)  (LSSEXT ((X), 18))
+#define EXTEND19(X)  (LSSEXT ((X), 19))
+#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)(signed32)(X))
 #define EXTEND64(X) ((signed_word)(signed64)(X))
 
diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in
index d8eba877fb8..26ec3789829 100644
--- a/sim/mips/Makefile.in
+++ b/sim/mips/Makefile.in
@@ -103,6 +103,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 1560b0a48ac..f606640f370 100755
--- a/sim/mips/configure
+++ b/sim/mips/configure
@@ -12297,7 +12297,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"
@@ -12313,6 +12314,12 @@ case "${target}" in
 			  mips32r2:mips32r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,f:mipsisa32r2"
 			sim_multi_default=mipsisa32r2
 			;;
+  mipsisa32r6*-*-*)	sim_gen=M16
+			sim_igen_machine="-M mips32r6,mips16,mips16e,mdmx,dsp,dsp2,smartmips"
+			sim_m16_machine="-M mips16,mips16e,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"
@@ -12325,6 +12332,12 @@ case "${target}" in
 			sim_igen_filter="32,64,f"
 			sim_mach_default="mipsisa64r2"
 			;;
+  mipsisa64r6*-*-*)	sim_gen=M16
+			sim_igen_machine="-M mips64r6,mips16,mips16e,mdmx,dsp,dsp2"
+			sim_m16_machine="-M mips16,mips16e,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"
@@ -12430,7 +12443,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 == NULL)
+       mach = STATE_ARCHITECTURE (SD)->mach;
+  }
 
   switch (mach)
     {
diff --git a/sim/mips/configure.ac b/sim/mips/configure.ac
index fee3816b57a..f9e793ae2a4 100644
--- a/sim/mips/configure.ac
+++ b/sim/mips/configure.ac
@@ -129,7 +129,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"
@@ -145,6 +146,12 @@ case "${target}" in
 			  mips32r2:mips32r2,mips3d,mips16,mips16e,mdmx,dsp,dsp2,smartmips:32,f:mipsisa32r2"
 			sim_multi_default=mipsisa32r2
 			;;
+  mipsisa32r6*-*-*)	sim_gen=M16
+			sim_igen_machine="-M mips32r6,mips16,mips16e,mdmx,dsp,dsp2,smartmips"
+			sim_m16_machine="-M mips16,mips16e,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"
@@ -157,6 +164,12 @@ case "${target}" in
 			sim_igen_filter="32,64,f"
 			sim_mach_default="mipsisa64r2"
 			;;
+  mipsisa64r6*-*-*)	sim_gen=M16
+			sim_igen_machine="-M mips64r6,mips16,mips16e,mdmx,dsp,dsp2"
+			sim_m16_machine="-M mips16,mips16e,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"
diff --git a/sim/mips/cp1.c b/sim/mips/cp1.c
index 03ed0c0558f..1c2b1c3b91a 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(unsigned64 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,113 @@ fp_test(unsigned64 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 */
+};
+
+unsigned64
+fp_classify (sim_cpu *cpu,
+	     address_word cia,
+	     unsigned64 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:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+  return sim_fpu_class_mips_mapping[sim_fpu_classify (&wop) - 1];
+}
+
+int
+fp_rint (sim_cpu *cpu,
+	 address_word cia,
+	 unsigned64 op,
+	 unsigned64 *ans,
+	 FP_formats fmt)
+{
+  sim_fpu wop = {0}, wtemp = {0}, wmagic = {0}, wans = {0};
+  signed64 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:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+
+  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 ((unsigned32 *) 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:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+    }
+
+  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,
@@ -625,6 +738,90 @@ fp_cmp(sim_cpu *cpu,
     }
 }
 
+unsigned64
+fp_r6_cmp (sim_cpu *cpu,
+	   address_word cia,
+	   unsigned64 op1,
+	   unsigned64 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:
+      abort ();
+      break;
+    }
+
+  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:
+	  fprintf (stderr, "Bad switch\n");
+	  abort ();
+	  break;
+	}
+     }
+   else
+     return 0;
+}
 
 /* Basic arithmetic operations.  */
 
@@ -635,7 +832,7 @@ fp_unary(sim_cpu *cpu,
 	 unsigned64 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);
@@ -696,9 +893,9 @@ fp_binary(sim_cpu *cpu,
 	  unsigned64 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;
@@ -889,6 +1086,90 @@ fp_mac(sim_cpu *cpu,
   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 *),
+	    unsigned64 op1,
+	    unsigned64 op2,
+	    unsigned64 op3,
+	    sim_fpu_round round,
+	    sim_fpu_denorm denorm,
+	    FP_formats fmt,
+	    unsigned64 *result)
+{
+  sim_fpu wop1, wop2, ans;
+  sim_fpu_status status = 0;
+  sim_fpu_status op_status;
+  unsigned32 t32 = 0;
+  unsigned64 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 unsigned64
+fp_fmac (sim_cpu *cpu,
+	 address_word cia,
+	 int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),
+	 unsigned64 op1,
+	 unsigned64 op2,
+	 unsigned64 op3,
+	 FP_formats fmt)
+{
+  sim_fpu_round round = rounding_mode (GETRM());
+  sim_fpu_denorm denorm = denorm_mode (cpu);
+  sim_fpu_status status = 0;
+  unsigned64 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_eprintf (SD, "Bad switch\n");
+      abort ();
+  }
+
+  update_fcsr (cpu, cia, status);
+  return result;
+}
+
 /* Common rsqrt code for single operands (.s or .d), intermediate rounding.  */
 static sim_fpu_status
 inner_rsqrt(unsigned64 op1,
@@ -1039,6 +1320,96 @@ fp_div(sim_cpu *cpu,
   return fp_binary(cpu, cia, &sim_fpu_div, op1, op2, fmt);
 }
 
+unsigned64
+fp_min (sim_cpu *cpu,
+	address_word cia,
+	unsigned64 op1,
+	unsigned64 op2,
+	FP_formats fmt)
+{
+  return fp_binary (cpu, cia, &sim_fpu_min, op1, op2, fmt);
+}
+
+unsigned64
+fp_max (sim_cpu *cpu,
+	address_word cia,
+	unsigned64 op1,
+	unsigned64 op2,
+	FP_formats fmt)
+{
+  return fp_binary (cpu, cia, &sim_fpu_max, op1, op2, fmt);
+}
+
+unsigned64
+fp_mina (sim_cpu *cpu,
+	 address_word cia,
+	 unsigned64 op1,
+	 unsigned64 op2,
+	 FP_formats fmt)
+{
+  unsigned64 ret = 0;
+  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:
+      fprintf (stderr, "Invalid fmt.\n");
+      abort ();
+    }
+
+  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;
+}
+
+unsigned64
+fp_maxa (sim_cpu *cpu,
+	 address_word cia,
+	 unsigned64 op1,
+	 unsigned64 op2,
+	 FP_formats fmt)
+{
+  unsigned64 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:
+      fprintf (stderr, "Invalid fmt.\n");
+      abort ();
+    }
+
+  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;
+}
+
 unsigned64
 fp_recip(sim_cpu *cpu,
          address_word cia,
@@ -1088,6 +1459,28 @@ fp_msub(sim_cpu *cpu,
   return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 0, fmt);
 }
 
+unsigned64
+fp_fmadd (sim_cpu *cpu,
+          address_word cia,
+          unsigned64 op1,
+          unsigned64 op2,
+          unsigned64 op3,
+          FP_formats fmt)
+{
+  return fp_fmac (cpu, cia, &sim_fpu_add, op1, op2, op3, fmt);
+}
+
+unsigned64
+fp_fmsub (sim_cpu *cpu,
+          address_word cia,
+          unsigned64 op1,
+          unsigned64 op2,
+          unsigned64 op3,
+          FP_formats fmt)
+{
+  return fp_fmac (cpu, cia, &sim_fpu_sub, op1, op2, op3, fmt);
+}
+
 unsigned64
 fp_nmadd(sim_cpu *cpu,
          address_word cia,
diff --git a/sim/mips/cp1.h b/sim/mips/cp1.h
index 0babdc28eca..9e6b9153e42 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 00c1b632889..2c3b5d3d7fd 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -1523,6 +1523,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
@@ -1531,7 +1535,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 08c5bb7a2dc..b41411cd887 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 160ca2a8c45..71acf9abdbc 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
+{
+  unsigned32 maj = (instr & 0xfc000000) >> 26;
+  unsigned32 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:
 {
   signed64 time = sim_events_time (SD);
   hi->op.timestamp = time;
@@ -509,6 +568,7 @@
 *mips32r2:
 *micromips64:
 *micromips32:
+*mips64r6:
 {
 #if 0 /* XXX FIXME: enable this only after some additional testing.  */
   if (UserMode && (SR & (status_UX|status_PX)) == 0)
@@ -1081,7 +1141,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
 {
   unsigned32 instruction = instruction_0;
   address_word base = GPR[basereg];
@@ -1111,12 +1171,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 +1198,8 @@
 	if (LLBIT)
 	  StoreMemory (AccessLength_DOUBLEWORD, memval, memval1, paddr, vaddr,
 		       isREAL);
-	GPR[rt] = LLBIT;
+	if (store_ll_bit)
+	  GPR[rt] = LLBIT;
       }
   }
 }
@@ -1376,6 +1438,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1763,8 +1826,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1812,8 +1877,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1841,8 +1908,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1868,8 +1937,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1888,8 +1959,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1922,6 +1995,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 +2041,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -1997,7 +2083,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 +2157,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2114,8 +2210,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2165,8 +2263,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2209,6 +2309,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 +2385,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2322,8 +2436,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -2370,6 +2486,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2409,6 +2526,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2432,6 +2550,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2450,6 +2569,8 @@
   if (RT != RD)
     Unpredictable ();
   check_u64 (SD_, instruction_0);
+  if (RT != RD)
+    Unpredictable ();
   do_dclo (SD_, RD, RS);
 }
 
@@ -2464,6 +2585,8 @@
   if (RT != RD)
     Unpredictable ();
   check_u64 (SD_, instruction_0);
+  if (RT != RD)
+    Unpredictable ();
   do_dclz (SD_, RD, RS);
 }
 
@@ -2771,6 +2894,7 @@
 000000,00001,5.RT,5.RD,5.SHIFT,111010::64::DROR
 "dror r<RD>, r<RT>, <SHIFT>"
 *mips64r2:
+*mips64r6:
 *vr5400:
 *vr5500:
 {
@@ -2781,6 +2905,7 @@
 000000,00001,5.RT,5.RD,5.SHIFT,111110::64::DROR32
 "dror32 r<RD>, r<RT>, <SHIFT>"
 *mips64r2:
+*mips64r6:
 *vr5400:
 *vr5500:
 {
@@ -2791,6 +2916,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 +2939,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2828,6 +2955,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2850,6 +2978,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2872,6 +3001,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2887,6 +3017,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2910,6 +3041,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2932,6 +3064,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2947,6 +3080,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2972,6 +3106,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -2987,6 +3122,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3009,6 +3145,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3026,8 +3163,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3048,8 +3187,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3071,8 +3212,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3086,7 +3229,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 +3247,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3114,7 +3261,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 +3381,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3251,8 +3402,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3268,6 +3421,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3335,8 +3489,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3354,8 +3510,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3405,8 +3563,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3424,8 +3584,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3498,6 +3660,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -3882,8 +4045,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3908,8 +4073,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3935,8 +4102,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -3973,7 +4142,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 +4155,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 +4259,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4109,7 +4284,7 @@
 *vr4100:
 *vr5000:
 {
-  do_sc (SD_, RT, OFFSET, BASE, instruction_0);
+  do_sc (SD_, RT, OFFSET, BASE, instruction_0, 1);
 }
 
 
@@ -4124,7 +4299,7 @@
 *vr5000:
 {
   check_u64 (SD_, instruction_0);
-  do_scd (SD_, RT, OFFSET, BASE);
+  do_scd (SD_, RT, OFFSET, BASE, 1);
 }
 
 
@@ -4135,6 +4310,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4200,8 +4376,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4239,16 +4417,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 +4448,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4296,8 +4476,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4322,8 +4504,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4348,8 +4532,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4375,8 +4561,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4404,8 +4592,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4435,8 +4625,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4465,8 +4657,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4495,8 +4689,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4514,8 +4710,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4542,8 +4740,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4561,8 +4761,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *r3900:
 *vr5000:
@@ -4637,8 +4839,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4656,8 +4860,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4674,8 +4880,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4708,8 +4916,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4759,8 +4969,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4776,8 +4988,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4827,8 +5041,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4844,8 +5060,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -4886,8 +5104,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4912,8 +5132,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -4996,6 +5218,8 @@
 *mipsIII:
 *mipsIV:
 *mips32:
+*mips32r6:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5051,10 +5275,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:
 //
@@ -5102,6 +5343,7 @@
 *mips32:
 *mips32r2:
 *micromips32:
+ *mips32r6:
 {
   int bigendian = (BigEndianCPU ? ! ReverseEndian : ReverseEndian);
   address_word vaddr;
@@ -5131,8 +5373,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5151,8 +5395,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5263,8 +5509,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5281,8 +5529,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5328,8 +5578,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   do_cfc1 (SD_, RT, FS);
 }
@@ -5365,8 +5617,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   do_ctc1 (SD_, RT, FS);
 }
@@ -5384,8 +5638,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5400,8 +5656,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5433,8 +5691,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5474,8 +5734,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5493,8 +5755,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5526,6 +5790,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5561,6 +5826,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5577,8 +5843,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5595,8 +5863,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5610,6 +5880,7 @@
 *mipsII:
 *mips32:
 *mips32r2:
+*mips32r6:
 {
   check_fpu (SD_);
   COP_LD (1, FT, do_load_double (SD_, GPR[BASE], EXTEND16 (OFFSET)));
@@ -5623,6 +5894,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5684,8 +5956,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5740,8 +6014,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5759,8 +6035,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5869,8 +6147,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5888,8 +6168,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -5907,8 +6189,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6005,8 +6289,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr5000:
 {
   do_recip_fmt (SD_, FMT, FD, FS);
@@ -6019,8 +6305,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6037,8 +6325,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6052,8 +6342,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr5000:
 {
   do_rsqrt_fmt (SD_, FMT, FD, FS);
@@ -6065,6 +6357,7 @@
 *mipsII:
 *mips32:
 *mips32r2:
+*mips32r6:
 {
   do_sdc1 (SD_, FT, OFFSET, BASE);
 }
@@ -6077,6 +6370,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6088,7 +6382,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 +6431,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6156,8 +6452,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6176,8 +6474,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6205,8 +6505,10 @@
 *mipsIV:
 *mipsV:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6223,8 +6525,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6249,8 +6553,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6272,8 +6578,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6287,8 +6595,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 
 
@@ -6301,11 +6611,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 +6642,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 +6653,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   DecodeCoproc (instruction_0, 0, cp0_dmfc0, RT, RD, SEL);
@@ -6350,6 +6667,7 @@
 *mipsV:
 *mips64:
 *mips64r2:
+*mips64r6:
 {
   check_u64 (SD_, instruction_0);
   DecodeCoproc (instruction_0, 0, cp0_dmtc0, RT, RD, SEL);
@@ -6363,8 +6681,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 {
@@ -6392,8 +6712,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6412,8 +6734,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 *r3900:
@@ -6446,8 +6770,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *r3900:
 {
@@ -6465,8 +6791,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6480,8 +6808,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6495,8 +6825,10 @@
 *mipsV:
 *mips32:
 *mips32r2:
+*mips32r6:
 *mips64:
 *mips64r2:
+*mips64r6:
 *vr4100:
 *vr5000:
 
@@ -6510,13 +6842,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 2c1e7195733..c844fe3a703 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..60a8c910416
--- /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:
+{
+  unsigned64 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:
+{
+  unsigned32 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:
+{
+  unsigned64 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:
+{
+  unsigned32 rs = GPR[RS];
+  unsigned32 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:
+{
+  unsigned64 rs = GPR[RS];
+  unsigned64 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 */
+  unsigned32 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 */
+  unsigned64 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:
+{
+  unsigned32 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:
+{
+  unsigned32 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:
+{
+  unsigned32 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:
+{
+  unsigned64 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:
+{
+  signed64 prod;
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  prod = ((signed64)(signed32) GPR[RS])
+    * ((signed64)(signed32) 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:
+{
+  signed64 prod;
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  prod = ((signed64)(signed32) GPR[RS])
+    * ((signed64)(signed32) 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:
+{
+  unsigned64 prod;
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  prod = ((unsigned64)(unsigned32) GPR[RS])
+    * ((unsigned64)(unsigned32) 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:
+{
+  unsigned64 prod;
+  if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT]))
+    Unpredictable ();
+  TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]);
+  prod = ((unsigned64)(unsigned32) GPR[RS])
+    * ((unsigned64)(unsigned32) 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:
+{
+  signed32 n = GPR[RS];
+  signed32 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:
+{
+  signed32 n = GPR[RS];
+  signed32 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:
+{
+  unsigned32 n = GPR[RS];
+  unsigned32 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:
+{
+  unsigned32 n = GPR[RS];
+  unsigned32 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:
+{
+  unsigned64 lo;
+  unsigned64 m00;
+  unsigned64 m01;
+  unsigned64 m10;
+  unsigned64 mid;
+  int sign;
+  unsigned64 op1 = GPR[RS];
+  unsigned64 op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* make signed multiply unsigned */
+  sign = 0;
+  if ((signed64) op1 < 0)
+    {
+      op1 = - op1;
+      ++sign;
+    }
+  if ((signed64) op2 < 0)
+    {
+      op2 = - op2;
+      ++sign;
+    }
+  /* multiply out the sub products */
+  m00 = ((unsigned64) VL4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m10 = ((unsigned64) VH4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m01 = ((unsigned64) VL4_8 (op1) * (unsigned64) VH4_8 (op2));
+  /* add the products */
+  mid = ((unsigned64) VH4_8 (m00)
+	 + (unsigned64) VL4_8 (m10)
+	 + (unsigned64) 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:
+{
+  unsigned64 lo;
+  unsigned64 hi;
+  unsigned64 m00;
+  unsigned64 m01;
+  unsigned64 m10;
+  unsigned64 m11;
+  unsigned64 mid;
+  int sign;
+  unsigned64 op1 = GPR[RS];
+  unsigned64 op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* make signed multiply unsigned */
+  sign = 0;
+  if ((signed64) op1 < 0)
+    {
+      op1 = - op1;
+      ++sign;
+    }
+  if ((signed64) op2 < 0)
+    {
+      op2 = - op2;
+      ++sign;
+    }
+  /* multiply out the 4 sub products */
+  m00 = ((unsigned64) VL4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m10 = ((unsigned64) VH4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m01 = ((unsigned64) VL4_8 (op1) * (unsigned64) VH4_8 (op2));
+  m11 = ((unsigned64) VH4_8 (op1) * (unsigned64) VH4_8 (op2));
+  /* add the products */
+  mid = ((unsigned64) VH4_8 (m00)
+	 + (unsigned64) VL4_8 (m10)
+	 + (unsigned64) VL4_8 (m01));
+  lo = U8_4 (mid, m00);
+  hi = (m11
+	+ (unsigned64) VH4_8 (mid)
+	+ (unsigned64) VH4_8 (m01)
+	+ (unsigned64) 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:
+{
+  unsigned64 lo;
+  unsigned64 m00;
+  unsigned64 m01;
+  unsigned64 m10;
+  unsigned64 mid;
+  unsigned64 op1 = GPR[RS];
+  unsigned64 op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* multiply out the sub products */
+  m00 = ((unsigned64) VL4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m10 = ((unsigned64) VH4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m01 = ((unsigned64) VL4_8 (op1) * (unsigned64) VH4_8 (op2));
+  /* add the products */
+  mid = ((unsigned64) VH4_8 (m00)
+	 + (unsigned64) VL4_8 (m10)
+	 + (unsigned64) 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:
+{
+  unsigned64 lo;
+  unsigned64 hi;
+  unsigned64 m00;
+  unsigned64 m01;
+  unsigned64 m10;
+  unsigned64 m11;
+  unsigned64 mid;
+  unsigned64 op1 = GPR[RS];
+  unsigned64 op2 = GPR[RT];
+
+  check_u64 (SD_, instruction_0);
+  TRACE_ALU_INPUT2 (op1, op2);
+  /* multiply out the 4 sub products */
+  m00 = ((unsigned64) VL4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m10 = ((unsigned64) VH4_8 (op1) * (unsigned64) VL4_8 (op2));
+  m01 = ((unsigned64) VL4_8 (op1) * (unsigned64) VH4_8 (op2));
+  m11 = ((unsigned64) VH4_8 (op1) * (unsigned64) VH4_8 (op2));
+  /* add the products */
+  mid = ((unsigned64) VH4_8 (m00)
+	 + (unsigned64) VL4_8 (m10)
+	 + (unsigned64) VL4_8 (m01));
+  lo = U8_4 (mid, m00);
+  hi = (m11
+	+ (unsigned64) VH4_8 (mid)
+	+ (unsigned64) VH4_8 (m01)
+	+ (unsigned64) 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:
+{
+  signed64 n = GPR[RS];
+  signed64 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:
+{
+  signed64 n = GPR[RS];
+  signed64 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:
+{
+  unsigned64 n = GPR[RS];
+  unsigned64 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:
+{
+  unsigned64 n = GPR[RS];
+  unsigned64 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 e8531405ebc..562e004ad13 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, unsigned64 op1, unsigned64 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, unsigned64 op1, unsigned64 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)
+unsigned64 fp_r6_cmp (SIM_STATE, unsigned64 op1, unsigned64 op2,
+		      FP_formats fmt, int cond);
+#define R6Compare(op1,op2,fmt,cond) fp_r6_cmp(SIM_ARGS, op1, op2, fmt, cond)
+unsigned64 fp_classify(SIM_STATE, unsigned64 op, FP_formats fmt);
+#define Classify(op, fmt) fp_classify(SIM_ARGS, op, fmt)
+int fp_rint(SIM_STATE, unsigned64 op, unsigned64 *ans, FP_formats fmt);
+#define RoundToIntegralExact(op, ans, fmt) fp_rint(SIM_ARGS, op, ans, fmt)
 unsigned64 fp_abs (SIM_STATE, unsigned64 op, FP_formats fmt);
 #define AbsoluteValue(op,fmt) fp_abs(SIM_ARGS, op, fmt)
 unsigned64 fp_neg (SIM_STATE, unsigned64 op, FP_formats fmt);
@@ -733,6 +791,14 @@ unsigned64 fp_mul (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
 #define Multiply(op1,op2,fmt) fp_mul(SIM_ARGS, op1, op2, fmt)
 unsigned64 fp_div (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
 #define Divide(op1,op2,fmt) fp_div(SIM_ARGS, op1, op2, fmt)
+unsigned64 fp_min (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
+#define Min(op1,op2,fmt) fp_min(SIM_ARGS, op1, op2, fmt)
+unsigned64 fp_max (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
+#define Max(op1,op2,fmt) fp_max(SIM_ARGS, op1, op2, fmt)
+unsigned64 fp_mina (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
+#define MinA(op1,op2,fmt) fp_mina(SIM_ARGS, op1, op2, fmt)
+unsigned64 fp_maxa (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt);
+#define MaxA(op1,op2,fmt) fp_maxa(SIM_ARGS, op1, op2, fmt)
 unsigned64 fp_recip (SIM_STATE, unsigned64 op, FP_formats fmt);
 #define Recip(op,fmt) fp_recip(SIM_ARGS, op, fmt)
 unsigned64 fp_sqrt (SIM_STATE, unsigned64 op, FP_formats fmt);
@@ -741,6 +807,12 @@ unsigned64 fp_rsqrt (SIM_STATE, unsigned64 op, FP_formats fmt);
 #define RSquareRoot(op,fmt) fp_rsqrt(SIM_ARGS, op, fmt)
 unsigned64 fp_madd (SIM_STATE, unsigned64 op1, unsigned64 op2,
 		    unsigned64 op3, FP_formats fmt);
+#define FusedMultiplyAdd(op1,op2,op3,fmt) fp_fmadd(SIM_ARGS, op1, op2, op3, fmt)
+unsigned64 fp_fmadd (SIM_STATE, unsigned64 op1, unsigned64 op2,
+		     unsigned64 op3, FP_formats fmt);
+#define FusedMultiplySub(op1,op2,op3,fmt) fp_fmsub(SIM_ARGS, op1, op2, op3, fmt)
+unsigned64 fp_fmsub (SIM_STATE, unsigned64 op1, unsigned64 op2,
+		     unsigned64 op3, FP_formats fmt);
 #define MultiplyAdd(op1,op2,op3,fmt) fp_madd(SIM_ARGS, op1, op2, op3, fmt)
 unsigned64 fp_msub (SIM_STATE, unsigned64 op1, unsigned64 op2,
 		    unsigned64 op3, FP_formats fmt);
diff --git a/sim/testsuite/mips/basic.exp b/sim/testsuite/mips/basic.exp
index 352b3b4e719..89cc35512db 100644
--- a/sim/testsuite/mips/basic.exp
+++ b/sim/testsuite/mips/basic.exp
@@ -34,14 +34,62 @@ proc run_micromips_test { name requested_machs } {
     set global_as_options $gas_old
 }
 
+# Runs endian tests
+proc run_endian_tests { name requested_machs } {
+    global global_as_options;
+    global global_ld_options;
+    run_sim_test $name $requested_machs
+    set gas_old $global_as_options;
+    set ld_old $global_ld_options;
+    append global_as_options " -EL "
+    append global_ld_options " -EL "
+    run_sim_test $name $requested_machs
+    set global_as_options $gas_old
+    set global_ld_options $ld_old
+}
+
 # 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
+        }
+    }
+}
+
 # Only test mips*-*-elf (e.g., no mips*-*-linux)
 if {[istarget mips*-*-elf]} {
+    # Used to locate the `run` program.
+    global arch
+    set arch "mips"
+
     set dspmodels ""
     set mdmxmodels ""
     set micromipsmodels ""
@@ -57,11 +105,11 @@ if {[istarget mips*-*-elf]} {
 	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 mipsisa32*-*-elf]} {
 	set models "mips32 mips32r2"
@@ -102,4 +150,14 @@ if {[istarget mips*-*-elf]} {
     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 "mips32r6"
+    run_endian_tests r6-llsc-dp.s "mips64r6"
 }
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..bd5c339134d
--- /dev/null
+++ b/sim/testsuite/mips/r6-branch.s
@@ -0,0 +1,290 @@
+# 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
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..32d4e58e7dc
--- /dev/null
+++ b/sim/testsuite/mips/r6-fpu.s
@@ -0,0 +1,446 @@
+# mips r6 fpu test for FMADD/FMSUB etc.
+# 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:
+
+  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 a0fcd0a7f08..f23ea643e02 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.25.1


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

* [PATCH v2 5/5] gdb: mips: Add MIPSR6 support
  2021-05-24 17:57     ` [PATCH v2 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
                         ` (3 preceding siblings ...)
  2021-05-24 17:58       ` [PATCH v2 4/5] sim: mips: Add simulator support for mips32r6/mips64r6 Faraz Shahbazker
@ 2021-05-24 17:58       ` Faraz Shahbazker
  2021-05-29  1:53         ` Simon Marchi
  4 siblings, 1 reply; 50+ messages in thread
From: Faraz Shahbazker @ 2021-05-24 17:58 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger; +Cc: Chao-ying Fu, Faraz Shahbazker

2021-05-24  Andrew Bennett  <andrew.bennett@imgtec.com>
	    Matthew Fortune  <matthew.fortune@mips.com>
	    Faraz Shahbazker  <fshahbazker@wavecomp.com>

gdb/ChangeLog:
	* mips-tdep.c (is_mipsr6_isa): New.
	(b0s21_imm): New define.
	(mips32_relative_offset21, mips32_relative_offset26): New.
	(is_add32bit_overflow, is_add64bit_overflow): New.
	(mips32_next_pc): Handle r6 compact and fpu coprocessor branches.
	Move handling of BLEZ, BGTZ opcode into ...
	(mips32_blez_pc): New.
	(mips32_instruction_is_compact_branch): New.
	(mips32_insn_at_pc_has_forbidden_slot):  New.
	(mips32_scan_prologue): Ignore pre-r6 addi encoding on r6.
	Stop at compact branch also.
	(LLSC_R6_OPCODE,LL_R6_FUNCT,LLE_FUNCT,
	LLD_R6_FUNCT,SC_R6_FUNCT,SCE_FUNCT,
	SCD_R6_FUNCT: New defines.
	(is_ll_insn, is_sc_insn): New.
	(mips_deal_with_atomic_sequence): Use is_ll_insn/is_sc_insn.
	Handle compact branches.
	(mips_about_to_return): Handle jrc and macro jr.
	(mips32_stack_frame_destroyed_p): Likewise.
	(mips32_instruction_has_delay_slot): Don't handle JALX no r6.
	Handle compact branches and coprocessor branches.
	(mips_adjust_breakpoint_address): Skip forbidden slot for
	compact branches.
---
 gdb/mips-tdep.c | 518 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 477 insertions(+), 41 deletions(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 2fe83324738..1009b4a56f5 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -76,6 +76,9 @@ static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
 static void mips_print_float_info (struct gdbarch *, struct ui_file *,
 				   struct frame_info *, const char *);
 
+static void mips_read_fp_register_single (struct frame_info *, int,
+					  gdb_byte *);
+
 /* A useful bit in the CP0 status register (MIPS_PS_REGNUM).  */
 /* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip.  */
 #define ST0_FR (1 << 26)
@@ -1471,6 +1474,16 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
   return extract_unsigned_integer (buf, instlen, byte_order);
 }
 
+/* Return one if the gdbarch is based on MIPS Release 6.  */
+static int
+is_mipsr6_isa (struct gdbarch *gdbarch)
+{
+  const struct bfd_arch_info *info = gdbarch_bfd_arch_info (gdbarch);
+
+  return (info->mach == bfd_mach_mipsisa32r6
+	  || info->mach == bfd_mach_mipsisa64r6);
+}
+
 /* These are the fields of 32 bit mips instructions.  */
 #define mips32_op(x) (x >> 26)
 #define itype_op(x) (x >> 26)
@@ -1513,6 +1526,7 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
 #define b0s11_op(x) ((x) & 0x7ff)
 #define b0s12_imm(x) ((x) & 0xfff)
 #define b0s16_imm(x) ((x) & 0xffff)
+#define b0s21_imm(x) ((x) & 0x1fffff)
 #define b0s26_imm(x) ((x) & 0x3ffffff)
 #define b6s10_ext(x) (((x) >> 6) & 0x3ff)
 #define b11s5_reg(x) (((x) >> 11) & 0x1f)
@@ -1549,6 +1563,18 @@ mips32_relative_offset (ULONGEST inst)
   return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2;
 }
 
+static LONGEST
+mips32_relative_offset21 (ULONGEST insn)
+{
+  return ((b0s21_imm (insn) ^ 0x100000) - 0x100000) << 2;
+}
+
+static LONGEST
+mips32_relative_offset26 (ULONGEST insn)
+{
+  return ((b0s26_imm (insn) ^ 0x2000000) - 0x2000000) << 2;
+}
+
 /* Determine the address of the next instruction executed after the INST
    floating condition branch instruction at PC.  COUNT specifies the
    number of the floating condition bits tested by the branch.  */
@@ -1607,6 +1633,71 @@ is_octeon_bbit_op (int op, struct gdbarch *gdbarch)
   return 0;
 }
 
+static int
+is_add32bit_overflow (int32_t a, int32_t b)
+{
+  int32_t r = (uint32_t) a + (uint32_t) b;
+  return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
+}
+
+static int
+is_add64bit_overflow (int64_t a, int64_t b)
+{
+  if (a != (int32_t)a)
+    return 1;
+  if (b != (int32_t)b)
+    return 1;
+  return is_add32bit_overflow ((int32_t)a, (int32_t)b);
+}
+
+/* Calculate address of next instruction after BLEZ.  */
+
+static CORE_ADDR
+mips32_blez_pc (struct gdbarch *gdbarch, struct regcache *regcache,
+		ULONGEST inst, CORE_ADDR pc, int invert)
+{
+  int rs = itype_rs (inst);
+  int rt = itype_rt (inst);
+  LONGEST val_rs = regcache_raw_get_signed (regcache, rs);
+  LONGEST val_rt = regcache_raw_get_signed (regcache, rt);
+  ULONGEST uval_rs = regcache_raw_get_unsigned (regcache, rs);
+  ULONGEST uval_rt = regcache_raw_get_unsigned (regcache, rt);
+  int taken = 0;
+  int delay_slot_size = 4;
+
+  /* BLEZ, BLEZL, BGTZ, BGTZL */
+  if (rt == 0)
+    taken = (val_rs <= 0);
+  else if (is_mipsr6_isa (gdbarch))
+    {
+      /* BLEZALC, BGTZALC */
+      if (rs == 0 && rt != 0)
+	taken = (val_rt <= 0);
+      /* BGEZALC, BLTZALC */
+      else if (rs == rt && rt != 0)
+	taken = (val_rt >= 0);
+      /* BGEUC, BLTUC */
+      else if (rs != rt && rs != 0 && rt != 0)
+	taken = (uval_rs >= uval_rt);
+
+      /* Step through the forbidden slot to avoid repeated exceptions we do
+	 not currently have access to the BD bit when hitting a breakpoint
+	 and therefore cannot tell if the breakpoint hit on the branch or the
+	 forbidden slot.  */
+      /* delay_slot_size = 0; */
+    }
+
+  if (invert)
+    taken = !taken;
+
+  /* Calculate branch target.  */
+  if (taken)
+    pc += mips32_relative_offset (inst);
+  else
+    pc += delay_slot_size;
+
+  return pc;
+}
 
 /* Determine where to set a single step breakpoint while considering
    branch prediction.  */
@@ -1617,12 +1708,17 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
   struct gdbarch *gdbarch = regcache->arch ();
   unsigned long inst;
   int op;
+  int mips64bitreg = 0;
+
+  if (mips_isa_regsize (gdbarch) == 8)
+    mips64bitreg = 1;
+
   inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
   op = itype_op (inst);
   if ((inst & 0xe0000000) != 0)		/* Not a special, jump or branch
 					   instruction.  */
     {
-      if (op >> 2 == 5)
+      if (op >> 2 == 5 && ((op & 0x02) == 0 || itype_rt (inst) == 0))
 	/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
 	{
 	  switch (op & 0x03)
@@ -1632,7 +1728,7 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	    case 1:		/* BNEL */
 	      goto neq_branch;
 	    case 2:		/* BLEZL */
-	      goto less_branch;
+	      goto lez_branch;
 	    case 3:		/* BGTZL */
 	      goto greater_branch;
 	    default:
@@ -1642,15 +1738,19 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
       else if (op == 17 && itype_rs (inst) == 8)
 	/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
 	pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 1);
-      else if (op == 17 && itype_rs (inst) == 9
+      else if (!is_mipsr6_isa (gdbarch)
+	       && op == 17
+	       && itype_rs (inst) == 9
 	       && (itype_rt (inst) & 2) == 0)
 	/* BC1ANY2F, BC1ANY2T: 010001 01001 xxx0x */
 	pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 2);
-      else if (op == 17 && itype_rs (inst) == 10
+      else if (!is_mipsr6_isa (gdbarch)
+               && op == 17
+               && itype_rs (inst) == 10
 	       && (itype_rt (inst) & 2) == 0)
 	/* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
 	pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 4);
-      else if (op == 29)
+      else if (!is_mipsr6_isa (gdbarch) && op == 29)
 	/* JALX: 011101 */
 	/* The new PC will be alternate mode.  */
 	{
@@ -1678,7 +1778,128 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	  else
 	    pc += 8;        /* After the delay slot.  */
 	}
+      else if (is_mipsr6_isa (gdbarch))
+	{
+	  /* BOVC, BEQZALC, BEQC and BNVC, BNEZALC, BNEC */
+	  if (op == 8 || op == 24)
+	    {
+	      int rs = rtype_rs (inst);
+	      int rt = rtype_rt (inst);
+	      LONGEST val_rs = regcache_raw_get_signed (regcache, rs);
+	      LONGEST val_rt = regcache_raw_get_signed (regcache, rt);
+	      int taken = 0;
+	      /* BOVC (BNVC) */
+	      if (rs >= rt)
+		{
+		  if (mips64bitreg == 1)
+		    taken = is_add64bit_overflow (val_rs, val_rt);
+		  else
+		    taken = is_add32bit_overflow (val_rs, val_rt);
+		}
+	      /* BEQZALC (BNEZALC) */
+	      else if (rs < rt && rs == 0)
+		taken = (val_rt == 0);
+	      /* BEQC (BNEC) */
+	      else
+		taken = (val_rs == val_rt);
+
+	      /* BNVC, BNEZALC, BNEC */
+	      if (op == 24)
+		taken = !taken;
+
+	      if (taken)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
+	    }
+	  /* BC1EQZ, BC1NEZ */
+	  else if (op == 17 && (itype_rs (inst) == 9 || itype_rs (inst) == 13))
+	    {
+	      gdb_byte status;
+	      gdb_byte true_val = 0;
+	      unsigned int fp = (gdbarch_num_regs (gdbarch)
+				 + mips_regnum (gdbarch)->fp0
+				 + itype_rt (inst));
+	      struct frame_info *frame = get_current_frame ();
+	      gdb_byte *raw_buffer = (gdb_byte *) alloca (sizeof (gdb_byte) * 4);
+	      mips_read_fp_register_single (frame, fp, raw_buffer);
+
+	      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+		status = *(raw_buffer + 3);
+	      else
+		status = *(raw_buffer);
 
+	      if (itype_rs (inst) == 13)
+		true_val = 1;
+
+	      if ((status & 0x1) == true_val)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		pc += 8;
+	    }
+	  else if (op == 22 || op == 23)
+	  /* BLEZC, BGEZC, BGEC, BGTZC, BLTZC, BLTC */
+	    {
+	      int rs = rtype_rs (inst);
+	      int rt = rtype_rt (inst);
+	      LONGEST val_rs = regcache_raw_get_signed (regcache, rs);
+	      LONGEST val_rt = regcache_raw_get_signed (regcache, rt);
+	      int taken = 0;
+	      /* The R5 rt == 0 case is handled above so we treat it as
+		 an unknown instruction here for future ISA usage.  */
+	      if (rs == 0 && rt != 0)
+		taken = (val_rt <= 0);
+	      else if (rs == rt && rt != 0)
+		taken = (val_rt >= 0);
+	      else if (rs != rt && rs != 0 && rt != 0)
+		taken = (val_rs >= val_rt);
+
+	      if (op == 23)
+		taken = !taken;
+
+	      if (taken)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
+	    }
+	  else if (op == 50 || op == 58)
+	  /* BC, BALC */
+	    pc += mips32_relative_offset26 (inst) + 4;
+	  else if ((op == 54 || op == 62)
+		   && rtype_rs (inst) == 0)
+	  /* JIC, JIALC */
+	    {
+	      pc = regcache_raw_get_signed (regcache, itype_rt (inst));
+	      pc += (itype_immediate (inst) ^ 0x8000) - 0x8000;
+	    }
+	  else if (op == 54 || op == 62)
+	  /* BEQZC, BNEZC */
+	    {
+	      int rs = itype_rs (inst);
+	      LONGEST rs_val = regcache_raw_get_signed (regcache, rs);
+	      int taken = (rs_val == 0);
+	      if (op == 62)
+		taken = !taken;
+	      if (taken)
+		pc += mips32_relative_offset21 (inst) + 4;
+	      else
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
+	    }
+	  else
+	    pc += 4;		/* Not a branch, next instruction is easy.  */
+	}
       else
 	pc += 4;		/* Not a branch, next instruction is easy.  */
     }
@@ -1722,7 +1943,6 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	      case 2:		/* BLTZL */
 	      case 16:		/* BLTZAL */
 	      case 18:		/* BLTZALL */
-	      less_branch:
 		if (regcache_raw_get_signed (regcache, itype_rs (inst)) < 0)
 		  pc += mips32_relative_offset (inst) + 4;
 		else
@@ -1738,22 +1958,38 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 		  pc += 8;	/* after the delay slot */
 		break;
 	      case 0x1c:	/* BPOSGE32 */
+	      case 0x1d:	/* BPOSGE32C */
 	      case 0x1e:	/* BPOSGE64 */
 		pc += 4;
 		if (itype_rs (inst) == 0)
 		  {
 		    unsigned int pos = (op & 2) ? 64 : 32;
 		    int dspctl = mips_regnum (gdbarch)->dspctl;
+		    int delay_slot_size = 4;
 
 		    if (dspctl == -1)
 		      /* No way to handle; it'll most likely trap anyway.  */
 		      break;
 
+		    /* BPOSGE32C */
+		    if (op == 0x1d)
+		      {
+			if (!is_mipsr6_isa (gdbarch))
+			  break;
+
+			/* Step through the forbidden slot to avoid repeated
+			   exceptions we do not currently have access to the BD
+			   bit when hitting a breakpoint and therefore cannot
+			   tell if the breakpoint hit on the branch or the
+			   forbidden slot.  */
+			/* delay_slot_size = 0; */
+		      }
+
 		    if ((regcache_raw_get_unsigned (regcache,
 						    dspctl) & 0x7f) >= pos)
 		      pc += mips32_relative_offset (inst);
 		    else
-		      pc += 4;
+		      pc += delay_slot_size;
 		  }
 		break;
 		/* All of the other instructions in the REGIMM category */
@@ -1787,19 +2023,14 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	  else
 	    pc += 8;
 	  break;
-	case 6:		/* BLEZ, BLEZL */
-	  if (regcache_raw_get_signed (regcache, itype_rs (inst)) <= 0)
-	    pc += mips32_relative_offset (inst) + 4;
-	  else
-	    pc += 8;
+	case 6:		/* BLEZ, BLEZL, BLEZALC, BGEZALC, BGEUC */
+	lez_branch:
+	  pc = mips32_blez_pc (gdbarch, regcache, inst, pc + 4, 0);
 	  break;
 	case 7:
 	default:
-	greater_branch:	/* BGTZ, BGTZL */
-	  if (regcache_raw_get_signed (regcache, itype_rs (inst)) > 0)
-	    pc += mips32_relative_offset (inst) + 4;
-	  else
-	    pc += 8;
+	greater_branch:	/* BGTZ, BGTZL, BGTZALC, BLTZALC, BLTUC */
+	  pc = mips32_blez_pc (gdbarch, regcache, inst, pc + 4, 1);
 	  break;
 	}			/* switch */
     }				/* else */
@@ -2422,6 +2653,72 @@ micromips_instruction_is_compact_branch (unsigned short insn)
     }
 }
 
+/* Return non-zero if the MIPS instruction INSN is a compact branch
+   or jump.  A value of 1 indicates an unconditional compact branch
+   and a value of 2 indicates a conditional compact branch.  */
+
+static int
+mips32_instruction_is_compact_branch (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  switch (itype_op (insn))
+    {
+    /* BC */
+    case 50:
+    /* BALC */
+    case 58:
+      if (is_mipsr6_isa (gdbarch))
+	return 1;
+      break;
+    /* BOVC, BEQZALC, BEQC */
+    case 8:
+    /* BNVC, BNEZALC, BNEC */
+    case 24:
+      if (is_mipsr6_isa (gdbarch))
+	return 2;
+      break;
+    /* BEQZC, JIC */
+    case 54:
+    /* BNEZC, JIALC */
+    case 62:
+      if (is_mipsr6_isa (gdbarch))
+	/* JIC, JIALC are unconditional */
+	return (itype_rs (insn) == 0) ? 1 : 2;
+      break;
+    /* BLEZC, BGEZC, BGEC */
+    case 22:
+    /* BGTZC, BLTZC, BLTC */
+    case 23:
+    /* BLEZALC, BGEZALC, BGEUC */
+    case 6:
+    /* BGTZALC, BLTZALC, BLTUC */
+    case 7:
+      if (is_mipsr6_isa (gdbarch)
+	  && itype_rt (insn) != 0)
+	return 2;
+      break;
+    /* BPOSGE32C */
+    case 1:
+      if (is_mipsr6_isa (gdbarch)
+	  && itype_rt (insn) == 0x1d && itype_rs (insn) == 0)
+	return 2;
+    }
+  return 0;
+}
+
+/* Return non-zero if a standard MIPS instruction at ADDR has a branch
+   forbidden slot (i.e. it is a conditional compact branch instruction).  */
+
+static int
+mips32_insn_at_pc_has_forbidden_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  int status;
+  ULONGEST insn = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
+  if (status)
+    return 0;
+
+  return mips32_instruction_is_compact_branch (gdbarch, insn) == 2;
+}
+
 struct mips_frame_cache
 {
   CORE_ADDR base;
@@ -3463,7 +3760,8 @@ mips32_scan_prologue (struct gdbarch *gdbarch,
       reg = high_word & 0x1f;
 
       if (high_word == 0x27bd		/* addiu $sp,$sp,-i */
-	  || high_word == 0x23bd	/* addi $sp,$sp,-i */
+	  || (high_word == 0x23bd	/* addi $sp,$sp,-i */
+	      && !is_mipsr6_isa (gdbarch))
 	  || high_word == 0x67bd)	/* daddiu $sp,$sp,-i */
 	{
 	  if (offset < 0)		/* Negative stack adjustment?  */
@@ -3598,7 +3896,9 @@ mips32_scan_prologue (struct gdbarch *gdbarch,
 
       /* A jump or branch, or enough non-prologue insns seen?  If so,
 	 then we must have reached the end of the prologue by now.  */
-      if (prev_delay_slot || non_prologue_insns > 1)
+      if (prev_delay_slot
+	  || non_prologue_insns > 1
+	  || mips32_instruction_is_compact_branch (gdbarch, inst))
 	break;
 
       prev_non_prologue_insn = this_non_prologue_insn;
@@ -3902,6 +4202,59 @@ mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
 #define LLD_OPCODE 0x34
 #define SC_OPCODE 0x38
 #define SCD_OPCODE 0x3c
+#define LLSC_R6_OPCODE 0x1f
+#define LL_R6_FUNCT 0x36
+#define LLE_FUNCT 0x2e
+#define LLD_R6_FUNCT 0x37
+#define SC_R6_FUNCT 0x26
+#define SCE_FUNCT 0x1e
+#define SCD_R6_FUNCT 0x27
+
+static int
+is_ll_insn (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  if (itype_op (insn) == LL_OPCODE
+      || itype_op (insn) == LLD_OPCODE)
+    return 1;
+
+  if (rtype_op (insn) == LLSC_R6_OPCODE
+      && rtype_funct (insn) == LLE_FUNCT
+      && (insn & 0x40) == 0)
+    return 1;
+
+  /* Handle LL and LLP varieties.  */
+  if (is_mipsr6_isa (gdbarch)
+      && rtype_op (insn) == LLSC_R6_OPCODE
+      && (rtype_funct (insn) == LL_R6_FUNCT
+	  || rtype_funct (insn) == LLD_R6_FUNCT
+	  || rtype_funct (insn) == LLE_FUNCT))
+    return 1;
+
+  return 0;
+}
+
+static int
+is_sc_insn (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  if (itype_op (insn) == SC_OPCODE
+      || itype_op (insn) == SCD_OPCODE)
+    return 1;
+
+  if (rtype_op (insn) == LLSC_R6_OPCODE
+      && rtype_funct (insn) == SCE_FUNCT
+      && (insn & 0x40) == 0)
+    return 1;
+
+  /* Handle SC and SCP varieties.  */
+  if (is_mipsr6_isa (gdbarch)
+      && rtype_op (insn) == LLSC_R6_OPCODE
+      && (rtype_funct (insn) == SC_R6_FUNCT
+	  || rtype_funct (insn) == SCD_R6_FUNCT
+	  || rtype_funct (insn) == SCE_FUNCT))
+    return 1;
+
+  return 0;
+}
 
 static std::vector<CORE_ADDR>
 mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
@@ -3914,10 +4267,11 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
   int index;
   int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */  
   const int atomic_sequence_length = 16; /* Instruction sequence length.  */
+  int is_mipsr6 = is_mipsr6_isa (gdbarch);
 
   insn = mips_fetch_instruction (gdbarch, ISA_MIPS, loc, NULL);
   /* Assume all atomic sequences start with a ll/lld instruction.  */
-  if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE)
+  if (!is_ll_insn (gdbarch, insn))
     return {};
 
   /* Assume that no atomic sequence is longer than "atomic_sequence_length" 
@@ -3947,28 +4301,72 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
 	  return {}; /* fallback to the standard single-step code.  */
 	case 4: /* BEQ */
 	case 5: /* BNE */
-	case 6: /* BLEZ */
-	case 7: /* BGTZ */
 	case 20: /* BEQL */
 	case 21: /* BNEL */
-	case 22: /* BLEZL */
-	case 23: /* BGTTL */
+	case 22: /* BLEZL (BLEZC, BGEZC, BGEC) */
+	case 23: /* BGTZL (BGTZC, BLTZC, BLTC) */
+	  is_branch = 1;
+	  break;
+	case 6: /* BLEZ (BLEZALC, BGEZALC, BGEUC) */
+	case 7: /* BGTZ (BGTZALC, BLTZALC, BLTUC) */
+	  if (is_mipsr6)
+	    {
+	      /* BLEZALC, BGTZALC */
+	      if (itype_rs (insn) == 0 && itype_rt (insn) != 0)
+		return {}; /* fallback to the standard single-step code.  */
+	      /* BGEZALC, BLTZALC */
+	      else if (itype_rs (insn) == itype_rt (insn)
+		       && itype_rt (insn) != 0)
+		return {}; /* fallback to the standard single-step code.  */
+	    }
 	  is_branch = 1;
 	  break;
+	case 8: /* BOVC, BEQZALC, BEQC */
+	case 24: /* BNVC, BNEZALC, BNEC */
+	  if (is_mipsr6)
+	    is_branch = 1;
+	  break;
+	case 50: /* BC */
+	case 58: /* BALC */
+	  if (is_mipsr6)
+	    return {}; /* fallback to the standard single-step code.  */
+	  break;
+	case 54: /* BEQZC, JIC */
+	case 62: /* BNEZC, JIALC */
+	  if (is_mipsr6)
+	    {
+	      if (itype_rs (insn) == 0) /* JIC, JIALC */
+		return {}; /* fallback to the standard single-step code.  */
+	      else
+		is_branch = 2; /* Marker for branches with a 21-bit offset.  */
+	    }
+	  break;
 	case 17: /* COP1 */
-	  is_branch = ((itype_rs (insn) == 9 || itype_rs (insn) == 10)
-		       && (itype_rt (insn) & 0x2) == 0);
-	  if (is_branch) /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+	  is_branch = ((!is_mipsr6
+			/* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+			&& (itype_rs (insn) == 9 || itype_rs (insn) == 10)
+			&& (itype_rt (insn) & 0x2) == 0)
+		       /* BZ.df:  010001 110xx */
+		       || (itype_rs (insn) & 0x18) == 0x18);
+	  if (is_branch)
 	    break;
 	/* Fall through.  */
 	case 18: /* COP2 */
 	case 19: /* COP3 */
-	  is_branch = (itype_rs (insn) == 8); /* BCzF, BCzFL, BCzT, BCzTL */
+	  /* BCzF, BCzFL, BCzT, BCzTL, BC*EQZ, BC*NEZ */
+	  is_branch = ((itype_rs (insn) == 8)
+		       || (is_mipsr6
+			   && (itype_rs (insn) == 9
+			       || itype_rs (insn) == 13)));
 	  break;
 	}
       if (is_branch)
 	{
-	  branch_bp = loc + mips32_relative_offset (insn) + 4;
+	  /* Is this a special PC21_S2 branch? */
+	  if (is_branch == 2)
+	    branch_bp = loc + mips32_relative_offset21 (insn) + 4;
+	  else
+	    branch_bp = loc + mips32_relative_offset (insn) + 4;
 	  if (last_breakpoint >= 1)
 	    return {}; /* More than one branch found, fallback to the
 			  standard single-step code.  */
@@ -3976,12 +4374,12 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
 	  last_breakpoint++;
 	}
 
-      if (itype_op (insn) == SC_OPCODE || itype_op (insn) == SCD_OPCODE)
+      if (is_sc_insn (gdbarch, insn))
 	break;
     }
 
   /* Assume that the atomic sequence ends with a sc/scd instruction.  */
-  if (itype_op (insn) != SC_OPCODE && itype_op (insn) != SCD_OPCODE)
+  if (!is_sc_insn (gdbarch, insn))
     return {};
 
   loc += MIPS_INSN32_SIZE;
@@ -4206,8 +4604,14 @@ mips_about_to_return (struct gdbarch *gdbarch, CORE_ADDR pc)
   gdb_assert (mips_pc_is_mips (pc));
 
   insn = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
-  hint = 0x7c0;
-  return (insn & ~hint) == 0x3e00008;			/* jr(.hb) $ra */
+  /* Mask the hint and the jalr/jr bit.  */
+  hint = 0x7c1;
+
+  if (is_mipsr6_isa (gdbarch) && insn == 0xd81f0000) /* jrc $31 */
+    return 1;
+
+  /* jr(.hb) $ra and "jalr(.hb) $ra" */
+  return ((insn & ~hint) == 0x3e00008);
 }
 
 
@@ -6711,7 +7115,9 @@ mips32_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 
 	  if (high_word != 0x27bd	/* addiu $sp,$sp,offset */
 	      && high_word != 0x67bd	/* daddiu $sp,$sp,offset */
-	      && inst != 0x03e00008	/* jr $ra */
+	      && (inst & ~0x1) != 0x03e00008 /* jr $31 or jalr $0, $31 */
+	      && (!is_mipsr6_isa (gdbarch)
+		  || inst != 0xd81f0000) /* jrc $31 */
 	      && inst != 0x00000000)	/* nop */
 	    return 0;
 	}
@@ -7092,22 +7498,31 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
   int op;
   int rs;
   int rt;
+  int is_mipsr6 = is_mipsr6_isa (gdbarch);
 
   op = itype_op (inst);
   if ((inst & 0xe0000000) != 0)
     {
       rs = itype_rs (inst);
       rt = itype_rt (inst);
-      return (is_octeon_bbit_op (op, gdbarch) 
-	      || op >> 2 == 5	/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx  */
-	      || op == 29	/* JALX: bits 011101  */
+      return (is_octeon_bbit_op (op, gdbarch)
+	      || (op >> 1 == 10) /* BEQL, BNEL: bits 01010x  */
+	      || (op >> 1 == 11 && rt == 0) /* BLEZL, BGTZL: bits 01011x  */
+	      || (!is_mipsr6 && op == 29)	/* JALX: bits 011101  */
 	      || (op == 17
 		  && (rs == 8
 				/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000  */
-		      || (rs == 9 && (rt & 0x2) == 0)
+		      || (!is_mipsr6 && rs == 9 && (rt & 0x2) == 0)
 				/* BC1ANY2F, BC1ANY2T: bits 010001 01001  */
-		      || (rs == 10 && (rt & 0x2) == 0))));
+		      || (!is_mipsr6 && rs == 10 && (rt & 0x2) == 0)))
 				/* BC1ANY4F, BC1ANY4T: bits 010001 01010  */
+	      || (is_mipsr6
+		  && ((op == 17
+		       && (rs == 9  /* BC1EQZ: 010001 01001  */
+			   || rs == 13))  /* BC1NEZ: 010001 01101  */
+		      || (op == 18
+			  && (rs == 9  /* BC2EQZ: 010010 01001  */
+			      || rs == 13)))));  /* BC2NEZ: 010010 01101  */
     }
   else
     switch (op & 0x07)		/* extract bits 28,27,26  */
@@ -7126,7 +7541,11 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
 		|| ((rt & 0x1e) == 0x1c && rs == 0));
 				/* BPOSGE32, BPOSGE64: bits 1110x  */
 	break;			/* end REGIMM  */
-      default:			/* J, JAL, BEQ, BNE, BLEZ, BGTZ  */
+	case 6:			/* BLEZ  */
+	case 7:			/* BGTZ  */
+	 return (itype_rt (inst) == 0);
+	 break;
+      default:			/* J, JAL, BEQ, BNE  */
 	return 1;
 	break;
       }
@@ -7338,7 +7757,18 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
 
      So, we'll use the second solution.  To do this we need to know if
      the instruction we're trying to set the breakpoint on is in the
-     branch delay slot.  */
+     branch delay slot.
+
+     A similar problem occurs for breakpoints on forbidden slots where
+     the trap will be reported for the branch with the BD bit set.
+     In this case it would be ideal to recover using solution 1 from
+     above as there is no problem with the branch being skipped
+     (since the forbidden slot only exists on not-taken branches).
+     However, the BD bit is not available in all scenarios currently
+     so instead we move the breakpoint on to the next instruction.
+     This means that it is not possible to stop on an instruction
+     that can be in a forbidden slot even if that instruction is
+     jumped to directly.  */
 
   boundary = mips_segment_boundary (bpaddr);
 
@@ -7360,6 +7790,12 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
       prev_addr = bpaddr - 4;
       if (mips32_insn_at_pc_has_delay_slot (gdbarch, prev_addr))
 	bpaddr = prev_addr;
+      /* If the previous instruction has a forbidden slot, we have to
+	 move the breakpoint to the following instruction to prevent
+	 breakpoints in forbidden slots being reported as unknown
+	 traps.  */
+      else if (mips32_insn_at_pc_has_forbidden_slot (gdbarch, prev_addr))
+	bpaddr += 4;
     }
   else
     {
-- 
2.25.1


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

* Re: [PATCH v2 5/5] gdb: mips: Add MIPSR6 support
  2021-05-24 17:58       ` [PATCH v2 5/5] gdb: mips: Add MIPSR6 support Faraz Shahbazker
@ 2021-05-29  1:53         ` Simon Marchi
  2021-06-27 19:10           ` [PATCH v3 " Faraz Shahbazker
  0 siblings, 1 reply; 50+ messages in thread
From: Simon Marchi @ 2021-05-29  1:53 UTC (permalink / raw)
  To: Faraz Shahbazker, gdb-patches, Mike Frysinger; +Cc: Chao-ying Fu



On 2021-05-24 1:58 p.m., Faraz Shahbazker wrote:
> 2021-05-24  Andrew Bennett  <andrew.bennett@imgtec.com>
> 	    Matthew Fortune  <matthew.fortune@mips.com>
> 	    Faraz Shahbazker  <fshahbazker@wavecomp.com>
> 
> gdb/ChangeLog:
> 	* mips-tdep.c (is_mipsr6_isa): New.
> 	(b0s21_imm): New define.
> 	(mips32_relative_offset21, mips32_relative_offset26): New.
> 	(is_add32bit_overflow, is_add64bit_overflow): New.
> 	(mips32_next_pc): Handle r6 compact and fpu coprocessor branches.
> 	Move handling of BLEZ, BGTZ opcode into ...
> 	(mips32_blez_pc): New.
> 	(mips32_instruction_is_compact_branch): New.
> 	(mips32_insn_at_pc_has_forbidden_slot):  New.
> 	(mips32_scan_prologue): Ignore pre-r6 addi encoding on r6.
> 	Stop at compact branch also.
> 	(LLSC_R6_OPCODE,LL_R6_FUNCT,LLE_FUNCT,
> 	LLD_R6_FUNCT,SC_R6_FUNCT,SCE_FUNCT,
> 	SCD_R6_FUNCT: New defines.
> 	(is_ll_insn, is_sc_insn): New.
> 	(mips_deal_with_atomic_sequence): Use is_ll_insn/is_sc_insn.
> 	Handle compact branches.
> 	(mips_about_to_return): Handle jrc and macro jr.
> 	(mips32_stack_frame_destroyed_p): Likewise.
> 	(mips32_instruction_has_delay_slot): Don't handle JALX no r6.
> 	Handle compact branches and coprocessor branches.
> 	(mips_adjust_breakpoint_address): Skip forbidden slot for
> 	compact branches.

Hi,

Please write a commit message describing what this does.

Simon

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

* [PATCH v3 5/5] gdb: mips: Add MIPSR6 support
  2021-05-29  1:53         ` Simon Marchi
@ 2021-06-27 19:10           ` Faraz Shahbazker
  0 siblings, 0 replies; 50+ messages in thread
From: Faraz Shahbazker @ 2021-06-27 19:10 UTC (permalink / raw)
  To: gdb-patches, Mike Frysinger, Simon Marchi; +Cc: Chao-ying Fu, Faraz Shahbazker

Introduce new instruction encodings from Release 6 of the MIPS
architecture[1]. Support breakpoints and single stepping with compact
branches, forbidden slots and new branch instruction and atomic
load-store instruction encodings.

[1] "MIPS64 Architecture for Programmers Volume II-A: The MIPS64
    Instruction Set Reference Manual", Document Number: MD00087,
    Revision 6.06, December 15, 2016, Section 3 "The MIPS64
    Instruction Set", pp. 42-530
https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00087-2B-MIPS64BIS-AFP-6.06.pdf

2021-05-24  Andrew Bennett  <andrew.bennett@imgtec.com>
	    Matthew Fortune  <matthew.fortune@mips.com>
	    Faraz Shahbazker  <fshahbazker@wavecomp.com>

gdb/ChangeLog:
	* mips-tdep.c (is_mipsr6_isa): New.
	(b0s21_imm): New define.
	(mips32_relative_offset21, mips32_relative_offset26): New.
	(is_add32bit_overflow, is_add64bit_overflow): New.
	(mips32_next_pc): Handle r6 compact and fpu coprocessor branches.
	Move handling of BLEZ, BGTZ opcode into ...
	(mips32_blez_pc): New.
	(mips32_instruction_is_compact_branch): New.
	(mips32_insn_at_pc_has_forbidden_slot):  New.
	(mips32_scan_prologue): Ignore pre-r6 addi encoding on r6.
	Stop at compact branch also.
	(LLSC_R6_OPCODE,LL_R6_FUNCT,LLE_FUNCT,
	LLD_R6_FUNCT,SC_R6_FUNCT,SCE_FUNCT,
	SCD_R6_FUNCT: New defines.
	(is_ll_insn, is_sc_insn): New.
	(mips_deal_with_atomic_sequence): Use is_ll_insn/is_sc_insn.
	Handle compact branches.
	(mips_about_to_return): Handle jrc and macro jr.
	(mips32_stack_frame_destroyed_p): Likewise.
	(mips32_instruction_has_delay_slot): Don't handle JALX no r6.
	Handle compact branches and coprocessor branches.
	(mips_adjust_breakpoint_address): Skip forbidden slot for
	compact branches.
---
 gdb/mips-tdep.c | 518 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 477 insertions(+), 41 deletions(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index 2fe83324738..1009b4a56f5 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -76,6 +76,9 @@ static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
 static void mips_print_float_info (struct gdbarch *, struct ui_file *,
 				   struct frame_info *, const char *);
 
+static void mips_read_fp_register_single (struct frame_info *, int,
+					  gdb_byte *);
+
 /* A useful bit in the CP0 status register (MIPS_PS_REGNUM).  */
 /* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip.  */
 #define ST0_FR (1 << 26)
@@ -1471,6 +1474,16 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
   return extract_unsigned_integer (buf, instlen, byte_order);
 }
 
+/* Return one if the gdbarch is based on MIPS Release 6.  */
+static int
+is_mipsr6_isa (struct gdbarch *gdbarch)
+{
+  const struct bfd_arch_info *info = gdbarch_bfd_arch_info (gdbarch);
+
+  return (info->mach == bfd_mach_mipsisa32r6
+	  || info->mach == bfd_mach_mipsisa64r6);
+}
+
 /* These are the fields of 32 bit mips instructions.  */
 #define mips32_op(x) (x >> 26)
 #define itype_op(x) (x >> 26)
@@ -1513,6 +1526,7 @@ mips_fetch_instruction (struct gdbarch *gdbarch,
 #define b0s11_op(x) ((x) & 0x7ff)
 #define b0s12_imm(x) ((x) & 0xfff)
 #define b0s16_imm(x) ((x) & 0xffff)
+#define b0s21_imm(x) ((x) & 0x1fffff)
 #define b0s26_imm(x) ((x) & 0x3ffffff)
 #define b6s10_ext(x) (((x) >> 6) & 0x3ff)
 #define b11s5_reg(x) (((x) >> 11) & 0x1f)
@@ -1549,6 +1563,18 @@ mips32_relative_offset (ULONGEST inst)
   return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2;
 }
 
+static LONGEST
+mips32_relative_offset21 (ULONGEST insn)
+{
+  return ((b0s21_imm (insn) ^ 0x100000) - 0x100000) << 2;
+}
+
+static LONGEST
+mips32_relative_offset26 (ULONGEST insn)
+{
+  return ((b0s26_imm (insn) ^ 0x2000000) - 0x2000000) << 2;
+}
+
 /* Determine the address of the next instruction executed after the INST
    floating condition branch instruction at PC.  COUNT specifies the
    number of the floating condition bits tested by the branch.  */
@@ -1607,6 +1633,71 @@ is_octeon_bbit_op (int op, struct gdbarch *gdbarch)
   return 0;
 }
 
+static int
+is_add32bit_overflow (int32_t a, int32_t b)
+{
+  int32_t r = (uint32_t) a + (uint32_t) b;
+  return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
+}
+
+static int
+is_add64bit_overflow (int64_t a, int64_t b)
+{
+  if (a != (int32_t)a)
+    return 1;
+  if (b != (int32_t)b)
+    return 1;
+  return is_add32bit_overflow ((int32_t)a, (int32_t)b);
+}
+
+/* Calculate address of next instruction after BLEZ.  */
+
+static CORE_ADDR
+mips32_blez_pc (struct gdbarch *gdbarch, struct regcache *regcache,
+		ULONGEST inst, CORE_ADDR pc, int invert)
+{
+  int rs = itype_rs (inst);
+  int rt = itype_rt (inst);
+  LONGEST val_rs = regcache_raw_get_signed (regcache, rs);
+  LONGEST val_rt = regcache_raw_get_signed (regcache, rt);
+  ULONGEST uval_rs = regcache_raw_get_unsigned (regcache, rs);
+  ULONGEST uval_rt = regcache_raw_get_unsigned (regcache, rt);
+  int taken = 0;
+  int delay_slot_size = 4;
+
+  /* BLEZ, BLEZL, BGTZ, BGTZL */
+  if (rt == 0)
+    taken = (val_rs <= 0);
+  else if (is_mipsr6_isa (gdbarch))
+    {
+      /* BLEZALC, BGTZALC */
+      if (rs == 0 && rt != 0)
+	taken = (val_rt <= 0);
+      /* BGEZALC, BLTZALC */
+      else if (rs == rt && rt != 0)
+	taken = (val_rt >= 0);
+      /* BGEUC, BLTUC */
+      else if (rs != rt && rs != 0 && rt != 0)
+	taken = (uval_rs >= uval_rt);
+
+      /* Step through the forbidden slot to avoid repeated exceptions we do
+	 not currently have access to the BD bit when hitting a breakpoint
+	 and therefore cannot tell if the breakpoint hit on the branch or the
+	 forbidden slot.  */
+      /* delay_slot_size = 0; */
+    }
+
+  if (invert)
+    taken = !taken;
+
+  /* Calculate branch target.  */
+  if (taken)
+    pc += mips32_relative_offset (inst);
+  else
+    pc += delay_slot_size;
+
+  return pc;
+}
 
 /* Determine where to set a single step breakpoint while considering
    branch prediction.  */
@@ -1617,12 +1708,17 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
   struct gdbarch *gdbarch = regcache->arch ();
   unsigned long inst;
   int op;
+  int mips64bitreg = 0;
+
+  if (mips_isa_regsize (gdbarch) == 8)
+    mips64bitreg = 1;
+
   inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
   op = itype_op (inst);
   if ((inst & 0xe0000000) != 0)		/* Not a special, jump or branch
 					   instruction.  */
     {
-      if (op >> 2 == 5)
+      if (op >> 2 == 5 && ((op & 0x02) == 0 || itype_rt (inst) == 0))
 	/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
 	{
 	  switch (op & 0x03)
@@ -1632,7 +1728,7 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	    case 1:		/* BNEL */
 	      goto neq_branch;
 	    case 2:		/* BLEZL */
-	      goto less_branch;
+	      goto lez_branch;
 	    case 3:		/* BGTZL */
 	      goto greater_branch;
 	    default:
@@ -1642,15 +1738,19 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
       else if (op == 17 && itype_rs (inst) == 8)
 	/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
 	pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 1);
-      else if (op == 17 && itype_rs (inst) == 9
+      else if (!is_mipsr6_isa (gdbarch)
+	       && op == 17
+	       && itype_rs (inst) == 9
 	       && (itype_rt (inst) & 2) == 0)
 	/* BC1ANY2F, BC1ANY2T: 010001 01001 xxx0x */
 	pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 2);
-      else if (op == 17 && itype_rs (inst) == 10
+      else if (!is_mipsr6_isa (gdbarch)
+               && op == 17
+               && itype_rs (inst) == 10
 	       && (itype_rt (inst) & 2) == 0)
 	/* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */
 	pc = mips32_bc1_pc (gdbarch, regcache, inst, pc + 4, 4);
-      else if (op == 29)
+      else if (!is_mipsr6_isa (gdbarch) && op == 29)
 	/* JALX: 011101 */
 	/* The new PC will be alternate mode.  */
 	{
@@ -1678,7 +1778,128 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	  else
 	    pc += 8;        /* After the delay slot.  */
 	}
+      else if (is_mipsr6_isa (gdbarch))
+	{
+	  /* BOVC, BEQZALC, BEQC and BNVC, BNEZALC, BNEC */
+	  if (op == 8 || op == 24)
+	    {
+	      int rs = rtype_rs (inst);
+	      int rt = rtype_rt (inst);
+	      LONGEST val_rs = regcache_raw_get_signed (regcache, rs);
+	      LONGEST val_rt = regcache_raw_get_signed (regcache, rt);
+	      int taken = 0;
+	      /* BOVC (BNVC) */
+	      if (rs >= rt)
+		{
+		  if (mips64bitreg == 1)
+		    taken = is_add64bit_overflow (val_rs, val_rt);
+		  else
+		    taken = is_add32bit_overflow (val_rs, val_rt);
+		}
+	      /* BEQZALC (BNEZALC) */
+	      else if (rs < rt && rs == 0)
+		taken = (val_rt == 0);
+	      /* BEQC (BNEC) */
+	      else
+		taken = (val_rs == val_rt);
+
+	      /* BNVC, BNEZALC, BNEC */
+	      if (op == 24)
+		taken = !taken;
+
+	      if (taken)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
+	    }
+	  /* BC1EQZ, BC1NEZ */
+	  else if (op == 17 && (itype_rs (inst) == 9 || itype_rs (inst) == 13))
+	    {
+	      gdb_byte status;
+	      gdb_byte true_val = 0;
+	      unsigned int fp = (gdbarch_num_regs (gdbarch)
+				 + mips_regnum (gdbarch)->fp0
+				 + itype_rt (inst));
+	      struct frame_info *frame = get_current_frame ();
+	      gdb_byte *raw_buffer = (gdb_byte *) alloca (sizeof (gdb_byte) * 4);
+	      mips_read_fp_register_single (frame, fp, raw_buffer);
+
+	      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+		status = *(raw_buffer + 3);
+	      else
+		status = *(raw_buffer);
 
+	      if (itype_rs (inst) == 13)
+		true_val = 1;
+
+	      if ((status & 0x1) == true_val)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		pc += 8;
+	    }
+	  else if (op == 22 || op == 23)
+	  /* BLEZC, BGEZC, BGEC, BGTZC, BLTZC, BLTC */
+	    {
+	      int rs = rtype_rs (inst);
+	      int rt = rtype_rt (inst);
+	      LONGEST val_rs = regcache_raw_get_signed (regcache, rs);
+	      LONGEST val_rt = regcache_raw_get_signed (regcache, rt);
+	      int taken = 0;
+	      /* The R5 rt == 0 case is handled above so we treat it as
+		 an unknown instruction here for future ISA usage.  */
+	      if (rs == 0 && rt != 0)
+		taken = (val_rt <= 0);
+	      else if (rs == rt && rt != 0)
+		taken = (val_rt >= 0);
+	      else if (rs != rt && rs != 0 && rt != 0)
+		taken = (val_rs >= val_rt);
+
+	      if (op == 23)
+		taken = !taken;
+
+	      if (taken)
+		pc += mips32_relative_offset (inst) + 4;
+	      else
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
+	    }
+	  else if (op == 50 || op == 58)
+	  /* BC, BALC */
+	    pc += mips32_relative_offset26 (inst) + 4;
+	  else if ((op == 54 || op == 62)
+		   && rtype_rs (inst) == 0)
+	  /* JIC, JIALC */
+	    {
+	      pc = regcache_raw_get_signed (regcache, itype_rt (inst));
+	      pc += (itype_immediate (inst) ^ 0x8000) - 0x8000;
+	    }
+	  else if (op == 54 || op == 62)
+	  /* BEQZC, BNEZC */
+	    {
+	      int rs = itype_rs (inst);
+	      LONGEST rs_val = regcache_raw_get_signed (regcache, rs);
+	      int taken = (rs_val == 0);
+	      if (op == 62)
+		taken = !taken;
+	      if (taken)
+		pc += mips32_relative_offset21 (inst) + 4;
+	      else
+		/* Step through the forbidden slot to avoid repeated exceptions
+		   we do not currently have access to the BD bit when hitting a
+		   breakpoint and therefore cannot tell if the breakpoint
+		   hit on the branch or the forbidden slot.  */
+		pc += 8;
+	    }
+	  else
+	    pc += 4;		/* Not a branch, next instruction is easy.  */
+	}
       else
 	pc += 4;		/* Not a branch, next instruction is easy.  */
     }
@@ -1722,7 +1943,6 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	      case 2:		/* BLTZL */
 	      case 16:		/* BLTZAL */
 	      case 18:		/* BLTZALL */
-	      less_branch:
 		if (regcache_raw_get_signed (regcache, itype_rs (inst)) < 0)
 		  pc += mips32_relative_offset (inst) + 4;
 		else
@@ -1738,22 +1958,38 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 		  pc += 8;	/* after the delay slot */
 		break;
 	      case 0x1c:	/* BPOSGE32 */
+	      case 0x1d:	/* BPOSGE32C */
 	      case 0x1e:	/* BPOSGE64 */
 		pc += 4;
 		if (itype_rs (inst) == 0)
 		  {
 		    unsigned int pos = (op & 2) ? 64 : 32;
 		    int dspctl = mips_regnum (gdbarch)->dspctl;
+		    int delay_slot_size = 4;
 
 		    if (dspctl == -1)
 		      /* No way to handle; it'll most likely trap anyway.  */
 		      break;
 
+		    /* BPOSGE32C */
+		    if (op == 0x1d)
+		      {
+			if (!is_mipsr6_isa (gdbarch))
+			  break;
+
+			/* Step through the forbidden slot to avoid repeated
+			   exceptions we do not currently have access to the BD
+			   bit when hitting a breakpoint and therefore cannot
+			   tell if the breakpoint hit on the branch or the
+			   forbidden slot.  */
+			/* delay_slot_size = 0; */
+		      }
+
 		    if ((regcache_raw_get_unsigned (regcache,
 						    dspctl) & 0x7f) >= pos)
 		      pc += mips32_relative_offset (inst);
 		    else
-		      pc += 4;
+		      pc += delay_slot_size;
 		  }
 		break;
 		/* All of the other instructions in the REGIMM category */
@@ -1787,19 +2023,14 @@ mips32_next_pc (struct regcache *regcache, CORE_ADDR pc)
 	  else
 	    pc += 8;
 	  break;
-	case 6:		/* BLEZ, BLEZL */
-	  if (regcache_raw_get_signed (regcache, itype_rs (inst)) <= 0)
-	    pc += mips32_relative_offset (inst) + 4;
-	  else
-	    pc += 8;
+	case 6:		/* BLEZ, BLEZL, BLEZALC, BGEZALC, BGEUC */
+	lez_branch:
+	  pc = mips32_blez_pc (gdbarch, regcache, inst, pc + 4, 0);
 	  break;
 	case 7:
 	default:
-	greater_branch:	/* BGTZ, BGTZL */
-	  if (regcache_raw_get_signed (regcache, itype_rs (inst)) > 0)
-	    pc += mips32_relative_offset (inst) + 4;
-	  else
-	    pc += 8;
+	greater_branch:	/* BGTZ, BGTZL, BGTZALC, BLTZALC, BLTUC */
+	  pc = mips32_blez_pc (gdbarch, regcache, inst, pc + 4, 1);
 	  break;
 	}			/* switch */
     }				/* else */
@@ -2422,6 +2653,72 @@ micromips_instruction_is_compact_branch (unsigned short insn)
     }
 }
 
+/* Return non-zero if the MIPS instruction INSN is a compact branch
+   or jump.  A value of 1 indicates an unconditional compact branch
+   and a value of 2 indicates a conditional compact branch.  */
+
+static int
+mips32_instruction_is_compact_branch (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  switch (itype_op (insn))
+    {
+    /* BC */
+    case 50:
+    /* BALC */
+    case 58:
+      if (is_mipsr6_isa (gdbarch))
+	return 1;
+      break;
+    /* BOVC, BEQZALC, BEQC */
+    case 8:
+    /* BNVC, BNEZALC, BNEC */
+    case 24:
+      if (is_mipsr6_isa (gdbarch))
+	return 2;
+      break;
+    /* BEQZC, JIC */
+    case 54:
+    /* BNEZC, JIALC */
+    case 62:
+      if (is_mipsr6_isa (gdbarch))
+	/* JIC, JIALC are unconditional */
+	return (itype_rs (insn) == 0) ? 1 : 2;
+      break;
+    /* BLEZC, BGEZC, BGEC */
+    case 22:
+    /* BGTZC, BLTZC, BLTC */
+    case 23:
+    /* BLEZALC, BGEZALC, BGEUC */
+    case 6:
+    /* BGTZALC, BLTZALC, BLTUC */
+    case 7:
+      if (is_mipsr6_isa (gdbarch)
+	  && itype_rt (insn) != 0)
+	return 2;
+      break;
+    /* BPOSGE32C */
+    case 1:
+      if (is_mipsr6_isa (gdbarch)
+	  && itype_rt (insn) == 0x1d && itype_rs (insn) == 0)
+	return 2;
+    }
+  return 0;
+}
+
+/* Return non-zero if a standard MIPS instruction at ADDR has a branch
+   forbidden slot (i.e. it is a conditional compact branch instruction).  */
+
+static int
+mips32_insn_at_pc_has_forbidden_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  int status;
+  ULONGEST insn = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status);
+  if (status)
+    return 0;
+
+  return mips32_instruction_is_compact_branch (gdbarch, insn) == 2;
+}
+
 struct mips_frame_cache
 {
   CORE_ADDR base;
@@ -3463,7 +3760,8 @@ mips32_scan_prologue (struct gdbarch *gdbarch,
       reg = high_word & 0x1f;
 
       if (high_word == 0x27bd		/* addiu $sp,$sp,-i */
-	  || high_word == 0x23bd	/* addi $sp,$sp,-i */
+	  || (high_word == 0x23bd	/* addi $sp,$sp,-i */
+	      && !is_mipsr6_isa (gdbarch))
 	  || high_word == 0x67bd)	/* daddiu $sp,$sp,-i */
 	{
 	  if (offset < 0)		/* Negative stack adjustment?  */
@@ -3598,7 +3896,9 @@ mips32_scan_prologue (struct gdbarch *gdbarch,
 
       /* A jump or branch, or enough non-prologue insns seen?  If so,
 	 then we must have reached the end of the prologue by now.  */
-      if (prev_delay_slot || non_prologue_insns > 1)
+      if (prev_delay_slot
+	  || non_prologue_insns > 1
+	  || mips32_instruction_is_compact_branch (gdbarch, inst))
 	break;
 
       prev_non_prologue_insn = this_non_prologue_insn;
@@ -3902,6 +4202,59 @@ mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
 #define LLD_OPCODE 0x34
 #define SC_OPCODE 0x38
 #define SCD_OPCODE 0x3c
+#define LLSC_R6_OPCODE 0x1f
+#define LL_R6_FUNCT 0x36
+#define LLE_FUNCT 0x2e
+#define LLD_R6_FUNCT 0x37
+#define SC_R6_FUNCT 0x26
+#define SCE_FUNCT 0x1e
+#define SCD_R6_FUNCT 0x27
+
+static int
+is_ll_insn (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  if (itype_op (insn) == LL_OPCODE
+      || itype_op (insn) == LLD_OPCODE)
+    return 1;
+
+  if (rtype_op (insn) == LLSC_R6_OPCODE
+      && rtype_funct (insn) == LLE_FUNCT
+      && (insn & 0x40) == 0)
+    return 1;
+
+  /* Handle LL and LLP varieties.  */
+  if (is_mipsr6_isa (gdbarch)
+      && rtype_op (insn) == LLSC_R6_OPCODE
+      && (rtype_funct (insn) == LL_R6_FUNCT
+	  || rtype_funct (insn) == LLD_R6_FUNCT
+	  || rtype_funct (insn) == LLE_FUNCT))
+    return 1;
+
+  return 0;
+}
+
+static int
+is_sc_insn (struct gdbarch *gdbarch, ULONGEST insn)
+{
+  if (itype_op (insn) == SC_OPCODE
+      || itype_op (insn) == SCD_OPCODE)
+    return 1;
+
+  if (rtype_op (insn) == LLSC_R6_OPCODE
+      && rtype_funct (insn) == SCE_FUNCT
+      && (insn & 0x40) == 0)
+    return 1;
+
+  /* Handle SC and SCP varieties.  */
+  if (is_mipsr6_isa (gdbarch)
+      && rtype_op (insn) == LLSC_R6_OPCODE
+      && (rtype_funct (insn) == SC_R6_FUNCT
+	  || rtype_funct (insn) == SCD_R6_FUNCT
+	  || rtype_funct (insn) == SCE_FUNCT))
+    return 1;
+
+  return 0;
+}
 
 static std::vector<CORE_ADDR>
 mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
@@ -3914,10 +4267,11 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
   int index;
   int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */  
   const int atomic_sequence_length = 16; /* Instruction sequence length.  */
+  int is_mipsr6 = is_mipsr6_isa (gdbarch);
 
   insn = mips_fetch_instruction (gdbarch, ISA_MIPS, loc, NULL);
   /* Assume all atomic sequences start with a ll/lld instruction.  */
-  if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE)
+  if (!is_ll_insn (gdbarch, insn))
     return {};
 
   /* Assume that no atomic sequence is longer than "atomic_sequence_length" 
@@ -3947,28 +4301,72 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
 	  return {}; /* fallback to the standard single-step code.  */
 	case 4: /* BEQ */
 	case 5: /* BNE */
-	case 6: /* BLEZ */
-	case 7: /* BGTZ */
 	case 20: /* BEQL */
 	case 21: /* BNEL */
-	case 22: /* BLEZL */
-	case 23: /* BGTTL */
+	case 22: /* BLEZL (BLEZC, BGEZC, BGEC) */
+	case 23: /* BGTZL (BGTZC, BLTZC, BLTC) */
+	  is_branch = 1;
+	  break;
+	case 6: /* BLEZ (BLEZALC, BGEZALC, BGEUC) */
+	case 7: /* BGTZ (BGTZALC, BLTZALC, BLTUC) */
+	  if (is_mipsr6)
+	    {
+	      /* BLEZALC, BGTZALC */
+	      if (itype_rs (insn) == 0 && itype_rt (insn) != 0)
+		return {}; /* fallback to the standard single-step code.  */
+	      /* BGEZALC, BLTZALC */
+	      else if (itype_rs (insn) == itype_rt (insn)
+		       && itype_rt (insn) != 0)
+		return {}; /* fallback to the standard single-step code.  */
+	    }
 	  is_branch = 1;
 	  break;
+	case 8: /* BOVC, BEQZALC, BEQC */
+	case 24: /* BNVC, BNEZALC, BNEC */
+	  if (is_mipsr6)
+	    is_branch = 1;
+	  break;
+	case 50: /* BC */
+	case 58: /* BALC */
+	  if (is_mipsr6)
+	    return {}; /* fallback to the standard single-step code.  */
+	  break;
+	case 54: /* BEQZC, JIC */
+	case 62: /* BNEZC, JIALC */
+	  if (is_mipsr6)
+	    {
+	      if (itype_rs (insn) == 0) /* JIC, JIALC */
+		return {}; /* fallback to the standard single-step code.  */
+	      else
+		is_branch = 2; /* Marker for branches with a 21-bit offset.  */
+	    }
+	  break;
 	case 17: /* COP1 */
-	  is_branch = ((itype_rs (insn) == 9 || itype_rs (insn) == 10)
-		       && (itype_rt (insn) & 0x2) == 0);
-	  if (is_branch) /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+	  is_branch = ((!is_mipsr6
+			/* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */
+			&& (itype_rs (insn) == 9 || itype_rs (insn) == 10)
+			&& (itype_rt (insn) & 0x2) == 0)
+		       /* BZ.df:  010001 110xx */
+		       || (itype_rs (insn) & 0x18) == 0x18);
+	  if (is_branch)
 	    break;
 	/* Fall through.  */
 	case 18: /* COP2 */
 	case 19: /* COP3 */
-	  is_branch = (itype_rs (insn) == 8); /* BCzF, BCzFL, BCzT, BCzTL */
+	  /* BCzF, BCzFL, BCzT, BCzTL, BC*EQZ, BC*NEZ */
+	  is_branch = ((itype_rs (insn) == 8)
+		       || (is_mipsr6
+			   && (itype_rs (insn) == 9
+			       || itype_rs (insn) == 13)));
 	  break;
 	}
       if (is_branch)
 	{
-	  branch_bp = loc + mips32_relative_offset (insn) + 4;
+	  /* Is this a special PC21_S2 branch? */
+	  if (is_branch == 2)
+	    branch_bp = loc + mips32_relative_offset21 (insn) + 4;
+	  else
+	    branch_bp = loc + mips32_relative_offset (insn) + 4;
 	  if (last_breakpoint >= 1)
 	    return {}; /* More than one branch found, fallback to the
 			  standard single-step code.  */
@@ -3976,12 +4374,12 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
 	  last_breakpoint++;
 	}
 
-      if (itype_op (insn) == SC_OPCODE || itype_op (insn) == SCD_OPCODE)
+      if (is_sc_insn (gdbarch, insn))
 	break;
     }
 
   /* Assume that the atomic sequence ends with a sc/scd instruction.  */
-  if (itype_op (insn) != SC_OPCODE && itype_op (insn) != SCD_OPCODE)
+  if (!is_sc_insn (gdbarch, insn))
     return {};
 
   loc += MIPS_INSN32_SIZE;
@@ -4206,8 +4604,14 @@ mips_about_to_return (struct gdbarch *gdbarch, CORE_ADDR pc)
   gdb_assert (mips_pc_is_mips (pc));
 
   insn = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL);
-  hint = 0x7c0;
-  return (insn & ~hint) == 0x3e00008;			/* jr(.hb) $ra */
+  /* Mask the hint and the jalr/jr bit.  */
+  hint = 0x7c1;
+
+  if (is_mipsr6_isa (gdbarch) && insn == 0xd81f0000) /* jrc $31 */
+    return 1;
+
+  /* jr(.hb) $ra and "jalr(.hb) $ra" */
+  return ((insn & ~hint) == 0x3e00008);
 }
 
 
@@ -6711,7 +7115,9 @@ mips32_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 
 	  if (high_word != 0x27bd	/* addiu $sp,$sp,offset */
 	      && high_word != 0x67bd	/* daddiu $sp,$sp,offset */
-	      && inst != 0x03e00008	/* jr $ra */
+	      && (inst & ~0x1) != 0x03e00008 /* jr $31 or jalr $0, $31 */
+	      && (!is_mipsr6_isa (gdbarch)
+		  || inst != 0xd81f0000) /* jrc $31 */
 	      && inst != 0x00000000)	/* nop */
 	    return 0;
 	}
@@ -7092,22 +7498,31 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
   int op;
   int rs;
   int rt;
+  int is_mipsr6 = is_mipsr6_isa (gdbarch);
 
   op = itype_op (inst);
   if ((inst & 0xe0000000) != 0)
     {
       rs = itype_rs (inst);
       rt = itype_rt (inst);
-      return (is_octeon_bbit_op (op, gdbarch) 
-	      || op >> 2 == 5	/* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx  */
-	      || op == 29	/* JALX: bits 011101  */
+      return (is_octeon_bbit_op (op, gdbarch)
+	      || (op >> 1 == 10) /* BEQL, BNEL: bits 01010x  */
+	      || (op >> 1 == 11 && rt == 0) /* BLEZL, BGTZL: bits 01011x  */
+	      || (!is_mipsr6 && op == 29)	/* JALX: bits 011101  */
 	      || (op == 17
 		  && (rs == 8
 				/* BC1F, BC1FL, BC1T, BC1TL: 010001 01000  */
-		      || (rs == 9 && (rt & 0x2) == 0)
+		      || (!is_mipsr6 && rs == 9 && (rt & 0x2) == 0)
 				/* BC1ANY2F, BC1ANY2T: bits 010001 01001  */
-		      || (rs == 10 && (rt & 0x2) == 0))));
+		      || (!is_mipsr6 && rs == 10 && (rt & 0x2) == 0)))
 				/* BC1ANY4F, BC1ANY4T: bits 010001 01010  */
+	      || (is_mipsr6
+		  && ((op == 17
+		       && (rs == 9  /* BC1EQZ: 010001 01001  */
+			   || rs == 13))  /* BC1NEZ: 010001 01101  */
+		      || (op == 18
+			  && (rs == 9  /* BC2EQZ: 010010 01001  */
+			      || rs == 13)))));  /* BC2NEZ: 010010 01101  */
     }
   else
     switch (op & 0x07)		/* extract bits 28,27,26  */
@@ -7126,7 +7541,11 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst)
 		|| ((rt & 0x1e) == 0x1c && rs == 0));
 				/* BPOSGE32, BPOSGE64: bits 1110x  */
 	break;			/* end REGIMM  */
-      default:			/* J, JAL, BEQ, BNE, BLEZ, BGTZ  */
+	case 6:			/* BLEZ  */
+	case 7:			/* BGTZ  */
+	 return (itype_rt (inst) == 0);
+	 break;
+      default:			/* J, JAL, BEQ, BNE  */
 	return 1;
 	break;
       }
@@ -7338,7 +7757,18 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
 
      So, we'll use the second solution.  To do this we need to know if
      the instruction we're trying to set the breakpoint on is in the
-     branch delay slot.  */
+     branch delay slot.
+
+     A similar problem occurs for breakpoints on forbidden slots where
+     the trap will be reported for the branch with the BD bit set.
+     In this case it would be ideal to recover using solution 1 from
+     above as there is no problem with the branch being skipped
+     (since the forbidden slot only exists on not-taken branches).
+     However, the BD bit is not available in all scenarios currently
+     so instead we move the breakpoint on to the next instruction.
+     This means that it is not possible to stop on an instruction
+     that can be in a forbidden slot even if that instruction is
+     jumped to directly.  */
 
   boundary = mips_segment_boundary (bpaddr);
 
@@ -7360,6 +7790,12 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
       prev_addr = bpaddr - 4;
       if (mips32_insn_at_pc_has_delay_slot (gdbarch, prev_addr))
 	bpaddr = prev_addr;
+      /* If the previous instruction has a forbidden slot, we have to
+	 move the breakpoint to the following instruction to prevent
+	 breakpoints in forbidden slots being reported as unknown
+	 traps.  */
+      else if (mips32_insn_at_pc_has_forbidden_slot (gdbarch, prev_addr))
+	bpaddr += 4;
     }
   else
     {
-- 
2.25.1


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

* Re: [EXTERNAL]Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-05-22  6:20     ` Eli Zaretskii
@ 2021-06-27 19:25       ` Faraz Shahbazker
  2021-06-27 19:33         ` Simon Marchi
  0 siblings, 1 reply; 50+ messages in thread
From: Faraz Shahbazker @ 2021-06-27 19:25 UTC (permalink / raw)
  To: Eli Zaretskii, Mike Frysinger; +Cc: gdb-patches, macro, cfu

On 5/22/21 11:50 AM, Eli Zaretskii wrote:
>> Date: Fri, 21 May 2021 21:46:33 -0400
>> From: Mike Frysinger via Gdb-patches <gdb-patches@sourceware.org>
>> Cc: Chao-ying Fu <cfu@wavecomp.com>, gdb-patches@sourceware.org,
>>   "Maciej W . Rozycki" <macro@orcam.me.uk>
>>
>> On 20 May 2021 13:15, Faraz Shahbazker wrote:
>>> 2021-05-19  Ali Lown  <ali.lown@imgtec.com>
>>> 	    Andrew Bennett  <andrew.bennett@imgtec.com>
>>> 	    Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
>>> 	    Faraz Shahbazker  <fshahbazker@wavecomp.com>
>>
>> i assume everyone has FSF papers in place ?
> 
> Not that I could see, no.
Can someone please clear this up for me? I was told by my manager in 
2019 that papers were in place for Wave Computing, after which I posted 
a number of submissions without any questions. I assumed that the same 
would be good even now. The people who dealt with the FSF paperwork back 
then are no longer with Wave, so I can't easily verify at my end.

Thanks,
Faraz

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

* Re: [EXTERNAL]Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-06-27 19:25       ` [EXTERNAL]Re: " Faraz Shahbazker
@ 2021-06-27 19:33         ` Simon Marchi
  2021-06-27 19:44           ` Eli Zaretskii
  2021-06-28  1:16           ` Mike Frysinger
  0 siblings, 2 replies; 50+ messages in thread
From: Simon Marchi @ 2021-06-27 19:33 UTC (permalink / raw)
  To: Faraz Shahbazker, Eli Zaretskii, Mike Frysinger; +Cc: cfu, gdb-patches, macro

On 2021-06-27 3:25 p.m., Faraz Shahbazker wrote:
> On 5/22/21 11:50 AM, Eli Zaretskii wrote:
>>> Date: Fri, 21 May 2021 21:46:33 -0400
>>> From: Mike Frysinger via Gdb-patches <gdb-patches@sourceware.org>
>>> Cc: Chao-ying Fu <cfu@wavecomp.com>, gdb-patches@sourceware.org,
>>>   "Maciej W . Rozycki" <macro@orcam.me.uk>
>>>
>>> On 20 May 2021 13:15, Faraz Shahbazker wrote:
>>>> 2021-05-19  Ali Lown  <ali.lown@imgtec.com>
>>>>         Andrew Bennett  <andrew.bennett@imgtec.com>
>>>>         Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
>>>>         Faraz Shahbazker  <fshahbazker@wavecomp.com>
>>>
>>> i assume everyone has FSF papers in place ?
>>
>> Not that I could see, no.
> Can someone please clear this up for me? I was told by my manager in 2019 that papers were in place for Wave Computing, after which I posted a number of submissions without any questions. I assumed that the same would be good even now. The people who dealt with the FSF paperwork back then are no longer with Wave, so I can't easily verify at my end.
> 
> Thanks,
> Faraz

I do see an entry matching that in copyright.list, covering GDB (as well
as many other projets).  At line 44659 in the file, for those who have
access to it.  Sim is part of GDB for copyright-related things?

Simon


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

* Re: [EXTERNAL]Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-06-27 19:33         ` Simon Marchi
@ 2021-06-27 19:44           ` Eli Zaretskii
  2021-06-27 20:24             ` Faraz Shahbazker
  2021-06-28  1:16           ` Mike Frysinger
  1 sibling, 1 reply; 50+ messages in thread
From: Eli Zaretskii @ 2021-06-27 19:44 UTC (permalink / raw)
  To: Simon Marchi; +Cc: fshahbazker, vapier, cfu, gdb-patches, macro

> Cc: cfu@wavecomp.com, gdb-patches@sourceware.org, macro@orcam.me.uk
> From: Simon Marchi <simon.marchi@polymtl.ca>
> Date: Sun, 27 Jun 2021 15:33:19 -0400
> 
> On 2021-06-27 3:25 p.m., Faraz Shahbazker wrote:
> > On 5/22/21 11:50 AM, Eli Zaretskii wrote:
> >>> Date: Fri, 21 May 2021 21:46:33 -0400
> >>> From: Mike Frysinger via Gdb-patches <gdb-patches@sourceware.org>
> >>> Cc: Chao-ying Fu <cfu@wavecomp.com>, gdb-patches@sourceware.org,
> >>>   "Maciej W . Rozycki" <macro@orcam.me.uk>
> >>>
> >>> On 20 May 2021 13:15, Faraz Shahbazker wrote:
> >>>> 2021-05-19  Ali Lown  <ali.lown@imgtec.com>
> >>>>         Andrew Bennett  <andrew.bennett@imgtec.com>
> >>>>         Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
> >>>>         Faraz Shahbazker  <fshahbazker@wavecomp.com>
> >>>
> >>> i assume everyone has FSF papers in place ?
> >>
> >> Not that I could see, no.
> > Can someone please clear this up for me? I was told by my manager in 2019 that papers were in place for Wave Computing, after which I posted a number of submissions without any questions. I assumed that the same would be good even now. The people who dealt with the FSF paperwork back then are no longer with Wave, so I can't easily verify at my end.
> > 
> > Thanks,
> > Faraz
> 
> I do see an entry matching that in copyright.list, covering GDB (as well
> as many other projets).  At line 44659 in the file, for those who have
> access to it.  Sim is part of GDB for copyright-related things?

Even if the assignment of Wave Computing covers Faraz, what about the
other three authors?  They aren't in the assignment list.

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

* Re: [EXTERNAL]Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-06-27 19:44           ` Eli Zaretskii
@ 2021-06-27 20:24             ` Faraz Shahbazker
  2021-06-28 12:17               ` Eli Zaretskii
  0 siblings, 1 reply; 50+ messages in thread
From: Faraz Shahbazker @ 2021-06-27 20:24 UTC (permalink / raw)
  To: Eli Zaretskii, Simon Marchi; +Cc: vapier, cfu, gdb-patches, macro

On 6/28/21 1:14 AM, Eli Zaretskii wrote:
>> Cc: cfu@wavecomp.com, gdb-patches@sourceware.org, macro@orcam.me.uk
>> From: Simon Marchi <simon.marchi@polymtl.ca>
>> Date: Sun, 27 Jun 2021 15:33:19 -0400
>>
>> On 2021-06-27 3:25 p.m., Faraz Shahbazker wrote:
>>> On 5/22/21 11:50 AM, Eli Zaretskii wrote:
>>>>> Date: Fri, 21 May 2021 21:46:33 -0400
>>>>> From: Mike Frysinger via Gdb-patches <gdb-patches@sourceware.org>
>>>>> Cc: Chao-ying Fu <cfu@wavecomp.com>, gdb-patches@sourceware.org,
>>>>>    "Maciej W . Rozycki" <macro@orcam.me.uk>
>>>>>
>>>>> On 20 May 2021 13:15, Faraz Shahbazker wrote:
>>>>>> 2021-05-19  Ali Lown  <ali.lown@imgtec.com>
>>>>>>          Andrew Bennett  <andrew.bennett@imgtec.com>
>>>>>>          Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
>>>>>>          Faraz Shahbazker  <fshahbazker@wavecomp.com>
>>>>>
>>>>> i assume everyone has FSF papers in place ?
>>>>
>>>> Not that I could see, no.
>>> Can someone please clear this up for me? I was told by my manager in 2019 that papers were in place for Wave Computing, after which I posted a number of submissions without any questions. I assumed that the same would be good even now. The people who dealt with the FSF paperwork back then are no longer with Wave, so I can't easily verify at my end.
>>>
>>> Thanks,
>>> Faraz
>>
>> I do see an entry matching that in copyright.list, covering GDB (as well
>> as many other projets).  At line 44659 in the file, for those who have
>> access to it.  Sim is part of GDB for copyright-related things?
> 
> Even if the assignment of Wave Computing covers Faraz, what about the
> other three authors?  They aren't in the assignment list.

I am sure RT-RK's assignment is in place, they regularly commit to FSF 
projects. The historical context for these contributors is that 
Imagination Technologies (@imgtec) spawned MIPS as a separate entity 
which was then acquired by Wave Computing. I know for sure that Wave has 
the rights to release/license this code. I can change those addresses to 
@wavecomp if that helps.

Maciej had adviced me to use the original email addresses of the 
developers as a means of retaining the historical context. Note that 
ali.lown@imgtec.com was once a valid address, whereas 
ali.lown@wavecomp.com never was, because Ali was never employed by Wave.

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

* Re: [EXTERNAL]Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-06-27 19:33         ` Simon Marchi
  2021-06-27 19:44           ` Eli Zaretskii
@ 2021-06-28  1:16           ` Mike Frysinger
  1 sibling, 0 replies; 50+ messages in thread
From: Mike Frysinger @ 2021-06-28  1:16 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Faraz Shahbazker, Eli Zaretskii, cfu, gdb-patches, macro

On 27 Jun 2021 15:33, Simon Marchi wrote:
> On 2021-06-27 3:25 p.m., Faraz Shahbazker wrote:
> > On 5/22/21 11:50 AM, Eli Zaretskii wrote:
> >>> Date: Fri, 21 May 2021 21:46:33 -0400
> >>> From: Mike Frysinger via Gdb-patches <gdb-patches@sourceware.org>
> >>> Cc: Chao-ying Fu <cfu@wavecomp.com>, gdb-patches@sourceware.org,
> >>>   "Maciej W . Rozycki" <macro@orcam.me.uk>
> >>>
> >>> On 20 May 2021 13:15, Faraz Shahbazker wrote:
> >>>> 2021-05-19  Ali Lown  <ali.lown@imgtec.com>
> >>>>         Andrew Bennett  <andrew.bennett@imgtec.com>
> >>>>         Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
> >>>>         Faraz Shahbazker  <fshahbazker@wavecomp.com>
> >>>
> >>> i assume everyone has FSF papers in place ?
> >>
> >> Not that I could see, no.
> > Can someone please clear this up for me? I was told by my manager in 2019 that papers were in place for Wave Computing, after which I posted a number of submissions without any questions. I assumed that the same would be good even now. The people who dealt with the FSF paperwork back then are no longer with Wave, so I can't easily verify at my end.
> 
> I do see an entry matching that in copyright.list, covering GDB (as well
> as many other projets).  At line 44659 in the file, for those who have
> access to it.  Sim is part of GDB for copyright-related things?

we've never done it separately, so sounds fine to keep it simple
-mike

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

* Re: [EXTERNAL]Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-06-27 20:24             ` Faraz Shahbazker
@ 2021-06-28 12:17               ` Eli Zaretskii
  2021-07-02 10:10                 ` Faraz Shahbazker
  0 siblings, 1 reply; 50+ messages in thread
From: Eli Zaretskii @ 2021-06-28 12:17 UTC (permalink / raw)
  To: Faraz Shahbazker; +Cc: simon.marchi, vapier, cfu, gdb-patches, macro

> Cc: vapier@gentoo.org, cfu@wavecomp.com, gdb-patches@sourceware.org,
>  macro@orcam.me.uk
> From: Faraz Shahbazker <fshahbazker@wavecomp.com>
> Date: Mon, 28 Jun 2021 01:54:05 +0530
> 
> On 6/28/21 1:14 AM, Eli Zaretskii wrote:
> >> Cc: cfu@wavecomp.com, gdb-patches@sourceware.org, macro@orcam.me.uk
> >> From: Simon Marchi <simon.marchi@polymtl.ca>
> >> Date: Sun, 27 Jun 2021 15:33:19 -0400
> >>
> >> On 2021-06-27 3:25 p.m., Faraz Shahbazker wrote:
> >>> On 5/22/21 11:50 AM, Eli Zaretskii wrote:
> >>>>> Date: Fri, 21 May 2021 21:46:33 -0400
> >>>>> From: Mike Frysinger via Gdb-patches <gdb-patches@sourceware.org>
> >>>>> Cc: Chao-ying Fu <cfu@wavecomp.com>, gdb-patches@sourceware.org,
> >>>>>    "Maciej W . Rozycki" <macro@orcam.me.uk>
> >>>>>
> >>>>> On 20 May 2021 13:15, Faraz Shahbazker wrote:
> >>>>>> 2021-05-19  Ali Lown  <ali.lown@imgtec.com>
> >>>>>>          Andrew Bennett  <andrew.bennett@imgtec.com>
> >>>>>>          Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
> >>>>>>          Faraz Shahbazker  <fshahbazker@wavecomp.com>
> >>>>>
> >>>>> i assume everyone has FSF papers in place ?
> >>>>
> >>>> Not that I could see, no.
> >>> Can someone please clear this up for me? I was told by my manager in 2019 that papers were in place for Wave Computing, after which I posted a number of submissions without any questions. I assumed that the same would be good even now. The people who dealt with the FSF paperwork back then are no longer with Wave, so I can't easily verify at my end.
> >>>
> >>> Thanks,
> >>> Faraz
> >>
> >> I do see an entry matching that in copyright.list, covering GDB (as well
> >> as many other projets).  At line 44659 in the file, for those who have
> >> access to it.  Sim is part of GDB for copyright-related things?
> > 
> > Even if the assignment of Wave Computing covers Faraz, what about the
> > other three authors?  They aren't in the assignment list.
> 
> I am sure RT-RK's assignment is in place, they regularly commit to FSF 
> projects. The historical context for these contributors is that 
> Imagination Technologies (@imgtec) spawned MIPS as a separate entity 
> which was then acquired by Wave Computing. I know for sure that Wave has 
> the rights to release/license this code. I can change those addresses to 
> @wavecomp if that helps.
> 
> Maciej had adviced me to use the original email addresses of the 
> developers as a means of retaining the historical context. Note that 
> ali.lown@imgtec.com was once a valid address, whereas 
> ali.lown@wavecomp.com never was, because Ali was never employed by Wave.

Thanks.  This all sounds very reasonable to me (and I do see the two
companies in the copyright assignments list), but I think the
situation is complicated enough to warrant a question to the FSF
copyright clerk.  At least that would be my suggestion; if Joel and
others think the issue is clear, I'm okay with their decision.

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

* Re: [EXTERNAL]Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-06-28 12:17               ` Eli Zaretskii
@ 2021-07-02 10:10                 ` Faraz Shahbazker
  2021-12-24 18:42                   ` Mike Frysinger
  0 siblings, 1 reply; 50+ messages in thread
From: Faraz Shahbazker @ 2021-07-02 10:10 UTC (permalink / raw)
  To: Eli Zaretskii, Mike Frysinger
  Cc: simon.marchi, Chao-ying Fu, gdb-patches, macro

So whats the final word? This series okay to commit?

- Faraz
________________________________
From: Eli Zaretskii <eliz@gnu.org>
Sent: Monday, June 28, 2021 5:17 AM
To: Faraz Shahbazker <fshahbazker@wavecomp.com>
Cc: simon.marchi@polymtl.ca <simon.marchi@polymtl.ca>; vapier@gentoo.org <vapier@gentoo.org>; Chao-ying Fu <cfu@wavecomp.com>; gdb-patches@sourceware.org <gdb-patches@sourceware.org>; macro@orcam.me.uk <macro@orcam.me.uk>
Subject: Re: [EXTERNAL]Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6

> Cc: vapier@gentoo.org, cfu@wavecomp.com, gdb-patches@sourceware.org,
>  macro@orcam.me.uk
> From: Faraz Shahbazker <fshahbazker@wavecomp.com>
> Date: Mon, 28 Jun 2021 01:54:05 +0530
>
> On 6/28/21 1:14 AM, Eli Zaretskii wrote:
> >> Cc: cfu@wavecomp.com, gdb-patches@sourceware.org, macro@orcam.me.uk
> >> From: Simon Marchi <simon.marchi@polymtl.ca>
> >> Date: Sun, 27 Jun 2021 15:33:19 -0400
> >>
> >> On 2021-06-27 3:25 p.m., Faraz Shahbazker wrote:
> >>> On 5/22/21 11:50 AM, Eli Zaretskii wrote:
> >>>>> Date: Fri, 21 May 2021 21:46:33 -0400
> >>>>> From: Mike Frysinger via Gdb-patches <gdb-patches@sourceware.org>
> >>>>> Cc: Chao-ying Fu <cfu@wavecomp.com>, gdb-patches@sourceware.org,
> >>>>>    "Maciej W . Rozycki" <macro@orcam.me.uk>
> >>>>>
> >>>>> On 20 May 2021 13:15, Faraz Shahbazker wrote:
> >>>>>> 2021-05-19  Ali Lown  <ali.lown@imgtec.com>
> >>>>>>          Andrew Bennett  <andrew.bennett@imgtec.com>
> >>>>>>          Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
> >>>>>>          Faraz Shahbazker  <fshahbazker@wavecomp.com>
> >>>>>
> >>>>> i assume everyone has FSF papers in place ?
> >>>>
> >>>> Not that I could see, no.
> >>> Can someone please clear this up for me? I was told by my manager in 2019 that papers were in place for Wave Computing, after which I posted a number of submissions without any questions. I assumed that the same would be good even now. The people who dealt with the FSF paperwork back then are no longer with Wave, so I can't easily verify at my end.
> >>>
> >>> Thanks,
> >>> Faraz
> >>
> >> I do see an entry matching that in copyright.list, covering GDB (as well
> >> as many other projets).  At line 44659 in the file, for those who have
> >> access to it.  Sim is part of GDB for copyright-related things?
> >
> > Even if the assignment of Wave Computing covers Faraz, what about the
> > other three authors?  They aren't in the assignment list.
>
> I am sure RT-RK's assignment is in place, they regularly commit to FSF
> projects. The historical context for these contributors is that
> Imagination Technologies (@imgtec) spawned MIPS as a separate entity
> which was then acquired by Wave Computing. I know for sure that Wave has
> the rights to release/license this code. I can change those addresses to
> @wavecomp if that helps.
>
> Maciej had adviced me to use the original email addresses of the
> developers as a means of retaining the historical context. Note that
> ali.lown@imgtec.com was once a valid address, whereas
> ali.lown@wavecomp.com never was, because Ali was never employed by Wave.

Thanks.  This all sounds very reasonable to me (and I do see the two
companies in the copyright assignments list), but I think the
situation is complicated enough to warrant a question to the FSF
copyright clerk.  At least that would be my suggestion; if Joel and
others think the issue is clear, I'm okay with their decision.

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

* Re: [EXTERNAL]Re: [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6
  2021-07-02 10:10                 ` Faraz Shahbazker
@ 2021-12-24 18:42                   ` Mike Frysinger
  0 siblings, 0 replies; 50+ messages in thread
From: Mike Frysinger @ 2021-12-24 18:42 UTC (permalink / raw)
  To: Faraz Shahbazker
  Cc: Eli Zaretskii, simon.marchi, Chao-ying Fu, gdb-patches, macro

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

On 02 Jul 2021 10:10, Faraz Shahbazker wrote:
> So whats the final word? This series okay to commit?

sorry, your e-mail was marked as spam for me (probably because you keep
sending html e-mails).  the sim code has had some refactors that might
cause these to not apply cleanly, and tbh, it's been too long since i
looked for me to remember what these are about.

can you rebase the series on top of the latest master branch and send
them out again to kickstart another round of review ?
-mike

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

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

* [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
@ 2022-02-02 10:17 ` Dragan Mladjenovic
  2022-02-02 10:17   ` [PATCH v5 1/4] sim: Allow toggling of quiet NaN-bit semantics Dragan Mladjenovic
                     ` (4 more replies)
  0 siblings, 5 replies; 50+ messages in thread
From: Dragan Mladjenovic @ 2022-02-02 10:17 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               |  324 ++++----
 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, 3965 insertions(+), 252 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] 50+ messages in thread

* [PATCH v5 1/4] sim: Allow toggling of quiet NaN-bit semantics
  2022-02-02 10:17 ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
@ 2022-02-02 10:17   ` Dragan Mladjenovic
  2022-02-02 10:17   ` [PATCH v5 2/4] sim: Factor out NaN handling in floating point operations Dragan Mladjenovic
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 50+ messages in thread
From: Dragan Mladjenovic @ 2022-02-02 10:17 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 | 31 ++++++++++++++++---------------
 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, 48 insertions(+), 18 deletions(-)

Changes from v4: Tidy up the comments. Designated initializers.

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index a05c57897ff..276ad234174 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,10 @@ 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..b0b318cb283 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] 50+ messages in thread

* [PATCH v5 2/4] sim: Factor out NaN handling in floating point operations
  2022-02-02 10:17 ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
  2022-02-02 10:17   ` [PATCH v5 1/4] sim: Allow toggling of quiet NaN-bit semantics Dragan Mladjenovic
@ 2022-02-02 10:17   ` Dragan Mladjenovic
  2022-02-02 10:17   ` [PATCH v5 3/4] sim: Add partial support for IEEE 754-2008 Dragan Mladjenovic
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 50+ messages in thread
From: Dragan Mladjenovic @ 2022-02-02 10:17 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 276ad234174..9174eaf17b4 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 b0b318cb283..2a141981687 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] 50+ messages in thread

* [PATCH v5 3/4] sim: Add partial support for IEEE 754-2008
  2022-02-02 10:17 ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
  2022-02-02 10:17   ` [PATCH v5 1/4] sim: Allow toggling of quiet NaN-bit semantics Dragan Mladjenovic
  2022-02-02 10:17   ` [PATCH v5 2/4] sim: Factor out NaN handling in floating point operations Dragan Mladjenovic
@ 2022-02-02 10:17   ` Dragan Mladjenovic
  2022-02-02 10:17   ` [PATCH v5 4/4] sim: mips: Add simulator support for mips32r6/mips64r6 Dragan Mladjenovic
  2022-02-04  5:48   ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Mike Frysinger
  4 siblings, 0 replies; 50+ messages in thread
From: Dragan Mladjenovic @ 2022-02-02 10:17 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 | 110 +++++++++++++++++++++++++++++++++++++++++--
 sim/common/sim-fpu.h |  26 +++++++++-
 2 files changed, 131 insertions(+), 5 deletions(-)

Changes form v4: Tidy up the comments.

diff --git a/sim/common/sim-fpu.c b/sim/common/sim-fpu.c
index 9174eaf17b4..ccaff9c7661 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,12 +2417,57 @@ 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,
+  .current_mode = sim_fpu_ieee754_1985,
 };
 
 const sim_fpu sim_fpu_zero = {
@@ -2406,6 +2490,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 2a141981687..a20b2861491 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] 50+ messages in thread

* [PATCH v5 4/4] sim: mips: Add simulator support for mips32r6/mips64r6
  2022-02-02 10:17 ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
                     ` (2 preceding siblings ...)
  2022-02-02 10:17   ` [PATCH v5 3/4] sim: Add partial support for IEEE 754-2008 Dragan Mladjenovic
@ 2022-02-02 10:17   ` Dragan Mladjenovic
  2022-12-25  0:26     ` Mike Frysinger
  2022-02-04  5:48   ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Mike Frysinger
  4 siblings, 1 reply; 50+ messages in thread
From: Dragan Mladjenovic @ 2022-02-02 10:17 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, 3749 insertions(+), 75 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 v4: Tidy up the comments, indentation.

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..196173c0227 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,109 @@ 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;
+
+  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 +729,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 +824,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 +869,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 +884,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 +934,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 +973,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 +999,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 +1068,89 @@ fp_mac(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);
+  return result;
+}
+
+/* Common FMAC code for .s, .d. Defers setting FCSR to caller.  */
+static sim_fpu_status
+inner_fmac (sim_cpu *cpu,
+	    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:
+      sim_io_error (SD, "Bad switch\n");
+    }
+
+  *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 (cpu, 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 +1240,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 +1306,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 +1443,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 +1771,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 +1806,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 +1856,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 +1891,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 +1911,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] 50+ messages in thread

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-02-02 10:17 ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
                     ` (3 preceding siblings ...)
  2022-02-02 10:17   ` [PATCH v5 4/4] sim: mips: Add simulator support for mips32r6/mips64r6 Dragan Mladjenovic
@ 2022-02-04  5:48   ` Mike Frysinger
  2022-02-04 12:29     ` Dragan Mladjenovic
  4 siblings, 1 reply; 50+ messages in thread
From: Mike Frysinger @ 2022-02-04  5:48 UTC (permalink / raw)
  To: Dragan Mladjenovic; +Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu

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

On 02 Feb 2022 11:17, Dragan Mladjenovic wrote:
> 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.

looks fine to me (as a non-MIPS expert)

the patches have been floating on the lists long enough that i think any
MIPS experts have had enough time to chime in if they were going to.  so
let's merge now.

do you folks have write access, or do you need me to do it ?
-mike

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

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

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-02-04  5:48   ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Mike Frysinger
@ 2022-02-04 12:29     ` Dragan Mladjenovic
  2022-02-06 14:57       ` Joel Brobecker
  0 siblings, 1 reply; 50+ messages in thread
From: Dragan Mladjenovic @ 2022-02-04 12:29 UTC (permalink / raw)
  To: gdb-patches, Maciej W . Rozycki, Chao-ying Fu

On 04-Feb-22 06:48, Mike Frysinger wrote:
> On 02 Feb 2022 11:17, Dragan Mladjenovic wrote:
>> 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.
> 
> looks fine to me (as a non-MIPS expert)
> 
> the patches have been floating on the lists long enough that i think any
> MIPS experts have had enough time to chime in if they were going to.  so
> let's merge now.
> 
> do you folks have write access, or do you need me to do it ?
> -mike

Thanks. I would be grateful if you could do it. It seem that my write 
access is either limited to gcc or something else is involved.

Best regards,

Dragan

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

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-02-04 12:29     ` Dragan Mladjenovic
@ 2022-02-06 14:57       ` Joel Brobecker
  2022-02-06 15:38         ` Dragan Mladjenovic
  0 siblings, 1 reply; 50+ messages in thread
From: Joel Brobecker @ 2022-02-06 14:57 UTC (permalink / raw)
  To: Dragan Mladjenovic
  Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu, Joel Brobecker

Hi Dragan,

> Thanks. I would be grateful if you could do it. It seem that my write access
> is either limited to gcc or something else is involved.

Do you have a copyright assignment on file for GDB? I searched the FSF
records, and couldn't find anything.

Thank you,
-- 
Joel

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

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-02-06 14:57       ` Joel Brobecker
@ 2022-02-06 15:38         ` Dragan Mladjenovic
  2022-02-06 16:28           ` Joel Brobecker
  0 siblings, 1 reply; 50+ messages in thread
From: Dragan Mladjenovic @ 2022-02-06 15:38 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu

On 06-Feb-22 15:57, Joel Brobecker wrote:
> Hi Dragan,
> 
>> Thanks. I would be grateful if you could do it. It seem that my write access
>> is either limited to gcc or something else is involved.
> 
> Do you have a copyright assignment on file for GDB? I searched the FSF
> records, and couldn't find anything.
> 
> Thank you,

Good catch,

I'll have to check this out, but previously we used rt-rk.com catch-all 
assignment. I assume there not such thing set up for syrmia.com.

Best regards,

Dragan

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

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-02-06 15:38         ` Dragan Mladjenovic
@ 2022-02-06 16:28           ` Joel Brobecker
  2022-02-06 18:49             ` Mike Frysinger
  0 siblings, 1 reply; 50+ messages in thread
From: Joel Brobecker @ 2022-02-06 16:28 UTC (permalink / raw)
  To: Dragan Mladjenovic
  Cc: Joel Brobecker, gdb-patches, Maciej W . Rozycki, Chao-ying Fu

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

> > Do you have a copyright assignment on file for GDB? I searched the FSF
> > records, and couldn't find anything.
> > 
> > Thank you,
> 
> Good catch,
> 
> I'll have to check this out, but previously we used rt-rk.com catch-all
> assignment. I assume there not such thing set up for syrmia.com.

That's correct. I couldn't see anything for syrmia.com in
the FSF records.

If you need it, attached is the form that can get you started.

-- 
Joel

[-- Attachment #2: request-assign.future --]
[-- Type: text/plain, Size: 965 bytes --]

Please email the following information to assign@gnu.org, and we
will send you the assignment form for your past and future changes.

Please use your full legal name (in ASCII characters) as the subject
line of the message.
----------------------------------------------------------------------
REQUEST: SEND FORM FOR PAST AND FUTURE CHANGES

[What is the name of the program or package you're contributing to?]


[Did you copy any files or text written by someone else in these changes?
Even if that material is free software, we need to know about it.]


[Do you have an employer who might have a basis to claim to own
your changes?  Do you attend a school which might make such a claim?]


[For the copyright registration, what country are you a citizen of?]


[What year were you born?]


[Please write your email address here.]


[Please write your postal address here.]





[Which files have you changed so far, and which new files have you written
so far?]

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

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-02-06 16:28           ` Joel Brobecker
@ 2022-02-06 18:49             ` Mike Frysinger
  2022-02-07 11:48               ` Dragan Mladjenovic
  0 siblings, 1 reply; 50+ messages in thread
From: Mike Frysinger @ 2022-02-06 18:49 UTC (permalink / raw)
  To: Joel Brobecker
  Cc: Dragan Mladjenovic, Chao-ying Fu, gdb-patches, Maciej W . Rozycki

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

On 06 Feb 2022 17:28, Joel Brobecker via Gdb-patches wrote:
> > > Do you have a copyright assignment on file for GDB? I searched the FSF
> > > records, and couldn't find anything.
> > > 
> > > Thank you,
> > 
> > Good catch,
> > 
> > I'll have to check this out, but previously we used rt-rk.com catch-all
> > assignment. I assume there not such thing set up for syrmia.com.
> 
> That's correct. I couldn't see anything for syrmia.com in
> the FSF records.
> 
> If you need it, attached is the form that can get you started.

i thought this was sorted out which is why i merged:
https://sourceware.org/pipermail/gdb-patches/2021-June/180419.html
-mike

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

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

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-02-06 18:49             ` Mike Frysinger
@ 2022-02-07 11:48               ` Dragan Mladjenovic
  2022-02-13 13:43                 ` Joel Brobecker
  0 siblings, 1 reply; 50+ messages in thread
From: Dragan Mladjenovic @ 2022-02-07 11:48 UTC (permalink / raw)
  To: Joel Brobecker, Chao-ying Fu, gdb-patches, Maciej W . Rozycki

On 06-Feb-22 19:49, Mike Frysinger wrote:
> On 06 Feb 2022 17:28, Joel Brobecker via Gdb-patches wrote:
>>>> Do you have a copyright assignment on file for GDB? I searched the FSF
>>>> records, and couldn't find anything.
>>>>
>>>> Thank you,
>>>
>>> Good catch,
>>>
>>> I'll have to check this out, but previously we used rt-rk.com catch-all
>>> assignment. I assume there not such thing set up for syrmia.com.
>>
>> That's correct. I couldn't see anything for syrmia.com in
>> the FSF records.
>>
>> If you need it, attached is the form that can get you started.
> 
> i thought this was sorted out which is why i merged:
> https://sourceware.org/pipermail/gdb-patches/2021-June/180419.html
> -mike

Hi,

Original changes are either fully owned by Wave (wavecomp.com) or 
possibly with addition of RT-RK (rt-rk.com). In any case those two
are covered by FSF assignments. I doubt that my changes done on behalf
of Syrmia are significant enough to require additional FSF assignment,
but that might be a reason I couldn't directly push the patches.

Do we need to wait with these patches until this gets sorted out on my part?

Best regards,

Dragan

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

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-02-07 11:48               ` Dragan Mladjenovic
@ 2022-02-13 13:43                 ` Joel Brobecker
  2022-02-14  0:04                   ` Mike Frysinger
  0 siblings, 1 reply; 50+ messages in thread
From: Joel Brobecker @ 2022-02-13 13:43 UTC (permalink / raw)
  To: Dragan Mladjenovic
  Cc: Joel Brobecker, Chao-ying Fu, gdb-patches, Maciej W . Rozycki

> Original changes are either fully owned by Wave (wavecomp.com) or possibly
> with addition of RT-RK (rt-rk.com). In any case those two
> are covered by FSF assignments. I doubt that my changes done on behalf
> of Syrmia are significant enough to require additional FSF assignment,
> but that might be a reason I couldn't directly push the patches.
> 
> Do we need to wait with these patches until this gets sorted out on my part?

I'm afraid so. The size and number of patches is such that we can't
accept them under the "tiny patch" rule.

-- 
Joel

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

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-02-13 13:43                 ` Joel Brobecker
@ 2022-02-14  0:04                   ` Mike Frysinger
  2022-04-15  7:24                     ` Dragan Mladjenovic
  0 siblings, 1 reply; 50+ messages in thread
From: Mike Frysinger @ 2022-02-14  0:04 UTC (permalink / raw)
  To: Joel Brobecker
  Cc: Dragan Mladjenovic, Maciej W . Rozycki, gdb-patches, Chao-ying Fu

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

On 13 Feb 2022 17:43, Joel Brobecker via Gdb-patches wrote:
> > Original changes are either fully owned by Wave (wavecomp.com) or possibly
> > with addition of RT-RK (rt-rk.com). In any case those two
> > are covered by FSF assignments. I doubt that my changes done on behalf
> > of Syrmia are significant enough to require additional FSF assignment,
> > but that might be a reason I couldn't directly push the patches.
> > 
> > Do we need to wait with these patches until this gets sorted out on my part?
> 
> I'm afraid so. The size and number of patches is such that we can't
> accept them under the "tiny patch" rule.

so we're clear, the patches before Dragan become involved should be cleared.
the changes he made on top of them is what he was referring to.

Dagan: can you follow the FSF copyright assignment just to avoid any further
confusion.
-mike

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

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

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-02-14  0:04                   ` Mike Frysinger
@ 2022-04-15  7:24                     ` Dragan Mladjenovic
  2022-04-15  7:35                       ` Eli Zaretskii
  0 siblings, 1 reply; 50+ messages in thread
From: Dragan Mladjenovic @ 2022-04-15  7:24 UTC (permalink / raw)
  To: Joel Brobecker, Maciej W . Rozycki, gdb-patches, Chao-ying Fu

On 14-Feb-22 01:04, Mike Frysinger wrote:
> On 13 Feb 2022 17:43, Joel Brobecker via Gdb-patches wrote:
>>> Original changes are either fully owned by Wave (wavecomp.com) or possibly
>>> with addition of RT-RK (rt-rk.com). In any case those two
>>> are covered by FSF assignments. I doubt that my changes done on behalf
>>> of Syrmia are significant enough to require additional FSF assignment,
>>> but that might be a reason I couldn't directly push the patches.
>>>
>>> Do we need to wait with these patches until this gets sorted out on my part?
>>
>> I'm afraid so. The size and number of patches is such that we can't
>> accept them under the "tiny patch" rule.
> 
> so we're clear, the patches before Dragan become involved should be cleared.
> the changes he made on top of them is what he was referring to.
> 
> Dagan: can you follow the FSF copyright assignment just to avoid any further
> confusion.
> -mike

Hi,

Sorry for the long wait. I've been told that the FSF assignment for 
Syrmia LLC should be in place now. Can somebody confirm that?

Best regards,

Dragan

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

* Re: [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6
  2022-04-15  7:24                     ` Dragan Mladjenovic
@ 2022-04-15  7:35                       ` Eli Zaretskii
  0 siblings, 0 replies; 50+ messages in thread
From: Eli Zaretskii @ 2022-04-15  7:35 UTC (permalink / raw)
  To: Dragan Mladjenovic; +Cc: brobecker, macro, gdb-patches, cfu

> Date: Fri, 15 Apr 2022 09:24:21 +0200
> From: Dragan Mladjenovic <Dragan.Mladjenovic@syrmia.com>
> 
> > Dagan: can you follow the FSF copyright assignment just to avoid any further
> > confusion.
> > -mike
> 
> Hi,
> 
> Sorry for the long wait. I've been told that the FSF assignment for 
> Syrmia LLC should be in place now. Can somebody confirm that?

I don't see it there, but maybe I don't know what to look for?  What
name(s) should it state, exactly?

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

* Re: [PATCH v5 4/4] sim: mips: Add simulator support for mips32r6/mips64r6
  2022-02-02 10:17   ` [PATCH v5 4/4] sim: mips: Add simulator support for mips32r6/mips64r6 Dragan Mladjenovic
@ 2022-12-25  0:26     ` Mike Frysinger
  2022-12-27 19:35       ` Dragan Mladjenovic
  0 siblings, 1 reply; 50+ messages in thread
From: Mike Frysinger @ 2022-12-25  0:26 UTC (permalink / raw)
  To: Dragan Mladjenovic
  Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

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

On 02 Feb 2022 11:17, Dragan Mladjenovic wrote:
> --- a/sim/mips/configure.ac
> +++ b/sim/mips/configure.ac
> @@ -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;
> +  }

why do you need this logic in the main engine run routine ?  why isn't the
STATE_ARCHITECTURE value already set to the correct value ?  if it isn't set
correctly all the time, this can lead to incorrect behavior elsewhere when
code checks it.

when the sim is opened, the bfd_mach is either explicitly passed in (which
gdb does), or initialized with a call to the bfd library APIs.  see the
sim/common/sim-utils.c:sim_analyze_program code.
-mike

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

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

* Re: [PATCH v5 4/4] sim: mips: Add simulator support for mips32r6/mips64r6
  2022-12-25  0:26     ` Mike Frysinger
@ 2022-12-27 19:35       ` Dragan Mladjenovic
  2022-12-28  0:12         ` Mike Frysinger
  0 siblings, 1 reply; 50+ messages in thread
From: Dragan Mladjenovic @ 2022-12-27 19:35 UTC (permalink / raw)
  To: Mike Frysinger
  Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

On 25-Dec-22 01:26, Mike Frysinger wrote:
> On 02 Feb 2022 11:17, Dragan Mladjenovic wrote:
>> --- a/sim/mips/configure.ac
>> +++ b/sim/mips/configure.ac
>> @@ -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;
>> +  }
> 
> why do you need this logic in the main engine run routine ?  why isn't the
> STATE_ARCHITECTURE value already set to the correct value ?  if it isn't set
> correctly all the time, this can lead to incorrect behavior elsewhere when
> code checks it.
> 
> when the sim is opened, the bfd_mach is either explicitly passed in (which
> gdb does), or initialized with a call to the bfd library APIs.  see the
> sim/common/sim-utils.c:sim_analyze_program code.
> -mike

Hi,

Sorry but the exact reason for doing so eludes me. It is done on 
internal jump for gdb 8 to gdb 10, permissibly to allow running
binary even whet set arch forces older mips isa, but I see little
use of that outside of testsuite maybe.

Best regards,
Dragan

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

* Re: [PATCH v5 4/4] sim: mips: Add simulator support for mips32r6/mips64r6
  2022-12-27 19:35       ` Dragan Mladjenovic
@ 2022-12-28  0:12         ` Mike Frysinger
  2023-01-13 14:09           ` Dragan Mladjenovic
  0 siblings, 1 reply; 50+ messages in thread
From: Mike Frysinger @ 2022-12-28  0:12 UTC (permalink / raw)
  To: Dragan Mladjenovic
  Cc: gdb-patches, Maciej W . Rozycki, Chao-ying Fu, Faraz Shahbazker

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

On 27 Dec 2022 20:35, Dragan Mladjenovic wrote:
> On 25-Dec-22 01:26, Mike Frysinger wrote:
> > On 02 Feb 2022 11:17, Dragan Mladjenovic wrote:
> >> --- a/sim/mips/configure.ac
> >> +++ b/sim/mips/configure.ac
> >> @@ -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;
> >> +  }
> > 
> > why do you need this logic in the main engine run routine ?  why isn't the
> > STATE_ARCHITECTURE value already set to the correct value ?  if it isn't set
> > correctly all the time, this can lead to incorrect behavior elsewhere when
> > code checks it.
> > 
> > when the sim is opened, the bfd_mach is either explicitly passed in (which
> > gdb does), or initialized with a call to the bfd library APIs.  see the
> > sim/common/sim-utils.c:sim_analyze_program code.
> 
> Sorry but the exact reason for doing so eludes me. It is done on 
> internal jump for gdb 8 to gdb 10, permissibly to allow running
> binary even whet set arch forces older mips isa, but I see little
> use of that outside of testsuite maybe.

i'd argue that if you load a binary for one ISA, then force the runtime
to use a different one, and the result crashes, then the sim is WAI.  it
should behave as real hardware does, and if you load a binary that needs
a newer ISA than a CPU provides, it won't work.

do you know if there's a testsuite, sim or gdb, that exercises this ?
-mike

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

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

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

On 28-Dec-22 01:12, Mike Frysinger wrote:
> On 27 Dec 2022 20:35, Dragan Mladjenovic wrote:
>> On 25-Dec-22 01:26, Mike Frysinger wrote:
>>> On 02 Feb 2022 11:17, Dragan Mladjenovic wrote:
>>>> --- a/sim/mips/configure.ac
>>>> +++ b/sim/mips/configure.ac
>>>> @@ -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;
>>>> +  }
>>>
>>> why do you need this logic in the main engine run routine ?  why isn't the
>>> STATE_ARCHITECTURE value already set to the correct value ?  if it isn't set
>>> correctly all the time, this can lead to incorrect behavior elsewhere when
>>> code checks it.
>>>
>>> when the sim is opened, the bfd_mach is either explicitly passed in (which
>>> gdb does), or initialized with a call to the bfd library APIs.  see the
>>> sim/common/sim-utils.c:sim_analyze_program code.
>>
>> Sorry but the exact reason for doing so eludes me. It is done on
>> internal jump for gdb 8 to gdb 10, permissibly to allow running
>> binary even whet set arch forces older mips isa, but I see little
>> use of that outside of testsuite maybe.
> 
> i'd argue that if you load a binary for one ISA, then force the runtime
> to use a different one, and the result crashes, then the sim is WAI.  it
> should behave as real hardware does, and if you load a binary that needs
> a newer ISA than a CPU provides, it won't work.
> 
> do you know if there's a testsuite, sim or gdb, that exercises this ?
> -mike

Hi,

Sorry for the late reply. I couldn't find any.


Best regards,
Dragan

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

end of thread, other threads:[~2023-01-13 14:10 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-20  7:45 [PATCH 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
2021-05-20  7:45 ` [PATCH 1/5] sim: Allow toggling of quiet NaN-bit semantics Faraz Shahbazker
2021-05-22  1:16   ` Mike Frysinger
2021-05-20  7:45 ` [PATCH 2/5] sim: Factor out NaN handling in floating point operations Faraz Shahbazker
2021-05-22  1:25   ` Mike Frysinger
2021-05-23  6:32     ` [EXTERNAL]Re: " Faraz Shahbazker
2021-05-24  1:26       ` Mike Frysinger
2021-05-20  7:45 ` [PATCH 3/5] sim: Add partial support for IEEE 754-2008 Faraz Shahbazker
2021-05-22  1:34   ` Mike Frysinger
2021-05-20  7:45 ` [PATCH 4/5] sim: mips: Add simulator support for mips32r6/mips64r6 Faraz Shahbazker
2021-05-22  1:46   ` Mike Frysinger
2021-05-22  6:20     ` Eli Zaretskii
2021-06-27 19:25       ` [EXTERNAL]Re: " Faraz Shahbazker
2021-06-27 19:33         ` Simon Marchi
2021-06-27 19:44           ` Eli Zaretskii
2021-06-27 20:24             ` Faraz Shahbazker
2021-06-28 12:17               ` Eli Zaretskii
2021-07-02 10:10                 ` Faraz Shahbazker
2021-12-24 18:42                   ` Mike Frysinger
2021-06-28  1:16           ` Mike Frysinger
2021-05-22  6:44     ` Faraz Shahbazker
2021-05-24 17:57     ` [PATCH v2 0/5] Add support for MIPS32/64 revision 6 Faraz Shahbazker
2021-05-24 17:57       ` [PATCH v2 1/5] sim: Allow toggling of quiet NaN-bit semantics Faraz Shahbazker
2021-05-24 17:57       ` [PATCH v2 2/5] sim: Factor out NaN handling in floating point operations Faraz Shahbazker
2021-05-24 17:58       ` [PATCH v2 3/5] sim: Add partial support for IEEE 754-2008 Faraz Shahbazker
2021-05-24 17:58       ` [PATCH v2 4/5] sim: mips: Add simulator support for mips32r6/mips64r6 Faraz Shahbazker
2021-05-24 17:58       ` [PATCH v2 5/5] gdb: mips: Add MIPSR6 support Faraz Shahbazker
2021-05-29  1:53         ` Simon Marchi
2021-06-27 19:10           ` [PATCH v3 " Faraz Shahbazker
2021-05-20  7:45 ` [PATCH " Faraz Shahbazker
2022-02-02 10:17 ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Dragan Mladjenovic
2022-02-02 10:17   ` [PATCH v5 1/4] sim: Allow toggling of quiet NaN-bit semantics Dragan Mladjenovic
2022-02-02 10:17   ` [PATCH v5 2/4] sim: Factor out NaN handling in floating point operations Dragan Mladjenovic
2022-02-02 10:17   ` [PATCH v5 3/4] sim: Add partial support for IEEE 754-2008 Dragan Mladjenovic
2022-02-02 10:17   ` [PATCH v5 4/4] sim: mips: Add simulator support for mips32r6/mips64r6 Dragan Mladjenovic
2022-12-25  0:26     ` Mike Frysinger
2022-12-27 19:35       ` Dragan Mladjenovic
2022-12-28  0:12         ` Mike Frysinger
2023-01-13 14:09           ` Dragan Mladjenovic
2022-02-04  5:48   ` [PATCH v5 0/4] sim: Add support for MIPS32/64 revision 6 Mike Frysinger
2022-02-04 12:29     ` Dragan Mladjenovic
2022-02-06 14:57       ` Joel Brobecker
2022-02-06 15:38         ` Dragan Mladjenovic
2022-02-06 16:28           ` Joel Brobecker
2022-02-06 18:49             ` Mike Frysinger
2022-02-07 11:48               ` Dragan Mladjenovic
2022-02-13 13:43                 ` Joel Brobecker
2022-02-14  0:04                   ` Mike Frysinger
2022-04-15  7:24                     ` Dragan Mladjenovic
2022-04-15  7:35                       ` Eli Zaretskii

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