diff mbox

[v4] MIPS: IEEE 754-2008 features support

Message ID alpine.DEB.1.10.1307262213460.32382@tp.orcam.me.uk
State New
Headers show

Commit Message

Maciej W. Rozycki July 26, 2013, 11:57 p.m. UTC
On Fri, 19 Jul 2013, Richard Sandiford wrote:

> > while the 2008 
> > NaN encoding has its shortcomings, e.g. unlike with the legacy encoding 
> > there's no single sNaN bit pattern to preset FPRs or variables with to 
> > catch uninitialised use that would work across all the floating-point 
> > formats (S, D and PS).  So it seems to me like there's no single superior 
> > setting we could make the default for a group option.
> 
> I see what you mean, and I suppose it wouldn't be too bad having
> separate -mabs=2008 and -mmac=2008 options for the legacy IEEE case.
> But when going to the trouble of switching NAN encoding, which needs a
> separate runtime, it seemed a shame that we couldn't also rely on the
> new improved ABS/NEG behaviour in that runtime too.  Instead we have
> to potentially pass all three of -mnan=2008 -mabs=2008 -mmac=2008
> in order to get what other targets get.  Oh well...

 I think the current situation does not preclude adding your proposed 
-mfp-model={legacy|2008} option in the future, especially if 
-mmac={legacy|2008} is eventually implemented, however I also think we 
ought to consider a valid use case first.

> > 1. Conceptually I see the toolchain as a whole and I don't see a value in 
> >    GCC producing known-unsupported assembly and relying on the assembler 
> >    (or the linker if applicable) to complain.  I agree pointing at the 
> >    other tool being incapable or obsolete is a useful practice, but I also 
> >    think a clear message from GCC itself would be more appropriate (e.g. 
> >    "`-mfoo' unsupported, please reconfigure against current binutils").
> 
> But doing that consistently would mean e.g. that we would need to test
> assembler support for each individual -march= option, since new -march=
> options are added fairly often.  It seems a lot of hassle to do that
> just so that we can force the user to rebuild GCC from the same sources
> as before.  I think it's more user-friendly to include support for -mfoo
> and assume that the assembler supports whatever's needed -- leaving it
> to issue an error if not -- both because the problem tool is the one that
> reports the error, and because we don't force users to rebuild GCC when
> the first build could quite easily have had the feature they wanted.

 Yes, I have to admit that it is a bit inconvenient.

> > 2. Technically I think we have an actual problem here, e.g. in the example 
> >    you referred we have a situation where GCC supports microMIPS 
> >    compilation in all cases, however non-microMIPS code is different
> >    depending on whether the compiler has been configured against modern or 
> >    obsolete binutils.  Now the latter case may prompt someone to upgrade
> >    binutils, but there is nothing to prompt that person to reconfigure GCC
> >    afterwards.  As a result we have two cases of a toolchain comprised of 
> >    the same versions of both GCC and binutils, but depending on the 
> >    "history" of the GCC binaries code produced will be different.  I think
> >    this is subtler and riskier than just rejecting the relevant compiler 
> >    option outright.
> 
> I think your argument is that it's bad for things like
> __attribute__((nomicromips)) to produce different code depending on the
> configured assembler, and that we should therefore just reject the attribute
> if the assembler doesn't support ".set nomicromips".  Is that right?

 No, __attribute__((nomicromips)) is a no-op if applied to source compiled 
to standard MIPS or MIPS16 code and following the principle I support here 
a compiler configured against a non-microMIPS assembler by definition 
could not be switched into the microMIPS mode.  Therefore the attribute 
can simply be silently ignored.

> That has negative consequences too though.  People often use GCC version
> checks to decide whether an attribute is supported.  Conditionally
> disabling even nomicromips would force users to have an autoconf-style
> test instead.  And the point is that __attribute__((nomicromips))
> indicates that the user _doesn't_ want a function to be micromips,
> so it wouldn't be very friendly to force them to upgrade to a binutils
> that does support micromips and then rebuild GCC.

 I consider actual feature tests always preferable to version checks.

> Instead the idea is that __attribute__((nomicromips)) should behave in
> the same way as when nomicromips is the default.
> 
> > Applying this to the 2008-NaN case the compiler would have to refrain from 
> > producing the .nan directive in the legacy case if built against old 
> > binutils but would produce the directive regardless in the 2008 case.  I 
> > don't feel safe with such an arrangement.
> 
> Hmm, I think you're arguing against something different from what I was
> suggesting.  I was saying that (within config/mips) the configure test
> should just control whether it's safe to use .nan _when no -mnan option
> has been given_.  (I.e. it shouldn't affect the case when -mnan is passed.)
> If no option is given, we should put a ".nan legacy" in there anyway for
> good measure if possible, but we can't if binutils is too old.  That's
> already what your patch does and I think we should keep that bit.

 The thing here is the high-level consequences of the NaN setting are 
different from ones with the microMIPS setting.

 In the latter case if you have an unannotated generated assembly source 
and assemble it with the "wrong" -mmicromips/-mno-micromips setting then 
two situations are possible: either the source will assemble and then link 
and work correctly or it will break either at the assembly stage (because 
of instructions unsupported in the mode selected) or at the link stage 
(because of unsupported cross-mode jumps or suchlike).  In neither case 
will incorrect computational results be produced.

 In the NaN case, assembling unannotated sources that have NaN data 
generated with the "wrong" -mnan= setting will assemble successfully and 
then either break at the link stage (because of NAN2008 ELF file header 
flag incompatibility) or link successfully and silently produce incorrect 
computational results.

 However picking generated assembly sources for later assembling is I 
believe not done very frequently, so I'll stop arguing here.

> I was suggesting that the behaviour of the -mnan option should be
> the same regardless of which version of binutils you use.  It should
> always pass the -mnan down to the assembler, and it should always
> generate the .nan directive.

 Here's an update to the previous version of the change, followed by the 
updated change itself.  I have manually verified compiler output for the 
presence or absence of a .nan directive, as applicable, across the six 
relevant cases, i.e. no option, -mnan=legacy and -mnan=2008 with old and 
new binutils each.  For consistency I have adjusted the default for -mabs= 
as well; no functional change here.

 OK?

2013-07-26  Maciej W. Rozycki  <macro@codesourcery.com>

	gcc/
	* config/mips/linux.h (GLIBC_DYNAMIC_LINKER): Handle `-mnan=2008'.
	(UCLIBC_DYNAMIC_LINKER): New macro.
	* config/mips/linux64.h (GLIBC_DYNAMIC_LINKER32): Handle 
	`-mnan=2008'.
	(GLIBC_DYNAMIC_LINKER64, GLIBC_DYNAMIC_LINKERN32): Likewise.
	(UCLIBC_DYNAMIC_LINKER32): Undefine macro first.  Handle 
	`-mnan=2008'.
	(UCLIBC_DYNAMIC_LINKER64): Redefine macro.
	(UCLIBC_DYNAMIC_LINKERN32): Likewise.
	* config/mips/mips-modes.def: Remove RESET_FLOAT_FORMAT calls
	for SF and DF modes.  Use ieee_quad_format for TF mode.
	* config/mips/mips-opts.h (mips_ieee_754_setting): New enum.
	* config/mips/mips.c (mips_file_start): Output a `.nan' directive.
	(mips_option_override): Handle `-mnan=legacy'.
	* config/mips/mips.h (TARGET_CPU_CPP_BUILTINS): Handle 
	`-mabs=2008' and `-mnan=2008'.
	(OPTION_DEFAULT_SPECS): Add "nan" default.
	(ASM_SPEC): Handle `-mnan='.
	[!HAVE_AS_NAN] (HAVE_AS_NAN): New macro.
	* config/mips/mips.md (abs<mode>2): Handle `-mabs=2008', update
	comment accordingly.
	(neg<mode>2): Likewise.
	* config/mips/mips.opt (mabs, mnan): New options.
	* doc/install.texi (Configuration): Document `--with-nan=' option.
	* doc/invoke.texi (Option Summary): List MIPS `-mabs=' and 
	`-mnan=' options.
	(MIPS Options): Document them.
	* config.gcc <mips*-*-*>: Handle `--with-nan='.
	* configure.ac <mips*-*-*>: Check for GAS `-mnan=2008' support.
	* configure: Regenerate.
	* config.in: Regenerate.

	gcc/testsuite/
	* gcc.target/mips/fabs-2008.c: New test case.
	* gcc.target/mips/fabs-legacy.c: New test case.
	* gcc.target/mips/fabsf-2008.c: New test case.
	* gcc.target/mips/fabsf-legacy.c: New test case.
	* gcc.target/mips/fneg-2008.c: New test case.
	* gcc.target/mips/fneg-legacy.c: New test case.
	* gcc.target/mips/fneg-2008.c: New test case.
	* gcc.target/mips/fneg-legacy.c: New test case.
	* gcc.target/mips/nan-2008.c: New test case.
	* gcc.target/mips/nan-legacy.c: New test case.
	* gcc.target/mips/nanf-2008.c: New test case.
	* gcc.target/mips/nanf-legacy.c: New test case.
	* gcc.target/mips/nans-2008.c: New test case.
	* gcc.target/mips/nans-legacy.c: New test case.
	* gcc.target/mips/nansf-2008.c: New test case.
	* gcc.target/mips/nansf-legacy.c: New test case.
	* gcc.target/mips/mips.exp: Handle `-mabs=' and `-mnan='.

  Maciej

gcc-mips-nan2008-as-nan.diff

Comments

Richard Sandiford July 27, 2013, 3:29 p.m. UTC | #1
"Maciej W. Rozycki" <macro@codesourcery.com> writes:
> 2013-07-26  Maciej W. Rozycki  <macro@codesourcery.com>
>
> 	gcc/
> 	* config/mips/linux.h (GLIBC_DYNAMIC_LINKER): Handle `-mnan=2008'.
> 	(UCLIBC_DYNAMIC_LINKER): New macro.
> 	* config/mips/linux64.h (GLIBC_DYNAMIC_LINKER32): Handle 
> 	`-mnan=2008'.
> 	(GLIBC_DYNAMIC_LINKER64, GLIBC_DYNAMIC_LINKERN32): Likewise.
> 	(UCLIBC_DYNAMIC_LINKER32): Undefine macro first.  Handle 
> 	`-mnan=2008'.
> 	(UCLIBC_DYNAMIC_LINKER64): Redefine macro.
> 	(UCLIBC_DYNAMIC_LINKERN32): Likewise.
> 	* config/mips/mips-modes.def: Remove RESET_FLOAT_FORMAT calls
> 	for SF and DF modes.  Use ieee_quad_format for TF mode.
> 	* config/mips/mips-opts.h (mips_ieee_754_setting): New enum.
> 	* config/mips/mips.c (mips_file_start): Output a `.nan' directive.
> 	(mips_option_override): Handle `-mnan=legacy'.
> 	* config/mips/mips.h (TARGET_CPU_CPP_BUILTINS): Handle 
> 	`-mabs=2008' and `-mnan=2008'.
> 	(OPTION_DEFAULT_SPECS): Add "nan" default.
> 	(ASM_SPEC): Handle `-mnan='.
> 	[!HAVE_AS_NAN] (HAVE_AS_NAN): New macro.
> 	* config/mips/mips.md (abs<mode>2): Handle `-mabs=2008', update
> 	comment accordingly.
> 	(neg<mode>2): Likewise.
> 	* config/mips/mips.opt (mabs, mnan): New options.
> 	* doc/install.texi (Configuration): Document `--with-nan=' option.
> 	* doc/invoke.texi (Option Summary): List MIPS `-mabs=' and 
> 	`-mnan=' options.
> 	(MIPS Options): Document them.
> 	* config.gcc <mips*-*-*>: Handle `--with-nan='.
> 	* configure.ac <mips*-*-*>: Check for GAS `-mnan=2008' support.
> 	* configure: Regenerate.
> 	* config.in: Regenerate.
>
> 	gcc/testsuite/
> 	* gcc.target/mips/fabs-2008.c: New test case.
> 	* gcc.target/mips/fabs-legacy.c: New test case.
> 	* gcc.target/mips/fabsf-2008.c: New test case.
> 	* gcc.target/mips/fabsf-legacy.c: New test case.
> 	* gcc.target/mips/fneg-2008.c: New test case.
> 	* gcc.target/mips/fneg-legacy.c: New test case.
> 	* gcc.target/mips/fneg-2008.c: New test case.
> 	* gcc.target/mips/fneg-legacy.c: New test case.
> 	* gcc.target/mips/nan-2008.c: New test case.
> 	* gcc.target/mips/nan-legacy.c: New test case.
> 	* gcc.target/mips/nanf-2008.c: New test case.
> 	* gcc.target/mips/nanf-legacy.c: New test case.
> 	* gcc.target/mips/nans-2008.c: New test case.
> 	* gcc.target/mips/nans-legacy.c: New test case.
> 	* gcc.target/mips/nansf-2008.c: New test case.
> 	* gcc.target/mips/nansf-legacy.c: New test case.
> 	* gcc.target/mips/mips.exp: Handle `-mabs=' and `-mnan='.

OK, thanks.

Richard
Maciej W. Rozycki July 29, 2013, 2:38 p.m. UTC | #2
On Sat, 27 Jul 2013, Richard Sandiford wrote:

> > 	gcc/
> > 	* config/mips/linux.h (GLIBC_DYNAMIC_LINKER): Handle `-mnan=2008'.
> > 	(UCLIBC_DYNAMIC_LINKER): New macro.
> > 	* config/mips/linux64.h (GLIBC_DYNAMIC_LINKER32): Handle 
> > 	`-mnan=2008'.
> > 	(GLIBC_DYNAMIC_LINKER64, GLIBC_DYNAMIC_LINKERN32): Likewise.
> > 	(UCLIBC_DYNAMIC_LINKER32): Undefine macro first.  Handle 
> > 	`-mnan=2008'.
> > 	(UCLIBC_DYNAMIC_LINKER64): Redefine macro.
> > 	(UCLIBC_DYNAMIC_LINKERN32): Likewise.
> > 	* config/mips/mips-modes.def: Remove RESET_FLOAT_FORMAT calls
> > 	for SF and DF modes.  Use ieee_quad_format for TF mode.
> > 	* config/mips/mips-opts.h (mips_ieee_754_setting): New enum.
> > 	* config/mips/mips.c (mips_file_start): Output a `.nan' directive.
> > 	(mips_option_override): Handle `-mnan=legacy'.
> > 	* config/mips/mips.h (TARGET_CPU_CPP_BUILTINS): Handle 
> > 	`-mabs=2008' and `-mnan=2008'.
> > 	(OPTION_DEFAULT_SPECS): Add "nan" default.
> > 	(ASM_SPEC): Handle `-mnan='.
> > 	[!HAVE_AS_NAN] (HAVE_AS_NAN): New macro.
> > 	* config/mips/mips.md (abs<mode>2): Handle `-mabs=2008', update
> > 	comment accordingly.
> > 	(neg<mode>2): Likewise.
> > 	* config/mips/mips.opt (mabs, mnan): New options.
> > 	* doc/install.texi (Configuration): Document `--with-nan=' option.
> > 	* doc/invoke.texi (Option Summary): List MIPS `-mabs=' and 
> > 	`-mnan=' options.
> > 	(MIPS Options): Document them.
> > 	* config.gcc <mips*-*-*>: Handle `--with-nan='.
> > 	* configure.ac <mips*-*-*>: Check for GAS `-mnan=2008' support.
> > 	* configure: Regenerate.
> > 	* config.in: Regenerate.
> >
> > 	gcc/testsuite/
> > 	* gcc.target/mips/fabs-2008.c: New test case.
> > 	* gcc.target/mips/fabs-legacy.c: New test case.
> > 	* gcc.target/mips/fabsf-2008.c: New test case.
> > 	* gcc.target/mips/fabsf-legacy.c: New test case.
> > 	* gcc.target/mips/fneg-2008.c: New test case.
> > 	* gcc.target/mips/fneg-legacy.c: New test case.
> > 	* gcc.target/mips/fneg-2008.c: New test case.
> > 	* gcc.target/mips/fneg-legacy.c: New test case.
> > 	* gcc.target/mips/nan-2008.c: New test case.
> > 	* gcc.target/mips/nan-legacy.c: New test case.
> > 	* gcc.target/mips/nanf-2008.c: New test case.
> > 	* gcc.target/mips/nanf-legacy.c: New test case.
> > 	* gcc.target/mips/nans-2008.c: New test case.
> > 	* gcc.target/mips/nans-legacy.c: New test case.
> > 	* gcc.target/mips/nansf-2008.c: New test case.
> > 	* gcc.target/mips/nansf-legacy.c: New test case.
> > 	* gcc.target/mips/mips.exp: Handle `-mabs=' and `-mnan='.
> 
> OK, thanks.

 Committed now, thanks for your review.

  Maciej
diff mbox

Patch

Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips-opts.h
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips-opts.h	2013-07-26 19:20:34.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/mips-opts.h	2013-07-26 22:34:54.078694917 +0100
@@ -29,6 +29,7 @@  enum mips_code_readable_setting {
 
 /* Enumerates the setting of the -mabs and -mnan options.  */
 enum mips_ieee_754_setting {
+  MIPS_IEEE_754_DEFAULT,
   MIPS_IEEE_754_LEGACY,
   MIPS_IEEE_754_2008
 };
Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips.c	2013-07-26 22:06:23.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/mips.c	2013-07-26 22:35:57.097753889 +0100
@@ -8846,11 +8846,10 @@  mips_file_start (void)
     fprintf (asm_out_file, "\t.section .gcc_compiled_long%d\n"
 	     "\t.previous\n", TARGET_LONG64 ? 64 : 32);
 
-#ifdef HAVE_AS_NAN
   /* Record the NaN encoding.  */
-  fprintf (asm_out_file, "\t.nan\t%s\n",
-	   mips_nan == MIPS_IEEE_754_2008 ? "2008" : "legacy");
-#endif
+  if (HAVE_AS_NAN || mips_nan != MIPS_IEEE_754_DEFAULT)
+    fprintf (asm_out_file, "\t.nan\t%s\n",
+	     mips_nan == MIPS_IEEE_754_2008 ? "2008" : "legacy");
 
 #ifdef HAVE_AS_GNU_ATTRIBUTE
   {
Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips.h
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips.h	2013-07-26 22:06:23.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/mips.h	2013-07-26 22:33:09.058694296 +0100
@@ -2905,6 +2905,10 @@  while (0)
 #define HAVE_AS_TLS 0
 #endif
 
+#ifndef HAVE_AS_NAN
+#define HAVE_AS_NAN 0
+#endif
+
 #ifndef USED_FOR_TARGET
 /* Information about ".set noFOO; ...; .set FOO" blocks.  */
 struct mips_asm_switch {
Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips.opt
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips.opt	2013-07-26 22:06:23.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/mips.opt	2013-07-26 22:41:59.688697021 +0100
@@ -206,11 +206,11 @@  Target Report Mask(FUSED_MADD)
 Generate floating-point multiply-add instructions
 
 mabs=
-Target RejectNegative Joined Enum(mips_ieee_754_value) Var(mips_abs) Init(MIPS_IEEE_754_LEGACY)
+Target RejectNegative Joined Enum(mips_ieee_754_value) Var(mips_abs) Init(MIPS_IEEE_754_DEFAULT)
 -mabs=MODE	Select the IEEE 754 ABS/NEG instruction execution mode
 
 mnan=
-Target RejectNegative Joined Enum(mips_ieee_754_value) Var(mips_nan) Init(MIPS_IEEE_754_LEGACY) Condition(HAVE_AS_NAN)
+Target RejectNegative Joined Enum(mips_ieee_754_value) Var(mips_nan) Init(MIPS_IEEE_754_DEFAULT)
 -mnan=ENCODING	Select the IEEE 754 NaN data encoding
 
 Enum
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nan-2008.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/testsuite/gcc.target/mips/nan-2008.c	2013-07-26 19:20:34.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nan-2008.c	2013-07-26 22:40:29.668690118 +0100
@@ -1,6 +1,5 @@ 
 /* { dg-do compile } */
 /* { dg-options "-mnan=2008 -EB" } */
-/* { dg-require-effective-target mips_nan } */
 
 double d = __builtin_nan ("");
 
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nan-legacy.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/testsuite/gcc.target/mips/nan-legacy.c	2013-07-26 19:20:34.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nan-legacy.c	2013-07-26 22:40:34.168698091 +0100
@@ -1,6 +1,5 @@ 
 /* { dg-do compile } */
 /* { dg-options "-mnan=legacy -EB" } */
-/* { dg-require-effective-target mips_nan } */
 
 double d = __builtin_nan ("");
 
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nanf-2008.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/testsuite/gcc.target/mips/nanf-2008.c	2013-07-26 19:20:34.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nanf-2008.c	2013-07-26 22:40:37.668698164 +0100
@@ -1,6 +1,5 @@ 
 /* { dg-do compile } */
 /* { dg-options "-mnan=2008 -EB" } */
-/* { dg-require-effective-target mips_nan } */
 
 float f = __builtin_nanf ("");
 
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nanf-legacy.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/testsuite/gcc.target/mips/nanf-legacy.c	2013-07-26 19:20:34.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nanf-legacy.c	2013-07-26 22:40:40.668694832 +0100
@@ -1,6 +1,5 @@ 
 /* { dg-do compile } */
 /* { dg-options "-mnan=legacy -EB" } */
-/* { dg-require-effective-target mips_nan } */
 
 float f = __builtin_nanf ("");
 
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nans-2008.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/testsuite/gcc.target/mips/nans-2008.c	2013-07-26 19:20:34.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nans-2008.c	2013-07-26 22:40:44.168689757 +0100
@@ -1,6 +1,5 @@ 
 /* { dg-do compile } */
 /* { dg-options "-mnan=2008 -EB" } */
-/* { dg-require-effective-target mips_nan } */
 
 double ds = __builtin_nans ("");
 
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nans-legacy.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/testsuite/gcc.target/mips/nans-legacy.c	2013-07-26 19:20:34.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nans-legacy.c	2013-07-26 22:40:47.668730098 +0100
@@ -1,6 +1,5 @@ 
 /* { dg-do compile } */
 /* { dg-options "-mnan=legacy -EB" } */
-/* { dg-require-effective-target mips_nan } */
 
 double ds = __builtin_nans ("");
 
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nansf-2008.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/testsuite/gcc.target/mips/nansf-2008.c	2013-07-26 19:20:34.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nansf-2008.c	2013-07-26 22:40:53.168694194 +0100
@@ -1,6 +1,5 @@ 
 /* { dg-do compile } */
 /* { dg-options "-mnan=2008 -EB" } */
-/* { dg-require-effective-target mips_nan } */
 
 float fs = __builtin_nansf ("");
 
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nansf-legacy.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/testsuite/gcc.target/mips/nansf-legacy.c	2013-07-26 19:20:34.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nansf-legacy.c	2013-07-26 22:40:56.668693901 +0100
@@ -1,6 +1,5 @@ 
 /* { dg-do compile } */
 /* { dg-options "-mnan=legacy -EB" } */
-/* { dg-require-effective-target mips_nan } */
 
 float fs = __builtin_nansf ("");
 
Index: gcc-fsf-trunk-quilt/gcc/testsuite/lib/target-supports.exp
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/testsuite/lib/target-supports.exp	2013-07-26 19:20:34.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/testsuite/lib/target-supports.exp	2013-07-26 19:04:06.000000000 +0100
@@ -975,18 +975,6 @@  proc check_effective_target_mips_eabi { 
     }]
 }
 
-# Return 1 if this is a MIPS target supporting -mnan=.
-# Old versions of binutils may not support this option.
-
-proc check_effective_target_mips_nan { } {
-    if { ![istarget mips*-*-*] } {
-	return 0
-    }
-    return [check_no_compiler_messages mips_nan object {
-	int dummy;
-    } "-mnan=2008"]
-}
-
 # Return 1 if the current multilib does not generate PIC by default.
 
 proc check_effective_target_nonpic { } {

gcc-mips-nan2008.diff
Index: gcc-fsf-trunk-quilt/gcc/config.gcc
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config.gcc	2013-07-26 19:03:41.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config.gcc	2013-07-26 19:20:34.228697260 +0100
@@ -3546,7 +3546,7 @@  case "${target}" in
 		;;
 
 	mips*-*-*)
-		supported_defaults="abi arch arch_32 arch_64 float fpu tune tune_32 tune_64 divide llsc mips-plt synci"
+		supported_defaults="abi arch arch_32 arch_64 float fpu nan tune tune_32 tune_64 divide llsc mips-plt synci"
 
 		case ${with_float} in
 		"" | soft | hard)
@@ -3568,6 +3568,16 @@  case "${target}" in
 			;;
 		esac
 
+		case ${with_nan} in
+		"" | 2008 | legacy)
+			# OK
+			;;
+		*)
+			echo "Unknown NaN encoding used in --with-nan=$with_nan" 1>&2
+			exit 1
+			;;
+		esac
+
 		case ${with_abi} in
 		"" | 32 | o64 | n32 | 64 | eabi)
 			# OK
@@ -3927,7 +3937,7 @@  case ${target} in
 esac
 
 t=
-all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu divide llsc mips-plt synci tls"
+all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan divide llsc mips-plt synci tls"
 for option in $all_defaults
 do
 	eval "val=\$with_"`echo $option | sed s/-/_/g`
Index: gcc-fsf-trunk-quilt/gcc/config.in
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config.in	2013-07-26 18:39:51.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config.in	2013-07-26 19:20:34.228697260 +0100
@@ -417,6 +417,12 @@ 
 #endif
 
 
+/* Define if the assembler understands -mnan=. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_NAN
+#endif
+
+
 /* Define if your assembler supports the -no-mul-bug-abort option. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_NO_MUL_BUG_ABORT_OPTION
Index: gcc-fsf-trunk-quilt/gcc/config/mips/linux.h
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/linux.h	2013-07-26 18:39:51.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/linux.h	2013-07-26 19:20:34.228697260 +0100
@@ -17,4 +17,9 @@  You should have received a copy of the G
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
-#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
+#define GLIBC_DYNAMIC_LINKER \
+  "%{mnan=2008:/lib/ld-linux-mipsn8.so.1;:/lib/ld.so.1}"
+
+#undef UCLIBC_DYNAMIC_LINKER
+#define UCLIBC_DYNAMIC_LINKER \
+  "%{mnan=2008:/lib/ld-uClibc-mipsn8.so.0;:/lib/ld-uClibc.so.0}"
Index: gcc-fsf-trunk-quilt/gcc/config/mips/linux64.h
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/linux64.h	2013-07-26 18:39:51.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/linux64.h	2013-07-26 19:20:34.228697260 +0100
@@ -22,10 +22,22 @@  along with GCC; see the file COPYING3.  
 #define GNU_USER_LINK_EMULATION64 "elf64%{EB:b}%{EL:l}tsmip"
 #define GNU_USER_LINK_EMULATIONN32 "elf32%{EB:b}%{EL:l}tsmipn32"
 
-#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
-#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld.so.1"
-#define GLIBC_DYNAMIC_LINKERN32 "/lib32/ld.so.1"
-#define UCLIBC_DYNAMIC_LINKERN32 "/lib32/ld-uClibc.so.0"
+#define GLIBC_DYNAMIC_LINKER32 \
+  "%{mnan=2008:/lib/ld-linux-mipsn8.so.1;:/lib/ld.so.1}"
+#define GLIBC_DYNAMIC_LINKER64 \
+  "%{mnan=2008:/lib64/ld-linux-mipsn8.so.1;:/lib64/ld.so.1}"
+#define GLIBC_DYNAMIC_LINKERN32 \
+  "%{mnan=2008:/lib32/ld-linux-mipsn8.so.1;:/lib32/ld.so.1}"
+
+#undef UCLIBC_DYNAMIC_LINKER32
+#define UCLIBC_DYNAMIC_LINKER32 \
+  "%{mnan=2008:/lib/ld-uClibc-mipsn8.so.0;:/lib/ld-uClibc.so.0}"
+#undef UCLIBC_DYNAMIC_LINKER64
+#define UCLIBC_DYNAMIC_LINKER64 \
+  "%{mnan=2008:/lib/ld64-uClibc-mipsn8.so.0;:/lib/ld64-uClibc.so.0}"
+#define UCLIBC_DYNAMIC_LINKERN32 \
+  "%{mnan=2008:/lib32/ld-uClibc-mipsn8.so.0;:/lib32/ld-uClibc.so.0}"
+
 #define BIONIC_DYNAMIC_LINKERN32 "/system/bin/linker32"
 #define GNU_USER_DYNAMIC_LINKERN32 \
   CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERN32, UCLIBC_DYNAMIC_LINKERN32, \
Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips-modes.def
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips-modes.def	2013-07-26 18:39:51.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/mips-modes.def	2013-07-26 19:20:34.228697260 +0100
@@ -17,12 +17,7 @@  You should have received a copy of the G
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
-/* MIPS has a quirky almost-IEEE format for all its
-   floating point.  */
-RESET_FLOAT_FORMAT (SF, mips_single_format);
-RESET_FLOAT_FORMAT (DF, mips_double_format);
-
-FLOAT_MODE (TF, 16, mips_quad_format);
+FLOAT_MODE (TF, 16, ieee_quad_format);
 
 /* Vector modes.  */
 VECTOR_MODES (INT, 4);        /* V4QI  V2HI      */
Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips-opts.h
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips-opts.h	2013-07-26 18:39:51.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/mips-opts.h	2013-07-27 00:16:54.078378235 +0100
@@ -27,6 +27,13 @@  enum mips_code_readable_setting {
   CODE_READABLE_YES
 };
 
+/* Enumerates the setting of the -mabs and -mnan options.  */
+enum mips_ieee_754_setting {
+  MIPS_IEEE_754_DEFAULT,
+  MIPS_IEEE_754_LEGACY,
+  MIPS_IEEE_754_2008
+};
+
 /* Enumerates the setting of the -mr10k-cache-barrier option.  */
 enum mips_r10k_cache_barrier_setting {
   R10K_CACHE_BARRIER_NONE,
Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips.c
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips.c	2013-07-26 19:03:57.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/mips.c	2013-07-27 00:16:54.078378235 +0100
@@ -8846,6 +8846,11 @@  mips_file_start (void)
     fprintf (asm_out_file, "\t.section .gcc_compiled_long%d\n"
 	     "\t.previous\n", TARGET_LONG64 ? 64 : 32);
 
+  /* Record the NaN encoding.  */
+  if (HAVE_AS_NAN || mips_nan != MIPS_IEEE_754_DEFAULT)
+    fprintf (asm_out_file, "\t.nan\t%s\n",
+	     mips_nan == MIPS_IEEE_754_2008 ? "2008" : "legacy");
+
 #ifdef HAVE_AS_GNU_ATTRIBUTE
   {
     int attr;
@@ -16983,6 +16988,15 @@  mips_option_override (void)
 	}
     }
 
+  /* Pre-IEEE 754-2008 MIPS hardware has a quirky almost-IEEE format
+     for all its floating point.  */
+  if (mips_nan != MIPS_IEEE_754_2008)
+    {
+      REAL_MODE_FORMAT (SFmode) = &mips_single_format;
+      REAL_MODE_FORMAT (DFmode) = &mips_double_format;
+      REAL_MODE_FORMAT (TFmode) = &mips_quad_format;
+    }
+
   /* Make sure that the user didn't turn off paired single support when
      MIPS-3D support is requested.  */
   if (TARGET_MIPS3D
Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips.h
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips.h	2013-07-26 19:01:56.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/mips.h	2013-07-27 00:16:54.078378235 +0100
@@ -507,6 +507,12 @@  struct mips_cpu_info {
       if (TARGET_PAIRED_SINGLE_FLOAT)					\
 	builtin_define ("__mips_paired_single_float");			\
 									\
+      if (mips_abs == MIPS_IEEE_754_2008)				\
+	builtin_define ("__mips_abs2008");				\
+									\
+      if (mips_nan == MIPS_IEEE_754_2008)				\
+	builtin_define ("__mips_nan2008");				\
+									\
       if (TARGET_BIG_ENDIAN)						\
 	{								\
 	  builtin_define_std ("MIPSEB");				\
@@ -743,6 +749,7 @@  struct mips_cpu_info {
    --with-abi is ignored if -mabi is specified.
    --with-float is ignored if -mhard-float or -msoft-float are
      specified.
+   --with-nan is ignored if -mnan is specified.
    --with-divide is ignored if -mdivide-traps or -mdivide-breaks are
      specified. */
 #define OPTION_DEFAULT_SPECS \
@@ -755,6 +762,7 @@  struct mips_cpu_info {
   {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
   {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \
   {"fpu", "%{!msingle-float:%{!mdouble-float:-m%(VALUE)-float}}" }, \
+  {"nan", "%{!mnan=*:-mnan=%(VALUE)}" }, \
   {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \
   {"llsc", "%{!mllsc:%{!mno-llsc:-m%(VALUE)}}" }, \
   {"mips-plt", "%{!mplt:%{!mno-plt:-m%(VALUE)}}" }, \
@@ -1160,7 +1168,7 @@  struct mips_cpu_info {
 %(subtarget_asm_debugging_spec) \
 %{mabi=*} %{!mabi=*: %(asm_abi_default_spec)} \
 %{mgp32} %{mgp64} %{march=*} %{mxgot:-xgot} \
-%{mfp32} %{mfp64} \
+%{mfp32} %{mfp64} %{mnan=*} \
 %{mshared} %{mno-shared} \
 %{msym32} %{mno-sym32} \
 %{mtune=*} \
@@ -2897,6 +2905,10 @@  while (0)
 #define HAVE_AS_TLS 0
 #endif
 
+#ifndef HAVE_AS_NAN
+#define HAVE_AS_NAN 0
+#endif
+
 #ifndef USED_FOR_TARGET
 /* Information about ".set noFOO; ...; .set FOO" blocks.  */
 struct mips_asm_switch {
Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips.md
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips.md	2013-07-26 19:01:56.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/mips.md	2013-07-26 19:24:47.798693582 +0100
@@ -2711,14 +2711,15 @@ 
 ;; Do not use the integer abs macro instruction, since that signals an
 ;; exception on -2147483648 (sigh).
 
-;; abs.fmt is an arithmetic instruction and treats all NaN inputs as
-;; invalid; it does not clear their sign bits.  We therefore can't use
-;; abs.fmt if the signs of NaNs matter.
+;; The "legacy" (as opposed to "2008") form of ABS.fmt is an arithmetic
+;; instruction that treats all NaN inputs as invalid; it does not clear
+;; their sign bit.  We therefore can't use that form if the signs of
+;; NaNs matter.
 
 (define_insn "abs<mode>2"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
 	(abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
-  "!HONOR_NANS (<MODE>mode)"
+  "mips_abs == MIPS_IEEE_754_2008 || !HONOR_NANS (<MODE>mode)"
   "abs.<fmt>\t%0,%1"
   [(set_attr "type" "fabs")
    (set_attr "mode" "<UNITMODE>")])
@@ -2793,14 +2794,15 @@ 
   [(set_attr "alu_type"	"sub")
    (set_attr "mode"	"DI")])
 
-;; neg.fmt is an arithmetic instruction and treats all NaN inputs as
-;; invalid; it does not flip their sign bit.  We therefore can't use
-;; neg.fmt if the signs of NaNs matter.
+;; The "legacy" (as opposed to "2008") form of NEG.fmt is an arithmetic
+;; instruction that treats all NaN inputs as invalid; it does not flip
+;; their sign bit.  We therefore can't use that form if the signs of
+;; NaNs matter.
 
 (define_insn "neg<mode>2"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
 	(neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
-  "!HONOR_NANS (<MODE>mode)"
+  "mips_abs == MIPS_IEEE_754_2008 || !HONOR_NANS (<MODE>mode)"
   "neg.<fmt>\t%0,%1"
   [(set_attr "type" "fneg")
    (set_attr "mode" "<UNITMODE>")])
Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips.opt
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips.opt	2013-07-26 19:03:46.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/config/mips/mips.opt	2013-07-27 00:16:54.078378235 +0100
@@ -205,6 +205,24 @@  mfused-madd
 Target Report Mask(FUSED_MADD)
 Generate floating-point multiply-add instructions
 
+mabs=
+Target RejectNegative Joined Enum(mips_ieee_754_value) Var(mips_abs) Init(MIPS_IEEE_754_DEFAULT)
+-mabs=MODE	Select the IEEE 754 ABS/NEG instruction execution mode
+
+mnan=
+Target RejectNegative Joined Enum(mips_ieee_754_value) Var(mips_nan) Init(MIPS_IEEE_754_DEFAULT)
+-mnan=ENCODING	Select the IEEE 754 NaN data encoding
+
+Enum
+Name(mips_ieee_754_value) Type(int)
+Known MIPS IEEE 754 settings (for use with the -mabs= and -mnan= options):
+
+EnumValue
+Enum(mips_ieee_754_value) String(2008) Value(MIPS_IEEE_754_2008)
+
+EnumValue
+Enum(mips_ieee_754_value) String(legacy) Value(MIPS_IEEE_754_LEGACY)
+
 mgp32
 Target Report RejectNegative InverseMask(64BIT)
 Use 32-bit general registers
Index: gcc-fsf-trunk-quilt/gcc/configure
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/configure	2013-07-26 19:02:04.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/configure	2013-07-26 19:20:34.228697260 +0100
@@ -26019,6 +26019,41 @@  $as_echo "$gcc_cv_ld_mips_personality_re
 $as_echo "#define HAVE_LD_PERSONALITY_RELAXATION 1" >>confdefs.h
 
     fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -mnan= support" >&5
+$as_echo_n "checking assembler for -mnan= support... " >&6; }
+if test "${gcc_cv_as_mips_nan+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_mips_nan=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -mnan=2008 -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_mips_nan=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_mips_nan" >&5
+$as_echo "$gcc_cv_as_mips_nan" >&6; }
+if test $gcc_cv_as_mips_nan = yes; then
+
+$as_echo "#define HAVE_AS_NAN 1" >>confdefs.h
+
+fi
+    if test x$gcc_cv_as_mips_nan = xno \
+       && test x$with_nan != x; then
+      as_fn_error "Requesting --with-nan= requires assembler support for -mnan=" "$LINENO" 5
+    fi
     ;;
 esac
 
Index: gcc-fsf-trunk-quilt/gcc/configure.ac
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/configure.ac	2013-07-26 19:02:04.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/configure.ac	2013-07-26 19:20:34.228697260 +0100
@@ -4168,6 +4168,17 @@  EOF
       [Define if your linker can relax absolute .eh_frame personality
 pointers into PC-relative form.])
     fi
+
+    gcc_GAS_CHECK_FEATURE([-mnan= support],
+      gcc_cv_as_mips_nan,,
+      [-mnan=2008],,,
+      [AC_DEFINE(HAVE_AS_NAN, 1,
+		 [Define if the assembler understands -mnan=.])])
+    if test x$gcc_cv_as_mips_nan = xno \
+       && test x$with_nan != x; then
+      AC_MSG_ERROR(
+	[Requesting --with-nan= requires assembler support for -mnan=])
+    fi
     ;;
 esac
 
Index: gcc-fsf-trunk-quilt/gcc/doc/install.texi
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/doc/install.texi	2013-07-26 18:39:51.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/doc/install.texi	2013-07-26 19:20:34.228697260 +0100
@@ -1221,6 +1221,24 @@  ISA for floating-point arithmetics.  You
 enables @option{-msse2} or @samp{avx} which enables @option{-mavx} by default.
 This option is only supported on i386 and x86-64 targets.
 
+@item --with-nan=@var{encoding}
+On MIPS targets, set the default encoding convention to use for the
+special not-a-number (NaN) IEEE 754 floating-point data.  The
+possibilities for @var{encoding} are:
+@table @code
+@item legacy
+Use the legacy encoding, as with the @option{-mnan=legacy} command-line
+option.
+@item 2008
+Use the 754-2008 encoding, as with the @option{-mnan=2008} command-line
+option.
+@end table
+To use this configuration option you must have an assembler version
+installed that supports the @option{-mnan=} command-line option too.
+In the absence of this configuration option the default convention is
+the legacy encoding, as when neither of the @option{-mnan=2008} and
+@option{-mnan=legacy} command-line options has been used.
+
 @item --with-divide=@var{type}
 Specify how the compiler should generate code for checking for
 division by zero.  This option is only supported on the MIPS target.
Index: gcc-fsf-trunk-quilt/gcc/doc/invoke.texi
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/doc/invoke.texi	2013-07-26 18:59:56.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/doc/invoke.texi	2013-07-26 19:20:34.228697260 +0100
@@ -750,7 +750,8 @@  Objective-C and Objective-C++ Dialects}.
 -mabi=@var{abi}  -mabicalls  -mno-abicalls @gol
 -mshared  -mno-shared  -mplt  -mno-plt  -mxgot  -mno-xgot @gol
 -mgp32  -mgp64  -mfp32  -mfp64  -mhard-float  -msoft-float @gol
--mno-float -msingle-float  -mdouble-float  @gol
+-mno-float  -msingle-float  -mdouble-float @gol
+-mabs=@var{mode}  -mnan=@var{encoding} @gol
 -mdsp  -mno-dsp  -mdspr2  -mno-dspr2 @gol
 -mmcu -mmno-mcu @gol
 -meva -mno-eva @gol
@@ -16324,6 +16325,48 @@  operations.
 Assume that the floating-point coprocessor supports double-precision
 operations.  This is the default.
 
+@item -mabs=2008
+@itemx -mabs=legacy
+@opindex mabs=2008
+@opindex mabs=legacy
+These options control the treatment of the special not-a-number (NaN)
+IEEE 754 floating-point data with the @code{abs.@i{fmt}} and
+@code{neg.@i{fmt}} machine instructions.
+
+By default or when the @option{-mabs=legacy} is used the legacy
+treatment is selected.  In this case these instructions are considered
+arithmetic and avoided where correct operation is required and the
+input operand might be a NaN.  A longer sequence of instructions that
+manipulate the sign bit of floating-point datum manually is used
+instead unless the @option{-ffinite-math-only} option has also been
+specified.
+
+The @option{-mabs=2008} option selects the IEEE 754-2008 treatment.  In
+this case these instructions are considered non-arithmetic and therefore
+operating correctly in all cases, including in particular where the
+input operand is a NaN.  These instructions are therefore always used
+for the respective operations.
+
+@item -mnan=2008
+@itemx -mnan=legacy
+@opindex mnan=2008
+@opindex mnan=legacy
+These options control the encoding of the special not-a-number (NaN)
+IEEE 754 floating-point data.
+
+The @option{-mnan=legacy} option selects the legacy encoding.  In this
+case quiet NaNs (qNaNs) are denoted by the first bit of their trailing
+significand field being 0, whereas signalling NaNs (sNaNs) are denoted
+by the first bit of their trailing significand field being 1.
+
+The @option{-mnan=2008} option selects the IEEE 754-2008 encoding.  In
+this case qNaNs are denoted by the first bit of their trailing
+significand field being 1, whereas sNaNs are denoted by the first bit of
+their trailing significand field being 0.
+
+The default is @option{-mnan=legacy} unless GCC has been configured with
+@option{--with-nan=2008}.
+
 @item -mllsc
 @itemx -mno-llsc
 @opindex mllsc
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fabs-2008.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fabs-2008.c	2013-07-26 19:20:34.228697260 +0100
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mabs=2008" } */
+
+NOMIPS16 double
+fabs_2008 (double d)
+{
+  return __builtin_fabs (d);
+}
+
+/* { dg-final { scan-assembler "\tabs\.d\t" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fabs-legacy.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fabs-legacy.c	2013-07-26 19:20:34.228697260 +0100
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mabs=legacy" } */
+
+NOMIPS16 double
+fabs_legacy (double d)
+{
+  return __builtin_fabs (d);
+}
+
+/* { dg-final { scan-assembler-not "\tabs\.d\t" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fabsf-2008.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fabsf-2008.c	2013-07-26 19:20:34.228697260 +0100
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mabs=2008" } */
+
+NOMIPS16 float
+fabsf_2008 (float f)
+{
+  return __builtin_fabsf (f);
+}
+
+/* { dg-final { scan-assembler "\tabs\.s\t" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fabsf-legacy.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fabsf-legacy.c	2013-07-26 19:20:34.228697260 +0100
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mabs=legacy" } */
+
+NOMIPS16 float
+fabsf_legacy (float f)
+{
+  return __builtin_fabsf (f);
+}
+
+/* { dg-final { scan-assembler-not "\tabs\.s\t" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fneg-2008.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fneg-2008.c	2013-07-26 19:20:34.228697260 +0100
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mabs=2008" } */
+
+NOMIPS16 double
+fneg_2008 (double d)
+{
+  return -d;
+}
+
+/* { dg-final { scan-assembler "\tneg\.d\t" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fneg-legacy.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fneg-legacy.c	2013-07-26 19:20:34.228697260 +0100
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mabs=legacy" } */
+
+NOMIPS16 double
+fneg_legacy (double d)
+{
+  return -d;
+}
+
+/* { dg-final { scan-assembler-not "\tneg\.d\t" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fnegf-2008.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fnegf-2008.c	2013-07-26 19:20:34.228697260 +0100
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mabs=2008" } */
+
+NOMIPS16 float
+fnegf_2008 (float f)
+{
+  return -f;
+}
+
+/* { dg-final { scan-assembler "\tneg\.s\t" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fnegf-legacy.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/fnegf-legacy.c	2013-07-26 19:20:34.228697260 +0100
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mabs=legacy" } */
+
+NOMIPS16 float
+fnegf_legacy (float f)
+{
+  return -f;
+}
+
+/* { dg-final { scan-assembler-not "\tneg\.s\t" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/mips.exp
===================================================================
--- gcc-fsf-trunk-quilt.orig/gcc/testsuite/gcc.target/mips/mips.exp	2013-07-26 18:39:51.000000000 +0100
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/mips.exp	2013-07-26 19:20:34.228697260 +0100
@@ -276,8 +276,10 @@  foreach option {
 
 # Add -mfoo= options to mips_option_groups.
 foreach option {
+    abs
     branch-cost
     code-readable
+    nan
     r10k-cache-barrier
     tune
 } {
@@ -705,6 +707,18 @@  proc mips-dg-init {} {
 	    "-msoft-float",
 	    #endif
 
+	    #ifdef __mips_abs2008
+	    "-mabs=2008",
+	    #else
+	    "-mabs=legacy",
+	    #endif
+
+	    #ifdef __mips_nan2008
+	    "-mnan=2008",
+	    #else
+	    "-mnan=legacy",
+	    #endif
+
 	    #if __mips_fpr == 64
 	    "-mfp64",
 	    #else
@@ -826,6 +840,8 @@  proc mips-dg-finish {} {
 #            |                           |
 #         -mfp64                      -mfp32
 #            |                           |
+#         -mabs=2008/-mabs=legacy     <no option>
+#            |                           |
 #         -mhard-float                -msoft-float
 #            |                           |
 #         -mno-sym32                  -msym32
@@ -913,6 +929,8 @@  proc mips-dg-options { args } {
     mips_option_dependency options "-mips3d" "-mpaired-single"
     mips_option_dependency options "-mpaired-single" "-mfp64"
     mips_option_dependency options "-mfp64" "-mhard-float"
+    mips_option_dependency options "-mabs=2008" "-mhard-float"
+    mips_option_dependency options "-mabs=legacy" "-mhard-float"
     mips_option_dependency options "-mrelax-pic-calls" "-mno-plt"
     mips_option_dependency options "-mrelax-pic-calls" "-mabicalls"
     mips_option_dependency options "-mrelax-pic-calls" "-mexplicit-relocs"
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nan-2008.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nan-2008.c	2013-07-27 00:16:54.078378235 +0100
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mnan=2008 -EB" } */
+
+double d = __builtin_nan ("");
+
+/* { dg-final { scan-assembler "\t\.nan\t2008\n" } } */
+/* { dg-final { scan-assembler "\t\.word\t2146959360\n\t.word\t0\n" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nan-legacy.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nan-legacy.c	2013-07-27 00:16:54.078378235 +0100
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mnan=legacy -EB" } */
+
+double d = __builtin_nan ("");
+
+/* { dg-final { scan-assembler "\t\.nan\tlegacy\n" } } */
+/* { dg-final { scan-assembler "\t\.word\t2146959359\n\t.word\t-1\n" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nanf-2008.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nanf-2008.c	2013-07-27 00:16:54.078378235 +0100
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mnan=2008 -EB" } */
+
+float f = __builtin_nanf ("");
+
+/* { dg-final { scan-assembler "\t\.nan\t2008\n" } } */
+/* { dg-final { scan-assembler "\t\.word\t2143289344\n" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nanf-legacy.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nanf-legacy.c	2013-07-27 00:16:54.078378235 +0100
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mnan=legacy -EB" } */
+
+float f = __builtin_nanf ("");
+
+/* { dg-final { scan-assembler "\t\.nan\tlegacy\n" } } */
+/* { dg-final { scan-assembler "\t\.word\t2143289343\n" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nans-2008.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nans-2008.c	2013-07-27 00:16:54.078378235 +0100
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mnan=2008 -EB" } */
+
+double ds = __builtin_nans ("");
+
+/* { dg-final { scan-assembler "\t\.nan\t2008\n" } } */
+/* { dg-final { scan-assembler "\t\.word\t2146697216\n\t.word\t0\n" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nans-legacy.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nans-legacy.c	2013-07-27 00:16:54.078378235 +0100
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mnan=legacy -EB" } */
+
+double ds = __builtin_nans ("");
+
+/* { dg-final { scan-assembler "\t\.nan\tlegacy\n" } } */
+/* { dg-final { scan-assembler "\t\.word\t2147483647\n\t.word\t-1\n" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nansf-2008.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nansf-2008.c	2013-07-27 00:16:54.078378235 +0100
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mnan=2008 -EB" } */
+
+float fs = __builtin_nansf ("");
+
+/* { dg-final { scan-assembler "\t\.nan\t2008\n" } } */
+/* { dg-final { scan-assembler "\t\.word\t2141192192\n" } } */
Index: gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nansf-legacy.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-fsf-trunk-quilt/gcc/testsuite/gcc.target/mips/nansf-legacy.c	2013-07-27 00:16:54.078378235 +0100
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mnan=legacy -EB" } */
+
+float fs = __builtin_nansf ("");
+
+/* { dg-final { scan-assembler "\t\.nan\tlegacy\n" } } */
+/* { dg-final { scan-assembler "\t\.word\t2147483647\n" } } */