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/fcnvuf.c		$Revision: 1.1 $
13 *
14 *  Purpose:
15 *	Fixed point to Floating-point Converts
16 *
17 *  External Interfaces:
18 *	dbl_to_dbl_fcnvuf(srcptr,_nullptr,dstptr,status)
19 *	dbl_to_sgl_fcnvuf(srcptr,_nullptr,dstptr,status)
20 *	sgl_to_dbl_fcnvuf(srcptr,_nullptr,dstptr,status)
21 *	sgl_to_sgl_fcnvuf(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 *  Fixed point to Floating-point Converts				*
39 ************************************************************************/
40
41/*
42 *  Convert Single Unsigned Fixed to Single Floating-point format
43 */
44
45int
46sgl_to_sgl_fcnvuf(
47			unsigned int *srcptr,
48			unsigned int *_nullptr,
49			sgl_floating_point *dstptr,
50			unsigned int *status)
51{
52	register unsigned int src, result = 0;
53	register int dst_exponent;
54
55	src = *srcptr;
56
57	/* Check for zero */
58	if (src == 0) {
59	       	Sgl_setzero(result);
60		*dstptr = result;
61	       	return(NOEXCEPTION);
62	}
63	/*
64	 * Generate exponent and normalized mantissa
65	 */
66	dst_exponent = 16;    /* initialize for normalization */
67	/*
68	 * Check word for most significant bit set.  Returns
69	 * a value in dst_exponent indicating the bit position,
70	 * between -1 and 30.
71	 */
72	Find_ms_one_bit(src,dst_exponent);
73	/*  left justify source, with msb at bit position 0  */
74	src <<= dst_exponent+1;
75	Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH);
76	Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
77
78	/* check for inexact */
79	if (Suint_isinexact_to_sgl(src)) {
80		switch (Rounding_mode()) {
81			case ROUNDPLUS:
82				Sgl_increment(result);
83				break;
84			case ROUNDMINUS: /* never negative */
85				break;
86			case ROUNDNEAREST:
87				Sgl_roundnearest_from_suint(src,result);
88				break;
89		}
90		if (Is_inexacttrap_enabled()) {
91			*dstptr = result;
92			return(INEXACTEXCEPTION);
93		}
94		else Set_inexactflag();
95	}
96	*dstptr = result;
97	return(NOEXCEPTION);
98}
99
100/*
101 *  Single Unsigned Fixed to Double Floating-point
102 */
103
104int
105sgl_to_dbl_fcnvuf(
106			unsigned int *srcptr,
107			unsigned int *_nullptr,
108			dbl_floating_point *dstptr,
109			unsigned int *status)
110{
111	register int dst_exponent;
112	register unsigned int src, resultp1 = 0, resultp2 = 0;
113
114	src = *srcptr;
115
116	/* Check for zero */
117	if (src == 0) {
118	       	Dbl_setzero(resultp1,resultp2);
119	       	Dbl_copytoptr(resultp1,resultp2,dstptr);
120	       	return(NOEXCEPTION);
121	}
122	/*
123	 * Generate exponent and normalized mantissa
124	 */
125	dst_exponent = 16;    /* initialize for normalization */
126	/*
127	 * Check word for most significant bit set.  Returns
128	 * a value in dst_exponent indicating the bit position,
129	 * between -1 and 30.
130	 */
131	Find_ms_one_bit(src,dst_exponent);
132	/*  left justify source, with msb at bit position 0  */
133	src <<= dst_exponent+1;
134	Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH);
135	Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH));
136	Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
137	Dbl_copytoptr(resultp1,resultp2,dstptr);
138	return(NOEXCEPTION);
139}
140
141/*
142 *  Double Unsigned Fixed to Single Floating-point
143 */
144
145int
146dbl_to_sgl_fcnvuf(
147			dbl_unsigned *srcptr,
148			unsigned int *_nullptr,
149			sgl_floating_point *dstptr,
150			unsigned int *status)
151{
152	int dst_exponent;
153	unsigned int srcp1, srcp2, result = 0;
154
155	Duint_copyfromptr(srcptr,srcp1,srcp2);
156
157	/* Check for zero */
158	if (srcp1 == 0 && srcp2 == 0) {
159	       	Sgl_setzero(result);
160	       	*dstptr = result;
161	       	return(NOEXCEPTION);
162	}
163	/*
164	 * Generate exponent and normalized mantissa
165	 */
166	dst_exponent = 16;    /* initialize for normalization */
167	if (srcp1 == 0) {
168		/*
169		 * Check word for most significant bit set.  Returns
170		 * a value in dst_exponent indicating the bit position,
171		 * between -1 and 30.
172		 */
173		Find_ms_one_bit(srcp2,dst_exponent);
174		/*  left justify source, with msb at bit position 0  */
175		srcp1 = srcp2 << dst_exponent+1;
176		srcp2 = 0;
177		/*
178		 *  since msb set is in second word, need to
179		 *  adjust bit position count
180		 */
181		dst_exponent += 32;
182	}
183	else {
184		/*
185		 * Check word for most significant bit set.  Returns
186		 * a value in dst_exponent indicating the bit position,
187		 * between -1 and 30.
188		 *
189		 */
190		Find_ms_one_bit(srcp1,dst_exponent);
191		/*  left justify source, with msb at bit position 0  */
192		if (dst_exponent >= 0) {
193			Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
194			 srcp1);
195			srcp2 <<= dst_exponent+1;
196		}
197	}
198	Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH);
199	Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
200
201	/* check for inexact */
202	if (Duint_isinexact_to_sgl(srcp1,srcp2)) {
203		switch (Rounding_mode()) {
204			case ROUNDPLUS:
205				Sgl_increment(result);
206				break;
207			case ROUNDMINUS: /* never negative */
208				break;
209			case ROUNDNEAREST:
210				Sgl_roundnearest_from_duint(srcp1,srcp2,result);
211				break;
212		}
213		if (Is_inexacttrap_enabled()) {
214			*dstptr = result;
215			return(INEXACTEXCEPTION);
216		}
217		else Set_inexactflag();
218	}
219	*dstptr = result;
220	return(NOEXCEPTION);
221}
222
223/*
224 *  Double Unsigned Fixed to Double Floating-point
225 */
226
227int
228dbl_to_dbl_fcnvuf(
229		    dbl_unsigned *srcptr,
230		    unsigned int *_nullptr,
231		    dbl_floating_point *dstptr,
232		    unsigned int *status)
233{
234	register int dst_exponent;
235	register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0;
236
237	Duint_copyfromptr(srcptr,srcp1,srcp2);
238
239	/* Check for zero */
240	if (srcp1 == 0 && srcp2 ==0) {
241	       	Dbl_setzero(resultp1,resultp2);
242	       	Dbl_copytoptr(resultp1,resultp2,dstptr);
243	       	return(NOEXCEPTION);
244	}
245	/*
246	 * Generate exponent and normalized mantissa
247	 */
248	dst_exponent = 16;    /* initialize for normalization */
249	if (srcp1 == 0) {
250		/*
251		 * Check word for most significant bit set.  Returns
252		 * a value in dst_exponent indicating the bit position,
253		 * between -1 and 30.
254		 */
255		Find_ms_one_bit(srcp2,dst_exponent);
256		/*  left justify source, with msb at bit position 0  */
257		srcp1 = srcp2 << dst_exponent+1;
258		srcp2 = 0;
259		/*
260		 *  since msb set is in second word, need to
261		 *  adjust bit position count
262		 */
263		dst_exponent += 32;
264	}
265	else {
266		/*
267		 * Check word for most significant bit set.  Returns
268		 * a value in dst_exponent indicating the bit position,
269		 * between -1 and 30.
270		 */
271		Find_ms_one_bit(srcp1,dst_exponent);
272		/*  left justify source, with msb at bit position 0  */
273		if (dst_exponent >= 0) {
274			Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
275			 srcp1);
276			srcp2 <<= dst_exponent+1;
277		}
278	}
279	Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH);
280	Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2);
281	Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
282
283	/* check for inexact */
284	if (Duint_isinexact_to_dbl(srcp2)) {
285		switch (Rounding_mode()) {
286			case ROUNDPLUS:
287				Dbl_increment(resultp1,resultp2);
288				break;
289			case ROUNDMINUS: /* never negative */
290				break;
291			case ROUNDNEAREST:
292				Dbl_roundnearest_from_duint(srcp2,resultp1,
293				resultp2);
294				break;
295		}
296		if (Is_inexacttrap_enabled()) {
297			Dbl_copytoptr(resultp1,resultp2,dstptr);
298			return(INEXACTEXCEPTION);
299		}
300		else Set_inexactflag();
301	}
302	Dbl_copytoptr(resultp1,resultp2,dstptr);
303	return(NOEXCEPTION);
304}
305
306