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/fcnvxf.c		$Revision: 1.1 $
13  *
14  *  Purpose:
15  *	Single Fixed-point to Single Floating-point
16  *	Single Fixed-point to Double Floating-point
17  *	Double Fixed-point to Single Floating-point
18  *	Double Fixed-point to Double Floating-point
19  *
20  *  External Interfaces:
21  *	dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
22  *	dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
23  *	sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
24  *	sgl_to_sgl_fcnvxf(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 fixed-point to single floating-point format
42  */
43 
44 int
sgl_to_sgl_fcnvxf(int * srcptr,unsigned int * nullptr,sgl_floating_point * dstptr,unsigned int * status)45 sgl_to_sgl_fcnvxf(
46 		    int *srcptr,
47 		    unsigned int *nullptr,
48 		    sgl_floating_point *dstptr,
49 		    unsigned int *status)
50 {
51 	register int src, dst_exponent;
52 	register unsigned int result = 0;
53 
54 	src = *srcptr;
55 	/*
56 	 * set sign bit of result and get magnitude of source
57 	 */
58 	if (src < 0) {
59 		Sgl_setone_sign(result);
60 		Int_negate(src);
61 	}
62 	else {
63 		Sgl_setzero_sign(result);
64         	/* Check for zero */
65         	if (src == 0) {
66                 	Sgl_setzero(result);
67 			*dstptr = result;
68                 	return(NOEXCEPTION);
69         	}
70 	}
71 	/*
72 	 * Generate exponent and normalized mantissa
73 	 */
74 	dst_exponent = 16;    /* initialize for normalization */
75 	/*
76 	 * Check word for most significant bit set.  Returns
77 	 * a value in dst_exponent indicating the bit position,
78 	 * between -1 and 30.
79 	 */
80 	Find_ms_one_bit(src,dst_exponent);
81 	/*  left justify source, with msb at bit position 1  */
82 	if (dst_exponent >= 0) src <<= dst_exponent;
83 	else src = 1 << 30;
84 	Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
85 	Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
86 
87 	/* check for inexact */
88 	if (Int_isinexact_to_sgl(src)) {
89 		switch (Rounding_mode()) {
90 			case ROUNDPLUS:
91 				if (Sgl_iszero_sign(result))
92 					Sgl_increment(result);
93 				break;
94 			case ROUNDMINUS:
95 				if (Sgl_isone_sign(result))
96 					Sgl_increment(result);
97 				break;
98 			case ROUNDNEAREST:
99 				Sgl_roundnearest_from_int(src,result);
100 		}
101 		if (Is_inexacttrap_enabled()) {
102 			*dstptr = result;
103 			return(INEXACTEXCEPTION);
104 		}
105 		else Set_inexactflag();
106 	}
107 	*dstptr = result;
108 	return(NOEXCEPTION);
109 }
110 
111 /*
112  *  Single Fixed-point to Double Floating-point
113  */
114 
115 int
sgl_to_dbl_fcnvxf(int * srcptr,unsigned int * nullptr,dbl_floating_point * dstptr,unsigned int * status)116 sgl_to_dbl_fcnvxf(
117 		    int *srcptr,
118 		    unsigned int *nullptr,
119 		    dbl_floating_point *dstptr,
120 		    unsigned int *status)
121 {
122 	register int src, dst_exponent;
123 	register unsigned int resultp1 = 0, resultp2 = 0;
124 
125 	src = *srcptr;
126 	/*
127 	 * set sign bit of result and get magnitude of source
128 	 */
129 	if (src < 0) {
130 		Dbl_setone_sign(resultp1);
131 		Int_negate(src);
132 	}
133 	else {
134 		Dbl_setzero_sign(resultp1);
135         	/* Check for zero */
136         	if (src == 0) {
137                 	Dbl_setzero(resultp1,resultp2);
138                 	Dbl_copytoptr(resultp1,resultp2,dstptr);
139                 	return(NOEXCEPTION);
140         	}
141 	}
142 	/*
143 	 * Generate exponent and normalized mantissa
144 	 */
145 	dst_exponent = 16;    /* initialize for normalization */
146 	/*
147 	 * Check word for most significant bit set.  Returns
148 	 * a value in dst_exponent indicating the bit position,
149 	 * between -1 and 30.
150 	 */
151 	Find_ms_one_bit(src,dst_exponent);
152 	/*  left justify source, with msb at bit position 1  */
153 	if (dst_exponent >= 0) src <<= dst_exponent;
154 	else src = 1 << 30;
155 	Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1);
156 	Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH));
157 	Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
158 	Dbl_copytoptr(resultp1,resultp2,dstptr);
159 	return(NOEXCEPTION);
160 }
161 
162 /*
163  *  Double Fixed-point to Single Floating-point
164  */
165 
166 int
dbl_to_sgl_fcnvxf(dbl_integer * srcptr,unsigned int * nullptr,sgl_floating_point * dstptr,unsigned int * status)167 dbl_to_sgl_fcnvxf(
168 			dbl_integer *srcptr,
169 			unsigned int *nullptr,
170 			sgl_floating_point *dstptr,
171 			unsigned int *status)
172 {
173 	int dst_exponent, srcp1;
174 	unsigned int result = 0, srcp2;
175 
176 	Dint_copyfromptr(srcptr,srcp1,srcp2);
177 	/*
178 	 * set sign bit of result and get magnitude of source
179 	 */
180 	if (srcp1 < 0) {
181 		Sgl_setone_sign(result);
182 		Dint_negate(srcp1,srcp2);
183 	}
184 	else {
185 		Sgl_setzero_sign(result);
186         	/* Check for zero */
187         	if (srcp1 == 0 && srcp2 == 0) {
188                 	Sgl_setzero(result);
189                 	*dstptr = result;
190                 	return(NOEXCEPTION);
191 		}
192         }
193 	/*
194 	 * Generate exponent and normalized mantissa
195 	 */
196 	dst_exponent = 16;    /* initialize for normalization */
197 	if (srcp1 == 0) {
198 		/*
199 		 * Check word for most significant bit set.  Returns
200 		 * a value in dst_exponent indicating the bit position,
201 		 * between -1 and 30.
202 		 */
203 		Find_ms_one_bit(srcp2,dst_exponent);
204 		/*  left justify source, with msb at bit position 1  */
205 		if (dst_exponent >= 0) {
206 			srcp1 = srcp2 << dst_exponent;
207 			srcp2 = 0;
208 		}
209 		else {
210 			srcp1 = srcp2 >> 1;
211 			srcp2 <<= 31;
212 		}
213 		/*
214 		 *  since msb set is in second word, need to
215 		 *  adjust bit position count
216 		 */
217 		dst_exponent += 32;
218 	}
219 	else {
220 		/*
221 		 * Check word for most significant bit set.  Returns
222 		 * a value in dst_exponent indicating the bit position,
223 		 * between -1 and 30.
224 		 *
225 		 */
226 		Find_ms_one_bit(srcp1,dst_exponent);
227 		/*  left justify source, with msb at bit position 1  */
228 		if (dst_exponent > 0) {
229 			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
230 			 srcp1);
231 			srcp2 <<= dst_exponent;
232 		}
233 		/*
234 		 * If dst_exponent = 0, we don't need to shift anything.
235 		 * If dst_exponent = -1, src = - 2**63 so we won't need to
236 		 * shift srcp2.
237 		 */
238 		else srcp1 >>= -(dst_exponent);
239 	}
240 	Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1);
241 	Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
242 
243 	/* check for inexact */
244 	if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
245 		switch (Rounding_mode()) {
246 			case ROUNDPLUS:
247 				if (Sgl_iszero_sign(result))
248 					Sgl_increment(result);
249 				break;
250 			case ROUNDMINUS:
251 				if (Sgl_isone_sign(result))
252 					Sgl_increment(result);
253 				break;
254 			case ROUNDNEAREST:
255 				Sgl_roundnearest_from_dint(srcp1,srcp2,result);
256 		}
257 		if (Is_inexacttrap_enabled()) {
258 			*dstptr = result;
259 			return(INEXACTEXCEPTION);
260 		}
261 		else Set_inexactflag();
262 	}
263 	*dstptr = result;
264 	return(NOEXCEPTION);
265 }
266 
267 /*
268  *  Double Fixed-point to Double Floating-point
269  */
270 
271 int
dbl_to_dbl_fcnvxf(dbl_integer * srcptr,unsigned int * nullptr,dbl_floating_point * dstptr,unsigned int * status)272 dbl_to_dbl_fcnvxf(
273 		    dbl_integer *srcptr,
274 		    unsigned int *nullptr,
275 		    dbl_floating_point *dstptr,
276 		    unsigned int *status)
277 {
278 	register int srcp1, dst_exponent;
279 	register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
280 
281 	Dint_copyfromptr(srcptr,srcp1,srcp2);
282 	/*
283 	 * set sign bit of result and get magnitude of source
284 	 */
285 	if (srcp1 < 0) {
286 		Dbl_setone_sign(resultp1);
287 		Dint_negate(srcp1,srcp2);
288 	}
289 	else {
290 		Dbl_setzero_sign(resultp1);
291         	/* Check for zero */
292         	if (srcp1 == 0 && srcp2 ==0) {
293                 	Dbl_setzero(resultp1,resultp2);
294                 	Dbl_copytoptr(resultp1,resultp2,dstptr);
295                 	return(NOEXCEPTION);
296 		}
297         }
298 	/*
299 	 * Generate exponent and normalized mantissa
300 	 */
301 	dst_exponent = 16;    /* initialize for normalization */
302 	if (srcp1 == 0) {
303 		/*
304 		 * Check word for most significant bit set.  Returns
305 		 * a value in dst_exponent indicating the bit position,
306 		 * between -1 and 30.
307 		 */
308 		Find_ms_one_bit(srcp2,dst_exponent);
309 		/*  left justify source, with msb at bit position 1  */
310 		if (dst_exponent >= 0) {
311 			srcp1 = srcp2 << dst_exponent;
312 			srcp2 = 0;
313 		}
314 		else {
315 			srcp1 = srcp2 >> 1;
316 			srcp2 <<= 31;
317 		}
318 		/*
319 		 *  since msb set is in second word, need to
320 		 *  adjust bit position count
321 		 */
322 		dst_exponent += 32;
323 	}
324 	else {
325 		/*
326 		 * Check word for most significant bit set.  Returns
327 		 * a value in dst_exponent indicating the bit position,
328 		 * between -1 and 30.
329 		 */
330 		Find_ms_one_bit(srcp1,dst_exponent);
331 		/*  left justify source, with msb at bit position 1  */
332 		if (dst_exponent > 0) {
333 			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
334 			 srcp1);
335 			srcp2 <<= dst_exponent;
336 		}
337 		/*
338 		 * If dst_exponent = 0, we don't need to shift anything.
339 		 * If dst_exponent = -1, src = - 2**63 so we won't need to
340 		 * shift srcp2.
341 		 */
342 		else srcp1 >>= -(dst_exponent);
343 	}
344 	Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
345 	Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
346 	Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
347 
348 	/* check for inexact */
349 	if (Dint_isinexact_to_dbl(srcp2)) {
350 		switch (Rounding_mode()) {
351 			case ROUNDPLUS:
352 				if (Dbl_iszero_sign(resultp1)) {
353 					Dbl_increment(resultp1,resultp2);
354 				}
355 				break;
356 			case ROUNDMINUS:
357 				if (Dbl_isone_sign(resultp1)) {
358 					Dbl_increment(resultp1,resultp2);
359 				}
360 				break;
361 			case ROUNDNEAREST:
362 				Dbl_roundnearest_from_dint(srcp2,resultp1,
363 				resultp2);
364 		}
365 		if (Is_inexacttrap_enabled()) {
366 			Dbl_copytoptr(resultp1,resultp2,dstptr);
367 			return(INEXACTEXCEPTION);
368 		}
369 		else Set_inexactflag();
370 	}
371 	Dbl_copytoptr(resultp1,resultp2,dstptr);
372 	return(NOEXCEPTION);
373 }
374