parisc: Avoid function pointers for kernel exception routines
[pandora-kernel.git] / arch / parisc / math-emu / fcnvfut.c
1 /*
2  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3  *
4  * Floating-point emulation code
5  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6  *
7  *    This program is free software; you can redistribute it and/or modify
8  *    it under the terms of the GNU General Public License as published by
9  *    the Free Software Foundation; either version 2, or (at your option)
10  *    any later version.
11  *
12  *    This program is distributed in the hope that it will be useful,
13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *    GNU General Public License for more details.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with this program; if not, write to the Free Software
19  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 /*
22  * BEGIN_DESC
23  *
24  *  File:
25  *      @(#)    pa/spmath/fcnvfut.c             $Revision: 1.1 $
26  *
27  *  Purpose:
28  *      Floating-point to Unsigned Fixed-point Converts with Truncation
29  *
30  *  External Interfaces:
31  *      dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
32  *      dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
33  *      sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
34  *      sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
35  *
36  *  Internal Interfaces:
37  *
38  *  Theory:
39  *      <<please update with a overview of the operation of this file>>
40  *
41  * END_DESC
42 */
43
44
45 #include "float.h"
46 #include "sgl_float.h"
47 #include "dbl_float.h"
48 #include "cnv_float.h"
49
50 /************************************************************************
51  *  Floating-point to Unsigned Fixed-point Converts with Truncation     *
52  ************************************************************************/
53
54 /*
55  *  Convert single floating-point to single fixed-point format
56  *  with truncated result
57  */
58 /*ARGSUSED*/
59 int
60 sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
61                     unsigned int *dstptr, unsigned int *status)
62 {
63         register unsigned int src, result;
64         register int src_exponent;
65
66         src = *srcptr;
67         src_exponent = Sgl_exponent(src) - SGL_BIAS;
68
69         /* 
70          * Test for overflow
71          */
72         if (src_exponent > SGL_FX_MAX_EXP + 1) {
73                 if (Sgl_isone_sign(src)) {
74                         result = 0;
75                 } else {
76                         result = 0xffffffff;
77                 }
78                 if (Is_invalidtrap_enabled()) {
79                         return(INVALIDEXCEPTION);
80                 }
81                 Set_invalidflag();
82                 *dstptr = result;
83                 return(NOEXCEPTION);
84         }
85         /*
86          * Generate result
87          */
88         if (src_exponent >= 0) {
89                 /* 
90                  * Check sign.
91                  * If negative, trap unimplemented.
92                  */
93                 if (Sgl_isone_sign(src)) {
94                         result = 0;
95                         if (Is_invalidtrap_enabled()) {
96                                 return(INVALIDEXCEPTION);
97                         }
98                         Set_invalidflag();
99                         *dstptr = result;
100                         return(NOEXCEPTION);
101                 }
102                 Sgl_clear_signexponent_set_hidden(src);
103                 Suint_from_sgl_mantissa(src,src_exponent,result);
104                 *dstptr = result;
105
106                 /* check for inexact */
107                 if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
108                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
109                         else Set_inexactflag();
110                 }
111         }
112         else {
113                 *dstptr = 0;
114
115                 /* check for inexact */
116                 if (Sgl_isnotzero_exponentmantissa(src)) {
117                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
118                         else Set_inexactflag();
119                 }
120         }
121         return(NOEXCEPTION);
122 }
123
124 /*
125  *  Single Floating-point to Double Unsigned Fixed 
126  */
127 /*ARGSUSED*/
128 int
129 sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
130                     dbl_unsigned * dstptr, unsigned int *status)
131 {
132         register int src_exponent;
133         register unsigned int src, resultp1, resultp2;
134
135         src = *srcptr;
136         src_exponent = Sgl_exponent(src) - SGL_BIAS;
137
138         /* 
139          * Test for overflow
140          */
141         if (src_exponent > DBL_FX_MAX_EXP + 1) {
142                 if (Sgl_isone_sign(src)) {
143                         resultp1 = resultp2 = 0;
144                 } else {
145                         resultp1 = resultp2 = 0xffffffff;
146                 }
147                 if (Is_invalidtrap_enabled()) {
148                         return(INVALIDEXCEPTION);
149                 }
150                 Set_invalidflag();
151                 Duint_copytoptr(resultp1,resultp2,dstptr);
152                 return(NOEXCEPTION);
153         }
154         /*
155          * Generate result
156          */
157         if (src_exponent >= 0) {
158                 /* 
159                  * Check sign.
160                  * If negative, trap unimplemented.
161                  */
162                 if (Sgl_isone_sign(src)) {
163                         resultp1 = resultp2 = 0;
164                         if (Is_invalidtrap_enabled()) {
165                                 return(INVALIDEXCEPTION);
166                         }
167                         Set_invalidflag();
168                         Duint_copytoptr(resultp1,resultp2,dstptr);
169                         return(NOEXCEPTION);
170                 }
171                 Sgl_clear_signexponent_set_hidden(src);
172                 Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
173                 Duint_copytoptr(resultp1,resultp2,dstptr);
174
175                 /* check for inexact */
176                 if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
177                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
178                         else Set_inexactflag();
179                 }
180         }
181         else {
182                 Duint_setzero(resultp1,resultp2);
183                 Duint_copytoptr(resultp1,resultp2,dstptr);
184
185                 /* check for inexact */
186                 if (Sgl_isnotzero_exponentmantissa(src)) {
187                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
188                         else Set_inexactflag();
189                 }
190         }
191         return(NOEXCEPTION);
192 }
193
194 /*
195  *  Double Floating-point to Single Unsigned Fixed 
196  */
197 /*ARGSUSED*/
198 int
199 dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
200                     unsigned int *dstptr, unsigned int *status)
201 {
202         register unsigned int srcp1, srcp2, result;
203         register int src_exponent;
204
205         Dbl_copyfromptr(srcptr,srcp1,srcp2);
206         src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
207
208         /* 
209          * Test for overflow
210          */
211         if (src_exponent > SGL_FX_MAX_EXP + 1) {
212                 if (Dbl_isone_sign(srcp1)) {
213                         result = 0;
214                 } else {
215                         result = 0xffffffff;
216                 }
217                 if (Is_invalidtrap_enabled()) {
218                         return(INVALIDEXCEPTION);
219                 }
220                 Set_invalidflag();
221                 *dstptr = result;
222                 return(NOEXCEPTION);
223         }
224         /*
225          * Generate result
226          */
227         if (src_exponent >= 0) {
228                 /* 
229                  * Check sign.
230                  * If negative, trap unimplemented.
231                  */
232                 if (Dbl_isone_sign(srcp1)) {
233                         result = 0;
234                         if (Is_invalidtrap_enabled()) {
235                                 return(INVALIDEXCEPTION);
236                         }
237                         Set_invalidflag();
238                         *dstptr = result;
239                         return(NOEXCEPTION);
240                 }
241                 Dbl_clear_signexponent_set_hidden(srcp1);
242                 Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
243                 *dstptr = result;
244
245                 /* check for inexact */
246                 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
247                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
248                         else Set_inexactflag();
249                 }
250         }
251         else {
252                 *dstptr = 0;
253
254                 /* check for inexact */
255                 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
256                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
257                         else Set_inexactflag();
258                 }
259         }
260         return(NOEXCEPTION);
261 }
262
263 /*
264  *  Double Floating-point to Double Unsigned Fixed 
265  */
266 /*ARGSUSED*/
267 int
268 dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
269                     dbl_unsigned * dstptr, unsigned int *status)
270 {
271         register int src_exponent;
272         register unsigned int srcp1, srcp2, resultp1, resultp2;
273
274         Dbl_copyfromptr(srcptr,srcp1,srcp2);
275         src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
276
277         /* 
278          * Test for overflow
279          */
280         if (src_exponent > DBL_FX_MAX_EXP + 1) {
281                 if (Dbl_isone_sign(srcp1)) {
282                         resultp1 = resultp2 = 0;
283                 } else {
284                         resultp1 = resultp2 = 0xffffffff;
285                 }
286                 if (Is_invalidtrap_enabled()) {
287                         return(INVALIDEXCEPTION);
288                 }
289                 Set_invalidflag();
290                 Duint_copytoptr(resultp1,resultp2,dstptr);
291                 return(NOEXCEPTION);
292         }
293         /*
294          * Generate result
295          */
296         if (src_exponent >= 0) {
297                 /* 
298                  * Check sign.
299                  * If negative, trap unimplemented.
300                  */
301                 if (Dbl_isone_sign(srcp1)) {
302                         resultp1 = resultp2 = 0;
303                         if (Is_invalidtrap_enabled()) {
304                                 return(INVALIDEXCEPTION);
305                         }
306                         Set_invalidflag();
307                         Duint_copytoptr(resultp1,resultp2,dstptr);
308                         return(NOEXCEPTION);
309                 }
310                 Dbl_clear_signexponent_set_hidden(srcp1);
311                 Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,
312                   resultp1,resultp2);
313                 Duint_copytoptr(resultp1,resultp2,dstptr);
314
315                 /* check for inexact */
316                 if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
317                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
318                         else Set_inexactflag();
319                 }
320         }
321         else {
322                 Duint_setzero(resultp1,resultp2);
323                 Duint_copytoptr(resultp1,resultp2,dstptr);
324
325                 /* check for inexact */
326                 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
327                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
328                         else Set_inexactflag();
329                 }
330         }
331         return(NOEXCEPTION);
332 }