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_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 /*---------------------------------------------------------------------------- 267 | Software IEC/IEEE double-precision conversion routines. 268 *----------------------------------------------------------------------------*/ 269 int float64_to_int32( float64 a STATUS_PARAM) 270 { 271 return long_to_int32(lrint(a)); 272 } 273 int float64_to_int32_round_to_zero( float64 a STATUS_PARAM) 274 { 275 return (int)a; 276 } 277 int64_t float64_to_int64( float64 a STATUS_PARAM) 278 { 279 return llrint(a); 280 } 281 int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM) 282 { 283 return (int64_t)a; 284 } 285 float32 float64_to_float32( float64 a STATUS_PARAM) 286 { 287 return a; 288 } 289 #ifdef FLOATX80 290 floatx80 float64_to_floatx80( float64 a STATUS_PARAM) 291 { 292 return a; 293 } 294 #endif 295 #ifdef FLOAT128 296 float128 float64_to_float128( float64 a STATUS_PARAM) 297 { 298 return a; 299 } 300 #endif 301 302 unsigned int float64_to_uint32( float64 a STATUS_PARAM) 303 { 304 int64_t v; 305 unsigned int res; 306 307 v = llrint(a); 308 if (v < 0) { 309 res = 0; 310 } else if (v > 0xffffffff) { 311 res = 0xffffffff; 312 } else { 313 res = v; 314 } 315 return res; 316 } 317 unsigned int float64_to_uint32_round_to_zero( float64 a STATUS_PARAM) 318 { 319 int64_t v; 320 unsigned int res; 321 322 v = (int64_t)a; 323 if (v < 0) { 324 res = 0; 325 } else if (v > 0xffffffff) { 326 res = 0xffffffff; 327 } else { 328 res = v; 329 } 330 return res; 331 } 332 uint64_t float64_to_uint64 (float64 a STATUS_PARAM) 333 { 334 int64_t v; 335 336 v = llrint(a + (float64)INT64_MIN); 337 338 return v - INT64_MIN; 339 } 340 uint64_t float64_to_uint64_round_to_zero (float64 a STATUS_PARAM) 341 { 342 int64_t v; 343 344 v = (int64_t)(a + (float64)INT64_MIN); 345 346 return v - INT64_MIN; 347 } 348 349 /*---------------------------------------------------------------------------- 350 | Software IEC/IEEE double-precision operations. 351 *----------------------------------------------------------------------------*/ 352 #if defined(__sun__) && \ 353 (defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10) 354 static inline float64 trunc(float64 x) 355 { 356 return x < 0 ? -floor(-x) : floor(x); 357 } 358 #endif 359 float64 float64_trunc_to_int( float64 a STATUS_PARAM ) 360 { 361 return trunc(a); 362 } 363 364 float64 float64_round_to_int( float64 a STATUS_PARAM ) 365 { 366 return rint(a); 367 } 368 369 float64 float64_rem( float64 a, float64 b STATUS_PARAM) 370 { 371 return remainder(a, b); 372 } 373 374 float64 float64_sqrt( float64 a STATUS_PARAM) 375 { 376 return sqrt(a); 377 } 378 int float64_compare( float64 a, float64 b STATUS_PARAM ) 379 { 380 if (a < b) { 381 return float_relation_less; 382 } else if (a == b) { 383 return float_relation_equal; 384 } else if (a > b) { 385 return float_relation_greater; 386 } else { 387 return float_relation_unordered; 388 } 389 } 390 int float64_compare_quiet( float64 a, float64 b STATUS_PARAM ) 391 { 392 if (isless(a, b)) { 393 return float_relation_less; 394 } else if (a == b) { 395 return float_relation_equal; 396 } else if (isgreater(a, b)) { 397 return float_relation_greater; 398 } else { 399 return float_relation_unordered; 400 } 401 } 402 int float64_is_signaling_nan( float64 a1) 403 { 404 float64u u; 405 uint64_t a; 406 u.f = a1; 407 a = u.i; 408 return 409 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) 410 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); 411 412 } 413 414 int float64_is_nan( float64 a1 ) 415 { 416 float64u u; 417 uint64_t a; 418 u.f = a1; 419 a = u.i; 420 421 return ( LIT64( 0xFFF0000000000000 ) < (bits64) ( a<<1 ) ); 422 423 } 424 425 #ifdef FLOATX80 426 427 /*---------------------------------------------------------------------------- 428 | Software IEC/IEEE extended double-precision conversion routines. 429 *----------------------------------------------------------------------------*/ 430 int floatx80_to_int32( floatx80 a STATUS_PARAM) 431 { 432 return long_to_int32(lrintl(a)); 433 } 434 int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM) 435 { 436 return (int)a; 437 } 438 int64_t floatx80_to_int64( floatx80 a STATUS_PARAM) 439 { 440 return llrintl(a); 441 } 442 int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM) 443 { 444 return (int64_t)a; 445 } 446 float32 floatx80_to_float32( floatx80 a STATUS_PARAM) 447 { 448 return a; 449 } 450 float64 floatx80_to_float64( floatx80 a STATUS_PARAM) 451 { 452 return a; 453 } 454 455 /*---------------------------------------------------------------------------- 456 | Software IEC/IEEE extended double-precision operations. 457 *----------------------------------------------------------------------------*/ 458 floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM) 459 { 460 return rintl(a); 461 } 462 floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM) 463 { 464 return remainderl(a, b); 465 } 466 floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM) 467 { 468 return sqrtl(a); 469 } 470 int floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM ) 471 { 472 if (a < b) { 473 return float_relation_less; 474 } else if (a == b) { 475 return float_relation_equal; 476 } else if (a > b) { 477 return float_relation_greater; 478 } else { 479 return float_relation_unordered; 480 } 481 } 482 int floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM ) 483 { 484 if (isless(a, b)) { 485 return float_relation_less; 486 } else if (a == b) { 487 return float_relation_equal; 488 } else if (isgreater(a, b)) { 489 return float_relation_greater; 490 } else { 491 return float_relation_unordered; 492 } 493 } 494 int floatx80_is_signaling_nan( floatx80 a1) 495 { 496 floatx80u u; 497 uint64_t aLow; 498 u.f = a1; 499 500 aLow = u.i.low & ~ LIT64( 0x4000000000000000 ); 501 return 502 ( ( u.i.high & 0x7FFF ) == 0x7FFF ) 503 && (bits64) ( aLow<<1 ) 504 && ( u.i.low == aLow ); 505 } 506 507 int floatx80_is_nan( floatx80 a1 ) 508 { 509 floatx80u u; 510 u.f = a1; 511 return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 ); 512 } 513 514 #endif 515