Annotation of previous_trunk/src/cpu/md-fpp.h, revision 1.1.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.