xref: /openbsd-src/sys/arch/hppa/spmath/fcnvfx.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: fcnvfx.c,v 1.7 2003/04/10 17:27:58 mickey Exp $	*/
2 /*
3   (c) Copyright 1986 HEWLETT-PACKARD COMPANY
4   To anyone who acknowledges that this file is provided "AS IS"
5   without any express or implied warranty:
6       permission to use, copy, modify, and distribute this file
7   for any purpose is hereby granted without fee, provided that
8   the above copyright notice and this notice appears in all
9   copies, and that the name of Hewlett-Packard Company not be
10   used in advertising or publicity pertaining to distribution
11   of the software without specific, written prior permission.
12   Hewlett-Packard Company makes no representations about the
13   suitability of this software for any purpose.
14 */
15 /* @(#)fcnvfx.c: Revision: 2.8.88.2 Date: 93/12/08 13:27:29 */
16 
17 #include "float.h"
18 #include "sgl_float.h"
19 #include "dbl_float.h"
20 #include "cnv_float.h"
21 
22 /*
23  *  Single Floating-point to Single Fixed-point
24  */
25 /*ARGSUSED*/
26 int
27 sgl_to_sgl_fcnvfx(srcptr, null, dstptr, status)
28 	sgl_floating_point *srcptr, *null;
29 	int *dstptr;
30 	unsigned int *status;
31 {
32 	register unsigned int src, temp;
33 	register int src_exponent, result;
34 	register int inexact = FALSE;
35 
36 	src = *srcptr;
37 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
38 
39 	/*
40 	 * Test for overflow
41 	 */
42 	if (src_exponent > SGL_FX_MAX_EXP) {
43 		/* check for MININT */
44 		if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
45 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
46 			if( Sgl_isnan(src) )
47 			  /*
48 			   * On NaN go unimplemented.
49 			   */
50 			  return(UNIMPLEMENTEDEXCEPTION);
51 			else {
52 			  if (Sgl_iszero_sign(src)) result = 0x7fffffff;
53 			  else result = 0x80000000;
54 
55 			  if (Is_overflowtrap_enabled()) {
56 			    if (Is_inexacttrap_enabled())
57 			      return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
58 			    else Set_inexactflag();
59 			    return(OVERFLOWEXCEPTION);
60 			  }
61 			  Set_overflowflag();
62 			  *dstptr = result;
63 			  if (Is_inexacttrap_enabled() )
64 				return(INEXACTEXCEPTION);
65 			  else Set_inexactflag();
66 			  return(NOEXCEPTION);
67 			}
68 		}
69 	}
70 	/*
71 	 * Generate result
72 	 */
73 	if (src_exponent >= 0) {
74 		temp = src;
75 		Sgl_clear_signexponent_set_hidden(temp);
76 		Int_from_sgl_mantissa(temp,src_exponent);
77 		if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
78 		else result = Sgl_all(temp);
79 
80 		/* check for inexact */
81 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
82 			inexact = TRUE;
83 			/*  round result  */
84 			switch (Rounding_mode()) {
85 			case ROUNDPLUS:
86 			     if (Sgl_iszero_sign(src)) result++;
87 			     break;
88 			case ROUNDMINUS:
89 			     if (Sgl_isone_sign(src)) result--;
90 			     break;
91 			case ROUNDNEAREST:
92 			     if (Sgl_isone_roundbit(src,src_exponent)) {
93 				if (Sgl_isone_stickybit(src,src_exponent)
94 				|| (Sgl_isone_lowmantissa(temp))) {
95 				   if (Sgl_iszero_sign(src)) result++;
96 				   else result--;
97 				}
98 			     }
99 			}
100 		}
101 	}
102 	else {
103 		result = 0;
104 
105 		/* check for inexact */
106 		if (Sgl_isnotzero_exponentmantissa(src)) {
107 			inexact = TRUE;
108 			/*  round result  */
109 			switch (Rounding_mode()) {
110 			case ROUNDPLUS:
111 			     if (Sgl_iszero_sign(src)) result++;
112 			     break;
113 			case ROUNDMINUS:
114 			     if (Sgl_isone_sign(src)) result--;
115 			     break;
116 			case ROUNDNEAREST:
117 			     if (src_exponent == -1)
118 				if (Sgl_isnotzero_mantissa(src)) {
119 				   if (Sgl_iszero_sign(src)) result++;
120 				   else result--;
121 				}
122 			}
123 		}
124 	}
125 	*dstptr = result;
126 	if (inexact) {
127 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
128 		else Set_inexactflag();
129 	}
130 	return(NOEXCEPTION);
131 }
132 
133 /*
134  *  Single Floating-point to Double Fixed-point
135  */
136 /*ARGSUSED*/
137 int
138 sgl_to_dbl_fcnvfx(srcptr, null, dstptr, status)
139 	sgl_floating_point *srcptr, *null;
140 	dbl_integer *dstptr;
141 	unsigned int *status;
142 {
143 	register int src_exponent, resultp1;
144 	register unsigned int src, temp, resultp2;
145 	register int inexact = FALSE;
146 
147 	src = *srcptr;
148 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
149 
150 	/*
151 	 * Test for overflow
152 	 */
153 	if (src_exponent > DBL_FX_MAX_EXP) {
154 		/* check for MININT */
155 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
156 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
157 			if( Sgl_isnan(src) )
158 			  /*
159 			   * On NaN go unimplemented.
160 			   */
161 			  return(UNIMPLEMENTEDEXCEPTION);
162 			else {
163 			  if (Sgl_iszero_sign(src)) {
164 				resultp1 = 0x7fffffff;
165 			      resultp2 = 0xffffffff;
166 			  }
167 			  else {
168 			    resultp1 = 0x80000000;
169 			    resultp2 = 0;
170 			  }
171 			  if (Is_overflowtrap_enabled()) {
172 			    if (Is_inexacttrap_enabled())
173 			      return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
174 			    else Set_inexactflag();
175 			    return(OVERFLOWEXCEPTION);
176 			  }
177 			  Set_overflowflag();
178 			  Dint_copytoptr(resultp1,resultp2,dstptr);
179 			  if (Is_inexacttrap_enabled() )
180 				return(INEXACTEXCEPTION);
181 			  else Set_inexactflag();
182 			  return(NOEXCEPTION);
183 			}
184 		}
185 		Dint_set_minint(resultp1,resultp2);
186 		Dint_copytoptr(resultp1,resultp2,dstptr);
187 		return(NOEXCEPTION);
188 	}
189 	/*
190 	 * Generate result
191 	 */
192 	if (src_exponent >= 0) {
193 		temp = src;
194 		Sgl_clear_signexponent_set_hidden(temp);
195 		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
196 		if (Sgl_isone_sign(src)) {
197 			Dint_setone_sign(resultp1,resultp2);
198 		}
199 
200 		/* check for inexact */
201 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
202 			inexact = TRUE;
203 			/*  round result  */
204 			switch (Rounding_mode()) {
205 			case ROUNDPLUS:
206 			     if (Sgl_iszero_sign(src)) {
207 				Dint_increment(resultp1,resultp2);
208 			     }
209 			     break;
210 			case ROUNDMINUS:
211 			     if (Sgl_isone_sign(src)) {
212 				Dint_decrement(resultp1,resultp2);
213 			     }
214 			     break;
215 			case ROUNDNEAREST:
216 			     if (Sgl_isone_roundbit(src,src_exponent))
217 				if (Sgl_isone_stickybit(src,src_exponent) ||
218 				(Dint_isone_lowp2(resultp2))) {
219 				   if (Sgl_iszero_sign(src)) {
220 				      Dint_increment(resultp1,resultp2);
221 				   }
222 				   else {
223 				      Dint_decrement(resultp1,resultp2);
224 				   }
225 				}
226 			}
227 		}
228 	}
229 	else {
230 		Dint_setzero(resultp1,resultp2);
231 
232 		/* check for inexact */
233 		if (Sgl_isnotzero_exponentmantissa(src)) {
234 			inexact = TRUE;
235 			/*  round result  */
236 			switch (Rounding_mode()) {
237 			case ROUNDPLUS:
238 			     if (Sgl_iszero_sign(src)) {
239 				Dint_increment(resultp1,resultp2);
240 			     }
241 			     break;
242 			case ROUNDMINUS:
243 			     if (Sgl_isone_sign(src)) {
244 				Dint_decrement(resultp1,resultp2);
245 			     }
246 			     break;
247 			case ROUNDNEAREST:
248 			     if (src_exponent == -1)
249 				if (Sgl_isnotzero_mantissa(src)) {
250 				   if (Sgl_iszero_sign(src)) {
251 				      Dint_increment(resultp1,resultp2);
252 				   }
253 				   else {
254 				      Dint_decrement(resultp1,resultp2);
255 				   }
256 				}
257 			}
258 		}
259 	}
260 	Dint_copytoptr(resultp1,resultp2,dstptr);
261 	if (inexact) {
262 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
263 		else Set_inexactflag();
264 	}
265 	return(NOEXCEPTION);
266 }
267 
268 /*
269  *  Double Floating-point to Single Fixed-point
270  */
271 /*ARGSUSED*/
272 int
273 dbl_to_sgl_fcnvfx(srcptr, null, dstptr, status)
274 	dbl_floating_point *srcptr, *null;
275 	int *dstptr;
276 	unsigned int *status;
277 {
278 	register unsigned int srcp1,srcp2, tempp1,tempp2;
279 	register int src_exponent, result;
280 	register int inexact = FALSE;
281 
282 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
283 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
284 
285 	/*
286 	 * Test for overflow
287 	 */
288 	if (src_exponent > SGL_FX_MAX_EXP) {
289 		/* check for MININT */
290 		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
291 			if( Dbl_isnan(srcp1,srcp2) )
292 			  /*
293 			   * On NaN go unimplemented.
294 			   */
295 			  return(UNIMPLEMENTEDEXCEPTION);
296 			else {
297 			  if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
298 			  else result = 0x80000000;
299 
300 			  if (Is_overflowtrap_enabled()) {
301 			    if (Is_inexacttrap_enabled())
302 			      return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
303 			    else Set_inexactflag();
304 			    return(OVERFLOWEXCEPTION);
305 			    }
306 			  Set_overflowflag();
307 			  *dstptr = result;
308 			  if (Is_inexacttrap_enabled() )
309 				return(INEXACTEXCEPTION);
310 			  else Set_inexactflag();
311 			  return(NOEXCEPTION);
312 			}
313 		}
314 	}
315 	/*
316 	 * Generate result
317 	 */
318 	if (src_exponent >= 0) {
319 		tempp1 = srcp1;
320 		tempp2 = srcp2;
321 		Dbl_clear_signexponent_set_hidden(tempp1);
322 		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
323 		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
324 			result = -Dbl_allp1(tempp1);
325 		else result = Dbl_allp1(tempp1);
326 
327 		/* check for inexact */
328 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
329 			inexact = TRUE;
330 			/*  round result  */
331 			switch (Rounding_mode()) {
332 			case ROUNDPLUS:
333 				if (Dbl_iszero_sign(srcp1))
334 					result++;
335 				break;
336 			case ROUNDMINUS:
337 				if (Dbl_isone_sign(srcp1)) result--;
338 				break;
339 			case ROUNDNEAREST:
340 				if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
341 				if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
342 				(Dbl_isone_lowmantissap1(tempp1))) {
343 					if (Dbl_iszero_sign(srcp1)) result++;
344 					else result--;
345 				}
346 			}
347 			/* check for overflow */
348 			if ((Dbl_iszero_sign(srcp1) && result < 0) ||
349 			    (Dbl_isone_sign(srcp1) && result > 0)) {
350 
351 				if (Dbl_iszero_sign(srcp1))
352 					result = 0x7fffffff;
353 				else
354 					result = 0x80000000;
355 
356 			    if (Is_overflowtrap_enabled()) {
357 			    if (Is_inexacttrap_enabled())
358 			      return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
359 			    else Set_inexactflag();
360 			    return(OVERFLOWEXCEPTION);
361 			    }
362 			  Set_overflowflag();
363 			  *dstptr = result;
364 			  if (Is_inexacttrap_enabled() )
365 				return(INEXACTEXCEPTION);
366 			  else Set_inexactflag();
367 			  return(NOEXCEPTION);
368 			}
369 		}
370 	}
371 	else {
372 		result = 0;
373 
374 		/* check for inexact */
375 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
376 			inexact = TRUE;
377 			/*  round result  */
378 			switch (Rounding_mode()) {
379 			case ROUNDPLUS:
380 				if (Dbl_iszero_sign(srcp1)) result++;
381 					break;
382 			case ROUNDMINUS:
383 				if (Dbl_isone_sign(srcp1)) result--;
384 				break;
385 			case ROUNDNEAREST:
386 				if (src_exponent == -1)
387 				if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
388 					if (Dbl_iszero_sign(srcp1)) result++;
389 					else result--;
390 				}
391 			}
392 		}
393 	}
394 	*dstptr = result;
395 	if (inexact) {
396 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
397 		else Set_inexactflag();
398 	}
399 	return(NOEXCEPTION);
400 }
401 
402 /*
403  *  Double Floating-point to Double Fixed-point
404  */
405 /*ARGSUSED*/
406 int
407 dbl_to_dbl_fcnvfx(srcptr, null, dstptr, status)
408 	dbl_floating_point *srcptr, *null;
409 	dbl_integer *dstptr;
410 	unsigned int *status;
411 {
412 	register int src_exponent, resultp1;
413 	register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
414 	register int inexact = FALSE;
415 
416 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
417 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
418 
419 	/*
420 	 * Test for overflow
421 	 */
422 	if (src_exponent > DBL_FX_MAX_EXP) {
423 		/* check for MININT */
424 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
425 		Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
426 			if( Dbl_isnan(srcp1,srcp2) )
427 			  /*
428 			   * On NaN go unimplemented.
429 			   */
430 			  return(UNIMPLEMENTEDEXCEPTION);
431 			else {
432 			  if (Dbl_iszero_sign(srcp1)) {
433 			     resultp1 = 0x7fffffff;
434 			      resultp2 = 0xffffffff;
435 			  }
436 			  else {
437 			    resultp1 = 0x80000000;
438 			    resultp2 = 0;
439 			  }
440 			  if (Is_overflowtrap_enabled()) {
441 			    if (Is_inexacttrap_enabled())
442 			      return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
443 			    else Set_inexactflag();
444 			    return(OVERFLOWEXCEPTION);
445 			  }
446 			  Set_overflowflag();
447 			  Dint_copytoptr(resultp1,resultp2,dstptr);
448 			  if (Is_inexacttrap_enabled() )
449 				return(INEXACTEXCEPTION);
450 			  else Set_inexactflag();
451 			  return(NOEXCEPTION);
452 			}
453 		}
454 	}
455 
456 	/*
457 	 * Generate result
458 	 */
459 	if (src_exponent >= 0) {
460 		tempp1 = srcp1;
461 		tempp2 = srcp2;
462 		Dbl_clear_signexponent_set_hidden(tempp1);
463 		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
464 				       resultp1, resultp2);
465 		if (Dbl_isone_sign(srcp1)) {
466 			Dint_setone_sign(resultp1,resultp2);
467 		}
468 
469 		/* check for inexact */
470 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
471 			inexact = TRUE;
472 			/*  round result  */
473 			switch (Rounding_mode()) {
474 			case ROUNDPLUS:
475 			     if (Dbl_iszero_sign(srcp1)) {
476 				Dint_increment(resultp1,resultp2);
477 			     }
478 			     break;
479 			case ROUNDMINUS:
480 			     if (Dbl_isone_sign(srcp1)) {
481 				Dint_decrement(resultp1,resultp2);
482 			     }
483 			     break;
484 			case ROUNDNEAREST:
485 			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
486 				if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
487 				(Dint_isone_lowp2(resultp2))) {
488 				   if (Dbl_iszero_sign(srcp1)) {
489 				      Dint_increment(resultp1,resultp2);
490 				   }
491 				   else {
492 				      Dint_decrement(resultp1,resultp2);
493 				   }
494 				}
495 			}
496 		}
497 	}
498 	else {
499 		Dint_setzero(resultp1,resultp2);
500 
501 		/* check for inexact */
502 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
503 			inexact = TRUE;
504 			/*  round result  */
505 			switch (Rounding_mode()) {
506 			case ROUNDPLUS:
507 			     if (Dbl_iszero_sign(srcp1)) {
508 				Dint_increment(resultp1,resultp2);
509 			     }
510 			     break;
511 			case ROUNDMINUS:
512 			     if (Dbl_isone_sign(srcp1)) {
513 				Dint_decrement(resultp1,resultp2);
514 			     }
515 			     break;
516 			case ROUNDNEAREST:
517 			     if (src_exponent == -1)
518 				if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
519 				   if (Dbl_iszero_sign(srcp1)) {
520 				      Dint_increment(resultp1,resultp2);
521 				   }
522 				   else {
523 				      Dint_decrement(resultp1,resultp2);
524 				   }
525 				}
526 			}
527 		}
528 	}
529 	Dint_copytoptr(resultp1,resultp2,dstptr);
530 	if (inexact) {
531 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
532 		else Set_inexactflag();
533 	}
534 	return(NOEXCEPTION);
535 }
536