softfloat-native.h revision 2c538c86c15d597cc875dc926e4e39285c5625df
1/* Native implementation of soft float functions */ 2#include <math.h> 3 4#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) \ 5 || defined(CONFIG_SOLARIS) 6#include <ieeefp.h> 7#define fabsf(f) ((float)fabs(f)) 8#else 9#include <fenv.h> 10#endif 11 12#if defined(__OpenBSD__) || defined(__NetBSD__) 13#include <sys/param.h> 14#endif 15 16/* 17 * Define some C99-7.12.3 classification macros and 18 * some C99-.12.4 for Solaris systems OS less than 10, 19 * or Solaris 10 systems running GCC 3.x or less. 20 * Solaris 10 with GCC4 does not need these macros as they 21 * are defined in <iso/math_c99.h> with a compiler directive 22 */ 23#if defined(CONFIG_SOLARIS) && \ 24 ((CONFIG_SOLARIS_VERSION <= 9 ) || \ 25 ((CONFIG_SOLARIS_VERSION == 10) && (__GNUC__ < 4))) \ 26 || (defined(__OpenBSD__) && (OpenBSD < 200811)) 27/* 28 * C99 7.12.3 classification macros 29 * and 30 * C99 7.12.14 comparison macros 31 * 32 * ... do not work on Solaris 10 using GNU CC 3.4.x. 33 * Try to workaround the missing / broken C99 math macros. 34 */ 35#if defined(__OpenBSD__) 36#define unordered(x, y) (isnan(x) || isnan(y)) 37#endif 38 39#ifdef __NetBSD__ 40#ifndef isgreater 41#define isgreater(x, y) __builtin_isgreater(x, y) 42#endif 43#ifndef isgreaterequal 44#define isgreaterequal(x, y) __builtin_isgreaterequal(x, y) 45#endif 46#ifndef isless 47#define isless(x, y) __builtin_isless(x, y) 48#endif 49#ifndef islessequal 50#define islessequal(x, y) __builtin_islessequal(x, y) 51#endif 52#ifndef isunordered 53#define isunordered(x, y) __builtin_isunordered(x, y) 54#endif 55#endif 56 57 58#define isnormal(x) (fpclass(x) >= FP_NZERO) 59#define isgreater(x, y) ((!unordered(x, y)) && ((x) > (y))) 60#define isgreaterequal(x, y) ((!unordered(x, y)) && ((x) >= (y))) 61#define isless(x, y) ((!unordered(x, y)) && ((x) < (y))) 62#define islessequal(x, y) ((!unordered(x, y)) && ((x) <= (y))) 63#define isunordered(x,y) unordered(x, y) 64#endif 65 66#if defined(__sun__) && !defined(CONFIG_NEEDS_LIBSUNMATH) 67 68#ifndef isnan 69# define isnan(x) \ 70 (sizeof (x) == sizeof (long double) ? isnan_ld (x) \ 71 : sizeof (x) == sizeof (double) ? isnan_d (x) \ 72 : isnan_f (x)) 73static inline int isnan_f (float x) { return x != x; } 74static inline int isnan_d (double x) { return x != x; } 75static inline int isnan_ld (long double x) { return x != x; } 76#endif 77 78#ifndef isinf 79# define isinf(x) \ 80 (sizeof (x) == sizeof (long double) ? isinf_ld (x) \ 81 : sizeof (x) == sizeof (double) ? isinf_d (x) \ 82 : isinf_f (x)) 83static inline int isinf_f (float x) { return isnan (x - x); } 84static inline int isinf_d (double x) { return isnan (x - x); } 85static inline int isinf_ld (long double x) { return isnan (x - x); } 86#endif 87#endif 88 89typedef float float32; 90typedef double float64; 91#ifdef FLOATX80 92typedef long double floatx80; 93#endif 94 95typedef union { 96 float32 f; 97 uint32_t i; 98} float32u; 99typedef union { 100 float64 f; 101 uint64_t i; 102} float64u; 103#ifdef FLOATX80 104typedef union { 105 floatx80 f; 106 struct { 107 uint64_t low; 108 uint16_t high; 109 } i; 110} floatx80u; 111#endif 112 113/*---------------------------------------------------------------------------- 114| Software IEC/IEEE floating-point rounding mode. 115*----------------------------------------------------------------------------*/ 116#if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) \ 117 || defined(CONFIG_SOLARIS) 118#if defined(__OpenBSD__) 119#define FE_RM FP_RM 120#define FE_RP FP_RP 121#define FE_RZ FP_RZ 122#endif 123enum { 124 float_round_nearest_even = FP_RN, 125 float_round_down = FP_RM, 126 float_round_up = FP_RP, 127 float_round_to_zero = FP_RZ 128}; 129#elif defined(__arm__) 130enum { 131 float_round_nearest_even = 0, 132 float_round_down = 1, 133 float_round_up = 2, 134 float_round_to_zero = 3 135}; 136#else 137enum { 138 float_round_nearest_even = FE_TONEAREST, 139 float_round_down = FE_DOWNWARD, 140 float_round_up = FE_UPWARD, 141 float_round_to_zero = FE_TOWARDZERO 142}; 143#endif 144 145typedef struct float_status { 146 int float_rounding_mode; 147#ifdef FLOATX80 148 int floatx80_rounding_precision; 149#endif 150} float_status; 151 152void set_float_rounding_mode(int val STATUS_PARAM); 153#ifdef FLOATX80 154void set_floatx80_rounding_precision(int val STATUS_PARAM); 155#endif 156 157/*---------------------------------------------------------------------------- 158| Software IEC/IEEE integer-to-floating-point conversion routines. 159*----------------------------------------------------------------------------*/ 160float32 int32_to_float32( int STATUS_PARAM); 161float32 uint32_to_float32( unsigned int STATUS_PARAM); 162float64 int32_to_float64( int STATUS_PARAM); 163float64 uint32_to_float64( unsigned int STATUS_PARAM); 164#ifdef FLOATX80 165floatx80 int32_to_floatx80( int STATUS_PARAM); 166#endif 167#ifdef FLOAT128 168float128 int32_to_float128( int STATUS_PARAM); 169#endif 170float32 int64_to_float32( int64_t STATUS_PARAM); 171float32 uint64_to_float32( uint64_t STATUS_PARAM); 172float64 int64_to_float64( int64_t STATUS_PARAM); 173float64 uint64_to_float64( uint64_t v STATUS_PARAM); 174#ifdef FLOATX80 175floatx80 int64_to_floatx80( int64_t STATUS_PARAM); 176#endif 177#ifdef FLOAT128 178float128 int64_to_float128( int64_t STATUS_PARAM); 179#endif 180 181/*---------------------------------------------------------------------------- 182| Software IEC/IEEE single-precision conversion routines. 183*----------------------------------------------------------------------------*/ 184int float32_to_int32( float32 STATUS_PARAM); 185int float32_to_int32_round_to_zero( float32 STATUS_PARAM); 186unsigned int float32_to_uint32( float32 a STATUS_PARAM); 187unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM); 188int64_t float32_to_int64( float32 STATUS_PARAM); 189int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM); 190float64 float32_to_float64( float32 STATUS_PARAM); 191#ifdef FLOATX80 192floatx80 float32_to_floatx80( float32 STATUS_PARAM); 193#endif 194#ifdef FLOAT128 195float128 float32_to_float128( float32 STATUS_PARAM); 196#endif 197 198/*---------------------------------------------------------------------------- 199| Software IEC/IEEE single-precision operations. 200*----------------------------------------------------------------------------*/ 201float32 float32_round_to_int( float32 STATUS_PARAM); 202INLINE float32 float32_add( float32 a, float32 b STATUS_PARAM) 203{ 204 return a + b; 205} 206INLINE float32 float32_sub( float32 a, float32 b STATUS_PARAM) 207{ 208 return a - b; 209} 210INLINE float32 float32_mul( float32 a, float32 b STATUS_PARAM) 211{ 212 return a * b; 213} 214INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM) 215{ 216 return a / b; 217} 218float32 float32_rem( float32, float32 STATUS_PARAM); 219float32 float32_sqrt( float32 STATUS_PARAM); 220INLINE int float32_eq( float32 a, float32 b STATUS_PARAM) 221{ 222 return a == b; 223} 224INLINE int float32_le( float32 a, float32 b STATUS_PARAM) 225{ 226 return a <= b; 227} 228INLINE int float32_lt( float32 a, float32 b STATUS_PARAM) 229{ 230 return a < b; 231} 232INLINE int float32_eq_signaling( float32 a, float32 b STATUS_PARAM) 233{ 234 return a <= b && a >= b; 235} 236INLINE int float32_le_quiet( float32 a, float32 b STATUS_PARAM) 237{ 238 return islessequal(a, b); 239} 240INLINE int float32_lt_quiet( float32 a, float32 b STATUS_PARAM) 241{ 242 return isless(a, b); 243} 244INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM) 245{ 246 return isunordered(a, b); 247 248} 249int float32_compare( float32, float32 STATUS_PARAM ); 250int float32_compare_quiet( float32, float32 STATUS_PARAM ); 251int float32_is_signaling_nan( float32 ); 252int float32_is_nan( float32 ); 253 254INLINE float32 float32_abs(float32 a) 255{ 256 return fabsf(a); 257} 258 259INLINE float32 float32_chs(float32 a) 260{ 261 return -a; 262} 263 264INLINE float32 float32_is_infinity(float32 a) 265{ 266 return fpclassify(a) == FP_INFINITE; 267} 268 269INLINE float32 float32_is_neg(float32 a) 270{ 271 float32u u; 272 u.f = a; 273 return u.i >> 31; 274} 275 276INLINE float32 float32_is_zero(float32 a) 277{ 278 return fpclassify(a) == FP_ZERO; 279} 280 281INLINE float32 float32_scalbn(float32 a, int n) 282{ 283 return scalbnf(a, n); 284} 285 286/*---------------------------------------------------------------------------- 287| Software IEC/IEEE double-precision conversion routines. 288*----------------------------------------------------------------------------*/ 289int float64_to_int32( float64 STATUS_PARAM ); 290int float64_to_int32_round_to_zero( float64 STATUS_PARAM ); 291unsigned int float64_to_uint32( float64 STATUS_PARAM ); 292unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM ); 293int64_t float64_to_int64( float64 STATUS_PARAM ); 294int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM ); 295uint64_t float64_to_uint64( float64 STATUS_PARAM ); 296uint64_t float64_to_uint64_round_to_zero( float64 STATUS_PARAM ); 297float32 float64_to_float32( float64 STATUS_PARAM ); 298#ifdef FLOATX80 299floatx80 float64_to_floatx80( float64 STATUS_PARAM ); 300#endif 301#ifdef FLOAT128 302float128 float64_to_float128( float64 STATUS_PARAM ); 303#endif 304 305/*---------------------------------------------------------------------------- 306| Software IEC/IEEE double-precision operations. 307*----------------------------------------------------------------------------*/ 308float64 float64_round_to_int( float64 STATUS_PARAM ); 309float64 float64_trunc_to_int( float64 STATUS_PARAM ); 310INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM) 311{ 312 return a + b; 313} 314INLINE float64 float64_sub( float64 a, float64 b STATUS_PARAM) 315{ 316 return a - b; 317} 318INLINE float64 float64_mul( float64 a, float64 b STATUS_PARAM) 319{ 320 return a * b; 321} 322INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM) 323{ 324 return a / b; 325} 326float64 float64_rem( float64, float64 STATUS_PARAM ); 327float64 float64_sqrt( float64 STATUS_PARAM ); 328INLINE int float64_eq( float64 a, float64 b STATUS_PARAM) 329{ 330 return a == b; 331} 332INLINE int float64_le( float64 a, float64 b STATUS_PARAM) 333{ 334 return a <= b; 335} 336INLINE int float64_lt( float64 a, float64 b STATUS_PARAM) 337{ 338 return a < b; 339} 340INLINE int float64_eq_signaling( float64 a, float64 b STATUS_PARAM) 341{ 342 return a <= b && a >= b; 343} 344INLINE int float64_le_quiet( float64 a, float64 b STATUS_PARAM) 345{ 346 return islessequal(a, b); 347} 348INLINE int float64_lt_quiet( float64 a, float64 b STATUS_PARAM) 349{ 350 return isless(a, b); 351 352} 353INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM) 354{ 355 return isunordered(a, b); 356 357} 358int float64_compare( float64, float64 STATUS_PARAM ); 359int float64_compare_quiet( float64, float64 STATUS_PARAM ); 360int float64_is_signaling_nan( float64 ); 361int float64_is_nan( float64 ); 362 363INLINE float64 float64_abs(float64 a) 364{ 365 return fabs(a); 366} 367 368INLINE float64 float64_chs(float64 a) 369{ 370 return -a; 371} 372 373INLINE float64 float64_is_infinity(float64 a) 374{ 375 return fpclassify(a) == FP_INFINITE; 376} 377 378INLINE float64 float64_is_neg(float64 a) 379{ 380 float64u u; 381 u.f = a; 382 return u.i >> 63; 383} 384 385INLINE float64 float64_is_zero(float64 a) 386{ 387 return fpclassify(a) == FP_ZERO; 388} 389 390INLINE float64 float64_scalbn(float64 a, int n) 391{ 392 return scalbn(a, n); 393} 394 395#ifdef FLOATX80 396 397/*---------------------------------------------------------------------------- 398| Software IEC/IEEE extended double-precision conversion routines. 399*----------------------------------------------------------------------------*/ 400int floatx80_to_int32( floatx80 STATUS_PARAM ); 401int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM ); 402int64_t floatx80_to_int64( floatx80 STATUS_PARAM); 403int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM); 404float32 floatx80_to_float32( floatx80 STATUS_PARAM ); 405float64 floatx80_to_float64( floatx80 STATUS_PARAM ); 406#ifdef FLOAT128 407float128 floatx80_to_float128( floatx80 STATUS_PARAM ); 408#endif 409 410/*---------------------------------------------------------------------------- 411| Software IEC/IEEE extended double-precision operations. 412*----------------------------------------------------------------------------*/ 413floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM ); 414INLINE floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM) 415{ 416 return a + b; 417} 418INLINE floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM) 419{ 420 return a - b; 421} 422INLINE floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM) 423{ 424 return a * b; 425} 426INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM) 427{ 428 return a / b; 429} 430floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM ); 431floatx80 floatx80_sqrt( floatx80 STATUS_PARAM ); 432INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM) 433{ 434 return a == b; 435} 436INLINE int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM) 437{ 438 return a <= b; 439} 440INLINE int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM) 441{ 442 return a < b; 443} 444INLINE int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM) 445{ 446 return a <= b && a >= b; 447} 448INLINE int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM) 449{ 450 return islessequal(a, b); 451} 452INLINE int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM) 453{ 454 return isless(a, b); 455 456} 457INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM) 458{ 459 return isunordered(a, b); 460 461} 462int floatx80_compare( floatx80, floatx80 STATUS_PARAM ); 463int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM ); 464int floatx80_is_signaling_nan( floatx80 ); 465int floatx80_is_nan( floatx80 ); 466 467INLINE floatx80 floatx80_abs(floatx80 a) 468{ 469 return fabsl(a); 470} 471 472INLINE floatx80 floatx80_chs(floatx80 a) 473{ 474 return -a; 475} 476 477INLINE floatx80 floatx80_is_infinity(floatx80 a) 478{ 479 return fpclassify(a) == FP_INFINITE; 480} 481 482INLINE floatx80 floatx80_is_neg(floatx80 a) 483{ 484 floatx80u u; 485 u.f = a; 486 return u.i.high >> 15; 487} 488 489INLINE floatx80 floatx80_is_zero(floatx80 a) 490{ 491 return fpclassify(a) == FP_ZERO; 492} 493 494INLINE floatx80 floatx80_scalbn(floatx80 a, int n) 495{ 496 return scalbnl(a, n); 497} 498 499#endif 500