|
|
1.1 root 1: //
2: // XM6i
3: // Copyright (C) 2013 [email protected]
4: //
5: // for host FPU mode
6: //
7:
8: #include <float.h>
9: #include <stdio.h>
10: #include <string.h>
11:
12: #include "cmake_config.h"
13: #include "fpu_emulate.h"
14:
15: /*
16: * M68881/2 の浮動小数点表現(IEEE754)をホストの浮動小数点表現に変換する。
17: */
18:
19: /* ホスト演算用のダミー fpemu */
20: static struct fpemu dummyfe;
21:
22: float
23: fpu_to_host_float(const uint32_t *src)
24: {
25: return *(const float *)src;
26: }
27:
28: double
29: fpu_to_host_double(const uint32_t *src)
30: {
31: double dst = 0; /* shut up gcc */
32: uint32_t *d = (uint32_t *)&dst;
33:
34: d[1] = src[0];
35: d[0] = src[1];
36: return dst;
37: }
38:
39: #if defined(HAVE_LONG_DOUBLE)
40: long double
41: fpu_to_host_ldouble(const uint32_t *src)
42: {
43: long double dst = 0; /* shut up gcc */
44: uint32_t *d = (uint32_t *)&dst;
45:
46: #if LONG_DOUBLE == 16
47: /* amd64 だと16バイト境界にしたいのでパディングがあるだけ */
48: d[3] = 0;
49: #endif
50: /* intel フォーマットは16bitパディングの位置が 68881 とは逆 */
51: d[2] = src[0] >> 16;
52: d[1] = src[1];
53: d[0] = src[2];
54:
55: return dst;
56: }
57: #endif /* HAVE_LONG_DOUBLE */
58:
59: void
60: host_float_to_fpu(uint32_t *dst, float src)
61: {
62: // stub
63: }
64:
65: void
66: host_double_to_fpu(uint32_t *dst, double src)
67: {
68: uint32_t *s = (uint32_t *)&src;
69:
70: dst[1] = s[0];
71: dst[0] = s[1];
72: }
73:
74: void
75: host_ldouble_to_fpu(uint32_t *dst, long double src)
76: {
77: // stub
78: }
79:
80: /*
81: * fpn 表現とホスト浮動小数点の変換
82: */
83:
84: /*
85: * +-INF を作成して返す。
86: * 符号部は fp の符号を使うが、指数部/仮数部はこちらで用意する。
87: * 特に ISINF(fp) で判定した場合 fp の仮数部は不定なので流用してはいけない。
88: */
89: static inline double
90: fp2dbl_inf(const struct fpn *fp)
91: {
92: uint64_t v;
93:
94: if (fp->fp_sign) {
95: // -INF
96: v = 0xfff0000000000000ULL;
97: } else {
98: // +INF
99: v = 0x7ff0000000000000ULL;
100: }
101: return *(double*)&v;
102: }
103:
104: double
105: fp2dbl(const struct fpn *fp)
106: {
107: int exp;
108: uint64_t v;
109:
110: if (ISNAN(fp)) {
111: exp = DBL_EXP_INFNAN;
112: } else if (ISINF(fp)) {
113: return fp2dbl_inf(fp);
114: } else {
115: exp = fp->fp_exp + DBL_EXP_BIAS;
116: // exp <= 0 は X 精度を D 精度にするとアンダーフローするケース。
117: if (ISZERO(fp) || exp <= 0) {
118: if (fp->fp_sign) {
119: return -0.0;
120: } else {
121: return 0.0;
122: }
123: } else if (exp >= DBL_EXP_INFNAN) {
124: return fp2dbl_inf(fp);
125: }
126: }
127:
128: v = (fp->fp_sign);
129: v <<= 11;
130: v |= exp;
131: v <<= FP_LG;
132: // mant の有効な上位の 52 ビットを取り出す
133: v |= fp->fp_mant[0] & (FP_1 - 1);
134: v <<= 32;
135: v |= fp->fp_mant[1];
136: v <<= 2;
137: v |= (fp->fp_mant[2] >> (32-2)) & 0x03;
138:
139: return *(double*)&v;
140: }
141:
142: long double
143: fp2ldbl(const struct fpn *f)
144: {
145: struct fpn fp;
146: uint32_t a[3];
147:
148: CPYFPN(&fp, f);
149: fpu_implode(&dummyfe, &fp, FTYPE_EXT, a);
150: return fpu_to_host_ldouble(a);
151: }
152:
153: void
154: dbl2fp(struct fpn *fp, double src)
155: {
156: uint32_t a[2];
157:
158: host_double_to_fpu(a, src);
159: fpu_explode(&dummyfe, fp, FTYPE_DBL, a);
160: return;
161: }
162:
163: void
164: ldbl2fp(struct fpn *fp, long double src)
165: {
166: // stub
167: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.