xref: /openbmc/linux/arch/mips/math-emu/sp_rint.c (revision 82e6fdd6)
1 /* IEEE754 floating point arithmetic
2  * single precision
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 "ieee754sp.h"
24 
25 union ieee754sp ieee754sp_rint(union ieee754sp x)
26 {
27 	union ieee754sp ret;
28 	u32 residue;
29 	int sticky;
30 	int round;
31 	int odd;
32 
33 	COMPXDP;		/* <-- DP needed for 64-bit mantissa tmp */
34 
35 	ieee754_clearcx();
36 
37 	EXPLODEXSP;
38 	FLUSHXSP;
39 
40 	if (xc == IEEE754_CLASS_SNAN)
41 		return ieee754sp_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 >= SP_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 << (xe + 1);
58 		residue <<= 31 - SP_FBITS;
59 		round = (residue >> 31) != 0;
60 		sticky = (residue << 1) != 0;
61 		xm >>= SP_FBITS - xe;
62 	}
63 
64 	odd = (xm & 0x1) != 0x0;
65 
66 	switch (ieee754_csr.rm) {
67 	case FPU_CSR_RN:	/* toward nearest */
68 		if (round && (sticky || odd))
69 			xm++;
70 		break;
71 	case FPU_CSR_RZ:	/* toward zero */
72 		break;
73 	case FPU_CSR_RU:	/* toward +infinity */
74 		if ((round || sticky) && !xs)
75 			xm++;
76 		break;
77 	case FPU_CSR_RD:	/* toward -infinity */
78 		if ((round || sticky) && xs)
79 			xm++;
80 		break;
81 	}
82 
83 	if (round || sticky)
84 		ieee754_setcx(IEEE754_INEXACT);
85 
86 	ret = ieee754sp_flong(xm);
87 	SPSIGN(ret) = xs;
88 
89 	return ret;
90 }
91