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