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 int ieee754dp_tint(union ieee754dp x)
0013 {
0014     u64 residue;
0015     int round;
0016     int sticky;
0017     int odd;
0018 
0019     COMPXDP;
0020 
0021     ieee754_clearcx();
0022 
0023     EXPLODEXDP;
0024     FLUSHXDP;
0025 
0026     switch (xc) {
0027     case IEEE754_CLASS_SNAN:
0028     case IEEE754_CLASS_QNAN:
0029         ieee754_setcx(IEEE754_INVALID_OPERATION);
0030         return ieee754si_indef();
0031 
0032     case IEEE754_CLASS_INF:
0033         ieee754_setcx(IEEE754_INVALID_OPERATION);
0034         return ieee754si_overflow(xs);
0035 
0036     case IEEE754_CLASS_ZERO:
0037         return 0;
0038 
0039     case IEEE754_CLASS_DNORM:
0040     case IEEE754_CLASS_NORM:
0041         break;
0042     }
0043     if (xe > 31) {
0044         /* Set invalid. We will only use overflow for floating
0045            point overflow */
0046         ieee754_setcx(IEEE754_INVALID_OPERATION);
0047         return ieee754si_overflow(xs);
0048     }
0049     /* oh gawd */
0050     if (xe > DP_FBITS) {
0051         xm <<= xe - DP_FBITS;
0052     } else if (xe < DP_FBITS) {
0053         if (xe < -1) {
0054             residue = xm;
0055             round = 0;
0056             sticky = residue != 0;
0057             xm = 0;
0058         } else {
0059             residue = xm << (64 - DP_FBITS + xe);
0060             round = (residue >> 63) != 0;
0061             sticky = (residue << 1) != 0;
0062             xm >>= DP_FBITS - xe;
0063         }
0064         /* Note: At this point upper 32 bits of xm are guaranteed
0065            to be zero */
0066         odd = (xm & 0x1) != 0x0;
0067         switch (ieee754_csr.rm) {
0068         case FPU_CSR_RN:
0069             if (round && (sticky || odd))
0070                 xm++;
0071             break;
0072         case FPU_CSR_RZ:
0073             break;
0074         case FPU_CSR_RU:    /* toward +Infinity */
0075             if ((round || sticky) && !xs)
0076                 xm++;
0077             break;
0078         case FPU_CSR_RD:    /* toward -Infinity */
0079             if ((round || sticky) && xs)
0080                 xm++;
0081             break;
0082         }
0083         /* look for valid corner case 0x80000000 */
0084         if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) {
0085             /* This can happen after rounding */
0086             ieee754_setcx(IEEE754_INVALID_OPERATION);
0087             return ieee754si_overflow(xs);
0088         }
0089         if (round || sticky)
0090             ieee754_setcx(IEEE754_INEXACT);
0091     }
0092     if (xs)
0093         return -xm;
0094     else
0095         return xm;
0096 }