xref: /linux/arch/parisc/math-emu/fcnvuf.c (revision 660662f857bc342b287572789b2494d0614e001d)
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/fcnvuf.c		$Revision: 1.1 $
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  Purpose:
151da177e4SLinus Torvalds  *	Fixed point to Floating-point Converts
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  *  External Interfaces:
181da177e4SLinus Torvalds  *	dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
191da177e4SLinus Torvalds  *	dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
201da177e4SLinus Torvalds  *	sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
211da177e4SLinus Torvalds  *	sgl_to_sgl_fcnvuf(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  *  Fixed point to Floating-point Converts				*
391da177e4SLinus Torvalds  ************************************************************************/
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds /*
421da177e4SLinus Torvalds  *  Convert Single Unsigned Fixed to Single Floating-point format
431da177e4SLinus Torvalds  */
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds int
461da177e4SLinus Torvalds sgl_to_sgl_fcnvuf(
471da177e4SLinus Torvalds 			unsigned int *srcptr,
481da177e4SLinus Torvalds 			unsigned int *nullptr,
491da177e4SLinus Torvalds 			sgl_floating_point *dstptr,
501da177e4SLinus Torvalds 			unsigned int *status)
511da177e4SLinus Torvalds {
521da177e4SLinus Torvalds 	register unsigned int src, result = 0;
531da177e4SLinus Torvalds 	register int dst_exponent;
541da177e4SLinus Torvalds 
551da177e4SLinus Torvalds 	src = *srcptr;
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds 	/* Check for zero */
581da177e4SLinus Torvalds 	if (src == 0) {
591da177e4SLinus Torvalds 	       	Sgl_setzero(result);
601da177e4SLinus Torvalds 		*dstptr = result;
611da177e4SLinus Torvalds 	       	return(NOEXCEPTION);
621da177e4SLinus Torvalds 	}
631da177e4SLinus Torvalds 	/*
641da177e4SLinus Torvalds 	 * Generate exponent and normalized mantissa
651da177e4SLinus Torvalds 	 */
661da177e4SLinus Torvalds 	dst_exponent = 16;    /* initialize for normalization */
671da177e4SLinus Torvalds 	/*
681da177e4SLinus Torvalds 	 * Check word for most significant bit set.  Returns
691da177e4SLinus Torvalds 	 * a value in dst_exponent indicating the bit position,
701da177e4SLinus Torvalds 	 * between -1 and 30.
711da177e4SLinus Torvalds 	 */
721da177e4SLinus Torvalds 	Find_ms_one_bit(src,dst_exponent);
731da177e4SLinus Torvalds 	/*  left justify source, with msb at bit position 0  */
741da177e4SLinus Torvalds 	src <<= dst_exponent+1;
751da177e4SLinus Torvalds 	Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH);
761da177e4SLinus Torvalds 	Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds 	/* check for inexact */
791da177e4SLinus Torvalds 	if (Suint_isinexact_to_sgl(src)) {
801da177e4SLinus Torvalds 		switch (Rounding_mode()) {
811da177e4SLinus Torvalds 			case ROUNDPLUS:
821da177e4SLinus Torvalds 				Sgl_increment(result);
831da177e4SLinus Torvalds 				break;
841da177e4SLinus Torvalds 			case ROUNDMINUS: /* never negative */
851da177e4SLinus Torvalds 				break;
861da177e4SLinus Torvalds 			case ROUNDNEAREST:
871da177e4SLinus Torvalds 				Sgl_roundnearest_from_suint(src,result);
881da177e4SLinus Torvalds 				break;
891da177e4SLinus Torvalds 		}
901da177e4SLinus Torvalds 		if (Is_inexacttrap_enabled()) {
911da177e4SLinus Torvalds 			*dstptr = result;
921da177e4SLinus Torvalds 			return(INEXACTEXCEPTION);
931da177e4SLinus Torvalds 		}
941da177e4SLinus Torvalds 		else Set_inexactflag();
951da177e4SLinus Torvalds 	}
961da177e4SLinus Torvalds 	*dstptr = result;
971da177e4SLinus Torvalds 	return(NOEXCEPTION);
981da177e4SLinus Torvalds }
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds /*
1011da177e4SLinus Torvalds  *  Single Unsigned Fixed to Double Floating-point
1021da177e4SLinus Torvalds  */
1031da177e4SLinus Torvalds 
1041da177e4SLinus Torvalds int
1051da177e4SLinus Torvalds sgl_to_dbl_fcnvuf(
1061da177e4SLinus Torvalds 			unsigned int *srcptr,
1071da177e4SLinus Torvalds 			unsigned int *nullptr,
1081da177e4SLinus Torvalds 			dbl_floating_point *dstptr,
1091da177e4SLinus Torvalds 			unsigned int *status)
1101da177e4SLinus Torvalds {
1111da177e4SLinus Torvalds 	register int dst_exponent;
1121da177e4SLinus Torvalds 	register unsigned int src, resultp1 = 0, resultp2 = 0;
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds 	src = *srcptr;
1151da177e4SLinus Torvalds 
1161da177e4SLinus Torvalds 	/* Check for zero */
1171da177e4SLinus Torvalds 	if (src == 0) {
1181da177e4SLinus Torvalds 	       	Dbl_setzero(resultp1,resultp2);
1191da177e4SLinus Torvalds 	       	Dbl_copytoptr(resultp1,resultp2,dstptr);
1201da177e4SLinus Torvalds 	       	return(NOEXCEPTION);
1211da177e4SLinus Torvalds 	}
1221da177e4SLinus Torvalds 	/*
1231da177e4SLinus Torvalds 	 * Generate exponent and normalized mantissa
1241da177e4SLinus Torvalds 	 */
1251da177e4SLinus Torvalds 	dst_exponent = 16;    /* initialize for normalization */
1261da177e4SLinus Torvalds 	/*
1271da177e4SLinus Torvalds 	 * Check word for most significant bit set.  Returns
1281da177e4SLinus Torvalds 	 * a value in dst_exponent indicating the bit position,
1291da177e4SLinus Torvalds 	 * between -1 and 30.
1301da177e4SLinus Torvalds 	 */
1311da177e4SLinus Torvalds 	Find_ms_one_bit(src,dst_exponent);
1321da177e4SLinus Torvalds 	/*  left justify source, with msb at bit position 0  */
1331da177e4SLinus Torvalds 	src <<= dst_exponent+1;
1341da177e4SLinus Torvalds 	Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH);
1351da177e4SLinus Torvalds 	Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH));
1361da177e4SLinus Torvalds 	Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
1371da177e4SLinus Torvalds 	Dbl_copytoptr(resultp1,resultp2,dstptr);
1381da177e4SLinus Torvalds 	return(NOEXCEPTION);
1391da177e4SLinus Torvalds }
1401da177e4SLinus Torvalds 
1411da177e4SLinus Torvalds /*
1421da177e4SLinus Torvalds  *  Double Unsigned Fixed to Single Floating-point
1431da177e4SLinus Torvalds  */
1441da177e4SLinus Torvalds 
1451da177e4SLinus Torvalds int
1461da177e4SLinus Torvalds dbl_to_sgl_fcnvuf(
1471da177e4SLinus Torvalds 			dbl_unsigned *srcptr,
1481da177e4SLinus Torvalds 			unsigned int *nullptr,
1491da177e4SLinus Torvalds 			sgl_floating_point *dstptr,
1501da177e4SLinus Torvalds 			unsigned int *status)
1511da177e4SLinus Torvalds {
1521da177e4SLinus Torvalds 	int dst_exponent;
1531da177e4SLinus Torvalds 	unsigned int srcp1, srcp2, result = 0;
1541da177e4SLinus Torvalds 
1551da177e4SLinus Torvalds 	Duint_copyfromptr(srcptr,srcp1,srcp2);
1561da177e4SLinus Torvalds 
1571da177e4SLinus Torvalds 	/* Check for zero */
1581da177e4SLinus Torvalds 	if (srcp1 == 0 && srcp2 == 0) {
1591da177e4SLinus Torvalds 	       	Sgl_setzero(result);
1601da177e4SLinus Torvalds 	       	*dstptr = result;
1611da177e4SLinus Torvalds 	       	return(NOEXCEPTION);
1621da177e4SLinus Torvalds 	}
1631da177e4SLinus Torvalds 	/*
1641da177e4SLinus Torvalds 	 * Generate exponent and normalized mantissa
1651da177e4SLinus Torvalds 	 */
1661da177e4SLinus Torvalds 	dst_exponent = 16;    /* initialize for normalization */
1671da177e4SLinus Torvalds 	if (srcp1 == 0) {
1681da177e4SLinus Torvalds 		/*
1691da177e4SLinus Torvalds 		 * Check word for most significant bit set.  Returns
1701da177e4SLinus Torvalds 		 * a value in dst_exponent indicating the bit position,
1711da177e4SLinus Torvalds 		 * between -1 and 30.
1721da177e4SLinus Torvalds 		 */
1731da177e4SLinus Torvalds 		Find_ms_one_bit(srcp2,dst_exponent);
1741da177e4SLinus Torvalds 		/*  left justify source, with msb at bit position 0  */
1751da177e4SLinus Torvalds 		srcp1 = srcp2 << dst_exponent+1;
1761da177e4SLinus Torvalds 		srcp2 = 0;
1771da177e4SLinus Torvalds 		/*
1781da177e4SLinus Torvalds 		 *  since msb set is in second word, need to
1791da177e4SLinus Torvalds 		 *  adjust bit position count
1801da177e4SLinus Torvalds 		 */
1811da177e4SLinus Torvalds 		dst_exponent += 32;
1821da177e4SLinus Torvalds 	}
1831da177e4SLinus Torvalds 	else {
1841da177e4SLinus Torvalds 		/*
1851da177e4SLinus Torvalds 		 * Check word for most significant bit set.  Returns
1861da177e4SLinus Torvalds 		 * a value in dst_exponent indicating the bit position,
1871da177e4SLinus Torvalds 		 * between -1 and 30.
1881da177e4SLinus Torvalds 		 *
1891da177e4SLinus Torvalds 		 */
1901da177e4SLinus Torvalds 		Find_ms_one_bit(srcp1,dst_exponent);
1911da177e4SLinus Torvalds 		/*  left justify source, with msb at bit position 0  */
1921da177e4SLinus Torvalds 		if (dst_exponent >= 0) {
1931da177e4SLinus Torvalds 			Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
1941da177e4SLinus Torvalds 			 srcp1);
1951da177e4SLinus Torvalds 			srcp2 <<= dst_exponent+1;
1961da177e4SLinus Torvalds 		}
1971da177e4SLinus Torvalds 	}
1981da177e4SLinus Torvalds 	Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH);
1991da177e4SLinus Torvalds 	Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds 	/* check for inexact */
2021da177e4SLinus Torvalds 	if (Duint_isinexact_to_sgl(srcp1,srcp2)) {
2031da177e4SLinus Torvalds 		switch (Rounding_mode()) {
2041da177e4SLinus Torvalds 			case ROUNDPLUS:
2051da177e4SLinus Torvalds 				Sgl_increment(result);
2061da177e4SLinus Torvalds 				break;
2071da177e4SLinus Torvalds 			case ROUNDMINUS: /* never negative */
2081da177e4SLinus Torvalds 				break;
2091da177e4SLinus Torvalds 			case ROUNDNEAREST:
2101da177e4SLinus Torvalds 				Sgl_roundnearest_from_duint(srcp1,srcp2,result);
2111da177e4SLinus Torvalds 				break;
2121da177e4SLinus Torvalds 		}
2131da177e4SLinus Torvalds 		if (Is_inexacttrap_enabled()) {
2141da177e4SLinus Torvalds 			*dstptr = result;
2151da177e4SLinus Torvalds 			return(INEXACTEXCEPTION);
2161da177e4SLinus Torvalds 		}
2171da177e4SLinus Torvalds 		else Set_inexactflag();
2181da177e4SLinus Torvalds 	}
2191da177e4SLinus Torvalds 	*dstptr = result;
2201da177e4SLinus Torvalds 	return(NOEXCEPTION);
2211da177e4SLinus Torvalds }
2221da177e4SLinus Torvalds 
2231da177e4SLinus Torvalds /*
2241da177e4SLinus Torvalds  *  Double Unsigned Fixed to Double Floating-point
2251da177e4SLinus Torvalds  */
2261da177e4SLinus Torvalds 
2271da177e4SLinus Torvalds int
2281da177e4SLinus Torvalds dbl_to_dbl_fcnvuf(
2291da177e4SLinus Torvalds 		    dbl_unsigned *srcptr,
2301da177e4SLinus Torvalds 		    unsigned int *nullptr,
2311da177e4SLinus Torvalds 		    dbl_floating_point *dstptr,
2321da177e4SLinus Torvalds 		    unsigned int *status)
2331da177e4SLinus Torvalds {
2341da177e4SLinus Torvalds 	register int dst_exponent;
2351da177e4SLinus Torvalds 	register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0;
2361da177e4SLinus Torvalds 
2371da177e4SLinus Torvalds 	Duint_copyfromptr(srcptr,srcp1,srcp2);
2381da177e4SLinus Torvalds 
2391da177e4SLinus Torvalds 	/* Check for zero */
2401da177e4SLinus Torvalds 	if (srcp1 == 0 && srcp2 ==0) {
2411da177e4SLinus Torvalds 	       	Dbl_setzero(resultp1,resultp2);
2421da177e4SLinus Torvalds 	       	Dbl_copytoptr(resultp1,resultp2,dstptr);
2431da177e4SLinus Torvalds 	       	return(NOEXCEPTION);
2441da177e4SLinus Torvalds 	}
2451da177e4SLinus Torvalds 	/*
2461da177e4SLinus Torvalds 	 * Generate exponent and normalized mantissa
2471da177e4SLinus Torvalds 	 */
2481da177e4SLinus Torvalds 	dst_exponent = 16;    /* initialize for normalization */
2491da177e4SLinus Torvalds 	if (srcp1 == 0) {
2501da177e4SLinus Torvalds 		/*
2511da177e4SLinus Torvalds 		 * Check word for most significant bit set.  Returns
2521da177e4SLinus Torvalds 		 * a value in dst_exponent indicating the bit position,
2531da177e4SLinus Torvalds 		 * between -1 and 30.
2541da177e4SLinus Torvalds 		 */
2551da177e4SLinus Torvalds 		Find_ms_one_bit(srcp2,dst_exponent);
2561da177e4SLinus Torvalds 		/*  left justify source, with msb at bit position 0  */
2571da177e4SLinus Torvalds 		srcp1 = srcp2 << dst_exponent+1;
2581da177e4SLinus Torvalds 		srcp2 = 0;
2591da177e4SLinus Torvalds 		/*
2601da177e4SLinus Torvalds 		 *  since msb set is in second word, need to
2611da177e4SLinus Torvalds 		 *  adjust bit position count
2621da177e4SLinus Torvalds 		 */
2631da177e4SLinus Torvalds 		dst_exponent += 32;
2641da177e4SLinus Torvalds 	}
2651da177e4SLinus Torvalds 	else {
2661da177e4SLinus Torvalds 		/*
2671da177e4SLinus Torvalds 		 * Check word for most significant bit set.  Returns
2681da177e4SLinus Torvalds 		 * a value in dst_exponent indicating the bit position,
2691da177e4SLinus Torvalds 		 * between -1 and 30.
2701da177e4SLinus Torvalds 		 */
2711da177e4SLinus Torvalds 		Find_ms_one_bit(srcp1,dst_exponent);
2721da177e4SLinus Torvalds 		/*  left justify source, with msb at bit position 0  */
2731da177e4SLinus Torvalds 		if (dst_exponent >= 0) {
2741da177e4SLinus Torvalds 			Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
2751da177e4SLinus Torvalds 			 srcp1);
2761da177e4SLinus Torvalds 			srcp2 <<= dst_exponent+1;
2771da177e4SLinus Torvalds 		}
2781da177e4SLinus Torvalds 	}
2791da177e4SLinus Torvalds 	Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH);
2801da177e4SLinus Torvalds 	Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2);
2811da177e4SLinus Torvalds 	Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
2821da177e4SLinus Torvalds 
2831da177e4SLinus Torvalds 	/* check for inexact */
2841da177e4SLinus Torvalds 	if (Duint_isinexact_to_dbl(srcp2)) {
2851da177e4SLinus Torvalds 		switch (Rounding_mode()) {
2861da177e4SLinus Torvalds 			case ROUNDPLUS:
2871da177e4SLinus Torvalds 				Dbl_increment(resultp1,resultp2);
2881da177e4SLinus Torvalds 				break;
2891da177e4SLinus Torvalds 			case ROUNDMINUS: /* never negative */
2901da177e4SLinus Torvalds 				break;
2911da177e4SLinus Torvalds 			case ROUNDNEAREST:
2921da177e4SLinus Torvalds 				Dbl_roundnearest_from_duint(srcp2,resultp1,
2931da177e4SLinus Torvalds 				resultp2);
2941da177e4SLinus Torvalds 				break;
2951da177e4SLinus Torvalds 		}
2961da177e4SLinus Torvalds 		if (Is_inexacttrap_enabled()) {
2971da177e4SLinus Torvalds 			Dbl_copytoptr(resultp1,resultp2,dstptr);
2981da177e4SLinus Torvalds 			return(INEXACTEXCEPTION);
2991da177e4SLinus Torvalds 		}
3001da177e4SLinus Torvalds 		else Set_inexactflag();
3011da177e4SLinus Torvalds 	}
3021da177e4SLinus Torvalds 	Dbl_copytoptr(resultp1,resultp2,dstptr);
3031da177e4SLinus Torvalds 	return(NOEXCEPTION);
3041da177e4SLinus Torvalds }
3051da177e4SLinus Torvalds 
306