xref: /openbmc/linux/arch/parisc/math-emu/fcnvfx.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*660662f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Floating-point emulation code
61da177e4SLinus Torvalds  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds /*
91da177e4SLinus Torvalds  * BEGIN_DESC
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  *  File:
121da177e4SLinus Torvalds  *	@(#)	pa/spmath/fcnvfx.c		$Revision: 1.1 $
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  Purpose:
151da177e4SLinus Torvalds  *	Single Floating-point to Single Fixed-point
161da177e4SLinus Torvalds  *	Single Floating-point to Double Fixed-point
171da177e4SLinus Torvalds  *	Double Floating-point to Single Fixed-point
181da177e4SLinus Torvalds  *	Double Floating-point to Double Fixed-point
191da177e4SLinus Torvalds  *
201da177e4SLinus Torvalds  *  External Interfaces:
211da177e4SLinus Torvalds  *	dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
221da177e4SLinus Torvalds  *	dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
231da177e4SLinus Torvalds  *	sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
241da177e4SLinus Torvalds  *	sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
251da177e4SLinus Torvalds  *
261da177e4SLinus Torvalds  *  Internal Interfaces:
271da177e4SLinus Torvalds  *
281da177e4SLinus Torvalds  *  Theory:
291da177e4SLinus Torvalds  *	<<please update with a overview of the operation of this file>>
301da177e4SLinus Torvalds  *
311da177e4SLinus Torvalds  * END_DESC
321da177e4SLinus Torvalds */
331da177e4SLinus Torvalds 
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds #include "float.h"
361da177e4SLinus Torvalds #include "sgl_float.h"
371da177e4SLinus Torvalds #include "dbl_float.h"
381da177e4SLinus Torvalds #include "cnv_float.h"
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds /*
411da177e4SLinus Torvalds  *  Single Floating-point to Single Fixed-point
421da177e4SLinus Torvalds  */
431da177e4SLinus Torvalds /*ARGSUSED*/
441da177e4SLinus Torvalds int
sgl_to_sgl_fcnvfx(sgl_floating_point * srcptr,sgl_floating_point * nullptr,int * dstptr,sgl_floating_point * status)451da177e4SLinus Torvalds sgl_to_sgl_fcnvfx(
461da177e4SLinus Torvalds 		    sgl_floating_point *srcptr,
471da177e4SLinus Torvalds 		    sgl_floating_point *nullptr,
481da177e4SLinus Torvalds 		    int *dstptr,
491da177e4SLinus Torvalds 		    sgl_floating_point *status)
501da177e4SLinus Torvalds {
511da177e4SLinus Torvalds 	register unsigned int src, temp;
521da177e4SLinus Torvalds 	register int src_exponent, result;
531da177e4SLinus Torvalds 	register boolean inexact = FALSE;
541da177e4SLinus Torvalds 
551da177e4SLinus Torvalds 	src = *srcptr;
561da177e4SLinus Torvalds 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
571da177e4SLinus Torvalds 
581da177e4SLinus Torvalds 	/*
591da177e4SLinus Torvalds 	 * Test for overflow
601da177e4SLinus Torvalds 	 */
611da177e4SLinus Torvalds 	if (src_exponent > SGL_FX_MAX_EXP) {
621da177e4SLinus Torvalds 		/* check for MININT */
631da177e4SLinus Torvalds 		if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
641da177e4SLinus Torvalds 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
651da177e4SLinus Torvalds                         if (Sgl_iszero_sign(src)) result = 0x7fffffff;
661da177e4SLinus Torvalds                         else result = 0x80000000;
671da177e4SLinus Torvalds 
681da177e4SLinus Torvalds 	                if (Is_invalidtrap_enabled()) {
691da177e4SLinus Torvalds                             return(INVALIDEXCEPTION);
701da177e4SLinus Torvalds                         }
711da177e4SLinus Torvalds                         Set_invalidflag();
721da177e4SLinus Torvalds 			*dstptr = result;
731da177e4SLinus Torvalds 			return(NOEXCEPTION);
741da177e4SLinus Torvalds        		}
751da177e4SLinus Torvalds 	}
761da177e4SLinus Torvalds 	/*
771da177e4SLinus Torvalds 	 * Generate result
781da177e4SLinus Torvalds 	 */
791da177e4SLinus Torvalds 	if (src_exponent >= 0) {
801da177e4SLinus Torvalds 		temp = src;
811da177e4SLinus Torvalds 		Sgl_clear_signexponent_set_hidden(temp);
821da177e4SLinus Torvalds 		Int_from_sgl_mantissa(temp,src_exponent);
831da177e4SLinus Torvalds 		if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
841da177e4SLinus Torvalds 		else result = Sgl_all(temp);
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds 		/* check for inexact */
871da177e4SLinus Torvalds 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
881da177e4SLinus Torvalds 			inexact = TRUE;
891da177e4SLinus Torvalds 			/*  round result  */
901da177e4SLinus Torvalds 			switch (Rounding_mode()) {
911da177e4SLinus Torvalds 			case ROUNDPLUS:
921da177e4SLinus Torvalds 			     if (Sgl_iszero_sign(src)) result++;
931da177e4SLinus Torvalds 			     break;
941da177e4SLinus Torvalds 			case ROUNDMINUS:
951da177e4SLinus Torvalds 			     if (Sgl_isone_sign(src)) result--;
961da177e4SLinus Torvalds 			     break;
971da177e4SLinus Torvalds 			case ROUNDNEAREST:
981da177e4SLinus Torvalds 			     if (Sgl_isone_roundbit(src,src_exponent)) {
991da177e4SLinus Torvalds 			        if (Sgl_isone_stickybit(src,src_exponent)
1001da177e4SLinus Torvalds 				|| (Sgl_isone_lowmantissa(temp)))
1011da177e4SLinus Torvalds 			           if (Sgl_iszero_sign(src)) result++;
1021da177e4SLinus Torvalds 			           else result--;
1031da177e4SLinus Torvalds 			     }
1041da177e4SLinus Torvalds 			}
1051da177e4SLinus Torvalds 		}
1061da177e4SLinus Torvalds 	}
1071da177e4SLinus Torvalds 	else {
1081da177e4SLinus Torvalds 		result = 0;
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds 		/* check for inexact */
1111da177e4SLinus Torvalds 		if (Sgl_isnotzero_exponentmantissa(src)) {
1121da177e4SLinus Torvalds 			inexact = TRUE;
1131da177e4SLinus Torvalds 			/*  round result  */
1141da177e4SLinus Torvalds 			switch (Rounding_mode()) {
1151da177e4SLinus Torvalds 			case ROUNDPLUS:
1161da177e4SLinus Torvalds 			     if (Sgl_iszero_sign(src)) result++;
1171da177e4SLinus Torvalds 			     break;
1181da177e4SLinus Torvalds 			case ROUNDMINUS:
1191da177e4SLinus Torvalds 			     if (Sgl_isone_sign(src)) result--;
1201da177e4SLinus Torvalds 			     break;
1211da177e4SLinus Torvalds 			case ROUNDNEAREST:
1221da177e4SLinus Torvalds 			     if (src_exponent == -1)
1231da177e4SLinus Torvalds 			        if (Sgl_isnotzero_mantissa(src))
1241da177e4SLinus Torvalds 			           if (Sgl_iszero_sign(src)) result++;
1251da177e4SLinus Torvalds 			           else result--;
1261da177e4SLinus Torvalds 			}
1271da177e4SLinus Torvalds 		}
1281da177e4SLinus Torvalds 	}
1291da177e4SLinus Torvalds 	*dstptr = result;
1301da177e4SLinus Torvalds 	if (inexact) {
1311da177e4SLinus Torvalds 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
1321da177e4SLinus Torvalds 		else Set_inexactflag();
1331da177e4SLinus Torvalds 	}
1341da177e4SLinus Torvalds 	return(NOEXCEPTION);
1351da177e4SLinus Torvalds }
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds /*
1381da177e4SLinus Torvalds  *  Single Floating-point to Double Fixed-point
1391da177e4SLinus Torvalds  */
1401da177e4SLinus Torvalds /*ARGSUSED*/
1411da177e4SLinus Torvalds int
sgl_to_dbl_fcnvfx(sgl_floating_point * srcptr,unsigned int * nullptr,dbl_integer * dstptr,unsigned int * status)1421da177e4SLinus Torvalds sgl_to_dbl_fcnvfx(
1431da177e4SLinus Torvalds 		sgl_floating_point *srcptr,
1441da177e4SLinus Torvalds 		unsigned int *nullptr,
1451da177e4SLinus Torvalds 		dbl_integer *dstptr,
1461da177e4SLinus Torvalds 		unsigned int *status)
1471da177e4SLinus Torvalds {
1481da177e4SLinus Torvalds 	register int src_exponent, resultp1;
1491da177e4SLinus Torvalds 	register unsigned int src, temp, resultp2;
1501da177e4SLinus Torvalds 	register boolean inexact = FALSE;
1511da177e4SLinus Torvalds 
1521da177e4SLinus Torvalds 	src = *srcptr;
1531da177e4SLinus Torvalds 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
1541da177e4SLinus Torvalds 
1551da177e4SLinus Torvalds 	/*
1561da177e4SLinus Torvalds 	 * Test for overflow
1571da177e4SLinus Torvalds 	 */
1581da177e4SLinus Torvalds 	if (src_exponent > DBL_FX_MAX_EXP) {
1591da177e4SLinus Torvalds 		/* check for MININT */
1601da177e4SLinus Torvalds 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
1611da177e4SLinus Torvalds 		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
1621da177e4SLinus Torvalds                         if (Sgl_iszero_sign(src)) {
1631da177e4SLinus Torvalds                               resultp1 = 0x7fffffff;
1641da177e4SLinus Torvalds 			      resultp2 = 0xffffffff;
1651da177e4SLinus Torvalds 			}
1661da177e4SLinus Torvalds                         else {
1671da177e4SLinus Torvalds 			    resultp1 = 0x80000000;
1681da177e4SLinus Torvalds 			    resultp2 = 0;
1691da177e4SLinus Torvalds 			}
1701da177e4SLinus Torvalds 	                if (Is_invalidtrap_enabled()) {
1711da177e4SLinus Torvalds                             return(INVALIDEXCEPTION);
1721da177e4SLinus Torvalds                         }
1731da177e4SLinus Torvalds                         Set_invalidflag();
1741da177e4SLinus Torvalds     		        Dint_copytoptr(resultp1,resultp2,dstptr);
1751da177e4SLinus Torvalds 			return(NOEXCEPTION);
1761da177e4SLinus Torvalds 		}
1771da177e4SLinus Torvalds 		Dint_set_minint(resultp1,resultp2);
1781da177e4SLinus Torvalds 		Dint_copytoptr(resultp1,resultp2,dstptr);
1791da177e4SLinus Torvalds 		return(NOEXCEPTION);
1801da177e4SLinus Torvalds 	}
1811da177e4SLinus Torvalds 	/*
1821da177e4SLinus Torvalds 	 * Generate result
1831da177e4SLinus Torvalds 	 */
1841da177e4SLinus Torvalds 	if (src_exponent >= 0) {
1851da177e4SLinus Torvalds 		temp = src;
1861da177e4SLinus Torvalds 		Sgl_clear_signexponent_set_hidden(temp);
1871da177e4SLinus Torvalds 		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
1881da177e4SLinus Torvalds 		if (Sgl_isone_sign(src)) {
1891da177e4SLinus Torvalds 			Dint_setone_sign(resultp1,resultp2);
1901da177e4SLinus Torvalds 		}
1911da177e4SLinus Torvalds 
1921da177e4SLinus Torvalds 		/* check for inexact */
1931da177e4SLinus Torvalds 		if (Sgl_isinexact_to_fix(src,src_exponent)) {
1941da177e4SLinus Torvalds 			inexact = TRUE;
1951da177e4SLinus Torvalds                         /*  round result  */
1961da177e4SLinus Torvalds                         switch (Rounding_mode()) {
1971da177e4SLinus Torvalds                         case ROUNDPLUS:
1981da177e4SLinus Torvalds                              if (Sgl_iszero_sign(src)) {
1991da177e4SLinus Torvalds 				Dint_increment(resultp1,resultp2);
2001da177e4SLinus Torvalds 			     }
2011da177e4SLinus Torvalds                              break;
2021da177e4SLinus Torvalds                         case ROUNDMINUS:
2031da177e4SLinus Torvalds                              if (Sgl_isone_sign(src)) {
2041da177e4SLinus Torvalds 				Dint_decrement(resultp1,resultp2);
2051da177e4SLinus Torvalds 			     }
2061da177e4SLinus Torvalds                              break;
2071da177e4SLinus Torvalds                         case ROUNDNEAREST:
2081da177e4SLinus Torvalds                              if (Sgl_isone_roundbit(src,src_exponent))
2091da177e4SLinus Torvalds                                 if (Sgl_isone_stickybit(src,src_exponent) ||
2101da177e4SLinus Torvalds 				(Dint_isone_lowp2(resultp2)))
2111da177e4SLinus Torvalds 				   if (Sgl_iszero_sign(src)) {
2121da177e4SLinus Torvalds 				      Dint_increment(resultp1,resultp2);
2131da177e4SLinus Torvalds 				   }
2141da177e4SLinus Torvalds                                    else {
2151da177e4SLinus Torvalds 				      Dint_decrement(resultp1,resultp2);
2161da177e4SLinus Torvalds 				   }
2171da177e4SLinus Torvalds                         }
2181da177e4SLinus Torvalds                 }
2191da177e4SLinus Torvalds         }
2201da177e4SLinus Torvalds 	else {
2211da177e4SLinus Torvalds 		Dint_setzero(resultp1,resultp2);
2221da177e4SLinus Torvalds 
2231da177e4SLinus Torvalds 		/* check for inexact */
2241da177e4SLinus Torvalds 		if (Sgl_isnotzero_exponentmantissa(src)) {
2251da177e4SLinus Torvalds 			inexact = TRUE;
2261da177e4SLinus Torvalds                         /*  round result  */
2271da177e4SLinus Torvalds                         switch (Rounding_mode()) {
2281da177e4SLinus Torvalds                         case ROUNDPLUS:
2291da177e4SLinus Torvalds                              if (Sgl_iszero_sign(src)) {
2301da177e4SLinus Torvalds 				Dint_increment(resultp1,resultp2);
2311da177e4SLinus Torvalds 			     }
2321da177e4SLinus Torvalds                              break;
2331da177e4SLinus Torvalds                         case ROUNDMINUS:
2341da177e4SLinus Torvalds                              if (Sgl_isone_sign(src)) {
2351da177e4SLinus Torvalds 				Dint_decrement(resultp1,resultp2);
2361da177e4SLinus Torvalds 			     }
2371da177e4SLinus Torvalds                              break;
2381da177e4SLinus Torvalds                         case ROUNDNEAREST:
2391da177e4SLinus Torvalds                              if (src_exponent == -1)
2401da177e4SLinus Torvalds                                 if (Sgl_isnotzero_mantissa(src))
2411da177e4SLinus Torvalds                                    if (Sgl_iszero_sign(src)) {
2421da177e4SLinus Torvalds 				      Dint_increment(resultp1,resultp2);
2431da177e4SLinus Torvalds 				   }
2441da177e4SLinus Torvalds                                    else {
2451da177e4SLinus Torvalds 				      Dint_decrement(resultp1,resultp2);
2461da177e4SLinus Torvalds 				   }
2471da177e4SLinus Torvalds 			}
2481da177e4SLinus Torvalds 		}
2491da177e4SLinus Torvalds 	}
2501da177e4SLinus Torvalds 	Dint_copytoptr(resultp1,resultp2,dstptr);
2511da177e4SLinus Torvalds 	if (inexact) {
2521da177e4SLinus Torvalds 		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
2531da177e4SLinus Torvalds 		else Set_inexactflag();
2541da177e4SLinus Torvalds 	}
2551da177e4SLinus Torvalds 	return(NOEXCEPTION);
2561da177e4SLinus Torvalds }
2571da177e4SLinus Torvalds 
2581da177e4SLinus Torvalds /*
2591da177e4SLinus Torvalds  *  Double Floating-point to Single Fixed-point
2601da177e4SLinus Torvalds  */
2611da177e4SLinus Torvalds /*ARGSUSED*/
2621da177e4SLinus Torvalds int
dbl_to_sgl_fcnvfx(dbl_floating_point * srcptr,unsigned int * nullptr,int * dstptr,unsigned int * status)2631da177e4SLinus Torvalds dbl_to_sgl_fcnvfx(
2641da177e4SLinus Torvalds 		    dbl_floating_point *srcptr,
2651da177e4SLinus Torvalds 		    unsigned int *nullptr,
2661da177e4SLinus Torvalds 		    int *dstptr,
2671da177e4SLinus Torvalds 		    unsigned int *status)
2681da177e4SLinus Torvalds {
2691da177e4SLinus Torvalds 	register unsigned int srcp1,srcp2, tempp1,tempp2;
2701da177e4SLinus Torvalds 	register int src_exponent, result;
2711da177e4SLinus Torvalds 	register boolean inexact = FALSE;
2721da177e4SLinus Torvalds 
2731da177e4SLinus Torvalds 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
2741da177e4SLinus Torvalds 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
2751da177e4SLinus Torvalds 
2761da177e4SLinus Torvalds 	/*
2771da177e4SLinus Torvalds 	 * Test for overflow
2781da177e4SLinus Torvalds 	 */
2791da177e4SLinus Torvalds 	if (src_exponent > SGL_FX_MAX_EXP) {
2801da177e4SLinus Torvalds 		/* check for MININT */
2811da177e4SLinus Torvalds 		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
2821da177e4SLinus Torvalds                         if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
2831da177e4SLinus Torvalds                         else result = 0x80000000;
2841da177e4SLinus Torvalds 
2851da177e4SLinus Torvalds 	                if (Is_invalidtrap_enabled()) {
2861da177e4SLinus Torvalds                             return(INVALIDEXCEPTION);
2871da177e4SLinus Torvalds                         }
2881da177e4SLinus Torvalds                         Set_invalidflag();
2891da177e4SLinus Torvalds 			*dstptr = result;
2901da177e4SLinus Torvalds 			return(NOEXCEPTION);
2911da177e4SLinus Torvalds 		}
2921da177e4SLinus Torvalds 	}
2931da177e4SLinus Torvalds 	/*
2941da177e4SLinus Torvalds 	 * Generate result
2951da177e4SLinus Torvalds 	 */
2961da177e4SLinus Torvalds 	if (src_exponent >= 0) {
2971da177e4SLinus Torvalds 		tempp1 = srcp1;
2981da177e4SLinus Torvalds 		tempp2 = srcp2;
2991da177e4SLinus Torvalds 		Dbl_clear_signexponent_set_hidden(tempp1);
3001da177e4SLinus Torvalds 		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
3011da177e4SLinus Torvalds 		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
3021da177e4SLinus Torvalds 			result = -Dbl_allp1(tempp1);
3031da177e4SLinus Torvalds 		else result = Dbl_allp1(tempp1);
3041da177e4SLinus Torvalds 
3051da177e4SLinus Torvalds 		/* check for inexact */
3061da177e4SLinus Torvalds 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
3071da177e4SLinus Torvalds                         inexact = TRUE;
3081da177e4SLinus Torvalds                         /*  round result  */
3091da177e4SLinus Torvalds                         switch (Rounding_mode()) {
3101da177e4SLinus Torvalds                         case ROUNDPLUS:
3111da177e4SLinus Torvalds                              if (Dbl_iszero_sign(srcp1)) result++;
3121da177e4SLinus Torvalds                              break;
3131da177e4SLinus Torvalds                         case ROUNDMINUS:
3141da177e4SLinus Torvalds                              if (Dbl_isone_sign(srcp1)) result--;
3151da177e4SLinus Torvalds                              break;
3161da177e4SLinus Torvalds                         case ROUNDNEAREST:
3171da177e4SLinus Torvalds                              if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
3181da177e4SLinus Torvalds                                 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
3191da177e4SLinus Torvalds 				(Dbl_isone_lowmantissap1(tempp1)))
3201da177e4SLinus Torvalds                                    if (Dbl_iszero_sign(srcp1)) result++;
3211da177e4SLinus Torvalds                                    else result--;
3221da177e4SLinus Torvalds                         }
3231da177e4SLinus Torvalds 			/* check for overflow */
3241da177e4SLinus Torvalds 			if ((Dbl_iszero_sign(srcp1) && result < 0) ||
3251da177e4SLinus Torvalds 			    (Dbl_isone_sign(srcp1) && result > 0)) {
3261da177e4SLinus Torvalds 
3271da177e4SLinus Torvalds                           if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
3281da177e4SLinus Torvalds                           else result = 0x80000000;
3291da177e4SLinus Torvalds 
3301da177e4SLinus Torvalds 	                  if (Is_invalidtrap_enabled()) {
3311da177e4SLinus Torvalds                             return(INVALIDEXCEPTION);
3321da177e4SLinus Torvalds                           }
3331da177e4SLinus Torvalds                           Set_invalidflag();
3341da177e4SLinus Torvalds 			  *dstptr = result;
3351da177e4SLinus Torvalds 			  return(NOEXCEPTION);
3361da177e4SLinus Torvalds 			}
3371da177e4SLinus Torvalds                 }
3381da177e4SLinus Torvalds 	}
3391da177e4SLinus Torvalds 	else {
3401da177e4SLinus Torvalds 		result = 0;
3411da177e4SLinus Torvalds 
3421da177e4SLinus Torvalds 		/* check for inexact */
3431da177e4SLinus Torvalds 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
3441da177e4SLinus Torvalds                         inexact = TRUE;
3451da177e4SLinus Torvalds                         /*  round result  */
3461da177e4SLinus Torvalds                         switch (Rounding_mode()) {
3471da177e4SLinus Torvalds                         case ROUNDPLUS:
3481da177e4SLinus Torvalds                              if (Dbl_iszero_sign(srcp1)) result++;
3491da177e4SLinus Torvalds                              break;
3501da177e4SLinus Torvalds                         case ROUNDMINUS:
3511da177e4SLinus Torvalds                              if (Dbl_isone_sign(srcp1)) result--;
3521da177e4SLinus Torvalds                              break;
3531da177e4SLinus Torvalds                         case ROUNDNEAREST:
3541da177e4SLinus Torvalds                              if (src_exponent == -1)
3551da177e4SLinus Torvalds                                 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
3561da177e4SLinus Torvalds                                    if (Dbl_iszero_sign(srcp1)) result++;
3571da177e4SLinus Torvalds                                    else result--;
3581da177e4SLinus Torvalds 			}
3591da177e4SLinus Torvalds                 }
3601da177e4SLinus Torvalds 	}
3611da177e4SLinus Torvalds 	*dstptr = result;
3621da177e4SLinus Torvalds         if (inexact) {
3631da177e4SLinus Torvalds                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
3641da177e4SLinus Torvalds 		else Set_inexactflag();
3651da177e4SLinus Torvalds         }
3661da177e4SLinus Torvalds 	return(NOEXCEPTION);
3671da177e4SLinus Torvalds }
3681da177e4SLinus Torvalds 
3691da177e4SLinus Torvalds /*
3701da177e4SLinus Torvalds  *  Double Floating-point to Double Fixed-point
3711da177e4SLinus Torvalds  */
3721da177e4SLinus Torvalds /*ARGSUSED*/
3731da177e4SLinus Torvalds int
dbl_to_dbl_fcnvfx(dbl_floating_point * srcptr,unsigned int * nullptr,dbl_integer * dstptr,unsigned int * status)3741da177e4SLinus Torvalds dbl_to_dbl_fcnvfx(
3751da177e4SLinus Torvalds 		    dbl_floating_point *srcptr,
3761da177e4SLinus Torvalds 		    unsigned int *nullptr,
3771da177e4SLinus Torvalds 		    dbl_integer *dstptr,
3781da177e4SLinus Torvalds 		    unsigned int *status)
3791da177e4SLinus Torvalds {
3801da177e4SLinus Torvalds 	register int src_exponent, resultp1;
3811da177e4SLinus Torvalds 	register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
3821da177e4SLinus Torvalds 	register boolean inexact = FALSE;
3831da177e4SLinus Torvalds 
3841da177e4SLinus Torvalds 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
3851da177e4SLinus Torvalds 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
3861da177e4SLinus Torvalds 
3871da177e4SLinus Torvalds 	/*
3881da177e4SLinus Torvalds 	 * Test for overflow
3891da177e4SLinus Torvalds 	 */
3901da177e4SLinus Torvalds 	if (src_exponent > DBL_FX_MAX_EXP) {
3911da177e4SLinus Torvalds 		/* check for MININT */
3921da177e4SLinus Torvalds 		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
3931da177e4SLinus Torvalds 		Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
3941da177e4SLinus Torvalds                         if (Dbl_iszero_sign(srcp1)) {
3951da177e4SLinus Torvalds                               resultp1 = 0x7fffffff;
3961da177e4SLinus Torvalds 			      resultp2 = 0xffffffff;
3971da177e4SLinus Torvalds 			}
3981da177e4SLinus Torvalds                         else {
3991da177e4SLinus Torvalds 			    resultp1 = 0x80000000;
4001da177e4SLinus Torvalds 			    resultp2 = 0;
4011da177e4SLinus Torvalds 			}
4021da177e4SLinus Torvalds 	                if (Is_invalidtrap_enabled()) {
4031da177e4SLinus Torvalds                             return(INVALIDEXCEPTION);
4041da177e4SLinus Torvalds                         }
4051da177e4SLinus Torvalds                         Set_invalidflag();
4061da177e4SLinus Torvalds     		        Dint_copytoptr(resultp1,resultp2,dstptr);
4071da177e4SLinus Torvalds 			return(NOEXCEPTION);
4081da177e4SLinus Torvalds 		}
4091da177e4SLinus Torvalds 	}
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds 	/*
4121da177e4SLinus Torvalds 	 * Generate result
4131da177e4SLinus Torvalds 	 */
4141da177e4SLinus Torvalds 	if (src_exponent >= 0) {
4151da177e4SLinus Torvalds 		tempp1 = srcp1;
4161da177e4SLinus Torvalds 		tempp2 = srcp2;
4171da177e4SLinus Torvalds 		Dbl_clear_signexponent_set_hidden(tempp1);
4181da177e4SLinus Torvalds 		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
4191da177e4SLinus Torvalds 		resultp2);
4201da177e4SLinus Torvalds 		if (Dbl_isone_sign(srcp1)) {
4211da177e4SLinus Torvalds 			Dint_setone_sign(resultp1,resultp2);
4221da177e4SLinus Torvalds 		}
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds 		/* check for inexact */
4251da177e4SLinus Torvalds 		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
4261da177e4SLinus Torvalds                         inexact = TRUE;
4271da177e4SLinus Torvalds                         /*  round result  */
4281da177e4SLinus Torvalds                         switch (Rounding_mode()) {
4291da177e4SLinus Torvalds                         case ROUNDPLUS:
4301da177e4SLinus Torvalds                              if (Dbl_iszero_sign(srcp1)) {
4311da177e4SLinus Torvalds 				Dint_increment(resultp1,resultp2);
4321da177e4SLinus Torvalds 			     }
4331da177e4SLinus Torvalds                              break;
4341da177e4SLinus Torvalds                         case ROUNDMINUS:
4351da177e4SLinus Torvalds                              if (Dbl_isone_sign(srcp1)) {
4361da177e4SLinus Torvalds 				Dint_decrement(resultp1,resultp2);
4371da177e4SLinus Torvalds 			     }
4381da177e4SLinus Torvalds                              break;
4391da177e4SLinus Torvalds                         case ROUNDNEAREST:
4401da177e4SLinus Torvalds                              if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
4411da177e4SLinus Torvalds                                 if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
4421da177e4SLinus Torvalds 				(Dint_isone_lowp2(resultp2)))
4431da177e4SLinus Torvalds                                    if (Dbl_iszero_sign(srcp1)) {
4441da177e4SLinus Torvalds 				      Dint_increment(resultp1,resultp2);
4451da177e4SLinus Torvalds 				   }
4461da177e4SLinus Torvalds                                    else {
4471da177e4SLinus Torvalds 				      Dint_decrement(resultp1,resultp2);
4481da177e4SLinus Torvalds 				   }
4491da177e4SLinus Torvalds                         }
4501da177e4SLinus Torvalds                 }
4511da177e4SLinus Torvalds 	}
4521da177e4SLinus Torvalds 	else {
4531da177e4SLinus Torvalds 		Dint_setzero(resultp1,resultp2);
4541da177e4SLinus Torvalds 
4551da177e4SLinus Torvalds 		/* check for inexact */
4561da177e4SLinus Torvalds 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
4571da177e4SLinus Torvalds                         inexact = TRUE;
4581da177e4SLinus Torvalds                         /*  round result  */
4591da177e4SLinus Torvalds                         switch (Rounding_mode()) {
4601da177e4SLinus Torvalds                         case ROUNDPLUS:
4611da177e4SLinus Torvalds                              if (Dbl_iszero_sign(srcp1)) {
4621da177e4SLinus Torvalds 				Dint_increment(resultp1,resultp2);
4631da177e4SLinus Torvalds 			     }
4641da177e4SLinus Torvalds                              break;
4651da177e4SLinus Torvalds                         case ROUNDMINUS:
4661da177e4SLinus Torvalds                              if (Dbl_isone_sign(srcp1)) {
4671da177e4SLinus Torvalds 				Dint_decrement(resultp1,resultp2);
4681da177e4SLinus Torvalds 			     }
4691da177e4SLinus Torvalds                              break;
4701da177e4SLinus Torvalds                         case ROUNDNEAREST:
4711da177e4SLinus Torvalds                              if (src_exponent == -1)
4721da177e4SLinus Torvalds                                 if (Dbl_isnotzero_mantissa(srcp1,srcp2))
4731da177e4SLinus Torvalds                                    if (Dbl_iszero_sign(srcp1)) {
4741da177e4SLinus Torvalds 				      Dint_increment(resultp1,resultp2);
4751da177e4SLinus Torvalds 				   }
4761da177e4SLinus Torvalds                                    else {
4771da177e4SLinus Torvalds 				      Dint_decrement(resultp1,resultp2);
4781da177e4SLinus Torvalds 				   }
4791da177e4SLinus Torvalds 			}
4801da177e4SLinus Torvalds                 }
4811da177e4SLinus Torvalds 	}
4821da177e4SLinus Torvalds 	Dint_copytoptr(resultp1,resultp2,dstptr);
4831da177e4SLinus Torvalds         if (inexact) {
4841da177e4SLinus Torvalds                 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
4851da177e4SLinus Torvalds         	else Set_inexactflag();
4861da177e4SLinus Torvalds         }
4871da177e4SLinus Torvalds 	return(NOEXCEPTION);
4881da177e4SLinus Torvalds }
489