diff options
author | Maciej W. Rozycki <macro@codesourcery.com> | 2013-05-16 23:33:55 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@codesourcery.com> | 2013-05-16 23:33:55 +0100 |
commit | 2848b105856e49d98f3c5026b6d8d790f9723c0c (patch) | |
tree | 66e6cc9d3c1c6d95324e50ceb1140d0eed52ec37 | |
parent | c58b274f01658400ba75886b04cb044ba9467a94 (diff) | |
download | glibc-2848b105856e49d98f3c5026b6d8d790f9723c0c.tar.gz glibc-2848b105856e49d98f3c5026b6d8d790f9723c0c.tar.xz glibc-2848b105856e49d98f3c5026b6d8d790f9723c0c.zip |
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.
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | ports/ChangeLog.aarch64 | 6 | ||||
-rw-r--r-- | ports/ChangeLog.alpha | 6 | ||||
-rw-r--r-- | ports/ChangeLog.mips | 14 | ||||
-rw-r--r-- | ports/ChangeLog.powerpc | 6 | ||||
-rw-r--r-- | ports/sysdeps/aarch64/soft-fp/sfp-machine.h | 2 | ||||
-rw-r--r-- | ports/sysdeps/alpha/soft-fp/sfp-machine.h | 1 | ||||
-rw-r--r-- | ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h | 8 | ||||
-rw-r--r-- | ports/sysdeps/mips/soft-fp/sfp-machine.h | 8 | ||||
-rw-r--r-- | ports/sysdeps/powerpc/soft-fp/sfp-machine.h | 1 | ||||
-rw-r--r-- | soft-fp/op-common.h | 57 | ||||
-rw-r--r-- | soft-fp/testit.c | 8 | ||||
-rw-r--r-- | sysdeps/sparc/sparc32/soft-fp/sfp-machine.h | 1 | ||||
-rw-r--r-- | sysdeps/sparc/sparc64/soft-fp/sfp-machine.h | 1 |
15 files changed, 124 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog index 72dba346ff..0533218c3d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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> * math/libm-test.inc (atanh_test_data): Use ERRNO_ERANGE together diff --git a/NEWS b/NEWS index 59aae3eb61..86c287ff29 100644 --- a/NEWS +++ b/NEWS @@ -17,7 +17,7 @@ Version 2.18 15086, 15160, 15214, 15221, 15232, 15234, 15283, 15285, 15287, 15304, 15305, 15307, 15309, 15327, 15330, 15335, 15336, 15337, 15342, 15346, 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 #15078). diff --git a/ports/ChangeLog.aarch64 b/ports/ChangeLog.aarch64 index a611ac22cf..a4fc2962d3 100644 --- a/ports/ChangeLog.aarch64 +++ b/ports/ChangeLog.aarch64 @@ -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> * sysdeps/unix/sysv/linux/aarch64/clone.S (__clone): diff --git a/ports/ChangeLog.alpha b/ports/ChangeLog.alpha index 9a77d276ab..3c16ce0077 100644 --- a/ports/ChangeLog.alpha +++ b/ports/ChangeLog.alpha @@ -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> * sysdeps/unix/sysv/linux/alpha/bits/mman.h (MAP_HUGE_MASK) diff --git a/ports/ChangeLog.mips b/ports/ChangeLog.mips index 472ae21fb2..8640a121db 100644 --- a/ports/ChangeLog.mips +++ b/ports/ChangeLog.mips @@ -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> * sysdeps/unix/sysv/linux/mips/kernel_rt_sigframe.h: Add missing diff --git a/ports/ChangeLog.powerpc b/ports/ChangeLog.powerpc index 2ba8e3754f..073df4f0b7 100644 --- a/ports/ChangeLog.powerpc +++ b/ports/ChangeLog.powerpc @@ -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> [BZ #13550] diff --git a/ports/sysdeps/aarch64/soft-fp/sfp-machine.h b/ports/sysdeps/aarch64/soft-fp/sfp-machine.h index b355986415..d21d00a934 100644 --- a/ports/sysdeps/aarch64/soft-fp/sfp-machine.h +++ b/ports/sysdeps/aarch64/soft-fp/sfp-machine.h @@ -25,6 +25,8 @@ #define _FP_NANSIGN_Q 0 #define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 0 + /* From my experiments it seems X is chosen unless one of the NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */ #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ diff --git a/ports/sysdeps/alpha/soft-fp/sfp-machine.h b/ports/sysdeps/alpha/soft-fp/sfp-machine.h index 343464c3a8..be266feccc 100644 --- a/ports/sysdeps/alpha/soft-fp/sfp-machine.h +++ b/ports/sysdeps/alpha/soft-fp/sfp-machine.h @@ -46,6 +46,7 @@ #define _FP_NANSIGN_Q 0 #define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 0 /* Alpha Architecture Handbook, 4.7.10.4 sez that we should prefer any type of NaN in Fb, then Fa. */ diff --git a/ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h b/ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h index c81067dfd7..1bdde5ace8 100644 --- a/ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h +++ b/ports/sysdeps/mips/mips64/soft-fp/sfp-machine.h @@ -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_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_D ((_FP_QNANBIT_D << 1) - 1) -#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1 +#define _FP_NANFRAC_S (_FP_QNANBIT_S - 1) +#define _FP_NANFRAC_D (_FP_QNANBIT_D - 1) +#define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1 #define _FP_NANSIGN_S 0 #define _FP_NANSIGN_D 0 #define _FP_NANSIGN_Q 0 #define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 1 + /* From my experiments it seems X is chosen unless one of the NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */ #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ diff --git a/ports/sysdeps/mips/soft-fp/sfp-machine.h b/ports/sysdeps/mips/soft-fp/sfp-machine.h index 3b2a40f0e2..8ccfaa60fd 100644 --- a/ports/sysdeps/mips/soft-fp/sfp-machine.h +++ b/ports/sysdeps/mips/soft-fp/sfp-machine.h @@ -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_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_D ((_FP_QNANBIT_D << 1) - 1), -1 -#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1 +#define _FP_NANFRAC_S (_FP_QNANBIT_S - 1) +#define _FP_NANFRAC_D (_FP_QNANBIT_D - 1), -1 +#define _FP_NANFRAC_Q (_FP_QNANBIT_Q - 1), -1, -1, -1 #define _FP_NANSIGN_S 0 #define _FP_NANSIGN_D 0 #define _FP_NANSIGN_Q 0 #define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 1 + /* From my experiments it seems X is chosen unless one of the NaNs is sNaN, in which case the result is NANSIGN/NANFRAC. */ #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ diff --git a/ports/sysdeps/powerpc/soft-fp/sfp-machine.h b/ports/sysdeps/powerpc/soft-fp/sfp-machine.h index 8a9afad3e6..c2a190e7ef 100644 --- a/ports/sysdeps/powerpc/soft-fp/sfp-machine.h +++ b/ports/sysdeps/powerpc/soft-fp/sfp-machine.h @@ -22,6 +22,7 @@ #define _FP_NANSIGN_Q 0 #define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 0 /* Someone please check this. */ #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h index a9d94d7f16..8b73b58c52 100644 --- a/soft-fp/op-common.h +++ b/soft-fp/op-common.h @@ -35,6 +35,16 @@ _FP_I_TYPE X##_e; \ _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 * of fp value and normalizing both the exponent and the fraction. @@ -74,7 +84,7 @@ do { \ { \ X##_c = FP_CLS_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); \ } \ break; \ @@ -112,7 +122,7 @@ do { \ do { \ if (X##_e == _FP_EXPMAX_##fs \ && !_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); \ } while (0) @@ -127,6 +137,39 @@ do { \ _FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \ } 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). */ #define _FP_EXP_NORMAL(fs, wc, X) (((X##_e + 1) & _FP_EXPMAX_##fs) > 1) @@ -159,7 +202,7 @@ do { \ X##_s = _FP_NANSIGN_##fs; \ } \ else \ - _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \ + _FP_SETQNAN(fs, wc, X); \ } \ } while (0) @@ -273,7 +316,7 @@ do { \ X##_s = _FP_NANSIGN_##fs; \ } \ else \ - _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \ + _FP_SETQNAN(fs, wc, X); \ break; \ } \ } while (0) @@ -287,7 +330,7 @@ do { \ if (X##_e == _FP_EXPMAX_##fs) \ { \ if (!_FP_FRAC_ZEROP_##wc(X) \ - && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ + && _FP_FRAC_SNANP(fs, X)) \ __ret = 1; \ } \ __ret; \ @@ -1199,7 +1242,7 @@ do { \ D##_e = _FP_EXPMAX_##dfs; \ 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_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \ - _FP_FRACBITS_##sfs)); \ @@ -1286,7 +1329,7 @@ do { \ /* Semi-raw NaN must have all workbits cleared. */ \ _FP_FRAC_LOW_##dwc(D) \ &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \ - _FP_FRAC_HIGH_##dfs(D) |= _FP_QNANBIT_SH_##dfs; \ + _FP_SETQNAN_SEMIRAW(dfs, dwc, D); \ } \ } \ } \ diff --git a/soft-fp/testit.c b/soft-fp/testit.c index 46a50c4401..f1e9b54758 100644 --- a/soft-fp/testit.c +++ b/soft-fp/testit.c @@ -200,17 +200,17 @@ double gen_special_double(int i) case 0: X_c = FP_CLS_NAN; #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 - _FP_FRAC_SET_1(X, _FP_QNANBIT_D | 0x1234); + _FP_FRAC_SET_1(X, (_FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D) | 0x1234); #endif break; case 2: X_c = FP_CLS_NAN; #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 - _FP_FRAC_SET_1(X, _FP_QNANBIT_D | 0x1); + _FP_FRAC_SET_1(X, (_FP_QNANNEGATEDP ? 0 : _FP_QNANBIT_D) | 0x1); #endif break; case 4: diff --git a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h index 17c4cd125f..35bd2ccc4a 100644 --- a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h +++ b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h @@ -47,6 +47,7 @@ #define _FP_NANSIGN_Q 0 #define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 0 /* If one NaN is signaling and the other is not, * we choose that one, otherwise we choose X. diff --git a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h index f2d106ec09..562fdfc1cf 100644 --- a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h +++ b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h @@ -60,6 +60,7 @@ do { \ #define _FP_NANSIGN_Q 0 #define _FP_KEEPNANFRACP 1 +#define _FP_QNANNEGATEDP 0 /* If one NaN is signaling and the other is not, * we choose that one, otherwise we choose Y. |