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