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 */
55int
56sgl_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 */
122int
123sgl_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 */
169int
170dbl_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 */
270int
271dbl_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