Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / m68k / m680x0 / fpu / bits / mathinline.h
blobe609eb5c1ba005e591418ca450d754411bb88ac4
1 /* Definitions of inline math functions implemented by the m68881/2.
2 Copyright (C) 1991-2014 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, see
17 <http://www.gnu.org/licenses/>. */
19 #ifndef _MATH_H
20 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
21 #endif
23 #ifndef __extern_inline
24 # define __MATH_INLINE __inline
25 #else
26 # define __MATH_INLINE __extern_inline
27 #endif
29 #ifdef __GNUC__
31 #ifdef __USE_ISOC99
32 /* GCC 3.1 and up have builtins that actually can be used. */
33 # if !__GNUC_PREREQ (3,1)
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 # undef isgreater
39 # undef isgreaterequal
40 # undef isless
41 # undef islessequal
42 # undef islessgreater
43 # undef isunordered
44 # define isgreater(x, y) \
45 __extension__ \
46 ({ char __result; \
47 __asm__ ("fcmp%.x %2,%1; fsogt %0" \
48 : "=dm" (__result) : "f" (x), "f" (y)); \
49 __result != 0; })
51 # define isgreaterequal(x, y) \
52 __extension__ \
53 ({ char __result; \
54 __asm__ ("fcmp%.x %2,%1; fsoge %0" \
55 : "=dm" (__result) : "f" (x), "f" (y)); \
56 __result != 0; })
58 # define isless(x, y) \
59 __extension__ \
60 ({ char __result; \
61 __asm__ ("fcmp%.x %2,%1; fsolt %0" \
62 : "=dm" (__result) : "f" (x), "f" (y)); \
63 __result != 0; })
65 # define islessequal(x, y) \
66 __extension__ \
67 ({ char __result; \
68 __asm__ ("fcmp%.x %2,%1; fsole %0" \
69 : "=dm" (__result) : "f" (x), "f" (y)); \
70 __result != 0; })
72 # define islessgreater(x, y) \
73 __extension__ \
74 ({ char __result; \
75 __asm__ ("fcmp%.x %2,%1; fsogl %0" \
76 : "=dm" (__result) : "f" (x), "f" (y)); \
77 __result != 0; })
79 # define isunordered(x, y) \
80 __extension__ \
81 ({ char __result; \
82 __asm__ ("fcmp%.x %2,%1; fsun %0" \
83 : "=dm" (__result) : "f" (x), "f" (y)); \
84 __result != 0; })
85 # endif /* GCC 3.1 */
87 /* Test for negative number. Used in the signbit() macro. */
88 __MATH_INLINE int
89 __NTH (__signbitf (float __x))
91 __extension__ union { float __f; int __i; } __u = { __f: __x };
92 return __u.__i < 0;
94 __MATH_INLINE int
95 __NTH (__signbit (double __x))
97 __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
98 return __u.__i[0] < 0;
100 __MATH_INLINE int
101 __NTH (__signbitl (long double __x))
103 __extension__ union { long double __d; int __i[3]; } __u = { __d: __x };
104 return __u.__i[0] < 0;
106 #endif
109 #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
110 || defined __LIBC_INTERNAL_MATH_INLINES
112 #ifdef __LIBC_INTERNAL_MATH_INLINES
113 /* This is used when defining the functions themselves. Define them with
114 __ names, and with `static inline' instead of `extern inline' so the
115 bodies will always be used, never an external function call. */
116 # define __m81_u(x) __CONCAT(__,x)
117 # define __m81_inline static __inline
118 #else
119 # define __m81_u(x) x
120 # define __m81_inline __MATH_INLINE
121 # define __M81_MATH_INLINES 1
122 #endif
124 /* Define a const math function. */
125 #define __m81_defun(rettype, func, args) \
126 __m81_inline rettype __attribute__((__const__)) \
127 __NTH (__m81_u(func) args)
129 /* Define the three variants of a math function that has a direct
130 implementation in the m68k fpu. FUNC is the name for C (which will be
131 suffixed with f and l for the float and long double version, resp). OP
132 is the name of the fpu operation (without leading f). */
134 #if defined __USE_MISC || defined __USE_ISOC99
135 # define __inline_mathop(func, op) \
136 __inline_mathop1(double, func, op) \
137 __inline_mathop1(float, __CONCAT(func,f), op) \
138 __inline_mathop1(long double, __CONCAT(func,l), op)
139 #else
140 # define __inline_mathop(func, op) \
141 __inline_mathop1(double, func, op)
142 #endif
144 #define __inline_mathop1(float_type,func, op) \
145 __m81_defun (float_type, func, (float_type __mathop_x)) \
147 float_type __result; \
148 __asm __volatile__ ("f" __STRING(op) "%.x %1, %0" \
149 : "=f" (__result) : "f" (__mathop_x)); \
150 return __result; \
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 __inline_mathop(__fabs, abs)
160 #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
161 __inline_mathop(__rint, int)
162 __inline_mathop(__expm1, etoxm1)
163 __inline_mathop(__log1p, lognp1)
164 #endif
166 #ifdef __USE_MISC
167 __inline_mathop(__significand, getman)
168 #endif
170 #ifdef __USE_ISOC99
171 __inline_mathop(__trunc, intrz)
172 #endif
174 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
176 __inline_mathop(atan, atan)
177 __inline_mathop(tanh, tanh)
179 # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
180 __inline_mathop(rint, int)
181 __inline_mathop(log1p, lognp1)
182 # endif
184 # ifdef __USE_MISC
185 __inline_mathop(significand, getman)
186 # endif
188 # ifdef __USE_ISOC99
189 __inline_mathop(trunc, intrz)
190 # endif
192 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
194 /* This macro contains the definition for the rest of the inline
195 functions, using FLOAT_TYPE as the domain type and S as the suffix
196 for the function names. */
198 #define __inline_functions(float_type, s) \
199 __m81_defun (float_type, __CONCAT(__floor,s), (float_type __x)) \
201 float_type __result; \
202 unsigned long int __ctrl_reg; \
203 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
204 /* Set rounding towards negative infinity. */ \
205 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
206 : "dmi" ((__ctrl_reg & ~0x10) | 0x20)); \
207 /* Convert X to an integer, using -Inf rounding. */ \
208 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
209 /* Restore the previous rounding mode. */ \
210 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
211 : "dmi" (__ctrl_reg)); \
212 return __result; \
215 __m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x)) \
217 float_type __result; \
218 unsigned long int __ctrl_reg; \
219 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
220 /* Set rounding towards positive infinity. */ \
221 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
222 : "dmi" (__ctrl_reg | 0x30)); \
223 /* Convert X to an integer, using +Inf rounding. */ \
224 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
225 /* Restore the previous rounding mode. */ \
226 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
227 : "dmi" (__ctrl_reg)); \
228 return __result; \
231 __inline_functions(double,)
232 #if defined __USE_MISC || defined __USE_ISOC99
233 __inline_functions(float,f)
234 __inline_functions(long double,l)
235 #endif
236 #undef __inline_functions
238 #ifdef __USE_MISC
240 # define __inline_functions(float_type, s) \
241 __m81_defun (int, __CONCAT(__isinf,s), (float_type __value)) \
243 /* There is no branch-condition for infinity, \
244 so we must extract and examine the condition codes manually. */ \
245 unsigned long int __fpsr; \
246 __asm ("ftst%.x %1\n" \
247 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
248 return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0; \
251 __m81_defun (int, __CONCAT(__finite,s), (float_type __value)) \
253 /* There is no branch-condition for infinity, so we must extract and \
254 examine the condition codes manually. */ \
255 unsigned long int __fpsr; \
256 __asm ("ftst%.x %1\n" \
257 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
258 return (__fpsr & (3 << 24)) == 0; \
261 __m81_defun (float_type, __CONCAT(__scalbn,s), \
262 (float_type __x, int __n)) \
264 float_type __result; \
265 __asm __volatile__ ("fscale%.l %1, %0" : "=f" (__result) \
266 : "dmi" (__n), "0" (__x)); \
267 return __result; \
270 __inline_functions(double,)
271 __inline_functions(float,f)
272 __inline_functions(long double,l)
273 # undef __inline_functions
275 #endif /* Use misc. */
277 #if defined __USE_MISC || defined __USE_XOPEN
279 # define __inline_functions(float_type, s) \
280 __m81_defun (int, __CONCAT(__isnan,s), (float_type __value)) \
282 char __result; \
283 __asm ("ftst%.x %1\n" \
284 "fsun %0" : "=dm" (__result) : "f" (__value)); \
285 return __result; \
288 __inline_functions(double,)
289 # ifdef __USE_MISC
290 __inline_functions(float,f)
291 __inline_functions(long double,l)
292 # endif
293 # undef __inline_functions
295 #endif
297 #ifdef __USE_ISOC99
299 # define __inline_functions(float_type, s) \
300 __m81_defun (float_type, __CONCAT(__scalbln,s), \
301 (float_type __x, long int __n)) \
303 return __CONCAT(__scalbn,s) (__x, __n); \
306 __m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x)) \
308 float_type __result; \
309 unsigned long int __ctrl_reg; \
310 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
311 /* Temporarily disable the inexact exception. */ \
312 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
313 : "dmi" (__ctrl_reg & ~0x200)); \
314 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
315 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
316 : "dmi" (__ctrl_reg)); \
317 return __result; \
320 __m81_defun (long int, __CONCAT(__lrint,s), (float_type __x)) \
322 long int __result; \
323 __asm __volatile__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \
324 return __result; \
327 __inline_functions (double,)
328 __inline_functions (float,f)
329 __inline_functions (long double,l)
330 # undef __inline_functions
332 #endif /* Use ISO C9x */
334 #ifdef __USE_GNU
336 # define __inline_functions(float_type, s) \
337 __m81_inline void \
338 __NTH (__m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx, \
339 float_type *__cosx)) \
341 __asm __volatile__ ("fsincos%.x %2,%1:%0" \
342 : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x)); \
345 __inline_functions (double,)
346 __inline_functions (float,f)
347 __inline_functions (long double,l)
348 # undef __inline_functions
350 #endif
352 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
354 /* Define inline versions of the user visible functions. */
356 /* Note that there must be no whitespace before the argument passed for
357 NAME, to make token pasting work correctly with -traditional. */
358 # define __inline_forward_c(rettype, name, args1, args2) \
359 __MATH_INLINE rettype __attribute__((__const__)) \
360 __NTH (name args1) \
362 return __CONCAT(__,name) args2; \
365 # define __inline_forward(rettype, name, args1, args2) \
366 __MATH_INLINE rettype __NTH (name args1) \
368 return __CONCAT(__,name) args2; \
371 __inline_forward_c(double,floor, (double __x), (__x))
372 __inline_forward_c(double,ceil, (double __x), (__x))
373 # ifdef __USE_MISC
374 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
375 __inline_forward_c(int,isinf, (double __value), (__value))
376 # endif
377 __inline_forward_c(int,finite, (double __value), (__value))
378 __inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n))
379 # endif
380 # if defined __USE_MISC || defined __USE_XOPEN
381 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
382 __inline_forward_c(int,isnan, (double __value), (__value))
383 # endif
384 # endif
385 # ifdef __USE_ISOC99
386 __inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n))
387 __inline_forward_c(double,nearbyint, (double __value), (__value))
388 __inline_forward_c(long int,lrint, (double __value), (__value))
389 # endif
390 # ifdef __USE_GNU
391 __inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
392 (__x, __sinx, __cosx))
393 # endif
395 # if defined __USE_MISC || defined __USE_ISOC99
397 __inline_forward_c(float,floorf, (float __x), (__x))
398 __inline_forward_c(float,ceilf, (float __x), (__x))
399 # ifdef __USE_MISC
400 __inline_forward_c(int,isinff, (float __value), (__value))
401 __inline_forward_c(int,finitef, (float __value), (__value))
402 __inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n))
403 __inline_forward_c(int,isnanf, (float __value), (__value))
404 # endif
405 # ifdef __USE_ISOC99
406 __inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n))
407 __inline_forward_c(float,nearbyintf, (float __value), (__value))
408 __inline_forward_c(long int,lrintf, (float __value), (__value))
409 # endif
410 # ifdef __USE_GNU
411 __inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
412 (__x, __sinx, __cosx))
413 # endif
415 __inline_forward_c(long double,floorl, (long double __x), (__x))
416 __inline_forward_c(long double,ceill, (long double __x), (__x))
417 # ifdef __USE_MISC
418 __inline_forward_c(int,isinfl, (long double __value), (__value))
419 __inline_forward_c(int,finitel, (long double __value), (__value))
420 __inline_forward_c(long double,scalbnl, (long double __x, int __n), (__x, __n))
421 __inline_forward_c(int,isnanl, (long double __value), (__value))
422 # endif
423 # ifdef __USE_ISOC99
424 __inline_forward_c(long double,scalblnl, (long double __x, long int __n),
425 (__x, __n))
426 __inline_forward_c(long double,nearbyintl, (long double __value), (__value))
427 __inline_forward_c(long int,lrintl, (long double __value), (__value))
428 # endif
429 # ifdef __USE_GNU
430 __inline_forward(void,sincosl,
431 (long double __x, long double *__sinx, long double *__cosx),
432 (__x, __sinx, __cosx))
433 # endif
435 #endif /* Use misc or ISO C99 */
437 #undef __inline_forward
438 #undef __inline_forward_c
440 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
442 #endif
443 #endif /* GCC. */