Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* IEEE754 floating point arithmetic
0003  * single precision
0004  */
0005 /*
0006  * MIPS floating point support
0007  * Copyright (C) 1994-2000 Algorithmics Ltd.
0008  */
0009 
0010 #include "ieee754sp.h"
0011 
0012 union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y)
0013 {
0014     int s;
0015 
0016     COMPXSP;
0017     COMPYSP;
0018 
0019     EXPLODEXSP;
0020     EXPLODEYSP;
0021 
0022     ieee754_clearcx();
0023 
0024     FLUSHXSP;
0025     FLUSHYSP;
0026 
0027     switch (CLPAIR(xc, yc)) {
0028     case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
0029     case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
0030     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
0031     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
0032     case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
0033         return ieee754sp_nanxcpt(y);
0034 
0035     case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
0036     case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
0037     case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
0038     case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
0039     case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
0040     case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
0041         return ieee754sp_nanxcpt(x);
0042 
0043     case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
0044     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
0045     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
0046     case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
0047         return y;
0048 
0049     case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
0050     case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
0051     case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
0052     case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
0053     case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
0054         return x;
0055 
0056 
0057     /*
0058      * Infinity handling
0059      */
0060     case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
0061         if (xs == ys)
0062             return x;
0063         ieee754_setcx(IEEE754_INVALID_OPERATION);
0064         return ieee754sp_indef();
0065 
0066     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
0067     case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
0068     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
0069         return y;
0070 
0071     case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
0072     case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
0073     case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
0074         return x;
0075 
0076     /*
0077      * Zero handling
0078      */
0079     case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
0080         if (xs == ys)
0081             return x;
0082         else
0083             return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
0084 
0085     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
0086     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
0087         return x;
0088 
0089     case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
0090     case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
0091         return y;
0092 
0093     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
0094         SPDNORMX;
0095         fallthrough;
0096     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
0097         SPDNORMY;
0098         break;
0099 
0100     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
0101         SPDNORMX;
0102         break;
0103 
0104     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
0105         break;
0106     }
0107     assert(xm & SP_HIDDEN_BIT);
0108     assert(ym & SP_HIDDEN_BIT);
0109 
0110     /*
0111      * Provide guard, round and stick bit space.
0112      */
0113     xm <<= 3;
0114     ym <<= 3;
0115 
0116     if (xe > ye) {
0117         /*
0118          * Have to shift y fraction right to align.
0119          */
0120         s = xe - ye;
0121         ym = XSPSRS(ym, s);
0122         ye += s;
0123     } else if (ye > xe) {
0124         /*
0125          * Have to shift x fraction right to align.
0126          */
0127         s = ye - xe;
0128         xm = XSPSRS(xm, s);
0129         xe += s;
0130     }
0131     assert(xe == ye);
0132     assert(xe <= SP_EMAX);
0133 
0134     if (xs == ys) {
0135         /*
0136          * Generate 28 bit result of adding two 27 bit numbers
0137          * leaving result in xm, xs and xe.
0138          */
0139         xm = xm + ym;
0140 
0141         if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */
0142             SPXSRSX1();
0143         }
0144     } else {
0145         if (xm >= ym) {
0146             xm = xm - ym;
0147         } else {
0148             xm = ym - xm;
0149             xs = ys;
0150         }
0151         if (xm == 0)
0152             return ieee754sp_zero(ieee754_csr.rm == FPU_CSR_RD);
0153 
0154         /*
0155          * Normalize in extended single precision
0156          */
0157         while ((xm >> (SP_FBITS + 3)) == 0) {
0158             xm <<= 1;
0159             xe--;
0160         }
0161     }
0162 
0163     return ieee754sp_format(xs, xe, xm);
0164 }