|
|
1.1.1.4 ! root 1: /* 1.1 root 2: * UAE - The Un*x Amiga Emulator 3: * 4: * MC68881 emulation 5: * 6: * Conversion routines for hosts knowing floating point format. 7: * 8: * Copyright 1996 Herman ten Brugge 9: * Modified 2005 Peter Keunecke 10: */ 11: 1.1.1.4 ! root 12: #ifndef FPP_H ! 13: #define FPP_H ! 14: ! 15: #define __USE_ISOC9X /* We might be able to pick up a NaN */ ! 16: ! 17: #include <math.h> ! 18: #include <float.h> ! 19: #include <fenv.h> ! 20: ! 21: //#pragma STDC FENV_ACCESS on ! 22: ! 23: #define USE_HOST_ROUNDING ! 24: 1.1 root 25: #define FPCR_ROUNDING_MODE 0x00000030 26: #define FPCR_ROUND_NEAR 0x00000000 27: #define FPCR_ROUND_ZERO 0x00000010 28: #define FPCR_ROUND_MINF 0x00000020 29: #define FPCR_ROUND_PINF 0x00000030 30: 31: #define FPCR_ROUNDING_PRECISION 0x000000c0 32: #define FPCR_PRECISION_SINGLE 0x00000040 33: #define FPCR_PRECISION_DOUBLE 0x00000080 34: #define FPCR_PRECISION_EXTENDED 0x00000000 35: 1.1.1.4 ! root 36: extern uae_u32 fpp_get_fpsr (void); ! 37: extern void fpsr_set_exception(uae_u32 exception); ! 38: ! 39: static int fp_rnd_prec = 80; ! 40: ! 41: /* Functions for setting host/library modes and getting status */ ! 42: STATIC_INLINE void set_fp_mode(uae_u32 mode_control) ! 43: { ! 44: switch(mode_control & FPCR_ROUNDING_PRECISION) { ! 45: case FPCR_PRECISION_EXTENDED: // X ! 46: fp_rnd_prec = 80; ! 47: break; ! 48: case FPCR_PRECISION_SINGLE: // S ! 49: fp_rnd_prec = 32; ! 50: break; ! 51: case FPCR_PRECISION_DOUBLE: // D ! 52: default: // undefined ! 53: fp_rnd_prec = 64; ! 54: break; ! 55: } ! 56: #ifdef USE_HOST_ROUNDING ! 57: switch(mode_control & FPCR_ROUNDING_MODE) { ! 58: case FPCR_ROUND_NEAR: // to neareset ! 59: fesetround(FE_TONEAREST); ! 60: break; ! 61: case FPCR_ROUND_ZERO: // to zero ! 62: fesetround(FE_TOWARDZERO); ! 63: break; ! 64: case FPCR_ROUND_MINF: // to minus ! 65: fesetround(FE_DOWNWARD); ! 66: break; ! 67: case FPCR_ROUND_PINF: // to plus ! 68: fesetround(FE_UPWARD); ! 69: break; ! 70: } ! 71: return; ! 72: #endif ! 73: } ! 74: STATIC_INLINE void get_fp_status(uae_u32 *status) 1.1.1.3 root 75: { 1.1.1.4 ! root 76: int exp_flags = fetestexcept(FE_ALL_EXCEPT); ! 77: if (exp_flags) { ! 78: if (exp_flags & FE_INEXACT) ! 79: *status |= 0x0200; ! 80: if (exp_flags & FE_DIVBYZERO) ! 81: *status |= 0x0400; ! 82: if (exp_flags & FE_UNDERFLOW) ! 83: *status |= 0x0800; ! 84: if (exp_flags & FE_OVERFLOW) ! 85: *status |= 0x1000; ! 86: if (exp_flags & FE_INVALID) ! 87: *status |= 0x2000; ! 88: } ! 89: /* FIXME: how to detect SNAN? */ ! 90: } ! 91: STATIC_INLINE void clear_fp_status(void) ! 92: { ! 93: feclearexcept (FE_ALL_EXCEPT); 1.1.1.2 root 94: } 95: 1.1.1.4 ! root 96: /* Helper functions */ ! 97: STATIC_INLINE const char *fp_print(fptype *fx) 1.1 root 98: { 1.1.1.4 ! root 99: static char fs[32]; ! 100: bool n, d; ! 101: ! 102: n = signbit(*fx) ? 1 : 0; ! 103: d = isnormal(*fx) ? 0 : 1; ! 104: ! 105: if (isinf(*fx)) { ! 106: sprintf(fs, "%c%s", n?'-':'+', "inf"); ! 107: } else if (isnan(*fx)) { ! 108: sprintf(fs, "%c%s", n?'-':'+', "nan"); ! 109: } else { ! 110: if (n) ! 111: *fx *= -1.0; ! 112: #ifdef USE_LONG_DOUBLE ! 113: sprintf(fs, "%c%#.16Le%s%s", n?'-':'+', *fx, "", d?"D":""); ! 114: #else ! 115: sprintf(fs, "%c%#.16e%s%s", n?'-':'+', *fx, "", d?"D":""); ! 116: #endif ! 117: } ! 118: ! 119: return fs; 1.1 root 120: } 121: 1.1.1.4 ! root 122: /* Functions for detecting float type */ ! 123: STATIC_INLINE bool fp_is_snan(fptype *fp) ! 124: { ! 125: return 0; /* FIXME: how to detect SNAN */ ! 126: } ! 127: STATIC_INLINE void fp_unset_snan(fptype *fp) 1.1 root 128: { 1.1.1.4 ! root 129: /* FIXME: how to unset SNAN */ ! 130: } ! 131: STATIC_INLINE bool fp_is_nan (fptype *fp) ! 132: { ! 133: return isnan(*fp) != 0; ! 134: } ! 135: STATIC_INLINE bool fp_is_infinity (fptype *fp) ! 136: { ! 137: return isinf(*fp) != 0; ! 138: } ! 139: STATIC_INLINE bool fp_is_zero(fptype *fp) ! 140: { ! 141: return (*fp == 0.0); ! 142: } ! 143: STATIC_INLINE bool fp_is_neg(fptype *fp) ! 144: { ! 145: return signbit(*fp) != 0; ! 146: } ! 147: STATIC_INLINE bool fp_is_denormal(fptype *fp) ! 148: { ! 149: return false; ! 150: //return (isnormal(*fp) == 0); /* FIXME: how to differ denormal/unnormal? */ ! 151: } ! 152: STATIC_INLINE bool fp_is_unnormal(fptype *fp) ! 153: { ! 154: return false; ! 155: //return (isnormal(*fp) == 0); /* FIXME: how to differ denormal/unnormal? */ ! 156: } 1.1.1.3 root 157: 1.1.1.4 ! root 158: /* Function for normalizing unnormals FIXME: how to do this with native floats? */ ! 159: STATIC_INLINE void fp_normalize(fptype *fp) ! 160: { 1.1 root 161: } 162: 1.1.1.4 ! root 163: /* Functions for converting between float formats */ ! 164: /* FIXME: how to preserve/fix denormals and unnormals? */ ! 165: ! 166: STATIC_INLINE void to_single(fptype *fp, uae_u32 wrd1) 1.1 root 167: { 1.1.1.4 ! root 168: union { ! 169: float f; ! 170: uae_u32 u; ! 171: } val; ! 172: ! 173: val.u = wrd1; ! 174: *fp = (fptype) val.f; ! 175: } ! 176: STATIC_INLINE uae_u32 from_single(fptype *fp) ! 177: { ! 178: union { ! 179: float f; ! 180: uae_u32 u; ! 181: } val; ! 182: ! 183: val.f = (float) *fp; ! 184: return val.u; ! 185: } 1.1 root 186: 1.1.1.4 ! root 187: STATIC_INLINE void to_double(fptype *fp, uae_u32 wrd1, uae_u32 wrd2) ! 188: { ! 189: union { ! 190: double d; ! 191: uae_u32 u[2]; ! 192: } val; ! 193: ! 194: #ifdef WORDS_BIGENDIAN ! 195: val.u[0] = wrd1; ! 196: val.u[1] = wrd2; ! 197: #else ! 198: val.u[1] = wrd1; ! 199: val.u[0] = wrd2; ! 200: #endif ! 201: *fp = (fptype) val.d; 1.1 root 202: } 1.1.1.4 ! root 203: STATIC_INLINE void from_double(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2) ! 204: { ! 205: union { ! 206: double d; ! 207: uae_u32 u[2]; ! 208: } val; ! 209: ! 210: val.d = (double) *fp; ! 211: #ifdef WORDS_BIGENDIAN ! 212: *wrd1 = val.u[0]; ! 213: *wrd2 = val.u[1]; ! 214: #else ! 215: *wrd1 = val.u[1]; ! 216: *wrd2 = val.u[0]; 1.1 root 217: #endif 1.1.1.4 ! root 218: } ! 219: #ifdef USE_LONG_DOUBLE ! 220: STATIC_INLINE void to_exten(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) 1.1 root 221: { 1.1.1.4 ! root 222: union { ! 223: long double ld; ! 224: uae_u32 u[3]; ! 225: } val; ! 226: ! 227: #if WORDS_BIGENDIAN ! 228: val.u[0] = (wrd1 & 0xffff0000) | ((wrd2 & 0xffff0000) >> 16); ! 229: val.u[1] = (wrd2 & 0x0000ffff) | ((wrd3 & 0xffff0000) >> 16); ! 230: val.u[2] = (wrd3 & 0x0000ffff) << 16; ! 231: #else ! 232: val.u[0] = wrd3; ! 233: val.u[1] = wrd2; ! 234: val.u[2] = wrd1 >> 16; ! 235: #endif ! 236: *fp = val.ld; 1.1 root 237: } 1.1.1.4 ! root 238: STATIC_INLINE void from_exten(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3) ! 239: { ! 240: union { ! 241: long double ld; ! 242: uae_u32 u[3]; ! 243: } val; ! 244: ! 245: val.ld = *fp; ! 246: #if WORDS_BIGENDIAN ! 247: *wrd1 = val.u[0] & 0xffff0000; ! 248: *wrd2 = ((val.u[0] & 0x0000ffff) << 16) | ((val.u[1] & 0xffff0000) >> 16); ! 249: *wrd3 = ((val.u[1] & 0x0000ffff) << 16) | ((val.u[2] & 0xffff0000) >> 16); ! 250: #else ! 251: *wrd3 = val.u[0]; ! 252: *wrd2 = val.u[1]; ! 253: *wrd1 = val.u[2] << 16; 1.1 root 254: #endif 1.1.1.4 ! root 255: } ! 256: #else // if !USE_LONG_DOUBLE ! 257: static const double twoto32 = 4294967296.0; ! 258: STATIC_INLINE void to_exten(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) 1.1 root 259: { 1.1.1.4 ! root 260: double frac; ! 261: if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) { ! 262: *fp = (wrd1 & 0x80000000) ? -0.0 : +0.0; ! 263: return; ! 264: } ! 265: frac = ((double)wrd2 + ((double)wrd3 / twoto32)) / 2147483648.0; ! 266: if (wrd1 & 0x80000000) ! 267: frac = -frac; ! 268: *fp = ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383); ! 269: } ! 270: STATIC_INLINE void from_exten(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3) ! 271: { ! 272: int expon; ! 273: double frac; ! 274: fptype v; ! 275: ! 276: v = *fp; ! 277: if (v == 0.0) { ! 278: *wrd1 = signbit(v) ? 0x80000000 : 0; ! 279: *wrd2 = 0; ! 280: *wrd3 = 0; ! 281: return; ! 282: } ! 283: if (v < 0) { ! 284: *wrd1 = 0x80000000; ! 285: v = -v; ! 286: } else { ! 287: *wrd1 = 0; ! 288: } ! 289: frac = frexp (v, &expon); ! 290: frac += 0.5 / (twoto32 * twoto32); ! 291: if (frac >= 1.0) { ! 292: frac /= 2.0; ! 293: expon++; ! 294: } ! 295: *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16); ! 296: *wrd2 = (uae_u32) (frac * twoto32); ! 297: *wrd3 = (uae_u32) ((frac * twoto32 - *wrd2) * twoto32); ! 298: } ! 299: #endif // !USE_LONG_DOUBLE ! 300: STATIC_INLINE void to_exten_fmovem(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) ! 301: { ! 302: to_exten(fp, wrd1, wrd2, wrd3); ! 303: } ! 304: STATIC_INLINE void from_exten_fmovem(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3) ! 305: { ! 306: from_exten(fp, wrd1, wrd2, wrd3); ! 307: } 1.1.1.3 root 308: 1.1.1.4 ! root 309: STATIC_INLINE void to_pack (fptype *fp, uae_u32 *wrd) ! 310: { ! 311: char *cp; ! 312: char str[100]; ! 313: ! 314: if (((wrd[0] >> 16) & 0x7fff) == 0x7fff) { ! 315: // infinity has extended exponent and all 0 packed fraction ! 316: // nans are copies bit by bit ! 317: to_exten(fp, wrd[0], wrd[1], wrd[2]); ! 318: return; ! 319: } ! 320: if (!(wrd[0] & 0xf) && !wrd[1] && !wrd[2]) { ! 321: // exponent is not cared about, if mantissa is zero ! 322: wrd[0] &= 0x80000000; ! 323: to_exten(fp, wrd[0], wrd[1], wrd[2]); ! 324: return; ! 325: } ! 326: ! 327: cp = str; ! 328: if (wrd[0] & 0x80000000) ! 329: *cp++ = '-'; ! 330: *cp++ = (wrd[0] & 0xf) + '0'; ! 331: *cp++ = '.'; ! 332: *cp++ = ((wrd[1] >> 28) & 0xf) + '0'; ! 333: *cp++ = ((wrd[1] >> 24) & 0xf) + '0'; ! 334: *cp++ = ((wrd[1] >> 20) & 0xf) + '0'; ! 335: *cp++ = ((wrd[1] >> 16) & 0xf) + '0'; ! 336: *cp++ = ((wrd[1] >> 12) & 0xf) + '0'; ! 337: *cp++ = ((wrd[1] >> 8) & 0xf) + '0'; ! 338: *cp++ = ((wrd[1] >> 4) & 0xf) + '0'; ! 339: *cp++ = ((wrd[1] >> 0) & 0xf) + '0'; ! 340: *cp++ = ((wrd[2] >> 28) & 0xf) + '0'; ! 341: *cp++ = ((wrd[2] >> 24) & 0xf) + '0'; ! 342: *cp++ = ((wrd[2] >> 20) & 0xf) + '0'; ! 343: *cp++ = ((wrd[2] >> 16) & 0xf) + '0'; ! 344: *cp++ = ((wrd[2] >> 12) & 0xf) + '0'; ! 345: *cp++ = ((wrd[2] >> 8) & 0xf) + '0'; ! 346: *cp++ = ((wrd[2] >> 4) & 0xf) + '0'; ! 347: *cp++ = ((wrd[2] >> 0) & 0xf) + '0'; ! 348: *cp++ = 'E'; ! 349: if (wrd[0] & 0x40000000) ! 350: *cp++ = '-'; ! 351: *cp++ = ((wrd[0] >> 24) & 0xf) + '0'; ! 352: *cp++ = ((wrd[0] >> 20) & 0xf) + '0'; ! 353: *cp++ = ((wrd[0] >> 16) & 0xf) + '0'; ! 354: *cp = 0; ! 355: ! 356: #ifdef USE_LONG_DOUBLE ! 357: sscanf (str, "%Le", fp); ! 358: #else ! 359: sscanf (str, "%le", fp); 1.1.1.3 root 360: #endif 1.1 root 361: } 1.1.1.4 ! root 362: STATIC_INLINE void from_pack (fptype *fp, uae_u32 *wrd, int kfactor) ! 363: { ! 364: int i, j, t; ! 365: int exp; ! 366: int ndigits; ! 367: char *cp, *strp; ! 368: char str[100]; ! 369: ! 370: if (fp_is_nan (fp)) { ! 371: // copy bit by bit, handle signaling nan ! 372: from_exten(fp, &wrd[0], &wrd[1], &wrd[2]); ! 373: return; ! 374: } ! 375: if (fp_is_infinity (fp)) { ! 376: // extended exponent and all 0 packed fraction ! 377: from_exten(fp, &wrd[0], &wrd[1], &wrd[2]); ! 378: wrd[1] = wrd[2] = 0; ! 379: return; ! 380: } ! 381: ! 382: wrd[0] = wrd[1] = wrd[2] = 0; ! 383: ! 384: #ifdef USE_LONG_DOUBLE ! 385: sprintf (str, "%#.17Le", *fp); ! 386: #else ! 387: sprintf (str, "%#.17e", *fp); 1.1 root 388: #endif 1.1.1.4 ! root 389: ! 390: // get exponent ! 391: cp = str; ! 392: while (*cp != 'e') { ! 393: if (*cp == 0) ! 394: return; ! 395: cp++; ! 396: } ! 397: cp++; ! 398: if (*cp == '+') ! 399: cp++; ! 400: exp = atoi (cp); ! 401: ! 402: // remove trailing zeros ! 403: cp = str; ! 404: while (*cp != 'e') ! 405: cp++; ! 406: cp[0] = 0; ! 407: cp--; ! 408: while (cp > str && *cp == '0') { ! 409: *cp = 0; ! 410: cp--; ! 411: } ! 412: ! 413: cp = str; ! 414: // get sign ! 415: if (*cp == '-') { ! 416: cp++; ! 417: wrd[0] = 0x80000000; ! 418: } else if (*cp == '+') { ! 419: cp++; ! 420: } ! 421: strp = cp; ! 422: ! 423: if (kfactor <= 0) { ! 424: ndigits = abs (exp) + (-kfactor) + 1; ! 425: } else { ! 426: if (kfactor > 17) { ! 427: kfactor = 17; ! 428: fpsr_set_exception(0x00002000); // OPERR ! 429: } ! 430: ndigits = kfactor; ! 431: } ! 432: ! 433: if (ndigits < 0) ! 434: ndigits = 0; ! 435: if (ndigits > 16) ! 436: ndigits = 16; ! 437: ! 438: // remove decimal point ! 439: strp[1] = strp[0]; ! 440: strp++; ! 441: // add trailing zeros ! 442: i = strlen (strp); ! 443: cp = strp + i; ! 444: while (i < ndigits) { ! 445: *cp++ = '0'; ! 446: i++; ! 447: } ! 448: i = ndigits + 1; ! 449: while (i < 17) { ! 450: strp[i] = 0; ! 451: i++; ! 452: } ! 453: *cp = 0; ! 454: i = ndigits - 1; ! 455: // need to round? ! 456: if (i >= 0 && strp[i + 1] >= '5') { ! 457: while (i >= 0) { ! 458: strp[i]++; ! 459: if (strp[i] <= '9') ! 460: break; ! 461: if (i == 0) { ! 462: strp[i] = '1'; ! 463: exp++; ! 464: } else { ! 465: strp[i] = '0'; ! 466: } ! 467: i--; ! 468: } ! 469: } ! 470: strp[ndigits] = 0; ! 471: ! 472: // store first digit of mantissa ! 473: cp = strp; ! 474: wrd[0] |= *cp++ - '0'; ! 475: ! 476: // store rest of mantissa ! 477: for (j = 1; j < 3; j++) { ! 478: for (i = 0; i < 8; i++) { ! 479: wrd[j] <<= 4; ! 480: if (*cp >= '0' && *cp <= '9') ! 481: wrd[j] |= *cp++ - '0'; ! 482: } ! 483: } ! 484: ! 485: // exponent ! 486: if (exp < 0) { ! 487: wrd[0] |= 0x40000000; ! 488: exp = -exp; ! 489: } ! 490: if (exp > 9999) // ?? ! 491: exp = 9999; ! 492: if (exp > 999) { ! 493: int d = exp / 1000; ! 494: wrd[0] |= d << 12; ! 495: exp -= d * 1000; ! 496: fpsr_set_exception(0x00002000); // OPERR ! 497: } ! 498: i = 100; ! 499: t = 0; ! 500: while (i >= 1) { ! 501: int d = exp / i; ! 502: t <<= 4; ! 503: t |= d; ! 504: exp -= d * i; ! 505: i /= 10; ! 506: } ! 507: wrd[0] |= t << 16; ! 508: } ! 509: ! 510: #ifndef USE_HOST_ROUNDING ! 511: #ifdef USE_LONG_DOUBLE ! 512: #define fp_round_to_minus_infinity(x) floorl(x) ! 513: #define fp_round_to_plus_infinity(x) ceill(x) ! 514: #define fp_round_to_zero(x) ((x) >= 0.0 ? floorl(x) : ceill(x)) ! 515: #define fp_round_to_nearest(x) roundl(x) ! 516: #else // if !USE_LONG_DOUBLE ! 517: #define fp_round_to_minus_infinity(x) floor(x) ! 518: #define fp_round_to_plus_infinity(x) ceil(x) ! 519: #define fp_round_to_zero(x) ((x) >= 0.0 ? floor(x) : ceil(x)) ! 520: #define fp_round_to_nearest(x) round(x) ! 521: #endif // !USE_LONG_DOUBLE ! 522: #endif // USE_HOST_ROUNDING 1.1 root 523: 1.1.1.4 ! root 524: STATIC_INLINE uae_s64 to_int(fptype *src, int size) 1.1 root 525: { 1.1.1.4 ! root 526: static fptype fxsizes[6] = ! 527: { ! 528: -128.0, 127.0, ! 529: -32768.0, 32767.0, ! 530: -2147483648.0, 2147483647.0 ! 531: }; ! 532: ! 533: if (*src < fxsizes[size * 2 + 0]) ! 534: *src = fxsizes[size * 2 + 0]; ! 535: if (*src > fxsizes[size * 2 + 1]) ! 536: *src = fxsizes[size * 2 + 1]; ! 537: #ifdef USE_HOST_ROUNDING ! 538: #ifdef USE_LONG_DOUBLE ! 539: return lrintl(*src); ! 540: #else ! 541: return lrint(*src); 1.1.1.3 root 542: #endif 1.1.1.4 ! root 543: #else ! 544: switch (regs.fpcr & FPCR_ROUNDING_MODE) ! 545: { ! 546: case FPCR_ROUND_ZERO: ! 547: return fp_round_to_zero (*src); ! 548: case FPCR_ROUND_MINF: ! 549: return fp_round_to_minus_infinity (*src); ! 550: case FPCR_ROUND_NEAR: ! 551: return fp_round_to_nearest (*src); ! 552: case FPCR_ROUND_PINF: ! 553: return fp_round_to_plus_infinity (*src); ! 554: default: ! 555: return (int) *src; ! 556: } 1.1 root 557: #endif 1.1.1.4 ! root 558: } ! 559: STATIC_INLINE fptype from_int(uae_s32 src) ! 560: { ! 561: return (fptype) src; ! 562: } 1.1 root 563: 1.1.1.4 ! root 564: /* Functions for returning exception state data */ ! 565: /* (almost impossible to emulate using native floats) */ ! 566: STATIC_INLINE fptype fp_get_internal_overflow(void) ! 567: { ! 568: return 0.0; ! 569: } ! 570: STATIC_INLINE fptype fp_get_internal_underflow(void) ! 571: { ! 572: return 0.0; ! 573: } ! 574: STATIC_INLINE fptype fp_get_internal(void) ! 575: { ! 576: return 0.0; ! 577: } ! 578: STATIC_INLINE fptype fp_get_internal_round(void) ! 579: { ! 580: return 0.0; ! 581: } ! 582: STATIC_INLINE fptype fp_get_internal_round_all(void) 1.1 root 583: { 1.1.1.4 ! root 584: return 0.0; ! 585: } ! 586: STATIC_INLINE fptype fp_get_internal_round_exten(void) ! 587: { ! 588: return 0.0; ! 589: } ! 590: STATIC_INLINE uae_u32 fp_get_internal_grs(void) ! 591: { ! 592: return 0.0; ! 593: } ! 594: ! 595: /* Function for denormalizing */ ! 596: STATIC_INLINE void fp_denormalize(fptype *fp, int esign) ! 597: { ! 598: // do nothing ! 599: } ! 600: ! 601: /* Functions for rounding */ 1.1 root 602: 1.1.1.4 ! root 603: // round to float with extended precision exponent ! 604: STATIC_INLINE void fp_round32(fptype *fp) ! 605: { ! 606: int expon; ! 607: float mant; ! 608: #ifdef USE_LONG_DOUBLE ! 609: mant = (float)(frexpl(*fp, &expon) * 2.0); ! 610: *fp = ldexpl((fptype)mant, expon - 1); ! 611: #else ! 612: mant = (float)(frexp(*fp, &expon) * 2.0); ! 613: *fp = ldexp((fptype)mant, expon - 1); ! 614: #endif 1.1 root 615: } 1.1.1.4 ! root 616: ! 617: // round to double with extended precision exponent ! 618: STATIC_INLINE void fp_round64(fptype *fp) ! 619: { ! 620: int expon; ! 621: double mant; ! 622: #ifdef USE_LONG_DOUBLE ! 623: mant = (double)(frexpl(*fp, &expon) * 2.0); ! 624: *fp = ldexpl((fptype)mant, expon - 1); ! 625: #else ! 626: mant = (double)(frexp(*fp, &expon) * 2.0); ! 627: *fp = ldexp((fptype)mant, expon - 1); 1.1 root 628: #endif 1.1.1.4 ! root 629: } 1.1 root 630: 1.1.1.4 ! root 631: // round to float ! 632: STATIC_INLINE void fp_round_single(fptype *fp) 1.1 root 633: { 1.1.1.4 ! root 634: *fp = (float) *fp; ! 635: } 1.1 root 636: 1.1.1.4 ! root 637: // round to double ! 638: STATIC_INLINE void fp_round_double(fptype *fp) ! 639: { ! 640: *fp = (double) *fp; 1.1 root 641: } 642: 1.1.1.4 ! root 643: // round to selected precision ! 644: STATIC_INLINE void fp_round(fptype *fp) 1.1 root 645: { 1.1.1.4 ! root 646: switch(fp_rnd_prec) { ! 647: case 32: ! 648: *fp = (float) *fp; ! 649: break; ! 650: case 64: ! 651: *fp = (double) *fp; ! 652: break; ! 653: default: ! 654: break; ! 655: } ! 656: } ! 657: 1.1.1.3 root 658: 1.1.1.4 ! root 659: /* Arithmetic functions */ ! 660: ! 661: #ifdef USE_LONG_DOUBLE ! 662: ! 663: STATIC_INLINE void fp_move(fptype *a, fptype *b) ! 664: { ! 665: *a = *b; ! 666: fp_round(a); ! 667: } ! 668: STATIC_INLINE void fp_move_single(fptype *a, fptype *b) ! 669: { ! 670: *a = *b; ! 671: fp_round_single(a); 1.1 root 672: } 1.1.1.4 ! root 673: STATIC_INLINE void fp_move_double(fptype *a, fptype *b) ! 674: { ! 675: *a = *b; ! 676: fp_round_double(a); ! 677: } ! 678: STATIC_INLINE void fp_int(fptype *a, fptype *b) ! 679: { ! 680: #ifdef USE_HOST_ROUNDING ! 681: *a = rintl(*b); ! 682: #else ! 683: switch (regs.fpcr & FPCR_ROUNDING_MODE) ! 684: { ! 685: case FPCR_ROUND_NEAR: ! 686: *a = fp_round_to_nearest(*b); ! 687: break; ! 688: case FPCR_ROUND_ZERO: ! 689: *a = fp_round_to_zero(*b); ! 690: break; ! 691: case FPCR_ROUND_MINF: ! 692: *a = fp_round_to_minus_infinity(*b); ! 693: break; ! 694: case FPCR_ROUND_PINF: ! 695: *a = fp_round_to_plus_infinity(*b); ! 696: break; ! 697: default: /* never reached */ ! 698: break; ! 699: } 1.1 root 700: #endif 1.1.1.4 ! root 701: fp_round(a); ! 702: } ! 703: STATIC_INLINE void fp_sinh(fptype *a, fptype *b) ! 704: { ! 705: *a = sinhl(*b); ! 706: fp_round(a); ! 707: } ! 708: STATIC_INLINE void fp_intrz(fptype *a, fptype *b) ! 709: { ! 710: #ifdef USE_HOST_ROUNDING ! 711: *a = truncl(*b); ! 712: #else ! 713: *a = fp_round_to_zero (*b); ! 714: #endif ! 715: fp_round(a); ! 716: } ! 717: STATIC_INLINE void fp_sqrt(fptype *a, fptype *b) ! 718: { ! 719: *a = sqrtl(*b); ! 720: fp_round(a); ! 721: } ! 722: STATIC_INLINE void fp_sqrt_single(fptype *a, fptype *b) ! 723: { ! 724: *a = sqrtl(*b); ! 725: fp_round_single(a); ! 726: } ! 727: STATIC_INLINE void fp_sqrt_double(fptype *a, fptype *b) ! 728: { ! 729: *a = sqrtl(*b); ! 730: fp_round_double(a); ! 731: } ! 732: STATIC_INLINE void fp_lognp1(fptype *a, fptype *b) ! 733: { ! 734: *a = log1pl(*b); ! 735: fp_round(a); ! 736: } ! 737: STATIC_INLINE void fp_etoxm1(fptype *a, fptype *b) ! 738: { ! 739: *a = expm1l(*b); ! 740: fp_round(a); ! 741: } ! 742: STATIC_INLINE void fp_tanh(fptype *a, fptype *b) ! 743: { ! 744: *a = tanhl(*b); ! 745: fp_round(a); ! 746: } ! 747: STATIC_INLINE void fp_atan(fptype *a, fptype *b) ! 748: { ! 749: *a = atanl(*b); ! 750: fp_round(a); ! 751: } ! 752: STATIC_INLINE void fp_asin(fptype *a, fptype *b) ! 753: { ! 754: *a = asinl(*b); ! 755: fp_round(a); ! 756: } ! 757: STATIC_INLINE void fp_atanh(fptype *a, fptype *b) ! 758: { ! 759: *a = atanhl(*b); ! 760: fp_round(a); ! 761: } ! 762: STATIC_INLINE void fp_sin(fptype *a, fptype *b) ! 763: { ! 764: *a = sinl(*b); ! 765: fp_round(a); ! 766: } ! 767: STATIC_INLINE void fp_tan(fptype *a, fptype *b) ! 768: { ! 769: *a = tanl(*b); ! 770: fp_round(a); ! 771: } ! 772: STATIC_INLINE void fp_etox(fptype *a, fptype *b) ! 773: { ! 774: *a = expl(*b); ! 775: fp_round(a); ! 776: } ! 777: STATIC_INLINE void fp_twotox(fptype *a, fptype *b) ! 778: { ! 779: *a = powl(2.0, *b); ! 780: fp_round(a); ! 781: } ! 782: STATIC_INLINE void fp_tentox(fptype *a, fptype *b) ! 783: { ! 784: *a = powl(10.0, *b); ! 785: fp_round(a); ! 786: } ! 787: STATIC_INLINE void fp_logn(fptype *a, fptype *b) ! 788: { ! 789: *a = logl(*b); ! 790: fp_round(a); ! 791: } ! 792: STATIC_INLINE void fp_log10(fptype *a, fptype *b) ! 793: { ! 794: *a = log10l(*b); ! 795: fp_round(a); ! 796: } ! 797: STATIC_INLINE void fp_log2(fptype *a, fptype *b) ! 798: { ! 799: *a = log2l(*b); ! 800: fp_round(a); ! 801: } ! 802: STATIC_INLINE void fp_abs(fptype *a, fptype *b) ! 803: { ! 804: *a = fabsl(*b); ! 805: fp_round(a); ! 806: } ! 807: STATIC_INLINE void fp_abs_single(fptype *a, fptype *b) ! 808: { ! 809: *a = fabsl(*b); ! 810: fp_round_single(a); ! 811: } ! 812: STATIC_INLINE void fp_abs_double(fptype *a, fptype *b) ! 813: { ! 814: *a = fabsl(*b); ! 815: fp_round_double(a); ! 816: } ! 817: STATIC_INLINE void fp_cosh(fptype *a, fptype *b) ! 818: { ! 819: *a = coshl(*b); ! 820: fp_round(a); ! 821: } ! 822: STATIC_INLINE void fp_neg(fptype *a, fptype *b) ! 823: { ! 824: *a = -(*b); ! 825: fp_round(a); ! 826: } ! 827: STATIC_INLINE void fp_neg_single(fptype *a, fptype *b) ! 828: { ! 829: *a = -(*b); ! 830: fp_round_single(a); ! 831: } ! 832: STATIC_INLINE void fp_neg_double(fptype *a, fptype *b) ! 833: { ! 834: *a = -(*b); ! 835: fp_round_double(a); ! 836: } ! 837: STATIC_INLINE void fp_acos(fptype *a, fptype *b) ! 838: { ! 839: *a = acosl(*b); ! 840: fp_round(a); ! 841: } ! 842: STATIC_INLINE void fp_cos(fptype *a, fptype *b) ! 843: { ! 844: *a = cosl(*b); ! 845: fp_round(a); ! 846: } ! 847: STATIC_INLINE void fp_getexp(fptype *a, fptype *b) ! 848: { ! 849: int expon; ! 850: frexpl(*b, &expon); ! 851: *a = (long double) (expon - 1); ! 852: fp_round(a); ! 853: } ! 854: STATIC_INLINE void fp_getman(fptype *a, fptype *b) ! 855: { ! 856: int expon; ! 857: *a = frexpl(*b, &expon) * 2.0; ! 858: fp_round(a); ! 859: } ! 860: STATIC_INLINE void fp_div(fptype *a, fptype *b) ! 861: { ! 862: *a /= *b; ! 863: fp_round(a); ! 864: } ! 865: STATIC_INLINE void fp_div_single(fptype *a, fptype *b) ! 866: { ! 867: *a /= *b; ! 868: fp_round_single(a); ! 869: } ! 870: STATIC_INLINE void fp_div_double(fptype *a, fptype *b) ! 871: { ! 872: *a /= *b; ! 873: fp_round_double(a); ! 874: } ! 875: STATIC_INLINE void fp_mod(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s) ! 876: { ! 877: fptype quot; ! 878: #ifdef USE_HOST_ROUNDING ! 879: quot = truncl(*a / *b); ! 880: #else ! 881: quot = fp_round_to_zero(*a / *b); ! 882: #endif ! 883: if (quot < 0.0) { ! 884: *s = 1; ! 885: quot = -quot; ! 886: } else { ! 887: *s = 0; ! 888: } ! 889: *q = (uae_u64)quot; ! 890: *a = fmodl(*a, *b); ! 891: fp_round(a); ! 892: } ! 893: STATIC_INLINE void fp_add(fptype *a, fptype *b) ! 894: { ! 895: *a += *b; ! 896: fp_round(a); ! 897: } ! 898: STATIC_INLINE void fp_add_single(fptype *a, fptype *b) ! 899: { ! 900: *a += *b; ! 901: fp_round_single(a); ! 902: } ! 903: STATIC_INLINE void fp_add_double(fptype *a, fptype *b) ! 904: { ! 905: *a += *b; ! 906: fp_round_double(a); ! 907: } ! 908: STATIC_INLINE void fp_mul(fptype *a, fptype *b) ! 909: { ! 910: *a *= *b; ! 911: fp_round(a); ! 912: } ! 913: STATIC_INLINE void fp_mul_single(fptype *a, fptype *b) ! 914: { ! 915: *a *= *b; ! 916: fp_round_single(a); ! 917: } ! 918: STATIC_INLINE void fp_mul_double(fptype *a, fptype *b) ! 919: { ! 920: *a *= *b; ! 921: fp_round_double(a); ! 922: } ! 923: STATIC_INLINE void fp_sgldiv(fptype *a, fptype *b) ! 924: { ! 925: fptype z; ! 926: float mant; ! 927: int expon; ! 928: z = *a / *b; ! 929: ! 930: mant = (float)(frexpl(z, &expon) * 2.0); ! 931: *a = ldexpl((fptype)mant, expon - 1); ! 932: } ! 933: STATIC_INLINE void fp_rem(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s) ! 934: { ! 935: fptype quot; ! 936: #ifdef USE_HOST_ROUNDING ! 937: quot = roundl(*a / *b); ! 938: #else ! 939: quot = fp_round_to_nearest(*a / *b); ! 940: #endif ! 941: if (quot < 0.0) { ! 942: *s = 1; ! 943: quot = -quot; ! 944: } else { ! 945: *s = 0; ! 946: } ! 947: *q = (uae_u64)quot; ! 948: *a = remainderl(*a, *b); ! 949: fp_round(a); ! 950: } ! 951: STATIC_INLINE void fp_scale(fptype *a, fptype *b) ! 952: { ! 953: *a = ldexpl(*a, (int) *b); ! 954: fp_round(a); ! 955: } ! 956: STATIC_INLINE void fp_sglmul(fptype *a, fptype *b) ! 957: { ! 958: fptype z; ! 959: float mant; ! 960: int expon; ! 961: /* FIXME: truncate mantissa of a and b to single precision */ ! 962: z = *a * (*b); 1.1 root 963: 1.1.1.4 ! root 964: mant = (float)(frexpl(z, &expon) * 2.0); ! 965: *a = ldexpl((fptype)mant, expon - 1); ! 966: } ! 967: STATIC_INLINE void fp_sub(fptype *a, fptype *b) ! 968: { ! 969: *a -= *b; ! 970: fp_round(a); ! 971: } ! 972: STATIC_INLINE void fp_sub_single(fptype *a, fptype *b) ! 973: { ! 974: *a -= *b; ! 975: fp_round_single(a); ! 976: } ! 977: STATIC_INLINE void fp_sub_double(fptype *a, fptype *b) ! 978: { ! 979: *a -= *b; ! 980: fp_round_double(a); ! 981: } ! 982: STATIC_INLINE void fp_cmp(fptype *a, fptype *b) 1.1 root 983: { 1.1.1.4 ! root 984: *a = (*a - *b); /* FIXME: comparing is different from subtraction */ ! 985: } ! 986: STATIC_INLINE void fp_tst(fptype *a, fptype *b) ! 987: { ! 988: *a = *b; /* FIXME: test b */ ! 989: } 1.1.1.3 root 990: 1.1.1.4 ! root 991: #else // if !USE_LONG_DOUBLE ! 992: ! 993: STATIC_INLINE void fp_move(fptype *a, fptype *b) ! 994: { ! 995: *a = *b; ! 996: fp_round(a); 1.1 root 997: } 1.1.1.4 ! root 998: STATIC_INLINE void fp_move_single(fptype *a, fptype *b) ! 999: { ! 1000: *a = *b; ! 1001: fp_round_single(a); ! 1002: } ! 1003: STATIC_INLINE void fp_move_double(fptype *a, fptype *b) ! 1004: { ! 1005: *a = *b; ! 1006: fp_round_double(a); ! 1007: } ! 1008: STATIC_INLINE void fp_int(fptype *a, fptype *b) ! 1009: { ! 1010: #ifdef USE_HOST_ROUNDING ! 1011: *a = rint(*b); ! 1012: #else ! 1013: switch (regs.fpcr & FPCR_ROUNDING_MODE) ! 1014: { ! 1015: case FPCR_ROUND_NEAR: ! 1016: *a = fp_round_to_nearest(*b); ! 1017: break; ! 1018: case FPCR_ROUND_ZERO: ! 1019: *a = fp_round_to_zero(*b); ! 1020: break; ! 1021: case FPCR_ROUND_MINF: ! 1022: *a = fp_round_to_minus_infinity(*b); ! 1023: break; ! 1024: case FPCR_ROUND_PINF: ! 1025: *a = fp_round_to_plus_infinity(*b); ! 1026: break; ! 1027: default: /* never reached */ ! 1028: break; ! 1029: } 1.1 root 1030: #endif 1.1.1.4 ! root 1031: fp_round(a); 1.1 root 1032: } 1.1.1.4 ! root 1033: STATIC_INLINE void fp_sinh(fptype *a, fptype *b) ! 1034: { ! 1035: *a = sinh(*b); ! 1036: fp_round(a); ! 1037: } ! 1038: STATIC_INLINE void fp_intrz(fptype *a, fptype *b) ! 1039: { ! 1040: #ifdef USE_HOST_ROUNDING ! 1041: *a = trunc(*b); ! 1042: #else ! 1043: *a = fp_round_to_zero (*b); 1.1 root 1044: #endif 1.1.1.4 ! root 1045: fp_round(a); ! 1046: } ! 1047: STATIC_INLINE void fp_sqrt(fptype *a, fptype *b) ! 1048: { ! 1049: *a = sqrt(*b); ! 1050: fp_round(a); ! 1051: } ! 1052: STATIC_INLINE void fp_sqrt_single(fptype *a, fptype *b) ! 1053: { ! 1054: *a = sqrt(*b); ! 1055: fp_round_single(a); ! 1056: } ! 1057: STATIC_INLINE void fp_sqrt_double(fptype *a, fptype *b) ! 1058: { ! 1059: *a = sqrt(*b); ! 1060: fp_round_double(a); ! 1061: } ! 1062: STATIC_INLINE void fp_lognp1(fptype *a, fptype *b) ! 1063: { ! 1064: *a = log1p(*b); ! 1065: fp_round(a); ! 1066: } ! 1067: STATIC_INLINE void fp_etoxm1(fptype *a, fptype *b) ! 1068: { ! 1069: *a = expm1(*b); ! 1070: fp_round(a); ! 1071: } ! 1072: STATIC_INLINE void fp_tanh(fptype *a, fptype *b) ! 1073: { ! 1074: *a = tanh(*b); ! 1075: fp_round(a); ! 1076: } ! 1077: STATIC_INLINE void fp_atan(fptype *a, fptype *b) ! 1078: { ! 1079: *a = atan(*b); ! 1080: fp_round(a); ! 1081: } ! 1082: STATIC_INLINE void fp_asin(fptype *a, fptype *b) ! 1083: { ! 1084: *a = asin(*b); ! 1085: fp_round(a); ! 1086: } ! 1087: STATIC_INLINE void fp_atanh(fptype *a, fptype *b) ! 1088: { ! 1089: *a = atanh(*b); ! 1090: fp_round(a); ! 1091: } ! 1092: STATIC_INLINE void fp_sin(fptype *a, fptype *b) ! 1093: { ! 1094: *a = sin(*b); ! 1095: fp_round(a); ! 1096: } ! 1097: STATIC_INLINE void fp_tan(fptype *a, fptype *b) ! 1098: { ! 1099: *a = tan(*b); ! 1100: fp_round(a); 1.1 root 1101: } 1.1.1.4 ! root 1102: STATIC_INLINE void fp_etox(fptype *a, fptype *b) ! 1103: { ! 1104: *a = exp(*b); ! 1105: fp_round(a); ! 1106: } ! 1107: STATIC_INLINE void fp_twotox(fptype *a, fptype *b) ! 1108: { ! 1109: *a = pow(2.0, *b); ! 1110: fp_round(a); ! 1111: } ! 1112: STATIC_INLINE void fp_tentox(fptype *a, fptype *b) ! 1113: { ! 1114: *a = pow(10.0, *b); ! 1115: fp_round(a); ! 1116: } ! 1117: STATIC_INLINE void fp_logn(fptype *a, fptype *b) ! 1118: { ! 1119: *a = log(*b); ! 1120: fp_round(a); ! 1121: } ! 1122: STATIC_INLINE void fp_log10(fptype *a, fptype *b) ! 1123: { ! 1124: *a = log10(*b); ! 1125: fp_round(a); ! 1126: } ! 1127: STATIC_INLINE void fp_log2(fptype *a, fptype *b) ! 1128: { ! 1129: *a = log2(*b); ! 1130: fp_round(a); ! 1131: } ! 1132: STATIC_INLINE void fp_abs(fptype *a, fptype *b) ! 1133: { ! 1134: *a = fabs(*b); ! 1135: fp_round(a); ! 1136: } ! 1137: STATIC_INLINE void fp_abs_single(fptype *a, fptype *b) ! 1138: { ! 1139: *a = fabs(*b); ! 1140: fp_round_single(a); ! 1141: } ! 1142: STATIC_INLINE void fp_abs_double(fptype *a, fptype *b) ! 1143: { ! 1144: *a = fabs(*b); ! 1145: fp_round_double(a); ! 1146: } ! 1147: STATIC_INLINE void fp_cosh(fptype *a, fptype *b) ! 1148: { ! 1149: *a = cosh(*b); ! 1150: fp_round(a); ! 1151: } ! 1152: STATIC_INLINE void fp_neg(fptype *a, fptype *b) ! 1153: { ! 1154: *a = -(*b); ! 1155: fp_round(a); ! 1156: } ! 1157: STATIC_INLINE void fp_neg_single(fptype *a, fptype *b) ! 1158: { ! 1159: *a = -(*b); ! 1160: fp_round_single(a); ! 1161: } ! 1162: STATIC_INLINE void fp_neg_double(fptype *a, fptype *b) ! 1163: { ! 1164: *a = -(*b); ! 1165: fp_round_double(a); ! 1166: } ! 1167: STATIC_INLINE void fp_acos(fptype *a, fptype *b) ! 1168: { ! 1169: *a = acos(*b); ! 1170: fp_round(a); ! 1171: } ! 1172: STATIC_INLINE void fp_cos(fptype *a, fptype *b) ! 1173: { ! 1174: *a = cos(*b); ! 1175: fp_round(a); ! 1176: } ! 1177: STATIC_INLINE void fp_getexp(fptype *a, fptype *b) ! 1178: { ! 1179: int expon; ! 1180: frexp(*b, &expon); ! 1181: *a = (long double) (expon - 1); ! 1182: fp_round(a); ! 1183: } ! 1184: STATIC_INLINE void fp_getman(fptype *a, fptype *b) ! 1185: { ! 1186: int expon; ! 1187: *a = frexp(*b, &expon) * 2.0; ! 1188: fp_round(a); ! 1189: } ! 1190: STATIC_INLINE void fp_div(fptype *a, fptype *b) ! 1191: { ! 1192: *a /= *b; ! 1193: fp_round(a); ! 1194: } ! 1195: STATIC_INLINE void fp_div_single(fptype *a, fptype *b) ! 1196: { ! 1197: *a /= *b; ! 1198: fp_round_single(a); ! 1199: } ! 1200: STATIC_INLINE void fp_div_double(fptype *a, fptype *b) ! 1201: { ! 1202: *a /= *b; ! 1203: fp_round_double(a); ! 1204: } ! 1205: STATIC_INLINE void fp_mod(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s) ! 1206: { ! 1207: fptype quot; ! 1208: #ifdef USE_HOST_ROUNDING ! 1209: quot = trunc(*a / *b); ! 1210: #else ! 1211: quot = fp_round_to_zero(*a / *b); ! 1212: #endif ! 1213: if (quot < 0.0) { ! 1214: *s = 1; ! 1215: quot = -quot; ! 1216: } else { ! 1217: *s = 0; ! 1218: } ! 1219: *q = (uae_u64)quot; ! 1220: *a = fmod(*a, *b); ! 1221: fp_round(a); ! 1222: } ! 1223: STATIC_INLINE void fp_add(fptype *a, fptype *b) ! 1224: { ! 1225: *a += *b; ! 1226: fp_round(a); ! 1227: } ! 1228: STATIC_INLINE void fp_add_single(fptype *a, fptype *b) ! 1229: { ! 1230: *a += *b; ! 1231: fp_round_single(a); ! 1232: } ! 1233: STATIC_INLINE void fp_add_double(fptype *a, fptype *b) ! 1234: { ! 1235: *a += *b; ! 1236: fp_round_double(a); ! 1237: } ! 1238: STATIC_INLINE void fp_mul(fptype *a, fptype *b) ! 1239: { ! 1240: *a *= *b; ! 1241: fp_round(a); ! 1242: } ! 1243: STATIC_INLINE void fp_mul_single(fptype *a, fptype *b) ! 1244: { ! 1245: *a *= *b; ! 1246: fp_round_single(a); ! 1247: } ! 1248: STATIC_INLINE void fp_mul_double(fptype *a, fptype *b) ! 1249: { ! 1250: *a *= *b; ! 1251: fp_round_double(a); ! 1252: } ! 1253: STATIC_INLINE void fp_sgldiv(fptype *a, fptype *b) ! 1254: { ! 1255: fptype z; ! 1256: float mant; ! 1257: int expon; ! 1258: z = *a / *b; ! 1259: ! 1260: mant = (float)(frexp(z, &expon) * 2.0); ! 1261: *a = ldexp((fptype)mant, expon - 1); ! 1262: } ! 1263: STATIC_INLINE void fp_rem(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s) ! 1264: { ! 1265: fptype quot; ! 1266: #ifdef USE_HOST_ROUNDING ! 1267: quot = round(*a / *b); ! 1268: #else ! 1269: quot = fp_round_to_nearest(*a / *b); ! 1270: #endif ! 1271: if (quot < 0.0) { ! 1272: *s = 1; ! 1273: quot = -quot; ! 1274: } else { ! 1275: *s = 0; ! 1276: } ! 1277: *q = (uae_u64)quot; ! 1278: *a = remainder(*a, *b); ! 1279: fp_round(a); ! 1280: } ! 1281: STATIC_INLINE void fp_scale(fptype *a, fptype *b) ! 1282: { ! 1283: *a = ldexp(*a, (int) *b); ! 1284: fp_round(a); ! 1285: } ! 1286: STATIC_INLINE void fp_sglmul(fptype *a, fptype *b) ! 1287: { ! 1288: fptype z; ! 1289: float mant; ! 1290: int expon; ! 1291: /* FIXME: truncate mantissa of a and b to single precision */ ! 1292: z = *a * (*b); ! 1293: ! 1294: mant = (float)(frexp(z, &expon) * 2.0); ! 1295: *a = ldexp((fptype)mant, expon - 1); ! 1296: } ! 1297: STATIC_INLINE void fp_sub(fptype *a, fptype *b) ! 1298: { ! 1299: *a -= *b; ! 1300: fp_round(a); ! 1301: } ! 1302: STATIC_INLINE void fp_sub_single(fptype *a, fptype *b) ! 1303: { ! 1304: *a -= *b; ! 1305: fp_round_single(a); ! 1306: } ! 1307: STATIC_INLINE void fp_sub_double(fptype *a, fptype *b) ! 1308: { ! 1309: *a -= *b; ! 1310: fp_round_double(a); ! 1311: } ! 1312: STATIC_INLINE void fp_cmp(fptype *a, fptype *b) ! 1313: { ! 1314: *a = (*a - *b); /* FIXME: comparing is different from subtraction */ ! 1315: } ! 1316: STATIC_INLINE void fp_tst(fptype *a, fptype *b) ! 1317: { ! 1318: *a = *b; /* FIXME: test b */ ! 1319: } ! 1320: ! 1321: #endif // !USE_LONG_DOUBLE ! 1322: 1.1 root 1323: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.