xref: /openbmc/linux/arch/parisc/math-emu/fcnvuf.c (revision 2a598d0b)
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 
45 int
46 sgl_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 
104 int
105 sgl_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 
145 int
146 dbl_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 
227 int
228 dbl_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