From b0c50524f1fb93adbd52e9950f92650e020b0d59 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 10 Apr 2008 19:21:13 +0000 Subject: Updated to fedora-glibc-20080410T1907 --- sysdeps/i386/i686/memcpy.S | 57 +++- sysdeps/ieee754/ldbl-128/e_lgammal_r.c | 6 + sysdeps/powerpc/fpu/Makefile | 1 + sysdeps/powerpc/fpu/test-powerpc-snan.c | 385 ++++++++++++++++++++++++ sysdeps/powerpc/powerpc32/fpu/s_isnan.S | 56 ++++ sysdeps/powerpc/powerpc32/fpu/s_isnan.c | 7 - sysdeps/powerpc/powerpc32/power4/fpu/w_sqrt.S | 119 ++++++++ sysdeps/powerpc/powerpc32/power4/fpu/w_sqrt.c | 62 ---- sysdeps/powerpc/powerpc32/power4/fpu/w_sqrtf.S | 111 +++++++ sysdeps/powerpc/powerpc32/power4/fpu/w_sqrtf.c | 60 ---- sysdeps/powerpc/powerpc32/power4/hp-timing.c | 25 ++ sysdeps/powerpc/powerpc32/power4/hp-timing.h | 152 ++++++++++ sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S | 62 ++++ sysdeps/powerpc/powerpc32/power5/fpu/s_isnanf.S | 46 +++ sysdeps/powerpc/powerpc32/power5/fpu/w_sqrt.S | 117 +++++++ sysdeps/powerpc/powerpc32/power5/fpu/w_sqrtf.S | 109 +++++++ sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S | 62 ++++ sysdeps/powerpc/powerpc32/power6/fpu/s_isnanf.S | 46 +++ sysdeps/powerpc/powerpc64/dl-machine.h | 49 +-- sysdeps/powerpc/powerpc64/fpu/s_isnan.S | 57 ++++ sysdeps/powerpc/powerpc64/fpu/s_isnan.c | 7 - sysdeps/powerpc/powerpc64/hp-timing.h | 6 +- sysdeps/powerpc/powerpc64/power5/fpu/s_isnan.S | 61 ++++ sysdeps/powerpc/powerpc64/power6/fpu/s_isnan.S | 60 ++++ sysdeps/powerpc/powerpc64/power6x/fpu/s_isnan.S | 59 ++++ sysdeps/unix/sysv/linux/i386/vfork.S | 3 +- sysdeps/unix/sysv/linux/x86_64/makecontext.c | 26 +- sysdeps/unix/sysv/linux/x86_64/vfork.S | 3 +- sysdeps/unix/sysv/syscalls.list | 2 +- 29 files changed, 1634 insertions(+), 182 deletions(-) create mode 100644 sysdeps/powerpc/fpu/test-powerpc-snan.c create mode 100644 sysdeps/powerpc/powerpc32/fpu/s_isnan.S delete mode 100644 sysdeps/powerpc/powerpc32/fpu/s_isnan.c create mode 100644 sysdeps/powerpc/powerpc32/power4/fpu/w_sqrt.S delete mode 100644 sysdeps/powerpc/powerpc32/power4/fpu/w_sqrt.c create mode 100644 sysdeps/powerpc/powerpc32/power4/fpu/w_sqrtf.S delete mode 100644 sysdeps/powerpc/powerpc32/power4/fpu/w_sqrtf.c create mode 100644 sysdeps/powerpc/powerpc32/power4/hp-timing.c create mode 100644 sysdeps/powerpc/powerpc32/power4/hp-timing.h create mode 100644 sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S create mode 100644 sysdeps/powerpc/powerpc32/power5/fpu/s_isnanf.S create mode 100644 sysdeps/powerpc/powerpc32/power5/fpu/w_sqrt.S create mode 100644 sysdeps/powerpc/powerpc32/power5/fpu/w_sqrtf.S create mode 100644 sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S create mode 100644 sysdeps/powerpc/powerpc32/power6/fpu/s_isnanf.S create mode 100644 sysdeps/powerpc/powerpc64/fpu/s_isnan.S delete mode 100644 sysdeps/powerpc/powerpc64/fpu/s_isnan.c create mode 100644 sysdeps/powerpc/powerpc64/power5/fpu/s_isnan.S create mode 100644 sysdeps/powerpc/powerpc64/power6/fpu/s_isnan.S create mode 100644 sysdeps/powerpc/powerpc64/power6x/fpu/s_isnan.S (limited to 'sysdeps') diff --git a/sysdeps/i386/i686/memcpy.S b/sysdeps/i386/i686/memcpy.S index 00e84ec2e5..ff5c66e9d4 100644 --- a/sysdeps/i386/i686/memcpy.S +++ b/sysdeps/i386/i686/memcpy.S @@ -1,7 +1,7 @@ /* Copy memory block and return pointer to beginning of destination block For Intel 80x86, x>=6. This file is part of the GNU C Library. - Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2003, 2004, 2008 Free Software Foundation, Inc. Contributed by Ulrich Drepper , 1999. The GNU C Library is free software; you can redistribute it and/or @@ -41,29 +41,64 @@ END (__memcpy_chk) ENTRY (BP_SYM (memcpy)) ENTER - movl LEN(%esp), %ecx movl %edi, %eax movl DEST(%esp), %edi movl %esi, %edx movl SRC(%esp), %esi - CHECK_BOUNDS_BOTH_WIDE (%edi, DEST(%esp), %ecx) - CHECK_BOUNDS_BOTH_WIDE (%esi, SRC(%esp), %ecx) + movl %edi, %ecx + xorl %esi, %ecx + andl $3, %ecx + movl LEN(%esp), %ecx cld - shrl $1, %ecx - jnc 1f + jne .Lunaligned + + cmpl $3, %ecx + jbe .Lunaligned + + testl $3, %esi + je 1f movsb -1: shrl $1, %ecx - jnc 2f - movsw -2: rep + decl %ecx + testl $3, %esi + je 1f + movsb + decl %ecx + testl $3, %esi + je 1f + movsb + decl %ecx +1: pushl %eax + movl %ecx, %eax + shrl $2, %ecx + rep movsl - movl %eax, %edi + movl %eax, %ecx + andl $3, %ecx + rep + movsb + popl %eax + +.Lend: movl %eax, %edi movl %edx, %esi movl DEST(%esp), %eax RETURN_BOUNDED_POINTER (DEST(%esp)) LEAVE RET_PTR + + /* When we come here the pointers do not have the same + alignment or the length is too short. No need to optimize for + aligned memory accesses. */ +.Lunaligned: + shrl $1, %ecx + jnc 1f + movsb +1: shrl $1, %ecx + jnc 2f + movsw +2: rep + movsl + jmp .Lend END (BP_SYM (memcpy)) libc_hidden_builtin_def (memcpy) diff --git a/sysdeps/ieee754/ldbl-128/e_lgammal_r.c b/sysdeps/ieee754/ldbl-128/e_lgammal_r.c index b9302974c0..d080448476 100644 --- a/sysdeps/ieee754/ldbl-128/e_lgammal_r.c +++ b/sysdeps/ieee754/ldbl-128/e_lgammal_r.c @@ -772,6 +772,12 @@ __ieee754_lgammal_r (x, signgamp) if (! __finitel (x)) return x * x; + if (x == 0.0L) + { + if (__signbitl (x)) + *signgamp = -1; + } + if (x < 0.0L) { q = -x; 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.S b/sysdeps/powerpc/powerpc32/fpu/s_isnan.S new file mode 100644 index 0000000000..6e3f396de9 --- /dev/null +++ b/sysdeps/powerpc/powerpc32/fpu/s_isnan.S @@ -0,0 +1,56 @@ +/* isnan(). PowerPC32 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) + 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/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/powerpc32/power4/fpu/w_sqrt.S b/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrt.S new file mode 100644 index 0000000000..6aef4e301b --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrt.S @@ -0,0 +1,119 @@ +/* sqrt function. PowerPC32 version. + Copyright (C) 2007 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., 1 Franklin Street, Fifth Floor, Boston MA + 02110-1301 USA. */ + +#include +#include + +/* double [fp1] sqrt (double x [fp1]) + Power4 (ISA V2.0) and above implement sqrt in hardware (not optional). + The fsqrt instruction generates the correct value for all inputs and + sets the appropriate floating point exceptions. Extented checking is + only needed to set errno (via __kernel_standard) if the input value + is negative. + + The fsqrt will set FPCC and FU (Floating Point Unordered or NaN + to indicated that the input value was negative or NaN. Use Move to + Condition Register from FPSCR to copy the FPCC field to cr1. The + branch on summary overflow transfers control to w_sqrt to process + any error conditions. Otherwise we can return the result directly. + + This part of the function is a leaf routine, so no need to stack a + frame or execute prologue/epilogue code. This means it is safe to + transfer directly to w_sqrt as long as the input value (f1) is + preserved. Putting the the sqrt result into f2 (double parameter 2) + allows passing both the input value and sqrt result into the extended + wrapper so there is no need to recompute. + + This tactic avoids the overhead of stacking a frame for the normal + (non-error) case. Until gcc supports prologue shrink-wrapping + this is the best we can do. */ + + .section ".text" + .machine power4 +EALIGN (__sqrt, 5, 0) + fsqrt fp2,fp1 + mcrfs cr1,4 + bso- cr1,.Lw_sqrt + fmr fp1,fp2 + blr + .align 4 +.Lw_sqrt: + mflr r0 + stwu r1,-16(r1) + cfi_adjust_cfa_offset(16) + fmr fp12,fp2 + stw r0,20(r1) + stw r30,8(r1) + cfi_offset(lr,20) + cfi_offset(r30,8) +#ifdef SHARED +# ifdef HAVE_ASM_PPC_REL16 + bcl 20,31,.LCF1 +.LCF1: + mflr r30 + addis r30,r30,_GLOBAL_OFFSET_TABLE_-.LCF1@ha + addi r30,r30,_GLOBAL_OFFSET_TABLE_-.LCF1@l + lwz r9,_LIB_VERSION@got(30) + lwz r0,0(r9) +# else + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr r30 + lwz r9,_LIB_VERSION@got(30) + lwz r0,0(r9) +# endif +#else + lis r9,_LIB_VERSION@ha + lwz r0,_LIB_VERSION@l(r9) +#endif +/* if (_LIB_VERSION == _IEEE_) return z; */ + cmpwi cr7,r0,-1 + beq- cr7,.L4 +/* if (x != x) return z; !isnan*/ + fcmpu cr7,fp1,fp1 + bne- cr7,.L4 +/* if (x < 0.0) + return __kernel_standard (x, x, 26) */ + fmr fp2,fp1 + fabs fp0,fp1 + li r3,26 + fcmpu cr7,fp1,fp0 + bne- cr7,.L11 +.L4: + lwz r0,20(r1) + fmr fp1,fp12 + lwz r30,8(r1) + addi r1,r1,16 + mtlr r0 + blr +.L11: + bl __kernel_standard@plt + fmr fp12,fp1 + b .L4 + END (__sqrt) + +weak_alias (__sqrt, sqrt) + +#ifdef NO_LONG_DOUBLE +weak_alias (__sqrt, sqrtl) +strong_alias (__sqrt, __sqrtl) +#endif +#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0) +compat_symbol (libm, __sqrt, sqrtl, GLIBC_2_0) +#endif + diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrt.c b/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrt.c deleted file mode 100644 index f59c193934..0000000000 --- a/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrt.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Double-precision floating point square root wrapper. - Copyright (C) 2004, 2007 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 "math.h" -#include "math_private.h" -#include - -#ifdef __STDC__ -double -__sqrt (double x) /* wrapper sqrt */ -#else -double -__sqrt (x) /* wrapper sqrt */ - double x; -#endif -{ - double z; -/* Power4 (ISA V2.0) and above implement sqrt in hardware. */ - __asm __volatile ( - " fsqrt %0,%1\n" - : "=f" (z) - : "f" (x)); -#ifdef _IEEE_LIBM - return z; -#else - if (__builtin_expect (_LIB_VERSION == _IEEE_, 0)) - return z; - - if (__builtin_expect (x != x, 0)) - return z; - - if (__builtin_expect (x < 0.0, 0)) - return __kernel_standard (x, x, 26); /* sqrt(negative) */ - else - return z; -#endif -} - -weak_alias (__sqrt, sqrt) -#ifdef NO_LONG_DOUBLE - strong_alias (__sqrt, __sqrtl) weak_alias (__sqrt, sqrtl) -#endif -#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0) -compat_symbol (libm, __sqrt, sqrtl, GLIBC_2_0); -#endif diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrtf.S b/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrtf.S new file mode 100644 index 0000000000..e5b8b9d565 --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrtf.S @@ -0,0 +1,111 @@ +/* sqrtf function. PowerPC32 version. + Copyright (C) 2007 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., 1 Franklin Street, Fifth Floor, Boston MA + 02110-1301 USA. */ + +#include +#include + +/* float [fp1] sqrts (float x [fp1]) + Power4 (ISA V2.0) and above implement sqrt in hardware (not optional). + The fsqrts instruction generates the correct value for all inputs and + sets the appropriate floating point exceptions. Extented checking is + only needed to set errno (via __kernel_standard) if the input value + is negative. + + The fsqrts will set FPCC and FU (Floating Point Unordered or NaN + to indicated that the input value was negative or NaN. Use Move to + Condition Register from FPSCR to copy the FPCC field to cr1. The + branch on summary overflow transfers control to w_sqrt to process + any error conditions. Otherwise we can return the result directly. + + This part of the function is a leaf routine, so no need to stack a + frame or execute prologue/epilogue code. This means it is safe to + transfer directly to w_sqrt as long as the input value (f1) is + preserved. Putting the the sqrt result into f2 (float parameter 2) + allows passing both the input value and sqrt result into the extended + wrapper so there is no need to recompute. + + This tactic avoids the overhead of stacking a frame for the normal + (non-error) case. Until gcc supports prologue shrink-wrapping + this is the best we can do. */ + + .section ".text" + .machine power4 +EALIGN (__sqrtf, 5, 0) + fsqrts fp2,fp1 + mcrfs cr1,4 + bso- cr1,.Lw_sqrtf + fmr fp1,fp2 + blr + .align 4 +.Lw_sqrtf: + mflr r0 + stwu r1,-16(r1) + cfi_adjust_cfa_offset(16) + fmr fp12,fp2 + stw r0,20(r1) + stw r30,8(r1) + cfi_offset(lr,20) + cfi_offset(r30,8) +#ifdef SHARED +# ifdef HAVE_ASM_PPC_REL16 + bcl 20,31,.LCF1 +.LCF1: + mflr r30 + addis r30,r30,_GLOBAL_OFFSET_TABLE_-.LCF1@ha + addi r30,r30,_GLOBAL_OFFSET_TABLE_-.LCF1@l + lwz r9,_LIB_VERSION@got(30) + lwz r0,0(r9) +# else + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr r30 + lwz r9,_LIB_VERSION@got(30) + lwz r0,0(r9) +# endif +#else + lis r9,_LIB_VERSION@ha + lwz r0,_LIB_VERSION@l(r9) +#endif +/* if (_LIB_VERSION == _IEEE_) return z; */ + cmpwi cr7,r0,-1 + beq- cr7,.L4 +/* if (x != x, 0) return z; !isnan */ + fcmpu cr7,fp1,fp1 + bne- cr7,.L4 +/* if (x < 0.0) + return __kernel_standard (x, x, 126) */ + fmr fp2,fp1 + fabs fp0,fp1 + li r3,126 + fcmpu cr7,1,0 + bne- cr7,.L11 +.L4: + lwz r0,20(r1) + fmr fp1,fp12 + lwz r30,8(r1) + addi r1,r1,16 + mtlr r0 + blr +.L11: + bl __kernel_standard@plt + fmr fp12,fp1 + b .L4 + END (__sqrtf) + +weak_alias (__sqrtf, sqrtf) + diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrtf.c b/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrtf.c deleted file mode 100644 index 4784869f07..0000000000 --- a/sysdeps/powerpc/powerpc32/power4/fpu/w_sqrtf.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Single-precision floating point square root wrapper. - Copyright (C) 2004, 2007 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 "math.h" -#include "math_private.h" -#include - -#include -#include - -#ifdef __STDC__ -float -__sqrtf (float x) /* wrapper sqrtf */ -#else -float -__sqrtf (x) /* wrapper sqrtf */ - float x; -#endif -{ -#ifdef _IEEE_LIBM - return __ieee754_sqrtf (x); -#else - float z; -/* Power4 (ISA V2.0) and above implement sqrtf in hardware. */ - __asm __volatile ( - " fsqrts %0,%1\n" - : "=f" (z) - : "f" (x)); - - if (__builtin_expect (_LIB_VERSION == _IEEE_, 0)) - return z; - - if (__builtin_expect (x != x, 0)) - return z; - - if (__builtin_expect (x < 0.0, 0)) - /* sqrtf(negative) */ - return (float) __kernel_standard ((double) x, (double) x, 126); - else - return z; -#endif -} - -weak_alias (__sqrtf, sqrtf) diff --git a/sysdeps/powerpc/powerpc32/power4/hp-timing.c b/sysdeps/powerpc/powerpc32/power4/hp-timing.c new file mode 100644 index 0000000000..332fe8af99 --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power4/hp-timing.c @@ -0,0 +1,25 @@ +/* Support for high precision, low overhead timing functions. + powerpc64 version. + Copyright (C) 2005, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + 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 + +/* We have to define the variable for the overhead. */ +hp_timing_t _dl_hp_timing_overhead; diff --git a/sysdeps/powerpc/powerpc32/power4/hp-timing.h b/sysdeps/powerpc/powerpc32/power4/hp-timing.h new file mode 100644 index 0000000000..5f719dd5a1 --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power4/hp-timing.h @@ -0,0 +1,152 @@ +/* High precision, low overhead timing functions. powerpc64 version. + Copyright (C) 2005, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + 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. */ + +#ifndef _HP_TIMING_H +#define _HP_TIMING_H 1 + +#include +#include +#include +#include + +/* The macros defined here use the powerpc 64-bit time base register. + The time base is nominally clocked at 1/8th the CPU clock, but this + can vary. + + The list of macros we need includes the following: + + - HP_TIMING_AVAIL: test for availability. + + - HP_TIMING_INLINE: this macro is non-zero if the functionality is not + implemented using function calls but instead uses some inlined code + which might simply consist of a few assembler instructions. We have to + know this since we might want to use the macros here in places where we + cannot make function calls. + + - hp_timing_t: This is the type for variables used to store the time + values. + + - HP_TIMING_ZERO: clear `hp_timing_t' object. + + - HP_TIMING_NOW: place timestamp for current time in variable given as + parameter. + + - HP_TIMING_DIFF_INIT: do whatever is necessary to be able to use the + HP_TIMING_DIFF macro. + + - HP_TIMING_DIFF: compute difference between two times and store it + in a third. Source and destination might overlap. + + - HP_TIMING_ACCUM: add time difference to another variable. This might + be a bit more complicated to implement for some platforms as the + operation should be thread-safe and 64bit arithmetic on 32bit platforms + is not. + + - HP_TIMING_ACCUM_NT: this is the variant for situations where we know + there are no threads involved. + + - HP_TIMING_PRINT: write decimal representation of the timing value into + the given string. This operation need not be inline even though + HP_TIMING_INLINE is specified. + +*/ + +/* We always assume having the timestamp register. */ +#define HP_TIMING_AVAIL (1) + +/* We indeed have inlined functions. */ +#define HP_TIMING_INLINE (1) + +/* We use 64bit values for the times. */ +typedef unsigned long long int hp_timing_t; + +/* Set timestamp value to zero. */ +#define HP_TIMING_ZERO(Var) (Var) = (0) + +/* That's quite simple. Use the `mftb' instruction. Note that the value + might not be 100% accurate since there might be some more instructions + running in this moment. This could be changed by using a barrier like + 'lwsync' right before the `mftb' instruciton. But we are not interested + in accurate clock cycles here so we don't do this. */ + +#define HP_TIMING_NOW(Var) \ + do { \ + union { long long ll; long ii[2]; } _var; \ + long tmp; \ + __asm__ __volatile__ ( \ + "1: mfspr %0,269;" \ + " mfspr %1,268;" \ + " mfspr %2,269;" \ + " cmpw %0,%2;" \ + " bne 1b;" \ + : "=r" (_var.ii[0]), "=r" (_var.ii[1]) , "=r" (tmp) \ + : : "cr0" \ + ); \ + Var = _var.ll; \ + } while (0) + + +/* Use two 'mftb' instructions in a row to find out how long it takes. + On current POWER4, POWER5, and 970 processors mftb take ~10 cycles. */ +#define HP_TIMING_DIFF_INIT() \ + do { \ + if (GLRO(dl_hp_timing_overhead) == 0) \ + { \ + int __cnt = 5; \ + GLRO(dl_hp_timing_overhead) = ~0ull; \ + do \ + { \ + hp_timing_t __t1, __t2; \ + HP_TIMING_NOW (__t1); \ + HP_TIMING_NOW (__t2); \ + if (__t2 - __t1 < GLRO(dl_hp_timing_overhead)) \ + GLRO(dl_hp_timing_overhead) = __t2 - __t1; \ + } \ + while (--__cnt > 0); \ + } \ + } while (0) + +/* It's simple arithmetic in 64-bit. */ +#define HP_TIMING_DIFF(Diff, Start, End) (Diff) = ((End) - (Start)) + +/* We need to insure that this add is atomic in threaded environments. We use + __arch_atomic_exchange_and_add_64 from atomic.h to get thread safety. */ +#define HP_TIMING_ACCUM(Sum, Diff) \ + do { \ + hp_timing_t __diff = (Diff) - GLRO(dl_hp_timing_overhead); \ + __arch_atomic_exchange_and_add_64 (&(Sum), __diff); \ + } while (0) + +/* No threads, no extra work. */ +#define HP_TIMING_ACCUM_NT(Sum, Diff) (Sum) += (Diff) + +/* Print the time value. */ +#define HP_TIMING_PRINT(Buf, Len, Val) \ + do { \ + char __buf[20]; \ + char *__cp = _itoa (Val, __buf + sizeof (__buf), 10, 0); \ + size_t __len = (Len); \ + char *__dest = (Buf); \ + while (__len-- > 0 && __cp < __buf + sizeof (__buf)) \ + *__dest++ = *__cp++; \ + memcpy (__dest, " ticks", MIN (__len, sizeof (" ticks"))); \ + } while (0) + +#endif /* hp-timing.h */ diff --git a/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S b/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S new file mode 100644 index 0000000000..91337483d7 --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power5/fpu/s_isnan.S @@ -0,0 +1,62 @@ +/* isnan(). PowerPC32 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 power5 +EALIGN (__isnan, 4, 0) + stwu r1,-32(r1) + cfi_adjust_cfa_offset (32) + ori r1,r1,0 + stfd fp1,24(r1) /* copy FPR to GPR */ + ori r1,r1,0 + lwz r4,24(r1) + lwz r5,28(r1) + lis r0,0x7ff0 /* const long r0 0x7ff00000 00000000 */ + clrlwi r4,r4,1 /* x = fabs(x) */ + cmpw cr7,r4,r0 /* if (fabs(x) =< inf) */ + cmpwi cr6,r5,0 + li r3,0 /* then return 0 */ + addi r1,r1,32 + cfi_adjust_cfa_offset (-32) + bltlr+ cr7 + bgt- cr7,L(NaN) + beqlr+ cr6 +L(NaN): + li r3,1 /* else return 1 */ + blr + END (__isnan) + +hidden_def (__isnan) +weak_alias (__isnan, isnan) + +#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/powerpc32/power5/fpu/s_isnanf.S b/sysdeps/powerpc/powerpc32/power5/fpu/s_isnanf.S new file mode 100644 index 0000000000..9b1e95f35f --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power5/fpu/s_isnanf.S @@ -0,0 +1,46 @@ +/* isnan(). PowerPC32 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 __isnanf(x) */ + .machine power5 +EALIGN (__isnanf, 4, 0) + stwu r1,-32(r1) + cfi_adjust_cfa_offset (32) + stfs fp1,28(r1) /* copy FPR to GPR */ + nop + nop + lwz r4,28(r1) + lis r0,0x7f80 /* const long r0 0x7f800000 */ + clrlwi r4,r4,1 /* x = fabs(x) */ + cmpw cr7,r4,r0 /* if (fabs(x) =< inf) */ + li r3,0 /* then return 0 */ + addi r1,r1,32 + cfi_adjust_cfa_offset (-32) + blelr+ cr7 +L(NaN): + li r3,1 /* else return 1 */ + blr + END (__isnanf) + +hidden_def (__isnanf) +weak_alias (__isnanf, isnanf) + diff --git a/sysdeps/powerpc/powerpc32/power5/fpu/w_sqrt.S b/sysdeps/powerpc/powerpc32/power5/fpu/w_sqrt.S new file mode 100644 index 0000000000..925930bf77 --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power5/fpu/w_sqrt.S @@ -0,0 +1,117 @@ +/* sqrt function. PowerPC32 version. + Copyright (C) 2007 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., 1 Franklin Street, Fifth Floor, Boston MA + 02110-1301 USA. */ + +#include +#include + +/* double [fp1] sqrt (double x [fp1]) + Power4 (ISA V2.0) and above implement sqrt in hardware (not optional). + The fsqrt instruction generates the correct value for all inputs and + sets the appropriate floating point exceptions. Extented checking is + only needed to set errno (via __kernel_standard) if the input value + is negative. + + So compare the input value against the absolute value of itself. + This will compare equal unless the value is negative (EDOM) or a NAN, + in which case we branch to the extend wrapper. If equal we can return + the result directly. + + This part of the function looks like a leaf routine, so no need to + stack a frame or execute prologue/epilogue code. It is safe to + branch directly to w_sqrt as long as the input value (f1) is + preserved. Putting the the sqrt result into f2 (float parameter 2) + allows passing both the input value and sqrt result into the extended + wrapper so there is no need to recompute. + + This tactic avoids the overhead of stacking a frame for the normal + (non-error) case. Until gcc supports prologue shrink-wrapping + this is the best we can do. */ + + .section ".text" + .machine power4 +EALIGN (__sqrt, 5, 0) + fabs fp0,fp1 + fsqrt fp2,fp1 + fcmpu cr1,fp0,fp1 + bne- cr1,.Lw_sqrt + fmr fp1,fp2 + blr + .align 4 +.Lw_sqrt: + mflr r0 + stwu r1,-16(r1) + cfi_adjust_cfa_offset(16) + fmr fp12,fp2 + stw r0,20(r1) + stw r30,8(r1) + cfi_offset(lr,20) + cfi_offset(r30,8) +#ifdef SHARED +# ifdef HAVE_ASM_PPC_REL16 + bcl 20,31,.LCF1 +.LCF1: + mflr r30 + addis r30,r30,_GLOBAL_OFFSET_TABLE_-.LCF1@ha + addi r30,r30,_GLOBAL_OFFSET_TABLE_-.LCF1@l + lwz r9,_LIB_VERSION@got(30) + lwz r0,0(r9) +# else + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr r30 + lwz r9,_LIB_VERSION@got(30) + lwz r0,0(r9) +# endif +#else + lis r9,_LIB_VERSION@ha + lwz r0,_LIB_VERSION@l(r9) +#endif +/* if (_LIB_VERSION == _IEEE_) return z; */ + cmpwi cr7,r0,-1 + beq- cr7,.L4 +/* if (x != x) return z; !isnan*/ + fcmpu cr7,fp1,fp1 + bne- cr7,.L4 +/* if (x < 0.0) + return __kernel_standard (x, x, 26) */ + fmr fp2,fp1 + li r3,26 + bne- cr1,.L11 +.L4: + lwz r0,20(r1) + fmr fp1,fp12 + lwz r30,8(r1) + addi r1,r1,16 + mtlr r0 + blr +.L11: + bl __kernel_standard@plt + fmr fp12,fp1 + b .L4 + END (__sqrt) + +weak_alias (__sqrt, sqrt) + +#ifdef NO_LONG_DOUBLE +weak_alias (__sqrt, sqrtl) +strong_alias (__sqrt, __sqrtl) +#endif +#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0) +compat_symbol (libm, __sqrt, sqrtl, GLIBC_2_0) +#endif + diff --git a/sysdeps/powerpc/powerpc32/power5/fpu/w_sqrtf.S b/sysdeps/powerpc/powerpc32/power5/fpu/w_sqrtf.S new file mode 100644 index 0000000000..891e69c9c0 --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power5/fpu/w_sqrtf.S @@ -0,0 +1,109 @@ +/* sqrtf function. PowerPC32 version. + Copyright (C) 2007 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., 1 Franklin Street, Fifth Floor, Boston MA + 02110-1301 USA. */ + +#include +#include + +/* float [fp1] sqrts (float x [fp1]) + Power4 (ISA V2.0) and above implement sqrt in hardware (not optional). + The fsqrts instruction generates the correct value for all inputs and + sets the appropriate floating point exceptions. Extented checking is + only needed to set errno (via __kernel_standard) if the input value + is negative. + + So compare the input value against the absolute value of itself. + This will compare equal unless the value is negative (EDOM) or a NAN, + in which case we branch to the extend wrapper. If equal we can return + the result directly. + + This part of the function looks like a leaf routine, so no need to + stack a frame or execute prologue/epilogue code. It is safe to + branch directly to w_sqrt as long as the input value (f1) is + preserved. Putting the the sqrt result into f2 (float parameter 2) + allows passing both the input value and sqrt result into the extended + wrapper so there is no need to recompute. + + This tactic avoids the overhead of stacking a frame for the normal + (non-error) case. Until gcc supports prologue shrink-wrapping + this is the best we can do. */ + + .section ".text" + .machine power4 +EALIGN (__sqrtf, 5, 0) + fabs fp0,fp1 + fsqrts fp2,fp1 + fcmpu cr1,fp0,fp1 + bne- cr1,.Lw_sqrtf + fmr fp1,fp2 + blr + .align 4 +.Lw_sqrtf: + mflr r0 + stwu r1,-16(r1) + cfi_adjust_cfa_offset(16) + fmr fp12,fp2 + stw r0,20(r1) + stw r30,8(r1) + cfi_offset(lr,20) + cfi_offset(r30,8) +#ifdef SHARED +# ifdef HAVE_ASM_PPC_REL16 + bcl 20,31,.LCF1 +.LCF1: + mflr r30 + addis r30,r30,_GLOBAL_OFFSET_TABLE_-.LCF1@ha + addi r30,r30,_GLOBAL_OFFSET_TABLE_-.LCF1@l + lwz r9,_LIB_VERSION@got(30) + lwz r0,0(r9) +# else + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr r30 + lwz r9,_LIB_VERSION@got(30) + lwz r0,0(r9) +# endif +#else + lis r9,_LIB_VERSION@ha + lwz r0,_LIB_VERSION@l(r9) +#endif +/* if (_LIB_VERSION == _IEEE_) return z; */ + cmpwi cr7,r0,-1 + beq- cr7,.L4 +/* if (x != x, 0) return z; !isnan */ + fcmpu cr7,fp1,fp1 + bne- cr7,.L4 +/* if (x < 0.0) + return __kernel_standard (x, x, 126) */ + fmr fp2,fp1 + li r3,126 + bne- cr1,.L11 +.L4: + lwz r0,20(r1) + fmr fp1,fp12 + lwz r30,8(r1) + addi r1,r1,16 + mtlr r0 + blr +.L11: + bl __kernel_standard@plt + fmr fp12,fp1 + b .L4 + END (__sqrtf) + +weak_alias (__sqrtf, sqrtf) + diff --git a/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S b/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S new file mode 100644 index 0000000000..dbaaf1c1a8 --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power6/fpu/s_isnan.S @@ -0,0 +1,62 @@ +/* isnan(). PowerPC32 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 power6 +EALIGN (__isnan, 4, 0) + stwu r1,-32(r1) + cfi_adjust_cfa_offset (32) + ori r1,r1,0 + stfd fp1,24(r1) /* copy FPR to GPR */ + ori r1,r1,0 + lwz r4,24(r1) + lwz r5,28(r1) + lis r0,0x7ff0 /* const long r0 0x7ff00000 00000000 */ + clrlwi r4,r4,1 /* x = fabs(x) */ + cmpw cr7,r4,r0 /* if (fabs(x) =< inf) */ + cmpwi cr6,r5,0 + li r3,0 /* then return 0 */ + addi r1,r1,32 + cfi_adjust_cfa_offset (-32) + bltlr+ cr7 + bgt- cr7,L(NaN) + beqlr+ cr6 +L(NaN): + li r3,1 /* else return 1 */ + blr + END (__isnan) + +hidden_def (__isnan) +weak_alias (__isnan, isnan) + +#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/powerpc32/power6/fpu/s_isnanf.S b/sysdeps/powerpc/powerpc32/power6/fpu/s_isnanf.S new file mode 100644 index 0000000000..12bf473a8d --- /dev/null +++ b/sysdeps/powerpc/powerpc32/power6/fpu/s_isnanf.S @@ -0,0 +1,46 @@ +/* isnanf(). PowerPC32 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 __isnanf(x) */ + .machine power6 +EALIGN (__isnanf, 4, 0) + stwu r1,-32(r1) + cfi_adjust_cfa_offset (32) + ori r1,r1,0 + stfs fp1,24(r1) /* copy FPR to GPR */ + ori r1,r1,0 + lwz r4,24(r1) + lis r0,0x7f80 /* const long r0 0x7f800000 */ + clrlwi r4,r4,1 /* x = fabs(x) */ + cmpw cr7,r4,r0 /* if (fabs(x) =< inf) */ + li r3,0 /* then return 0 */ + addi r1,r1,32 + cfi_adjust_cfa_offset (-32) + blelr+ cr7 +L(NaN): + li r3,1 /* else return 1 */ + blr + END (__isnan) + +hidden_def (__isnanf) +weak_alias (__isnanf, isnanf) + diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h index 89a69e1a23..c837393d79 100644 --- a/sysdeps/powerpc/powerpc64/dl-machine.h +++ b/sysdeps/powerpc/powerpc64/dl-machine.h @@ -246,30 +246,35 @@ BODY_PREFIX "_dl_start_user:\n" \ " " END_2(_dl_start_user) "\n" \ " .popsection"); -/* Nonzero iff TYPE should not be allowed to resolve to one of - the main executable's symbols, as for a COPY reloc. */ -#define elf_machine_lookup_noexec_p(type) ((type) == R_PPC64_COPY) +/* ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to + one of the main executable's symbols, as for a COPY reloc. + + To make function pointer comparisons work on most targets, the + relevant ABI states that the address of a non-local function in a + dynamically linked executable is the address of the PLT entry for + that function. This is quite reasonable since using the real + function address in a non-PIC executable would typically require + dynamic relocations in .text, something to be avoided. For such + functions, the linker emits a SHN_UNDEF symbol in the executable + with value equal to the PLT entry address. Normally, SHN_UNDEF + symbols have a value of zero, so this is a clue to ld.so that it + should treat these symbols specially. For relocations not in + ELF_RTYPE_CLASS_PLT (eg. those on function pointers), ld.so should + use the value of the executable SHN_UNDEF symbol, ie. the PLT entry + address. For relocations in ELF_RTYPE_CLASS_PLT (eg. the relocs in + the PLT itself), ld.so should use the value of the corresponding + defined symbol in the object that defines the function, ie. the + real function address. This complicates ld.so in that there are + now two possible values for a given symbol, and it gets even worse + because protected symbols need yet another set of rules. + + On PowerPC64 we don't need any of this. The linker won't emit + SHN_UNDEF symbols with non-zero values. ld.so can make all + relocations behave "normally", ie. always use the real address + like PLT relocations. So always set ELF_RTYPE_CLASS_PLT. */ -/* Nonzero iff TYPE describes relocation of a PLT entry, so - PLT entries should not be allowed to define the value. */ -#define elf_machine_lookup_noplt_p(type) ((type) == R_PPC64_JMP_SLOT) - -/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so - PLT entries should not be allowed to define the value. - ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one - of the main executable's symbols, as for a COPY reloc. */ - -#if !defined RTLD_BOOTSTRAP || USE___THREAD -#define elf_machine_type_class(type) \ - /* This covers all the TLS relocs, though most won't appear. */ \ - (((((type) >= R_PPC64_DTPMOD64 && (type) <= R_PPC64_TPREL16_HIGHESTA) \ - || (type) == R_PPC64_ADDR24) * ELF_RTYPE_CLASS_PLT) \ - | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY)) -#else #define elf_machine_type_class(type) \ - ((((type) == R_PPC64_ADDR24) * ELF_RTYPE_CLASS_PLT) \ - | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY)) -#endif + (ELF_RTYPE_CLASS_PLT | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY)) /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ #define ELF_MACHINE_JMP_SLOT R_PPC64_JMP_SLOT 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 diff --git a/sysdeps/powerpc/powerpc64/hp-timing.h b/sysdeps/powerpc/powerpc64/hp-timing.h index b58cca9003..e107a2dd49 100644 --- a/sysdeps/powerpc/powerpc64/hp-timing.h +++ b/sysdeps/powerpc/powerpc64/hp-timing.h @@ -1,5 +1,5 @@ /* High precision, low overhead timing functions. powerpc64 version. - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 1998. @@ -85,7 +85,11 @@ typedef unsigned long long int hp_timing_t; running in this moment. This could be changed by using a barrier like 'lwsync' right before the `mftb' instruciton. But we are not interested in accurate clock cycles here so we don't do this. */ +#ifdef _ARCH_PWR4 +#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("mfspr %0,268" : "=r" (Var)) +#else #define HP_TIMING_NOW(Var) __asm__ __volatile__ ("mftb %0" : "=r" (Var)) +#endif /* Use two 'mftb' instructions in a row to find out how long it takes. On current POWER4, POWER5, and 970 processors mftb take ~10 cycles. */ diff --git a/sysdeps/powerpc/powerpc64/power5/fpu/s_isnan.S b/sysdeps/powerpc/powerpc64/power5/fpu/s_isnan.S new file mode 100644 index 0000000000..d46d049d45 --- /dev/null +++ b/sysdeps/powerpc/powerpc64/power5/fpu/s_isnan.S @@ -0,0 +1,61 @@ +/* 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 power5 +EALIGN (__isnan, 4, 0) + CALL_MCOUNT 0 + stfd fp1,-8(r1) /* copy FPR to GPR */ + lis r0,0x7ff0 + nop /* insure the following is in a different */ + nop /* dispatch group */ + ld r4,-8(r1) + sldi r0,r0,32 /* const long r0 0x7ff00000 00000000 */ + clrldi r4,r4,1 /* x = fabs(x) */ + cmpd cr7,r4,r0 /* if (fabs(x) <= inf) */ + li r3,0 /* then return 0 */ + blelr+ cr7 + li r3,1 /* else return 1 */ + 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/power6/fpu/s_isnan.S b/sysdeps/powerpc/powerpc64/power6/fpu/s_isnan.S new file mode 100644 index 0000000000..fe0c56ca8e --- /dev/null +++ b/sysdeps/powerpc/powerpc64/power6/fpu/s_isnan.S @@ -0,0 +1,60 @@ +/* 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 power6 +EALIGN (__isnan, 4, 0) + CALL_MCOUNT 0 + stfd fp1,-8(r1) /* copy FPR to GPR */ + ori r1,r1,0 + ld r4,-8(r1) + lis r0,0x7ff0 + sldi r0,r0,32 /* const long r0 0x7ff00000 00000000 */ + clrldi r4,r4,1 /* x = fabs(x) */ + cmpd cr7,r4,r0 /* if (fabs(x) <= inf) */ + li r3,0 /* then return 0 */ + blelr+ cr7 + li r3,1 /* else return 1 */ + 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/power6x/fpu/s_isnan.S b/sysdeps/powerpc/powerpc64/power6x/fpu/s_isnan.S new file mode 100644 index 0000000000..47dd49a751 --- /dev/null +++ b/sysdeps/powerpc/powerpc64/power6x/fpu/s_isnan.S @@ -0,0 +1,59 @@ +/* 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 power6 +EALIGN (__isnan, 4, 0) + CALL_MCOUNT 0 + mftgpr r4,fp1 /* copy FPR to GPR */ + lis r0,0x7ff0 + ori r1,r1,0 + clrldi r4,r4,1 /* x = fabs(x) */ + sldi r0,r0,32 /* const long r0 0x7ff00000 00000000 */ + cmpd cr7,r4,r0 /* if (fabs(x) <= inf) */ + li r3,0 /* then return 0 */ + blelr+ cr7 + li r3,1 /* else return 1 */ + 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/unix/sysv/linux/i386/vfork.S b/sysdeps/unix/sysv/linux/i386/vfork.S index eefd4b49cb..2494d9bef0 100644 --- a/sysdeps/unix/sysv/linux/i386/vfork.S +++ b/sysdeps/unix/sysv/linux/i386/vfork.S @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2002, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2002, 2004, 2005, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Schwab . @@ -34,6 +34,7 @@ ENTRY (__vfork) /* Pop the return PC value into ECX. */ popl %ecx cfi_adjust_cfa_offset (-4) + cfi_register (%eip, %ecx) #ifdef SAVE_PID SAVE_PID diff --git a/sysdeps/unix/sysv/linux/x86_64/makecontext.c b/sysdeps/unix/sysv/linux/x86_64/makecontext.c index 5deea7d1b2..615dede522 100644 --- a/sysdeps/unix/sysv/linux/x86_64/makecontext.c +++ b/sysdeps/unix/sysv/linux/x86_64/makecontext.c @@ -1,5 +1,5 @@ /* Create new context. - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2008 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger , 2002. @@ -78,31 +78,39 @@ __makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) sp[idx_uc_link] = (unsigned long int) ucp->uc_link; va_start (ap, argc); - /* Handle arguments. */ + /* Handle arguments. + + The standard says the parameters must all be int values. This is + an historic accident and would be done differently today. For + x86-64 all integer values are passed as 64-bit values and + therefore extending the API to copy 64-bit values instead of + 32-bit ints makes sense. It does not break existing + functionality and it does not violate the standard which says + that passing non-int values means undefined behavior. */ for (i = 0; i < argc; ++i) switch (i) { case 0: - ucp->uc_mcontext.gregs [REG_RDI] = va_arg (ap, int); + ucp->uc_mcontext.gregs[REG_RDI] = va_arg (ap, long int); break; case 1: - ucp->uc_mcontext.gregs [REG_RSI] = va_arg (ap, int); + ucp->uc_mcontext.gregs[REG_RSI] = va_arg (ap, long int); break; case 2: - ucp->uc_mcontext.gregs [REG_RDX] = va_arg (ap, int); + ucp->uc_mcontext.gregs[REG_RDX] = va_arg (ap, long int); break; case 3: - ucp->uc_mcontext.gregs [REG_RCX] = va_arg (ap, int); + ucp->uc_mcontext.gregs[REG_RCX] = va_arg (ap, long int); break; case 4: - ucp->uc_mcontext.gregs [REG_R8] = va_arg (ap, int); + ucp->uc_mcontext.gregs[REG_R8] = va_arg (ap, long int); break; case 5: - ucp->uc_mcontext.gregs [REG_R9] = va_arg (ap, int); + ucp->uc_mcontext.gregs[REG_R9] = va_arg (ap, long int); break; default: /* Put value on stack. */ - sp[(i - 5)] = va_arg (ap, int); + sp[i - 5] = va_arg (ap, unsigned long int); break; } va_end (ap); diff --git a/sysdeps/unix/sysv/linux/x86_64/vfork.S b/sysdeps/unix/sysv/linux/x86_64/vfork.S index 4bad38892b..e289656ad2 100644 --- a/sysdeps/unix/sysv/linux/x86_64/vfork.S +++ b/sysdeps/unix/sysv/linux/x86_64/vfork.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2002, 2004, 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 @@ -31,6 +31,7 @@ ENTRY (__vfork) is preserved by the syscall and that we're allowed to destroy. */ popq %rdi cfi_adjust_cfa_offset(-8) + cfi_register(%rip, %rdi) #ifdef SAVE_PID SAVE_PID diff --git a/sysdeps/unix/sysv/syscalls.list b/sysdeps/unix/sysv/syscalls.list index 436d05eb9a..f65ed79f70 100644 --- a/sysdeps/unix/sysv/syscalls.list +++ b/sysdeps/unix/sysv/syscalls.list @@ -11,6 +11,6 @@ settimeofday - settimeofday i:PP __settimeofday settimeofday signal - signal i:ii signal stime - stime i:p stime time - time Ei:P time -times - times i:p __times times +times - times Ei:p __times times ulimit - ulimit i:ii ulimit utime - utime i:sP utime -- cgit v1.2.3