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