xref: /openbsd-src/sys/arch/hppa/spmath/fcnvfx.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: fcnvfx.c,v 1.5 2001/03/29 03:58:18 mickey Exp $	*/
2 
3 /*
4  * Copyright 1996 1995 by Open Software Foundation, Inc.
5  *              All Rights Reserved
6  *
7  * Permission to use, copy, modify, and distribute this software and
8  * its documentation for any purpose and without fee is hereby granted,
9  * provided that the above copyright notice appears in all copies and
10  * that both the copyright notice and this permission notice appear in
11  * supporting documentation.
12  *
13  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
14  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15  * FOR A PARTICULAR PURPOSE.
16  *
17  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
20  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  */
24 /*
25  * pmk1.1
26  */
27 /*
28  * (c) Copyright 1986 HEWLETT-PACKARD COMPANY
29  *
30  * To anyone who acknowledges that this file is provided "AS IS"
31  * without any express or implied warranty:
32  *     permission to use, copy, modify, and distribute this file
33  * for any purpose is hereby granted without fee, provided that
34  * the above copyright notice and this notice appears in all
35  * copies, and that the name of Hewlett-Packard Company not be
36  * used in advertising or publicity pertaining to distribution
37  * of the software without specific, written prior permission.
38  * Hewlett-Packard Company makes no representations about the
39  * suitability of this software for any purpose.
40  */
41 
42 #include "../spmath/float.h"
43 #include "../spmath/sgl_float.h"
44 #include "../spmath/dbl_float.h"
45 #include "../spmath/cnv_float.h"
46 
47 /*
48  *  Single Floating-point to Single Fixed-point
49  */
50 /*ARGSUSED*/
51 int
52 sgl_to_sgl_fcnvfx(srcptr,dstptr,status)
53 
54 sgl_floating_point *srcptr;
55 int *dstptr;
56 unsigned int *status;
57 {
58 	register unsigned int src, temp;
59 	register int src_exponent, result;
60 	register int inexact = FALSE;
61 
62 	src = *srcptr;
63 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
64 
65 	/*
66 	 * Test for overflow
67 	 */
68 	if (src_exponent > SGL_FX_MAX_EXP) {
69 		/* check for MININT */
70 		if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
71 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
72 			/*
73 			 * Since source is a number which cannot be
74 			 * represented in fixed-point format, return
75 			 * largest (or smallest) fixed-point number.
76 			 */
77 			Sgl_return_overflow(src,dstptr);
78 		}
79 	}
80 	/*
81 	 * Generate result
82 	 */
83 	if (src_exponent >= 0) {
84 		temp = src;
85 		Sgl_clear_signexponent_set_hidden(temp);
86 		Int_from_sgl_mantissa(temp,src_exponent);
87 		if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
88 		else result = Sgl_all(temp);
89 
90 		/* check for inexact */
91 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
92 			inexact = TRUE;
93 			/*  round result  */
94 			switch (Rounding_mode()) {
95 			case ROUNDPLUS:
96 			     if (Sgl_iszero_sign(src)) result++;
97 			     break;
98 			case ROUNDMINUS:
99 			     if (Sgl_isone_sign(src)) result--;
100 			     break;
101 			case ROUNDNEAREST:
102 			     if (Sgl_isone_roundbit(src,src_exponent)) {
103 				if (Sgl_isone_stickybit(src,src_exponent)
104 				|| (Sgl_isone_lowmantissa(temp))) {
105 				   if (Sgl_iszero_sign(src)) result++;
106 				   else result--;
107 				}
108 			     }
109 			}
110 		}
111 	}
112 	else {
113 		result = 0;
114 
115 		/* check for inexact */
116 		if (Sgl_isnotzero_exponentmantissa(src)) {
117 			inexact = TRUE;
118 			/*  round result  */
119 			switch (Rounding_mode()) {
120 			case ROUNDPLUS:
121 			     if (Sgl_iszero_sign(src)) result++;
122 			     break;
123 			case ROUNDMINUS:
124 			     if (Sgl_isone_sign(src)) result--;
125 			     break;
126 			case ROUNDNEAREST:
127 			     if (src_exponent == -1)
128 				if (Sgl_isnotzero_mantissa(src)) {
129 				   if (Sgl_iszero_sign(src)) result++;
130 				   else result--;
131 				}
132 			}
133 		}
134 	}
135 	*dstptr = result;
136 	if (inexact) {
137 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
138 		else Set_inexactflag();
139 	}
140 	return(NOEXCEPTION);
141 }
142 
143 /*
144  *  Single Floating-point to Double Fixed-point
145  */
146 /*ARGSUSED*/
147 int
148 sgl_to_dbl_fcnvfx(srcptr,dstptr,status)
149 
150 sgl_floating_point *srcptr;
151 dbl_integer *dstptr;
152 unsigned int *status;
153 {
154 	register int src_exponent, resultp1;
155 	register unsigned int src, temp, resultp2;
156 	register int inexact = FALSE;
157 
158 	src = *srcptr;
159 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
160 
161 	/*
162 	 * Test for overflow
163 	 */
164 	if (src_exponent > DBL_FX_MAX_EXP) {
165 		/* check for MININT */
166 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
167 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
168 			/*
169 			 * Since source is a number which cannot be
170 			 * represented in fixed-point format, return
171 			 * largest (or smallest) fixed-point number.
172 			 */
173 			Sgl_return_overflow_dbl(src,dstptr);
174 		}
175 		Dint_set_minint(resultp1,resultp2);
176 		Dint_copytoptr(resultp1,resultp2,dstptr);
177 		return(NOEXCEPTION);
178 	}
179 	/*
180 	 * Generate result
181 	 */
182 	if (src_exponent >= 0) {
183 		temp = src;
184 		Sgl_clear_signexponent_set_hidden(temp);
185 		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
186 		if (Sgl_isone_sign(src)) {
187 			Dint_setone_sign(resultp1,resultp2);
188 		}
189 
190 		/* check for inexact */
191 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
192 			inexact = TRUE;
193 			/*  round result  */
194 			switch (Rounding_mode()) {
195 			case ROUNDPLUS:
196 			     if (Sgl_iszero_sign(src)) {
197 				Dint_increment(resultp1,resultp2);
198 			     }
199 			     break;
200 			case ROUNDMINUS:
201 			     if (Sgl_isone_sign(src)) {
202 				Dint_decrement(resultp1,resultp2);
203 			     }
204 			     break;
205 			case ROUNDNEAREST:
206 			     if (Sgl_isone_roundbit(src,src_exponent))
207 				if (Sgl_isone_stickybit(src,src_exponent) ||
208 				(Dint_isone_lowp2(resultp2))) {
209 				   if (Sgl_iszero_sign(src)) {
210 				      Dint_increment(resultp1,resultp2);
211 				   }
212 				   else {
213 				      Dint_decrement(resultp1,resultp2);
214 				   }
215 				}
216 			}
217 		}
218 	}
219 	else {
220 		Dint_setzero(resultp1,resultp2);
221 
222 		/* check for inexact */
223 		if (Sgl_isnotzero_exponentmantissa(src)) {
224 			inexact = TRUE;
225 			/*  round result  */
226 			switch (Rounding_mode()) {
227 			case ROUNDPLUS:
228 			     if (Sgl_iszero_sign(src)) {
229 				Dint_increment(resultp1,resultp2);
230 			     }
231 			     break;
232 			case ROUNDMINUS:
233 			     if (Sgl_isone_sign(src)) {
234 				Dint_decrement(resultp1,resultp2);
235 			     }
236 			     break;
237 			case ROUNDNEAREST:
238 			     if (src_exponent == -1)
239 				if (Sgl_isnotzero_mantissa(src)) {
240 				   if (Sgl_iszero_sign(src)) {
241 				      Dint_increment(resultp1,resultp2);
242 				   }
243 				   else {
244 				      Dint_decrement(resultp1,resultp2);
245 				   }
246 				}
247 			}
248 		}
249 	}
250 	Dint_copytoptr(resultp1,resultp2,dstptr);
251 	if (inexact) {
252 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
253 		else Set_inexactflag();
254 	}
255 	return(NOEXCEPTION);
256 }
257 
258 /*
259  *  Double Floating-point to Single Fixed-point
260  */
261 /*ARGSUSED*/
262 int
263 dbl_to_sgl_fcnvfx(srcptr,dstptr,status)
264 
265 dbl_floating_point *srcptr;
266 int *dstptr;
267 unsigned int *status;
268 {
269 	register unsigned int srcp1,srcp2, tempp1,tempp2;
270 	register int src_exponent, result;
271 	register int inexact = FALSE;
272 
273 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
274 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
275 
276 	/*
277 	 * Test for overflow
278 	 */
279 	if (src_exponent > SGL_FX_MAX_EXP) {
280 		/* check for MININT */
281 		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
282 			/*
283 			 * Since source is a number which cannot be
284 			 * represented in fixed-point format, return
285 			 * largest (or smallest) fixed-point number.
286 			 */
287 			Dbl_return_overflow(srcp1,srcp2,dstptr);
288 		}
289 	}
290 	/*
291 	 * Generate result
292 	 */
293 	if (src_exponent >= 0) {
294 		tempp1 = srcp1;
295 		tempp2 = srcp2;
296 		Dbl_clear_signexponent_set_hidden(tempp1);
297 		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
298 		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
299 			result = -Dbl_allp1(tempp1);
300 		else result = Dbl_allp1(tempp1);
301 
302 		/* check for inexact */
303 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
304 			inexact = TRUE;
305 			/*  round result  */
306 			switch (Rounding_mode()) {
307 			case ROUNDPLUS:
308 			     if (Dbl_iszero_sign(srcp1)) result++;
309 			     break;
310 			case ROUNDMINUS:
311 			     if (Dbl_isone_sign(srcp1)) result--;
312 			     break;
313 			case ROUNDNEAREST:
314 			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
315 				if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
316 				(Dbl_isone_lowmantissap1(tempp1))) {
317 				   if (Dbl_iszero_sign(srcp1)) result++;
318 				   else result--;
319 				}
320 			}
321 			/* check for overflow */
322 			if ((Dbl_iszero_sign(srcp1) && result < 0) ||
323 			    (Dbl_isone_sign(srcp1) && result > 0)) {
324 				Dbl_return_overflow(srcp1,srcp2,dstptr);
325 			}
326 		}
327 	}
328 	else {
329 		result = 0;
330 
331 		/* check for inexact */
332 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
333 			inexact = TRUE;
334 			/*  round result  */
335 			switch (Rounding_mode()) {
336 			case ROUNDPLUS:
337 			     if (Dbl_iszero_sign(srcp1)) result++;
338 			     break;
339 			case ROUNDMINUS:
340 			     if (Dbl_isone_sign(srcp1)) result--;
341 			     break;
342 			case ROUNDNEAREST:
343 			     if (src_exponent == -1)
344 				if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
345 				   if (Dbl_iszero_sign(srcp1)) result++;
346 				   else result--;
347 				}
348 			}
349 		}
350 	}
351 	*dstptr = result;
352 	if (inexact) {
353 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
354 		else Set_inexactflag();
355 	}
356 	return(NOEXCEPTION);
357 }
358 
359 /*
360  *  Double Floating-point to Double Fixed-point
361  */
362 /*ARGSUSED*/
363 int
364 dbl_to_dbl_fcnvfx(srcptr,dstptr,status)
365 
366 dbl_floating_point *srcptr;
367 dbl_integer *dstptr;
368 unsigned int *status;
369 {
370 	register int src_exponent, resultp1;
371 	register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
372 	register int inexact = FALSE;
373 
374 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
375 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
376 
377 	/*
378 	 * Test for overflow
379 	 */
380 	if (src_exponent > DBL_FX_MAX_EXP) {
381 		/* check for MININT */
382 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
383 		Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
384 			/*
385 			 * Since source is a number which cannot be
386 			 * represented in fixed-point format, return
387 			 * largest (or smallest) fixed-point number.
388 			 */
389 			Dbl_return_overflow_dbl(srcp1,srcp2,dstptr);
390 		}
391 	}
392 
393 	/*
394 	 * Generate result
395 	 */
396 	if (src_exponent >= 0) {
397 		tempp1 = srcp1;
398 		tempp2 = srcp2;
399 		Dbl_clear_signexponent_set_hidden(tempp1);
400 		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
401 				       resultp1, resultp2);
402 		if (Dbl_isone_sign(srcp1)) {
403 			Dint_setone_sign(resultp1,resultp2);
404 		}
405 
406 		/* check for inexact */
407 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
408 			inexact = TRUE;
409 			/*  round result  */
410 			switch (Rounding_mode()) {
411 			case ROUNDPLUS:
412 			     if (Dbl_iszero_sign(srcp1)) {
413 				Dint_increment(resultp1,resultp2);
414 			     }
415 			     break;
416 			case ROUNDMINUS:
417 			     if (Dbl_isone_sign(srcp1)) {
418 				Dint_decrement(resultp1,resultp2);
419 			     }
420 			     break;
421 			case ROUNDNEAREST:
422 			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
423 				if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
424 				(Dint_isone_lowp2(resultp2))) {
425 				   if (Dbl_iszero_sign(srcp1)) {
426 				      Dint_increment(resultp1,resultp2);
427 				   }
428 				   else {
429 				      Dint_decrement(resultp1,resultp2);
430 				   }
431 				}
432 			}
433 		}
434 	}
435 	else {
436 		Dint_setzero(resultp1,resultp2);
437 
438 		/* check for inexact */
439 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
440 			inexact = TRUE;
441 			/*  round result  */
442 			switch (Rounding_mode()) {
443 			case ROUNDPLUS:
444 			     if (Dbl_iszero_sign(srcp1)) {
445 				Dint_increment(resultp1,resultp2);
446 			     }
447 			     break;
448 			case ROUNDMINUS:
449 			     if (Dbl_isone_sign(srcp1)) {
450 				Dint_decrement(resultp1,resultp2);
451 			     }
452 			     break;
453 			case ROUNDNEAREST:
454 			     if (src_exponent == -1)
455 				if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
456 				   if (Dbl_iszero_sign(srcp1)) {
457 				      Dint_increment(resultp1,resultp2);
458 				   }
459 				   else {
460 				      Dint_decrement(resultp1,resultp2);
461 				   }
462 				}
463 			}
464 		}
465 	}
466 	Dint_copytoptr(resultp1,resultp2,dstptr);
467 	if (inexact) {
468 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
469 		else Set_inexactflag();
470 	}
471 	return(NOEXCEPTION);
472 }
473