Update.
[glibc.git] / sysdeps / i386 / fpu / bits / mathinline.h
blobbf5b99a00e827bce1c4c2695007a3fb2f7966524
1 /* Inline math functions for i387.
2 Copyright (C) 1995, 1996, 1997, 1998 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.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
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 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #ifndef _MATH_H
22 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
23 #endif
25 #ifdef __cplusplus
26 # define __MATH_INLINE __inline
27 #else
28 # define __MATH_INLINE extern __inline
29 #endif
32 #if defined __USE_ISOC9X && defined __GNUC__ && __GNUC__ >= 2
33 /* ISO C 9X defines some macros to perform unordered comparisons. The
34 ix87 FPU supports this with special opcodes and we should use them.
35 These must not be inline functions since we have to be able to handle
36 all floating-point types. */
37 # ifdef __i686__
38 /* For the PentiumPro and more recent processors we can provide
39 better code. */
40 # define isgreater(x, y) \
41 ({ register char __result; \
42 __asm__ ("fucomip %%st(1), %%st; seta %%al" \
43 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
44 __result; })
45 # define isgreaterequal(x, y) \
46 ({ register char __result; \
47 __asm__ ("fucomip %%st(1), %%st; setae %%al" \
48 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
49 __result; })
51 # define isless(x, y) \
52 ({ register char __result; \
53 __asm__ ("fucomip %%st(1), %%st; seta %%al" \
54 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \
55 __result; })
57 # define islessequal(x, y) \
58 ({ register char __result; \
59 __asm__ ("fucomip %%st(1), %%st; setae %%al" \
60 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \
61 __result; })
63 # define islessgreater(x, y) \
64 ({ register char __result; \
65 __asm__ ("fucomip %%st(1), %%st; setne %%al" \
66 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
67 __result; })
69 # define isunordered(x, y) \
70 ({ register char __result; \
71 __asm__ ("fucomip %%st(1), %%st; setp %%al" \
72 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \
73 __result; })
74 # else
75 /* This is the dumb, portable code for i386 and above. */
76 # define isgreater(x, y) \
77 ({ register char __result; \
78 __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \
79 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
80 __result; })
82 # define isgreaterequal(x, y) \
83 ({ register char __result; \
84 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \
85 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
86 __result; })
88 # define isless(x, y) \
89 ({ register char __result; \
90 __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \
91 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
92 __result; })
94 # define islessequal(x, y) \
95 ({ register char __result; \
96 __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \
97 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
98 __result; })
100 # define islessgreater(x, y) \
101 ({ register char __result; \
102 __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al" \
103 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
104 __result; })
106 # define isunordered(x, y) \
107 ({ register char __result; \
108 __asm__ ("fucompp; fnstsw; sahf; setp %%al" \
109 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
110 __result; })
111 # endif /* __i686__ */
113 /* Test for negative number. Used in the signbit() macro. */
114 __MATH_INLINE int
115 __signbitf (float __x)
117 union { float __f; int __i; } __u = { __f: __x }; return __u.__i < 0;
119 __MATH_INLINE int
120 __signbit (double __x)
122 union { double __d; int __i[2]; } __u = { __d: __x }; return __u.__i[1] < 0;
124 __MATH_INLINE int
125 __signbitl (long double __x)
127 union { long double __l; int __i[3]; } __u = { __l: __x };
128 return (__u.__i[2] & 0x8000) != 0;
130 #endif
133 /* The gcc, version 2.7 or below, has problems with all this inlining
134 code. So disable it for this version of the compiler. */
135 #if defined __GNUC__ && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 7))
137 #if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
138 && defined __OPTIMIZE__)
140 /* A macro to define float, double, and long double versions of various
141 math functions for the ix87 FPU. FUNC is the function name (which will
142 be suffixed with f and l for the float and long double version,
143 respectively). OP is the name of the FPU operation. */
145 #if defined __USE_MISC || defined __USE_ISOC9X
146 # define __inline_mathop(func, op) \
147 __inline_mathop_ (double, func, op) \
148 __inline_mathop_ (float, __CONCAT(func,f), op) \
149 __inline_mathop_ (long double, __CONCAT(func,l), op)
150 #else
151 # define __inline_mathop(func, op) \
152 __inline_mathop_ (double, func, op)
153 #endif
155 #define __inline_mathop_(float_type, func, op) \
156 __inline_mathop_decl_ (float_type, func, op, "0" (__x))
159 #if defined __USE_MISC || defined __USE_ISOC9X
160 # define __inline_mathop_decl(func, op, params...) \
161 __inline_mathop_decl_ (double, func, op, params) \
162 __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \
163 __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params)
164 #else
165 # define __inline_mathop_decl(func, op, params...) \
166 __inline_mathop_decl_ (double, func, op, params)
167 #endif
169 #define __inline_mathop_decl_(float_type, func, op, params...) \
170 __MATH_INLINE float_type func (float_type); \
171 __MATH_INLINE float_type func (float_type __x) \
173 register float_type __result; \
174 __asm __volatile__ (op : "=t" (__result) : params); \
175 return __result; \
179 #if defined __USE_MISC || defined __USE_ISOC9X
180 # define __inline_mathcode(func, arg, code) \
181 __inline_mathcode_ (double, func, arg, code) \
182 __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \
183 __inline_mathcode_ (long double, __CONCAT(func,l), arg, code)
184 # define __inline_mathcode2(func, arg1, arg2, code) \
185 __inline_mathcode2_ (double, func, arg1, arg2, code) \
186 __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \
187 __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code)
188 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
189 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \
190 __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \
191 __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code)
192 #else
193 # define __inline_mathcode(func, arg, code) \
194 __inline_mathcode_ (double, func, (arg), code)
195 # define __inline_mathcode2(func, arg1, arg2, code) \
196 __inline_mathcode2_ (double, func, arg1, arg2, code)
197 # define __inline_mathcode3(func, arg1, arg2, arg3, code) \
198 __inline_mathcode3_ (double, func, arg1, arg2, arg3, code)
199 #endif
201 #define __inline_mathcode_(float_type, func, arg, code) \
202 __MATH_INLINE float_type func (float_type); \
203 __MATH_INLINE float_type func (float_type arg) \
205 code; \
208 #define __inline_mathcode2_(float_type, func, arg1, arg2, code) \
209 __MATH_INLINE float_type func (float_type, float_type); \
210 __MATH_INLINE float_type func (float_type arg1, float_type arg2) \
212 code; \
215 #define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \
216 __MATH_INLINE float_type func (float_type, float_type, float_type); \
217 __MATH_INLINE float_type func (float_type arg1, float_type arg2, \
218 float_type arg3) \
220 code; \
222 #endif
225 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
226 /* Miscellaneous functions */
228 __inline_mathcode (__sgn, __x, \
229 return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0))
231 __inline_mathcode (__pow2, __x, \
232 register long double __value; \
233 register long double __exponent; \
234 __extension__ long long int __p = (long long int) __x; \
235 if (__x == (long double) __p) \
237 __asm __volatile__ \
238 ("fscale" \
239 : "=t" (__value) : "0" (1.0), "u" (__x)); \
240 return __value; \
242 __asm __volatile__ \
243 ("fldl %%st(0)\n\t" \
244 "frndint # int(x)\n\t" \
245 "fxch\n\t" \
246 "fsub %%st(1) # fract(x)\n\t" \
247 "f2xm1 # 2^(fract(x)) - 1\n\t" \
248 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
249 __value += 1.0; \
250 __asm __volatile__ \
251 ("fscale" \
252 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
253 return __value)
255 #define __sincos_code \
256 register long double __cosr; \
257 register long double __sinr; \
258 __asm __volatile__ \
259 ("fsincos\n\t" \
260 "fnstsw %%ax\n\t" \
261 "testl $0x400, %%eax\n\t" \
262 "jz 1f\n\t" \
263 "fldpi\n\t" \
264 "fadd %%st(0)\n\t" \
265 "fxch %%st(1)\n\t" \
266 "2: fprem1\n\t" \
267 "fnstsw %%ax\n\t" \
268 "testl $0x400, %%eax\n\t" \
269 "jnz 2b\n\t" \
270 "fstp %%st(1)\n\t" \
271 "fsincos\n\t" \
272 "1:" \
273 : "=t" (__cosr), "=u" (__sinr) : "0" (__x)); \
274 *__sinx = __sinr; \
275 *__cosx = __cosr
277 __MATH_INLINE void __sincos (double __x, double *__sinx, double *__cosx);
278 __MATH_INLINE void
279 __sincos (double __x, double *__sinx, double *__cosx)
281 __sincos_code;
284 __MATH_INLINE void __sincosf (float __x, float *__sinx, float *__cosx);
285 __MATH_INLINE void
286 __sincosf (float __x, float *__sinx, float *__cosx)
288 __sincos_code;
291 __MATH_INLINE void __sincosl (long double __x, long double *__sinx,
292 long double *__cosx);
293 __MATH_INLINE void
294 __sincosl (long double __x, long double *__sinx, long double *__cosx)
296 __sincos_code;
300 /* Optimized inline implementation, sometimes with reduced precision
301 and/or argument range. */
303 #define __expm1_code \
304 register long double __value; \
305 register long double __exponent; \
306 register long double __temp; \
307 __asm __volatile__ \
308 ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \
309 "fmul %%st(1) # x * log2(e)\n\t" \
310 "fst %%st(1)\n\t" \
311 "frndint # int(x * log2(e))\n\t" \
312 "fxch\n\t" \
313 "fsub %%st(1) # fract(x * log2(e))\n\t" \
314 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
315 "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \
316 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
317 __asm __volatile__ \
318 ("fscale # 2^int(x * log2(e))\n\t" \
319 : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \
320 __temp -= 1.0; \
321 return __temp + __value
322 __inline_mathcode_ (long double, __expm1l, __x, __expm1_code)
325 #define __exp_code \
326 register long double __value; \
327 register long double __exponent; \
328 __asm __volatile__ \
329 ("fldl2e # e^x = 2^(x * log2(e))\n\t" \
330 "fmul %%st(1) # x * log2(e)\n\t" \
331 "fst %%st(1)\n\t" \
332 "frndint # int(x * log2(e))\n\t" \
333 "fxch\n\t" \
334 "fsub %%st(1) # fract(x * log2(e))\n\t" \
335 "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \
336 : "=t" (__value), "=u" (__exponent) : "0" (__x)); \
337 __value += 1.0; \
338 __asm __volatile__ \
339 ("fscale" \
340 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
341 return __value
342 __inline_mathcode (exp, __x, __exp_code)
343 __inline_mathcode_ (long double, __expl, __x, __exp_code)
346 __inline_mathcode (tan, __x, \
347 register long double __value; \
348 register long double __value2 __attribute__ ((__unused__)); \
349 __asm __volatile__ \
350 ("fptan" \
351 : "=t" (__value2), "=u" (__value) : "0" (__x)); \
352 return __value)
355 #define __atan2_code \
356 register long double __value; \
357 __asm __volatile__ \
358 ("fpatan\n\t" \
359 : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \
360 return __value
361 __inline_mathcode2 (atan2, __y, __x, __atan2_code)
362 __inline_mathcode2_ (long double, __atan2l, __y, __x, __atan2_code)
365 __inline_mathcode2 (fmod, __x, __y, \
366 register long double __value; \
367 __asm __volatile__ \
368 ("1: fprem\n\t" \
369 "fnstsw %%ax\n\t" \
370 "sahf\n\t" \
371 "jp 1b" \
372 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
373 return __value)
376 __inline_mathcode2 (pow, __x, __y, \
377 register long double __value; \
378 register long double __exponent; \
379 __extension__ long long int __p = (long long int) __y; \
380 if (__x == 0.0 && __y > 0.0) \
381 return 0.0; \
382 if (__y == (double) __p) \
384 long double __r = 1.0; \
385 if (__p == 0) \
386 return 1.0; \
387 if (__p < 0) \
389 __p = -__p; \
390 __x = 1.0 / __x; \
392 while (1) \
394 if (__p & 1) \
395 __r *= __x; \
396 __p >>= 1; \
397 if (__p == 0) \
398 return __r; \
399 __x *= __x; \
401 /* NOTREACHED */ \
403 __asm __volatile__ \
404 ("fyl2x" : "=t" (__value) : "0" (__x), "u" (1.0) : "st(1)"); \
405 __asm __volatile__ \
406 ("fmul %%st(1) # y * log2(x)\n\t" \
407 "fst %%st(1)\n\t" \
408 "frndint # int(y * log2(x))\n\t" \
409 "fxch\n\t" \
410 "fsub %%st(1) # fract(y * log2(x))\n\t" \
411 "f2xm1 # 2^(fract(y * log2(x))) - 1\n\t" \
412 : "=t" (__value), "=u" (__exponent) : "0" (__y), "1" (__value)); \
413 __value += 1.0; \
414 __asm __volatile__ \
415 ("fscale" \
416 : "=t" (__value) : "0" (__value), "u" (__exponent)); \
417 return __value)
420 __inline_mathop (sqrt, "fsqrt")
421 __inline_mathop_ (long double, __sqrtl, "fsqrt")
423 #if defined __GNUC__ && (__GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 8)
424 __inline_mathcode_ (double, fabs, __x, return __builtin_fabs (__x))
425 __inline_mathcode_ (float, fabsf, __x, return __builtin_fabsf (__x))
426 __inline_mathcode_ (long double, fabsl, __x, return __builtin_fabsl (__x))
427 __inline_mathcode_ (long double, __fabsl, __x, return __builtin_fabsl (__x))
428 #else
429 __inline_mathop (fabs, "fabs")
430 __inline_mathop_ (long double, __fabsl, "fabs")
431 #endif
433 /* The argument range of this inline version is reduced. */
434 __inline_mathop (sin, "fsin")
435 /* The argument range of this inline version is reduced. */
436 __inline_mathop (cos, "fcos")
438 __inline_mathop (atan, "fld1; fpatan")
439 __inline_mathop (log, "fldln2; fxch; fyl2x")
440 __inline_mathop (log10, "fldlg2; fxch; fyl2x")
442 __inline_mathcode (asin, __x, return __atan2l (__x, __sqrtl (1.0 - __x * __x)))
443 __inline_mathcode (acos, __x, return __atan2l (__sqrtl (1.0 - __x * __x), __x))
445 __inline_mathcode_ (long double, __sgn1l, __x, return __x >= 0.0 ? 1.0 : -1.0)
448 /* The argument range of the inline version of sinhl is slightly reduced. */
449 __inline_mathcode (sinh, __x, \
450 register long double __exm1 = __expm1l (__fabsl (__x)); \
451 return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x))
453 __inline_mathcode (cosh, __x, \
454 register long double __ex = __expl (__x); \
455 return 0.5 * (__ex + 1.0 / __ex))
457 __inline_mathcode (tanh, __x, \
458 register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \
459 return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x))
462 __inline_mathcode (floor, __x, \
463 register long double __value; \
464 __volatile unsigned short int __cw; \
465 __volatile unsigned short int __cwtmp; \
466 __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
467 __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ \
468 __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
469 __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
470 __asm __volatile ("fldcw %0" : : "m" (__cw)); \
471 return __value)
473 __inline_mathcode (ceil, __x, \
474 register long double __value; \
475 __volatile unsigned short int __cw; \
476 __volatile unsigned short int __cwtmp; \
477 __asm __volatile ("fnstcw %0" : "=m" (__cw)); \
478 __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ \
479 __asm __volatile ("fldcw %0" : : "m" (__cwtmp)); \
480 __asm __volatile ("frndint" : "=t" (__value) : "0" (__x)); \
481 __asm __volatile ("fldcw %0" : : "m" (__cw)); \
482 return __value)
484 #define __ldexp_code \
485 register long double __value; \
486 __asm __volatile__ \
487 ("fscale" \
488 : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \
489 return __value
491 __MATH_INLINE double ldexp (double __x, int __y);
492 __MATH_INLINE double
493 ldexp (double __x, int __y)
495 __ldexp_code;
499 /* Optimized versions for some non-standardized functions. */
500 #if defined __USE_ISOC9X || defined __USE_MISC
502 __inline_mathop(log2, "fld1; fxch; fyl2x")
504 __inline_mathcode (expm1, __x, __expm1_code)
506 /* We cannot rely on M_SQRT being defined. So we do it for ourself
507 here. */
508 # define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */
510 __inline_mathcode (log1p, __x, \
511 register long double __value; \
512 if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \
513 __value = logl (1.0 + __x); \
514 else \
515 __asm __volatile__ \
516 ("fldln2\n\t" \
517 "fxch\n\t" \
518 "fyl2xp1" \
519 : "=t" (__value) : "0" (__x)); \
520 return __value)
523 /* The argument range of the inline version of asinhl is slightly reduced. */
524 __inline_mathcode (asinh, __x, \
525 register long double __y = __fabsl (__x); \
526 return (log1pl (__y * __y / (__sqrtl (__y * __y + 1.0) + 1.0) + __y) \
527 * __sgn1l (__x)))
529 __inline_mathcode (acosh, __x, \
530 return logl (__x + __sqrtl (__x - 1.0) * __sqrtl (__x + 1.0)))
532 __inline_mathcode (atanh, __x, \
533 register long double __y = __fabsl (__x); \
534 return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x))
537 /* The argument range of the inline version of hypotl is slightly reduced. */
538 __inline_mathcode2 (hypot, __x, __y, return __sqrtl (__x * __x + __y * __y))
540 __inline_mathcode(logb, __x, \
541 register long double __value; \
542 register long double __junk; \
543 __asm __volatile__ \
544 ("fxtract\n\t" \
545 : "=t" (__junk), "=u" (__value) : "0" (__x)); \
546 return __value)
548 __MATH_INLINE float ldexpf (float __x, int __y);
549 __MATH_INLINE float
550 ldexpf (float __x, int __y)
552 __ldexp_code;
555 __MATH_INLINE long double ldexpl (long double __x, int __y);
556 __MATH_INLINE long double
557 ldexpl (long double __x, int __y)
559 __ldexp_code;
562 __inline_mathcode3 (fma, __x, __y, __z, return (__x * __y) + __z)
563 #endif
566 #ifdef __USE_MISC
568 __inline_mathcode2 (drem, __x, __y, \
569 register double __value; \
570 __asm __volatile__ \
571 ("1: fprem1\n\t" \
572 "fstsw %%ax\n\t" \
573 "sahf\n\t" \
574 "jp 1b" \
575 : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \
576 return __value)
579 /* This function is used in the `isfinite' macro. */
580 __MATH_INLINE int __finite (double __x) __attribute__ ((__const__));
581 __MATH_INLINE int
582 __finite (double __x)
584 return (__extension__
585 (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1]
586 | 0x800fffff) + 1) >> 31));
589 /* Miscellaneous functions */
591 __inline_mathcode (__coshm1, __x, \
592 register long double __exm1 = __expm1l (__fabsl (__x)); \
593 return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1)
595 __inline_mathcode (__acosh1p, __x, \
596 return log1pl (__x + __sqrtl (__x) * __sqrtl (__x + 2.0)))
598 #endif /* __USE_MISC */
600 /* Undefine some of the large macros which are not used anymore. */
601 #undef __expm1_code
602 #undef __exp_code
603 #undef __atan2_code
604 #undef __sincos_code
606 #endif /* __NO_MATH_INLINES */
609 /* This code is used internally in the GNU libc. */
610 #ifdef __LIBC_INTERNAL_MATH_INLINES
611 __inline_mathop (__ieee754_sqrt, "fsqrt")
612 __inline_mathcode2 (__ieee754_atan2, __y, __x,
613 register long double __value;
614 __asm __volatile__ ("fpatan\n\t"
615 : "=t" (__value)
616 : "0" (__x), "u" (__y) : "st(1)");
617 return __value;)
618 #endif
620 #endif /* __GNUC__ */