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