18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/)
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Floating-point emulation code
68c2ecf20Sopenharmony_ci *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci * BEGIN_DESC
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci *  File:
128c2ecf20Sopenharmony_ci *	@(#)	pa/spmath/fmpyfadd.c		$Revision: 1.1 $
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci *  Purpose:
158c2ecf20Sopenharmony_ci *	Double Floating-point Multiply Fused Add
168c2ecf20Sopenharmony_ci *	Double Floating-point Multiply Negate Fused Add
178c2ecf20Sopenharmony_ci *	Single Floating-point Multiply Fused Add
188c2ecf20Sopenharmony_ci *	Single Floating-point Multiply Negate Fused Add
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci *  External Interfaces:
218c2ecf20Sopenharmony_ci *	dbl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
228c2ecf20Sopenharmony_ci *	dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
238c2ecf20Sopenharmony_ci *	sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
248c2ecf20Sopenharmony_ci *	sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci *  Internal Interfaces:
278c2ecf20Sopenharmony_ci *
288c2ecf20Sopenharmony_ci *  Theory:
298c2ecf20Sopenharmony_ci *	<<please update with a overview of the operation of this file>>
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci * END_DESC
328c2ecf20Sopenharmony_ci*/
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include "float.h"
368c2ecf20Sopenharmony_ci#include "sgl_float.h"
378c2ecf20Sopenharmony_ci#include "dbl_float.h"
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/*
418c2ecf20Sopenharmony_ci *  Double Floating-point Multiply Fused Add
428c2ecf20Sopenharmony_ci */
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ciint
458c2ecf20Sopenharmony_cidbl_fmpyfadd(
468c2ecf20Sopenharmony_ci	    dbl_floating_point *src1ptr,
478c2ecf20Sopenharmony_ci	    dbl_floating_point *src2ptr,
488c2ecf20Sopenharmony_ci	    dbl_floating_point *src3ptr,
498c2ecf20Sopenharmony_ci	    unsigned int *status,
508c2ecf20Sopenharmony_ci	    dbl_floating_point *dstptr)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
538c2ecf20Sopenharmony_ci	register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
548c2ecf20Sopenharmony_ci	unsigned int rightp1, rightp2, rightp3, rightp4;
558c2ecf20Sopenharmony_ci	unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
568c2ecf20Sopenharmony_ci	register int mpy_exponent, add_exponent, count;
578c2ecf20Sopenharmony_ci	boolean inexact = FALSE, is_tiny = FALSE;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	unsigned int signlessleft1, signlessright1, save;
608c2ecf20Sopenharmony_ci	register int result_exponent, diff_exponent;
618c2ecf20Sopenharmony_ci	int sign_save, jumpsize;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
648c2ecf20Sopenharmony_ci	Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
658c2ecf20Sopenharmony_ci	Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	/*
688c2ecf20Sopenharmony_ci	 * set sign bit of result of multiply
698c2ecf20Sopenharmony_ci	 */
708c2ecf20Sopenharmony_ci	if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
718c2ecf20Sopenharmony_ci		Dbl_setnegativezerop1(resultp1);
728c2ecf20Sopenharmony_ci	else Dbl_setzerop1(resultp1);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	/*
758c2ecf20Sopenharmony_ci	 * Generate multiply exponent
768c2ecf20Sopenharmony_ci	 */
778c2ecf20Sopenharmony_ci	mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	/*
808c2ecf20Sopenharmony_ci	 * check first operand for NaN's or infinity
818c2ecf20Sopenharmony_ci	 */
828c2ecf20Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd1p1)) {
838c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
848c2ecf20Sopenharmony_ci			if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
858c2ecf20Sopenharmony_ci			    Dbl_isnotnan(opnd3p1,opnd3p2)) {
868c2ecf20Sopenharmony_ci				if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
878c2ecf20Sopenharmony_ci					/*
888c2ecf20Sopenharmony_ci					 * invalid since operands are infinity
898c2ecf20Sopenharmony_ci					 * and zero
908c2ecf20Sopenharmony_ci					 */
918c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
928c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
938c2ecf20Sopenharmony_ci					Set_invalidflag();
948c2ecf20Sopenharmony_ci					Dbl_makequietnan(resultp1,resultp2);
958c2ecf20Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
968c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
978c2ecf20Sopenharmony_ci				}
988c2ecf20Sopenharmony_ci				/*
998c2ecf20Sopenharmony_ci				 * Check third operand for infinity with a
1008c2ecf20Sopenharmony_ci				 *  sign opposite of the multiply result
1018c2ecf20Sopenharmony_ci				 */
1028c2ecf20Sopenharmony_ci				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
1038c2ecf20Sopenharmony_ci				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
1048c2ecf20Sopenharmony_ci					/*
1058c2ecf20Sopenharmony_ci					 * invalid since attempting a magnitude
1068c2ecf20Sopenharmony_ci					 * subtraction of infinities
1078c2ecf20Sopenharmony_ci					 */
1088c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
1098c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
1108c2ecf20Sopenharmony_ci					Set_invalidflag();
1118c2ecf20Sopenharmony_ci					Dbl_makequietnan(resultp1,resultp2);
1128c2ecf20Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
1138c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
1148c2ecf20Sopenharmony_ci				}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci				/*
1178c2ecf20Sopenharmony_ci			 	 * return infinity
1188c2ecf20Sopenharmony_ci			 	 */
1198c2ecf20Sopenharmony_ci				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
1208c2ecf20Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
1218c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
1228c2ecf20Sopenharmony_ci			}
1238c2ecf20Sopenharmony_ci		}
1248c2ecf20Sopenharmony_ci		else {
1258c2ecf20Sopenharmony_ci			/*
1268c2ecf20Sopenharmony_ci		 	 * is NaN; signaling or quiet?
1278c2ecf20Sopenharmony_ci		 	 */
1288c2ecf20Sopenharmony_ci			if (Dbl_isone_signaling(opnd1p1)) {
1298c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
1308c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
1318c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
1328c2ecf20Sopenharmony_ci				/* make NaN quiet */
1338c2ecf20Sopenharmony_ci				Set_invalidflag();
1348c2ecf20Sopenharmony_ci				Dbl_set_quiet(opnd1p1);
1358c2ecf20Sopenharmony_ci			}
1368c2ecf20Sopenharmony_ci			/*
1378c2ecf20Sopenharmony_ci			 * is second operand a signaling NaN?
1388c2ecf20Sopenharmony_ci			 */
1398c2ecf20Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd2p1)) {
1408c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
1418c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
1428c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
1438c2ecf20Sopenharmony_ci				/* make NaN quiet */
1448c2ecf20Sopenharmony_ci				Set_invalidflag();
1458c2ecf20Sopenharmony_ci				Dbl_set_quiet(opnd2p1);
1468c2ecf20Sopenharmony_ci				Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
1478c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
1488c2ecf20Sopenharmony_ci			}
1498c2ecf20Sopenharmony_ci			/*
1508c2ecf20Sopenharmony_ci			 * is third operand a signaling NaN?
1518c2ecf20Sopenharmony_ci			 */
1528c2ecf20Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd3p1)) {
1538c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
1548c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
1558c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
1568c2ecf20Sopenharmony_ci				/* make NaN quiet */
1578c2ecf20Sopenharmony_ci				Set_invalidflag();
1588c2ecf20Sopenharmony_ci				Dbl_set_quiet(opnd3p1);
1598c2ecf20Sopenharmony_ci				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
1608c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
1618c2ecf20Sopenharmony_ci			}
1628c2ecf20Sopenharmony_ci			/*
1638c2ecf20Sopenharmony_ci		 	 * return quiet NaN
1648c2ecf20Sopenharmony_ci		 	 */
1658c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
1668c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
1678c2ecf20Sopenharmony_ci		}
1688c2ecf20Sopenharmony_ci	}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	/*
1718c2ecf20Sopenharmony_ci	 * check second operand for NaN's or infinity
1728c2ecf20Sopenharmony_ci	 */
1738c2ecf20Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd2p1)) {
1748c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
1758c2ecf20Sopenharmony_ci			if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
1768c2ecf20Sopenharmony_ci				if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
1778c2ecf20Sopenharmony_ci					/*
1788c2ecf20Sopenharmony_ci					 * invalid since multiply operands are
1798c2ecf20Sopenharmony_ci					 * zero & infinity
1808c2ecf20Sopenharmony_ci					 */
1818c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
1828c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
1838c2ecf20Sopenharmony_ci					Set_invalidflag();
1848c2ecf20Sopenharmony_ci					Dbl_makequietnan(opnd2p1,opnd2p2);
1858c2ecf20Sopenharmony_ci					Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
1868c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
1878c2ecf20Sopenharmony_ci				}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci				/*
1908c2ecf20Sopenharmony_ci				 * Check third operand for infinity with a
1918c2ecf20Sopenharmony_ci				 *  sign opposite of the multiply result
1928c2ecf20Sopenharmony_ci				 */
1938c2ecf20Sopenharmony_ci				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
1948c2ecf20Sopenharmony_ci				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
1958c2ecf20Sopenharmony_ci					/*
1968c2ecf20Sopenharmony_ci					 * invalid since attempting a magnitude
1978c2ecf20Sopenharmony_ci					 * subtraction of infinities
1988c2ecf20Sopenharmony_ci					 */
1998c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
2008c2ecf20Sopenharmony_ci				       		return(OPC_2E_INVALIDEXCEPTION);
2018c2ecf20Sopenharmony_ci				       	Set_invalidflag();
2028c2ecf20Sopenharmony_ci				       	Dbl_makequietnan(resultp1,resultp2);
2038c2ecf20Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
2048c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
2058c2ecf20Sopenharmony_ci				}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci				/*
2088c2ecf20Sopenharmony_ci				 * return infinity
2098c2ecf20Sopenharmony_ci				 */
2108c2ecf20Sopenharmony_ci				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
2118c2ecf20Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
2128c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
2138c2ecf20Sopenharmony_ci			}
2148c2ecf20Sopenharmony_ci		}
2158c2ecf20Sopenharmony_ci		else {
2168c2ecf20Sopenharmony_ci			/*
2178c2ecf20Sopenharmony_ci			 * is NaN; signaling or quiet?
2188c2ecf20Sopenharmony_ci			 */
2198c2ecf20Sopenharmony_ci			if (Dbl_isone_signaling(opnd2p1)) {
2208c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
2218c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
2228c2ecf20Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
2238c2ecf20Sopenharmony_ci				/* make NaN quiet */
2248c2ecf20Sopenharmony_ci				Set_invalidflag();
2258c2ecf20Sopenharmony_ci				Dbl_set_quiet(opnd2p1);
2268c2ecf20Sopenharmony_ci			}
2278c2ecf20Sopenharmony_ci			/*
2288c2ecf20Sopenharmony_ci			 * is third operand a signaling NaN?
2298c2ecf20Sopenharmony_ci			 */
2308c2ecf20Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd3p1)) {
2318c2ecf20Sopenharmony_ci			       	/* trap if INVALIDTRAP enabled */
2328c2ecf20Sopenharmony_ci			       	if (Is_invalidtrap_enabled())
2338c2ecf20Sopenharmony_ci				   		return(OPC_2E_INVALIDEXCEPTION);
2348c2ecf20Sopenharmony_ci			       	/* make NaN quiet */
2358c2ecf20Sopenharmony_ci			       	Set_invalidflag();
2368c2ecf20Sopenharmony_ci			       	Dbl_set_quiet(opnd3p1);
2378c2ecf20Sopenharmony_ci				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
2388c2ecf20Sopenharmony_ci		       		return(NOEXCEPTION);
2398c2ecf20Sopenharmony_ci			}
2408c2ecf20Sopenharmony_ci			/*
2418c2ecf20Sopenharmony_ci			 * return quiet NaN
2428c2ecf20Sopenharmony_ci			 */
2438c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
2448c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
2458c2ecf20Sopenharmony_ci		}
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	/*
2498c2ecf20Sopenharmony_ci	 * check third operand for NaN's or infinity
2508c2ecf20Sopenharmony_ci	 */
2518c2ecf20Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd3p1)) {
2528c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
2538c2ecf20Sopenharmony_ci			/* return infinity */
2548c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
2558c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
2568c2ecf20Sopenharmony_ci		} else {
2578c2ecf20Sopenharmony_ci			/*
2588c2ecf20Sopenharmony_ci			 * is NaN; signaling or quiet?
2598c2ecf20Sopenharmony_ci			 */
2608c2ecf20Sopenharmony_ci			if (Dbl_isone_signaling(opnd3p1)) {
2618c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
2628c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
2638c2ecf20Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
2648c2ecf20Sopenharmony_ci				/* make NaN quiet */
2658c2ecf20Sopenharmony_ci				Set_invalidflag();
2668c2ecf20Sopenharmony_ci				Dbl_set_quiet(opnd3p1);
2678c2ecf20Sopenharmony_ci			}
2688c2ecf20Sopenharmony_ci			/*
2698c2ecf20Sopenharmony_ci			 * return quiet NaN
2708c2ecf20Sopenharmony_ci 			 */
2718c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
2728c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
2738c2ecf20Sopenharmony_ci		}
2748c2ecf20Sopenharmony_ci    	}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	/*
2778c2ecf20Sopenharmony_ci	 * Generate multiply mantissa
2788c2ecf20Sopenharmony_ci	 */
2798c2ecf20Sopenharmony_ci	if (Dbl_isnotzero_exponent(opnd1p1)) {
2808c2ecf20Sopenharmony_ci		/* set hidden bit */
2818c2ecf20Sopenharmony_ci		Dbl_clear_signexponent_set_hidden(opnd1p1);
2828c2ecf20Sopenharmony_ci	}
2838c2ecf20Sopenharmony_ci	else {
2848c2ecf20Sopenharmony_ci		/* check for zero */
2858c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
2868c2ecf20Sopenharmony_ci			/*
2878c2ecf20Sopenharmony_ci			 * Perform the add opnd3 with zero here.
2888c2ecf20Sopenharmony_ci			 */
2898c2ecf20Sopenharmony_ci			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
2908c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
2918c2ecf20Sopenharmony_ci					Dbl_or_signs(opnd3p1,resultp1);
2928c2ecf20Sopenharmony_ci				} else {
2938c2ecf20Sopenharmony_ci					Dbl_and_signs(opnd3p1,resultp1);
2948c2ecf20Sopenharmony_ci				}
2958c2ecf20Sopenharmony_ci			}
2968c2ecf20Sopenharmony_ci			/*
2978c2ecf20Sopenharmony_ci			 * Now let's check for trapped underflow case.
2988c2ecf20Sopenharmony_ci			 */
2998c2ecf20Sopenharmony_ci			else if (Dbl_iszero_exponent(opnd3p1) &&
3008c2ecf20Sopenharmony_ci			         Is_underflowtrap_enabled()) {
3018c2ecf20Sopenharmony_ci                    		/* need to normalize results mantissa */
3028c2ecf20Sopenharmony_ci                    		sign_save = Dbl_signextendedsign(opnd3p1);
3038c2ecf20Sopenharmony_ci				result_exponent = 0;
3048c2ecf20Sopenharmony_ci                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
3058c2ecf20Sopenharmony_ci                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
3068c2ecf20Sopenharmony_ci                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
3078c2ecf20Sopenharmony_ci                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
3088c2ecf20Sopenharmony_ci							unfl);
3098c2ecf20Sopenharmony_ci                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
3108c2ecf20Sopenharmony_ci                    		/* inexact = FALSE */
3118c2ecf20Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
3128c2ecf20Sopenharmony_ci			}
3138c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
3148c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
3158c2ecf20Sopenharmony_ci		}
3168c2ecf20Sopenharmony_ci		/* is denormalized, adjust exponent */
3178c2ecf20Sopenharmony_ci		Dbl_clear_signexponent(opnd1p1);
3188c2ecf20Sopenharmony_ci		Dbl_leftshiftby1(opnd1p1,opnd1p2);
3198c2ecf20Sopenharmony_ci		Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
3208c2ecf20Sopenharmony_ci	}
3218c2ecf20Sopenharmony_ci	/* opnd2 needs to have hidden bit set with msb in hidden bit */
3228c2ecf20Sopenharmony_ci	if (Dbl_isnotzero_exponent(opnd2p1)) {
3238c2ecf20Sopenharmony_ci		Dbl_clear_signexponent_set_hidden(opnd2p1);
3248c2ecf20Sopenharmony_ci	}
3258c2ecf20Sopenharmony_ci	else {
3268c2ecf20Sopenharmony_ci		/* check for zero */
3278c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
3288c2ecf20Sopenharmony_ci			/*
3298c2ecf20Sopenharmony_ci			 * Perform the add opnd3 with zero here.
3308c2ecf20Sopenharmony_ci			 */
3318c2ecf20Sopenharmony_ci			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
3328c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
3338c2ecf20Sopenharmony_ci					Dbl_or_signs(opnd3p1,resultp1);
3348c2ecf20Sopenharmony_ci				} else {
3358c2ecf20Sopenharmony_ci					Dbl_and_signs(opnd3p1,resultp1);
3368c2ecf20Sopenharmony_ci				}
3378c2ecf20Sopenharmony_ci			}
3388c2ecf20Sopenharmony_ci			/*
3398c2ecf20Sopenharmony_ci			 * Now let's check for trapped underflow case.
3408c2ecf20Sopenharmony_ci			 */
3418c2ecf20Sopenharmony_ci			else if (Dbl_iszero_exponent(opnd3p1) &&
3428c2ecf20Sopenharmony_ci			    Is_underflowtrap_enabled()) {
3438c2ecf20Sopenharmony_ci                    		/* need to normalize results mantissa */
3448c2ecf20Sopenharmony_ci                    		sign_save = Dbl_signextendedsign(opnd3p1);
3458c2ecf20Sopenharmony_ci				result_exponent = 0;
3468c2ecf20Sopenharmony_ci                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
3478c2ecf20Sopenharmony_ci                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
3488c2ecf20Sopenharmony_ci                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
3498c2ecf20Sopenharmony_ci                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
3508c2ecf20Sopenharmony_ci							unfl);
3518c2ecf20Sopenharmony_ci                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
3528c2ecf20Sopenharmony_ci                    		/* inexact = FALSE */
3538c2ecf20Sopenharmony_ci				return(OPC_2E_UNDERFLOWEXCEPTION);
3548c2ecf20Sopenharmony_ci			}
3558c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
3568c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
3578c2ecf20Sopenharmony_ci		}
3588c2ecf20Sopenharmony_ci		/* is denormalized; want to normalize */
3598c2ecf20Sopenharmony_ci		Dbl_clear_signexponent(opnd2p1);
3608c2ecf20Sopenharmony_ci		Dbl_leftshiftby1(opnd2p1,opnd2p2);
3618c2ecf20Sopenharmony_ci		Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
3628c2ecf20Sopenharmony_ci	}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	/* Multiply the first two source mantissas together */
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	/*
3678c2ecf20Sopenharmony_ci	 * The intermediate result will be kept in tmpres,
3688c2ecf20Sopenharmony_ci	 * which needs enough room for 106 bits of mantissa,
3698c2ecf20Sopenharmony_ci	 * so lets call it a Double extended.
3708c2ecf20Sopenharmony_ci	 */
3718c2ecf20Sopenharmony_ci	Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	/*
3748c2ecf20Sopenharmony_ci	 * Four bits at a time are inspected in each loop, and a
3758c2ecf20Sopenharmony_ci	 * simple shift and add multiply algorithm is used.
3768c2ecf20Sopenharmony_ci	 */
3778c2ecf20Sopenharmony_ci	for (count = DBL_P-1; count >= 0; count -= 4) {
3788c2ecf20Sopenharmony_ci		Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
3798c2ecf20Sopenharmony_ci		if (Dbit28p2(opnd1p2)) {
3808c2ecf20Sopenharmony_ci	 		/* Fourword_add should be an ADD followed by 3 ADDC's */
3818c2ecf20Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
3828c2ecf20Sopenharmony_ci			 opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
3838c2ecf20Sopenharmony_ci		}
3848c2ecf20Sopenharmony_ci		if (Dbit29p2(opnd1p2)) {
3858c2ecf20Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
3868c2ecf20Sopenharmony_ci			 opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
3878c2ecf20Sopenharmony_ci		}
3888c2ecf20Sopenharmony_ci		if (Dbit30p2(opnd1p2)) {
3898c2ecf20Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
3908c2ecf20Sopenharmony_ci			 opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
3918c2ecf20Sopenharmony_ci		}
3928c2ecf20Sopenharmony_ci		if (Dbit31p2(opnd1p2)) {
3938c2ecf20Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
3948c2ecf20Sopenharmony_ci			 opnd2p1, opnd2p2, 0, 0);
3958c2ecf20Sopenharmony_ci		}
3968c2ecf20Sopenharmony_ci		Dbl_rightshiftby4(opnd1p1,opnd1p2);
3978c2ecf20Sopenharmony_ci	}
3988c2ecf20Sopenharmony_ci	if (Is_dexthiddenoverflow(tmpresp1)) {
3998c2ecf20Sopenharmony_ci		/* result mantissa >= 2 (mantissa overflow) */
4008c2ecf20Sopenharmony_ci		mpy_exponent++;
4018c2ecf20Sopenharmony_ci		Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
4028c2ecf20Sopenharmony_ci	}
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	/*
4058c2ecf20Sopenharmony_ci	 * Restore the sign of the mpy result which was saved in resultp1.
4068c2ecf20Sopenharmony_ci	 * The exponent will continue to be kept in mpy_exponent.
4078c2ecf20Sopenharmony_ci	 */
4088c2ecf20Sopenharmony_ci	Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	/*
4118c2ecf20Sopenharmony_ci	 * No rounding is required, since the result of the multiply
4128c2ecf20Sopenharmony_ci	 * is exact in the extended format.
4138c2ecf20Sopenharmony_ci	 */
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	/*
4168c2ecf20Sopenharmony_ci	 * Now we are ready to perform the add portion of the operation.
4178c2ecf20Sopenharmony_ci	 *
4188c2ecf20Sopenharmony_ci	 * The exponents need to be kept as integers for now, since the
4198c2ecf20Sopenharmony_ci	 * multiply result might not fit into the exponent field.  We
4208c2ecf20Sopenharmony_ci	 * can't overflow or underflow because of this yet, since the
4218c2ecf20Sopenharmony_ci	 * add could bring the final result back into range.
4228c2ecf20Sopenharmony_ci	 */
4238c2ecf20Sopenharmony_ci	add_exponent = Dbl_exponent(opnd3p1);
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	/*
4268c2ecf20Sopenharmony_ci	 * Check for denormalized or zero add operand.
4278c2ecf20Sopenharmony_ci	 */
4288c2ecf20Sopenharmony_ci	if (add_exponent == 0) {
4298c2ecf20Sopenharmony_ci		/* check for zero */
4308c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
4318c2ecf20Sopenharmony_ci			/* right is zero */
4328c2ecf20Sopenharmony_ci			/* Left can't be zero and must be result.
4338c2ecf20Sopenharmony_ci			 *
4348c2ecf20Sopenharmony_ci			 * The final result is now in tmpres and mpy_exponent,
4358c2ecf20Sopenharmony_ci			 * and needs to be rounded and squeezed back into
4368c2ecf20Sopenharmony_ci			 * double precision format from double extended.
4378c2ecf20Sopenharmony_ci			 */
4388c2ecf20Sopenharmony_ci			result_exponent = mpy_exponent;
4398c2ecf20Sopenharmony_ci			Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
4408c2ecf20Sopenharmony_ci				resultp1,resultp2,resultp3,resultp4);
4418c2ecf20Sopenharmony_ci			sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
4428c2ecf20Sopenharmony_ci			goto round;
4438c2ecf20Sopenharmony_ci		}
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci		/*
4468c2ecf20Sopenharmony_ci		 * Neither are zeroes.
4478c2ecf20Sopenharmony_ci		 * Adjust exponent and normalize add operand.
4488c2ecf20Sopenharmony_ci		 */
4498c2ecf20Sopenharmony_ci		sign_save = Dbl_signextendedsign(opnd3p1);	/* save sign */
4508c2ecf20Sopenharmony_ci		Dbl_clear_signexponent(opnd3p1);
4518c2ecf20Sopenharmony_ci		Dbl_leftshiftby1(opnd3p1,opnd3p2);
4528c2ecf20Sopenharmony_ci		Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
4538c2ecf20Sopenharmony_ci		Dbl_set_sign(opnd3p1,sign_save);	/* restore sign */
4548c2ecf20Sopenharmony_ci	} else {
4558c2ecf20Sopenharmony_ci		Dbl_clear_exponent_set_hidden(opnd3p1);
4568c2ecf20Sopenharmony_ci	}
4578c2ecf20Sopenharmony_ci	/*
4588c2ecf20Sopenharmony_ci	 * Copy opnd3 to the double extended variable called right.
4598c2ecf20Sopenharmony_ci	 */
4608c2ecf20Sopenharmony_ci	Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	/*
4638c2ecf20Sopenharmony_ci	 * A zero "save" helps discover equal operands (for later),
4648c2ecf20Sopenharmony_ci	 * and is used in swapping operands (if needed).
4658c2ecf20Sopenharmony_ci	 */
4668c2ecf20Sopenharmony_ci	Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	/*
4698c2ecf20Sopenharmony_ci	 * Compare magnitude of operands.
4708c2ecf20Sopenharmony_ci	 */
4718c2ecf20Sopenharmony_ci	Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
4728c2ecf20Sopenharmony_ci	Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
4738c2ecf20Sopenharmony_ci	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
4748c2ecf20Sopenharmony_ci	    Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
4758c2ecf20Sopenharmony_ci		/*
4768c2ecf20Sopenharmony_ci		 * Set the left operand to the larger one by XOR swap.
4778c2ecf20Sopenharmony_ci		 * First finish the first word "save".
4788c2ecf20Sopenharmony_ci		 */
4798c2ecf20Sopenharmony_ci		Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
4808c2ecf20Sopenharmony_ci		Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
4818c2ecf20Sopenharmony_ci		Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
4828c2ecf20Sopenharmony_ci			rightp2,rightp3,rightp4);
4838c2ecf20Sopenharmony_ci		/* also setup exponents used in rest of routine */
4848c2ecf20Sopenharmony_ci		diff_exponent = add_exponent - mpy_exponent;
4858c2ecf20Sopenharmony_ci		result_exponent = add_exponent;
4868c2ecf20Sopenharmony_ci	} else {
4878c2ecf20Sopenharmony_ci		/* also setup exponents used in rest of routine */
4888c2ecf20Sopenharmony_ci		diff_exponent = mpy_exponent - add_exponent;
4898c2ecf20Sopenharmony_ci		result_exponent = mpy_exponent;
4908c2ecf20Sopenharmony_ci	}
4918c2ecf20Sopenharmony_ci	/* Invariant: left is not smaller than right. */
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	/*
4948c2ecf20Sopenharmony_ci	 * Special case alignment of operands that would force alignment
4958c2ecf20Sopenharmony_ci	 * beyond the extent of the extension.  A further optimization
4968c2ecf20Sopenharmony_ci	 * could special case this but only reduces the path length for
4978c2ecf20Sopenharmony_ci	 * this infrequent case.
4988c2ecf20Sopenharmony_ci	 */
4998c2ecf20Sopenharmony_ci	if (diff_exponent > DBLEXT_THRESHOLD) {
5008c2ecf20Sopenharmony_ci		diff_exponent = DBLEXT_THRESHOLD;
5018c2ecf20Sopenharmony_ci	}
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	/* Align right operand by shifting it to the right */
5048c2ecf20Sopenharmony_ci	Dblext_clear_sign(rightp1);
5058c2ecf20Sopenharmony_ci	Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
5068c2ecf20Sopenharmony_ci		/*shifted by*/diff_exponent);
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	/* Treat sum and difference of the operands separately. */
5098c2ecf20Sopenharmony_ci	if ((int)save < 0) {
5108c2ecf20Sopenharmony_ci		/*
5118c2ecf20Sopenharmony_ci		 * Difference of the two operands.  Overflow can occur if the
5128c2ecf20Sopenharmony_ci		 * multiply overflowed.  A borrow can occur out of the hidden
5138c2ecf20Sopenharmony_ci		 * bit and force a post normalization phase.
5148c2ecf20Sopenharmony_ci		 */
5158c2ecf20Sopenharmony_ci		Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
5168c2ecf20Sopenharmony_ci			rightp1,rightp2,rightp3,rightp4,
5178c2ecf20Sopenharmony_ci			resultp1,resultp2,resultp3,resultp4);
5188c2ecf20Sopenharmony_ci		sign_save = Dbl_signextendedsign(resultp1);
5198c2ecf20Sopenharmony_ci		if (Dbl_iszero_hidden(resultp1)) {
5208c2ecf20Sopenharmony_ci			/* Handle normalization */
5218c2ecf20Sopenharmony_ci		/* A straightforward algorithm would now shift the
5228c2ecf20Sopenharmony_ci		 * result and extension left until the hidden bit
5238c2ecf20Sopenharmony_ci		 * becomes one.  Not all of the extension bits need
5248c2ecf20Sopenharmony_ci		 * participate in the shift.  Only the two most
5258c2ecf20Sopenharmony_ci		 * significant bits (round and guard) are needed.
5268c2ecf20Sopenharmony_ci		 * If only a single shift is needed then the guard
5278c2ecf20Sopenharmony_ci		 * bit becomes a significant low order bit and the
5288c2ecf20Sopenharmony_ci		 * extension must participate in the rounding.
5298c2ecf20Sopenharmony_ci		 * If more than a single shift is needed, then all
5308c2ecf20Sopenharmony_ci		 * bits to the right of the guard bit are zeros,
5318c2ecf20Sopenharmony_ci		 * and the guard bit may or may not be zero. */
5328c2ecf20Sopenharmony_ci			Dblext_leftshiftby1(resultp1,resultp2,resultp3,
5338c2ecf20Sopenharmony_ci				resultp4);
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci			/* Need to check for a zero result.  The sign and
5368c2ecf20Sopenharmony_ci			 * exponent fields have already been zeroed.  The more
5378c2ecf20Sopenharmony_ci			 * efficient test of the full object can be used.
5388c2ecf20Sopenharmony_ci			 */
5398c2ecf20Sopenharmony_ci			 if(Dblext_iszero(resultp1,resultp2,resultp3,resultp4)){
5408c2ecf20Sopenharmony_ci				/* Must have been "x-x" or "x+(-x)". */
5418c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS))
5428c2ecf20Sopenharmony_ci					Dbl_setone_sign(resultp1);
5438c2ecf20Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
5448c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
5458c2ecf20Sopenharmony_ci			}
5468c2ecf20Sopenharmony_ci			result_exponent--;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci			/* Look to see if normalization is finished. */
5498c2ecf20Sopenharmony_ci			if (Dbl_isone_hidden(resultp1)) {
5508c2ecf20Sopenharmony_ci				/* No further normalization is needed */
5518c2ecf20Sopenharmony_ci				goto round;
5528c2ecf20Sopenharmony_ci			}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci			/* Discover first one bit to determine shift amount.
5558c2ecf20Sopenharmony_ci			 * Use a modified binary search.  We have already
5568c2ecf20Sopenharmony_ci			 * shifted the result one position right and still
5578c2ecf20Sopenharmony_ci			 * not found a one so the remainder of the extension
5588c2ecf20Sopenharmony_ci			 * must be zero and simplifies rounding. */
5598c2ecf20Sopenharmony_ci			/* Scan bytes */
5608c2ecf20Sopenharmony_ci			while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
5618c2ecf20Sopenharmony_ci				Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
5628c2ecf20Sopenharmony_ci				result_exponent -= 8;
5638c2ecf20Sopenharmony_ci			}
5648c2ecf20Sopenharmony_ci			/* Now narrow it down to the nibble */
5658c2ecf20Sopenharmony_ci			if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
5668c2ecf20Sopenharmony_ci				/* The lower nibble contains the
5678c2ecf20Sopenharmony_ci				 * normalizing one */
5688c2ecf20Sopenharmony_ci				Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
5698c2ecf20Sopenharmony_ci				result_exponent -= 4;
5708c2ecf20Sopenharmony_ci			}
5718c2ecf20Sopenharmony_ci			/* Select case where first bit is set (already
5728c2ecf20Sopenharmony_ci			 * normalized) otherwise select the proper shift. */
5738c2ecf20Sopenharmony_ci			jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
5748c2ecf20Sopenharmony_ci			if (jumpsize <= 7) switch(jumpsize) {
5758c2ecf20Sopenharmony_ci			case 1:
5768c2ecf20Sopenharmony_ci				Dblext_leftshiftby3(resultp1,resultp2,resultp3,
5778c2ecf20Sopenharmony_ci					resultp4);
5788c2ecf20Sopenharmony_ci				result_exponent -= 3;
5798c2ecf20Sopenharmony_ci				break;
5808c2ecf20Sopenharmony_ci			case 2:
5818c2ecf20Sopenharmony_ci			case 3:
5828c2ecf20Sopenharmony_ci				Dblext_leftshiftby2(resultp1,resultp2,resultp3,
5838c2ecf20Sopenharmony_ci					resultp4);
5848c2ecf20Sopenharmony_ci				result_exponent -= 2;
5858c2ecf20Sopenharmony_ci				break;
5868c2ecf20Sopenharmony_ci			case 4:
5878c2ecf20Sopenharmony_ci			case 5:
5888c2ecf20Sopenharmony_ci			case 6:
5898c2ecf20Sopenharmony_ci			case 7:
5908c2ecf20Sopenharmony_ci				Dblext_leftshiftby1(resultp1,resultp2,resultp3,
5918c2ecf20Sopenharmony_ci					resultp4);
5928c2ecf20Sopenharmony_ci				result_exponent -= 1;
5938c2ecf20Sopenharmony_ci				break;
5948c2ecf20Sopenharmony_ci			}
5958c2ecf20Sopenharmony_ci		} /* end if (hidden...)... */
5968c2ecf20Sopenharmony_ci	/* Fall through and round */
5978c2ecf20Sopenharmony_ci	} /* end if (save < 0)... */
5988c2ecf20Sopenharmony_ci	else {
5998c2ecf20Sopenharmony_ci		/* Add magnitudes */
6008c2ecf20Sopenharmony_ci		Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
6018c2ecf20Sopenharmony_ci			rightp1,rightp2,rightp3,rightp4,
6028c2ecf20Sopenharmony_ci			/*to*/resultp1,resultp2,resultp3,resultp4);
6038c2ecf20Sopenharmony_ci		sign_save = Dbl_signextendedsign(resultp1);
6048c2ecf20Sopenharmony_ci		if (Dbl_isone_hiddenoverflow(resultp1)) {
6058c2ecf20Sopenharmony_ci	    		/* Prenormalization required. */
6068c2ecf20Sopenharmony_ci	    		Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
6078c2ecf20Sopenharmony_ci				resultp4);
6088c2ecf20Sopenharmony_ci	    		result_exponent++;
6098c2ecf20Sopenharmony_ci		} /* end if hiddenoverflow... */
6108c2ecf20Sopenharmony_ci	} /* end else ...add magnitudes... */
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	/* Round the result.  If the extension and lower two words are
6138c2ecf20Sopenharmony_ci	 * all zeros, then the result is exact.  Otherwise round in the
6148c2ecf20Sopenharmony_ci	 * correct direction.  Underflow is possible. If a postnormalization
6158c2ecf20Sopenharmony_ci	 * is necessary, then the mantissa is all zeros so no shift is needed.
6168c2ecf20Sopenharmony_ci	 */
6178c2ecf20Sopenharmony_ci  round:
6188c2ecf20Sopenharmony_ci	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
6198c2ecf20Sopenharmony_ci		Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
6208c2ecf20Sopenharmony_ci			result_exponent,is_tiny);
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci	Dbl_set_sign(resultp1,/*using*/sign_save);
6238c2ecf20Sopenharmony_ci	if (Dblext_isnotzero_mantissap3(resultp3) ||
6248c2ecf20Sopenharmony_ci	    Dblext_isnotzero_mantissap4(resultp4)) {
6258c2ecf20Sopenharmony_ci		inexact = TRUE;
6268c2ecf20Sopenharmony_ci		switch(Rounding_mode()) {
6278c2ecf20Sopenharmony_ci		case ROUNDNEAREST: /* The default. */
6288c2ecf20Sopenharmony_ci			if (Dblext_isone_highp3(resultp3)) {
6298c2ecf20Sopenharmony_ci				/* at least 1/2 ulp */
6308c2ecf20Sopenharmony_ci				if (Dblext_isnotzero_low31p3(resultp3) ||
6318c2ecf20Sopenharmony_ci				    Dblext_isnotzero_mantissap4(resultp4) ||
6328c2ecf20Sopenharmony_ci				    Dblext_isone_lowp2(resultp2)) {
6338c2ecf20Sopenharmony_ci					/* either exactly half way and odd or
6348c2ecf20Sopenharmony_ci					 * more than 1/2ulp */
6358c2ecf20Sopenharmony_ci					Dbl_increment(resultp1,resultp2);
6368c2ecf20Sopenharmony_ci				}
6378c2ecf20Sopenharmony_ci			}
6388c2ecf20Sopenharmony_ci	    		break;
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci		case ROUNDPLUS:
6418c2ecf20Sopenharmony_ci	    		if (Dbl_iszero_sign(resultp1)) {
6428c2ecf20Sopenharmony_ci				/* Round up positive results */
6438c2ecf20Sopenharmony_ci				Dbl_increment(resultp1,resultp2);
6448c2ecf20Sopenharmony_ci			}
6458c2ecf20Sopenharmony_ci			break;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci		case ROUNDMINUS:
6488c2ecf20Sopenharmony_ci	    		if (Dbl_isone_sign(resultp1)) {
6498c2ecf20Sopenharmony_ci				/* Round down negative results */
6508c2ecf20Sopenharmony_ci				Dbl_increment(resultp1,resultp2);
6518c2ecf20Sopenharmony_ci			}
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci		case ROUNDZERO:;
6548c2ecf20Sopenharmony_ci			/* truncate is simple */
6558c2ecf20Sopenharmony_ci		} /* end switch... */
6568c2ecf20Sopenharmony_ci		if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
6578c2ecf20Sopenharmony_ci	}
6588c2ecf20Sopenharmony_ci	if (result_exponent >= DBL_INFINITY_EXPONENT) {
6598c2ecf20Sopenharmony_ci                /* trap if OVERFLOWTRAP enabled */
6608c2ecf20Sopenharmony_ci                if (Is_overflowtrap_enabled()) {
6618c2ecf20Sopenharmony_ci                        /*
6628c2ecf20Sopenharmony_ci                         * Adjust bias of result
6638c2ecf20Sopenharmony_ci                         */
6648c2ecf20Sopenharmony_ci                        Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
6658c2ecf20Sopenharmony_ci                        Dbl_copytoptr(resultp1,resultp2,dstptr);
6668c2ecf20Sopenharmony_ci                        if (inexact)
6678c2ecf20Sopenharmony_ci                            if (Is_inexacttrap_enabled())
6688c2ecf20Sopenharmony_ci                                return (OPC_2E_OVERFLOWEXCEPTION |
6698c2ecf20Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
6708c2ecf20Sopenharmony_ci                            else Set_inexactflag();
6718c2ecf20Sopenharmony_ci                        return (OPC_2E_OVERFLOWEXCEPTION);
6728c2ecf20Sopenharmony_ci                }
6738c2ecf20Sopenharmony_ci                inexact = TRUE;
6748c2ecf20Sopenharmony_ci                Set_overflowflag();
6758c2ecf20Sopenharmony_ci                /* set result to infinity or largest number */
6768c2ecf20Sopenharmony_ci                Dbl_setoverflow(resultp1,resultp2);
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	} else if (result_exponent <= 0) {	/* underflow case */
6798c2ecf20Sopenharmony_ci		if (Is_underflowtrap_enabled()) {
6808c2ecf20Sopenharmony_ci                        /*
6818c2ecf20Sopenharmony_ci                         * Adjust bias of result
6828c2ecf20Sopenharmony_ci                         */
6838c2ecf20Sopenharmony_ci                	Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
6848c2ecf20Sopenharmony_ci			Dbl_copytoptr(resultp1,resultp2,dstptr);
6858c2ecf20Sopenharmony_ci                        if (inexact)
6868c2ecf20Sopenharmony_ci                            if (Is_inexacttrap_enabled())
6878c2ecf20Sopenharmony_ci                                return (OPC_2E_UNDERFLOWEXCEPTION |
6888c2ecf20Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
6898c2ecf20Sopenharmony_ci                            else Set_inexactflag();
6908c2ecf20Sopenharmony_ci	    		return(OPC_2E_UNDERFLOWEXCEPTION);
6918c2ecf20Sopenharmony_ci		}
6928c2ecf20Sopenharmony_ci		else if (inexact && is_tiny) Set_underflowflag();
6938c2ecf20Sopenharmony_ci	}
6948c2ecf20Sopenharmony_ci	else Dbl_set_exponent(resultp1,result_exponent);
6958c2ecf20Sopenharmony_ci	Dbl_copytoptr(resultp1,resultp2,dstptr);
6968c2ecf20Sopenharmony_ci	if (inexact)
6978c2ecf20Sopenharmony_ci		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
6988c2ecf20Sopenharmony_ci		else Set_inexactflag();
6998c2ecf20Sopenharmony_ci    	return(NOEXCEPTION);
7008c2ecf20Sopenharmony_ci}
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci/*
7038c2ecf20Sopenharmony_ci *  Double Floating-point Multiply Negate Fused Add
7048c2ecf20Sopenharmony_ci */
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_cidbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_cidbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
7098c2ecf20Sopenharmony_ciunsigned int *status;
7108c2ecf20Sopenharmony_ci{
7118c2ecf20Sopenharmony_ci	unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
7128c2ecf20Sopenharmony_ci	register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
7138c2ecf20Sopenharmony_ci	unsigned int rightp1, rightp2, rightp3, rightp4;
7148c2ecf20Sopenharmony_ci	unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
7158c2ecf20Sopenharmony_ci	register int mpy_exponent, add_exponent, count;
7168c2ecf20Sopenharmony_ci	boolean inexact = FALSE, is_tiny = FALSE;
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	unsigned int signlessleft1, signlessright1, save;
7198c2ecf20Sopenharmony_ci	register int result_exponent, diff_exponent;
7208c2ecf20Sopenharmony_ci	int sign_save, jumpsize;
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
7238c2ecf20Sopenharmony_ci	Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
7248c2ecf20Sopenharmony_ci	Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	/*
7278c2ecf20Sopenharmony_ci	 * set sign bit of result of multiply
7288c2ecf20Sopenharmony_ci	 */
7298c2ecf20Sopenharmony_ci	if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
7308c2ecf20Sopenharmony_ci		Dbl_setzerop1(resultp1);
7318c2ecf20Sopenharmony_ci	else
7328c2ecf20Sopenharmony_ci		Dbl_setnegativezerop1(resultp1);
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	/*
7358c2ecf20Sopenharmony_ci	 * Generate multiply exponent
7368c2ecf20Sopenharmony_ci	 */
7378c2ecf20Sopenharmony_ci	mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	/*
7408c2ecf20Sopenharmony_ci	 * check first operand for NaN's or infinity
7418c2ecf20Sopenharmony_ci	 */
7428c2ecf20Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd1p1)) {
7438c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
7448c2ecf20Sopenharmony_ci			if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
7458c2ecf20Sopenharmony_ci			    Dbl_isnotnan(opnd3p1,opnd3p2)) {
7468c2ecf20Sopenharmony_ci				if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
7478c2ecf20Sopenharmony_ci					/*
7488c2ecf20Sopenharmony_ci					 * invalid since operands are infinity
7498c2ecf20Sopenharmony_ci					 * and zero
7508c2ecf20Sopenharmony_ci					 */
7518c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
7528c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
7538c2ecf20Sopenharmony_ci					Set_invalidflag();
7548c2ecf20Sopenharmony_ci					Dbl_makequietnan(resultp1,resultp2);
7558c2ecf20Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
7568c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
7578c2ecf20Sopenharmony_ci				}
7588c2ecf20Sopenharmony_ci				/*
7598c2ecf20Sopenharmony_ci				 * Check third operand for infinity with a
7608c2ecf20Sopenharmony_ci				 *  sign opposite of the multiply result
7618c2ecf20Sopenharmony_ci				 */
7628c2ecf20Sopenharmony_ci				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
7638c2ecf20Sopenharmony_ci				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
7648c2ecf20Sopenharmony_ci					/*
7658c2ecf20Sopenharmony_ci					 * invalid since attempting a magnitude
7668c2ecf20Sopenharmony_ci					 * subtraction of infinities
7678c2ecf20Sopenharmony_ci					 */
7688c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
7698c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
7708c2ecf20Sopenharmony_ci					Set_invalidflag();
7718c2ecf20Sopenharmony_ci					Dbl_makequietnan(resultp1,resultp2);
7728c2ecf20Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
7738c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
7748c2ecf20Sopenharmony_ci				}
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci				/*
7778c2ecf20Sopenharmony_ci			 	 * return infinity
7788c2ecf20Sopenharmony_ci			 	 */
7798c2ecf20Sopenharmony_ci				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
7808c2ecf20Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
7818c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
7828c2ecf20Sopenharmony_ci			}
7838c2ecf20Sopenharmony_ci		}
7848c2ecf20Sopenharmony_ci		else {
7858c2ecf20Sopenharmony_ci			/*
7868c2ecf20Sopenharmony_ci		 	 * is NaN; signaling or quiet?
7878c2ecf20Sopenharmony_ci		 	 */
7888c2ecf20Sopenharmony_ci			if (Dbl_isone_signaling(opnd1p1)) {
7898c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
7908c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
7918c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
7928c2ecf20Sopenharmony_ci				/* make NaN quiet */
7938c2ecf20Sopenharmony_ci				Set_invalidflag();
7948c2ecf20Sopenharmony_ci				Dbl_set_quiet(opnd1p1);
7958c2ecf20Sopenharmony_ci			}
7968c2ecf20Sopenharmony_ci			/*
7978c2ecf20Sopenharmony_ci			 * is second operand a signaling NaN?
7988c2ecf20Sopenharmony_ci			 */
7998c2ecf20Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd2p1)) {
8008c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
8018c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
8028c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
8038c2ecf20Sopenharmony_ci				/* make NaN quiet */
8048c2ecf20Sopenharmony_ci				Set_invalidflag();
8058c2ecf20Sopenharmony_ci				Dbl_set_quiet(opnd2p1);
8068c2ecf20Sopenharmony_ci				Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
8078c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
8088c2ecf20Sopenharmony_ci			}
8098c2ecf20Sopenharmony_ci			/*
8108c2ecf20Sopenharmony_ci			 * is third operand a signaling NaN?
8118c2ecf20Sopenharmony_ci			 */
8128c2ecf20Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd3p1)) {
8138c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
8148c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
8158c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
8168c2ecf20Sopenharmony_ci				/* make NaN quiet */
8178c2ecf20Sopenharmony_ci				Set_invalidflag();
8188c2ecf20Sopenharmony_ci				Dbl_set_quiet(opnd3p1);
8198c2ecf20Sopenharmony_ci				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
8208c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
8218c2ecf20Sopenharmony_ci			}
8228c2ecf20Sopenharmony_ci			/*
8238c2ecf20Sopenharmony_ci		 	 * return quiet NaN
8248c2ecf20Sopenharmony_ci		 	 */
8258c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
8268c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
8278c2ecf20Sopenharmony_ci		}
8288c2ecf20Sopenharmony_ci	}
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	/*
8318c2ecf20Sopenharmony_ci	 * check second operand for NaN's or infinity
8328c2ecf20Sopenharmony_ci	 */
8338c2ecf20Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd2p1)) {
8348c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
8358c2ecf20Sopenharmony_ci			if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
8368c2ecf20Sopenharmony_ci				if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
8378c2ecf20Sopenharmony_ci					/*
8388c2ecf20Sopenharmony_ci					 * invalid since multiply operands are
8398c2ecf20Sopenharmony_ci					 * zero & infinity
8408c2ecf20Sopenharmony_ci					 */
8418c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
8428c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
8438c2ecf20Sopenharmony_ci					Set_invalidflag();
8448c2ecf20Sopenharmony_ci					Dbl_makequietnan(opnd2p1,opnd2p2);
8458c2ecf20Sopenharmony_ci					Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
8468c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
8478c2ecf20Sopenharmony_ci				}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci				/*
8508c2ecf20Sopenharmony_ci				 * Check third operand for infinity with a
8518c2ecf20Sopenharmony_ci				 *  sign opposite of the multiply result
8528c2ecf20Sopenharmony_ci				 */
8538c2ecf20Sopenharmony_ci				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
8548c2ecf20Sopenharmony_ci				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
8558c2ecf20Sopenharmony_ci					/*
8568c2ecf20Sopenharmony_ci					 * invalid since attempting a magnitude
8578c2ecf20Sopenharmony_ci					 * subtraction of infinities
8588c2ecf20Sopenharmony_ci					 */
8598c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
8608c2ecf20Sopenharmony_ci				       		return(OPC_2E_INVALIDEXCEPTION);
8618c2ecf20Sopenharmony_ci				       	Set_invalidflag();
8628c2ecf20Sopenharmony_ci				       	Dbl_makequietnan(resultp1,resultp2);
8638c2ecf20Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
8648c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
8658c2ecf20Sopenharmony_ci				}
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci				/*
8688c2ecf20Sopenharmony_ci				 * return infinity
8698c2ecf20Sopenharmony_ci				 */
8708c2ecf20Sopenharmony_ci				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
8718c2ecf20Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
8728c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
8738c2ecf20Sopenharmony_ci			}
8748c2ecf20Sopenharmony_ci		}
8758c2ecf20Sopenharmony_ci		else {
8768c2ecf20Sopenharmony_ci			/*
8778c2ecf20Sopenharmony_ci			 * is NaN; signaling or quiet?
8788c2ecf20Sopenharmony_ci			 */
8798c2ecf20Sopenharmony_ci			if (Dbl_isone_signaling(opnd2p1)) {
8808c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
8818c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
8828c2ecf20Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
8838c2ecf20Sopenharmony_ci				/* make NaN quiet */
8848c2ecf20Sopenharmony_ci				Set_invalidflag();
8858c2ecf20Sopenharmony_ci				Dbl_set_quiet(opnd2p1);
8868c2ecf20Sopenharmony_ci			}
8878c2ecf20Sopenharmony_ci			/*
8888c2ecf20Sopenharmony_ci			 * is third operand a signaling NaN?
8898c2ecf20Sopenharmony_ci			 */
8908c2ecf20Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd3p1)) {
8918c2ecf20Sopenharmony_ci			       	/* trap if INVALIDTRAP enabled */
8928c2ecf20Sopenharmony_ci			       	if (Is_invalidtrap_enabled())
8938c2ecf20Sopenharmony_ci				   		return(OPC_2E_INVALIDEXCEPTION);
8948c2ecf20Sopenharmony_ci			       	/* make NaN quiet */
8958c2ecf20Sopenharmony_ci			       	Set_invalidflag();
8968c2ecf20Sopenharmony_ci			       	Dbl_set_quiet(opnd3p1);
8978c2ecf20Sopenharmony_ci				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
8988c2ecf20Sopenharmony_ci		       		return(NOEXCEPTION);
8998c2ecf20Sopenharmony_ci			}
9008c2ecf20Sopenharmony_ci			/*
9018c2ecf20Sopenharmony_ci			 * return quiet NaN
9028c2ecf20Sopenharmony_ci			 */
9038c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
9048c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
9058c2ecf20Sopenharmony_ci		}
9068c2ecf20Sopenharmony_ci	}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	/*
9098c2ecf20Sopenharmony_ci	 * check third operand for NaN's or infinity
9108c2ecf20Sopenharmony_ci	 */
9118c2ecf20Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd3p1)) {
9128c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
9138c2ecf20Sopenharmony_ci			/* return infinity */
9148c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
9158c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
9168c2ecf20Sopenharmony_ci		} else {
9178c2ecf20Sopenharmony_ci			/*
9188c2ecf20Sopenharmony_ci			 * is NaN; signaling or quiet?
9198c2ecf20Sopenharmony_ci			 */
9208c2ecf20Sopenharmony_ci			if (Dbl_isone_signaling(opnd3p1)) {
9218c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
9228c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
9238c2ecf20Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
9248c2ecf20Sopenharmony_ci				/* make NaN quiet */
9258c2ecf20Sopenharmony_ci				Set_invalidflag();
9268c2ecf20Sopenharmony_ci				Dbl_set_quiet(opnd3p1);
9278c2ecf20Sopenharmony_ci			}
9288c2ecf20Sopenharmony_ci			/*
9298c2ecf20Sopenharmony_ci			 * return quiet NaN
9308c2ecf20Sopenharmony_ci 			 */
9318c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
9328c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
9338c2ecf20Sopenharmony_ci		}
9348c2ecf20Sopenharmony_ci    	}
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci	/*
9378c2ecf20Sopenharmony_ci	 * Generate multiply mantissa
9388c2ecf20Sopenharmony_ci	 */
9398c2ecf20Sopenharmony_ci	if (Dbl_isnotzero_exponent(opnd1p1)) {
9408c2ecf20Sopenharmony_ci		/* set hidden bit */
9418c2ecf20Sopenharmony_ci		Dbl_clear_signexponent_set_hidden(opnd1p1);
9428c2ecf20Sopenharmony_ci	}
9438c2ecf20Sopenharmony_ci	else {
9448c2ecf20Sopenharmony_ci		/* check for zero */
9458c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
9468c2ecf20Sopenharmony_ci			/*
9478c2ecf20Sopenharmony_ci			 * Perform the add opnd3 with zero here.
9488c2ecf20Sopenharmony_ci			 */
9498c2ecf20Sopenharmony_ci			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
9508c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
9518c2ecf20Sopenharmony_ci					Dbl_or_signs(opnd3p1,resultp1);
9528c2ecf20Sopenharmony_ci				} else {
9538c2ecf20Sopenharmony_ci					Dbl_and_signs(opnd3p1,resultp1);
9548c2ecf20Sopenharmony_ci				}
9558c2ecf20Sopenharmony_ci			}
9568c2ecf20Sopenharmony_ci			/*
9578c2ecf20Sopenharmony_ci			 * Now let's check for trapped underflow case.
9588c2ecf20Sopenharmony_ci			 */
9598c2ecf20Sopenharmony_ci			else if (Dbl_iszero_exponent(opnd3p1) &&
9608c2ecf20Sopenharmony_ci			         Is_underflowtrap_enabled()) {
9618c2ecf20Sopenharmony_ci                    		/* need to normalize results mantissa */
9628c2ecf20Sopenharmony_ci                    		sign_save = Dbl_signextendedsign(opnd3p1);
9638c2ecf20Sopenharmony_ci				result_exponent = 0;
9648c2ecf20Sopenharmony_ci                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
9658c2ecf20Sopenharmony_ci                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
9668c2ecf20Sopenharmony_ci                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
9678c2ecf20Sopenharmony_ci                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
9688c2ecf20Sopenharmony_ci							unfl);
9698c2ecf20Sopenharmony_ci                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
9708c2ecf20Sopenharmony_ci                    		/* inexact = FALSE */
9718c2ecf20Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
9728c2ecf20Sopenharmony_ci			}
9738c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
9748c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
9758c2ecf20Sopenharmony_ci		}
9768c2ecf20Sopenharmony_ci		/* is denormalized, adjust exponent */
9778c2ecf20Sopenharmony_ci		Dbl_clear_signexponent(opnd1p1);
9788c2ecf20Sopenharmony_ci		Dbl_leftshiftby1(opnd1p1,opnd1p2);
9798c2ecf20Sopenharmony_ci		Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
9808c2ecf20Sopenharmony_ci	}
9818c2ecf20Sopenharmony_ci	/* opnd2 needs to have hidden bit set with msb in hidden bit */
9828c2ecf20Sopenharmony_ci	if (Dbl_isnotzero_exponent(opnd2p1)) {
9838c2ecf20Sopenharmony_ci		Dbl_clear_signexponent_set_hidden(opnd2p1);
9848c2ecf20Sopenharmony_ci	}
9858c2ecf20Sopenharmony_ci	else {
9868c2ecf20Sopenharmony_ci		/* check for zero */
9878c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
9888c2ecf20Sopenharmony_ci			/*
9898c2ecf20Sopenharmony_ci			 * Perform the add opnd3 with zero here.
9908c2ecf20Sopenharmony_ci			 */
9918c2ecf20Sopenharmony_ci			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
9928c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
9938c2ecf20Sopenharmony_ci					Dbl_or_signs(opnd3p1,resultp1);
9948c2ecf20Sopenharmony_ci				} else {
9958c2ecf20Sopenharmony_ci					Dbl_and_signs(opnd3p1,resultp1);
9968c2ecf20Sopenharmony_ci				}
9978c2ecf20Sopenharmony_ci			}
9988c2ecf20Sopenharmony_ci			/*
9998c2ecf20Sopenharmony_ci			 * Now let's check for trapped underflow case.
10008c2ecf20Sopenharmony_ci			 */
10018c2ecf20Sopenharmony_ci			else if (Dbl_iszero_exponent(opnd3p1) &&
10028c2ecf20Sopenharmony_ci			    Is_underflowtrap_enabled()) {
10038c2ecf20Sopenharmony_ci                    		/* need to normalize results mantissa */
10048c2ecf20Sopenharmony_ci                    		sign_save = Dbl_signextendedsign(opnd3p1);
10058c2ecf20Sopenharmony_ci				result_exponent = 0;
10068c2ecf20Sopenharmony_ci                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
10078c2ecf20Sopenharmony_ci                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
10088c2ecf20Sopenharmony_ci                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
10098c2ecf20Sopenharmony_ci                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
10108c2ecf20Sopenharmony_ci							unfl);
10118c2ecf20Sopenharmony_ci                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
10128c2ecf20Sopenharmony_ci                    		/* inexact = FALSE */
10138c2ecf20Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
10148c2ecf20Sopenharmony_ci			}
10158c2ecf20Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
10168c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
10178c2ecf20Sopenharmony_ci		}
10188c2ecf20Sopenharmony_ci		/* is denormalized; want to normalize */
10198c2ecf20Sopenharmony_ci		Dbl_clear_signexponent(opnd2p1);
10208c2ecf20Sopenharmony_ci		Dbl_leftshiftby1(opnd2p1,opnd2p2);
10218c2ecf20Sopenharmony_ci		Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
10228c2ecf20Sopenharmony_ci	}
10238c2ecf20Sopenharmony_ci
10248c2ecf20Sopenharmony_ci	/* Multiply the first two source mantissas together */
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	/*
10278c2ecf20Sopenharmony_ci	 * The intermediate result will be kept in tmpres,
10288c2ecf20Sopenharmony_ci	 * which needs enough room for 106 bits of mantissa,
10298c2ecf20Sopenharmony_ci	 * so lets call it a Double extended.
10308c2ecf20Sopenharmony_ci	 */
10318c2ecf20Sopenharmony_ci	Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	/*
10348c2ecf20Sopenharmony_ci	 * Four bits at a time are inspected in each loop, and a
10358c2ecf20Sopenharmony_ci	 * simple shift and add multiply algorithm is used.
10368c2ecf20Sopenharmony_ci	 */
10378c2ecf20Sopenharmony_ci	for (count = DBL_P-1; count >= 0; count -= 4) {
10388c2ecf20Sopenharmony_ci		Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
10398c2ecf20Sopenharmony_ci		if (Dbit28p2(opnd1p2)) {
10408c2ecf20Sopenharmony_ci	 		/* Fourword_add should be an ADD followed by 3 ADDC's */
10418c2ecf20Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
10428c2ecf20Sopenharmony_ci			 opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
10438c2ecf20Sopenharmony_ci		}
10448c2ecf20Sopenharmony_ci		if (Dbit29p2(opnd1p2)) {
10458c2ecf20Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
10468c2ecf20Sopenharmony_ci			 opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
10478c2ecf20Sopenharmony_ci		}
10488c2ecf20Sopenharmony_ci		if (Dbit30p2(opnd1p2)) {
10498c2ecf20Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
10508c2ecf20Sopenharmony_ci			 opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
10518c2ecf20Sopenharmony_ci		}
10528c2ecf20Sopenharmony_ci		if (Dbit31p2(opnd1p2)) {
10538c2ecf20Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
10548c2ecf20Sopenharmony_ci			 opnd2p1, opnd2p2, 0, 0);
10558c2ecf20Sopenharmony_ci		}
10568c2ecf20Sopenharmony_ci		Dbl_rightshiftby4(opnd1p1,opnd1p2);
10578c2ecf20Sopenharmony_ci	}
10588c2ecf20Sopenharmony_ci	if (Is_dexthiddenoverflow(tmpresp1)) {
10598c2ecf20Sopenharmony_ci		/* result mantissa >= 2 (mantissa overflow) */
10608c2ecf20Sopenharmony_ci		mpy_exponent++;
10618c2ecf20Sopenharmony_ci		Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
10628c2ecf20Sopenharmony_ci	}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_ci	/*
10658c2ecf20Sopenharmony_ci	 * Restore the sign of the mpy result which was saved in resultp1.
10668c2ecf20Sopenharmony_ci	 * The exponent will continue to be kept in mpy_exponent.
10678c2ecf20Sopenharmony_ci	 */
10688c2ecf20Sopenharmony_ci	Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	/*
10718c2ecf20Sopenharmony_ci	 * No rounding is required, since the result of the multiply
10728c2ecf20Sopenharmony_ci	 * is exact in the extended format.
10738c2ecf20Sopenharmony_ci	 */
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	/*
10768c2ecf20Sopenharmony_ci	 * Now we are ready to perform the add portion of the operation.
10778c2ecf20Sopenharmony_ci	 *
10788c2ecf20Sopenharmony_ci	 * The exponents need to be kept as integers for now, since the
10798c2ecf20Sopenharmony_ci	 * multiply result might not fit into the exponent field.  We
10808c2ecf20Sopenharmony_ci	 * can't overflow or underflow because of this yet, since the
10818c2ecf20Sopenharmony_ci	 * add could bring the final result back into range.
10828c2ecf20Sopenharmony_ci	 */
10838c2ecf20Sopenharmony_ci	add_exponent = Dbl_exponent(opnd3p1);
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci	/*
10868c2ecf20Sopenharmony_ci	 * Check for denormalized or zero add operand.
10878c2ecf20Sopenharmony_ci	 */
10888c2ecf20Sopenharmony_ci	if (add_exponent == 0) {
10898c2ecf20Sopenharmony_ci		/* check for zero */
10908c2ecf20Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
10918c2ecf20Sopenharmony_ci			/* right is zero */
10928c2ecf20Sopenharmony_ci			/* Left can't be zero and must be result.
10938c2ecf20Sopenharmony_ci			 *
10948c2ecf20Sopenharmony_ci			 * The final result is now in tmpres and mpy_exponent,
10958c2ecf20Sopenharmony_ci			 * and needs to be rounded and squeezed back into
10968c2ecf20Sopenharmony_ci			 * double precision format from double extended.
10978c2ecf20Sopenharmony_ci			 */
10988c2ecf20Sopenharmony_ci			result_exponent = mpy_exponent;
10998c2ecf20Sopenharmony_ci			Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
11008c2ecf20Sopenharmony_ci				resultp1,resultp2,resultp3,resultp4);
11018c2ecf20Sopenharmony_ci			sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
11028c2ecf20Sopenharmony_ci			goto round;
11038c2ecf20Sopenharmony_ci		}
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci		/*
11068c2ecf20Sopenharmony_ci		 * Neither are zeroes.
11078c2ecf20Sopenharmony_ci		 * Adjust exponent and normalize add operand.
11088c2ecf20Sopenharmony_ci		 */
11098c2ecf20Sopenharmony_ci		sign_save = Dbl_signextendedsign(opnd3p1);	/* save sign */
11108c2ecf20Sopenharmony_ci		Dbl_clear_signexponent(opnd3p1);
11118c2ecf20Sopenharmony_ci		Dbl_leftshiftby1(opnd3p1,opnd3p2);
11128c2ecf20Sopenharmony_ci		Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
11138c2ecf20Sopenharmony_ci		Dbl_set_sign(opnd3p1,sign_save);	/* restore sign */
11148c2ecf20Sopenharmony_ci	} else {
11158c2ecf20Sopenharmony_ci		Dbl_clear_exponent_set_hidden(opnd3p1);
11168c2ecf20Sopenharmony_ci	}
11178c2ecf20Sopenharmony_ci	/*
11188c2ecf20Sopenharmony_ci	 * Copy opnd3 to the double extended variable called right.
11198c2ecf20Sopenharmony_ci	 */
11208c2ecf20Sopenharmony_ci	Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	/*
11238c2ecf20Sopenharmony_ci	 * A zero "save" helps discover equal operands (for later),
11248c2ecf20Sopenharmony_ci	 * and is used in swapping operands (if needed).
11258c2ecf20Sopenharmony_ci	 */
11268c2ecf20Sopenharmony_ci	Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	/*
11298c2ecf20Sopenharmony_ci	 * Compare magnitude of operands.
11308c2ecf20Sopenharmony_ci	 */
11318c2ecf20Sopenharmony_ci	Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
11328c2ecf20Sopenharmony_ci	Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
11338c2ecf20Sopenharmony_ci	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
11348c2ecf20Sopenharmony_ci	    Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
11358c2ecf20Sopenharmony_ci		/*
11368c2ecf20Sopenharmony_ci		 * Set the left operand to the larger one by XOR swap.
11378c2ecf20Sopenharmony_ci		 * First finish the first word "save".
11388c2ecf20Sopenharmony_ci		 */
11398c2ecf20Sopenharmony_ci		Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
11408c2ecf20Sopenharmony_ci		Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
11418c2ecf20Sopenharmony_ci		Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
11428c2ecf20Sopenharmony_ci			rightp2,rightp3,rightp4);
11438c2ecf20Sopenharmony_ci		/* also setup exponents used in rest of routine */
11448c2ecf20Sopenharmony_ci		diff_exponent = add_exponent - mpy_exponent;
11458c2ecf20Sopenharmony_ci		result_exponent = add_exponent;
11468c2ecf20Sopenharmony_ci	} else {
11478c2ecf20Sopenharmony_ci		/* also setup exponents used in rest of routine */
11488c2ecf20Sopenharmony_ci		diff_exponent = mpy_exponent - add_exponent;
11498c2ecf20Sopenharmony_ci		result_exponent = mpy_exponent;
11508c2ecf20Sopenharmony_ci	}
11518c2ecf20Sopenharmony_ci	/* Invariant: left is not smaller than right. */
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	/*
11548c2ecf20Sopenharmony_ci	 * Special case alignment of operands that would force alignment
11558c2ecf20Sopenharmony_ci	 * beyond the extent of the extension.  A further optimization
11568c2ecf20Sopenharmony_ci	 * could special case this but only reduces the path length for
11578c2ecf20Sopenharmony_ci	 * this infrequent case.
11588c2ecf20Sopenharmony_ci	 */
11598c2ecf20Sopenharmony_ci	if (diff_exponent > DBLEXT_THRESHOLD) {
11608c2ecf20Sopenharmony_ci		diff_exponent = DBLEXT_THRESHOLD;
11618c2ecf20Sopenharmony_ci	}
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	/* Align right operand by shifting it to the right */
11648c2ecf20Sopenharmony_ci	Dblext_clear_sign(rightp1);
11658c2ecf20Sopenharmony_ci	Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
11668c2ecf20Sopenharmony_ci		/*shifted by*/diff_exponent);
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	/* Treat sum and difference of the operands separately. */
11698c2ecf20Sopenharmony_ci	if ((int)save < 0) {
11708c2ecf20Sopenharmony_ci		/*
11718c2ecf20Sopenharmony_ci		 * Difference of the two operands.  Overflow can occur if the
11728c2ecf20Sopenharmony_ci		 * multiply overflowed.  A borrow can occur out of the hidden
11738c2ecf20Sopenharmony_ci		 * bit and force a post normalization phase.
11748c2ecf20Sopenharmony_ci		 */
11758c2ecf20Sopenharmony_ci		Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
11768c2ecf20Sopenharmony_ci			rightp1,rightp2,rightp3,rightp4,
11778c2ecf20Sopenharmony_ci			resultp1,resultp2,resultp3,resultp4);
11788c2ecf20Sopenharmony_ci		sign_save = Dbl_signextendedsign(resultp1);
11798c2ecf20Sopenharmony_ci		if (Dbl_iszero_hidden(resultp1)) {
11808c2ecf20Sopenharmony_ci			/* Handle normalization */
11818c2ecf20Sopenharmony_ci		/* A straightforward algorithm would now shift the
11828c2ecf20Sopenharmony_ci		 * result and extension left until the hidden bit
11838c2ecf20Sopenharmony_ci		 * becomes one.  Not all of the extension bits need
11848c2ecf20Sopenharmony_ci		 * participate in the shift.  Only the two most
11858c2ecf20Sopenharmony_ci		 * significant bits (round and guard) are needed.
11868c2ecf20Sopenharmony_ci		 * If only a single shift is needed then the guard
11878c2ecf20Sopenharmony_ci		 * bit becomes a significant low order bit and the
11888c2ecf20Sopenharmony_ci		 * extension must participate in the rounding.
11898c2ecf20Sopenharmony_ci		 * If more than a single shift is needed, then all
11908c2ecf20Sopenharmony_ci		 * bits to the right of the guard bit are zeros,
11918c2ecf20Sopenharmony_ci		 * and the guard bit may or may not be zero. */
11928c2ecf20Sopenharmony_ci			Dblext_leftshiftby1(resultp1,resultp2,resultp3,
11938c2ecf20Sopenharmony_ci				resultp4);
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci			/* Need to check for a zero result.  The sign and
11968c2ecf20Sopenharmony_ci			 * exponent fields have already been zeroed.  The more
11978c2ecf20Sopenharmony_ci			 * efficient test of the full object can be used.
11988c2ecf20Sopenharmony_ci			 */
11998c2ecf20Sopenharmony_ci			 if (Dblext_iszero(resultp1,resultp2,resultp3,resultp4)) {
12008c2ecf20Sopenharmony_ci				/* Must have been "x-x" or "x+(-x)". */
12018c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS))
12028c2ecf20Sopenharmony_ci					Dbl_setone_sign(resultp1);
12038c2ecf20Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
12048c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
12058c2ecf20Sopenharmony_ci			}
12068c2ecf20Sopenharmony_ci			result_exponent--;
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci			/* Look to see if normalization is finished. */
12098c2ecf20Sopenharmony_ci			if (Dbl_isone_hidden(resultp1)) {
12108c2ecf20Sopenharmony_ci				/* No further normalization is needed */
12118c2ecf20Sopenharmony_ci				goto round;
12128c2ecf20Sopenharmony_ci			}
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci			/* Discover first one bit to determine shift amount.
12158c2ecf20Sopenharmony_ci			 * Use a modified binary search.  We have already
12168c2ecf20Sopenharmony_ci			 * shifted the result one position right and still
12178c2ecf20Sopenharmony_ci			 * not found a one so the remainder of the extension
12188c2ecf20Sopenharmony_ci			 * must be zero and simplifies rounding. */
12198c2ecf20Sopenharmony_ci			/* Scan bytes */
12208c2ecf20Sopenharmony_ci			while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
12218c2ecf20Sopenharmony_ci				Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
12228c2ecf20Sopenharmony_ci				result_exponent -= 8;
12238c2ecf20Sopenharmony_ci			}
12248c2ecf20Sopenharmony_ci			/* Now narrow it down to the nibble */
12258c2ecf20Sopenharmony_ci			if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
12268c2ecf20Sopenharmony_ci				/* The lower nibble contains the
12278c2ecf20Sopenharmony_ci				 * normalizing one */
12288c2ecf20Sopenharmony_ci				Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
12298c2ecf20Sopenharmony_ci				result_exponent -= 4;
12308c2ecf20Sopenharmony_ci			}
12318c2ecf20Sopenharmony_ci			/* Select case where first bit is set (already
12328c2ecf20Sopenharmony_ci			 * normalized) otherwise select the proper shift. */
12338c2ecf20Sopenharmony_ci			jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
12348c2ecf20Sopenharmony_ci			if (jumpsize <= 7) switch(jumpsize) {
12358c2ecf20Sopenharmony_ci			case 1:
12368c2ecf20Sopenharmony_ci				Dblext_leftshiftby3(resultp1,resultp2,resultp3,
12378c2ecf20Sopenharmony_ci					resultp4);
12388c2ecf20Sopenharmony_ci				result_exponent -= 3;
12398c2ecf20Sopenharmony_ci				break;
12408c2ecf20Sopenharmony_ci			case 2:
12418c2ecf20Sopenharmony_ci			case 3:
12428c2ecf20Sopenharmony_ci				Dblext_leftshiftby2(resultp1,resultp2,resultp3,
12438c2ecf20Sopenharmony_ci					resultp4);
12448c2ecf20Sopenharmony_ci				result_exponent -= 2;
12458c2ecf20Sopenharmony_ci				break;
12468c2ecf20Sopenharmony_ci			case 4:
12478c2ecf20Sopenharmony_ci			case 5:
12488c2ecf20Sopenharmony_ci			case 6:
12498c2ecf20Sopenharmony_ci			case 7:
12508c2ecf20Sopenharmony_ci				Dblext_leftshiftby1(resultp1,resultp2,resultp3,
12518c2ecf20Sopenharmony_ci					resultp4);
12528c2ecf20Sopenharmony_ci				result_exponent -= 1;
12538c2ecf20Sopenharmony_ci				break;
12548c2ecf20Sopenharmony_ci			}
12558c2ecf20Sopenharmony_ci		} /* end if (hidden...)... */
12568c2ecf20Sopenharmony_ci	/* Fall through and round */
12578c2ecf20Sopenharmony_ci	} /* end if (save < 0)... */
12588c2ecf20Sopenharmony_ci	else {
12598c2ecf20Sopenharmony_ci		/* Add magnitudes */
12608c2ecf20Sopenharmony_ci		Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
12618c2ecf20Sopenharmony_ci			rightp1,rightp2,rightp3,rightp4,
12628c2ecf20Sopenharmony_ci			/*to*/resultp1,resultp2,resultp3,resultp4);
12638c2ecf20Sopenharmony_ci		sign_save = Dbl_signextendedsign(resultp1);
12648c2ecf20Sopenharmony_ci		if (Dbl_isone_hiddenoverflow(resultp1)) {
12658c2ecf20Sopenharmony_ci	    		/* Prenormalization required. */
12668c2ecf20Sopenharmony_ci	    		Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
12678c2ecf20Sopenharmony_ci				resultp4);
12688c2ecf20Sopenharmony_ci	    		result_exponent++;
12698c2ecf20Sopenharmony_ci		} /* end if hiddenoverflow... */
12708c2ecf20Sopenharmony_ci	} /* end else ...add magnitudes... */
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci	/* Round the result.  If the extension and lower two words are
12738c2ecf20Sopenharmony_ci	 * all zeros, then the result is exact.  Otherwise round in the
12748c2ecf20Sopenharmony_ci	 * correct direction.  Underflow is possible. If a postnormalization
12758c2ecf20Sopenharmony_ci	 * is necessary, then the mantissa is all zeros so no shift is needed.
12768c2ecf20Sopenharmony_ci	 */
12778c2ecf20Sopenharmony_ci  round:
12788c2ecf20Sopenharmony_ci	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
12798c2ecf20Sopenharmony_ci		Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
12808c2ecf20Sopenharmony_ci			result_exponent,is_tiny);
12818c2ecf20Sopenharmony_ci	}
12828c2ecf20Sopenharmony_ci	Dbl_set_sign(resultp1,/*using*/sign_save);
12838c2ecf20Sopenharmony_ci	if (Dblext_isnotzero_mantissap3(resultp3) ||
12848c2ecf20Sopenharmony_ci	    Dblext_isnotzero_mantissap4(resultp4)) {
12858c2ecf20Sopenharmony_ci		inexact = TRUE;
12868c2ecf20Sopenharmony_ci		switch(Rounding_mode()) {
12878c2ecf20Sopenharmony_ci		case ROUNDNEAREST: /* The default. */
12888c2ecf20Sopenharmony_ci			if (Dblext_isone_highp3(resultp3)) {
12898c2ecf20Sopenharmony_ci				/* at least 1/2 ulp */
12908c2ecf20Sopenharmony_ci				if (Dblext_isnotzero_low31p3(resultp3) ||
12918c2ecf20Sopenharmony_ci				    Dblext_isnotzero_mantissap4(resultp4) ||
12928c2ecf20Sopenharmony_ci				    Dblext_isone_lowp2(resultp2)) {
12938c2ecf20Sopenharmony_ci					/* either exactly half way and odd or
12948c2ecf20Sopenharmony_ci					 * more than 1/2ulp */
12958c2ecf20Sopenharmony_ci					Dbl_increment(resultp1,resultp2);
12968c2ecf20Sopenharmony_ci				}
12978c2ecf20Sopenharmony_ci			}
12988c2ecf20Sopenharmony_ci	    		break;
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci		case ROUNDPLUS:
13018c2ecf20Sopenharmony_ci	    		if (Dbl_iszero_sign(resultp1)) {
13028c2ecf20Sopenharmony_ci				/* Round up positive results */
13038c2ecf20Sopenharmony_ci				Dbl_increment(resultp1,resultp2);
13048c2ecf20Sopenharmony_ci			}
13058c2ecf20Sopenharmony_ci			break;
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci		case ROUNDMINUS:
13088c2ecf20Sopenharmony_ci	    		if (Dbl_isone_sign(resultp1)) {
13098c2ecf20Sopenharmony_ci				/* Round down negative results */
13108c2ecf20Sopenharmony_ci				Dbl_increment(resultp1,resultp2);
13118c2ecf20Sopenharmony_ci			}
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci		case ROUNDZERO:;
13148c2ecf20Sopenharmony_ci			/* truncate is simple */
13158c2ecf20Sopenharmony_ci		} /* end switch... */
13168c2ecf20Sopenharmony_ci		if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
13178c2ecf20Sopenharmony_ci	}
13188c2ecf20Sopenharmony_ci	if (result_exponent >= DBL_INFINITY_EXPONENT) {
13198c2ecf20Sopenharmony_ci		/* Overflow */
13208c2ecf20Sopenharmony_ci		if (Is_overflowtrap_enabled()) {
13218c2ecf20Sopenharmony_ci                        /*
13228c2ecf20Sopenharmony_ci                         * Adjust bias of result
13238c2ecf20Sopenharmony_ci                         */
13248c2ecf20Sopenharmony_ci                        Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
13258c2ecf20Sopenharmony_ci                        Dbl_copytoptr(resultp1,resultp2,dstptr);
13268c2ecf20Sopenharmony_ci                        if (inexact)
13278c2ecf20Sopenharmony_ci                            if (Is_inexacttrap_enabled())
13288c2ecf20Sopenharmony_ci                                return (OPC_2E_OVERFLOWEXCEPTION |
13298c2ecf20Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
13308c2ecf20Sopenharmony_ci                            else Set_inexactflag();
13318c2ecf20Sopenharmony_ci                        return (OPC_2E_OVERFLOWEXCEPTION);
13328c2ecf20Sopenharmony_ci		}
13338c2ecf20Sopenharmony_ci		inexact = TRUE;
13348c2ecf20Sopenharmony_ci		Set_overflowflag();
13358c2ecf20Sopenharmony_ci		Dbl_setoverflow(resultp1,resultp2);
13368c2ecf20Sopenharmony_ci	} else if (result_exponent <= 0) {	/* underflow case */
13378c2ecf20Sopenharmony_ci		if (Is_underflowtrap_enabled()) {
13388c2ecf20Sopenharmony_ci                        /*
13398c2ecf20Sopenharmony_ci                         * Adjust bias of result
13408c2ecf20Sopenharmony_ci                         */
13418c2ecf20Sopenharmony_ci                	Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
13428c2ecf20Sopenharmony_ci			Dbl_copytoptr(resultp1,resultp2,dstptr);
13438c2ecf20Sopenharmony_ci                        if (inexact)
13448c2ecf20Sopenharmony_ci                            if (Is_inexacttrap_enabled())
13458c2ecf20Sopenharmony_ci                                return (OPC_2E_UNDERFLOWEXCEPTION |
13468c2ecf20Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
13478c2ecf20Sopenharmony_ci                            else Set_inexactflag();
13488c2ecf20Sopenharmony_ci	    		return(OPC_2E_UNDERFLOWEXCEPTION);
13498c2ecf20Sopenharmony_ci		}
13508c2ecf20Sopenharmony_ci		else if (inexact && is_tiny) Set_underflowflag();
13518c2ecf20Sopenharmony_ci	}
13528c2ecf20Sopenharmony_ci	else Dbl_set_exponent(resultp1,result_exponent);
13538c2ecf20Sopenharmony_ci	Dbl_copytoptr(resultp1,resultp2,dstptr);
13548c2ecf20Sopenharmony_ci	if (inexact)
13558c2ecf20Sopenharmony_ci		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
13568c2ecf20Sopenharmony_ci		else Set_inexactflag();
13578c2ecf20Sopenharmony_ci    	return(NOEXCEPTION);
13588c2ecf20Sopenharmony_ci}
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci/*
13618c2ecf20Sopenharmony_ci *  Single Floating-point Multiply Fused Add
13628c2ecf20Sopenharmony_ci */
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_cisgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_cisgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
13678c2ecf20Sopenharmony_ciunsigned int *status;
13688c2ecf20Sopenharmony_ci{
13698c2ecf20Sopenharmony_ci	unsigned int opnd1, opnd2, opnd3;
13708c2ecf20Sopenharmony_ci	register unsigned int tmpresp1, tmpresp2;
13718c2ecf20Sopenharmony_ci	unsigned int rightp1, rightp2;
13728c2ecf20Sopenharmony_ci	unsigned int resultp1, resultp2 = 0;
13738c2ecf20Sopenharmony_ci	register int mpy_exponent, add_exponent, count;
13748c2ecf20Sopenharmony_ci	boolean inexact = FALSE, is_tiny = FALSE;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	unsigned int signlessleft1, signlessright1, save;
13778c2ecf20Sopenharmony_ci	register int result_exponent, diff_exponent;
13788c2ecf20Sopenharmony_ci	int sign_save, jumpsize;
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci	Sgl_copyfromptr(src1ptr,opnd1);
13818c2ecf20Sopenharmony_ci	Sgl_copyfromptr(src2ptr,opnd2);
13828c2ecf20Sopenharmony_ci	Sgl_copyfromptr(src3ptr,opnd3);
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci	/*
13858c2ecf20Sopenharmony_ci	 * set sign bit of result of multiply
13868c2ecf20Sopenharmony_ci	 */
13878c2ecf20Sopenharmony_ci	if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2))
13888c2ecf20Sopenharmony_ci		Sgl_setnegativezero(resultp1);
13898c2ecf20Sopenharmony_ci	else Sgl_setzero(resultp1);
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci	/*
13928c2ecf20Sopenharmony_ci	 * Generate multiply exponent
13938c2ecf20Sopenharmony_ci	 */
13948c2ecf20Sopenharmony_ci	mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
13958c2ecf20Sopenharmony_ci
13968c2ecf20Sopenharmony_ci	/*
13978c2ecf20Sopenharmony_ci	 * check first operand for NaN's or infinity
13988c2ecf20Sopenharmony_ci	 */
13998c2ecf20Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd1)) {
14008c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd1)) {
14018c2ecf20Sopenharmony_ci			if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
14028c2ecf20Sopenharmony_ci				if (Sgl_iszero_exponentmantissa(opnd2)) {
14038c2ecf20Sopenharmony_ci					/*
14048c2ecf20Sopenharmony_ci					 * invalid since operands are infinity
14058c2ecf20Sopenharmony_ci					 * and zero
14068c2ecf20Sopenharmony_ci					 */
14078c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
14088c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
14098c2ecf20Sopenharmony_ci					Set_invalidflag();
14108c2ecf20Sopenharmony_ci					Sgl_makequietnan(resultp1);
14118c2ecf20Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
14128c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
14138c2ecf20Sopenharmony_ci				}
14148c2ecf20Sopenharmony_ci				/*
14158c2ecf20Sopenharmony_ci				 * Check third operand for infinity with a
14168c2ecf20Sopenharmony_ci				 *  sign opposite of the multiply result
14178c2ecf20Sopenharmony_ci				 */
14188c2ecf20Sopenharmony_ci				if (Sgl_isinfinity(opnd3) &&
14198c2ecf20Sopenharmony_ci				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
14208c2ecf20Sopenharmony_ci					/*
14218c2ecf20Sopenharmony_ci					 * invalid since attempting a magnitude
14228c2ecf20Sopenharmony_ci					 * subtraction of infinities
14238c2ecf20Sopenharmony_ci					 */
14248c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
14258c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
14268c2ecf20Sopenharmony_ci					Set_invalidflag();
14278c2ecf20Sopenharmony_ci					Sgl_makequietnan(resultp1);
14288c2ecf20Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
14298c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
14308c2ecf20Sopenharmony_ci				}
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci				/*
14338c2ecf20Sopenharmony_ci			 	 * return infinity
14348c2ecf20Sopenharmony_ci			 	 */
14358c2ecf20Sopenharmony_ci				Sgl_setinfinity_exponentmantissa(resultp1);
14368c2ecf20Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
14378c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
14388c2ecf20Sopenharmony_ci			}
14398c2ecf20Sopenharmony_ci		}
14408c2ecf20Sopenharmony_ci		else {
14418c2ecf20Sopenharmony_ci			/*
14428c2ecf20Sopenharmony_ci		 	 * is NaN; signaling or quiet?
14438c2ecf20Sopenharmony_ci		 	 */
14448c2ecf20Sopenharmony_ci			if (Sgl_isone_signaling(opnd1)) {
14458c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
14468c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
14478c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
14488c2ecf20Sopenharmony_ci				/* make NaN quiet */
14498c2ecf20Sopenharmony_ci				Set_invalidflag();
14508c2ecf20Sopenharmony_ci				Sgl_set_quiet(opnd1);
14518c2ecf20Sopenharmony_ci			}
14528c2ecf20Sopenharmony_ci			/*
14538c2ecf20Sopenharmony_ci			 * is second operand a signaling NaN?
14548c2ecf20Sopenharmony_ci			 */
14558c2ecf20Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd2)) {
14568c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
14578c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
14588c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
14598c2ecf20Sopenharmony_ci				/* make NaN quiet */
14608c2ecf20Sopenharmony_ci				Set_invalidflag();
14618c2ecf20Sopenharmony_ci				Sgl_set_quiet(opnd2);
14628c2ecf20Sopenharmony_ci				Sgl_copytoptr(opnd2,dstptr);
14638c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
14648c2ecf20Sopenharmony_ci			}
14658c2ecf20Sopenharmony_ci			/*
14668c2ecf20Sopenharmony_ci			 * is third operand a signaling NaN?
14678c2ecf20Sopenharmony_ci			 */
14688c2ecf20Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd3)) {
14698c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
14708c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
14718c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
14728c2ecf20Sopenharmony_ci				/* make NaN quiet */
14738c2ecf20Sopenharmony_ci				Set_invalidflag();
14748c2ecf20Sopenharmony_ci				Sgl_set_quiet(opnd3);
14758c2ecf20Sopenharmony_ci				Sgl_copytoptr(opnd3,dstptr);
14768c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
14778c2ecf20Sopenharmony_ci			}
14788c2ecf20Sopenharmony_ci			/*
14798c2ecf20Sopenharmony_ci		 	 * return quiet NaN
14808c2ecf20Sopenharmony_ci		 	 */
14818c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd1,dstptr);
14828c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
14838c2ecf20Sopenharmony_ci		}
14848c2ecf20Sopenharmony_ci	}
14858c2ecf20Sopenharmony_ci
14868c2ecf20Sopenharmony_ci	/*
14878c2ecf20Sopenharmony_ci	 * check second operand for NaN's or infinity
14888c2ecf20Sopenharmony_ci	 */
14898c2ecf20Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd2)) {
14908c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd2)) {
14918c2ecf20Sopenharmony_ci			if (Sgl_isnotnan(opnd3)) {
14928c2ecf20Sopenharmony_ci				if (Sgl_iszero_exponentmantissa(opnd1)) {
14938c2ecf20Sopenharmony_ci					/*
14948c2ecf20Sopenharmony_ci					 * invalid since multiply operands are
14958c2ecf20Sopenharmony_ci					 * zero & infinity
14968c2ecf20Sopenharmony_ci					 */
14978c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
14988c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
14998c2ecf20Sopenharmony_ci					Set_invalidflag();
15008c2ecf20Sopenharmony_ci					Sgl_makequietnan(opnd2);
15018c2ecf20Sopenharmony_ci					Sgl_copytoptr(opnd2,dstptr);
15028c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
15038c2ecf20Sopenharmony_ci				}
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_ci				/*
15068c2ecf20Sopenharmony_ci				 * Check third operand for infinity with a
15078c2ecf20Sopenharmony_ci				 *  sign opposite of the multiply result
15088c2ecf20Sopenharmony_ci				 */
15098c2ecf20Sopenharmony_ci				if (Sgl_isinfinity(opnd3) &&
15108c2ecf20Sopenharmony_ci				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
15118c2ecf20Sopenharmony_ci					/*
15128c2ecf20Sopenharmony_ci					 * invalid since attempting a magnitude
15138c2ecf20Sopenharmony_ci					 * subtraction of infinities
15148c2ecf20Sopenharmony_ci					 */
15158c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
15168c2ecf20Sopenharmony_ci				       		return(OPC_2E_INVALIDEXCEPTION);
15178c2ecf20Sopenharmony_ci				       	Set_invalidflag();
15188c2ecf20Sopenharmony_ci				       	Sgl_makequietnan(resultp1);
15198c2ecf20Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
15208c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
15218c2ecf20Sopenharmony_ci				}
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci				/*
15248c2ecf20Sopenharmony_ci				 * return infinity
15258c2ecf20Sopenharmony_ci				 */
15268c2ecf20Sopenharmony_ci				Sgl_setinfinity_exponentmantissa(resultp1);
15278c2ecf20Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
15288c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
15298c2ecf20Sopenharmony_ci			}
15308c2ecf20Sopenharmony_ci		}
15318c2ecf20Sopenharmony_ci		else {
15328c2ecf20Sopenharmony_ci			/*
15338c2ecf20Sopenharmony_ci			 * is NaN; signaling or quiet?
15348c2ecf20Sopenharmony_ci			 */
15358c2ecf20Sopenharmony_ci			if (Sgl_isone_signaling(opnd2)) {
15368c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
15378c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
15388c2ecf20Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
15398c2ecf20Sopenharmony_ci				/* make NaN quiet */
15408c2ecf20Sopenharmony_ci				Set_invalidflag();
15418c2ecf20Sopenharmony_ci				Sgl_set_quiet(opnd2);
15428c2ecf20Sopenharmony_ci			}
15438c2ecf20Sopenharmony_ci			/*
15448c2ecf20Sopenharmony_ci			 * is third operand a signaling NaN?
15458c2ecf20Sopenharmony_ci			 */
15468c2ecf20Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd3)) {
15478c2ecf20Sopenharmony_ci			       	/* trap if INVALIDTRAP enabled */
15488c2ecf20Sopenharmony_ci			       	if (Is_invalidtrap_enabled())
15498c2ecf20Sopenharmony_ci				   		return(OPC_2E_INVALIDEXCEPTION);
15508c2ecf20Sopenharmony_ci			       	/* make NaN quiet */
15518c2ecf20Sopenharmony_ci			       	Set_invalidflag();
15528c2ecf20Sopenharmony_ci			       	Sgl_set_quiet(opnd3);
15538c2ecf20Sopenharmony_ci				Sgl_copytoptr(opnd3,dstptr);
15548c2ecf20Sopenharmony_ci		       		return(NOEXCEPTION);
15558c2ecf20Sopenharmony_ci			}
15568c2ecf20Sopenharmony_ci			/*
15578c2ecf20Sopenharmony_ci			 * return quiet NaN
15588c2ecf20Sopenharmony_ci			 */
15598c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd2,dstptr);
15608c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
15618c2ecf20Sopenharmony_ci		}
15628c2ecf20Sopenharmony_ci	}
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci	/*
15658c2ecf20Sopenharmony_ci	 * check third operand for NaN's or infinity
15668c2ecf20Sopenharmony_ci	 */
15678c2ecf20Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd3)) {
15688c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd3)) {
15698c2ecf20Sopenharmony_ci			/* return infinity */
15708c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
15718c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
15728c2ecf20Sopenharmony_ci		} else {
15738c2ecf20Sopenharmony_ci			/*
15748c2ecf20Sopenharmony_ci			 * is NaN; signaling or quiet?
15758c2ecf20Sopenharmony_ci			 */
15768c2ecf20Sopenharmony_ci			if (Sgl_isone_signaling(opnd3)) {
15778c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
15788c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
15798c2ecf20Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
15808c2ecf20Sopenharmony_ci				/* make NaN quiet */
15818c2ecf20Sopenharmony_ci				Set_invalidflag();
15828c2ecf20Sopenharmony_ci				Sgl_set_quiet(opnd3);
15838c2ecf20Sopenharmony_ci			}
15848c2ecf20Sopenharmony_ci			/*
15858c2ecf20Sopenharmony_ci			 * return quiet NaN
15868c2ecf20Sopenharmony_ci 			 */
15878c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
15888c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
15898c2ecf20Sopenharmony_ci		}
15908c2ecf20Sopenharmony_ci    	}
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci	/*
15938c2ecf20Sopenharmony_ci	 * Generate multiply mantissa
15948c2ecf20Sopenharmony_ci	 */
15958c2ecf20Sopenharmony_ci	if (Sgl_isnotzero_exponent(opnd1)) {
15968c2ecf20Sopenharmony_ci		/* set hidden bit */
15978c2ecf20Sopenharmony_ci		Sgl_clear_signexponent_set_hidden(opnd1);
15988c2ecf20Sopenharmony_ci	}
15998c2ecf20Sopenharmony_ci	else {
16008c2ecf20Sopenharmony_ci		/* check for zero */
16018c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd1)) {
16028c2ecf20Sopenharmony_ci			/*
16038c2ecf20Sopenharmony_ci			 * Perform the add opnd3 with zero here.
16048c2ecf20Sopenharmony_ci			 */
16058c2ecf20Sopenharmony_ci			if (Sgl_iszero_exponentmantissa(opnd3)) {
16068c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
16078c2ecf20Sopenharmony_ci					Sgl_or_signs(opnd3,resultp1);
16088c2ecf20Sopenharmony_ci				} else {
16098c2ecf20Sopenharmony_ci					Sgl_and_signs(opnd3,resultp1);
16108c2ecf20Sopenharmony_ci				}
16118c2ecf20Sopenharmony_ci			}
16128c2ecf20Sopenharmony_ci			/*
16138c2ecf20Sopenharmony_ci			 * Now let's check for trapped underflow case.
16148c2ecf20Sopenharmony_ci			 */
16158c2ecf20Sopenharmony_ci			else if (Sgl_iszero_exponent(opnd3) &&
16168c2ecf20Sopenharmony_ci			         Is_underflowtrap_enabled()) {
16178c2ecf20Sopenharmony_ci                    		/* need to normalize results mantissa */
16188c2ecf20Sopenharmony_ci                    		sign_save = Sgl_signextendedsign(opnd3);
16198c2ecf20Sopenharmony_ci				result_exponent = 0;
16208c2ecf20Sopenharmony_ci                    		Sgl_leftshiftby1(opnd3);
16218c2ecf20Sopenharmony_ci                    		Sgl_normalize(opnd3,result_exponent);
16228c2ecf20Sopenharmony_ci                    		Sgl_set_sign(opnd3,/*using*/sign_save);
16238c2ecf20Sopenharmony_ci                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
16248c2ecf20Sopenharmony_ci							unfl);
16258c2ecf20Sopenharmony_ci                    		Sgl_copytoptr(opnd3,dstptr);
16268c2ecf20Sopenharmony_ci                    		/* inexact = FALSE */
16278c2ecf20Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
16288c2ecf20Sopenharmony_ci			}
16298c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
16308c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
16318c2ecf20Sopenharmony_ci		}
16328c2ecf20Sopenharmony_ci		/* is denormalized, adjust exponent */
16338c2ecf20Sopenharmony_ci		Sgl_clear_signexponent(opnd1);
16348c2ecf20Sopenharmony_ci		Sgl_leftshiftby1(opnd1);
16358c2ecf20Sopenharmony_ci		Sgl_normalize(opnd1,mpy_exponent);
16368c2ecf20Sopenharmony_ci	}
16378c2ecf20Sopenharmony_ci	/* opnd2 needs to have hidden bit set with msb in hidden bit */
16388c2ecf20Sopenharmony_ci	if (Sgl_isnotzero_exponent(opnd2)) {
16398c2ecf20Sopenharmony_ci		Sgl_clear_signexponent_set_hidden(opnd2);
16408c2ecf20Sopenharmony_ci	}
16418c2ecf20Sopenharmony_ci	else {
16428c2ecf20Sopenharmony_ci		/* check for zero */
16438c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd2)) {
16448c2ecf20Sopenharmony_ci			/*
16458c2ecf20Sopenharmony_ci			 * Perform the add opnd3 with zero here.
16468c2ecf20Sopenharmony_ci			 */
16478c2ecf20Sopenharmony_ci			if (Sgl_iszero_exponentmantissa(opnd3)) {
16488c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
16498c2ecf20Sopenharmony_ci					Sgl_or_signs(opnd3,resultp1);
16508c2ecf20Sopenharmony_ci				} else {
16518c2ecf20Sopenharmony_ci					Sgl_and_signs(opnd3,resultp1);
16528c2ecf20Sopenharmony_ci				}
16538c2ecf20Sopenharmony_ci			}
16548c2ecf20Sopenharmony_ci			/*
16558c2ecf20Sopenharmony_ci			 * Now let's check for trapped underflow case.
16568c2ecf20Sopenharmony_ci			 */
16578c2ecf20Sopenharmony_ci			else if (Sgl_iszero_exponent(opnd3) &&
16588c2ecf20Sopenharmony_ci			    Is_underflowtrap_enabled()) {
16598c2ecf20Sopenharmony_ci                    		/* need to normalize results mantissa */
16608c2ecf20Sopenharmony_ci                    		sign_save = Sgl_signextendedsign(opnd3);
16618c2ecf20Sopenharmony_ci				result_exponent = 0;
16628c2ecf20Sopenharmony_ci                    		Sgl_leftshiftby1(opnd3);
16638c2ecf20Sopenharmony_ci                    		Sgl_normalize(opnd3,result_exponent);
16648c2ecf20Sopenharmony_ci                    		Sgl_set_sign(opnd3,/*using*/sign_save);
16658c2ecf20Sopenharmony_ci                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
16668c2ecf20Sopenharmony_ci							unfl);
16678c2ecf20Sopenharmony_ci                    		Sgl_copytoptr(opnd3,dstptr);
16688c2ecf20Sopenharmony_ci                    		/* inexact = FALSE */
16698c2ecf20Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
16708c2ecf20Sopenharmony_ci			}
16718c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
16728c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
16738c2ecf20Sopenharmony_ci		}
16748c2ecf20Sopenharmony_ci		/* is denormalized; want to normalize */
16758c2ecf20Sopenharmony_ci		Sgl_clear_signexponent(opnd2);
16768c2ecf20Sopenharmony_ci		Sgl_leftshiftby1(opnd2);
16778c2ecf20Sopenharmony_ci		Sgl_normalize(opnd2,mpy_exponent);
16788c2ecf20Sopenharmony_ci	}
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_ci	/* Multiply the first two source mantissas together */
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_ci	/*
16838c2ecf20Sopenharmony_ci	 * The intermediate result will be kept in tmpres,
16848c2ecf20Sopenharmony_ci	 * which needs enough room for 106 bits of mantissa,
16858c2ecf20Sopenharmony_ci	 * so lets call it a Double extended.
16868c2ecf20Sopenharmony_ci	 */
16878c2ecf20Sopenharmony_ci	Sglext_setzero(tmpresp1,tmpresp2);
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci	/*
16908c2ecf20Sopenharmony_ci	 * Four bits at a time are inspected in each loop, and a
16918c2ecf20Sopenharmony_ci	 * simple shift and add multiply algorithm is used.
16928c2ecf20Sopenharmony_ci	 */
16938c2ecf20Sopenharmony_ci	for (count = SGL_P-1; count >= 0; count -= 4) {
16948c2ecf20Sopenharmony_ci		Sglext_rightshiftby4(tmpresp1,tmpresp2);
16958c2ecf20Sopenharmony_ci		if (Sbit28(opnd1)) {
16968c2ecf20Sopenharmony_ci	 		/* Twoword_add should be an ADD followed by 2 ADDC's */
16978c2ecf20Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
16988c2ecf20Sopenharmony_ci		}
16998c2ecf20Sopenharmony_ci		if (Sbit29(opnd1)) {
17008c2ecf20Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
17018c2ecf20Sopenharmony_ci		}
17028c2ecf20Sopenharmony_ci		if (Sbit30(opnd1)) {
17038c2ecf20Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
17048c2ecf20Sopenharmony_ci		}
17058c2ecf20Sopenharmony_ci		if (Sbit31(opnd1)) {
17068c2ecf20Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
17078c2ecf20Sopenharmony_ci		}
17088c2ecf20Sopenharmony_ci		Sgl_rightshiftby4(opnd1);
17098c2ecf20Sopenharmony_ci	}
17108c2ecf20Sopenharmony_ci	if (Is_sexthiddenoverflow(tmpresp1)) {
17118c2ecf20Sopenharmony_ci		/* result mantissa >= 2 (mantissa overflow) */
17128c2ecf20Sopenharmony_ci		mpy_exponent++;
17138c2ecf20Sopenharmony_ci		Sglext_rightshiftby4(tmpresp1,tmpresp2);
17148c2ecf20Sopenharmony_ci	} else {
17158c2ecf20Sopenharmony_ci		Sglext_rightshiftby3(tmpresp1,tmpresp2);
17168c2ecf20Sopenharmony_ci	}
17178c2ecf20Sopenharmony_ci
17188c2ecf20Sopenharmony_ci	/*
17198c2ecf20Sopenharmony_ci	 * Restore the sign of the mpy result which was saved in resultp1.
17208c2ecf20Sopenharmony_ci	 * The exponent will continue to be kept in mpy_exponent.
17218c2ecf20Sopenharmony_ci	 */
17228c2ecf20Sopenharmony_ci	Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_ci	/*
17258c2ecf20Sopenharmony_ci	 * No rounding is required, since the result of the multiply
17268c2ecf20Sopenharmony_ci	 * is exact in the extended format.
17278c2ecf20Sopenharmony_ci	 */
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci	/*
17308c2ecf20Sopenharmony_ci	 * Now we are ready to perform the add portion of the operation.
17318c2ecf20Sopenharmony_ci	 *
17328c2ecf20Sopenharmony_ci	 * The exponents need to be kept as integers for now, since the
17338c2ecf20Sopenharmony_ci	 * multiply result might not fit into the exponent field.  We
17348c2ecf20Sopenharmony_ci	 * can't overflow or underflow because of this yet, since the
17358c2ecf20Sopenharmony_ci	 * add could bring the final result back into range.
17368c2ecf20Sopenharmony_ci	 */
17378c2ecf20Sopenharmony_ci	add_exponent = Sgl_exponent(opnd3);
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	/*
17408c2ecf20Sopenharmony_ci	 * Check for denormalized or zero add operand.
17418c2ecf20Sopenharmony_ci	 */
17428c2ecf20Sopenharmony_ci	if (add_exponent == 0) {
17438c2ecf20Sopenharmony_ci		/* check for zero */
17448c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd3)) {
17458c2ecf20Sopenharmony_ci			/* right is zero */
17468c2ecf20Sopenharmony_ci			/* Left can't be zero and must be result.
17478c2ecf20Sopenharmony_ci			 *
17488c2ecf20Sopenharmony_ci			 * The final result is now in tmpres and mpy_exponent,
17498c2ecf20Sopenharmony_ci			 * and needs to be rounded and squeezed back into
17508c2ecf20Sopenharmony_ci			 * double precision format from double extended.
17518c2ecf20Sopenharmony_ci			 */
17528c2ecf20Sopenharmony_ci			result_exponent = mpy_exponent;
17538c2ecf20Sopenharmony_ci			Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
17548c2ecf20Sopenharmony_ci			sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
17558c2ecf20Sopenharmony_ci			goto round;
17568c2ecf20Sopenharmony_ci		}
17578c2ecf20Sopenharmony_ci
17588c2ecf20Sopenharmony_ci		/*
17598c2ecf20Sopenharmony_ci		 * Neither are zeroes.
17608c2ecf20Sopenharmony_ci		 * Adjust exponent and normalize add operand.
17618c2ecf20Sopenharmony_ci		 */
17628c2ecf20Sopenharmony_ci		sign_save = Sgl_signextendedsign(opnd3);	/* save sign */
17638c2ecf20Sopenharmony_ci		Sgl_clear_signexponent(opnd3);
17648c2ecf20Sopenharmony_ci		Sgl_leftshiftby1(opnd3);
17658c2ecf20Sopenharmony_ci		Sgl_normalize(opnd3,add_exponent);
17668c2ecf20Sopenharmony_ci		Sgl_set_sign(opnd3,sign_save);		/* restore sign */
17678c2ecf20Sopenharmony_ci	} else {
17688c2ecf20Sopenharmony_ci		Sgl_clear_exponent_set_hidden(opnd3);
17698c2ecf20Sopenharmony_ci	}
17708c2ecf20Sopenharmony_ci	/*
17718c2ecf20Sopenharmony_ci	 * Copy opnd3 to the double extended variable called right.
17728c2ecf20Sopenharmony_ci	 */
17738c2ecf20Sopenharmony_ci	Sgl_copyto_sglext(opnd3,rightp1,rightp2);
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	/*
17768c2ecf20Sopenharmony_ci	 * A zero "save" helps discover equal operands (for later),
17778c2ecf20Sopenharmony_ci	 * and is used in swapping operands (if needed).
17788c2ecf20Sopenharmony_ci	 */
17798c2ecf20Sopenharmony_ci	Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);
17808c2ecf20Sopenharmony_ci
17818c2ecf20Sopenharmony_ci	/*
17828c2ecf20Sopenharmony_ci	 * Compare magnitude of operands.
17838c2ecf20Sopenharmony_ci	 */
17848c2ecf20Sopenharmony_ci	Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
17858c2ecf20Sopenharmony_ci	Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
17868c2ecf20Sopenharmony_ci	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
17878c2ecf20Sopenharmony_ci	    Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
17888c2ecf20Sopenharmony_ci		/*
17898c2ecf20Sopenharmony_ci		 * Set the left operand to the larger one by XOR swap.
17908c2ecf20Sopenharmony_ci		 * First finish the first word "save".
17918c2ecf20Sopenharmony_ci		 */
17928c2ecf20Sopenharmony_ci		Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
17938c2ecf20Sopenharmony_ci		Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
17948c2ecf20Sopenharmony_ci		Sglext_swap_lower(tmpresp2,rightp2);
17958c2ecf20Sopenharmony_ci		/* also setup exponents used in rest of routine */
17968c2ecf20Sopenharmony_ci		diff_exponent = add_exponent - mpy_exponent;
17978c2ecf20Sopenharmony_ci		result_exponent = add_exponent;
17988c2ecf20Sopenharmony_ci	} else {
17998c2ecf20Sopenharmony_ci		/* also setup exponents used in rest of routine */
18008c2ecf20Sopenharmony_ci		diff_exponent = mpy_exponent - add_exponent;
18018c2ecf20Sopenharmony_ci		result_exponent = mpy_exponent;
18028c2ecf20Sopenharmony_ci	}
18038c2ecf20Sopenharmony_ci	/* Invariant: left is not smaller than right. */
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci	/*
18068c2ecf20Sopenharmony_ci	 * Special case alignment of operands that would force alignment
18078c2ecf20Sopenharmony_ci	 * beyond the extent of the extension.  A further optimization
18088c2ecf20Sopenharmony_ci	 * could special case this but only reduces the path length for
18098c2ecf20Sopenharmony_ci	 * this infrequent case.
18108c2ecf20Sopenharmony_ci	 */
18118c2ecf20Sopenharmony_ci	if (diff_exponent > SGLEXT_THRESHOLD) {
18128c2ecf20Sopenharmony_ci		diff_exponent = SGLEXT_THRESHOLD;
18138c2ecf20Sopenharmony_ci	}
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	/* Align right operand by shifting it to the right */
18168c2ecf20Sopenharmony_ci	Sglext_clear_sign(rightp1);
18178c2ecf20Sopenharmony_ci	Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci	/* Treat sum and difference of the operands separately. */
18208c2ecf20Sopenharmony_ci	if ((int)save < 0) {
18218c2ecf20Sopenharmony_ci		/*
18228c2ecf20Sopenharmony_ci		 * Difference of the two operands.  Overflow can occur if the
18238c2ecf20Sopenharmony_ci		 * multiply overflowed.  A borrow can occur out of the hidden
18248c2ecf20Sopenharmony_ci		 * bit and force a post normalization phase.
18258c2ecf20Sopenharmony_ci		 */
18268c2ecf20Sopenharmony_ci		Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
18278c2ecf20Sopenharmony_ci			resultp1,resultp2);
18288c2ecf20Sopenharmony_ci		sign_save = Sgl_signextendedsign(resultp1);
18298c2ecf20Sopenharmony_ci		if (Sgl_iszero_hidden(resultp1)) {
18308c2ecf20Sopenharmony_ci			/* Handle normalization */
18318c2ecf20Sopenharmony_ci		/* A straightforward algorithm would now shift the
18328c2ecf20Sopenharmony_ci		 * result and extension left until the hidden bit
18338c2ecf20Sopenharmony_ci		 * becomes one.  Not all of the extension bits need
18348c2ecf20Sopenharmony_ci		 * participate in the shift.  Only the two most
18358c2ecf20Sopenharmony_ci		 * significant bits (round and guard) are needed.
18368c2ecf20Sopenharmony_ci		 * If only a single shift is needed then the guard
18378c2ecf20Sopenharmony_ci		 * bit becomes a significant low order bit and the
18388c2ecf20Sopenharmony_ci		 * extension must participate in the rounding.
18398c2ecf20Sopenharmony_ci		 * If more than a single shift is needed, then all
18408c2ecf20Sopenharmony_ci		 * bits to the right of the guard bit are zeros,
18418c2ecf20Sopenharmony_ci		 * and the guard bit may or may not be zero. */
18428c2ecf20Sopenharmony_ci			Sglext_leftshiftby1(resultp1,resultp2);
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_ci			/* Need to check for a zero result.  The sign and
18458c2ecf20Sopenharmony_ci			 * exponent fields have already been zeroed.  The more
18468c2ecf20Sopenharmony_ci			 * efficient test of the full object can be used.
18478c2ecf20Sopenharmony_ci			 */
18488c2ecf20Sopenharmony_ci			 if (Sglext_iszero(resultp1,resultp2)) {
18498c2ecf20Sopenharmony_ci				/* Must have been "x-x" or "x+(-x)". */
18508c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS))
18518c2ecf20Sopenharmony_ci					Sgl_setone_sign(resultp1);
18528c2ecf20Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
18538c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
18548c2ecf20Sopenharmony_ci			}
18558c2ecf20Sopenharmony_ci			result_exponent--;
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci			/* Look to see if normalization is finished. */
18588c2ecf20Sopenharmony_ci			if (Sgl_isone_hidden(resultp1)) {
18598c2ecf20Sopenharmony_ci				/* No further normalization is needed */
18608c2ecf20Sopenharmony_ci				goto round;
18618c2ecf20Sopenharmony_ci			}
18628c2ecf20Sopenharmony_ci
18638c2ecf20Sopenharmony_ci			/* Discover first one bit to determine shift amount.
18648c2ecf20Sopenharmony_ci			 * Use a modified binary search.  We have already
18658c2ecf20Sopenharmony_ci			 * shifted the result one position right and still
18668c2ecf20Sopenharmony_ci			 * not found a one so the remainder of the extension
18678c2ecf20Sopenharmony_ci			 * must be zero and simplifies rounding. */
18688c2ecf20Sopenharmony_ci			/* Scan bytes */
18698c2ecf20Sopenharmony_ci			while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
18708c2ecf20Sopenharmony_ci				Sglext_leftshiftby8(resultp1,resultp2);
18718c2ecf20Sopenharmony_ci				result_exponent -= 8;
18728c2ecf20Sopenharmony_ci			}
18738c2ecf20Sopenharmony_ci			/* Now narrow it down to the nibble */
18748c2ecf20Sopenharmony_ci			if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
18758c2ecf20Sopenharmony_ci				/* The lower nibble contains the
18768c2ecf20Sopenharmony_ci				 * normalizing one */
18778c2ecf20Sopenharmony_ci				Sglext_leftshiftby4(resultp1,resultp2);
18788c2ecf20Sopenharmony_ci				result_exponent -= 4;
18798c2ecf20Sopenharmony_ci			}
18808c2ecf20Sopenharmony_ci			/* Select case where first bit is set (already
18818c2ecf20Sopenharmony_ci			 * normalized) otherwise select the proper shift. */
18828c2ecf20Sopenharmony_ci			jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
18838c2ecf20Sopenharmony_ci			if (jumpsize <= 7) switch(jumpsize) {
18848c2ecf20Sopenharmony_ci			case 1:
18858c2ecf20Sopenharmony_ci				Sglext_leftshiftby3(resultp1,resultp2);
18868c2ecf20Sopenharmony_ci				result_exponent -= 3;
18878c2ecf20Sopenharmony_ci				break;
18888c2ecf20Sopenharmony_ci			case 2:
18898c2ecf20Sopenharmony_ci			case 3:
18908c2ecf20Sopenharmony_ci				Sglext_leftshiftby2(resultp1,resultp2);
18918c2ecf20Sopenharmony_ci				result_exponent -= 2;
18928c2ecf20Sopenharmony_ci				break;
18938c2ecf20Sopenharmony_ci			case 4:
18948c2ecf20Sopenharmony_ci			case 5:
18958c2ecf20Sopenharmony_ci			case 6:
18968c2ecf20Sopenharmony_ci			case 7:
18978c2ecf20Sopenharmony_ci				Sglext_leftshiftby1(resultp1,resultp2);
18988c2ecf20Sopenharmony_ci				result_exponent -= 1;
18998c2ecf20Sopenharmony_ci				break;
19008c2ecf20Sopenharmony_ci			}
19018c2ecf20Sopenharmony_ci		} /* end if (hidden...)... */
19028c2ecf20Sopenharmony_ci	/* Fall through and round */
19038c2ecf20Sopenharmony_ci	} /* end if (save < 0)... */
19048c2ecf20Sopenharmony_ci	else {
19058c2ecf20Sopenharmony_ci		/* Add magnitudes */
19068c2ecf20Sopenharmony_ci		Sglext_addition(tmpresp1,tmpresp2,
19078c2ecf20Sopenharmony_ci			rightp1,rightp2, /*to*/resultp1,resultp2);
19088c2ecf20Sopenharmony_ci		sign_save = Sgl_signextendedsign(resultp1);
19098c2ecf20Sopenharmony_ci		if (Sgl_isone_hiddenoverflow(resultp1)) {
19108c2ecf20Sopenharmony_ci	    		/* Prenormalization required. */
19118c2ecf20Sopenharmony_ci	    		Sglext_arithrightshiftby1(resultp1,resultp2);
19128c2ecf20Sopenharmony_ci	    		result_exponent++;
19138c2ecf20Sopenharmony_ci		} /* end if hiddenoverflow... */
19148c2ecf20Sopenharmony_ci	} /* end else ...add magnitudes... */
19158c2ecf20Sopenharmony_ci
19168c2ecf20Sopenharmony_ci	/* Round the result.  If the extension and lower two words are
19178c2ecf20Sopenharmony_ci	 * all zeros, then the result is exact.  Otherwise round in the
19188c2ecf20Sopenharmony_ci	 * correct direction.  Underflow is possible. If a postnormalization
19198c2ecf20Sopenharmony_ci	 * is necessary, then the mantissa is all zeros so no shift is needed.
19208c2ecf20Sopenharmony_ci	 */
19218c2ecf20Sopenharmony_ci  round:
19228c2ecf20Sopenharmony_ci	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
19238c2ecf20Sopenharmony_ci		Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
19248c2ecf20Sopenharmony_ci	}
19258c2ecf20Sopenharmony_ci	Sgl_set_sign(resultp1,/*using*/sign_save);
19268c2ecf20Sopenharmony_ci	if (Sglext_isnotzero_mantissap2(resultp2)) {
19278c2ecf20Sopenharmony_ci		inexact = TRUE;
19288c2ecf20Sopenharmony_ci		switch(Rounding_mode()) {
19298c2ecf20Sopenharmony_ci		case ROUNDNEAREST: /* The default. */
19308c2ecf20Sopenharmony_ci			if (Sglext_isone_highp2(resultp2)) {
19318c2ecf20Sopenharmony_ci				/* at least 1/2 ulp */
19328c2ecf20Sopenharmony_ci				if (Sglext_isnotzero_low31p2(resultp2) ||
19338c2ecf20Sopenharmony_ci				    Sglext_isone_lowp1(resultp1)) {
19348c2ecf20Sopenharmony_ci					/* either exactly half way and odd or
19358c2ecf20Sopenharmony_ci					 * more than 1/2ulp */
19368c2ecf20Sopenharmony_ci					Sgl_increment(resultp1);
19378c2ecf20Sopenharmony_ci				}
19388c2ecf20Sopenharmony_ci			}
19398c2ecf20Sopenharmony_ci	    		break;
19408c2ecf20Sopenharmony_ci
19418c2ecf20Sopenharmony_ci		case ROUNDPLUS:
19428c2ecf20Sopenharmony_ci	    		if (Sgl_iszero_sign(resultp1)) {
19438c2ecf20Sopenharmony_ci				/* Round up positive results */
19448c2ecf20Sopenharmony_ci				Sgl_increment(resultp1);
19458c2ecf20Sopenharmony_ci			}
19468c2ecf20Sopenharmony_ci			break;
19478c2ecf20Sopenharmony_ci
19488c2ecf20Sopenharmony_ci		case ROUNDMINUS:
19498c2ecf20Sopenharmony_ci	    		if (Sgl_isone_sign(resultp1)) {
19508c2ecf20Sopenharmony_ci				/* Round down negative results */
19518c2ecf20Sopenharmony_ci				Sgl_increment(resultp1);
19528c2ecf20Sopenharmony_ci			}
19538c2ecf20Sopenharmony_ci
19548c2ecf20Sopenharmony_ci		case ROUNDZERO:;
19558c2ecf20Sopenharmony_ci			/* truncate is simple */
19568c2ecf20Sopenharmony_ci		} /* end switch... */
19578c2ecf20Sopenharmony_ci		if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
19588c2ecf20Sopenharmony_ci	}
19598c2ecf20Sopenharmony_ci	if (result_exponent >= SGL_INFINITY_EXPONENT) {
19608c2ecf20Sopenharmony_ci		/* Overflow */
19618c2ecf20Sopenharmony_ci		if (Is_overflowtrap_enabled()) {
19628c2ecf20Sopenharmony_ci                        /*
19638c2ecf20Sopenharmony_ci                         * Adjust bias of result
19648c2ecf20Sopenharmony_ci                         */
19658c2ecf20Sopenharmony_ci                        Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
19668c2ecf20Sopenharmony_ci                        Sgl_copytoptr(resultp1,dstptr);
19678c2ecf20Sopenharmony_ci                        if (inexact)
19688c2ecf20Sopenharmony_ci                            if (Is_inexacttrap_enabled())
19698c2ecf20Sopenharmony_ci                                return (OPC_2E_OVERFLOWEXCEPTION |
19708c2ecf20Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
19718c2ecf20Sopenharmony_ci                            else Set_inexactflag();
19728c2ecf20Sopenharmony_ci                        return (OPC_2E_OVERFLOWEXCEPTION);
19738c2ecf20Sopenharmony_ci		}
19748c2ecf20Sopenharmony_ci		inexact = TRUE;
19758c2ecf20Sopenharmony_ci		Set_overflowflag();
19768c2ecf20Sopenharmony_ci		Sgl_setoverflow(resultp1);
19778c2ecf20Sopenharmony_ci	} else if (result_exponent <= 0) {	/* underflow case */
19788c2ecf20Sopenharmony_ci		if (Is_underflowtrap_enabled()) {
19798c2ecf20Sopenharmony_ci                        /*
19808c2ecf20Sopenharmony_ci                         * Adjust bias of result
19818c2ecf20Sopenharmony_ci                         */
19828c2ecf20Sopenharmony_ci                	Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
19838c2ecf20Sopenharmony_ci			Sgl_copytoptr(resultp1,dstptr);
19848c2ecf20Sopenharmony_ci                        if (inexact)
19858c2ecf20Sopenharmony_ci                            if (Is_inexacttrap_enabled())
19868c2ecf20Sopenharmony_ci                                return (OPC_2E_UNDERFLOWEXCEPTION |
19878c2ecf20Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
19888c2ecf20Sopenharmony_ci                            else Set_inexactflag();
19898c2ecf20Sopenharmony_ci	    		return(OPC_2E_UNDERFLOWEXCEPTION);
19908c2ecf20Sopenharmony_ci		}
19918c2ecf20Sopenharmony_ci		else if (inexact && is_tiny) Set_underflowflag();
19928c2ecf20Sopenharmony_ci	}
19938c2ecf20Sopenharmony_ci	else Sgl_set_exponent(resultp1,result_exponent);
19948c2ecf20Sopenharmony_ci	Sgl_copytoptr(resultp1,dstptr);
19958c2ecf20Sopenharmony_ci	if (inexact)
19968c2ecf20Sopenharmony_ci		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
19978c2ecf20Sopenharmony_ci		else Set_inexactflag();
19988c2ecf20Sopenharmony_ci    	return(NOEXCEPTION);
19998c2ecf20Sopenharmony_ci}
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci/*
20028c2ecf20Sopenharmony_ci *  Single Floating-point Multiply Negate Fused Add
20038c2ecf20Sopenharmony_ci */
20048c2ecf20Sopenharmony_ci
20058c2ecf20Sopenharmony_cisgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
20068c2ecf20Sopenharmony_ci
20078c2ecf20Sopenharmony_cisgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
20088c2ecf20Sopenharmony_ciunsigned int *status;
20098c2ecf20Sopenharmony_ci{
20108c2ecf20Sopenharmony_ci	unsigned int opnd1, opnd2, opnd3;
20118c2ecf20Sopenharmony_ci	register unsigned int tmpresp1, tmpresp2;
20128c2ecf20Sopenharmony_ci	unsigned int rightp1, rightp2;
20138c2ecf20Sopenharmony_ci	unsigned int resultp1, resultp2 = 0;
20148c2ecf20Sopenharmony_ci	register int mpy_exponent, add_exponent, count;
20158c2ecf20Sopenharmony_ci	boolean inexact = FALSE, is_tiny = FALSE;
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_ci	unsigned int signlessleft1, signlessright1, save;
20188c2ecf20Sopenharmony_ci	register int result_exponent, diff_exponent;
20198c2ecf20Sopenharmony_ci	int sign_save, jumpsize;
20208c2ecf20Sopenharmony_ci
20218c2ecf20Sopenharmony_ci	Sgl_copyfromptr(src1ptr,opnd1);
20228c2ecf20Sopenharmony_ci	Sgl_copyfromptr(src2ptr,opnd2);
20238c2ecf20Sopenharmony_ci	Sgl_copyfromptr(src3ptr,opnd3);
20248c2ecf20Sopenharmony_ci
20258c2ecf20Sopenharmony_ci	/*
20268c2ecf20Sopenharmony_ci	 * set sign bit of result of multiply
20278c2ecf20Sopenharmony_ci	 */
20288c2ecf20Sopenharmony_ci	if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2))
20298c2ecf20Sopenharmony_ci		Sgl_setzero(resultp1);
20308c2ecf20Sopenharmony_ci	else
20318c2ecf20Sopenharmony_ci		Sgl_setnegativezero(resultp1);
20328c2ecf20Sopenharmony_ci
20338c2ecf20Sopenharmony_ci	/*
20348c2ecf20Sopenharmony_ci	 * Generate multiply exponent
20358c2ecf20Sopenharmony_ci	 */
20368c2ecf20Sopenharmony_ci	mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
20378c2ecf20Sopenharmony_ci
20388c2ecf20Sopenharmony_ci	/*
20398c2ecf20Sopenharmony_ci	 * check first operand for NaN's or infinity
20408c2ecf20Sopenharmony_ci	 */
20418c2ecf20Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd1)) {
20428c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd1)) {
20438c2ecf20Sopenharmony_ci			if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
20448c2ecf20Sopenharmony_ci				if (Sgl_iszero_exponentmantissa(opnd2)) {
20458c2ecf20Sopenharmony_ci					/*
20468c2ecf20Sopenharmony_ci					 * invalid since operands are infinity
20478c2ecf20Sopenharmony_ci					 * and zero
20488c2ecf20Sopenharmony_ci					 */
20498c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
20508c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
20518c2ecf20Sopenharmony_ci					Set_invalidflag();
20528c2ecf20Sopenharmony_ci					Sgl_makequietnan(resultp1);
20538c2ecf20Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
20548c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
20558c2ecf20Sopenharmony_ci				}
20568c2ecf20Sopenharmony_ci				/*
20578c2ecf20Sopenharmony_ci				 * Check third operand for infinity with a
20588c2ecf20Sopenharmony_ci				 *  sign opposite of the multiply result
20598c2ecf20Sopenharmony_ci				 */
20608c2ecf20Sopenharmony_ci				if (Sgl_isinfinity(opnd3) &&
20618c2ecf20Sopenharmony_ci				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
20628c2ecf20Sopenharmony_ci					/*
20638c2ecf20Sopenharmony_ci					 * invalid since attempting a magnitude
20648c2ecf20Sopenharmony_ci					 * subtraction of infinities
20658c2ecf20Sopenharmony_ci					 */
20668c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
20678c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
20688c2ecf20Sopenharmony_ci					Set_invalidflag();
20698c2ecf20Sopenharmony_ci					Sgl_makequietnan(resultp1);
20708c2ecf20Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
20718c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
20728c2ecf20Sopenharmony_ci				}
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci				/*
20758c2ecf20Sopenharmony_ci			 	 * return infinity
20768c2ecf20Sopenharmony_ci			 	 */
20778c2ecf20Sopenharmony_ci				Sgl_setinfinity_exponentmantissa(resultp1);
20788c2ecf20Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
20798c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
20808c2ecf20Sopenharmony_ci			}
20818c2ecf20Sopenharmony_ci		}
20828c2ecf20Sopenharmony_ci		else {
20838c2ecf20Sopenharmony_ci			/*
20848c2ecf20Sopenharmony_ci		 	 * is NaN; signaling or quiet?
20858c2ecf20Sopenharmony_ci		 	 */
20868c2ecf20Sopenharmony_ci			if (Sgl_isone_signaling(opnd1)) {
20878c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
20888c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
20898c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
20908c2ecf20Sopenharmony_ci				/* make NaN quiet */
20918c2ecf20Sopenharmony_ci				Set_invalidflag();
20928c2ecf20Sopenharmony_ci				Sgl_set_quiet(opnd1);
20938c2ecf20Sopenharmony_ci			}
20948c2ecf20Sopenharmony_ci			/*
20958c2ecf20Sopenharmony_ci			 * is second operand a signaling NaN?
20968c2ecf20Sopenharmony_ci			 */
20978c2ecf20Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd2)) {
20988c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
20998c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
21008c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
21018c2ecf20Sopenharmony_ci				/* make NaN quiet */
21028c2ecf20Sopenharmony_ci				Set_invalidflag();
21038c2ecf20Sopenharmony_ci				Sgl_set_quiet(opnd2);
21048c2ecf20Sopenharmony_ci				Sgl_copytoptr(opnd2,dstptr);
21058c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
21068c2ecf20Sopenharmony_ci			}
21078c2ecf20Sopenharmony_ci			/*
21088c2ecf20Sopenharmony_ci			 * is third operand a signaling NaN?
21098c2ecf20Sopenharmony_ci			 */
21108c2ecf20Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd3)) {
21118c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
21128c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
21138c2ecf20Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
21148c2ecf20Sopenharmony_ci				/* make NaN quiet */
21158c2ecf20Sopenharmony_ci				Set_invalidflag();
21168c2ecf20Sopenharmony_ci				Sgl_set_quiet(opnd3);
21178c2ecf20Sopenharmony_ci				Sgl_copytoptr(opnd3,dstptr);
21188c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
21198c2ecf20Sopenharmony_ci			}
21208c2ecf20Sopenharmony_ci			/*
21218c2ecf20Sopenharmony_ci		 	 * return quiet NaN
21228c2ecf20Sopenharmony_ci		 	 */
21238c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd1,dstptr);
21248c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
21258c2ecf20Sopenharmony_ci		}
21268c2ecf20Sopenharmony_ci	}
21278c2ecf20Sopenharmony_ci
21288c2ecf20Sopenharmony_ci	/*
21298c2ecf20Sopenharmony_ci	 * check second operand for NaN's or infinity
21308c2ecf20Sopenharmony_ci	 */
21318c2ecf20Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd2)) {
21328c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd2)) {
21338c2ecf20Sopenharmony_ci			if (Sgl_isnotnan(opnd3)) {
21348c2ecf20Sopenharmony_ci				if (Sgl_iszero_exponentmantissa(opnd1)) {
21358c2ecf20Sopenharmony_ci					/*
21368c2ecf20Sopenharmony_ci					 * invalid since multiply operands are
21378c2ecf20Sopenharmony_ci					 * zero & infinity
21388c2ecf20Sopenharmony_ci					 */
21398c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
21408c2ecf20Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
21418c2ecf20Sopenharmony_ci					Set_invalidflag();
21428c2ecf20Sopenharmony_ci					Sgl_makequietnan(opnd2);
21438c2ecf20Sopenharmony_ci					Sgl_copytoptr(opnd2,dstptr);
21448c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
21458c2ecf20Sopenharmony_ci				}
21468c2ecf20Sopenharmony_ci
21478c2ecf20Sopenharmony_ci				/*
21488c2ecf20Sopenharmony_ci				 * Check third operand for infinity with a
21498c2ecf20Sopenharmony_ci				 *  sign opposite of the multiply result
21508c2ecf20Sopenharmony_ci				 */
21518c2ecf20Sopenharmony_ci				if (Sgl_isinfinity(opnd3) &&
21528c2ecf20Sopenharmony_ci				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
21538c2ecf20Sopenharmony_ci					/*
21548c2ecf20Sopenharmony_ci					 * invalid since attempting a magnitude
21558c2ecf20Sopenharmony_ci					 * subtraction of infinities
21568c2ecf20Sopenharmony_ci					 */
21578c2ecf20Sopenharmony_ci					if (Is_invalidtrap_enabled())
21588c2ecf20Sopenharmony_ci				       		return(OPC_2E_INVALIDEXCEPTION);
21598c2ecf20Sopenharmony_ci				       	Set_invalidflag();
21608c2ecf20Sopenharmony_ci				       	Sgl_makequietnan(resultp1);
21618c2ecf20Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
21628c2ecf20Sopenharmony_ci					return(NOEXCEPTION);
21638c2ecf20Sopenharmony_ci				}
21648c2ecf20Sopenharmony_ci
21658c2ecf20Sopenharmony_ci				/*
21668c2ecf20Sopenharmony_ci				 * return infinity
21678c2ecf20Sopenharmony_ci				 */
21688c2ecf20Sopenharmony_ci				Sgl_setinfinity_exponentmantissa(resultp1);
21698c2ecf20Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
21708c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
21718c2ecf20Sopenharmony_ci			}
21728c2ecf20Sopenharmony_ci		}
21738c2ecf20Sopenharmony_ci		else {
21748c2ecf20Sopenharmony_ci			/*
21758c2ecf20Sopenharmony_ci			 * is NaN; signaling or quiet?
21768c2ecf20Sopenharmony_ci			 */
21778c2ecf20Sopenharmony_ci			if (Sgl_isone_signaling(opnd2)) {
21788c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
21798c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
21808c2ecf20Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
21818c2ecf20Sopenharmony_ci				/* make NaN quiet */
21828c2ecf20Sopenharmony_ci				Set_invalidflag();
21838c2ecf20Sopenharmony_ci				Sgl_set_quiet(opnd2);
21848c2ecf20Sopenharmony_ci			}
21858c2ecf20Sopenharmony_ci			/*
21868c2ecf20Sopenharmony_ci			 * is third operand a signaling NaN?
21878c2ecf20Sopenharmony_ci			 */
21888c2ecf20Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd3)) {
21898c2ecf20Sopenharmony_ci			       	/* trap if INVALIDTRAP enabled */
21908c2ecf20Sopenharmony_ci			       	if (Is_invalidtrap_enabled())
21918c2ecf20Sopenharmony_ci				   		return(OPC_2E_INVALIDEXCEPTION);
21928c2ecf20Sopenharmony_ci			       	/* make NaN quiet */
21938c2ecf20Sopenharmony_ci			       	Set_invalidflag();
21948c2ecf20Sopenharmony_ci			       	Sgl_set_quiet(opnd3);
21958c2ecf20Sopenharmony_ci				Sgl_copytoptr(opnd3,dstptr);
21968c2ecf20Sopenharmony_ci		       		return(NOEXCEPTION);
21978c2ecf20Sopenharmony_ci			}
21988c2ecf20Sopenharmony_ci			/*
21998c2ecf20Sopenharmony_ci			 * return quiet NaN
22008c2ecf20Sopenharmony_ci			 */
22018c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd2,dstptr);
22028c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
22038c2ecf20Sopenharmony_ci		}
22048c2ecf20Sopenharmony_ci	}
22058c2ecf20Sopenharmony_ci
22068c2ecf20Sopenharmony_ci	/*
22078c2ecf20Sopenharmony_ci	 * check third operand for NaN's or infinity
22088c2ecf20Sopenharmony_ci	 */
22098c2ecf20Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd3)) {
22108c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd3)) {
22118c2ecf20Sopenharmony_ci			/* return infinity */
22128c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
22138c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
22148c2ecf20Sopenharmony_ci		} else {
22158c2ecf20Sopenharmony_ci			/*
22168c2ecf20Sopenharmony_ci			 * is NaN; signaling or quiet?
22178c2ecf20Sopenharmony_ci			 */
22188c2ecf20Sopenharmony_ci			if (Sgl_isone_signaling(opnd3)) {
22198c2ecf20Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
22208c2ecf20Sopenharmony_ci				if (Is_invalidtrap_enabled())
22218c2ecf20Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
22228c2ecf20Sopenharmony_ci				/* make NaN quiet */
22238c2ecf20Sopenharmony_ci				Set_invalidflag();
22248c2ecf20Sopenharmony_ci				Sgl_set_quiet(opnd3);
22258c2ecf20Sopenharmony_ci			}
22268c2ecf20Sopenharmony_ci			/*
22278c2ecf20Sopenharmony_ci			 * return quiet NaN
22288c2ecf20Sopenharmony_ci 			 */
22298c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
22308c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
22318c2ecf20Sopenharmony_ci		}
22328c2ecf20Sopenharmony_ci    	}
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_ci	/*
22358c2ecf20Sopenharmony_ci	 * Generate multiply mantissa
22368c2ecf20Sopenharmony_ci	 */
22378c2ecf20Sopenharmony_ci	if (Sgl_isnotzero_exponent(opnd1)) {
22388c2ecf20Sopenharmony_ci		/* set hidden bit */
22398c2ecf20Sopenharmony_ci		Sgl_clear_signexponent_set_hidden(opnd1);
22408c2ecf20Sopenharmony_ci	}
22418c2ecf20Sopenharmony_ci	else {
22428c2ecf20Sopenharmony_ci		/* check for zero */
22438c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd1)) {
22448c2ecf20Sopenharmony_ci			/*
22458c2ecf20Sopenharmony_ci			 * Perform the add opnd3 with zero here.
22468c2ecf20Sopenharmony_ci			 */
22478c2ecf20Sopenharmony_ci			if (Sgl_iszero_exponentmantissa(opnd3)) {
22488c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
22498c2ecf20Sopenharmony_ci					Sgl_or_signs(opnd3,resultp1);
22508c2ecf20Sopenharmony_ci				} else {
22518c2ecf20Sopenharmony_ci					Sgl_and_signs(opnd3,resultp1);
22528c2ecf20Sopenharmony_ci				}
22538c2ecf20Sopenharmony_ci			}
22548c2ecf20Sopenharmony_ci			/*
22558c2ecf20Sopenharmony_ci			 * Now let's check for trapped underflow case.
22568c2ecf20Sopenharmony_ci			 */
22578c2ecf20Sopenharmony_ci			else if (Sgl_iszero_exponent(opnd3) &&
22588c2ecf20Sopenharmony_ci			         Is_underflowtrap_enabled()) {
22598c2ecf20Sopenharmony_ci                    		/* need to normalize results mantissa */
22608c2ecf20Sopenharmony_ci                    		sign_save = Sgl_signextendedsign(opnd3);
22618c2ecf20Sopenharmony_ci				result_exponent = 0;
22628c2ecf20Sopenharmony_ci                    		Sgl_leftshiftby1(opnd3);
22638c2ecf20Sopenharmony_ci                    		Sgl_normalize(opnd3,result_exponent);
22648c2ecf20Sopenharmony_ci                    		Sgl_set_sign(opnd3,/*using*/sign_save);
22658c2ecf20Sopenharmony_ci                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
22668c2ecf20Sopenharmony_ci							unfl);
22678c2ecf20Sopenharmony_ci                    		Sgl_copytoptr(opnd3,dstptr);
22688c2ecf20Sopenharmony_ci                    		/* inexact = FALSE */
22698c2ecf20Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
22708c2ecf20Sopenharmony_ci			}
22718c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
22728c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
22738c2ecf20Sopenharmony_ci		}
22748c2ecf20Sopenharmony_ci		/* is denormalized, adjust exponent */
22758c2ecf20Sopenharmony_ci		Sgl_clear_signexponent(opnd1);
22768c2ecf20Sopenharmony_ci		Sgl_leftshiftby1(opnd1);
22778c2ecf20Sopenharmony_ci		Sgl_normalize(opnd1,mpy_exponent);
22788c2ecf20Sopenharmony_ci	}
22798c2ecf20Sopenharmony_ci	/* opnd2 needs to have hidden bit set with msb in hidden bit */
22808c2ecf20Sopenharmony_ci	if (Sgl_isnotzero_exponent(opnd2)) {
22818c2ecf20Sopenharmony_ci		Sgl_clear_signexponent_set_hidden(opnd2);
22828c2ecf20Sopenharmony_ci	}
22838c2ecf20Sopenharmony_ci	else {
22848c2ecf20Sopenharmony_ci		/* check for zero */
22858c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd2)) {
22868c2ecf20Sopenharmony_ci			/*
22878c2ecf20Sopenharmony_ci			 * Perform the add opnd3 with zero here.
22888c2ecf20Sopenharmony_ci			 */
22898c2ecf20Sopenharmony_ci			if (Sgl_iszero_exponentmantissa(opnd3)) {
22908c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
22918c2ecf20Sopenharmony_ci					Sgl_or_signs(opnd3,resultp1);
22928c2ecf20Sopenharmony_ci				} else {
22938c2ecf20Sopenharmony_ci					Sgl_and_signs(opnd3,resultp1);
22948c2ecf20Sopenharmony_ci				}
22958c2ecf20Sopenharmony_ci			}
22968c2ecf20Sopenharmony_ci			/*
22978c2ecf20Sopenharmony_ci			 * Now let's check for trapped underflow case.
22988c2ecf20Sopenharmony_ci			 */
22998c2ecf20Sopenharmony_ci			else if (Sgl_iszero_exponent(opnd3) &&
23008c2ecf20Sopenharmony_ci			    Is_underflowtrap_enabled()) {
23018c2ecf20Sopenharmony_ci                    		/* need to normalize results mantissa */
23028c2ecf20Sopenharmony_ci                    		sign_save = Sgl_signextendedsign(opnd3);
23038c2ecf20Sopenharmony_ci				result_exponent = 0;
23048c2ecf20Sopenharmony_ci                    		Sgl_leftshiftby1(opnd3);
23058c2ecf20Sopenharmony_ci                    		Sgl_normalize(opnd3,result_exponent);
23068c2ecf20Sopenharmony_ci                    		Sgl_set_sign(opnd3,/*using*/sign_save);
23078c2ecf20Sopenharmony_ci                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
23088c2ecf20Sopenharmony_ci							unfl);
23098c2ecf20Sopenharmony_ci                    		Sgl_copytoptr(opnd3,dstptr);
23108c2ecf20Sopenharmony_ci                    		/* inexact = FALSE */
23118c2ecf20Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
23128c2ecf20Sopenharmony_ci			}
23138c2ecf20Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
23148c2ecf20Sopenharmony_ci			return(NOEXCEPTION);
23158c2ecf20Sopenharmony_ci		}
23168c2ecf20Sopenharmony_ci		/* is denormalized; want to normalize */
23178c2ecf20Sopenharmony_ci		Sgl_clear_signexponent(opnd2);
23188c2ecf20Sopenharmony_ci		Sgl_leftshiftby1(opnd2);
23198c2ecf20Sopenharmony_ci		Sgl_normalize(opnd2,mpy_exponent);
23208c2ecf20Sopenharmony_ci	}
23218c2ecf20Sopenharmony_ci
23228c2ecf20Sopenharmony_ci	/* Multiply the first two source mantissas together */
23238c2ecf20Sopenharmony_ci
23248c2ecf20Sopenharmony_ci	/*
23258c2ecf20Sopenharmony_ci	 * The intermediate result will be kept in tmpres,
23268c2ecf20Sopenharmony_ci	 * which needs enough room for 106 bits of mantissa,
23278c2ecf20Sopenharmony_ci	 * so lets call it a Double extended.
23288c2ecf20Sopenharmony_ci	 */
23298c2ecf20Sopenharmony_ci	Sglext_setzero(tmpresp1,tmpresp2);
23308c2ecf20Sopenharmony_ci
23318c2ecf20Sopenharmony_ci	/*
23328c2ecf20Sopenharmony_ci	 * Four bits at a time are inspected in each loop, and a
23338c2ecf20Sopenharmony_ci	 * simple shift and add multiply algorithm is used.
23348c2ecf20Sopenharmony_ci	 */
23358c2ecf20Sopenharmony_ci	for (count = SGL_P-1; count >= 0; count -= 4) {
23368c2ecf20Sopenharmony_ci		Sglext_rightshiftby4(tmpresp1,tmpresp2);
23378c2ecf20Sopenharmony_ci		if (Sbit28(opnd1)) {
23388c2ecf20Sopenharmony_ci	 		/* Twoword_add should be an ADD followed by 2 ADDC's */
23398c2ecf20Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
23408c2ecf20Sopenharmony_ci		}
23418c2ecf20Sopenharmony_ci		if (Sbit29(opnd1)) {
23428c2ecf20Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
23438c2ecf20Sopenharmony_ci		}
23448c2ecf20Sopenharmony_ci		if (Sbit30(opnd1)) {
23458c2ecf20Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
23468c2ecf20Sopenharmony_ci		}
23478c2ecf20Sopenharmony_ci		if (Sbit31(opnd1)) {
23488c2ecf20Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
23498c2ecf20Sopenharmony_ci		}
23508c2ecf20Sopenharmony_ci		Sgl_rightshiftby4(opnd1);
23518c2ecf20Sopenharmony_ci	}
23528c2ecf20Sopenharmony_ci	if (Is_sexthiddenoverflow(tmpresp1)) {
23538c2ecf20Sopenharmony_ci		/* result mantissa >= 2 (mantissa overflow) */
23548c2ecf20Sopenharmony_ci		mpy_exponent++;
23558c2ecf20Sopenharmony_ci		Sglext_rightshiftby4(tmpresp1,tmpresp2);
23568c2ecf20Sopenharmony_ci	} else {
23578c2ecf20Sopenharmony_ci		Sglext_rightshiftby3(tmpresp1,tmpresp2);
23588c2ecf20Sopenharmony_ci	}
23598c2ecf20Sopenharmony_ci
23608c2ecf20Sopenharmony_ci	/*
23618c2ecf20Sopenharmony_ci	 * Restore the sign of the mpy result which was saved in resultp1.
23628c2ecf20Sopenharmony_ci	 * The exponent will continue to be kept in mpy_exponent.
23638c2ecf20Sopenharmony_ci	 */
23648c2ecf20Sopenharmony_ci	Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));
23658c2ecf20Sopenharmony_ci
23668c2ecf20Sopenharmony_ci	/*
23678c2ecf20Sopenharmony_ci	 * No rounding is required, since the result of the multiply
23688c2ecf20Sopenharmony_ci	 * is exact in the extended format.
23698c2ecf20Sopenharmony_ci	 */
23708c2ecf20Sopenharmony_ci
23718c2ecf20Sopenharmony_ci	/*
23728c2ecf20Sopenharmony_ci	 * Now we are ready to perform the add portion of the operation.
23738c2ecf20Sopenharmony_ci	 *
23748c2ecf20Sopenharmony_ci	 * The exponents need to be kept as integers for now, since the
23758c2ecf20Sopenharmony_ci	 * multiply result might not fit into the exponent field.  We
23768c2ecf20Sopenharmony_ci	 * can't overflow or underflow because of this yet, since the
23778c2ecf20Sopenharmony_ci	 * add could bring the final result back into range.
23788c2ecf20Sopenharmony_ci	 */
23798c2ecf20Sopenharmony_ci	add_exponent = Sgl_exponent(opnd3);
23808c2ecf20Sopenharmony_ci
23818c2ecf20Sopenharmony_ci	/*
23828c2ecf20Sopenharmony_ci	 * Check for denormalized or zero add operand.
23838c2ecf20Sopenharmony_ci	 */
23848c2ecf20Sopenharmony_ci	if (add_exponent == 0) {
23858c2ecf20Sopenharmony_ci		/* check for zero */
23868c2ecf20Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd3)) {
23878c2ecf20Sopenharmony_ci			/* right is zero */
23888c2ecf20Sopenharmony_ci			/* Left can't be zero and must be result.
23898c2ecf20Sopenharmony_ci			 *
23908c2ecf20Sopenharmony_ci			 * The final result is now in tmpres and mpy_exponent,
23918c2ecf20Sopenharmony_ci			 * and needs to be rounded and squeezed back into
23928c2ecf20Sopenharmony_ci			 * double precision format from double extended.
23938c2ecf20Sopenharmony_ci			 */
23948c2ecf20Sopenharmony_ci			result_exponent = mpy_exponent;
23958c2ecf20Sopenharmony_ci			Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
23968c2ecf20Sopenharmony_ci			sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
23978c2ecf20Sopenharmony_ci			goto round;
23988c2ecf20Sopenharmony_ci		}
23998c2ecf20Sopenharmony_ci
24008c2ecf20Sopenharmony_ci		/*
24018c2ecf20Sopenharmony_ci		 * Neither are zeroes.
24028c2ecf20Sopenharmony_ci		 * Adjust exponent and normalize add operand.
24038c2ecf20Sopenharmony_ci		 */
24048c2ecf20Sopenharmony_ci		sign_save = Sgl_signextendedsign(opnd3);	/* save sign */
24058c2ecf20Sopenharmony_ci		Sgl_clear_signexponent(opnd3);
24068c2ecf20Sopenharmony_ci		Sgl_leftshiftby1(opnd3);
24078c2ecf20Sopenharmony_ci		Sgl_normalize(opnd3,add_exponent);
24088c2ecf20Sopenharmony_ci		Sgl_set_sign(opnd3,sign_save);		/* restore sign */
24098c2ecf20Sopenharmony_ci	} else {
24108c2ecf20Sopenharmony_ci		Sgl_clear_exponent_set_hidden(opnd3);
24118c2ecf20Sopenharmony_ci	}
24128c2ecf20Sopenharmony_ci	/*
24138c2ecf20Sopenharmony_ci	 * Copy opnd3 to the double extended variable called right.
24148c2ecf20Sopenharmony_ci	 */
24158c2ecf20Sopenharmony_ci	Sgl_copyto_sglext(opnd3,rightp1,rightp2);
24168c2ecf20Sopenharmony_ci
24178c2ecf20Sopenharmony_ci	/*
24188c2ecf20Sopenharmony_ci	 * A zero "save" helps discover equal operands (for later),
24198c2ecf20Sopenharmony_ci	 * and is used in swapping operands (if needed).
24208c2ecf20Sopenharmony_ci	 */
24218c2ecf20Sopenharmony_ci	Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);
24228c2ecf20Sopenharmony_ci
24238c2ecf20Sopenharmony_ci	/*
24248c2ecf20Sopenharmony_ci	 * Compare magnitude of operands.
24258c2ecf20Sopenharmony_ci	 */
24268c2ecf20Sopenharmony_ci	Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
24278c2ecf20Sopenharmony_ci	Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
24288c2ecf20Sopenharmony_ci	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
24298c2ecf20Sopenharmony_ci	    Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
24308c2ecf20Sopenharmony_ci		/*
24318c2ecf20Sopenharmony_ci		 * Set the left operand to the larger one by XOR swap.
24328c2ecf20Sopenharmony_ci		 * First finish the first word "save".
24338c2ecf20Sopenharmony_ci		 */
24348c2ecf20Sopenharmony_ci		Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
24358c2ecf20Sopenharmony_ci		Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
24368c2ecf20Sopenharmony_ci		Sglext_swap_lower(tmpresp2,rightp2);
24378c2ecf20Sopenharmony_ci		/* also setup exponents used in rest of routine */
24388c2ecf20Sopenharmony_ci		diff_exponent = add_exponent - mpy_exponent;
24398c2ecf20Sopenharmony_ci		result_exponent = add_exponent;
24408c2ecf20Sopenharmony_ci	} else {
24418c2ecf20Sopenharmony_ci		/* also setup exponents used in rest of routine */
24428c2ecf20Sopenharmony_ci		diff_exponent = mpy_exponent - add_exponent;
24438c2ecf20Sopenharmony_ci		result_exponent = mpy_exponent;
24448c2ecf20Sopenharmony_ci	}
24458c2ecf20Sopenharmony_ci	/* Invariant: left is not smaller than right. */
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci	/*
24488c2ecf20Sopenharmony_ci	 * Special case alignment of operands that would force alignment
24498c2ecf20Sopenharmony_ci	 * beyond the extent of the extension.  A further optimization
24508c2ecf20Sopenharmony_ci	 * could special case this but only reduces the path length for
24518c2ecf20Sopenharmony_ci	 * this infrequent case.
24528c2ecf20Sopenharmony_ci	 */
24538c2ecf20Sopenharmony_ci	if (diff_exponent > SGLEXT_THRESHOLD) {
24548c2ecf20Sopenharmony_ci		diff_exponent = SGLEXT_THRESHOLD;
24558c2ecf20Sopenharmony_ci	}
24568c2ecf20Sopenharmony_ci
24578c2ecf20Sopenharmony_ci	/* Align right operand by shifting it to the right */
24588c2ecf20Sopenharmony_ci	Sglext_clear_sign(rightp1);
24598c2ecf20Sopenharmony_ci	Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
24608c2ecf20Sopenharmony_ci
24618c2ecf20Sopenharmony_ci	/* Treat sum and difference of the operands separately. */
24628c2ecf20Sopenharmony_ci	if ((int)save < 0) {
24638c2ecf20Sopenharmony_ci		/*
24648c2ecf20Sopenharmony_ci		 * Difference of the two operands.  Overflow can occur if the
24658c2ecf20Sopenharmony_ci		 * multiply overflowed.  A borrow can occur out of the hidden
24668c2ecf20Sopenharmony_ci		 * bit and force a post normalization phase.
24678c2ecf20Sopenharmony_ci		 */
24688c2ecf20Sopenharmony_ci		Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
24698c2ecf20Sopenharmony_ci			resultp1,resultp2);
24708c2ecf20Sopenharmony_ci		sign_save = Sgl_signextendedsign(resultp1);
24718c2ecf20Sopenharmony_ci		if (Sgl_iszero_hidden(resultp1)) {
24728c2ecf20Sopenharmony_ci			/* Handle normalization */
24738c2ecf20Sopenharmony_ci		/* A straightforward algorithm would now shift the
24748c2ecf20Sopenharmony_ci		 * result and extension left until the hidden bit
24758c2ecf20Sopenharmony_ci		 * becomes one.  Not all of the extension bits need
24768c2ecf20Sopenharmony_ci		 * participate in the shift.  Only the two most
24778c2ecf20Sopenharmony_ci		 * significant bits (round and guard) are needed.
24788c2ecf20Sopenharmony_ci		 * If only a single shift is needed then the guard
24798c2ecf20Sopenharmony_ci		 * bit becomes a significant low order bit and the
24808c2ecf20Sopenharmony_ci		 * extension must participate in the rounding.
24818c2ecf20Sopenharmony_ci		 * If more than a single shift is needed, then all
24828c2ecf20Sopenharmony_ci		 * bits to the right of the guard bit are zeros,
24838c2ecf20Sopenharmony_ci		 * and the guard bit may or may not be zero. */
24848c2ecf20Sopenharmony_ci			Sglext_leftshiftby1(resultp1,resultp2);
24858c2ecf20Sopenharmony_ci
24868c2ecf20Sopenharmony_ci			/* Need to check for a zero result.  The sign and
24878c2ecf20Sopenharmony_ci			 * exponent fields have already been zeroed.  The more
24888c2ecf20Sopenharmony_ci			 * efficient test of the full object can be used.
24898c2ecf20Sopenharmony_ci			 */
24908c2ecf20Sopenharmony_ci			 if (Sglext_iszero(resultp1,resultp2)) {
24918c2ecf20Sopenharmony_ci				/* Must have been "x-x" or "x+(-x)". */
24928c2ecf20Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS))
24938c2ecf20Sopenharmony_ci					Sgl_setone_sign(resultp1);
24948c2ecf20Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
24958c2ecf20Sopenharmony_ci				return(NOEXCEPTION);
24968c2ecf20Sopenharmony_ci			}
24978c2ecf20Sopenharmony_ci			result_exponent--;
24988c2ecf20Sopenharmony_ci
24998c2ecf20Sopenharmony_ci			/* Look to see if normalization is finished. */
25008c2ecf20Sopenharmony_ci			if (Sgl_isone_hidden(resultp1)) {
25018c2ecf20Sopenharmony_ci				/* No further normalization is needed */
25028c2ecf20Sopenharmony_ci				goto round;
25038c2ecf20Sopenharmony_ci			}
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_ci			/* Discover first one bit to determine shift amount.
25068c2ecf20Sopenharmony_ci			 * Use a modified binary search.  We have already
25078c2ecf20Sopenharmony_ci			 * shifted the result one position right and still
25088c2ecf20Sopenharmony_ci			 * not found a one so the remainder of the extension
25098c2ecf20Sopenharmony_ci			 * must be zero and simplifies rounding. */
25108c2ecf20Sopenharmony_ci			/* Scan bytes */
25118c2ecf20Sopenharmony_ci			while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
25128c2ecf20Sopenharmony_ci				Sglext_leftshiftby8(resultp1,resultp2);
25138c2ecf20Sopenharmony_ci				result_exponent -= 8;
25148c2ecf20Sopenharmony_ci			}
25158c2ecf20Sopenharmony_ci			/* Now narrow it down to the nibble */
25168c2ecf20Sopenharmony_ci			if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
25178c2ecf20Sopenharmony_ci				/* The lower nibble contains the
25188c2ecf20Sopenharmony_ci				 * normalizing one */
25198c2ecf20Sopenharmony_ci				Sglext_leftshiftby4(resultp1,resultp2);
25208c2ecf20Sopenharmony_ci				result_exponent -= 4;
25218c2ecf20Sopenharmony_ci			}
25228c2ecf20Sopenharmony_ci			/* Select case where first bit is set (already
25238c2ecf20Sopenharmony_ci			 * normalized) otherwise select the proper shift. */
25248c2ecf20Sopenharmony_ci			jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
25258c2ecf20Sopenharmony_ci			if (jumpsize <= 7) switch(jumpsize) {
25268c2ecf20Sopenharmony_ci			case 1:
25278c2ecf20Sopenharmony_ci				Sglext_leftshiftby3(resultp1,resultp2);
25288c2ecf20Sopenharmony_ci				result_exponent -= 3;
25298c2ecf20Sopenharmony_ci				break;
25308c2ecf20Sopenharmony_ci			case 2:
25318c2ecf20Sopenharmony_ci			case 3:
25328c2ecf20Sopenharmony_ci				Sglext_leftshiftby2(resultp1,resultp2);
25338c2ecf20Sopenharmony_ci				result_exponent -= 2;
25348c2ecf20Sopenharmony_ci				break;
25358c2ecf20Sopenharmony_ci			case 4:
25368c2ecf20Sopenharmony_ci			case 5:
25378c2ecf20Sopenharmony_ci			case 6:
25388c2ecf20Sopenharmony_ci			case 7:
25398c2ecf20Sopenharmony_ci				Sglext_leftshiftby1(resultp1,resultp2);
25408c2ecf20Sopenharmony_ci				result_exponent -= 1;
25418c2ecf20Sopenharmony_ci				break;
25428c2ecf20Sopenharmony_ci			}
25438c2ecf20Sopenharmony_ci		} /* end if (hidden...)... */
25448c2ecf20Sopenharmony_ci	/* Fall through and round */
25458c2ecf20Sopenharmony_ci	} /* end if (save < 0)... */
25468c2ecf20Sopenharmony_ci	else {
25478c2ecf20Sopenharmony_ci		/* Add magnitudes */
25488c2ecf20Sopenharmony_ci		Sglext_addition(tmpresp1,tmpresp2,
25498c2ecf20Sopenharmony_ci			rightp1,rightp2, /*to*/resultp1,resultp2);
25508c2ecf20Sopenharmony_ci		sign_save = Sgl_signextendedsign(resultp1);
25518c2ecf20Sopenharmony_ci		if (Sgl_isone_hiddenoverflow(resultp1)) {
25528c2ecf20Sopenharmony_ci	    		/* Prenormalization required. */
25538c2ecf20Sopenharmony_ci	    		Sglext_arithrightshiftby1(resultp1,resultp2);
25548c2ecf20Sopenharmony_ci	    		result_exponent++;
25558c2ecf20Sopenharmony_ci		} /* end if hiddenoverflow... */
25568c2ecf20Sopenharmony_ci	} /* end else ...add magnitudes... */
25578c2ecf20Sopenharmony_ci
25588c2ecf20Sopenharmony_ci	/* Round the result.  If the extension and lower two words are
25598c2ecf20Sopenharmony_ci	 * all zeros, then the result is exact.  Otherwise round in the
25608c2ecf20Sopenharmony_ci	 * correct direction.  Underflow is possible. If a postnormalization
25618c2ecf20Sopenharmony_ci	 * is necessary, then the mantissa is all zeros so no shift is needed.
25628c2ecf20Sopenharmony_ci	 */
25638c2ecf20Sopenharmony_ci  round:
25648c2ecf20Sopenharmony_ci	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
25658c2ecf20Sopenharmony_ci		Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
25668c2ecf20Sopenharmony_ci	}
25678c2ecf20Sopenharmony_ci	Sgl_set_sign(resultp1,/*using*/sign_save);
25688c2ecf20Sopenharmony_ci	if (Sglext_isnotzero_mantissap2(resultp2)) {
25698c2ecf20Sopenharmony_ci		inexact = TRUE;
25708c2ecf20Sopenharmony_ci		switch(Rounding_mode()) {
25718c2ecf20Sopenharmony_ci		case ROUNDNEAREST: /* The default. */
25728c2ecf20Sopenharmony_ci			if (Sglext_isone_highp2(resultp2)) {
25738c2ecf20Sopenharmony_ci				/* at least 1/2 ulp */
25748c2ecf20Sopenharmony_ci				if (Sglext_isnotzero_low31p2(resultp2) ||
25758c2ecf20Sopenharmony_ci				    Sglext_isone_lowp1(resultp1)) {
25768c2ecf20Sopenharmony_ci					/* either exactly half way and odd or
25778c2ecf20Sopenharmony_ci					 * more than 1/2ulp */
25788c2ecf20Sopenharmony_ci					Sgl_increment(resultp1);
25798c2ecf20Sopenharmony_ci				}
25808c2ecf20Sopenharmony_ci			}
25818c2ecf20Sopenharmony_ci	    		break;
25828c2ecf20Sopenharmony_ci
25838c2ecf20Sopenharmony_ci		case ROUNDPLUS:
25848c2ecf20Sopenharmony_ci	    		if (Sgl_iszero_sign(resultp1)) {
25858c2ecf20Sopenharmony_ci				/* Round up positive results */
25868c2ecf20Sopenharmony_ci				Sgl_increment(resultp1);
25878c2ecf20Sopenharmony_ci			}
25888c2ecf20Sopenharmony_ci			break;
25898c2ecf20Sopenharmony_ci
25908c2ecf20Sopenharmony_ci		case ROUNDMINUS:
25918c2ecf20Sopenharmony_ci	    		if (Sgl_isone_sign(resultp1)) {
25928c2ecf20Sopenharmony_ci				/* Round down negative results */
25938c2ecf20Sopenharmony_ci				Sgl_increment(resultp1);
25948c2ecf20Sopenharmony_ci			}
25958c2ecf20Sopenharmony_ci
25968c2ecf20Sopenharmony_ci		case ROUNDZERO:;
25978c2ecf20Sopenharmony_ci			/* truncate is simple */
25988c2ecf20Sopenharmony_ci		} /* end switch... */
25998c2ecf20Sopenharmony_ci		if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
26008c2ecf20Sopenharmony_ci	}
26018c2ecf20Sopenharmony_ci	if (result_exponent >= SGL_INFINITY_EXPONENT) {
26028c2ecf20Sopenharmony_ci		/* Overflow */
26038c2ecf20Sopenharmony_ci		if (Is_overflowtrap_enabled()) {
26048c2ecf20Sopenharmony_ci                        /*
26058c2ecf20Sopenharmony_ci                         * Adjust bias of result
26068c2ecf20Sopenharmony_ci                         */
26078c2ecf20Sopenharmony_ci                        Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
26088c2ecf20Sopenharmony_ci                        Sgl_copytoptr(resultp1,dstptr);
26098c2ecf20Sopenharmony_ci                        if (inexact)
26108c2ecf20Sopenharmony_ci                            if (Is_inexacttrap_enabled())
26118c2ecf20Sopenharmony_ci                                return (OPC_2E_OVERFLOWEXCEPTION |
26128c2ecf20Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
26138c2ecf20Sopenharmony_ci                            else Set_inexactflag();
26148c2ecf20Sopenharmony_ci                        return (OPC_2E_OVERFLOWEXCEPTION);
26158c2ecf20Sopenharmony_ci		}
26168c2ecf20Sopenharmony_ci		inexact = TRUE;
26178c2ecf20Sopenharmony_ci		Set_overflowflag();
26188c2ecf20Sopenharmony_ci		Sgl_setoverflow(resultp1);
26198c2ecf20Sopenharmony_ci	} else if (result_exponent <= 0) {	/* underflow case */
26208c2ecf20Sopenharmony_ci		if (Is_underflowtrap_enabled()) {
26218c2ecf20Sopenharmony_ci                        /*
26228c2ecf20Sopenharmony_ci                         * Adjust bias of result
26238c2ecf20Sopenharmony_ci                         */
26248c2ecf20Sopenharmony_ci                	Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
26258c2ecf20Sopenharmony_ci			Sgl_copytoptr(resultp1,dstptr);
26268c2ecf20Sopenharmony_ci                        if (inexact)
26278c2ecf20Sopenharmony_ci                            if (Is_inexacttrap_enabled())
26288c2ecf20Sopenharmony_ci                                return (OPC_2E_UNDERFLOWEXCEPTION |
26298c2ecf20Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
26308c2ecf20Sopenharmony_ci                            else Set_inexactflag();
26318c2ecf20Sopenharmony_ci	    		return(OPC_2E_UNDERFLOWEXCEPTION);
26328c2ecf20Sopenharmony_ci		}
26338c2ecf20Sopenharmony_ci		else if (inexact && is_tiny) Set_underflowflag();
26348c2ecf20Sopenharmony_ci	}
26358c2ecf20Sopenharmony_ci	else Sgl_set_exponent(resultp1,result_exponent);
26368c2ecf20Sopenharmony_ci	Sgl_copytoptr(resultp1,dstptr);
26378c2ecf20Sopenharmony_ci	if (inexact)
26388c2ecf20Sopenharmony_ci		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
26398c2ecf20Sopenharmony_ci		else Set_inexactflag();
26408c2ecf20Sopenharmony_ci    	return(NOEXCEPTION);
26418c2ecf20Sopenharmony_ci}
26428c2ecf20Sopenharmony_ci
2643