Don't define via builtins.
[kopensolaris-gnu/glibc.git] / sysdeps / i386 / fpu / bits / mathinline.h
1 /* Inline math functions for i387.
2    Copyright (C) 1995,96,97,98,99,2000,2001,2003 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by John C. Bowman <bowman@math.ualberta.ca>, 1995.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #ifndef _MATH_H
22 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
23 #endif
24
25 #ifdef __cplusplus
26 # define __MATH_INLINE __inline
27 #else
28 # define __MATH_INLINE extern __inline
29 #endif
30
31
32 #if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2
33 /* GCC 2.97 and up have builtins that actually can be used.  */
34 # if !__GNUC_PREREQ (2,97)
35 /* ISO C99 defines some macros to perform unordered comparisons.  The
36    ix87 FPU supports this with special opcodes and we should use them.
37    These must not be inline functions since we have to be able to handle
38    all floating-point types.  */
39 #  undef isgreater
40 #  undef isgreaterequal
41 #  undef isless
42 #  undef islessequal
43 #  undef islessgreater
44 #  undef isunordered
45 #  ifdef __i686__
46 /* For the PentiumPro and more recent processors we can provide
47    better code.  */
48 #   define isgreater(x, y) \
49      ({ register char __result;                                               \
50         __asm__ ("fucomip %%st(1), %%st; seta %%al"                           \
51                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
52         __result; })
53 #   define isgreaterequal(x, y) \
54      ({ register char __result;                                               \
55         __asm__ ("fucomip %%st(1), %%st; setae %%al"                          \
56                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
57         __result; })
58
59 #   define isless(x, y) \
60      ({ register char __result;                                               \
61         __asm__ ("fucomip %%st(1), %%st; seta %%al"                           \
62                  : "=a" (__result) : "u" (x), "t" (y) : "cc", "st");          \
63         __result; })
64
65 #   define islessequal(x, y) \
66      ({ register char __result;                                               \
67         __asm__ ("fucomip %%st(1), %%st; setae %%al"                          \
68                  : "=a" (__result) : "u" (x), "t" (y) : "cc", "st");          \
69         __result; })
70
71 #   define islessgreater(x, y) \
72      ({ register char __result;                                               \
73         __asm__ ("fucomip %%st(1), %%st; setne %%al"                          \
74                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
75         __result; })
76
77 #   define isunordered(x, y) \
78      ({ register char __result;                                               \
79         __asm__ ("fucomip %%st(1), %%st; setp %%al"                           \
80                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");          \
81         __result; })
82 #  else
83 /* This is the dumb, portable code for i386 and above.  */
84 #   define isgreater(x, y) \
85      ({ register char __result;                                               \
86         __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al"              \
87                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
88         __result; })
89
90 #   define isgreaterequal(x, y) \
91      ({ register char __result;                                               \
92         __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al"              \
93                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
94         __result; })
95
96 #   define isless(x, y) \
97      ({ register char __result;                                               \
98         __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al"              \
99                  : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
100         __result; })
101
102 #   define islessequal(x, y) \
103      ({ register char __result;                                               \
104         __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al"              \
105                  : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
106         __result; })
107
108 #   define islessgreater(x, y) \
109      ({ register char __result;                                               \
110         __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al"              \
111                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
112         __result; })
113
114 #   define isunordered(x, y) \
115      ({ register char __result;                                               \
116         __asm__ ("fucompp; fnstsw; sahf; setp %%al"                           \
117                  : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
118         __result; })
119 #  endif /* __i686__ */
120 # endif /* GCC 2.97 */
121
122 /* The gcc, version 2.7 or below, has problems with all this inlining
123    code.  So disable it for this version of the compiler.  */
124 # if __GNUC_PREREQ (2, 8)
125 /* Test for negative number.  Used in the signbit() macro.  */
126 __MATH_INLINE int
127 __signbitf (float __x) __THROW
128 {
129   __extension__ union { float __f; int __i; } __u = { __f: __x };
130   return __u.__i < 0;
131 }
132 __MATH_INLINE int
133 __signbit (double __x) __THROW
134 {
135   __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
136   return __u.__i[1] < 0;
137 }
138 __MATH_INLINE int
139 __signbitl (long double __x) __THROW
140 {
141   __extension__ union { long double __l; int __i[3]; } __u = { __l: __x };
142   return (__u.__i[2] & 0x8000) != 0;
143 }
144 # endif
145 #endif
146
147
148 /* The gcc, version 2.7 or below, has problems with all this inlining
149    code.  So disable it for this version of the compiler.  */
150 #if __GNUC_PREREQ (2, 8)
151
152 #if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
153      && defined __OPTIMIZE__)
154
155 /* A macro to define float, double, and long double versions of various
156    math functions for the ix87 FPU.  FUNC is the function name (which will
157    be suffixed with f and l for the float and long double version,
158    respectively).  OP is the name of the FPU operation.
159    We define two sets of macros.  The set with the additional NP
160    doesn't add a prototype declaration.  */
161
162 #if defined __USE_MISC || defined __USE_ISOC99
163 # define __inline_mathop(func, op) \
164   __inline_mathop_ (double, func, op)                                         \
165   __inline_mathop_ (float, __CONCAT(func,f), op)                              \
166   __inline_mathop_ (long double, __CONCAT(func,l), op)
167 # define __inline_mathopNP(func, op) \
168   __inline_mathopNP_ (double, func, op)                                       \
169   __inline_mathopNP_ (float, __CONCAT(func,f), op)                            \
170   __inline_mathopNP_ (long double, __CONCAT(func,l), op)
171 #else
172 # define __inline_mathop(func, op) \
173   __inline_mathop_ (double, func, op)
174 # define __inline_mathopNP(func, op) \
175   __inline_mathopNP_ (double, func, op)
176 #endif
177
178 #define __inline_mathop_(float_type, func, op) \
179   __inline_mathop_decl_ (float_type, func, op, "0" (__x))
180 #define __inline_mathopNP_(float_type, func, op) \
181   __inline_mathop_declNP_ (float_type, func, op, "0" (__x))
182
183
184 #if defined __USE_MISC || defined __USE_ISOC99
185 # define __inline_mathop_decl(func, op, params...) \
186   __inline_mathop_decl_ (double, func, op, params)                            \
187   __inline_mathop_decl_ (float, __CONCAT(func,f), op, params)                 \
188   __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
189 # define __inline_mathop_declNP(func, op, params...) \
190   __inline_mathop_declNP_ (double, func, op, params)                          \
191   __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params)               \
192   __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params)
193 #else
194 # define __inline_mathop_decl(func, op, params...) \
195   __inline_mathop_decl_ (double, func, op, params)
196 # define __inline_mathop_declNP(func, op, params...) \
197   __inline_mathop_declNP_ (double, func, op, params)
198 #endif
199
200 #define __inline_mathop_decl_(float_type, func, op, params...) \
201   __MATH_INLINE float_type func (float_type) __THROW;                         \
202   __inline_mathop_declNP_ (float_type, func, op, params)
203
204 #define __inline_mathop_declNP_(float_type, func, op, params...) \
205   __MATH_INLINE float_type func (float_type __x) __THROW                      \
206   {                                                                           \
207     register float_type __result;                                             \
208     __asm __volatile__ (op : "=t" (__result) : params);                       \
209     return __result;                                                          \
210   }
211
212
213 #if defined __USE_MISC || defined __USE_ISOC99
214 # define __inline_mathcode(func, arg, code) \
215   __inline_mathcode_ (double, func, arg, code)                                \
216   __inline_mathcode_ (float, __CONCAT(func,f), arg, code)                     \
217   __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
218 # define __inline_mathcodeNP(func, arg, code) \
219   __inline_mathcodeNP_ (double, func, arg, code)                                      \
220   __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code)                   \
221   __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code)
222 # define __inline_mathcode2(func, arg1, arg2, code) \
223   __inline_mathcode2_ (double, func, arg1, arg2, code)                        \
224   __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code)             \
225   __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
226 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
227   __inline_mathcodeNP2_ (double, func, arg1, arg2, code)                              \
228   __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code)           \
229   __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code)
230 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
231   __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)                  \
232   __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code)       \
233   __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
234 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
235   __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)                \
236   __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code)             \
237   __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
238 #else
239 # define __inline_mathcode(func, arg, code) \
240   __inline_mathcode_ (double, func, (arg), code)
241 # define __inline_mathcodeNP(func, arg, code) \
242   __inline_mathcodeNP_ (double, func, (arg), code)
243 # define __inline_mathcode2(func, arg1, arg2, code) \
244   __inline_mathcode2_ (double, func, arg1, arg2, code)
245 # define __inline_mathcodeNP2(func, arg1, arg2, code) \
246   __inline_mathcodeNP2_ (double, func, arg1, arg2, code)
247 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
248   __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
249 # define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \
250   __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code)
251 #endif
252
253 #define __inline_mathcode_(float_type, func, arg, code) \
254   __MATH_INLINE float_type func (float_type) __THROW;                         \
255   __inline_mathcodeNP_(float_type, func, arg, code)
256
257 #define __inline_mathcodeNP_(float_type, func, arg, code) \
258   __MATH_INLINE float_type func (float_type arg) __THROW                      \
259   {                                                                           \
260     code;                                                                     \
261   }
262
263
264 #define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
265   __MATH_INLINE float_type func (float_type, float_type) __THROW;             \
266   __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code)
267
268 #define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \
269   __MATH_INLINE float_type func (float_type arg1, float_type arg2) __THROW    \
270   {                                                                           \
271     code;                                                                     \
272   }
273
274 #define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
275   __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \
276   __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code)
277
278 #define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \
279   __MATH_INLINE float_type func (float_type arg1, float_type arg2,            \
280                                  float_type arg3) __THROW                     \
281   {                                                                           \
282     code;                                                                     \
283   }
284 #endif
285
286
287 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
288 /* Miscellaneous functions */
289
290 __inline_mathcode (__sgn, __x, \
291   return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
292
293 /* __FAST_MATH__ is defined by gcc -ffast-math.  */
294 #ifdef __FAST_MATH__
295 __inline_mathcode (__pow2, __x, \
296   register long double __value;                                               \
297   register long double __exponent;                                            \
298   __extension__ long long int __p = (long long int) __x;                      \
299   if (__x == (long double) __p)                                               \
300     {                                                                         \
301       __asm __volatile__                                                      \
302         ("fscale"                                                             \
303          : "=t" (__value) : "0" (1.0), "u" (__x));                            \
304       return __value;                                                         \
305     }                                                                         \
306   __asm __volatile__                                                          \
307     ("fld       %%st(0)\n\t"                                                  \
308      "frndint                   # int(x)\n\t"                                 \
309      "fxch\n\t"                                                               \
310      "fsub      %%st(1)         # fract(x)\n\t"                               \
311      "f2xm1                     # 2^(fract(x)) - 1\n\t"                       \
312      : "=t" (__value), "=u" (__exponent) : "0" (__x));                        \
313   __value += 1.0;                                                             \
314   __asm __volatile__                                                          \
315     ("fscale"                                                                 \
316      : "=t" (__value) : "0" (__value), "u" (__exponent));                     \
317   return __value)
318
319 # ifdef __USE_GNU
320 #  define __sincos_code \
321   register long double __cosr;                                                \
322   register long double __sinr;                                                \
323   __asm __volatile__                                                          \
324     ("fsincos\n\t"                                                            \
325      "fnstsw    %%ax\n\t"                                                     \
326      "testl     $0x400, %%eax\n\t"                                            \
327      "jz        1f\n\t"                                                       \
328      "fldpi\n\t"                                                              \
329      "fadd      %%st(0)\n\t"                                                  \
330      "fxch      %%st(1)\n\t"                                                  \
331      "2: fprem1\n\t"                                                          \
332      "fnstsw    %%ax\n\t"                                                     \
333      "testl     $0x400, %%eax\n\t"                                            \
334      "jnz       2b\n\t"                                                       \
335      "fstp      %%st(1)\n\t"                                                  \
336      "fsincos\n\t"                                                            \
337      "1:"                                                                     \
338      : "=t" (__cosr), "=u" (__sinr) : "0" (__x));                             \
339   *__sinx = __sinr;                                                           \
340   *__cosx = __cosr
341
342 __MATH_INLINE void
343 __sincos (double __x, double *__sinx, double *__cosx) __THROW
344 {
345   __sincos_code;
346 }
347
348 __MATH_INLINE void
349 __sincosf (float __x, float *__sinx, float *__cosx) __THROW
350 {
351   __sincos_code;
352 }
353
354 __MATH_INLINE void
355 __sincosl (long double __x, long double *__sinx, long double *__cosx) __THROW
356 {
357   __sincos_code;
358 }
359 # endif
360
361
362 /* Optimized inline implementation, sometimes with reduced precision
363    and/or argument range.  */
364
365 # define __expm1_code \
366   register long double __value;                                               \
367   register long double __exponent;                                            \
368   register long double __temp;                                                \
369   __asm __volatile__                                                          \
370     ("fldl2e                    # e^x - 1 = 2^(x * log2(e)) - 1\n\t"          \
371      "fmul      %%st(1)         # x * log2(e)\n\t"                            \
372      "fst       %%st(1)\n\t"                                                  \
373      "frndint                   # int(x * log2(e))\n\t"                       \
374      "fxch\n\t"                                                               \
375      "fsub      %%st(1)         # fract(x * log2(e))\n\t"                     \
376      "f2xm1                     # 2^(fract(x * log2(e))) - 1\n\t"             \
377      "fscale                    # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
378      : "=t" (__value), "=u" (__exponent) : "0" (__x));                        \
379   __asm __volatile__                                                          \
380     ("fscale                    # 2^int(x * log2(e))\n\t"                     \
381      : "=t" (__temp) : "0" (1.0), "u" (__exponent));                          \
382   __temp -= 1.0;                                                              \
383   __temp += __value;                                                          \
384   return __temp ? __temp : __x
385 __inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code)
386
387
388 # define __exp_code \
389   register long double __value;                                               \
390   register long double __exponent;                                            \
391   __asm __volatile__                                                          \
392     ("fldl2e                    # e^x = 2^(x * log2(e))\n\t"                  \
393      "fmul      %%st(1)         # x * log2(e)\n\t"                            \
394      "fst       %%st(1)\n\t"                                                  \
395      "frndint                   # int(x * log2(e))\n\t"                       \
396      "fxch\n\t"                                                               \
397      "fsub      %%st(1)         # fract(x * log2(e))\n\t"                     \
398      "f2xm1                     # 2^(fract(x * log2(e))) - 1\n\t"             \
399      : "=t" (__value), "=u" (__exponent) : "0" (__x));                        \
400   __value += 1.0;                                                             \
401   __asm __volatile__                                                          \
402     ("fscale"                                                                 \
403      : "=t" (__value) : "0" (__value), "u" (__exponent));                     \
404   return __value
405 __inline_mathcodeNP (exp, __x, __exp_code)
406 __inline_mathcodeNP_ (long double, __expl, __x, __exp_code)
407
408
409 __inline_mathcodeNP (tan, __x, \
410   register long double __value;                                               \
411   register long double __value2 __attribute__ ((__unused__));                 \
412   __asm __volatile__                                                          \
413     ("fptan"                                                                  \
414      : "=t" (__value2), "=u" (__value) : "0" (__x));                          \
415   return __value)
416 #endif /* __FAST_MATH__ */
417
418
419 #define __atan2_code \
420   register long double __value;                                               \
421   __asm __volatile__                                                          \
422     ("fpatan"                                                                 \
423      : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)");                      \
424   return __value
425 __inline_mathcodeNP2 (atan2, __y, __x, __atan2_code)
426 __inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code)
427
428
429 __inline_mathcodeNP2 (fmod, __x, __y, \
430   register long double __value;                                               \
431   __asm __volatile__                                                          \
432     ("1:        fprem\n\t"                                                    \
433      "fnstsw    %%ax\n\t"                                                     \
434      "sahf\n\t"                                                               \
435      "jp        1b"                                                           \
436      : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc");                   \
437   return __value)
438
439
440 #ifdef __FAST_MATH__
441 # if !__GNUC_PREREQ (3,3)
442 __inline_mathopNP (sqrt, "fsqrt")
443 __inline_mathopNP_ (long double, __sqrtl, "fsqrt")
444 #  define __libc_sqrtl(n) __sqrtl (n)
445 # else
446 #  define __libc_sqrtl(n) __builtin_sqrtl (n)
447 # endif
448 #endif
449
450 #if __GNUC_PREREQ (2, 8)
451 __inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x))
452 __inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x))
453 __inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x))
454 __inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
455 #else
456 __inline_mathop (fabs, "fabs")
457 __inline_mathop_ (long double, __fabsl, "fabs")
458 #endif
459
460 #ifdef __FAST_MATH__
461 /* The argument range of this inline version is reduced.  */
462 __inline_mathopNP (sin, "fsin")
463 /* The argument range of this inline version is reduced.  */
464 __inline_mathopNP (cos, "fcos")
465
466 __inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)")
467 __inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)")
468
469 __inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x)))
470 __inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x))
471 #endif /* __FAST_MATH__ */
472
473 __inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)")
474
475 __inline_mathcode_ (long double, __sgn1l, __x, \
476   __extension__ union { long double __xld; unsigned int __xi[3]; } __n =      \
477     { __xld: __x };                                                           \
478   __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff;                              \
479   __n.__xi[1] = 0x80000000;                                                   \
480   __n.__xi[0] = 0;                                                            \
481   return __n.__xld)
482
483
484 #ifdef __FAST_MATH__
485 /* The argument range of the inline version of sinhl is slightly reduced.  */
486 __inline_mathcodeNP (sinh, __x, \
487   register long double __exm1 = __expm1l (__fabsl (__x));                     \
488   return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
489
490 __inline_mathcodeNP (cosh, __x, \
491   register long double __ex = __expl (__x);                                   \
492   return 0.5 * (__ex + 1.0 / __ex))
493
494 __inline_mathcodeNP (tanh, __x, \
495   register long double __exm1 = __expm1l (-__fabsl (__x + __x));              \
496   return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
497 #endif
498
499 __inline_mathcodeNP (floor, __x, \
500   register long double __value;                                               \
501   __volatile unsigned short int __cw;                                         \
502   __volatile unsigned short int __cwtmp;                                      \
503   __asm __volatile ("fnstcw %0" : "=m" (__cw));                               \
504   __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */                     \
505   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));                            \
506   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));                  \
507   __asm __volatile ("fldcw %0" : : "m" (__cw));                               \
508   return __value)
509
510 __inline_mathcodeNP (ceil, __x, \
511   register long double __value;                                               \
512   __volatile unsigned short int __cw;                                         \
513   __volatile unsigned short int __cwtmp;                                      \
514   __asm __volatile ("fnstcw %0" : "=m" (__cw));                               \
515   __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */                       \
516   __asm __volatile ("fldcw %0" : : "m" (__cwtmp));                            \
517   __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));                  \
518   __asm __volatile ("fldcw %0" : : "m" (__cw));                               \
519   return __value)
520
521 #ifdef __FAST_MATH__
522 # define __ldexp_code \
523   register long double __value;                                               \
524   __asm __volatile__                                                          \
525     ("fscale"                                                                 \
526      : "=t" (__value) : "0" (__x), "u" ((long double) __y));                  \
527   return __value
528
529 __MATH_INLINE double
530 ldexp (double __x, int __y) __THROW
531 {
532   __ldexp_code;
533 }
534 #endif
535
536
537 /* Optimized versions for some non-standardized functions.  */
538 #if defined __USE_ISOC99 || defined __USE_MISC
539
540 # ifdef __FAST_MATH__
541 __inline_mathcodeNP (expm1, __x, __expm1_code)
542
543 /* We cannot rely on M_SQRT being defined.  So we do it for ourself
544    here.  */
545 #  define __M_SQRT2     1.41421356237309504880L /* sqrt(2) */
546
547 __inline_mathcodeNP (log1p, __x, \
548   register long double __value;                                               \
549   if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2)                                 \
550     __value = logl (1.0 + __x);                                               \
551   else                                                                        \
552     __asm __volatile__                                                        \
553       ("fldln2\n\t"                                                           \
554        "fxch\n\t"                                                             \
555        "fyl2xp1"                                                              \
556        : "=t" (__value) : "0" (__x) : "st(1)");                               \
557   return __value)
558
559
560 /* The argument range of the inline version of asinhl is slightly reduced.  */
561 __inline_mathcodeNP (asinh, __x, \
562   register long double  __y = __fabsl (__x);                                  \
563   return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y)   \
564           * __sgn1l (__x)))
565
566 __inline_mathcodeNP (acosh, __x, \
567   return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0)))
568
569 __inline_mathcodeNP (atanh, __x, \
570   register long double __y = __fabsl (__x);                                   \
571   return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
572
573 /* The argument range of the inline version of hypotl is slightly reduced.  */
574 __inline_mathcodeNP2 (hypot, __x, __y,
575                       return __libc_sqrtl (__x * __x + __y * __y))
576
577 __inline_mathcodeNP(logb, __x, \
578   register long double __value;                                               \
579   register long double __junk;                                                \
580   __asm __volatile__                                                          \
581     ("fxtract\n\t"                                                            \
582      : "=t" (__junk), "=u" (__value) : "0" (__x));                            \
583   return __value)
584
585 # endif
586 #endif
587
588 #ifdef __USE_ISOC99
589 #ifdef __FAST_MATH__
590 __inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)")
591
592 __MATH_INLINE float
593 ldexpf (float __x, int __y) __THROW
594 {
595   __ldexp_code;
596 }
597
598 __MATH_INLINE long double
599 ldexpl (long double __x, int __y) __THROW
600 {
601   __ldexp_code;
602 }
603
604 __inline_mathcodeNP3 (fma, __x, __y, __z, return (__x * __y) + __z)
605
606 __inline_mathopNP (rint, "frndint")
607 #endif /* __FAST_MATH__ */
608
609 #define __lrint_code \
610   long int __lrintres;                                                        \
611   __asm__ __volatile__                                                        \
612     ("fistpl %0"                                                              \
613      : "=m" (__lrintres) : "t" (__x) : "st");                                 \
614   return __lrintres
615 __MATH_INLINE long int
616 lrintf (float __x) __THROW
617 {
618   __lrint_code;
619 }
620 __MATH_INLINE long int
621 lrint (double __x) __THROW
622 {
623   __lrint_code;
624 }
625 __MATH_INLINE long int
626 lrintl (long double __x) __THROW
627 {
628   __lrint_code;
629 }
630 #undef __lrint_code
631
632 #define __llrint_code \
633   long long int __llrintres;                                                  \
634   __asm__ __volatile__                                                        \
635     ("fistpll %0"                                                             \
636      : "=m" (__llrintres) : "t" (__x) : "st");                                \
637   return __llrintres
638 __MATH_INLINE long long int
639 llrintf (float __x) __THROW
640 {
641   __llrint_code;
642 }
643 __MATH_INLINE long long int
644 llrint (double __x) __THROW
645 {
646   __llrint_code;
647 }
648 __MATH_INLINE long long int
649 llrintl (long double __x) __THROW
650 {
651   __llrint_code;
652 }
653 #undef __llrint_code
654
655 #endif
656
657
658 #ifdef __USE_MISC
659
660 __inline_mathcodeNP2 (drem, __x, __y, \
661   register double __value;                                                    \
662   register int __clobbered;                                                   \
663   __asm __volatile__                                                          \
664     ("1:        fprem1\n\t"                                                   \
665      "fstsw     %%ax\n\t"                                                     \
666      "sahf\n\t"                                                               \
667      "jp        1b"                                                           \
668      : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc");    \
669   return __value)
670
671
672 /* This function is used in the `isfinite' macro.  */
673 __MATH_INLINE int
674 __finite (double __x) __THROW
675 {
676   return (__extension__
677           (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
678              | 0x800fffffu) + 1) >> 31));
679 }
680
681 /* Miscellaneous functions */
682 #ifdef __FAST_MATH__
683 __inline_mathcode (__coshm1, __x, \
684   register long double __exm1 = __expm1l (__fabsl (__x));                     \
685   return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
686
687 __inline_mathcode (__acosh1p, __x, \
688   return log1pl (__x + __libc_sqrtl (__x) * __libc_sqrtl (__x + 2.0)))
689
690 #endif /* __FAST_MATH__ */
691 #endif /* __USE_MISC  */
692
693 /* Undefine some of the large macros which are not used anymore.  */
694 #undef __atan2_code
695 #ifdef __FAST_MATH__
696 # undef __expm1_code
697 # undef __exp_code
698 # undef __sincos_code
699 #endif /* __FAST_MATH__ */
700
701 #endif /* __NO_MATH_INLINES  */
702
703
704 /* This code is used internally in the GNU libc.  */
705 #ifdef __LIBC_INTERNAL_MATH_INLINES
706 __inline_mathop (__ieee754_sqrt, "fsqrt")
707 __inline_mathcode2 (__ieee754_atan2, __y, __x,
708                     register long double __value;
709                     __asm __volatile__ ("fpatan\n\t"
710                                         : "=t" (__value)
711                                         : "0" (__x), "u" (__y) : "st(1)");
712                     return __value;)
713 #endif
714
715 #endif /* __GNUC__  */