xref: /openbsd/sys/arch/hppa/spmath/fcnvxf.c (revision 7eec34da)
1*7eec34daSmickey /*	$OpenBSD: fcnvxf.c,v 1.7 2003/04/10 17:27:58 mickey Exp $	*/
2c2feb252Smickey /*
3c2feb252Smickey   (c) Copyright 1986 HEWLETT-PACKARD COMPANY
4c2feb252Smickey   To anyone who acknowledges that this file is provided "AS IS"
5c2feb252Smickey   without any express or implied warranty:
6c2feb252Smickey       permission to use, copy, modify, and distribute this file
7c2feb252Smickey   for any purpose is hereby granted without fee, provided that
8c2feb252Smickey   the above copyright notice and this notice appears in all
9c2feb252Smickey   copies, and that the name of Hewlett-Packard Company not be
10c2feb252Smickey   used in advertising or publicity pertaining to distribution
11c2feb252Smickey   of the software without specific, written prior permission.
12c2feb252Smickey   Hewlett-Packard Company makes no representations about the
13c2feb252Smickey   suitability of this software for any purpose.
14c2feb252Smickey */
15c2feb252Smickey /* @(#)fcnvxf.c: Revision: 2.7.88.1 Date: 93/12/07 15:06:16 */
16b94afd46Smickey 
17c2feb252Smickey #include "float.h"
18c2feb252Smickey #include "sgl_float.h"
19c2feb252Smickey #include "dbl_float.h"
20c2feb252Smickey #include "cnv_float.h"
218a472b3eSmickey 
228a472b3eSmickey /*
238a472b3eSmickey  *  Convert single fixed-point to single floating-point format
248a472b3eSmickey  */
25b94afd46Smickey int
sgl_to_sgl_fcnvxf(srcptr,null,dstptr,status)26*7eec34daSmickey sgl_to_sgl_fcnvxf(srcptr, null, dstptr, status)
27*7eec34daSmickey 	int *srcptr, *null;
288a472b3eSmickey 	sgl_floating_point *dstptr;
29b94afd46Smickey 	unsigned int *status;
308a472b3eSmickey {
318a472b3eSmickey 	register int src, dst_exponent;
328a472b3eSmickey 	register unsigned int result = 0;
338a472b3eSmickey 
348a472b3eSmickey 	src = *srcptr;
358a472b3eSmickey 	/*
368a472b3eSmickey 	 * set sign bit of result and get magnitude of source
378a472b3eSmickey 	 */
388a472b3eSmickey 	if (src < 0) {
398a472b3eSmickey 		Sgl_setone_sign(result);
408a472b3eSmickey 		Int_negate(src);
418a472b3eSmickey 	}
428a472b3eSmickey 	else {
438a472b3eSmickey 		Sgl_setzero_sign(result);
448a472b3eSmickey 		/* Check for zero */
458a472b3eSmickey 		if (src == 0) {
468a472b3eSmickey 			Sgl_setzero(result);
478a472b3eSmickey 			*dstptr = result;
488a472b3eSmickey 			return(NOEXCEPTION);
498a472b3eSmickey 		}
508a472b3eSmickey 	}
518a472b3eSmickey 	/*
528a472b3eSmickey 	 * Generate exponent and normalized mantissa
538a472b3eSmickey 	 */
548a472b3eSmickey 	dst_exponent = 16;    /* initialize for normalization */
558a472b3eSmickey 	/*
568a472b3eSmickey 	 * Check word for most significant bit set.  Returns
578a472b3eSmickey 	 * a value in dst_exponent indicating the bit position,
588a472b3eSmickey 	 * between -1 and 30.
598a472b3eSmickey 	 */
608a472b3eSmickey 	Find_ms_one_bit(src,dst_exponent);
618a472b3eSmickey 	/*  left justify source, with msb at bit position 1  */
628a472b3eSmickey 	if (dst_exponent >= 0) src <<= dst_exponent;
638a472b3eSmickey 	else src = 1 << 30;
648a472b3eSmickey 	Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
658a472b3eSmickey 	Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
668a472b3eSmickey 
678a472b3eSmickey 	/* check for inexact */
688a472b3eSmickey 	if (Int_isinexact_to_sgl(src)) {
698a472b3eSmickey 		switch (Rounding_mode()) {
708a472b3eSmickey 			case ROUNDPLUS:
718a472b3eSmickey 				if (Sgl_iszero_sign(result))
728a472b3eSmickey 					Sgl_increment(result);
738a472b3eSmickey 				break;
748a472b3eSmickey 			case ROUNDMINUS:
758a472b3eSmickey 				if (Sgl_isone_sign(result))
768a472b3eSmickey 					Sgl_increment(result);
778a472b3eSmickey 				break;
788a472b3eSmickey 			case ROUNDNEAREST:
798a472b3eSmickey 				Sgl_roundnearest_from_int(src,result);
808a472b3eSmickey 		}
818a472b3eSmickey 		if (Is_inexacttrap_enabled()) {
828a472b3eSmickey 			*dstptr = result;
838a472b3eSmickey 			return(INEXACTEXCEPTION);
848a472b3eSmickey 		}
858a472b3eSmickey 		else Set_inexactflag();
868a472b3eSmickey 	}
878a472b3eSmickey 	*dstptr = result;
888a472b3eSmickey 	return(NOEXCEPTION);
898a472b3eSmickey }
908a472b3eSmickey 
918a472b3eSmickey /*
928a472b3eSmickey  *  Single Fixed-point to Double Floating-point
938a472b3eSmickey  */
94b94afd46Smickey int
sgl_to_dbl_fcnvxf(srcptr,null,dstptr,status)95*7eec34daSmickey sgl_to_dbl_fcnvxf(srcptr, null, dstptr, status)
96*7eec34daSmickey 	int *srcptr, *null;
978a472b3eSmickey 	dbl_floating_point *dstptr;
98b94afd46Smickey 	unsigned int *status;
998a472b3eSmickey {
1008a472b3eSmickey 	register int src, dst_exponent;
1018a472b3eSmickey 	register unsigned int resultp1 = 0, resultp2 = 0;
1028a472b3eSmickey 
1038a472b3eSmickey 	src = *srcptr;
1048a472b3eSmickey 	/*
1058a472b3eSmickey 	 * set sign bit of result and get magnitude of source
1068a472b3eSmickey 	 */
1078a472b3eSmickey 	if (src < 0) {
1088a472b3eSmickey 		Dbl_setone_sign(resultp1);
1098a472b3eSmickey 		Int_negate(src);
1108a472b3eSmickey 	}
1118a472b3eSmickey 	else {
1128a472b3eSmickey 		Dbl_setzero_sign(resultp1);
1138a472b3eSmickey 		/* Check for zero */
1148a472b3eSmickey 		if (src == 0) {
1158a472b3eSmickey 			Dbl_setzero(resultp1,resultp2);
1168a472b3eSmickey 			Dbl_copytoptr(resultp1,resultp2,dstptr);
1178a472b3eSmickey 			return(NOEXCEPTION);
1188a472b3eSmickey 		}
1198a472b3eSmickey 	}
1208a472b3eSmickey 	/*
1218a472b3eSmickey 	 * Generate exponent and normalized mantissa
1228a472b3eSmickey 	 */
1238a472b3eSmickey 	dst_exponent = 16;    /* initialize for normalization */
1248a472b3eSmickey 	/*
1258a472b3eSmickey 	 * Check word for most significant bit set.  Returns
1268a472b3eSmickey 	 * a value in dst_exponent indicating the bit position,
1278a472b3eSmickey 	 * between -1 and 30.
1288a472b3eSmickey 	 */
1298a472b3eSmickey 	Find_ms_one_bit(src,dst_exponent);
1308a472b3eSmickey 	/*  left justify source, with msb at bit position 1  */
1318a472b3eSmickey 	if (dst_exponent >= 0) src <<= dst_exponent;
1328a472b3eSmickey 	else src = 1 << 30;
133b94afd46Smickey 	Dbl_set_mantissap1(resultp1, (src >> (DBL_EXP_LENGTH - 1)));
134b94afd46Smickey 	Dbl_set_mantissap2(resultp2, (src << (33-DBL_EXP_LENGTH)));
1358a472b3eSmickey 	Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
1368a472b3eSmickey 	Dbl_copytoptr(resultp1,resultp2,dstptr);
1378a472b3eSmickey 	return(NOEXCEPTION);
1388a472b3eSmickey }
1398a472b3eSmickey 
1408a472b3eSmickey /*
1418a472b3eSmickey  *  Double Fixed-point to Single Floating-point
1428a472b3eSmickey  */
143b94afd46Smickey int
dbl_to_sgl_fcnvxf(srcptr,null,dstptr,status)144*7eec34daSmickey dbl_to_sgl_fcnvxf(srcptr, null, dstptr, status)
145*7eec34daSmickey 	dbl_integer *srcptr, *null;
1468a472b3eSmickey 	sgl_floating_point *dstptr;
147b94afd46Smickey 	unsigned int *status;
1488a472b3eSmickey {
1498a472b3eSmickey 	int dst_exponent, srcp1;
1508a472b3eSmickey 	unsigned int result = 0, srcp2;
1518a472b3eSmickey 
1528a472b3eSmickey 	Dint_copyfromptr(srcptr,srcp1,srcp2);
1538a472b3eSmickey 	/*
1548a472b3eSmickey 	 * set sign bit of result and get magnitude of source
1558a472b3eSmickey 	 */
1568a472b3eSmickey 	if (srcp1 < 0) {
1578a472b3eSmickey 		Sgl_setone_sign(result);
1588a472b3eSmickey 		Dint_negate(srcp1,srcp2);
1598a472b3eSmickey 	}
1608a472b3eSmickey 	else {
1618a472b3eSmickey 		Sgl_setzero_sign(result);
1628a472b3eSmickey 		/* Check for zero */
1638a472b3eSmickey 		if (srcp1 == 0 && srcp2 == 0) {
1648a472b3eSmickey 			Sgl_setzero(result);
1658a472b3eSmickey 			*dstptr = result;
1668a472b3eSmickey 			return(NOEXCEPTION);
1678a472b3eSmickey 		}
1688a472b3eSmickey 	}
1698a472b3eSmickey 	/*
1708a472b3eSmickey 	 * Generate exponent and normalized mantissa
1718a472b3eSmickey 	 */
1728a472b3eSmickey 	dst_exponent = 16;    /* initialize for normalization */
1738a472b3eSmickey 	if (srcp1 == 0) {
1748a472b3eSmickey 		/*
1758a472b3eSmickey 		 * Check word for most significant bit set.  Returns
1768a472b3eSmickey 		 * a value in dst_exponent indicating the bit position,
1778a472b3eSmickey 		 * between -1 and 30.
1788a472b3eSmickey 		 */
1798a472b3eSmickey 		Find_ms_one_bit(srcp2,dst_exponent);
1808a472b3eSmickey 		/*  left justify source, with msb at bit position 1  */
1818a472b3eSmickey 		if (dst_exponent >= 0) {
1828a472b3eSmickey 			srcp1 = srcp2 << dst_exponent;
1838a472b3eSmickey 			srcp2 = 0;
1848a472b3eSmickey 		}
1858a472b3eSmickey 		else {
1868a472b3eSmickey 			srcp1 = srcp2 >> 1;
1878a472b3eSmickey 			srcp2 <<= 31;
1888a472b3eSmickey 		}
1898a472b3eSmickey 		/*
1908a472b3eSmickey 		 *  since msb set is in second word, need to
1918a472b3eSmickey 		 *  adjust bit position count
1928a472b3eSmickey 		 */
1938a472b3eSmickey 		dst_exponent += 32;
1948a472b3eSmickey 	}
1958a472b3eSmickey 	else {
1968a472b3eSmickey 		/*
1978a472b3eSmickey 		 * Check word for most significant bit set.  Returns
1988a472b3eSmickey 		 * a value in dst_exponent indicating the bit position,
1998a472b3eSmickey 		 * between -1 and 30.
2008a472b3eSmickey 		 *
2018a472b3eSmickey 		 */
2028a472b3eSmickey 		Find_ms_one_bit(srcp1,dst_exponent);
2038a472b3eSmickey 		/*  left justify source, with msb at bit position 1  */
2048a472b3eSmickey 		if (dst_exponent > 0) {
2058a472b3eSmickey 			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
2068a472b3eSmickey 			 srcp1);
2078a472b3eSmickey 			srcp2 <<= dst_exponent;
2088a472b3eSmickey 		}
2098a472b3eSmickey 		/*
2108a472b3eSmickey 		 * If dst_exponent = 0, we don't need to shift anything.
2118a472b3eSmickey 		 * If dst_exponent = -1, src = - 2**63 so we won't need to
2128a472b3eSmickey 		 * shift srcp2.
2138a472b3eSmickey 		 */
2148a472b3eSmickey 		else srcp1 >>= -(dst_exponent);
2158a472b3eSmickey 	}
216b94afd46Smickey 	Sgl_set_mantissa(result, (srcp1 >> (SGL_EXP_LENGTH - 1)));
2178a472b3eSmickey 	Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
2188a472b3eSmickey 
2198a472b3eSmickey 	/* check for inexact */
2208a472b3eSmickey 	if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
2218a472b3eSmickey 		switch (Rounding_mode()) {
2228a472b3eSmickey 			case ROUNDPLUS:
2238a472b3eSmickey 				if (Sgl_iszero_sign(result))
2248a472b3eSmickey 					Sgl_increment(result);
2258a472b3eSmickey 				break;
2268a472b3eSmickey 			case ROUNDMINUS:
2278a472b3eSmickey 				if (Sgl_isone_sign(result))
2288a472b3eSmickey 					Sgl_increment(result);
2298a472b3eSmickey 				break;
2308a472b3eSmickey 			case ROUNDNEAREST:
2318a472b3eSmickey 				Sgl_roundnearest_from_dint(srcp1,srcp2,result);
2328a472b3eSmickey 		}
2338a472b3eSmickey 		if (Is_inexacttrap_enabled()) {
2348a472b3eSmickey 			*dstptr = result;
2358a472b3eSmickey 			return(INEXACTEXCEPTION);
2368a472b3eSmickey 		}
2378a472b3eSmickey 		else Set_inexactflag();
2388a472b3eSmickey 	}
2398a472b3eSmickey 	*dstptr = result;
2408a472b3eSmickey 	return(NOEXCEPTION);
2418a472b3eSmickey }
2428a472b3eSmickey 
2438a472b3eSmickey /*
2448a472b3eSmickey  *  Double Fixed-point to Double Floating-point
2458a472b3eSmickey  */
246b94afd46Smickey int
dbl_to_dbl_fcnvxf(srcptr,null,dstptr,status)247*7eec34daSmickey dbl_to_dbl_fcnvxf(srcptr, null, dstptr, status)
248*7eec34daSmickey 	dbl_integer *srcptr, *null;
2498a472b3eSmickey 	dbl_floating_point *dstptr;
250b94afd46Smickey 	unsigned int *status;
2518a472b3eSmickey {
2528a472b3eSmickey 	register int srcp1, dst_exponent;
2538a472b3eSmickey 	register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
2548a472b3eSmickey 
2558a472b3eSmickey 	Dint_copyfromptr(srcptr,srcp1,srcp2);
2568a472b3eSmickey 	/*
2578a472b3eSmickey 	 * set sign bit of result and get magnitude of source
2588a472b3eSmickey 	 */
2598a472b3eSmickey 	if (srcp1 < 0) {
2608a472b3eSmickey 		Dbl_setone_sign(resultp1);
2618a472b3eSmickey 		Dint_negate(srcp1,srcp2);
2628a472b3eSmickey 	}
2638a472b3eSmickey 	else {
2648a472b3eSmickey 		Dbl_setzero_sign(resultp1);
2658a472b3eSmickey 		/* Check for zero */
2668a472b3eSmickey 		if (srcp1 == 0 && srcp2 ==0) {
2678a472b3eSmickey 			Dbl_setzero(resultp1,resultp2);
2688a472b3eSmickey 			Dbl_copytoptr(resultp1,resultp2,dstptr);
2698a472b3eSmickey 			return(NOEXCEPTION);
2708a472b3eSmickey 		}
2718a472b3eSmickey 	}
2728a472b3eSmickey 	/*
2738a472b3eSmickey 	 * Generate exponent and normalized mantissa
2748a472b3eSmickey 	 */
2758a472b3eSmickey 	dst_exponent = 16;    /* initialize for normalization */
2768a472b3eSmickey 	if (srcp1 == 0) {
2778a472b3eSmickey 		/*
2788a472b3eSmickey 		 * Check word for most significant bit set.  Returns
2798a472b3eSmickey 		 * a value in dst_exponent indicating the bit position,
2808a472b3eSmickey 		 * between -1 and 30.
2818a472b3eSmickey 		 */
2828a472b3eSmickey 		Find_ms_one_bit(srcp2,dst_exponent);
2838a472b3eSmickey 		/*  left justify source, with msb at bit position 1  */
2848a472b3eSmickey 		if (dst_exponent >= 0) {
2858a472b3eSmickey 			srcp1 = srcp2 << dst_exponent;
2868a472b3eSmickey 			srcp2 = 0;
2878a472b3eSmickey 		}
2888a472b3eSmickey 		else {
2898a472b3eSmickey 			srcp1 = srcp2 >> 1;
2908a472b3eSmickey 			srcp2 <<= 31;
2918a472b3eSmickey 		}
2928a472b3eSmickey 		/*
2938a472b3eSmickey 		 *  since msb set is in second word, need to
2948a472b3eSmickey 		 *  adjust bit position count
2958a472b3eSmickey 		 */
2968a472b3eSmickey 		dst_exponent += 32;
2978a472b3eSmickey 	}
2988a472b3eSmickey 	else {
2998a472b3eSmickey 		/*
3008a472b3eSmickey 		 * Check word for most significant bit set.  Returns
3018a472b3eSmickey 		 * a value in dst_exponent indicating the bit position,
3028a472b3eSmickey 		 * between -1 and 30.
3038a472b3eSmickey 		 */
3048a472b3eSmickey 		Find_ms_one_bit(srcp1,dst_exponent);
3058a472b3eSmickey 		/*  left justify source, with msb at bit position 1  */
3068a472b3eSmickey 		if (dst_exponent > 0) {
3078a472b3eSmickey 			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
3088a472b3eSmickey 			 srcp1);
3098a472b3eSmickey 			srcp2 <<= dst_exponent;
3108a472b3eSmickey 		}
3118a472b3eSmickey 		/*
3128a472b3eSmickey 		 * If dst_exponent = 0, we don't need to shift anything.
3138a472b3eSmickey 		 * If dst_exponent = -1, src = - 2**63 so we won't need to
3148a472b3eSmickey 		 * shift srcp2.
3158a472b3eSmickey 		 */
3168a472b3eSmickey 		else srcp1 >>= -(dst_exponent);
3178a472b3eSmickey 	}
3188a472b3eSmickey 	Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
3198a472b3eSmickey 	Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
3208a472b3eSmickey 	Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
3218a472b3eSmickey 
3228a472b3eSmickey 	/* check for inexact */
3238a472b3eSmickey 	if (Dint_isinexact_to_dbl(srcp2)) {
3248a472b3eSmickey 		switch (Rounding_mode()) {
3258a472b3eSmickey 			case ROUNDPLUS:
3268a472b3eSmickey 				if (Dbl_iszero_sign(resultp1)) {
3278a472b3eSmickey 					Dbl_increment(resultp1,resultp2);
3288a472b3eSmickey 				}
3298a472b3eSmickey 				break;
3308a472b3eSmickey 			case ROUNDMINUS:
3318a472b3eSmickey 				if (Dbl_isone_sign(resultp1)) {
3328a472b3eSmickey 					Dbl_increment(resultp1,resultp2);
3338a472b3eSmickey 				}
3348a472b3eSmickey 				break;
3358a472b3eSmickey 			case ROUNDNEAREST:
3368a472b3eSmickey 				Dbl_roundnearest_from_dint(srcp2,resultp1,
3378a472b3eSmickey 				resultp2);
3388a472b3eSmickey 		}
3398a472b3eSmickey 		if (Is_inexacttrap_enabled()) {
3408a472b3eSmickey 			Dbl_copytoptr(resultp1,resultp2,dstptr);
3418a472b3eSmickey 			return(INEXACTEXCEPTION);
3428a472b3eSmickey 		}
3438a472b3eSmickey 		else Set_inexactflag();
3448a472b3eSmickey 	}
3458a472b3eSmickey 	Dbl_copytoptr(resultp1,resultp2,dstptr);
3468a472b3eSmickey 	return(NOEXCEPTION);
3478a472b3eSmickey }
348