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., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21 /*
22  * BEGIN_DESC
23  *
24  *  File:
25  *	@(#)	pa/spmath/fcnvfut.c		$Revision: $
26  *
27  *  Purpose:
28  *	Floating-point to Unsigned Fixed-point Converts with Truncation
29  *
30  *  External Interfaces:
31  *	dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
32  *	dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
33  *	sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
34  *	sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
35  *
36  *  Internal Interfaces:
37  *
38  *  Theory:
39  *	<<please update with a overview of the operation of this file>>
40  *
41  * END_DESC
42 */
43 
44 
45 #include "float.h"
46 #include "sgl_float.h"
47 #include "dbl_float.h"
48 #include "cnv_float.h"
49 
50 /************************************************************************
51  *  Floating-point to Unsigned Fixed-point Converts with Truncation	*
52  ************************************************************************/
53 
54 /*
55  *  Convert single floating-point to single fixed-point format
56  *  with truncated result
57  */
58 /*ARGSUSED*/
59 int
sgl_to_sgl_fcnvfut(sgl_floating_point * srcptr,unsigned int * nullptr,unsigned int * dstptr,unsigned int * status)60 sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
61 		    unsigned int *dstptr, unsigned int *status)
62 {
63 	register unsigned int src, result;
64 	register int src_exponent;
65 
66 	src = *srcptr;
67 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
68 
69 	/*
70 	 * Test for overflow
71 	 */
72 	if (src_exponent > SGL_FX_MAX_EXP + 1) {
73 		if (Sgl_isone_sign(src)) {
74 			result = 0;
75 		} else {
76 			result = 0xffffffff;
77 		}
78 		if (Is_invalidtrap_enabled()) {
79 			return(INVALIDEXCEPTION);
80 		}
81 		Set_invalidflag();
82 		*dstptr = result;
83 		return(NOEXCEPTION);
84 	}
85 	/*
86 	 * Generate result
87 	 */
88 	if (src_exponent >= 0) {
89 		/*
90 		 * Check sign.
91 		 * If negative, trap unimplemented.
92 		 */
93 		if (Sgl_isone_sign(src)) {
94 			result = 0;
95 			if (Is_invalidtrap_enabled()) {
96 				return(INVALIDEXCEPTION);
97 			}
98 			Set_invalidflag();
99 			*dstptr = result;
100 			return(NOEXCEPTION);
101 		}
102 		Sgl_clear_signexponent_set_hidden(src);
103 		Suint_from_sgl_mantissa(src,src_exponent,result);
104 		*dstptr = result;
105 
106 		/* check for inexact */
107 		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
108 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
109 			else Set_inexactflag();
110 		}
111 	}
112 	else {
113 		*dstptr = 0;
114 
115 		/* check for inexact */
116 		if (Sgl_isnotzero_exponentmantissa(src)) {
117 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
118 			else Set_inexactflag();
119 		}
120 	}
121 	return(NOEXCEPTION);
122 }
123 
124 /*
125  *  Single Floating-point to Double Unsigned Fixed
126  */
127 /*ARGSUSED*/
128 int
sgl_to_dbl_fcnvfut(sgl_floating_point * srcptr,unsigned int * nullptr,dbl_unsigned * dstptr,unsigned int * status)129 sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
130 		    dbl_unsigned * dstptr, unsigned int *status)
131 {
132 	register int src_exponent;
133 	register unsigned int src, resultp1, resultp2;
134 
135 	src = *srcptr;
136 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
137 
138 	/*
139 	 * Test for overflow
140 	 */
141 	if (src_exponent > DBL_FX_MAX_EXP + 1) {
142 		if (Sgl_isone_sign(src)) {
143 			resultp1 = resultp2 = 0;
144 		} else {
145 			resultp1 = resultp2 = 0xffffffff;
146 		}
147 		if (Is_invalidtrap_enabled()) {
148 			return(INVALIDEXCEPTION);
149 		}
150 		Set_invalidflag();
151     		Duint_copytoptr(resultp1,resultp2,dstptr);
152 		return(NOEXCEPTION);
153 	}
154 	/*
155 	 * Generate result
156 	 */
157 	if (src_exponent >= 0) {
158 		/*
159 		 * Check sign.
160 		 * If negative, trap unimplemented.
161 		 */
162 		if (Sgl_isone_sign(src)) {
163 			resultp1 = resultp2 = 0;
164 			if (Is_invalidtrap_enabled()) {
165 				return(INVALIDEXCEPTION);
166 			}
167 			Set_invalidflag();
168     			Duint_copytoptr(resultp1,resultp2,dstptr);
169 			return(NOEXCEPTION);
170 		}
171 		Sgl_clear_signexponent_set_hidden(src);
172 		Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
173 		Duint_copytoptr(resultp1,resultp2,dstptr);
174 
175 		/* check for inexact */
176 		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
177 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
178 			else Set_inexactflag();
179 		}
180 	}
181 	else {
182 		Duint_setzero(resultp1,resultp2);
183 		Duint_copytoptr(resultp1,resultp2,dstptr);
184 
185 		/* check for inexact */
186 		if (Sgl_isnotzero_exponentmantissa(src)) {
187 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
188 			else Set_inexactflag();
189 		}
190 	}
191 	return(NOEXCEPTION);
192 }
193 
194 /*
195  *  Double Floating-point to Single Unsigned Fixed
196  */
197 /*ARGSUSED*/
198 int
dbl_to_sgl_fcnvfut(dbl_floating_point * srcptr,unsigned int * nullptr,unsigned int * dstptr,unsigned int * status)199 dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
200 		    unsigned int *dstptr, unsigned int *status)
201 {
202 	register unsigned int srcp1, srcp2, result;
203 	register int src_exponent;
204 
205 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
206 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
207 
208 	/*
209 	 * Test for overflow
210 	 */
211 	if (src_exponent > SGL_FX_MAX_EXP + 1) {
212 		if (Dbl_isone_sign(srcp1)) {
213 			result = 0;
214 		} else {
215 			result = 0xffffffff;
216 		}
217 		if (Is_invalidtrap_enabled()) {
218 			return(INVALIDEXCEPTION);
219 		}
220 		Set_invalidflag();
221 		*dstptr = result;
222 		return(NOEXCEPTION);
223 	}
224 	/*
225 	 * Generate result
226 	 */
227 	if (src_exponent >= 0) {
228 		/*
229 		 * Check sign.
230 		 * If negative, trap unimplemented.
231 		 */
232 		if (Dbl_isone_sign(srcp1)) {
233 			result = 0;
234 			if (Is_invalidtrap_enabled()) {
235 				return(INVALIDEXCEPTION);
236 			}
237 			Set_invalidflag();
238 			*dstptr = result;
239 			return(NOEXCEPTION);
240 		}
241 		Dbl_clear_signexponent_set_hidden(srcp1);
242 		Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
243 		*dstptr = result;
244 
245 		/* check for inexact */
246 		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
247 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
248 			else Set_inexactflag();
249 		}
250 	}
251 	else {
252 		*dstptr = 0;
253 
254 		/* check for inexact */
255 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
256 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
257 			else Set_inexactflag();
258 		}
259 	}
260 	return(NOEXCEPTION);
261 }
262 
263 /*
264  *  Double Floating-point to Double Unsigned Fixed
265  */
266 /*ARGSUSED*/
267 int
dbl_to_dbl_fcnvfut(dbl_floating_point * srcptr,unsigned int * nullptr,dbl_unsigned * dstptr,unsigned int * status)268 dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
269 		    dbl_unsigned * dstptr, unsigned int *status)
270 {
271 	register int src_exponent;
272 	register unsigned int srcp1, srcp2, resultp1, resultp2;
273 
274 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
275 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
276 
277 	/*
278 	 * Test for overflow
279 	 */
280 	if (src_exponent > DBL_FX_MAX_EXP + 1) {
281 		if (Dbl_isone_sign(srcp1)) {
282 			resultp1 = resultp2 = 0;
283 		} else {
284 			resultp1 = resultp2 = 0xffffffff;
285 		}
286 		if (Is_invalidtrap_enabled()) {
287 			return(INVALIDEXCEPTION);
288 		}
289 		Set_invalidflag();
290     		Duint_copytoptr(resultp1,resultp2,dstptr);
291 		return(NOEXCEPTION);
292 	}
293 	/*
294 	 * Generate result
295 	 */
296 	if (src_exponent >= 0) {
297 		/*
298 		 * Check sign.
299 		 * If negative, trap unimplemented.
300 		 */
301 		if (Dbl_isone_sign(srcp1)) {
302 			resultp1 = resultp2 = 0;
303 			if (Is_invalidtrap_enabled()) {
304 				return(INVALIDEXCEPTION);
305 			}
306 			Set_invalidflag();
307     			Duint_copytoptr(resultp1,resultp2,dstptr);
308 			return(NOEXCEPTION);
309 		}
310 		Dbl_clear_signexponent_set_hidden(srcp1);
311 		Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,
312 		  resultp1,resultp2);
313 		Duint_copytoptr(resultp1,resultp2,dstptr);
314 
315 		/* check for inexact */
316 		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
317 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
318 			else Set_inexactflag();
319 		}
320 	}
321 	else {
322 		Duint_setzero(resultp1,resultp2);
323 		Duint_copytoptr(resultp1,resultp2,dstptr);
324 
325 		/* check for inexact */
326 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
327 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
328 			else Set_inexactflag();
329 		}
330 	}
331 	return(NOEXCEPTION);
332 }
333