OSDN Git Service

Hand-optimize wrappers on i386:
[uclinux-h8/uClibc.git] / libm / ldouble_wrappers.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Wrapper functions implementing all the long double math functions
4  * defined by SuSv3 by actually calling the double version of
5  * each function and then casting the result back to a long double
6  * to return to the user.
7  *
8  * Copyright (C) 2005 by Erik Andersen <andersen@uclibc.org>
9  *
10  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
11  */
12
13 #include <features.h>
14 /* Prevent math.h from defining colliding inlines */
15 #undef __USE_EXTERN_INLINES
16 #include "math.h"
17 #include <complex.h>
18
19 #define STRINGIZE(s) #s
20
21 #define WRAPPER1(func) \
22 long double func##l(long double x) \
23 { \
24         return (long double) func((double) x); \
25 }
26
27 #define int_WRAPPER1(func) \
28 int func##l(long double x) \
29 { \
30         return func((double) x); \
31 }
32
33 #if defined __i386__ && defined __OPTIMIZE__
34 # undef WRAPPER1
35 # undef int_WRAPPER1
36 /* gcc 4.3.1 generates really ugly code with redundant pair of store/load:
37  *      sub    $0x10,%esp
38  *      fldt    0x14(%esp)
39  *      fstpl   0x8(%esp)
40  *      fldl    0x8(%esp) <-- ??
41  *      fstpl   (%esp)    <-- ??
42  *      call    function
43  *      add     $0x10,%esp
44  *      ret
45  * I can hope newer gcc will eliminate that. However, I don't think
46  * it will be smart enough to reuse argument stack space and use
47  * jump instead of call. Let's do it by hand.
48  * The asm below loads long double x into st(0), then stores it back
49  * to the same location as a double. At this point, stack looks exactly
50  * as "double func(double)" expects it to be.
51  * The return value is returned in st(0) per ABI in both cases (returning
52  * a long double or returning a double). So we can simply jump to func.
53  * Using __GI_func in jump to make optimized intra-library jump.
54  * gcc will still generate a useless "ret" after asm. Oh well...
55  */
56 # define WRAPPER1(func) \
57 long double func##l(long double x) \
58 { \
59         long double fp_top; \
60         __asm ( \
61         "       fldt    %1\n" \
62         "       fstpl   %1\n" \
63         "       jmp     " STRINGIZE(__GI_##func) "\n" \
64         : "=t" (fp_top) \
65         : "m" (x) \
66         ); \
67         return fp_top; \
68 }
69 # define int_WRAPPER1(func) \
70 int func##l(long double x) \
71 { \
72         int ret; \
73         __asm ( \
74         "       fldt    %1\n" \
75         "       fstpl   %1\n" \
76         "       jmp     " STRINGIZE(__GI_##func) "\n" \
77         : "=a" (ret) \
78         : "m" (x) \
79         ); \
80         return ret; \
81 }
82 #endif /* __i386__ */
83
84
85 /* Implement the following, as defined by SuSv3 */
86 #if 0
87 long double acoshl(long double);
88 long double acosl(long double);
89 long double asinhl(long double);
90 long double asinl(long double);
91 long double atan2l(long double, long double);
92 long double atanhl(long double);
93 long double atanl(long double);
94 long double cargl(long double complex);
95 long double cbrtl(long double);
96 long double ceill(long double);
97 long double copysignl(long double, long double);
98 long double coshl(long double);
99 long double cosl(long double);
100 long double erfcl(long double);
101 long double erfl(long double);
102 long double exp2l(long double);
103 long double expl(long double);
104 long double expm1l(long double);
105 long double fabsl(long double);
106 long double fdiml(long double, long double);
107 long double floorl(long double);
108 long double fmal(long double, long double, long double);
109 long double fmaxl(long double, long double);
110 long double fminl(long double, long double);
111 long double fmodl(long double, long double);
112 long double frexpl(long double value, int *);
113 long double hypotl(long double, long double);
114 int         ilogbl(long double);
115 long double ldexpl(long double, int);
116 long double lgammal(long double);
117 long long   llrintl(long double);
118 long long   llroundl(long double);
119 long double log10l(long double);
120 long double log1pl(long double);
121 long double log2l(long double);
122 long double logbl(long double);
123 long double logl(long double);
124 long        lrintl(long double);
125 long        lroundl(long double);
126 long double modfl(long double, long double *);
127 long double nearbyintl(long double);
128 long double nextafterl(long double, long double);
129 long double nexttowardl(long double, long double);
130 long double powl(long double, long double);
131 long double remainderl(long double, long double);
132 long double remquol(long double, long double, int *);
133 long double rintl(long double);
134 long double roundl(long double);
135 long double scalblnl(long double, long);
136 long double scalbnl(long double, int);
137 long double sinhl(long double);
138 long double sinl(long double);
139 long double sqrtl(long double);
140 long double tanhl(long double);
141 long double tanl(long double);
142 long double tgammal(long double);
143 long double truncl(long double);
144 #endif
145
146 #ifdef L_acoshl
147 WRAPPER1(acosh)
148 #endif
149
150 #ifdef L_acosl
151 WRAPPER1(acos)
152 #endif
153
154 #ifdef L_asinhl
155 WRAPPER1(asinh)
156 #endif
157
158 #ifdef L_asinl
159 WRAPPER1(asin)
160 #endif
161
162 #ifdef L_atan2l
163 long double atan2l (long double x, long double y)
164 {
165         return (long double) atan2( (double)x, (double)y );
166 }
167 #endif
168
169 #ifdef L_atanhl
170 WRAPPER1(atanh)
171 #endif
172
173 #ifdef L_atanl
174 WRAPPER1(atan)
175 #endif
176
177 #ifdef L_cargl
178 long double cargl (long double complex x)
179 {
180         return (long double) carg( (double complex)x );
181 }
182 #endif
183
184 #ifdef L_cbrtl
185 WRAPPER1(cbrt)
186 #endif
187
188 #ifdef L_ceill
189 WRAPPER1(ceil)
190 #endif
191
192 #ifdef L_copysignl
193 long double copysignl (long double x, long double y)
194 {
195         return (long double) copysign( (double)x, (double)y );
196 }
197 #endif
198
199 #ifdef L_coshl
200 WRAPPER1(cosh)
201 #endif
202
203 #ifdef L_cosl
204 WRAPPER1(cos)
205 #endif
206
207 #ifdef L_erfcl
208 WRAPPER1(erfc)
209 #endif
210
211 #ifdef L_erfl
212 WRAPPER1(erf)
213 #endif
214
215 #ifdef L_exp2l
216 WRAPPER1(exp2)
217 #endif
218
219 #ifdef L_expl
220 WRAPPER1(exp)
221 #endif
222
223 #ifdef L_expm1l
224 WRAPPER1(expm1)
225 #endif
226
227 #ifdef L_fabsl
228 WRAPPER1(fabs)
229 #endif
230
231 #ifdef L_fdiml
232 long double fdiml (long double x, long double y)
233 {
234         return (long double) fdim( (double)x, (double)y );
235 }
236 #endif
237
238 #ifdef L_floorl
239 WRAPPER1(floor)
240 #endif
241
242 #ifdef L_fmal
243 long double fmal (long double x, long double y, long double z)
244 {
245         return (long double) fma( (double)x, (double)y, (double)z );
246 }
247 #endif
248
249 #ifdef L_fmaxl
250 long double fmaxl (long double x, long double y)
251 {
252         return (long double) fmax( (double)x, (double)y );
253 }
254 #endif
255
256 #ifdef L_fminl
257 long double fminl (long double x, long double y)
258 {
259         return (long double) fmin( (double)x, (double)y );
260 }
261 #endif
262
263 #ifdef L_fmodl
264 long double fmodl (long double x, long double y)
265 {
266         return (long double) fmod( (double)x, (double)y );
267 }
268 #endif
269
270 #ifdef L_frexpl
271 long double frexpl (long double x, int *exp)
272 {
273         return (long double) frexp( (double)x, exp );
274 }
275 #endif
276
277 #ifdef L_hypotl
278 long double hypotl (long double x, long double y)
279 {
280         return (long double) hypot( (double)x, (double)y );
281 }
282 #endif
283
284 #ifdef L_ilogbl
285 int_WRAPPER1(ilogb)
286 #endif
287
288 #ifdef L_ldexpl
289 long double ldexpl (long double x, int exp)
290 {
291         return (long double) ldexp( (double)x, exp );
292 }
293 #endif
294
295 #ifdef L_lgammal
296 WRAPPER1(lgamma)
297 #endif
298
299 #ifdef L_llrintl
300 long long llrintl (long double x)
301 {
302         return llrint( (double)x );
303 }
304 #endif
305
306 #ifdef L_llroundl
307 long long llroundl (long double x)
308 {
309         return llround( (double)x );
310 }
311 #endif
312
313 #ifdef L_log10l
314 WRAPPER1(log10)
315 #endif
316
317 #ifdef L_log1pl
318 WRAPPER1(log1p)
319 #endif
320
321 #ifdef L_log2l
322 WRAPPER1(log2)
323 #endif
324
325 #ifdef L_logbl
326 WRAPPER1(logb)
327 #endif
328
329 #ifdef L_logl
330 WRAPPER1(log)
331 #endif
332
333 #ifdef L_lrintl
334 long lrintl (long double x)
335 {
336         return lrint( (double)x );
337 }
338 #endif
339
340 #ifdef L_lroundl
341 long lroundl (long double x)
342 {
343         return lround( (double)x );
344 }
345 #endif
346
347 #ifdef L_modfl
348 long double modfl (long double x, long double *iptr)
349 {
350         double y, result;
351         result = modf ( x, &y );
352         *iptr = (long double)y;
353         return (long double) result;
354 }
355 #endif
356
357 #ifdef L_nearbyintl
358 WRAPPER1(nearbyint)
359 #endif
360
361 #ifdef L_nextafterl
362 long double nextafterl (long double x, long double y)
363 {
364         return (long double) nextafter( (double)x, (double)y );
365 }
366 #endif
367
368 #ifdef L_nexttowardl
369 long double nexttowardl (long double x, long double y)
370 {
371         return (long double) nexttoward( (double)x, (double)y );
372 }
373 #endif
374
375 #ifdef L_powl
376 long double powl (long double x, long double y)
377 {
378         return (long double) pow( (double)x, (double)y );
379 }
380 #endif
381
382 #ifdef L_remainderl
383 long double remainderl (long double x, long double y)
384 {
385         return (long double) remainder( (double)x, (double)y );
386 }
387 #endif
388
389 #ifdef L_remquol
390 long double remquol (long double x, long double y, int *quo)
391 {
392         return (long double) remquo( (double)x, (double)y, quo );
393 }
394 #endif
395
396 #ifdef L_rintl
397 WRAPPER1(rint)
398 #endif
399
400 #ifdef L_roundl
401 WRAPPER1(round)
402 #endif
403
404 #ifdef L_scalblnl
405 long double scalblnl (long double x, long exp)
406 {
407         return (long double) scalbln( (double)x, exp );
408 }
409 #endif
410
411 #ifdef L_scalbnl
412 long double scalbnl (long double x, int exp)
413 {
414         return (long double) scalbn( (double)x, exp );
415 }
416 #endif
417
418 #ifdef L_sinhl
419 WRAPPER1(sinh)
420 #endif
421
422 #ifdef L_sinl
423 WRAPPER1(sin)
424 #endif
425
426 #ifdef L_sqrtl
427 WRAPPER1(sqrt)
428 #endif
429
430 #ifdef L_tanhl
431 WRAPPER1(tanh)
432 #endif
433
434 #ifdef L_tanl
435 WRAPPER1(tan)
436 #endif
437
438 #ifdef L_tgammal
439 WRAPPER1(tgamma)
440 #endif
441
442 #ifdef L_truncl
443 WRAPPER1(trunc)
444 #endif
445
446 #ifdef __DO_C99_MATH__
447
448 #ifdef L_fpclassifyl
449 int_WRAPPER1(__fpclassify);
450 #endif
451
452 #ifdef L_finitel
453 int_WRAPPER1(__finite)
454 #endif
455
456 #ifdef L___signbitl
457 int_WRAPPER1(__signbit)
458 #endif
459
460 #ifdef L_isnanl
461 int_WRAPPER1(__isnan)
462 libm_hidden_def(__isnanl)
463 #endif
464
465 #ifdef L_isinfl
466 int_WRAPPER1(__isinf)
467 libm_hidden_def(__isinfl)
468 #endif
469
470 #endif