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