]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/m68k/m680x0/fpu/bits/mathinline.h
5350e0dd6fded2039dddd1b277a6d70eeb510d8f
[thirdparty/glibc.git] / sysdeps / m68k / m680x0 / fpu / bits / mathinline.h
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.
4
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.
9
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.
14
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/>. */
18
19 #ifndef _MATH_H
20 # error "Never use <bits/mathinline.h> directly; include <math.h> instead."
21 #endif
22
23 #ifndef __extern_inline
24 # define __MATH_INLINE __inline
25 #else
26 # define __MATH_INLINE __extern_inline
27 #endif
28
29 #ifdef __GNUC__
30
31 #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
32 || defined __LIBC_INTERNAL_MATH_INLINES
33
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)
42 #else
43 # define __m81_u(x) x
44 # define __m81_inline __MATH_INLINE
45 # define __m81_nth(fn) __NTH (fn)
46 # define __M81_MATH_INLINES 1
47 #endif
48
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)
53
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). */
58
59 #ifdef __USE_ISOC99
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)
64 #else
65 # define __inline_mathop(func, op, attrs) \
66 __inline_mathop1(double, func, op, attrs)
67 #endif
68
69 #define __inline_mathop1(float_type,func, op, attrs) \
70 __m81_defun (float_type, func, (float_type __mathop_x), attrs) \
71 { \
72 float_type __result; \
73 __asm __volatile__ ("f" __STRING(op) "%.x %1, %0" \
74 : "=f" (__result) : "f" (__mathop_x)); \
75 return __result; \
76 }
77
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__)))
84
85 #if defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
86 __inline_mathop(__rint, int,)
87 __inline_mathop(__expm1, etoxm1,)
88 __inline_mathop(__log1p, lognp1,)
89 #endif
90
91 #ifdef __USE_MISC
92 __inline_mathop(__significand, getman,)
93 #endif
94
95 #ifdef __USE_ISOC99
96 __inline_mathop(__trunc, intrz, __attribute__ ((__const__)))
97 #endif
98
99 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
100
101 __inline_mathop(atan, atan,)
102 __inline_mathop(tanh, tanh,)
103
104 # if defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
105 __inline_mathop(rint, int,)
106 __inline_mathop(log1p, lognp1,)
107 # endif
108
109 # ifdef __USE_MISC
110 __inline_mathop(significand, getman,)
111 # endif
112
113 # ifdef __USE_ISOC99
114 __inline_mathop(trunc, intrz, __attribute__ ((__const__)))
115 # endif
116
117 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
118
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. */
122
123 #define __inline_functions(float_type, m) \
124 __m81_defun (float_type, m(__floor), (float_type __x), \
125 __attribute__ ((__const__))) \
126 { \
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)); \
138 return __result; \
139 } \
140 \
141 __m81_defun (float_type, m(__ceil), (float_type __x), \
142 __attribute__ ((__const__))) \
143 { \
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)); \
155 return __result; \
156 }
157
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)
162 #ifdef __USE_ISOC99
163 __inline_functions(float, __CONCAT_f)
164 __inline_functions(long double, __CONCAT_l)
165 #endif
166 #undef __inline_functions
167
168 #ifdef __USE_MISC
169
170 # define __inline_functions(float_type, m) \
171 __m81_defun (int, m(__isinf), (float_type __value), \
172 __attribute__ ((__const__))) \
173 { \
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; \
180 } \
181 \
182 __m81_defun (int, m(__finite), (float_type __value), \
183 __attribute__ ((__const__))) \
184 { \
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; \
191 } \
192 \
193 __m81_defun (float_type, m(__scalbn), \
194 (float_type __x, int __n),) \
195 { \
196 float_type __result; \
197 __asm __volatile__ ("fscale%.l %1, %0" : "=f" (__result) \
198 : "dmi" (__n), "0" (__x)); \
199 return __result; \
200 }
201
202 __inline_functions(double, __CONCAT_d)
203 __inline_functions(float, __CONCAT_f)
204 __inline_functions(long double, __CONCAT_l)
205 # undef __inline_functions
206
207 #endif /* Use misc. */
208
209 #if defined __USE_MISC || defined __USE_XOPEN
210
211 # define __inline_functions(float_type, m) \
212 __m81_defun (int, m(__isnan), (float_type __value), \
213 __attribute__ ((__const__))) \
214 { \
215 char __result; \
216 __asm ("ftst%.x %1\n" \
217 "fsun %0" : "=dm" (__result) : "f" (__value)); \
218 return __result; \
219 }
220
221 __inline_functions(double, __CONCAT_d)
222 # ifdef __USE_MISC
223 __inline_functions(float, __CONCAT_f)
224 __inline_functions(long double, __CONCAT_l)
225 # endif
226 # undef __inline_functions
227
228 #endif
229
230 #ifdef __USE_ISOC99
231
232 # define __inline_functions(float_type, m) \
233 __m81_defun (float_type, m(__scalbln), \
234 (float_type __x, long int __n),) \
235 { \
236 return m(__scalbn) (__x, __n); \
237 } \
238 \
239 __m81_defun (float_type, m(__nearbyint), (float_type __x),) \
240 { \
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)); \
250 return __result; \
251 } \
252 \
253 __m81_defun (long int, m(__lrint), (float_type __x),) \
254 { \
255 long int __result; \
256 __asm __volatile__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \
257 return __result; \
258 }
259
260 __inline_functions (double, __CONCAT_d)
261 __inline_functions (float, __CONCAT_f)
262 __inline_functions (long double, __CONCAT_l)
263 # undef __inline_functions
264
265 #endif /* Use ISO C9x */
266
267 #ifdef __USE_GNU
268
269 # define __inline_functions(float_type, m) \
270 __m81_inline void \
271 __m81_nth (__m81_u(m(__sincos)) \
272 (float_type __x, float_type *__sinx, float_type *__cosx)) \
273 { \
274 __asm __volatile__ ("fsincos%.x %2,%1:%0" \
275 : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x)); \
276 }
277
278 __inline_functions (double, __CONCAT_d)
279 __inline_functions (float, __CONCAT_f)
280 __inline_functions (long double, __CONCAT_l)
281 # undef __inline_functions
282
283 #endif
284
285 #undef __CONCAT_d
286 #undef __CONCAT_f
287 #undef __CONCAT_l
288
289 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
290
291 /* Define inline versions of the user visible functions. */
292
293 # define __inline_forward_c(rettype, name, args1, args2) \
294 __MATH_INLINE rettype __attribute__((__const__)) \
295 __NTH (name args1) \
296 { \
297 return __CONCAT(__,name) args2; \
298 }
299
300 # define __inline_forward(rettype, name, args1, args2) \
301 __MATH_INLINE rettype __NTH (name args1) \
302 { \
303 return __CONCAT(__,name) args2; \
304 }
305
306 __inline_forward_c(double,floor, (double __x), (__x))
307 __inline_forward_c(double,ceil, (double __x), (__x))
308 # ifdef __USE_MISC
309 # ifndef __USE_ISOC99 /* Conflict with macro of same name. */
310 __inline_forward_c(int,isinf, (double __value), (__value))
311 # endif
312 __inline_forward_c(int,finite, (double __value), (__value))
313 __inline_forward(double,scalbn, (double __x, int __n), (__x, __n))
314 # endif
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))
318 # endif
319 # endif
320 # ifdef __USE_ISOC99
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))
324 # endif
325 # ifdef __USE_GNU
326 __inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
327 (__x, __sinx, __cosx))
328 # endif
329
330 # ifdef __USE_ISOC99
331
332 __inline_forward_c(float,floorf, (float __x), (__x))
333 __inline_forward_c(float,ceilf, (float __x), (__x))
334 # ifdef __USE_MISC
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))
339 # endif
340 # ifdef __USE_ISOC99
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))
344 # endif
345 # ifdef __USE_GNU
346 __inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
347 (__x, __sinx, __cosx))
348 # endif
349
350 __inline_forward_c(long double,floorl, (long double __x), (__x))
351 __inline_forward_c(long double,ceill, (long double __x), (__x))
352 # ifdef __USE_MISC
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))
357 # endif
358 # ifdef __USE_ISOC99
359 __inline_forward(long double,scalblnl, (long double __x, long int __n),
360 (__x, __n))
361 __inline_forward(long double,nearbyintl, (long double __value), (__value))
362 __inline_forward(long int,lrintl, (long double __value), (__value))
363 # endif
364 # ifdef __USE_GNU
365 __inline_forward(void,sincosl,
366 (long double __x, long double *__sinx, long double *__cosx),
367 (__x, __sinx, __cosx))
368 # endif
369
370 #endif /* Use misc or ISO C99 */
371
372 #undef __inline_forward
373 #undef __inline_forward_c
374
375 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
376
377 #endif
378 #endif /* GCC. */