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 s64 ieee754dp_tlong(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 ieee754di_indef();
0031 
0032     case IEEE754_CLASS_INF:
0033         ieee754_setcx(IEEE754_INVALID_OPERATION);
0034         return ieee754di_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 >= 63) {
0044         /* look for valid corner case */
0045         if (xe == 63 && xs && xm == DP_HIDDEN_BIT)
0046             return -0x8000000000000000LL;
0047         /* Set invalid. We will only use overflow for floating
0048            point overflow */
0049         ieee754_setcx(IEEE754_INVALID_OPERATION);
0050         return ieee754di_overflow(xs);
0051     }
0052     /* oh gawd */
0053     if (xe > DP_FBITS) {
0054         xm <<= xe - DP_FBITS;
0055     } else if (xe < DP_FBITS) {
0056         if (xe < -1) {
0057             residue = xm;
0058             round = 0;
0059             sticky = residue != 0;
0060             xm = 0;
0061         } else {
0062             /* Shifting a u64 64 times does not work,
0063             * so we do it in two steps. Be aware that xe
0064             * may be -1 */
0065             residue = xm << (xe + 1);
0066             residue <<= 63 - DP_FBITS;
0067             round = (residue >> 63) != 0;
0068             sticky = (residue << 1) != 0;
0069             xm >>= DP_FBITS - xe;
0070         }
0071         odd = (xm & 0x1) != 0x0;
0072         switch (ieee754_csr.rm) {
0073         case FPU_CSR_RN:
0074             if (round && (sticky || odd))
0075                 xm++;
0076             break;
0077         case FPU_CSR_RZ:
0078             break;
0079         case FPU_CSR_RU:    /* toward +Infinity */
0080             if ((round || sticky) && !xs)
0081                 xm++;
0082             break;
0083         case FPU_CSR_RD:    /* toward -Infinity */
0084             if ((round || sticky) && xs)
0085                 xm++;
0086             break;
0087         }
0088         if ((xm >> 63) != 0) {
0089             /* This can happen after rounding */
0090             ieee754_setcx(IEEE754_INVALID_OPERATION);
0091             return ieee754di_overflow(xs);
0092         }
0093         if (round || sticky)
0094             ieee754_setcx(IEEE754_INEXACT);
0095     }
0096     if (xs)
0097         return -xm;
0098     else
0099         return xm;
0100 }