xref: /openbmc/linux/arch/mips/math-emu/dp_rint.c (revision 3ec404d8)
13ec404d8SAleksandar Markovic /* IEEE754 floating point arithmetic
23ec404d8SAleksandar Markovic  * double precision: common utilities
33ec404d8SAleksandar Markovic  */
43ec404d8SAleksandar Markovic /*
53ec404d8SAleksandar Markovic  * MIPS floating point support
63ec404d8SAleksandar Markovic  * Copyright (C) 1994-2000 Algorithmics Ltd.
73ec404d8SAleksandar Markovic  * Copyright (C) 2017 Imagination Technologies, Ltd.
83ec404d8SAleksandar Markovic  * Author: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
93ec404d8SAleksandar Markovic  *
103ec404d8SAleksandar Markovic  *  This program is free software; you can distribute it and/or modify it
113ec404d8SAleksandar Markovic  *  under the terms of the GNU General Public License (Version 2) as
123ec404d8SAleksandar Markovic  *  published by the Free Software Foundation.
133ec404d8SAleksandar Markovic  *
143ec404d8SAleksandar Markovic  *  This program is distributed in the hope it will be useful, but WITHOUT
153ec404d8SAleksandar Markovic  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
163ec404d8SAleksandar Markovic  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
173ec404d8SAleksandar Markovic  *  for more details.
183ec404d8SAleksandar Markovic  *
193ec404d8SAleksandar Markovic  *  You should have received a copy of the GNU General Public License along
203ec404d8SAleksandar Markovic  *  with this program.
213ec404d8SAleksandar Markovic  */
223ec404d8SAleksandar Markovic 
233ec404d8SAleksandar Markovic #include "ieee754dp.h"
243ec404d8SAleksandar Markovic 
253ec404d8SAleksandar Markovic union ieee754dp ieee754dp_rint(union ieee754dp x)
263ec404d8SAleksandar Markovic {
273ec404d8SAleksandar Markovic 	union ieee754dp ret;
283ec404d8SAleksandar Markovic 	u64 residue;
293ec404d8SAleksandar Markovic 	int sticky;
303ec404d8SAleksandar Markovic 	int round;
313ec404d8SAleksandar Markovic 	int odd;
323ec404d8SAleksandar Markovic 
333ec404d8SAleksandar Markovic 	COMPXDP;
343ec404d8SAleksandar Markovic 
353ec404d8SAleksandar Markovic 	ieee754_clearcx();
363ec404d8SAleksandar Markovic 
373ec404d8SAleksandar Markovic 	EXPLODEXDP;
383ec404d8SAleksandar Markovic 	FLUSHXDP;
393ec404d8SAleksandar Markovic 
403ec404d8SAleksandar Markovic 	if (xc == IEEE754_CLASS_SNAN)
413ec404d8SAleksandar Markovic 		return ieee754dp_nanxcpt(x);
423ec404d8SAleksandar Markovic 
433ec404d8SAleksandar Markovic 	if ((xc == IEEE754_CLASS_QNAN) ||
443ec404d8SAleksandar Markovic 	    (xc == IEEE754_CLASS_INF) ||
453ec404d8SAleksandar Markovic 	    (xc == IEEE754_CLASS_ZERO))
463ec404d8SAleksandar Markovic 		return x;
473ec404d8SAleksandar Markovic 
483ec404d8SAleksandar Markovic 	if (xe >= DP_FBITS)
493ec404d8SAleksandar Markovic 		return x;
503ec404d8SAleksandar Markovic 
513ec404d8SAleksandar Markovic 	if (xe < -1) {
523ec404d8SAleksandar Markovic 		residue = xm;
533ec404d8SAleksandar Markovic 		round = 0;
543ec404d8SAleksandar Markovic 		sticky = residue != 0;
553ec404d8SAleksandar Markovic 		xm = 0;
563ec404d8SAleksandar Markovic 	} else {
573ec404d8SAleksandar Markovic 		residue = xm << (64 - DP_FBITS + xe);
583ec404d8SAleksandar Markovic 		round = (residue >> 63) != 0;
593ec404d8SAleksandar Markovic 		sticky = (residue << 1) != 0;
603ec404d8SAleksandar Markovic 		xm >>= DP_FBITS - xe;
613ec404d8SAleksandar Markovic 	}
623ec404d8SAleksandar Markovic 
633ec404d8SAleksandar Markovic 	odd = (xm & 0x1) != 0x0;
643ec404d8SAleksandar Markovic 
653ec404d8SAleksandar Markovic 	switch (ieee754_csr.rm) {
663ec404d8SAleksandar Markovic 	case FPU_CSR_RN:	/* toward nearest */
673ec404d8SAleksandar Markovic 		if (round && (sticky || odd))
683ec404d8SAleksandar Markovic 			xm++;
693ec404d8SAleksandar Markovic 		break;
703ec404d8SAleksandar Markovic 	case FPU_CSR_RZ:	/* toward zero */
713ec404d8SAleksandar Markovic 		break;
723ec404d8SAleksandar Markovic 	case FPU_CSR_RU:	/* toward +infinity */
733ec404d8SAleksandar Markovic 		if ((round || sticky) && !xs)
743ec404d8SAleksandar Markovic 			xm++;
753ec404d8SAleksandar Markovic 		break;
763ec404d8SAleksandar Markovic 	case FPU_CSR_RD:	/* toward -infinity */
773ec404d8SAleksandar Markovic 		if ((round || sticky) && xs)
783ec404d8SAleksandar Markovic 			xm++;
793ec404d8SAleksandar Markovic 		break;
803ec404d8SAleksandar Markovic 	}
813ec404d8SAleksandar Markovic 
823ec404d8SAleksandar Markovic 	if (round || sticky)
833ec404d8SAleksandar Markovic 		ieee754_setcx(IEEE754_INEXACT);
843ec404d8SAleksandar Markovic 
853ec404d8SAleksandar Markovic 	ret = ieee754dp_flong(xm);
863ec404d8SAleksandar Markovic 	DPSIGN(ret) = xs;
873ec404d8SAleksandar Markovic 
883ec404d8SAleksandar Markovic 	return ret;
893ec404d8SAleksandar Markovic }
90