xref: /openbmc/linux/arch/mips/math-emu/sp_fmax.c (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
1ea65cc9bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a79f5f9bSMarkos Chandras /*
3a79f5f9bSMarkos Chandras  * IEEE754 floating point arithmetic
4a79f5f9bSMarkos Chandras  * single precision: MAX{,A}.f
5a79f5f9bSMarkos Chandras  * MAX : Scalar Floating-Point Maximum
6a79f5f9bSMarkos Chandras  * MAXA: Scalar Floating-Point argument with Maximum Absolute Value
7a79f5f9bSMarkos Chandras  *
8a79f5f9bSMarkos Chandras  * MAX.S : FPR[fd] = maxNum(FPR[fs],FPR[ft])
9a79f5f9bSMarkos Chandras  * MAXA.S: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
10a79f5f9bSMarkos Chandras  *
11a79f5f9bSMarkos Chandras  * MIPS floating point support
12a79f5f9bSMarkos Chandras  * Copyright (C) 2015 Imagination Technologies, Ltd.
13a79f5f9bSMarkos Chandras  * Author: Markos Chandras <markos.chandras@imgtec.com>
14a79f5f9bSMarkos Chandras  */
15a79f5f9bSMarkos Chandras 
16a79f5f9bSMarkos Chandras #include "ieee754sp.h"
17a79f5f9bSMarkos Chandras 
ieee754sp_fmax(union ieee754sp x,union ieee754sp y)18a79f5f9bSMarkos Chandras union ieee754sp ieee754sp_fmax(union ieee754sp x, union ieee754sp y)
19a79f5f9bSMarkos Chandras {
20a79f5f9bSMarkos Chandras 	COMPXSP;
21a79f5f9bSMarkos Chandras 	COMPYSP;
22a79f5f9bSMarkos Chandras 
23a79f5f9bSMarkos Chandras 	EXPLODEXSP;
24a79f5f9bSMarkos Chandras 	EXPLODEYSP;
25a79f5f9bSMarkos Chandras 
26a79f5f9bSMarkos Chandras 	FLUSHXSP;
27a79f5f9bSMarkos Chandras 	FLUSHYSP;
28a79f5f9bSMarkos Chandras 
29a79f5f9bSMarkos Chandras 	ieee754_clearcx();
30a79f5f9bSMarkos Chandras 
31a79f5f9bSMarkos Chandras 	switch (CLPAIR(xc, yc)) {
32a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
33a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
34a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
35a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
36a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
37a79f5f9bSMarkos Chandras 		return ieee754sp_nanxcpt(y);
38a79f5f9bSMarkos Chandras 
39a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
40a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
41a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
42a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
43a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
44a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
45a79f5f9bSMarkos Chandras 		return ieee754sp_nanxcpt(x);
46a79f5f9bSMarkos 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 	 */
61a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
62a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
63a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
64a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
65a79f5f9bSMarkos Chandras 		return x;
66a79f5f9bSMarkos Chandras 
67a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
68a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
69a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
70a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
71a79f5f9bSMarkos Chandras 		return y;
72a79f5f9bSMarkos Chandras 
73a79f5f9bSMarkos Chandras 	/*
74a79f5f9bSMarkos Chandras 	 * Infinity and zero handling
75a79f5f9bSMarkos Chandras 	 */
76a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
77a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
78a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
79a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
80a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
81a79f5f9bSMarkos Chandras 		return xs ? y : x;
82a79f5f9bSMarkos Chandras 
83a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
84a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
85a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
86a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
87a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
88a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
89a79f5f9bSMarkos Chandras 		return ys ? x : y;
90a79f5f9bSMarkos Chandras 
91a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
9215560a58SAleksandar Markovic 		return ieee754sp_zero(xs & ys);
93a79f5f9bSMarkos Chandras 
94a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
95a79f5f9bSMarkos Chandras 		SPDNORMX;
96*c9b02990SLiangliang Huang 		fallthrough;
97a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
98a79f5f9bSMarkos Chandras 		SPDNORMY;
99a79f5f9bSMarkos Chandras 		break;
100a79f5f9bSMarkos Chandras 
101a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
102a79f5f9bSMarkos Chandras 		SPDNORMX;
103a79f5f9bSMarkos Chandras 	}
104a79f5f9bSMarkos Chandras 
105a79f5f9bSMarkos Chandras 	/* Finally get to do some computation */
106a79f5f9bSMarkos Chandras 
107a79f5f9bSMarkos Chandras 	assert(xm & SP_HIDDEN_BIT);
108a79f5f9bSMarkos Chandras 	assert(ym & SP_HIDDEN_BIT);
109a79f5f9bSMarkos Chandras 
110a79f5f9bSMarkos Chandras 	/* Compare signs */
111a79f5f9bSMarkos Chandras 	if (xs > ys)
112a79f5f9bSMarkos Chandras 		return y;
113a79f5f9bSMarkos Chandras 	else if (xs < ys)
114a79f5f9bSMarkos Chandras 		return x;
115a79f5f9bSMarkos Chandras 
116aabf5cf0SAleksandar Markovic 	/* Signs of inputs are equal, let's compare exponents */
117aabf5cf0SAleksandar Markovic 	if (xs == 0) {
118aabf5cf0SAleksandar Markovic 		/* Inputs are both positive */
119a79f5f9bSMarkos Chandras 		if (xe > ye)
120a79f5f9bSMarkos Chandras 			return x;
121a79f5f9bSMarkos Chandras 		else if (xe < ye)
122a79f5f9bSMarkos Chandras 			return y;
123aabf5cf0SAleksandar Markovic 	} else {
124aabf5cf0SAleksandar Markovic 		/* Inputs are both negative */
125aabf5cf0SAleksandar Markovic 		if (xe > ye)
126aabf5cf0SAleksandar Markovic 			return y;
127aabf5cf0SAleksandar Markovic 		else if (xe < ye)
128aabf5cf0SAleksandar Markovic 			return x;
129aabf5cf0SAleksandar Markovic 	}
130a79f5f9bSMarkos 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 */
134a79f5f9bSMarkos Chandras 		if (xm <= ym)
135a79f5f9bSMarkos Chandras 			return y;
136a79f5f9bSMarkos Chandras 		return x;
137a79f5f9bSMarkos Chandras 	}
138aabf5cf0SAleksandar Markovic 	/* Inputs are both negative, with equal signs and exponents */
139aabf5cf0SAleksandar Markovic 	if (xm <= ym)
140aabf5cf0SAleksandar Markovic 		return x;
141aabf5cf0SAleksandar Markovic 	return y;
142aabf5cf0SAleksandar Markovic }
143a79f5f9bSMarkos Chandras 
ieee754sp_fmaxa(union ieee754sp x,union ieee754sp y)144a79f5f9bSMarkos Chandras union ieee754sp ieee754sp_fmaxa(union ieee754sp x, union ieee754sp y)
145a79f5f9bSMarkos Chandras {
146a79f5f9bSMarkos Chandras 	COMPXSP;
147a79f5f9bSMarkos Chandras 	COMPYSP;
148a79f5f9bSMarkos Chandras 
149a79f5f9bSMarkos Chandras 	EXPLODEXSP;
150a79f5f9bSMarkos Chandras 	EXPLODEYSP;
151a79f5f9bSMarkos Chandras 
152a79f5f9bSMarkos Chandras 	FLUSHXSP;
153a79f5f9bSMarkos Chandras 	FLUSHYSP;
154a79f5f9bSMarkos Chandras 
155a79f5f9bSMarkos Chandras 	ieee754_clearcx();
156a79f5f9bSMarkos Chandras 
157a79f5f9bSMarkos Chandras 	switch (CLPAIR(xc, yc)) {
158a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
159a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
160a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
161a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
162a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
163a79f5f9bSMarkos Chandras 		return ieee754sp_nanxcpt(y);
164a79f5f9bSMarkos Chandras 
165a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
166a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
167a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
168a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
169a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
170a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
171a79f5f9bSMarkos Chandras 		return ieee754sp_nanxcpt(x);
172a79f5f9bSMarkos 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 	 */
187a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
188a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
189a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
190a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
191a79f5f9bSMarkos Chandras 		return x;
192a79f5f9bSMarkos Chandras 
193a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
194a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
195a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
196a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
197a79f5f9bSMarkos Chandras 		return y;
198a79f5f9bSMarkos Chandras 
199a79f5f9bSMarkos Chandras 	/*
200a79f5f9bSMarkos Chandras 	 * Infinity and zero handling
201a79f5f9bSMarkos Chandras 	 */
2023444c4ebSAleksandar Markovic 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
2033444c4ebSAleksandar Markovic 		return ieee754sp_inf(xs & ys);
2043444c4ebSAleksandar Markovic 
205a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
206a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
207a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
208a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
209a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
210a79f5f9bSMarkos Chandras 		return x;
211a79f5f9bSMarkos Chandras 
212a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
213a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
214a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
215a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
216a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
217a79f5f9bSMarkos Chandras 		return y;
218a79f5f9bSMarkos Chandras 
219a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
22015560a58SAleksandar Markovic 		return ieee754sp_zero(xs & ys);
221a79f5f9bSMarkos Chandras 
222a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
223a79f5f9bSMarkos Chandras 		SPDNORMX;
224*c9b02990SLiangliang Huang 		fallthrough;
225a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
226a79f5f9bSMarkos Chandras 		SPDNORMY;
227a79f5f9bSMarkos Chandras 		break;
228a79f5f9bSMarkos Chandras 
229a79f5f9bSMarkos Chandras 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
230a79f5f9bSMarkos Chandras 		SPDNORMX;
231a79f5f9bSMarkos Chandras 	}
232a79f5f9bSMarkos Chandras 
233a79f5f9bSMarkos Chandras 	/* Finally get to do some computation */
234a79f5f9bSMarkos Chandras 
235a79f5f9bSMarkos Chandras 	assert(xm & SP_HIDDEN_BIT);
236a79f5f9bSMarkos Chandras 	assert(ym & SP_HIDDEN_BIT);
237a79f5f9bSMarkos Chandras 
238a79f5f9bSMarkos Chandras 	/* Compare exponent */
239a79f5f9bSMarkos Chandras 	if (xe > ye)
240a79f5f9bSMarkos Chandras 		return x;
241a79f5f9bSMarkos Chandras 	else if (xe < ye)
242a79f5f9bSMarkos Chandras 		return y;
243a79f5f9bSMarkos Chandras 
244a79f5f9bSMarkos Chandras 	/* Compare mantissa */
2451a41b3b4SAleksandar Markovic 	if (xm < ym)
246a79f5f9bSMarkos Chandras 		return y;
2471a41b3b4SAleksandar Markovic 	else if (xm > ym)
248a79f5f9bSMarkos Chandras 		return x;
2491a41b3b4SAleksandar Markovic 	else if (xs == 0)
2501a41b3b4SAleksandar Markovic 		return x;
2511a41b3b4SAleksandar Markovic 	return y;
252a79f5f9bSMarkos Chandras }
253