[v3,4/4] sim: mips: Add simulator support for mips32r6/mips64r6

Message ID 20220111212406.32312-5-Dragan.Mladjenovic@syrmia.com
State New
Headers show
Series
  • sim: Add support for MIPS32/64 revision 6
Related show

Commit Message

Dragan Mladjenovic Jan. 11, 2022, 9:24 p.m.
From: Faraz Shahbazker <fshahbazker@wavecomp.com>


2022-01-11  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                     |  409 +++++++++-
 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, 3748 insertions(+), 53 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 v2: Fix Werror failures; Minor typos; Exclude mips16 from mipsisa[32|64]r6.

-- 
2.17.1

Comments

Simon Marchi via Gdb-patches Jan. 12, 2022, 10:57 a.m. | #1
On 11 Jan 2022 22:24, Dragan Mladjenovic wrote:

i don't have substantial feedback on this since i'm not a MIPS expert

> +static sim_fpu_status

> +inner_fmac (int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),

> +	    uint64_t op1,

> +	    uint64_t op2,

> +	    uint64_t op3,

> +	    sim_fpu_round round,

> +	    sim_fpu_denorm denorm,

> +	    FP_formats fmt,

> +	    uint64_t *result)

> +{

> +  sim_fpu wop1, wop2, ans;

> +  sim_fpu_status status = 0;

> +  sim_fpu_status op_status;

> +  uint32_t t32 = 0;

> +  uint64_t t64 = 0;

> +

> +  switch (fmt)

> +  {


bad indentation on switch body.  some other funcs in this patch have the same
problem, so please go through it and double check.

> +    default:

> +      sim_io_eprintf (SD, "Bad switch\n");

> +      abort ();


when you have access to SD, you can use sim_io_error to do the msg+abort.
sim_io_error (SD, "%s: unaccounted switch", __func__);

if you have a sim_cpu, you can use CPU_STATE (cpu).
-mike

Patch

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..9d52630a624 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,113 @@  fp_test(uint64_t op1,
   return status;
 }
 
+static const int sim_fpu_class_mips_mapping[] = {
+	FP_R6CLASS_SNAN, /* SIM_FPU_IS_SNAN = 1, Noisy not-a-number */
+	FP_R6CLASS_QNAN, /* SIM_FPU_IS_QNAN = 2, Quiet not-a-number */
+	FP_R6CLASS_NEGINF, /* SIM_FPU_IS_NINF = 3, -infinity */
+	FP_R6CLASS_POSINF, /* SIM_FPU_IS_PINF = 4, +infinity */
+	FP_R6CLASS_NEGNORM, /* SIM_FPU_IS_NNUMBER = 5, -num - [-MAX .. -MIN] */
+	FP_R6CLASS_POSNORM, /* SIM_FPU_IS_PNUMBER = 6, +num - [+MIN .. +MAX] */
+	FP_R6CLASS_NEGSUB, /* SIM_FPU_IS_NDENORM = 7, -denorm - (MIN .. 0) */
+	FP_R6CLASS_POSSUB, /* SIM_FPU_IS_PDENORM = 8, +denorm - (0 .. MIN) */
+	FP_R6CLASS_NEGZERO, /* SIM_FPU_IS_NZERO = 9, -0 */
+	FP_R6CLASS_POSZERO /* SIM_FPU_IS_PZERO = 10, +0 */
+};
+
+uint64_t
+fp_classify (sim_cpu *cpu,
+	     address_word cia,
+	     uint64_t op,
+	     FP_formats fmt)
+{
+  sim_fpu wop;
+
+  /* The format type has already been checked:  */
+  switch (fmt)
+    {
+    case fmt_single:
+      sim_fpu_32to (&wop, op);
+      break;
+    case fmt_double:
+      sim_fpu_64to (&wop, op);
+      break;
+    default:
+      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,
+	 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:
+      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 ((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:
+      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,
     }
 }
 
+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:
+      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,
 	 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);
@@ -696,9 +893,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;
@@ -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 *),
+	    uint64_t op1,
+	    uint64_t op2,
+	    uint64_t op3,
+	    sim_fpu_round round,
+	    sim_fpu_denorm denorm,
+	    FP_formats fmt,
+	    uint64_t *result)
+{
+  sim_fpu wop1, wop2, ans;
+  sim_fpu_status status = 0;
+  sim_fpu_status op_status;
+  uint32_t t32 = 0;
+  uint64_t t64 = 0;
+
+  switch (fmt)
+  {
+    case fmt_single:
+      sim_fpu_32to (&wop1, op1);
+      sim_fpu_32to (&wop2, op2);
+      status |= sim_fpu_mul (&ans, &wop1, &wop2);
+      wop1 = ans;
+      op_status = 0;
+      sim_fpu_32to (&wop2, op3);
+      op_status |= (*sim_fpu_op) (&ans, &wop2, &wop1);
+      op_status |= sim_fpu_round_32 (&ans, round, denorm);
+      status |= op_status;
+      sim_fpu_to32 (&t32, &ans);
+      t64 = t32;
+      break;
+    case fmt_double:
+      sim_fpu_64to (&wop1, op1);
+      sim_fpu_64to (&wop2, op2);
+      status |= sim_fpu_mul (&ans, &wop1, &wop2);
+      wop1 = ans;
+      op_status = 0;
+      sim_fpu_64to (&wop2, op3);
+      op_status |= (*sim_fpu_op) (&ans, &wop2, &wop1);
+      op_status |= sim_fpu_round_64 (&ans, round, denorm);
+      status |= op_status;
+      sim_fpu_to64 (&t64, &ans);
+      break;
+    default:
+      fprintf (stderr, "Bad switch\n");
+      abort ();
+      break;
+  }
+
+  *result = t64;
+  return status;
+}
+
+static uint64_t
+fp_fmac (sim_cpu *cpu,
+	 address_word cia,
+	 int (*sim_fpu_op) (sim_fpu *, const sim_fpu *, const sim_fpu *),
+	 uint64_t op1,
+	 uint64_t op2,
+	 uint64_t op3,
+	 FP_formats fmt)
+{
+  sim_fpu_round round = rounding_mode (GETRM());
+  sim_fpu_denorm denorm = denorm_mode (cpu);
+  sim_fpu_status status = 0;
+  uint64_t result = 0;
+
+  switch (fmt)
+  {
+    case fmt_single:
+    case fmt_double:
+      status = inner_fmac (sim_fpu_op, op1, op2, op3, round,
+			   denorm, fmt, &result);
+      break;
+    default:
+      sim_io_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(uint64_t op1,
@@ -1039,6 +1320,96 @@  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:
+      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;
+}
+
+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:
+      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;
+}
+
 uint64_t
 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);
 }
 
+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,
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