[PATCH] s390: kexec fixes and improvements.
[linux-2.6] / arch / parisc / math-emu / fcnvfxt.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/fcnvfxt.c             $Revision: 1.1 $
26  *
27  *  Purpose:
28  *      Single Floating-point to Single Fixed-point /w truncated result
29  *      Single Floating-point to Double Fixed-point /w truncated result
30  *      Double Floating-point to Single Fixed-point /w truncated result
31  *      Double Floating-point to Double Fixed-point /w truncated result
32  *
33  *  External Interfaces:
34  *      dbl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
35  *      dbl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
36  *      sgl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
37  *      sgl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
38  *
39  *  Internal Interfaces:
40  *
41  *  Theory:
42  *      <<please update with a overview of the operation of this file>>
43  *
44  * END_DESC
45 */
46
47
48 #include "float.h"
49 #include "sgl_float.h"
50 #include "dbl_float.h"
51 #include "cnv_float.h"
52
53 /*
54  *  Convert single floating-point to single fixed-point format
55  *  with truncated result
56  */
57 /*ARGSUSED*/
58 int
59 sgl_to_sgl_fcnvfxt(
60                     sgl_floating_point *srcptr,
61                     unsigned int *nullptr,
62                     int *dstptr,
63                     unsigned int *status)
64 {
65         register unsigned int src, temp;
66         register int src_exponent, result;
67
68         src = *srcptr;
69         src_exponent = Sgl_exponent(src) - SGL_BIAS;
70
71         /* 
72          * Test for overflow
73          */
74         if (src_exponent > SGL_FX_MAX_EXP) {
75                 /* check for MININT */
76                 if ((src_exponent > SGL_FX_MAX_EXP + 1) || 
77                 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
78                         if (Sgl_iszero_sign(src)) result = 0x7fffffff;
79                         else result = 0x80000000; 
80
81                         if (Is_invalidtrap_enabled()) {
82                             return(INVALIDEXCEPTION);
83                         }
84                         Set_invalidflag();
85                         *dstptr = result;
86                         return(NOEXCEPTION);
87                 }
88         }
89         /*
90          * Generate result
91          */
92         if (src_exponent >= 0) {
93                 temp = src;
94                 Sgl_clear_signexponent_set_hidden(temp);
95                 Int_from_sgl_mantissa(temp,src_exponent);
96                 if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
97                 else result = Sgl_all(temp);
98                 *dstptr = result;
99
100                 /* check for inexact */
101                 if (Sgl_isinexact_to_fix(src,src_exponent)) {
102                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
103                         else Set_inexactflag();
104                 }
105         }
106         else {
107                 *dstptr = 0;
108
109                 /* check for inexact */
110                 if (Sgl_isnotzero_exponentmantissa(src)) {
111                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
112                         else Set_inexactflag();
113                 }
114         }
115         return(NOEXCEPTION);
116 }
117
118 /*
119  *  Single Floating-point to Double Fixed-point 
120  */
121 /*ARGSUSED*/
122 int
123 sgl_to_dbl_fcnvfxt(
124                     sgl_floating_point *srcptr,
125                     unsigned int *nullptr,
126                     dbl_integer *dstptr,
127                     unsigned int *status)
128 {
129         register int src_exponent, resultp1;
130         register unsigned int src, temp, resultp2;
131
132         src = *srcptr;
133         src_exponent = Sgl_exponent(src) - SGL_BIAS;
134
135         /* 
136          * Test for overflow
137          */
138         if (src_exponent > DBL_FX_MAX_EXP) {
139                 /* check for MININT */
140                 if ((src_exponent > DBL_FX_MAX_EXP + 1) || 
141                 Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
142                         if (Sgl_iszero_sign(src)) {
143                               resultp1 = 0x7fffffff;
144                               resultp2 = 0xffffffff;
145                         }
146                         else {
147                             resultp1 = 0x80000000; 
148                             resultp2 = 0;
149                         }
150                         if (Is_invalidtrap_enabled()) {
151                             return(INVALIDEXCEPTION);
152                         }
153                         Set_invalidflag();
154                         Dint_copytoptr(resultp1,resultp2,dstptr);
155                         return(NOEXCEPTION);
156                 }
157                 Dint_set_minint(resultp1,resultp2);
158                 Dint_copytoptr(resultp1,resultp2,dstptr);
159                 return(NOEXCEPTION);
160         }
161         /*
162          * Generate result
163          */
164         if (src_exponent >= 0) {
165                 temp = src;
166                 Sgl_clear_signexponent_set_hidden(temp);
167                 Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
168                 if (Sgl_isone_sign(src)) {
169                         Dint_setone_sign(resultp1,resultp2);
170                 }
171                 Dint_copytoptr(resultp1,resultp2,dstptr);
172
173                 /* check for inexact */
174                 if (Sgl_isinexact_to_fix(src,src_exponent)) {
175                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
176                         else Set_inexactflag();
177                 }
178         }
179         else {
180                 Dint_setzero(resultp1,resultp2);
181                 Dint_copytoptr(resultp1,resultp2,dstptr);
182
183                 /* check for inexact */
184                 if (Sgl_isnotzero_exponentmantissa(src)) {
185                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
186                         else Set_inexactflag();
187                 }
188         }
189         return(NOEXCEPTION);
190 }
191
192 /*
193  *  Double Floating-point to Single Fixed-point 
194  */
195 /*ARGSUSED*/
196 int
197 dbl_to_sgl_fcnvfxt(
198                         dbl_floating_point *srcptr,
199                         unsigned int *nullptr,
200                         int *dstptr,
201                         unsigned int *status)
202 {
203         register unsigned int srcp1, srcp2, tempp1, tempp2;
204         register int src_exponent, result;
205
206         Dbl_copyfromptr(srcptr,srcp1,srcp2);
207         src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
208
209         /* 
210          * Test for overflow
211          */
212         if (src_exponent > SGL_FX_MAX_EXP) {
213                 /* check for MININT */
214                 if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
215                         if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
216                         else result = 0x80000000; 
217
218                         if (Is_invalidtrap_enabled()) {
219                             return(INVALIDEXCEPTION);
220                         }
221                         Set_invalidflag();
222                         *dstptr = result;
223                         return(NOEXCEPTION);
224                 }
225         }
226         /*
227          * Generate result
228          */
229         if (src_exponent >= 0) {
230                 tempp1 = srcp1;
231                 tempp2 = srcp2;
232                 Dbl_clear_signexponent_set_hidden(tempp1);
233                 Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
234                 if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
235                         result = -Dbl_allp1(tempp1);
236                 else result = Dbl_allp1(tempp1);
237                 *dstptr = result;
238
239                 /* check for inexact */
240                 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
241                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
242                         else Set_inexactflag();
243                 }
244         }
245         else {
246                 *dstptr = 0;
247
248                 /* check for inexact */
249                 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
250                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
251                         else Set_inexactflag();
252                 }
253         }
254         return(NOEXCEPTION);
255 }
256
257 /*
258  *  Double Floating-point to Double Fixed-point 
259  */
260 /*ARGSUSED*/
261 int
262 dbl_to_dbl_fcnvfxt(
263                         dbl_floating_point *srcptr,
264                         unsigned int *nullptr,
265                         dbl_integer *dstptr,
266                         unsigned int *status)
267 {
268         register int src_exponent, resultp1;
269         register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
270
271         Dbl_copyfromptr(srcptr,srcp1,srcp2);
272         src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
273
274         /* 
275          * Test for overflow
276          */
277         if (src_exponent > DBL_FX_MAX_EXP) {
278                 /* check for MININT */
279                 if ((src_exponent > DBL_FX_MAX_EXP + 1) || 
280                 Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
281                         if (Dbl_iszero_sign(srcp1)) {
282                               resultp1 = 0x7fffffff;
283                               resultp2 = 0xffffffff;
284                         }
285                         else {
286                             resultp1 = 0x80000000; 
287                             resultp2 = 0;
288                         }
289                         if (Is_invalidtrap_enabled()) {
290                             return(INVALIDEXCEPTION);
291                         }
292                         Set_invalidflag();
293                         Dint_copytoptr(resultp1,resultp2,dstptr);
294                         return(NOEXCEPTION);
295                 }
296         }
297         /*
298          * Generate result
299          */
300         if (src_exponent >= 0) {
301                 tempp1 = srcp1;
302                 tempp2 = srcp2;
303                 Dbl_clear_signexponent_set_hidden(tempp1);
304                 Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
305                 resultp1,resultp2);
306                 if (Dbl_isone_sign(srcp1)) {
307                         Dint_setone_sign(resultp1,resultp2);
308                 }
309                 Dint_copytoptr(resultp1,resultp2,dstptr);
310
311                 /* check for inexact */
312                 if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
313                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
314                         else Set_inexactflag();
315                 }
316         }
317         else {
318                 Dint_setzero(resultp1,resultp2);
319                 Dint_copytoptr(resultp1,resultp2,dstptr);
320
321                 /* check for inexact */
322                 if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
323                         if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
324                         else Set_inexactflag();
325                 }
326         }
327         return(NOEXCEPTION);
328 }