xref: /openbmc/linux/arch/mips/math-emu/dp_rint.c (revision f6cc69f1)
1f6cc69f1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
23ec404d8SAleksandar Markovic /* IEEE754 floating point arithmetic
33ec404d8SAleksandar Markovic  * double precision: common utilities
43ec404d8SAleksandar Markovic  */
53ec404d8SAleksandar Markovic /*
63ec404d8SAleksandar Markovic  * MIPS floating point support
73ec404d8SAleksandar Markovic  * Copyright (C) 1994-2000 Algorithmics Ltd.
83ec404d8SAleksandar Markovic  * Copyright (C) 2017 Imagination Technologies, Ltd.
93ec404d8SAleksandar Markovic  * Author: Aleksandar Markovic <aleksandar.markovic@imgtec.com>
103ec404d8SAleksandar Markovic  */
113ec404d8SAleksandar Markovic 
123ec404d8SAleksandar Markovic #include "ieee754dp.h"
133ec404d8SAleksandar Markovic 
ieee754dp_rint(union ieee754dp x)143ec404d8SAleksandar Markovic union ieee754dp ieee754dp_rint(union ieee754dp x)
153ec404d8SAleksandar Markovic {
163ec404d8SAleksandar Markovic 	union ieee754dp ret;
173ec404d8SAleksandar Markovic 	u64 residue;
183ec404d8SAleksandar Markovic 	int sticky;
193ec404d8SAleksandar Markovic 	int round;
203ec404d8SAleksandar Markovic 	int odd;
213ec404d8SAleksandar Markovic 
223ec404d8SAleksandar Markovic 	COMPXDP;
233ec404d8SAleksandar Markovic 
243ec404d8SAleksandar Markovic 	ieee754_clearcx();
253ec404d8SAleksandar Markovic 
263ec404d8SAleksandar Markovic 	EXPLODEXDP;
273ec404d8SAleksandar Markovic 	FLUSHXDP;
283ec404d8SAleksandar Markovic 
293ec404d8SAleksandar Markovic 	if (xc == IEEE754_CLASS_SNAN)
303ec404d8SAleksandar Markovic 		return ieee754dp_nanxcpt(x);
313ec404d8SAleksandar Markovic 
323ec404d8SAleksandar Markovic 	if ((xc == IEEE754_CLASS_QNAN) ||
333ec404d8SAleksandar Markovic 	    (xc == IEEE754_CLASS_INF) ||
343ec404d8SAleksandar Markovic 	    (xc == IEEE754_CLASS_ZERO))
353ec404d8SAleksandar Markovic 		return x;
363ec404d8SAleksandar Markovic 
373ec404d8SAleksandar Markovic 	if (xe >= DP_FBITS)
383ec404d8SAleksandar Markovic 		return x;
393ec404d8SAleksandar Markovic 
403ec404d8SAleksandar Markovic 	if (xe < -1) {
413ec404d8SAleksandar Markovic 		residue = xm;
423ec404d8SAleksandar Markovic 		round = 0;
433ec404d8SAleksandar Markovic 		sticky = residue != 0;
443ec404d8SAleksandar Markovic 		xm = 0;
453ec404d8SAleksandar Markovic 	} else {
463ec404d8SAleksandar Markovic 		residue = xm << (64 - DP_FBITS + xe);
473ec404d8SAleksandar Markovic 		round = (residue >> 63) != 0;
483ec404d8SAleksandar Markovic 		sticky = (residue << 1) != 0;
493ec404d8SAleksandar Markovic 		xm >>= DP_FBITS - xe;
503ec404d8SAleksandar Markovic 	}
513ec404d8SAleksandar Markovic 
523ec404d8SAleksandar Markovic 	odd = (xm & 0x1) != 0x0;
533ec404d8SAleksandar Markovic 
543ec404d8SAleksandar Markovic 	switch (ieee754_csr.rm) {
553ec404d8SAleksandar Markovic 	case FPU_CSR_RN:	/* toward nearest */
563ec404d8SAleksandar Markovic 		if (round && (sticky || odd))
573ec404d8SAleksandar Markovic 			xm++;
583ec404d8SAleksandar Markovic 		break;
593ec404d8SAleksandar Markovic 	case FPU_CSR_RZ:	/* toward zero */
603ec404d8SAleksandar Markovic 		break;
613ec404d8SAleksandar Markovic 	case FPU_CSR_RU:	/* toward +infinity */
623ec404d8SAleksandar Markovic 		if ((round || sticky) && !xs)
633ec404d8SAleksandar Markovic 			xm++;
643ec404d8SAleksandar Markovic 		break;
653ec404d8SAleksandar Markovic 	case FPU_CSR_RD:	/* toward -infinity */
663ec404d8SAleksandar Markovic 		if ((round || sticky) && xs)
673ec404d8SAleksandar Markovic 			xm++;
683ec404d8SAleksandar Markovic 		break;
693ec404d8SAleksandar Markovic 	}
703ec404d8SAleksandar Markovic 
713ec404d8SAleksandar Markovic 	if (round || sticky)
723ec404d8SAleksandar Markovic 		ieee754_setcx(IEEE754_INEXACT);
733ec404d8SAleksandar Markovic 
743ec404d8SAleksandar Markovic 	ret = ieee754dp_flong(xm);
753ec404d8SAleksandar Markovic 	DPSIGN(ret) = xs;
763ec404d8SAleksandar Markovic 
773ec404d8SAleksandar Markovic 	return ret;
783ec404d8SAleksandar Markovic }
79