xref: /linux/arch/mips/math-emu/sp_fmin.c (revision aabf5cf02e22ebc4e541adf835910f388b6c3e65)
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;
994e9561b2SMarkos Chandras 
1004e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
1014e9561b2SMarkos Chandras 		SPDNORMY;
1024e9561b2SMarkos Chandras 		break;
1034e9561b2SMarkos Chandras 
1044e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
1054e9561b2SMarkos Chandras 		SPDNORMX;
1064e9561b2SMarkos Chandras 	}
1074e9561b2SMarkos Chandras 
1084e9561b2SMarkos Chandras 	/* Finally get to do some computation */
1094e9561b2SMarkos Chandras 
1104e9561b2SMarkos Chandras 	assert(xm & SP_HIDDEN_BIT);
1114e9561b2SMarkos Chandras 	assert(ym & SP_HIDDEN_BIT);
1124e9561b2SMarkos Chandras 
1134e9561b2SMarkos Chandras 	/* Compare signs */
1144e9561b2SMarkos Chandras 	if (xs > ys)
1154e9561b2SMarkos Chandras 		return x;
1164e9561b2SMarkos Chandras 	else if (xs < ys)
1174e9561b2SMarkos Chandras 		return y;
1184e9561b2SMarkos Chandras 
119*aabf5cf0SAleksandar Markovic 	/* Signs of inputs are the same, let's compare exponents */
120*aabf5cf0SAleksandar Markovic 	if (xs == 0) {
121*aabf5cf0SAleksandar Markovic 		/* Inputs are both positive */
1224e9561b2SMarkos Chandras 		if (xe > ye)
1234e9561b2SMarkos Chandras 			return y;
1244e9561b2SMarkos Chandras 		else if (xe < ye)
1254e9561b2SMarkos Chandras 			return x;
126*aabf5cf0SAleksandar Markovic 	} else {
127*aabf5cf0SAleksandar Markovic 		/* Inputs are both negative */
128*aabf5cf0SAleksandar Markovic 		if (xe > ye)
129*aabf5cf0SAleksandar Markovic 			return x;
130*aabf5cf0SAleksandar Markovic 		else if (xe < ye)
131*aabf5cf0SAleksandar Markovic 			return y;
132*aabf5cf0SAleksandar Markovic 	}
1334e9561b2SMarkos Chandras 
134*aabf5cf0SAleksandar Markovic 	/* Signs and exponents of inputs are equal, let's compare mantissas */
135*aabf5cf0SAleksandar Markovic 	if (xs == 0) {
136*aabf5cf0SAleksandar Markovic 		/* Inputs are both positive, with equal signs and exponents */
1374e9561b2SMarkos Chandras 		if (xm <= ym)
1384e9561b2SMarkos Chandras 			return x;
1394e9561b2SMarkos Chandras 		return y;
1404e9561b2SMarkos Chandras 	}
141*aabf5cf0SAleksandar Markovic 	/* Inputs are both negative, with equal signs and exponents */
142*aabf5cf0SAleksandar Markovic 	if (xm <= ym)
143*aabf5cf0SAleksandar Markovic 		return y;
144*aabf5cf0SAleksandar Markovic 	return x;
145*aabf5cf0SAleksandar Markovic }
1464e9561b2SMarkos Chandras 
1474e9561b2SMarkos Chandras union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
1484e9561b2SMarkos Chandras {
1494e9561b2SMarkos Chandras 	COMPXSP;
1504e9561b2SMarkos Chandras 	COMPYSP;
1514e9561b2SMarkos Chandras 
1524e9561b2SMarkos Chandras 	EXPLODEXSP;
1534e9561b2SMarkos Chandras 	EXPLODEYSP;
1544e9561b2SMarkos Chandras 
1554e9561b2SMarkos Chandras 	FLUSHXSP;
1564e9561b2SMarkos Chandras 	FLUSHYSP;
1574e9561b2SMarkos Chandras 
1584e9561b2SMarkos Chandras 	ieee754_clearcx();
1594e9561b2SMarkos Chandras 
1604e9561b2SMarkos Chandras 	switch (CLPAIR(xc, yc)) {
1614e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
1624e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
1634e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
1644e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
1654e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
1664e9561b2SMarkos Chandras 		return ieee754sp_nanxcpt(y);
1674e9561b2SMarkos Chandras 
1684e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
1694e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
1704e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
1714e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
1724e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
1734e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
1744e9561b2SMarkos Chandras 		return ieee754sp_nanxcpt(x);
1754e9561b2SMarkos Chandras 
176e78bf0dcSAleksandar Markovic 	/*
177e78bf0dcSAleksandar Markovic 	 * Quiet NaN handling
178e78bf0dcSAleksandar Markovic 	 */
179e78bf0dcSAleksandar Markovic 
180e78bf0dcSAleksandar Markovic 	/*
181e78bf0dcSAleksandar Markovic 	 *    The case of both inputs quiet NaNs
182e78bf0dcSAleksandar Markovic 	 */
183e78bf0dcSAleksandar Markovic 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
184e78bf0dcSAleksandar Markovic 		return x;
185e78bf0dcSAleksandar Markovic 
186e78bf0dcSAleksandar Markovic 	/*
187e78bf0dcSAleksandar Markovic 	 *    The cases of exactly one input quiet NaN (numbers
188e78bf0dcSAleksandar Markovic 	 *    are here preferred as returned values to NaNs)
189e78bf0dcSAleksandar Markovic 	 */
1904e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
1914e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
1924e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
1934e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
1944e9561b2SMarkos Chandras 		return x;
1954e9561b2SMarkos Chandras 
1964e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
1974e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
1984e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
1994e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
2004e9561b2SMarkos Chandras 		return y;
2014e9561b2SMarkos Chandras 
2024e9561b2SMarkos Chandras 	/*
2034e9561b2SMarkos Chandras 	 * Infinity and zero handling
2044e9561b2SMarkos Chandras 	 */
2054e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
2064e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
2074e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
2084e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
2094e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
2104e9561b2SMarkos Chandras 		return x;
2114e9561b2SMarkos Chandras 
2124e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
2134e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
2144e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
2154e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
2164e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
2174e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
2184e9561b2SMarkos Chandras 		return y;
2194e9561b2SMarkos Chandras 
2204e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
22115560a58SAleksandar Markovic 		return ieee754sp_zero(xs | ys);
2224e9561b2SMarkos Chandras 
2234e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
2244e9561b2SMarkos Chandras 		SPDNORMX;
2254e9561b2SMarkos Chandras 
2264e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
2274e9561b2SMarkos Chandras 		SPDNORMY;
2284e9561b2SMarkos Chandras 		break;
2294e9561b2SMarkos Chandras 
2304e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
2314e9561b2SMarkos Chandras 		SPDNORMX;
2324e9561b2SMarkos Chandras 	}
2334e9561b2SMarkos Chandras 
2344e9561b2SMarkos Chandras 	/* Finally get to do some computation */
2354e9561b2SMarkos Chandras 
2364e9561b2SMarkos Chandras 	assert(xm & SP_HIDDEN_BIT);
2374e9561b2SMarkos Chandras 	assert(ym & SP_HIDDEN_BIT);
2384e9561b2SMarkos Chandras 
2394e9561b2SMarkos Chandras 	/* Compare exponent */
2404e9561b2SMarkos Chandras 	if (xe > ye)
2414e9561b2SMarkos Chandras 		return y;
2424e9561b2SMarkos Chandras 	else if (xe < ye)
2434e9561b2SMarkos Chandras 		return x;
2444e9561b2SMarkos Chandras 
2454e9561b2SMarkos Chandras 	/* Compare mantissa */
2464e9561b2SMarkos Chandras 	if (xm <= ym)
2474e9561b2SMarkos Chandras 		return x;
2484e9561b2SMarkos Chandras 	return y;
2494e9561b2SMarkos Chandras }
250