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