xref: /openbsd/sys/arch/hppa/spmath/fcnvfx.c (revision 5b133f3f)
1 /*	$OpenBSD: fcnvfx.c,v 1.9 2023/03/08 04:43:07 guenther 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 int
sgl_to_sgl_fcnvfx(srcptr,null,dstptr,status)26 sgl_to_sgl_fcnvfx(srcptr, null, dstptr, status)
27 	sgl_floating_point *srcptr, *null;
28 	int *dstptr;
29 	unsigned int *status;
30 {
31 	register unsigned int src, temp;
32 	register int src_exponent, result;
33 	register int inexact = FALSE;
34 
35 	src = *srcptr;
36 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
37 
38 	/*
39 	 * Test for overflow
40 	 */
41 	if (src_exponent > SGL_FX_MAX_EXP) {
42 		/* check for MININT */
43 		if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
44 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
45 			if (Sgl_iszero_sign(src)) result = 0x7fffffff;
46 			else result = 0x80000000;
47 
48 			if (Is_invalidtrap_enabled()) {
49 				return(INVALIDEXCEPTION);
50 			}
51 			Set_invalidflag();
52 			*dstptr = result;
53 			return(NOEXCEPTION);
54 		}
55 	}
56 	/*
57 	 * Generate result
58 	 */
59 	if (src_exponent >= 0) {
60 		temp = src;
61 		Sgl_clear_signexponent_set_hidden(temp);
62 		Int_from_sgl_mantissa(temp,src_exponent);
63 		if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
64 		else result = Sgl_all(temp);
65 
66 		/* check for inexact */
67 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
68 			inexact = TRUE;
69 			/*  round result  */
70 			switch (Rounding_mode()) {
71 			case ROUNDPLUS:
72 			     if (Sgl_iszero_sign(src)) result++;
73 			     break;
74 			case ROUNDMINUS:
75 			     if (Sgl_isone_sign(src)) result--;
76 			     break;
77 			case ROUNDNEAREST:
78 			     if (Sgl_isone_roundbit(src,src_exponent)) {
79 				if (Sgl_isone_stickybit(src,src_exponent)
80 				|| (Sgl_isone_lowmantissa(temp))) {
81 				   if (Sgl_iszero_sign(src)) result++;
82 				   else result--;
83 				}
84 			     }
85 			}
86 		}
87 	}
88 	else {
89 		result = 0;
90 
91 		/* check for inexact */
92 		if (Sgl_isnotzero_exponentmantissa(src)) {
93 			inexact = TRUE;
94 			/*  round result  */
95 			switch (Rounding_mode()) {
96 			case ROUNDPLUS:
97 			     if (Sgl_iszero_sign(src)) result++;
98 			     break;
99 			case ROUNDMINUS:
100 			     if (Sgl_isone_sign(src)) result--;
101 			     break;
102 			case ROUNDNEAREST:
103 			     if (src_exponent == -1)
104 				if (Sgl_isnotzero_mantissa(src)) {
105 				   if (Sgl_iszero_sign(src)) result++;
106 				   else result--;
107 				}
108 			}
109 		}
110 	}
111 	*dstptr = result;
112 	if (inexact) {
113 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
114 		else Set_inexactflag();
115 	}
116 	return(NOEXCEPTION);
117 }
118 
119 /*
120  *  Single Floating-point to Double Fixed-point
121  */
122 int
sgl_to_dbl_fcnvfx(srcptr,null,dstptr,status)123 sgl_to_dbl_fcnvfx(srcptr, null, dstptr, status)
124 	sgl_floating_point *srcptr, *null;
125 	dbl_integer *dstptr;
126 	unsigned int *status;
127 {
128 	register int src_exponent, resultp1;
129 	register unsigned int src, temp, resultp2;
130 	register int inexact = FALSE;
131 
132 	src = *srcptr;
133 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
134 
135 	/*
136 	 * Test for overflow
137 	 */
138 	if (src_exponent > DBL_FX_MAX_EXP) {
139 		/* check for MININT */
140 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
141 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
142 			if (Sgl_iszero_sign(src)) {
143 				resultp1 = 0x7fffffff;
144 				resultp2 = 0xffffffff;
145 			}
146 			else {
147 				resultp1 = 0x80000000;
148 				resultp2 = 0;
149 			}
150 
151 			if (Is_invalidtrap_enabled()) {
152 				return(INVALIDEXCEPTION);
153 			}
154 			Set_invalidflag();
155 			Dint_copytoptr(resultp1,resultp2,dstptr);
156 			return(NOEXCEPTION);
157 		}
158 		Dint_set_minint(resultp1,resultp2);
159 		Dint_copytoptr(resultp1,resultp2,dstptr);
160 		return(NOEXCEPTION);
161 	}
162 	/*
163 	 * Generate result
164 	 */
165 	if (src_exponent >= 0) {
166 		temp = src;
167 		Sgl_clear_signexponent_set_hidden(temp);
168 		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
169 		if (Sgl_isone_sign(src)) {
170 			Dint_setone_sign(resultp1,resultp2);
171 		}
172 
173 		/* check for inexact */
174 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
175 			inexact = TRUE;
176 			/*  round result  */
177 			switch (Rounding_mode()) {
178 			case ROUNDPLUS:
179 			     if (Sgl_iszero_sign(src)) {
180 				Dint_increment(resultp1,resultp2);
181 			     }
182 			     break;
183 			case ROUNDMINUS:
184 			     if (Sgl_isone_sign(src)) {
185 				Dint_decrement(resultp1,resultp2);
186 			     }
187 			     break;
188 			case ROUNDNEAREST:
189 			     if (Sgl_isone_roundbit(src,src_exponent))
190 				if (Sgl_isone_stickybit(src,src_exponent) ||
191 				(Dint_isone_lowp2(resultp2))) {
192 				   if (Sgl_iszero_sign(src)) {
193 				      Dint_increment(resultp1,resultp2);
194 				   }
195 				   else {
196 				      Dint_decrement(resultp1,resultp2);
197 				   }
198 				}
199 			}
200 		}
201 	}
202 	else {
203 		Dint_setzero(resultp1,resultp2);
204 
205 		/* check for inexact */
206 		if (Sgl_isnotzero_exponentmantissa(src)) {
207 			inexact = TRUE;
208 			/*  round result  */
209 			switch (Rounding_mode()) {
210 			case ROUNDPLUS:
211 			     if (Sgl_iszero_sign(src)) {
212 				Dint_increment(resultp1,resultp2);
213 			     }
214 			     break;
215 			case ROUNDMINUS:
216 			     if (Sgl_isone_sign(src)) {
217 				Dint_decrement(resultp1,resultp2);
218 			     }
219 			     break;
220 			case ROUNDNEAREST:
221 			     if (src_exponent == -1)
222 				if (Sgl_isnotzero_mantissa(src)) {
223 				   if (Sgl_iszero_sign(src)) {
224 				      Dint_increment(resultp1,resultp2);
225 				   }
226 				   else {
227 				      Dint_decrement(resultp1,resultp2);
228 				   }
229 				}
230 			}
231 		}
232 	}
233 	Dint_copytoptr(resultp1,resultp2,dstptr);
234 	if (inexact) {
235 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
236 		else Set_inexactflag();
237 	}
238 	return(NOEXCEPTION);
239 }
240 
241 /*
242  *  Double Floating-point to Single Fixed-point
243  */
244 int
dbl_to_sgl_fcnvfx(srcptr,null,dstptr,status)245 dbl_to_sgl_fcnvfx(srcptr, null, dstptr, status)
246 	dbl_floating_point *srcptr, *null;
247 	int *dstptr;
248 	unsigned int *status;
249 {
250 	register unsigned int srcp1,srcp2, tempp1,tempp2;
251 	register int src_exponent, result;
252 	register int inexact = FALSE;
253 
254 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
255 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
256 
257 	/*
258 	 * Test for overflow
259 	 */
260 	if (src_exponent > SGL_FX_MAX_EXP) {
261 		/* check for MININT */
262 		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
263 			if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
264 			else result = 0x80000000;
265 
266 			if (Is_invalidtrap_enabled()) {
267 				return(INVALIDEXCEPTION);
268 			}
269 			Set_invalidflag();
270 			*dstptr = result;
271 			return(NOEXCEPTION);
272 		}
273 	}
274 	/*
275 	 * Generate result
276 	 */
277 	if (src_exponent >= 0) {
278 		tempp1 = srcp1;
279 		tempp2 = srcp2;
280 		Dbl_clear_signexponent_set_hidden(tempp1);
281 		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
282 		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
283 			result = -Dbl_allp1(tempp1);
284 		else result = Dbl_allp1(tempp1);
285 
286 		/* check for inexact */
287 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
288 			inexact = TRUE;
289 			/*  round result  */
290 			switch (Rounding_mode()) {
291 			case ROUNDPLUS:
292 				if (Dbl_iszero_sign(srcp1))
293 					result++;
294 				break;
295 			case ROUNDMINUS:
296 				if (Dbl_isone_sign(srcp1)) result--;
297 				break;
298 			case ROUNDNEAREST:
299 				if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
300 				if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
301 				(Dbl_isone_lowmantissap1(tempp1))) {
302 					if (Dbl_iszero_sign(srcp1)) result++;
303 					else result--;
304 				}
305 			}
306 			/* check for overflow */
307 			if ((Dbl_iszero_sign(srcp1) && result < 0) ||
308 			    (Dbl_isone_sign(srcp1) && result > 0)) {
309 
310 				if (Dbl_iszero_sign(srcp1))
311 					result = 0x7fffffff;
312 				else
313 					result = 0x80000000;
314 
315 			    if (Is_overflowtrap_enabled()) {
316 			    if (Is_inexacttrap_enabled())
317 			      return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
318 			    else Set_inexactflag();
319 			    return(OVERFLOWEXCEPTION);
320 			    }
321 			  Set_overflowflag();
322 			  *dstptr = result;
323 			  if (Is_inexacttrap_enabled() )
324 				return(INEXACTEXCEPTION);
325 			  else Set_inexactflag();
326 			  return(NOEXCEPTION);
327 			}
328 		}
329 	}
330 	else {
331 		result = 0;
332 
333 		/* check for inexact */
334 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
335 			inexact = TRUE;
336 			/*  round result  */
337 			switch (Rounding_mode()) {
338 			case ROUNDPLUS:
339 				if (Dbl_iszero_sign(srcp1)) result++;
340 					break;
341 			case ROUNDMINUS:
342 				if (Dbl_isone_sign(srcp1)) result--;
343 				break;
344 			case ROUNDNEAREST:
345 				if (src_exponent == -1)
346 				if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
347 					if (Dbl_iszero_sign(srcp1)) result++;
348 					else result--;
349 				}
350 			}
351 		}
352 	}
353 	*dstptr = result;
354 	if (inexact) {
355 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
356 		else Set_inexactflag();
357 	}
358 	return(NOEXCEPTION);
359 }
360 
361 /*
362  *  Double Floating-point to Double Fixed-point
363  */
364 int
dbl_to_dbl_fcnvfx(srcptr,null,dstptr,status)365 dbl_to_dbl_fcnvfx(srcptr, null, dstptr, status)
366 	dbl_floating_point *srcptr, *null;
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 			if (Dbl_iszero_sign(srcp1)) {
385 				resultp1 = 0x7fffffff;
386 				resultp2 = 0xffffffff;
387 			}
388 			else {
389 				resultp1 = 0x80000000;
390 				resultp2 = 0;
391 			}
392 
393 			if (Is_invalidtrap_enabled()) {
394 				return(INVALIDEXCEPTION);
395 			}
396 			Set_invalidflag();
397 			Dint_copytoptr(resultp1,resultp2,dstptr);
398 			return(NOEXCEPTION);
399 		}
400 	}
401 
402 	/*
403 	 * Generate result
404 	 */
405 	if (src_exponent >= 0) {
406 		tempp1 = srcp1;
407 		tempp2 = srcp2;
408 		Dbl_clear_signexponent_set_hidden(tempp1);
409 		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
410 				       resultp1, resultp2);
411 		if (Dbl_isone_sign(srcp1)) {
412 			Dint_setone_sign(resultp1,resultp2);
413 		}
414 
415 		/* check for inexact */
416 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
417 			inexact = TRUE;
418 			/*  round result  */
419 			switch (Rounding_mode()) {
420 			case ROUNDPLUS:
421 			     if (Dbl_iszero_sign(srcp1)) {
422 				Dint_increment(resultp1,resultp2);
423 			     }
424 			     break;
425 			case ROUNDMINUS:
426 			     if (Dbl_isone_sign(srcp1)) {
427 				Dint_decrement(resultp1,resultp2);
428 			     }
429 			     break;
430 			case ROUNDNEAREST:
431 			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
432 				if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
433 				(Dint_isone_lowp2(resultp2))) {
434 				   if (Dbl_iszero_sign(srcp1)) {
435 				      Dint_increment(resultp1,resultp2);
436 				   }
437 				   else {
438 				      Dint_decrement(resultp1,resultp2);
439 				   }
440 				}
441 			}
442 		}
443 	}
444 	else {
445 		Dint_setzero(resultp1,resultp2);
446 
447 		/* check for inexact */
448 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
449 			inexact = TRUE;
450 			/*  round result  */
451 			switch (Rounding_mode()) {
452 			case ROUNDPLUS:
453 			     if (Dbl_iszero_sign(srcp1)) {
454 				Dint_increment(resultp1,resultp2);
455 			     }
456 			     break;
457 			case ROUNDMINUS:
458 			     if (Dbl_isone_sign(srcp1)) {
459 				Dint_decrement(resultp1,resultp2);
460 			     }
461 			     break;
462 			case ROUNDNEAREST:
463 			     if (src_exponent == -1)
464 				if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
465 				   if (Dbl_iszero_sign(srcp1)) {
466 				      Dint_increment(resultp1,resultp2);
467 				   }
468 				   else {
469 				      Dint_decrement(resultp1,resultp2);
470 				   }
471 				}
472 			}
473 		}
474 	}
475 	Dint_copytoptr(resultp1,resultp2,dstptr);
476 	if (inexact) {
477 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
478 		else Set_inexactflag();
479 	}
480 	return(NOEXCEPTION);
481 }
482