Add Changelog ...
[glibc.git] / sysdeps / m68k / m680x0 / fpu / bits / mathinline.h
blobffcc39edfdcf88c52b88d1a4f7f9589b3c25c403
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, 2008, 2010, 2012
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, see
18 <http://www.gnu.org/licenses/>. */
20 #ifndef _MATH_H
21 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
22 #endif
24 #ifndef __extern_inline
25 # define __MATH_INLINE __inline
26 #else
27 # define __MATH_INLINE __extern_inline
28 #endif
30 #ifdef __GNUC__
32 #ifdef __USE_ISOC99
33 /* GCC 3.1 and up have builtins that actually can be used. */
34 # if !__GNUC_PREREQ (3,1)
35 /* ISO C99 defines some macros to perform unordered comparisons. The
36 m68k FPU supports this with special opcodes and we should use them.
37 These must not be inline functions since we have to be able to handle
38 all floating-point types. */
39 # undef isgreater
40 # undef isgreaterequal
41 # undef isless
42 # undef islessequal
43 # undef islessgreater
44 # undef isunordered
45 # define isgreater(x, y) \
46 __extension__ \
47 ({ char __result; \
48 __asm__ ("fcmp%.x %2,%1; fsogt %0" \
49 : "=dm" (__result) : "f" (x), "f" (y)); \
50 __result != 0; })
52 # define isgreaterequal(x, y) \
53 __extension__ \
54 ({ char __result; \
55 __asm__ ("fcmp%.x %2,%1; fsoge %0" \
56 : "=dm" (__result) : "f" (x), "f" (y)); \
57 __result != 0; })
59 # define isless(x, y) \
60 __extension__ \
61 ({ char __result; \
62 __asm__ ("fcmp%.x %2,%1; fsolt %0" \
63 : "=dm" (__result) : "f" (x), "f" (y)); \
64 __result != 0; })
66 # define islessequal(x, y) \
67 __extension__ \
68 ({ char __result; \
69 __asm__ ("fcmp%.x %2,%1; fsole %0" \
70 : "=dm" (__result) : "f" (x), "f" (y)); \
71 __result != 0; })
73 # define islessgreater(x, y) \
74 __extension__ \
75 ({ char __result; \
76 __asm__ ("fcmp%.x %2,%1; fsogl %0" \
77 : "=dm" (__result) : "f" (x), "f" (y)); \
78 __result != 0; })
80 # define isunordered(x, y) \
81 __extension__ \
82 ({ char __result; \
83 __asm__ ("fcmp%.x %2,%1; fsun %0" \
84 : "=dm" (__result) : "f" (x), "f" (y)); \
85 __result != 0; })
86 # endif /* GCC 3.1 */
88 /* Test for negative number. Used in the signbit() macro. */
89 __MATH_INLINE int
90 __NTH (__signbitf (float __x))
92 __extension__ union { float __f; int __i; } __u = { __f: __x };
93 return __u.__i < 0;
95 __MATH_INLINE int
96 __NTH (__signbit (double __x))
98 __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
99 return __u.__i[0] < 0;
101 __MATH_INLINE int
102 __NTH (__signbitl (long double __x))
104 __extension__ union { long double __d; int __i[3]; } __u = { __d: __x };
105 return __u.__i[0] < 0;
107 #endif
110 #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
111 || defined __LIBC_INTERNAL_MATH_INLINES
113 #ifdef __LIBC_INTERNAL_MATH_INLINES
114 /* This is used when defining the functions themselves. Define them with
115 __ names, and with `static inline' instead of `extern inline' so the
116 bodies will always be used, never an external function call. */
117 # define __m81_u(x) __CONCAT(__,x)
118 # define __m81_inline static __inline
119 #else
120 # define __m81_u(x) x
121 # define __m81_inline __MATH_INLINE
122 # define __M81_MATH_INLINES 1
123 #endif
125 /* Define a const math function. */
126 #define __m81_defun(rettype, func, args) \
127 __m81_inline rettype __attribute__((__const__)) \
128 __NTH (__m81_u(func) args)
130 /* Define the three variants of a math function that has a direct
131 implementation in the m68k fpu. FUNC is the name for C (which will be
132 suffixed with f and l for the float and long double version, resp). OP
133 is the name of the fpu operation (without leading f). */
135 #if defined __USE_MISC || defined __USE_ISOC99
136 # define __inline_mathop(func, op) \
137 __inline_mathop1(double, func, op) \
138 __inline_mathop1(float, __CONCAT(func,f), op) \
139 __inline_mathop1(long double, __CONCAT(func,l), op)
140 #else
141 # define __inline_mathop(func, op) \
142 __inline_mathop1(double, func, op)
143 #endif
145 #define __inline_mathop1(float_type,func, op) \
146 __m81_defun (float_type, func, (float_type __mathop_x)) \
148 float_type __result; \
149 __asm __volatile__ ("f" __STRING(op) "%.x %1, %0" \
150 : "=f" (__result) : "f" (__mathop_x)); \
151 return __result; \
154 __inline_mathop(__atan, atan)
155 __inline_mathop(__cos, cos)
156 __inline_mathop(__sin, sin)
157 __inline_mathop(__tan, tan)
158 __inline_mathop(__tanh, tanh)
159 __inline_mathop(__fabs, abs)
161 #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
162 __inline_mathop(__rint, int)
163 __inline_mathop(__expm1, etoxm1)
164 __inline_mathop(__log1p, lognp1)
165 #endif
167 #ifdef __USE_MISC
168 __inline_mathop(__significand, getman)
169 #endif
171 #ifdef __USE_ISOC99
172 __inline_mathop(__trunc, intrz)
173 #endif
175 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
177 __inline_mathop(atan, atan)
178 __inline_mathop(tanh, tanh)
180 # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
181 __inline_mathop(rint, int)
182 __inline_mathop(log1p, lognp1)
183 # endif
185 # ifdef __USE_MISC
186 __inline_mathop(significand, getman)
187 # endif
189 # ifdef __USE_ISOC99
190 __inline_mathop(trunc, intrz)
191 # endif
193 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
195 /* This macro contains the definition for the rest of the inline
196 functions, using FLOAT_TYPE as the domain type and S as the suffix
197 for the function names. */
199 #define __inline_functions(float_type, s) \
200 __m81_defun (float_type, __CONCAT(__floor,s), (float_type __x)) \
202 float_type __result; \
203 unsigned long int __ctrl_reg; \
204 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
205 /* Set rounding towards negative infinity. */ \
206 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
207 : "dmi" ((__ctrl_reg & ~0x10) | 0x20)); \
208 /* Convert X to an integer, using -Inf rounding. */ \
209 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
210 /* Restore the previous rounding mode. */ \
211 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
212 : "dmi" (__ctrl_reg)); \
213 return __result; \
216 __m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x)) \
218 float_type __result; \
219 unsigned long int __ctrl_reg; \
220 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
221 /* Set rounding towards positive infinity. */ \
222 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
223 : "dmi" (__ctrl_reg | 0x30)); \
224 /* Convert X to an integer, using +Inf rounding. */ \
225 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
226 /* Restore the previous rounding mode. */ \
227 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
228 : "dmi" (__ctrl_reg)); \
229 return __result; \
232 __inline_functions(double,)
233 #if defined __USE_MISC || defined __USE_ISOC99
234 __inline_functions(float,f)
235 __inline_functions(long double,l)
236 #endif
237 #undef __inline_functions
239 #ifdef __USE_MISC
241 # define __inline_functions(float_type, s) \
242 __m81_defun (int, __CONCAT(__isinf,s), (float_type __value)) \
244 /* There is no branch-condition for infinity, \
245 so we must extract and examine the condition codes manually. */ \
246 unsigned long int __fpsr; \
247 __asm ("ftst%.x %1\n" \
248 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
249 return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0; \
252 __m81_defun (int, __CONCAT(__finite,s), (float_type __value)) \
254 /* There is no branch-condition for infinity, so we must extract and \
255 examine the condition codes manually. */ \
256 unsigned long int __fpsr; \
257 __asm ("ftst%.x %1\n" \
258 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
259 return (__fpsr & (3 << 24)) == 0; \
262 __m81_defun (float_type, __CONCAT(__scalbn,s), \
263 (float_type __x, int __n)) \
265 float_type __result; \
266 __asm __volatile__ ("fscale%.l %1, %0" : "=f" (__result) \
267 : "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)) \
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 (float_type, __CONCAT(__scalbln,s), \
302 (float_type __x, long int __n)) \
304 return __CONCAT(__scalbn,s) (__x, __n); \
307 __m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x)) \
309 float_type __result; \
310 unsigned long int __ctrl_reg; \
311 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
312 /* Temporarily disable the inexact exception. */ \
313 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
314 : "dmi" (__ctrl_reg & ~0x200)); \
315 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
316 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
317 : "dmi" (__ctrl_reg)); \
318 return __result; \
321 __m81_defun (long int, __CONCAT(__lrint,s), (float_type __x)) \
323 long int __result; \
324 __asm __volatile__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \
325 return __result; \
328 __inline_functions (double,)
329 __inline_functions (float,f)
330 __inline_functions (long double,l)
331 # undef __inline_functions
333 #endif /* Use ISO C9x */
335 #ifdef __USE_GNU
337 # define __inline_functions(float_type, s) \
338 __m81_inline void \
339 __NTH (__m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx, \
340 float_type *__cosx)) \
342 __asm __volatile__ ("fsincos%.x %2,%1:%0" \
343 : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x)); \
346 __inline_functions (double,)
347 __inline_functions (float,f)
348 __inline_functions (long double,l)
349 # undef __inline_functions
351 #endif
353 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
355 /* Define inline versions of the user visible functions. */
357 /* Note that there must be no whitespace before the argument passed for
358 NAME, to make token pasting work correctly with -traditional. */
359 # define __inline_forward_c(rettype, name, args1, args2) \
360 __MATH_INLINE rettype __attribute__((__const__)) \
361 __NTH (name args1) \
363 return __CONCAT(__,name) args2; \
366 # define __inline_forward(rettype, name, args1, args2) \
367 __MATH_INLINE rettype __NTH (name args1) \
369 return __CONCAT(__,name) args2; \
372 __inline_forward_c(double,floor, (double __x), (__x))
373 __inline_forward_c(double,ceil, (double __x), (__x))
374 # ifdef __USE_MISC
375 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
376 __inline_forward_c(int,isinf, (double __value), (__value))
377 # endif
378 __inline_forward_c(int,finite, (double __value), (__value))
379 __inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n))
380 # endif
381 # if defined __USE_MISC || defined __USE_XOPEN
382 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
383 __inline_forward_c(int,isnan, (double __value), (__value))
384 # endif
385 # endif
386 # ifdef __USE_ISOC99
387 __inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n))
388 __inline_forward_c(double,nearbyint, (double __value), (__value))
389 __inline_forward_c(long int,lrint, (double __value), (__value))
390 # endif
391 # ifdef __USE_GNU
392 __inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
393 (__x, __sinx, __cosx))
394 # endif
396 # if defined __USE_MISC || defined __USE_ISOC99
398 __inline_forward_c(float,floorf, (float __x), (__x))
399 __inline_forward_c(float,ceilf, (float __x), (__x))
400 # ifdef __USE_MISC
401 __inline_forward_c(int,isinff, (float __value), (__value))
402 __inline_forward_c(int,finitef, (float __value), (__value))
403 __inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n))
404 __inline_forward_c(int,isnanf, (float __value), (__value))
405 # endif
406 # ifdef __USE_ISOC99
407 __inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n))
408 __inline_forward_c(float,nearbyintf, (float __value), (__value))
409 __inline_forward_c(long int,lrintf, (float __value), (__value))
410 # endif
411 # ifdef __USE_GNU
412 __inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
413 (__x, __sinx, __cosx))
414 # endif
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 # endif
430 # ifdef __USE_GNU
431 __inline_forward(void,sincosl,
432 (long double __x, long double *__sinx, long double *__cosx),
433 (__x, __sinx, __cosx))
434 # endif
436 #endif /* Use misc or ISO C99 */
438 #undef __inline_forward
439 #undef __inline_forward_c
441 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
443 #endif
444 #endif /* GCC. */