xref: /openbmc/linux/arch/mips/math-emu/sp_fmin.c (revision d9fd5a71)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * IEEE754 floating point arithmetic
4  * single precision: MIN{,A}.f
5  * MIN : Scalar Floating-Point Minimum
6  * MINA: Scalar Floating-Point argument with Minimum Absolute Value
7  *
8  * MIN.S : FPR[fd] = minNum(FPR[fs],FPR[ft])
9  * MINA.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_fmin(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 ? x : y;
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 ? y : x;
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 		fallthrough;
97 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
98 		SPDNORMY;
99 		break;
100 
101 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
102 		SPDNORMX;
103 	}
104 
105 	/* Finally get to do some computation */
106 
107 	assert(xm & SP_HIDDEN_BIT);
108 	assert(ym & SP_HIDDEN_BIT);
109 
110 	/* Compare signs */
111 	if (xs > ys)
112 		return x;
113 	else if (xs < ys)
114 		return y;
115 
116 	/* Signs of inputs are the same, let's compare exponents */
117 	if (xs == 0) {
118 		/* Inputs are both positive */
119 		if (xe > ye)
120 			return y;
121 		else if (xe < ye)
122 			return x;
123 	} else {
124 		/* Inputs are both negative */
125 		if (xe > ye)
126 			return x;
127 		else if (xe < ye)
128 			return y;
129 	}
130 
131 	/* Signs and exponents of inputs are equal, let's compare mantissas */
132 	if (xs == 0) {
133 		/* Inputs are both positive, with equal signs and exponents */
134 		if (xm <= ym)
135 			return x;
136 		return y;
137 	}
138 	/* Inputs are both negative, with equal signs and exponents */
139 	if (xm <= ym)
140 		return y;
141 	return x;
142 }
143 
144 union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
145 {
146 	COMPXSP;
147 	COMPYSP;
148 
149 	EXPLODEXSP;
150 	EXPLODEYSP;
151 
152 	FLUSHXSP;
153 	FLUSHYSP;
154 
155 	ieee754_clearcx();
156 
157 	switch (CLPAIR(xc, yc)) {
158 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
159 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
160 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
161 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
162 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
163 		return ieee754sp_nanxcpt(y);
164 
165 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
166 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
167 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
168 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
169 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
170 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
171 		return ieee754sp_nanxcpt(x);
172 
173 	/*
174 	 * Quiet NaN handling
175 	 */
176 
177 	/*
178 	 *    The case of both inputs quiet NaNs
179 	 */
180 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
181 		return x;
182 
183 	/*
184 	 *    The cases of exactly one input quiet NaN (numbers
185 	 *    are here preferred as returned values to NaNs)
186 	 */
187 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
188 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
189 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
190 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
191 		return x;
192 
193 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
194 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
195 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
196 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
197 		return y;
198 
199 	/*
200 	 * Infinity and zero handling
201 	 */
202 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
203 		return ieee754sp_inf(xs | ys);
204 
205 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
206 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
207 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
208 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
209 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
210 		return y;
211 
212 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
213 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
214 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
215 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
216 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
217 		return x;
218 
219 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
220 		return ieee754sp_zero(xs | ys);
221 
222 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
223 		SPDNORMX;
224 		fallthrough;
225 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
226 		SPDNORMY;
227 		break;
228 
229 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
230 		SPDNORMX;
231 	}
232 
233 	/* Finally get to do some computation */
234 
235 	assert(xm & SP_HIDDEN_BIT);
236 	assert(ym & SP_HIDDEN_BIT);
237 
238 	/* Compare exponent */
239 	if (xe > ye)
240 		return y;
241 	else if (xe < ye)
242 		return x;
243 
244 	/* Compare mantissa */
245 	if (xm < ym)
246 		return x;
247 	else if (xm > ym)
248 		return y;
249 	else if (xs == 1)
250 		return x;
251 	return y;
252 }
253