xref: /openbsd-src/sys/arch/hppa/spmath/fcnvff.c (revision de8cc8edbc71bd3e3bc7fbffa27ba0e564c37d8b)
1 /*	$OpenBSD: fcnvff.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 /* @(#)fcnvff.c: Revision: 2.8.88.1 Date: 93/12/07 15:06:09 */
16 
17 #include "float.h"
18 #include "sgl_float.h"
19 #include "dbl_float.h"
20 #include "cnv_float.h"
21 
22 /*
23  *  Single Floating-point to Double Floating-point
24  */
25 /*ARGSUSED*/
26 int
27 sgl_to_dbl_fcnvff(srcptr, null, dstptr, status)
28 	sgl_floating_point *srcptr, *null;
29 	dbl_floating_point *dstptr;
30 	unsigned int *status;
31 {
32 	register unsigned int src, resultp1, resultp2;
33 	register int src_exponent;
34 
35 	src = *srcptr;
36 	src_exponent = Sgl_exponent(src);
37 	Dbl_allp1(resultp1) = Sgl_all(src);  /* set sign of result */
38 	/*
39 	 * Test for NaN or infinity
40 	 */
41 	if (src_exponent == SGL_INFINITY_EXPONENT) {
42 		/*
43 		 * determine if NaN or infinity
44 		 */
45 		if (Sgl_iszero_mantissa(src)) {
46 			/*
47 			 * is infinity; want to return double infinity
48 			 */
49 			Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
50 			Dbl_copytoptr(resultp1,resultp2,dstptr);
51 			return(NOEXCEPTION);
52 		}
53 		else {
54 			/*
55 			 * is NaN; signaling or quiet?
56 			 */
57 			if (Sgl_isone_signaling(src)) {
58 				/* trap if INVALIDTRAP enabled */
59 				if (Is_invalidtrap_enabled())
60 					return(INVALIDEXCEPTION);
61 				/* make NaN quiet */
62 				else {
63 					Set_invalidflag();
64 					Sgl_set_quiet(src);
65 				}
66 			}
67 			/*
68 			 * NaN is quiet, return as double NaN
69 			 */
70 			Dbl_setinfinity_exponent(resultp1);
71 			Sgl_to_dbl_mantissa(src,resultp1,resultp2);
72 			Dbl_copytoptr(resultp1,resultp2,dstptr);
73 			return(NOEXCEPTION);
74 		}
75 	}
76 	/*
77 	 * Test for zero or denormalized
78 	 */
79 	if (src_exponent == 0) {
80 		/*
81 		 * determine if zero or denormalized
82 		 */
83 		if (Sgl_isnotzero_mantissa(src)) {
84 			/*
85 			 * is denormalized; want to normalize
86 			 */
87 			Sgl_clear_signexponent(src);
88 			Sgl_leftshiftby1(src);
89 			Sgl_normalize(src,src_exponent);
90 			Sgl_to_dbl_exponent(src_exponent,resultp1);
91 			Sgl_to_dbl_mantissa(src,resultp1,resultp2);
92 		}
93 		else {
94 			Dbl_setzero_exponentmantissa(resultp1,resultp2);
95 		}
96 		Dbl_copytoptr(resultp1,resultp2,dstptr);
97 		return(NOEXCEPTION);
98 	}
99 	/*
100 	 * No special cases, just complete the conversion
101 	 */
102 	Sgl_to_dbl_exponent(src_exponent, resultp1);
103 	Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
104 	Dbl_copytoptr(resultp1,resultp2,dstptr);
105 	return(NOEXCEPTION);
106 }
107 
108 /*
109  *  Double Floating-point to Single Floating-point
110  */
111 /*ARGSUSED*/
112 int
113 dbl_to_sgl_fcnvff(srcptr, null, dstptr, status)
114 	dbl_floating_point *srcptr, *null;
115 	sgl_floating_point *dstptr;
116 	unsigned int *status;
117 {
118 	register unsigned int srcp1, srcp2, result;
119 	register int src_exponent, dest_exponent, dest_mantissa;
120 	register int inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
121 	register int lsb_odd = FALSE;
122 	int is_tiny;
123 
124 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
125 	src_exponent = Dbl_exponent(srcp1);
126 	Sgl_all(result) = Dbl_allp1(srcp1);  /* set sign of result */
127 	/*
128 	 * Test for NaN or infinity
129 	 */
130 	if (src_exponent == DBL_INFINITY_EXPONENT) {
131 		/*
132 		 * determine if NaN or infinity
133 		 */
134 		if (Dbl_iszero_mantissa(srcp1,srcp2)) {
135 			/*
136 			 * is infinity; want to return single infinity
137 			 */
138 			Sgl_setinfinity_exponentmantissa(result);
139 			*dstptr = result;
140 			return(NOEXCEPTION);
141 		}
142 		/*
143 		 * is NaN; signaling or quiet?
144 		 */
145 		if (Dbl_isone_signaling(srcp1)) {
146 			/* trap if INVALIDTRAP enabled */
147 			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
148 			else {
149 				Set_invalidflag();
150 				/* make NaN quiet */
151 				Dbl_set_quiet(srcp1);
152 			}
153 		}
154 		/*
155 		 * NaN is quiet, return as single NaN
156 		 */
157 		Sgl_setinfinity_exponent(result);
158 		Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
159 		if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
160 		*dstptr = result;
161 		return(NOEXCEPTION);
162 	}
163 	/*
164 	 * Generate result
165 	 */
166 	Dbl_to_sgl_exponent(src_exponent,dest_exponent);
167 	if (dest_exponent > 0) {
168 		Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit,
169 		stickybit,lsb_odd);
170 	}
171 	else {
172 		if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
173 			Sgl_setzero_exponentmantissa(result);
174 			*dstptr = result;
175 			return(NOEXCEPTION);
176 		}
177 		if (Is_underflowtrap_enabled()) {
178 			Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
179 			guardbit,stickybit,lsb_odd);
180 		}
181 		else {
182 			/* compute result, determine inexact info,
183 			 * and set Underflowflag if appropriate
184 			 */
185 			Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
186 			dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
187 			is_tiny);
188 		}
189 	}
190 	/*
191 	 * Now round result if not exact
192 	 */
193 	if (inexact) {
194 		switch (Rounding_mode()) {
195 			case ROUNDPLUS:
196 				if (Sgl_iszero_sign(result)) dest_mantissa++;
197 				break;
198 			case ROUNDMINUS:
199 				if (Sgl_isone_sign(result)) dest_mantissa++;
200 				break;
201 			case ROUNDNEAREST:
202 				if (guardbit) {
203 				   if (stickybit || lsb_odd) dest_mantissa++;
204 				   }
205 		}
206 	}
207 	Sgl_set_exponentmantissa(result,dest_mantissa);
208 
209 	/*
210 	 * check for mantissa overflow after rounding
211 	 */
212 	if ((dest_exponent>0 || Is_underflowtrap_enabled()) &&
213 	    Sgl_isone_hidden(result)) dest_exponent++;
214 
215 	/*
216 	 * Test for overflow
217 	 */
218 	if (dest_exponent >= SGL_INFINITY_EXPONENT) {
219 		/* trap if OVERFLOWTRAP enabled */
220 		if (Is_overflowtrap_enabled()) {
221 			/*
222 			 * Check for gross overflow
223 			 */
224 			if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP)
225 				return(UNIMPLEMENTEDEXCEPTION);
226 
227 			/*
228 			 * Adjust bias of result
229 			 */
230 			Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
231 			*dstptr = result;
232 			if (inexact) {
233 			    if (Is_inexacttrap_enabled())
234 				return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
235 			    else
236 				Set_inexactflag();
237 			}
238 			return(OVERFLOWEXCEPTION);
239 		}
240 		Set_overflowflag();
241 		inexact = TRUE;
242 		/* set result to infinity or largest number */
243 		Sgl_setoverflow(result);
244 	}
245 	/*
246 	 * Test for underflow
247 	 */
248 	else if (dest_exponent <= 0) {
249 		/* trap if UNDERFLOWTRAP enabled */
250 		if (Is_underflowtrap_enabled()) {
251 			/*
252 			 * Check for gross underflow
253 			 */
254 			if (dest_exponent <= -(SGL_WRAP))
255 				return(UNIMPLEMENTEDEXCEPTION);
256 			/*
257 			 * Adjust bias of result
258 			 */
259 			Sgl_setwrapped_exponent(result,dest_exponent,unfl);
260 			*dstptr = result;
261 			if (inexact) {
262 			    if (Is_inexacttrap_enabled())
263 				return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION);
264 			    else
265 				Set_inexactflag();
266 			}
267 			return(UNDERFLOWEXCEPTION);
268 		}
269 		 /*
270 		  * result is denormalized or signed zero
271 		  */
272 	       if (inexact && is_tiny) Set_underflowflag();
273 
274 	}
275 	else Sgl_set_exponent(result,dest_exponent);
276 	*dstptr = result;
277 	/*
278 	 * Trap if inexact trap is enabled
279 	 */
280 	if (inexact) {
281 		if (Is_inexacttrap_enabled())
282 			return(INEXACTEXCEPTION);
283 		else
284 			Set_inexactflag();
285 	}
286 	return(NOEXCEPTION);
287 }
288