1 /* IEEE754 floating point arithmetic 2 * double precision: common utilities 3 */ 4 /* 5 * MIPS floating point support 6 * Copyright (C) 1994-2000 Algorithmics Ltd. 7 * Copyright (C) 2017 Imagination Technologies, Ltd. 8 * Author: Aleksandar Markovic <aleksandar.markovic@imgtec.com> 9 * 10 * This program is free software; you can distribute it and/or modify it 11 * under the terms of the GNU General Public License (Version 2) as 12 * published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program. 21 */ 22 23 #include "ieee754dp.h" 24 25 union ieee754dp ieee754dp_rint(union ieee754dp x) 26 { 27 union ieee754dp ret; 28 u64 residue; 29 int sticky; 30 int round; 31 int odd; 32 33 COMPXDP; 34 35 ieee754_clearcx(); 36 37 EXPLODEXDP; 38 FLUSHXDP; 39 40 if (xc == IEEE754_CLASS_SNAN) 41 return ieee754dp_nanxcpt(x); 42 43 if ((xc == IEEE754_CLASS_QNAN) || 44 (xc == IEEE754_CLASS_INF) || 45 (xc == IEEE754_CLASS_ZERO)) 46 return x; 47 48 if (xe >= DP_FBITS) 49 return x; 50 51 if (xe < -1) { 52 residue = xm; 53 round = 0; 54 sticky = residue != 0; 55 xm = 0; 56 } else { 57 residue = xm << (64 - DP_FBITS + xe); 58 round = (residue >> 63) != 0; 59 sticky = (residue << 1) != 0; 60 xm >>= DP_FBITS - xe; 61 } 62 63 odd = (xm & 0x1) != 0x0; 64 65 switch (ieee754_csr.rm) { 66 case FPU_CSR_RN: /* toward nearest */ 67 if (round && (sticky || odd)) 68 xm++; 69 break; 70 case FPU_CSR_RZ: /* toward zero */ 71 break; 72 case FPU_CSR_RU: /* toward +infinity */ 73 if ((round || sticky) && !xs) 74 xm++; 75 break; 76 case FPU_CSR_RD: /* toward -infinity */ 77 if ((round || sticky) && xs) 78 xm++; 79 break; 80 } 81 82 if (round || sticky) 83 ieee754_setcx(IEEE754_INEXACT); 84 85 ret = ieee754dp_flong(xm); 86 DPSIGN(ret) = xs; 87 88 return ret; 89 } 90