[PATCH,MIPS] MIPS64r6 support

Matthew Fortune Matthew.Fortune@imgtec.com
Mon Jun 9 15:18:00 GMT 2014


This patch introduces the next major architecture release for MIPS.

MIPS64r6 contains significant changes to the MIPS architecture. The
specification can be found here:

http://www.imgtec.com/mips/architectures/mips64.asp

binutils support for MIP64r6 is currently under review and is posted
here:

https://sourceware.org/ml/binutils/2014-04/msg00274.html

The initial support for MIP64r6 is intentionally minimal to make review
easier. Performance enhancements and use of new MIPS64r6 features will
be introduced separately. The current patch makes no attempt to
get the testsuite appropriately configured for MIPS64r6 as the existing
structure relies on each MIPS revision being a superset of the previous.
Recommendations on how to rework the mips.exp logic to cope with this
would be appreciated.

This patch focusses entirely on generic support for MIPS64r6 and
therefore only adds support to the mipsisa3264 configuration. Vendor 
configuration changes will be posted separately.

Two dummy processors have been introduced with this support as the
removal of instructions in MIPS64r6 means that it does not make sense
to link the new architecture with any pre-existing implementation of
MIPS.

All being well this patch is clean for coding standards and has been
tested using the GCC testsuites (but by completely disabling any test
which is not expected to work with MIPS64r6). The testsuite changes
do of course need addressing prior to committing this work.

Regards,
Matthew

gcc/

	* config.gcc: Add mipsisa64r6 and mipsisa32r6 cpu support.
	* config/mips/constraints.md (ZD): Add r6 restrictions.
	* config/mips/linux.h (GLIBC_DYNAMIC_LINKER): Update.
	(UCLIBC_DYNAMIC_LINKER): Likewise.
	* config/mips/linux64.h (GLIBC_DYNAMIC_LINKER32): Likewise.
	(GLIBC_DYNAMIC_LINKER64): Likewise.
	(GLIBC_DYNAMIC_LINKERN32): Likewise.
	(UCLIBC_DYNAMIC_LINKER32): Likewise.
	(UCLIBC_DYNAMIC_LINKER64): Likewise.
	(UCLIBC_DYNAMIC_LINKERN32): Likewise.
	* config/mips/loongson.md
	(<u>div<mode>3, <u>mod<mode>3): Remove.  Move to mips.md.
	* config/mips/mips-cpus.def (mips32r6, mips64r6): Define.
	* config/mips/mips-modes.def (CCF): New mode.
	* config/mips/mips-protos.h
	(mipsr6_9bit_offset_address_p): New prototype.
	* config/mips/mips-tables.opt: Regenerate.
	* config/mips/mips.c (MIPS_JALR0): New macro.
	(mips_rtx_cost_data): Add pseudo-processors W32 and W64.
	(mipsr6_9bit_offset_address_p): New function.
	(mips_rtx_costs): Account for r6 multiplies.
	(mips_emit_compare): Implement r6 FPU comparisons.
	(mips_expand_conditional_move): Implement r6 selects.
	(mips_expand_conditional_trap): Account for removed trap immediate.
	(mips_expand_block_move): Disable inline move when LWL/LWR are removed.
	(mips_print_float_branch_condition): Update for r6 FPU branches.
	(mips_print_operand): Handle CCF mode compares.
	(mips_interrupt_extra_call_saved_reg_p): Do not attempt to call-save
	MD_REGS for r6.
	(mips_hard_regno_mode_ok_p): Support CCF mode.
	(mips_mode_ok_for_mov_fmt_p): Likewise.
	(mips_secondary_reload_class): CCFmode can be loaded directly.
	(mips_set_fast_mult_zero_zero_p): Account for r6 multiplies.
	(mips_option_override): Ensure r6 is used with fp64.  Set default
	mips_nan modes.  Check for mips_nan support.  Prevent DSP with r6.
	(mips_conditional_register_usage): Disable MD_REGS for r6. Disable
	FPSW for r6.
	(mips_mulsidi3_gen_fn): Support r6 multiplies.
	(mips_trampoline_init): Account for JR removal.
	* config/mips/mips.h (ISA_MIPS32R6, ISA_MIPS64R6): Define.
	(TARGET_CPU_CPP_BUILTINS): Rework for mips32/mips64.
	(ISA_HAS_JR): New macro.
	(ISA_HAS_R6MUL): Likewise.
	(ISA_HAS_R6DMUL): Likewise.
	(ISA_HAS_R6DIV): Likewise.
	(ISA_HAS_R6DDIV): Likewise.
	(ISA_HAS_CCF): Likewise.
	(ISA_HAS_SEL): Likewise.
	(ISA_HAS_COND_TRAPI): Likewise.
	(ISA_HAS_FP_MADDF_MSUBF): Likewise.
	(ISA_HAS_LWL_LWR): Likewise.
	(ISA_HAS_NAN_LEGACY): Likewise.
	(ISA_HAS_NAN_2008): Likewise.
	(ISA_HAS_PREFETCH_9BIT): Likewise.
	(MULTILIB_ISA_DEFAULT): Handle mips32r6 and mips64r6.
	(MIPS_ISA_LEVEL_SPEC): Likewise.
	(MIPS_ISA_SYNCI_SPEC): Likewise.
	(ISA_HAS_64BIT_REGS): Likewise.
	(ISA_HAS_BRANCHLIKELY): Likewise.
	(ISA_HAS_MUL3): Likewise.
	(ISA_HAS_DMULT): Likewise.
	(ISA_HAS_DDIV): Likewise.
	(ISA_HAS_DIV): Likewise.
	(ISA_HAS_MULT): Likewise.
	(ISA_HAS_FP_CONDMOVE): Likewise.
	(ISA_HAS_8CC): Likewise.
	(ISA_HAS_FP4): Likewise.
	(ISA_HAS_PAIRED_SINGLE): Likewise.
	(ISA_HAS_MADD_MSUB): Likewise.
	(ISA_HAS_FP_RECIP_RSQRT): Likewise.
	(ISA_HAS_DSP): Likewise.
	(ISA_HAS_DSPR2): Likewise.
	(MIPSR6_9BIT_OFFSET_P): New macro.
	* config/mips/mips.md (processor): Add w32 and w64.
	(type): Add idiv3nc.
	(FPCC): New mode iterator.
	(reg): Add CCF mode.
	(fpcmp): New mode attribute.
	(fcond): Add ordered, ltgt and ne codes.
	(fcond): Update code attribute.
	(sel): New code attribute.
	(selinv): Likewise.
	(ctrap<mode>4): Update condition.
	(*conditional_trapi<mode>): New define_insn.
	(*conditional_trap<mode>): Update to handle only register case.
	(mul<mode>3): Expand R6 multiplies.
	(<su>mulsi3_highpart): Likewise.
	(<su>muldi3_highpart): Likewise.
	(mul<mode>3_mul3_loongson): Rename...
	(mul<mode>3_mul3_r6): To this.  Add R6 mul instruction.
	(<u>mulsidi3_32bit_r6): New expander.
	(<u>mulsidi3_32bit): Restrict to pre-r6 multiplies.
	(<u>mulsidi3_32bit_r4000): Likewise.
	(<u>mulsidi3_64bit): Likewise.
	(<su>mulsi3_highpart_internal): Likewise.
	(mulsidi3_64bit_r6dmul): New instruction.
	(<su>mulsi3_highpart_r6): Likewise.
	(<su>muldi3_highpart_r6): Likewise.
	(*maddf<mode>): Likewise.
	(*msubf<mode>): Likewise.
	(movccf): Likewise.
	(*sel<code><GPR:mode>_using_<GPR2:mode>): Likewise.
	(*sel<mode>): Likewise.
	(<u>div<mode>3): Moved from loongson.md.  Add R6 instructions.
	(<u>mod<mode>3): Likewise.
	(extvmisalign<mode>): Require ISA_HAS_LWL_LWR.
	(extzvmisalign<mode>): Likewise.
	(insvmisalign<mode>): Likewise.
	(clear_hazard_<mode>): Account for R6 displacement field sizes.
	(*branch_fp): Rename...
	(*branch_fp_<mode>): To this.  Add FCCmode support.
	(*branch_fp_inverted): Rename...
	(*branch_fp_inverted_<mode>): To this.  Add FCCmode support.
	(s<code>_<mode>): Rename...
	(s<code>_<SCALARF:mode>_using_<FPCC:mode>): To this.  Add FCCmode
	condition support.
	(s<code>_<mode> swapped): Rename...
	(s<code>_<SCALARF:mode>_using_<FPCC:mode> swapped): To this. Add
	FCCmode condition support.
	(mov<mode>cc GPR): Expand R6 selects.
	(mov<mode>cc FPR): Expand R6 selects.
	(*tls_get_tp_<mode>_split): Do not .set push for >= mips32r2.
	* config/mips/netbsd.h (TARGET_CPU_CPP_BUILTINS): Update similarly to
	mips.h.
	(ASM_SPEC): Add mips32r6, mips64r6.
	* config/mips/t-isa3264 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES): Update
	for mips32r6/mips64r6.
	* doc/invoke.texi: Document -mips32r6,-mips64r6.

libgcc/

	* config.host: Support mipsisa32r6 and mipsisa64r6.
	* config/mips/mips16.S: Do not build for R6.
---
 gcc/config.gcc                  |   22 ++-
 gcc/config/mips/constraints.md  |    8 +-
 gcc/config/mips/linux.h         |    5 +-
 gcc/config/mips/linux64.h       |   15 +-
 gcc/config/mips/loongson.md     |   30 ---
 gcc/config/mips/mips-cpus.def   |    2 +
 gcc/config/mips/mips-modes.def  |    3 +
 gcc/config/mips/mips-protos.h   |    1 +
 gcc/config/mips/mips-tables.opt |  404 ++++++++++++++++++++-------------------
 gcc/config/mips/mips.c          |  253 ++++++++++++++++++++++---
 gcc/config/mips/mips.h          |  126 ++++++++-----
 gcc/config/mips/mips.md         |  292 ++++++++++++++++++++++++-----
 gcc/config/mips/netbsd.h        |   25 +--
 gcc/config/mips/t-isa3264       |    6 +-
 gcc/doc/invoke.texi             |   15 ++-
 libgcc/config.host              |    4 +-
 libgcc/config/mips/mips16.S     |    2 +-
 17 files changed, 835 insertions(+), 378 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index c3f3ea6..117415e 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1952,6 +1952,9 @@ mips64*-*-linux* | mipsisa64*-*-linux*)
 			tm_defines="${tm_defines} MIPS_CPU_STRING_DEFAULT=\\\"octeon\\\""
 			target_cpu_default=MASK_SOFT_FLOAT_ABI
 			;;
+		mipsisa64r6*-*-linux*)
+			tm_defines="${tm_defines} MIPS_ISA_DEFAULT=69"
+			;;
 		mipsisa64r2*-*-linux*)
 			tm_defines="${tm_defines} MIPS_ISA_DEFAULT=65"
 			;;
@@ -1968,6 +1971,9 @@ mips*-*-linux*)				# Linux MIPS, either endian.
 	fi
 	tm_file="${tm_file} mips/linux-common.h"
 	case ${target} in
+	mipsisa32r6*)
+		tm_defines="${tm_defines} MIPS_ISA_DEFAULT=37"
+		;;
         mipsisa32r2*)
 		tm_defines="${tm_defines} MIPS_ISA_DEFAULT=33"
                 ;;
@@ -2000,12 +2006,18 @@ mips*-sde-elf*)
 	    ;;
 	esac
 	case ${target} in
+	  mipsisa32r6*)
+	    tm_defines="MIPS_ISA_DEFAULT=37 MIPS_ABI_DEFAULT=ABI_32"
+	    ;;
 	  mipsisa32r2*)
 	    tm_defines="MIPS_ISA_DEFAULT=33 MIPS_ABI_DEFAULT=ABI_32"
 	    ;;
 	  mipsisa32*)
 	    tm_defines="MIPS_ISA_DEFAULT=32 MIPS_ABI_DEFAULT=ABI_32"
 	    ;;
+	  mipsisa64r6*)
+	    tm_defines="MIPS_ISA_DEFAULT=69 MIPS_ABI_DEFAULT=ABI_N32"
+	    ;;
 	  mipsisa64r2*)
 	    tm_defines="MIPS_ISA_DEFAULT=65 MIPS_ABI_DEFAULT=ABI_N32"
 	    ;;
@@ -2016,17 +2028,25 @@ mips*-sde-elf*)
 	;;
 mipsisa32-*-elf* | mipsisa32el-*-elf* | \
 mipsisa32r2-*-elf* | mipsisa32r2el-*-elf* | \
+mipsisa32r6-*-elf* | mipsisa32r6el-*-elf* | \
 mipsisa64-*-elf* | mipsisa64el-*-elf* | \
-mipsisa64r2-*-elf* | mipsisa64r2el-*-elf*)
+mipsisa64r2-*-elf* | mipsisa64r2el-*-elf* | \
+mipsisa64r6-*-elf* | mipsisa64r6el-*-elf*)
 	tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
 	tmake_file="mips/t-isa3264"
 	case ${target} in
+	  mipsisa32r6*)
+	    tm_defines="${tm_defines} MIPS_ISA_DEFAULT=37"
+	    ;;
 	  mipsisa32r2*)
 	    tm_defines="${tm_defines} MIPS_ISA_DEFAULT=33"
 	    ;;
 	  mipsisa32*)
 	    tm_defines="${tm_defines} MIPS_ISA_DEFAULT=32"
 	    ;;
+	  mipsisa64r6*)
+	    tm_defines="${tm_defines} MIPS_ISA_DEFAULT=69"
+	    ;;
 	  mipsisa64r2*)
 	    tm_defines="${tm_defines} MIPS_ISA_DEFAULT=65"
 	    ;;
diff --git a/gcc/config/mips/constraints.md b/gcc/config/mips/constraints.md
index f6834fd..f93ae1c 100644
--- a/gcc/config/mips/constraints.md
+++ b/gcc/config/mips/constraints.md
@@ -324,10 +324,14 @@ (define_address_constraint "ZD"
   "When compiling microMIPS code, this constraint matches an address operand
    that is formed from a base register and a 12-bit offset.  These operands
    can be used for microMIPS instructions such as @code{prefetch}.  When
-   not compiling for microMIPS code, @code{ZD} is equivalent to @code{p}."
+   not compiling for microMIPS code, @code{ZD} is either equivalent to
+   @code{p} or matches an address operand that is formed from a base register
+   and a 9-bit offset, depending on ISA support."
    (if_then_else (match_test "TARGET_MICROMIPS")
 		 (match_test "umips_12bit_offset_address_p (op, mode)")
-		 (match_test "mips_address_insns (op, mode, false)")))
+		 (if_then_else (match_test "ISA_HAS_PREFETCH_9BIT")
+			(match_test "mipsr6_9bit_offset_address_p (op, mode)")
+			(match_test "mips_address_insns (op, mode, false)"))))
 
 (define_memory_constraint "ZR"
  "@internal
diff --git a/gcc/config/mips/linux.h b/gcc/config/mips/linux.h
index e539422..751623f 100644
--- a/gcc/config/mips/linux.h
+++ b/gcc/config/mips/linux.h
@@ -18,8 +18,9 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #define GLIBC_DYNAMIC_LINKER \
-  "%{mnan=2008:/lib/ld-linux-mipsn8.so.1;:/lib/ld.so.1}"
+  "%{mnan=2008|mips32r6|mips64r6:/lib/ld-linux-mipsn8.so.1;:/lib/ld.so.1}"
 
 #undef UCLIBC_DYNAMIC_LINKER
 #define UCLIBC_DYNAMIC_LINKER \
-  "%{mnan=2008:/lib/ld-uClibc-mipsn8.so.0;:/lib/ld-uClibc.so.0}"
+  "%{mnan=2008|mips32r6|mips64r6:/lib/ld-uClibc-mipsn8.so.0;" \
+  ":/lib/ld-uClibc.so.0}"
diff --git a/gcc/config/mips/linux64.h b/gcc/config/mips/linux64.h
index 7ad3b2a..d09fe23 100644
--- a/gcc/config/mips/linux64.h
+++ b/gcc/config/mips/linux64.h
@@ -23,20 +23,23 @@ along with GCC; see the file COPYING3.  If not see
 #define GNU_USER_LINK_EMULATIONN32 "elf32%{EB:b}%{EL:l}tsmipn32"
 
 #define GLIBC_DYNAMIC_LINKER32 \
-  "%{mnan=2008:/lib/ld-linux-mipsn8.so.1;:/lib/ld.so.1}"
+  "%{mnan=2008|mips32r6|mips64r6:/lib/ld-linux-mipsn8.so.1;:/lib/ld.so.1}"
 #define GLIBC_DYNAMIC_LINKER64 \
-  "%{mnan=2008:/lib64/ld-linux-mipsn8.so.1;:/lib64/ld.so.1}"
+  "%{mnan=2008|mips32r6|mips64r6:/lib64/ld-linux-mipsn8.so.1;:/lib64/ld.so.1}"
 #define GLIBC_DYNAMIC_LINKERN32 \
-  "%{mnan=2008:/lib32/ld-linux-mipsn8.so.1;:/lib32/ld.so.1}"
+  "%{mnan=2008|mips32r6|mips64r6:/lib32/ld-linux-mipsn8.so.1;:/lib32/ld.so.1}"
 
 #undef UCLIBC_DYNAMIC_LINKER32
 #define UCLIBC_DYNAMIC_LINKER32 \
-  "%{mnan=2008:/lib/ld-uClibc-mipsn8.so.0;:/lib/ld-uClibc.so.0}"
+  "%{mnan=2008|mips32r6|mips64r6:/lib/ld-uClibc-mipsn8.so.0;" \
+  ":/lib/ld-uClibc.so.0}"
 #undef UCLIBC_DYNAMIC_LINKER64
 #define UCLIBC_DYNAMIC_LINKER64 \
-  "%{mnan=2008:/lib/ld64-uClibc-mipsn8.so.0;:/lib/ld64-uClibc.so.0}"
+  "%{mnan=2008|mips32r6|mips64r6:/lib/ld64-uClibc-mipsn8.so.0;" \
+  ":/lib/ld64-uClibc.so.0}"
 #define UCLIBC_DYNAMIC_LINKERN32 \
-  "%{mnan=2008:/lib32/ld-uClibc-mipsn8.so.0;:/lib32/ld-uClibc.so.0}"
+  "%{mnan=2008|mips32r6|mips64r6:/lib32/ld-uClibc-mipsn8.so.0;" \
+  ":/lib32/ld-uClibc.so.0}"
 
 #define BIONIC_DYNAMIC_LINKERN32 "/system/bin/linker32"
 #define GNU_USER_DYNAMIC_LINKERN32 \
diff --git a/gcc/config/mips/loongson.md b/gcc/config/mips/loongson.md
index 474033d..0869131 100644
--- a/gcc/config/mips/loongson.md
+++ b/gcc/config/mips/loongson.md
@@ -907,33 +907,3 @@ (define_expand "reduc_umin_<mode>"
   mips_expand_vec_reduc (operands[0], operands[1], gen_umin<mode>3);
   DONE;
 })
-
-;; Integer division and modulus.  For integer multiplication, see mips.md.
-
-(define_insn "<u>div<mode>3"
-  [(set (match_operand:GPR 0 "register_operand" "=&d")
-	(any_div:GPR (match_operand:GPR 1 "register_operand" "d")
-		     (match_operand:GPR 2 "register_operand" "d")))]
-  "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A"
-  {
-    if (TARGET_LOONGSON_2EF)
-      return mips_output_division ("<d>div<u>.g\t%0,%1,%2", operands);
-    else
-      return mips_output_division ("gs<d>div<u>\t%0,%1,%2", operands);
-  }
-  [(set_attr "type" "idiv3")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "<u>mod<mode>3"
-  [(set (match_operand:GPR 0 "register_operand" "=&d")
-	(any_mod:GPR (match_operand:GPR 1 "register_operand" "d")
-		     (match_operand:GPR 2 "register_operand" "d")))]
-  "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A"
-  {
-    if (TARGET_LOONGSON_2EF)
-      return mips_output_division ("<d>mod<u>.g\t%0,%1,%2", operands);
-    else
-      return mips_output_division ("gs<d>mod<u>\t%0,%1,%2", operands);
-  }
-  [(set_attr "type" "idiv3")
-   (set_attr "mode" "<MODE>")])
diff --git a/gcc/config/mips/mips-cpus.def b/gcc/config/mips/mips-cpus.def
index d5528d3..8f48077 100644
--- a/gcc/config/mips/mips-cpus.def
+++ b/gcc/config/mips/mips-cpus.def
@@ -50,11 +50,13 @@ MIPS_CPU ("mips32r2", PROCESSOR_74KF2_1, 33, PTF_AVOID_BRANCHLIKELY)
    as mips32r2.  */
 MIPS_CPU ("mips32r3", PROCESSOR_M4K, 34, PTF_AVOID_BRANCHLIKELY)
 MIPS_CPU ("mips32r5", PROCESSOR_P5600, 36, PTF_AVOID_BRANCHLIKELY)
+MIPS_CPU ("mips32r6", PROCESSOR_W32, 37, PTF_AVOID_BRANCHLIKELY)
 MIPS_CPU ("mips64", PROCESSOR_5KC, 64, PTF_AVOID_BRANCHLIKELY)
 /* ??? For now just tune the generic MIPS64r2 and above for 5KC as well.   */
 MIPS_CPU ("mips64r2", PROCESSOR_5KC, 65, PTF_AVOID_BRANCHLIKELY)
 MIPS_CPU ("mips64r3", PROCESSOR_5KC, 66, PTF_AVOID_BRANCHLIKELY)
 MIPS_CPU ("mips64r5", PROCESSOR_5KC, 68, PTF_AVOID_BRANCHLIKELY)
+MIPS_CPU ("mips64r6", PROCESSOR_W64, 69, PTF_AVOID_BRANCHLIKELY)
 
 /* MIPS I processors.  */
 MIPS_CPU ("r3000", PROCESSOR_R3000, 1, 0)
diff --git a/gcc/config/mips/mips-modes.def b/gcc/config/mips/mips-modes.def
index fa1d1e7..96d72c1 100644
--- a/gcc/config/mips/mips-modes.def
+++ b/gcc/config/mips/mips-modes.def
@@ -46,3 +46,6 @@ ADJUST_ALIGNMENT (CCV4, 16);
 
 /* For MIPS DSP control registers.  */
 CC_MODE (CCDSP);
+
+/* For floating point conditions in FP registers.  */
+CC_MODE (CCF);
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 0b32a70..9560506 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -341,6 +341,7 @@ extern bool umips_load_store_pair_p (bool, rtx *);
 extern void umips_output_load_store_pair (bool, rtx *);
 extern bool umips_movep_target_p (rtx, rtx);
 extern bool umips_12bit_offset_address_p (rtx, enum machine_mode);
+extern bool mipsr6_9bit_offset_address_p (rtx, enum machine_mode);
 extern bool lwsp_swsp_address_p (rtx, enum machine_mode);
 extern bool m16_based_address_p (rtx, enum machine_mode,
 			         int (*)(rtx_def*, machine_mode)); 
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 1fb5ba2..38e338e 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -168,6 +168,9 @@ along with GCC; see the file COPYING3.  If not see
 #define MIPS_JR(DEST) \
   (((DEST) << 21) | 0x8)
 
+#define MIPS_JALR0(DEST) \
+  (((DEST) << 21) | 0x9)
+
 /* Return the opcode for:
 
        bal     . + (1 + OFFSET) * 4.  */
@@ -1193,6 +1196,32 @@ static const struct mips_rtx_cost_data
     COSTS_N_INSNS (8),            /* int_div_di */
 		    2,            /* branch_cost */
 		   10             /* memory_latency */
+  },
+  { /* W32 */
+    COSTS_N_INSNS (4),            /* fp_add */
+    COSTS_N_INSNS (4),            /* fp_mult_sf */
+    COSTS_N_INSNS (5),            /* fp_mult_df */
+    COSTS_N_INSNS (17),           /* fp_div_sf */
+    COSTS_N_INSNS (32),           /* fp_div_df */
+    COSTS_N_INSNS (5),            /* int_mult_si */
+    COSTS_N_INSNS (5),            /* int_mult_di */
+    COSTS_N_INSNS (41),           /* int_div_si */
+    COSTS_N_INSNS (41),           /* int_div_di */
+		     1,           /* branch_cost */
+		     4            /* memory_latency */
+  },
+  { /* W64 */
+    COSTS_N_INSNS (4),            /* fp_add */
+    COSTS_N_INSNS (4),            /* fp_mult_sf */
+    COSTS_N_INSNS (5),            /* fp_mult_df */
+    COSTS_N_INSNS (17),           /* fp_div_sf */
+    COSTS_N_INSNS (32),           /* fp_div_df */
+    COSTS_N_INSNS (5),            /* int_mult_si */
+    COSTS_N_INSNS (5),            /* int_mult_di */
+    COSTS_N_INSNS (41),           /* int_div_si */
+    COSTS_N_INSNS (41),           /* int_div_di */
+		     1,           /* branch_cost */
+		     4            /* memory_latency */
   }
 };
 

@@ -2596,6 +2625,20 @@ umips_12bit_offset_address_p (rtx x, enum machine_mode mode)
 	  && UMIPS_12BIT_OFFSET_P (INTVAL (addr.offset)));
 }
 
+/* Return true if X is a legitimate address with a 9-bit offset.
+   MODE is the mode of the value being accessed.  */
+
+bool
+mipsr6_9bit_offset_address_p (rtx x, enum machine_mode mode)
+{
+  struct mips_address_info addr;
+
+  return (mips_classify_address (&addr, x, mode, false)
+	  && addr.type == ADDRESS_REG
+	  && CONST_INT_P (addr.offset)
+	  && MIPSR6_9BIT_OFFSET_P (INTVAL (addr.offset)));
+}
+
 /* Return the number of instructions needed to load constant X,
    assuming that BASE_INSN_LENGTH is the length of one instruction.
    Return 0 if X isn't a valid constant.  */
@@ -4104,13 +4147,14 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       if (float_mode_p)
 	*total = mips_fp_mult_cost (mode);
       else if (mode == DImode && !TARGET_64BIT)
+	/* R6 impact ??? */
 	/* Synthesized from 2 mulsi3s, 1 mulsidi3 and two additions,
 	   where the mulsidi3 always includes an MFHI and an MFLO.  */
 	*total = (speed
 		  ? mips_cost->int_mult_si * 3 + 6
 		  : COSTS_N_INSNS (ISA_HAS_MUL3 ? 7 : 9));
       else if (!speed)
-	*total = COSTS_N_INSNS (ISA_HAS_MUL3 ? 1 : 2) + 1;
+	*total = COSTS_N_INSNS ((ISA_HAS_MUL3 || ISA_HAS_R6MUL) ? 1 : 2) + 1;
       else if (mode == DImode)
 	*total = mips_cost->int_mult_di;
       else
@@ -4186,6 +4230,46 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	}
       *total = mips_zero_extend_cost (mode, XEXP (x, 0));
       return false;
+    case TRUNCATE:
+      /* Costings for highpart multiplies.  */
+      if (ISA_HAS_R6MUL
+	  && (GET_CODE (XEXP (x, 0)) == ASHIFTRT
+	      || GET_CODE (XEXP (x, 0)) == LSHIFTRT)
+	  && CONST_INT_P (XEXP (XEXP (x, 0), 1))
+	  && ((INTVAL (XEXP (XEXP (x, 0), 1)) == 32
+	       && GET_MODE (XEXP (x, 0)) == DImode)
+	      || (ISA_HAS_R6DMUL
+		  && INTVAL (XEXP (XEXP (x, 0), 1)) == 64
+		  && GET_MODE (XEXP (x, 0)) == TImode))
+	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+	  && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND
+	       && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SIGN_EXTEND)
+	      || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
+		  && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1))
+		      == ZERO_EXTEND))))
+	{
+	  if (!speed)
+	    *total = COSTS_N_INSNS (1) + 1;
+	  else if (mode == DImode)
+	    *total = mips_cost->int_mult_di;
+	  else
+	    *total = mips_cost->int_mult_si;
+
+	  /* Sign extension is free, zero extension costs for DImode when
+	     on a 64bit core / when DMUL is present.  */
+	  if (ISA_HAS_R6DMUL && GET_MODE (XEXP (x, 0)) == DImode)
+	    {
+	      if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND)
+		*total += rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 0),
+				    ZERO_EXTEND, 0, speed);
+
+	      if (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == ZERO_EXTEND)
+		*total += rtx_cost (XEXP (XEXP (XEXP (x, 0), 0), 1),
+				    ZERO_EXTEND, 0, speed);
+	    }
+	  return true;
+	}
+      return false;
 
     case FLOAT:
     case UNSIGNED_FLOAT:
@@ -4969,17 +5053,32 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p)
     {
       enum rtx_code cmp_code;
 
-      /* Floating-point tests use a separate C.cond.fmt comparison to
-	 set a condition code register.  The branch or conditional move
-	 will then compare that register against zero.
+      /* Floating-point tests use a separate C.cond.fmt or CMP.cond.fmt
+	 comparison to set a condition code register.  The branch or
+	 conditional move will then compare that register against zero.
 
 	 Set CMP_CODE to the code of the comparison instruction and
 	 *CODE to the code that the branch or move should use.  */
       cmp_code = *code;
-      *code = mips_reversed_fp_cond (&cmp_code) ? EQ : NE;
-      *op0 = (ISA_HAS_8CC
-	      ? mips_allocate_fcc (CCmode)
-	      : gen_rtx_REG (CCmode, FPSW_REGNUM));
+      if (ISA_HAS_CCF)
+        {
+	  /* All FP conditions can be implemented directly with CMP.cond.fmt
+	     or by reversing the operands.  */
+	  *code = NE;
+	  *op0 = gen_reg_rtx (CCFmode);
+	}
+      else
+	{
+	  /* Three FP conditions cannot be implemented by reversing the
+	     operands for C.cond.fmt, instead a reversed condition code is
+	     required and a test for false.  */
+	  *code = mips_reversed_fp_cond (&cmp_code) ? EQ : NE;
+	  if (ISA_HAS_8CC)
+	    *op0 = mips_allocate_fcc (CCmode);
+	  else
+	    *op0 = gen_rtx_REG (CCmode, FPSW_REGNUM);
+	}
+
       *op1 = const0_rtx;
       mips_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1);
     }
@@ -5069,9 +5168,37 @@ mips_expand_conditional_move (rtx *operands)
 
   mips_emit_compare (&code, &op0, &op1, true);
   cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-			  gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), cond,
-						operands[2], operands[3])));
+
+  /* There is no direct support for general conditional GP move involving
+     two registers using SEL.  */
+  if (ISA_HAS_SEL
+      && INTEGRAL_MODE_P (GET_MODE (operands[2]))
+      && register_operand (operands[2], VOIDmode)
+      && register_operand (operands[3], VOIDmode))
+    {
+      enum machine_mode mode = GET_MODE (operands[0]);
+      rtx temp = gen_reg_rtx (mode);
+      rtx temp2 = gen_reg_rtx (mode);
+
+      emit_insn (gen_rtx_SET (VOIDmode, temp,
+			      gen_rtx_IF_THEN_ELSE (mode, cond,
+						    operands[2], const0_rtx)));
+
+      /* Flip the test for the second operand.  */
+      cond = gen_rtx_fmt_ee ((code == EQ) ? NE : EQ, GET_MODE (op0), op0, op1);
+
+      emit_insn (gen_rtx_SET (VOIDmode, temp2,
+			      gen_rtx_IF_THEN_ELSE (mode, cond,
+						    operands[3], const0_rtx)));
+
+      /* Merge the two results, at least one is guaranteed to be zero.  */
+      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+			      gen_rtx_IOR (mode, temp, temp2)));
+    }
+  else
+    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+			    gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), cond,
+						  operands[2], operands[3])));
 }
 
 /* Perform the comparison in COMPARISON, then trap if the condition holds.  */
@@ -5105,7 +5232,9 @@ mips_expand_conditional_trap (rtx comparison)
 
   mode = GET_MODE (XEXP (comparison, 0));
   op0 = force_reg (mode, op0);
-  if (!arith_operand (op1, mode))
+  if (!arith_operand (op1, mode)
+      || (!ISA_HAS_COND_TRAPI
+	  && !register_operand (op1, mode)))
     op1 = force_reg (mode, op1);
 
   emit_insn (gen_rtx_TRAP_IF (VOIDmode,
@@ -7420,6 +7549,10 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length,
 bool
 mips_expand_block_move (rtx dest, rtx src, rtx length)
 {
+  /* Disable entirely for R6 initially.  */
+  if (!ISA_HAS_LWL_LWR)
+    return false;
+
   if (CONST_INT_P (length))
     {
       if (INTVAL (length) <= MIPS_MAX_MOVE_BYTES_STRAIGHT)
@@ -8181,11 +8314,17 @@ mips_print_float_branch_condition (FILE *file, enum rtx_code code, int letter)
   switch (code)
     {
     case EQ:
-      fputs ("c1f", file);
+      if (ISA_HAS_CCF)
+	fputs ("c1eqz", file);
+      else
+	fputs ("c1f", file);
       break;
 
     case NE:
-      fputs ("c1t", file);
+      if (ISA_HAS_CCF)
+	fputs ("c1nez", file);
+      else
+	fputs ("c1t", file);
       break;
 
     default:
@@ -8315,7 +8454,7 @@ mips_print_operand (FILE *file, rtx op, int letter)
       break;
 
     case 'Z':
-      if (ISA_HAS_8CC)
+      if (ISA_HAS_8CC || ISA_HAS_CCF)
 	{
 	  mips_print_operand (file, op, 0);
 	  fputc (',', file);
@@ -9803,7 +9942,8 @@ mips_must_initialize_gp_p (void)
 static bool
 mips_interrupt_extra_call_saved_reg_p (unsigned int regno)
 {
-  if (MD_REG_P (regno))
+  if ((ISA_HAS_MULT || TARGET_DSP)
+      && MD_REG_P (regno))
     return true;
 
   if (TARGET_DSP && DSP_ACC_REG_P (regno))
@@ -11753,6 +11893,10 @@ mips_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
 	    && ST_REG_P (regno)
 	    && (regno - ST_REG_FIRST) % 4 == 0);
 
+  if (mode == CCFmode)
+    return (ISA_HAS_CCF
+	    && FP_REG_P (regno));
+
   if (mode == CCmode)
     return ISA_HAS_8CC ? ST_REG_P (regno) : regno == FPSW_REGNUM;
 
@@ -11925,6 +12069,9 @@ mips_mode_ok_for_mov_fmt_p (enum machine_mode mode)
 {
   switch (mode)
     {
+    case CCFmode:
+      return TARGET_HARD_FLOAT;
+
     case SFmode:
       return TARGET_HARD_FLOAT;
 
@@ -12190,6 +12337,10 @@ mips_secondary_reload_class (enum reg_class rclass,
 	/* In this case we can use mov.fmt.  */
 	return NO_REGS;
 
+      /* We don't need a reload if the pseudo is in memory in CCF mode.  */
+      if (mode == CCFmode && regno == -1)
+	return NO_REGS;
+
       /* Otherwise, we need to reload through an integer register.  */
       return GR_REGS;
     }
@@ -15789,7 +15940,7 @@ mips_mult_zero_zero_cost (struct mips_sim *state, bool setting)
 static void
 mips_set_fast_mult_zero_zero_p (struct mips_sim *state)
 {
-  if (TARGET_MIPS16)
+  if (TARGET_MIPS16 || !ISA_HAS_MULT)
     /* No MTLO or MTHI available.  */
     mips_tuning_info.fast_mult_zero_zero_p = true;
   else
@@ -17035,7 +17186,9 @@ mips_option_override (void)
 
   if ((target_flags_explicit & MASK_FLOAT64) != 0)
     {
-      if (TARGET_SINGLE_FLOAT && TARGET_FLOAT64)
+      if (mips_isa_rev >= 6 && !TARGET_FLOAT64)
+	error ("unsupported combination: %s", "-mips[32|64]r6 -mfp32");
+      else if (TARGET_SINGLE_FLOAT && TARGET_FLOAT64)
 	error ("unsupported combination: %s", "-mfp64 -msingle-float");
       else if (TARGET_64BIT && TARGET_DOUBLE_FLOAT && !TARGET_FLOAT64)
 	error ("unsupported combination: %s", "-mgp64 -mfp32 -mdouble-float");
@@ -17052,8 +17205,12 @@ mips_option_override (void)
   else
     {
       /* -msingle-float selects 32-bit float registers.  Otherwise the
-	 float registers should be the same size as the integer ones.  */
-      if (TARGET_64BIT && TARGET_DOUBLE_FLOAT)
+	 float registers should be the same size as the integer ones.
+	 MIPS R6 has 64-bit float registers regardless of the size of
+	 the integer ones.  */
+      if (mips_isa_rev >= 6 && TARGET_DOUBLE_FLOAT)
+	target_flags |= MASK_FLOAT64;
+      else if (TARGET_64BIT && TARGET_DOUBLE_FLOAT)
 	target_flags |= MASK_FLOAT64;
       else
 	target_flags &= ~MASK_FLOAT64;
@@ -17209,6 +17366,25 @@ mips_option_override (void)
 	}
     }
 
+  /* Set NaN and ABS defaults.  */
+  if (mips_nan == MIPS_IEEE_754_DEFAULT && !ISA_HAS_NANLEGACY)
+    mips_nan = MIPS_IEEE_754_2008;
+  if (mips_abs == MIPS_IEEE_754_DEFAULT && !ISA_HAS_NANLEGACY)
+    mips_abs = MIPS_IEEE_754_2008;
+
+  /* Check for NaN encoding support.  */
+  if ((mips_nan == MIPS_IEEE_754_LEGACY
+       || mips_abs == MIPS_IEEE_754_LEGACY)
+      && !ISA_HAS_NANLEGACY)
+    warning (0, "the %qs architecture does not support the NaN legacy"
+	     " encoding", mips_arch_info->name);
+
+  if ((mips_nan == MIPS_IEEE_754_2008
+       || mips_abs == MIPS_IEEE_754_2008)
+      && !ISA_HAS_NAN2008)
+    warning (0, "the %qs architecture does not support the NaN 2008"
+	     " encoding", mips_arch_info->name);
+
   /* Pre-IEEE 754-2008 MIPS hardware has a quirky almost-IEEE format
      for all its floating point.  */
   if (mips_nan != MIPS_IEEE_754_2008)
@@ -17263,6 +17439,10 @@ mips_option_override (void)
   if (TARGET_DSPR2)
     TARGET_DSP = true;
 
+  if (TARGET_DSP && mips_isa_rev >= 6)
+    error ("the %qs architecture does not support DSP instructions",
+	   mips_arch_info->name);
+
   /* .eh_frame addresses should be the same width as a C pointer.
      Most MIPS ABIs support only one pointer size, so the assembler
      will usually know exactly how big an .eh_frame address is.
@@ -17443,6 +17623,10 @@ mips_conditional_register_usage (void)
     AND_COMPL_HARD_REG_SET (accessible_reg_set,
 			    reg_class_contents[(int) DSP_ACC_REGS]);
 
+  if (!ISA_HAS_MULT && !ISA_HAS_DMULT)
+    AND_COMPL_HARD_REG_SET (accessible_reg_set,
+			    reg_class_contents[(int) MD_REGS]);
+
   if (!TARGET_HARD_FLOAT)
     {
       AND_COMPL_HARD_REG_SET (accessible_reg_set,
@@ -17457,7 +17641,8 @@ mips_conditional_register_usage (void)
 	 RTL that refers directly to ST_REG_FIRST.  */
       AND_COMPL_HARD_REG_SET (accessible_reg_set,
 			      reg_class_contents[(int) ST_REGS]);
-      SET_HARD_REG_BIT (accessible_reg_set, FPSW_REGNUM);
+      if (!ISA_HAS_CCF)
+	SET_HARD_REG_BIT (accessible_reg_set, FPSW_REGNUM);
       fixed_regs[FPSW_REGNUM] = call_used_regs[FPSW_REGNUM] = 1;
     }
   if (TARGET_MIPS16)
@@ -17658,6 +17843,8 @@ mips_mulsidi3_gen_fn (enum rtx_code ext_code)
 	 the extension is not needed for signed multiplication.  In order to
 	 ensure that we always remove the redundant sign-extension in this
 	 case we still expand mulsidi3 for DMUL.  */
+      if (ISA_HAS_R6DMUL)
+	return signed_p ? gen_mulsidi3_64bit_r6dmul : NULL;
       if (ISA_HAS_DMUL3)
 	return signed_p ? gen_mulsidi3_64bit_dmul : NULL;
       if (TARGET_MIPS16)
@@ -17670,6 +17857,8 @@ mips_mulsidi3_gen_fn (enum rtx_code ext_code)
     }
   else
     {
+      if (ISA_HAS_R6MUL)
+	return (signed_p ? gen_mulsidi3_32bit_r6 : gen_umulsidi3_32bit_r6);
       if (TARGET_MIPS16)
 	return (signed_p
 		? gen_mulsidi3_32bit_mips16
@@ -18006,7 +18195,10 @@ mips_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
       trampoline[i++] = OP (MIPS_LOAD_PTR (STATIC_CHAIN_REGNUM,
 					   static_chain_offset,
 					   PIC_FUNCTION_ADDR_REGNUM));
-      trampoline[i++] = OP (MIPS_JR (AT_REGNUM));
+      if (ISA_HAS_JR)
+	trampoline[i++] = OP (MIPS_JR (AT_REGNUM));
+      else
+	trampoline[i++] = OP (MIPS_JALR0 (AT_REGNUM));
       trampoline[i++] = OP (MIPS_MOVE (PIC_FUNCTION_ADDR_REGNUM, AT_REGNUM));
     }
   else if (ptr_mode == DImode)
@@ -18032,7 +18224,10 @@ mips_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
       trampoline[i++] = OP (MIPS_LOAD_PTR (STATIC_CHAIN_REGNUM,
 					   static_chain_offset - 12,
 					   RETURN_ADDR_REGNUM));
-      trampoline[i++] = OP (MIPS_JR (PIC_FUNCTION_ADDR_REGNUM));
+      if (ISA_HAS_JR)
+	trampoline[i++] = OP (MIPS_JR (PIC_FUNCTION_ADDR_REGNUM));
+      else
+	trampoline[i++] = OP (MIPS_JALR0 (PIC_FUNCTION_ADDR_REGNUM));
       trampoline[i++] = OP (MIPS_MOVE (RETURN_ADDR_REGNUM, AT_REGNUM));
     }
   else
@@ -18074,7 +18269,12 @@ mips_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
 
       /* Emit the JR here, if we can.  */
       if (!ISA_HAS_LOAD_DELAY)
-	trampoline[i++] = OP (MIPS_JR (PIC_FUNCTION_ADDR_REGNUM));
+	{
+	  if (ISA_HAS_JR)
+	    trampoline[i++] = OP (MIPS_JR (PIC_FUNCTION_ADDR_REGNUM));
+	  else
+	    trampoline[i++] = OP (MIPS_JALR0 (PIC_FUNCTION_ADDR_REGNUM));
+	}
 
       /* Emit the load of the static chain register.  */
       opcode = OP (MIPS_LOAD_PTR (STATIC_CHAIN_REGNUM,
@@ -18086,7 +18286,10 @@ mips_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
       /* Emit the JR, if we couldn't above.  */
       if (ISA_HAS_LOAD_DELAY)
 	{
-	  trampoline[i++] = OP (MIPS_JR (PIC_FUNCTION_ADDR_REGNUM));
+	  if (ISA_HAS_JR)
+	    trampoline[i++] = OP (MIPS_JR (PIC_FUNCTION_ADDR_REGNUM));
+	  else
+	    trampoline[i++] = OP (MIPS_JALR0 (PIC_FUNCTION_ADDR_REGNUM));
 	  trampoline[i++] = OP (MIPS_NOP);
 	}
     }
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 38eea44..79114c6 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -210,10 +210,12 @@ struct mips_cpu_info {
 #define ISA_MIPS32R2		    (mips_isa == 33)
 #define ISA_MIPS32R3		    (mips_isa == 34)
 #define ISA_MIPS32R5		    (mips_isa == 36)
+#define ISA_MIPS32R6		    (mips_isa == 37)
 #define ISA_MIPS64                  (mips_isa == 64)
 #define ISA_MIPS64R2		    (mips_isa == 65)
 #define ISA_MIPS64R3		    (mips_isa == 66)
 #define ISA_MIPS64R5		    (mips_isa == 68)
+#define ISA_MIPS64R6		    (mips_isa == 69)
 
 /* Architecture target defines.  */
 #define TARGET_LOONGSON_2E          (mips_arch == PROCESSOR_LOONGSON_2E)
@@ -444,42 +446,12 @@ struct mips_cpu_info {
 	  builtin_define ("__mips=4");					\
 	  builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS4");			\
 	}								\
-      else if (ISA_MIPS32)						\
+      else if (mips_isa >= 32 && mips_isa < 64)				\
 	{								\
 	  builtin_define ("__mips=32");					\
 	  builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32");		\
 	}								\
-      else if (ISA_MIPS32R2)						\
-	{								\
-	  builtin_define ("__mips=32");					\
-	  builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32");		\
-	}								\
-      else if (ISA_MIPS32R3)						\
-	{								\
-	  builtin_define ("__mips=32");					\
-	  builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32");		\
-	}								\
-      else if (ISA_MIPS32R5)						\
-	{								\
-	  builtin_define ("__mips=32");					\
-	  builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32");		\
-	}								\
-      else if (ISA_MIPS64)						\
-	{								\
-	  builtin_define ("__mips=64");					\
-	  builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64");		\
-	}								\
-      else if (ISA_MIPS64R2)						\
-	{								\
-	  builtin_define ("__mips=64");					\
-	  builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64");		\
-	}								\
-      else if (ISA_MIPS64R3)						\
-	{								\
-	  builtin_define ("__mips=64");					\
-	  builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64");		\
-	}								\
-      else if (ISA_MIPS64R5)						\
+      else if (mips_isa >= 64)						\
 	{								\
 	  builtin_define ("__mips=64");					\
 	  builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64");		\
@@ -657,10 +629,14 @@ struct mips_cpu_info {
 #define MULTILIB_ISA_DEFAULT "mips32"
 #elif MIPS_ISA_DEFAULT == 33
 #define MULTILIB_ISA_DEFAULT "mips32r2"
+#elif MIPS_ISA_DEFAULT == 37
+#define MULTILIB_ISA_DEFAULT "mips32r6"
 #elif MIPS_ISA_DEFAULT == 64
 #define MULTILIB_ISA_DEFAULT "mips64"
 #elif MIPS_ISA_DEFAULT == 65
 #define MULTILIB_ISA_DEFAULT "mips64r2"
+#elif MIPS_ISA_DEFAULT == 69
+#define MULTILIB_ISA_DEFAULT "mips64r6"
 #else
 #define MULTILIB_ISA_DEFAULT "mips1"
 #endif
@@ -727,11 +703,13 @@ struct mips_cpu_info {
        |march=34k*|march=74k*|march=m14k*|march=1004k*: -mips32r2} \
      %{march=mips32r3: -mips32r3} \
      %{march=mips32r5|march=p5600: -mips32r5} \
+     %{march=mips32r6: -mips32r6} \
      %{march=mips64|march=5k*|march=20k*|march=sb1*|march=sr71000 \
        |march=xlr: -mips64} \
      %{march=mips64r2|march=loongson3a|march=octeon|march=xlp: -mips64r2} \
      %{march=mips64r3: -mips64r3} \
      %{march=mips64r5: -mips64r5} \
+     %{march=mips64r6: -mips64r6} \
      %{!march=*: -" MULTILIB_ISA_DEFAULT "}}"
 
 /* A spec that infers a -mhard-float or -msoft-float setting from an
@@ -754,8 +732,8 @@ struct mips_cpu_info {
 /* Infer a -msynci setting from a -mips argument, on the assumption that
    -msynci is desired where possible.  */
 #define MIPS_ISA_SYNCI_SPEC \
-  "%{msynci|mno-synci:;:%{mips32r2|mips32r3|mips32r5|mips64r2|mips64r3 \
-                          |mips64r5:-msynci;:-mno-synci}}"
+  "%{msynci|mno-synci:;:%{mips32r2|mips32r3|mips32r5|mips32r6|mips64r2 \
+			  |mips64r3|mips64r5|mips64r6:-msynci;:-mno-synci}}"
 
 #if (MIPS_ABI_DEFAULT == ABI_O64 \
      || MIPS_ABI_DEFAULT == ABI_N32 \
@@ -833,12 +811,15 @@ struct mips_cpu_info {
 				 || ISA_MIPS64				\
 				 || ISA_MIPS64R2			\
 				 || ISA_MIPS64R3			\
-				 || ISA_MIPS64R5)
+				 || ISA_MIPS64R5			\
+				 || ISA_MIPS64R6)
+
+#define ISA_HAS_JR		(mips_isa_rev <= 5)
 
 /* ISA has branch likely instructions (e.g. mips2).  */
 /* Disable branchlikely for tx39 until compare rewrite.  They haven't
    been generated up to this point.  */
-#define ISA_HAS_BRANCHLIKELY	(!ISA_MIPS1)
+#define ISA_HAS_BRANCHLIKELY	(!ISA_MIPS1 && mips_isa_rev <= 5)
 
 /* ISA has a three-operand multiplication instruction (usually spelt "mul").  */
 #define ISA_HAS_MUL3		((TARGET_MIPS3900                       \
@@ -848,7 +829,8 @@ struct mips_cpu_info {
 				  || TARGET_MIPS7000			\
 				  || TARGET_MIPS9000			\
 				  || TARGET_MAD				\
-				  || mips_isa_rev >= 1)			\
+				  || (mips_isa_rev >= 1			\
+				      && mips_isa_rev <= 5))		\
 				 && !TARGET_MIPS16)
 
 /* ISA has a three-operand multiplication instruction.  */
@@ -857,29 +839,40 @@ struct mips_cpu_info {
 				 && !TARGET_MIPS16)
 
 /* ISA supports instructions DMULT and DMULTU. */
-#define ISA_HAS_DMULT		(TARGET_64BIT && !TARGET_MIPS5900)
+#define ISA_HAS_DMULT		(TARGET_64BIT				\
+				 && !TARGET_MIPS5900			\
+				 && mips_isa_rev <= 5)
 
 /* ISA supports instructions MULT and MULTU.
    This is always true, but the macro is needed for ISA_HAS_<D>MULT
    in mips.md.  */
-#define ISA_HAS_MULT		(1)
+#define ISA_HAS_MULT		(mips_isa_rev <= 5)
+
+#define ISA_HAS_R6MUL		(mips_isa_rev >= 6)
+#define ISA_HAS_R6DMUL		(TARGET_64BIT && mips_isa_rev >= 6)
 
 /* ISA supports instructions DDIV and DDIVU. */
-#define ISA_HAS_DDIV		(TARGET_64BIT && !TARGET_MIPS5900)
+#define ISA_HAS_DDIV		(TARGET_64BIT				\
+				 && !TARGET_MIPS5900			\
+				 && mips_isa_rev <= 5)
 
 /* ISA supports instructions DIV and DIVU.
    This is always true, but the macro is needed for ISA_HAS_<D>DIV
    in mips.md.  */
-#define ISA_HAS_DIV		(1)
+#define ISA_HAS_DIV		(mips_isa_rev <= 5)
 
 #define ISA_HAS_DIV3		((TARGET_LOONGSON_2EF			\
 				  || TARGET_LOONGSON_3A)		\
 				 && !TARGET_MIPS16)
 
+#define ISA_HAS_R6DIV		(mips_isa_rev >= 6)
+#define ISA_HAS_R6DDIV		(TARGET_64BIT && mips_isa_rev >= 6)
+
 /* ISA has the floating-point conditional move instructions introduced
    in mips4.  */
 #define ISA_HAS_FP_CONDMOVE	((ISA_MIPS4				\
-				  || mips_isa_rev >= 1)			\
+				  || (mips_isa_rev >= 1			\
+				      && mips_isa_rev <= 5))		\
 				 && !TARGET_MIPS5500			\
 				 && !TARGET_MIPS16)
 
@@ -896,7 +889,15 @@ struct mips_cpu_info {
 
 /* ISA has the mips4 FP condition code instructions: FP-compare to CC,
    branch on CC, and move (both FP and non-FP) on CC.  */
-#define ISA_HAS_8CC		(ISA_MIPS4 || mips_isa_rev >= 1)
+#define ISA_HAS_8CC		(ISA_MIPS4				\
+				 || (mips_isa_rev >= 1			\
+				     && mips_isa_rev <= 5))
+
+/* ISA has the FP condition code instructions that store the flag in an
+   FP register.  */
+#define ISA_HAS_CCF		(mips_isa_rev >= 6)
+
+#define ISA_HAS_SEL		(mips_isa_rev >= 6)
 
 /* This is a catch all for other mips4 instructions: indexed load, the
    FP madd and msub instructions, and the FP recip and recip sqrt
@@ -904,7 +905,8 @@ struct mips_cpu_info {
    ISA_HAS_* macros.  */
 #define ISA_HAS_FP4		((ISA_MIPS4				\
 				  || ISA_MIPS64				\
-				  || mips_isa_rev >= 2)			\
+				  || (mips_isa_rev >= 2			\
+				      && mips_isa_rev <= 5))		\
 				 && !TARGET_MIPS16)
 
 /* ISA has floating-point indexed load and store instructions
@@ -912,14 +914,22 @@ struct mips_cpu_info {
 #define ISA_HAS_LXC1_SXC1	ISA_HAS_FP4
 
 /* ISA has paired-single instructions.  */
-#define ISA_HAS_PAIRED_SINGLE	(ISA_MIPS64 || mips_isa_rev >= 2)
+#define ISA_HAS_PAIRED_SINGLE	(ISA_MIPS64				\
+				 || (mips_isa_rev >= 2			\
+				     && mips_isa_rev <= 5))
 
 /* ISA has conditional trap instructions.  */
 #define ISA_HAS_COND_TRAP	(!ISA_MIPS1				\
 				 && !TARGET_MIPS16)
 
+/* ISA has conditional trap with immediate instructions.  */
+#define ISA_HAS_COND_TRAPI	(!ISA_MIPS1				\
+				 && mips_isa_rev <= 5			\
+				 && !TARGET_MIPS16)
+
 /* ISA has integer multiply-accumulate instructions, madd and msub.  */
-#define ISA_HAS_MADD_MSUB	(mips_isa_rev >= 1)
+#define ISA_HAS_MADD_MSUB	(mips_isa_rev >= 1			\
+				 && mips_isa_rev <= 5)
 
 /* Integer multiply-accumulate instructions should be generated.  */
 #define GENERATE_MADD_MSUB	(TARGET_IMADD && !TARGET_MIPS16)
@@ -927,6 +937,9 @@ struct mips_cpu_info {
 /* ISA has floating-point madd and msub instructions 'd = a * b [+-] c'.  */
 #define ISA_HAS_FP_MADD4_MSUB4  ISA_HAS_FP4
 
+/* ISA has floating-point maddf and msubf instructions 'd = d [+-] a * b'.  */
+#define ISA_HAS_FP_MADDF_MSUBF  (mips_isa_rev >= 6)
+
 /* ISA has floating-point madd and msub instructions 'c = a * b [+-] c'.  */
 #define ISA_HAS_FP_MADD3_MSUB3  TARGET_LOONGSON_2EF
 
@@ -948,10 +961,19 @@ struct mips_cpu_info {
 				       || ((TARGET_FLOAT64		\
 					    || mips_isa_rev >= 2)	\
 					   && (MODE) == DFmode)))	\
+				  || (((MODE) == SFmode			\
+				       || (MODE) == DFmode)		\
+				      && (mips_isa_rev >= 6))		\
 				  || (TARGET_SB1			\
 				      && (MODE) == V2SFmode))		\
 				 && !TARGET_MIPS16)
 
+#define ISA_HAS_LWL_LWR		(mips_isa_rev <= 5)
+
+#define ISA_HAS_NANLEGACY	(mips_isa_rev <= 5)
+
+#define ISA_HAS_NAN2008		(mips_isa_rev >= 2)
+
 /* ISA has count leading zeroes/ones instruction (not implemented).  */
 #define ISA_HAS_CLZ_CLO		(mips_isa_rev >= 1 && !TARGET_MIPS16)
 
@@ -1009,6 +1031,9 @@ struct mips_cpu_info {
 				  || mips_isa_rev >= 1)			\
 				 && !TARGET_MIPS16)
 
+/* ISA has data prefetch with limited 9-bit displacement.  */
+#define ISA_HAS_PREFETCH_9BIT	(mips_isa_rev >= 6)
+
 /* ISA has data indexed prefetch instructions.  This controls use of
    'prefx', along with TARGET_HARD_FLOAT and TARGET_DOUBLE_FLOAT.
    (prefx is a cop1x instruction, so can only be used if FP is
@@ -1044,10 +1069,14 @@ struct mips_cpu_info {
 				 && TARGET_64BIT)
 
 /* The DSP ASE is available.  */
-#define ISA_HAS_DSP		(TARGET_DSP && !TARGET_MIPS16)
+#define ISA_HAS_DSP		(TARGET_DSP				\
+				 && mips_isa_rev <= 5			\
+				 && !TARGET_MIPS16)
 
 /* Revision 2 of the DSP ASE is available.  */
-#define ISA_HAS_DSPR2		(TARGET_DSPR2 && !TARGET_MIPS16)
+#define ISA_HAS_DSPR2		(TARGET_DSPR2				\
+				 && mips_isa_rev <= 5			\
+				 && !TARGET_MIPS16)
 
 /* True if the result of a load is not available to the next instruction.
    A nop will then be needed between instructions like "lw $4,..."
@@ -2086,6 +2115,7 @@ enum reg_class
 #define SMALL_INT_UNSIGNED(X) SMALL_OPERAND_UNSIGNED (INTVAL (X))
 #define LUI_INT(X) LUI_OPERAND (INTVAL (X))
 #define UMIPS_12BIT_OFFSET_P(OFFSET) (IN_RANGE (OFFSET, -2048, 2047))
+#define MIPSR6_9BIT_OFFSET_P(OFFSET) (IN_RANGE (OFFSET, -256, 255))
 
 /* The HI and LO registers can only be reloaded via the general
    registers.  Condition code registers can only be loaded to the
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 9912ddc..afd170b 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -66,6 +66,8 @@ (define_enum "processor" [
   xlr
   xlp
   p5600
+  w32
+  w64
 ])
 
 (define_c_enum "unspec" [
@@ -327,6 +329,7 @@ (define_attr "accum_in" "none,0,1,2,3,4,5" (const_string "none"))
 ;; imadd	integer multiply-add
 ;; idiv		integer divide 2 operands
 ;; idiv3	integer divide 3 operands
+;; idiv3nc	integer divide 3 operands without clobbering HI/LO
 ;; move		integer register move ({,D}ADD{,U} with rt = 0)
 ;; fmove	floating point register move
 ;; fadd		floating point add/subtract
@@ -359,9 +362,9 @@ (define_attr "accum_in" "none,0,1,2,3,4,5" (const_string "none"))
 (define_attr "type"
   "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore,
    prefetch,prefetchx,condmove,mtc,mfc,mthi,mtlo,mfhi,mflo,const,arith,logical,
-   shift,slt,signext,clz,pop,trap,imul,imul3,imul3nc,imadd,idiv,idiv3,move,
-   fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt,
-   frsqrt,frsqrt1,frsqrt2,dspmac,dspmacsat,accext,accmod,dspalu,dspalusat,
+   shift,slt,signext,clz,pop,trap,imul,imul3,imul3nc,imadd,idiv,idiv3,idiv3nc,
+   move,fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,
+   fsqrt,frsqrt,frsqrt1,frsqrt2,dspmac,dspmacsat,accext,accmod,dspalu,dspalusat,
    multi,atomic,syncloop,nop,ghost,multimem"
   (cond [(eq_attr "jal" "!unset") (const_string "call")
 	 (eq_attr "got" "load") (const_string "load")
@@ -759,6 +762,11 @@ (define_mode_iterator MOVECC [SI (DI "TARGET_64BIT")
 				   && !TARGET_LOONGSON_2EF
 				   && !TARGET_MIPS5900")])
 
+;; This mode iterator allows :FPCC to be used anywhere that an FP condition
+;; is needed.
+(define_mode_iterator FPCC [(CC "!ISA_HAS_CCF")
+			    (CCF "ISA_HAS_CCF")])
+
 ;; 32-bit integer moves for which we provide move patterns.
 (define_mode_iterator IMOVE32
   [SI
@@ -848,7 +856,7 @@ (define_mode_attr si8_di5 [(SI "8") (DI "5")])
 
 ;; This attribute gives the best constraint to use for registers of
 ;; a given mode.
-(define_mode_attr reg [(SI "d") (DI "d") (CC "z")])
+(define_mode_attr reg [(SI "d") (DI "d") (CC "z") (CCF "f")])
 
 ;; This attribute gives the format suffix for floating-point operations.
 (define_mode_attr fmt [(SF "s") (DF "d") (V2SF "ps")])
@@ -888,6 +896,9 @@ (define_mode_attr divide_condition
 (define_mode_attr sqrt_condition
   [(SF "!ISA_MIPS1") (DF "!ISA_MIPS1") (V2SF "TARGET_SB1")])
 
+;; This attribute provides the correct nmemonic for each FP condition mode.
+(define_mode_attr fpcmp [(CC "c") (CCF "cmp")])
+
 ;; This code iterator allows signed and unsigned widening multiplications
 ;; to use the same template.
 (define_code_iterator any_extend [sign_extend zero_extend])
@@ -910,7 +921,10 @@ (define_code_iterator any_mod [mod umod])
 
 ;; This code iterator allows all native floating-point comparisons to be
 ;; generated from the same template.
-(define_code_iterator fcond [unordered uneq unlt unle eq lt le])
+(define_code_iterator fcond [unordered uneq unlt unle eq lt le
+			     (ordered "ISA_HAS_CCF")
+			     (ltgt "ISA_HAS_CCF")
+			     (ne "ISA_HAS_CCF")])
 
 ;; This code iterator is used for comparisons that can be implemented
 ;; by swapping the operands.
@@ -983,7 +997,10 @@ (define_code_attr fcond [(unordered "un")
 			 (unle "ule")
 			 (eq "eq")
 			 (lt "lt")
-			 (le "le")])
+			 (le "le")
+			 (ordered "or")
+			 (ltgt "ne")
+			 (ne "une")])
 
 ;; Similar, but for swapped conditions.
 (define_code_attr swapped_fcond [(ge "le")
@@ -997,6 +1014,10 @@ (define_code_attr bbv [(eq "0") (ne "1")])
 
 ;; This is the inverse value of bbv.
 (define_code_attr bbinv [(eq "1") (ne "0")])
+
+;; The sel nmemonic to use depending on the condition test.
+(define_code_attr sel [(eq "seleqz") (ne "selnez")])
+(define_code_attr selinv [(eq "selnez") (ne "seleqz")])
 

 ;; .........................
 ;;
@@ -1105,16 +1126,25 @@ (define_expand "ctrap<mode>4"
 			    [(match_operand:GPR 1 "reg_or_0_operand")
 			     (match_operand:GPR 2 "arith_operand")])
 	    (match_operand 3 "const_0_operand"))]
-  "ISA_HAS_COND_TRAP"
+  "ISA_HAS_COND_TRAPI || ISA_HAS_COND_TRAP"
 {
   mips_expand_conditional_trap (operands[0]);
   DONE;
 })
 
+(define_insn "*conditional_trapi<mode>"
+  [(trap_if (match_operator:GPR 0 "trap_comparison_operator"
+			[(match_operand:GPR 1 "reg_or_0_operand" "dJ")
+			 (match_operand:GPR 2 "const_arith_operand" "I")])
+	    (const_int 0))]
+  "ISA_HAS_COND_TRAPI"
+  "t%C0\t%z1,%2"
+  [(set_attr "type" "trap")])
+
 (define_insn "*conditional_trap<mode>"
   [(trap_if (match_operator:GPR 0 "trap_comparison_operator"
 				[(match_operand:GPR 1 "reg_or_0_operand" "dJ")
-				 (match_operand:GPR 2 "arith_operand" "dI")])
+				 (match_operand:GPR 2 "register_operand" "d")])
 	    (const_int 0))]
   "ISA_HAS_COND_TRAP"
   "t%C0\t%z1,%2"
@@ -1484,13 +1514,13 @@ (define_expand "mul<mode>3"
   [(set (match_operand:GPR 0 "register_operand")
 	(mult:GPR (match_operand:GPR 1 "register_operand")
 		  (match_operand:GPR 2 "register_operand")))]
-  "ISA_HAS_<D>MULT"
+  "ISA_HAS_<D>MULT || ISA_HAS_R6<D>MUL"
 {
   rtx lo;
 
-  if (TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A)
-    emit_insn (gen_mul<mode>3_mul3_loongson (operands[0], operands[1],
-                                             operands[2]));
+  if (TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A || ISA_HAS_R6<D>MUL)
+    emit_insn (gen_mul<mode>3_mul3_r6 (operands[0], operands[1],
+                                       operands[2]));
   else if (ISA_HAS_<D>MUL3)
     emit_insn (gen_mul<mode>3_mul3 (operands[0], operands[1], operands[2]));
   else if (TARGET_MIPS16)
@@ -1507,16 +1537,18 @@ (define_expand "mul<mode>3"
   DONE;
 })
 
-(define_insn "mul<mode>3_mul3_loongson"
+(define_insn "mul<mode>3_mul3_r6"
   [(set (match_operand:GPR 0 "register_operand" "=d")
         (mult:GPR (match_operand:GPR 1 "register_operand" "d")
                   (match_operand:GPR 2 "register_operand" "d")))]
-  "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A"
+  "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A || ISA_HAS_R6<D>MUL"
 {
   if (TARGET_LOONGSON_2EF)
     return "<d>multu.g\t%0,%1,%2";
-  else
+  else if (TARGET_LOONGSON_3A)
     return "gs<d>multu\t%0,%1,%2";
+  else
+    return "<d>mul\t%0,%1,%2";
 }
   [(set_attr "type" "imul3nc")
    (set_attr "mode" "<MODE>")])
@@ -1915,6 +1947,24 @@ (define_expand "<u>mulsidi3"
   DONE;
 })
 
+(define_expand "<u>mulsidi3_32bit_r6"
+  [(set (match_operand:DI 0 "register_operand")
+	(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
+		 (any_extend:DI (match_operand:SI 2 "register_operand"))))]
+  "!TARGET_64BIT && ISA_HAS_R6MUL"
+{
+  rtx dest = gen_reg_rtx (DImode);
+  rtx low = mips_subword (dest, 0);
+  rtx high = mips_subword (dest, 1);
+
+  emit_insn (gen_mulsi3_mul3_r6 (low, operands[1], operands[2]));
+  emit_insn (gen_<su>mulsi3_highpart_r6 (high, operands[1], operands[2]));
+
+  emit_move_insn (mips_subword (operands[0], 0), low);
+  emit_move_insn (mips_subword (operands[0], 1), high);
+  DONE;
+})
+
 (define_expand "<u>mulsidi3_32bit_mips16"
   [(set (match_operand:DI 0 "register_operand")
 	(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
@@ -1936,7 +1986,7 @@ (define_insn "<u>mulsidi3_32bit"
   [(set (match_operand:DI 0 "muldiv_target_operand" "=ka")
 	(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
 		 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
-  "!TARGET_64BIT && (!TARGET_FIX_R4000 || ISA_HAS_DSP)"
+  "!TARGET_64BIT && (!TARGET_FIX_R4000 || ISA_HAS_DSP) && ISA_HAS_MULT"
 {
   if (ISA_HAS_DSP_MULT)
     return "mult<u>\t%q0,%1,%2";
@@ -1951,7 +2001,7 @@ (define_insn "<u>mulsidi3_32bit_r4000"
 	(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
 		 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
    (clobber (match_scratch:DI 3 "=x"))]
-  "!TARGET_64BIT && TARGET_FIX_R4000 && !ISA_HAS_DSP"
+  "!TARGET_64BIT && TARGET_FIX_R4000 && !ISA_HAS_DSP && ISA_HAS_MULT"
   "mult<u>\t%1,%2\;mflo\t%L0\;mfhi\t%M0"
   [(set_attr "type" "imul")
    (set_attr "mode" "SI")
@@ -1963,7 +2013,8 @@ (define_insn_and_split "<u>mulsidi3_64bit"
 		 (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
    (clobber (match_scratch:TI 3 "=x"))
    (clobber (match_scratch:DI 4 "=d"))]
-  "TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DMUL3 && !TARGET_MIPS16"
+  "TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DMUL3
+   && !TARGET_MIPS16 && ISA_HAS_MULT"
   "#"
   "&& reload_completed"
   [(const_int 0)]
@@ -2046,6 +2097,15 @@ (define_insn "mulsidi3_64bit_dmul"
   [(set_attr "type" "imul3")
    (set_attr "mode" "DI")])
 
+(define_insn "mulsidi3_64bit_r6dmul"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
+		 (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
+  "ISA_HAS_R6DMUL"
+  "dmul\t%0,%1,%2"
+  [(set_attr "type" "imul3nc")
+   (set_attr "mode" "DI")])
+
 ;; Widening multiply with negation.
 (define_insn "*muls<u>_di"
   [(set (match_operand:DI 0 "muldiv_target_operand" "=x")
@@ -2103,12 +2163,27 @@ (define_expand "<su>mulsi3_highpart"
   else if (TARGET_MIPS16)
     emit_insn (gen_<su>mulsi3_highpart_split (operands[0], operands[1],
 					      operands[2]));
+  else if (ISA_HAS_R6MUL)
+    emit_insn (gen_<su>mulsi3_highpart_r6 (operands[0], operands[1],
+					   operands[2]));
   else
     emit_insn (gen_<su>mulsi3_highpart_internal (operands[0], operands[1],
 					         operands[2]));
   DONE;
 })
 
+(define_insn "<su>mulsi3_highpart_r6"
+  [(set (match_operand:SI 0 "register_operand" "=d")
+	(truncate:SI
+	 (lshiftrt:DI
+	  (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
+		   (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
+	  (const_int 32))))]
+  "ISA_HAS_R6MUL"
+  "muh<u>\t%0,%1,%2"
+  [(set_attr "type" "imul3nc")
+   (set_attr "mode" "SI")])
+
 (define_insn_and_split "<su>mulsi3_highpart_internal"
   [(set (match_operand:SI 0 "register_operand" "=d")
 	(truncate:SI
@@ -2117,7 +2192,7 @@ (define_insn_and_split "<su>mulsi3_highpart_internal"
 		   (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
 	  (const_int 32))))
    (clobber (match_scratch:SI 3 "=l"))]
-  "!ISA_HAS_MULHI && !TARGET_MIPS16"
+  "ISA_HAS_MULT && !ISA_HAS_MULHI && !TARGET_MIPS16"
   { return TARGET_FIX_R4000 ? "mult<u>\t%1,%2\n\tmfhi\t%0" : "#"; }
   "&& reload_completed && !TARGET_FIX_R4000"
   [(const_int 0)]
@@ -2195,17 +2270,34 @@ (define_expand "<su>muldi3_highpart"
 	  (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand"))
 		   (any_extend:TI (match_operand:DI 2 "register_operand")))
 	  (const_int 64))))]
-  "ISA_HAS_DMULT && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
+  "ISA_HAS_R6DMUL
+   || (ISA_HAS_DMULT
+       && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120))"
 {
   if (TARGET_MIPS16)
     emit_insn (gen_<su>muldi3_highpart_split (operands[0], operands[1],
 					      operands[2]));
+  else if (ISA_HAS_R6DMUL)
+    emit_insn (gen_<su>muldi3_highpart_r6 (operands[0], operands[1],
+					   operands[2]));
   else
     emit_insn (gen_<su>muldi3_highpart_internal (operands[0], operands[1],
 						 operands[2]));
   DONE;
 })
 
+(define_insn "<su>muldi3_highpart_r6"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(truncate:DI
+	 (lshiftrt:TI
+	  (mult:TI (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
+		   (any_extend:TI (match_operand:DI 2 "register_operand" "d")))
+	  (const_int 64))))]
+  "ISA_HAS_R6DMUL"
+  "dmuh<u>\t%0,%1,%2"
+  [(set_attr "type" "imul3nc")
+   (set_attr "mode" "DI")])
+
 (define_insn_and_split "<su>muldi3_highpart_internal"
   [(set (match_operand:DI 0 "register_operand" "=d")
 	(truncate:DI
@@ -2344,6 +2436,16 @@ (define_insn "*madd4<mode>"
    (set_attr "accum_in"	"3")
    (set_attr "mode" "<UNITMODE>")])
 
+(define_insn "*maddf<mode>"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+	(plus:ANYF (match_operand:ANYF 1 "register_operand" "0")
+		   (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
+			      (match_operand:ANYF 3 "register_operand" "f"))))]
+  "ISA_HAS_FP_MADDF_MSUBF"
+  "maddf.<fmt>\t%0,%2,%3"
+  [(set_attr "type" "fmadd")
+   (set_attr "mode" "<UNITMODE>")])
+
 (define_insn "*madd3<mode>"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
 	(plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
@@ -2366,6 +2468,16 @@ (define_insn "*msub4<mode>"
    (set_attr "accum_in"	"3")
    (set_attr "mode" "<UNITMODE>")])
 
+(define_insn "*msubf<mode>"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+	(minus:ANYF (match_operand:ANYF 1 "register_operand" "0")
+		    (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
+			       (match_operand:ANYF 3 "register_operand" "f"))))]
+  "ISA_HAS_FP_MADDF_MSUBF"
+  "msubf.<fmt>\t%0,%2,%3"
+  [(set_attr "type" "fmadd")
+   (set_attr "mode" "<UNITMODE>")])
+
 (define_insn "*msub3<mode>"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
 	(minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
@@ -2727,6 +2839,40 @@ (define_insn "<u>divmod<GPR:mode>4_hilo_<HILO:mode>"
   { return mips_output_division ("<GPR:d>div<u>\t%.,%1,%2", operands); }
   [(set_attr "type" "idiv")
    (set_attr "mode" "<GPR:MODE>")])
+
+;; Integer division and modulus.
+
+(define_insn "<u>div<mode>3"
+  [(set (match_operand:GPR 0 "register_operand" "=&d")
+	(any_div:GPR (match_operand:GPR 1 "register_operand" "d")
+		     (match_operand:GPR 2 "register_operand" "d")))]
+  "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A || ISA_HAS_R6<D>DIV"
+  {
+    if (TARGET_LOONGSON_2EF)
+      return mips_output_division ("<d>div<u>.g\t%0,%1,%2", operands);
+    else if (TARGET_LOONGSON_3A)
+      return mips_output_division ("gs<d>div<u>\t%0,%1,%2", operands);
+    else
+      return mips_output_division ("<d>div<u>\t%0,%1,%2", operands);
+  }
+  [(set_attr "type" "idiv3")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "<u>mod<mode>3"
+  [(set (match_operand:GPR 0 "register_operand" "=&d")
+	(any_mod:GPR (match_operand:GPR 1 "register_operand" "d")
+		     (match_operand:GPR 2 "register_operand" "d")))]
+  "TARGET_LOONGSON_2EF || TARGET_LOONGSON_3A || ISA_HAS_R6<D>DIV"
+  {
+    if (TARGET_LOONGSON_2EF)
+      return mips_output_division ("<d>mod<u>.g\t%0,%1,%2", operands);
+    else if (TARGET_LOONGSON_3A)
+      return mips_output_division ("gs<d>mod<u>\t%0,%1,%2", operands);
+    else
+      return mips_output_division ("<d>mod<u>\t%0,%1,%2", operands);
+  }
+  [(set_attr "type" "idiv3")
+   (set_attr "mode" "<MODE>")])
 

 ;;
 ;;  ....................
@@ -3872,7 +4018,7 @@ (define_expand "extvmisalign<mode>"
 	(sign_extract:GPR (match_operand:BLK 1 "memory_operand")
 			  (match_operand 2 "const_int_operand")
 			  (match_operand 3 "const_int_operand")))]
-  "!TARGET_MIPS16"
+  "ISA_HAS_LWL_LWR && !TARGET_MIPS16"
 {
   if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
 					 INTVAL (operands[2]),
@@ -3909,7 +4055,7 @@ (define_expand "extzvmisalign<mode>"
 	(zero_extract:GPR (match_operand:BLK 1 "memory_operand")
 			  (match_operand 2 "const_int_operand")
 			  (match_operand 3 "const_int_operand")))]
-  "!TARGET_MIPS16"
+  "ISA_HAS_LWL_LWR && !TARGET_MIPS16"
 {
   if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
 					 INTVAL (operands[2]),
@@ -3960,7 +4106,7 @@ (define_expand "insvmisalign<mode>"
 			  (match_operand 1 "const_int_operand")
 			  (match_operand 2 "const_int_operand"))
 	(match_operand:GPR 3 "reg_or_0_operand"))]
-  "!TARGET_MIPS16"
+  "ISA_HAS_LWL_LWR && !TARGET_MIPS16"
 {
   if (mips_expand_ins_as_unaligned_store (operands[0], operands[3],
 					  INTVAL (operands[1]),
@@ -4713,6 +4859,13 @@ (define_expand "movsf"
     DONE;
 })
 
+(define_insn "movccf"
+  [(set (match_operand:CCF 0 "nonimmediate_operand" "=f,f,m")
+	(match_operand:CCF 1 "nonimmediate_operand" "f,m,f"))]
+  "ISA_HAS_CCF"
+  { return mips_output_move (operands[0], operands[1]); }
+  [(set_attr "move_type" "fmove,fpload,fpstore")])
+
 (define_insn "*movsf_hardfloat"
   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
 	(match_operand:SF 1 "move_operand" "f,G,m,f,G,*d,*f,*G*d,*m,*d"))]
@@ -5231,7 +5384,7 @@ (define_insn "clear_hazard_<mode>"
 (define_insn "mips_cache"
   [(set (mem:BLK (scratch))
 	(unspec:BLK [(match_operand:SI 0 "const_int_operand")
-		     (match_operand:QI 1 "address_operand" "p")]
+		     (match_operand:QI 1 "address_operand" "ZD")]
 		    UNSPEC_MIPS_CACHE))]
   "ISA_HAS_CACHE"
   "cache\t%X0,%a1")
@@ -5508,11 +5661,11 @@ (define_insn "dshd"
 
 ;; Conditional branches on floating-point equality tests.
 
-(define_insn "*branch_fp"
+(define_insn "*branch_fp_<mode>"
   [(set (pc)
         (if_then_else
          (match_operator 1 "equality_operator"
-                         [(match_operand:CC 2 "register_operand" "z")
+                         [(match_operand:FPCC 2 "register_operand" "<reg>")
 			  (const_int 0)])
          (label_ref (match_operand 0 "" ""))
          (pc)))]
@@ -5524,11 +5677,11 @@ (define_insn "*branch_fp"
 }
   [(set_attr "type" "branch")])
 
-(define_insn "*branch_fp_inverted"
+(define_insn "*branch_fp_inverted_<mode>"
   [(set (pc)
         (if_then_else
          (match_operator 1 "equality_operator"
-                         [(match_operand:CC 2 "register_operand" "z")
+                         [(match_operand:FPCC 2 "register_operand" "<reg>")
 			  (const_int 0)])
          (pc)
          (label_ref (match_operand 0 "" ""))))]
@@ -5872,21 +6025,21 @@ (define_insn "*sle<u>_<GPR:mode><GPR2:mode>_mips16"
 ;;
 ;;  ....................
 
-(define_insn "s<code>_<mode>"
-  [(set (match_operand:CC 0 "register_operand" "=z")
-	(fcond:CC (match_operand:SCALARF 1 "register_operand" "f")
-		  (match_operand:SCALARF 2 "register_operand" "f")))]
+(define_insn "s<code>_<SCALARF:mode>_using_<FPCC:mode>"
+  [(set (match_operand:FPCC 0 "register_operand" "=<reg>")
+	(fcond:FPCC (match_operand:SCALARF 1 "register_operand" "f")
+		    (match_operand:SCALARF 2 "register_operand" "f")))]
   ""
-  "c.<fcond>.<fmt>\t%Z0%1,%2"
+  "<fpcmp>.<fcond>.<fmt>\t%Z0%1,%2"
   [(set_attr "type" "fcmp")
    (set_attr "mode" "FPSW")])
 
-(define_insn "s<code>_<mode>"
-  [(set (match_operand:CC 0 "register_operand" "=z")
-	(swapped_fcond:CC (match_operand:SCALARF 1 "register_operand" "f")
-		          (match_operand:SCALARF 2 "register_operand" "f")))]
+(define_insn "s<code>_<SCALARF:mode>_using_<FPCC:mode>"
+  [(set (match_operand:FPCC 0 "register_operand" "=<reg>")
+	(swapped_fcond:FPCC (match_operand:SCALARF 1 "register_operand" "f")
+		            (match_operand:SCALARF 2 "register_operand" "f")))]
   ""
-  "c.<swapped_fcond>.<fmt>\t%Z0%2,%1"
+  "<fpcmp>.<swapped_fcond>.<fmt>\t%Z0%2,%1"
   [(set_attr "type" "fcmp")
    (set_attr "mode" "FPSW")])
 

@@ -6906,6 +7059,41 @@ (define_insn "*mov<SCALARF:mode>_on_<MOVECC:mode>"
   [(set_attr "type" "condmove")
    (set_attr "mode" "<SCALARF:MODE>")])
 
+(define_insn "*sel<code><GPR:mode>_using_<GPR2:mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=d,d")
+	(if_then_else:GPR
+	 (equality_op:GPR2 (match_operand:GPR2 1 "register_operand" "d,d")
+		           (const_int 0))
+	 (match_operand:GPR 2 "reg_or_0_operand" "d,J")
+	 (match_operand:GPR 3 "reg_or_0_operand" "J,d")))]
+  "ISA_HAS_SEL
+   && (register_operand (operands[2], <GPR:MODE>mode)
+       ^ register_operand (operands[3], <GPR:MODE>mode))"
+  "@
+   <sel>\t%0,%2,%1
+   <selinv>\t%0,%3,%1"
+  [(set_attr "type" "condmove")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; sel.fmt copies the 3rd argument when the 1st is non-zero and the 2nd
+;; argument if the 1st is zero.  This means operand 2 and 3 are
+;; inverted in the instruction.
+
+(define_insn "*sel<mode>"
+  [(set (match_operand:SCALARF 0 "register_operand" "=f,f,f")
+	(if_then_else:SCALARF
+	 (ne:CCF (match_operand:CCF 1 "register_operand" "0,f,f")
+		 (const_int 0))
+	 (match_operand:SCALARF 2 "reg_or_0_operand" "f,G,f")
+	 (match_operand:SCALARF 3 "reg_or_0_operand" "f,f,G")))]
+  "ISA_HAS_SEL && ISA_HAS_CCF"
+  "@
+   sel.<fmt>\t%0,%3,%2
+   seleqz.<fmt>\t%0,%3,%1
+   selnez.<fmt>\t%0,%2,%1"
+  [(set_attr "type" "condmove")
+   (set_attr "mode" "<SCALARF:MODE>")])
+
 ;; These are the main define_expand's used to make conditional moves.
 
 (define_expand "mov<mode>cc"
@@ -6914,8 +7102,13 @@ (define_expand "mov<mode>cc"
 	(if_then_else:GPR (match_dup 5)
 			  (match_operand:GPR 2 "reg_or_0_operand")
 			  (match_operand:GPR 3 "reg_or_0_operand")))]
-  "ISA_HAS_CONDMOVE"
+  "ISA_HAS_CONDMOVE || ISA_HAS_SEL"
 {
+  if (ISA_HAS_SEL
+      && (GET_MODE (XEXP (operands[1], 0)) != SImode)
+      && (GET_MODE (XEXP (operands[1], 0)) != DImode))
+    FAIL;
+
   mips_expand_conditional_move (operands);
   DONE;
 })
@@ -6924,10 +7117,16 @@ (define_expand "mov<mode>cc"
   [(set (match_dup 4) (match_operand 1 "comparison_operator"))
    (set (match_operand:SCALARF 0 "register_operand")
 	(if_then_else:SCALARF (match_dup 5)
-			      (match_operand:SCALARF 2 "register_operand")
-			      (match_operand:SCALARF 3 "register_operand")))]
-  "ISA_HAS_FP_CONDMOVE"
-{
+			      (match_operand:SCALARF 2 "reg_or_0_operand")
+			      (match_operand:SCALARF 3 "reg_or_0_operand")))]
+  "ISA_HAS_FP_CONDMOVE
+   || (ISA_HAS_SEL && ISA_HAS_CCF)"
+{
+  if (ISA_HAS_SEL
+      && GET_MODE (XEXP (operands[1], 0)) != SFmode
+      && GET_MODE (XEXP (operands[1], 0)) != DFmode)
+    FAIL;
+
   mips_expand_conditional_move (operands);
   DONE;
 })
@@ -7042,7 +7241,12 @@ (define_insn "*tls_get_tp_<mode>_split"
   [(set (reg:P TLS_GET_TP_REGNUM)
 	(unspec:P [(const_int 0)] UNSPEC_TLS_GET_TP))]
   "HAVE_AS_TLS && !TARGET_MIPS16"
-  ".set\tpush\;.set\tmips32r2\t\;rdhwr\t$3,$29\;.set\tpop"
+  {
+    if (mips_isa_rev >= 2)
+      return "rdhwr\t$3,$29";
+
+    return ".set\tpush\;.set\tmips32r2\t\;rdhwr\t$3,$29\;.set\tpop";
+  }
   [(set_attr "type" "unknown")
    ; Since rdhwr always generates a trap for now, putting it in a delay
    ; slot would make the kernel's emulation of it much slower.
diff --git a/gcc/config/mips/netbsd.h b/gcc/config/mips/netbsd.h
index efa2886..ed41e0f 100644
--- a/gcc/config/mips/netbsd.h
+++ b/gcc/config/mips/netbsd.h
@@ -84,21 +84,13 @@ along with GCC; see the file COPYING3.  If not see
 	builtin_define ("__mips=3");				\
       else if (ISA_MIPS4)					\
 	builtin_define ("__mips=4");				\
-      else if (ISA_MIPS32)					\
-	{							\
-	  builtin_define ("__mips=32");				\
-	  builtin_define ("__mips_isa_rev=1");			\
-	}							\
-      else if (ISA_MIPS32R2)					\
-	{							\
-	  builtin_define ("__mips=32");				\
-	  builtin_define ("__mips_isa_rev=2");			\
-	}							\
-      else if (ISA_MIPS64)					\
-	{							\
-	  builtin_define ("__mips=64");				\
-	  builtin_define ("__mips_isa_rev=1");			\
-	}							\
+      else if (mips_isa >= 32 && mips_isa < 64)			\
+	builtin_define ("__mips=32");				\
+      else if (mips_isa >= 64)					\
+	builtin_define ("__mips=64");				\
+      if (mips_isa_rev > 0)					\
+        builtin_define_with_int_value ("__mips_isa_rev",	\
+                                       mips_isa_rev);		\
 								\
       if (TARGET_HARD_FLOAT)					\
 	builtin_define ("__mips_hard_float");			\
@@ -141,7 +133,8 @@ along with GCC; see the file COPYING3.  If not see
   "%{EL:-m elf32lmip} \
    %{EB:-m elf32bmip} \
    %(endian_spec) \
-   %{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips32r2} %{mips64} \
+   %{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips32r2} \
+   %{mips32r6} %{mips64} %{mips64r6} \
    %(netbsd_link_spec)"
 
 #define NETBSD_ENTRY_POINT "__start"
diff --git a/gcc/config/mips/t-isa3264 b/gcc/config/mips/t-isa3264
index 8fffdf8..8455745 100644
--- a/gcc/config/mips/t-isa3264
+++ b/gcc/config/mips/t-isa3264
@@ -22,10 +22,10 @@ ifneq ($(filter MIPS_ABI_DEFAULT=ABI_EABI,$(tm_defines)),)
 MULTILIB_OPTIONS = msoft-float EL/EB mips32/mips32r2/mips64/mips64r2
 MULTILIB_DIRNAMES = soft-float el eb mips32 mips32r2 mips64 mips64r2
 else
-MULTILIB_OPTIONS = msoft-float/mfp64 EL/EB mips32/mips32r2/mips64/mips64r2
-MULTILIB_DIRNAMES = soft-float fp64 el eb mips32 mips32r2 mips64 mips64r2
+MULTILIB_OPTIONS = msoft-float/mfp64 EL/EB mips32/mips32r2/mips32r6/mips64/mips64r2/mips64r6
+MULTILIB_DIRNAMES = soft-float fp64 el eb mips32 mips32r2 mips32r6 mips64 mips64r2 mips64r6
 ifneq ($(filter MIPS_ISA_DEFAULT=33,$(tm_defines)),)
-MULTILIB_EXCLUSIONS = mips32/mfp64 mips64/mfp64 mips64r2/mfp64
+MULTILIB_EXCLUSIONS = mips32/mfp64 mips64/mfp64 mips64r2/mfp64 mips32r6/mfp64 mips64r6/mfp64
 else
 MULTILIB_EXCLUSIONS = !mips32r2/mfp64
 endif
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 76d8a2f..c8076a8 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -772,7 +772,7 @@ Objective-C and Objective-C++ Dialects}.
 @emph{MIPS Options}
 @gccoptlist{-EL  -EB  -march=@var{arch}  -mtune=@var{arch} @gol
 -mips1  -mips2  -mips3  -mips4  -mips32  -mips32r2  -mips32r3  -mips32r5 @gol
--mips64  -mips64r2  -mips64r3  -mips64r5 @gol
+-mips32r6  -mips64  -mips64r2  -mips64r3  -mips64r5  -mips64r6 @gol
 -mips16  -mno-mips16  -mflip-mips16 @gol
 -minterlink-compressed -mno-interlink-compressed @gol
 -minterlink-mips16  -mno-interlink-mips16 @gol
@@ -17192,8 +17192,9 @@ Generate code that runs on @var{arch}, which can be the name of a
 generic MIPS ISA, or the name of a particular processor.
 The ISA names are:
 @samp{mips1}, @samp{mips2}, @samp{mips3}, @samp{mips4},
-@samp{mips32}, @samp{mips32r2}, @samp{mips32r3}, @samp{mips32r5}, 
-@samp{mips64}, @samp{mips64r2}, @samp{mips64r3} and @samp{mips64r5}.
+@samp{mips32}, @samp{mips32r2}, @samp{mips32r3}, @samp{mips32r5},
+@samp{mips32r6}, @samp{mips64}, @samp{mips64r2}, @samp{mips64r3},
+@samp{mips64r5} and @samp{mips64r6}.
 The processor names are:
 @samp{4kc}, @samp{4km}, @samp{4kp}, @samp{4ksc},
 @samp{4kec}, @samp{4kem}, @samp{4kep}, @samp{4ksd},
@@ -17300,6 +17301,10 @@ Equivalent to @option{-march=mips32r3}.
 @opindex mips32r5
 Equivalent to @option{-march=mips32r5}.
 
+@item -mips32r6
+@opindex mips32r6
+Equivalent to @option{-march=mips32r6}.
+
 @item -mips64
 @opindex mips64
 Equivalent to @option{-march=mips64}.
@@ -17316,6 +17321,10 @@ Equivalent to @option{-march=mips64r3}.
 @opindex mips64r5
 Equivalent to @option{-march=mips64r5}.
 
+@item -mips64r6
+@opindex mips64r6
+Equivalent to @option{-march=mips64r6}.
+
 @item -mips16
 @itemx -mno-mips16
 @opindex mips16
diff --git a/libgcc/config.host b/libgcc/config.host
index 5f13a9f..5631138 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -828,8 +828,10 @@ mips*-sde-elf*)
 	;;
 mipsisa32-*-elf* | mipsisa32el-*-elf* | \
 mipsisa32r2-*-elf* | mipsisa32r2el-*-elf* | \
+mipsisa32r6-*-elf* | mipsisa32r6el-*-elf* | \
 mipsisa64-*-elf* | mipsisa64el-*-elf* | \
-mipsisa64r2-*-elf* | mipsisa64r2el-*-elf*)
+mipsisa64r2-*-elf* | mipsisa64r2el-*-elf* | \
+mipsisa64r6-*-elf* | mipsisa64r6el-*-elf*)
 	tmake_file="$tmake_file mips/t-elf mips/t-crtstuff mips/t-mips16"
 	extra_parts="$extra_parts crti.o crtn.o"
 	;;
diff --git a/libgcc/config/mips/mips16.S b/libgcc/config/mips/mips16.S
index 6a43a98..2c3f74a 100644
--- a/libgcc/config/mips/mips16.S
+++ b/libgcc/config/mips/mips16.S
@@ -21,7 +21,7 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
-#ifdef __mips_micromips
+#if defined(__mips_micromips) || __mips_isa_rev >= 6
   /* DO NOTHING */
 #else
 
-- 
1.7.1



More information about the Gcc-patches mailing list