The asm code cannot currently be used with tcc since tcc doesn't support 't' constraint. Use inline C implementation instead, place it win32/include/tcc/tcc_libm.h, and include it from win32/include/math.h. Since fpclassify now works, it also fixes few other macros which depend on it. Implicitly fixed: isfinite, isinf, isnan, isnormal. The implementations were taken from musl-libc rs-1.0 (MIT license).
Unified · Split
| @@ -313,13 +313,9 @@ extern "C" { · 312 unmodified lines | ||
| 313 | 313 | |
| 314 | 314 | extern int __cdecl __fpclassifyf (float); |
| 315 | 315 | extern int __cdecl __fpclassify (double); |
| 316 | + extern int __cdecl __fpclassifyl (long double); | |
| 316 | 317 | |
| 317 | − __CRT_INLINE int __cdecl __fpclassifyl (long double x){ | |
| 318 | − unsigned short sw; | |
| 319 | − __asm__ ("fxam; fstsw %%ax;" : "=a" (sw): "t" (x)); | |
| 320 | − return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); | |
| 321 | − } | |
| 322 | − | |
| 318 | +/* Implemented at tcc/tcc_libm.h */ | |
| 323 | 319 | #define fpclassify(x) (sizeof (x) == sizeof (float) ? __fpclassifyf (x) \ |
| 324 | 320 | : sizeof (x) == sizeof (double) ? __fpclassify (x) \ |
| 325 | 321 | : __fpclassifyl (x)) |
| @@ -339,24 +335,12 @@ extern "C" { · 13 unmodified lines | ||
| 339 | 335 | #define isnormal(x) (fpclassify(x) == FP_NORMAL) |
| 340 | 336 | |
| 341 | 337 | /* 7.12.3.6 The signbit macro */ |
| 342 | − __CRT_INLINE int __cdecl __signbit (double x) { | |
| 343 | − unsigned short stw; | |
| 344 | − __asm__ ( "fxam; fstsw %%ax;": "=a" (stw) : "t" (x)); | |
| 345 | − return stw & 0x0200; | |
| 346 | − } | |
| 347 | 338 | |
| 348 | − __CRT_INLINE int __cdecl __signbitf (float x) { | |
| 349 | − unsigned short stw; | |
| 350 | − __asm__ ("fxam; fstsw %%ax;": "=a" (stw) : "t" (x)); | |
| 351 | − return stw & 0x0200; | |
| 352 | − } | |
| 353 | − | |
| 354 | − __CRT_INLINE int __cdecl __signbitl (long double x) { | |
| 355 | − unsigned short stw; | |
| 356 | − __asm__ ("fxam; fstsw %%ax;": "=a" (stw) : "t" (x)); | |
| 357 | − return stw & 0x0200; | |
| 358 | − } | |
| 339 | + extern int __cdecl __signbitf (float); | |
| 340 | + extern int __cdecl __signbit (double); | |
| 341 | + extern int __cdecl __signbitl (long double); | |
| 359 | 342 | |
| 343 | +/* Implemented at tcc/tcc_libm.h */ | |
| 360 | 344 | #define signbit(x) (sizeof (x) == sizeof (float) ? __signbitf (x) \ |
| 361 | 345 | : sizeof (x) == sizeof (double) ? __signbit (x) \ |
| 362 | 346 | : __signbitl (x)) |
| @@ -746,5 +730,8 @@ extern "C++" { · 383 unmodified lines | ||
| 746 | 730 | * which always returns true: yes, (NaN != NaN) is true). |
| 747 | 731 | */ |
| 748 | 732 | |
| 733 | +/* Mini libm (inline __fpclassify*, __signbit* and variants) */ | |
| 734 | +#include "tcc/tcc_libm.h" | |
| 735 | + | |
| 749 | 736 | #endif /* End _MATH_H_ */ |
| 750 | 737 | |
| @@ -0,0 +1,88 @@ | ||
| 1 | +#ifndef _TCC_LIBM_H_ | |
| 2 | +#define _TCC_LIBM_H_ | |
| 3 | + | |
| 4 | +#include "../include/math.h" | |
| 5 | + | |
| 6 | +/* TCC uses 8 bytes for double and long double, so effectively the l variants | |
| 7 | + * are never used. For now, they just run the normal (double) variant. | |
| 8 | + */ | |
| 9 | + | |
| 10 | +/* | |
| 11 | + * most of the code in this file is taken from MUSL rs-1.0 (MIT license) | |
| 12 | + * - musl-libc: http://git.musl-libc.org/cgit/musl/tree/src/math?h=rs-1.0 | |
| 13 | + * - License: http://git.musl-libc.org/cgit/musl/tree/COPYRIGHT?h=rs-1.0 | |
| 14 | + */ | |
| 15 | + | |
| 16 | +/******************************************************************************* | |
| 17 | + Start of code based on MUSL | |
| 18 | +*******************************************************************************/ | |
| 19 | +/* | |
| 20 | +musl as a whole is licensed under the following standard MIT license: | |
| 21 | + | |
| 22 | +---------------------------------------------------------------------- | |
| 23 | +Copyright � 2005-2014 Rich Felker, et al. | |
| 24 | + | |
| 25 | +Permission is hereby granted, free of charge, to any person obtaining | |
| 26 | +a copy of this software and associated documentation files (the | |
| 27 | +"Software"), to deal in the Software without restriction, including | |
| 28 | +without limitation the rights to use, copy, modify, merge, publish, | |
| 29 | +distribute, sublicense, and/or sell copies of the Software, and to | |
| 30 | +permit persons to whom the Software is furnished to do so, subject to | |
| 31 | +the following conditions: | |
| 32 | + | |
| 33 | +The above copyright notice and this permission notice shall be | |
| 34 | +included in all copies or substantial portions of the Software. | |
| 35 | + | |
| 36 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 37 | +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| 38 | +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| 39 | +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| 40 | +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| 41 | +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| 42 | +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 43 | +---------------------------------------------------------------------- | |
| 44 | +*/ | |
| 45 | + | |
| 46 | +/* fpclassify */ | |
| 47 | + | |
| 48 | +__CRT_INLINE int __cdecl __fpclassify (double x) { | |
| 49 | + union {double f; uint64_t i;} u = {x}; | |
| 50 | + int e = u.i>>52 & 0x7ff; | |
| 51 | + if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; | |
| 52 | + if (e==0x7ff) return u.i<<12 ? FP_NAN : FP_INFINITE; | |
| 53 | + return FP_NORMAL; | |
| 54 | +} | |
| 55 | + | |
| 56 | +__CRT_INLINE int __cdecl __fpclassifyf (float x) { | |
| 57 | + union {float f; uint32_t i;} u = {x}; | |
| 58 | + int e = u.i>>23 & 0xff; | |
| 59 | + if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; | |
| 60 | + if (e==0xff) return u.i<<9 ? FP_NAN : FP_INFINITE; | |
| 61 | + return FP_NORMAL; | |
| 62 | +} | |
| 63 | + | |
| 64 | +__CRT_INLINE int __cdecl __fpclassifyl (long double x) { | |
| 65 | + return __fpclassify(x); | |
| 66 | +} | |
| 67 | + | |
| 68 | +/* signbit */ | |
| 69 | + | |
| 70 | +__CRT_INLINE int __cdecl __signbit (double x) { | |
| 71 | + union {double d; uint64_t i;} y = { x }; | |
| 72 | + return y.i>>63; | |
| 73 | +} | |
| 74 | + | |
| 75 | +__CRT_INLINE int __cdecl __signbitf (float x) { | |
| 76 | + union {float f; uint32_t i; } y = { x }; | |
| 77 | + return y.i>>31; | |
| 78 | +} | |
| 79 | + | |
| 80 | +__CRT_INLINE int __cdecl __signbitl (long double x) { | |
| 81 | + return __signbit(x); | |
| 82 | +} | |
| 83 | + | |
| 84 | +/******************************************************************************* | |
| 85 | + End of code based on MUSL | |
| 86 | +*******************************************************************************/ | |
| 87 | + | |
| 88 | +#endif /* _TCC_LIBM_H_ */ | |