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