]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/m68k/m680x0/fpu/bits/mathinline.h
1 /* Definitions of inline math functions implemented by the m68881/2.
2 Copyright (C) 1991-2015 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/>. */
20 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
23 #ifndef __extern_inline
24 # define __MATH_INLINE __inline
26 # define __MATH_INLINE __extern_inline
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. */
39 # undef isgreaterequal
44 # define isgreater(x, y) \
47 __asm__ ("fcmp%.x %2,%1; fsogt %0" \
48 : "=dm" (__result) : "f" (x), "f" (y)); \
51 # define isgreaterequal(x, y) \
54 __asm__ ("fcmp%.x %2,%1; fsoge %0" \
55 : "=dm" (__result) : "f" (x), "f" (y)); \
58 # define isless(x, y) \
61 __asm__ ("fcmp%.x %2,%1; fsolt %0" \
62 : "=dm" (__result) : "f" (x), "f" (y)); \
65 # define islessequal(x, y) \
68 __asm__ ("fcmp%.x %2,%1; fsole %0" \
69 : "=dm" (__result) : "f" (x), "f" (y)); \
72 # define islessgreater(x, y) \
75 __asm__ ("fcmp%.x %2,%1; fsogl %0" \
76 : "=dm" (__result) : "f" (x), "f" (y)); \
79 # define isunordered(x, y) \
82 __asm__ ("fcmp%.x %2,%1; fsun %0" \
83 : "=dm" (__result) : "f" (x), "f" (y)); \
87 /* Test for negative number. Used in the signbit() macro. */
89 __NTH (__signbitf (float __x
))
91 __extension__
union { float __f
; int __i
; } __u
= { __f
: __x
};
95 __NTH (__signbit (double __x
))
97 __extension__
union { double __d
; int __i
[2]; } __u
= { __d
: __x
};
98 return __u
.__i
[0] < 0;
101 __NTH (__signbitl (long double __x
))
103 __extension__
union { long double __d
; int __i
[3]; } __u
= { __d
: __x
};
104 return __u
.__i
[0] < 0;
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
119 # define __m81_u(x) x
120 # define __m81_inline __MATH_INLINE
121 # define __M81_MATH_INLINES 1
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). */
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)
140 # define __inline_mathop(func, op) \
141 __inline_mathop1(double, func, op)
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)); \
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_XOPEN_EXTENDED || defined __USE_ISOC99
161 __inline_mathop(__rint
, int)
162 __inline_mathop(__expm1
, etoxm1
)
163 __inline_mathop(__log1p
, lognp1
)
167 __inline_mathop(__significand
, getman
)
171 __inline_mathop(__trunc
, intrz
)
174 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
176 __inline_mathop(atan
, atan
)
177 __inline_mathop(tanh
, tanh
)
179 # if defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
180 __inline_mathop(rint
, int)
181 __inline_mathop(log1p
, lognp1
)
185 __inline_mathop(significand
, getman
)
189 __inline_mathop(trunc
, intrz
)
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)); \
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)); \
231 __inline_functions(double,)
233 __inline_functions(float,f
)
234 __inline_functions(long double,l
)
236 #undef __inline_functions
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)); \
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)) \
283 __asm ("ftst%.x %1\n" \
284 "fsun %0" : "=dm" (__result) : "f" (__value)); \
288 __inline_functions(double,)
290 __inline_functions(float,f
)
291 __inline_functions(long double,l
)
293 # undef __inline_functions
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)); \
320 __m81_defun (long int, __CONCAT(__lrint,s), (float_type __x)) \
323 __asm __volatile__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \
327 __inline_functions (double,)
328 __inline_functions (float,f
)
329 __inline_functions (long double,l
)
330 # undef __inline_functions
332 #endif /* Use ISO C9x */
336 # define __inline_functions(float_type, s) \
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
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__)) \
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
))
374 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
375 __inline_forward_c(int,isinf
, (double __value
), (__value
))
377 __inline_forward_c(int,finite
, (double __value
), (__value
))
378 __inline_forward_c(double,scalbn
, (double __x
, int __n
), (__x
, __n
))
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
))
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
))
391 __inline_forward(void,sincos
, (double __x
, double *__sinx
, double *__cosx
),
392 (__x
, __sinx
, __cosx
))
397 __inline_forward_c(float,floorf
, (float __x
), (__x
))
398 __inline_forward_c(float,ceilf
, (float __x
), (__x
))
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
))
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
))
411 __inline_forward(void,sincosf
, (float __x
, float *__sinx
, float *__cosx
),
412 (__x
, __sinx
, __cosx
))
415 __inline_forward_c(long double,floorl
, (long double __x
), (__x
))
416 __inline_forward_c(long double,ceill
, (long double __x
), (__x
))
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
))
424 __inline_forward_c(long double,scalblnl
, (long double __x
, long int __n
),
426 __inline_forward_c(long double,nearbyintl
, (long double __value
), (__value
))
427 __inline_forward_c(long int,lrintl
, (long double __value
), (__value
))
430 __inline_forward(void,sincosl
,
431 (long double __x
, long double *__sinx
, long double *__cosx
),
432 (__x
, __sinx
, __cosx
))
435 #endif /* Use misc or ISO C99 */
437 #undef __inline_forward
438 #undef __inline_forward_c
440 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */