diff --git a/ChangeLog b/ChangeLog index 79035751dc..48f90f47f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-02-19 Steven Munroe + + [BZ #5768] + * sysdeps/powerpc/fpu/Makefile (libm-tests): Add test-powerpc-snan. + * sysdeps/powerpc/fpu/test-powerpc-snan.c: New file. + +2008-02-18 Steven Munroe + + [BZ #5768] + * sysdeps/powerpc/powerpc32/fpu/s_isnan.S: New file. + * sysdeps/powerpc/powerpc32/fpu/s_isnan.c: Removed. + * sysdeps/powerpc/powerpc64/fpu/s_isnan.S: New file. + * sysdeps/powerpc/powerpc64/fpu/s_isnan.c: Removed. + 2008-04-10 Jakub Jelinek * stdlib/tst-makecontext.c (othervar): New variable. diff --git a/sysdeps/powerpc/fpu/Makefile b/sysdeps/powerpc/fpu/Makefile index 060c952d15..ce67ff87df 100644 --- a/sysdeps/powerpc/fpu/Makefile +++ b/sysdeps/powerpc/fpu/Makefile @@ -1,5 +1,6 @@ ifeq ($(subdir),math) libm-support += fenv_const fe_nomask fe_mask t_sqrt +libm-tests += test-powerpc-snan # libm needs ld.so to access dl_hwcap $(objpfx)libm.so: $(elfobjdir)/ld.so diff --git a/sysdeps/powerpc/fpu/test-powerpc-snan.c b/sysdeps/powerpc/fpu/test-powerpc-snan.c new file mode 100644 index 0000000000..93b212abcb --- /dev/null +++ b/sysdeps/powerpc/fpu/test-powerpc-snan.c @@ -0,0 +1,385 @@ +/* Test Signalling NaN in isnan, isinf etc functions. + Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _GNU_SOURCE +#define __USE_GNU +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int dest_offset; +char *dest_address; +double value = 123.456; +double zero = 0.0; + +float SNANf; +double SNAN; +long double SNANl; + +static sigjmp_buf sigfpe_buf; + +void +init_signaling_nan() +{ + union { + double _ld16; + double _d8; + unsigned int _ui4[4]; + float _f4; + } nan_temp; + + nan_temp._ui4[0] = 0x7fa00000; + SNANf = nan_temp._f4; + + nan_temp._ui4[0] = 0x7ff40000; + nan_temp._ui4[1] = 0x00000000; + SNAN = nan_temp._d8; + + nan_temp._ui4[0] = 0x7ff40000; + nan_temp._ui4[1] = 0x00000000; + nan_temp._ui4[2] = 0x00000000; + nan_temp._ui4[3] = 0x00000000; + SNANl = nan_temp._ld16; +} + +static float +snan_float (void) +{ + return SNANf; +} + +static double +snan_double (void) +{ + return SNAN; +} + +typedef long double ldouble; + +static ldouble +snan_ldouble (void) +{ + return SNANl; +} + + +void +myFPsighandler(int signal, + siginfo_t *info, + void *context) +{ + siglongjmp(sigfpe_buf, 0); +} + +int +set_sigaction_FP(void) +{ + struct sigaction sa; + /* register RT signal handler via sigaction */ + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = &myFPsighandler; + sigemptyset(&sa.sa_mask); + sigaction(SIGFPE, &sa, NULL); + + return 0; +} + +int +remove_sigaction_FP(void) +{ + struct sigaction sa; + /* restore default RT signal handler via sigaction */ + sa.sa_flags = SA_SIGINFO; + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sigaction(SIGFPE, &sa, NULL); + + return 0; +} + +static int errors = 0; + +static void +check (const char *testname, int result) +{ + if (!result) { + printf ("Failure: %s\n", testname); + errors++; + } +} + +#define TEST_FUNC(NAME, FLOAT) \ +static void \ +NAME (void) \ +{ \ + /* Variables are declared volatile to forbid some compiler \ + optimizations. */ \ + volatile FLOAT Inf_var, NaN_var, zero_var, one_var, SNaN_var; \ + fenv_t saved_fenv; \ + \ + zero_var = 0.0; \ + one_var = 1.0; \ + NaN_var = zero_var / zero_var; \ + SNaN_var = snan_##FLOAT (); \ + Inf_var = one_var / zero_var; \ + \ + (void) &zero_var; \ + (void) &one_var; \ + (void) &NaN_var; \ + (void) &SNaN_var; \ + (void) &Inf_var; \ + \ + set_sigaction_FP (); \ + fegetenv(&saved_fenv); \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnan(NaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnan (NaN)", isnan (NaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnan(-NaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnan (-NaN)", isnan (-NaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnan(SNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnan (SNaN)", isnan (SNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnan(-SNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnan (-SNaN)", isnan (-SNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isinf(NaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isinf (NaN)", !isinf (NaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isinf(-NaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isinf (-NaN)", !isinf (-NaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isinf(SNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isinf (SNaN)", !isinf (SNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isinf(-SNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isinf (-SNaN)", !isinf (-SNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isfinite(NaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isfinite (NaN)", !isfinite (NaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isfinite(-NaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isfinite (-NaN)", !isfinite (-NaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isfinite(SNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isfinite (SNaN)", !isfinite (SNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isfinite(-SNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isfinite (-SNaN)", !isfinite (-SNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnormal(NaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnormal (NaN)", !isnormal (NaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnormal(-NaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnormal (-NaN)", !isnormal (-NaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnormal(SNaN) isnormal SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnormal (SNaN)", !isnormal (SNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " isnormal(-SNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " isnormal (-SNaN)", !isnormal (-SNaN_var)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " fpclassify(NaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " fpclassify (NaN)", (fpclassify (NaN_var)==FP_NAN)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " fpclassify(-NaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " fpclassify (-NaN)", (fpclassify (-NaN_var)==FP_NAN)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " fpclassify(SNaN) isnormal SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " fpclassify (SNaN)", (fpclassify (SNaN_var)==FP_NAN)); \ + } \ + \ + feclearexcept(FE_ALL_EXCEPT); \ + feenableexcept (FE_ALL_EXCEPT); \ + if (sigsetjmp(sigfpe_buf, 0)) \ + { \ + printf (#FLOAT " fpclassify(-SNaN) raised SIGFPE\n"); \ + errors++; \ + } else { \ + check (#FLOAT " fpclassify (-SNaN)", (fpclassify (-SNaN_var)==FP_NAN)); \ + } \ + \ + fesetenv(&saved_fenv); /* restore saved fenv */ \ + remove_sigaction_FP(); \ +} + +TEST_FUNC (float_test, float) +TEST_FUNC (double_test, double) +#ifndef NO_LONG_DOUBLE +TEST_FUNC (ldouble_test, ldouble) +#endif + +static int +do_test (void) +{ + init_signaling_nan(); + + float_test(); + double_test(); +#ifndef NO_LONG_DOUBLE + ldouble_test(); +#endif + + return errors != 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" + diff --git a/sysdeps/powerpc/powerpc32/fpu/s_isnan.c b/sysdeps/powerpc/powerpc32/fpu/s_isnan.c deleted file mode 100644 index 397717ba9c..0000000000 --- a/sysdeps/powerpc/powerpc32/fpu/s_isnan.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#ifndef IS_IN_libm -# if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0) -compat_symbol (libc, __isnan, __isnanl, GLIBC_2_0); -compat_symbol (libc, isnan, isnanl, GLIBC_2_0); -# endif -#endif diff --git a/sysdeps/powerpc/powerpc64/fpu/s_isnan.S b/sysdeps/powerpc/powerpc64/fpu/s_isnan.S new file mode 100644 index 0000000000..9963896f2d --- /dev/null +++ b/sysdeps/powerpc/powerpc64/fpu/s_isnan.S @@ -0,0 +1,57 @@ +/* isnan(). PowerPC64 version. + Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* int __isnan(x) */ + .machine power4 +EALIGN (__isnan, 4, 0) + CALL_MCOUNT 0 + mffs fp0 + mtfsb0 4*cr6+lt /* reset_fpscr_bit (FPSCR_VE) */ + fcmpu cr7,fp1,fp1 + mtfsf 255,fp0 + li r3,0 + beqlr+ cr7 /* (x == x) then not a NAN */ + li r3,1 /* else must be a NAN */ + blr + END (__isnan) + +hidden_def (__isnan) +weak_alias (__isnan, isnan) + +/* It turns out that the 'double' version will also always work for + single-precision. */ +strong_alias (__isnan, __isnanf) +hidden_def (__isnanf) +weak_alias (__isnanf, isnanf) + +#ifdef NO_LONG_DOUBLE +strong_alias (__isnan, __isnanl) +weak_alias (__isnan, isnanl) +#endif + +#ifndef IS_IN_libm +# if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0) +compat_symbol (libc, __isnan, __isnanl, GLIBC_2_0); +compat_symbol (libc, isnan, isnanl, GLIBC_2_0); +# endif +#endif + diff --git a/sysdeps/powerpc/powerpc64/fpu/s_isnan.c b/sysdeps/powerpc/powerpc64/fpu/s_isnan.c deleted file mode 100644 index 397717ba9c..0000000000 --- a/sysdeps/powerpc/powerpc64/fpu/s_isnan.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#ifndef IS_IN_libm -# if LONG_DOUBLE_COMPAT(libc, GLIBC_2_0) -compat_symbol (libc, __isnan, __isnanl, GLIBC_2_0); -compat_symbol (libc, isnan, isnanl, GLIBC_2_0); -# endif -#endif