1/* Definitions of libc internal inline math functions implemented
2 by the m68881/2.
3 Copyright (C) 1991-2024 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5
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.
10
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.
15
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 <https://www.gnu.org/licenses/>. */
19
20#ifndef _MATHIMPL_H
21#define _MATHIMPL_H
22
23/* This file contains the definitions of the inline math functions that
24 are only used internally inside libm, not visible to the user. */
25
26#define __MATH_INLINE __extern_inline
27
28/* This is used when defining the functions themselves. Define them with
29 __ names, and with `static inline' instead of `extern inline' so the
30 bodies will always be used, never an external function call.
31 Note: GCC 6 objects to __attribute__ ((__leaf__)) on static functions. */
32#define __m81_u(x) __CONCAT(__,x)
33#define __m81_inline static __inline
34#define __m81_nth(fn) __NTH (fn)
35
36/* Define a math function. */
37#define __m81_defun(rettype, func, args, attrs) \
38 __m81_inline rettype attrs \
39 __m81_nth (__m81_u(func) args)
40
41/* Define the three variants of a math function that has a direct
42 implementation in the m68k fpu. FUNC is the name for C (which will be
43 suffixed with f and l for the float and long double version, resp). OP
44 is the name of the fpu operation (without leading f). */
45
46# define __inline_mathop(func, op, attrs) \
47 __inline_mathop1(double, func, op, attrs) \
48 __inline_mathop1(float, __CONCAT(func,f), op, attrs) \
49 __inline_mathop1(long double, __CONCAT(func,l), op, attrs)
50
51#define __inline_mathop1(float_type,func, op, attrs) \
52 __m81_defun (float_type, func, (float_type __mathop_x), attrs) \
53 { \
54 float_type __result; \
55 __asm __volatile__ ("f" __STRING(op) "%.x %1, %0" \
56 : "=f" (__result) : "f" (__mathop_x)); \
57 return __result; \
58 }
59
60__inline_mathop(__atan, atan,)
61__inline_mathop(__cos, cos,)
62__inline_mathop(__sin, sin,)
63__inline_mathop(__tan, tan,)
64__inline_mathop(__tanh, tanh,)
65__inline_mathop(__fabs, abs, __attribute__ ((__const__)))
66
67__inline_mathop(__rint, int,)
68__inline_mathop(__expm1, etoxm1,)
69__inline_mathop(__log1p, lognp1,)
70
71__inline_mathop(__significand, getman,)
72
73__inline_mathop(__trunc, intrz, __attribute__ ((__const__)))
74
75
76/* This macro contains the definition for the rest of the inline
77 functions, using FLOAT_TYPE as the domain type and M as a macro
78 that adds the suffix for the function names. */
79
80#define __inline_functions(float_type, m) \
81__m81_defun (float_type, m(__floor), (float_type __x), \
82 __attribute__ ((__const__))) \
83{ \
84 float_type __result; \
85 unsigned long int __ctrl_reg; \
86 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
87 /* Set rounding towards negative infinity. */ \
88 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
89 : "dmi" ((__ctrl_reg & ~0x10) | 0x20)); \
90 /* Convert X to an integer, using -Inf rounding. */ \
91 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
92 /* Restore the previous rounding mode. */ \
93 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
94 : "dmi" (__ctrl_reg)); \
95 return __result; \
96} \
97 \
98__m81_defun (float_type, m(__ceil), (float_type __x), \
99 __attribute__ ((__const__))) \
100{ \
101 float_type __result; \
102 unsigned long int __ctrl_reg; \
103 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
104 /* Set rounding towards positive infinity. */ \
105 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
106 : "dmi" (__ctrl_reg | 0x30)); \
107 /* Convert X to an integer, using +Inf rounding. */ \
108 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
109 /* Restore the previous rounding mode. */ \
110 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
111 : "dmi" (__ctrl_reg)); \
112 return __result; \
113}
114
115#define __CONCAT_d(arg) arg
116#define __CONCAT_f(arg) arg ## f
117#define __CONCAT_l(arg) arg ## l
118__inline_functions(double, __CONCAT_d)
119__inline_functions(float, __CONCAT_f)
120__inline_functions(long double, __CONCAT_l)
121#undef __inline_functions
122
123# define __inline_functions(float_type, m) \
124__m81_defun (int, m(__isinf), (float_type __value), \
125 __attribute__ ((__const__))) \
126{ \
127 /* There is no branch-condition for infinity, \
128 so we must extract and examine the condition codes manually. */ \
129 unsigned long int __fpsr; \
130 __asm ("ftst%.x %1\n" \
131 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
132 return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0; \
133} \
134 \
135__m81_defun (int, m(__finite), (float_type __value), \
136 __attribute__ ((__const__))) \
137{ \
138 /* There is no branch-condition for infinity, so we must extract and \
139 examine the condition codes manually. */ \
140 unsigned long int __fpsr; \
141 __asm ("ftst%.x %1\n" \
142 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
143 return (__fpsr & (3 << 24)) == 0; \
144} \
145 \
146__m81_defun (float_type, m(__scalbn), \
147 (float_type __x, int __n),) \
148{ \
149 float_type __result; \
150 __asm __volatile__ ("fscale%.l %1, %0" : "=f" (__result) \
151 : "dmi" (__n), "0" (__x)); \
152 return __result; \
153}
154
155__inline_functions(double, __CONCAT_d)
156__inline_functions(float, __CONCAT_f)
157__inline_functions(long double, __CONCAT_l)
158#undef __inline_functions
159
160# define __inline_functions(float_type, m) \
161__m81_defun (int, m(__isnan), (float_type __value), \
162 __attribute__ ((__const__))) \
163{ \
164 char __result; \
165 __asm ("ftst%.x %1\n" \
166 "fsun %0" : "=dm" (__result) : "f" (__value)); \
167 return __result; \
168}
169
170__inline_functions(double, __CONCAT_d)
171__inline_functions(float, __CONCAT_f)
172__inline_functions(long double, __CONCAT_l)
173#undef __inline_functions
174
175# define __inline_functions(float_type, m) \
176__m81_defun (float_type, m(__scalbln), \
177 (float_type __x, long int __n),) \
178{ \
179 return m(__scalbn) (__x, __n); \
180} \
181 \
182__m81_defun (float_type, m(__nearbyint), (float_type __x),) \
183{ \
184 float_type __result; \
185 unsigned long int __ctrl_reg; \
186 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
187 /* Temporarily disable the inexact exception. */ \
188 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
189 : "dmi" (__ctrl_reg & ~0x200)); \
190 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
191 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
192 : "dmi" (__ctrl_reg)); \
193 return __result; \
194} \
195 \
196__m81_defun (long int, m(__lrint), (float_type __x),) \
197{ \
198 long int __result; \
199 __asm __volatile__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \
200 return __result; \
201}
202
203__inline_functions (double, __CONCAT_d)
204__inline_functions (float, __CONCAT_f)
205__inline_functions (long double, __CONCAT_l)
206#undef __inline_functions
207
208#define __inline_functions(float_type, m) \
209__m81_inline void \
210__m81_nth (__m81_u(m(__sincos)) \
211 (float_type __x, float_type *__sinx, float_type *__cosx)) \
212{ \
213 __asm __volatile__ ("fsincos%.x %2,%1:%0" \
214 : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x)); \
215}
216
217__inline_functions (double, __CONCAT_d)
218__inline_functions (float, __CONCAT_f)
219__inline_functions (long double, __CONCAT_l)
220#undef __inline_functions
221
222#undef __CONCAT_d
223#undef __CONCAT_f
224#undef __CONCAT_l
225
226/* Define the three variants of a math function that has a direct
227 implementation in the m68k fpu. FUNC is the name for C (which will be
228 suffixed with f and l for the float and long double version, resp). OP
229 is the name of the fpu operation (without leading f). */
230
231#define __inline_mathop(func, op, attrs) \
232 __inline_mathop1(double, func, op, attrs) \
233 __inline_mathop1(float, __CONCAT(func,f), op, attrs) \
234 __inline_mathop1(long double, __CONCAT(func,l), op, attrs)
235
236#define __inline_mathop1(float_type,func, op, attrs) \
237 __m81_defun (float_type, func, (float_type __mathop_x), attrs) \
238 { \
239 float_type __result; \
240 __asm __volatile__ ("f" __STRING(op) "%.x %1, %0" \
241 : "=f" (__result) : "f" (__mathop_x)); \
242 return __result; \
243 }
244
245__inline_mathop (__ieee754_acos, acos,)
246__inline_mathop (__ieee754_asin, asin,)
247__inline_mathop (__ieee754_cosh, cosh,)
248__inline_mathop (__ieee754_sinh, sinh,)
249__inline_mathop (__ieee754_exp, etox,)
250__inline_mathop (__ieee754_exp2, twotox,)
251__inline_mathop (__ieee754_exp10, tentox,)
252__inline_mathop (__ieee754_log10, log10,)
253__inline_mathop (__ieee754_log2, log2,)
254__inline_mathop (__ieee754_log, logn,)
255__inline_mathop (__ieee754_sqrt, sqrt,)
256__inline_mathop (__ieee754_atanh, atanh,)
257
258__m81_defun (double, __ieee754_remainder, (double __x, double __y),)
259{
260 double __result;
261 __asm ("frem%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
262 return __result;
263}
264
265__m81_defun (float, __ieee754_remainderf, (float __x, float __y),)
266{
267 float __result;
268 __asm ("frem%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
269 return __result;
270}
271
272__m81_defun (long double,
273 __ieee754_remainderl, (long double __x, long double __y),)
274{
275 long double __result;
276 __asm ("frem%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
277 return __result;
278}
279
280__m81_defun (double, __ieee754_fmod, (double __x, double __y),)
281{
282 double __result;
283 __asm ("fmod%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
284 return __result;
285}
286
287__m81_defun (float, __ieee754_fmodf, (float __x, float __y),)
288{
289 float __result;
290 __asm ("fmod%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
291 return __result;
292}
293
294__m81_defun (long double,
295 __ieee754_fmodl, (long double __x, long double __y),)
296{
297 long double __result;
298 __asm ("fmod%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
299 return __result;
300}
301
302/* Get the m68881 condition codes, to quickly check multiple conditions. */
303static __inline__ unsigned long
304__m81_test (long double __val)
305{
306 unsigned long __fpsr;
307 __asm ("ftst%.x %1; fmove%.l %/fpsr,%0" : "=dm" (__fpsr) : "f" (__val));
308 return __fpsr;
309}
310
311/* Bit values returned by __m81_test. */
312#define __M81_COND_NAN (1 << 24)
313#define __M81_COND_INF (2 << 24)
314#define __M81_COND_ZERO (4 << 24)
315#define __M81_COND_NEG (8 << 24)
316
317#endif /* _MATHIMPL_H */
318

source code of glibc/sysdeps/m68k/m680x0/fpu/mathimpl.h