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