Annotation of previous_trunk/src/cpu/md-fpp.h, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.