Merge master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6
[linux-2.6] / arch / parisc / math-emu / fcnvxf.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/fcnvxf.c              $Revision: 1.1 $
26  *
27  *  Purpose:
28  *      Single Fixed-point to Single Floating-point
29  *      Single Fixed-point to Double Floating-point 
30  *      Double Fixed-point to Single Floating-point 
31  *      Double Fixed-point to Double Floating-point 
32  *
33  *  External Interfaces:
34  *      dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
35  *      dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
36  *      sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
37  *      sgl_to_sgl_fcnvxf(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 fixed-point to single floating-point format
55  */
56
57 int
58 sgl_to_sgl_fcnvxf(
59                     int *srcptr,
60                     unsigned int *nullptr,
61                     sgl_floating_point *dstptr,
62                     unsigned int *status)
63 {
64         register int src, dst_exponent;
65         register unsigned int result = 0;
66
67         src = *srcptr;
68         /* 
69          * set sign bit of result and get magnitude of source 
70          */
71         if (src < 0) {
72                 Sgl_setone_sign(result);  
73                 Int_negate(src);
74         }
75         else {
76                 Sgl_setzero_sign(result);
77                 /* Check for zero */ 
78                 if (src == 0) { 
79                         Sgl_setzero(result); 
80                         *dstptr = result;
81                         return(NOEXCEPTION); 
82                 } 
83         }
84         /*
85          * Generate exponent and normalized mantissa
86          */
87         dst_exponent = 16;    /* initialize for normalization */
88         /*
89          * Check word for most significant bit set.  Returns
90          * a value in dst_exponent indicating the bit position,
91          * between -1 and 30.
92          */
93         Find_ms_one_bit(src,dst_exponent);
94         /*  left justify source, with msb at bit position 1  */
95         if (dst_exponent >= 0) src <<= dst_exponent;
96         else src = 1 << 30;
97         Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
98         Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
99
100         /* check for inexact */
101         if (Int_isinexact_to_sgl(src)) {
102                 switch (Rounding_mode()) {
103                         case ROUNDPLUS: 
104                                 if (Sgl_iszero_sign(result)) 
105                                         Sgl_increment(result);
106                                 break;
107                         case ROUNDMINUS: 
108                                 if (Sgl_isone_sign(result)) 
109                                         Sgl_increment(result);
110                                 break;
111                         case ROUNDNEAREST:
112                                 Sgl_roundnearest_from_int(src,result);
113                 }
114                 if (Is_inexacttrap_enabled()) {
115                         *dstptr = result;
116                         return(INEXACTEXCEPTION);
117                 }
118                 else Set_inexactflag();
119         }
120         *dstptr = result;
121         return(NOEXCEPTION);
122 }
123
124 /*
125  *  Single Fixed-point to Double Floating-point 
126  */
127
128 int
129 sgl_to_dbl_fcnvxf(
130                     int *srcptr,
131                     unsigned int *nullptr,
132                     dbl_floating_point *dstptr,
133                     unsigned int *status)
134 {
135         register int src, dst_exponent;
136         register unsigned int resultp1 = 0, resultp2 = 0;
137
138         src = *srcptr;
139         /* 
140          * set sign bit of result and get magnitude of source 
141          */
142         if (src < 0) {
143                 Dbl_setone_sign(resultp1);  
144                 Int_negate(src);
145         }
146         else {
147                 Dbl_setzero_sign(resultp1);
148                 /* Check for zero */
149                 if (src == 0) {
150                         Dbl_setzero(resultp1,resultp2);
151                         Dbl_copytoptr(resultp1,resultp2,dstptr);
152                         return(NOEXCEPTION);
153                 }
154         }
155         /*
156          * Generate exponent and normalized mantissa
157          */
158         dst_exponent = 16;    /* initialize for normalization */
159         /*
160          * Check word for most significant bit set.  Returns
161          * a value in dst_exponent indicating the bit position,
162          * between -1 and 30.
163          */
164         Find_ms_one_bit(src,dst_exponent);
165         /*  left justify source, with msb at bit position 1  */
166         if (dst_exponent >= 0) src <<= dst_exponent;
167         else src = 1 << 30;
168         Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1);
169         Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH));
170         Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
171         Dbl_copytoptr(resultp1,resultp2,dstptr);
172         return(NOEXCEPTION);
173 }
174
175 /*
176  *  Double Fixed-point to Single Floating-point 
177  */
178
179 int
180 dbl_to_sgl_fcnvxf(
181                         dbl_integer *srcptr,
182                         unsigned int *nullptr,
183                         sgl_floating_point *dstptr,
184                         unsigned int *status)
185 {
186         int dst_exponent, srcp1;
187         unsigned int result = 0, srcp2;
188
189         Dint_copyfromptr(srcptr,srcp1,srcp2);
190         /* 
191          * set sign bit of result and get magnitude of source 
192          */
193         if (srcp1 < 0) {
194                 Sgl_setone_sign(result);  
195                 Dint_negate(srcp1,srcp2);
196         }
197         else {
198                 Sgl_setzero_sign(result);
199                 /* Check for zero */
200                 if (srcp1 == 0 && srcp2 == 0) {
201                         Sgl_setzero(result);
202                         *dstptr = result;
203                         return(NOEXCEPTION);
204                 }
205         }
206         /*
207          * Generate exponent and normalized mantissa
208          */
209         dst_exponent = 16;    /* initialize for normalization */
210         if (srcp1 == 0) {
211                 /*
212                  * Check word for most significant bit set.  Returns
213                  * a value in dst_exponent indicating the bit position,
214                  * between -1 and 30.
215                  */
216                 Find_ms_one_bit(srcp2,dst_exponent);
217                 /*  left justify source, with msb at bit position 1  */
218                 if (dst_exponent >= 0) {
219                         srcp1 = srcp2 << dst_exponent;    
220                         srcp2 = 0;
221                 }
222                 else {
223                         srcp1 = srcp2 >> 1;
224                         srcp2 <<= 31; 
225                 }
226                 /*
227                  *  since msb set is in second word, need to 
228                  *  adjust bit position count
229                  */
230                 dst_exponent += 32;
231         }
232         else {
233                 /*
234                  * Check word for most significant bit set.  Returns
235                  * a value in dst_exponent indicating the bit position,
236                  * between -1 and 30.
237                  *
238                  */
239                 Find_ms_one_bit(srcp1,dst_exponent);
240                 /*  left justify source, with msb at bit position 1  */
241                 if (dst_exponent > 0) {
242                         Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
243                          srcp1); 
244                         srcp2 <<= dst_exponent;
245                 }
246                 /*
247                  * If dst_exponent = 0, we don't need to shift anything.
248                  * If dst_exponent = -1, src = - 2**63 so we won't need to 
249                  * shift srcp2.
250                  */
251                 else srcp1 >>= -(dst_exponent);
252         }
253         Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1);
254         Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
255
256         /* check for inexact */
257         if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
258                 switch (Rounding_mode()) {
259                         case ROUNDPLUS: 
260                                 if (Sgl_iszero_sign(result)) 
261                                         Sgl_increment(result);
262                                 break;
263                         case ROUNDMINUS: 
264                                 if (Sgl_isone_sign(result)) 
265                                         Sgl_increment(result);
266                                 break;
267                         case ROUNDNEAREST:
268                                 Sgl_roundnearest_from_dint(srcp1,srcp2,result);
269                 }
270                 if (Is_inexacttrap_enabled()) {
271                         *dstptr = result;
272                         return(INEXACTEXCEPTION);
273                 }
274                 else Set_inexactflag();
275         }
276         *dstptr = result;
277         return(NOEXCEPTION);
278 }
279
280 /*
281  *  Double Fixed-point to Double Floating-point 
282  */
283
284 int
285 dbl_to_dbl_fcnvxf(
286                     dbl_integer *srcptr,
287                     unsigned int *nullptr,
288                     dbl_floating_point *dstptr,
289                     unsigned int *status)
290 {
291         register int srcp1, dst_exponent;
292         register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
293
294         Dint_copyfromptr(srcptr,srcp1,srcp2);
295         /* 
296          * set sign bit of result and get magnitude of source 
297          */
298         if (srcp1 < 0) {
299                 Dbl_setone_sign(resultp1);
300                 Dint_negate(srcp1,srcp2);
301         }
302         else {
303                 Dbl_setzero_sign(resultp1);
304                 /* Check for zero */
305                 if (srcp1 == 0 && srcp2 ==0) {
306                         Dbl_setzero(resultp1,resultp2);
307                         Dbl_copytoptr(resultp1,resultp2,dstptr);
308                         return(NOEXCEPTION);
309                 }
310         }
311         /*
312          * Generate exponent and normalized mantissa
313          */
314         dst_exponent = 16;    /* initialize for normalization */
315         if (srcp1 == 0) {
316                 /*
317                  * Check word for most significant bit set.  Returns
318                  * a value in dst_exponent indicating the bit position,
319                  * between -1 and 30.
320                  */
321                 Find_ms_one_bit(srcp2,dst_exponent);
322                 /*  left justify source, with msb at bit position 1  */
323                 if (dst_exponent >= 0) {
324                         srcp1 = srcp2 << dst_exponent;    
325                         srcp2 = 0;
326                 }
327                 else {
328                         srcp1 = srcp2 >> 1;
329                         srcp2 <<= 31;
330                 }
331                 /*
332                  *  since msb set is in second word, need to 
333                  *  adjust bit position count
334                  */
335                 dst_exponent += 32;
336         }
337         else {
338                 /*
339                  * Check word for most significant bit set.  Returns
340                  * a value in dst_exponent indicating the bit position,
341                  * between -1 and 30.
342                  */
343                 Find_ms_one_bit(srcp1,dst_exponent);
344                 /*  left justify source, with msb at bit position 1  */
345                 if (dst_exponent > 0) {
346                         Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
347                          srcp1); 
348                         srcp2 <<= dst_exponent;
349                 }
350                 /*
351                  * If dst_exponent = 0, we don't need to shift anything.
352                  * If dst_exponent = -1, src = - 2**63 so we won't need to 
353                  * shift srcp2.
354                  */
355                 else srcp1 >>= -(dst_exponent);
356         }
357         Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
358         Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
359         Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
360
361         /* check for inexact */
362         if (Dint_isinexact_to_dbl(srcp2)) {
363                 switch (Rounding_mode()) {
364                         case ROUNDPLUS: 
365                                 if (Dbl_iszero_sign(resultp1)) {
366                                         Dbl_increment(resultp1,resultp2);
367                                 }
368                                 break;
369                         case ROUNDMINUS: 
370                                 if (Dbl_isone_sign(resultp1)) {
371                                         Dbl_increment(resultp1,resultp2);
372                                 }
373                                 break;
374                         case ROUNDNEAREST:
375                                 Dbl_roundnearest_from_dint(srcp2,resultp1,
376                                 resultp2);
377                 }
378                 if (Is_inexacttrap_enabled()) {
379                         Dbl_copytoptr(resultp1,resultp2,dstptr);
380                         return(INEXACTEXCEPTION);
381                 }
382                 else Set_inexactflag();
383         }
384         Dbl_copytoptr(resultp1,resultp2,dstptr);
385         return(NOEXCEPTION);
386 }