* sysdeps/m68k/fpu/bits/mathinline.h (isgreater, isgreaterequal)
[glibc.git] / sysdeps / m68k / fpu / bits / mathinline.h
blob4b1bfeaf130a9e3f67ccf0aec31e3c69fbc2c5eb
1 /* Definitions of inline math functions implemented by the m68881/2.
2 Copyright (C) 1991,92,93,94,96,97,98,99,2000,2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #ifdef __GNUC__
22 #ifdef __USE_ISOC99
24 # if __GNUC_PREREQ (3,1)
25 /* GCC 3.1 and up have builtins that actually can be used. */
26 # define isgreater(x, y) __builtin_isgreater (x, y)
27 # define isgreaterequal(x, y) __builtin_isgreaterequal (x, y)
28 # define isless(x, y) __builtin_isless (x, y)
29 # define islessequal(x, y) __builtin_islessequal (x, y)
30 # define islessgreater(x, y) __builtin_islessgreater (x, y)
31 # define isunordered(x, y) __builtin_isunordered (x, y)
32 # else
33 /* ISO C99 defines some macros to perform unordered comparisons. The
34 m68k 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 # define isgreater(x, y) \
38 __extension__ \
39 ({ char __result; \
40 __asm__ ("fcmp%.x %2,%1; fsogt %0" \
41 : "=dm" (__result) : "f" (x), "f" (y)); \
42 __result != 0; })
44 # define isgreaterequal(x, y) \
45 __extension__ \
46 ({ char __result; \
47 __asm__ ("fcmp%.x %2,%1; fsoge %0" \
48 : "=dm" (__result) : "f" (x), "f" (y)); \
49 __result != 0; })
51 # define isless(x, y) \
52 __extension__ \
53 ({ char __result; \
54 __asm__ ("fcmp%.x %2,%1; fsolt %0" \
55 : "=dm" (__result) : "f" (x), "f" (y)); \
56 __result != 0; })
58 # define islessequal(x, y) \
59 __extension__ \
60 ({ char __result; \
61 __asm__ ("fcmp%.x %2,%1; fsole %0" \
62 : "=dm" (__result) : "f" (x), "f" (y)); \
63 __result != 0; })
65 # define islessgreater(x, y) \
66 __extension__ \
67 ({ char __result; \
68 __asm__ ("fcmp%.x %2,%1; fsogl %0" \
69 : "=dm" (__result) : "f" (x), "f" (y)); \
70 __result != 0; })
72 # define isunordered(x, y) \
73 __extension__ \
74 ({ char __result; \
75 __asm__ ("fcmp%.x %2,%1; fsun %0" \
76 : "=dm" (__result) : "f" (x), "f" (y)); \
77 __result != 0; })
78 # endif /* GCC 3.1 */
79 #endif
82 #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
83 || defined __LIBC_INTERNAL_MATH_INLINES
85 #ifdef __LIBC_INTERNAL_MATH_INLINES
86 /* This is used when defining the functions themselves. Define them with
87 __ names, and with `static inline' instead of `extern inline' so the
88 bodies will always be used, never an external function call. */
89 # define __m81_u(x) __CONCAT(__,x)
90 # define __m81_inline static __inline
91 #else
92 # define __m81_u(x) x
93 # ifdef __cplusplus
94 # define __m81_inline __inline
95 # else
96 # define __m81_inline extern __inline
97 # endif
98 # define __M81_MATH_INLINES 1
99 #endif
101 /* Define a const math function. */
102 #define __m81_defun(rettype, func, args) \
103 __m81_inline rettype __attribute__((__const__)) \
104 __m81_u(func) args
106 /* Define the three variants of a math function that has a direct
107 implementation in the m68k fpu. FUNC is the name for C (which will be
108 suffixed with f and l for the float and long double version, resp). OP
109 is the name of the fpu operation (without leading f). */
111 #if defined __USE_MISC || defined __USE_ISOC99
112 # define __inline_mathop(func, op) \
113 __inline_mathop1(double, func, op) \
114 __inline_mathop1(float, __CONCAT(func,f), op) \
115 __inline_mathop1(long double, __CONCAT(func,l), op)
116 #else
117 # define __inline_mathop(func, op) \
118 __inline_mathop1(double, func, op)
119 #endif
121 #define __inline_mathop1(float_type,func, op) \
122 __m81_defun (float_type, func, (float_type __mathop_x)) __THROW \
124 float_type __result; \
125 __asm("f" __STRING(op) "%.x %1, %0" : "=f" (__result) : "f" (__mathop_x));\
126 return __result; \
129 __inline_mathop(__atan, atan)
130 __inline_mathop(__cos, cos)
131 __inline_mathop(__sin, sin)
132 __inline_mathop(__tan, tan)
133 __inline_mathop(__tanh, tanh)
134 __inline_mathop(__fabs, abs)
136 #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
137 __inline_mathop(__rint, int)
138 __inline_mathop(__expm1, etoxm1)
139 __inline_mathop(__log1p, lognp1)
140 #endif
142 #ifdef __USE_MISC
143 __inline_mathop(__significand, getman)
144 #endif
146 #ifdef __USE_ISOC99
147 __inline_mathop(__trunc, intrz)
148 #endif
150 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
152 __inline_mathop(atan, atan)
153 __inline_mathop(cos, cos)
154 __inline_mathop(sin, sin)
155 __inline_mathop(tan, tan)
156 __inline_mathop(tanh, tanh)
158 # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
159 __inline_mathop(rint, int)
160 __inline_mathop(expm1, etoxm1)
161 __inline_mathop(log1p, lognp1)
162 # endif
164 # ifdef __USE_MISC
165 __inline_mathop(significand, getman)
166 # endif
168 # ifdef __USE_ISOC99
169 __inline_mathop(trunc, intrz)
170 # endif
172 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
174 /* This macro contains the definition for the rest of the inline
175 functions, using FLOAT_TYPE as the domain type and S as the suffix
176 for the function names. */
178 #define __inline_functions(float_type, s) \
179 __m81_inline float_type \
180 __m81_u(__CONCAT(__frexp,s))(float_type __value, int *__expptr) __THROW \
182 float_type __mantissa, __exponent; \
183 int __iexponent; \
184 unsigned long __fpsr; \
185 __asm("ftst%.x %1\n" \
186 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
187 if (__fpsr & (7 << 24)) \
189 /* Not finite or zero. */ \
190 *__expptr = 0; \
191 return __value; \
193 __asm("fgetexp%.x %1, %0" : "=f" (__exponent) : "f" (__value)); \
194 __iexponent = (int) __exponent + 1; \
195 *__expptr = __iexponent; \
196 __asm("fscale%.l %2, %0" : "=f" (__mantissa) \
197 : "0" (__value), "dmi" (-__iexponent)); \
198 return __mantissa; \
201 __m81_defun (float_type, __CONCAT(__floor,s), (float_type __x)) __THROW \
203 float_type __result; \
204 unsigned long int __ctrl_reg; \
205 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
206 /* Set rounding towards negative infinity. */ \
207 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
208 : "dmi" ((__ctrl_reg & ~0x10) | 0x20)); \
209 /* Convert X to an integer, using -Inf rounding. */ \
210 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
211 /* Restore the previous rounding mode. */ \
212 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
213 : "dmi" (__ctrl_reg)); \
214 return __result; \
217 __m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x)) __THROW \
219 float_type __result; \
220 unsigned long int __ctrl_reg; \
221 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
222 /* Set rounding towards positive infinity. */ \
223 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
224 : "dmi" (__ctrl_reg | 0x30)); \
225 /* Convert X to an integer, using +Inf rounding. */ \
226 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
227 /* Restore the previous rounding mode. */ \
228 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
229 : "dmi" (__ctrl_reg)); \
230 return __result; \
233 __inline_functions(double,)
234 #if defined __USE_MISC || defined __USE_ISOC99
235 __inline_functions(float,f)
236 __inline_functions(long double,l)
237 #endif
238 #undef __inline_functions
240 #ifdef __USE_MISC
242 # define __inline_functions(float_type, s) \
243 __m81_defun (int, __CONCAT(__isinf,s), (float_type __value)) __THROW \
245 /* There is no branch-condition for infinity, \
246 so we must extract and examine the condition codes manually. */ \
247 unsigned long int __fpsr; \
248 __asm("ftst%.x %1\n" \
249 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
250 return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0; \
253 __m81_defun (int, __CONCAT(__finite,s), (float_type __value)) __THROW \
255 /* There is no branch-condition for infinity, so we must extract and \
256 examine the condition codes manually. */ \
257 unsigned long int __fpsr; \
258 __asm ("ftst%.x %1\n" \
259 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
260 return (__fpsr & (3 << 24)) == 0; \
263 __m81_defun (float_type, __CONCAT(__scalbn,s), \
264 (float_type __x, int __n)) __THROW \
266 float_type __result; \
267 __asm ("fscale%.l %1, %0" : "=f" (__result) : "dmi" (__n), "0" (__x)); \
268 return __result; \
271 __inline_functions(double,)
272 __inline_functions(float,f)
273 __inline_functions(long double,l)
274 # undef __inline_functions
276 #endif /* Use misc. */
278 #if defined __USE_MISC || defined __USE_XOPEN
280 # define __inline_functions(float_type, s) \
281 __m81_defun (int, __CONCAT(__isnan,s), (float_type __value)) __THROW \
283 char __result; \
284 __asm("ftst%.x %1\n" \
285 "fsun %0" : "=dm" (__result) : "f" (__value)); \
286 return __result; \
289 __inline_functions(double,)
290 # ifdef __USE_MISC
291 __inline_functions(float,f)
292 __inline_functions(long double,l)
293 # endif
294 # undef __inline_functions
296 #endif
298 #ifdef __USE_ISOC99
300 # define __inline_functions(float_type, s) \
301 __m81_defun (int, __CONCAT(__signbit,s), (float_type __value)) __THROW \
303 /* There is no branch-condition for the sign bit, so we must extract \
304 and examine the condition codes manually. */ \
305 unsigned long int __fpsr; \
306 __asm ("ftst%.x %1\n" \
307 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
308 return (__fpsr >> 27) & 1; \
311 __m81_defun (float_type, __CONCAT(__scalbln,s), \
312 (float_type __x, long int __n)) __THROW \
314 return __CONCAT(__scalbn,s) (__x, __n); \
317 __m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x)) __THROW \
319 float_type __result; \
320 unsigned long int __ctrl_reg; \
321 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
322 /* Temporarily disable the inexact exception. */ \
323 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
324 : "dmi" (__ctrl_reg & ~0x200)); \
325 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
326 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
327 : "dmi" (__ctrl_reg)); \
328 return __result; \
331 __m81_defun (long int, __CONCAT(__lrint,s), (float_type __x)) __THROW \
333 long int __result; \
334 __asm ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \
335 return __result; \
338 __m81_inline float_type \
339 __m81_u(__CONCAT(__fma,s))(float_type __x, float_type __y, \
340 float_type __z) __THROW \
342 return (__x * __y) + __z; \
345 __inline_functions (double,)
346 __inline_functions (float,f)
347 __inline_functions (long double,l)
348 # undef __inline_functions
350 #endif /* Use ISO C9x */
352 #ifdef __USE_GNU
354 # define __inline_functions(float_type, s) \
355 __m81_inline void \
356 __m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx, \
357 float_type *__cosx) __THROW \
359 __asm ("fsincos%.x %2,%1:%0" \
360 : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x)); \
363 __inline_functions (double,)
364 __inline_functions (float,f)
365 __inline_functions (long double,l)
366 # undef __inline_functions
368 #endif
370 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
372 /* Define inline versions of the user visible functions. */
374 /* Note that there must be no whitespace before the argument passed for
375 NAME, to make token pasting work correctly with -traditional. */
376 # define __inline_forward_c(rettype, name, args1, args2) \
377 extern __inline rettype __attribute__((__const__)) \
378 name args1 __THROW \
380 return __CONCAT(__,name) args2; \
383 # define __inline_forward(rettype, name, args1, args2) \
384 extern __inline rettype name args1 __THROW \
386 return __CONCAT(__,name) args2; \
389 __inline_forward(double,frexp, (double __value, int *__expptr),
390 (__value, __expptr))
391 __inline_forward_c(double,floor, (double __x), (__x))
392 __inline_forward_c(double,ceil, (double __x), (__x))
393 # ifdef __USE_MISC
394 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
395 __inline_forward_c(int,isinf, (double __value), (__value))
396 # endif
397 __inline_forward_c(int,finite, (double __value), (__value))
398 __inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n))
399 # endif
400 # if defined __USE_MISC || defined __USE_XOPEN
401 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
402 __inline_forward_c(int,isnan, (double __value), (__value))
403 # endif
404 # endif
405 # ifdef __USE_ISOC99
406 __inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n))
407 __inline_forward_c(double,nearbyint, (double __value), (__value))
408 __inline_forward_c(long int,lrint, (double __value), (__value))
409 __inline_forward_c(double,fma, (double __x, double __y, double __z),
410 (__x, __y, __z))
411 # endif
412 # ifdef __USE_GNU
413 __inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
414 (__x, __sinx, __cosx))
415 # endif
417 # if defined __USE_MISC || defined __USE_ISOC99
419 __inline_forward(float,frexpf, (float __value, int *__expptr),
420 (__value, __expptr))
421 __inline_forward_c(float,floorf, (float __x), (__x))
422 __inline_forward_c(float,ceilf, (float __x), (__x))
423 # ifdef __USE_MISC
424 __inline_forward_c(int,isinff, (float __value), (__value))
425 __inline_forward_c(int,finitef, (float __value), (__value))
426 __inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n))
427 __inline_forward_c(int,isnanf, (float __value), (__value))
428 # endif
429 # ifdef __USE_ISOC99
430 __inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n))
431 __inline_forward_c(float,nearbyintf, (float __value), (__value))
432 __inline_forward_c(long int,lrintf, (float __value), (__value))
433 __inline_forward_c(float,fmaf, (float __x, float __y, float __z),
434 (__x, __y, __z))
435 # endif
436 # ifdef __USE_GNU
437 __inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
438 (__x, __sinx, __cosx))
439 # endif
441 __inline_forward(long double,frexpl, (long double __value, int *__expptr),
442 (__value, __expptr))
443 __inline_forward_c(long double,floorl, (long double __x), (__x))
444 __inline_forward_c(long double,ceill, (long double __x), (__x))
445 # ifdef __USE_MISC
446 __inline_forward_c(int,isinfl, (long double __value), (__value))
447 __inline_forward_c(int,finitel, (long double __value), (__value))
448 __inline_forward_c(long double,scalbnl, (long double __x, int __n), (__x, __n))
449 __inline_forward_c(int,isnanl, (long double __value), (__value))
450 # endif
451 # ifdef __USE_ISOC99
452 __inline_forward_c(long double,scalblnl, (long double __x, long int __n),
453 (__x, __n))
454 __inline_forward_c(long double,nearbyintl, (long double __value), (__value))
455 __inline_forward_c(long int,lrintl, (long double __value), (__value))
456 __inline_forward_c(long double,fmal,
457 (long double __x, long double __y, long double __z),
458 (__x, __y, __z))
459 # endif
460 # ifdef __USE_GNU
461 __inline_forward(void,sincosl,
462 (long double __x, long double *__sinx, long double *__cosx),
463 (__x, __sinx, __cosx))
464 # endif
466 #endif /* Use misc or ISO C99 */
468 #undef __inline_forward
469 #undef __inline_forward_c
471 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
473 #endif
474 #endif /* GCC. */