|
|
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:
23: #if USE_LONG_DOUBLE
24: STATIC_INLINE long double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
25: {
26: uae_u32 longarray[] = {wrd3,wrd2,((wrd1>>16)&0xffff)}; // little endian
27: register long double *longdoublewords = (long double *)longarray;
28:
29: return(*longdoublewords);
30: }
31: #define HAVE_to_exten
32:
33: STATIC_INLINE void from_exten(long double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
34: {
35: register uae_u32 *longarray = (uae_u32 *)&src;
36: register uae_u16 *finalword = (uae_u16 *)(&src + 8);
37:
38: *wrd1 = ((uae_u32)*finalword)<<16;
39: *wrd2 = longarray[1];
40: *wrd3 = longarray[0]; // little endian
41: }
42: #define HAVE_from_exten
43: #endif /* USE_LONG_DOUBLE */
44:
45: #if defined(X86_MSVC_ASSEMBLY)
46: #ifndef HAVE_to_single
47: #define HAVE_to_single
48: STATIC_INLINE double to_single (uae_u32 longvalue)
49: {
50: double floatfake;
51:
52: __asm {
53: fld dword ptr longvalue;
54: fstp qword ptr floatfake;
55: }
56: return(floatfake);
57: }
58: #endif
59:
60: #ifndef HAVE_from_single
61: #define HAVE_from_single
62: STATIC_INLINE uae_u32 from_single (double floatfake)
63: {
64: uae_u32 longvalue;
65:
66: __asm {
67: fld qword ptr floatfake;
68: fstp dword ptr longvalue;
69: }
70: return(longvalue);
71: }
72: #endif
73:
74: #ifndef HAVE_to_exten
75: #define HAVE_to_exten
76: STATIC_INLINE double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
77: {
78: uae_u32 longarray[] = {wrd3,wrd2,((wrd1>>16)&0xffff)}; // little endian
79: double extenfake;
80:
81: __asm {
82: fld tbyte ptr longarray;
83: fstp qword ptr extenfake;
84: }
85: return(extenfake);
86: }
87: #endif
88:
89: #ifndef HAVE_from_exten
90: #define HAVE_from_exten
91: STATIC_INLINE void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
92: {
93: uae_u32 longarray[3], *srcarray = (uae_u32 *)&src;
94:
95: __asm {
96: fld qword ptr src;
97: fstp tbyte ptr longarray;
98: }
99: *wrd1 = (longarray[2] & 0xffff) <<16;
100: *wrd2 = longarray[1];
101: *wrd3 = longarray[0]; // little endian
102: if (!srcarray[0] && (srcarray[1]==0x7ff00000 || srcarray[1]==0xfff00000))
103: *wrd2 = 0; // The MSB of the mantissa was set wrongly for infinity, causing a NaN
104: }
105: #endif
106: #endif /* X86_MSVC_ASSEMBLY */
107:
108: #ifndef HAVE_to_single
109: #define HAVE_to_single
110: STATIC_INLINE double to_single (uae_u32 value)
111: {
112: union {
113: float f;
114: uae_u32 u;
115: } val;
116:
117: val.u = value;
118: return val.f;
119: }
120: #endif
121:
122: #ifndef HAVE_from_single
123: #define HAVE_from_single
124: STATIC_INLINE uae_u32 from_single (double src)
125: {
126: union {
127: float f;
128: uae_u32 u;
129: } val;
130:
131: val.f = (float) src;
132: return val.u;
133: }
134: #endif
135:
136: #ifndef HAVE_to_double
137: #define HAVE_to_double
138: STATIC_INLINE double to_double(uae_u32 wrd1, uae_u32 wrd2)
139: {
140: union {
141: double d;
142: uae_u32 u[2];
143: } val;
144:
145: val.u[0] = wrd2; // little endian
146: val.u[1] = wrd1;
147: return val.d;
148: }
149: #endif
150:
151: #ifndef HAVE_from_double
152: #define HAVE_from_double
153: STATIC_INLINE void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2)
154: {
155: register uae_u32 *longarray = (uae_u32 *)&src;
156:
157: *wrd1 = longarray[1]; // little endian
158: *wrd2 = longarray[0];
159: }
160: #endif
161:
162: static double twoto32 = 4294967296.0;
163: #ifndef HAVE_to_exten
164: #define HAVE_to_exten
165: STATIC_INLINE double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
166: {
167: double frac;
168:
169: if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
170: return 0.0;
171: frac = ((double)wrd2 + ((double)wrd3 / twoto32)) / 2147483648.0;
172: if (wrd1 & 0x80000000)
173: frac = -frac;
174: return ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383);
175: }
176: #endif
177:
178: #ifndef HAVE_from_exten
179: #define HAVE_from_exten
180: STATIC_INLINE void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
181: {
182: int expon;
183: double frac;
184:
185: if (src == 0.0) {
186: *wrd1 = 0;
187: *wrd2 = 0;
188: *wrd3 = 0;
189: return;
190: }
191: if (src < 0) {
192: *wrd1 = 0x80000000;
193: src = -src;
194: } else {
195: *wrd1 = 0;
196: }
197: frac = frexp (src, &expon);
198: frac += 0.5 / (twoto32 * twoto32);
199: if (frac >= 1.0) {
200: frac /= 2.0;
201: expon++;
202: }
203: *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
204: *wrd2 = (uae_u32) (frac * twoto32);
205: *wrd3 = (uae_u32) ((frac * twoto32 - *wrd2) * twoto32);
206: }
207: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.