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*/
46int
47sgl_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*/
115int
116sgl_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*/
185int
186dbl_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*/
254int
255dbl_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