xref: /linux/arch/parisc/math-emu/fcnvuf.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3*1da177e4SLinus Torvalds  *
4*1da177e4SLinus Torvalds  * Floating-point emulation code
5*1da177e4SLinus Torvalds  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6*1da177e4SLinus Torvalds  *
7*1da177e4SLinus Torvalds  *    This program is free software; you can redistribute it and/or modify
8*1da177e4SLinus Torvalds  *    it under the terms of the GNU General Public License as published by
9*1da177e4SLinus Torvalds  *    the Free Software Foundation; either version 2, or (at your option)
10*1da177e4SLinus Torvalds  *    any later version.
11*1da177e4SLinus Torvalds  *
12*1da177e4SLinus Torvalds  *    This program is distributed in the hope that it will be useful,
13*1da177e4SLinus Torvalds  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*1da177e4SLinus Torvalds  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*1da177e4SLinus Torvalds  *    GNU General Public License for more details.
16*1da177e4SLinus Torvalds  *
17*1da177e4SLinus Torvalds  *    You should have received a copy of the GNU General Public License
18*1da177e4SLinus Torvalds  *    along with this program; if not, write to the Free Software
19*1da177e4SLinus Torvalds  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20*1da177e4SLinus Torvalds  */
21*1da177e4SLinus Torvalds /*
22*1da177e4SLinus Torvalds  * BEGIN_DESC
23*1da177e4SLinus Torvalds  *
24*1da177e4SLinus Torvalds  *  File:
25*1da177e4SLinus Torvalds  *	@(#)	pa/spmath/fcnvuf.c		$Revision: 1.1 $
26*1da177e4SLinus Torvalds  *
27*1da177e4SLinus Torvalds  *  Purpose:
28*1da177e4SLinus Torvalds  *	Fixed point to Floating-point Converts
29*1da177e4SLinus Torvalds  *
30*1da177e4SLinus Torvalds  *  External Interfaces:
31*1da177e4SLinus Torvalds  *	dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
32*1da177e4SLinus Torvalds  *	dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
33*1da177e4SLinus Torvalds  *	sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
34*1da177e4SLinus Torvalds  *	sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
35*1da177e4SLinus Torvalds  *
36*1da177e4SLinus Torvalds  *  Internal Interfaces:
37*1da177e4SLinus Torvalds  *
38*1da177e4SLinus Torvalds  *  Theory:
39*1da177e4SLinus Torvalds  *	<<please update with a overview of the operation of this file>>
40*1da177e4SLinus Torvalds  *
41*1da177e4SLinus Torvalds  * END_DESC
42*1da177e4SLinus Torvalds */
43*1da177e4SLinus Torvalds 
44*1da177e4SLinus Torvalds 
45*1da177e4SLinus Torvalds #include "float.h"
46*1da177e4SLinus Torvalds #include "sgl_float.h"
47*1da177e4SLinus Torvalds #include "dbl_float.h"
48*1da177e4SLinus Torvalds #include "cnv_float.h"
49*1da177e4SLinus Torvalds 
50*1da177e4SLinus Torvalds /************************************************************************
51*1da177e4SLinus Torvalds  *  Fixed point to Floating-point Converts				*
52*1da177e4SLinus Torvalds  ************************************************************************/
53*1da177e4SLinus Torvalds 
54*1da177e4SLinus Torvalds /*
55*1da177e4SLinus Torvalds  *  Convert Single Unsigned Fixed to Single Floating-point format
56*1da177e4SLinus Torvalds  */
57*1da177e4SLinus Torvalds 
58*1da177e4SLinus Torvalds int
59*1da177e4SLinus Torvalds sgl_to_sgl_fcnvuf(
60*1da177e4SLinus Torvalds 			unsigned int *srcptr,
61*1da177e4SLinus Torvalds 			unsigned int *nullptr,
62*1da177e4SLinus Torvalds 			sgl_floating_point *dstptr,
63*1da177e4SLinus Torvalds 			unsigned int *status)
64*1da177e4SLinus Torvalds {
65*1da177e4SLinus Torvalds 	register unsigned int src, result = 0;
66*1da177e4SLinus Torvalds 	register int dst_exponent;
67*1da177e4SLinus Torvalds 
68*1da177e4SLinus Torvalds 	src = *srcptr;
69*1da177e4SLinus Torvalds 
70*1da177e4SLinus Torvalds 	/* Check for zero */
71*1da177e4SLinus Torvalds 	if (src == 0) {
72*1da177e4SLinus Torvalds 	       	Sgl_setzero(result);
73*1da177e4SLinus Torvalds 		*dstptr = result;
74*1da177e4SLinus Torvalds 	       	return(NOEXCEPTION);
75*1da177e4SLinus Torvalds 	}
76*1da177e4SLinus Torvalds 	/*
77*1da177e4SLinus Torvalds 	 * Generate exponent and normalized mantissa
78*1da177e4SLinus Torvalds 	 */
79*1da177e4SLinus Torvalds 	dst_exponent = 16;    /* initialize for normalization */
80*1da177e4SLinus Torvalds 	/*
81*1da177e4SLinus Torvalds 	 * Check word for most significant bit set.  Returns
82*1da177e4SLinus Torvalds 	 * a value in dst_exponent indicating the bit position,
83*1da177e4SLinus Torvalds 	 * between -1 and 30.
84*1da177e4SLinus Torvalds 	 */
85*1da177e4SLinus Torvalds 	Find_ms_one_bit(src,dst_exponent);
86*1da177e4SLinus Torvalds 	/*  left justify source, with msb at bit position 0  */
87*1da177e4SLinus Torvalds 	src <<= dst_exponent+1;
88*1da177e4SLinus Torvalds 	Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH);
89*1da177e4SLinus Torvalds 	Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
90*1da177e4SLinus Torvalds 
91*1da177e4SLinus Torvalds 	/* check for inexact */
92*1da177e4SLinus Torvalds 	if (Suint_isinexact_to_sgl(src)) {
93*1da177e4SLinus Torvalds 		switch (Rounding_mode()) {
94*1da177e4SLinus Torvalds 			case ROUNDPLUS:
95*1da177e4SLinus Torvalds 				Sgl_increment(result);
96*1da177e4SLinus Torvalds 				break;
97*1da177e4SLinus Torvalds 			case ROUNDMINUS: /* never negative */
98*1da177e4SLinus Torvalds 				break;
99*1da177e4SLinus Torvalds 			case ROUNDNEAREST:
100*1da177e4SLinus Torvalds 				Sgl_roundnearest_from_suint(src,result);
101*1da177e4SLinus Torvalds 				break;
102*1da177e4SLinus Torvalds 		}
103*1da177e4SLinus Torvalds 		if (Is_inexacttrap_enabled()) {
104*1da177e4SLinus Torvalds 			*dstptr = result;
105*1da177e4SLinus Torvalds 			return(INEXACTEXCEPTION);
106*1da177e4SLinus Torvalds 		}
107*1da177e4SLinus Torvalds 		else Set_inexactflag();
108*1da177e4SLinus Torvalds 	}
109*1da177e4SLinus Torvalds 	*dstptr = result;
110*1da177e4SLinus Torvalds 	return(NOEXCEPTION);
111*1da177e4SLinus Torvalds }
112*1da177e4SLinus Torvalds 
113*1da177e4SLinus Torvalds /*
114*1da177e4SLinus Torvalds  *  Single Unsigned Fixed to Double Floating-point
115*1da177e4SLinus Torvalds  */
116*1da177e4SLinus Torvalds 
117*1da177e4SLinus Torvalds int
118*1da177e4SLinus Torvalds sgl_to_dbl_fcnvuf(
119*1da177e4SLinus Torvalds 			unsigned int *srcptr,
120*1da177e4SLinus Torvalds 			unsigned int *nullptr,
121*1da177e4SLinus Torvalds 			dbl_floating_point *dstptr,
122*1da177e4SLinus Torvalds 			unsigned int *status)
123*1da177e4SLinus Torvalds {
124*1da177e4SLinus Torvalds 	register int dst_exponent;
125*1da177e4SLinus Torvalds 	register unsigned int src, resultp1 = 0, resultp2 = 0;
126*1da177e4SLinus Torvalds 
127*1da177e4SLinus Torvalds 	src = *srcptr;
128*1da177e4SLinus Torvalds 
129*1da177e4SLinus Torvalds 	/* Check for zero */
130*1da177e4SLinus Torvalds 	if (src == 0) {
131*1da177e4SLinus Torvalds 	       	Dbl_setzero(resultp1,resultp2);
132*1da177e4SLinus Torvalds 	       	Dbl_copytoptr(resultp1,resultp2,dstptr);
133*1da177e4SLinus Torvalds 	       	return(NOEXCEPTION);
134*1da177e4SLinus Torvalds 	}
135*1da177e4SLinus Torvalds 	/*
136*1da177e4SLinus Torvalds 	 * Generate exponent and normalized mantissa
137*1da177e4SLinus Torvalds 	 */
138*1da177e4SLinus Torvalds 	dst_exponent = 16;    /* initialize for normalization */
139*1da177e4SLinus Torvalds 	/*
140*1da177e4SLinus Torvalds 	 * Check word for most significant bit set.  Returns
141*1da177e4SLinus Torvalds 	 * a value in dst_exponent indicating the bit position,
142*1da177e4SLinus Torvalds 	 * between -1 and 30.
143*1da177e4SLinus Torvalds 	 */
144*1da177e4SLinus Torvalds 	Find_ms_one_bit(src,dst_exponent);
145*1da177e4SLinus Torvalds 	/*  left justify source, with msb at bit position 0  */
146*1da177e4SLinus Torvalds 	src <<= dst_exponent+1;
147*1da177e4SLinus Torvalds 	Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH);
148*1da177e4SLinus Torvalds 	Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH));
149*1da177e4SLinus Torvalds 	Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
150*1da177e4SLinus Torvalds 	Dbl_copytoptr(resultp1,resultp2,dstptr);
151*1da177e4SLinus Torvalds 	return(NOEXCEPTION);
152*1da177e4SLinus Torvalds }
153*1da177e4SLinus Torvalds 
154*1da177e4SLinus Torvalds /*
155*1da177e4SLinus Torvalds  *  Double Unsigned Fixed to Single Floating-point
156*1da177e4SLinus Torvalds  */
157*1da177e4SLinus Torvalds 
158*1da177e4SLinus Torvalds int
159*1da177e4SLinus Torvalds dbl_to_sgl_fcnvuf(
160*1da177e4SLinus Torvalds 			dbl_unsigned *srcptr,
161*1da177e4SLinus Torvalds 			unsigned int *nullptr,
162*1da177e4SLinus Torvalds 			sgl_floating_point *dstptr,
163*1da177e4SLinus Torvalds 			unsigned int *status)
164*1da177e4SLinus Torvalds {
165*1da177e4SLinus Torvalds 	int dst_exponent;
166*1da177e4SLinus Torvalds 	unsigned int srcp1, srcp2, result = 0;
167*1da177e4SLinus Torvalds 
168*1da177e4SLinus Torvalds 	Duint_copyfromptr(srcptr,srcp1,srcp2);
169*1da177e4SLinus Torvalds 
170*1da177e4SLinus Torvalds 	/* Check for zero */
171*1da177e4SLinus Torvalds 	if (srcp1 == 0 && srcp2 == 0) {
172*1da177e4SLinus Torvalds 	       	Sgl_setzero(result);
173*1da177e4SLinus Torvalds 	       	*dstptr = result;
174*1da177e4SLinus Torvalds 	       	return(NOEXCEPTION);
175*1da177e4SLinus Torvalds 	}
176*1da177e4SLinus Torvalds 	/*
177*1da177e4SLinus Torvalds 	 * Generate exponent and normalized mantissa
178*1da177e4SLinus Torvalds 	 */
179*1da177e4SLinus Torvalds 	dst_exponent = 16;    /* initialize for normalization */
180*1da177e4SLinus Torvalds 	if (srcp1 == 0) {
181*1da177e4SLinus Torvalds 		/*
182*1da177e4SLinus Torvalds 		 * Check word for most significant bit set.  Returns
183*1da177e4SLinus Torvalds 		 * a value in dst_exponent indicating the bit position,
184*1da177e4SLinus Torvalds 		 * between -1 and 30.
185*1da177e4SLinus Torvalds 		 */
186*1da177e4SLinus Torvalds 		Find_ms_one_bit(srcp2,dst_exponent);
187*1da177e4SLinus Torvalds 		/*  left justify source, with msb at bit position 0  */
188*1da177e4SLinus Torvalds 		srcp1 = srcp2 << dst_exponent+1;
189*1da177e4SLinus Torvalds 		srcp2 = 0;
190*1da177e4SLinus Torvalds 		/*
191*1da177e4SLinus Torvalds 		 *  since msb set is in second word, need to
192*1da177e4SLinus Torvalds 		 *  adjust bit position count
193*1da177e4SLinus Torvalds 		 */
194*1da177e4SLinus Torvalds 		dst_exponent += 32;
195*1da177e4SLinus Torvalds 	}
196*1da177e4SLinus Torvalds 	else {
197*1da177e4SLinus Torvalds 		/*
198*1da177e4SLinus Torvalds 		 * Check word for most significant bit set.  Returns
199*1da177e4SLinus Torvalds 		 * a value in dst_exponent indicating the bit position,
200*1da177e4SLinus Torvalds 		 * between -1 and 30.
201*1da177e4SLinus Torvalds 		 *
202*1da177e4SLinus Torvalds 		 */
203*1da177e4SLinus Torvalds 		Find_ms_one_bit(srcp1,dst_exponent);
204*1da177e4SLinus Torvalds 		/*  left justify source, with msb at bit position 0  */
205*1da177e4SLinus Torvalds 		if (dst_exponent >= 0) {
206*1da177e4SLinus Torvalds 			Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
207*1da177e4SLinus Torvalds 			 srcp1);
208*1da177e4SLinus Torvalds 			srcp2 <<= dst_exponent+1;
209*1da177e4SLinus Torvalds 		}
210*1da177e4SLinus Torvalds 	}
211*1da177e4SLinus Torvalds 	Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH);
212*1da177e4SLinus Torvalds 	Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
213*1da177e4SLinus Torvalds 
214*1da177e4SLinus Torvalds 	/* check for inexact */
215*1da177e4SLinus Torvalds 	if (Duint_isinexact_to_sgl(srcp1,srcp2)) {
216*1da177e4SLinus Torvalds 		switch (Rounding_mode()) {
217*1da177e4SLinus Torvalds 			case ROUNDPLUS:
218*1da177e4SLinus Torvalds 				Sgl_increment(result);
219*1da177e4SLinus Torvalds 				break;
220*1da177e4SLinus Torvalds 			case ROUNDMINUS: /* never negative */
221*1da177e4SLinus Torvalds 				break;
222*1da177e4SLinus Torvalds 			case ROUNDNEAREST:
223*1da177e4SLinus Torvalds 				Sgl_roundnearest_from_duint(srcp1,srcp2,result);
224*1da177e4SLinus Torvalds 				break;
225*1da177e4SLinus Torvalds 		}
226*1da177e4SLinus Torvalds 		if (Is_inexacttrap_enabled()) {
227*1da177e4SLinus Torvalds 			*dstptr = result;
228*1da177e4SLinus Torvalds 			return(INEXACTEXCEPTION);
229*1da177e4SLinus Torvalds 		}
230*1da177e4SLinus Torvalds 		else Set_inexactflag();
231*1da177e4SLinus Torvalds 	}
232*1da177e4SLinus Torvalds 	*dstptr = result;
233*1da177e4SLinus Torvalds 	return(NOEXCEPTION);
234*1da177e4SLinus Torvalds }
235*1da177e4SLinus Torvalds 
236*1da177e4SLinus Torvalds /*
237*1da177e4SLinus Torvalds  *  Double Unsigned Fixed to Double Floating-point
238*1da177e4SLinus Torvalds  */
239*1da177e4SLinus Torvalds 
240*1da177e4SLinus Torvalds int
241*1da177e4SLinus Torvalds dbl_to_dbl_fcnvuf(
242*1da177e4SLinus Torvalds 		    dbl_unsigned *srcptr,
243*1da177e4SLinus Torvalds 		    unsigned int *nullptr,
244*1da177e4SLinus Torvalds 		    dbl_floating_point *dstptr,
245*1da177e4SLinus Torvalds 		    unsigned int *status)
246*1da177e4SLinus Torvalds {
247*1da177e4SLinus Torvalds 	register int dst_exponent;
248*1da177e4SLinus Torvalds 	register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0;
249*1da177e4SLinus Torvalds 
250*1da177e4SLinus Torvalds 	Duint_copyfromptr(srcptr,srcp1,srcp2);
251*1da177e4SLinus Torvalds 
252*1da177e4SLinus Torvalds 	/* Check for zero */
253*1da177e4SLinus Torvalds 	if (srcp1 == 0 && srcp2 ==0) {
254*1da177e4SLinus Torvalds 	       	Dbl_setzero(resultp1,resultp2);
255*1da177e4SLinus Torvalds 	       	Dbl_copytoptr(resultp1,resultp2,dstptr);
256*1da177e4SLinus Torvalds 	       	return(NOEXCEPTION);
257*1da177e4SLinus Torvalds 	}
258*1da177e4SLinus Torvalds 	/*
259*1da177e4SLinus Torvalds 	 * Generate exponent and normalized mantissa
260*1da177e4SLinus Torvalds 	 */
261*1da177e4SLinus Torvalds 	dst_exponent = 16;    /* initialize for normalization */
262*1da177e4SLinus Torvalds 	if (srcp1 == 0) {
263*1da177e4SLinus Torvalds 		/*
264*1da177e4SLinus Torvalds 		 * Check word for most significant bit set.  Returns
265*1da177e4SLinus Torvalds 		 * a value in dst_exponent indicating the bit position,
266*1da177e4SLinus Torvalds 		 * between -1 and 30.
267*1da177e4SLinus Torvalds 		 */
268*1da177e4SLinus Torvalds 		Find_ms_one_bit(srcp2,dst_exponent);
269*1da177e4SLinus Torvalds 		/*  left justify source, with msb at bit position 0  */
270*1da177e4SLinus Torvalds 		srcp1 = srcp2 << dst_exponent+1;
271*1da177e4SLinus Torvalds 		srcp2 = 0;
272*1da177e4SLinus Torvalds 		/*
273*1da177e4SLinus Torvalds 		 *  since msb set is in second word, need to
274*1da177e4SLinus Torvalds 		 *  adjust bit position count
275*1da177e4SLinus Torvalds 		 */
276*1da177e4SLinus Torvalds 		dst_exponent += 32;
277*1da177e4SLinus Torvalds 	}
278*1da177e4SLinus Torvalds 	else {
279*1da177e4SLinus Torvalds 		/*
280*1da177e4SLinus Torvalds 		 * Check word for most significant bit set.  Returns
281*1da177e4SLinus Torvalds 		 * a value in dst_exponent indicating the bit position,
282*1da177e4SLinus Torvalds 		 * between -1 and 30.
283*1da177e4SLinus Torvalds 		 */
284*1da177e4SLinus Torvalds 		Find_ms_one_bit(srcp1,dst_exponent);
285*1da177e4SLinus Torvalds 		/*  left justify source, with msb at bit position 0  */
286*1da177e4SLinus Torvalds 		if (dst_exponent >= 0) {
287*1da177e4SLinus Torvalds 			Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
288*1da177e4SLinus Torvalds 			 srcp1);
289*1da177e4SLinus Torvalds 			srcp2 <<= dst_exponent+1;
290*1da177e4SLinus Torvalds 		}
291*1da177e4SLinus Torvalds 	}
292*1da177e4SLinus Torvalds 	Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH);
293*1da177e4SLinus Torvalds 	Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2);
294*1da177e4SLinus Torvalds 	Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
295*1da177e4SLinus Torvalds 
296*1da177e4SLinus Torvalds 	/* check for inexact */
297*1da177e4SLinus Torvalds 	if (Duint_isinexact_to_dbl(srcp2)) {
298*1da177e4SLinus Torvalds 		switch (Rounding_mode()) {
299*1da177e4SLinus Torvalds 			case ROUNDPLUS:
300*1da177e4SLinus Torvalds 				Dbl_increment(resultp1,resultp2);
301*1da177e4SLinus Torvalds 				break;
302*1da177e4SLinus Torvalds 			case ROUNDMINUS: /* never negative */
303*1da177e4SLinus Torvalds 				break;
304*1da177e4SLinus Torvalds 			case ROUNDNEAREST:
305*1da177e4SLinus Torvalds 				Dbl_roundnearest_from_duint(srcp2,resultp1,
306*1da177e4SLinus Torvalds 				resultp2);
307*1da177e4SLinus Torvalds 				break;
308*1da177e4SLinus Torvalds 		}
309*1da177e4SLinus Torvalds 		if (Is_inexacttrap_enabled()) {
310*1da177e4SLinus Torvalds 			Dbl_copytoptr(resultp1,resultp2,dstptr);
311*1da177e4SLinus Torvalds 			return(INEXACTEXCEPTION);
312*1da177e4SLinus Torvalds 		}
313*1da177e4SLinus Torvalds 		else Set_inexactflag();
314*1da177e4SLinus Torvalds 	}
315*1da177e4SLinus Torvalds 	Dbl_copytoptr(resultp1,resultp2,dstptr);
316*1da177e4SLinus Torvalds 	return(NOEXCEPTION);
317*1da177e4SLinus Torvalds }
318*1da177e4SLinus Torvalds 
319