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