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
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. */
31 # undef isgreaterequal
36 # define isgreater(x, y) \
39 __asm__ ("fcmp%.x %2,%1; fsogt %0" \
40 : "=dm" (__result) : "f" (x), "f" (y)); \
43 # define isgreaterequal(x, y) \
46 __asm__ ("fcmp%.x %2,%1; fsoge %0" \
47 : "=dm" (__result) : "f" (x), "f" (y)); \
50 # define isless(x, y) \
53 __asm__ ("fcmp%.x %2,%1; fsolt %0" \
54 : "=dm" (__result) : "f" (x), "f" (y)); \
57 # define islessequal(x, y) \
60 __asm__ ("fcmp%.x %2,%1; fsole %0" \
61 : "=dm" (__result) : "f" (x), "f" (y)); \
64 # define islessgreater(x, y) \
67 __asm__ ("fcmp%.x %2,%1; fsogl %0" \
68 : "=dm" (__result) : "f" (x), "f" (y)); \
71 # define isunordered(x, y) \
74 __asm__ ("fcmp%.x %2,%1; fsun %0" \
75 : "=dm" (__result) : "f" (x), "f" (y)); \
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
93 # define __m81_inline __inline
95 # define __m81_inline extern __inline
97 # define __M81_MATH_INLINES 1
100 /* Define a const math function. */
101 #define __m81_defun(rettype, func, args) \
102 __m81_inline rettype __attribute__((__const__)) \
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)
116 # define __inline_mathop(func, op) \
117 __inline_mathop1(double, func, op)
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));\
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
)
142 __inline_mathop(__significand
, getman
)
146 __inline_mathop(__trunc
, intrz
)
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
)
164 __inline_mathop(significand
, getman
)
168 __inline_mathop(trunc
, intrz
)
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)); \
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)); \
210 __inline_functions(double,)
211 #if defined __USE_MISC || defined __USE_ISOC99
212 __inline_functions(float,f
)
213 __inline_functions(long double,l
)
215 #undef __inline_functions
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)); \
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)) \
261 __asm("ftst%.x %1\n" \
262 "fsun %0" : "=dm" (__result) : "f" (__value)); \
266 __inline_functions(double,)
268 __inline_functions(float,f
)
269 __inline_functions(long double,l
)
271 # undef __inline_functions
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)); \
308 __m81_defun (long int, __CONCAT(__lrint,s), (float_type __x)) \
311 __asm ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \
315 __m81_inline float_type \
316 __m81_u(__CONCAT(__fma,s))(float_type __x, float_type __y, \
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 */
331 # define __inline_functions(float_type, s) \
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
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__)) \
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
))
369 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
370 __inline_forward_c(int,isinf
, (double __value
), (__value
))
372 __inline_forward_c(int,finite
, (double __value
), (__value
))
373 __inline_forward_c(double,scalbn
, (double __x
, int __n
), (__x
, __n
))
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
))
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
),
388 __inline_forward(void,sincos
, (double __x
, double *__sinx
, double *__cosx
),
389 (__x
, __sinx
, __cosx
))
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
))
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
))
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
),
410 __inline_forward(void,sincosf
, (float __x
, float *__sinx
, float *__cosx
),
411 (__x
, __sinx
, __cosx
))
414 __inline_forward_c(long double,floorl
, (long double __x
), (__x
))
415 __inline_forward_c(long double,ceill
, (long double __x
), (__x
))
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
))
423 __inline_forward_c(long double,scalblnl
, (long double __x
, long int __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
),
432 __inline_forward(void,sincosl
,
433 (long double __x
, long double *__sinx
, long double *__cosx
),
434 (__x
, __sinx
, __cosx
))
437 #endif /* Use misc or ISO C99 */
439 #undef __inline_forward
440 #undef __inline_forward_c
442 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */