|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.