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

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: 
1.1.1.4 ! root       12: #include <math.h>
        !            13: 
1.1       root       14: #define        FPCR_ROUNDING_MODE      0x00000030
                     15: #define        FPCR_ROUND_NEAR         0x00000000
                     16: #define        FPCR_ROUND_ZERO         0x00000010
                     17: #define        FPCR_ROUND_MINF         0x00000020
                     18: #define        FPCR_ROUND_PINF         0x00000030
                     19: 
                     20: #define        FPCR_ROUNDING_PRECISION 0x000000c0
                     21: #define        FPCR_PRECISION_SINGLE   0x00000040
                     22: #define        FPCR_PRECISION_DOUBLE   0x00000080
                     23: #define FPCR_PRECISION_EXTENDED        0x00000000
                     24: 
1.1.1.3   root       25: extern void to_single(fpdata *fpd, uae_u32 value);
                     26: extern void to_double(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2);
                     27: extern void to_exten(fpdata *fpd, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3);
                     28: 
                     29: STATIC_INLINE void exten_zeronormalize(uae_u32 *pwrd1, uae_u32 *pwrd2, uae_u32 *pwrd3)
                     30: {
                     31:        uae_u32 wrd1 = *pwrd1;
                     32:        uae_u32 wrd2 = *pwrd2;
                     33:        uae_u32 wrd3 = *pwrd3;
                     34:        int exp = (wrd1 >> 16) & 0x7fff;
                     35:        // Force zero if mantissa is zero but exponent is non-zero
                     36:        // M68k FPU automatically convert them to plain zeros.
                     37:        // x86 FPU considers them invalid values
                     38:        if (exp != 0 && exp != 0x7fff && !wrd2 && !wrd3) {
                     39:                *pwrd1 = (wrd1 & 0x80000000);
                     40:        }
                     41: }
1.1.1.2   root       42: 
1.1       root       43: #if USE_LONG_DOUBLE
1.1.1.3   root       44: STATIC_INLINE void to_exten_x(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
1.1       root       45: {
1.1.1.3   root       46:        // force correct long double alignment
                     47:        union
                     48:        {
                     49:                long double lf;
                     50:                uae_u32 longarray[3];
                     51:        } uld;
                     52:        exten_zeronormalize(&wrd1, &wrd2, &wrd3);
                     53:        // little endian order
                     54:        uld.longarray[0] = wrd3;
                     55:        uld.longarray[1] = wrd2;
                     56:        uld.longarray[2] = wrd1 >> 16;
                     57:        long double *longdoublewords = (long double *)uld.longarray;
                     58:        *fp = *longdoublewords;
1.1       root       59: }
                     60: #define HAVE_to_exten
                     61: 
1.1.1.3   root       62: STATIC_INLINE void from_exten_x(fptype fp, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
1.1       root       63: {
1.1.1.3   root       64:        uae_u32 *longarray = (uae_u32 *)&fp;
                     65:        uae_u16 *finalword = (uae_u16 *)(((uae_u8*)&fp) + 8);
1.1       root       66: 
1.1.1.3   root       67:        *wrd1 = finalword[0] << 16;
1.1.1.2   root       68:        *wrd2 = longarray[1];
                     69:        *wrd3 = longarray[0]; // little endian
1.1       root       70: }
                     71: #define HAVE_from_exten
                     72: #endif /* USE_LONG_DOUBLE */
                     73: 
1.1.1.3   root       74: #if defined(X86_MSVC_ASSEMBLY_FPU)
1.1       root       75: #ifndef HAVE_to_single
                     76: #define HAVE_to_single
1.1.1.3   root       77: STATIC_INLINE double to_single_x (uae_u32 longvalue)
1.1       root       78: {
1.1.1.3   root       79:        double floatfake;
1.1       root       80: 
1.1.1.3   root       81:        __asm {
                     82:                fld dword ptr longvalue;
                     83:                fstp qword ptr floatfake;
                     84:        }
                     85:        return floatfake;
1.1       root       86: }
                     87: #endif
                     88: 
                     89: #ifndef HAVE_from_single
                     90: #define HAVE_from_single
1.1.1.3   root       91: STATIC_INLINE uae_u32 from_single_x (double floatfake)
1.1       root       92: {
1.1.1.3   root       93:        uae_u32 longvalue;
1.1       root       94: 
1.1.1.3   root       95:        __asm {
                     96:                fld qword ptr floatfake;
                     97:                fstp dword ptr longvalue;
                     98:        }
                     99:        return longvalue;
1.1       root      100: }
                    101: #endif
                    102: 
                    103: #ifndef HAVE_to_exten
                    104: #define HAVE_to_exten
1.1.1.3   root      105: STATIC_INLINE void to_exten_x(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
1.1       root      106: {
1.1.1.3   root      107:        uae_u32 longarray[3];
                    108:        double  extenfake;
1.1       root      109: 
1.1.1.3   root      110:        exten_normalize(&wrd1, &wrd2, &wrd3);
                    111:        longarray[0] = wrd3; // littlen endian
                    112:        longarray[1] = wrd2;
                    113:        longarray[2] = wrd2 >> 16;
                    114: 
                    115:        __asm {
                    116:                fld tbyte ptr longarray;
                    117:                fstp qword ptr extenfake;
                    118:        }
                    119:        *fp = extenfake;
1.1       root      120: }
                    121: #endif
                    122: 
                    123: #ifndef HAVE_from_exten
                    124: #define HAVE_from_exten
1.1.1.3   root      125: STATIC_INLINE void from_exten_x(fptype fp, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
1.1       root      126: {
1.1.1.3   root      127:        fptype src = fp;
                    128:        uae_u32 longarray[3], *srcarray = (uae_u32 *)&src;
                    129:        __asm {
                    130:                fld qword ptr src;
                    131:                fstp tbyte ptr longarray;
                    132:        }
                    133:        *wrd1 = (longarray[2] & 0xffff) <<16;
                    134:        *wrd2 =  longarray[1];
                    135:        *wrd3 =  longarray[0]; // little endian
                    136:        if (!srcarray[0] && (srcarray[1] == 0x7ff00000 || srcarray[1] == 0xfff00000))
                    137:                *wrd2 = 0; // The MSB of the mantissa was set wrongly for infinity, causing a NaN
1.1       root      138: }
                    139: #endif
                    140: #endif /* X86_MSVC_ASSEMBLY */
                    141: 
                    142: #ifndef HAVE_to_single
                    143: #define HAVE_to_single
1.1.1.3   root      144: STATIC_INLINE double to_single_x (uae_u32 value)
1.1       root      145: {
1.1.1.3   root      146:        union {
                    147:                float f;
                    148:                uae_u32 u;
                    149:        } val;
1.1       root      150: 
1.1.1.3   root      151:        val.u = value;
                    152:        return val.f;
1.1       root      153: }
                    154: #endif
                    155: 
                    156: #ifndef HAVE_from_single
                    157: #define HAVE_from_single
1.1.1.3   root      158: STATIC_INLINE uae_u32 from_single_x (double src)
1.1       root      159: {
1.1.1.3   root      160:        union {
                    161:                float f;
                    162:                uae_u32 u;
                    163:        } val;
1.1       root      164: 
1.1.1.3   root      165:        val.f = (float) src;
                    166:        return val.u;
1.1       root      167: }
                    168: #endif
                    169: 
                    170: #ifndef HAVE_to_double
                    171: #define HAVE_to_double
1.1.1.3   root      172: STATIC_INLINE double to_double_x(uae_u32 wrd1, uae_u32 wrd2)
1.1       root      173: {
1.1.1.3   root      174:        union {
                    175:                double d;
                    176:                uae_u32 u[2];
                    177:        } val;
                    178: 
1.1.1.4 ! root      179: #ifdef WORDS_BIGENDIAN
        !           180:        val.u[0] = wrd1;
        !           181:        val.u[1] = wrd2;
        !           182: #else
1.1.1.3   root      183:        val.u[1] = wrd1;
1.1.1.4 ! root      184:        val.u[0] = wrd2;
        !           185: #endif
1.1.1.3   root      186:        return val.d;
1.1       root      187: }
                    188: #endif
                    189: 
                    190: #ifndef HAVE_from_double
                    191: #define HAVE_from_double
1.1.1.3   root      192: STATIC_INLINE void from_double_x(double src, uae_u32 * wrd1, uae_u32 * wrd2)
1.1       root      193: {
1.1.1.3   root      194:        uae_u32 *longarray = (uae_u32 *)&src;
1.1       root      195: 
1.1.1.3   root      196:        *wrd1 = longarray[1]; // little endian
                    197:        *wrd2 = longarray[0];
1.1       root      198: }
                    199: #endif
                    200: 
1.1.1.3   root      201: static const double twoto32 = 4294967296.0;
1.1       root      202: #ifndef HAVE_to_exten
                    203: #define HAVE_to_exten
1.1.1.3   root      204: STATIC_INLINE void to_exten_x(fptype *fp, uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
1.1       root      205: {
1.1.1.3   root      206:        double frac;
                    207:        exten_zeronormalize(&wrd1, &wrd2, &wrd3);
                    208:        if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
                    209:                *fp = (wrd1 & 0x80000000) ? -0.0 : +0.0;
                    210:                return;
                    211:        }
                    212:        frac = ((double)wrd2 + ((double)wrd3 / twoto32)) / 2147483648.0;
                    213:        if (wrd1 & 0x80000000)
                    214:                frac = -frac;
                    215:        *fp = ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383);
1.1       root      216: }
                    217: #endif
                    218: 
                    219: #ifndef HAVE_from_exten
                    220: #define HAVE_from_exten
1.1.1.3   root      221: STATIC_INLINE void from_exten_x(fptype fp, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
1.1       root      222: {
1.1.1.3   root      223:        int expon;
                    224:        double frac;
                    225:        fptype v;
                    226: 
                    227:        v = fp;
                    228:        if (v == 0.0) {
                    229:                *wrd1 = signbit(v) ? 0x80000000 : 0;
                    230:                *wrd2 = 0;
                    231:                *wrd3 = 0;
                    232:                return;
                    233:        }
                    234:        if (v < 0) {
                    235:                *wrd1 = 0x80000000;
                    236:                v = -v;
                    237:        } else {
                    238:                *wrd1 = 0;
                    239:        }
                    240:        frac = frexp (v, &expon);
                    241:        frac += 0.5 / (twoto32 * twoto32);
                    242:        if (frac >= 1.0) {
                    243:                frac /= 2.0;
                    244:                expon++;
                    245:        }
                    246:        *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
                    247:        *wrd2 = (uae_u32) (frac * twoto32);
                    248:        *wrd3 = (uae_u32) ((frac * twoto32 - *wrd2) * twoto32);
1.1       root      249: }
                    250: #endif

unix.superglobalmegacorp.com

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