MIPS: math-emu: Add support for the MIPS R6 MIN{, A} FPU instruction
[linux-drm-fsl-dcu.git] / arch / mips / math-emu / sp_fmin.c
1 /*
2  * IEEE754 floating point arithmetic
3  * single precision: MIN{,A}.f
4  * MIN : Scalar Floating-Point Minimum
5  * MINA: Scalar Floating-Point argument with Minimum Absolute Value
6  *
7  * MIN.S : FPR[fd] = minNum(FPR[fs],FPR[ft])
8  * MINA.S: FPR[fd] = maxNumMag(FPR[fs],FPR[ft])
9  *
10  * MIPS floating point support
11  * Copyright (C) 2015 Imagination Technologies, Ltd.
12  * Author: Markos Chandras <markos.chandras@imgtec.com>
13  *
14  *  This program is free software; you can distribute it and/or modify it
15  *  under the terms of the GNU General Public License as published by the
16  *  Free Software Foundation; version 2 of the License.
17  */
18
19 #include "ieee754sp.h"
20
21 union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y)
22 {
23         COMPXSP;
24         COMPYSP;
25
26         EXPLODEXSP;
27         EXPLODEYSP;
28
29         FLUSHXSP;
30         FLUSHYSP;
31
32         ieee754_clearcx();
33
34         switch (CLPAIR(xc, yc)) {
35         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
36         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
37         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
38         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
39         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
40                 return ieee754sp_nanxcpt(y);
41
42         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
43         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
44         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
45         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
46         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
47         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
48                 return ieee754sp_nanxcpt(x);
49
50         /* numbers are preferred to NaNs */
51         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
52         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
53         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
54         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
55                 return x;
56
57         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
58         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
59         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
60         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
61         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
62                 return y;
63
64         /*
65          * Infinity and zero handling
66          */
67         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
68         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
69         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
70         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
71         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
72                 return xs ? x : y;
73
74         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
75         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
76         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
77         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
78         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
79         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
80                 return ys ? y : x;
81
82         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
83                 if (xs == ys)
84                         return x;
85                 return ieee754sp_zero(1);
86
87         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
88                 SPDNORMX;
89
90         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
91                 SPDNORMY;
92                 break;
93
94         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
95                 SPDNORMX;
96         }
97
98         /* Finally get to do some computation */
99
100         assert(xm & SP_HIDDEN_BIT);
101         assert(ym & SP_HIDDEN_BIT);
102
103         /* Compare signs */
104         if (xs > ys)
105                 return x;
106         else if (xs < ys)
107                 return y;
108
109         /* Compare exponent */
110         if (xe > ye)
111                 return y;
112         else if (xe < ye)
113                 return x;
114
115         /* Compare mantissa */
116         if (xm <= ym)
117                 return x;
118         return y;
119 }
120
121 union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y)
122 {
123         COMPXSP;
124         COMPYSP;
125
126         EXPLODEXSP;
127         EXPLODEYSP;
128
129         FLUSHXSP;
130         FLUSHYSP;
131
132         ieee754_clearcx();
133
134         switch (CLPAIR(xc, yc)) {
135         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
136         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
137         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
138         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
139         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
140                 return ieee754sp_nanxcpt(y);
141
142         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
143         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
144         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
145         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
146         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
147         case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
148                 return ieee754sp_nanxcpt(x);
149
150         /* numbers are preferred to NaNs */
151         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
152         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
153         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
154         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
155                 return x;
156
157         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
158         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
159         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
160         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
161         case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
162                 return y;
163
164         /*
165          * Infinity and zero handling
166          */
167         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
168         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
169         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
170         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
171         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
172                 return x;
173
174         case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
175         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
176         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
177         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
178         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
179         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
180                 return y;
181
182         case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
183                 if (xs == ys)
184                         return x;
185                 return ieee754sp_zero(1);
186
187         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
188                 SPDNORMX;
189
190         case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
191                 SPDNORMY;
192                 break;
193
194         case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
195                 SPDNORMX;
196         }
197
198         /* Finally get to do some computation */
199
200         assert(xm & SP_HIDDEN_BIT);
201         assert(ym & SP_HIDDEN_BIT);
202
203         /* Compare exponent */
204         if (xe > ye)
205                 return y;
206         else if (xe < ye)
207                 return x;
208
209         /* Compare mantissa */
210         if (xm <= ym)
211                 return x;
212         return y;
213 }