]>
Commit | Line | Data |
---|---|---|
5da9d124 AS |
1 | /* Definitions of libc internal inline math functions implemented |
2 | by the m68881/2. | |
2b778ceb | 3 | Copyright (C) 1991-2021 Free Software Foundation, Inc. |
5da9d124 AS |
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 | |
3214b89b AJ |
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. | |
5da9d124 AS |
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 | |
3214b89b | 14 | Lesser General Public License for more details. |
5da9d124 | 15 | |
3214b89b | 16 | You should have received a copy of the GNU Lesser General Public |
ab84e3ff | 17 | License along with the GNU C Library. If not, see |
5a82c748 | 18 | <https://www.gnu.org/licenses/>. */ |
5da9d124 | 19 | |
4bad2e01 AZ |
20 | #ifndef _MATHIMPL_H |
21 | #define _MATHIMPL_H | |
22 | ||
5da9d124 AS |
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 | ||
4bad2e01 AZ |
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 | ||
66425185 JM |
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,) | |
22679b2c | 255 | __inline_mathop (__ieee754_sqrt, sqrt,) |
66425185 | 256 | __inline_mathop (__ieee754_atanh, atanh,) |
5da9d124 | 257 | |
66425185 | 258 | __m81_defun (double, __ieee754_remainder, (double __x, double __y),) |
5da9d124 AS |
259 | { |
260 | double __result; | |
261 | __asm ("frem%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x)); | |
262 | return __result; | |
263 | } | |
264 | ||
66425185 | 265 | __m81_defun (float, __ieee754_remainderf, (float __x, float __y),) |
5da9d124 AS |
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, | |
66425185 | 273 | __ieee754_remainderl, (long double __x, long double __y),) |
5da9d124 AS |
274 | { |
275 | long double __result; | |
276 | __asm ("frem%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x)); | |
277 | return __result; | |
278 | } | |
279 | ||
66425185 | 280 | __m81_defun (double, __ieee754_fmod, (double __x, double __y),) |
5da9d124 AS |
281 | { |
282 | double __result; | |
283 | __asm ("fmod%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x)); | |
284 | return __result; | |
285 | } | |
286 | ||
66425185 | 287 | __m81_defun (float, __ieee754_fmodf, (float __x, float __y),) |
5da9d124 AS |
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, | |
66425185 | 295 | __ieee754_fmodl, (long double __x, long double __y),) |
5da9d124 AS |
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. */ | |
303 | static __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) | |
4bad2e01 AZ |
316 | |
317 | #endif /* _MATHIMPL_H */ |