1 /*        $NetBSD: fcnvxf.c,v 1.4 2012/02/04 17:03:10 skrll Exp $     */
2 
3 /*        $OpenBSD: fcnvxf.c,v 1.5 2001/03/29 03:58:18 mickey Exp $   */
4 
5 /*
6  * Copyright 1996 1995 by Open Software Foundation, Inc.
7  *              All Rights Reserved
8  *
9  * Permission to use, copy, modify, and distribute this software and
10  * its documentation for any purpose and without fee is hereby granted,
11  * provided that the above copyright notice appears in all copies and
12  * that both the copyright notice and this permission notice appear in
13  * supporting documentation.
14  *
15  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17  * FOR A PARTICULAR PURPOSE.
18  *
19  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
22  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
23  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24  *
25  */
26 /*
27  * pmk1.1
28  */
29 /*
30  * (c) Copyright 1986 HEWLETT-PACKARD COMPANY
31  *
32  * To anyone who acknowledges that this file is provided "AS IS"
33  * without any express or implied warranty:
34  *     permission to use, copy, modify, and distribute this file
35  * for any purpose is hereby granted without fee, provided that
36  * the above copyright notice and this notice appears in all
37  * copies, and that the name of Hewlett-Packard Company not be
38  * used in advertising or publicity pertaining to distribution
39  * of the software without specific, written prior permission.
40  * Hewlett-Packard Company makes no representations about the
41  * suitability of this software for any purpose.
42  */
43 
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: fcnvxf.c,v 1.4 2012/02/04 17:03:10 skrll Exp $");
46 
47 #include "../spmath/float.h"
48 #include "../spmath/sgl_float.h"
49 #include "../spmath/dbl_float.h"
50 #include "../spmath/cnv_float.h"
51 
52 /*
53  *  Convert single fixed-point to single floating-point format
54  */
55 int
sgl_to_sgl_fcnvxf(int * srcptr,sgl_floating_point * dstptr,unsigned int * status)56 sgl_to_sgl_fcnvxf(int *srcptr, sgl_floating_point *dstptr,
57     unsigned int *status)
58 {
59           register int src, dst_exponent;
60           register unsigned int result = 0;
61 
62           src = *srcptr;
63           /*
64            * set sign bit of result and get magnitude of source
65            */
66           if (src < 0) {
67                     Sgl_setone_sign(result);
68                     Int_negate(src);
69           }
70           else {
71                     Sgl_setzero_sign(result);
72                     /* Check for zero */
73                     if (src == 0) {
74                               Sgl_setzero(result);
75                               *dstptr = result;
76                               return(NOEXCEPTION);
77                     }
78           }
79           /*
80            * Generate exponent and normalized mantissa
81            */
82           dst_exponent = 16;    /* initialize for normalization */
83           /*
84            * Check word for most significant bit set.  Returns
85            * a value in dst_exponent indicating the bit position,
86            * between -1 and 30.
87            */
88           Find_ms_one_bit(src,dst_exponent);
89           /*  left justify source, with msb at bit position 1  */
90           if (dst_exponent >= 0) src <<= dst_exponent;
91           else src = 1 << 30;
92           Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
93           Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
94 
95           /* check for inexact */
96           if (Int_isinexact_to_sgl(src)) {
97                     switch (Rounding_mode()) {
98                               case ROUNDPLUS:
99                                         if (Sgl_iszero_sign(result))
100                                                   Sgl_increment(result);
101                                         break;
102                               case ROUNDMINUS:
103                                         if (Sgl_isone_sign(result))
104                                                   Sgl_increment(result);
105                                         break;
106                               case ROUNDNEAREST:
107                                         Sgl_roundnearest_from_int(src,result);
108                     }
109                     if (Is_inexacttrap_enabled()) {
110                               *dstptr = result;
111                               return(INEXACTEXCEPTION);
112                     }
113                     else Set_inexactflag();
114           }
115           *dstptr = result;
116           return(NOEXCEPTION);
117 }
118 
119 /*
120  *  Single Fixed-point to Double Floating-point
121  */
122 int
sgl_to_dbl_fcnvxf(int * srcptr,dbl_floating_point * dstptr,unsigned int * status)123 sgl_to_dbl_fcnvxf(int *srcptr, dbl_floating_point *dstptr,
124     unsigned int *status)
125 {
126           register int src, dst_exponent;
127           register unsigned int resultp1 = 0, resultp2 = 0;
128 
129           src = *srcptr;
130           /*
131            * set sign bit of result and get magnitude of source
132            */
133           if (src < 0) {
134                     Dbl_setone_sign(resultp1);
135                     Int_negate(src);
136           }
137           else {
138                     Dbl_setzero_sign(resultp1);
139                     /* Check for zero */
140                     if (src == 0) {
141                               Dbl_setzero(resultp1,resultp2);
142                               Dbl_copytoptr(resultp1,resultp2,dstptr);
143                               return(NOEXCEPTION);
144                     }
145           }
146           /*
147            * Generate exponent and normalized mantissa
148            */
149           dst_exponent = 16;    /* initialize for normalization */
150           /*
151            * Check word for most significant bit set.  Returns
152            * a value in dst_exponent indicating the bit position,
153            * between -1 and 30.
154            */
155           Find_ms_one_bit(src,dst_exponent);
156           /*  left justify source, with msb at bit position 1  */
157           if (dst_exponent >= 0) src <<= dst_exponent;
158           else src = 1 << 30;
159           Dbl_set_mantissap1(resultp1, (src >> (DBL_EXP_LENGTH - 1)));
160           Dbl_set_mantissap2(resultp2, (src << (33-DBL_EXP_LENGTH)));
161           Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
162           Dbl_copytoptr(resultp1,resultp2,dstptr);
163           return(NOEXCEPTION);
164 }
165 
166 /*
167  *  Double Fixed-point to Single Floating-point
168  */
169 int
dbl_to_sgl_fcnvxf(dbl_integer * srcptr,sgl_floating_point * dstptr,unsigned int * status)170 dbl_to_sgl_fcnvxf(dbl_integer *srcptr, sgl_floating_point *dstptr,
171     unsigned int *status)
172 {
173           int dst_exponent, srcp1;
174           unsigned int result = 0, srcp2;
175 
176           Dint_copyfromptr(srcptr,srcp1,srcp2);
177           /*
178            * set sign bit of result and get magnitude of source
179            */
180           if (srcp1 < 0) {
181                     Sgl_setone_sign(result);
182                     Dint_negate(srcp1,srcp2);
183           }
184           else {
185                     Sgl_setzero_sign(result);
186                     /* Check for zero */
187                     if (srcp1 == 0 && srcp2 == 0) {
188                               Sgl_setzero(result);
189                               *dstptr = result;
190                               return(NOEXCEPTION);
191                     }
192           }
193           /*
194            * Generate exponent and normalized mantissa
195            */
196           dst_exponent = 16;    /* initialize for normalization */
197           if (srcp1 == 0) {
198                     /*
199                      * Check word for most significant bit set.  Returns
200                      * a value in dst_exponent indicating the bit position,
201                      * between -1 and 30.
202                      */
203                     Find_ms_one_bit(srcp2,dst_exponent);
204                     /*  left justify source, with msb at bit position 1  */
205                     if (dst_exponent >= 0) {
206                               srcp1 = srcp2 << dst_exponent;
207                               srcp2 = 0;
208                     }
209                     else {
210                               srcp1 = srcp2 >> 1;
211                               srcp2 <<= 31;
212                     }
213                     /*
214                      *  since msb set is in second word, need to
215                      *  adjust bit position count
216                      */
217                     dst_exponent += 32;
218           }
219           else {
220                     /*
221                      * Check word for most significant bit set.  Returns
222                      * a value in dst_exponent indicating the bit position,
223                      * between -1 and 30.
224                      *
225                      */
226                     Find_ms_one_bit(srcp1,dst_exponent);
227                     /*  left justify source, with msb at bit position 1  */
228                     if (dst_exponent > 0) {
229                               Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
230                                srcp1);
231                               srcp2 <<= dst_exponent;
232                     }
233                     /*
234                      * If dst_exponent = 0, we don't need to shift anything.
235                      * If dst_exponent = -1, src = - 2**63 so we won't need to
236                      * shift srcp2.
237                      */
238                     else srcp1 >>= -(dst_exponent);
239           }
240           Sgl_set_mantissa(result, (srcp1 >> (SGL_EXP_LENGTH - 1)));
241           Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
242 
243           /* check for inexact */
244           if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
245                     switch (Rounding_mode()) {
246                               case ROUNDPLUS:
247                                         if (Sgl_iszero_sign(result))
248                                                   Sgl_increment(result);
249                                         break;
250                               case ROUNDMINUS:
251                                         if (Sgl_isone_sign(result))
252                                                   Sgl_increment(result);
253                                         break;
254                               case ROUNDNEAREST:
255                                         Sgl_roundnearest_from_dint(srcp1,srcp2,result);
256                     }
257                     if (Is_inexacttrap_enabled()) {
258                               *dstptr = result;
259                               return(INEXACTEXCEPTION);
260                     }
261                     else Set_inexactflag();
262           }
263           *dstptr = result;
264           return(NOEXCEPTION);
265 }
266 
267 /*
268  *  Double Fixed-point to Double Floating-point
269  */
270 int
dbl_to_dbl_fcnvxf(dbl_integer * srcptr,dbl_floating_point * dstptr,unsigned int * status)271 dbl_to_dbl_fcnvxf(dbl_integer *srcptr, dbl_floating_point *dstptr,
272     unsigned int *status)
273 {
274           register int srcp1, dst_exponent;
275           register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
276 
277           Dint_copyfromptr(srcptr,srcp1,srcp2);
278           /*
279            * set sign bit of result and get magnitude of source
280            */
281           if (srcp1 < 0) {
282                     Dbl_setone_sign(resultp1);
283                     Dint_negate(srcp1,srcp2);
284           }
285           else {
286                     Dbl_setzero_sign(resultp1);
287                     /* Check for zero */
288                     if (srcp1 == 0 && srcp2 ==0) {
289                               Dbl_setzero(resultp1,resultp2);
290                               Dbl_copytoptr(resultp1,resultp2,dstptr);
291                               return(NOEXCEPTION);
292                     }
293           }
294           /*
295            * Generate exponent and normalized mantissa
296            */
297           dst_exponent = 16;    /* initialize for normalization */
298           if (srcp1 == 0) {
299                     /*
300                      * Check word for most significant bit set.  Returns
301                      * a value in dst_exponent indicating the bit position,
302                      * between -1 and 30.
303                      */
304                     Find_ms_one_bit(srcp2,dst_exponent);
305                     /*  left justify source, with msb at bit position 1  */
306                     if (dst_exponent >= 0) {
307                               srcp1 = srcp2 << dst_exponent;
308                               srcp2 = 0;
309                     }
310                     else {
311                               srcp1 = srcp2 >> 1;
312                               srcp2 <<= 31;
313                     }
314                     /*
315                      *  since msb set is in second word, need to
316                      *  adjust bit position count
317                      */
318                     dst_exponent += 32;
319           }
320           else {
321                     /*
322                      * Check word for most significant bit set.  Returns
323                      * a value in dst_exponent indicating the bit position,
324                      * between -1 and 30.
325                      */
326                     Find_ms_one_bit(srcp1,dst_exponent);
327                     /*  left justify source, with msb at bit position 1  */
328                     if (dst_exponent > 0) {
329                               Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
330                                srcp1);
331                               srcp2 <<= dst_exponent;
332                     }
333                     /*
334                      * If dst_exponent = 0, we don't need to shift anything.
335                      * If dst_exponent = -1, src = - 2**63 so we won't need to
336                      * shift srcp2.
337                      */
338                     else srcp1 >>= -(dst_exponent);
339           }
340           Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
341           Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
342           Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
343 
344           /* check for inexact */
345           if (Dint_isinexact_to_dbl(srcp2)) {
346                     switch (Rounding_mode()) {
347                               case ROUNDPLUS:
348                                         if (Dbl_iszero_sign(resultp1)) {
349                                                   Dbl_increment(resultp1,resultp2);
350                                         }
351                                         break;
352                               case ROUNDMINUS:
353                                         if (Dbl_isone_sign(resultp1)) {
354                                                   Dbl_increment(resultp1,resultp2);
355                                         }
356                                         break;
357                               case ROUNDNEAREST:
358                                         Dbl_roundnearest_from_dint(srcp2,resultp1,
359                                         resultp2);
360                     }
361                     if (Is_inexacttrap_enabled()) {
362                               Dbl_copytoptr(resultp1,resultp2,dstptr);
363                               return(INEXACTEXCEPTION);
364                     }
365                     else Set_inexactflag();
366           }
367           Dbl_copytoptr(resultp1,resultp2,dstptr);
368           return(NOEXCEPTION);
369 }
370