Annotation of previous/src/cpu/md-fpp.h, revision 1.1.1.4

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

unix.superglobalmegacorp.com

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