xref: /netbsd/sys/arch/hppa/spmath/fcnvxf.c (revision c4a72b64)
1 /*	$NetBSD: fcnvxf.c,v 1.1 2002/06/05 01:04:25 fredette 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 "../spmath/float.h"
45 #include "../spmath/sgl_float.h"
46 #include "../spmath/dbl_float.h"
47 #include "../spmath/cnv_float.h"
48 
49 /*
50  *  Convert single fixed-point to single floating-point format
51  */
52 int
53 sgl_to_sgl_fcnvxf(srcptr,dstptr,status)
54 
55 int *srcptr;
56 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
123 sgl_to_dbl_fcnvxf(srcptr,dstptr,status)
124 
125 int *srcptr;
126 dbl_floating_point *dstptr;
127 unsigned int *status;
128 {
129 	register int src, dst_exponent;
130 	register unsigned int resultp1 = 0, resultp2 = 0;
131 
132 	src = *srcptr;
133 	/*
134 	 * set sign bit of result and get magnitude of source
135 	 */
136 	if (src < 0) {
137 		Dbl_setone_sign(resultp1);
138 		Int_negate(src);
139 	}
140 	else {
141 		Dbl_setzero_sign(resultp1);
142 		/* Check for zero */
143 		if (src == 0) {
144 			Dbl_setzero(resultp1,resultp2);
145 			Dbl_copytoptr(resultp1,resultp2,dstptr);
146 			return(NOEXCEPTION);
147 		}
148 	}
149 	/*
150 	 * Generate exponent and normalized mantissa
151 	 */
152 	dst_exponent = 16;    /* initialize for normalization */
153 	/*
154 	 * Check word for most significant bit set.  Returns
155 	 * a value in dst_exponent indicating the bit position,
156 	 * between -1 and 30.
157 	 */
158 	Find_ms_one_bit(src,dst_exponent);
159 	/*  left justify source, with msb at bit position 1  */
160 	if (dst_exponent >= 0) src <<= dst_exponent;
161 	else src = 1 << 30;
162 	Dbl_set_mantissap1(resultp1, (src >> (DBL_EXP_LENGTH - 1)));
163 	Dbl_set_mantissap2(resultp2, (src << (33-DBL_EXP_LENGTH)));
164 	Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
165 	Dbl_copytoptr(resultp1,resultp2,dstptr);
166 	return(NOEXCEPTION);
167 }
168 
169 /*
170  *  Double Fixed-point to Single Floating-point
171  */
172 int
173 dbl_to_sgl_fcnvxf(srcptr,dstptr,status)
174 
175 dbl_integer *srcptr;
176 sgl_floating_point *dstptr;
177 unsigned int *status;
178 {
179 	int dst_exponent, srcp1;
180 	unsigned int result = 0, srcp2;
181 
182 	Dint_copyfromptr(srcptr,srcp1,srcp2);
183 	/*
184 	 * set sign bit of result and get magnitude of source
185 	 */
186 	if (srcp1 < 0) {
187 		Sgl_setone_sign(result);
188 		Dint_negate(srcp1,srcp2);
189 	}
190 	else {
191 		Sgl_setzero_sign(result);
192 		/* Check for zero */
193 		if (srcp1 == 0 && srcp2 == 0) {
194 			Sgl_setzero(result);
195 			*dstptr = result;
196 			return(NOEXCEPTION);
197 		}
198 	}
199 	/*
200 	 * Generate exponent and normalized mantissa
201 	 */
202 	dst_exponent = 16;    /* initialize for normalization */
203 	if (srcp1 == 0) {
204 		/*
205 		 * Check word for most significant bit set.  Returns
206 		 * a value in dst_exponent indicating the bit position,
207 		 * between -1 and 30.
208 		 */
209 		Find_ms_one_bit(srcp2,dst_exponent);
210 		/*  left justify source, with msb at bit position 1  */
211 		if (dst_exponent >= 0) {
212 			srcp1 = srcp2 << dst_exponent;
213 			srcp2 = 0;
214 		}
215 		else {
216 			srcp1 = srcp2 >> 1;
217 			srcp2 <<= 31;
218 		}
219 		/*
220 		 *  since msb set is in second word, need to
221 		 *  adjust bit position count
222 		 */
223 		dst_exponent += 32;
224 	}
225 	else {
226 		/*
227 		 * Check word for most significant bit set.  Returns
228 		 * a value in dst_exponent indicating the bit position,
229 		 * between -1 and 30.
230 		 *
231 		 */
232 		Find_ms_one_bit(srcp1,dst_exponent);
233 		/*  left justify source, with msb at bit position 1  */
234 		if (dst_exponent > 0) {
235 			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
236 			 srcp1);
237 			srcp2 <<= dst_exponent;
238 		}
239 		/*
240 		 * If dst_exponent = 0, we don't need to shift anything.
241 		 * If dst_exponent = -1, src = - 2**63 so we won't need to
242 		 * shift srcp2.
243 		 */
244 		else srcp1 >>= -(dst_exponent);
245 	}
246 	Sgl_set_mantissa(result, (srcp1 >> (SGL_EXP_LENGTH - 1)));
247 	Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
248 
249 	/* check for inexact */
250 	if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
251 		switch (Rounding_mode()) {
252 			case ROUNDPLUS:
253 				if (Sgl_iszero_sign(result))
254 					Sgl_increment(result);
255 				break;
256 			case ROUNDMINUS:
257 				if (Sgl_isone_sign(result))
258 					Sgl_increment(result);
259 				break;
260 			case ROUNDNEAREST:
261 				Sgl_roundnearest_from_dint(srcp1,srcp2,result);
262 		}
263 		if (Is_inexacttrap_enabled()) {
264 			*dstptr = result;
265 			return(INEXACTEXCEPTION);
266 		}
267 		else Set_inexactflag();
268 	}
269 	*dstptr = result;
270 	return(NOEXCEPTION);
271 }
272 
273 /*
274  *  Double Fixed-point to Double Floating-point
275  */
276 int
277 dbl_to_dbl_fcnvxf(srcptr,dstptr,status)
278 
279 dbl_integer *srcptr;
280 dbl_floating_point *dstptr;
281 unsigned int *status;
282 {
283 	register int srcp1, dst_exponent;
284 	register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
285 
286 	Dint_copyfromptr(srcptr,srcp1,srcp2);
287 	/*
288 	 * set sign bit of result and get magnitude of source
289 	 */
290 	if (srcp1 < 0) {
291 		Dbl_setone_sign(resultp1);
292 		Dint_negate(srcp1,srcp2);
293 	}
294 	else {
295 		Dbl_setzero_sign(resultp1);
296 		/* Check for zero */
297 		if (srcp1 == 0 && srcp2 ==0) {
298 			Dbl_setzero(resultp1,resultp2);
299 			Dbl_copytoptr(resultp1,resultp2,dstptr);
300 			return(NOEXCEPTION);
301 		}
302 	}
303 	/*
304 	 * Generate exponent and normalized mantissa
305 	 */
306 	dst_exponent = 16;    /* initialize for normalization */
307 	if (srcp1 == 0) {
308 		/*
309 		 * Check word for most significant bit set.  Returns
310 		 * a value in dst_exponent indicating the bit position,
311 		 * between -1 and 30.
312 		 */
313 		Find_ms_one_bit(srcp2,dst_exponent);
314 		/*  left justify source, with msb at bit position 1  */
315 		if (dst_exponent >= 0) {
316 			srcp1 = srcp2 << dst_exponent;
317 			srcp2 = 0;
318 		}
319 		else {
320 			srcp1 = srcp2 >> 1;
321 			srcp2 <<= 31;
322 		}
323 		/*
324 		 *  since msb set is in second word, need to
325 		 *  adjust bit position count
326 		 */
327 		dst_exponent += 32;
328 	}
329 	else {
330 		/*
331 		 * Check word for most significant bit set.  Returns
332 		 * a value in dst_exponent indicating the bit position,
333 		 * between -1 and 30.
334 		 */
335 		Find_ms_one_bit(srcp1,dst_exponent);
336 		/*  left justify source, with msb at bit position 1  */
337 		if (dst_exponent > 0) {
338 			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
339 			 srcp1);
340 			srcp2 <<= dst_exponent;
341 		}
342 		/*
343 		 * If dst_exponent = 0, we don't need to shift anything.
344 		 * If dst_exponent = -1, src = - 2**63 so we won't need to
345 		 * shift srcp2.
346 		 */
347 		else srcp1 >>= -(dst_exponent);
348 	}
349 	Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
350 	Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
351 	Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
352 
353 	/* check for inexact */
354 	if (Dint_isinexact_to_dbl(srcp2)) {
355 		switch (Rounding_mode()) {
356 			case ROUNDPLUS:
357 				if (Dbl_iszero_sign(resultp1)) {
358 					Dbl_increment(resultp1,resultp2);
359 				}
360 				break;
361 			case ROUNDMINUS:
362 				if (Dbl_isone_sign(resultp1)) {
363 					Dbl_increment(resultp1,resultp2);
364 				}
365 				break;
366 			case ROUNDNEAREST:
367 				Dbl_roundnearest_from_dint(srcp2,resultp1,
368 				resultp2);
369 		}
370 		if (Is_inexacttrap_enabled()) {
371 			Dbl_copytoptr(resultp1,resultp2,dstptr);
372 			return(INEXACTEXCEPTION);
373 		}
374 		else Set_inexactflag();
375 	}
376 	Dbl_copytoptr(resultp1,resultp2,dstptr);
377 	return(NOEXCEPTION);
378 }
379