1
2
3
4
5
6
7
8
9
10
11
12#include "ieee754dp.h"
13
14
15
16static void srl128(u64 *hptr, u64 *lptr, int count)
17{
18 u64 low;
19
20 if (count >= 128) {
21 *lptr = *hptr != 0 || *lptr != 0;
22 *hptr = 0;
23 } else if (count >= 64) {
24 if (count == 64) {
25 *lptr = *hptr | (*lptr != 0);
26 } else {
27 low = *lptr;
28 *lptr = *hptr >> (count - 64);
29 *lptr |= (*hptr << (128 - count)) != 0 || low != 0;
30 }
31 *hptr = 0;
32 } else {
33 low = *lptr;
34 *lptr = low >> count | *hptr << (64 - count);
35 *lptr |= (low << (64 - count)) != 0;
36 *hptr = *hptr >> count;
37 }
38}
39
40static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
41 union ieee754dp y, enum maddf_flags flags)
42{
43 int re;
44 int rs;
45 unsigned int lxm;
46 unsigned int hxm;
47 unsigned int lym;
48 unsigned int hym;
49 u64 lrm;
50 u64 hrm;
51 u64 lzm;
52 u64 hzm;
53 u64 t;
54 u64 at;
55 int s;
56
57 COMPXDP;
58 COMPYDP;
59 COMPZDP;
60
61 EXPLODEXDP;
62 EXPLODEYDP;
63 EXPLODEZDP;
64
65 FLUSHXDP;
66 FLUSHYDP;
67 FLUSHZDP;
68
69 ieee754_clearcx();
70
71 rs = xs ^ ys;
72 if (flags & MADDF_NEGATE_PRODUCT)
73 rs ^= 1;
74 if (flags & MADDF_NEGATE_ADDITION)
75 zs ^= 1;
76
77
78
79
80
81 if (zc == IEEE754_CLASS_SNAN)
82 return ieee754dp_nanxcpt(z);
83 if (xc == IEEE754_CLASS_SNAN)
84 return ieee754dp_nanxcpt(x);
85 if (yc == IEEE754_CLASS_SNAN)
86 return ieee754dp_nanxcpt(y);
87 if (zc == IEEE754_CLASS_QNAN)
88 return z;
89 if (xc == IEEE754_CLASS_QNAN)
90 return x;
91 if (yc == IEEE754_CLASS_QNAN)
92 return y;
93
94 if (zc == IEEE754_CLASS_DNORM)
95 DPDNORMZ;
96
97
98 switch (CLPAIR(xc, yc)) {
99
100
101
102
103 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
104 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
105 ieee754_setcx(IEEE754_INVALID_OPERATION);
106 return ieee754dp_indef();
107
108 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
109 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
110 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
111 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
112 case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
113 if ((zc == IEEE754_CLASS_INF) && (zs != rs)) {
114
115
116
117
118 ieee754_setcx(IEEE754_INVALID_OPERATION);
119 return ieee754dp_indef();
120 }
121
122
123
124
125
126 return ieee754dp_inf(rs);
127
128 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
129 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
130 case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
131 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
132 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
133 if (zc == IEEE754_CLASS_INF)
134 return ieee754dp_inf(zs);
135 if (zc == IEEE754_CLASS_ZERO) {
136
137 if (zs == rs)
138
139
140
141
142
143
144 return z;
145
146 return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
147 }
148
149 return z;
150
151 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
152 DPDNORMX;
153
154
155 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
156 if (zc == IEEE754_CLASS_INF)
157 return ieee754dp_inf(zs);
158 DPDNORMY;
159 break;
160
161 case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
162 if (zc == IEEE754_CLASS_INF)
163 return ieee754dp_inf(zs);
164 DPDNORMX;
165 break;
166
167 case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
168 if (zc == IEEE754_CLASS_INF)
169 return ieee754dp_inf(zs);
170
171 }
172
173
174
175
176
177
178
179
180
181
182 assert(xm & DP_HIDDEN_BIT);
183 assert(ym & DP_HIDDEN_BIT);
184
185 re = xe + ye;
186
187
188 xm <<= 64 - (DP_FBITS + 1);
189 ym <<= 64 - (DP_FBITS + 1);
190
191
192
193
194
195 lxm = xm;
196 hxm = xm >> 32;
197 lym = ym;
198 hym = ym >> 32;
199
200 lrm = DPXMULT(lxm, lym);
201 hrm = DPXMULT(hxm, hym);
202
203 t = DPXMULT(lxm, hym);
204
205 at = lrm + (t << 32);
206 hrm += at < lrm;
207 lrm = at;
208
209 hrm = hrm + (t >> 32);
210
211 t = DPXMULT(hxm, lym);
212
213 at = lrm + (t << 32);
214 hrm += at < lrm;
215 lrm = at;
216
217 hrm = hrm + (t >> 32);
218
219
220 if ((int64_t)hrm < 0) {
221 lrm = (hrm << 63) | (lrm >> 1);
222 hrm = hrm >> 1;
223 re++;
224 }
225
226 assert(hrm & (1 << 62));
227
228 if (zc == IEEE754_CLASS_ZERO) {
229
230
231
232
233
234 srl128(&hrm, &lrm, (126 - 55));
235 return ieee754dp_format(rs, re, lrm);
236 }
237
238
239 lzm = 0;
240 hzm = zm << 10;
241 assert(hzm & (1 << 62));
242
243
244 if (ze > re) {
245
246
247
248 s = ze - re;
249 srl128(&hrm, &lrm, s);
250 re += s;
251 } else if (re > ze) {
252
253
254
255 s = re - ze;
256 srl128(&hzm, &lzm, s);
257 ze += s;
258 }
259 assert(ze == re);
260 assert(ze <= DP_EMAX);
261
262
263 if (zs == rs) {
264
265
266
267
268 hzm = hzm + hrm + (lzm > (lzm + lrm));
269 lzm = lzm + lrm;
270 if ((int64_t)hzm < 0) {
271 srl128(&hzm, &lzm, 1);
272 ze++;
273 }
274 } else {
275 if (hzm > hrm || (hzm == hrm && lzm >= lrm)) {
276 hzm = hzm - hrm - (lzm < lrm);
277 lzm = lzm - lrm;
278 } else {
279 hzm = hrm - hzm - (lrm < lzm);
280 lzm = lrm - lzm;
281 zs = rs;
282 }
283 if (lzm == 0 && hzm == 0)
284 return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
285
286
287
288
289 if (hzm == 0) {
290
291 if ((int64_t)lzm < 0) {
292
293 hzm = lzm >> 1;
294 lzm = lzm << 63;
295 ze -= 63;
296 } else {
297 hzm = lzm;
298 lzm = 0;
299 ze -= 64;
300 }
301 }
302
303 t = 0;
304 while ((hzm >> (62 - t)) == 0)
305 t++;
306
307 assert(t <= 62);
308 if (t) {
309 hzm = hzm << t | lzm >> (64 - t);
310 lzm = lzm << t;
311 ze -= t;
312 }
313 }
314
315
316
317
318
319
320 srl128(&hzm, &lzm, (126 - 55));
321
322 return ieee754dp_format(zs, ze, lzm);
323}
324
325union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
326 union ieee754dp y)
327{
328 return _dp_maddf(z, x, y, 0);
329}
330
331union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
332 union ieee754dp y)
333{
334 return _dp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
335}
336
337union ieee754dp ieee754dp_madd(union ieee754dp z, union ieee754dp x,
338 union ieee754dp y)
339{
340 return _dp_maddf(z, x, y, 0);
341}
342
343union ieee754dp ieee754dp_msub(union ieee754dp z, union ieee754dp x,
344 union ieee754dp y)
345{
346 return _dp_maddf(z, x, y, MADDF_NEGATE_ADDITION);
347}
348
349union ieee754dp ieee754dp_nmadd(union ieee754dp z, union ieee754dp x,
350 union ieee754dp y)
351{
352 return _dp_maddf(z, x, y, MADDF_NEGATE_PRODUCT|MADDF_NEGATE_ADDITION);
353}
354
355union ieee754dp ieee754dp_nmsub(union ieee754dp z, union ieee754dp x,
356 union ieee754dp y)
357{
358 return _dp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
359}
360