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