root/arch/mips/math-emu/dp_maddf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. srl128
  2. _dp_maddf
  3. ieee754dp_maddf
  4. ieee754dp_msubf

   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. */
  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 
  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 
 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 
 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 }

/* [<][>][^][v][top][bottom][index][help] */