Protect declarations of inline functions by feature tests to avoid
[kopensolaris-gnu/glibc.git] / sysdeps / m68k / fpu / bits / mathinline.h
1 /* Definitions of inline math functions implemented by the m68881/2.
2    Copyright (C) 1991, 92, 93, 94, 96, 97 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #ifdef  __GNUC__
21
22 #ifdef __USE_ISOC9X
23
24 /* ISO C 9X defines some macros to perform unordered comparisons.  The
25    m68k FPU supports this with special opcodes and we should use them.
26    These must not be inline functions since we have to be able to handle
27    all floating-point types.  */
28 # define isgreater(x, y)                                        \
29    __extension__                                        \
30    ({ char __result;                                    \
31       __asm__ ("fcmp%.x %2,%1; fsogt %0"                \
32                : "=dm" (__result) : "f" (x), "f" (y));  \
33       (int) __result; })
34
35 # define isgreaterequal(x, y)                           \
36    __extension__                                        \
37    ({ char __result;                                    \
38       __asm__ ("fcmp%.x %2,%1; fsoge %0"                \
39                : "=dm" (__result) : "f" (x), "f" (y));  \
40       (int) __result; })
41
42 # define isless(x, y)                                   \
43    __extension__                                        \
44    ({ char __result;                                    \
45       __asm__ ("fcmp%.x %2,%1; fsolt %0"                \
46                : "=dm" (__result) : "f" (x), "f" (y));  \
47       (int) __result; })
48
49 # define islessequal(x, y)                              \
50    __extension__                                        \
51    ({ char __result;                                    \
52       __asm__ ("fcmp%.x %2,%1; fsole %0"                \
53                : "=dm" (__result) : "f" (x), "f" (y));  \
54       (int) __result; })
55
56 # define islessgreater(x, y)                            \
57    __extension__                                        \
58    ({ char __result;                                    \
59       __asm__ ("fcmp%.x %2,%1; fsogl %0"                \
60                : "=dm" (__result) : "f" (x), "f" (y));  \
61       (int) __result; })
62
63 # define isunordered(x, y)                              \
64    __extension__                                        \
65    ({ char __result;                                    \
66       __asm__ ("fcmp%.x %2,%1; fsun %0"                 \
67                : "=dm" (__result) : "f" (x), "f" (y));  \
68       (int) __result; })
69 #endif
70
71
72 #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
73     || defined __LIBC_INTERNAL_MATH_INLINES
74
75 #ifdef  __LIBC_INTERNAL_MATH_INLINES
76 /* This is used when defining the functions themselves.  Define them with
77    __ names, and with `static inline' instead of `extern inline' so the
78    bodies will always be used, never an external function call.  */
79 # define __m81_u(x)             __CONCAT(__,x)
80 # define __m81_inline           static __inline
81 #else
82 # define __m81_u(x)             x
83 # ifdef __cplusplus
84 #  define __m81_inline          __inline
85 # else
86 #  define __m81_inline          extern __inline
87 # endif
88 # define __M81_MATH_INLINES     1
89 #endif
90
91 /* Define a const math function.  */
92 #define __m81_defun(rettype, func, args)                                      \
93   __m81_inline rettype __attribute__((__const__))                             \
94   __m81_u(func) args
95
96 /* Define the three variants of a math function that has a direct
97    implementation in the m68k fpu.  FUNC is the name for C (which will be
98    suffixed with f and l for the float and long double version, resp).  OP
99    is the name of the fpu operation (without leading f).  */
100
101 #if defined __USE_MISC || defined __USE_ISOC9X
102 # define __inline_mathop(func, op)                      \
103   __inline_mathop1(double, func, op)                    \
104   __inline_mathop1(float, __CONCAT(func,f), op)         \
105   __inline_mathop1(long double, __CONCAT(func,l), op)
106 #else
107 # define __inline_mathop(func, op)                      \
108   __inline_mathop1(double, func, op)
109 #endif
110
111 #define __inline_mathop1(float_type,func, op)                                 \
112   __m81_defun (float_type, func, (float_type __mathop_x))                     \
113   {                                                                           \
114     float_type __result;                                                      \
115     __asm("f" __STRING(op) "%.x %1, %0" : "=f" (__result) : "f" (__mathop_x));\
116     return __result;                                                          \
117   }
118
119 #ifdef __LIBC_INTERNAL_MATH_INLINES
120 /* ieee style elementary functions */
121 /* These are internal to the implementation of libm.  */
122 __inline_mathop(__ieee754_acos, acos)
123 __inline_mathop(__ieee754_asin, asin)
124 __inline_mathop(__ieee754_cosh, cosh)
125 __inline_mathop(__ieee754_sinh, sinh)
126 __inline_mathop(__ieee754_exp, etox)
127 __inline_mathop(__ieee754_exp2, twotox)
128 __inline_mathop(__ieee754_log10, log10)
129 __inline_mathop(__ieee754_log, logn)
130 __inline_mathop(__ieee754_sqrt, sqrt)
131 __inline_mathop(__ieee754_atanh, atanh)
132 #endif
133
134 __inline_mathop(__atan, atan)
135 __inline_mathop(__cos, cos)
136 __inline_mathop(__sin, sin)
137 __inline_mathop(__tan, tan)
138 __inline_mathop(__tanh, tanh)
139 __inline_mathop(__fabs, abs)
140
141 #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC9X
142 __inline_mathop(__rint, int)
143 __inline_mathop(__expm1, etoxm1)
144 __inline_mathop(__log1p, lognp1)
145 #endif
146
147 #ifdef __USE_MISC
148 __inline_mathop(__significand, getman)
149 #endif
150
151 #ifdef __USE_ISOC9X
152 __inline_mathop(__log2, log2)
153 __inline_mathop(__trunc, intrz)
154 #endif
155
156 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
157
158 __inline_mathop(atan, atan)
159 __inline_mathop(cos, cos)
160 __inline_mathop(sin, sin)
161 __inline_mathop(tan, tan)
162 __inline_mathop(tanh, tanh)
163
164 # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC9X
165 __inline_mathop(rint, int)
166 __inline_mathop(expm1, etoxm1)
167 __inline_mathop(log1p, lognp1)
168 # endif
169
170 # ifdef __USE_MISC
171 __inline_mathop(significand, getman)
172 # endif
173
174 # ifdef __USE_ISOC9X
175 __inline_mathop(log2, log2)
176 __inline_mathop(exp2, twotox)
177 __inline_mathop(trunc, intrz)
178 # endif
179
180 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
181
182 /* This macro contains the definition for the rest of the inline
183    functions, using __FLOAT_TYPE as the domain type and __S as the suffix
184    for the function names.  */
185
186 #ifdef __LIBC_INTERNAL_MATH_INLINES
187 /* Internally used functions.  */
188 # define __internal_inline_functions(float_type, s)                          \
189 __m81_defun (float_type, __CONCAT(__ieee754_remainder,s),                    \
190              (float_type __x, float_type __y))                               \
191 {                                                                            \
192   float_type __result;                                                       \
193   __asm("frem%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));          \
194   return __result;                                                           \
195 }                                                                            \
196                                                                              \
197 __m81_defun (float_type, __CONCAT(__ieee754_fmod,s),                         \
198              (float_type __x, float_type __y))                               \
199 {                                                                            \
200   float_type __result;                                                       \
201   __asm("fmod%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));          \
202   return __result;                                                           \
203 }
204
205 __internal_inline_functions (double,)
206 __internal_inline_functions (float,f)
207 __internal_inline_functions (long double,l)
208 # undef __internal_inline_functions
209
210 /* Get the m68881 condition codes, to quickly check multiple conditions.  */
211 static __inline__ unsigned long
212 __m81_test (long double __val)
213 {
214   unsigned long __fpsr;
215   __asm ("ftst%.x %1; fmove%.l %/fpsr,%0" : "=dm" (__fpsr) : "f" (__val));
216   return __fpsr;
217 }
218
219 /* Bit values returned by __m81_test.  */
220 # define __M81_COND_NAN (1 << 24)
221 # define __M81_COND_INF (2 << 24)
222 # define __M81_COND_ZERO (4 << 24)
223 # define __M81_COND_NEG (8 << 24)
224
225 #endif /* __LIBC_INTENRAL_MATH_INLINES */
226
227 /* The rest of the functions are available to the user.  */
228
229 #define __inline_functions(float_type, s)                                 \
230 __m81_inline float_type                                                   \
231 __m81_u(__CONCAT(__frexp,s))(float_type __value, int *__expptr)           \
232 {                                                                         \
233   float_type __mantissa, __exponent;                                      \
234   int __iexponent;                                                        \
235   unsigned long __fpsr;                                                   \
236   __asm("ftst%.x %1\n"                                                    \
237         "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));          \
238   if (__fpsr & (7 << 24))                                                 \
239     {                                                                     \
240       /* Not finite or zero.  */                                          \
241       *__expptr = 0;                                                      \
242       return __value;                                                     \
243     }                                                                     \
244   __asm("fgetexp%.x %1, %0" : "=f" (__exponent) : "f" (__value));         \
245   __iexponent = (int) __exponent + 1;                                     \
246   *__expptr = __iexponent;                                                \
247   __asm("fscale%.l %2, %0" : "=f" (__mantissa)                            \
248         : "0" (__value), "dmi" (-__iexponent));                           \
249   return __mantissa;                                                      \
250 }                                                                         \
251                                                                           \
252 __m81_defun (float_type, __CONCAT(__floor,s), (float_type __x))           \
253 {                                                                         \
254   float_type __result;                                                    \
255   unsigned long int __ctrl_reg;                                           \
256   __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));            \
257   /* Set rounding towards negative infinity.  */                          \
258   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
259                       : "dmi" ((__ctrl_reg & ~0x10) | 0x20));             \
260   /* Convert X to an integer, using -Inf rounding.  */                    \
261   __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));    \
262   /* Restore the previous rounding mode.  */                              \
263   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
264                       : "dmi" (__ctrl_reg));                              \
265   return __result;                                                        \
266 }                                                                         \
267                                                                           \
268 __m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x))            \
269 {                                                                         \
270   float_type __result;                                                    \
271   unsigned long int __ctrl_reg;                                           \
272   __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));            \
273   /* Set rounding towards positive infinity.  */                          \
274   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
275                       : "dmi" (__ctrl_reg | 0x30));                       \
276   /* Convert X to an integer, using +Inf rounding.  */                    \
277   __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));    \
278   /* Restore the previous rounding mode.  */                              \
279   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
280                       : "dmi" (__ctrl_reg));                              \
281   return __result;                                                        \
282 }
283
284 __inline_functions(double,)
285 #if defined __USE_MISC || defined __USE_ISOC9X
286 __inline_functions(float,f)
287 __inline_functions(long double,l)
288 #endif
289 #undef __inline_functions
290
291 #ifdef __USE_MISC
292
293 # define __inline_functions(float_type, s)                                \
294 __m81_defun (int, __CONCAT(__isinf,s), (float_type __value))              \
295 {                                                                         \
296   /* There is no branch-condition for infinity,                           \
297      so we must extract and examine the condition codes manually.  */     \
298   unsigned long int __fpsr;                                               \
299   __asm("ftst%.x %1\n"                                                    \
300         "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));          \
301   return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0;        \
302 }                                                                         \
303                                                                           \
304 __m81_defun (int, __CONCAT(__finite,s), (float_type __value))             \
305 {                                                                         \
306   /* There is no branch-condition for infinity, so we must extract and    \
307      examine the condition codes manually.  */                            \
308   unsigned long int __fpsr;                                               \
309   __asm ("ftst%.x %1\n"                                                   \
310          "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));         \
311   return (__fpsr & (3 << 24)) == 0;                                       \
312 }                                                                         \
313                                                                           \
314 __m81_defun (float_type, __CONCAT(__scalbn,s),                            \
315              (float_type __x, int __n))                                   \
316 {                                                                         \
317   float_type __result;                                                    \
318   __asm ("fscale%.l %1, %0" : "=f" (__result) : "dmi" (__n), "0" (__x));  \
319   return __result;                                                        \
320 }
321
322 __inline_functions(double,)
323 __inline_functions(float,f)
324 __inline_functions(long double,l)
325 # undef __inline_functions
326
327 #endif /* Use misc.  */
328
329 #if defined __USE_MISC || defined __USE_XOPEN
330
331 # define __inline_functions(float_type, s)                                \
332 __m81_defun (int, __CONCAT(__isnan,s), (float_type __value))              \
333 {                                                                         \
334   char __result;                                                          \
335   __asm("ftst%.x %1\n"                                                    \
336         "fsun %0" : "=dm" (__result) : "f" (__value));                    \
337   return __result;                                                        \
338 }
339
340 __inline_functions(double,)
341 # ifdef __USE_MISC
342 __inline_functions(float,f)
343 __inline_functions(long double,l)
344 # endif
345 # undef __inline_functions
346
347 #endif
348
349 #ifdef __USE_ISOC9X
350
351 # define __inline_functions(float_type, s)                                \
352 __m81_defun (int, __CONCAT(__signbit,s), (float_type __value))            \
353 {                                                                         \
354   /* There is no branch-condition for the sign bit, so we must extract    \
355      and examine the condition codes manually.  */                        \
356   unsigned long int __fpsr;                                               \
357   __asm ("ftst%.x %1\n"                                                   \
358          "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));         \
359   return (__fpsr >> 27) & 1;                                              \
360 }                                                                         \
361                                                                           \
362 __m81_defun (float_type, __CONCAT(__scalbln,s),                           \
363              (float_type __x, long int __n))                              \
364 {                                                                         \
365   return __CONCAT(__scalbn,s) (__x, __n);                                 \
366 }                                                                         \
367                                                                           \
368 __m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x))       \
369 {                                                                         \
370   float_type __result;                                                    \
371   unsigned long int __ctrl_reg;                                           \
372   __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));            \
373   /* Temporarily disable the inexact exception.  */                       \
374   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
375                       : "dmi" (__ctrl_reg & ~0x200));                     \
376   __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));    \
377   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
378                       : "dmi" (__ctrl_reg));                              \
379   return __result;                                                        \
380 }                                                                         \
381                                                                           \
382 __m81_defun (long int, __CONCAT(__lrint,s), (float_type __x))             \
383 {                                                                         \
384   long int __result;                                                      \
385   __asm ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x));               \
386   return __result;                                                        \
387 }                                                                         \
388                                                                           \
389 __m81_inline float_type                                                   \
390 __m81_u(__CONCAT(__fma,s))(float_type __x, float_type __y,                \
391                            float_type __z)                                \
392 {                                                                         \
393   return (__x * __y) + __z;                                               \
394 }
395
396 __inline_functions (double,)
397 __inline_functions (float,f)
398 __inline_functions (long double,l)
399 # undef __inline_functions
400
401 #endif /* Use ISO C9x */
402
403 #ifdef __USE_GNU
404
405 # define __inline_functions(float_type, s)                              \
406 __m81_inline void                                                       \
407 __m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx,       \
408                               float_type *__cosx)                       \
409 {                                                                       \
410   __asm ("fsincos%.x %2,%1:%0"                                          \
411          : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x));                 \
412 }
413
414 __inline_functions (double,)
415 __inline_functions (float,f)
416 __inline_functions (long double,l)
417 # undef __inline_functions
418
419 #endif
420
421 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
422
423 /* Define inline versions of the user visible functions.  */
424
425 /* Note that there must be no whitespace before the argument passed for
426    NAME, to make token pasting work correctly with -traditional.  */
427 # define __inline_forward_c(rettype, name, args1, args2)        \
428 extern __inline rettype __attribute__((__const__))      \
429 name args1                                              \
430 {                                                       \
431   return __CONCAT(__,name) args2;                       \
432 }
433
434 # define __inline_forward(rettype, name, args1, args2)  \
435 extern __inline rettype name args1                      \
436 {                                                       \
437   return __CONCAT(__,name) args2;                       \
438 }
439
440 __inline_forward(double,frexp, (double __value, int *__expptr),
441                  (__value, __expptr))
442 __inline_forward_c(double,floor, (double __x), (__x))
443 __inline_forward_c(double,ceil, (double __x), (__x))
444 # ifdef __USE_MISC
445 __inline_forward_c(int,isinf, (double __value), (__value))
446 __inline_forward_c(int,finite, (double __value), (__value))
447 __inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n))
448 __inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n))
449 # endif
450 # if defined __USE_MISC || defined __USE_XOPEN
451 #  ifndef __USE_ISOC9X /* Conflict with macro of same name.  */
452 __inline_forward_c(int,isnan, (double __value), (__value))
453 #  endif
454 # endif
455 # ifdef __USE_ISOC9X
456 __inline_forward_c(double,nearbyint, (double __value), (__value))
457 __inline_forward_c(long int,lrint, (double __value), (__value))
458 __inline_forward_c(double,fma, (double __x, double __y, double __z),
459                    (__x, __y, __z))
460 # endif
461 # ifdef __USE_GNU
462 __inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
463                  (__x, __sinx, __cosx))
464 # endif
465
466 # if defined __USE_MISC || defined __USE_ISOC9X
467
468 __inline_forward(float,frexpf, (float __value, int *__expptr),
469                  (__value, __expptr))
470 __inline_forward_c(float,floorf, (float __x), (__x))
471 __inline_forward_c(float,ceilf, (float __x), (__x))
472 #  ifdef __USE_MISC
473 __inline_forward_c(int,isinff, (float __value), (__value))
474 __inline_forward_c(int,finitef, (float __value), (__value))
475 __inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n))
476 __inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n))
477 __inline_forward_c(int,isnanf, (float __value), (__value))
478 #  endif
479 # ifdef __USE_ISOC9X
480 __inline_forward_c(float,nearbyintf, (float __value), (__value))
481 __inline_forward_c(long int,lrintf, (float __value), (__value))
482 __inline_forward_c(float,fmaf, (float __x, float __y, float __z),
483                    (__x, __y, __z))
484 # endif
485 # ifdef __USE_GNU
486 __inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
487                  (__x, __sinx, __cosx))
488 # endif
489
490 __inline_forward(long double,frexpl, (long double __value, int *__expptr),
491                  (__value, __expptr))
492 __inline_forward_c(long double,floorl, (long double __x), (__x))
493 __inline_forward_c(long double,ceill, (long double __x), (__x))
494 # ifdef __USE_MISC
495 __inline_forward_c(int,isinfl, (long double __value), (__value))
496 __inline_forward_c(int,finitel, (long double __value), (__value))
497 __inline_forward_c(long double,scalbnl, (long double __x, int __n), (__x, __n))
498 __inline_forward_c(long double,scalblnl, (long double __x, long int __n),
499                    (__x, __n))
500 __inline_forward_c(int,isnanl, (long double __value), (__value))
501 # endif
502 # ifdef __USE_ISOC9X
503 __inline_forward_c(long double,nearbyintl, (long double __value), (__value))
504 __inline_forward_c(long int,lrintl, (long double __value), (__value))
505 __inline_forward_c(long double,fmal,
506                    (long double __x, long double __y, long double __z),
507                    (__x, __y, __z))
508 # endif
509 # ifdef __USE_GNU
510 __inline_forward(void,sincosl,
511                  (long double __x, long double *__sinx, long double *__cosx),
512                  (__x, __sinx, __cosx))
513 # endif
514
515 #endif /* Use misc or ISO C9X */
516
517 #undef __inline_forward
518 #undef __inline_forward_c
519
520 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
521
522 #endif
523 #endif  /* GCC.  */