xref: /linux/arch/mips/math-emu/sp_fmin.c (revision c9b0299034665d594e56ee343f28033d1b24de6d)
1ea65cc9bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
24e9561b2SMarkos Chandras /*
34e9561b2SMarkos Chandras  * IEEE754 floating point arithmetic
44e9561b2SMarkos Chandras  * single precision: MIN{,A}.f
54e9561b2SMarkos Chandras  * MIN : Scalar Floating-Point Minimum
64e9561b2SMarkos Chandras  * MINA: Scalar Floating-Point argument with Minimum Absolute Value
74e9561b2SMarkos Chandras  *
84e9561b2SMarkos Chandras  * MIN.S : FPR[fd] = minNum(FPR[fs],FPR[ft])
94e9561b2SMarkos Chandras  * MINA.S: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
104e9561b2SMarkos Chandras  *
114e9561b2SMarkos Chandras  * MIPS floating point support
124e9561b2SMarkos Chandras  * Copyright (C) 2015 Imagination Technologies, Ltd.
134e9561b2SMarkos Chandras  * Author: Markos Chandras <markos.chandras@imgtec.com>
144e9561b2SMarkos Chandras  */
154e9561b2SMarkos Chandras 
164e9561b2SMarkos Chandras #include "ieee754sp.h"
174e9561b2SMarkos Chandras 
184e9561b2SMarkos Chandras union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
194e9561b2SMarkos Chandras {
204e9561b2SMarkos Chandras 	COMPXSP;
214e9561b2SMarkos Chandras 	COMPYSP;
224e9561b2SMarkos Chandras 
234e9561b2SMarkos Chandras 	EXPLODEXSP;
244e9561b2SMarkos Chandras 	EXPLODEYSP;
254e9561b2SMarkos Chandras 
264e9561b2SMarkos Chandras 	FLUSHXSP;
274e9561b2SMarkos Chandras 	FLUSHYSP;
284e9561b2SMarkos Chandras 
294e9561b2SMarkos Chandras 	ieee754_clearcx();
304e9561b2SMarkos Chandras 
314e9561b2SMarkos Chandras 	switch (CLPAIR(xc, yc)) {
324e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
334e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
344e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
354e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
364e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
374e9561b2SMarkos Chandras 		return ieee754sp_nanxcpt(y);
384e9561b2SMarkos Chandras 
394e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
404e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
414e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
424e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
434e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
444e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
454e9561b2SMarkos Chandras 		return ieee754sp_nanxcpt(x);
464e9561b2SMarkos Chandras 
47e78bf0dcSAleksandar Markovic 	/*
48e78bf0dcSAleksandar Markovic 	 * Quiet NaN handling
49e78bf0dcSAleksandar Markovic 	 */
50e78bf0dcSAleksandar Markovic 
51e78bf0dcSAleksandar Markovic 	/*
52e78bf0dcSAleksandar Markovic 	 *    The case of both inputs quiet NaNs
53e78bf0dcSAleksandar Markovic 	 */
54e78bf0dcSAleksandar Markovic 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
55e78bf0dcSAleksandar Markovic 		return x;
56e78bf0dcSAleksandar Markovic 
57e78bf0dcSAleksandar Markovic 	/*
58e78bf0dcSAleksandar Markovic 	 *    The cases of exactly one input quiet NaN (numbers
59e78bf0dcSAleksandar Markovic 	 *    are here preferred as returned values to NaNs)
60e78bf0dcSAleksandar Markovic 	 */
614e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
624e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
634e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
644e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
654e9561b2SMarkos Chandras 		return x;
664e9561b2SMarkos Chandras 
674e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
684e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
694e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
704e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
714e9561b2SMarkos Chandras 		return y;
724e9561b2SMarkos Chandras 
734e9561b2SMarkos Chandras 	/*
744e9561b2SMarkos Chandras 	 * Infinity and zero handling
754e9561b2SMarkos Chandras 	 */
764e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
774e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
784e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
794e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
804e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
814e9561b2SMarkos Chandras 		return xs ? x : y;
824e9561b2SMarkos Chandras 
834e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
844e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
854e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
864e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
874e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
884e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
894e9561b2SMarkos Chandras 		return ys ? y : x;
904e9561b2SMarkos Chandras 
914e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
9215560a58SAleksandar Markovic 		return ieee754sp_zero(xs | ys);
934e9561b2SMarkos Chandras 
944e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
954e9561b2SMarkos Chandras 		SPDNORMX;
96*c9b02990SLiangliang Huang 		fallthrough;
974e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
984e9561b2SMarkos Chandras 		SPDNORMY;
994e9561b2SMarkos Chandras 		break;
1004e9561b2SMarkos Chandras 
1014e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
1024e9561b2SMarkos Chandras 		SPDNORMX;
1034e9561b2SMarkos Chandras 	}
1044e9561b2SMarkos Chandras 
1054e9561b2SMarkos Chandras 	/* Finally get to do some computation */
1064e9561b2SMarkos Chandras 
1074e9561b2SMarkos Chandras 	assert(xm & SP_HIDDEN_BIT);
1084e9561b2SMarkos Chandras 	assert(ym & SP_HIDDEN_BIT);
1094e9561b2SMarkos Chandras 
1104e9561b2SMarkos Chandras 	/* Compare signs */
1114e9561b2SMarkos Chandras 	if (xs > ys)
1124e9561b2SMarkos Chandras 		return x;
1134e9561b2SMarkos Chandras 	else if (xs < ys)
1144e9561b2SMarkos Chandras 		return y;
1154e9561b2SMarkos Chandras 
116aabf5cf0SAleksandar Markovic 	/* Signs of inputs are the same, let's compare exponents */
117aabf5cf0SAleksandar Markovic 	if (xs == 0) {
118aabf5cf0SAleksandar Markovic 		/* Inputs are both positive */
1194e9561b2SMarkos Chandras 		if (xe > ye)
1204e9561b2SMarkos Chandras 			return y;
1214e9561b2SMarkos Chandras 		else if (xe < ye)
1224e9561b2SMarkos Chandras 			return x;
123aabf5cf0SAleksandar Markovic 	} else {
124aabf5cf0SAleksandar Markovic 		/* Inputs are both negative */
125aabf5cf0SAleksandar Markovic 		if (xe > ye)
126aabf5cf0SAleksandar Markovic 			return x;
127aabf5cf0SAleksandar Markovic 		else if (xe < ye)
128aabf5cf0SAleksandar Markovic 			return y;
129aabf5cf0SAleksandar Markovic 	}
1304e9561b2SMarkos Chandras 
131aabf5cf0SAleksandar Markovic 	/* Signs and exponents of inputs are equal, let's compare mantissas */
132aabf5cf0SAleksandar Markovic 	if (xs == 0) {
133aabf5cf0SAleksandar Markovic 		/* Inputs are both positive, with equal signs and exponents */
1344e9561b2SMarkos Chandras 		if (xm <= ym)
1354e9561b2SMarkos Chandras 			return x;
1364e9561b2SMarkos Chandras 		return y;
1374e9561b2SMarkos Chandras 	}
138aabf5cf0SAleksandar Markovic 	/* Inputs are both negative, with equal signs and exponents */
139aabf5cf0SAleksandar Markovic 	if (xm <= ym)
140aabf5cf0SAleksandar Markovic 		return y;
141aabf5cf0SAleksandar Markovic 	return x;
142aabf5cf0SAleksandar Markovic }
1434e9561b2SMarkos Chandras 
1444e9561b2SMarkos Chandras union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
1454e9561b2SMarkos Chandras {
1464e9561b2SMarkos Chandras 	COMPXSP;
1474e9561b2SMarkos Chandras 	COMPYSP;
1484e9561b2SMarkos Chandras 
1494e9561b2SMarkos Chandras 	EXPLODEXSP;
1504e9561b2SMarkos Chandras 	EXPLODEYSP;
1514e9561b2SMarkos Chandras 
1524e9561b2SMarkos Chandras 	FLUSHXSP;
1534e9561b2SMarkos Chandras 	FLUSHYSP;
1544e9561b2SMarkos Chandras 
1554e9561b2SMarkos Chandras 	ieee754_clearcx();
1564e9561b2SMarkos Chandras 
1574e9561b2SMarkos Chandras 	switch (CLPAIR(xc, yc)) {
1584e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
1594e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
1604e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
1614e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
1624e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
1634e9561b2SMarkos Chandras 		return ieee754sp_nanxcpt(y);
1644e9561b2SMarkos Chandras 
1654e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
1664e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
1674e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
1684e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
1694e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
1704e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
1714e9561b2SMarkos Chandras 		return ieee754sp_nanxcpt(x);
1724e9561b2SMarkos Chandras 
173e78bf0dcSAleksandar Markovic 	/*
174e78bf0dcSAleksandar Markovic 	 * Quiet NaN handling
175e78bf0dcSAleksandar Markovic 	 */
176e78bf0dcSAleksandar Markovic 
177e78bf0dcSAleksandar Markovic 	/*
178e78bf0dcSAleksandar Markovic 	 *    The case of both inputs quiet NaNs
179e78bf0dcSAleksandar Markovic 	 */
180e78bf0dcSAleksandar Markovic 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
181e78bf0dcSAleksandar Markovic 		return x;
182e78bf0dcSAleksandar Markovic 
183e78bf0dcSAleksandar Markovic 	/*
184e78bf0dcSAleksandar Markovic 	 *    The cases of exactly one input quiet NaN (numbers
185e78bf0dcSAleksandar Markovic 	 *    are here preferred as returned values to NaNs)
186e78bf0dcSAleksandar Markovic 	 */
1874e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
1884e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
1894e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
1904e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
1914e9561b2SMarkos Chandras 		return x;
1924e9561b2SMarkos Chandras 
1934e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
1944e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
1954e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
1964e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
1974e9561b2SMarkos Chandras 		return y;
1984e9561b2SMarkos Chandras 
1994e9561b2SMarkos Chandras 	/*
2004e9561b2SMarkos Chandras 	 * Infinity and zero handling
2014e9561b2SMarkos Chandras 	 */
2023444c4ebSAleksandar Markovic 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
2033444c4ebSAleksandar Markovic 		return ieee754sp_inf(xs | ys);
2043444c4ebSAleksandar Markovic 
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):
210304bfe47SAleksandar Markovic 		return y;
2114e9561b2SMarkos Chandras 
2124e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
2134e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
2144e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
2154e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
2164e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
217304bfe47SAleksandar Markovic 		return x;
2184e9561b2SMarkos Chandras 
2194e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
22015560a58SAleksandar Markovic 		return ieee754sp_zero(xs | ys);
2214e9561b2SMarkos Chandras 
2224e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
2234e9561b2SMarkos Chandras 		SPDNORMX;
224*c9b02990SLiangliang Huang 		fallthrough;
2254e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
2264e9561b2SMarkos Chandras 		SPDNORMY;
2274e9561b2SMarkos Chandras 		break;
2284e9561b2SMarkos Chandras 
2294e9561b2SMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
2304e9561b2SMarkos Chandras 		SPDNORMX;
2314e9561b2SMarkos Chandras 	}
2324e9561b2SMarkos Chandras 
2334e9561b2SMarkos Chandras 	/* Finally get to do some computation */
2344e9561b2SMarkos Chandras 
2354e9561b2SMarkos Chandras 	assert(xm & SP_HIDDEN_BIT);
2364e9561b2SMarkos Chandras 	assert(ym & SP_HIDDEN_BIT);
2374e9561b2SMarkos Chandras 
2384e9561b2SMarkos Chandras 	/* Compare exponent */
2394e9561b2SMarkos Chandras 	if (xe > ye)
2404e9561b2SMarkos Chandras 		return y;
2414e9561b2SMarkos Chandras 	else if (xe < ye)
2424e9561b2SMarkos Chandras 		return x;
2434e9561b2SMarkos Chandras 
2444e9561b2SMarkos Chandras 	/* Compare mantissa */
2451a41b3b4SAleksandar Markovic 	if (xm < ym)
2461a41b3b4SAleksandar Markovic 		return x;
2471a41b3b4SAleksandar Markovic 	else if (xm > ym)
2481a41b3b4SAleksandar Markovic 		return y;
2491a41b3b4SAleksandar Markovic 	else if (xs == 1)
2504e9561b2SMarkos Chandras 		return x;
2514e9561b2SMarkos Chandras 	return y;
2524e9561b2SMarkos Chandras }
253