public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCHv2,MIPS 1/2] MIPS64r6 support
@ 2014-11-14 23:29 Matthew Fortune
  2014-12-12 21:49 ` Moore, Catherine
  0 siblings, 1 reply; 4+ messages in thread
From: Matthew Fortune @ 2014-11-14 23:29 UTC (permalink / raw)
  To: 'gcc-patches@gcc.gnu.org' (gcc-patches@gcc.gnu.org)
  Cc: Moore, Catherine (Catherine_Moore@mentor.com),
	Rich Fuhler, Steve Ellcey, Richard Sandiford

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

Now that MIPS o32 FPXX ABI extensions are in place I am refreshing the
MIPS32R6/MIPS64R6 patch.

All previous comments have been addressed and the interactions between
FPXX and R6 have been accounted for.

I have left memcpy inlining disabled although I do have a patch which
will enable a very basic version of that for R6.  The DSP ASE is
marked as unavailable for now in order to separate out at least some
changes from this initial patch.

To handle some of the unusual restrictions we now have in the testsuite,
I have invented what might be called a 'ghost' option.  A ghost option
works much like (-mips16) and (-mmicromips) where the brackets mean:
Prepare an environment where this option could be added but do not add
it. A ghost option does the same thing but does not actually represent
a compiler option it is a feature which the ISA selection code can
act upon to increase or decrease the ISA level according to the
availability of the required feature. (I would like to remove all the
isa/isa_rev handling code at some point and switch to this kind of
mechanism throughout as I think it is quite tidy)

There are some test failures which I haven't been able to find a good
solution for but they are spurious failures anyway. The issue is that
the loongson vector extension tests (loongson*.c) have to be built
using the loongson-2f architecture. These tests include stdint.h
by virtue of including loongson.h and in turn means that they end up
including the 'stubs-<abi>.h' file from glibc headers. Since loongson
only supports nan1985 they need the stubs-o32_hard.h header to be
present but because a mipsr6 build of the toolchain only has nan2008
support then only stubs-o32_hard_2008.h exists. Likewise for n32/n64.
The only real option is to xfail the test but I haven't figured out a
neat way to do that yet as it needs to depend on the effective target.
Since these failures only occur when regtesting a mipsr6 configuration
I think they can be dealt with in a follow up patch.

I do have some more test configurations to run through since rebasing
this work but mips32r2, mips64r2, mips32r6, mips64r6 show no regressions
for mips*-linux-gnu.

Thanks,
Matthew 

gcc/

	* config.gcc: Add mipsisa64r6 and mipsisa32r6 cpu support.
	* config/mips/constraints.md (ZD): Add r6 restrictions.
	* config/mips/gnu-user.h (DRIVER_SELF_SPECS): Add MIPS_ISA_LEVEL_SPEC.
	* config/mips/loongson.md
	(<u>div<mode>3, <u>mod<mode>3): 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
	(mips_9bit_offset_address_p): New prototype.
	* config/mips/mips-tables.opt: Regenerate.
	* config/mips/mips.c (MIPS_JR): Use JALR $, <reg> for R6.
	(mips_rtx_cost_data): Add pseudo-processors W32 and W64.
	(mips_9bit_offset_address_p): New function.
	(mips_rtx_costs): Account for R6 multiply and FMA instructions.
	(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 callee-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 multiply instructions.
	(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 multiply instructions.
	* config/mips/mips.h (ISA_MIPS32R6, ISA_MIPS64R6): Define.
	(TARGET_CPU_CPP_BUILTINS): Rework for mips32/mips64.
	(ISA_HAS_JR): New macro.
	(ISA_HAS_HILO): 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_IEEE_754_LEGACY): Likewise.
	(ISA_HAS_IEEE_754_2008): Likewise.
	(ISA_HAS_PREFETCH_9BIT): Likewise.
	(MIPSR6_9BIT_OFFSET_P): New macro.
	(BASE_DRIVER_SELF_SPECS): Use MIPS_ISA_DRIVER_SELF_SPECS.
	(DRIVER_SELF_SPECS): Use MIPS_ISA_LEVEL_SPEC.
	(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.
	* config/mips/mips.md (processor): Add w32 and w64.
	(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_trap_reg<mode>): New define_insn.
	(*conditional_trap<mode>): Update condition.
	(mul<mode>3): Expand R6 multiply instructions.
	(<su>mulsi3_highpart): Likewise.
	(<su>muldi3_highpart): Likewise.
	(mul<mode>3_mul3_loongson): Rename...
	(mul<mode>3_mul3_hilo): 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.
	(fma<mode>4): 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.
	(mips_cache): Account for R6 displacement field sizes.
	(*branch_fp): Rename...
	(*branch_fp_<mode>): To this.  Add CCFmode support.
	(*branch_fp_inverted): Rename...
	(*branch_fp_inverted_<mode>): To this.  Add CCFmode 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
	CCFmode 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.
	* doc/md.texi: Update comment for ZD constraint.

libgcc/

	* config.host: Support mipsisa32r6 and mipsisa64r6.
	* config/mips/mips16.S: Do not build for R6.

gcc/testsuite/

	* gcc.dg/torture/mips-hilo-2.c: Unconditionally pass for R6 onwards.
	* gcc.dg/torture/pr19683-1.c: Likewise.
	* gcc.target/mips/branch-cost-2.c: Require MOVN.
	* gcc.target/mips/movcc-1.c: Likewise.
	* gcc.target/mips/movcc-2.c: Likewise.
	* gcc.target/mips/movcc-3.c: Likewise.
	* gcc.target/mips/call-saved-4.c: Require LDC.
	* gcc.target/mips/dmult-1.c: Require R5 or earlier.
	* gcc.target/mips/fpcmp-1.c: Likewise.
	* gcc.target/mips/fpcmp-2.c: Likewise.
	* gcc.target/mips/neg-abs-2.c: Likewise.
	* gcc.target/mips/timode-1.c: Likewise.
	* gcc.target/mips/unaligned-1.c: Likewise.
	* gcc.target/mips/madd-3.c: Require MADD.
	* gcc.target/mips/madd-9.c: Likewise.
	* gcc.target/mips/maddu-3.c: Likewise.
	* gcc.target/mips/msub-3.c: Likewise.
	* gcc.target/mips/msubu-3.c: Likewise.
	* gcc.target/mips/mult-1.c: Require INS and not DMUL.
	* gcc.target/mips/mips-ps-type-2.c: Require MADD.PS.
	* gcc.target/mips/mips.exp (mips_option_groups): Add ins, dmul, ldc,
	movn, madd, maddps.
	(mips-dg-options): INS available from R2.  LDC available from MIPS II,
	DMUL is present in octeon.  Describe all features removed from R6.

[-- Attachment #2: 0001-Basic-MIPSr6-support.patch --]
[-- Type: application/octet-stream, Size: 114222 bytes --]

From f1c0e3461c7f0a1c2fcc53af8dc9bdbc53f2c046 Mon Sep 17 00:00:00 2001
From: Matthew Fortune <matthew.fortune@imgtec.com>
Date: Sat, 7 Jun 2014 23:37:32 +0100
Subject: [PATCH 1/3] Basic MIPSr6 support

gcc/

	* config.gcc: Add mipsisa64r6 and mipsisa32r6 cpu support.
	* config/mips/constraints.md (ZD): Add r6 restrictions.
	* config/mips/gnu-user.h (DRIVER_SELF_SPECS): Add MIPS_ISA_LEVEL_SPEC.
	* config/mips/loongson.md
	(<u>div<mode>3, <u>mod<mode>3): 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
	(mips_9bit_offset_address_p): New prototype.
	* config/mips/mips-tables.opt: Regenerate.
	* config/mips/mips.c (MIPS_JR): Use JALR $, <reg> for R6.
	(mips_rtx_cost_data): Add pseudo-processors W32 and W64.
	(mips_9bit_offset_address_p): New function.
	(mips_rtx_costs): Account for R6 multiply and FMA instructions.
	(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 callee-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 multiply instructions.
	(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 multiply instructions.
	* config/mips/mips.h (ISA_MIPS32R6, ISA_MIPS64R6): Define.
	(TARGET_CPU_CPP_BUILTINS): Rework for mips32/mips64.
	(ISA_HAS_JR): New macro.
	(ISA_HAS_HILO): 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_IEEE_754_LEGACY): Likewise.
	(ISA_HAS_IEEE_754_2008): Likewise.
	(ISA_HAS_PREFETCH_9BIT): Likewise.
	(MIPSR6_9BIT_OFFSET_P): New macro.
	(BASE_DRIVER_SELF_SPECS): Use MIPS_ISA_DRIVER_SELF_SPECS.
	(DRIVER_SELF_SPECS): Use MIPS_ISA_LEVEL_SPEC.
	(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.
	* config/mips/mips.md (processor): Add w32 and w64.
	(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_trap_reg<mode>): New define_insn.
	(*conditional_trap<mode>): Update condition.
	(mul<mode>3): Expand R6 multiply instructions.
	(<su>mulsi3_highpart): Likewise.
	(<su>muldi3_highpart): Likewise.
	(mul<mode>3_mul3_loongson): Rename...
	(mul<mode>3_mul3_hilo): 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.
	(fma<mode>4): 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.
	(mips_cache): Account for R6 displacement field sizes.
	(*branch_fp): Rename...
	(*branch_fp_<mode>): To this.  Add CCFmode support.
	(*branch_fp_inverted): Rename...
	(*branch_fp_inverted_<mode>): To this.  Add CCFmode 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
	CCFmode 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.
	* doc/md.texi: Update comment for ZD constraint.

libgcc/

	* config.host: Support mipsisa32r6 and mipsisa64r6.
	* config/mips/mips16.S: Do not build for R6.

gcc/testsuite/

	* gcc.dg/torture/mips-hilo-2.c: Unconditionally pass for R6 onwards.
	* gcc.dg/torture/pr19683-1.c: Likewise.
	* gcc.target/mips/branch-cost-2.c: Require MOVN.
	* gcc.target/mips/movcc-1.c: Likewise.
	* gcc.target/mips/movcc-2.c: Likewise.
	* gcc.target/mips/movcc-3.c: Likewise.
	* gcc.target/mips/call-saved-4.c: Require LDC.
	* gcc.target/mips/dmult-1.c: Require R5 or earlier.
	* gcc.target/mips/fpcmp-1.c: Likewise.
	* gcc.target/mips/fpcmp-2.c: Likewise.
	* gcc.target/mips/neg-abs-2.c: Likewise.
	* gcc.target/mips/timode-1.c: Likewise.
	* gcc.target/mips/unaligned-1.c: Likewise.
	* gcc.target/mips/madd-3.c: Require MADD.
	* gcc.target/mips/madd-9.c: Likewise.
	* gcc.target/mips/maddu-3.c: Likewise.
	* gcc.target/mips/msub-3.c: Likewise.
	* gcc.target/mips/msubu-3.c: Likewise.
	* gcc.target/mips/mult-1.c: Require INS and not DMUL.
	* gcc.target/mips/mips-ps-type-2.c: Require MADD.PS.
	* gcc.target/mips/mips.exp (mips_option_groups): Add ins, dmul, ldc,
	movn, madd, maddps.
	(mips-dg-options): INS available from R2.  LDC available from MIPS II,
	DMUL is present in octeon.  Describe all features removed from R6.
---
 gcc/config.gcc                                 |  26 +-
 gcc/config/mips/constraints.md                 |  10 +-
 gcc/config/mips/gnu-user.h                     |   1 +
 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                | 406 +++++++++++++------------
 gcc/config/mips/mips.c                         | 267 ++++++++++++++--
 gcc/config/mips/mips.h                         | 139 ++++++---
 gcc/config/mips/mips.md                        | 280 ++++++++++++++---
 gcc/config/mips/netbsd.h                       |  25 +-
 gcc/config/mips/t-isa3264                      |   6 +-
 gcc/doc/invoke.texi                            |  15 +-
 gcc/doc/md.texi                                |   6 +-
 gcc/testsuite/gcc.dg/torture/mips-hilo-2.c     |   4 +
 gcc/testsuite/gcc.dg/torture/pr19683-1.c       |   4 +
 gcc/testsuite/gcc.target/mips/args-3.c         |   2 +-
 gcc/testsuite/gcc.target/mips/branch-cost-2.c  |   2 +-
 gcc/testsuite/gcc.target/mips/call-saved-4.c   |   2 +-
 gcc/testsuite/gcc.target/mips/dmult-1.c        |   2 +-
 gcc/testsuite/gcc.target/mips/fpcmp-1.c        |   2 +-
 gcc/testsuite/gcc.target/mips/fpcmp-2.c        |   2 +-
 gcc/testsuite/gcc.target/mips/madd-3.c         |   2 +-
 gcc/testsuite/gcc.target/mips/madd-9.c         |   2 +-
 gcc/testsuite/gcc.target/mips/maddu-3.c        |   2 +-
 gcc/testsuite/gcc.target/mips/mips-ps-type-2.c |   2 +-
 gcc/testsuite/gcc.target/mips/mips.exp         |  66 +++-
 gcc/testsuite/gcc.target/mips/movcc-1.c        |   2 +-
 gcc/testsuite/gcc.target/mips/movcc-2.c        |   2 +-
 gcc/testsuite/gcc.target/mips/movcc-3.c        |   2 +-
 gcc/testsuite/gcc.target/mips/msub-3.c         |   2 +-
 gcc/testsuite/gcc.target/mips/msubu-3.c        |   2 +-
 gcc/testsuite/gcc.target/mips/mult-1.c         |   2 +-
 gcc/testsuite/gcc.target/mips/neg-abs-2.c      |   2 +-
 gcc/testsuite/gcc.target/mips/timode-1.c       |   2 +-
 gcc/testsuite/gcc.target/mips/unaligned-1.c    |   2 +-
 libgcc/config.host                             |   4 +-
 libgcc/config/mips/mips16.S                    |   9 +-
 39 files changed, 940 insertions(+), 402 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 0af4a1a..73f0e63 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1955,6 +1955,9 @@ mips*-*-linux*)				# Linux MIPS, either endian.
 	tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/linux.h mips/linux-common.h"
 	extra_options="${extra_options} linux-android.opt"
 	case ${target} in
+		mipsisa32r6*)
+			default_mips_arch=mips32r6
+			;;
 		mipsisa32r2*)
 			default_mips_arch=mips32r2
 			;;
@@ -1973,6 +1976,11 @@ mips*-*-linux*)				# Linux MIPS, either endian.
 			target_cpu_default=MASK_SOFT_FLOAT_ABI
 			enable_mips_multilibs="yes"
 			;;
+		mipsisa64r6*-*-linux*)
+			default_mips_abi=n32
+			default_mips_arch=mips64r6
+			enable_mips_multilibs="yes"
+			;;
 		mipsisa64r2*-*-linux*)
 			default_mips_abi=n32
 			default_mips_arch=mips64r2
@@ -2015,12 +2023,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"
 	    ;;
@@ -2031,17 +2045,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"
 	    ;;
@@ -4167,8 +4189,10 @@ case ${target} in
 		    mips4)    tm_defines="$tm_defines MIPS_ISA_DEFAULT=4" ;;
 		    mips32)   tm_defines="$tm_defines MIPS_ISA_DEFAULT=32" ;;
 		    mips32r2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=33" ;;
+		    mips32r6) tm_defines="$tm_defines MIPS_ISA_DEFAULT=37" ;;
 		    mips64)   tm_defines="$tm_defines MIPS_ISA_DEFAULT=64" ;;
 		    mips64r2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=65" ;;
+		    mips64r6) tm_defines="$tm_defines MIPS_ISA_DEFAULT=69" ;;
 		esac
 		case ${default_mips_abi} in
 		    32)   tm_defines="$tm_defines MIPS_ABI_DEFAULT=ABI_32" ;;
diff --git a/gcc/config/mips/constraints.md b/gcc/config/mips/constraints.md
index fa33c30..816880c 100644
--- a/gcc/config/mips/constraints.md
+++ b/gcc/config/mips/constraints.md
@@ -321,13 +321,13 @@ (define_memory_constraint "ZC"
 	 (match_test "mips_address_insns (XEXP (op, 0), mode, false)"))))
 
 (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}."
+  "An address suitable for a @code{prefetch} instruction, or for any other
+   instruction with the same addressing mode as @code{prefetch}."
    (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 "mips_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/gnu-user.h b/gcc/config/mips/gnu-user.h
index 6c02054..6501a27 100644
--- a/gcc/config/mips/gnu-user.h
+++ b/gcc/config/mips/gnu-user.h
@@ -132,6 +132,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 
 #undef DRIVER_SELF_SPECS
 #define DRIVER_SELF_SPECS \
+  MIPS_ISA_LEVEL_SPEC,    \
   BASE_DRIVER_SELF_SPECS, \
   LINUX_DRIVER_SELF_SPECS
 
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 e2985b8..0d21783 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 adeda598..087403e 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -347,6 +347,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, machine_mode);
+extern bool mips_9bit_offset_address_p (rtx, machine_mode);
 extern bool lwsp_swsp_address_p (rtx, machine_mode);
 extern bool m16_based_address_p (rtx, machine_mode,
 			         int (*)(rtx_def*, machine_mode)); 
diff --git a/gcc/config/mips/mips-tables.opt b/gcc/config/mips/mips-tables.opt
index 99d2ed8..c8cdfa7 100644
--- a/gcc/config/mips/mips-tables.opt
+++ b/gcc/config/mips/mips-tables.opt
@@ -82,593 +82,605 @@ EnumValue
 Enum(mips_mips_opt_value) String(32r5) Value(7)
 
 EnumValue
-Enum(mips_arch_opt_value) String(mips64) Value(8) Canonical
+Enum(mips_arch_opt_value) String(mips32r6) Value(8) Canonical
 
 EnumValue
-Enum(mips_mips_opt_value) String(64) Value(8)
+Enum(mips_mips_opt_value) String(32r6) Value(8)
 
 EnumValue
-Enum(mips_arch_opt_value) String(mips64r2) Value(9) Canonical
+Enum(mips_arch_opt_value) String(mips64) Value(9) Canonical
 
 EnumValue
-Enum(mips_mips_opt_value) String(64r2) Value(9)
+Enum(mips_mips_opt_value) String(64) Value(9)
 
 EnumValue
-Enum(mips_arch_opt_value) String(mips64r3) Value(10) Canonical
+Enum(mips_arch_opt_value) String(mips64r2) Value(10) Canonical
 
 EnumValue
-Enum(mips_mips_opt_value) String(64r3) Value(10)
+Enum(mips_mips_opt_value) String(64r2) Value(10)
 
 EnumValue
-Enum(mips_arch_opt_value) String(mips64r5) Value(11) Canonical
+Enum(mips_arch_opt_value) String(mips64r3) Value(11) Canonical
 
 EnumValue
-Enum(mips_mips_opt_value) String(64r5) Value(11)
+Enum(mips_mips_opt_value) String(64r3) Value(11)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r3000) Value(12) Canonical
+Enum(mips_arch_opt_value) String(mips64r5) Value(12) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r3k) Value(12)
+Enum(mips_mips_opt_value) String(64r5) Value(12)
 
 EnumValue
-Enum(mips_arch_opt_value) String(3000) Value(12)
+Enum(mips_arch_opt_value) String(mips64r6) Value(13) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(3k) Value(12)
+Enum(mips_mips_opt_value) String(64r6) Value(13)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r2000) Value(13) Canonical
+Enum(mips_arch_opt_value) String(r3000) Value(14) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r2k) Value(13)
+Enum(mips_arch_opt_value) String(r3k) Value(14)
 
 EnumValue
-Enum(mips_arch_opt_value) String(2000) Value(13)
+Enum(mips_arch_opt_value) String(3000) Value(14)
 
 EnumValue
-Enum(mips_arch_opt_value) String(2k) Value(13)
+Enum(mips_arch_opt_value) String(3k) Value(14)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r3900) Value(14) Canonical
+Enum(mips_arch_opt_value) String(r2000) Value(15) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(3900) Value(14)
+Enum(mips_arch_opt_value) String(r2k) Value(15)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r6000) Value(15) Canonical
+Enum(mips_arch_opt_value) String(2000) Value(15)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r6k) Value(15)
+Enum(mips_arch_opt_value) String(2k) Value(15)
 
 EnumValue
-Enum(mips_arch_opt_value) String(6000) Value(15)
+Enum(mips_arch_opt_value) String(r3900) Value(16) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(6k) Value(15)
+Enum(mips_arch_opt_value) String(3900) Value(16)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4000) Value(16) Canonical
+Enum(mips_arch_opt_value) String(r6000) Value(17) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4k) Value(16)
+Enum(mips_arch_opt_value) String(r6k) Value(17)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4000) Value(16)
+Enum(mips_arch_opt_value) String(6000) Value(17)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4k) Value(16)
+Enum(mips_arch_opt_value) String(6k) Value(17)
 
 EnumValue
-Enum(mips_arch_opt_value) String(vr4100) Value(17) Canonical
+Enum(mips_arch_opt_value) String(r4000) Value(18) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(4100) Value(17)
+Enum(mips_arch_opt_value) String(r4k) Value(18)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4100) Value(17)
+Enum(mips_arch_opt_value) String(4000) Value(18)
 
 EnumValue
-Enum(mips_arch_opt_value) String(vr4111) Value(18) Canonical
+Enum(mips_arch_opt_value) String(4k) Value(18)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4111) Value(18)
+Enum(mips_arch_opt_value) String(vr4100) Value(19) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4111) Value(18)
+Enum(mips_arch_opt_value) String(4100) Value(19)
 
 EnumValue
-Enum(mips_arch_opt_value) String(vr4120) Value(19) Canonical
+Enum(mips_arch_opt_value) String(r4100) Value(19)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4120) Value(19)
+Enum(mips_arch_opt_value) String(vr4111) Value(20) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4120) Value(19)
+Enum(mips_arch_opt_value) String(4111) Value(20)
 
 EnumValue
-Enum(mips_arch_opt_value) String(vr4130) Value(20) Canonical
+Enum(mips_arch_opt_value) String(r4111) Value(20)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4130) Value(20)
+Enum(mips_arch_opt_value) String(vr4120) Value(21) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4130) Value(20)
+Enum(mips_arch_opt_value) String(4120) Value(21)
 
 EnumValue
-Enum(mips_arch_opt_value) String(vr4300) Value(21) Canonical
+Enum(mips_arch_opt_value) String(r4120) Value(21)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4300) Value(21)
+Enum(mips_arch_opt_value) String(vr4130) Value(22) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4300) Value(21)
+Enum(mips_arch_opt_value) String(4130) Value(22)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4400) Value(22) Canonical
+Enum(mips_arch_opt_value) String(r4130) Value(22)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4400) Value(22)
+Enum(mips_arch_opt_value) String(vr4300) Value(23) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4600) Value(23) Canonical
+Enum(mips_arch_opt_value) String(4300) Value(23)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4600) Value(23)
+Enum(mips_arch_opt_value) String(r4300) Value(23)
 
 EnumValue
-Enum(mips_arch_opt_value) String(orion) Value(24) Canonical
+Enum(mips_arch_opt_value) String(r4400) Value(24) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4650) Value(25) Canonical
+Enum(mips_arch_opt_value) String(4400) Value(24)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4650) Value(25)
+Enum(mips_arch_opt_value) String(r4600) Value(25) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4700) Value(26) Canonical
+Enum(mips_arch_opt_value) String(4600) Value(25)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4700) Value(26)
+Enum(mips_arch_opt_value) String(orion) Value(26) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r5900) Value(27) Canonical
+Enum(mips_arch_opt_value) String(r4650) Value(27) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(5900) Value(27)
+Enum(mips_arch_opt_value) String(4650) Value(27)
 
 EnumValue
-Enum(mips_arch_opt_value) String(loongson2e) Value(28) Canonical
+Enum(mips_arch_opt_value) String(r4700) Value(28) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(loongson2f) Value(29) Canonical
+Enum(mips_arch_opt_value) String(4700) Value(28)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r8000) Value(30) Canonical
+Enum(mips_arch_opt_value) String(r5900) Value(29) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r8k) Value(30)
+Enum(mips_arch_opt_value) String(5900) Value(29)
 
 EnumValue
-Enum(mips_arch_opt_value) String(8000) Value(30)
+Enum(mips_arch_opt_value) String(loongson2e) Value(30) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(8k) Value(30)
+Enum(mips_arch_opt_value) String(loongson2f) Value(31) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r10000) Value(31) Canonical
+Enum(mips_arch_opt_value) String(r8000) Value(32) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r10k) Value(31)
+Enum(mips_arch_opt_value) String(r8k) Value(32)
 
 EnumValue
-Enum(mips_arch_opt_value) String(10000) Value(31)
+Enum(mips_arch_opt_value) String(8000) Value(32)
 
 EnumValue
-Enum(mips_arch_opt_value) String(10k) Value(31)
+Enum(mips_arch_opt_value) String(8k) Value(32)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r12000) Value(32) Canonical
+Enum(mips_arch_opt_value) String(r10000) Value(33) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r12k) Value(32)
+Enum(mips_arch_opt_value) String(r10k) Value(33)
 
 EnumValue
-Enum(mips_arch_opt_value) String(12000) Value(32)
+Enum(mips_arch_opt_value) String(10000) Value(33)
 
 EnumValue
-Enum(mips_arch_opt_value) String(12k) Value(32)
+Enum(mips_arch_opt_value) String(10k) Value(33)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r14000) Value(33) Canonical
+Enum(mips_arch_opt_value) String(r12000) Value(34) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r14k) Value(33)
+Enum(mips_arch_opt_value) String(r12k) Value(34)
 
 EnumValue
-Enum(mips_arch_opt_value) String(14000) Value(33)
+Enum(mips_arch_opt_value) String(12000) Value(34)
 
 EnumValue
-Enum(mips_arch_opt_value) String(14k) Value(33)
+Enum(mips_arch_opt_value) String(12k) Value(34)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r16000) Value(34) Canonical
+Enum(mips_arch_opt_value) String(r14000) Value(35) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r16k) Value(34)
+Enum(mips_arch_opt_value) String(r14k) Value(35)
 
 EnumValue
-Enum(mips_arch_opt_value) String(16000) Value(34)
+Enum(mips_arch_opt_value) String(14000) Value(35)
 
 EnumValue
-Enum(mips_arch_opt_value) String(16k) Value(34)
+Enum(mips_arch_opt_value) String(14k) Value(35)
 
 EnumValue
-Enum(mips_arch_opt_value) String(vr5000) Value(35) Canonical
+Enum(mips_arch_opt_value) String(r16000) Value(36) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(vr5k) Value(35)
+Enum(mips_arch_opt_value) String(r16k) Value(36)
 
 EnumValue
-Enum(mips_arch_opt_value) String(5000) Value(35)
+Enum(mips_arch_opt_value) String(16000) Value(36)
 
 EnumValue
-Enum(mips_arch_opt_value) String(5k) Value(35)
+Enum(mips_arch_opt_value) String(16k) Value(36)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r5000) Value(35)
+Enum(mips_arch_opt_value) String(vr5000) Value(37) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r5k) Value(35)
+Enum(mips_arch_opt_value) String(vr5k) Value(37)
 
 EnumValue
-Enum(mips_arch_opt_value) String(vr5400) Value(36) Canonical
+Enum(mips_arch_opt_value) String(5000) Value(37)
 
 EnumValue
-Enum(mips_arch_opt_value) String(5400) Value(36)
+Enum(mips_arch_opt_value) String(5k) Value(37)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r5400) Value(36)
+Enum(mips_arch_opt_value) String(r5000) Value(37)
 
 EnumValue
-Enum(mips_arch_opt_value) String(vr5500) Value(37) Canonical
+Enum(mips_arch_opt_value) String(r5k) Value(37)
 
 EnumValue
-Enum(mips_arch_opt_value) String(5500) Value(37)
+Enum(mips_arch_opt_value) String(vr5400) Value(38) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r5500) Value(37)
+Enum(mips_arch_opt_value) String(5400) Value(38)
 
 EnumValue
-Enum(mips_arch_opt_value) String(rm7000) Value(38) Canonical
+Enum(mips_arch_opt_value) String(r5400) Value(38)
 
 EnumValue
-Enum(mips_arch_opt_value) String(rm7k) Value(38)
+Enum(mips_arch_opt_value) String(vr5500) Value(39) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(7000) Value(38)
+Enum(mips_arch_opt_value) String(5500) Value(39)
 
 EnumValue
-Enum(mips_arch_opt_value) String(7k) Value(38)
+Enum(mips_arch_opt_value) String(r5500) Value(39)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r7000) Value(38)
+Enum(mips_arch_opt_value) String(rm7000) Value(40) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r7k) Value(38)
+Enum(mips_arch_opt_value) String(rm7k) Value(40)
 
 EnumValue
-Enum(mips_arch_opt_value) String(rm9000) Value(39) Canonical
+Enum(mips_arch_opt_value) String(7000) Value(40)
 
 EnumValue
-Enum(mips_arch_opt_value) String(rm9k) Value(39)
+Enum(mips_arch_opt_value) String(7k) Value(40)
 
 EnumValue
-Enum(mips_arch_opt_value) String(9000) Value(39)
+Enum(mips_arch_opt_value) String(r7000) Value(40)
 
 EnumValue
-Enum(mips_arch_opt_value) String(9k) Value(39)
+Enum(mips_arch_opt_value) String(r7k) Value(40)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r9000) Value(39)
+Enum(mips_arch_opt_value) String(rm9000) Value(41) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r9k) Value(39)
+Enum(mips_arch_opt_value) String(rm9k) Value(41)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4kc) Value(40) Canonical
+Enum(mips_arch_opt_value) String(9000) Value(41)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4kc) Value(40)
+Enum(mips_arch_opt_value) String(9k) Value(41)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4km) Value(41) Canonical
+Enum(mips_arch_opt_value) String(r9000) Value(41)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4km) Value(41)
+Enum(mips_arch_opt_value) String(r9k) Value(41)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4kp) Value(42) Canonical
+Enum(mips_arch_opt_value) String(4kc) Value(42) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4kp) Value(42)
+Enum(mips_arch_opt_value) String(r4kc) Value(42)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4ksc) Value(43) Canonical
+Enum(mips_arch_opt_value) String(4km) Value(43) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4ksc) Value(43)
+Enum(mips_arch_opt_value) String(r4km) Value(43)
 
 EnumValue
-Enum(mips_arch_opt_value) String(m4k) Value(44) Canonical
+Enum(mips_arch_opt_value) String(4kp) Value(44) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(m14kc) Value(45) Canonical
+Enum(mips_arch_opt_value) String(r4kp) Value(44)
 
 EnumValue
-Enum(mips_arch_opt_value) String(m14k) Value(46) Canonical
+Enum(mips_arch_opt_value) String(4ksc) Value(45) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(m14ke) Value(47) Canonical
+Enum(mips_arch_opt_value) String(r4ksc) Value(45)
 
 EnumValue
-Enum(mips_arch_opt_value) String(m14kec) Value(48) Canonical
+Enum(mips_arch_opt_value) String(m4k) Value(46) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(4kec) Value(49) Canonical
+Enum(mips_arch_opt_value) String(m14kc) Value(47) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4kec) Value(49)
+Enum(mips_arch_opt_value) String(m14k) Value(48) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(4kem) Value(50) Canonical
+Enum(mips_arch_opt_value) String(m14ke) Value(49) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4kem) Value(50)
+Enum(mips_arch_opt_value) String(m14kec) Value(50) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(4kep) Value(51) Canonical
+Enum(mips_arch_opt_value) String(4kec) Value(51) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4kep) Value(51)
+Enum(mips_arch_opt_value) String(r4kec) Value(51)
 
 EnumValue
-Enum(mips_arch_opt_value) String(4ksd) Value(52) Canonical
+Enum(mips_arch_opt_value) String(4kem) Value(52) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r4ksd) Value(52)
+Enum(mips_arch_opt_value) String(r4kem) Value(52)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kc) Value(53) Canonical
+Enum(mips_arch_opt_value) String(4kep) Value(53) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kc) Value(53)
+Enum(mips_arch_opt_value) String(r4kep) Value(53)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kf2_1) Value(54) Canonical
+Enum(mips_arch_opt_value) String(4ksd) Value(54) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kf2_1) Value(54)
+Enum(mips_arch_opt_value) String(r4ksd) Value(54)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kf) Value(55) Canonical
+Enum(mips_arch_opt_value) String(24kc) Value(55) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kf) Value(55)
+Enum(mips_arch_opt_value) String(r24kc) Value(55)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kf1_1) Value(56) Canonical
+Enum(mips_arch_opt_value) String(24kf2_1) Value(56) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kf1_1) Value(56)
+Enum(mips_arch_opt_value) String(r24kf2_1) Value(56)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kfx) Value(57) Canonical
+Enum(mips_arch_opt_value) String(24kf) Value(57) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kfx) Value(57)
+Enum(mips_arch_opt_value) String(r24kf) Value(57)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kx) Value(58) Canonical
+Enum(mips_arch_opt_value) String(24kf1_1) Value(58) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kx) Value(58)
+Enum(mips_arch_opt_value) String(r24kf1_1) Value(58)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kec) Value(59) Canonical
+Enum(mips_arch_opt_value) String(24kfx) Value(59) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kec) Value(59)
+Enum(mips_arch_opt_value) String(r24kfx) Value(59)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kef2_1) Value(60) Canonical
+Enum(mips_arch_opt_value) String(24kx) Value(60) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kef2_1) Value(60)
+Enum(mips_arch_opt_value) String(r24kx) Value(60)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kef) Value(61) Canonical
+Enum(mips_arch_opt_value) String(24kec) Value(61) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kef) Value(61)
+Enum(mips_arch_opt_value) String(r24kec) Value(61)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kef1_1) Value(62) Canonical
+Enum(mips_arch_opt_value) String(24kef2_1) Value(62) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kef1_1) Value(62)
+Enum(mips_arch_opt_value) String(r24kef2_1) Value(62)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kefx) Value(63) Canonical
+Enum(mips_arch_opt_value) String(24kef) Value(63) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kefx) Value(63)
+Enum(mips_arch_opt_value) String(r24kef) Value(63)
 
 EnumValue
-Enum(mips_arch_opt_value) String(24kex) Value(64) Canonical
+Enum(mips_arch_opt_value) String(24kef1_1) Value(64) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r24kex) Value(64)
+Enum(mips_arch_opt_value) String(r24kef1_1) Value(64)
 
 EnumValue
-Enum(mips_arch_opt_value) String(34kc) Value(65) Canonical
+Enum(mips_arch_opt_value) String(24kefx) Value(65) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r34kc) Value(65)
+Enum(mips_arch_opt_value) String(r24kefx) Value(65)
 
 EnumValue
-Enum(mips_arch_opt_value) String(34kf2_1) Value(66) Canonical
+Enum(mips_arch_opt_value) String(24kex) Value(66) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r34kf2_1) Value(66)
+Enum(mips_arch_opt_value) String(r24kex) Value(66)
 
 EnumValue
-Enum(mips_arch_opt_value) String(34kf) Value(67) Canonical
+Enum(mips_arch_opt_value) String(34kc) Value(67) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r34kf) Value(67)
+Enum(mips_arch_opt_value) String(r34kc) Value(67)
 
 EnumValue
-Enum(mips_arch_opt_value) String(34kf1_1) Value(68) Canonical
+Enum(mips_arch_opt_value) String(34kf2_1) Value(68) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r34kf1_1) Value(68)
+Enum(mips_arch_opt_value) String(r34kf2_1) Value(68)
 
 EnumValue
-Enum(mips_arch_opt_value) String(34kfx) Value(69) Canonical
+Enum(mips_arch_opt_value) String(34kf) Value(69) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r34kfx) Value(69)
+Enum(mips_arch_opt_value) String(r34kf) Value(69)
 
 EnumValue
-Enum(mips_arch_opt_value) String(34kx) Value(70) Canonical
+Enum(mips_arch_opt_value) String(34kf1_1) Value(70) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r34kx) Value(70)
+Enum(mips_arch_opt_value) String(r34kf1_1) Value(70)
 
 EnumValue
-Enum(mips_arch_opt_value) String(34kn) Value(71) Canonical
+Enum(mips_arch_opt_value) String(34kfx) Value(71) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r34kn) Value(71)
+Enum(mips_arch_opt_value) String(r34kfx) Value(71)
 
 EnumValue
-Enum(mips_arch_opt_value) String(74kc) Value(72) Canonical
+Enum(mips_arch_opt_value) String(34kx) Value(72) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r74kc) Value(72)
+Enum(mips_arch_opt_value) String(r34kx) Value(72)
 
 EnumValue
-Enum(mips_arch_opt_value) String(74kf2_1) Value(73) Canonical
+Enum(mips_arch_opt_value) String(34kn) Value(73) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r74kf2_1) Value(73)
+Enum(mips_arch_opt_value) String(r34kn) Value(73)
 
 EnumValue
-Enum(mips_arch_opt_value) String(74kf) Value(74) Canonical
+Enum(mips_arch_opt_value) String(74kc) Value(74) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r74kf) Value(74)
+Enum(mips_arch_opt_value) String(r74kc) Value(74)
 
 EnumValue
-Enum(mips_arch_opt_value) String(74kf1_1) Value(75) Canonical
+Enum(mips_arch_opt_value) String(74kf2_1) Value(75) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r74kf1_1) Value(75)
+Enum(mips_arch_opt_value) String(r74kf2_1) Value(75)
 
 EnumValue
-Enum(mips_arch_opt_value) String(74kfx) Value(76) Canonical
+Enum(mips_arch_opt_value) String(74kf) Value(76) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r74kfx) Value(76)
+Enum(mips_arch_opt_value) String(r74kf) Value(76)
 
 EnumValue
-Enum(mips_arch_opt_value) String(74kx) Value(77) Canonical
+Enum(mips_arch_opt_value) String(74kf1_1) Value(77) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r74kx) Value(77)
+Enum(mips_arch_opt_value) String(r74kf1_1) Value(77)
 
 EnumValue
-Enum(mips_arch_opt_value) String(74kf3_2) Value(78) Canonical
+Enum(mips_arch_opt_value) String(74kfx) Value(78) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r74kf3_2) Value(78)
+Enum(mips_arch_opt_value) String(r74kfx) Value(78)
 
 EnumValue
-Enum(mips_arch_opt_value) String(1004kc) Value(79) Canonical
+Enum(mips_arch_opt_value) String(74kx) Value(79) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r1004kc) Value(79)
+Enum(mips_arch_opt_value) String(r74kx) Value(79)
 
 EnumValue
-Enum(mips_arch_opt_value) String(1004kf2_1) Value(80) Canonical
+Enum(mips_arch_opt_value) String(74kf3_2) Value(80) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r1004kf2_1) Value(80)
+Enum(mips_arch_opt_value) String(r74kf3_2) Value(80)
 
 EnumValue
-Enum(mips_arch_opt_value) String(1004kf) Value(81) Canonical
+Enum(mips_arch_opt_value) String(1004kc) Value(81) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r1004kf) Value(81)
+Enum(mips_arch_opt_value) String(r1004kc) Value(81)
 
 EnumValue
-Enum(mips_arch_opt_value) String(1004kf1_1) Value(82) Canonical
+Enum(mips_arch_opt_value) String(1004kf2_1) Value(82) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r1004kf1_1) Value(82)
+Enum(mips_arch_opt_value) String(r1004kf2_1) Value(82)
 
 EnumValue
-Enum(mips_arch_opt_value) String(p5600) Value(83) Canonical
+Enum(mips_arch_opt_value) String(1004kf) Value(83) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(5kc) Value(84) Canonical
+Enum(mips_arch_opt_value) String(r1004kf) Value(83)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r5kc) Value(84)
+Enum(mips_arch_opt_value) String(1004kf1_1) Value(84) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(5kf) Value(85) Canonical
+Enum(mips_arch_opt_value) String(r1004kf1_1) Value(84)
 
 EnumValue
-Enum(mips_arch_opt_value) String(r5kf) Value(85)
+Enum(mips_arch_opt_value) String(p5600) Value(85) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(20kc) Value(86) Canonical
+Enum(mips_arch_opt_value) String(5kc) Value(86) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(r20kc) Value(86)
+Enum(mips_arch_opt_value) String(r5kc) Value(86)
 
 EnumValue
-Enum(mips_arch_opt_value) String(sb1) Value(87) Canonical
+Enum(mips_arch_opt_value) String(5kf) Value(87) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(sb1a) Value(88) Canonical
+Enum(mips_arch_opt_value) String(r5kf) Value(87)
 
 EnumValue
-Enum(mips_arch_opt_value) String(sr71000) Value(89) Canonical
+Enum(mips_arch_opt_value) String(20kc) Value(88) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(sr71k) Value(89)
+Enum(mips_arch_opt_value) String(r20kc) Value(88)
 
 EnumValue
-Enum(mips_arch_opt_value) String(xlr) Value(90) Canonical
+Enum(mips_arch_opt_value) String(sb1) Value(89) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(loongson3a) Value(91) Canonical
+Enum(mips_arch_opt_value) String(sb1a) Value(90) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(octeon) Value(92) Canonical
+Enum(mips_arch_opt_value) String(sr71000) Value(91) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(octeon+) Value(93) Canonical
+Enum(mips_arch_opt_value) String(sr71k) Value(91)
 
 EnumValue
-Enum(mips_arch_opt_value) String(octeon2) Value(94) Canonical
+Enum(mips_arch_opt_value) String(xlr) Value(92) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(octeon3) Value(95) Canonical
+Enum(mips_arch_opt_value) String(loongson3a) Value(93) Canonical
 
 EnumValue
-Enum(mips_arch_opt_value) String(xlp) Value(96) Canonical
+Enum(mips_arch_opt_value) String(octeon) Value(94) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(octeon+) Value(95) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(octeon2) Value(96) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(octeon3) Value(97) Canonical
+
+EnumValue
+Enum(mips_arch_opt_value) String(xlp) Value(98) Canonical
 
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 02268f3..7797b31 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -182,9 +182,10 @@ along with GCC; see the file COPYING3.  If not see
 #define MIPS_LUI(DEST, VALUE) \
   ((0xf << 26) | ((DEST) << 16) | (VALUE))
 
-/* Return the opcode to jump to register DEST.  */
+/* Return the opcode to jump to register DEST.  When the JR opcode is not
+   available use JALR $0, DEST.  */
 #define MIPS_JR(DEST) \
-  (((DEST) << 21) | 0x8)
+  (((DEST) << 21) | (ISA_HAS_JR ? 0x8 : 0x9))
 
 /* Return the opcode for:
 
@@ -1225,6 +1226,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 */
   }
 };
 \f
@@ -2593,6 +2620,20 @@ umips_12bit_offset_address_p (rtx x, 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
+mips_9bit_offset_address_p (rtx x, 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)
+	  && MIPS_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.  */
@@ -4102,6 +4143,11 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1);
       return false;
 
+    case FMA:
+      if (ISA_HAS_FP_MADDF_MSUBF)
+	*total = mips_fp_mult_cost (mode);
+      return false;
+
     case MULT:
       if (float_mode_p)
 	*total = mips_fp_mult_cost (mode);
@@ -4112,7 +4158,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 		  ? 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
@@ -4188,6 +4234,52 @@ 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.  Matching patterns of the form:
+
+	 (lshiftrt:DI (mult:DI (sign_extend:DI (...)
+			       (sign_extend:DI (...))
+		      (const_int 32)
+      */
+      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.  */
+	  for (int i = 0; i < 2; ++i)
+	    {
+	      rtx op = XEXP (XEXP (XEXP (x, 0), 0), i);
+	      if (ISA_HAS_R6DMUL
+		  && GET_CODE (op) == ZERO_EXTEND
+		  && GET_MODE (op) == DImode)
+		*total += rtx_cost (op, MULT, i, speed);
+	      else
+		*total += rtx_cost (XEXP (op, 0), GET_CODE (op), 0, speed);
+	    }
+
+	  return true;
+	}
+      return false;
 
     case FLOAT:
     case UNSIGNED_FLOAT:
@@ -4971,17 +5063,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 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);
     }
@@ -5071,9 +5178,45 @@ 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))
+    {
+      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
+    {
+      if (FLOAT_MODE_P (GET_MODE (operands[2])) && !ISA_HAS_SEL)
+	{
+	  operands[2] = force_reg (GET_MODE (operands[0]), operands[2]);
+	  operands[3] = force_reg (GET_MODE (operands[0]), operands[3]);
+	}
+
+      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.  */
@@ -5107,7 +5250,9 @@ mips_expand_conditional_trap (rtx comparison)
 
   mode = GET_MODE (XEXP (comparison, 0));
   op0 = force_reg (mode, op0);
-  if (!arith_operand (op1, mode))
+  if (!(ISA_HAS_COND_TRAPI
+	? arith_operand (op1, mode)
+	: reg_or_0_operand (op1, mode)))
     op1 = force_reg (mode, op1);
 
   emit_insn (gen_rtx_TRAP_IF (VOIDmode,
@@ -7462,6 +7607,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)
@@ -8224,11 +8373,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:
@@ -8358,7 +8513,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);
@@ -9910,7 +10065,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_HILO || TARGET_DSP)
+      && MD_REG_P (regno))
     return true;
 
   if (TARGET_DSP && DSP_ACC_REG_P (regno))
@@ -11884,7 +12040,7 @@ mips_hard_regno_mode_ok_p (unsigned int regno, machine_mode mode)
   size = GET_MODE_SIZE (mode);
   mclass = GET_MODE_CLASS (mode);
 
-  if (GP_REG_P (regno))
+  if (GP_REG_P (regno) && mode != CCFmode)
     return ((regno - GP_REG_FIRST) & 1) == 0 || size <= UNITS_PER_WORD;
 
   if (FP_REG_P (regno)
@@ -11896,6 +12052,15 @@ mips_hard_regno_mode_ok_p (unsigned int regno, machine_mode mode)
       if (TARGET_O32_FP64A_ABI && size <= 4 && (regno & 1) != 0)
 	return false;
 
+      /* Prevent the use of odd-numbered registers for CCFmode with the
+	 o32 FPXX ABI, otherwise allow them.
+	 The FPXX ABI does not permit double-precision data to be placed
+	 in odd-numbered registers and double-precision compares write
+	 them as 64-bit values.  Without this restriction the R6 FPXX
+	 ABI would not be able to execute in FR=1 FRE=1 mode.  */
+      if (mode == CCFmode && ISA_HAS_CCF)
+	return !(TARGET_FLOATXX && (regno & 1) != 0);
+
       /* Allow 64-bit vector modes for Loongson-2E/2F.  */
       if (TARGET_LOONGSON_VECTORS
 	  && (mode == V2SImode
@@ -12055,6 +12220,7 @@ mips_mode_ok_for_mov_fmt_p (machine_mode mode)
 {
   switch (mode)
     {
+    case CCFmode:
     case SFmode:
       return TARGET_HARD_FLOAT;
 
@@ -15917,8 +16083,10 @@ 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)
-    /* No MTLO or MTHI available.  */
+  if (TARGET_MIPS16 || !ISA_HAS_HILO)
+    /* No MTLO or MTHI available for MIPS16. Also, when there are no HI or LO
+       registers then there is no reason to zero them, arbitrarily choose to
+       say that "MULT $0,$0" would be faster.  */
     mips_tuning_info.fast_mult_zero_zero_p = true;
   else
     {
@@ -17162,7 +17330,10 @@ 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 ("the %qs architecture does not support %<-mfp32%>",
+	       mips_arch_info->name);
+      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");
@@ -17178,9 +17349,13 @@ 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)
+      /* -msingle-float selects 32-bit float registers.  On r6 and later,
+	 -mdouble-float selects 64-bit float registers, since the old paired
+	 register model is not supported.  In other cases the float registers
+	 should be the same size as the integer ones.  */
+      if (mips_isa_rev >= 6 && TARGET_DOUBLE_FLOAT && !TARGET_FLOATXX)
+	target_flags |= MASK_FLOAT64;
+      else if (TARGET_64BIT && TARGET_DOUBLE_FLOAT)
 	target_flags |= MASK_FLOAT64;
       else
 	target_flags &= ~MASK_FLOAT64;
@@ -17188,6 +17363,8 @@ mips_option_override (void)
 
   if (mips_abi != ABI_32 && TARGET_FLOATXX)
     error ("%<-mfpxx%> can only be used with the o32 ABI");
+  else if (TARGET_FLOAT64 && TARGET_FLOATXX)
+    error ("unsupported combination: %s", "-mfp64 -mfpxx");
   else if (ISA_MIPS1 && !TARGET_FLOAT32)
     error ("%<-march=%s%> requires %<-mfp32%>", mips_arch_info->name);
   else if (TARGET_FLOATXX && !mips_lra_flag)
@@ -17365,6 +17542,27 @@ mips_option_override (void)
 	}
     }
 
+  /* Set NaN and ABS defaults.  */
+  if (mips_nan == MIPS_IEEE_754_DEFAULT && !ISA_HAS_IEEE_754_LEGACY)
+    mips_nan = MIPS_IEEE_754_2008;
+  if (mips_abs == MIPS_IEEE_754_DEFAULT && !ISA_HAS_IEEE_754_LEGACY)
+    mips_abs = MIPS_IEEE_754_2008;
+
+  /* Check for IEEE 754 legacy/2008 support.  */
+  if ((mips_nan == MIPS_IEEE_754_LEGACY
+       || mips_abs == MIPS_IEEE_754_LEGACY)
+      && !ISA_HAS_IEEE_754_LEGACY)
+    warning (0, "the %qs architecture does not support %<-m%s=legacy%>",
+	     mips_arch_info->name,
+	     mips_nan == MIPS_IEEE_754_LEGACY ? "nan" : "abs");
+
+  if ((mips_nan == MIPS_IEEE_754_2008
+       || mips_abs == MIPS_IEEE_754_2008)
+      && !ISA_HAS_IEEE_754_2008)
+    warning (0, "the %qs architecture does not support %<-m%s=2008%>",
+	     mips_arch_info->name,
+	     mips_nan == MIPS_IEEE_754_2008 ? "nan" : "abs");
+
   /* Pre-IEEE 754-2008 MIPS hardware has a quirky almost-IEEE format
      for all its floating point.  */
   if (mips_nan != MIPS_IEEE_754_2008)
@@ -17419,6 +17617,14 @@ 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);
+      TARGET_DSP = false;
+      TARGET_DSPR2 = false;
+    }
+
   /* .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.
@@ -17599,6 +17805,10 @@ mips_conditional_register_usage (void)
     AND_COMPL_HARD_REG_SET (accessible_reg_set,
 			    reg_class_contents[(int) DSP_ACC_REGS]);
 
+  if (!ISA_HAS_HILO)
+    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,
@@ -17613,7 +17823,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)
@@ -17788,6 +17999,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)
@@ -17800,6 +18013,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
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 8a38829..c110b5e 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)
@@ -458,42 +460,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");		\
@@ -673,10 +645,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
@@ -743,11 +719,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
@@ -776,8 +754,11 @@ 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}}"
+
+#define MIPS_ISA_NAN2008_SPEC \
+  "%{mnan*:;mips32r6|mips64r6:-mnan=2008}"
 
 #if (MIPS_ABI_DEFAULT == ABI_O64 \
      || MIPS_ABI_DEFAULT == ABI_N32 \
@@ -827,11 +808,14 @@ struct mips_cpu_info {
 
 /* A spec that infers the -mdsp setting from an -march argument.  */
 #define BASE_DRIVER_SELF_SPECS \
+  MIPS_ISA_NAN2008_SPEC,       \
   "%{!mno-dsp: \
      %{march=24ke*|march=34kc*|march=34kf*|march=34kx*|march=1004k*: -mdsp} \
      %{march=74k*|march=m14ke*: %{!mno-dspr2: -mdspr2 -mdsp}}}"
 
-#define DRIVER_SELF_SPECS BASE_DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS \
+  MIPS_ISA_LEVEL_SPEC,	  \
+  BASE_DRIVER_SELF_SPECS
 
 #define GENERATE_DIVIDE_TRAPS (TARGET_DIVIDE_TRAPS \
                                && ISA_HAS_COND_TRAP)
@@ -864,12 +848,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 32 single-precision registers.  */
 #define ISA_HAS_ODD_SPREG	((mips_isa_rev >= 1			\
@@ -885,7 +872,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.  */
@@ -893,30 +881,48 @@ struct mips_cpu_info {
 				 && TARGET_OCTEON			\
 				 && !TARGET_MIPS16)
 
+/* ISA has HI and LO registers.  */
+#define ISA_HAS_HILO		(mips_isa_rev <= 5)
+
 /* ISA supports instructions DMULT and DMULTU. */
-#define ISA_HAS_DMULT		(TARGET_64BIT && !TARGET_MIPS5900)
+#define ISA_HAS_DMULT		(TARGET_64BIT				\
+				 && !TARGET_MIPS5900			\
+				 && ISA_HAS_HILO)
 
-/* 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)
+/* ISA supports instructions MULT and MULTU.  */
+#define ISA_HAS_MULT		ISA_HAS_HILO
+
+/* ISA supports instructions MUL, MULU, MUH, MUHU.  */
+#define ISA_HAS_R6MUL		(mips_isa_rev >= 6)
+
+/* ISA supports instructions DMUL, DMULU, DMUH, DMUHU.  */
+#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)
 
+/* ISA supports instructions DIV, DIVU, MOD and MODU.  */
+#define ISA_HAS_R6DIV		(mips_isa_rev >= 6)
+
+/* ISA supports instructions DDIV, DDIVU, DMOD and DMODU.  */
+#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)
 
@@ -933,7 +939,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
@@ -941,7 +955,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
@@ -949,14 +964,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)
@@ -964,6 +987,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
 
@@ -985,10 +1011,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 && !TARGET_MIPS16)
+
+#define ISA_HAS_IEEE_754_LEGACY	(mips_isa_rev <= 5)
+
+#define ISA_HAS_IEEE_754_2008	(mips_isa_rev >= 2)
+
 /* ISA has count leading zeroes/ones instruction (not implemented).  */
 #define ISA_HAS_CLZ_CLO		(mips_isa_rev >= 1 && !TARGET_MIPS16)
 
@@ -1046,6 +1081,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
@@ -2133,6 +2171,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 MIPS_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 647bf85..add17a8 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -67,6 +67,8 @@ (define_enum "processor" [
   xlr
   xlp
   p5600
+  w32
+  w64
 ])
 
 (define_c_enum "unspec" [
@@ -766,6 +768,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
@@ -855,7 +862,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")])
@@ -895,6 +902,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 mnemonic 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])
@@ -917,7 +927,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.
@@ -990,7 +1003,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")
@@ -1004,6 +1020,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 mnemonic to use depending on the condition test.
+(define_code_attr sel [(eq "seleqz") (ne "selnez")])
+(define_code_attr selinv [(eq "selnez") (ne "seleqz")])
 \f
 ;; .........................
 ;;
@@ -1112,18 +1132,27 @@ (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_trap_reg<mode>"
+  [(trap_if (match_operator:GPR 0 "trap_comparison_operator"
+				[(match_operand:GPR 1 "reg_or_0_operand" "dJ")
+				 (match_operand:GPR 2 "reg_or_0_operand" "dJ")])
+	    (const_int 0))]
+  "ISA_HAS_COND_TRAP && !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")])
 	    (const_int 0))]
-  "ISA_HAS_COND_TRAP"
+  "ISA_HAS_COND_TRAPI"
   "t%C0\t%z1,%2"
   [(set_attr "type" "trap")])
 \f
@@ -1491,13 +1520,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_nohilo (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)
@@ -1514,16 +1543,18 @@ (define_expand "mul<mode>3"
   DONE;
 })
 
-(define_insn "mul<mode>3_mul3_loongson"
+(define_insn "mul<mode>3_mul3_nohilo"
   [(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>")])
@@ -1959,6 +1990,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_nohilo (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"))
@@ -1980,7 +2029,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";
@@ -1995,7 +2044,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")
@@ -2007,7 +2056,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)]
@@ -2090,6 +2140,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")
@@ -2147,12 +2206,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
@@ -2161,7 +2235,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)]
@@ -2239,17 +2313,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
@@ -2388,6 +2479,16 @@ (define_insn "*madd4<mode>"
    (set_attr "accum_in"	"3")
    (set_attr "mode" "<UNITMODE>")])
 
+(define_insn "fma<mode>4"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+	(fma:ANYF (match_operand:ANYF 1 "register_operand" "f")
+		  (match_operand:ANYF 2 "register_operand" "f")
+		  (match_operand:ANYF 3 "register_operand" "0")))]
+  "ISA_HAS_FP_MADDF_MSUBF"
+  "maddf.<fmt>\t%0,%1,%2"
+  [(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")
@@ -2771,6 +2872,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>")])
 \f
 ;;
 ;;  ....................
@@ -3916,7 +4051,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"
 {
   if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
 					 INTVAL (operands[2]),
@@ -3953,7 +4088,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"
 {
   if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
 					 INTVAL (operands[2]),
@@ -4004,7 +4139,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"
 {
   if (mips_expand_ins_as_unaligned_store (operands[0], operands[3],
 					  INTVAL (operands[1]),
@@ -4760,6 +4895,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"))]
@@ -5278,7 +5420,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")
@@ -5555,11 +5697,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)))]
@@ -5571,11 +5713,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 "" ""))))]
@@ -5919,21 +6061,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")])
 \f
@@ -6953,6 +7095,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"
@@ -6961,8 +7138,11 @@ (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 && !INTEGRAL_MODE_P (GET_MODE (XEXP (operands[1], 0))))
+    FAIL;
+
   mips_expand_conditional_move (operands);
   DONE;
 })
@@ -6971,10 +7151,25 @@ (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 && !FLOAT_MODE_P (GET_MODE (XEXP (operands[1], 0))))
+    FAIL;
+
+  /* Workaround an LRA bug which means that tied operands in the sel.fmt
+     pattern lead to the double precision destination of sel.d getting
+     reloaded with the full register file usable and the restrictions on
+     whether the CCFmode input can be used in odd-numbered single-precision
+     registers are ignored.  For consistency reasons the CCF mode values
+     must be guaranteed to only exist in the even-registers because of
+     the unusual duality between single and double precision values.  */
+  if (ISA_HAS_SEL && <MODE>mode == DFmode
+      && (!TARGET_ODD_SPREG || TARGET_FLOATXX))
+    FAIL;
+
   mips_expand_conditional_move (operands);
   DONE;
 })
@@ -7089,7 +7284,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 294e17d..97a94a5 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -782,7 +782,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
@@ -17555,8 +17555,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},
@@ -17663,6 +17664,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}.
@@ -17679,6 +17684,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/gcc/doc/md.texi b/gcc/doc/md.texi
index 6404147..0d7bd98 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -2994,10 +2994,8 @@ operands can be used for microMIPS instructions such as @code{ll} and
 equivalent to @code{R}.
 
 @item 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}.
+An address suitable for a @code{prefetch} instruction, or for any other
+instruction with the same addressing mode as @code{prefetch}.
 @end table
 
 @item Motorola 680x0---@file{config/m68k/constraints.md}
diff --git a/gcc/testsuite/gcc.dg/torture/mips-hilo-2.c b/gcc/testsuite/gcc.dg/torture/mips-hilo-2.c
index dbe9493..78f7710 100644
--- a/gcc/testsuite/gcc.dg/torture/mips-hilo-2.c
+++ b/gcc/testsuite/gcc.dg/torture/mips-hilo-2.c
@@ -5,6 +5,7 @@
 extern void abort (void);
 extern void exit (int);
 
+#if __mips_isa_rev <= 5
 unsigned int g;
 
 unsigned __attribute__ ((nomips16)) long long f (unsigned int x)
@@ -15,13 +16,16 @@ unsigned __attribute__ ((nomips16)) long long f (unsigned int x)
   asm ("mflo\t%0" : "=r" (g) : "l" (u.parts[1]));
   return u.ll;
 }
+#endif
 
 int __attribute__ ((nomips16)) main ()
 {
+#if __mips_isa_rev <= 5
   union { unsigned long long ll; unsigned int parts[2]; } u;
 
   u.ll = f (0x12345678);
   if (g != u.parts[1])
     abort ();
+#endif
   exit (0);
 }
diff --git a/gcc/testsuite/gcc.dg/torture/pr19683-1.c b/gcc/testsuite/gcc.dg/torture/pr19683-1.c
index 05bf174..aa7205f 100644
--- a/gcc/testsuite/gcc.dg/torture/pr19683-1.c
+++ b/gcc/testsuite/gcc.dg/torture/pr19683-1.c
@@ -14,6 +14,7 @@ extern void exit (int);
 #define IN(X) unsigned int x##X = ptr[0]
 #define OUT(X) ptr[0] = x##X
 
+#if __mips_isa_rev <= 5
 union u { unsigned long long ll; unsigned int i[2]; };
 
 unsigned int __attribute__ ((nomips16))
@@ -28,15 +29,18 @@ foo (volatile unsigned int *ptr)
   asm ("#" : "=l" (result) : "l" (u.i[1]));
   return result;
 }
+#endif
 
 int __attribute__ ((nomips16))
 main (void)
 {
+#if __mips_isa_rev <= 5
   unsigned int array[] = { 1000 * 1000 * 1000 };
   union u u;
 
   u.ll = (unsigned long long) array[0] * array[0];
   if (foo (array) != u.i[1])
     abort ();
+#endif
   exit (0);
 }
diff --git a/gcc/testsuite/gcc.target/mips/args-3.c b/gcc/testsuite/gcc.target/mips/args-3.c
index 6a79ce6..5eddabf 100644
--- a/gcc/testsuite/gcc.target/mips/args-3.c
+++ b/gcc/testsuite/gcc.target/mips/args-3.c
@@ -24,7 +24,7 @@ int foo (float inf, int64 in64, int32 in32)
     abort ();
 #endif
 
-#if (__mips == 4 || __mips == 32 || __mips == 64) && !defined (__mips16)
+#if (__mips == 4 || ((__mips == 32 || __mips == 64) && __mips_isa_rev < 6)) && !defined (__mips16)
   __asm__ ("move %0,%.\n\tmovn %0,%1,%2"
 	   : "=&r" (res32) : "r" (in32), "r" (in64 != 0));
   if (res32 != 60)
diff --git a/gcc/testsuite/gcc.target/mips/branch-cost-2.c b/gcc/testsuite/gcc.target/mips/branch-cost-2.c
index 3b2c4a1..5a422ae 100644
--- a/gcc/testsuite/gcc.target/mips/branch-cost-2.c
+++ b/gcc/testsuite/gcc.target/mips/branch-cost-2.c
@@ -1,4 +1,4 @@
-/* { dg-options "-mbranch-cost=10 isa>=4" } */
+/* { dg-options "-mbranch-cost=10 (HAS_MOVN)" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 NOMIPS16 int
 foo (int x, int y, int z, int k)
diff --git a/gcc/testsuite/gcc.target/mips/call-saved-4.c b/gcc/testsuite/gcc.target/mips/call-saved-4.c
index e126175..846ea32 100644
--- a/gcc/testsuite/gcc.target/mips/call-saved-4.c
+++ b/gcc/testsuite/gcc.target/mips/call-saved-4.c
@@ -1,5 +1,5 @@
 /* Check that we save the correct call-saved GPRs and FPRs.  */
-/* { dg-options "isa>=2 -mabi=32 -mfp32" } */
+/* { dg-options "(HAS_LDC) -mabi=32 -mfp32" } */
 
 void bar (void);
 
diff --git a/gcc/testsuite/gcc.target/mips/dmult-1.c b/gcc/testsuite/gcc.target/mips/dmult-1.c
index f8c0b8b..9257316 100644
--- a/gcc/testsuite/gcc.target/mips/dmult-1.c
+++ b/gcc/testsuite/gcc.target/mips/dmult-1.c
@@ -1,4 +1,4 @@
-/* { dg-options "forbid_cpu=octeon.* -mgp64" } */
+/* { dg-options "isa_rev<=5 forbid_cpu=octeon.* -mgp64" } */
 /* { dg-final { scan-assembler "\tdmult\t" } } */
 /* { dg-final { scan-assembler "\tmflo\t" } } */
 /* { dg-final { scan-assembler-not "\tdmul\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fpcmp-1.c b/gcc/testsuite/gcc.target/mips/fpcmp-1.c
index c0594ff..03c2f79 100644
--- a/gcc/testsuite/gcc.target/mips/fpcmp-1.c
+++ b/gcc/testsuite/gcc.target/mips/fpcmp-1.c
@@ -1,5 +1,5 @@
 /* We used to use c.lt.fmt instead of c.ule.fmt here.  */
-/* { dg-options "-mhard-float" } */
+/* { dg-options "isa_rev<=5 -mhard-float" } */
 NOMIPS16 int f1 (float x, float y) { return __builtin_isless (x, y); }
 NOMIPS16 int f2 (double x, double y) { return __builtin_isless (x, y); }
 /* { dg-final { scan-assembler "\tc\\.ule\\.s\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/fpcmp-2.c b/gcc/testsuite/gcc.target/mips/fpcmp-2.c
index 23d5cb0..6936b90 100644
--- a/gcc/testsuite/gcc.target/mips/fpcmp-2.c
+++ b/gcc/testsuite/gcc.target/mips/fpcmp-2.c
@@ -1,5 +1,5 @@
 /* We used to use c.le.fmt instead of c.ult.fmt here.  */
-/* { dg-options "-mhard-float" } */
+/* { dg-options "isa_rev<=5 -mhard-float" } */
 NOMIPS16 int f1 (float x, float y) { return __builtin_islessequal (x, y); }
 NOMIPS16 int f2 (double x, double y) { return __builtin_islessequal (x, y); }
 /* { dg-final { scan-assembler "\tc\\.ult\\.s\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/madd-3.c b/gcc/testsuite/gcc.target/mips/madd-3.c
index 29f4c9b..b0771ad 100644
--- a/gcc/testsuite/gcc.target/mips/madd-3.c
+++ b/gcc/testsuite/gcc.target/mips/madd-3.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "isa_rev>=1 -mgp32" } */
+/* { dg-options "(HAS_MADD) -mgp32" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler-times "\tmadd\t" 3 } } */
 
diff --git a/gcc/testsuite/gcc.target/mips/madd-9.c b/gcc/testsuite/gcc.target/mips/madd-9.c
index 28681a9..acafc7a 100644
--- a/gcc/testsuite/gcc.target/mips/madd-9.c
+++ b/gcc/testsuite/gcc.target/mips/madd-9.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "isa_rev>=1 -mgp32 -mtune=4kc" } */
+/* { dg-options "(HAS_MADD) -mgp32 -mtune=4kc" } */
 /* References to X within the loop need to have a higher frequency than
    references to X outside the loop, otherwise there is no reason
    to prefer multiply/accumulator registers over GPRs.  */
diff --git a/gcc/testsuite/gcc.target/mips/maddu-3.c b/gcc/testsuite/gcc.target/mips/maddu-3.c
index 27a7350..e180fa7 100644
--- a/gcc/testsuite/gcc.target/mips/maddu-3.c
+++ b/gcc/testsuite/gcc.target/mips/maddu-3.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
 /* This test requires widening_mul */
-/* { dg-options "isa_rev>=1 -mgp32 -fexpensive-optimizations" } */
+/* { dg-options "(HAS_MADD) -mgp32 -fexpensive-optimizations" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler-times "\tmaddu\t" 3 } } */
 
diff --git a/gcc/testsuite/gcc.target/mips/mips-ps-type-2.c b/gcc/testsuite/gcc.target/mips/mips-ps-type-2.c
index f52cf91..a4dfbae 100644
--- a/gcc/testsuite/gcc.target/mips/mips-ps-type-2.c
+++ b/gcc/testsuite/gcc.target/mips/mips-ps-type-2.c
@@ -1,7 +1,7 @@
 /* Test v2sf calculations.  The nmadd and nmsub patterns need
    -ffinite-math-only.  */
 /* { dg-do compile } */
-/* { dg-options "isa_rev>=2 -mgp32 -mpaired-single -ffinite-math-only" } */
+/* { dg-options "(HAS_MADDPS) -mgp32 -mpaired-single -ffinite-math-only" } */
 /* { dg-skip-if "nmadd and nmsub need combine" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler "\tcvt.ps.s\t" } } */
 /* { dg-final { scan-assembler "\tmov.ps\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index a9beb27..ddb20b9 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -246,6 +246,12 @@ set mips_option_groups {
     small-data "-G[0-9]+"
     warnings "-w"
     dump "-fdump-.*"
+    ins "HAS_INS"
+    dmul "NOT_HAS_DMUL"
+    ldc "HAS_LDC"
+    movn "HAS_MOVN"
+    madd "HAS_MADD"
+    maddps "HAS_MADDPS"
 }
 
 for { set option 0 } { $option < 32 } { incr option } {
@@ -1055,6 +1061,9 @@ proc mips-dg-options { args } {
 	     && (($gp_size == 32 && [mips_have_test_option_p options "-mfp64"])
 		 || [mips_have_test_option_p options "-msynci"]
 		 || [mips_have_test_option_p options "-mdsp"]
+		 || [mips_have_test_option_p options "HAS_INS"]
+		 || [mips_have_test_option_p options "HAS_MADD"]
+		 || [mips_have_test_option_p options "HAS_MADDPS"]
 		 || [mips_have_test_option_p options "-mdspr2"]) } {
 	    if { $gp_size == 32 } {
 		mips_make_test_option options "-mips32r2"
@@ -1076,6 +1085,12 @@ proc mips-dg-options { args } {
 	    } else {
 		mips_make_test_option options "-mips64"
 	    }
+        # We need MIPS IV or higher for:
+	#
+	#
+	} elseif { $isa < 3
+		   && [mips_have_test_option_p options "HAS_MOVN"] } {
+	    mips_make_test_option options "-mips4"
         # We need MIPS III or higher for:
 	#
 	#   - the "cache" instruction
@@ -1094,8 +1109,38 @@ proc mips-dg-options { args } {
 		   && ([mips_have_test_option_p options "-mbranch-likely"]
 		       || [mips_have_test_option_p options "-mfix-r10000"]
 		       || ($gp_size == 32
-			   && [mips_have_test_option_p options "-mfpxx"])) } {
+			   && ([mips_have_test_option_p options "-mfpxx"]
+			       || [mips_have_test_option_p options "HAS_LDC"]))) } {
 	    mips_make_test_option options "-mips2"
+	# We need to use octeon's base ISA if a test must not run with an
+	# architecture that supports dmul.
+	} elseif { [regexp -- "^-march=octeon.*\$" $arch]
+		   && [mips_have_test_option_p options "NOT_HAS_DMUL"] } {
+	    mips_make_test_option options "-mips${isa}r${isa_rev}"
+	# Check whether we need to switch from mips*r6 down to mips*r5 due
+	# to options that are incompatible with mips*r6.  If we do, use
+	# -mnan=2008 because r6 is nan2008 by default and without this flag
+	# tests that include stdlib.h will fail due to not finding
+	# stubs-o32_hard.h  (r6 compilers only have stubs-o32_hard_2008.h)
+	} elseif { $isa_rev > 5
+		   && ([mips_have_test_option_p options "-mdsp"]
+		       || [mips_have_test_option_p options "-mdspr2"]
+		       || [mips_have_test_option_p options "-mips16"]
+		       || [mips_have_test_option_p options "-mmicromips"]
+		       || [mips_have_test_option_p options "-mfp32"]
+		       || [mips_have_test_option_p options "-mfix-r10000"]
+		       || [mips_have_test_option_p options "NOT_HAS_DMUL"]
+		       || [mips_have_test_option_p options "HAS_MOVN"]
+		       || [mips_have_test_option_p options "HAS_MADD"]
+		       || [mips_have_test_option_p options "-mpaired-single"]
+		       || [mips_have_test_option_p options "-mnan=legacy"]
+		       || [mips_have_test_option_p options "-mabs=legacy"]) } {
+	    if { $gp_size == 32 } {
+		mips_make_test_option options "-mips32r5"
+	    } else {
+		mips_make_test_option options "-mips64r5"
+	    }
+	    mips_make_test_option options "-mnan=2008"
 	# Check whether we need to switch from a 32-bit processor to the
 	# "nearest" 64-bit processor.
 	} elseif { $gp_size == 64 && [mips_32bit_arch_p $arch] } {
@@ -1120,6 +1165,10 @@ proc mips-dg-options { args } {
 	unset isa_rev
     }
 
+    # Re-calculate the isa_rev for use in the abi handling code below
+    set arch [mips_option options arch]
+    set isa_rev [mips_arch_info $arch isa_rev]
+
     # Set an appropriate ABI, handling dependencies between the pre-abi
     # options and the abi options.  This should mirror the abi and post-abi
     # code below.
@@ -1184,8 +1233,8 @@ proc mips-dg-options { args } {
     if { $abi_test_option_p } {
 	if { $eabi_p } {
 	    mips_make_test_option options "-mno-abicalls"
-	    if { $gp_size == 32 } {
-		mips_make_test_option options "-mfp32"
+	    if { $isa_rev < 6 && $gp_size == 32 } {
+		    mips_make_test_option options "-mfp32"
 	    }
 	}
 	if { [mips_using_mips16_p options]
@@ -1230,6 +1279,17 @@ proc mips-dg-options { args } {
 	    mips_make_test_option options "-mno-dsp"
 	    mips_make_test_option options "-mno-synci"
 	}
+        if { $isa_rev > 5 } {
+	    mips_make_test_option options "-mno-dsp"
+	    mips_make_test_option options "-mno-mips16"
+	    if { [mips_have_test_option_p options "-mdsp"] } {
+		mips_make_test_option options "-mfp64"
+	    }
+	    mips_make_test_option options "-mno-fix-r10000"
+	    mips_make_test_option options "-mno-paired-single"
+	    mips_make_test_option options "-mnan=2008"
+	    mips_make_test_option options "-mabs=2008"
+	}
 	unset arch
 	unset isa
 	unset isa_rev
diff --git a/gcc/testsuite/gcc.target/mips/movcc-1.c b/gcc/testsuite/gcc.target/mips/movcc-1.c
index b3fe188..7943fec 100644
--- a/gcc/testsuite/gcc.target/mips/movcc-1.c
+++ b/gcc/testsuite/gcc.target/mips/movcc-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "isa>=4" } */
+/* { dg-options "(HAS_MOVN)" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler "\tmovz\t" } } */
 /* { dg-final { scan-assembler "\tmovn\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/movcc-2.c b/gcc/testsuite/gcc.target/mips/movcc-2.c
index 2638d51..1926e64 100644
--- a/gcc/testsuite/gcc.target/mips/movcc-2.c
+++ b/gcc/testsuite/gcc.target/mips/movcc-2.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "isa>=4" } */
+/* { dg-options "(HAS_MOVN)" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler "\tmovz\t" } } */
 /* { dg-final { scan-assembler "\tmovn\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/movcc-3.c b/gcc/testsuite/gcc.target/mips/movcc-3.c
index f356465..55434b7 100644
--- a/gcc/testsuite/gcc.target/mips/movcc-3.c
+++ b/gcc/testsuite/gcc.target/mips/movcc-3.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "isa>=4 -mhard-float" } */
+/* { dg-options "(HAS_MOVN) -mhard-float" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler "\tmovt\t" } } */
 /* { dg-final { scan-assembler "\tmovf\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/msub-3.c b/gcc/testsuite/gcc.target/mips/msub-3.c
index aedd043..132db85 100644
--- a/gcc/testsuite/gcc.target/mips/msub-3.c
+++ b/gcc/testsuite/gcc.target/mips/msub-3.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
 /* This test requires widening_mul */
-/* { dg-options "isa_rev>=1 -mgp32 -fexpensive-optimizations" } */
+/* { dg-options "(HAS_MADD) -mgp32 -fexpensive-optimizations" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler-times "\tmsub\t" 2 } } */
 
diff --git a/gcc/testsuite/gcc.target/mips/msubu-3.c b/gcc/testsuite/gcc.target/mips/msubu-3.c
index 2e936eb..07cb7c7 100644
--- a/gcc/testsuite/gcc.target/mips/msubu-3.c
+++ b/gcc/testsuite/gcc.target/mips/msubu-3.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
 /* This test requires widening_mul */
-/* { dg-options "isa_rev>=1 -mgp32 -fexpensive-optimizations" } */
+/* { dg-options "(HAS_MADD) -mgp32 -fexpensive-optimizations" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler-times "\tmsubu\t" 2 } } */
 
diff --git a/gcc/testsuite/gcc.target/mips/mult-1.c b/gcc/testsuite/gcc.target/mips/mult-1.c
index 1038797..bd9757c 100644
--- a/gcc/testsuite/gcc.target/mips/mult-1.c
+++ b/gcc/testsuite/gcc.target/mips/mult-1.c
@@ -1,7 +1,7 @@
 /* For SI->DI widening multiplication we should use DINS to combine the two
    halves.  For Octeon use DMUL with explicit widening.  */
 /* This test requires widening_mul */
-/* { dg-options "-mgp64 isa_rev>=2 forbid_cpu=octeon.* -fexpensive-optimizations" } */
+/* { dg-options "-mgp64 (HAS_INS) (NOT_HAS_DMUL) -fexpensive-optimizations" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler "\tdins\t" } } */
 /* { dg-final { scan-assembler-not "\tdsll\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/neg-abs-2.c b/gcc/testsuite/gcc.target/mips/neg-abs-2.c
index 435751e..59e797d 100644
--- a/gcc/testsuite/gcc.target/mips/neg-abs-2.c
+++ b/gcc/testsuite/gcc.target/mips/neg-abs-2.c
@@ -1,7 +1,7 @@
 /* Make sure that we avoid abs.fmt and neg.fmt when the signs of NaNs
    matter.  */
 /* { dg-do compile } */
-/* { dg-options "-mhard-float -fno-finite-math-only" } */
+/* { dg-options "isa_rev<=5 -mhard-float -fno-finite-math-only -mabs=legacy" } */
 /* { dg-final { scan-assembler-not "\tneg.s\t" } } */
 /* { dg-final { scan-assembler-not "\tneg.d\t" } } */
 /* { dg-final { scan-assembler-not "\tabs.s\t" } } */
diff --git a/gcc/testsuite/gcc.target/mips/timode-1.c b/gcc/testsuite/gcc.target/mips/timode-1.c
index 606fee0..be3d317 100644
--- a/gcc/testsuite/gcc.target/mips/timode-1.c
+++ b/gcc/testsuite/gcc.target/mips/timode-1.c
@@ -1,4 +1,4 @@
-/* { dg-options "-mgp64" } */
+/* { dg-options "isa_rev<=5 -mgp64" } */
 /* { dg-skip-if "we deliberately use calls when optimizing for size" { *-*-* } { "-Os" } { "" } } */
 typedef int int128_t __attribute__((mode(TI)));
 typedef unsigned int uint128_t __attribute__((mode(TI)));
diff --git a/gcc/testsuite/gcc.target/mips/unaligned-1.c b/gcc/testsuite/gcc.target/mips/unaligned-1.c
index 938f52d..4888ca8 100644
--- a/gcc/testsuite/gcc.target/mips/unaligned-1.c
+++ b/gcc/testsuite/gcc.target/mips/unaligned-1.c
@@ -1,4 +1,4 @@
-/* { dg-options "-mgp64" } */
+/* { dg-options "isa_rev<=5 -mgp64" } */
 /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
 /* { dg-final { scan-assembler-times "\tsdl\t" 1 } } */
 /* { dg-final { scan-assembler-times "\tsdr\t" 1 } } */
diff --git a/libgcc/config.host b/libgcc/config.host
index 9903d15..b10d725 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -827,8 +827,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 c0c73ff..1783d11 100644
--- a/libgcc/config/mips/mips16.S
+++ b/libgcc/config/mips/mips16.S
@@ -23,12 +23,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #include "auto-host.h"
 
-#if defined(__mips_micromips) || defined(__mips_soft_float)
+#if defined(__mips_micromips) || defined(__mips_soft_float) \
+    || __mips_isa_rev >= 6
   /* Do nothing because this code is only needed when linking
      against mips16 hard-float objects.  Neither micromips code
-     nor soft-float code can be linked against mips16 hard-float
-     objects so we do not need these routines when building libgcc
-     for those cases.  */
+     nor soft-float nor MIPS R6 code can be linked against mips16
+     hard-float objects so we do not need these routines when
+     building libgcc for those cases.  */
 #else
 
 #if defined(HAVE_AS_MODULE)
-- 
1.9.4


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

* RE: [PATCHv2,MIPS 1/2] MIPS64r6 support
  2014-11-14 23:29 [PATCHv2,MIPS 1/2] MIPS64r6 support Matthew Fortune
@ 2014-12-12 21:49 ` Moore, Catherine
  2014-12-12 21:58   ` Matthew Fortune
  2014-12-19 20:20   ` Matthew Fortune
  0 siblings, 2 replies; 4+ messages in thread
From: Moore, Catherine @ 2014-12-12 21:49 UTC (permalink / raw)
  To: Matthew Fortune,
	'gcc-patches@gcc.gnu.org' (gcc-patches@gcc.gnu.org)
  Cc: Rich Fuhler, Steve Ellcey, Richard Sandiford

Hi Matthew,

> -----Original Message-----
> From: Matthew Fortune [mailto:Matthew.Fortune@imgtec.com]
> Sent: Friday, November 14, 2014 6:07 PM

Overall, this patch looks really good.  It took me a while to get through it, but I only have a couple of minor comments.

diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 02268f3..7797b31 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c

@@ -11896,6 +12052,15 @@ mips_hard_regno_mode_ok_p (unsigned int regno, machine_mode mode)
       if (TARGET_O32_FP64A_ABI && size <= 4 && (regno & 1) != 0)
        return false;

+      /* Prevent the use of odd-numbered registers for CCFmode with the
+        o32 FPXX ABI, otherwise allow them.
+        The FPXX ABI does not permit double-precision data to be placed
+        in odd-numbered registers and double-precision compares write
+        them as 64-bit values.  Without this restriction the R6 FPXX
+        ABI would not be able to execute in FR=1 FRE=1 mode.  */
+      if (mode == CCFmode && ISA_HAS_CCF)
+       return !(TARGET_FLOATXX && (regno & 1) != 0);
+
       /* Allow 64-bit vector modes for Loongson-2E/2F.  */
       if (TARGET_LOONGSON_VECTORS
          && (mode == V2SImode

I don't think we ever have CCFmode when ISA_HAS_CCF is false.  Maybe just check for CCFmode?
If there really is a need for both conditions, then the order of the checks needs to be reversed.  Also, the comment
is hard to follow.

How about:

/* The FPXX ABI requires double-precision values to be placed in even-numbered registers.  Disallow
     odd-numbered registers with CCFmode because CCF mode double-precision compares will write a 64-bit value
     to a register.  */

Did I get that right?


diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 8a38829..c110b5e 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h


-/* 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)
+/* ISA supports instructions MULT and MULTU.  */
+#define ISA_HAS_MULT           ISA_HAS_HILO
+

I preferred the definition in your original patch :
#define ISA_HAS_MULT	mips_isa_rev <= 5

Would you mind switching it back?

Okay with those changes.
Catherine


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

* RE: [PATCHv2,MIPS 1/2] MIPS64r6 support
  2014-12-12 21:49 ` Moore, Catherine
@ 2014-12-12 21:58   ` Matthew Fortune
  2014-12-19 20:20   ` Matthew Fortune
  1 sibling, 0 replies; 4+ messages in thread
From: Matthew Fortune @ 2014-12-12 21:58 UTC (permalink / raw)
  To: Moore, Catherine,
	'gcc-patches@gcc.gnu.org' (gcc-patches@gcc.gnu.org)
  Cc: Rich Fuhler, Steve Ellcey, Richard Sandiford

Moore, Catherine <Catherine_Moore@mentor.com> writes:
> Hi Matthew,
> 
> > -----Original Message-----
> > From: Matthew Fortune [mailto:Matthew.Fortune@imgtec.com]
> > Sent: Friday, November 14, 2014 6:07 PM
> 
> Overall, this patch looks really good.  It took me a while to get
> through it, but I only have a couple of minor comments.
> 
> diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index
> 02268f3..7797b31 100644
> --- a/gcc/config/mips/mips.c
> +++ b/gcc/config/mips/mips.c
> 
> @@ -11896,6 +12052,15 @@ mips_hard_regno_mode_ok_p (unsigned int regno,
> machine_mode mode)
>        if (TARGET_O32_FP64A_ABI && size <= 4 && (regno & 1) != 0)
>         return false;
> 
> +      /* Prevent the use of odd-numbered registers for CCFmode with the
> +        o32 FPXX ABI, otherwise allow them.
> +        The FPXX ABI does not permit double-precision data to be placed
> +        in odd-numbered registers and double-precision compares write
> +        them as 64-bit values.  Without this restriction the R6 FPXX
> +        ABI would not be able to execute in FR=1 FRE=1 mode.  */
> +      if (mode == CCFmode && ISA_HAS_CCF)
> +       return !(TARGET_FLOATXX && (regno & 1) != 0);
> +
>        /* Allow 64-bit vector modes for Loongson-2E/2F.  */
>        if (TARGET_LOONGSON_VECTORS
>           && (mode == V2SImode
> 
> I don't think we ever have CCFmode when ISA_HAS_CCF is false.  Maybe
> just check for CCFmode?

Good point. I'll remove the ISA_HAS_CCF part.

> If there really is a need for both conditions, then the order of the
> checks needs to be reversed.  Also, the comment is hard to follow.
> 
> How about:
> 
> /* The FPXX ABI requires double-precision values to be placed in even-
> numbered registers.  Disallow
>      odd-numbered registers with CCFmode because CCF mode double-
> precision compares will write a 64-bit value
>      to a register.  */
> 
> Did I get that right?

I think that captures it, thanks.

> diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index
> 8a38829..c110b5e 100644
> --- a/gcc/config/mips/mips.h
> +++ b/gcc/config/mips/mips.h
> 
> 
> -/* 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)
> +/* ISA supports instructions MULT and MULTU.  */
> +#define ISA_HAS_MULT           ISA_HAS_HILO
> +
> 
> I preferred the definition in your original patch :
> #define ISA_HAS_MULT	mips_isa_rev <= 5
> 
> Would you mind switching it back?

Fine with me.

I'll sync the work with trunk and do some testsuite runs to check for
regressions in the interim and commit early next week probably.

Thanks for the review,
Matthew

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

* RE: [PATCHv2,MIPS 1/2] MIPS64r6 support
  2014-12-12 21:49 ` Moore, Catherine
  2014-12-12 21:58   ` Matthew Fortune
@ 2014-12-19 20:20   ` Matthew Fortune
  1 sibling, 0 replies; 4+ messages in thread
From: Matthew Fortune @ 2014-12-19 20:20 UTC (permalink / raw)
  To: Moore, Catherine,
	'gcc-patches@gcc.gnu.org' (gcc-patches@gcc.gnu.org)
  Cc: Rich Fuhler, Steve Ellcey, Richard Sandiford

> Okay with those changes.

Committed as r218973

Thanks,
Matthew

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

end of thread, other threads:[~2014-12-19 20:19 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-14 23:29 [PATCHv2,MIPS 1/2] MIPS64r6 support Matthew Fortune
2014-12-12 21:49 ` Moore, Catherine
2014-12-12 21:58   ` Matthew Fortune
2014-12-19 20:20   ` Matthew Fortune

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