• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * IEEE754 floating point arithmetic
4  * double precision: MADDF.f (Fused Multiply Add)
5  * MADDF.fmt: FPR[fd] = FPR[fd] + (FPR[fs] x FPR[ft])
6  *
7  * MIPS floating point support
8  * Copyright (C) 2015 Imagination Technologies, Ltd.
9  * Author: Markos Chandras <markos.chandras@imgtec.com>
10  */
11 
12 #include "ieee754dp.h"
13 
14 
15 /* 128 bits shift right logical with rounding. */
srl128(u64 * hptr,u64 * lptr,int count)16 static 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 
_dp_maddf(union ieee754dp z,union ieee754dp x,union ieee754dp y,enum maddf_flags flags)40 static 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 	/*
72 	 * Handle the cases when at least one of x, y or z is a NaN.
73 	 * Order of precedence is sNaN, qNaN and z, x, y.
74 	 */
75 	if (zc == IEEE754_CLASS_SNAN)
76 		return ieee754dp_nanxcpt(z);
77 	if (xc == IEEE754_CLASS_SNAN)
78 		return ieee754dp_nanxcpt(x);
79 	if (yc == IEEE754_CLASS_SNAN)
80 		return ieee754dp_nanxcpt(y);
81 	if (zc == IEEE754_CLASS_QNAN)
82 		return z;
83 	if (xc == IEEE754_CLASS_QNAN)
84 		return x;
85 	if (yc == IEEE754_CLASS_QNAN)
86 		return y;
87 
88 	if (zc == IEEE754_CLASS_DNORM)
89 		DPDNORMZ;
90 	/* ZERO z cases are handled separately below */
91 
92 	switch (CLPAIR(xc, yc)) {
93 
94 	/*
95 	 * Infinity handling
96 	 */
97 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
98 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
99 		ieee754_setcx(IEEE754_INVALID_OPERATION);
100 		return ieee754dp_indef();
101 
102 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
103 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
104 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
105 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
106 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
107 		if ((zc == IEEE754_CLASS_INF) &&
108 		    ((!(flags & MADDF_NEGATE_PRODUCT) && (zs != (xs ^ ys))) ||
109 		     ((flags & MADDF_NEGATE_PRODUCT) && (zs == (xs ^ ys))))) {
110 			/*
111 			 * Cases of addition of infinities with opposite signs
112 			 * or subtraction of infinities with same signs.
113 			 */
114 			ieee754_setcx(IEEE754_INVALID_OPERATION);
115 			return ieee754dp_indef();
116 		}
117 		/*
118 		 * z is here either not an infinity, or an infinity having the
119 		 * same sign as product (x*y) (in case of MADDF.D instruction)
120 		 * or product -(x*y) (in MSUBF.D case). The result must be an
121 		 * infinity, and its sign is determined only by the value of
122 		 * (flags & MADDF_NEGATE_PRODUCT) and the signs of x and y.
123 		 */
124 		if (flags & MADDF_NEGATE_PRODUCT)
125 			return ieee754dp_inf(1 ^ (xs ^ ys));
126 		else
127 			return ieee754dp_inf(xs ^ ys);
128 
129 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
130 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
131 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
132 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
133 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
134 		if (zc == IEEE754_CLASS_INF)
135 			return ieee754dp_inf(zs);
136 		if (zc == IEEE754_CLASS_ZERO) {
137 			/* Handle cases +0 + (-0) and similar ones. */
138 			if ((!(flags & MADDF_NEGATE_PRODUCT)
139 					&& (zs == (xs ^ ys))) ||
140 			    ((flags & MADDF_NEGATE_PRODUCT)
141 					&& (zs != (xs ^ ys))))
142 				/*
143 				 * Cases of addition of zeros of equal signs
144 				 * or subtraction of zeroes of opposite signs.
145 				 * The sign of the resulting zero is in any
146 				 * such case determined only by the sign of z.
147 				 */
148 				return z;
149 
150 			return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
151 		}
152 		/* x*y is here 0, and z is not 0, so just return z */
153 		return z;
154 
155 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
156 		DPDNORMX;
157 		/* fall through */
158 
159 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
160 		if (zc == IEEE754_CLASS_INF)
161 			return ieee754dp_inf(zs);
162 		DPDNORMY;
163 		break;
164 
165 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
166 		if (zc == IEEE754_CLASS_INF)
167 			return ieee754dp_inf(zs);
168 		DPDNORMX;
169 		break;
170 
171 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
172 		if (zc == IEEE754_CLASS_INF)
173 			return ieee754dp_inf(zs);
174 		/* continue to real computations */
175 	}
176 
177 	/* Finally get to do some computation */
178 
179 	/*
180 	 * Do the multiplication bit first
181 	 *
182 	 * rm = xm * ym, re = xe + ye basically
183 	 *
184 	 * At this point xm and ym should have been normalized.
185 	 */
186 	assert(xm & DP_HIDDEN_BIT);
187 	assert(ym & DP_HIDDEN_BIT);
188 
189 	re = xe + ye;
190 	rs = xs ^ ys;
191 	if (flags & MADDF_NEGATE_PRODUCT)
192 		rs ^= 1;
193 
194 	/* shunt to top of word */
195 	xm <<= 64 - (DP_FBITS + 1);
196 	ym <<= 64 - (DP_FBITS + 1);
197 
198 	/*
199 	 * Multiply 64 bits xm and ym to give 128 bits result in hrm:lrm.
200 	 */
201 
202 	lxm = xm;
203 	hxm = xm >> 32;
204 	lym = ym;
205 	hym = ym >> 32;
206 
207 	lrm = DPXMULT(lxm, lym);
208 	hrm = DPXMULT(hxm, hym);
209 
210 	t = DPXMULT(lxm, hym);
211 
212 	at = lrm + (t << 32);
213 	hrm += at < lrm;
214 	lrm = at;
215 
216 	hrm = hrm + (t >> 32);
217 
218 	t = DPXMULT(hxm, lym);
219 
220 	at = lrm + (t << 32);
221 	hrm += at < lrm;
222 	lrm = at;
223 
224 	hrm = hrm + (t >> 32);
225 
226 	/* Put explicit bit at bit 126 if necessary */
227 	if ((int64_t)hrm < 0) {
228 		lrm = (hrm << 63) | (lrm >> 1);
229 		hrm = hrm >> 1;
230 		re++;
231 	}
232 
233 	assert(hrm & (1 << 62));
234 
235 	if (zc == IEEE754_CLASS_ZERO) {
236 		/*
237 		 * Move explicit bit from bit 126 to bit 55 since the
238 		 * ieee754dp_format code expects the mantissa to be
239 		 * 56 bits wide (53 + 3 rounding bits).
240 		 */
241 		srl128(&hrm, &lrm, (126 - 55));
242 		return ieee754dp_format(rs, re, lrm);
243 	}
244 
245 	/* Move explicit bit from bit 52 to bit 126 */
246 	lzm = 0;
247 	hzm = zm << 10;
248 	assert(hzm & (1 << 62));
249 
250 	/* Make the exponents the same */
251 	if (ze > re) {
252 		/*
253 		 * Have to shift y fraction right to align.
254 		 */
255 		s = ze - re;
256 		srl128(&hrm, &lrm, s);
257 		re += s;
258 	} else if (re > ze) {
259 		/*
260 		 * Have to shift x fraction right to align.
261 		 */
262 		s = re - ze;
263 		srl128(&hzm, &lzm, s);
264 		ze += s;
265 	}
266 	assert(ze == re);
267 	assert(ze <= DP_EMAX);
268 
269 	/* Do the addition */
270 	if (zs == rs) {
271 		/*
272 		 * Generate 128 bit result by adding two 127 bit numbers
273 		 * leaving result in hzm:lzm, zs and ze.
274 		 */
275 		hzm = hzm + hrm + (lzm > (lzm + lrm));
276 		lzm = lzm + lrm;
277 		if ((int64_t)hzm < 0) {        /* carry out */
278 			srl128(&hzm, &lzm, 1);
279 			ze++;
280 		}
281 	} else {
282 		if (hzm > hrm || (hzm == hrm && lzm >= lrm)) {
283 			hzm = hzm - hrm - (lzm < lrm);
284 			lzm = lzm - lrm;
285 		} else {
286 			hzm = hrm - hzm - (lrm < lzm);
287 			lzm = lrm - lzm;
288 			zs = rs;
289 		}
290 		if (lzm == 0 && hzm == 0)
291 			return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD);
292 
293 		/*
294 		 * Put explicit bit at bit 126 if necessary.
295 		 */
296 		if (hzm == 0) {
297 			/* left shift by 63 or 64 bits */
298 			if ((int64_t)lzm < 0) {
299 				/* MSB of lzm is the explicit bit */
300 				hzm = lzm >> 1;
301 				lzm = lzm << 63;
302 				ze -= 63;
303 			} else {
304 				hzm = lzm;
305 				lzm = 0;
306 				ze -= 64;
307 			}
308 		}
309 
310 		t = 0;
311 		while ((hzm >> (62 - t)) == 0)
312 			t++;
313 
314 		assert(t <= 62);
315 		if (t) {
316 			hzm = hzm << t | lzm >> (64 - t);
317 			lzm = lzm << t;
318 			ze -= t;
319 		}
320 	}
321 
322 	/*
323 	 * Move explicit bit from bit 126 to bit 55 since the
324 	 * ieee754dp_format code expects the mantissa to be
325 	 * 56 bits wide (53 + 3 rounding bits).
326 	 */
327 	srl128(&hzm, &lzm, (126 - 55));
328 
329 	return ieee754dp_format(zs, ze, lzm);
330 }
331 
ieee754dp_maddf(union ieee754dp z,union ieee754dp x,union ieee754dp y)332 union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
333 				union ieee754dp y)
334 {
335 	return _dp_maddf(z, x, y, 0);
336 }
337 
ieee754dp_msubf(union ieee754dp z,union ieee754dp x,union ieee754dp y)338 union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
339 				union ieee754dp y)
340 {
341 	return _dp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
342 }
343