Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* IEEE754 floating point arithmetic
0003  * double precision: common utilities
0004  */
0005 /*
0006  * MIPS floating point support
0007  * Copyright (C) 1994-2000 Algorithmics Ltd.
0008  */
0009 
0010 #include "ieee754dp.h"
0011 
0012 union ieee754dp ieee754dp_sub(union ieee754dp x, union ieee754dp y)
0013 {
0014     int s;
0015 
0016     COMPXDP;
0017     COMPYDP;
0018 
0019     EXPLODEXDP;
0020     EXPLODEYDP;
0021 
0022     ieee754_clearcx();
0023 
0024     FLUSHXDP;
0025     FLUSHYDP;
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 ieee754dp_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 ieee754dp_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 ieee754dp_indef();
0065 
0066     case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
0067     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
0068     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
0069         return ieee754dp_inf(ys ^ 1);
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 ieee754dp_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         /* quick fix up */
0092         DPSIGN(y) ^= 1;
0093         return y;
0094 
0095     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
0096         DPDNORMX;
0097         fallthrough;
0098     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
0099         /* normalize ym,ye */
0100         DPDNORMY;
0101         break;
0102 
0103     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
0104         /* normalize xm,xe */
0105         DPDNORMX;
0106         break;
0107 
0108     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
0109         break;
0110     }
0111     /* flip sign of y and handle as add */
0112     ys ^= 1;
0113 
0114     assert(xm & DP_HIDDEN_BIT);
0115     assert(ym & DP_HIDDEN_BIT);
0116 
0117 
0118     /* provide guard,round and stick bit dpace */
0119     xm <<= 3;
0120     ym <<= 3;
0121 
0122     if (xe > ye) {
0123         /*
0124          * Have to shift y fraction right to align
0125          */
0126         s = xe - ye;
0127         ym = XDPSRS(ym, s);
0128         ye += s;
0129     } else if (ye > xe) {
0130         /*
0131          * Have to shift x fraction right to align
0132          */
0133         s = ye - xe;
0134         xm = XDPSRS(xm, s);
0135         xe += s;
0136     }
0137     assert(xe == ye);
0138     assert(xe <= DP_EMAX);
0139 
0140     if (xs == ys) {
0141         /* generate 28 bit result of adding two 27 bit numbers
0142          */
0143         xm = xm + ym;
0144 
0145         if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */
0146             xm = XDPSRS1(xm);   /* shift preserving sticky */
0147             xe++;
0148         }
0149     } else {
0150         if (xm >= ym) {
0151             xm = xm - ym;
0152         } else {
0153             xm = ym - xm;
0154             xs = ys;
0155         }
0156         if (xm == 0) {
0157             if (ieee754_csr.rm == FPU_CSR_RD)
0158                 return ieee754dp_zero(1);   /* round negative inf. => sign = -1 */
0159             else
0160                 return ieee754dp_zero(0);   /* other round modes   => sign = 1 */
0161         }
0162 
0163         /* normalize to rounding precision
0164          */
0165         while ((xm >> (DP_FBITS + 3)) == 0) {
0166             xm <<= 1;
0167             xe--;
0168         }
0169     }
0170 
0171     return ieee754dp_format(xs, xe, xm);
0172 }