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