1 /* Native implementation of soft float functions. Only a single status 2 context is supported */ 3 #include "softfloat.h" 4 #include <math.h> 5 #if defined(CONFIG_SOLARIS) 6 #include <fenv.h> 7 #endif 8 9 void set_float_rounding_mode(int val STATUS_PARAM) 10 { 11 STATUS(float_rounding_mode) = val; 12 #if (defined(CONFIG_BSD) && !defined(__APPLE__) && !defined(__GLIBC__)) || \ 13 (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) 14 fpsetround(val); 15 #else 16 fesetround(val); 17 #endif 18 } 19 20 #ifdef FLOATX80 21 void set_floatx80_rounding_precision(int val STATUS_PARAM) 22 { 23 STATUS(floatx80_rounding_precision) = val; 24 } 25 #endif 26 27 #if defined(CONFIG_BSD) || \ 28 (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) 29 #define lrint(d) ((int32_t)rint(d)) 30 #define llrint(d) ((int64_t)rint(d)) 31 #define lrintf(f) ((int32_t)rint(f)) 32 #define llrintf(f) ((int64_t)rint(f)) 33 #define sqrtf(f) ((float)sqrt(f)) 34 #define remainderf(fa, fb) ((float)remainder(fa, fb)) 35 #define rintf(f) ((float)rint(f)) 36 #if !defined(__sparc__) && \ 37 (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) 38 extern long double rintl(long double); 39 extern long double scalbnl(long double, int); 40 41 long long 42 llrintl(long double x) { 43 return ((long long) rintl(x)); 44 } 45 46 long 47 lrintl(long double x) { 48 return ((long) rintl(x)); 49 } 50 51 long double 52 ldexpl(long double x, int n) { 53 return (scalbnl(x, n)); 54 } 55 #endif 56 #endif 57 58 #if defined(_ARCH_PPC) 59 60 /* correct (but slow) PowerPC rint() (glibc version is incorrect) */ 61 static double qemu_rint(double x) 62 { 63 double y = 4503599627370496.0; 64 if (fabs(x) >= y) 65 return x; 66 if (x < 0) 67 y = -y; 68 y = (x + y) - y; 69 if (y == 0.0) 70 y = copysign(y, x); 71 return y; 72 } 73 74 #define rint qemu_rint 75 #endif 76 77 /*---------------------------------------------------------------------------- 78 | Software IEC/IEEE integer-to-floating-point conversion routines. 79 *----------------------------------------------------------------------------*/ 80 float32 int32_to_float32(int v STATUS_PARAM) 81 { 82 return (float32)v; 83 } 84 85 float32 uint32_to_float32(unsigned int v STATUS_PARAM) 86 { 87 return (float32)v; 88 } 89 90 float64 int32_to_float64(int v STATUS_PARAM) 91 { 92 return (float64)v; 93 } 94 95 float64 uint32_to_float64(unsigned int v STATUS_PARAM) 96 { 97 return (float64)v; 98 } 99 100 #ifdef FLOATX80 101 floatx80 int32_to_floatx80(int v STATUS_PARAM) 102 { 103 return (floatx80)v; 104 } 105 #endif 106 float32 int64_to_float32( int64_t v STATUS_PARAM) 107 { 108 return (float32)v; 109 } 110 float32 uint64_to_float32( uint64_t v STATUS_PARAM) 111 { 112 return (float32)v; 113 } 114 float64 int64_to_float64( int64_t v STATUS_PARAM) 115 { 116 return (float64)v; 117 } 118 float64 uint64_to_float64( uint64_t v STATUS_PARAM) 119 { 120 return (float64)v; 121 } 122 #ifdef FLOATX80 123 floatx80 int64_to_floatx80( int64_t v STATUS_PARAM) 124 { 125 return (floatx80)v; 126 } 127 #endif 128 129 /* XXX: this code implements the x86 behaviour, not the IEEE one. */ 130 #if HOST_LONG_BITS == 32 131 static inline int long_to_int32(long a) 132 { 133 return a; 134 } 135 #else 136 static inline int long_to_int32(long a) 137 { 138 if (a != (int32_t)a) 139 a = 0x80000000; 140 return a; 141 } 142 #endif 143 144 /*---------------------------------------------------------------------------- 145 | Software IEC/IEEE single-precision conversion routines. 146 *----------------------------------------------------------------------------*/ 147 int float32_to_int32( float32 a STATUS_PARAM) 148 { 149 return long_to_int32(lrintf(a)); 150 } 151 int float32_to_int32_round_to_zero( float32 a STATUS_PARAM) 152 { 153 return (int)a; 154 } 155 int64_t float32_to_int64( float32 a STATUS_PARAM) 156 { 157 return llrintf(a); 158 } 159 160 int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM) 161 { 162 return (int64_t)a; 163 } 164 165 float64 float32_to_float64( float32 a STATUS_PARAM) 166 { 167 return a; 168 } 169 #ifdef FLOATX80 170 floatx80 float32_to_floatx80( float32 a STATUS_PARAM) 171 { 172 return a; 173 } 174 #endif 175 176 unsigned int float32_to_uint32( float32 a STATUS_PARAM) 177 { 178 int64_t v; 179 unsigned int res; 180 181 v = llrintf(a); 182 if (v < 0) { 183 res = 0; 184 } else if (v > 0xffffffff) { 185 res = 0xffffffff; 186 } else { 187 res = v; 188 } 189 return res; 190 } 191 unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM) 192 { 193 int64_t v; 194 unsigned int res; 195 196 v = (int64_t)a; 197 if (v < 0) { 198 res = 0; 199 } else if (v > 0xffffffff) { 200 res = 0xffffffff; 201 } else { 202 res = v; 203 } 204 return res; 205 } 206 207 /*---------------------------------------------------------------------------- 208 | Software IEC/IEEE single-precision operations. 209 *----------------------------------------------------------------------------*/ 210 float32 float32_round_to_int( float32 a STATUS_PARAM) 211 { 212 return rintf(a); 213 } 214 215 float32 float32_rem( float32 a, float32 b STATUS_PARAM) 216 { 217 return remainderf(a, b); 218 } 219 220 float32 float32_sqrt( float32 a STATUS_PARAM) 221 { 222 return sqrtf(a); 223 } 224 int float32_compare( float32 a, float32 b STATUS_PARAM ) 225 { 226 if (a < b) { 227 return float_relation_less; 228 } else if (a == b) { 229 return float_relation_equal; 230 } else if (a > b) { 231 return float_relation_greater; 232 } else { 233 return float_relation_unordered; 234 } 235 } 236 int float32_compare_quiet( float32 a, float32 b STATUS_PARAM ) 237 { 238 if (isless(a, b)) { 239 return float_relation_less; 240 } else if (a == b) { 241 return float_relation_equal; 242 } else if (isgreater(a, b)) { 243 return float_relation_greater; 244 } else { 245 return float_relation_unordered; 246 } 247 } 248 int float32_is_signaling_nan( float32 a1) 249 { 250 float32u u; 251 uint32_t a; 252 u.f = a1; 253 a = u.i; 254 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 255 } 256 257 int float32_is_quiet_nan( float32 a1 ) 258 { 259 float32u u; 260 uint64_t a; 261 u.f = a1; 262 a = u.i; 263 return ( 0xFF800000 < ( a<<1 ) ); 264 } 265 266 int float32_is_any_nan( float32 a1 ) 267 { 268 float32u u; 269 uint32_t a; 270 u.f = a1; 271 a = u.i; 272 return (a & ~(1 << 31)) > 0x7f800000U; 273 } 274 275 /*---------------------------------------------------------------------------- 276 | Software IEC/IEEE double-precision conversion routines. 277 *----------------------------------------------------------------------------*/ 278 int float64_to_int32( float64 a STATUS_PARAM) 279 { 280 return long_to_int32(lrint(a)); 281 } 282 int float64_to_int32_round_to_zero( float64 a STATUS_PARAM) 283 { 284 return (int)a; 285 } 286 int64_t float64_to_int64( float64 a STATUS_PARAM) 287 { 288 return llrint(a); 289 } 290 int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM) 291 { 292 return (int64_t)a; 293 } 294 float32 float64_to_float32( float64 a STATUS_PARAM) 295 { 296 return a; 297 } 298 #ifdef FLOATX80 299 floatx80 float64_to_floatx80( float64 a STATUS_PARAM) 300 { 301 return a; 302 } 303 #endif 304 #ifdef FLOAT128 305 float128 float64_to_float128( float64 a STATUS_PARAM) 306 { 307 return a; 308 } 309 #endif 310 311 unsigned int float64_to_uint32( float64 a STATUS_PARAM) 312 { 313 int64_t v; 314 unsigned int res; 315 316 v = llrint(a); 317 if (v < 0) { 318 res = 0; 319 } else if (v > 0xffffffff) { 320 res = 0xffffffff; 321 } else { 322 res = v; 323 } 324 return res; 325 } 326 unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM) 327 { 328 int64_t v; 329 unsigned int res; 330 331 v = (int64_t)a; 332 if (v < 0) { 333 res = 0; 334 } else if (v > 0xffffffff) { 335 res = 0xffffffff; 336 } else { 337 res = v; 338 } 339 return res; 340 } 341 uint64_t float64_to_uint64 (float64 a STATUS_PARAM) 342 { 343 int64_t v; 344 345 v = llrint(a + (float64)INT64_MIN); 346 347 return v - INT64_MIN; 348 } 349 uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM) 350 { 351 int64_t v; 352 353 v = (int64_t)(a + (float64)INT64_MIN); 354 355 return v - INT64_MIN; 356 } 357 358 /*---------------------------------------------------------------------------- 359 | Software IEC/IEEE double-precision operations. 360 *----------------------------------------------------------------------------*/ 361 #if defined(__sun__) && \ 362 (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) 363 static inline float64 trunc(float64 x) 364 { 365 return x < 0 ? -floor(-x) : floor(x); 366 } 367 #endif 368 float64 float64_trunc_to_int( float64 a STATUS_PARAM ) 369 { 370 return trunc(a); 371 } 372 373 float64 float64_round_to_int( float64 a STATUS_PARAM ) 374 { 375 return rint(a); 376 } 377 378 float64 float64_rem( float64 a, float64 b STATUS_PARAM) 379 { 380 return remainder(a, b); 381 } 382 383 float64 float64_sqrt( float64 a STATUS_PARAM) 384 { 385 return sqrt(a); 386 } 387 int float64_compare( float64 a, float64 b STATUS_PARAM ) 388 { 389 if (a < b) { 390 return float_relation_less; 391 } else if (a == b) { 392 return float_relation_equal; 393 } else if (a > b) { 394 return float_relation_greater; 395 } else { 396 return float_relation_unordered; 397 } 398 } 399 int float64_compare_quiet( float64 a, float64 b STATUS_PARAM ) 400 { 401 if (isless(a, b)) { 402 return float_relation_less; 403 } else if (a == b) { 404 return float_relation_equal; 405 } else if (isgreater(a, b)) { 406 return float_relation_greater; 407 } else { 408 return float_relation_unordered; 409 } 410 } 411 int float64_is_signaling_nan( float64 a1) 412 { 413 float64u u; 414 uint64_t a; 415 u.f = a1; 416 a = u.i; 417 return 418 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) 419 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); 420 421 } 422 423 int float64_is_quiet_nan( float64 a1 ) 424 { 425 float64u u; 426 uint64_t a; 427 u.f = a1; 428 a = u.i; 429 430 return ( LIT64( 0xFFF0000000000000 ) < (uint64_t) ( a<<1 ) ); 431 432 } 433 434 int float64_is_any_nan( float64 a1 ) 435 { 436 float64u u; 437 uint64_t a; 438 u.f = a1; 439 a = u.i; 440 441 return (a & ~(1ULL << 63)) > LIT64 (0x7FF0000000000000 ); 442 } 443 444 #ifdef FLOATX80 445 446 /*---------------------------------------------------------------------------- 447 | Software IEC/IEEE extended double-precision conversion routines. 448 *----------------------------------------------------------------------------*/ 449 int floatx80_to_int32( floatx80 a STATUS_PARAM) 450 { 451 return long_to_int32(lrintl(a)); 452 } 453 int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM) 454 { 455 return (int)a; 456 } 457 int64_t floatx80_to_int64( floatx80 a STATUS_PARAM) 458 { 459 return llrintl(a); 460 } 461 int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM) 462 { 463 return (int64_t)a; 464 } 465 float32 floatx80_to_float32( floatx80 a STATUS_PARAM) 466 { 467 return a; 468 } 469 float64 floatx80_to_float64( floatx80 a STATUS_PARAM) 470 { 471 return a; 472 } 473 474 /*---------------------------------------------------------------------------- 475 | Software IEC/IEEE extended double-precision operations. 476 *----------------------------------------------------------------------------*/ 477 floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM) 478 { 479 return rintl(a); 480 } 481 floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM) 482 { 483 return remainderl(a, b); 484 } 485 floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM) 486 { 487 return sqrtl(a); 488 } 489 int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM ) 490 { 491 if (a < b) { 492 return float_relation_less; 493 } else if (a == b) { 494 return float_relation_equal; 495 } else if (a > b) { 496 return float_relation_greater; 497 } else { 498 return float_relation_unordered; 499 } 500 } 501 int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM ) 502 { 503 if (isless(a, b)) { 504 return float_relation_less; 505 } else if (a == b) { 506 return float_relation_equal; 507 } else if (isgreater(a, b)) { 508 return float_relation_greater; 509 } else { 510 return float_relation_unordered; 511 } 512 } 513 int floatx80_is_signaling_nan( floatx80 a1) 514 { 515 floatx80u u; 516 uint64_t aLow; 517 u.f = a1; 518 519 aLow = u.i.low & ~ LIT64( 0x4000000000000000 ); 520 return 521 ( ( u.i.high & 0x7FFF ) == 0x7FFF ) 522 && (uint64_t) ( aLow<<1 ) 523 && ( u.i.low == aLow ); 524 } 525 526 int floatx80_is_quiet_nan( floatx80 a1 ) 527 { 528 floatx80u u; 529 u.f = a1; 530 return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (uint64_t) ( u.i.low<<1 ); 531 } 532 533 int floatx80_is_any_nan( floatx80 a1 ) 534 { 535 floatx80u u; 536 u.f = a1; 537 return ((u.i.high & 0x7FFF) == 0x7FFF) && ( u.i.low<<1 ); 538 } 539 540 #endif 541