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