xref: /netbsd-src/sys/arch/hppa/spmath/fcnvfxt.c (revision d72340ff8e2fb5c3ca49ab85c798389cda4408d6)
1 /*	$NetBSD: fcnvfxt.c,v 1.5 2012/02/04 17:03:09 skrll Exp $	*/
2 
3 /*	$OpenBSD: fcnvfxt.c,v 1.8 2010/07/30 18:05:23 kettenis 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: fcnvfxt.c,v 1.5 2012/02/04 17:03:09 skrll 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 floating-point to single fixed-point format
54  *  with truncated result
55  */
56 /*ARGSUSED*/
57 int
sgl_to_sgl_fcnvfxt(sgl_floating_point * srcptr,int * dstptr,unsigned int * status)58 sgl_to_sgl_fcnvfxt(sgl_floating_point *srcptr, int *dstptr,
59     unsigned int *status)
60 {
61 	register unsigned int src, temp;
62 	register int src_exponent, result;
63 
64 	src = *srcptr;
65 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
66 
67 	/*
68 	 * Test for overflow
69 	 */
70 	if (src_exponent > SGL_FX_MAX_EXP) {
71 		/* check for MININT */
72 		if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
73 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
74 			if (Sgl_iszero_sign(src)) result = 0x7fffffff;
75 			else result = 0x80000000;
76 
77 			if (Is_invalidtrap_enabled()) {
78 				return(INVALIDEXCEPTION);
79 			}
80 			Set_invalidflag();
81 			*dstptr = result;
82 			return(NOEXCEPTION);
83 		}
84 	}
85 	/*
86 	 * Generate result
87 	 */
88 	if (src_exponent >= 0) {
89 		temp = src;
90 		Sgl_clear_signexponent_set_hidden(temp);
91 		Int_from_sgl_mantissa(temp,src_exponent);
92 		if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
93 		else result = Sgl_all(temp);
94 		*dstptr = result;
95 
96 		/* check for inexact */
97 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
98 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
99 			else Set_inexactflag();
100 		}
101 	}
102 	else {
103 		*dstptr = 0;
104 
105 		/* check for inexact */
106 		if (Sgl_isnotzero_exponentmantissa(src)) {
107 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
108 			else Set_inexactflag();
109 		}
110 	}
111 	return(NOEXCEPTION);
112 }
113 
114 /*
115  *  Single Floating-point to Double Fixed-point
116  */
117 /*ARGSUSED*/
118 int
sgl_to_dbl_fcnvfxt(sgl_floating_point * srcptr,dbl_integer * dstptr,unsigned int * status)119 sgl_to_dbl_fcnvfxt(sgl_floating_point *srcptr, dbl_integer *dstptr,
120     unsigned int *status)
121 {
122 	register int src_exponent, resultp1;
123 	register unsigned int src, temp, resultp2;
124 
125 	src = *srcptr;
126 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
127 
128 	/*
129 	 * Test for overflow
130 	 */
131 	if (src_exponent > DBL_FX_MAX_EXP) {
132 		/* check for MININT */
133 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
134 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
135 			if (Sgl_iszero_sign(src)) {
136 				resultp1 = 0x7fffffff;
137 				resultp2 = 0xffffffff;
138 			}
139 			else {
140 				resultp1 = 0x80000000;
141 				resultp2 = 0;
142 			}
143 
144 			if (Is_invalidtrap_enabled()) {
145 				return(INVALIDEXCEPTION);
146 			}
147 			Set_invalidflag();
148 			Dint_copytoptr(resultp1,resultp2,dstptr);
149 			return(NOEXCEPTION);
150 		}
151 		Dint_set_minint(resultp1,resultp2);
152 		Dint_copytoptr(resultp1,resultp2,dstptr);
153 		return(NOEXCEPTION);
154 	}
155 	/*
156 	 * Generate result
157 	 */
158 	if (src_exponent >= 0) {
159 		temp = src;
160 		Sgl_clear_signexponent_set_hidden(temp);
161 		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
162 		if (Sgl_isone_sign(src)) {
163 			Dint_setone_sign(resultp1,resultp2);
164 		}
165 		Dint_copytoptr(resultp1,resultp2,dstptr);
166 
167 		/* check for inexact */
168 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
169 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
170 			else Set_inexactflag();
171 		}
172 	}
173 	else {
174 		Dint_setzero(resultp1,resultp2);
175 		Dint_copytoptr(resultp1,resultp2,dstptr);
176 
177 		/* check for inexact */
178 		if (Sgl_isnotzero_exponentmantissa(src)) {
179 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
180 			else Set_inexactflag();
181 		}
182 	}
183 	return(NOEXCEPTION);
184 }
185 
186 /*
187  *  Double Floating-point to Single Fixed-point
188  */
189 /*ARGSUSED*/
190 int
dbl_to_sgl_fcnvfxt(dbl_floating_point * srcptr,int * dstptr,unsigned int * status)191 dbl_to_sgl_fcnvfxt(dbl_floating_point *srcptr, int *dstptr,
192     unsigned int *status)
193 {
194 	register unsigned int srcp1, srcp2, tempp1, tempp2;
195 	register int src_exponent, result;
196 
197 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
198 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
199 
200 	/*
201 	 * Test for overflow
202 	 */
203 	if (src_exponent > SGL_FX_MAX_EXP) {
204 		/* check for MININT */
205 		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
206 			if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
207 			else result = 0x80000000;
208 
209 			if (Is_invalidtrap_enabled()) {
210 				return(INVALIDEXCEPTION);
211 			}
212 			Set_invalidflag();
213 			*dstptr = result;
214 			return(NOEXCEPTION);
215 		}
216 	}
217 	/*
218 	 * Generate result
219 	 */
220 	if (src_exponent >= 0) {
221 		tempp1 = srcp1;
222 		tempp2 = srcp2;
223 		Dbl_clear_signexponent_set_hidden(tempp1);
224 		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
225 		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
226 			result = -Dbl_allp1(tempp1);
227 		else result = Dbl_allp1(tempp1);
228 		*dstptr = result;
229 
230 		/* check for inexact */
231 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
232 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
233 			else Set_inexactflag();
234 		}
235 	}
236 	else {
237 		*dstptr = 0;
238 
239 		/* check for inexact */
240 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
241 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
242 			else Set_inexactflag();
243 		}
244 	}
245 	return(NOEXCEPTION);
246 }
247 
248 /*
249  *  Double Floating-point to Double Fixed-point
250  */
251 /*ARGSUSED*/
252 int
dbl_to_dbl_fcnvfxt(dbl_floating_point * srcptr,dbl_integer * dstptr,unsigned int * status)253 dbl_to_dbl_fcnvfxt(dbl_floating_point *srcptr, dbl_integer *dstptr,
254     unsigned int *status)
255 {
256 	register int src_exponent, resultp1;
257 	register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
258 
259 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
260 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
261 
262 	/*
263 	 * Test for overflow
264 	 */
265 	if (src_exponent > DBL_FX_MAX_EXP) {
266 		/* check for MININT */
267 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
268 		Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
269 			if (Dbl_iszero_sign(srcp1)) {
270 				resultp1 = 0x7fffffff;
271 				resultp2 = 0xffffffff;
272 			}
273 			else {
274 				resultp1 = 0x80000000;
275 				resultp2 = 0;
276 			}
277 
278 			if (Is_invalidtrap_enabled()) {
279 				return(INVALIDEXCEPTION);
280 			}
281 			Set_invalidflag();
282 			Dint_copytoptr(resultp1,resultp2,dstptr);
283 			return(NOEXCEPTION);
284 		}
285 	}
286 	/*
287 	 * Generate result
288 	 */
289 	if (src_exponent >= 0) {
290 		tempp1 = srcp1;
291 		tempp2 = srcp2;
292 		Dbl_clear_signexponent_set_hidden(tempp1);
293 		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
294 		resultp1,resultp2);
295 		if (Dbl_isone_sign(srcp1)) {
296 			Dint_setone_sign(resultp1,resultp2);
297 		}
298 		Dint_copytoptr(resultp1,resultp2,dstptr);
299 
300 		/* check for inexact */
301 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
302 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
303 			else Set_inexactflag();
304 		}
305 	}
306 	else {
307 		Dint_setzero(resultp1,resultp2);
308 		Dint_copytoptr(resultp1,resultp2,dstptr);
309 
310 		/* check for inexact */
311 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
312 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
313 			else Set_inexactflag();
314 		}
315 	}
316 	return(NOEXCEPTION);
317 }
318