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

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

DEFINITIONS

This source file includes following definitions.
  1. _sp_maddf
  2. ieee754sp_maddf
  3. ieee754sp_msubf

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

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