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