|
|
1.1 ! root 1: /* ! 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: ! 12: #ifndef FPP_H ! 13: #define FPP_H ! 14: ! 15: #include <softfloat.h> ! 16: ! 17: ! 18: #define FPCR_ROUNDING_MODE 0x00000030 ! 19: #define FPCR_ROUND_NEAR 0x00000000 ! 20: #define FPCR_ROUND_ZERO 0x00000010 ! 21: #define FPCR_ROUND_MINF 0x00000020 ! 22: #define FPCR_ROUND_PINF 0x00000030 ! 23: ! 24: #define FPCR_ROUNDING_PRECISION 0x000000c0 ! 25: #define FPCR_PRECISION_SINGLE 0x00000040 ! 26: #define FPCR_PRECISION_DOUBLE 0x00000080 ! 27: #define FPCR_PRECISION_EXTENDED 0x00000000 ! 28: ! 29: extern uae_u32 fpp_get_fpsr (void); ! 30: ! 31: ! 32: /* Functions for setting host/library modes and getting status */ ! 33: STATIC_INLINE void set_fp_mode(uae_u32 mode_control) ! 34: { ! 35: float_detect_tininess = float_tininess_before_rounding; ! 36: ! 37: switch(mode_control & FPCR_ROUNDING_PRECISION) { ! 38: case FPCR_PRECISION_SINGLE: // single ! 39: floatx80_rounding_precision = 32; ! 40: break; ! 41: case FPCR_PRECISION_DOUBLE: // double ! 42: floatx80_rounding_precision = 64; ! 43: break; ! 44: case FPCR_PRECISION_EXTENDED: // extended ! 45: floatx80_rounding_precision = 80; ! 46: break; ! 47: default: // double ! 48: floatx80_rounding_precision = 64; ! 49: break; ! 50: } ! 51: ! 52: switch(mode_control & FPCR_ROUNDING_MODE) { ! 53: case FPCR_ROUND_NEAR: // to neareset ! 54: float_rounding_mode = float_round_nearest_even; ! 55: break; ! 56: case FPCR_ROUND_ZERO: // to zero ! 57: float_rounding_mode = float_round_to_zero; ! 58: break; ! 59: case FPCR_ROUND_MINF: // to minus ! 60: float_rounding_mode = float_round_down; ! 61: break; ! 62: case FPCR_ROUND_PINF: // to plus ! 63: float_rounding_mode = float_round_up; ! 64: break; ! 65: } ! 66: } ! 67: STATIC_INLINE void get_fp_status(uae_u32 *status) ! 68: { ! 69: if (float_exception_flags & float_flag_signaling) ! 70: *status |= 0x4000; ! 71: if (float_exception_flags & float_flag_invalid) ! 72: *status |= 0x2000; ! 73: if (float_exception_flags & float_flag_overflow) ! 74: *status |= 0x1000; ! 75: if (float_exception_flags & float_flag_underflow) ! 76: *status |= 0x0800; ! 77: if (float_exception_flags & float_flag_divbyzero) ! 78: *status |= 0x0400; ! 79: if (float_exception_flags & float_flag_inexact) ! 80: *status |= 0x0200; ! 81: if (float_exception_flags & float_flag_decimal) ! 82: *status |= 0x0100; ! 83: } ! 84: STATIC_INLINE void clear_fp_status(void) ! 85: { ! 86: float_exception_flags = 0; ! 87: } ! 88: ! 89: /* Helper functions */ ! 90: STATIC_INLINE const char *fp_print(fptype *fx) ! 91: { ! 92: static char fs[32]; ! 93: bool n, u, d; ! 94: fptype x; ! 95: int32 len; ! 96: int8 save_exception_flags; ! 97: ! 98: n = floatx80_is_negative(*fx); ! 99: u = floatx80_is_unnormal(*fx); ! 100: d = floatx80_is_denormal(*fx); ! 101: ! 102: if (floatx80_is_infinity(*fx)) { ! 103: sprintf(fs, "%c%s", n?'-':'+', "inf"); ! 104: } else if (floatx80_is_signaling_nan(*fx)) { ! 105: sprintf(fs, "%c%s", n?'-':'+', "snan"); ! 106: } else if (floatx80_is_nan(*fx)) { ! 107: sprintf(fs, "%c%s", n?'-':'+', "nan"); ! 108: } else { ! 109: len = 17; ! 110: save_exception_flags = float_exception_flags; ! 111: float_exception_flags = 0; ! 112: x = floatx80_to_floatdecimal(*fx, &len); ! 113: ! 114: sprintf(fs, "%c%01lld.%016llde%c%04d%s%s", n?'-':'+', ! 115: x.low/LIT64(10000000000000000), x.low%LIT64(10000000000000000), ! 116: (x.high&0x4000)?'-':'+', x.high&0x3FFF, d?"D":u?"U":"", ! 117: (float_exception_flags&float_flag_inexact)?"~":""); ! 118: ! 119: float_exception_flags = save_exception_flags; ! 120: } ! 121: ! 122: return fs; ! 123: } ! 124: ! 125: /* Functions for detecting float type */ ! 126: STATIC_INLINE bool fp_is_snan(fptype *fp) ! 127: { ! 128: return floatx80_is_signaling_nan(*fp) != 0; ! 129: } ! 130: STATIC_INLINE void fp_unset_snan(fptype *fp) ! 131: { ! 132: fp->low |= LIT64(0x4000000000000000); ! 133: } ! 134: STATIC_INLINE bool fp_is_nan (fptype *fp) ! 135: { ! 136: return floatx80_is_nan(*fp) != 0; ! 137: } ! 138: STATIC_INLINE bool fp_is_infinity (fptype *fp) ! 139: { ! 140: return floatx80_is_infinity(*fp) != 0; ! 141: } ! 142: STATIC_INLINE bool fp_is_zero(fptype *fp) ! 143: { ! 144: return floatx80_is_zero(*fp) != 0; ! 145: } ! 146: STATIC_INLINE bool fp_is_neg(fptype *fp) ! 147: { ! 148: return floatx80_is_negative(*fp) != 0; ! 149: } ! 150: STATIC_INLINE bool fp_is_denormal(fptype *fp) ! 151: { ! 152: return floatx80_is_denormal(*fp) != 0; ! 153: } ! 154: STATIC_INLINE bool fp_is_unnormal(fptype *fp) ! 155: { ! 156: return floatx80_is_unnormal(*fp) != 0; ! 157: } ! 158: ! 159: /* Function for normalizing unnormals */ ! 160: STATIC_INLINE void fp_normalize(fptype *fp) ! 161: { ! 162: *fp = floatx80_normalize(*fp); ! 163: } ! 164: ! 165: /* Functions for converting between float formats */ ! 166: STATIC_INLINE void to_single(fptype *fp, uae_u32 wrd1) ! 167: { ! 168: float32 f = wrd1; ! 169: *fp = float32_to_floatx80_allowunnormal(f); ! 170: } ! 171: STATIC_INLINE uae_u32 from_single(fptype *fp) ! 172: { ! 173: float32 f = floatx80_to_float32(*fp); ! 174: return f; ! 175: } ! 176: ! 177: STATIC_INLINE void to_double(fptype *fp, uae_u32 wrd1, uae_u32 wrd2) ! 178: { ! 179: float64 f = ((float64)wrd1 << 32) | wrd2; ! 180: *fp = float64_to_floatx80_allowunnormal(f); ! 181: } ! 182: STATIC_INLINE void from_double(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2) ! 183: { ! 184: float64 f = floatx80_to_float64(*fp); ! 185: *wrd1 = f >> 32; ! 186: *wrd2 = (uae_u32)f; ! 187: } ! 188: ! 189: STATIC_INLINE void to_exten(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) ! 190: { ! 191: fp->high = (uae_u16)(wrd1 >> 16); ! 192: fp->low = ((uae_u64)wrd2 << 32) | wrd3; ! 193: } ! 194: STATIC_INLINE void from_exten(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3) ! 195: { ! 196: floatx80 f = floatx80_to_floatx80(*fp); ! 197: *wrd1 = (uae_u32)(f.high << 16); ! 198: *wrd2 = f.low >> 32; ! 199: *wrd3 = (uae_u32)f.low; ! 200: } ! 201: STATIC_INLINE void to_exten_fmovem(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) ! 202: { ! 203: fp->high = (uae_u16)(wrd1 >> 16); ! 204: fp->low = ((uae_u64)wrd2 << 32) | wrd3; ! 205: } ! 206: STATIC_INLINE void from_exten_fmovem(fptype *fp, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3) ! 207: { ! 208: *wrd1 = (uae_u32)(fp->high << 16); ! 209: *wrd2 = fp->low >> 32; ! 210: *wrd3 = (uae_u32)fp->low; ! 211: } ! 212: ! 213: STATIC_INLINE uae_s64 to_int(fptype *src, int size) ! 214: { ! 215: switch (size) { ! 216: case 0: return floatx80_to_int8(*src); ! 217: case 1: return floatx80_to_int16(*src); ! 218: case 2: return floatx80_to_int32(*src); ! 219: default: return 0; ! 220: } ! 221: } ! 222: STATIC_INLINE fptype from_int(uae_s32 src) ! 223: { ! 224: return int32_to_floatx80(src); ! 225: } ! 226: ! 227: STATIC_INLINE void to_pack(fptype *fp, uae_u32 *wrd) ! 228: { ! 229: floatx80 f; ! 230: int i; ! 231: uae_s32 exp; ! 232: uae_s64 mant; ! 233: uae_u32 pack_exp, pack_int, pack_se, pack_sm; ! 234: uae_u64 pack_frac; ! 235: ! 236: if (((wrd[0] >> 16) & 0x7fff) == 0x7fff) { ! 237: // infinity has extended exponent and all 0 packed fraction ! 238: // nans are copies bit by bit ! 239: to_exten(fp, wrd[0], wrd[1], wrd[2]); ! 240: return; ! 241: } ! 242: if (!(wrd[0] & 0xf) && !wrd[1] && !wrd[2]) { ! 243: // exponent is not cared about, if mantissa is zero ! 244: wrd[0] &= 0x80000000; ! 245: to_exten(fp, wrd[0], wrd[1], wrd[2]); ! 246: return; ! 247: } ! 248: ! 249: pack_exp = (wrd[0] >> 16) & 0xFFF; // packed exponent ! 250: pack_int = wrd[0] & 0xF; // packed integer part ! 251: pack_frac = ((uae_u64)wrd[1] << 32) | wrd[2]; // packed fraction ! 252: pack_se = (wrd[0] >> 30) & 1; // sign of packed exponent ! 253: pack_sm = (wrd[0] >> 31) & 1; // sign of packed significand ! 254: ! 255: exp = 0; ! 256: ! 257: for (i = 0; i < 3; i++) { ! 258: exp *= 10; ! 259: exp += (pack_exp >> (8 - i * 4)) & 0xF; ! 260: } ! 261: ! 262: if (pack_se) { ! 263: exp = -exp; ! 264: } ! 265: ! 266: exp -= 16; ! 267: ! 268: if (exp < 0) { ! 269: exp = -exp; ! 270: pack_se = 1; ! 271: } ! 272: ! 273: mant = pack_int; ! 274: ! 275: for (i = 0; i < 16; i++) { ! 276: mant *= 10; ! 277: mant += (pack_frac >> (60 - i * 4)) & 0xF; ! 278: } ! 279: ! 280: f.high = exp & 0x3FFF; ! 281: f.high |= pack_se ? 0x4000 : 0; ! 282: f.high |= pack_sm ? 0x8000 : 0; ! 283: f.low = mant; ! 284: ! 285: *fp = floatdecimal_to_floatx80(f); ! 286: } ! 287: STATIC_INLINE void from_pack(fptype *fp, uae_u32 *wrd, uae_s32 kfactor) ! 288: { ! 289: floatx80 f = floatx80_to_floatdecimal(*fp, &kfactor); ! 290: ! 291: uae_u32 pack_exp, pack_exp4, pack_int, pack_se, pack_sm; ! 292: uae_u64 pack_frac; ! 293: ! 294: uae_u32 exponent; ! 295: uae_u64 significand; ! 296: ! 297: uae_s32 len; ! 298: uae_u64 digit; ! 299: ! 300: if ((f.high & 0x7FFF) == 0x7FFF) { ! 301: wrd[0] = (uae_u32)(f.high << 16); ! 302: wrd[1] = f.low >> 32; ! 303: wrd[2] = (uae_u32)f.low; ! 304: } else { ! 305: exponent = f.high & 0x3FFF; ! 306: significand = f.low; ! 307: ! 308: pack_int = 0; ! 309: pack_frac = 0; ! 310: len = kfactor; // SoftFloat saved len to kfactor variable ! 311: while (len > 0) { ! 312: len--; ! 313: digit = significand % 10; ! 314: significand /= 10; ! 315: if (len == 0) { ! 316: pack_int = digit; ! 317: } else { ! 318: pack_frac |= digit << (64 - len * 4); ! 319: } ! 320: } ! 321: ! 322: pack_exp = 0; ! 323: pack_exp4 = 0; ! 324: len = 4; ! 325: while (len > 0) { ! 326: len--; ! 327: digit = exponent % 10; ! 328: exponent /= 10; ! 329: if (len == 0) { ! 330: pack_exp4 = digit; ! 331: } else { ! 332: pack_exp |= digit << (12 - len * 4); ! 333: } ! 334: } ! 335: ! 336: pack_se = f.high & 0x4000; ! 337: pack_sm = f.high & 0x8000; ! 338: ! 339: wrd[0] = pack_exp << 16; ! 340: wrd[0] |= pack_exp4 << 12; ! 341: wrd[0] |= pack_int; ! 342: wrd[0] |= pack_se ? 0x40000000 : 0; ! 343: wrd[0] |= pack_sm ? 0x80000000 : 0; ! 344: ! 345: wrd[1] = pack_frac >> 32; ! 346: wrd[2] = pack_frac & 0xffffffff; ! 347: } ! 348: } ! 349: ! 350: /* Functions for returning exception state data */ ! 351: STATIC_INLINE fptype fp_get_internal_overflow(void) ! 352: { ! 353: return getFloatInternalOverflow(); ! 354: } ! 355: STATIC_INLINE fptype fp_get_internal_underflow(void) ! 356: { ! 357: return getFloatInternalUnderflow(); ! 358: } ! 359: STATIC_INLINE fptype fp_get_internal_round_all(void) ! 360: { ! 361: return getFloatInternalRoundedAll(); ! 362: } ! 363: STATIC_INLINE fptype fp_get_internal_round(void) ! 364: { ! 365: return getFloatInternalRoundedSome(); ! 366: } ! 367: STATIC_INLINE fptype fp_get_internal_round_exten(void) ! 368: { ! 369: return getFloatInternalFloatx80(); ! 370: } ! 371: STATIC_INLINE fptype fp_get_internal(void) ! 372: { ! 373: return getFloatInternalUnrounded(); ! 374: } ! 375: STATIC_INLINE uae_u32 fp_get_internal_grs(void) ! 376: { ! 377: return (uae_u32)getFloatInternalGRS(); ! 378: } ! 379: ! 380: /* Function for denormalizing */ ! 381: STATIC_INLINE void fp_denormalize(fptype *fp, int esign) ! 382: { ! 383: *fp = floatx80_denormalize(*fp, esign); ! 384: } ! 385: ! 386: /* Functions for rounding */ ! 387: ! 388: // round to float with extended precision exponent ! 389: STATIC_INLINE void fp_round32(fptype *fp) ! 390: { ! 391: *fp = floatx80_round32(*fp); ! 392: } ! 393: ! 394: // round to double with extended precision exponent ! 395: STATIC_INLINE void fp_round64(fptype *fp) ! 396: { ! 397: *fp = floatx80_round64(*fp); ! 398: } ! 399: ! 400: // round to float ! 401: STATIC_INLINE void fp_round_single(fptype *fp) ! 402: { ! 403: *fp = floatx80_round_to_float32(*fp); ! 404: } ! 405: ! 406: // round to double ! 407: STATIC_INLINE void fp_round_double(fptype *fp) ! 408: { ! 409: *fp = floatx80_round_to_float64(*fp); ! 410: } ! 411: ! 412: // round to selected precision ! 413: STATIC_INLINE void fp_round(fptype *a) ! 414: { ! 415: switch(floatx80_rounding_precision) { ! 416: case 32: ! 417: *a = floatx80_round_to_float32(*a); ! 418: break; ! 419: case 64: ! 420: *a = floatx80_round_to_float64(*a); ! 421: break; ! 422: default: ! 423: break; ! 424: } ! 425: } ! 426: ! 427: /* Arithmetic functions */ ! 428: STATIC_INLINE void fp_move(fptype *a, fptype *b) ! 429: { ! 430: *a = floatx80_move(*b); ! 431: } ! 432: STATIC_INLINE void fp_int(fptype *a, fptype *b) ! 433: { ! 434: *a = floatx80_round_to_int(*b); ! 435: } ! 436: STATIC_INLINE void fp_intrz(fptype *a, fptype *b) ! 437: { ! 438: *a = floatx80_round_to_int_toward_zero(*b); ! 439: } ! 440: STATIC_INLINE void fp_sqrt(fptype *a, fptype *b) ! 441: { ! 442: *a = floatx80_sqrt(*b); ! 443: } ! 444: STATIC_INLINE void fp_abs(fptype *a, fptype *b) ! 445: { ! 446: *a = floatx80_abs(*b); ! 447: } ! 448: STATIC_INLINE void fp_neg(fptype *a, fptype *b) ! 449: { ! 450: *a = floatx80_neg(*b); ! 451: } ! 452: STATIC_INLINE void fp_getexp(fptype *a, fptype *b) ! 453: { ! 454: *a = floatx80_getexp(*b); ! 455: } ! 456: STATIC_INLINE void fp_getman(fptype *a, fptype *b) ! 457: { ! 458: *a = floatx80_getman(*b); ! 459: } ! 460: STATIC_INLINE void fp_div(fptype *a, fptype *b) ! 461: { ! 462: *a = floatx80_div(*a, *b); ! 463: } ! 464: STATIC_INLINE void fp_mod(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s) ! 465: { ! 466: *a = floatx80_mod(*a, *b, q, s); ! 467: } ! 468: STATIC_INLINE void fp_add(fptype *a, fptype *b) ! 469: { ! 470: *a = floatx80_add(*a, *b); ! 471: } ! 472: STATIC_INLINE void fp_mul(fptype *a, fptype *b) ! 473: { ! 474: *a = floatx80_mul(*a, *b); ! 475: } ! 476: STATIC_INLINE void fp_sgldiv(fptype *a, fptype *b) ! 477: { ! 478: *a = floatx80_sgldiv(*a, *b); ! 479: } ! 480: STATIC_INLINE void fp_rem(fptype *a, fptype *b, uae_u64 *q, uae_s8 *s) ! 481: { ! 482: *a = floatx80_rem(*a, *b, q, s); ! 483: } ! 484: STATIC_INLINE void fp_scale(fptype *a, fptype *b) ! 485: { ! 486: *a = floatx80_scale(*a, *b); ! 487: } ! 488: STATIC_INLINE void fp_sglmul(fptype *a, fptype *b) ! 489: { ! 490: *a = floatx80_sglmul(*a, *b); ! 491: } ! 492: STATIC_INLINE void fp_sub(fptype *a, fptype *b) ! 493: { ! 494: *a = floatx80_sub(*a, *b); ! 495: } ! 496: STATIC_INLINE void fp_cmp(fptype *a, fptype *b) ! 497: { ! 498: *a = floatx80_cmp(*a, *b); ! 499: } ! 500: STATIC_INLINE void fp_tst(fptype *a, fptype *b) ! 501: { ! 502: *a = floatx80_tst(*b); ! 503: } ! 504: ! 505: STATIC_INLINE void fp_sinh(fptype *a, fptype *b) ! 506: { ! 507: *a = floatx80_sinh(*b); ! 508: } ! 509: STATIC_INLINE void fp_lognp1(fptype *a, fptype *b) ! 510: { ! 511: *a = floatx80_lognp1(*b); ! 512: } ! 513: STATIC_INLINE void fp_etoxm1(fptype *a, fptype *b) ! 514: { ! 515: *a = floatx80_etoxm1(*b); ! 516: } ! 517: STATIC_INLINE void fp_tanh(fptype *a, fptype *b) ! 518: { ! 519: *a = floatx80_tanh(*b); ! 520: } ! 521: STATIC_INLINE void fp_atan(fptype *a, fptype *b) ! 522: { ! 523: *a = floatx80_atan(*b); ! 524: } ! 525: STATIC_INLINE void fp_asin(fptype *a, fptype *b) ! 526: { ! 527: *a = floatx80_asin(*b); ! 528: } ! 529: STATIC_INLINE void fp_atanh(fptype *a, fptype *b) ! 530: { ! 531: *a = floatx80_atanh(*b); ! 532: } ! 533: STATIC_INLINE void fp_sin(fptype *a, fptype *b) ! 534: { ! 535: *a = floatx80_sin(*b); ! 536: } ! 537: STATIC_INLINE void fp_tan(fptype *a, fptype *b) ! 538: { ! 539: *a = floatx80_tan(*b); ! 540: } ! 541: STATIC_INLINE void fp_etox(fptype *a, fptype *b) ! 542: { ! 543: *a = floatx80_etox(*b); ! 544: } ! 545: STATIC_INLINE void fp_twotox(fptype *a, fptype *b) ! 546: { ! 547: *a = floatx80_twotox(*b); ! 548: } ! 549: STATIC_INLINE void fp_tentox(fptype *a, fptype *b) ! 550: { ! 551: *a = floatx80_tentox(*b); ! 552: } ! 553: STATIC_INLINE void fp_logn(fptype *a, fptype *b) ! 554: { ! 555: *a = floatx80_logn(*b); ! 556: } ! 557: STATIC_INLINE void fp_log10(fptype *a, fptype *b) ! 558: { ! 559: *a = floatx80_log10(*b); ! 560: } ! 561: STATIC_INLINE void fp_log2(fptype *a, fptype *b) ! 562: { ! 563: *a = floatx80_log2(*b); ! 564: } ! 565: STATIC_INLINE void fp_cosh(fptype *a, fptype *b) ! 566: { ! 567: *a = floatx80_cosh(*b); ! 568: } ! 569: STATIC_INLINE void fp_acos(fptype *a, fptype *b) ! 570: { ! 571: *a = floatx80_acos(*b); ! 572: } ! 573: STATIC_INLINE void fp_cos(fptype *a, fptype *b) ! 574: { ! 575: *a = floatx80_cos(*b); ! 576: } ! 577: ! 578: /* Functions with fixed precision */ ! 579: STATIC_INLINE void fp_move_single(fptype *a, fptype *b) ! 580: { ! 581: int8 oldprec = floatx80_rounding_precision; ! 582: floatx80_rounding_precision = 32; ! 583: *a = floatx80_move(*b); ! 584: floatx80_rounding_precision = oldprec; ! 585: } ! 586: STATIC_INLINE void fp_abs_single(fptype *a, fptype *b) ! 587: { ! 588: int8 oldprec = floatx80_rounding_precision; ! 589: floatx80_rounding_precision = 32; ! 590: *a = floatx80_abs(*b); ! 591: floatx80_rounding_precision = oldprec; ! 592: } ! 593: STATIC_INLINE void fp_neg_single(fptype *a, fptype *b) ! 594: { ! 595: int8 oldprec = floatx80_rounding_precision; ! 596: floatx80_rounding_precision = 32; ! 597: *a = floatx80_neg(*b); ! 598: floatx80_rounding_precision = oldprec; ! 599: } ! 600: STATIC_INLINE void fp_add_single(fptype *a, fptype *b) ! 601: { ! 602: int8 oldprec = floatx80_rounding_precision; ! 603: floatx80_rounding_precision = 32; ! 604: *a = floatx80_add(*a, *b); ! 605: floatx80_rounding_precision = oldprec; ! 606: } ! 607: STATIC_INLINE void fp_sub_single(fptype *a, fptype *b) ! 608: { ! 609: int8 oldprec = floatx80_rounding_precision; ! 610: floatx80_rounding_precision = 32; ! 611: *a = floatx80_sub(*a, *b); ! 612: floatx80_rounding_precision = oldprec; ! 613: } ! 614: STATIC_INLINE void fp_mul_single(fptype *a, fptype *b) ! 615: { ! 616: int8 oldprec = floatx80_rounding_precision; ! 617: floatx80_rounding_precision = 32; ! 618: *a = floatx80_mul(*a, *b); ! 619: floatx80_rounding_precision = oldprec; ! 620: } ! 621: STATIC_INLINE void fp_div_single(fptype *a, fptype *b) ! 622: { ! 623: int8 oldprec = floatx80_rounding_precision; ! 624: floatx80_rounding_precision = 32; ! 625: *a = floatx80_div(*a, *b); ! 626: floatx80_rounding_precision = oldprec; ! 627: } ! 628: STATIC_INLINE void fp_sqrt_single(fptype *a, fptype *b) ! 629: { ! 630: int8 oldprec = floatx80_rounding_precision; ! 631: floatx80_rounding_precision = 32; ! 632: *a = floatx80_sqrt(*b); ! 633: floatx80_rounding_precision = oldprec; ! 634: } ! 635: STATIC_INLINE void fp_move_double(fptype *a, fptype *b) ! 636: { ! 637: int8 oldprec = floatx80_rounding_precision; ! 638: floatx80_rounding_precision = 64; ! 639: *a = floatx80_move(*b); ! 640: floatx80_rounding_precision = oldprec; ! 641: } ! 642: STATIC_INLINE void fp_abs_double(fptype *a, fptype *b) ! 643: { ! 644: int8 oldprec = floatx80_rounding_precision; ! 645: floatx80_rounding_precision = 64; ! 646: *a = floatx80_abs(*b); ! 647: floatx80_rounding_precision = oldprec; ! 648: } ! 649: STATIC_INLINE void fp_neg_double(fptype *a, fptype *b) ! 650: { ! 651: int8 oldprec = floatx80_rounding_precision; ! 652: floatx80_rounding_precision = 64; ! 653: *a = floatx80_neg(*b); ! 654: floatx80_rounding_precision = oldprec; ! 655: } ! 656: STATIC_INLINE void fp_add_double(fptype *a, fptype *b) ! 657: { ! 658: int8 oldprec = floatx80_rounding_precision; ! 659: floatx80_rounding_precision = 64; ! 660: *a = floatx80_add(*a, *b); ! 661: floatx80_rounding_precision = oldprec; ! 662: } ! 663: STATIC_INLINE void fp_sub_double(fptype *a, fptype *b) ! 664: { ! 665: int8 oldprec = floatx80_rounding_precision; ! 666: floatx80_rounding_precision = 64; ! 667: *a = floatx80_sub(*a, *b); ! 668: floatx80_rounding_precision = oldprec; ! 669: } ! 670: STATIC_INLINE void fp_mul_double(fptype *a, fptype *b) ! 671: { ! 672: int8 oldprec = floatx80_rounding_precision; ! 673: floatx80_rounding_precision = 64; ! 674: *a = floatx80_mul(*a, *b); ! 675: floatx80_rounding_precision = oldprec; ! 676: } ! 677: STATIC_INLINE void fp_div_double(fptype *a, fptype *b) ! 678: { ! 679: int8 oldprec = floatx80_rounding_precision; ! 680: floatx80_rounding_precision = 64; ! 681: *a = floatx80_div(*a, *b); ! 682: floatx80_rounding_precision = oldprec; ! 683: } ! 684: STATIC_INLINE void fp_sqrt_double(fptype *a, fptype *b) ! 685: { ! 686: int8 oldprec = floatx80_rounding_precision; ! 687: floatx80_rounding_precision = 64; ! 688: *a = floatx80_sqrt(*b); ! 689: floatx80_rounding_precision = oldprec; ! 690: } ! 691: ! 692: ! 693: ! 694: #if 0 /* Old fallback functions disabled */ ! 695: static const long double twoto32 = 4294967296.0; ! 696: ! 697: STATIC_INLINE void to_native(long double *fp, fptype fpx) ! 698: { ! 699: int expon; ! 700: long double frac; ! 701: ! 702: expon = fpx.high & 0x7fff; ! 703: ! 704: if (floatx80_is_zero(fpx)) { ! 705: *fp = floatx80_is_negative(fpx) ? -0.0 : +0.0; ! 706: return; ! 707: } ! 708: if (floatx80_is_nan(fpx)) { ! 709: *fp = sqrtl(-1); ! 710: return; ! 711: } ! 712: if (floatx80_is_infinity(fpx)) { ! 713: *fp = floatx80_is_negative(fpx) ? logl(0.0) : (1.0/0.0); ! 714: return; ! 715: } ! 716: ! 717: frac = (long double)fpx.low / (long double)(twoto32 * 2147483648.0); ! 718: if (floatx80_is_negative(fpx)) ! 719: frac = -frac; ! 720: *fp = ldexpl (frac, expon - 16383); ! 721: } ! 722: STATIC_INLINE void from_native(long double fp, fptype *fpx) ! 723: { ! 724: int expon; ! 725: long double frac; ! 726: ! 727: if (signbit(fp)) ! 728: fpx->high = 0x8000; ! 729: else ! 730: fpx->high = 0x0000; ! 731: ! 732: if (isnan(fp)) { ! 733: fpx->high |= 0x7fff; ! 734: fpx->low = LIT64(0xffffffffffffffff); ! 735: return; ! 736: } ! 737: if (isinf(fp)) { ! 738: fpx->high |= 0x7fff; ! 739: fpx->low = LIT64(0x0000000000000000); ! 740: return; ! 741: } ! 742: if (fp == 0.0) { ! 743: fpx->low = LIT64(0x0000000000000000); ! 744: return; ! 745: } ! 746: if (fp < 0.0) ! 747: fp = -fp; ! 748: ! 749: frac = frexpl (fp, &expon); ! 750: frac += 0.5 / (twoto32 * twoto32); ! 751: if (frac >= 1.0) { ! 752: frac /= 2.0; ! 753: expon++; ! 754: } ! 755: fpx->high |= (expon + 16383 - 1) & 0x7fff; ! 756: fpx->low = (bits64)(frac * (long double)(twoto32 * twoto32)); ! 757: ! 758: while (!(fpx->low & LIT64( 0x8000000000000000))) { ! 759: if (fpx->high == 0) { ! 760: break; ! 761: } ! 762: fpx->low <<= 1; ! 763: fpx->high--; ! 764: } ! 765: } ! 766: ! 767: STATIC_INLINE void fp_sinhf(fptype *a, fptype *b) ! 768: { ! 769: flag e = 0; ! 770: floatx80_sinh_check(*a, &e); ! 771: if (e) return; ! 772: long double fp; ! 773: to_native(&fp, *b); ! 774: fp = sinhl(fp); ! 775: from_native(fp, a); ! 776: fp_round(a); ! 777: } ! 778: STATIC_INLINE void fp_lognp1f(fptype *a, fptype *b) ! 779: { ! 780: flag e = 0; ! 781: floatx80_lognp1_check(*a, &e); ! 782: if (e) return; ! 783: long double fp; ! 784: to_native(&fp, *b); ! 785: fp = log1pl(fp); ! 786: from_native(fp, a); ! 787: fp_round(a); ! 788: } ! 789: STATIC_INLINE void fp_etoxm1f(fptype *a, fptype *b) ! 790: { ! 791: flag e = 0; ! 792: floatx80_etoxm1_check(*a, &e); ! 793: if (e) return; ! 794: long double fp; ! 795: to_native(&fp, *b); ! 796: fp = expm1l(fp); ! 797: from_native(fp, a); ! 798: fp_round(a); ! 799: } ! 800: STATIC_INLINE void fp_tanhf(fptype *a, fptype *b) ! 801: { ! 802: flag e = 0; ! 803: floatx80_tanh_check(*a, &e); ! 804: if (e) return; ! 805: long double fp; ! 806: to_native(&fp, *b); ! 807: fp = tanhl(fp); ! 808: from_native(fp, a); ! 809: fp_round(a); ! 810: } ! 811: STATIC_INLINE void fp_atanf(fptype *a, fptype *b) ! 812: { ! 813: flag e = 0; ! 814: floatx80_atan_check(*a, &e); ! 815: if (e) return; ! 816: long double fp; ! 817: to_native(&fp, *b); ! 818: fp = atanl(fp); ! 819: from_native(fp, a); ! 820: fp_round(a); ! 821: } ! 822: STATIC_INLINE void fp_asinf(fptype *a, fptype *b) ! 823: { ! 824: flag e = 0; ! 825: floatx80_asin_check(*a, &e); ! 826: if (e) return; ! 827: long double fp; ! 828: to_native(&fp, *b); ! 829: fp = asinl(fp); ! 830: from_native(fp, a); ! 831: fp_round(a); ! 832: } ! 833: STATIC_INLINE void fp_atanhf(fptype *a, fptype *b) ! 834: { ! 835: flag e = 0; ! 836: floatx80_atanh_check(*a, &e); ! 837: if (e) return; ! 838: long double fp; ! 839: to_native(&fp, *b); ! 840: fp = atanhl(fp); ! 841: from_native(fp, a); ! 842: fp_round(a); ! 843: } ! 844: STATIC_INLINE void fp_sinf(fptype *a, fptype *b) ! 845: { ! 846: flag e = 0; ! 847: floatx80_sin_check(*a, &e); ! 848: if (e) return; ! 849: long double fp; ! 850: to_native(&fp, *b); ! 851: fp = sinl(fp); ! 852: from_native(fp, a); ! 853: fp_round(a); ! 854: } ! 855: STATIC_INLINE void fp_tanf(fptype *a, fptype *b) ! 856: { ! 857: flag e = 0; ! 858: floatx80_tan_check(*a, &e); ! 859: if (e) return; ! 860: long double fp; ! 861: to_native(&fp, *b); ! 862: fp = tanl(fp); ! 863: from_native(fp, a); ! 864: fp_round(a); ! 865: } ! 866: STATIC_INLINE void fp_etoxf(fptype *a, fptype *b) ! 867: { ! 868: flag e = 0; ! 869: floatx80_etox_check(*a, &e); ! 870: if (e) return; ! 871: long double fp; ! 872: to_native(&fp, *b); ! 873: fp = expl(fp); ! 874: from_native(fp, a); ! 875: fp_round(a); ! 876: } ! 877: STATIC_INLINE void fp_twotoxf(fptype *a, fptype *b) ! 878: { ! 879: flag e = 0; ! 880: floatx80_twotox_check(*a, &e); ! 881: if (e) return; ! 882: long double fp; ! 883: to_native(&fp, *b); ! 884: fp = powl(2.0, fp); ! 885: from_native(fp, a); ! 886: fp_round(a); ! 887: } ! 888: STATIC_INLINE void fp_tentoxf(fptype *a, fptype *b) ! 889: { ! 890: flag e = 0; ! 891: floatx80_tentox_check(*a, &e); ! 892: if (e) return; ! 893: long double fp; ! 894: to_native(&fp, *b); ! 895: fp = powl(10.0, fp); ! 896: from_native(fp, a); ! 897: fp_round(a); ! 898: } ! 899: STATIC_INLINE void fp_lognf(fptype *a, fptype *b) ! 900: { ! 901: flag e = 0; ! 902: floatx80_logn_check(*a, &e); ! 903: if (e) return; ! 904: long double fp; ! 905: to_native(&fp, *b); ! 906: fp = logl(fp); ! 907: from_native(fp, a); ! 908: fp_round(a); ! 909: } ! 910: STATIC_INLINE void fp_log10f(fptype *a, fptype *b) ! 911: { ! 912: flag e = 0; ! 913: floatx80_log10_check(*a, &e); ! 914: if (e) return; ! 915: long double fp; ! 916: to_native(&fp, *b); ! 917: fp = log10l(fp); ! 918: from_native(fp, a); ! 919: fp_round(a); ! 920: } ! 921: STATIC_INLINE void fp_log2f(fptype *a, fptype *b) ! 922: { ! 923: flag e = 0; ! 924: floatx80_log2_check(*a, &e); ! 925: if (e) return; ! 926: long double fp; ! 927: to_native(&fp, *b); ! 928: fp = log2l(fp); ! 929: from_native(fp, a); ! 930: fp_round(a); ! 931: } ! 932: STATIC_INLINE void fp_coshf(fptype *a, fptype *b) ! 933: { ! 934: flag e = 0; ! 935: floatx80_cosh_check(*a, &e); ! 936: if (e) return; ! 937: long double fp; ! 938: to_native(&fp, *b); ! 939: fp = coshl(fp); ! 940: from_native(fp, a); ! 941: fp_round(a); ! 942: } ! 943: STATIC_INLINE void fp_acosf(fptype *a, fptype *b) ! 944: { ! 945: flag e = 0; ! 946: floatx80_acos_check(*a, &e); ! 947: if (e) return; ! 948: long double fp; ! 949: to_native(&fp, *b); ! 950: fp = acosl(fp); ! 951: from_native(fp, a); ! 952: fp_round(a); ! 953: } ! 954: STATIC_INLINE void fp_cosf(fptype *a, fptype *b) ! 955: { ! 956: flag e = 0; ! 957: floatx80_cos_check(*a, &e); ! 958: if (e) return; ! 959: long double fp; ! 960: to_native(&fp, *b); ! 961: fp = cosl(fp); ! 962: from_native(fp, a); ! 963: fp_round(a); ! 964: } ! 965: #endif ! 966: ! 967: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.