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 s64 ieee754sp_tlong(union ieee754sp x)
0013 {
0014     u32 residue;
0015     int round;
0016     int sticky;
0017     int odd;
0018 
0019     COMPXDP;        /* <-- need 64-bit mantissa tmp */
0020 
0021     ieee754_clearcx();
0022 
0023     EXPLODEXSP;
0024     FLUSHXSP;
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 == SP_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 > SP_FBITS) {
0054         xm <<= xe - SP_FBITS;
0055     } else if (xe < SP_FBITS) {
0056         if (xe < -1) {
0057             residue = xm;
0058             round = 0;
0059             sticky = residue != 0;
0060             xm = 0;
0061         } else {
0062             residue = xm << (32 - SP_FBITS + xe);
0063             round = (residue >> 31) != 0;
0064             sticky = (residue << 1) != 0;
0065             xm >>= SP_FBITS - xe;
0066         }
0067         odd = (xm & 0x1) != 0x0;
0068         switch (ieee754_csr.rm) {
0069         case FPU_CSR_RN:
0070             if (round && (sticky || odd))
0071                 xm++;
0072             break;
0073         case FPU_CSR_RZ:
0074             break;
0075         case FPU_CSR_RU:    /* toward +Infinity */
0076             if ((round || sticky) && !xs)
0077                 xm++;
0078             break;
0079         case FPU_CSR_RD:    /* toward -Infinity */
0080             if ((round || sticky) && xs)
0081                 xm++;
0082             break;
0083         }
0084         if ((xm >> 63) != 0) {
0085             /* This can happen after rounding */
0086             ieee754_setcx(IEEE754_INVALID_OPERATION);
0087             return ieee754di_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 }