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