MIPS: soft-fp NaN representation corrections

[BZ #15442] This adds support for the inverse interpretation of the
quiet bit of IEEE 754 floating-point NaN data that some processors
use.  This includes in particular MIPS architecture processors; the
payload used for the canonical qNaN encoding is updated accordingly
so as not to interfere with the quiet bit.
This commit is contained in:
Maciej W. Rozycki 2013-05-16 23:33:55 +01:00
parent c58b274f01
commit 2848b10585
15 changed files with 124 additions and 18 deletions

View File

@ -1,3 +1,24 @@
2013-05-16 Maciej W. Rozycki <macro@codesourcery.com>
[BZ #15442]
* soft-fp/op-common.h (_FP_FRAC_SNANP): New macro.
(_FP_FRAC_SNANP_SEMIRAW): Likewise.
(_FP_UNPACK_CANONICAL): Use _FP_FRAC_SNANP.
(_FP_CHECK_SIGNAN_SEMIRAW): Use _FP_FRAC_SNANP_SEMIRAW.
(_FP_SETQNAN): New macro.
(_FP_SETQNAN_SEMIRAW): Likewise.
(_FP_PACK_SEMIRAW): Use _FP_SETQNAN.
(_FP_PACK_CANONICAL): Use _FP_SETQNAN.
(_FP_ISSIGNAN): Use _FP_FRAC_SNANP.
(FP_EXTEND): Use _FP_FRAC_SNANP.
(FP_TRUNC): Use _FP_SETQNAN_SEMIRAW.
* soft-fp/testit.c (gen_special_double): Take _FP_QNANNEGATEDP
into account.
* sysdeps/sparc/sparc32/soft-fp/sfp-machine.h (_FP_QNANNEGATEDP):
New macro.
* sysdeps/sparc/sparc64/soft-fp/sfp-machine.h (_FP_QNANNEGATEDP):
Likewise.
2013-05-16 Joseph Myers <joseph@codesourcery.com> 2013-05-16 Joseph Myers <joseph@codesourcery.com>
* math/libm-test.inc (atanh_test_data): Use ERRNO_ERANGE together * math/libm-test.inc (atanh_test_data): Use ERRNO_ERANGE together

2
NEWS
View File

@ -17,7 +17,7 @@ Version 2.18
15086, 15160, 15214, 15221, 15232, 15234, 15283, 15285, 15287, 15304, 15086, 15160, 15214, 15221, 15232, 15234, 15283, 15285, 15287, 15304,
15305, 15307, 15309, 15327, 15330, 15335, 15336, 15337, 15342, 15346, 15305, 15307, 15309, 15327, 15330, 15335, 15336, 15337, 15342, 15346,
15359, 15361, 15366, 15380, 15394, 15395, 15405, 15406, 15409, 15416, 15359, 15361, 15366, 15380, 15394, 15395, 15405, 15406, 15409, 15416,
15418, 15419, 15423, 15426, 15429, 15448. 15418, 15419, 15423, 15426, 15429, 15442, 15448.
* CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla * CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla
#15078). #15078).

View File

@ -1,3 +1,9 @@
2013-05-16 Maciej W. Rozycki <macro@codesourcery.com>
[BZ #15442]
* sysdeps/aarch64/soft-fp/sfp-machine.h (_FP_QNANNEGATEDP): New
macro.
2013-05-12 Marcus Shawcroft <marcus.shawcroft@linaro.org> 2013-05-12 Marcus Shawcroft <marcus.shawcroft@linaro.org>
* sysdeps/unix/sysv/linux/aarch64/clone.S (__clone): * sysdeps/unix/sysv/linux/aarch64/clone.S (__clone):

View File

@ -1,3 +1,9 @@
2013-05-16 Maciej W. Rozycki <macro@codesourcery.com>
[BZ #15442]
* sysdeps/alpha/soft-fp/sfp-machine.h (_FP_QNANNEGATEDP): New
macro.
2013-03-06 Andreas Jaeger <aj@suse.de> 2013-03-06 Andreas Jaeger <aj@suse.de>
* sysdeps/unix/sysv/linux/alpha/bits/mman.h (MAP_HUGE_MASK) * sysdeps/unix/sysv/linux/alpha/bits/mman.h (MAP_HUGE_MASK)

View File

@ -1,3 +1,17 @@
2013-05-16 Maciej W. Rozycki <macro@codesourcery.com>
[BZ #15442]
* sysdeps/mips/mips64/soft-fp/sfp-machine.h (_FP_QNANNEGATEDP):
New macro.
(_FP_NANFRAC_S): Don't set the quiet bit.
(_FP_NANFRAC_D): Likewise.
(_FP_NANFRAC_Q): Likewise.
* sysdeps/mips/soft-fp/sfp-machine.h (_FP_QNANNEGATEDP): New
macro.
(_FP_NANFRAC_S): Don't set the quiet bit.
(_FP_NANFRAC_D): Likewise.
(_FP_NANFRAC_Q): Likewise.
2013-05-16 Ryan S. Arnold <rsa@linux.vnet.ibm.com> 2013-05-16 Ryan S. Arnold <rsa@linux.vnet.ibm.com>
* sysdeps/unix/sysv/linux/mips/kernel_rt_sigframe.h: Add missing * sysdeps/unix/sysv/linux/mips/kernel_rt_sigframe.h: Add missing

View File

@ -1,3 +1,9 @@
2013-05-16 Maciej W. Rozycki <macro@codesourcery.com>
[BZ #15442]
* sysdeps/powerpc/soft-fp/sfp-machine.h (_FP_QNANNEGATEDP): New
macro.
2013-02-28 Joseph Myers <joseph@codesourcery.com> 2013-02-28 Joseph Myers <joseph@codesourcery.com>
[BZ #13550] [BZ #13550]

View File

@ -25,6 +25,8 @@
#define _FP_NANSIGN_Q 0 #define _FP_NANSIGN_Q 0
#define _FP_KEEPNANFRACP 1 #define _FP_KEEPNANFRACP 1
#define _FP_QNANNEGATEDP 0
/* From my experiments it seems X is chosen unless one of the /* From my experiments it seems X is chosen unless one of the
NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */ NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */
#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \

View File

@ -46,6 +46,7 @@
#define _FP_NANSIGN_Q 0 #define _FP_NANSIGN_Q 0
#define _FP_KEEPNANFRACP 1 #define _FP_KEEPNANFRACP 1
#define _FP_QNANNEGATEDP 0
/* Alpha Architecture Handbook, 4.7.10.4 sez that we should prefer any /* Alpha Architecture Handbook, 4.7.10.4 sez that we should prefer any
type of NaN in Fb, then Fa. */ type of NaN in Fb, then Fa. */

View File

@ -17,14 +17,16 @@
#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y) #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) #define _FP_NANFRAC_S (_FP_QNANBIT_S - 1)
#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1) #define _FP_NANFRAC_D (_FP_QNANBIT_D - 1)
#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1 #define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1
#define _FP_NANSIGN_S 0 #define _FP_NANSIGN_S 0
#define _FP_NANSIGN_D 0 #define _FP_NANSIGN_D 0
#define _FP_NANSIGN_Q 0 #define _FP_NANSIGN_Q 0
#define _FP_KEEPNANFRACP 1 #define _FP_KEEPNANFRACP 1
#define _FP_QNANNEGATEDP 1
/* From my experiments it seems X is chosen unless one of the /* From my experiments it seems X is chosen unless one of the
NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */ NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */
#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \

View File

@ -14,14 +14,16 @@
#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) #define _FP_NANFRAC_S (_FP_QNANBIT_S - 1)
#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1 #define _FP_NANFRAC_D (_FP_QNANBIT_D - 1), -1
#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1 #define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1, -1, -1
#define _FP_NANSIGN_S 0 #define _FP_NANSIGN_S 0
#define _FP_NANSIGN_D 0 #define _FP_NANSIGN_D 0
#define _FP_NANSIGN_Q 0 #define _FP_NANSIGN_Q 0
#define _FP_KEEPNANFRACP 1 #define _FP_KEEPNANFRACP 1
#define _FP_QNANNEGATEDP 1
/* From my experiments it seems X is chosen unless one of the /* From my experiments it seems X is chosen unless one of the
NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */ NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */
#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \

View File

@ -22,6 +22,7 @@
#define _FP_NANSIGN_Q 0 #define _FP_NANSIGN_Q 0
#define _FP_KEEPNANFRACP 1 #define _FP_KEEPNANFRACP 1
#define _FP_QNANNEGATEDP 0
/* Someone please check this. */ /* Someone please check this. */
#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \

View File

@ -35,6 +35,16 @@
_FP_I_TYPE X##_e; \ _FP_I_TYPE X##_e; \
_FP_FRAC_DECL_##wc(X) _FP_FRAC_DECL_##wc(X)
/* Test whether the qNaN bit denotes a signaling NaN. */
#define _FP_FRAC_SNANP(fs, X) \
((_FP_QNANNEGATEDP) \
? (_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \
: !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))
#define _FP_FRAC_SNANP_SEMIRAW(fs, X) \
((_FP_QNANNEGATEDP) \
? (_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs) \
: !(_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs))
/* /*
* Finish truely unpacking a native fp value by classifying the kind * Finish truely unpacking a native fp value by classifying the kind
* of fp value and normalizing both the exponent and the fraction. * of fp value and normalizing both the exponent and the fraction.
@ -74,7 +84,7 @@ do { \
{ \ { \
X##_c = FP_CLS_NAN; \ X##_c = FP_CLS_NAN; \
/* Check for signaling NaN */ \ /* Check for signaling NaN */ \
if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ if (_FP_FRAC_SNANP(fs, X)) \
FP_SET_EXCEPTION(FP_EX_INVALID); \ FP_SET_EXCEPTION(FP_EX_INVALID); \
} \ } \
break; \ break; \
@ -112,7 +122,7 @@ do { \
do { \ do { \
if (X##_e == _FP_EXPMAX_##fs \ if (X##_e == _FP_EXPMAX_##fs \
&& !_FP_FRAC_ZEROP_##wc(X) \ && !_FP_FRAC_ZEROP_##wc(X) \
&& !(_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs)) \ && _FP_FRAC_SNANP_SEMIRAW(fs, X)) \
FP_SET_EXCEPTION(FP_EX_INVALID); \ FP_SET_EXCEPTION(FP_EX_INVALID); \
} while (0) } while (0)
@ -127,6 +137,39 @@ do { \
_FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \ _FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \
} while (0) } while (0)
/* Make the fractional part a quiet NaN, preserving the payload
if possible, otherwise make it the canonical quiet NaN and set
the sign bit accordingly. */
#define _FP_SETQNAN(fs, wc, X) \
do { \
if (_FP_QNANNEGATEDP) \
{ \
_FP_FRAC_HIGH_RAW_##fs(X) &= _FP_QNANBIT_##fs - 1; \
if (_FP_FRAC_ZEROP_##wc(X)) \
{ \
X##_s = _FP_NANSIGN_##fs; \
_FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
} \
} \
else \
_FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
} while (0)
#define _FP_SETQNAN_SEMIRAW(fs, wc, X) \
do { \
if (_FP_QNANNEGATEDP) \
{ \
_FP_FRAC_HIGH_##fs(X) &= _FP_QNANBIT_SH_##fs - 1; \
if (_FP_FRAC_ZEROP_##wc(X)) \
{ \
X##_s = _FP_NANSIGN_##fs; \
_FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
_FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
} \
} \
else \
_FP_FRAC_HIGH_##fs(X) |= _FP_QNANBIT_SH_##fs; \
} while (0)
/* Test whether a biased exponent is normal (not zero or maximum). */ /* Test whether a biased exponent is normal (not zero or maximum). */
#define _FP_EXP_NORMAL(fs, wc, X) (((X##_e + 1) & _FP_EXPMAX_##fs) > 1) #define _FP_EXP_NORMAL(fs, wc, X) (((X##_e + 1) & _FP_EXPMAX_##fs) > 1)
@ -159,7 +202,7 @@ do { \
X##_s = _FP_NANSIGN_##fs; \ X##_s = _FP_NANSIGN_##fs; \
} \ } \
else \ else \
_FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \ _FP_SETQNAN(fs, wc, X); \
} \ } \
} while (0) } while (0)
@ -273,7 +316,7 @@ do { \
X##_s = _FP_NANSIGN_##fs; \ X##_s = _FP_NANSIGN_##fs; \
} \ } \
else \ else \
_FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \ _FP_SETQNAN(fs, wc, X); \
break; \ break; \
} \ } \
} while (0) } while (0)
@ -287,7 +330,7 @@ do { \
if (X##_e == _FP_EXPMAX_##fs) \ if (X##_e == _FP_EXPMAX_##fs) \
{ \ { \
if (!_FP_FRAC_ZEROP_##wc(X) \ if (!_FP_FRAC_ZEROP_##wc(X) \
&& !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ && _FP_FRAC_SNANP(fs, X)) \
__ret = 1; \ __ret = 1; \
} \ } \
__ret; \ __ret; \
@ -1199,7 +1242,7 @@ do { \
D##_e = _FP_EXPMAX_##dfs; \ D##_e = _FP_EXPMAX_##dfs; \
if (!_FP_FRAC_ZEROP_##swc(S)) \ if (!_FP_FRAC_ZEROP_##swc(S)) \
{ \ { \
if (!(_FP_FRAC_HIGH_RAW_##sfs(S) & _FP_QNANBIT_##sfs)) \ if (_FP_FRAC_SNANP(sfs, S)) \
FP_SET_EXCEPTION(FP_EX_INVALID); \ FP_SET_EXCEPTION(FP_EX_INVALID); \
_FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \ _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \
- _FP_FRACBITS_##sfs)); \ - _FP_FRACBITS_##sfs)); \
@ -1286,7 +1329,7 @@ do { \
/* Semi-raw NaN must have all workbits cleared. */ \ /* Semi-raw NaN must have all workbits cleared. */ \
_FP_FRAC_LOW_##dwc(D) \ _FP_FRAC_LOW_##dwc(D) \
&= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \ &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \
_FP_FRAC_HIGH_##dfs(D) |= _FP_QNANBIT_SH_##dfs; \ _FP_SETQNAN_SEMIRAW(dfs, dwc, D); \
} \ } \
} \ } \
} \ } \

View File

@ -200,17 +200,17 @@ double gen_special_double(int i)
case 0: case 0:
X_c = FP_CLS_NAN; X_c = FP_CLS_NAN;
#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
__FP_FRAC_SET_2(X, _FP_QNANBIT_D, 0x1234); __FP_FRAC_SET_2(X, _FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D, 0x1234);
#else #else
_FP_FRAC_SET_1(X, _FP_QNANBIT_D | 0x1234); _FP_FRAC_SET_1(X, (_FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D) | 0x1234);
#endif #endif
break; break;
case 2: case 2:
X_c = FP_CLS_NAN; X_c = FP_CLS_NAN;
#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D #if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
__FP_FRAC_SET_2(X, _FP_QNANBIT_D, 0x1); __FP_FRAC_SET_2(X, _FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D, 0x1);
#else #else
_FP_FRAC_SET_1(X, _FP_QNANBIT_D | 0x1); _FP_FRAC_SET_1(X, (_FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D) | 0x1);
#endif #endif
break; break;
case 4: case 4:

View File

@ -47,6 +47,7 @@
#define _FP_NANSIGN_Q 0 #define _FP_NANSIGN_Q 0
#define _FP_KEEPNANFRACP 1 #define _FP_KEEPNANFRACP 1
#define _FP_QNANNEGATEDP 0
/* If one NaN is signaling and the other is not, /* If one NaN is signaling and the other is not,
* we choose that one, otherwise we choose X. * we choose that one, otherwise we choose X.

View File

@ -60,6 +60,7 @@ do { \
#define _FP_NANSIGN_Q 0 #define _FP_NANSIGN_Q 0
#define _FP_KEEPNANFRACP 1 #define _FP_KEEPNANFRACP 1
#define _FP_QNANNEGATEDP 0
/* If one NaN is signaling and the other is not, /* If one NaN is signaling and the other is not,
* we choose that one, otherwise we choose Y. * we choose that one, otherwise we choose Y.