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