spi: omap2-mcspi: Use dma_request_chan() for requesting DMA channel
[cascardo/linux.git] / arch / mips / math-emu / ieee754sp.c
1 /* IEEE754 floating point arithmetic
2  * single precision
3  */
4 /*
5  * MIPS floating point support
6  * Copyright (C) 1994-2000 Algorithmics Ltd.
7  *
8  *  This program is free software; you can distribute it and/or modify it
9  *  under the terms of the GNU General Public License (Version 2) as
10  *  published by the Free Software Foundation.
11  *
12  *  This program is distributed in the hope it will be useful, but WITHOUT
13  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  *  for more details.
16  *
17  *  You should have received a copy of the GNU General Public License along
18  *  with this program; if not, write to the Free Software Foundation, Inc.,
19  *  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
20  */
21
22 #include <linux/compiler.h>
23
24 #include "ieee754sp.h"
25
26 int ieee754sp_class(union ieee754sp x)
27 {
28         COMPXSP;
29         EXPLODEXSP;
30         return xc;
31 }
32
33 static inline int ieee754sp_isnan(union ieee754sp x)
34 {
35         return ieee754_class_nan(ieee754sp_class(x));
36 }
37
38 static inline int ieee754sp_issnan(union ieee754sp x)
39 {
40         int qbit;
41
42         assert(ieee754sp_isnan(x));
43         qbit = (SPMANT(x) & SP_MBIT(SP_FBITS - 1)) == SP_MBIT(SP_FBITS - 1);
44         return ieee754_csr.nan2008 ^ qbit;
45 }
46
47
48 /*
49  * Raise the Invalid Operation IEEE 754 exception
50  * and convert the signaling NaN supplied to a quiet NaN.
51  */
52 union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r)
53 {
54         assert(ieee754sp_issnan(r));
55
56         ieee754_setcx(IEEE754_INVALID_OPERATION);
57         if (ieee754_csr.nan2008)
58                 SPMANT(r) |= SP_MBIT(SP_FBITS - 1);
59         else
60                 r = ieee754sp_indef();
61
62         return r;
63 }
64
65 static unsigned ieee754sp_get_rounding(int sn, unsigned xm)
66 {
67         /* inexact must round of 3 bits
68          */
69         if (xm & (SP_MBIT(3) - 1)) {
70                 switch (ieee754_csr.rm) {
71                 case FPU_CSR_RZ:
72                         break;
73                 case FPU_CSR_RN:
74                         xm += 0x3 + ((xm >> 3) & 1);
75                         /* xm += (xm&0x8)?0x4:0x3 */
76                         break;
77                 case FPU_CSR_RU:        /* toward +Infinity */
78                         if (!sn)        /* ?? */
79                                 xm += 0x8;
80                         break;
81                 case FPU_CSR_RD:        /* toward -Infinity */
82                         if (sn) /* ?? */
83                                 xm += 0x8;
84                         break;
85                 }
86         }
87         return xm;
88 }
89
90
91 /* generate a normal/denormal number with over,under handling
92  * sn is sign
93  * xe is an unbiased exponent
94  * xm is 3bit extended precision value.
95  */
96 union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
97 {
98         assert(xm);             /* we don't gen exact zeros (probably should) */
99
100         assert((xm >> (SP_FBITS + 1 + 3)) == 0);        /* no execess */
101         assert(xm & (SP_HIDDEN_BIT << 3));
102
103         if (xe < SP_EMIN) {
104                 /* strip lower bits */
105                 int es = SP_EMIN - xe;
106
107                 if (ieee754_csr.nod) {
108                         ieee754_setcx(IEEE754_UNDERFLOW);
109                         ieee754_setcx(IEEE754_INEXACT);
110
111                         switch(ieee754_csr.rm) {
112                         case FPU_CSR_RN:
113                         case FPU_CSR_RZ:
114                                 return ieee754sp_zero(sn);
115                         case FPU_CSR_RU:      /* toward +Infinity */
116                                 if (sn == 0)
117                                         return ieee754sp_min(0);
118                                 else
119                                         return ieee754sp_zero(1);
120                         case FPU_CSR_RD:      /* toward -Infinity */
121                                 if (sn == 0)
122                                         return ieee754sp_zero(0);
123                                 else
124                                         return ieee754sp_min(1);
125                         }
126                 }
127
128                 if (xe == SP_EMIN - 1 &&
129                     ieee754sp_get_rounding(sn, xm) >> (SP_FBITS + 1 + 3))
130                 {
131                         /* Not tiny after rounding */
132                         ieee754_setcx(IEEE754_INEXACT);
133                         xm = ieee754sp_get_rounding(sn, xm);
134                         xm >>= 1;
135                         /* Clear grs bits */
136                         xm &= ~(SP_MBIT(3) - 1);
137                         xe++;
138                 } else {
139                         /* sticky right shift es bits
140                          */
141                         SPXSRSXn(es);
142                         assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
143                         assert(xe == SP_EMIN);
144                 }
145         }
146         if (xm & (SP_MBIT(3) - 1)) {
147                 ieee754_setcx(IEEE754_INEXACT);
148                 if ((xm & (SP_HIDDEN_BIT << 3)) == 0) {
149                         ieee754_setcx(IEEE754_UNDERFLOW);
150                 }
151
152                 /* inexact must round of 3 bits
153                  */
154                 xm = ieee754sp_get_rounding(sn, xm);
155                 /* adjust exponent for rounding add overflowing
156                  */
157                 if (xm >> (SP_FBITS + 1 + 3)) {
158                         /* add causes mantissa overflow */
159                         xm >>= 1;
160                         xe++;
161                 }
162         }
163         /* strip grs bits */
164         xm >>= 3;
165
166         assert((xm >> (SP_FBITS + 1)) == 0);    /* no execess */
167         assert(xe >= SP_EMIN);
168
169         if (xe > SP_EMAX) {
170                 ieee754_setcx(IEEE754_OVERFLOW);
171                 ieee754_setcx(IEEE754_INEXACT);
172                 /* -O can be table indexed by (rm,sn) */
173                 switch (ieee754_csr.rm) {
174                 case FPU_CSR_RN:
175                         return ieee754sp_inf(sn);
176                 case FPU_CSR_RZ:
177                         return ieee754sp_max(sn);
178                 case FPU_CSR_RU:        /* toward +Infinity */
179                         if (sn == 0)
180                                 return ieee754sp_inf(0);
181                         else
182                                 return ieee754sp_max(1);
183                 case FPU_CSR_RD:        /* toward -Infinity */
184                         if (sn == 0)
185                                 return ieee754sp_max(0);
186                         else
187                                 return ieee754sp_inf(1);
188                 }
189         }
190         /* gen norm/denorm/zero */
191
192         if ((xm & SP_HIDDEN_BIT) == 0) {
193                 /* we underflow (tiny/zero) */
194                 assert(xe == SP_EMIN);
195                 if (ieee754_csr.mx & IEEE754_UNDERFLOW)
196                         ieee754_setcx(IEEE754_UNDERFLOW);
197                 return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
198         } else {
199                 assert((xm >> (SP_FBITS + 1)) == 0);    /* no execess */
200                 assert(xm & SP_HIDDEN_BIT);
201
202                 return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
203         }
204 }