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