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_sub(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_ZERO, IEEE754_CLASS_INF):
0067     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
0068     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
0069         return ieee754sp_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 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         /* quick fix up */
0092         SPSIGN(y) ^= 1;
0093         return y;
0094 
0095     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
0096         SPDNORMX;
0097         fallthrough;
0098     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
0099         SPDNORMY;
0100         break;
0101 
0102     case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
0103         SPDNORMX;
0104         break;
0105 
0106     case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
0107         break;
0108     }
0109     /* flip sign of y and handle as add */
0110     ys ^= 1;
0111 
0112     assert(xm & SP_HIDDEN_BIT);
0113     assert(ym & SP_HIDDEN_BIT);
0114 
0115 
0116     /* provide guard,round and stick bit space */
0117     xm <<= 3;
0118     ym <<= 3;
0119 
0120     if (xe > ye) {
0121         /*
0122          * have to shift y fraction right to align
0123          */
0124         s = xe - ye;
0125         ym = XSPSRS(ym, s);
0126         ye += s;
0127     } else if (ye > xe) {
0128         /*
0129          * have to shift x fraction right to align
0130          */
0131         s = ye - xe;
0132         xm = XSPSRS(xm, s);
0133         xe += s;
0134     }
0135     assert(xe == ye);
0136     assert(xe <= SP_EMAX);
0137 
0138     if (xs == ys) {
0139         /* generate 28 bit result of adding two 27 bit numbers
0140          */
0141         xm = xm + ym;
0142 
0143         if (xm >> (SP_FBITS + 1 + 3)) { /* carry out */
0144             SPXSRSX1(); /* shift preserving sticky */
0145         }
0146     } else {
0147         if (xm >= ym) {
0148             xm = xm - ym;
0149         } else {
0150             xm = ym - xm;
0151             xs = ys;
0152         }
0153         if (xm == 0) {
0154             if (ieee754_csr.rm == FPU_CSR_RD)
0155                 return ieee754sp_zero(1);   /* round negative inf. => sign = -1 */
0156             else
0157                 return ieee754sp_zero(0);   /* other round modes   => sign = 1 */
0158         }
0159         /* normalize to rounding precision
0160          */
0161         while ((xm >> (SP_FBITS + 3)) == 0) {
0162             xm <<= 1;
0163             xe--;
0164         }
0165     }
0166 
0167     return ieee754sp_format(xs, xe, xm);
0168 }