[PATCH v2] MIPS: NaN encoding fixes and IEEE 754-2008 updates
Maciej W. Rozycki
macro@codesourcery.com
Fri Mar 21 20:20:00 GMT 2014
Hi,
As many of you have been aware it has been a long practice for software
using IEEE 754 floating-point arithmetic run on MIPS processors to use an
encoding of Not-a-Number (NaN) data different to one used by software run
on other processors. And as of IEEE 754-2008 revision this encoding does
not follow one recommended in the standard, as specified in section 6.2.1,
where it is stated that quiet NaNs should have the first bit (d1) of their
significand set to 1 while signalling NaNs should have that bit set to 0,
but MIPS software interprets the two bits in the opposite manner.
A recent MIPS Architecture revision[1][2] provides for processors that
support the IEEE 754-2008 preferred NaN encoding format. As the two
formats (further referred to as "legacy NaN" and "2008 NaN") are
incompatible to each other, tools have been updated to provide support for
the two formats to help people avoid using incompatible binary modules.
In particular GCC versions that produce the 2008 NaN encoding predefine
the `__mips_nan2008' macro that can be used to select code to compile at
the preprocessor level.
This change corrects inconsistencies for the MIPS target in NaN encodings
between endiannesses and makes sure the correct encodings are used both in
the legacy-NaN and the 2008-NaN mode.
This code unconditionally expects floating-point types having the
significand field width of 24, 53, 64 and 113 bits to be present.
Additionally the 64-bit format expects the leading significand bit to be
explicitly encoded as in Intel x86/x87 FPUs. Having no better choice I
have implemented the handling of these extra data types as they might be
reasonably implemented by MIPS hardware. Ideally this code should be
audited and dead pieces disabled for targets that do not use them.
Furthermore some macros are present that encode constants comprising
whole or parts of NaN data of different widths. They use different
encodings and data formats between endiannesses, apparently implying the
Intel x86/x87 format for the little endianness and Motorola M68k format
for the big endianness. Neither fully applies for MIPS targets, so I have
added separate definitions for the values that make sense and are actually
referred to from code elsewhere. Any future references to the currently
unused macros defined for non-MIPS targets to support a long double data
type will cause a build failure on MIPS, which is exactly what we want.
For nan and nanf I decided to switch to __builtin_nan and __builtin_nanf
respectively as the implementation where available -- which is always true
for GCC versions that support the 2008-NaN encoding on the MIPS target.
These built-ins guarantee the correct NaN encoding for all platforms and
compilation options and are already used elsewhere in Newlib (which is
where I copied the preprocessor condition from).
For MIPS, additionally, in many cases they produce slightly better or at
worst identical code; unfortunately in some other ones GCC misses the
opportunity to inline the value loaded -- it looks to me like with these
built-ins the compiler always insists to put the value loaded in memory.
I don't think this should stop us from using them regardless though, the
maintainability gain is too high compared to the memory loss, which is on
the order of 4 to 8 bytes.
FWIW I have regression-tested the change with the mips-sde-elf target,
although I can't say this provides much value as the newlib test suite
doesn't seem to cover much of IEEE arithmetic. However this change has
been used for ~1yr with the Mentor CodeBench toolchain with no problems
spotted.
Please apply.
2013-03-21 Maciej W. Rozycki <macro@codesourcery.com>
newlib/
* libc/stdlib/gd_qnan.h (f_QNAN, d_QNAN0, d_QNAN1): Add MIPS
versions.
(ld_QNAN0, ld_QNAN1, ld_QNAN2, ld_QNAN3): Don't define for MIPS.
(ldus_QNAN0, ldus_QNAN1, ldus_QNAN2, ldus_QNAN3, ldus_QNAN4):
Likewise.
* libc/stdlib/ldtoa.c (nan113, nan64, nan53, nan24): Add MIPS
versions.
(enan): Handle legacy MIPS payloads.
* libm/common/s_nan.c (nan): Use __builtin_nan if supported by
the compiler.
* libm/common/sf_nan.c (nanf): Likewise.
Maciej
References:
[1] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
MIPS32 Architecture", MIPS Technologies, Inc., Document Number:
MD00082, Revision 5.03, Sept. 9, 2013, Section 5.4.1.5 "Quiet
Non-Number (QNaN)", p. 71,
[2] "MIPS Architecture For Programmers, Volume I-A: Introduction to the
MIPS64 Architecture", MIPS Technologies, Inc., Document Number:
MD00083, Revision 5.03, Sept. 9, 2013, Section 5.4.1.5 "Quiet
Non-Number (QNaN)", p. 74.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: newlib-mips-nan2008.diff
Type: text/x-diff
Size: 6191 bytes
Desc:
URL: <http://sourceware.org/pipermail/newlib/attachments/20140321/9f6020de/attachment.bin>
More information about the Newlib
mailing list