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*/
45int
46sgl_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*/
109int
110sgl_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*/
183int
184dbl_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*/
248int
249dbl_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