1/*
2 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
3 *
4 * Floating-point emulation code
5 *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
6 *
7 *    This program is free software; you can redistribute it and/or modify
8 *    it under the terms of the GNU General Public License as published by
9 *    the Free Software Foundation; either version 2, or (at your option)
10 *    any later version.
11 *
12 *    This program is distributed in the hope that it will be useful,
13 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *    GNU General Public License for more details.
16 *
17 *    You should have received a copy of the GNU General Public License
18 *    along with this program; if not, write to the Free Software
19 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21/*
22 * BEGIN_DESC
23 *
24 *  File:
25 *	@(#)	pa/spmath/fcnvff.c		$Revision: 1.1 $
26 *
27 *  Purpose:
28 *	Single Floating-point to Double Floating-point
29 *	Double Floating-point to Single Floating-point
30 *
31 *  External Interfaces:
32 *	dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status)
33 *	sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status)
34 *
35 *  Internal Interfaces:
36 *
37 *  Theory:
38 *	<<please update with a overview of the operation of this file>>
39 *
40 * END_DESC
41*/
42
43
44#include "float.h"
45#include "sgl_float.h"
46#include "dbl_float.h"
47#include "cnv_float.h"
48
49/*
50 *  Single Floating-point to Double Floating-point
51 */
52/*ARGSUSED*/
53int
54sgl_to_dbl_fcnvff(
55	    sgl_floating_point *srcptr,
56	    unsigned int *nullptr,
57	    dbl_floating_point *dstptr,
58	    unsigned int *status)
59{
60	register unsigned int src, resultp1, resultp2;
61	register int src_exponent;
62
63	src = *srcptr;
64	src_exponent = Sgl_exponent(src);
65	Dbl_allp1(resultp1) = Sgl_all(src);  /* set sign of result */
66	/*
67 	 * Test for NaN or infinity
68 	 */
69	if (src_exponent == SGL_INFINITY_EXPONENT) {
70		/*
71		 * determine if NaN or infinity
72		 */
73		if (Sgl_iszero_mantissa(src)) {
74			/*
75			 * is infinity; want to return double infinity
76			 */
77			Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
78			Dbl_copytoptr(resultp1,resultp2,dstptr);
79			return(NOEXCEPTION);
80		}
81		else {
82			/*
83			 * is NaN; signaling or quiet?
84			 */
85			if (Sgl_isone_signaling(src)) {
86				/* trap if INVALIDTRAP enabled */
87				if (Is_invalidtrap_enabled())
88					return(INVALIDEXCEPTION);
89				/* make NaN quiet */
90				else {
91					Set_invalidflag();
92					Sgl_set_quiet(src);
93				}
94			}
95			/*
96			 * NaN is quiet, return as double NaN
97			 */
98			Dbl_setinfinity_exponent(resultp1);
99			Sgl_to_dbl_mantissa(src,resultp1,resultp2);
100			Dbl_copytoptr(resultp1,resultp2,dstptr);
101			return(NOEXCEPTION);
102		}
103	}
104	/*
105 	 * Test for zero or denormalized
106 	 */
107	if (src_exponent == 0) {
108		/*
109		 * determine if zero or denormalized
110		 */
111		if (Sgl_isnotzero_mantissa(src)) {
112			/*
113			 * is denormalized; want to normalize
114			 */
115			Sgl_clear_signexponent(src);
116			Sgl_leftshiftby1(src);
117			Sgl_normalize(src,src_exponent);
118			Sgl_to_dbl_exponent(src_exponent,resultp1);
119			Sgl_to_dbl_mantissa(src,resultp1,resultp2);
120		}
121		else {
122			Dbl_setzero_exponentmantissa(resultp1,resultp2);
123		}
124		Dbl_copytoptr(resultp1,resultp2,dstptr);
125		return(NOEXCEPTION);
126	}
127	/*
128	 * No special cases, just complete the conversion
129	 */
130	Sgl_to_dbl_exponent(src_exponent, resultp1);
131	Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
132	Dbl_copytoptr(resultp1,resultp2,dstptr);
133	return(NOEXCEPTION);
134}
135
136/*
137 *  Double Floating-point to Single Floating-point
138 */
139/*ARGSUSED*/
140int
141dbl_to_sgl_fcnvff(
142		    dbl_floating_point *srcptr,
143		    unsigned int *nullptr,
144		    sgl_floating_point *dstptr,
145		    unsigned int *status)
146{
147        register unsigned int srcp1, srcp2, result;
148        register int src_exponent, dest_exponent, dest_mantissa;
149        register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
150	register boolean lsb_odd = FALSE;
151	boolean is_tiny;
152
153	Dbl_copyfromptr(srcptr,srcp1,srcp2);
154        src_exponent = Dbl_exponent(srcp1);
155	Sgl_all(result) = Dbl_allp1(srcp1);  /* set sign of result */
156        /*
157         * Test for NaN or infinity
158         */
159        if (src_exponent == DBL_INFINITY_EXPONENT) {
160                /*
161                 * determine if NaN or infinity
162                 */
163                if (Dbl_iszero_mantissa(srcp1,srcp2)) {
164                        /*
165                         * is infinity; want to return single infinity
166                         */
167                        Sgl_setinfinity_exponentmantissa(result);
168                        *dstptr = result;
169                        return(NOEXCEPTION);
170                }
171                /*
172                 * is NaN; signaling or quiet?
173                 */
174                if (Dbl_isone_signaling(srcp1)) {
175                        /* trap if INVALIDTRAP enabled */
176                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
177                        else {
178				Set_invalidflag();
179                        	/* make NaN quiet */
180                        	Dbl_set_quiet(srcp1);
181			}
182                }
183                /*
184                 * NaN is quiet, return as single NaN
185                 */
186                Sgl_setinfinity_exponent(result);
187		Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
188		if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
189                *dstptr = result;
190                return(NOEXCEPTION);
191        }
192        /*
193         * Generate result
194         */
195        Dbl_to_sgl_exponent(src_exponent,dest_exponent);
196	if (dest_exponent > 0) {
197        	Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit,
198		stickybit,lsb_odd);
199	}
200	else {
201		if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
202			Sgl_setzero_exponentmantissa(result);
203			*dstptr = result;
204			return(NOEXCEPTION);
205		}
206                if (Is_underflowtrap_enabled()) {
207			Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
208			guardbit,stickybit,lsb_odd);
209                }
210		else {
211			/* compute result, determine inexact info,
212			 * and set Underflowflag if appropriate
213			 */
214			Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
215			dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
216			is_tiny);
217		}
218	}
219        /*
220         * Now round result if not exact
221         */
222        if (inexact) {
223                switch (Rounding_mode()) {
224                        case ROUNDPLUS:
225                                if (Sgl_iszero_sign(result)) dest_mantissa++;
226                                break;
227                        case ROUNDMINUS:
228                                if (Sgl_isone_sign(result)) dest_mantissa++;
229                                break;
230                        case ROUNDNEAREST:
231                                if (guardbit) {
232                                   if (stickybit || lsb_odd) dest_mantissa++;
233                                   }
234                }
235        }
236        Sgl_set_exponentmantissa(result,dest_mantissa);
237
238        /*
239         * check for mantissa overflow after rounding
240         */
241        if ((dest_exponent>0 || Is_underflowtrap_enabled()) &&
242	    Sgl_isone_hidden(result)) dest_exponent++;
243
244        /*
245         * Test for overflow
246         */
247        if (dest_exponent >= SGL_INFINITY_EXPONENT) {
248                /* trap if OVERFLOWTRAP enabled */
249                if (Is_overflowtrap_enabled()) {
250                        /*
251                         * Check for gross overflow
252                         */
253                        if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP)
254                        	return(UNIMPLEMENTEDEXCEPTION);
255
256                        /*
257                         * Adjust bias of result
258                         */
259			Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
260			*dstptr = result;
261			if (inexact)
262			    if (Is_inexacttrap_enabled())
263				return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
264			    else Set_inexactflag();
265                        return(OVERFLOWEXCEPTION);
266                }
267                Set_overflowflag();
268		inexact = TRUE;
269		/* set result to infinity or largest number */
270		Sgl_setoverflow(result);
271        }
272        /*
273         * Test for underflow
274         */
275        else if (dest_exponent <= 0) {
276                /* trap if UNDERFLOWTRAP enabled */
277                if (Is_underflowtrap_enabled()) {
278                        /*
279                         * Check for gross underflow
280                         */
281                        if (dest_exponent <= -(SGL_WRAP))
282                        	return(UNIMPLEMENTEDEXCEPTION);
283                        /*
284                         * Adjust bias of result
285                         */
286			Sgl_setwrapped_exponent(result,dest_exponent,unfl);
287			*dstptr = result;
288			if (inexact)
289			    if (Is_inexacttrap_enabled())
290				return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION);
291			    else Set_inexactflag();
292                        return(UNDERFLOWEXCEPTION);
293                }
294                 /*
295                  * result is denormalized or signed zero
296                  */
297               if (inexact && is_tiny) Set_underflowflag();
298
299        }
300	else Sgl_set_exponent(result,dest_exponent);
301	*dstptr = result;
302        /*
303         * Trap if inexact trap is enabled
304         */
305        if (inexact)
306        	if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
307        	else Set_inexactflag();
308        return(NOEXCEPTION);
309}
310