~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/math-emu/sp_maddf.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * IEEE754 floating point arithmetic
  4  * single 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 "ieee754sp.h"
 13 
 14 
 15 static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
 16                                  union ieee754sp y, enum maddf_flags flags)
 17 {
 18         int re;
 19         int rs;
 20         unsigned int rm;
 21         u64 rm64;
 22         u64 zm64;
 23         int s;
 24 
 25         COMPXSP;
 26         COMPYSP;
 27         COMPZSP;
 28 
 29         EXPLODEXSP;
 30         EXPLODEYSP;
 31         EXPLODEZSP;
 32 
 33         FLUSHXSP;
 34         FLUSHYSP;
 35         FLUSHZSP;
 36 
 37         ieee754_clearcx();
 38 
 39         rs = xs ^ ys;
 40         if (flags & MADDF_NEGATE_PRODUCT)
 41                 rs ^= 1;
 42         if (flags & MADDF_NEGATE_ADDITION)
 43                 zs ^= 1;
 44 
 45         /*
 46          * Handle the cases when at least one of x, y or z is a NaN.
 47          * Order of precedence is sNaN, qNaN and z, x, y.
 48          */
 49         if (zc == IEEE754_CLASS_SNAN)
 50                 return ieee754sp_nanxcpt(z);
 51         if (xc == IEEE754_CLASS_SNAN)
 52                 return ieee754sp_nanxcpt(x);
 53         if (yc == IEEE754_CLASS_SNAN)
 54                 return ieee754sp_nanxcpt(y);
 55         if (zc == IEEE754_CLASS_QNAN)
 56                 return z;
 57         if (xc == IEEE754_CLASS_QNAN)
 58                 return x;
 59         if (yc == IEEE754_CLASS_QNAN)
 60                 return y;
 61 
 62         if (zc == IEEE754_CLASS_DNORM)
 63                 SPDNORMZ;
 64         /* ZERO z cases are handled separately below */
 65 
 66         switch (CLPAIR(xc, yc)) {
 67 
 68 
 69         /*
 70          * Infinity handling
 71          */
 72         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
 73         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
 74                 ieee754_setcx(IEEE754_INVALID_OPERATION);
 75                 return ieee754sp_indef();
 76 
 77         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
 78         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
 79         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
 80         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
 81         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
 82                 if ((zc == IEEE754_CLASS_INF) && (zs != rs)) {
 83                         /*
 84                          * Cases of addition of infinities with opposite signs
 85                          * or subtraction of infinities with same signs.
 86                          */
 87                         ieee754_setcx(IEEE754_INVALID_OPERATION);
 88                         return ieee754sp_indef();
 89                 }
 90                 /*
 91                  * z is here either not an infinity, or an infinity having the
 92                  * same sign as product (x*y). The result must be an infinity,
 93                  * and its sign is determined only by the sign of product (x*y).
 94                  */
 95                 return ieee754sp_inf(rs);
 96 
 97         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
 98         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
 99         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
100         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
101         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
102                 if (zc == IEEE754_CLASS_INF)
103                         return ieee754sp_inf(zs);
104                 if (zc == IEEE754_CLASS_ZERO) {
105                         /* Handle cases +0 + (-0) and similar ones. */
106                         if (zs == rs)
107                                 /*
108                                  * Cases of addition of zeros of equal signs
109                                  * or subtraction of zeroes of opposite signs.
110                                  * The sign of the resulting zero is in any
111                                  * such case determined only by the sign of z.
112                                  */
113                                 return z;
114 
115                         return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
116                 }
117                 /* x*y is here 0, and z is not 0, so just return z */
118                 return z;
119 
120         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
121                 SPDNORMX;
122                 fallthrough;
123         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
124                 if (zc == IEEE754_CLASS_INF)
125                         return ieee754sp_inf(zs);
126                 SPDNORMY;
127                 break;
128 
129         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
130                 if (zc == IEEE754_CLASS_INF)
131                         return ieee754sp_inf(zs);
132                 SPDNORMX;
133                 break;
134 
135         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
136                 if (zc == IEEE754_CLASS_INF)
137                         return ieee754sp_inf(zs);
138                 /* continue to real computations */
139         }
140 
141         /* Finally get to do some computation */
142 
143         /*
144          * Do the multiplication bit first
145          *
146          * rm = xm * ym, re = xe + ye basically
147          *
148          * At this point xm and ym should have been normalized.
149          */
150 
151         /* rm = xm * ym, re = xe+ye basically */
152         assert(xm & SP_HIDDEN_BIT);
153         assert(ym & SP_HIDDEN_BIT);
154 
155         re = xe + ye;
156 
157         /* Multiple 24 bit xm and ym to give 48 bit results */
158         rm64 = (uint64_t)xm * ym;
159 
160         /* Shunt to top of word */
161         rm64 = rm64 << 16;
162 
163         /* Put explicit bit at bit 62 if necessary */
164         if ((int64_t) rm64 < 0) {
165                 rm64 = rm64 >> 1;
166                 re++;
167         }
168 
169         assert(rm64 & (1 << 62));
170 
171         if (zc == IEEE754_CLASS_ZERO) {
172                 /*
173                  * Move explicit bit from bit 62 to bit 26 since the
174                  * ieee754sp_format code expects the mantissa to be
175                  * 27 bits wide (24 + 3 rounding bits).
176                  */
177                 rm = XSPSRS64(rm64, (62 - 26));
178                 return ieee754sp_format(rs, re, rm);
179         }
180 
181         /* Move explicit bit from bit 23 to bit 62 */
182         zm64 = (uint64_t)zm << (62 - 23);
183         assert(zm64 & (1 << 62));
184 
185         /* Make the exponents the same */
186         if (ze > re) {
187                 /*
188                  * Have to shift r fraction right to align.
189                  */
190                 s = ze - re;
191                 rm64 = XSPSRS64(rm64, s);
192                 re += s;
193         } else if (re > ze) {
194                 /*
195                  * Have to shift z fraction right to align.
196                  */
197                 s = re - ze;
198                 zm64 = XSPSRS64(zm64, s);
199                 ze += s;
200         }
201         assert(ze == re);
202         assert(ze <= SP_EMAX);
203 
204         /* Do the addition */
205         if (zs == rs) {
206                 /*
207                  * Generate 64 bit result by adding two 63 bit numbers
208                  * leaving result in zm64, zs and ze.
209                  */
210                 zm64 = zm64 + rm64;
211                 if ((int64_t)zm64 < 0) {        /* carry out */
212                         zm64 = XSPSRS1(zm64);
213                         ze++;
214                 }
215         } else {
216                 if (zm64 >= rm64) {
217                         zm64 = zm64 - rm64;
218                 } else {
219                         zm64 = rm64 - zm64;
220                         zs = rs;
221                 }
222                 if (zm64 == 0)
223                         return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
224 
225                 /*
226                  * Put explicit bit at bit 62 if necessary.
227                  */
228                 while ((zm64 >> 62) == 0) {
229                         zm64 <<= 1;
230                         ze--;
231                 }
232         }
233 
234         /*
235          * Move explicit bit from bit 62 to bit 26 since the
236          * ieee754sp_format code expects the mantissa to be
237          * 27 bits wide (24 + 3 rounding bits).
238          */
239         zm = XSPSRS64(zm64, (62 - 26));
240 
241         return ieee754sp_format(zs, ze, zm);
242 }
243 
244 union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
245                                 union ieee754sp y)
246 {
247         return _sp_maddf(z, x, y, 0);
248 }
249 
250 union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
251                                 union ieee754sp y)
252 {
253         return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
254 }
255 
256 union ieee754sp ieee754sp_madd(union ieee754sp z, union ieee754sp x,
257                                 union ieee754sp y)
258 {
259         return _sp_maddf(z, x, y, 0);
260 }
261 
262 union ieee754sp ieee754sp_msub(union ieee754sp z, union ieee754sp x,
263                                 union ieee754sp y)
264 {
265         return _sp_maddf(z, x, y, MADDF_NEGATE_ADDITION);
266 }
267 
268 union ieee754sp ieee754sp_nmadd(union ieee754sp z, union ieee754sp x,
269                                 union ieee754sp y)
270 {
271         return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT|MADDF_NEGATE_ADDITION);
272 }
273 
274 union ieee754sp ieee754sp_nmsub(union ieee754sp z, union ieee754sp x,
275                                 union ieee754sp y)
276 {
277         return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
278 }
279 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php