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