xref: /linux/arch/mips/math-emu/sp_fmin.c (revision 2a14b21acd056499cb150014e93d805a5ade2ce1)
14e9561b2SMarkos Chandras /*
24e9561b2SMarkos Chandras  * IEEE754 floating point arithmetic
34e9561b2SMarkos Chandras  * single precision: MIN{,A}.f
44e9561b2SMarkos Chandras  * MIN : Scalar Floating-Point Minimum
54e9561b2SMarkos Chandras  * MINA: Scalar Floating-Point argument with Minimum Absolute Value
64e9561b2SMarkos Chandras  *
74e9561b2SMarkos Chandras  * MIN.S : FPR[fd] = minNum(FPR[fs],FPR[ft])
84e9561b2SMarkos Chandras  * MINA.S: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
94e9561b2SMarkos Chandras  *
104e9561b2SMarkos Chandras  * MIPS floating point support
114e9561b2SMarkos Chandras  * Copyright (C) 2015 Imagination Technologies, Ltd.
124e9561b2SMarkos Chandras  * Author: Markos Chandras <markos.chandras@imgtec.com>
134e9561b2SMarkos Chandras  *
144e9561b2SMarkos Chandras  *  This program is free software; you can distribute it and/or modify it
154e9561b2SMarkos Chandras  *  under the terms of the GNU General Public License as published by the
164e9561b2SMarkos Chandras  *  Free Software Foundation; version 2 of the License.
174e9561b2SMarkos Chandras  */
184e9561b2SMarkos Chandras 
194e9561b2SMarkos Chandras #include "ieee754sp.h"
204e9561b2SMarkos Chandras 
214e9561b2SMarkos Chandras union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
224e9561b2SMarkos Chandras {
234e9561b2SMarkos Chandras 	COMPXSP;
244e9561b2SMarkos Chandras 	COMPYSP;
254e9561b2SMarkos Chandras 
264e9561b2SMarkos Chandras 	EXPLODEXSP;
274e9561b2SMarkos Chandras 	EXPLODEYSP;
284e9561b2SMarkos Chandras 
294e9561b2SMarkos Chandras 	FLUSHXSP;
304e9561b2SMarkos Chandras 	FLUSHYSP;
314e9561b2SMarkos Chandras 
324e9561b2SMarkos Chandras 	ieee754_clearcx();
334e9561b2SMarkos Chandras 
344e9561b2SMarkos Chandras 	switch (CLPAIR(xc, yc)) {
354e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
364e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
374e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
384e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
394e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
404e9561b2SMarkos Chandras 		return ieee754sp_nanxcpt(y);
414e9561b2SMarkos Chandras 
424e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
434e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
444e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
454e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
464e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
474e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
484e9561b2SMarkos Chandras 		return ieee754sp_nanxcpt(x);
494e9561b2SMarkos Chandras 
50e78bf0dcSAleksandar Markovic 	/*
51e78bf0dcSAleksandar Markovic 	 * Quiet NaN handling
52e78bf0dcSAleksandar Markovic 	 */
53e78bf0dcSAleksandar Markovic 
54e78bf0dcSAleksandar Markovic 	/*
55e78bf0dcSAleksandar Markovic 	 *    The case of both inputs quiet NaNs
56e78bf0dcSAleksandar Markovic 	 */
57e78bf0dcSAleksandar Markovic 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
58e78bf0dcSAleksandar Markovic 		return x;
59e78bf0dcSAleksandar Markovic 
60e78bf0dcSAleksandar Markovic 	/*
61e78bf0dcSAleksandar Markovic 	 *    The cases of exactly one input quiet NaN (numbers
62e78bf0dcSAleksandar Markovic 	 *    are here preferred as returned values to NaNs)
63e78bf0dcSAleksandar Markovic 	 */
644e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
654e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
664e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
674e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
684e9561b2SMarkos Chandras 		return x;
694e9561b2SMarkos Chandras 
704e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
714e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
724e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
734e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
744e9561b2SMarkos Chandras 		return y;
754e9561b2SMarkos Chandras 
764e9561b2SMarkos Chandras 	/*
774e9561b2SMarkos Chandras 	 * Infinity and zero handling
784e9561b2SMarkos Chandras 	 */
794e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
804e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
814e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
824e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
834e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
844e9561b2SMarkos Chandras 		return xs ? x : y;
854e9561b2SMarkos Chandras 
864e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
874e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
884e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
894e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
904e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
914e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
924e9561b2SMarkos Chandras 		return ys ? y : x;
934e9561b2SMarkos Chandras 
944e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
9515560a58SAleksandar Markovic 		return ieee754sp_zero(xs | ys);
964e9561b2SMarkos Chandras 
974e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
984e9561b2SMarkos Chandras 		SPDNORMX;
99*2a14b21aSAleksandar Markovic 		/* fall through */
1004e9561b2SMarkos Chandras 
1014e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
1024e9561b2SMarkos Chandras 		SPDNORMY;
1034e9561b2SMarkos Chandras 		break;
1044e9561b2SMarkos Chandras 
1054e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
1064e9561b2SMarkos Chandras 		SPDNORMX;
1074e9561b2SMarkos Chandras 	}
1084e9561b2SMarkos Chandras 
1094e9561b2SMarkos Chandras 	/* Finally get to do some computation */
1104e9561b2SMarkos Chandras 
1114e9561b2SMarkos Chandras 	assert(xm & SP_HIDDEN_BIT);
1124e9561b2SMarkos Chandras 	assert(ym & SP_HIDDEN_BIT);
1134e9561b2SMarkos Chandras 
1144e9561b2SMarkos Chandras 	/* Compare signs */
1154e9561b2SMarkos Chandras 	if (xs > ys)
1164e9561b2SMarkos Chandras 		return x;
1174e9561b2SMarkos Chandras 	else if (xs < ys)
1184e9561b2SMarkos Chandras 		return y;
1194e9561b2SMarkos Chandras 
120aabf5cf0SAleksandar Markovic 	/* Signs of inputs are the same, let's compare exponents */
121aabf5cf0SAleksandar Markovic 	if (xs == 0) {
122aabf5cf0SAleksandar Markovic 		/* Inputs are both positive */
1234e9561b2SMarkos Chandras 		if (xe > ye)
1244e9561b2SMarkos Chandras 			return y;
1254e9561b2SMarkos Chandras 		else if (xe < ye)
1264e9561b2SMarkos Chandras 			return x;
127aabf5cf0SAleksandar Markovic 	} else {
128aabf5cf0SAleksandar Markovic 		/* Inputs are both negative */
129aabf5cf0SAleksandar Markovic 		if (xe > ye)
130aabf5cf0SAleksandar Markovic 			return x;
131aabf5cf0SAleksandar Markovic 		else if (xe < ye)
132aabf5cf0SAleksandar Markovic 			return y;
133aabf5cf0SAleksandar Markovic 	}
1344e9561b2SMarkos Chandras 
135aabf5cf0SAleksandar Markovic 	/* Signs and exponents of inputs are equal, let's compare mantissas */
136aabf5cf0SAleksandar Markovic 	if (xs == 0) {
137aabf5cf0SAleksandar Markovic 		/* Inputs are both positive, with equal signs and exponents */
1384e9561b2SMarkos Chandras 		if (xm <= ym)
1394e9561b2SMarkos Chandras 			return x;
1404e9561b2SMarkos Chandras 		return y;
1414e9561b2SMarkos Chandras 	}
142aabf5cf0SAleksandar Markovic 	/* Inputs are both negative, with equal signs and exponents */
143aabf5cf0SAleksandar Markovic 	if (xm <= ym)
144aabf5cf0SAleksandar Markovic 		return y;
145aabf5cf0SAleksandar Markovic 	return x;
146aabf5cf0SAleksandar Markovic }
1474e9561b2SMarkos Chandras 
1484e9561b2SMarkos Chandras union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
1494e9561b2SMarkos Chandras {
1504e9561b2SMarkos Chandras 	COMPXSP;
1514e9561b2SMarkos Chandras 	COMPYSP;
1524e9561b2SMarkos Chandras 
1534e9561b2SMarkos Chandras 	EXPLODEXSP;
1544e9561b2SMarkos Chandras 	EXPLODEYSP;
1554e9561b2SMarkos Chandras 
1564e9561b2SMarkos Chandras 	FLUSHXSP;
1574e9561b2SMarkos Chandras 	FLUSHYSP;
1584e9561b2SMarkos Chandras 
1594e9561b2SMarkos Chandras 	ieee754_clearcx();
1604e9561b2SMarkos Chandras 
1614e9561b2SMarkos Chandras 	switch (CLPAIR(xc, yc)) {
1624e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
1634e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
1644e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
1654e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
1664e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
1674e9561b2SMarkos Chandras 		return ieee754sp_nanxcpt(y);
1684e9561b2SMarkos Chandras 
1694e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
1704e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
1714e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
1724e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
1734e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
1744e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
1754e9561b2SMarkos Chandras 		return ieee754sp_nanxcpt(x);
1764e9561b2SMarkos Chandras 
177e78bf0dcSAleksandar Markovic 	/*
178e78bf0dcSAleksandar Markovic 	 * Quiet NaN handling
179e78bf0dcSAleksandar Markovic 	 */
180e78bf0dcSAleksandar Markovic 
181e78bf0dcSAleksandar Markovic 	/*
182e78bf0dcSAleksandar Markovic 	 *    The case of both inputs quiet NaNs
183e78bf0dcSAleksandar Markovic 	 */
184e78bf0dcSAleksandar Markovic 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
185e78bf0dcSAleksandar Markovic 		return x;
186e78bf0dcSAleksandar Markovic 
187e78bf0dcSAleksandar Markovic 	/*
188e78bf0dcSAleksandar Markovic 	 *    The cases of exactly one input quiet NaN (numbers
189e78bf0dcSAleksandar Markovic 	 *    are here preferred as returned values to NaNs)
190e78bf0dcSAleksandar Markovic 	 */
1914e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
1924e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
1934e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
1944e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
1954e9561b2SMarkos Chandras 		return x;
1964e9561b2SMarkos Chandras 
1974e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
1984e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
1994e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
2004e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
2014e9561b2SMarkos Chandras 		return y;
2024e9561b2SMarkos Chandras 
2034e9561b2SMarkos Chandras 	/*
2044e9561b2SMarkos Chandras 	 * Infinity and zero handling
2054e9561b2SMarkos Chandras 	 */
2063444c4ebSAleksandar Markovic 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
2073444c4ebSAleksandar Markovic 		return ieee754sp_inf(xs | ys);
2083444c4ebSAleksandar Markovic 
2094e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
2104e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
2114e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
2124e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
2134e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
214304bfe47SAleksandar Markovic 		return y;
2154e9561b2SMarkos Chandras 
2164e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
2174e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
2184e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
2194e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
2204e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
221304bfe47SAleksandar Markovic 		return x;
2224e9561b2SMarkos Chandras 
2234e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
22415560a58SAleksandar Markovic 		return ieee754sp_zero(xs | ys);
2254e9561b2SMarkos Chandras 
2264e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
2274e9561b2SMarkos Chandras 		SPDNORMX;
228*2a14b21aSAleksandar Markovic 		/* fall through */
2294e9561b2SMarkos Chandras 
2304e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
2314e9561b2SMarkos Chandras 		SPDNORMY;
2324e9561b2SMarkos Chandras 		break;
2334e9561b2SMarkos Chandras 
2344e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
2354e9561b2SMarkos Chandras 		SPDNORMX;
2364e9561b2SMarkos Chandras 	}
2374e9561b2SMarkos Chandras 
2384e9561b2SMarkos Chandras 	/* Finally get to do some computation */
2394e9561b2SMarkos Chandras 
2404e9561b2SMarkos Chandras 	assert(xm & SP_HIDDEN_BIT);
2414e9561b2SMarkos Chandras 	assert(ym & SP_HIDDEN_BIT);
2424e9561b2SMarkos Chandras 
2434e9561b2SMarkos Chandras 	/* Compare exponent */
2444e9561b2SMarkos Chandras 	if (xe > ye)
2454e9561b2SMarkos Chandras 		return y;
2464e9561b2SMarkos Chandras 	else if (xe < ye)
2474e9561b2SMarkos Chandras 		return x;
2484e9561b2SMarkos Chandras 
2494e9561b2SMarkos Chandras 	/* Compare mantissa */
2501a41b3b4SAleksandar Markovic 	if (xm < ym)
2511a41b3b4SAleksandar Markovic 		return x;
2521a41b3b4SAleksandar Markovic 	else if (xm > ym)
2531a41b3b4SAleksandar Markovic 		return y;
2541a41b3b4SAleksandar Markovic 	else if (xs == 1)
2554e9561b2SMarkos Chandras 		return x;
2564e9561b2SMarkos Chandras 	return y;
2574e9561b2SMarkos Chandras }
258