1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include "ieee754sp.h"
16
17
18static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
19 union ieee754sp y, enum maddf_flags flags)
20{
21 int re;
22 int rs;
23 unsigned int rm;
24 u64 rm64;
25 u64 zm64;
26 int s;
27
28 COMPXSP;
29 COMPYSP;
30 COMPZSP;
31
32 EXPLODEXSP;
33 EXPLODEYSP;
34 EXPLODEZSP;
35
36 FLUSHXSP;
37 FLUSHYSP;
38 FLUSHZSP;
39
40 ieee754_clearcx();
41
42
43
44
45
46 if (zc == IEEE754_CLASS_SNAN)
47 return ieee754sp_nanxcpt(z);
48 if (xc == IEEE754_CLASS_SNAN)
49 return ieee754sp_nanxcpt(x);
50 if (yc == IEEE754_CLASS_SNAN)
51 return ieee754sp_nanxcpt(y);
52 if (zc == IEEE754_CLASS_QNAN)
53 return z;
54 if (xc == IEEE754_CLASS_QNAN)
55 return x;
56 if (yc == IEEE754_CLASS_QNAN)
57 return y;
58
59 if (zc == IEEE754_CLASS_DNORM)
60 SPDNORMZ;
61
62
63 switch (CLPAIR(xc, yc)) {
64
65
66
67
68
69 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
70 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
71 ieee754_setcx(IEEE754_INVALID_OPERATION);
72 return ieee754sp_indef();
73
74 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
75 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
76 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
77 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
78 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
79 if ((zc == IEEE754_CLASS_INF) &&
80 ((!(flags & MADDF_NEGATE_PRODUCT) && (zs != (xs ^ ys))) ||
81 ((flags & MADDF_NEGATE_PRODUCT) && (zs == (xs ^ ys))))) {
82
83
84
85
86 ieee754_setcx(IEEE754_INVALID_OPERATION);
87 return ieee754sp_indef();
88 }
89
90
91
92
93
94
95
96 if (flags & MADDF_NEGATE_PRODUCT)
97 return ieee754sp_inf(1 ^ (xs ^ ys));
98 else
99 return ieee754sp_inf(xs ^ ys);
100
101 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
102 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
103 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
104 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
105 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
106 if (zc == IEEE754_CLASS_INF)
107 return ieee754sp_inf(zs);
108 if (zc == IEEE754_CLASS_ZERO) {
109
110 if ((!(flags & MADDF_NEGATE_PRODUCT)
111 && (zs == (xs ^ ys))) ||
112 ((flags & MADDF_NEGATE_PRODUCT)
113 && (zs != (xs ^ ys))))
114
115
116
117
118
119
120 return z;
121
122 return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
123 }
124
125 return z;
126
127 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
128 SPDNORMX;
129
130
131 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
132 if (zc == IEEE754_CLASS_INF)
133 return ieee754sp_inf(zs);
134 SPDNORMY;
135 break;
136
137 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
138 if (zc == IEEE754_CLASS_INF)
139 return ieee754sp_inf(zs);
140 SPDNORMX;
141 break;
142
143 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
144 if (zc == IEEE754_CLASS_INF)
145 return ieee754sp_inf(zs);
146
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160 assert(xm & SP_HIDDEN_BIT);
161 assert(ym & SP_HIDDEN_BIT);
162
163 re = xe + ye;
164 rs = xs ^ ys;
165 if (flags & MADDF_NEGATE_PRODUCT)
166 rs ^= 1;
167
168
169 rm64 = (uint64_t)xm * ym;
170
171
172 rm64 = rm64 << 16;
173
174
175 if ((int64_t) rm64 < 0) {
176 rm64 = rm64 >> 1;
177 re++;
178 }
179
180 assert(rm64 & (1 << 62));
181
182 if (zc == IEEE754_CLASS_ZERO) {
183
184
185
186
187
188 rm = XSPSRS64(rm64, (62 - 26));
189 return ieee754sp_format(rs, re, rm);
190 }
191
192
193 zm64 = (uint64_t)zm << (62 - 23);
194 assert(zm64 & (1 << 62));
195
196
197 if (ze > re) {
198
199
200
201 s = ze - re;
202 rm64 = XSPSRS64(rm64, s);
203 re += s;
204 } else if (re > ze) {
205
206
207
208 s = re - ze;
209 zm64 = XSPSRS64(zm64, s);
210 ze += s;
211 }
212 assert(ze == re);
213 assert(ze <= SP_EMAX);
214
215
216 if (zs == rs) {
217
218
219
220
221 zm64 = zm64 + rm64;
222 if ((int64_t)zm64 < 0) {
223 zm64 = XSPSRS1(zm64);
224 ze++;
225 }
226 } else {
227 if (zm64 >= rm64) {
228 zm64 = zm64 - rm64;
229 } else {
230 zm64 = rm64 - zm64;
231 zs = rs;
232 }
233 if (zm64 == 0)
234 return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
235
236
237
238
239 while ((zm64 >> 62) == 0) {
240 zm64 <<= 1;
241 ze--;
242 }
243 }
244
245
246
247
248
249
250 zm = XSPSRS64(zm64, (62 - 26));
251
252 return ieee754sp_format(zs, ze, zm);
253}
254
255union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
256 union ieee754sp y)
257{
258 return _sp_maddf(z, x, y, 0);
259}
260
261union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
262 union ieee754sp y)
263{
264 return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
265}
266