]>
git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/m68k/m680x0/fpu/bits/mathinline.h
5350e0dd6fded2039dddd1b277a6d70eeb510d8f
1 /* Definitions of inline math functions implemented by the m68881/2.
2 Copyright (C) 1991-2019 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
31 #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
32 || defined __LIBC_INTERNAL_MATH_INLINES
34 #ifdef __LIBC_INTERNAL_MATH_INLINES
35 /* This is used when defining the functions themselves. Define them with
36 __ names, and with `static inline' instead of `extern inline' so the
37 bodies will always be used, never an external function call.
38 Note: GCC 6 objects to __attribute__ ((__leaf__)) on static functions. */
39 # define __m81_u(x) __CONCAT(__,x)
40 # define __m81_inline static __inline
41 # define __m81_nth(fn) __NTHNL (fn)
44 # define __m81_inline __MATH_INLINE
45 # define __m81_nth(fn) __NTH (fn)
46 # define __M81_MATH_INLINES 1
49 /* Define a math function. */
50 #define __m81_defun(rettype, func, args, attrs) \
51 __m81_inline rettype attrs \
52 __m81_nth (__m81_u(func) args)
54 /* Define the three variants of a math function that has a direct
55 implementation in the m68k fpu. FUNC is the name for C (which will be
56 suffixed with f and l for the float and long double version, resp). OP
57 is the name of the fpu operation (without leading f). */
60 # define __inline_mathop(func, op, attrs) \
61 __inline_mathop1(double, func, op, attrs) \
62 __inline_mathop1(float, __CONCAT(func,f), op, attrs) \
63 __inline_mathop1(long double, __CONCAT(func,l), op, attrs)
65 # define __inline_mathop(func, op, attrs) \
66 __inline_mathop1(double, func, op, attrs)
69 #define __inline_mathop1(float_type,func, op, attrs) \
70 __m81_defun (float_type, func, (float_type __mathop_x), attrs) \
72 float_type __result; \
73 __asm __volatile__ ("f" __STRING(op) "%.x %1, %0" \
74 : "=f" (__result) : "f" (__mathop_x)); \
78 __inline_mathop(__atan
, atan
,)
79 __inline_mathop(__cos
, cos
,)
80 __inline_mathop(__sin
, sin
,)
81 __inline_mathop(__tan
, tan
,)
82 __inline_mathop(__tanh
, tanh
,)
83 __inline_mathop(__fabs
, abs
, __attribute__ ((__const__
)))
85 #if defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
86 __inline_mathop(__rint
, int,)
87 __inline_mathop(__expm1
, etoxm1
,)
88 __inline_mathop(__log1p
, lognp1
,)
92 __inline_mathop(__significand
, getman
,)
96 __inline_mathop(__trunc
, intrz
, __attribute__ ((__const__
)))
99 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
101 __inline_mathop(atan
, atan
,)
102 __inline_mathop(tanh
, tanh
,)
104 # if defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
105 __inline_mathop(rint
, int,)
106 __inline_mathop(log1p
, lognp1
,)
110 __inline_mathop(significand
, getman
,)
114 __inline_mathop(trunc
, intrz
, __attribute__ ((__const__
)))
117 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
119 /* This macro contains the definition for the rest of the inline
120 functions, using FLOAT_TYPE as the domain type and M as a macro
121 that adds the suffix for the function names. */
123 #define __inline_functions(float_type, m) \
124 __m81_defun (float_type, m(__floor), (float_type __x), \
125 __attribute__ ((__const__))) \
127 float_type __result; \
128 unsigned long int __ctrl_reg; \
129 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
130 /* Set rounding towards negative infinity. */ \
131 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
132 : "dmi" ((__ctrl_reg & ~0x10) | 0x20)); \
133 /* Convert X to an integer, using -Inf rounding. */ \
134 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
135 /* Restore the previous rounding mode. */ \
136 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
137 : "dmi" (__ctrl_reg)); \
141 __m81_defun (float_type, m(__ceil), (float_type __x), \
142 __attribute__ ((__const__))) \
144 float_type __result; \
145 unsigned long int __ctrl_reg; \
146 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
147 /* Set rounding towards positive infinity. */ \
148 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
149 : "dmi" (__ctrl_reg | 0x30)); \
150 /* Convert X to an integer, using +Inf rounding. */ \
151 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
152 /* Restore the previous rounding mode. */ \
153 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
154 : "dmi" (__ctrl_reg)); \
158 #define __CONCAT_d(arg) arg
159 #define __CONCAT_f(arg) arg ## f
160 #define __CONCAT_l(arg) arg ## l
161 __inline_functions(double, __CONCAT_d
)
163 __inline_functions(float, __CONCAT_f
)
164 __inline_functions(long double, __CONCAT_l
)
166 #undef __inline_functions
170 # define __inline_functions(float_type, m) \
171 __m81_defun (int, m(__isinf), (float_type __value), \
172 __attribute__ ((__const__))) \
174 /* There is no branch-condition for infinity, \
175 so we must extract and examine the condition codes manually. */ \
176 unsigned long int __fpsr; \
177 __asm ("ftst%.x %1\n" \
178 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
179 return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0; \
182 __m81_defun (int, m(__finite), (float_type __value), \
183 __attribute__ ((__const__))) \
185 /* There is no branch-condition for infinity, so we must extract and \
186 examine the condition codes manually. */ \
187 unsigned long int __fpsr; \
188 __asm ("ftst%.x %1\n" \
189 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
190 return (__fpsr & (3 << 24)) == 0; \
193 __m81_defun (float_type, m(__scalbn), \
194 (float_type __x, int __n),) \
196 float_type __result; \
197 __asm __volatile__ ("fscale%.l %1, %0" : "=f" (__result) \
198 : "dmi" (__n), "0" (__x)); \
202 __inline_functions(double, __CONCAT_d
)
203 __inline_functions(float, __CONCAT_f
)
204 __inline_functions(long double, __CONCAT_l
)
205 # undef __inline_functions
207 #endif /* Use misc. */
209 #if defined __USE_MISC || defined __USE_XOPEN
211 # define __inline_functions(float_type, m) \
212 __m81_defun (int, m(__isnan), (float_type __value), \
213 __attribute__ ((__const__))) \
216 __asm ("ftst%.x %1\n" \
217 "fsun %0" : "=dm" (__result) : "f" (__value)); \
221 __inline_functions(double, __CONCAT_d
)
223 __inline_functions(float, __CONCAT_f
)
224 __inline_functions(long double, __CONCAT_l
)
226 # undef __inline_functions
232 # define __inline_functions(float_type, m) \
233 __m81_defun (float_type, m(__scalbln), \
234 (float_type __x, long int __n),) \
236 return m(__scalbn) (__x, __n); \
239 __m81_defun (float_type, m(__nearbyint), (float_type __x),) \
241 float_type __result; \
242 unsigned long int __ctrl_reg; \
243 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
244 /* Temporarily disable the inexact exception. */ \
245 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
246 : "dmi" (__ctrl_reg & ~0x200)); \
247 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
248 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
249 : "dmi" (__ctrl_reg)); \
253 __m81_defun (long int, m(__lrint), (float_type __x),) \
256 __asm __volatile__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \
260 __inline_functions (double, __CONCAT_d
)
261 __inline_functions (float, __CONCAT_f
)
262 __inline_functions (long double, __CONCAT_l
)
263 # undef __inline_functions
265 #endif /* Use ISO C9x */
269 # define __inline_functions(float_type, m) \
271 __m81_nth (__m81_u(m(__sincos)) \
272 (float_type __x, float_type *__sinx, float_type *__cosx)) \
274 __asm __volatile__ ("fsincos%.x %2,%1:%0" \
275 : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x)); \
278 __inline_functions (double, __CONCAT_d
)
279 __inline_functions (float, __CONCAT_f
)
280 __inline_functions (long double, __CONCAT_l
)
281 # undef __inline_functions
289 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
291 /* Define inline versions of the user visible functions. */
293 # define __inline_forward_c(rettype, name, args1, args2) \
294 __MATH_INLINE rettype __attribute__((__const__)) \
297 return __CONCAT(__,name) args2; \
300 # define __inline_forward(rettype, name, args1, args2) \
301 __MATH_INLINE rettype __NTH (name args1) \
303 return __CONCAT(__,name) args2; \
306 __inline_forward_c(double,floor
, (double __x
), (__x
))
307 __inline_forward_c(double,ceil
, (double __x
), (__x
))
309 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
310 __inline_forward_c(int,isinf
, (double __value
), (__value
))
312 __inline_forward_c(int,finite
, (double __value
), (__value
))
313 __inline_forward(double,scalbn
, (double __x
, int __n
), (__x
, __n
))
315 # if defined __USE_MISC || defined __USE_XOPEN
316 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
317 __inline_forward_c(int,isnan
, (double __value
), (__value
))
321 __inline_forward(double,scalbln
, (double __x
, long int __n
), (__x
, __n
))
322 __inline_forward(double,nearbyint
, (double __value
), (__value
))
323 __inline_forward(long int,lrint
, (double __value
), (__value
))
326 __inline_forward(void,sincos
, (double __x
, double *__sinx
, double *__cosx
),
327 (__x
, __sinx
, __cosx
))
332 __inline_forward_c(float,floorf
, (float __x
), (__x
))
333 __inline_forward_c(float,ceilf
, (float __x
), (__x
))
335 __inline_forward_c(int,isinff
, (float __value
), (__value
))
336 __inline_forward_c(int,finitef
, (float __value
), (__value
))
337 __inline_forward(float,scalbnf
, (float __x
, int __n
), (__x
, __n
))
338 __inline_forward_c(int,isnanf
, (float __value
), (__value
))
341 __inline_forward(float,scalblnf
, (float __x
, long int __n
), (__x
, __n
))
342 __inline_forward(float,nearbyintf
, (float __value
), (__value
))
343 __inline_forward(long int,lrintf
, (float __value
), (__value
))
346 __inline_forward(void,sincosf
, (float __x
, float *__sinx
, float *__cosx
),
347 (__x
, __sinx
, __cosx
))
350 __inline_forward_c(long double,floorl
, (long double __x
), (__x
))
351 __inline_forward_c(long double,ceill
, (long double __x
), (__x
))
353 __inline_forward_c(int,isinfl
, (long double __value
), (__value
))
354 __inline_forward_c(int,finitel
, (long double __value
), (__value
))
355 __inline_forward(long double,scalbnl
, (long double __x
, int __n
), (__x
, __n
))
356 __inline_forward_c(int,isnanl
, (long double __value
), (__value
))
359 __inline_forward(long double,scalblnl
, (long double __x
, long int __n
),
361 __inline_forward(long double,nearbyintl
, (long double __value
), (__value
))
362 __inline_forward(long int,lrintl
, (long double __value
), (__value
))
365 __inline_forward(void,sincosl
,
366 (long double __x
, long double *__sinx
, long double *__cosx
),
367 (__x
, __sinx
, __cosx
))
370 #endif /* Use misc or ISO C99 */
372 #undef __inline_forward
373 #undef __inline_forward_c
375 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */