qemu/fpu/softfloat-native.c
<<
>>
Prefs
   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
   9void 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
  21void 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)
  38extern long double rintl(long double);
  39extern long double scalbnl(long double, int);
  40
  41long long
  42llrintl(long double x) {
  43        return ((long long) rintl(x));
  44}
  45
  46long
  47lrintl(long double x) {
  48        return ((long) rintl(x));
  49}
  50
  51long double
  52ldexpl(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) */
  61static 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*----------------------------------------------------------------------------*/
  80float32 int32_to_float32(int v STATUS_PARAM)
  81{
  82    return (float32)v;
  83}
  84
  85float32 uint32_to_float32(unsigned int v STATUS_PARAM)
  86{
  87    return (float32)v;
  88}
  89
  90float64 int32_to_float64(int v STATUS_PARAM)
  91{
  92    return (float64)v;
  93}
  94
  95float64 uint32_to_float64(unsigned int v STATUS_PARAM)
  96{
  97    return (float64)v;
  98}
  99
 100#ifdef FLOATX80
 101floatx80 int32_to_floatx80(int v STATUS_PARAM)
 102{
 103    return (floatx80)v;
 104}
 105#endif
 106float32 int64_to_float32( int64_t v STATUS_PARAM)
 107{
 108    return (float32)v;
 109}
 110float32 uint64_to_float32( uint64_t v STATUS_PARAM)
 111{
 112    return (float32)v;
 113}
 114float64 int64_to_float64( int64_t v STATUS_PARAM)
 115{
 116    return (float64)v;
 117}
 118float64 uint64_to_float64( uint64_t v STATUS_PARAM)
 119{
 120    return (float64)v;
 121}
 122#ifdef FLOATX80
 123floatx80 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
 131static inline int long_to_int32(long a)
 132{
 133    return a;
 134}
 135#else
 136static 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*----------------------------------------------------------------------------*/
 147int float32_to_int32( float32 a STATUS_PARAM)
 148{
 149    return long_to_int32(lrintf(a));
 150}
 151int float32_to_int32_round_to_zero( float32 a STATUS_PARAM)
 152{
 153    return (int)a;
 154}
 155int64_t float32_to_int64( float32 a STATUS_PARAM)
 156{
 157    return llrintf(a);
 158}
 159
 160int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM)
 161{
 162    return (int64_t)a;
 163}
 164
 165float64 float32_to_float64( float32 a STATUS_PARAM)
 166{
 167    return a;
 168}
 169#ifdef FLOATX80
 170floatx80 float32_to_floatx80( float32 a STATUS_PARAM)
 171{
 172    return a;
 173}
 174#endif
 175
 176unsigned 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}
 191unsigned 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*----------------------------------------------------------------------------*/
 210float32 float32_round_to_int( float32 a STATUS_PARAM)
 211{
 212    return rintf(a);
 213}
 214
 215float32 float32_rem( float32 a, float32 b STATUS_PARAM)
 216{
 217    return remainderf(a, b);
 218}
 219
 220float32 float32_sqrt( float32 a STATUS_PARAM)
 221{
 222    return sqrtf(a);
 223}
 224int 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}
 236int 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}
 248int 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
 257int 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/*----------------------------------------------------------------------------
 267| Software IEC/IEEE double-precision conversion routines.
 268*----------------------------------------------------------------------------*/
 269int float64_to_int32( float64 a STATUS_PARAM)
 270{
 271    return long_to_int32(lrint(a));
 272}
 273int float64_to_int32_round_to_zero( float64 a STATUS_PARAM)
 274{
 275    return (int)a;
 276}
 277int64_t float64_to_int64( float64 a STATUS_PARAM)
 278{
 279    return llrint(a);
 280}
 281int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM)
 282{
 283    return (int64_t)a;
 284}
 285float32 float64_to_float32( float64 a STATUS_PARAM)
 286{
 287    return a;
 288}
 289#ifdef FLOATX80
 290floatx80 float64_to_floatx80( float64 a STATUS_PARAM)
 291{
 292    return a;
 293}
 294#endif
 295#ifdef FLOAT128
 296float128 float64_to_float128( float64 a STATUS_PARAM)
 297{
 298    return a;
 299}
 300#endif
 301
 302unsigned 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}
 317unsigned 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}
 332uint64_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}
 340uint64_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)
 354static inline float64 trunc(float64 x)
 355{
 356    return x < 0 ? -floor(-x) : floor(x);
 357}
 358#endif
 359float64 float64_trunc_to_int( float64 a STATUS_PARAM )
 360{
 361    return trunc(a);
 362}
 363
 364float64 float64_round_to_int( float64 a STATUS_PARAM )
 365{
 366    return rint(a);
 367}
 368
 369float64 float64_rem( float64 a, float64 b STATUS_PARAM)
 370{
 371    return remainder(a, b);
 372}
 373
 374float64 float64_sqrt( float64 a STATUS_PARAM)
 375{
 376    return sqrt(a);
 377}
 378int 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}
 390int 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}
 402int 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
 414int float64_is_quiet_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*----------------------------------------------------------------------------*/
 430int floatx80_to_int32( floatx80 a STATUS_PARAM)
 431{
 432    return long_to_int32(lrintl(a));
 433}
 434int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM)
 435{
 436    return (int)a;
 437}
 438int64_t floatx80_to_int64( floatx80 a STATUS_PARAM)
 439{
 440    return llrintl(a);
 441}
 442int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM)
 443{
 444    return (int64_t)a;
 445}
 446float32 floatx80_to_float32( floatx80 a STATUS_PARAM)
 447{
 448    return a;
 449}
 450float64 floatx80_to_float64( floatx80 a STATUS_PARAM)
 451{
 452    return a;
 453}
 454
 455/*----------------------------------------------------------------------------
 456| Software IEC/IEEE extended double-precision operations.
 457*----------------------------------------------------------------------------*/
 458floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
 459{
 460    return rintl(a);
 461}
 462floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
 463{
 464    return remainderl(a, b);
 465}
 466floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
 467{
 468    return sqrtl(a);
 469}
 470int 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}
 482int 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}
 494int 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
 507int floatx80_is_quiet_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