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

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

unix.superglobalmegacorp.com

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