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

unix.superglobalmegacorp.com

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