diff options
author | Andreas Schwab <schwab@redhat.com> | 2009-08-26 12:04:34 +0200 |
---|---|---|
committer | Andreas Schwab <schwab@redhat.com> | 2009-08-26 12:04:34 +0200 |
commit | 19fe1be84e6f775e3a7f4cd03b093338d6a317bf (patch) | |
tree | 1d28740af54a3d9194373f7f561baf579c3a8f44 /sysdeps | |
parent | bc9dd948ffc9cf1992d3e77e753789ab897e3dc6 (diff) | |
parent | 2df4be8c3545f6158e468660a73f794573fb6f07 (diff) |
Merge commit 'origin/master' into fedora/master
Diffstat (limited to 'sysdeps')
21 files changed, 812 insertions, 31 deletions
diff --git a/sysdeps/i386/fpu/bits/mathinline.h b/sysdeps/i386/fpu/bits/mathinline.h index a786cc69cd..8005997520 100644 --- a/sysdeps/i386/fpu/bits/mathinline.h +++ b/sysdeps/i386/fpu/bits/mathinline.h @@ -1,5 +1,5 @@ /* Inline math functions for i387. - Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2003,2004,2006,2007 + Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2003,2004,2006,2007,2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995. @@ -153,6 +153,10 @@ __NTH (__signbitl (long double __x)) #if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \ && defined __OPTIMIZE__) +/* The inline functions do not set errno or raise necessarily the + correct exceptions. */ +# undef math_errhandling + /* A macro to define float, double, and long double versions of various math functions for the ix87 FPU. FUNC is the function name (which will be suffixed with f and l for the float and long double version, diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c new file mode 100644 index 0000000000..9123fdc7bd --- /dev/null +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c @@ -0,0 +1,67 @@ +/* @(#)s_ceil.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * ceil(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to ceil(x). + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double huge = 1.0e300; +#else +static double huge = 1.0e300; +#endif + +#ifdef __STDC__ + double __ceil(double x) +#else + double __ceil(x) + double x; +#endif +{ + int64_t i0,i; + int32_t j0; + EXTRACT_WORDS64(i0,x); + j0 = ((i0>>52)&0x7ff)-0x3ff; + if(j0<=51) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0<0) {i0=INT64_C(0x8000000000000000);} + else if(i0!=0) { i0=INT64_C(0x3ff0000000000000);} + } + } else { + i = INT64_C(0x000fffffffffffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0>0) i0 += UINT64_C(0x0010000000000000)>>j0; + i0 &= (~i); + } + } + } else { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + INSERT_WORDS64(x,i0); + return x; +} +weak_alias (__ceil, ceil) +#ifdef NO_LONG_DOUBLE +strong_alias (__ceil, __ceill) +weak_alias (__ceil, ceill) +#endif diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_isinf.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_isinf.c new file mode 100644 index 0000000000..c48e979a84 --- /dev/null +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_isinf.c @@ -0,0 +1,30 @@ +/* + * Written by J.T. Conklin <jtc@netbsd.org>. + * Changed to return -1 for -Inf by Ulrich Drepper <drepper@cygnus.com>. + * Public domain. + */ + +/* + * isinf(x) returns 1 is x is inf, -1 if x is -inf, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +int +__isinf (double x) +{ + int64_t ix; + EXTRACT_WORDS64(ix,x); + int64_t t = ix & UINT64_C(0x7fffffffffffffff); + t ^= UINT64_C(0x7ff0000000000000); + t |= -t; + return ~(t >> 63) & (ix >> 62); +} +hidden_def (__isinf) +weak_alias (__isinf, isinf) +#ifdef NO_LONG_DOUBLE +strong_alias (__isinf, __isinfl) +weak_alias (__isinf, isinfl) +#endif diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_isnan.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_isnan.c new file mode 100644 index 0000000000..3b08c54dd4 --- /dev/null +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_isnan.c @@ -0,0 +1,39 @@ +/* @(#)s_isnan.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * isnan(x) returns 1 is x is nan, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + int __isnan(double x) +#else + int __isnan(x) + double x; +#endif +{ + int64_t hx; + EXTRACT_WORDS64(hx,x); + hx &= UINT64_C(0x7fffffffffffffff); + hx = UINT64_C(0x7ff0000000000000) - hx; + return (int)(((uint64_t)hx)>>63); +} +hidden_def (__isnan) +weak_alias (__isnan, isnan) +#ifdef NO_LONG_DOUBLE +strong_alias (__isnan, __isnanl) +weak_alias (__isnan, isnanl) +#endif diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_llround.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_llround.c new file mode 100644 index 0000000000..f7c9ea568f --- /dev/null +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_llround.c @@ -0,0 +1 @@ +/* The code is the same as lround. Use an alias, see l_round.c. */ diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_lround.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_lround.c new file mode 100644 index 0000000000..30ea5db7cc --- /dev/null +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_lround.c @@ -0,0 +1,80 @@ +/* Round double value to long int. + Copyright (C) 1997, 2004, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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 llround __hidden_llround +#define __llround __hidden___llround + +#include <math.h> + +#include "math_private.h" + + +long int +__lround (double x) +{ + int32_t j0; + int64_t i0; + long int result; + int sign; + + EXTRACT_WORDS64 (i0, x); + j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; + sign = i0 < 0 ? -1 : 1; + i0 &= UINT64_C(0xfffffffffffff); + i0 |= UINT64_C(0x10000000000000); + + if (j0 < (int32_t) (8 * sizeof (long int)) - 1) + { + if (j0 < 0) + return j0 < -1 ? 0 : sign; + else if (j0 >= 52) + result = i0 << (j0 - 52); + else + { + i0 += UINT64_C(0x8000000000000) >> j0; + + result = i0 >> (52 - j0); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long int) x; + } + + return sign * result; +} + +weak_alias (__lround, lround) +#ifdef NO_LONG_DOUBLE +strong_alias (__lround, __lroundl) +weak_alias (__lround, lroundl) +#endif + +/* long long has the same width as long on 64-bit machines. */ +#undef llround +#undef __llround +strong_alias (__lround, __llround) +weak_alias (__lround, llround) +#ifdef NO_LONG_DOUBLE +strong_alias (__lround, __llroundl) +weak_alias (__lround, llroundl) +#endif diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c new file mode 100644 index 0000000000..cb49019ddb --- /dev/null +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c @@ -0,0 +1,86 @@ +/* Adapted for use as nearbyint by Ulrich Drepper <drepper@cygnus.com>. */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * rint(x) + * Return x rounded to integral value according to the prevailing + * rounding mode. + * Method: + * Using floating addition. + * Exception: + * Inexact flag raised if x not equal to rint(x). + */ + +#include <fenv.h> +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +TWO52[2]={ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +#ifdef __STDC__ + double __nearbyint(double x) +#else + double __nearbyint(x) + double x; +#endif +{ + fenv_t env; + int64_t i0,sx; + int32_t j0; + EXTRACT_WORDS64(i0,x); + sx = (i0>>63)&1; + j0 = ((i0>>52)&0x7ff)-0x3ff; + if(j0<52) { + if(j0<0) { + if((i0&UINT64_C(0x7fffffffffffffff))==0) return x; + uint64_t i = i0 & UINT64_C(0xfffffffffffff); + i0 &= UINT64_C(0xfffe000000000000); + i0 |= (((i|-i) >> 12) & UINT64_C(0x8000000000000)); + INSERT_WORDS64(x,i0); + feholdexcept (&env); + double w = TWO52[sx]+x; + double t = w-TWO52[sx]; + fesetenv (&env); + EXTRACT_WORDS64(i0,t); + INSERT_WORDS64(t,(i0&UINT64_C(0x7fffffffffffffff))|(sx<<63)); + return t; + } else { + uint64_t i = UINT64_C(0x000fffffffffffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + i>>=1; + if((i0&i)!=0) + i0 = (i0&(~i))|(UINT64_C(0x4000000000000)>>j0); + } + } else { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + INSERT_WORDS64(x,i0); + feholdexcept (&env); + double w = TWO52[sx]+x; + double t = w-TWO52[sx]; + fesetenv (&env); + return t; +} +weak_alias (__nearbyint, nearbyint) +#ifdef NO_LONG_DOUBLE +strong_alias (__nearbyint, __nearbyintl) +weak_alias (__nearbyint, nearbyintl) +#endif diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c new file mode 100644 index 0000000000..4a60aa3278 --- /dev/null +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c @@ -0,0 +1,79 @@ +/* @(#)s_rint.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * rint(x) + * Return x rounded to integral value according to the prevailing + * rounding mode. + * Method: + * Using floating addition. + * Exception: + * Inexact flag raised if x not equal to rint(x). + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +TWO52[2]={ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +#ifdef __STDC__ + double __rint(double x) +#else + double __rint(x) + double x; +#endif +{ + int64_t i0,sx; + int32_t j0; + EXTRACT_WORDS64(i0,x); + sx = (i0>>63)&1; + j0 = ((i0>>52)&0x7ff)-0x3ff; + if(j0<52) { + if(j0<0) { + if((i0 & UINT64_C(0x7fffffffffffffff))==0) return x; + uint64_t i = i0 & UINT64_C(0xfffffffffffff); + i0 &= UINT64_C(0xfffe000000000000); + i0 |= (((i|-i) >> 12) & UINT64_C(0x8000000000000)); + INSERT_WORDS64(x,i0); + double w = TWO52[sx]+x; + double t = w-TWO52[sx]; + EXTRACT_WORDS64(i0,t); + INSERT_WORDS64(t,(i0&UINT64_C(0x7fffffffffffffff))|(sx<<63)); + return t; + } else { + uint64_t i = UINT64_C(0x000fffffffffffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + i>>=1; + if((i0&i)!=0) + i0 = (i0&(~i))|(UINT64_C(0x4000000000000)>>j0); + } + } else { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + INSERT_WORDS64(x,i0); + double w = TWO52[sx]+x; + return w-TWO52[sx]; +} +weak_alias (__rint, rint) +#ifdef NO_LONG_DOUBLE +strong_alias (__rint, __rintl) +weak_alias (__rint, rintl) +#endif diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_round.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_round.c new file mode 100644 index 0000000000..5bd857910c --- /dev/null +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_round.c @@ -0,0 +1,77 @@ +/* Round double to integer away from zero. + Copyright (C) 1997, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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" + + +static const double huge = 1.0e300; + + +double +__round (double x) +{ + int64_t i0, j0; + + EXTRACT_WORDS64 (i0, x); + j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; + if (__builtin_expect (j0 < 52, 1)) + { + if (j0 < 0) + { + if (huge + x > 0.0) + { + i0 &= UINT64_C(0x8000000000000000); + if (j0 == -1) + i0 |= UINT64_C(0x3ff0000000000000); + } + } + else + { + uint64_t i = UINT64_C(0x000fffffffffffff) >> j0; + if ((i0 & i) == 0) + /* X is integral. */ + return x; + if (huge + x > 0.0) + { + /* Raise inexact if x != 0. */ + i0 += UINT64_C(0x0008000000000000) >> j0; + i0 &= ~i; + } + } + } + else + { + if (j0 == 0x400) + /* Inf or NaN. */ + return x + x; + else + return x; + } + + INSERT_WORDS64 (x, i0); + return x; +} +weak_alias (__round, round) +#ifdef NO_LONG_DOUBLE +strong_alias (__round, __roundl) +weak_alias (__round, roundl) +#endif diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_scalbn.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_scalbn.c new file mode 100644 index 0000000000..25cf3b1699 --- /dev/null +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_scalbn.c @@ -0,0 +1,68 @@ +/* @(#)s_scalbn.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * scalbn (double x, int n) + * scalbn(x,n) returns x* 2**n computed by exponent + * manipulation rather than by actually performing an + * exponentiation or a multiplication. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ +huge = 1.0e+300, +tiny = 1.0e-300; + +#ifdef __STDC__ + double __scalbn (double x, int n) +#else + double __scalbn (x,n) + double x; int n; +#endif +{ + int64_t ix; + int64_t k; + EXTRACT_WORDS64(ix,x); + k = (ix >> 52) & 0x7ff; /* extract exponent */ + if (k==0) { /* 0 or subnormal x */ + if ((ix & UINT64_C(0xfffffffffffff))==0) return x; /* +-0 */ + x *= two54; + EXTRACT_WORDS64(ix,x); + k = ((ix >> 52) & 0x7ff) - 54; + } + if (k==0x7ff) return x+x; /* NaN or Inf */ + k = k+n; + if (n> 50000 || k > 0x7fe) + return huge*__copysign(huge,x); /* overflow */ + if (n< -50000) return tiny*__copysign(tiny,x); /*underflow*/ + if (k > 0) /* normal result */ + {INSERT_WORDS64(x,(ix&UINT64_C(0x800fffffffffffff))|(k<<52)); + return x;} + if (k <= -54) + return tiny*__copysign(tiny,x); /*underflow*/ + k += 54; /* subnormal result */ + INSERT_WORDS64(x,(ix&INT64_C(0x800fffffffffffff))|(k<<52)); + return x*twom54; +} +weak_alias (__scalbn, scalbn) +#ifdef NO_LONG_DOUBLE +strong_alias (__scalbn, __scalbnl) +weak_alias (__scalbn, scalbnl) +#endif diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c new file mode 100644 index 0000000000..9add5ade71 --- /dev/null +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c @@ -0,0 +1,56 @@ +/* Truncate argument to nearest integral value not larger than the argument. + Copyright (C) 1997, 1998, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + 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" + + +double +__trunc (double x) +{ + int64_t i0, j0; + int64_t sx; + + EXTRACT_WORDS64 (i0, x); + sx = i0 & UINT64_C(0x8000000000000000); + j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; + if (j0 < 52) + { + if (j0 < 0) + /* The magnitude of the number is < 1 so the result is +-0. */ + INSERT_WORDS64 (x, sx); + else + INSERT_WORDS64 (x, sx | (i0 & ~(UINT64_C(0x000fffffffffffff) >> j0))); + } + else + { + if (j0 == 0x400) + /* x is inf or NaN. */ + return x + x; + } + + return x; +} +weak_alias (__trunc, trunc) +#ifdef NO_LONG_DOUBLE +strong_alias (__trunc, __truncl) +weak_alias (__trunc, truncl) +#endif diff --git a/sysdeps/unix/Makefile b/sysdeps/unix/Makefile index 2696e7fb62..f7140884a1 100644 --- a/sysdeps/unix/Makefile +++ b/sysdeps/unix/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1991,1992,1993,1994,1995,1996,1997,1998,1999,2003, 2006, 2008 +# Copyright (C) 1991,1992,1993,1994,1995,1996,1997,1998,1999,2003,2006,2008,2009 # Free Software Foundation, Inc. # This file is part of the GNU C Library. @@ -260,7 +260,6 @@ ifndef inhibit-unix-syscalls # which specifies objects to be compiled as simple Unix system calls. -include $(common-objpfx)sysd-syscalls -omit-deps += $(foreach t,$(sysd-rules-targets),$(unix-syscalls:%=$t)) ifeq (misc,$(subdir)) sysdep_routines += $(unix-extra-syscalls) @@ -306,9 +305,9 @@ endif endif # This is the end of the pipeline for compiling the syscall stubs. -# The stdin in assembler with cpp using sysdep.h macros. -# Be sure to disable debugging info since it would all just say "<stdin>". -compile-syscall = $(filter-out -g%,$(COMPILE.S)) -x assembler-with-cpp -o $@ - +# The stdin is assembler with cpp using sysdep.h macros. +compile-syscall = $(COMPILE.S) -o $@ -x assembler-with-cpp - \ + $(compile-mkdep-flags) ifndef avoid-generated $(common-objpfx)sysd-syscalls: $(..)sysdeps/unix/make-syscalls.sh \ @@ -323,16 +322,13 @@ $(common-objpfx)sysd-syscalls: $(..)sysdeps/unix/make-syscalls.sh \ mv -f $@T $@ endif -# The syscall objects depend on s-proto.d or s-proto-cancel.d, which -# are generated to specify dependencies generated syscalls have on -# headers. +# The $(bppfx)syscall.ob objects depend on s-proto-bp.d, which are +# generated to specify dependencies generated BP stubs have on headers. # These deps use file names relative to a subdir, so don't # include them in the parent directory. ifneq (,$(filter $(unix-syscalls),$(routines) $(sysdep_routines) $(aux))) ifndef no_deps --include $(common-objpfx)s-proto.d -include $(common-objpfx)s-proto-bp.d --include $(common-objpfx)s-proto-cancel.d endif endif @@ -340,7 +336,7 @@ $(common-objpfx)s-%.d: $(..)sysdeps/unix/s-%.S \ $(wildcard $(+sysdep_dirs:%=%/syscalls.list)) $(+make-deps) -common-generated += s-proto.d s-proto-bp.d s-proto-cancel.d +common-generated += s-proto-bp.d postclean-generated += sysd-syscalls endif diff --git a/sysdeps/unix/make-syscalls.sh b/sysdeps/unix/make-syscalls.sh index 8abb0349bf..a8b8a262a7 100644 --- a/sysdeps/unix/make-syscalls.sh +++ b/sysdeps/unix/make-syscalls.sh @@ -83,12 +83,13 @@ while read file srcfile caller syscall args strong weak; do ;; esac - cancellable= - noerrno= + cancellable=0 + noerrno=0 + errval=0 case $args in - C*) cancellable=-cancel; args=`echo $args | sed 's/C:\?//'`;; - E*) noerrno=_NOERRNO; args=`echo $args | sed 's/E:\?//'`;; - V*) noerrno=_ERRVAL; args=`echo $args | sed 's/V:\?//'`;; + C*) cancellable=1; args=`echo $args | sed 's/C:\?//'`;; + E*) noerrno=1; args=`echo $args | sed 's/E:\?//'`;; + V*) errval=1; args=`echo $args | sed 's/V:\?//'`;; esac # Derive the number of arguments from the argument signature @@ -115,7 +116,7 @@ while read file srcfile caller syscall args strong weak; do x--) # Undefined callnum for an extra syscall. if [ x$caller != x- ]; then - if [ x$noerrno != x ]; then + if [ $noerrno != 0 ]; then echo >&2 "$0: no number for $fileno, no-error syscall ($strong $weak)" exit 2 fi @@ -151,7 +152,7 @@ shared-only-routines += $file ;; esac - echo " \$(common-objpfx)s-proto$cancellable.d" + echo " \$(..)sysdeps/unix/make-syscalls.sh" case x"$callnum" in x_) echo "\ @@ -161,11 +162,17 @@ shared-only-routines += $file x*) echo "\ \$(make-target-directory) - (echo '#include <sysdep$cancellable.h>'; \\ - echo 'PSEUDO$noerrno ($strong, $syscall, $nargs)'; \\ - echo ' ret$noerrno'; \\ - echo 'PSEUDO_END$noerrno($strong)'; \\ - echo 'libc_hidden_def ($strong)'; \\" + (echo '#define SYSCALL_NAME $syscall'; \\ + echo '#define SYSCALL_NARGS $nargs'; \\ + echo '#define SYSCALL_SYMBOL $strong'; \\" + [ $cancellable = 0 ] || echo "\ + echo '#define SYSCALL_CANCELLABLE 1'; \\" + [ $noerrno = 0 ] || echo "\ + echo '#define SYSCALL_NOERRNO 1'; \\" + [ $errval = 0 ] || echo "\ + echo '#define SYSCALL_ERRVAL 1'; \\" + echo "\ + echo '#include <syscall-template.S>'; \\" ;; esac @@ -201,7 +208,7 @@ shared-only-routines += $file vcount=`expr $vcount + 1` echo " echo 'strong_alias ($strong, $source)'; \\" fi - echo " echo 'symbol_version($source, $base, $ver)'; \\" + echo " echo 'symbol_version ($source, $base, $ver)'; \\" ;; !*) name=`echo $name | sed 's/.//'` diff --git a/sysdeps/unix/syscall-template.S b/sysdeps/unix/syscall-template.S new file mode 100644 index 0000000000..66319f158b --- /dev/null +++ b/sysdeps/unix/syscall-template.S @@ -0,0 +1,88 @@ +/* Assembly code template for system call stubs. + Copyright (C) 2009 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. */ + +/* The real guts of this work are in the macros defined in the + machine- and kernel-specific sysdep.h header file. When we + are defining a cancellable system call, the sysdep-cancel.h + versions of those macros are what we really use. + + Each system call's object is built by a rule in sysd-syscalls + generated by make-syscalls.sh that #include's this file after + defining a few macros: + SYSCALL_NAME syscall name + SYSCALL_NARGS number of arguments this call takes + SYSCALL_SYMBOL primary symbol name + SYSCALL_CANCELLABLE 1 if the call is a cancelation point + SYSCALL_NOERRNO 1 to define a no-errno version (see below) + SYSCALL_ERRVAL 1 to define an error-value version (see below) + + We used to simply pipe the correct three lines below through cpp into + the assembler. The main reason to have this file instead is so that + stub objects can be assembled with -g and get source line information + that leads a user back to a source file and these fine comments. The + average user otherwise has a hard time knowing which "syscall-like" + functions in libc are plain stubs and which have nontrivial C wrappers. + Some versions of the "plain" stub generation macros are more than a few + instructions long and the untrained eye might not distinguish them from + some compiled code that inexplicably lacks source line information. */ + +#if SYSCALL_CANCELLABLE +# include <sysdep-cancel.h> +#else +# include <sysdep.h> +#endif + +#define T_PSEUDO(SYMBOL, NAME, N) PSEUDO (SYMBOL, NAME, N) +#define T_PSEUDO_NOERRNO(SYMBOL, NAME, N) PSEUDO_NOERRNO (SYMBOL, NAME, N) +#define T_PSEUDO_ERRVAL(SYMBOL, NAME, N) PSEUDO_ERRVAL (SYMBOL, NAME, N) +#define T_PSEUDO_END(SYMBOL) PSEUDO_END (SYMBOL) +#define T_PSEUDO_END_NOERRNO(SYMBOL) PSEUDO_END_NOERRNO (SYMBOL) +#define T_PSEUDO_END_ERRVAL(SYMBOL) PSEUDO_END_ERRVAL (SYMBOL) + +#if SYSCALL_NOERRNO + +/* This kind of system call stub never returns an error. + We return the return value register to the caller unexamined. */ + +T_PSEUDO_NOERRNO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) + ret_NOERRNO +T_PSEUDO_END_NOERRNO (SYSCALL_SYMBOL) + +#elif SYSCALL_ERRVAL + +/* This kind of system call stub returns the errno code as its return + value, or zero for success. We may massage the kernel's return value + to meet that ABI, but we never set errno here. */ + +T_PSEUDO_ERRVAL (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) + ret_ERRVAL +T_PSEUDO_END_ERRVAL (SYSCALL_SYMBOL) + +#else + +/* This is a "normal" system call stub: if there is an error, + it returns -1 and sets errno. */ + +T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS) + ret +T_PSEUDO_END (SYSCALL_SYMBOL) + +#endif + +libc_hidden_def (SYSCALL_SYMBOL) diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S index f9c60ad5cf..5564a11af2 100644 --- a/sysdeps/x86_64/dl-trampoline.S +++ b/sysdeps/x86_64/dl-trampoline.S @@ -197,7 +197,6 @@ _dl_x86_64_save_sse: ret L(no_avx5): # endif -# define YMM_SIZE 16 movdqa %xmm0, %fs:RTLD_SAVESPACE_SSE+0*XMM_SIZE movdqa %xmm1, %fs:RTLD_SAVESPACE_SSE+1*XMM_SIZE movdqa %xmm2, %fs:RTLD_SAVESPACE_SSE+2*XMM_SIZE diff --git a/sysdeps/x86_64/fpu/bits/mathinline.h b/sysdeps/x86_64/fpu/bits/mathinline.h index e8a919fe92..8d4850dfc0 100644 --- a/sysdeps/x86_64/fpu/bits/mathinline.h +++ b/sysdeps/x86_64/fpu/bits/mathinline.h @@ -1,5 +1,5 @@ /* Inline math functions for x86-64. - Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2007, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>, 2002. @@ -35,14 +35,16 @@ __MATH_INLINE int __NTH (__signbitf (float __x)) { - __extension__ union { float __f; int __i; } __u = { __f: __x }; - return __u.__i < 0; + int __m; + asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); + return __m & 0x8; } __MATH_INLINE int __NTH (__signbit (double __x)) { - __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; - return __u.__i[1] < 0; + int __m; + asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); + return __m & 0x80; } __MATH_INLINE int __NTH (__signbitl (long double __x)) diff --git a/sysdeps/x86_64/fpu/math_private.h b/sysdeps/x86_64/fpu/math_private.h index 4febcbb5ec..4be753654a 100644 --- a/sysdeps/x86_64/fpu/math_private.h +++ b/sysdeps/x86_64/fpu/math_private.h @@ -18,4 +18,41 @@ do \ while (0) #include <math/math_private.h> + +/* We can do a few things better on x86-64. */ + +/* Direct movement of float into integer register. */ +#undef EXTRACT_WORDS64 +#define EXTRACT_WORDS64(i,d) \ +do { \ + long int i_; \ + asm ("movd %1, %0" : "=rm" (i_) : "x" (d)); \ + (i) = i_; \ +} while (0) + +/* And the reverse. */ +#undef INSERT_WORDS64 +#define INSERT_WORDS64(d,i) \ +do { \ + long int i_ = i; \ + asm ("movd %1, %0" : "=x" (d) : "rm" (i_)); \ +} while (0) + +/* Direct movement of float into integer register. */ +#undef GET_FLOAT_WORD +#define GET_FLOAT_WORD(i,d) \ +do { \ + int i_; \ + asm ("movd %1, %0" : "=rm" (i_) : "x" (d)); \ + (i) = i_; \ +} while (0) + +/* And the reverse. */ +#undef SET_FLOAT_WORD +#define SET_FLOAT_WORD(d,i) \ +do { \ + int i_ = i; \ + asm ("movd %1, %0" : "=x" (d) : "rm" (i_)); \ +} while (0) + #endif diff --git a/sysdeps/x86_64/fpu/s_scalbln.c b/sysdeps/x86_64/fpu/s_scalbln.c new file mode 100644 index 0000000000..1009713fbc --- /dev/null +++ b/sysdeps/x86_64/fpu/s_scalbln.c @@ -0,0 +1,2 @@ +/* Nothing to do. This function is the same as scalbn. So we define an + alias. */ diff --git a/sysdeps/x86_64/fpu/s_scalbn.c b/sysdeps/x86_64/fpu/s_scalbn.c new file mode 100644 index 0000000000..74d34655ad --- /dev/null +++ b/sysdeps/x86_64/fpu/s_scalbn.c @@ -0,0 +1,9 @@ +#define scalbln __renamed_scalbln +#define __scalbln __renamed___scalbln + +#include <sysdeps/ieee754/dbl-64/wordsize-64/s_scalbn.c> + +#undef scalbln +#undef __scalbln +strong_alias (__scalbn, __scalbln) +weak_alias (__scalbn, scalbln) diff --git a/sysdeps/x86_64/fpu/s_signbit.S b/sysdeps/x86_64/fpu/s_signbit.S new file mode 100644 index 0000000000..0bfd62e30d --- /dev/null +++ b/sysdeps/x86_64/fpu/s_signbit.S @@ -0,0 +1,27 @@ +/* Return nonzero value if number is negative. + Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redha.com>, 2009. + + 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 <sysdep.h> + +ENTRY(__signbit) + pmovmskb %xmm0, %eax + andl $0x80, %eax + ret +END(__signbit) diff --git a/sysdeps/x86_64/fpu/s_signbitf.S b/sysdeps/x86_64/fpu/s_signbitf.S new file mode 100644 index 0000000000..f0681d0124 --- /dev/null +++ b/sysdeps/x86_64/fpu/s_signbitf.S @@ -0,0 +1,27 @@ +/* Return nonzero value if number is negative. + Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redha.com>, 2009. + + 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 <sysdep.h> + +ENTRY(__signbitf) + pmovmskb %xmm0, %eax + andl $0x8, %eax + ret +END(__signbitf) |