xref: /openbmc/linux/arch/parisc/math-emu/fcnvfut.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/fcnvfut.c		$Revision: 1.1 $
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  Purpose:
151da177e4SLinus Torvalds  *	Floating-point to Unsigned Fixed-point Converts with Truncation
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  *  External Interfaces:
181da177e4SLinus Torvalds  *	dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
191da177e4SLinus Torvalds  *	dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
201da177e4SLinus Torvalds  *	sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
211da177e4SLinus Torvalds  *	sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
221da177e4SLinus Torvalds  *
231da177e4SLinus Torvalds  *  Internal Interfaces:
241da177e4SLinus Torvalds  *
251da177e4SLinus Torvalds  *  Theory:
261da177e4SLinus Torvalds  *	<<please update with a overview of the operation of this file>>
271da177e4SLinus Torvalds  *
281da177e4SLinus Torvalds  * END_DESC
291da177e4SLinus Torvalds */
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds #include "float.h"
331da177e4SLinus Torvalds #include "sgl_float.h"
341da177e4SLinus Torvalds #include "dbl_float.h"
351da177e4SLinus Torvalds #include "cnv_float.h"
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds /************************************************************************
381da177e4SLinus Torvalds  *  Floating-point to Unsigned Fixed-point Converts with Truncation	*
391da177e4SLinus Torvalds  ************************************************************************/
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds /*
421da177e4SLinus Torvalds  *  Convert single floating-point to single fixed-point format
431da177e4SLinus Torvalds  *  with truncated result
441da177e4SLinus Torvalds  */
451da177e4SLinus Torvalds /*ARGSUSED*/
461da177e4SLinus Torvalds int
sgl_to_sgl_fcnvfut(sgl_floating_point * srcptr,unsigned int * nullptr,unsigned int * dstptr,unsigned int * status)471da177e4SLinus Torvalds sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
481da177e4SLinus Torvalds 		    unsigned int *dstptr, unsigned int *status)
491da177e4SLinus Torvalds {
501da177e4SLinus Torvalds 	register unsigned int src, result;
511da177e4SLinus Torvalds 	register int src_exponent;
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds 	src = *srcptr;
541da177e4SLinus Torvalds 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds 	/*
571da177e4SLinus Torvalds 	 * Test for overflow
581da177e4SLinus Torvalds 	 */
591da177e4SLinus Torvalds 	if (src_exponent > SGL_FX_MAX_EXP + 1) {
601da177e4SLinus Torvalds 		if (Sgl_isone_sign(src)) {
611da177e4SLinus Torvalds 			result = 0;
621da177e4SLinus Torvalds 		} else {
631da177e4SLinus Torvalds 			result = 0xffffffff;
641da177e4SLinus Torvalds 		}
651da177e4SLinus Torvalds 		if (Is_invalidtrap_enabled()) {
661da177e4SLinus Torvalds 			return(INVALIDEXCEPTION);
671da177e4SLinus Torvalds 		}
681da177e4SLinus Torvalds 		Set_invalidflag();
691da177e4SLinus Torvalds 		*dstptr = result;
701da177e4SLinus Torvalds 		return(NOEXCEPTION);
711da177e4SLinus Torvalds 	}
721da177e4SLinus Torvalds 	/*
731da177e4SLinus Torvalds 	 * Generate result
741da177e4SLinus Torvalds 	 */
751da177e4SLinus Torvalds 	if (src_exponent >= 0) {
761da177e4SLinus Torvalds 		/*
771da177e4SLinus Torvalds 		 * Check sign.
781da177e4SLinus Torvalds 		 * If negative, trap unimplemented.
791da177e4SLinus Torvalds 		 */
801da177e4SLinus Torvalds 		if (Sgl_isone_sign(src)) {
811da177e4SLinus Torvalds 			result = 0;
821da177e4SLinus Torvalds 			if (Is_invalidtrap_enabled()) {
831da177e4SLinus Torvalds 				return(INVALIDEXCEPTION);
841da177e4SLinus Torvalds 			}
851da177e4SLinus Torvalds 			Set_invalidflag();
861da177e4SLinus Torvalds 			*dstptr = result;
871da177e4SLinus Torvalds 			return(NOEXCEPTION);
881da177e4SLinus Torvalds 		}
891da177e4SLinus Torvalds 		Sgl_clear_signexponent_set_hidden(src);
901da177e4SLinus Torvalds 		Suint_from_sgl_mantissa(src,src_exponent,result);
911da177e4SLinus Torvalds 		*dstptr = result;
921da177e4SLinus Torvalds 
931da177e4SLinus Torvalds 		/* check for inexact */
941da177e4SLinus Torvalds 		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
951da177e4SLinus Torvalds 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
961da177e4SLinus Torvalds 			else Set_inexactflag();
971da177e4SLinus Torvalds 		}
981da177e4SLinus Torvalds 	}
991da177e4SLinus Torvalds 	else {
1001da177e4SLinus Torvalds 		*dstptr = 0;
1011da177e4SLinus Torvalds 
1021da177e4SLinus Torvalds 		/* check for inexact */
1031da177e4SLinus Torvalds 		if (Sgl_isnotzero_exponentmantissa(src)) {
1041da177e4SLinus Torvalds 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
1051da177e4SLinus Torvalds 			else Set_inexactflag();
1061da177e4SLinus Torvalds 		}
1071da177e4SLinus Torvalds 	}
1081da177e4SLinus Torvalds 	return(NOEXCEPTION);
1091da177e4SLinus Torvalds }
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds /*
1121da177e4SLinus Torvalds  *  Single Floating-point to Double Unsigned Fixed
1131da177e4SLinus Torvalds  */
1141da177e4SLinus Torvalds /*ARGSUSED*/
1151da177e4SLinus Torvalds int
sgl_to_dbl_fcnvfut(sgl_floating_point * srcptr,unsigned int * nullptr,dbl_unsigned * dstptr,unsigned int * status)1161da177e4SLinus Torvalds sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
1171da177e4SLinus Torvalds 		    dbl_unsigned * dstptr, unsigned int *status)
1181da177e4SLinus Torvalds {
1191da177e4SLinus Torvalds 	register int src_exponent;
1201da177e4SLinus Torvalds 	register unsigned int src, resultp1, resultp2;
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds 	src = *srcptr;
1231da177e4SLinus Torvalds 	src_exponent = Sgl_exponent(src) - SGL_BIAS;
1241da177e4SLinus Torvalds 
1251da177e4SLinus Torvalds 	/*
1261da177e4SLinus Torvalds 	 * Test for overflow
1271da177e4SLinus Torvalds 	 */
1281da177e4SLinus Torvalds 	if (src_exponent > DBL_FX_MAX_EXP + 1) {
1291da177e4SLinus Torvalds 		if (Sgl_isone_sign(src)) {
1301da177e4SLinus Torvalds 			resultp1 = resultp2 = 0;
1311da177e4SLinus Torvalds 		} else {
1321da177e4SLinus Torvalds 			resultp1 = resultp2 = 0xffffffff;
1331da177e4SLinus Torvalds 		}
1341da177e4SLinus Torvalds 		if (Is_invalidtrap_enabled()) {
1351da177e4SLinus Torvalds 			return(INVALIDEXCEPTION);
1361da177e4SLinus Torvalds 		}
1371da177e4SLinus Torvalds 		Set_invalidflag();
1381da177e4SLinus Torvalds     		Duint_copytoptr(resultp1,resultp2,dstptr);
1391da177e4SLinus Torvalds 		return(NOEXCEPTION);
1401da177e4SLinus Torvalds 	}
1411da177e4SLinus Torvalds 	/*
1421da177e4SLinus Torvalds 	 * Generate result
1431da177e4SLinus Torvalds 	 */
1441da177e4SLinus Torvalds 	if (src_exponent >= 0) {
1451da177e4SLinus Torvalds 		/*
1461da177e4SLinus Torvalds 		 * Check sign.
1471da177e4SLinus Torvalds 		 * If negative, trap unimplemented.
1481da177e4SLinus Torvalds 		 */
1491da177e4SLinus Torvalds 		if (Sgl_isone_sign(src)) {
1501da177e4SLinus Torvalds 			resultp1 = resultp2 = 0;
1511da177e4SLinus Torvalds 			if (Is_invalidtrap_enabled()) {
1521da177e4SLinus Torvalds 				return(INVALIDEXCEPTION);
1531da177e4SLinus Torvalds 			}
1541da177e4SLinus Torvalds 			Set_invalidflag();
1551da177e4SLinus Torvalds     			Duint_copytoptr(resultp1,resultp2,dstptr);
1561da177e4SLinus Torvalds 			return(NOEXCEPTION);
1571da177e4SLinus Torvalds 		}
1581da177e4SLinus Torvalds 		Sgl_clear_signexponent_set_hidden(src);
1591da177e4SLinus Torvalds 		Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
1601da177e4SLinus Torvalds 		Duint_copytoptr(resultp1,resultp2,dstptr);
1611da177e4SLinus Torvalds 
1621da177e4SLinus Torvalds 		/* check for inexact */
1631da177e4SLinus Torvalds 		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
1641da177e4SLinus Torvalds 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
1651da177e4SLinus Torvalds 			else Set_inexactflag();
1661da177e4SLinus Torvalds 		}
1671da177e4SLinus Torvalds 	}
1681da177e4SLinus Torvalds 	else {
1691da177e4SLinus Torvalds 		Duint_setzero(resultp1,resultp2);
1701da177e4SLinus Torvalds 		Duint_copytoptr(resultp1,resultp2,dstptr);
1711da177e4SLinus Torvalds 
1721da177e4SLinus Torvalds 		/* check for inexact */
1731da177e4SLinus Torvalds 		if (Sgl_isnotzero_exponentmantissa(src)) {
1741da177e4SLinus Torvalds 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
1751da177e4SLinus Torvalds 			else Set_inexactflag();
1761da177e4SLinus Torvalds 		}
1771da177e4SLinus Torvalds 	}
1781da177e4SLinus Torvalds 	return(NOEXCEPTION);
1791da177e4SLinus Torvalds }
1801da177e4SLinus Torvalds 
1811da177e4SLinus Torvalds /*
1821da177e4SLinus Torvalds  *  Double Floating-point to Single Unsigned Fixed
1831da177e4SLinus Torvalds  */
1841da177e4SLinus Torvalds /*ARGSUSED*/
1851da177e4SLinus Torvalds int
dbl_to_sgl_fcnvfut(dbl_floating_point * srcptr,unsigned int * nullptr,unsigned int * dstptr,unsigned int * status)1861da177e4SLinus Torvalds dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
1871da177e4SLinus Torvalds 		    unsigned int *dstptr, unsigned int *status)
1881da177e4SLinus Torvalds {
1891da177e4SLinus Torvalds 	register unsigned int srcp1, srcp2, result;
1901da177e4SLinus Torvalds 	register int src_exponent;
1911da177e4SLinus Torvalds 
1921da177e4SLinus Torvalds 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
1931da177e4SLinus Torvalds 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
1941da177e4SLinus Torvalds 
1951da177e4SLinus Torvalds 	/*
1961da177e4SLinus Torvalds 	 * Test for overflow
1971da177e4SLinus Torvalds 	 */
1981da177e4SLinus Torvalds 	if (src_exponent > SGL_FX_MAX_EXP + 1) {
1991da177e4SLinus Torvalds 		if (Dbl_isone_sign(srcp1)) {
2001da177e4SLinus Torvalds 			result = 0;
2011da177e4SLinus Torvalds 		} else {
2021da177e4SLinus Torvalds 			result = 0xffffffff;
2031da177e4SLinus Torvalds 		}
2041da177e4SLinus Torvalds 		if (Is_invalidtrap_enabled()) {
2051da177e4SLinus Torvalds 			return(INVALIDEXCEPTION);
2061da177e4SLinus Torvalds 		}
2071da177e4SLinus Torvalds 		Set_invalidflag();
2081da177e4SLinus Torvalds 		*dstptr = result;
2091da177e4SLinus Torvalds 		return(NOEXCEPTION);
2101da177e4SLinus Torvalds 	}
2111da177e4SLinus Torvalds 	/*
2121da177e4SLinus Torvalds 	 * Generate result
2131da177e4SLinus Torvalds 	 */
2141da177e4SLinus Torvalds 	if (src_exponent >= 0) {
2151da177e4SLinus Torvalds 		/*
2161da177e4SLinus Torvalds 		 * Check sign.
2171da177e4SLinus Torvalds 		 * If negative, trap unimplemented.
2181da177e4SLinus Torvalds 		 */
2191da177e4SLinus Torvalds 		if (Dbl_isone_sign(srcp1)) {
2201da177e4SLinus Torvalds 			result = 0;
2211da177e4SLinus Torvalds 			if (Is_invalidtrap_enabled()) {
2221da177e4SLinus Torvalds 				return(INVALIDEXCEPTION);
2231da177e4SLinus Torvalds 			}
2241da177e4SLinus Torvalds 			Set_invalidflag();
2251da177e4SLinus Torvalds 			*dstptr = result;
2261da177e4SLinus Torvalds 			return(NOEXCEPTION);
2271da177e4SLinus Torvalds 		}
2281da177e4SLinus Torvalds 		Dbl_clear_signexponent_set_hidden(srcp1);
2291da177e4SLinus Torvalds 		Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
2301da177e4SLinus Torvalds 		*dstptr = result;
2311da177e4SLinus Torvalds 
2321da177e4SLinus Torvalds 		/* check for inexact */
2331da177e4SLinus Torvalds 		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
2341da177e4SLinus Torvalds 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
2351da177e4SLinus Torvalds 			else Set_inexactflag();
2361da177e4SLinus Torvalds 		}
2371da177e4SLinus Torvalds 	}
2381da177e4SLinus Torvalds 	else {
2391da177e4SLinus Torvalds 		*dstptr = 0;
2401da177e4SLinus Torvalds 
2411da177e4SLinus Torvalds 		/* check for inexact */
2421da177e4SLinus Torvalds 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
2431da177e4SLinus Torvalds 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
2441da177e4SLinus Torvalds 			else Set_inexactflag();
2451da177e4SLinus Torvalds 		}
2461da177e4SLinus Torvalds 	}
2471da177e4SLinus Torvalds 	return(NOEXCEPTION);
2481da177e4SLinus Torvalds }
2491da177e4SLinus Torvalds 
2501da177e4SLinus Torvalds /*
2511da177e4SLinus Torvalds  *  Double Floating-point to Double Unsigned Fixed
2521da177e4SLinus Torvalds  */
2531da177e4SLinus Torvalds /*ARGSUSED*/
2541da177e4SLinus Torvalds int
dbl_to_dbl_fcnvfut(dbl_floating_point * srcptr,unsigned int * nullptr,dbl_unsigned * dstptr,unsigned int * status)2551da177e4SLinus Torvalds dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
2561da177e4SLinus Torvalds 		    dbl_unsigned * dstptr, unsigned int *status)
2571da177e4SLinus Torvalds {
2581da177e4SLinus Torvalds 	register int src_exponent;
2591da177e4SLinus Torvalds 	register unsigned int srcp1, srcp2, resultp1, resultp2;
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds 	Dbl_copyfromptr(srcptr,srcp1,srcp2);
2621da177e4SLinus Torvalds 	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
2631da177e4SLinus Torvalds 
2641da177e4SLinus Torvalds 	/*
2651da177e4SLinus Torvalds 	 * Test for overflow
2661da177e4SLinus Torvalds 	 */
2671da177e4SLinus Torvalds 	if (src_exponent > DBL_FX_MAX_EXP + 1) {
2681da177e4SLinus Torvalds 		if (Dbl_isone_sign(srcp1)) {
2691da177e4SLinus Torvalds 			resultp1 = resultp2 = 0;
2701da177e4SLinus Torvalds 		} else {
2711da177e4SLinus Torvalds 			resultp1 = resultp2 = 0xffffffff;
2721da177e4SLinus Torvalds 		}
2731da177e4SLinus Torvalds 		if (Is_invalidtrap_enabled()) {
2741da177e4SLinus Torvalds 			return(INVALIDEXCEPTION);
2751da177e4SLinus Torvalds 		}
2761da177e4SLinus Torvalds 		Set_invalidflag();
2771da177e4SLinus Torvalds     		Duint_copytoptr(resultp1,resultp2,dstptr);
2781da177e4SLinus Torvalds 		return(NOEXCEPTION);
2791da177e4SLinus Torvalds 	}
2801da177e4SLinus Torvalds 	/*
2811da177e4SLinus Torvalds 	 * Generate result
2821da177e4SLinus Torvalds 	 */
2831da177e4SLinus Torvalds 	if (src_exponent >= 0) {
2841da177e4SLinus Torvalds 		/*
2851da177e4SLinus Torvalds 		 * Check sign.
2861da177e4SLinus Torvalds 		 * If negative, trap unimplemented.
2871da177e4SLinus Torvalds 		 */
2881da177e4SLinus Torvalds 		if (Dbl_isone_sign(srcp1)) {
2891da177e4SLinus Torvalds 			resultp1 = resultp2 = 0;
2901da177e4SLinus Torvalds 			if (Is_invalidtrap_enabled()) {
2911da177e4SLinus Torvalds 				return(INVALIDEXCEPTION);
2921da177e4SLinus Torvalds 			}
2931da177e4SLinus Torvalds 			Set_invalidflag();
2941da177e4SLinus Torvalds     			Duint_copytoptr(resultp1,resultp2,dstptr);
2951da177e4SLinus Torvalds 			return(NOEXCEPTION);
2961da177e4SLinus Torvalds 		}
2971da177e4SLinus Torvalds 		Dbl_clear_signexponent_set_hidden(srcp1);
2981da177e4SLinus Torvalds 		Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,
2991da177e4SLinus Torvalds 		  resultp1,resultp2);
3001da177e4SLinus Torvalds 		Duint_copytoptr(resultp1,resultp2,dstptr);
3011da177e4SLinus Torvalds 
3021da177e4SLinus Torvalds 		/* check for inexact */
3031da177e4SLinus Torvalds 		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
3041da177e4SLinus Torvalds 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
3051da177e4SLinus Torvalds 			else Set_inexactflag();
3061da177e4SLinus Torvalds 		}
3071da177e4SLinus Torvalds 	}
3081da177e4SLinus Torvalds 	else {
3091da177e4SLinus Torvalds 		Duint_setzero(resultp1,resultp2);
3101da177e4SLinus Torvalds 		Duint_copytoptr(resultp1,resultp2,dstptr);
3111da177e4SLinus Torvalds 
3121da177e4SLinus Torvalds 		/* check for inexact */
3131da177e4SLinus Torvalds 		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
3141da177e4SLinus Torvalds 			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
3151da177e4SLinus Torvalds 			else Set_inexactflag();
3161da177e4SLinus Torvalds 		}
3171da177e4SLinus Torvalds 	}
3181da177e4SLinus Torvalds 	return(NOEXCEPTION);
3191da177e4SLinus Torvalds }
320