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
44int
45sgl_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
115int
116sgl_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
166int
167dbl_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
271int
272dbl_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