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

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

DEFINITIONS

This source file includes following definitions.
  1. ieee754sp_class
  2. ieee754sp_isnan
  3. ieee754sp_issnan
  4. ieee754sp_nanxcpt
  5. ieee754sp_get_rounding
  6. ieee754sp_format

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* IEEE754 floating point arithmetic
   3  * single precision
   4  */
   5 /*
   6  * MIPS floating point support
   7  * Copyright (C) 1994-2000 Algorithmics Ltd.
   8  */
   9 
  10 #include <linux/compiler.h>
  11 
  12 #include "ieee754sp.h"
  13 
  14 int ieee754sp_class(union ieee754sp x)
  15 {
  16         COMPXSP;
  17         EXPLODEXSP;
  18         return xc;
  19 }
  20 
  21 static inline int ieee754sp_isnan(union ieee754sp x)
  22 {
  23         return ieee754_class_nan(ieee754sp_class(x));
  24 }
  25 
  26 static inline int ieee754sp_issnan(union ieee754sp x)
  27 {
  28         int qbit;
  29 
  30         assert(ieee754sp_isnan(x));
  31         qbit = (SPMANT(x) & SP_MBIT(SP_FBITS - 1)) == SP_MBIT(SP_FBITS - 1);
  32         return ieee754_csr.nan2008 ^ qbit;
  33 }
  34 
  35 
  36 /*
  37  * Raise the Invalid Operation IEEE 754 exception
  38  * and convert the signaling NaN supplied to a quiet NaN.
  39  */
  40 union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r)
  41 {
  42         assert(ieee754sp_issnan(r));
  43 
  44         ieee754_setcx(IEEE754_INVALID_OPERATION);
  45         if (ieee754_csr.nan2008) {
  46                 SPMANT(r) |= SP_MBIT(SP_FBITS - 1);
  47         } else {
  48                 SPMANT(r) &= ~SP_MBIT(SP_FBITS - 1);
  49                 if (!ieee754sp_isnan(r))
  50                         SPMANT(r) |= SP_MBIT(SP_FBITS - 2);
  51         }
  52 
  53         return r;
  54 }
  55 
  56 static unsigned int ieee754sp_get_rounding(int sn, unsigned int xm)
  57 {
  58         /* inexact must round of 3 bits
  59          */
  60         if (xm & (SP_MBIT(3) - 1)) {
  61                 switch (ieee754_csr.rm) {
  62                 case FPU_CSR_RZ:
  63                         break;
  64                 case FPU_CSR_RN:
  65                         xm += 0x3 + ((xm >> 3) & 1);
  66                         /* xm += (xm&0x8)?0x4:0x3 */
  67                         break;
  68                 case FPU_CSR_RU:        /* toward +Infinity */
  69                         if (!sn)        /* ?? */
  70                                 xm += 0x8;
  71                         break;
  72                 case FPU_CSR_RD:        /* toward -Infinity */
  73                         if (sn) /* ?? */
  74                                 xm += 0x8;
  75                         break;
  76                 }
  77         }
  78         return xm;
  79 }
  80 
  81 
  82 /* generate a normal/denormal number with over,under handling
  83  * sn is sign
  84  * xe is an unbiased exponent
  85  * xm is 3bit extended precision value.
  86  */
  87 union ieee754sp ieee754sp_format(int sn, int xe, unsigned int xm)
  88 {
  89         assert(xm);             /* we don't gen exact zeros (probably should) */
  90 
  91         assert((xm >> (SP_FBITS + 1 + 3)) == 0);        /* no excess */
  92         assert(xm & (SP_HIDDEN_BIT << 3));
  93 
  94         if (xe < SP_EMIN) {
  95                 /* strip lower bits */
  96                 int es = SP_EMIN - xe;
  97 
  98                 if (ieee754_csr.nod) {
  99                         ieee754_setcx(IEEE754_UNDERFLOW);
 100                         ieee754_setcx(IEEE754_INEXACT);
 101 
 102                         switch(ieee754_csr.rm) {
 103                         case FPU_CSR_RN:
 104                         case FPU_CSR_RZ:
 105                                 return ieee754sp_zero(sn);
 106                         case FPU_CSR_RU:      /* toward +Infinity */
 107                                 if (sn == 0)
 108                                         return ieee754sp_min(0);
 109                                 else
 110                                         return ieee754sp_zero(1);
 111                         case FPU_CSR_RD:      /* toward -Infinity */
 112                                 if (sn == 0)
 113                                         return ieee754sp_zero(0);
 114                                 else
 115                                         return ieee754sp_min(1);
 116                         }
 117                 }
 118 
 119                 if (xe == SP_EMIN - 1 &&
 120                     ieee754sp_get_rounding(sn, xm) >> (SP_FBITS + 1 + 3))
 121                 {
 122                         /* Not tiny after rounding */
 123                         ieee754_setcx(IEEE754_INEXACT);
 124                         xm = ieee754sp_get_rounding(sn, xm);
 125                         xm >>= 1;
 126                         /* Clear grs bits */
 127                         xm &= ~(SP_MBIT(3) - 1);
 128                         xe++;
 129                 } else {
 130                         /* sticky right shift es bits
 131                          */
 132                         xm = XSPSRS(xm, es);
 133                         xe += es;
 134                         assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
 135                         assert(xe == SP_EMIN);
 136                 }
 137         }
 138         if (xm & (SP_MBIT(3) - 1)) {
 139                 ieee754_setcx(IEEE754_INEXACT);
 140                 if ((xm & (SP_HIDDEN_BIT << 3)) == 0) {
 141                         ieee754_setcx(IEEE754_UNDERFLOW);
 142                 }
 143 
 144                 /* inexact must round of 3 bits
 145                  */
 146                 xm = ieee754sp_get_rounding(sn, xm);
 147                 /* adjust exponent for rounding add overflowing
 148                  */
 149                 if (xm >> (SP_FBITS + 1 + 3)) {
 150                         /* add causes mantissa overflow */
 151                         xm >>= 1;
 152                         xe++;
 153                 }
 154         }
 155         /* strip grs bits */
 156         xm >>= 3;
 157 
 158         assert((xm >> (SP_FBITS + 1)) == 0);    /* no excess */
 159         assert(xe >= SP_EMIN);
 160 
 161         if (xe > SP_EMAX) {
 162                 ieee754_setcx(IEEE754_OVERFLOW);
 163                 ieee754_setcx(IEEE754_INEXACT);
 164                 /* -O can be table indexed by (rm,sn) */
 165                 switch (ieee754_csr.rm) {
 166                 case FPU_CSR_RN:
 167                         return ieee754sp_inf(sn);
 168                 case FPU_CSR_RZ:
 169                         return ieee754sp_max(sn);
 170                 case FPU_CSR_RU:        /* toward +Infinity */
 171                         if (sn == 0)
 172                                 return ieee754sp_inf(0);
 173                         else
 174                                 return ieee754sp_max(1);
 175                 case FPU_CSR_RD:        /* toward -Infinity */
 176                         if (sn == 0)
 177                                 return ieee754sp_max(0);
 178                         else
 179                                 return ieee754sp_inf(1);
 180                 }
 181         }
 182         /* gen norm/denorm/zero */
 183 
 184         if ((xm & SP_HIDDEN_BIT) == 0) {
 185                 /* we underflow (tiny/zero) */
 186                 assert(xe == SP_EMIN);
 187                 if (ieee754_csr.mx & IEEE754_UNDERFLOW)
 188                         ieee754_setcx(IEEE754_UNDERFLOW);
 189                 return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
 190         } else {
 191                 assert((xm >> (SP_FBITS + 1)) == 0);    /* no excess */
 192                 assert(xm & SP_HIDDEN_BIT);
 193 
 194                 return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
 195         }
 196 }

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