ec00b4b71147551862d8ef1e316de66fd8df978a
[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,98,99,2000,2002, 2003
3      Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
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 #ifdef  __GNUC__
22
23 #ifdef __USE_ISOC99
24
25 # if __GNUC_PREREQ (3,1)
26 /* GCC 3.1 and up have builtins that actually can be used.  */
27 #  define isgreater(x, y) __builtin_isgreater (x, y)
28 #  define isgreaterequal(x, y) __builtin_isgreaterequal (x, y)
29 #  define isless(x, y) __builtin_isless (x, y)
30 #  define islessequal(x, y) __builtin_islessequal (x, y)
31 #  define islessgreater(x, y) __builtin_islessgreater (x, y)
32 #  define isunordered(x, y) __builtin_isunordered (x, y)
33 # else
34 /* ISO C99 defines some macros to perform unordered comparisons.  The
35    m68k FPU supports this with special opcodes and we should use them.
36    These must not be inline functions since we have to be able to handle
37    all floating-point types.  */
38 #  define isgreater(x, y)                                       \
39    __extension__                                        \
40    ({ char __result;                                    \
41       __asm__ ("fcmp%.x %2,%1; fsogt %0"                \
42                : "=dm" (__result) : "f" (x), "f" (y));  \
43       __result != 0; })
44
45 #  define isgreaterequal(x, y)                          \
46    __extension__                                        \
47    ({ char __result;                                    \
48       __asm__ ("fcmp%.x %2,%1; fsoge %0"                \
49                : "=dm" (__result) : "f" (x), "f" (y));  \
50       __result != 0; })
51
52 #  define isless(x, y)                                  \
53    __extension__                                        \
54    ({ char __result;                                    \
55       __asm__ ("fcmp%.x %2,%1; fsolt %0"                \
56                : "=dm" (__result) : "f" (x), "f" (y));  \
57       __result != 0; })
58
59 #  define islessequal(x, y)                             \
60    __extension__                                        \
61    ({ char __result;                                    \
62       __asm__ ("fcmp%.x %2,%1; fsole %0"                \
63                : "=dm" (__result) : "f" (x), "f" (y));  \
64       __result != 0; })
65
66 #  define islessgreater(x, y)                           \
67    __extension__                                        \
68    ({ char __result;                                    \
69       __asm__ ("fcmp%.x %2,%1; fsogl %0"                \
70                : "=dm" (__result) : "f" (x), "f" (y));  \
71       __result != 0; })
72
73 #  define isunordered(x, y)                             \
74    __extension__                                        \
75    ({ char __result;                                    \
76       __asm__ ("fcmp%.x %2,%1; fsun %0"                 \
77                : "=dm" (__result) : "f" (x), "f" (y));  \
78       __result != 0; })
79 # endif /* GCC 3.1 */
80 #endif
81
82
83 #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
84     || defined __LIBC_INTERNAL_MATH_INLINES
85
86 #ifdef  __LIBC_INTERNAL_MATH_INLINES
87 /* This is used when defining the functions themselves.  Define them with
88    __ names, and with `static inline' instead of `extern inline' so the
89    bodies will always be used, never an external function call.  */
90 # define __m81_u(x)             __CONCAT(__,x)
91 # define __m81_inline           static __inline
92 #else
93 # define __m81_u(x)             x
94 # ifdef __cplusplus
95 #  define __m81_inline          __inline
96 # else
97 #  define __m81_inline          extern __inline
98 # endif
99 # define __M81_MATH_INLINES     1
100 #endif
101
102 /* Define a const math function.  */
103 #define __m81_defun(rettype, func, args)                                      \
104   __m81_inline rettype __attribute__((__const__))                             \
105   __m81_u(func) args
106
107 /* Define the three variants of a math function that has a direct
108    implementation in the m68k fpu.  FUNC is the name for C (which will be
109    suffixed with f and l for the float and long double version, resp).  OP
110    is the name of the fpu operation (without leading f).  */
111
112 #if defined __USE_MISC || defined __USE_ISOC99
113 # define __inline_mathop(func, op)                      \
114   __inline_mathop1(double, func, op)                    \
115   __inline_mathop1(float, __CONCAT(func,f), op)         \
116   __inline_mathop1(long double, __CONCAT(func,l), op)
117 #else
118 # define __inline_mathop(func, op)                      \
119   __inline_mathop1(double, func, op)
120 #endif
121
122 #define __inline_mathop1(float_type,func, op)                                 \
123   __m81_defun (float_type, func, (float_type __mathop_x)) __THROW             \
124   {                                                                           \
125     float_type __result;                                                      \
126     __asm("f" __STRING(op) "%.x %1, %0" : "=f" (__result) : "f" (__mathop_x));\
127     return __result;                                                          \
128   }
129
130 __inline_mathop(__atan, atan)
131 __inline_mathop(__cos, cos)
132 __inline_mathop(__sin, sin)
133 __inline_mathop(__tan, tan)
134 __inline_mathop(__tanh, tanh)
135 __inline_mathop(__fabs, abs)
136
137 #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
138 __inline_mathop(__rint, int)
139 __inline_mathop(__expm1, etoxm1)
140 __inline_mathop(__log1p, lognp1)
141 #endif
142
143 #ifdef __USE_MISC
144 __inline_mathop(__significand, getman)
145 #endif
146
147 #ifdef __USE_ISOC99
148 __inline_mathop(__trunc, intrz)
149 #endif
150
151 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
152
153 __inline_mathop(atan, atan)
154 __inline_mathop(cos, cos)
155 __inline_mathop(sin, sin)
156 __inline_mathop(tan, tan)
157 __inline_mathop(tanh, tanh)
158
159 # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
160 __inline_mathop(rint, int)
161 __inline_mathop(expm1, etoxm1)
162 __inline_mathop(log1p, lognp1)
163 # endif
164
165 # ifdef __USE_MISC
166 __inline_mathop(significand, getman)
167 # endif
168
169 # ifdef __USE_ISOC99
170 __inline_mathop(trunc, intrz)
171 # endif
172
173 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
174
175 /* This macro contains the definition for the rest of the inline
176    functions, using FLOAT_TYPE as the domain type and S as the suffix
177    for the function names.  */
178
179 #define __inline_functions(float_type, s)                                 \
180 __m81_defun (float_type, __CONCAT(__floor,s), (float_type __x)) __THROW   \
181 {                                                                         \
182   float_type __result;                                                    \
183   unsigned long int __ctrl_reg;                                           \
184   __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));            \
185   /* Set rounding towards negative infinity.  */                          \
186   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
187                       : "dmi" ((__ctrl_reg & ~0x10) | 0x20));             \
188   /* Convert X to an integer, using -Inf rounding.  */                    \
189   __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));    \
190   /* Restore the previous rounding mode.  */                              \
191   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
192                       : "dmi" (__ctrl_reg));                              \
193   return __result;                                                        \
194 }                                                                         \
195                                                                           \
196 __m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x)) __THROW    \
197 {                                                                         \
198   float_type __result;                                                    \
199   unsigned long int __ctrl_reg;                                           \
200   __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));            \
201   /* Set rounding towards positive infinity.  */                          \
202   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
203                       : "dmi" (__ctrl_reg | 0x30));                       \
204   /* Convert X to an integer, using +Inf rounding.  */                    \
205   __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));    \
206   /* Restore the previous rounding mode.  */                              \
207   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
208                       : "dmi" (__ctrl_reg));                              \
209   return __result;                                                        \
210 }
211
212 __inline_functions(double,)
213 #if defined __USE_MISC || defined __USE_ISOC99
214 __inline_functions(float,f)
215 __inline_functions(long double,l)
216 #endif
217 #undef __inline_functions
218
219 #ifdef __USE_MISC
220
221 # define __inline_functions(float_type, s)                                \
222 __m81_defun (int, __CONCAT(__isinf,s), (float_type __value)) __THROW      \
223 {                                                                         \
224   /* There is no branch-condition for infinity,                           \
225      so we must extract and examine the condition codes manually.  */     \
226   unsigned long int __fpsr;                                               \
227   __asm("ftst%.x %1\n"                                                    \
228         "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));          \
229   return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0;        \
230 }                                                                         \
231                                                                           \
232 __m81_defun (int, __CONCAT(__finite,s), (float_type __value)) __THROW     \
233 {                                                                         \
234   /* There is no branch-condition for infinity, so we must extract and    \
235      examine the condition codes manually.  */                            \
236   unsigned long int __fpsr;                                               \
237   __asm ("ftst%.x %1\n"                                                   \
238          "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));         \
239   return (__fpsr & (3 << 24)) == 0;                                       \
240 }                                                                         \
241                                                                           \
242 __m81_defun (float_type, __CONCAT(__scalbn,s),                            \
243              (float_type __x, int __n)) __THROW                           \
244 {                                                                         \
245   float_type __result;                                                    \
246   __asm ("fscale%.l %1, %0" : "=f" (__result) : "dmi" (__n), "0" (__x));  \
247   return __result;                                                        \
248 }
249
250 __inline_functions(double,)
251 __inline_functions(float,f)
252 __inline_functions(long double,l)
253 # undef __inline_functions
254
255 #endif /* Use misc.  */
256
257 #if defined __USE_MISC || defined __USE_XOPEN
258
259 # define __inline_functions(float_type, s)                                \
260 __m81_defun (int, __CONCAT(__isnan,s), (float_type __value)) __THROW      \
261 {                                                                         \
262   char __result;                                                          \
263   __asm("ftst%.x %1\n"                                                    \
264         "fsun %0" : "=dm" (__result) : "f" (__value));                    \
265   return __result;                                                        \
266 }
267
268 __inline_functions(double,)
269 # ifdef __USE_MISC
270 __inline_functions(float,f)
271 __inline_functions(long double,l)
272 # endif
273 # undef __inline_functions
274
275 #endif
276
277 #ifdef __USE_ISOC99
278
279 # define __inline_functions(float_type, s)                                \
280 __m81_defun (int, __CONCAT(__signbit,s), (float_type __value)) __THROW    \
281 {                                                                         \
282   /* There is no branch-condition for the sign bit, so we must extract    \
283      and examine the condition codes manually.  */                        \
284   unsigned long int __fpsr;                                               \
285   __asm ("ftst%.x %1\n"                                                   \
286          "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));         \
287   return (__fpsr >> 27) & 1;                                              \
288 }                                                                         \
289                                                                           \
290 __m81_defun (float_type, __CONCAT(__scalbln,s),                           \
291              (float_type __x, long int __n)) __THROW                      \
292 {                                                                         \
293   return __CONCAT(__scalbn,s) (__x, __n);                                 \
294 }                                                                         \
295                                                                           \
296 __m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x)) __THROW \
297 {                                                                         \
298   float_type __result;                                                    \
299   unsigned long int __ctrl_reg;                                           \
300   __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));            \
301   /* Temporarily disable the inexact exception.  */                       \
302   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
303                       : "dmi" (__ctrl_reg & ~0x200));                     \
304   __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));    \
305   __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */              \
306                       : "dmi" (__ctrl_reg));                              \
307   return __result;                                                        \
308 }                                                                         \
309                                                                           \
310 __m81_defun (long int, __CONCAT(__lrint,s), (float_type __x)) __THROW     \
311 {                                                                         \
312   long int __result;                                                      \
313   __asm ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x));               \
314   return __result;                                                        \
315 }                                                                         \
316                                                                           \
317 __m81_inline float_type                                                   \
318 __m81_u(__CONCAT(__fma,s))(float_type __x, float_type __y,                \
319                            float_type __z) __THROW                        \
320 {                                                                         \
321   return (__x * __y) + __z;                                               \
322 }
323
324 __inline_functions (double,)
325 __inline_functions (float,f)
326 __inline_functions (long double,l)
327 # undef __inline_functions
328
329 #endif /* Use ISO C9x */
330
331 #ifdef __USE_GNU
332
333 # define __inline_functions(float_type, s)                              \
334 __m81_inline void                                                       \
335 __m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx,       \
336                               float_type *__cosx) __THROW               \
337 {                                                                       \
338   __asm ("fsincos%.x %2,%1:%0"                                          \
339          : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x));                 \
340 }
341
342 __inline_functions (double,)
343 __inline_functions (float,f)
344 __inline_functions (long double,l)
345 # undef __inline_functions
346
347 #endif
348
349 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
350
351 /* Define inline versions of the user visible functions.  */
352
353 /* Note that there must be no whitespace before the argument passed for
354    NAME, to make token pasting work correctly with -traditional.  */
355 # define __inline_forward_c(rettype, name, args1, args2)        \
356 extern __inline rettype __attribute__((__const__))      \
357 name args1 __THROW                                      \
358 {                                                       \
359   return __CONCAT(__,name) args2;                       \
360 }
361
362 # define __inline_forward(rettype, name, args1, args2)  \
363 extern __inline rettype name args1 __THROW              \
364 {                                                       \
365   return __CONCAT(__,name) args2;                       \
366 }
367
368 __inline_forward_c(double,floor, (double __x), (__x))
369 __inline_forward_c(double,ceil, (double __x), (__x))
370 # ifdef __USE_MISC
371 #  ifndef __USE_ISOC99 /* Conflict with macro of same name.  */
372 __inline_forward_c(int,isinf, (double __value), (__value))
373 #  endif
374 __inline_forward_c(int,finite, (double __value), (__value))
375 __inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n))
376 # endif
377 # if defined __USE_MISC || defined __USE_XOPEN
378 #  ifndef __USE_ISOC99 /* Conflict with macro of same name.  */
379 __inline_forward_c(int,isnan, (double __value), (__value))
380 #  endif
381 # endif
382 # ifdef __USE_ISOC99
383 __inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n))
384 __inline_forward_c(double,nearbyint, (double __value), (__value))
385 __inline_forward_c(long int,lrint, (double __value), (__value))
386 __inline_forward_c(double,fma, (double __x, double __y, double __z),
387                    (__x, __y, __z))
388 # endif
389 # ifdef __USE_GNU
390 __inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
391                  (__x, __sinx, __cosx))
392 # endif
393
394 # if defined __USE_MISC || defined __USE_ISOC99
395
396 __inline_forward_c(float,floorf, (float __x), (__x))
397 __inline_forward_c(float,ceilf, (float __x), (__x))
398 #  ifdef __USE_MISC
399 __inline_forward_c(int,isinff, (float __value), (__value))
400 __inline_forward_c(int,finitef, (float __value), (__value))
401 __inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n))
402 __inline_forward_c(int,isnanf, (float __value), (__value))
403 #  endif
404 # ifdef __USE_ISOC99
405 __inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n))
406 __inline_forward_c(float,nearbyintf, (float __value), (__value))
407 __inline_forward_c(long int,lrintf, (float __value), (__value))
408 __inline_forward_c(float,fmaf, (float __x, float __y, float __z),
409                    (__x, __y, __z))
410 # endif
411 # ifdef __USE_GNU
412 __inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
413                  (__x, __sinx, __cosx))
414 # endif
415
416 __inline_forward_c(long double,floorl, (long double __x), (__x))
417 __inline_forward_c(long double,ceill, (long double __x), (__x))
418 # ifdef __USE_MISC
419 __inline_forward_c(int,isinfl, (long double __value), (__value))
420 __inline_forward_c(int,finitel, (long double __value), (__value))
421 __inline_forward_c(long double,scalbnl, (long double __x, int __n), (__x, __n))
422 __inline_forward_c(int,isnanl, (long double __value), (__value))
423 # endif
424 # ifdef __USE_ISOC99
425 __inline_forward_c(long double,scalblnl, (long double __x, long int __n),
426                    (__x, __n))
427 __inline_forward_c(long double,nearbyintl, (long double __value), (__value))
428 __inline_forward_c(long int,lrintl, (long double __value), (__value))
429 __inline_forward_c(long double,fmal,
430                    (long double __x, long double __y, long double __z),
431                    (__x, __y, __z))
432 # endif
433 # ifdef __USE_GNU
434 __inline_forward(void,sincosl,
435                  (long double __x, long double *__sinx, long double *__cosx),
436                  (__x, __sinx, __cosx))
437 # endif
438
439 #endif /* Use misc or ISO C99 */
440
441 #undef __inline_forward
442 #undef __inline_forward_c
443
444 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
445
446 #endif
447 #endif  /* GCC.  */