GNU Linux-libre 4.19.314-gnu1
[releases.git] / arch / parisc / math-emu / fcnvuf.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/fcnvuf.c              $Revision: 1.1 $
26  *
27  *  Purpose:
28  *      Fixed point to Floating-point Converts
29  *
30  *  External Interfaces:
31  *      dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
32  *      dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
33  *      sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
34  *      sgl_to_sgl_fcnvuf(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  *  Fixed point to Floating-point Converts                              *
52  ************************************************************************/
53
54 /*
55  *  Convert Single Unsigned Fixed to Single Floating-point format
56  */
57
58 int
59 sgl_to_sgl_fcnvuf(
60                         unsigned int *srcptr,
61                         unsigned int *nullptr,
62                         sgl_floating_point *dstptr,
63                         unsigned int *status)
64 {
65         register unsigned int src, result = 0;
66         register int dst_exponent;
67
68         src = *srcptr;
69
70         /* Check for zero */ 
71         if (src == 0) { 
72                 Sgl_setzero(result); 
73                 *dstptr = result;
74                 return(NOEXCEPTION); 
75         } 
76         /*
77          * Generate exponent and normalized mantissa
78          */
79         dst_exponent = 16;    /* initialize for normalization */
80         /*
81          * Check word for most significant bit set.  Returns
82          * a value in dst_exponent indicating the bit position,
83          * between -1 and 30.
84          */
85         Find_ms_one_bit(src,dst_exponent);
86         /*  left justify source, with msb at bit position 0  */
87         src <<= dst_exponent+1;
88         Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH);
89         Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
90
91         /* check for inexact */
92         if (Suint_isinexact_to_sgl(src)) {
93                 switch (Rounding_mode()) {
94                         case ROUNDPLUS: 
95                                 Sgl_increment(result);
96                                 break;
97                         case ROUNDMINUS: /* never negative */
98                                 break;
99                         case ROUNDNEAREST:
100                                 Sgl_roundnearest_from_suint(src,result);
101                                 break;
102                 }
103                 if (Is_inexacttrap_enabled()) {
104                         *dstptr = result;
105                         return(INEXACTEXCEPTION);
106                 }
107                 else Set_inexactflag();
108         }
109         *dstptr = result;
110         return(NOEXCEPTION);
111 }
112
113 /*
114  *  Single Unsigned Fixed to Double Floating-point 
115  */
116
117 int
118 sgl_to_dbl_fcnvuf(
119                         unsigned int *srcptr,
120                         unsigned int *nullptr,
121                         dbl_floating_point *dstptr,
122                         unsigned int *status)
123 {
124         register int dst_exponent;
125         register unsigned int src, resultp1 = 0, resultp2 = 0;
126
127         src = *srcptr;
128
129         /* Check for zero */
130         if (src == 0) {
131                 Dbl_setzero(resultp1,resultp2);
132                 Dbl_copytoptr(resultp1,resultp2,dstptr);
133                 return(NOEXCEPTION);
134         }
135         /*
136          * Generate exponent and normalized mantissa
137          */
138         dst_exponent = 16;    /* initialize for normalization */
139         /*
140          * Check word for most significant bit set.  Returns
141          * a value in dst_exponent indicating the bit position,
142          * between -1 and 30.
143          */
144         Find_ms_one_bit(src,dst_exponent);
145         /*  left justify source, with msb at bit position 0  */
146         src <<= dst_exponent+1;
147         Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH);
148         Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH));
149         Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
150         Dbl_copytoptr(resultp1,resultp2,dstptr);
151         return(NOEXCEPTION);
152 }
153
154 /*
155  *  Double Unsigned Fixed to Single Floating-point 
156  */
157
158 int
159 dbl_to_sgl_fcnvuf(
160                         dbl_unsigned *srcptr,
161                         unsigned int *nullptr,
162                         sgl_floating_point *dstptr,
163                         unsigned int *status)
164 {
165         int dst_exponent;
166         unsigned int srcp1, srcp2, result = 0;
167
168         Duint_copyfromptr(srcptr,srcp1,srcp2);
169
170         /* Check for zero */
171         if (srcp1 == 0 && srcp2 == 0) {
172                 Sgl_setzero(result);
173                 *dstptr = result;
174                 return(NOEXCEPTION);
175         }
176         /*
177          * Generate exponent and normalized mantissa
178          */
179         dst_exponent = 16;    /* initialize for normalization */
180         if (srcp1 == 0) {
181                 /*
182                  * Check word for most significant bit set.  Returns
183                  * a value in dst_exponent indicating the bit position,
184                  * between -1 and 30.
185                  */
186                 Find_ms_one_bit(srcp2,dst_exponent);
187                 /*  left justify source, with msb at bit position 0  */
188                 srcp1 = srcp2 << dst_exponent+1;    
189                 srcp2 = 0;
190                 /*
191                  *  since msb set is in second word, need to 
192                  *  adjust bit position count
193                  */
194                 dst_exponent += 32;
195         }
196         else {
197                 /*
198                  * Check word for most significant bit set.  Returns
199                  * a value in dst_exponent indicating the bit position,
200                  * between -1 and 30.
201                  *
202                  */
203                 Find_ms_one_bit(srcp1,dst_exponent);
204                 /*  left justify source, with msb at bit position 0  */
205                 if (dst_exponent >= 0) {
206                         Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
207                          srcp1); 
208                         srcp2 <<= dst_exponent+1;
209                 }
210         }
211         Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH);
212         Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
213
214         /* check for inexact */
215         if (Duint_isinexact_to_sgl(srcp1,srcp2)) {
216                 switch (Rounding_mode()) {
217                         case ROUNDPLUS: 
218                                 Sgl_increment(result);
219                                 break;
220                         case ROUNDMINUS: /* never negative */
221                                 break;
222                         case ROUNDNEAREST:
223                                 Sgl_roundnearest_from_duint(srcp1,srcp2,result);
224                                 break;
225                 }
226                 if (Is_inexacttrap_enabled()) {
227                         *dstptr = result;
228                         return(INEXACTEXCEPTION);
229                 }
230                 else Set_inexactflag();
231         }
232         *dstptr = result;
233         return(NOEXCEPTION);
234 }
235
236 /*
237  *  Double Unsigned Fixed to Double Floating-point 
238  */
239
240 int
241 dbl_to_dbl_fcnvuf(
242                     dbl_unsigned *srcptr,
243                     unsigned int *nullptr,
244                     dbl_floating_point *dstptr,
245                     unsigned int *status)
246 {
247         register int dst_exponent;
248         register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0;
249
250         Duint_copyfromptr(srcptr,srcp1,srcp2);
251
252         /* Check for zero */
253         if (srcp1 == 0 && srcp2 ==0) {
254                 Dbl_setzero(resultp1,resultp2);
255                 Dbl_copytoptr(resultp1,resultp2,dstptr);
256                 return(NOEXCEPTION);
257         }
258         /*
259          * Generate exponent and normalized mantissa
260          */
261         dst_exponent = 16;    /* initialize for normalization */
262         if (srcp1 == 0) {
263                 /*
264                  * Check word for most significant bit set.  Returns
265                  * a value in dst_exponent indicating the bit position,
266                  * between -1 and 30.
267                  */
268                 Find_ms_one_bit(srcp2,dst_exponent);
269                 /*  left justify source, with msb at bit position 0  */
270                 srcp1 = srcp2 << dst_exponent+1;
271                 srcp2 = 0;
272                 /*
273                  *  since msb set is in second word, need to 
274                  *  adjust bit position count
275                  */
276                 dst_exponent += 32;
277         }
278         else {
279                 /*
280                  * Check word for most significant bit set.  Returns
281                  * a value in dst_exponent indicating the bit position,
282                  * between -1 and 30.
283                  */
284                 Find_ms_one_bit(srcp1,dst_exponent);
285                 /*  left justify source, with msb at bit position 0  */
286                 if (dst_exponent >= 0) {
287                         Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
288                          srcp1); 
289                         srcp2 <<= dst_exponent+1;
290                 }
291         }
292         Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH);
293         Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2);
294         Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
295
296         /* check for inexact */
297         if (Duint_isinexact_to_dbl(srcp2)) {
298                 switch (Rounding_mode()) {
299                         case ROUNDPLUS: 
300                                 Dbl_increment(resultp1,resultp2);
301                                 break;
302                         case ROUNDMINUS: /* never negative */
303                                 break;
304                         case ROUNDNEAREST:
305                                 Dbl_roundnearest_from_duint(srcp2,resultp1,
306                                 resultp2);
307                                 break;
308                 }
309                 if (Is_inexacttrap_enabled()) {
310                         Dbl_copytoptr(resultp1,resultp2,dstptr);
311                         return(INEXACTEXCEPTION);
312                 }
313                 else Set_inexactflag();
314         }
315         Dbl_copytoptr(resultp1,resultp2,dstptr);
316         return(NOEXCEPTION);
317 }
318