PageRenderTime 68ms CodeModel.GetById 10ms app.highlight 53ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/parisc/math-emu/fcnvfu.c

https://bitbucket.org/evzijst/gittest
C | 536 lines | 393 code | 25 blank | 118 comment | 102 complexity | 9e7bfb0ce27c0927010528242e001086 MD5 | raw file
  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/fcnvfu.c		$Revision: 1.1 $
 26 *
 27 *  Purpose:
 28 *	Floating-point to Unsigned Fixed-point Converts
 29 *
 30 *  External Interfaces:
 31 *	dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
 32 *	dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
 33 *	sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
 34 *	sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
 35 *
 36 *  Internal Interfaces:
 37 *
 38 *  Theory:
 39 *	<<please update with a overview of the operation of this file>>
 40 *
 41 * END_DESC
 42*/
 43
 44
 45#include "float.h"
 46#include "sgl_float.h"
 47#include "dbl_float.h"
 48#include "cnv_float.h"
 49
 50/************************************************************************
 51 *  Floating-point to Unsigned Fixed-point Converts			*
 52 ************************************************************************/
 53
 54/*
 55 *  Single Floating-point to Single Unsigned Fixed 
 56 */
 57/*ARGSUSED*/
 58int
 59sgl_to_sgl_fcnvfu(
 60			sgl_floating_point *srcptr,
 61			unsigned int *nullptr,
 62			unsigned int *dstptr,
 63			unsigned int *status)
 64{
 65	register unsigned int src, result;
 66	register int src_exponent;
 67	register boolean inexact = FALSE;
 68
 69	src = *srcptr;
 70	src_exponent = Sgl_exponent(src) - SGL_BIAS;
 71
 72	/* 
 73	 * Test for overflow
 74	 */
 75	if (src_exponent > SGL_FX_MAX_EXP + 1) {
 76		if (Sgl_isone_sign(src)) {
 77			result = 0;
 78		} else {
 79			result = 0xffffffff;
 80		}
 81		if (Is_invalidtrap_enabled()) {
 82			return(INVALIDEXCEPTION);
 83		}
 84		Set_invalidflag();
 85		*dstptr = result;
 86		return(NOEXCEPTION);
 87	}
 88	/*
 89	 * Generate result
 90	 */
 91	if (src_exponent >= 0) {
 92		/* 
 93		 * Check sign.
 94		 * If negative, trap unimplemented.
 95		 */
 96		if (Sgl_isone_sign(src)) {
 97			result = 0;
 98			if (Is_invalidtrap_enabled()) {
 99				return(INVALIDEXCEPTION);
100			}
101			Set_invalidflag();
102			*dstptr = result;
103			return(NOEXCEPTION);
104		}
105		Sgl_clear_signexponent_set_hidden(src);
106		Suint_from_sgl_mantissa(src,src_exponent,result);
107
108		/* check for inexact */
109		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
110			inexact = TRUE;
111			/*  round result  */
112			switch (Rounding_mode()) {
113			case ROUNDPLUS:
114				result++;
115				break;
116			case ROUNDMINUS: /* never negative */
117				break;
118			case ROUNDNEAREST:
119				if (Sgl_isone_roundbit(src,src_exponent) &&
120				    (Sgl_isone_stickybit(src,src_exponent) ||
121				     (result & 1))) {
122			     		result++;
123				}
124				break;
125			}
126		}
127	} else {
128		result = 0;
129
130		/* check for inexact */
131		if (Sgl_isnotzero_exponentmantissa(src)) {
132			inexact = TRUE;
133			/*  round result  */
134			switch (Rounding_mode()) {
135			case ROUNDPLUS:
136				if (Sgl_iszero_sign(src)) {
137					result++;
138				}
139				break;
140			case ROUNDMINUS:
141				if (Sgl_isone_sign(src)) {
142					result = 0;
143					if (Is_invalidtrap_enabled()) {
144						return(INVALIDEXCEPTION);
145					}
146					Set_invalidflag();
147					inexact = FALSE;
148				}
149				break;
150			case ROUNDNEAREST:
151				if (src_exponent == -1 &&
152				    Sgl_isnotzero_mantissa(src)) {
153					if (Sgl_isone_sign(src)) {
154						result = 0;
155						if (Is_invalidtrap_enabled()) {
156							return(INVALIDEXCEPTION);
157						}
158						Set_invalidflag();
159						inexact = FALSE;
160					}
161			      		else result++;
162				}
163				break;
164			}
165		}
166	}
167	*dstptr = result;
168	if (inexact) {
169		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
170		else Set_inexactflag();
171	}
172	return(NOEXCEPTION);
173}
174
175/*
176 *  Single Floating-point to Double Unsigned Fixed 
177 */
178/*ARGSUSED*/
179int
180sgl_to_dbl_fcnvfu(
181		    sgl_floating_point *srcptr,
182		    unsigned int *nullptr,
183		    dbl_unsigned *dstptr,
184		    unsigned int *status)
185{
186	register int src_exponent;
187	register unsigned int src, resultp1, resultp2;
188	register boolean inexact = FALSE;
189
190	src = *srcptr;
191	src_exponent = Sgl_exponent(src) - SGL_BIAS;
192
193	/* 
194	 * Test for overflow
195	 */
196	if (src_exponent > DBL_FX_MAX_EXP + 1) {
197		if (Sgl_isone_sign(src)) {
198			resultp1 = resultp2 = 0;
199		} else {
200			resultp1 = resultp2 = 0xffffffff;
201		}
202		if (Is_invalidtrap_enabled()) {
203			return(INVALIDEXCEPTION);
204		}
205		Set_invalidflag();
206    		Duint_copytoptr(resultp1,resultp2,dstptr);
207		return(NOEXCEPTION);
208	}
209	/*
210	 * Generate result
211	 */
212	if (src_exponent >= 0) {
213		/* 
214		 * Check sign.
215		 * If negative, trap unimplemented.
216		 */
217		if (Sgl_isone_sign(src)) {
218			resultp1 = resultp2 = 0;
219			if (Is_invalidtrap_enabled()) {
220				return(INVALIDEXCEPTION);
221			}
222			Set_invalidflag();
223    			Duint_copytoptr(resultp1,resultp2,dstptr);
224			return(NOEXCEPTION);
225		}
226		Sgl_clear_signexponent_set_hidden(src);
227		Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
228
229		/* check for inexact */
230		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
231			inexact = TRUE;
232			/*  round result  */
233			switch (Rounding_mode()) {
234			case ROUNDPLUS:
235				Duint_increment(resultp1,resultp2);
236				break;
237			case ROUNDMINUS: /* never negative */
238				break;
239			case ROUNDNEAREST:
240				if (Sgl_isone_roundbit(src,src_exponent) &&
241				    (Sgl_isone_stickybit(src,src_exponent) || 
242				     Duint_isone_lowp2(resultp2))) {
243					Duint_increment(resultp1,resultp2);
244				}
245				break;
246			}
247		}
248	} else {
249		Duint_setzero(resultp1,resultp2);
250
251		/* check for inexact */
252		if (Sgl_isnotzero_exponentmantissa(src)) {
253			inexact = TRUE;
254			/*  round result  */
255			switch (Rounding_mode()) {
256			case ROUNDPLUS:
257				if (Sgl_iszero_sign(src)) {
258					Duint_increment(resultp1,resultp2);
259				}
260				break;
261			case ROUNDMINUS:
262				if (Sgl_isone_sign(src)) {
263					resultp1 = resultp2 = 0;
264					if (Is_invalidtrap_enabled()) {
265						return(INVALIDEXCEPTION);
266					}
267					Set_invalidflag();
268					inexact = FALSE;
269				}
270				break;
271			case ROUNDNEAREST:
272				if (src_exponent == -1 &&
273				    Sgl_isnotzero_mantissa(src)) {
274					if (Sgl_isone_sign(src)) {
275						resultp1 = 0;
276						resultp2 = 0;
277						if (Is_invalidtrap_enabled()) {
278							return(INVALIDEXCEPTION);
279						}
280						Set_invalidflag();
281						inexact = FALSE;
282					}
283					else Duint_increment(resultp1,resultp2);
284				}
285			}
286		}
287	}
288	Duint_copytoptr(resultp1,resultp2,dstptr);
289	if (inexact) {
290		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
291		else Set_inexactflag();
292	}
293	return(NOEXCEPTION);
294}
295
296/*
297 *  Double Floating-point to Single Unsigned Fixed 
298 */
299/*ARGSUSED*/
300int
301dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
302		   unsigned int *dstptr, unsigned int *status)
303{
304	register unsigned int srcp1, srcp2, result;
305	register int src_exponent;
306	register boolean inexact = FALSE;
307
308	Dbl_copyfromptr(srcptr,srcp1,srcp2);
309	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
310
311	/* 
312	 * Test for overflow
313	 */
314	if (src_exponent > SGL_FX_MAX_EXP + 1) {
315		if (Dbl_isone_sign(srcp1)) {
316			result = 0;
317		} else {
318			result = 0xffffffff;
319		}
320		if (Is_invalidtrap_enabled()) {
321			return(INVALIDEXCEPTION);
322		}
323		Set_invalidflag();
324		*dstptr = result;
325		return(NOEXCEPTION);
326	}
327	/*
328	 * Generate result
329	 */
330	if (src_exponent >= 0) {
331		/* 
332		 * Check sign.
333		 * If negative, trap unimplemented.
334		 */
335		if (Dbl_isone_sign(srcp1)) {
336			result = 0;
337			if (Is_invalidtrap_enabled()) {
338				return(INVALIDEXCEPTION);
339			}
340			Set_invalidflag();
341			*dstptr = result;
342			return(NOEXCEPTION);
343		}
344		Dbl_clear_signexponent_set_hidden(srcp1);
345		Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
346
347		/* check for inexact */
348		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
349			inexact = TRUE;
350			/*  round result  */
351			switch (Rounding_mode()) {
352			case ROUNDPLUS:
353			     result++;
354			     break;
355			case ROUNDMINUS: /* never negative */
356			     break;
357			case ROUNDNEAREST:
358			     if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) &&
359				(Dbl_isone_stickybit(srcp1,srcp2,src_exponent)||
360				 result&1))
361				   result++;
362			     break;
363			}
364			/* check for overflow */
365			if (result == 0) {
366				result = 0xffffffff;
367				if (Is_invalidtrap_enabled()) {
368					return(INVALIDEXCEPTION);
369				}
370				Set_invalidflag();
371				*dstptr = result;
372				return(NOEXCEPTION);
373			}
374		}
375	} else {
376		result = 0;
377
378		/* check for inexact */
379		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
380			inexact = TRUE;
381			/*  round result  */
382			switch (Rounding_mode()) {
383			case ROUNDPLUS:
384				if (Dbl_iszero_sign(srcp1)) result++;
385				break;
386			case ROUNDMINUS:
387				if (Dbl_isone_sign(srcp1)) {
388					result = 0;
389					if (Is_invalidtrap_enabled()) {
390						return(INVALIDEXCEPTION);
391					}
392					Set_invalidflag();
393					inexact = FALSE;
394				}
395				break;
396			case ROUNDNEAREST:
397				if (src_exponent == -1 &&
398				    Dbl_isnotzero_mantissa(srcp1,srcp2))
399					if (Dbl_isone_sign(srcp1)) {
400						result = 0;
401						if (Is_invalidtrap_enabled()) {
402							return(INVALIDEXCEPTION);
403						}
404						Set_invalidflag();
405						inexact = FALSE;
406					}
407					else result++;
408			}
409		}
410	}
411	*dstptr = result;
412	if (inexact) {
413		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
414		else Set_inexactflag();
415	}
416	return(NOEXCEPTION);
417}
418
419/*
420 *  Double Floating-point to Double Unsigned Fixed 
421 */
422/*ARGSUSED*/
423int
424dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
425		   dbl_unsigned * dstptr, unsigned int *status)
426{
427	register int src_exponent;
428	register unsigned int srcp1, srcp2, resultp1, resultp2;
429	register boolean inexact = FALSE;
430
431	Dbl_copyfromptr(srcptr,srcp1,srcp2);
432	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
433
434	/* 
435	 * Test for overflow
436	 */
437	if (src_exponent > DBL_FX_MAX_EXP + 1) {
438		if (Dbl_isone_sign(srcp1)) {
439			resultp1 = resultp2 = 0;
440		} else {
441			resultp1 = resultp2 = 0xffffffff;
442		}
443		if (Is_invalidtrap_enabled()) {
444			return(INVALIDEXCEPTION);
445		}
446		Set_invalidflag();
447    		Duint_copytoptr(resultp1,resultp2,dstptr);
448		return(NOEXCEPTION);
449	}
450 
451	/*
452	 * Generate result
453	 */
454	if (src_exponent >= 0) {
455		/* 
456		 * Check sign.
457		 * If negative, trap unimplemented.
458		 */
459		if (Dbl_isone_sign(srcp1)) {
460			resultp1 = resultp2 = 0;
461			if (Is_invalidtrap_enabled()) {
462				return(INVALIDEXCEPTION);
463			}
464			Set_invalidflag();
465    			Duint_copytoptr(resultp1,resultp2,dstptr);
466			return(NOEXCEPTION);
467		}
468		Dbl_clear_signexponent_set_hidden(srcp1);
469		Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
470		  resultp2);
471
472		/* check for inexact */
473		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
474			inexact = TRUE;
475			/*  round result  */
476			switch (Rounding_mode()) {
477			case ROUNDPLUS:
478				Duint_increment(resultp1,resultp2);
479				break;
480			case ROUNDMINUS: /* never negative */
481				break;
482			case ROUNDNEAREST:
483				if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
484				  if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 
485				     Duint_isone_lowp2(resultp2))
486					Duint_increment(resultp1,resultp2);
487			} 
488		}
489	} else {
490		Duint_setzero(resultp1,resultp2);
491
492		/* check for inexact */
493		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
494			inexact = TRUE;
495			/*  round result  */
496			switch (Rounding_mode()) {
497			case ROUNDPLUS:
498				if (Dbl_iszero_sign(srcp1)) {
499					Duint_increment(resultp1,resultp2);
500				}
501				break;
502			case ROUNDMINUS:
503				if (Dbl_isone_sign(srcp1)) {
504					resultp1 = resultp2 = 0;
505					if (Is_invalidtrap_enabled()) {
506						return(INVALIDEXCEPTION);
507					}
508					Set_invalidflag();
509					inexact = FALSE;
510				}
511				break;
512			case ROUNDNEAREST:
513				if (src_exponent == -1 &&
514				    Dbl_isnotzero_mantissa(srcp1,srcp2))
515					if (Dbl_iszero_sign(srcp1)) {
516						Duint_increment(resultp1,resultp2);
517					} else {
518						resultp1 = 0;
519						resultp2 = 0;
520						if (Is_invalidtrap_enabled()) {
521							return(INVALIDEXCEPTION);
522						}
523						Set_invalidflag();
524						inexact = FALSE;
525					}
526			}
527		}
528	}
529	Duint_copytoptr(resultp1,resultp2,dstptr);
530	if (inexact) {
531		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
532		else Set_inexactflag();
533	}
534	return(NOEXCEPTION);
535}
536