|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * MC68881 emulation
5: *
6: * Conversion routines for hosts with unknown floating point format.
7: *
8: * Copyright 1996 Herman ten Brugge
9: */
10:
1.1.1.2 ! root 11: #include <SDL_endian.h>
! 12:
! 13: typedef double fpu_register;
! 14: typedef union {
! 15: fpu_register val;
! 16: uae_u32 parts[sizeof(fpu_register) / 4];
! 17: } fpu_register_parts;
! 18: enum {
! 19: #if SDL_BYTEORDER == SDL_BIG_ENDIAN
! 20: FHI = 0,
! 21: FLO = 1
! 22: #else
! 23: FHI = 1,
! 24: FLO = 0
! 25: #endif
! 26: };
! 27:
! 28:
1.1 root 29: #ifndef HAVE_to_single
1.1.1.2 ! root 30: STATIC_INLINE double to_single(uae_u32 value)
1.1 root 31: {
1.1.1.2 ! root 32: uae_u32 sign;
! 33: uae_u32 expon;
! 34: fpu_register result;
! 35: fpu_register_parts * p = (fpu_register_parts *)&result;
1.1 root 36:
1.1.1.2 ! root 37: if ((value & 0x7fffffff) == 0)
! 38: return (0.0);
! 39:
! 40: sign = (value & 0x80000000);
! 41: expon = ((value & 0x7F800000) >> 23) + 1023 - 127;
! 42:
! 43: p->parts[FLO] = value << 29;
! 44: p->parts[FHI] = sign | (expon << 20) | ((value & 0x007FFFFF) >> 3);
! 45:
! 46: return result;
1.1 root 47: }
48: #endif
49:
50: #ifndef HAVE_from_single
1.1.1.2 ! root 51: STATIC_INLINE uae_u32 from_single(double src)
1.1 root 52: {
1.1.1.2 ! root 53: uae_u32 sign;
! 54: uae_u32 expon;
! 55: uae_u32 result;
! 56: fpu_register_parts const *p = (fpu_register_parts const *)&src;
! 57:
! 58: if (src == 0.0)
! 59: return 0;
! 60:
! 61: sign = (p->parts[FHI] & 0x80000000);
! 62: expon = (p->parts[FHI] & 0x7FF00000) >> 20;
! 63:
! 64: if (expon + 127 < 1023) {
! 65: expon = 0;
! 66: } else if (expon > 1023 + 127) {
! 67: expon = 255;
! 68: } else {
! 69: expon = expon + 127 - 1023;
! 70: }
1.1 root 71:
1.1.1.2 ! root 72: result = sign | (expon << 23) | ((p->parts[FHI] & 0x000FFFFF) << 3) | (p->parts[FLO] >> 29);
! 73:
! 74: return result;
1.1 root 75: }
76: #endif
77:
78: #ifndef HAVE_to_exten
79: STATIC_INLINE double to_exten(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
80: {
81: double frac;
82:
83: if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
84: return 0.0;
85: frac = (double) wrd2 / 2147483648.0 +
86: (double) wrd3 / 9223372036854775808.0;
87: if (wrd1 & 0x80000000)
88: frac = -frac;
89: return ldexp (frac, ((wrd1 >> 16) & 0x7fff) - 16383);
90: }
91: #endif
92:
93: #ifndef HAVE_from_exten
94: STATIC_INLINE void from_exten(double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3)
95: {
96: int expon;
97: double frac;
98:
99: if (src == 0.0) {
100: *wrd1 = 0;
101: *wrd2 = 0;
102: *wrd3 = 0;
103: return;
104: }
105: if (src < 0) {
106: *wrd1 = 0x80000000;
107: src = -src;
108: } else {
109: *wrd1 = 0;
110: }
111: frac = frexp (src, &expon);
112: frac += 0.5 / 18446744073709551616.0;
113: if (frac >= 1.0) {
114: frac /= 2.0;
115: expon++;
116: }
117: *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
118: *wrd2 = (uae_u32) (frac * 4294967296.0);
119: *wrd3 = (uae_u32) (frac * 18446744073709551616.0 - *wrd2 * 4294967296.0);
120: }
121: #endif
122:
123: #ifndef HAVE_to_double
124: STATIC_INLINE double to_double(uae_u32 wrd1, uae_u32 wrd2)
125: {
1.1.1.2 ! root 126: fpu_register result;
! 127: fpu_register_parts *p = (fpu_register_parts *)&result;
1.1 root 128:
1.1.1.2 ! root 129: if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0)
! 130: return 0.0;
! 131:
! 132: p->parts[FLO] = wrd2;
! 133: p->parts[FHI] = wrd1;
! 134:
! 135: return result;
1.1 root 136: }
137: #endif
138:
139: #ifndef HAVE_from_double
140: STATIC_INLINE void from_double(double src, uae_u32 * wrd1, uae_u32 * wrd2)
141: {
1.1.1.2 ! root 142: /*
! 143: if (src == 0.0) {
! 144: *wrd1 = *wrd2 = 0;
! 145: return;
! 146: }
! 147: */
! 148: fpu_register_parts const *p = (fpu_register_parts const *)&src;
! 149: *wrd2 = p->parts[FLO];
! 150: *wrd1 = p->parts[FHI];
1.1 root 151: }
152: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.