diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2012-06-15 13:56:26 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2012-06-15 13:56:26 -0700 |
commit | 25f1282ae5072ccf586f041356ddde02f069c4ff (patch) | |
tree | 53f39d78147d790ad171d3f3eae438f915a47519 /sysdeps/i386 | |
parent | ed1825f858842b102f735b129ca1e569e2247809 (diff) | |
download | glibc-25f1282ae5072ccf586f041356ddde02f069c4ff.tar glibc-25f1282ae5072ccf586f041356ddde02f069c4ff.tar.gz glibc-25f1282ae5072ccf586f041356ddde02f069c4ff.tar.bz2 glibc-25f1282ae5072ccf586f041356ddde02f069c4ff.zip |
Use i386 bits/mathinline.h for i386 and x86_64
Diffstat (limited to 'sysdeps/i386')
-rw-r--r-- | sysdeps/i386/fpu/bits/mathinline.h | 968 |
1 files changed, 0 insertions, 968 deletions
diff --git a/sysdeps/i386/fpu/bits/mathinline.h b/sysdeps/i386/fpu/bits/mathinline.h deleted file mode 100644 index 6446b1d875..0000000000 --- a/sysdeps/i386/fpu/bits/mathinline.h +++ /dev/null @@ -1,968 +0,0 @@ -/* Inline math functions for i387 and SSE. - Copyright (C) 1995-2012 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, see - <http://www.gnu.org/licenses/>. */ - -#ifndef _MATH_H -# error "Never use <bits/mathinline.h> directly; include <math.h> instead." -#endif - -#ifndef __extern_always_inline -# define __MATH_INLINE __inline -#else -# define __MATH_INLINE __extern_always_inline -#endif - - -#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2 -/* GCC 2.97 and up have builtins that actually can be used. */ -# if !__GNUC_PREREQ (2,97) -/* ISO C99 defines some macros to perform unordered comparisons. The - ix87 FPU supports this with special opcodes and we should use them. - These must not be inline functions since we have to be able to handle - all floating-point types. */ -# undef isgreater -# undef isgreaterequal -# undef isless -# undef islessequal -# undef islessgreater -# undef isunordered -# ifdef __i686__ -/* For the PentiumPro and more recent processors we can provide - better code. */ -# define isgreater(x, y) \ - ({ register char __result; \ - __asm__ ("fucomip %%st(1), %%st; seta %%al" \ - : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ - __result; }) -# define isgreaterequal(x, y) \ - ({ register char __result; \ - __asm__ ("fucomip %%st(1), %%st; setae %%al" \ - : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ - __result; }) - -# define isless(x, y) \ - ({ register char __result; \ - __asm__ ("fucomip %%st(1), %%st; seta %%al" \ - : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \ - __result; }) - -# define islessequal(x, y) \ - ({ register char __result; \ - __asm__ ("fucomip %%st(1), %%st; setae %%al" \ - : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \ - __result; }) - -# define islessgreater(x, y) \ - ({ register char __result; \ - __asm__ ("fucomip %%st(1), %%st; setne %%al" \ - : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ - __result; }) - -# define isunordered(x, y) \ - ({ register char __result; \ - __asm__ ("fucomip %%st(1), %%st; setp %%al" \ - : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ - __result; }) -# else -/* This is the dumb, portable code for i386 and above. */ -# define isgreater(x, y) \ - ({ register char __result; \ - __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ - : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ - __result; }) - -# define isgreaterequal(x, y) \ - ({ register char __result; \ - __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \ - : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ - __result; }) - -# define isless(x, y) \ - ({ register char __result; \ - __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ - : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ - __result; }) - -# define islessequal(x, y) \ - ({ register char __result; \ - __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \ - : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ - __result; }) - -# define islessgreater(x, y) \ - ({ register char __result; \ - __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al" \ - : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ - __result; }) - -# define isunordered(x, y) \ - ({ register char __result; \ - __asm__ ("fucompp; fnstsw; sahf; setp %%al" \ - : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ - __result; }) -# endif /* __i686__ */ -# endif /* GCC 2.97 */ - -/* The gcc, version 2.7 or below, has problems with all this inlining - code. So disable it for this version of the compiler. */ -# if __GNUC_PREREQ (2, 8) -__BEGIN_NAMESPACE_C99 - -/* Test for negative number. Used in the signbit() macro. */ -__MATH_INLINE int -__NTH (__signbitf (float __x)) -{ -# ifdef __SSE2_MATH__ - int __m; - __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); - return (__m & 0x8) != 0; -# else - __extension__ union { float __f; int __i; } __u = { __f: __x }; - return __u.__i < 0; -# endif -} -__MATH_INLINE int -__NTH (__signbit (double __x)) -{ -# ifdef __SSE2_MATH__ - int __m; - __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); - return (__m & 0x80) != 0; -# else - __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; - return __u.__i[1] < 0; -# endif -} -__MATH_INLINE int -__NTH (__signbitl (long double __x)) -{ - __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; - return (__u.__i[2] & 0x8000) != 0; -} - -__END_NAMESPACE_C99 -# endif -#endif - - -/* The gcc, version 2.7 or below, has problems with all this inlining - code. So disable it for this version of the compiler. */ -#if __GNUC_PREREQ (2, 8) -# if !__GNUC_PREREQ (3, 4) && !defined __NO_MATH_INLINES \ - && defined __OPTIMIZE__ -/* GCC 3.4 introduced builtins for all functions below, so - there's no need to define any of these inline functions. */ - -# ifdef __USE_ISOC99 -__BEGIN_NAMESPACE_C99 - -/* Round to nearest integer. */ -# ifdef __SSE_MATH__ -__MATH_INLINE long int -__NTH (lrintf (float __x)) -{ - long int __res; - /* Mark as volatile since the result is dependent on the state of - the SSE control register (the rounding mode). Otherwise GCC might - remove these assembler instructions since it does not know about - the rounding mode change and cannot currently be told. */ - __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x)); - return __res; -} -# endif -# ifdef __SSE2_MATH__ -__MATH_INLINE long int -__NTH (lrint (double __x)) -{ - long int __res; - /* Mark as volatile since the result is dependent on the state of - the SSE control register (the rounding mode). Otherwise GCC might - remove these assembler instructions since it does not know about - the rounding mode change and cannot currently be told. */ - __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x)); - return __res; -} -# endif -# ifdef __x86_64__ -__MATH_INLINE long long int -__NTH (llrintf (float __x)) -{ - long long int __res; - /* Mark as volatile since the result is dependent on the state of - the SSE control register (the rounding mode). Otherwise GCC might - remove these assembler instructions since it does not know about - the rounding mode change and cannot currently be told. */ - __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x)); - return __res; -} -__MATH_INLINE long long int -__NTH (llrint (double __x)) -{ - long long int __res; - /* Mark as volatile since the result is dependent on the state of - the SSE control register (the rounding mode). Otherwise GCC might - remove these assembler instructions since it does not know about - the rounding mode change and cannot currently be told. */ - __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x)); - return __res; -} -# endif - -# if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \ - && defined __SSE2_MATH__ -/* Determine maximum of two values. */ -__MATH_INLINE float -__NTH (fmaxf (float __x, float __y)) -{ -# ifdef __AVX__ - float __res; - __asm ("vmaxss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); - return __res; -# else - __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y)); - return __x; -# endif -} -__MATH_INLINE double -__NTH (fmax (double __x, double __y)) -{ -# ifdef __AVX__ - float __res; - __asm ("vmaxsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); - return __res; -# else - __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y)); - return __x; -# endif -} - -/* Determine minimum of two values. */ -__MATH_INLINE float -__NTH (fminf (float __x, float __y)) -{ -# ifdef __AVX__ - float __res; - __asm ("vminss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); - return __res; -# else - __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y)); - return __x; -# endif -} -__MATH_INLINE double -__NTH (fmin (double __x, double __y)) -{ -# ifdef __AVX__ - float __res; - __asm ("vminsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); - return __res; -# else - __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y)); - return __x; -# endif -} -# endif - -__END_NAMESPACE_C99 -# endif - -# if defined __SSE4_1__ && defined __SSE2_MATH__ -# if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 -__BEGIN_NAMESPACE_C99 - -/* Round to nearest integer. */ -__MATH_INLINE double -__NTH (rint (double __x)) -{ - double __res; - /* Mark as volatile since the result is dependent on the state of - the SSE control register (the rounding mode). Otherwise GCC might - remove these assembler instructions since it does not know about - the rounding mode change and cannot currently be told. */ - __asm __volatile__ ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x)); - return __res; -} -__MATH_INLINE float -__NTH (rintf (float __x)) -{ - float __res; - /* Mark as volatile since the result is dependent on the state of - the SSE control register (the rounding mode). Otherwise GCC might - remove these assembler instructions since it does not know about - the rounding mode change and cannot currently be told. */ - __asm __volatile__ ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x)); - return __res; -} - -# ifdef __USE_ISOC99 -/* Round to nearest integer without raising inexact exception. */ -__MATH_INLINE double -__NTH (nearbyint (double __x)) -{ - double __res; - /* Mark as volatile since the result is dependent on the state of - the SSE control register (the rounding mode). Otherwise GCC might - remove these assembler instructions since it does not know about - the rounding mode change and cannot currently be told. */ - __asm __volatile__ ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x)); - return __res; -} -__MATH_INLINE float -__NTH (nearbyintf (float __x)) -{ - float __res; - /* Mark as volatile since the result is dependent on the state of - the SSE control register (the rounding mode). Otherwise GCC might - remove these assembler instructions since it does not know about - the rounding mode change and cannot currently be told. */ - __asm __volatile__ ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x)); - return __res; -} -# endif - -__END_NAMESPACE_C99 -# endif - -__BEGIN_NAMESPACE_STD -/* Smallest integral value not less than X. */ -__MATH_INLINE double -__NTH (ceil (double __x)) -{ - double __res; - __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x)); - return __res; -} -__END_NAMESPACE_STD - -__BEGIN_NAMESPACE_C99 -__MATH_INLINE float -__NTH (ceilf (float __x)) -{ - float __res; - __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x)); - return __res; -} -__END_NAMESPACE_C99 - -__BEGIN_NAMESPACE_STD -/* Largest integer not greater than X. */ -__MATH_INLINE double -__NTH (floor (double __x)) -{ - double __res; - __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x)); - return __res; -} -__END_NAMESPACE_STD - -__BEGIN_NAMESPACE_C99 -__MATH_INLINE float -__NTH (floorf (float __x)) -{ - float __res; - __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x)); - return __res; -} -__END_NAMESPACE_C99 -# endif -# endif -#endif - -#ifndef __x86_64__ -# 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, - respectively). OP is the name of the FPU operation. - We define two sets of macros. The set with the additional NP - doesn't add a prototype declaration. */ - -# if defined __USE_MISC || defined __USE_ISOC99 -# define __inline_mathop(func, op) \ - __inline_mathop_ (double, func, op) \ - __inline_mathop_ (float, __CONCAT(func,f), op) \ - __inline_mathop_ (long double, __CONCAT(func,l), op) -# define __inline_mathopNP(func, op) \ - __inline_mathopNP_ (double, func, op) \ - __inline_mathopNP_ (float, __CONCAT(func,f), op) \ - __inline_mathopNP_ (long double, __CONCAT(func,l), op) -# else -# define __inline_mathop(func, op) \ - __inline_mathop_ (double, func, op) -# define __inline_mathopNP(func, op) \ - __inline_mathopNP_ (double, func, op) -# endif - -# define __inline_mathop_(float_type, func, op) \ - __inline_mathop_decl_ (float_type, func, op, "0" (__x)) -# define __inline_mathopNP_(float_type, func, op) \ - __inline_mathop_declNP_ (float_type, func, op, "0" (__x)) - - -# if defined __USE_MISC || defined __USE_ISOC99 -# define __inline_mathop_decl(func, op, params...) \ - __inline_mathop_decl_ (double, func, op, params) \ - __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \ - __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params) -# define __inline_mathop_declNP(func, op, params...) \ - __inline_mathop_declNP_ (double, func, op, params) \ - __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \ - __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params) -# else -# define __inline_mathop_decl(func, op, params...) \ - __inline_mathop_decl_ (double, func, op, params) -# define __inline_mathop_declNP(func, op, params...) \ - __inline_mathop_declNP_ (double, func, op, params) -# endif - -# define __inline_mathop_decl_(float_type, func, op, params...) \ - __MATH_INLINE float_type func (float_type) __THROW; \ - __inline_mathop_declNP_ (float_type, func, op, params) - -# define __inline_mathop_declNP_(float_type, func, op, params...) \ - __MATH_INLINE float_type __NTH (func (float_type __x)) \ - { \ - register float_type __result; \ - __asm __volatile__ (op : "=t" (__result) : params); \ - return __result; \ - } - - -# if defined __USE_MISC || defined __USE_ISOC99 -# define __inline_mathcode(func, arg, code) \ - __inline_mathcode_ (double, func, arg, code) \ - __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \ - __inline_mathcode_ (long double, __CONCAT(func,l), arg, code) -# define __inline_mathcodeNP(func, arg, code) \ - __inline_mathcodeNP_ (double, func, arg, code) \ - __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \ - __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code) -# define __inline_mathcode2(func, arg1, arg2, code) \ - __inline_mathcode2_ (double, func, arg1, arg2, code) \ - __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \ - __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code) -# define __inline_mathcodeNP2(func, arg1, arg2, code) \ - __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \ - __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \ - __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code) -# define __inline_mathcode3(func, arg1, arg2, arg3, code) \ - __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \ - __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ - __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) -# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ - __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \ - __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ - __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) -# else -# define __inline_mathcode(func, arg, code) \ - __inline_mathcode_ (double, func, (arg), code) -# define __inline_mathcodeNP(func, arg, code) \ - __inline_mathcodeNP_ (double, func, (arg), code) -# define __inline_mathcode2(func, arg1, arg2, code) \ - __inline_mathcode2_ (double, func, arg1, arg2, code) -# define __inline_mathcodeNP2(func, arg1, arg2, code) \ - __inline_mathcodeNP2_ (double, func, arg1, arg2, code) -# define __inline_mathcode3(func, arg1, arg2, arg3, code) \ - __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) -# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ - __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) -# endif - -# define __inline_mathcode_(float_type, func, arg, code) \ - __MATH_INLINE float_type func (float_type) __THROW; \ - __inline_mathcodeNP_(float_type, func, arg, code) - -# define __inline_mathcodeNP_(float_type, func, arg, code) \ - __MATH_INLINE float_type __NTH (func (float_type arg)) \ - { \ - code; \ - } - - -# define __inline_mathcode2_(float_type, func, arg1, arg2, code) \ - __MATH_INLINE float_type func (float_type, float_type) __THROW; \ - __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code) - -# define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \ - __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \ - { \ - code; \ - } - -# define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \ - __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \ - __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) - -# define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \ - __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \ - float_type arg3)) \ - { \ - code; \ - } -# endif - - -# if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ -/* Miscellaneous functions */ - -/* __FAST_MATH__ is defined by gcc -ffast-math. */ -# ifdef __FAST_MATH__ -# ifdef __USE_GNU -# define __sincos_code \ - register long double __cosr; \ - register long double __sinr; \ - register unsigned int __swtmp; \ - __asm __volatile__ \ - ("fsincos\n\t" \ - "fnstsw %w2\n\t" \ - "testl $0x400, %2\n\t" \ - "jz 1f\n\t" \ - "fldpi\n\t" \ - "fadd %%st(0)\n\t" \ - "fxch %%st(1)\n\t" \ - "2: fprem1\n\t" \ - "fnstsw %w2\n\t" \ - "testl $0x400, %2\n\t" \ - "jnz 2b\n\t" \ - "fstp %%st(1)\n\t" \ - "fsincos\n\t" \ - "1:" \ - : "=t" (__cosr), "=u" (__sinr), "=a" (__swtmp) : "0" (__x)); \ - *__sinx = __sinr; \ - *__cosx = __cosr - -__MATH_INLINE void -__NTH (__sincos (double __x, double *__sinx, double *__cosx)) -{ - __sincos_code; -} - -__MATH_INLINE void -__NTH (__sincosf (float __x, float *__sinx, float *__cosx)) -{ - __sincos_code; -} - -__MATH_INLINE void -__NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx)) -{ - __sincos_code; -} -# endif - - -/* Optimized inline implementation, sometimes with reduced precision - and/or argument range. */ - -# if __GNUC_PREREQ (3, 5) -# define __expm1_code \ - register long double __temp; \ - __temp = __builtin_expm1l (__x); \ - return __temp ? __temp : __x -# else -# define __expm1_code \ - register long double __value; \ - register long double __exponent; \ - register long double __temp; \ - __asm __volatile__ \ - ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \ - "fmul %%st(1) # x * log2(e)\n\t" \ - "fst %%st(1)\n\t" \ - "frndint # int(x * log2(e))\n\t" \ - "fxch\n\t" \ - "fsub %%st(1) # fract(x * log2(e))\n\t" \ - "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ - "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \ - : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ - __asm __volatile__ \ - ("fscale # 2^int(x * log2(e))\n\t" \ - : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \ - __temp -= 1.0; \ - __temp += __value; \ - return __temp ? __temp : __x -# endif -__inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code) - -# if __GNUC_PREREQ (3, 4) -__inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x)) -# else -# define __exp_code \ - register long double __value; \ - register long double __exponent; \ - __asm __volatile__ \ - ("fldl2e # e^x = 2^(x * log2(e))\n\t" \ - "fmul %%st(1) # x * log2(e)\n\t" \ - "fst %%st(1)\n\t" \ - "frndint # int(x * log2(e))\n\t" \ - "fxch\n\t" \ - "fsub %%st(1) # fract(x * log2(e))\n\t" \ - "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ - : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ - __value += 1.0; \ - __asm __volatile__ \ - ("fscale" \ - : "=t" (__value) : "0" (__value), "u" (__exponent)); \ - return __value -__inline_mathcodeNP (exp, __x, __exp_code) -__inline_mathcodeNP_ (long double, __expl, __x, __exp_code) -# endif - - -# if !__GNUC_PREREQ (3, 5) -__inline_mathcodeNP (tan, __x, \ - register long double __value; \ - register long double __value2 __attribute__ ((__unused__)); \ - __asm __volatile__ \ - ("fptan" \ - : "=t" (__value2), "=u" (__value) : "0" (__x)); \ - return __value) -# endif -# endif /* __FAST_MATH__ */ - - -# if __GNUC_PREREQ (3, 4) -__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, - return __builtin_atan2l (__y, __x)) -# else -# define __atan2_code \ - register long double __value; \ - __asm __volatile__ \ - ("fpatan" \ - : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \ - return __value -# ifdef __FAST_MATH__ -__inline_mathcodeNP2 (atan2, __y, __x, __atan2_code) -# endif -__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code) -# endif - - -# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) -__inline_mathcodeNP2 (fmod, __x, __y, \ - register long double __value; \ - __asm __volatile__ \ - ("1: fprem\n\t" \ - "fnstsw %%ax\n\t" \ - "sahf\n\t" \ - "jp 1b" \ - : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \ - return __value) -# endif - - -# ifdef __FAST_MATH__ -# if !__GNUC_PREREQ (3,3) -__inline_mathopNP (sqrt, "fsqrt") -__inline_mathopNP_ (long double, __sqrtl, "fsqrt") -# define __libc_sqrtl(n) __sqrtl (n) -# else -# define __libc_sqrtl(n) __builtin_sqrtl (n) -# endif -# endif - -# if __GNUC_PREREQ (2, 8) -__inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x)) -# if defined __USE_MISC || defined __USE_ISOC99 -__inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x)) -__inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x)) -# endif -__inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x)) -# else -__inline_mathop (fabs, "fabs") -__inline_mathop_ (long double, __fabsl, "fabs") -# endif - -# ifdef __FAST_MATH__ -# if !__GNUC_PREREQ (3, 4) -/* The argument range of this inline version is reduced. */ -__inline_mathopNP (sin, "fsin") -/* The argument range of this inline version is reduced. */ -__inline_mathopNP (cos, "fcos") - -__inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)") -# endif - -# if !__GNUC_PREREQ (3, 5) -__inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)") - -__inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x))) -__inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x)) -# endif - -# if !__GNUC_PREREQ (3, 4) -__inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)") -# endif -# endif /* __FAST_MATH__ */ - -__inline_mathcode_ (long double, __sgn1l, __x, \ - __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \ - { __xld: __x }; \ - __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \ - __n.__xi[1] = 0x80000000; \ - __n.__xi[0] = 0; \ - return __n.__xld) - - -# ifdef __FAST_MATH__ -/* The argument range of the inline version of sinhl is slightly reduced. */ -__inline_mathcodeNP (sinh, __x, \ - register long double __exm1 = __expm1l (__fabsl (__x)); \ - return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x)) - -__inline_mathcodeNP (cosh, __x, \ - register long double __ex = __expl (__x); \ - return 0.5 * (__ex + 1.0 / __ex)) - -__inline_mathcodeNP (tanh, __x, \ - register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \ - return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x)) -# endif - -__inline_mathcodeNP (floor, __x, \ - register long double __value; \ - register int __ignore; \ - unsigned short int __cw; \ - unsigned short int __cwtmp; \ - __asm __volatile ("fnstcw %3\n\t" \ - "movzwl %3, %1\n\t" \ - "andl $0xf3ff, %1\n\t" \ - "orl $0x0400, %1\n\t" /* rounding down */ \ - "movw %w1, %2\n\t" \ - "fldcw %2\n\t" \ - "frndint\n\t" \ - "fldcw %3" \ - : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ - "=m" (__cw) \ - : "0" (__x)); \ - return __value) - -__inline_mathcodeNP (ceil, __x, \ - register long double __value; \ - register int __ignore; \ - unsigned short int __cw; \ - unsigned short int __cwtmp; \ - __asm __volatile ("fnstcw %3\n\t" \ - "movzwl %3, %1\n\t" \ - "andl $0xf3ff, %1\n\t" \ - "orl $0x0800, %1\n\t" /* rounding up */ \ - "movw %w1, %2\n\t" \ - "fldcw %2\n\t" \ - "frndint\n\t" \ - "fldcw %3" \ - : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ - "=m" (__cw) \ - : "0" (__x)); \ - return __value) - -# ifdef __FAST_MATH__ -# define __ldexp_code \ - register long double __value; \ - __asm __volatile__ \ - ("fscale" \ - : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \ - return __value - -__MATH_INLINE double -__NTH (ldexp (double __x, int __y)) -{ - __ldexp_code; -} -# endif - - -/* Optimized versions for some non-standardized functions. */ -# if defined __USE_ISOC99 || defined __USE_MISC - -# ifdef __FAST_MATH__ -__inline_mathcodeNP (expm1, __x, __expm1_code) - -/* We cannot rely on M_SQRT being defined. So we do it for ourself - here. */ -# define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */ - -# if !__GNUC_PREREQ (3, 5) -__inline_mathcodeNP (log1p, __x, \ - register long double __value; \ - if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \ - __value = logl (1.0 + __x); \ - else \ - __asm __volatile__ \ - ("fldln2\n\t" \ - "fxch\n\t" \ - "fyl2xp1" \ - : "=t" (__value) : "0" (__x) : "st(1)"); \ - return __value) -# endif - - -/* The argument range of the inline version of asinhl is slightly reduced. */ -__inline_mathcodeNP (asinh, __x, \ - register long double __y = __fabsl (__x); \ - return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \ - * __sgn1l (__x))) - -__inline_mathcodeNP (acosh, __x, \ - return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0))) - -__inline_mathcodeNP (atanh, __x, \ - register long double __y = __fabsl (__x); \ - return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x)) - -/* The argument range of the inline version of hypotl is slightly reduced. */ -__inline_mathcodeNP2 (hypot, __x, __y, - return __libc_sqrtl (__x * __x + __y * __y)) - -# if !__GNUC_PREREQ (3, 5) -__inline_mathcodeNP(logb, __x, \ - register long double __value; \ - register long double __junk; \ - __asm __volatile__ \ - ("fxtract\n\t" \ - : "=t" (__junk), "=u" (__value) : "0" (__x)); \ - return __value) -# endif - -# endif -# endif - -# ifdef __USE_ISOC99 -# ifdef __FAST_MATH__ - -# if !__GNUC_PREREQ (3, 5) -__inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)") -# endif - -__MATH_INLINE float -__NTH (ldexpf (float __x, int __y)) -{ - __ldexp_code; -} - -__MATH_INLINE long double -__NTH (ldexpl (long double __x, int __y)) -{ - __ldexp_code; -} - -__inline_mathopNP (rint, "frndint") -# endif /* __FAST_MATH__ */ - -# define __lrint_code \ - long int __lrintres; \ - __asm__ __volatile__ \ - ("fistpl %0" \ - : "=m" (__lrintres) : "t" (__x) : "st"); \ - return __lrintres -__MATH_INLINE long int -__NTH (lrintf (float __x)) -{ - __lrint_code; -} -__MATH_INLINE long int -__NTH (lrint (double __x)) -{ - __lrint_code; -} -__MATH_INLINE long int -__NTH (lrintl (long double __x)) -{ - __lrint_code; -} -# undef __lrint_code - -# define __llrint_code \ - long long int __llrintres; \ - __asm__ __volatile__ \ - ("fistpll %0" \ - : "=m" (__llrintres) : "t" (__x) : "st"); \ - return __llrintres -__MATH_INLINE long long int -__NTH (llrintf (float __x)) -{ - __llrint_code; -} -__MATH_INLINE long long int -__NTH (llrint (double __x)) -{ - __llrint_code; -} -__MATH_INLINE long long int -__NTH (llrintl (long double __x)) -{ - __llrint_code; -} -# undef __llrint_code - -# endif - - -# ifdef __USE_MISC - -# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) -__inline_mathcodeNP2 (drem, __x, __y, \ - register double __value; \ - register int __clobbered; \ - __asm __volatile__ \ - ("1: fprem1\n\t" \ - "fstsw %%ax\n\t" \ - "sahf\n\t" \ - "jp 1b" \ - : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \ - return __value) -# endif - - -/* This function is used in the `isfinite' macro. */ -__MATH_INLINE int -__NTH (__finite (double __x)) -{ - return (__extension__ - (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1] - | 0x800fffffu) + 1) >> 31)); -} - -# endif /* __USE_MISC */ - -/* Undefine some of the large macros which are not used anymore. */ -# undef __atan2_code -# ifdef __FAST_MATH__ -# undef __expm1_code -# undef __exp_code -# undef __sincos_code -# endif /* __FAST_MATH__ */ - -# endif /* __NO_MATH_INLINES */ - - -/* This code is used internally in the GNU libc. */ -# ifdef __LIBC_INTERNAL_MATH_INLINES -__inline_mathop (__ieee754_sqrt, "fsqrt") -__inline_mathcode2 (__ieee754_atan2, __y, __x, - register long double __value; - __asm __volatile__ ("fpatan\n\t" - : "=t" (__value) - : "0" (__x), "u" (__y) : "st(1)"); - return __value;) -# endif - -#endif /* !__x86_64__ */ |