162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/)
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Floating-point emulation code
662306a36Sopenharmony_ci *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci * BEGIN_DESC
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci *  File:
1262306a36Sopenharmony_ci *	@(#)	pa/spmath/fmpyfadd.c		$Revision: 1.1 $
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *  Purpose:
1562306a36Sopenharmony_ci *	Double Floating-point Multiply Fused Add
1662306a36Sopenharmony_ci *	Double Floating-point Multiply Negate Fused Add
1762306a36Sopenharmony_ci *	Single Floating-point Multiply Fused Add
1862306a36Sopenharmony_ci *	Single Floating-point Multiply Negate Fused Add
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci *  External Interfaces:
2162306a36Sopenharmony_ci *	dbl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
2262306a36Sopenharmony_ci *	dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
2362306a36Sopenharmony_ci *	sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
2462306a36Sopenharmony_ci *	sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci *  Internal Interfaces:
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci *  Theory:
2962306a36Sopenharmony_ci *	<<please update with a overview of the operation of this file>>
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * END_DESC
3262306a36Sopenharmony_ci*/
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#include "float.h"
3662306a36Sopenharmony_ci#include "sgl_float.h"
3762306a36Sopenharmony_ci#include "dbl_float.h"
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/*
4162306a36Sopenharmony_ci *  Double Floating-point Multiply Fused Add
4262306a36Sopenharmony_ci */
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ciint
4562306a36Sopenharmony_cidbl_fmpyfadd(
4662306a36Sopenharmony_ci	    dbl_floating_point *src1ptr,
4762306a36Sopenharmony_ci	    dbl_floating_point *src2ptr,
4862306a36Sopenharmony_ci	    dbl_floating_point *src3ptr,
4962306a36Sopenharmony_ci	    unsigned int *status,
5062306a36Sopenharmony_ci	    dbl_floating_point *dstptr)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
5362306a36Sopenharmony_ci	register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
5462306a36Sopenharmony_ci	unsigned int rightp1, rightp2, rightp3, rightp4;
5562306a36Sopenharmony_ci	unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
5662306a36Sopenharmony_ci	register int mpy_exponent, add_exponent, count;
5762306a36Sopenharmony_ci	boolean inexact = FALSE, is_tiny = FALSE;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	unsigned int signlessleft1, signlessright1, save;
6062306a36Sopenharmony_ci	register int result_exponent, diff_exponent;
6162306a36Sopenharmony_ci	int sign_save, jumpsize;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
6462306a36Sopenharmony_ci	Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
6562306a36Sopenharmony_ci	Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	/*
6862306a36Sopenharmony_ci	 * set sign bit of result of multiply
6962306a36Sopenharmony_ci	 */
7062306a36Sopenharmony_ci	if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
7162306a36Sopenharmony_ci		Dbl_setnegativezerop1(resultp1);
7262306a36Sopenharmony_ci	else Dbl_setzerop1(resultp1);
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	/*
7562306a36Sopenharmony_ci	 * Generate multiply exponent
7662306a36Sopenharmony_ci	 */
7762306a36Sopenharmony_ci	mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	/*
8062306a36Sopenharmony_ci	 * check first operand for NaN's or infinity
8162306a36Sopenharmony_ci	 */
8262306a36Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd1p1)) {
8362306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
8462306a36Sopenharmony_ci			if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
8562306a36Sopenharmony_ci			    Dbl_isnotnan(opnd3p1,opnd3p2)) {
8662306a36Sopenharmony_ci				if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
8762306a36Sopenharmony_ci					/*
8862306a36Sopenharmony_ci					 * invalid since operands are infinity
8962306a36Sopenharmony_ci					 * and zero
9062306a36Sopenharmony_ci					 */
9162306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
9262306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
9362306a36Sopenharmony_ci					Set_invalidflag();
9462306a36Sopenharmony_ci					Dbl_makequietnan(resultp1,resultp2);
9562306a36Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
9662306a36Sopenharmony_ci					return(NOEXCEPTION);
9762306a36Sopenharmony_ci				}
9862306a36Sopenharmony_ci				/*
9962306a36Sopenharmony_ci				 * Check third operand for infinity with a
10062306a36Sopenharmony_ci				 *  sign opposite of the multiply result
10162306a36Sopenharmony_ci				 */
10262306a36Sopenharmony_ci				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
10362306a36Sopenharmony_ci				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
10462306a36Sopenharmony_ci					/*
10562306a36Sopenharmony_ci					 * invalid since attempting a magnitude
10662306a36Sopenharmony_ci					 * subtraction of infinities
10762306a36Sopenharmony_ci					 */
10862306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
10962306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
11062306a36Sopenharmony_ci					Set_invalidflag();
11162306a36Sopenharmony_ci					Dbl_makequietnan(resultp1,resultp2);
11262306a36Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
11362306a36Sopenharmony_ci					return(NOEXCEPTION);
11462306a36Sopenharmony_ci				}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci				/*
11762306a36Sopenharmony_ci			 	 * return infinity
11862306a36Sopenharmony_ci			 	 */
11962306a36Sopenharmony_ci				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
12062306a36Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
12162306a36Sopenharmony_ci				return(NOEXCEPTION);
12262306a36Sopenharmony_ci			}
12362306a36Sopenharmony_ci		}
12462306a36Sopenharmony_ci		else {
12562306a36Sopenharmony_ci			/*
12662306a36Sopenharmony_ci		 	 * is NaN; signaling or quiet?
12762306a36Sopenharmony_ci		 	 */
12862306a36Sopenharmony_ci			if (Dbl_isone_signaling(opnd1p1)) {
12962306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
13062306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
13162306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
13262306a36Sopenharmony_ci				/* make NaN quiet */
13362306a36Sopenharmony_ci				Set_invalidflag();
13462306a36Sopenharmony_ci				Dbl_set_quiet(opnd1p1);
13562306a36Sopenharmony_ci			}
13662306a36Sopenharmony_ci			/*
13762306a36Sopenharmony_ci			 * is second operand a signaling NaN?
13862306a36Sopenharmony_ci			 */
13962306a36Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd2p1)) {
14062306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
14162306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
14262306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
14362306a36Sopenharmony_ci				/* make NaN quiet */
14462306a36Sopenharmony_ci				Set_invalidflag();
14562306a36Sopenharmony_ci				Dbl_set_quiet(opnd2p1);
14662306a36Sopenharmony_ci				Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
14762306a36Sopenharmony_ci				return(NOEXCEPTION);
14862306a36Sopenharmony_ci			}
14962306a36Sopenharmony_ci			/*
15062306a36Sopenharmony_ci			 * is third operand a signaling NaN?
15162306a36Sopenharmony_ci			 */
15262306a36Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd3p1)) {
15362306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
15462306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
15562306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
15662306a36Sopenharmony_ci				/* make NaN quiet */
15762306a36Sopenharmony_ci				Set_invalidflag();
15862306a36Sopenharmony_ci				Dbl_set_quiet(opnd3p1);
15962306a36Sopenharmony_ci				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
16062306a36Sopenharmony_ci				return(NOEXCEPTION);
16162306a36Sopenharmony_ci			}
16262306a36Sopenharmony_ci			/*
16362306a36Sopenharmony_ci		 	 * return quiet NaN
16462306a36Sopenharmony_ci		 	 */
16562306a36Sopenharmony_ci			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
16662306a36Sopenharmony_ci			return(NOEXCEPTION);
16762306a36Sopenharmony_ci		}
16862306a36Sopenharmony_ci	}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	/*
17162306a36Sopenharmony_ci	 * check second operand for NaN's or infinity
17262306a36Sopenharmony_ci	 */
17362306a36Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd2p1)) {
17462306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
17562306a36Sopenharmony_ci			if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
17662306a36Sopenharmony_ci				if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
17762306a36Sopenharmony_ci					/*
17862306a36Sopenharmony_ci					 * invalid since multiply operands are
17962306a36Sopenharmony_ci					 * zero & infinity
18062306a36Sopenharmony_ci					 */
18162306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
18262306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
18362306a36Sopenharmony_ci					Set_invalidflag();
18462306a36Sopenharmony_ci					Dbl_makequietnan(opnd2p1,opnd2p2);
18562306a36Sopenharmony_ci					Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
18662306a36Sopenharmony_ci					return(NOEXCEPTION);
18762306a36Sopenharmony_ci				}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci				/*
19062306a36Sopenharmony_ci				 * Check third operand for infinity with a
19162306a36Sopenharmony_ci				 *  sign opposite of the multiply result
19262306a36Sopenharmony_ci				 */
19362306a36Sopenharmony_ci				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
19462306a36Sopenharmony_ci				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
19562306a36Sopenharmony_ci					/*
19662306a36Sopenharmony_ci					 * invalid since attempting a magnitude
19762306a36Sopenharmony_ci					 * subtraction of infinities
19862306a36Sopenharmony_ci					 */
19962306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
20062306a36Sopenharmony_ci				       		return(OPC_2E_INVALIDEXCEPTION);
20162306a36Sopenharmony_ci				       	Set_invalidflag();
20262306a36Sopenharmony_ci				       	Dbl_makequietnan(resultp1,resultp2);
20362306a36Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
20462306a36Sopenharmony_ci					return(NOEXCEPTION);
20562306a36Sopenharmony_ci				}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci				/*
20862306a36Sopenharmony_ci				 * return infinity
20962306a36Sopenharmony_ci				 */
21062306a36Sopenharmony_ci				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
21162306a36Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
21262306a36Sopenharmony_ci				return(NOEXCEPTION);
21362306a36Sopenharmony_ci			}
21462306a36Sopenharmony_ci		}
21562306a36Sopenharmony_ci		else {
21662306a36Sopenharmony_ci			/*
21762306a36Sopenharmony_ci			 * is NaN; signaling or quiet?
21862306a36Sopenharmony_ci			 */
21962306a36Sopenharmony_ci			if (Dbl_isone_signaling(opnd2p1)) {
22062306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
22162306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
22262306a36Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
22362306a36Sopenharmony_ci				/* make NaN quiet */
22462306a36Sopenharmony_ci				Set_invalidflag();
22562306a36Sopenharmony_ci				Dbl_set_quiet(opnd2p1);
22662306a36Sopenharmony_ci			}
22762306a36Sopenharmony_ci			/*
22862306a36Sopenharmony_ci			 * is third operand a signaling NaN?
22962306a36Sopenharmony_ci			 */
23062306a36Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd3p1)) {
23162306a36Sopenharmony_ci			       	/* trap if INVALIDTRAP enabled */
23262306a36Sopenharmony_ci			       	if (Is_invalidtrap_enabled())
23362306a36Sopenharmony_ci				   		return(OPC_2E_INVALIDEXCEPTION);
23462306a36Sopenharmony_ci			       	/* make NaN quiet */
23562306a36Sopenharmony_ci			       	Set_invalidflag();
23662306a36Sopenharmony_ci			       	Dbl_set_quiet(opnd3p1);
23762306a36Sopenharmony_ci				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
23862306a36Sopenharmony_ci		       		return(NOEXCEPTION);
23962306a36Sopenharmony_ci			}
24062306a36Sopenharmony_ci			/*
24162306a36Sopenharmony_ci			 * return quiet NaN
24262306a36Sopenharmony_ci			 */
24362306a36Sopenharmony_ci			Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
24462306a36Sopenharmony_ci			return(NOEXCEPTION);
24562306a36Sopenharmony_ci		}
24662306a36Sopenharmony_ci	}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	/*
24962306a36Sopenharmony_ci	 * check third operand for NaN's or infinity
25062306a36Sopenharmony_ci	 */
25162306a36Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd3p1)) {
25262306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
25362306a36Sopenharmony_ci			/* return infinity */
25462306a36Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
25562306a36Sopenharmony_ci			return(NOEXCEPTION);
25662306a36Sopenharmony_ci		} else {
25762306a36Sopenharmony_ci			/*
25862306a36Sopenharmony_ci			 * is NaN; signaling or quiet?
25962306a36Sopenharmony_ci			 */
26062306a36Sopenharmony_ci			if (Dbl_isone_signaling(opnd3p1)) {
26162306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
26262306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
26362306a36Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
26462306a36Sopenharmony_ci				/* make NaN quiet */
26562306a36Sopenharmony_ci				Set_invalidflag();
26662306a36Sopenharmony_ci				Dbl_set_quiet(opnd3p1);
26762306a36Sopenharmony_ci			}
26862306a36Sopenharmony_ci			/*
26962306a36Sopenharmony_ci			 * return quiet NaN
27062306a36Sopenharmony_ci 			 */
27162306a36Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
27262306a36Sopenharmony_ci			return(NOEXCEPTION);
27362306a36Sopenharmony_ci		}
27462306a36Sopenharmony_ci    	}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	/*
27762306a36Sopenharmony_ci	 * Generate multiply mantissa
27862306a36Sopenharmony_ci	 */
27962306a36Sopenharmony_ci	if (Dbl_isnotzero_exponent(opnd1p1)) {
28062306a36Sopenharmony_ci		/* set hidden bit */
28162306a36Sopenharmony_ci		Dbl_clear_signexponent_set_hidden(opnd1p1);
28262306a36Sopenharmony_ci	}
28362306a36Sopenharmony_ci	else {
28462306a36Sopenharmony_ci		/* check for zero */
28562306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
28662306a36Sopenharmony_ci			/*
28762306a36Sopenharmony_ci			 * Perform the add opnd3 with zero here.
28862306a36Sopenharmony_ci			 */
28962306a36Sopenharmony_ci			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
29062306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
29162306a36Sopenharmony_ci					Dbl_or_signs(opnd3p1,resultp1);
29262306a36Sopenharmony_ci				} else {
29362306a36Sopenharmony_ci					Dbl_and_signs(opnd3p1,resultp1);
29462306a36Sopenharmony_ci				}
29562306a36Sopenharmony_ci			}
29662306a36Sopenharmony_ci			/*
29762306a36Sopenharmony_ci			 * Now let's check for trapped underflow case.
29862306a36Sopenharmony_ci			 */
29962306a36Sopenharmony_ci			else if (Dbl_iszero_exponent(opnd3p1) &&
30062306a36Sopenharmony_ci			         Is_underflowtrap_enabled()) {
30162306a36Sopenharmony_ci                    		/* need to normalize results mantissa */
30262306a36Sopenharmony_ci                    		sign_save = Dbl_signextendedsign(opnd3p1);
30362306a36Sopenharmony_ci				result_exponent = 0;
30462306a36Sopenharmony_ci                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
30562306a36Sopenharmony_ci                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
30662306a36Sopenharmony_ci                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
30762306a36Sopenharmony_ci                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
30862306a36Sopenharmony_ci							unfl);
30962306a36Sopenharmony_ci                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
31062306a36Sopenharmony_ci                    		/* inexact = FALSE */
31162306a36Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
31262306a36Sopenharmony_ci			}
31362306a36Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
31462306a36Sopenharmony_ci			return(NOEXCEPTION);
31562306a36Sopenharmony_ci		}
31662306a36Sopenharmony_ci		/* is denormalized, adjust exponent */
31762306a36Sopenharmony_ci		Dbl_clear_signexponent(opnd1p1);
31862306a36Sopenharmony_ci		Dbl_leftshiftby1(opnd1p1,opnd1p2);
31962306a36Sopenharmony_ci		Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci	/* opnd2 needs to have hidden bit set with msb in hidden bit */
32262306a36Sopenharmony_ci	if (Dbl_isnotzero_exponent(opnd2p1)) {
32362306a36Sopenharmony_ci		Dbl_clear_signexponent_set_hidden(opnd2p1);
32462306a36Sopenharmony_ci	}
32562306a36Sopenharmony_ci	else {
32662306a36Sopenharmony_ci		/* check for zero */
32762306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
32862306a36Sopenharmony_ci			/*
32962306a36Sopenharmony_ci			 * Perform the add opnd3 with zero here.
33062306a36Sopenharmony_ci			 */
33162306a36Sopenharmony_ci			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
33262306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
33362306a36Sopenharmony_ci					Dbl_or_signs(opnd3p1,resultp1);
33462306a36Sopenharmony_ci				} else {
33562306a36Sopenharmony_ci					Dbl_and_signs(opnd3p1,resultp1);
33662306a36Sopenharmony_ci				}
33762306a36Sopenharmony_ci			}
33862306a36Sopenharmony_ci			/*
33962306a36Sopenharmony_ci			 * Now let's check for trapped underflow case.
34062306a36Sopenharmony_ci			 */
34162306a36Sopenharmony_ci			else if (Dbl_iszero_exponent(opnd3p1) &&
34262306a36Sopenharmony_ci			    Is_underflowtrap_enabled()) {
34362306a36Sopenharmony_ci                    		/* need to normalize results mantissa */
34462306a36Sopenharmony_ci                    		sign_save = Dbl_signextendedsign(opnd3p1);
34562306a36Sopenharmony_ci				result_exponent = 0;
34662306a36Sopenharmony_ci                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
34762306a36Sopenharmony_ci                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
34862306a36Sopenharmony_ci                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
34962306a36Sopenharmony_ci                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
35062306a36Sopenharmony_ci							unfl);
35162306a36Sopenharmony_ci                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
35262306a36Sopenharmony_ci                    		/* inexact = FALSE */
35362306a36Sopenharmony_ci				return(OPC_2E_UNDERFLOWEXCEPTION);
35462306a36Sopenharmony_ci			}
35562306a36Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
35662306a36Sopenharmony_ci			return(NOEXCEPTION);
35762306a36Sopenharmony_ci		}
35862306a36Sopenharmony_ci		/* is denormalized; want to normalize */
35962306a36Sopenharmony_ci		Dbl_clear_signexponent(opnd2p1);
36062306a36Sopenharmony_ci		Dbl_leftshiftby1(opnd2p1,opnd2p2);
36162306a36Sopenharmony_ci		Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	/* Multiply the first two source mantissas together */
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	/*
36762306a36Sopenharmony_ci	 * The intermediate result will be kept in tmpres,
36862306a36Sopenharmony_ci	 * which needs enough room for 106 bits of mantissa,
36962306a36Sopenharmony_ci	 * so lets call it a Double extended.
37062306a36Sopenharmony_ci	 */
37162306a36Sopenharmony_ci	Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	/*
37462306a36Sopenharmony_ci	 * Four bits at a time are inspected in each loop, and a
37562306a36Sopenharmony_ci	 * simple shift and add multiply algorithm is used.
37662306a36Sopenharmony_ci	 */
37762306a36Sopenharmony_ci	for (count = DBL_P-1; count >= 0; count -= 4) {
37862306a36Sopenharmony_ci		Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
37962306a36Sopenharmony_ci		if (Dbit28p2(opnd1p2)) {
38062306a36Sopenharmony_ci	 		/* Fourword_add should be an ADD followed by 3 ADDC's */
38162306a36Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
38262306a36Sopenharmony_ci			 opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
38362306a36Sopenharmony_ci		}
38462306a36Sopenharmony_ci		if (Dbit29p2(opnd1p2)) {
38562306a36Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
38662306a36Sopenharmony_ci			 opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
38762306a36Sopenharmony_ci		}
38862306a36Sopenharmony_ci		if (Dbit30p2(opnd1p2)) {
38962306a36Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
39062306a36Sopenharmony_ci			 opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
39162306a36Sopenharmony_ci		}
39262306a36Sopenharmony_ci		if (Dbit31p2(opnd1p2)) {
39362306a36Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
39462306a36Sopenharmony_ci			 opnd2p1, opnd2p2, 0, 0);
39562306a36Sopenharmony_ci		}
39662306a36Sopenharmony_ci		Dbl_rightshiftby4(opnd1p1,opnd1p2);
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci	if (Is_dexthiddenoverflow(tmpresp1)) {
39962306a36Sopenharmony_ci		/* result mantissa >= 2 (mantissa overflow) */
40062306a36Sopenharmony_ci		mpy_exponent++;
40162306a36Sopenharmony_ci		Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
40262306a36Sopenharmony_ci	}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	/*
40562306a36Sopenharmony_ci	 * Restore the sign of the mpy result which was saved in resultp1.
40662306a36Sopenharmony_ci	 * The exponent will continue to be kept in mpy_exponent.
40762306a36Sopenharmony_ci	 */
40862306a36Sopenharmony_ci	Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	/*
41162306a36Sopenharmony_ci	 * No rounding is required, since the result of the multiply
41262306a36Sopenharmony_ci	 * is exact in the extended format.
41362306a36Sopenharmony_ci	 */
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	/*
41662306a36Sopenharmony_ci	 * Now we are ready to perform the add portion of the operation.
41762306a36Sopenharmony_ci	 *
41862306a36Sopenharmony_ci	 * The exponents need to be kept as integers for now, since the
41962306a36Sopenharmony_ci	 * multiply result might not fit into the exponent field.  We
42062306a36Sopenharmony_ci	 * can't overflow or underflow because of this yet, since the
42162306a36Sopenharmony_ci	 * add could bring the final result back into range.
42262306a36Sopenharmony_ci	 */
42362306a36Sopenharmony_ci	add_exponent = Dbl_exponent(opnd3p1);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	/*
42662306a36Sopenharmony_ci	 * Check for denormalized or zero add operand.
42762306a36Sopenharmony_ci	 */
42862306a36Sopenharmony_ci	if (add_exponent == 0) {
42962306a36Sopenharmony_ci		/* check for zero */
43062306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
43162306a36Sopenharmony_ci			/* right is zero */
43262306a36Sopenharmony_ci			/* Left can't be zero and must be result.
43362306a36Sopenharmony_ci			 *
43462306a36Sopenharmony_ci			 * The final result is now in tmpres and mpy_exponent,
43562306a36Sopenharmony_ci			 * and needs to be rounded and squeezed back into
43662306a36Sopenharmony_ci			 * double precision format from double extended.
43762306a36Sopenharmony_ci			 */
43862306a36Sopenharmony_ci			result_exponent = mpy_exponent;
43962306a36Sopenharmony_ci			Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
44062306a36Sopenharmony_ci				resultp1,resultp2,resultp3,resultp4);
44162306a36Sopenharmony_ci			sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
44262306a36Sopenharmony_ci			goto round;
44362306a36Sopenharmony_ci		}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci		/*
44662306a36Sopenharmony_ci		 * Neither are zeroes.
44762306a36Sopenharmony_ci		 * Adjust exponent and normalize add operand.
44862306a36Sopenharmony_ci		 */
44962306a36Sopenharmony_ci		sign_save = Dbl_signextendedsign(opnd3p1);	/* save sign */
45062306a36Sopenharmony_ci		Dbl_clear_signexponent(opnd3p1);
45162306a36Sopenharmony_ci		Dbl_leftshiftby1(opnd3p1,opnd3p2);
45262306a36Sopenharmony_ci		Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
45362306a36Sopenharmony_ci		Dbl_set_sign(opnd3p1,sign_save);	/* restore sign */
45462306a36Sopenharmony_ci	} else {
45562306a36Sopenharmony_ci		Dbl_clear_exponent_set_hidden(opnd3p1);
45662306a36Sopenharmony_ci	}
45762306a36Sopenharmony_ci	/*
45862306a36Sopenharmony_ci	 * Copy opnd3 to the double extended variable called right.
45962306a36Sopenharmony_ci	 */
46062306a36Sopenharmony_ci	Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	/*
46362306a36Sopenharmony_ci	 * A zero "save" helps discover equal operands (for later),
46462306a36Sopenharmony_ci	 * and is used in swapping operands (if needed).
46562306a36Sopenharmony_ci	 */
46662306a36Sopenharmony_ci	Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	/*
46962306a36Sopenharmony_ci	 * Compare magnitude of operands.
47062306a36Sopenharmony_ci	 */
47162306a36Sopenharmony_ci	Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
47262306a36Sopenharmony_ci	Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
47362306a36Sopenharmony_ci	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
47462306a36Sopenharmony_ci	    Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
47562306a36Sopenharmony_ci		/*
47662306a36Sopenharmony_ci		 * Set the left operand to the larger one by XOR swap.
47762306a36Sopenharmony_ci		 * First finish the first word "save".
47862306a36Sopenharmony_ci		 */
47962306a36Sopenharmony_ci		Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
48062306a36Sopenharmony_ci		Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
48162306a36Sopenharmony_ci		Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
48262306a36Sopenharmony_ci			rightp2,rightp3,rightp4);
48362306a36Sopenharmony_ci		/* also setup exponents used in rest of routine */
48462306a36Sopenharmony_ci		diff_exponent = add_exponent - mpy_exponent;
48562306a36Sopenharmony_ci		result_exponent = add_exponent;
48662306a36Sopenharmony_ci	} else {
48762306a36Sopenharmony_ci		/* also setup exponents used in rest of routine */
48862306a36Sopenharmony_ci		diff_exponent = mpy_exponent - add_exponent;
48962306a36Sopenharmony_ci		result_exponent = mpy_exponent;
49062306a36Sopenharmony_ci	}
49162306a36Sopenharmony_ci	/* Invariant: left is not smaller than right. */
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	/*
49462306a36Sopenharmony_ci	 * Special case alignment of operands that would force alignment
49562306a36Sopenharmony_ci	 * beyond the extent of the extension.  A further optimization
49662306a36Sopenharmony_ci	 * could special case this but only reduces the path length for
49762306a36Sopenharmony_ci	 * this infrequent case.
49862306a36Sopenharmony_ci	 */
49962306a36Sopenharmony_ci	if (diff_exponent > DBLEXT_THRESHOLD) {
50062306a36Sopenharmony_ci		diff_exponent = DBLEXT_THRESHOLD;
50162306a36Sopenharmony_ci	}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	/* Align right operand by shifting it to the right */
50462306a36Sopenharmony_ci	Dblext_clear_sign(rightp1);
50562306a36Sopenharmony_ci	Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
50662306a36Sopenharmony_ci		/*shifted by*/diff_exponent);
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	/* Treat sum and difference of the operands separately. */
50962306a36Sopenharmony_ci	if ((int)save < 0) {
51062306a36Sopenharmony_ci		/*
51162306a36Sopenharmony_ci		 * Difference of the two operands.  Overflow can occur if the
51262306a36Sopenharmony_ci		 * multiply overflowed.  A borrow can occur out of the hidden
51362306a36Sopenharmony_ci		 * bit and force a post normalization phase.
51462306a36Sopenharmony_ci		 */
51562306a36Sopenharmony_ci		Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
51662306a36Sopenharmony_ci			rightp1,rightp2,rightp3,rightp4,
51762306a36Sopenharmony_ci			resultp1,resultp2,resultp3,resultp4);
51862306a36Sopenharmony_ci		sign_save = Dbl_signextendedsign(resultp1);
51962306a36Sopenharmony_ci		if (Dbl_iszero_hidden(resultp1)) {
52062306a36Sopenharmony_ci			/* Handle normalization */
52162306a36Sopenharmony_ci		/* A straightforward algorithm would now shift the
52262306a36Sopenharmony_ci		 * result and extension left until the hidden bit
52362306a36Sopenharmony_ci		 * becomes one.  Not all of the extension bits need
52462306a36Sopenharmony_ci		 * participate in the shift.  Only the two most
52562306a36Sopenharmony_ci		 * significant bits (round and guard) are needed.
52662306a36Sopenharmony_ci		 * If only a single shift is needed then the guard
52762306a36Sopenharmony_ci		 * bit becomes a significant low order bit and the
52862306a36Sopenharmony_ci		 * extension must participate in the rounding.
52962306a36Sopenharmony_ci		 * If more than a single shift is needed, then all
53062306a36Sopenharmony_ci		 * bits to the right of the guard bit are zeros,
53162306a36Sopenharmony_ci		 * and the guard bit may or may not be zero. */
53262306a36Sopenharmony_ci			Dblext_leftshiftby1(resultp1,resultp2,resultp3,
53362306a36Sopenharmony_ci				resultp4);
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci			/* Need to check for a zero result.  The sign and
53662306a36Sopenharmony_ci			 * exponent fields have already been zeroed.  The more
53762306a36Sopenharmony_ci			 * efficient test of the full object can be used.
53862306a36Sopenharmony_ci			 */
53962306a36Sopenharmony_ci			 if(Dblext_iszero(resultp1,resultp2,resultp3,resultp4)){
54062306a36Sopenharmony_ci				/* Must have been "x-x" or "x+(-x)". */
54162306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS))
54262306a36Sopenharmony_ci					Dbl_setone_sign(resultp1);
54362306a36Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
54462306a36Sopenharmony_ci				return(NOEXCEPTION);
54562306a36Sopenharmony_ci			}
54662306a36Sopenharmony_ci			result_exponent--;
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci			/* Look to see if normalization is finished. */
54962306a36Sopenharmony_ci			if (Dbl_isone_hidden(resultp1)) {
55062306a36Sopenharmony_ci				/* No further normalization is needed */
55162306a36Sopenharmony_ci				goto round;
55262306a36Sopenharmony_ci			}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci			/* Discover first one bit to determine shift amount.
55562306a36Sopenharmony_ci			 * Use a modified binary search.  We have already
55662306a36Sopenharmony_ci			 * shifted the result one position right and still
55762306a36Sopenharmony_ci			 * not found a one so the remainder of the extension
55862306a36Sopenharmony_ci			 * must be zero and simplifies rounding. */
55962306a36Sopenharmony_ci			/* Scan bytes */
56062306a36Sopenharmony_ci			while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
56162306a36Sopenharmony_ci				Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
56262306a36Sopenharmony_ci				result_exponent -= 8;
56362306a36Sopenharmony_ci			}
56462306a36Sopenharmony_ci			/* Now narrow it down to the nibble */
56562306a36Sopenharmony_ci			if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
56662306a36Sopenharmony_ci				/* The lower nibble contains the
56762306a36Sopenharmony_ci				 * normalizing one */
56862306a36Sopenharmony_ci				Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
56962306a36Sopenharmony_ci				result_exponent -= 4;
57062306a36Sopenharmony_ci			}
57162306a36Sopenharmony_ci			/* Select case where first bit is set (already
57262306a36Sopenharmony_ci			 * normalized) otherwise select the proper shift. */
57362306a36Sopenharmony_ci			jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
57462306a36Sopenharmony_ci			if (jumpsize <= 7) switch(jumpsize) {
57562306a36Sopenharmony_ci			case 1:
57662306a36Sopenharmony_ci				Dblext_leftshiftby3(resultp1,resultp2,resultp3,
57762306a36Sopenharmony_ci					resultp4);
57862306a36Sopenharmony_ci				result_exponent -= 3;
57962306a36Sopenharmony_ci				break;
58062306a36Sopenharmony_ci			case 2:
58162306a36Sopenharmony_ci			case 3:
58262306a36Sopenharmony_ci				Dblext_leftshiftby2(resultp1,resultp2,resultp3,
58362306a36Sopenharmony_ci					resultp4);
58462306a36Sopenharmony_ci				result_exponent -= 2;
58562306a36Sopenharmony_ci				break;
58662306a36Sopenharmony_ci			case 4:
58762306a36Sopenharmony_ci			case 5:
58862306a36Sopenharmony_ci			case 6:
58962306a36Sopenharmony_ci			case 7:
59062306a36Sopenharmony_ci				Dblext_leftshiftby1(resultp1,resultp2,resultp3,
59162306a36Sopenharmony_ci					resultp4);
59262306a36Sopenharmony_ci				result_exponent -= 1;
59362306a36Sopenharmony_ci				break;
59462306a36Sopenharmony_ci			}
59562306a36Sopenharmony_ci		} /* end if (hidden...)... */
59662306a36Sopenharmony_ci	/* Fall through and round */
59762306a36Sopenharmony_ci	} /* end if (save < 0)... */
59862306a36Sopenharmony_ci	else {
59962306a36Sopenharmony_ci		/* Add magnitudes */
60062306a36Sopenharmony_ci		Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
60162306a36Sopenharmony_ci			rightp1,rightp2,rightp3,rightp4,
60262306a36Sopenharmony_ci			/*to*/resultp1,resultp2,resultp3,resultp4);
60362306a36Sopenharmony_ci		sign_save = Dbl_signextendedsign(resultp1);
60462306a36Sopenharmony_ci		if (Dbl_isone_hiddenoverflow(resultp1)) {
60562306a36Sopenharmony_ci	    		/* Prenormalization required. */
60662306a36Sopenharmony_ci	    		Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
60762306a36Sopenharmony_ci				resultp4);
60862306a36Sopenharmony_ci	    		result_exponent++;
60962306a36Sopenharmony_ci		} /* end if hiddenoverflow... */
61062306a36Sopenharmony_ci	} /* end else ...add magnitudes... */
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci	/* Round the result.  If the extension and lower two words are
61362306a36Sopenharmony_ci	 * all zeros, then the result is exact.  Otherwise round in the
61462306a36Sopenharmony_ci	 * correct direction.  Underflow is possible. If a postnormalization
61562306a36Sopenharmony_ci	 * is necessary, then the mantissa is all zeros so no shift is needed.
61662306a36Sopenharmony_ci	 */
61762306a36Sopenharmony_ci  round:
61862306a36Sopenharmony_ci	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
61962306a36Sopenharmony_ci		Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
62062306a36Sopenharmony_ci			result_exponent,is_tiny);
62162306a36Sopenharmony_ci	}
62262306a36Sopenharmony_ci	Dbl_set_sign(resultp1,/*using*/sign_save);
62362306a36Sopenharmony_ci	if (Dblext_isnotzero_mantissap3(resultp3) ||
62462306a36Sopenharmony_ci	    Dblext_isnotzero_mantissap4(resultp4)) {
62562306a36Sopenharmony_ci		inexact = TRUE;
62662306a36Sopenharmony_ci		switch(Rounding_mode()) {
62762306a36Sopenharmony_ci		case ROUNDNEAREST: /* The default. */
62862306a36Sopenharmony_ci			if (Dblext_isone_highp3(resultp3)) {
62962306a36Sopenharmony_ci				/* at least 1/2 ulp */
63062306a36Sopenharmony_ci				if (Dblext_isnotzero_low31p3(resultp3) ||
63162306a36Sopenharmony_ci				    Dblext_isnotzero_mantissap4(resultp4) ||
63262306a36Sopenharmony_ci				    Dblext_isone_lowp2(resultp2)) {
63362306a36Sopenharmony_ci					/* either exactly half way and odd or
63462306a36Sopenharmony_ci					 * more than 1/2ulp */
63562306a36Sopenharmony_ci					Dbl_increment(resultp1,resultp2);
63662306a36Sopenharmony_ci				}
63762306a36Sopenharmony_ci			}
63862306a36Sopenharmony_ci	    		break;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci		case ROUNDPLUS:
64162306a36Sopenharmony_ci	    		if (Dbl_iszero_sign(resultp1)) {
64262306a36Sopenharmony_ci				/* Round up positive results */
64362306a36Sopenharmony_ci				Dbl_increment(resultp1,resultp2);
64462306a36Sopenharmony_ci			}
64562306a36Sopenharmony_ci			break;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci		case ROUNDMINUS:
64862306a36Sopenharmony_ci	    		if (Dbl_isone_sign(resultp1)) {
64962306a36Sopenharmony_ci				/* Round down negative results */
65062306a36Sopenharmony_ci				Dbl_increment(resultp1,resultp2);
65162306a36Sopenharmony_ci			}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci		case ROUNDZERO:;
65462306a36Sopenharmony_ci			/* truncate is simple */
65562306a36Sopenharmony_ci		} /* end switch... */
65662306a36Sopenharmony_ci		if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
65762306a36Sopenharmony_ci	}
65862306a36Sopenharmony_ci	if (result_exponent >= DBL_INFINITY_EXPONENT) {
65962306a36Sopenharmony_ci                /* trap if OVERFLOWTRAP enabled */
66062306a36Sopenharmony_ci                if (Is_overflowtrap_enabled()) {
66162306a36Sopenharmony_ci                        /*
66262306a36Sopenharmony_ci                         * Adjust bias of result
66362306a36Sopenharmony_ci                         */
66462306a36Sopenharmony_ci                        Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
66562306a36Sopenharmony_ci                        Dbl_copytoptr(resultp1,resultp2,dstptr);
66662306a36Sopenharmony_ci                        if (inexact)
66762306a36Sopenharmony_ci                            if (Is_inexacttrap_enabled())
66862306a36Sopenharmony_ci                                return (OPC_2E_OVERFLOWEXCEPTION |
66962306a36Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
67062306a36Sopenharmony_ci                            else Set_inexactflag();
67162306a36Sopenharmony_ci                        return (OPC_2E_OVERFLOWEXCEPTION);
67262306a36Sopenharmony_ci                }
67362306a36Sopenharmony_ci                inexact = TRUE;
67462306a36Sopenharmony_ci                Set_overflowflag();
67562306a36Sopenharmony_ci                /* set result to infinity or largest number */
67662306a36Sopenharmony_ci                Dbl_setoverflow(resultp1,resultp2);
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	} else if (result_exponent <= 0) {	/* underflow case */
67962306a36Sopenharmony_ci		if (Is_underflowtrap_enabled()) {
68062306a36Sopenharmony_ci                        /*
68162306a36Sopenharmony_ci                         * Adjust bias of result
68262306a36Sopenharmony_ci                         */
68362306a36Sopenharmony_ci                	Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
68462306a36Sopenharmony_ci			Dbl_copytoptr(resultp1,resultp2,dstptr);
68562306a36Sopenharmony_ci                        if (inexact)
68662306a36Sopenharmony_ci                            if (Is_inexacttrap_enabled())
68762306a36Sopenharmony_ci                                return (OPC_2E_UNDERFLOWEXCEPTION |
68862306a36Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
68962306a36Sopenharmony_ci                            else Set_inexactflag();
69062306a36Sopenharmony_ci	    		return(OPC_2E_UNDERFLOWEXCEPTION);
69162306a36Sopenharmony_ci		}
69262306a36Sopenharmony_ci		else if (inexact && is_tiny) Set_underflowflag();
69362306a36Sopenharmony_ci	}
69462306a36Sopenharmony_ci	else Dbl_set_exponent(resultp1,result_exponent);
69562306a36Sopenharmony_ci	Dbl_copytoptr(resultp1,resultp2,dstptr);
69662306a36Sopenharmony_ci	if (inexact)
69762306a36Sopenharmony_ci		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
69862306a36Sopenharmony_ci		else Set_inexactflag();
69962306a36Sopenharmony_ci    	return(NOEXCEPTION);
70062306a36Sopenharmony_ci}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci/*
70362306a36Sopenharmony_ci *  Double Floating-point Multiply Negate Fused Add
70462306a36Sopenharmony_ci */
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_cidbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_cidbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
70962306a36Sopenharmony_ciunsigned int *status;
71062306a36Sopenharmony_ci{
71162306a36Sopenharmony_ci	unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
71262306a36Sopenharmony_ci	register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
71362306a36Sopenharmony_ci	unsigned int rightp1, rightp2, rightp3, rightp4;
71462306a36Sopenharmony_ci	unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
71562306a36Sopenharmony_ci	register int mpy_exponent, add_exponent, count;
71662306a36Sopenharmony_ci	boolean inexact = FALSE, is_tiny = FALSE;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	unsigned int signlessleft1, signlessright1, save;
71962306a36Sopenharmony_ci	register int result_exponent, diff_exponent;
72062306a36Sopenharmony_ci	int sign_save, jumpsize;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
72362306a36Sopenharmony_ci	Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
72462306a36Sopenharmony_ci	Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	/*
72762306a36Sopenharmony_ci	 * set sign bit of result of multiply
72862306a36Sopenharmony_ci	 */
72962306a36Sopenharmony_ci	if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1))
73062306a36Sopenharmony_ci		Dbl_setzerop1(resultp1);
73162306a36Sopenharmony_ci	else
73262306a36Sopenharmony_ci		Dbl_setnegativezerop1(resultp1);
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_ci	/*
73562306a36Sopenharmony_ci	 * Generate multiply exponent
73662306a36Sopenharmony_ci	 */
73762306a36Sopenharmony_ci	mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	/*
74062306a36Sopenharmony_ci	 * check first operand for NaN's or infinity
74162306a36Sopenharmony_ci	 */
74262306a36Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd1p1)) {
74362306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
74462306a36Sopenharmony_ci			if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
74562306a36Sopenharmony_ci			    Dbl_isnotnan(opnd3p1,opnd3p2)) {
74662306a36Sopenharmony_ci				if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
74762306a36Sopenharmony_ci					/*
74862306a36Sopenharmony_ci					 * invalid since operands are infinity
74962306a36Sopenharmony_ci					 * and zero
75062306a36Sopenharmony_ci					 */
75162306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
75262306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
75362306a36Sopenharmony_ci					Set_invalidflag();
75462306a36Sopenharmony_ci					Dbl_makequietnan(resultp1,resultp2);
75562306a36Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
75662306a36Sopenharmony_ci					return(NOEXCEPTION);
75762306a36Sopenharmony_ci				}
75862306a36Sopenharmony_ci				/*
75962306a36Sopenharmony_ci				 * Check third operand for infinity with a
76062306a36Sopenharmony_ci				 *  sign opposite of the multiply result
76162306a36Sopenharmony_ci				 */
76262306a36Sopenharmony_ci				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
76362306a36Sopenharmony_ci				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
76462306a36Sopenharmony_ci					/*
76562306a36Sopenharmony_ci					 * invalid since attempting a magnitude
76662306a36Sopenharmony_ci					 * subtraction of infinities
76762306a36Sopenharmony_ci					 */
76862306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
76962306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
77062306a36Sopenharmony_ci					Set_invalidflag();
77162306a36Sopenharmony_ci					Dbl_makequietnan(resultp1,resultp2);
77262306a36Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
77362306a36Sopenharmony_ci					return(NOEXCEPTION);
77462306a36Sopenharmony_ci				}
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci				/*
77762306a36Sopenharmony_ci			 	 * return infinity
77862306a36Sopenharmony_ci			 	 */
77962306a36Sopenharmony_ci				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
78062306a36Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
78162306a36Sopenharmony_ci				return(NOEXCEPTION);
78262306a36Sopenharmony_ci			}
78362306a36Sopenharmony_ci		}
78462306a36Sopenharmony_ci		else {
78562306a36Sopenharmony_ci			/*
78662306a36Sopenharmony_ci		 	 * is NaN; signaling or quiet?
78762306a36Sopenharmony_ci		 	 */
78862306a36Sopenharmony_ci			if (Dbl_isone_signaling(opnd1p1)) {
78962306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
79062306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
79162306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
79262306a36Sopenharmony_ci				/* make NaN quiet */
79362306a36Sopenharmony_ci				Set_invalidflag();
79462306a36Sopenharmony_ci				Dbl_set_quiet(opnd1p1);
79562306a36Sopenharmony_ci			}
79662306a36Sopenharmony_ci			/*
79762306a36Sopenharmony_ci			 * is second operand a signaling NaN?
79862306a36Sopenharmony_ci			 */
79962306a36Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd2p1)) {
80062306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
80162306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
80262306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
80362306a36Sopenharmony_ci				/* make NaN quiet */
80462306a36Sopenharmony_ci				Set_invalidflag();
80562306a36Sopenharmony_ci				Dbl_set_quiet(opnd2p1);
80662306a36Sopenharmony_ci				Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
80762306a36Sopenharmony_ci				return(NOEXCEPTION);
80862306a36Sopenharmony_ci			}
80962306a36Sopenharmony_ci			/*
81062306a36Sopenharmony_ci			 * is third operand a signaling NaN?
81162306a36Sopenharmony_ci			 */
81262306a36Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd3p1)) {
81362306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
81462306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
81562306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
81662306a36Sopenharmony_ci				/* make NaN quiet */
81762306a36Sopenharmony_ci				Set_invalidflag();
81862306a36Sopenharmony_ci				Dbl_set_quiet(opnd3p1);
81962306a36Sopenharmony_ci				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
82062306a36Sopenharmony_ci				return(NOEXCEPTION);
82162306a36Sopenharmony_ci			}
82262306a36Sopenharmony_ci			/*
82362306a36Sopenharmony_ci		 	 * return quiet NaN
82462306a36Sopenharmony_ci		 	 */
82562306a36Sopenharmony_ci			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
82662306a36Sopenharmony_ci			return(NOEXCEPTION);
82762306a36Sopenharmony_ci		}
82862306a36Sopenharmony_ci	}
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	/*
83162306a36Sopenharmony_ci	 * check second operand for NaN's or infinity
83262306a36Sopenharmony_ci	 */
83362306a36Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd2p1)) {
83462306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
83562306a36Sopenharmony_ci			if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
83662306a36Sopenharmony_ci				if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
83762306a36Sopenharmony_ci					/*
83862306a36Sopenharmony_ci					 * invalid since multiply operands are
83962306a36Sopenharmony_ci					 * zero & infinity
84062306a36Sopenharmony_ci					 */
84162306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
84262306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
84362306a36Sopenharmony_ci					Set_invalidflag();
84462306a36Sopenharmony_ci					Dbl_makequietnan(opnd2p1,opnd2p2);
84562306a36Sopenharmony_ci					Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
84662306a36Sopenharmony_ci					return(NOEXCEPTION);
84762306a36Sopenharmony_ci				}
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci				/*
85062306a36Sopenharmony_ci				 * Check third operand for infinity with a
85162306a36Sopenharmony_ci				 *  sign opposite of the multiply result
85262306a36Sopenharmony_ci				 */
85362306a36Sopenharmony_ci				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
85462306a36Sopenharmony_ci				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
85562306a36Sopenharmony_ci					/*
85662306a36Sopenharmony_ci					 * invalid since attempting a magnitude
85762306a36Sopenharmony_ci					 * subtraction of infinities
85862306a36Sopenharmony_ci					 */
85962306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
86062306a36Sopenharmony_ci				       		return(OPC_2E_INVALIDEXCEPTION);
86162306a36Sopenharmony_ci				       	Set_invalidflag();
86262306a36Sopenharmony_ci				       	Dbl_makequietnan(resultp1,resultp2);
86362306a36Sopenharmony_ci					Dbl_copytoptr(resultp1,resultp2,dstptr);
86462306a36Sopenharmony_ci					return(NOEXCEPTION);
86562306a36Sopenharmony_ci				}
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci				/*
86862306a36Sopenharmony_ci				 * return infinity
86962306a36Sopenharmony_ci				 */
87062306a36Sopenharmony_ci				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
87162306a36Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
87262306a36Sopenharmony_ci				return(NOEXCEPTION);
87362306a36Sopenharmony_ci			}
87462306a36Sopenharmony_ci		}
87562306a36Sopenharmony_ci		else {
87662306a36Sopenharmony_ci			/*
87762306a36Sopenharmony_ci			 * is NaN; signaling or quiet?
87862306a36Sopenharmony_ci			 */
87962306a36Sopenharmony_ci			if (Dbl_isone_signaling(opnd2p1)) {
88062306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
88162306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
88262306a36Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
88362306a36Sopenharmony_ci				/* make NaN quiet */
88462306a36Sopenharmony_ci				Set_invalidflag();
88562306a36Sopenharmony_ci				Dbl_set_quiet(opnd2p1);
88662306a36Sopenharmony_ci			}
88762306a36Sopenharmony_ci			/*
88862306a36Sopenharmony_ci			 * is third operand a signaling NaN?
88962306a36Sopenharmony_ci			 */
89062306a36Sopenharmony_ci			else if (Dbl_is_signalingnan(opnd3p1)) {
89162306a36Sopenharmony_ci			       	/* trap if INVALIDTRAP enabled */
89262306a36Sopenharmony_ci			       	if (Is_invalidtrap_enabled())
89362306a36Sopenharmony_ci				   		return(OPC_2E_INVALIDEXCEPTION);
89462306a36Sopenharmony_ci			       	/* make NaN quiet */
89562306a36Sopenharmony_ci			       	Set_invalidflag();
89662306a36Sopenharmony_ci			       	Dbl_set_quiet(opnd3p1);
89762306a36Sopenharmony_ci				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
89862306a36Sopenharmony_ci		       		return(NOEXCEPTION);
89962306a36Sopenharmony_ci			}
90062306a36Sopenharmony_ci			/*
90162306a36Sopenharmony_ci			 * return quiet NaN
90262306a36Sopenharmony_ci			 */
90362306a36Sopenharmony_ci			Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
90462306a36Sopenharmony_ci			return(NOEXCEPTION);
90562306a36Sopenharmony_ci		}
90662306a36Sopenharmony_ci	}
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	/*
90962306a36Sopenharmony_ci	 * check third operand for NaN's or infinity
91062306a36Sopenharmony_ci	 */
91162306a36Sopenharmony_ci	if (Dbl_isinfinity_exponent(opnd3p1)) {
91262306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
91362306a36Sopenharmony_ci			/* return infinity */
91462306a36Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
91562306a36Sopenharmony_ci			return(NOEXCEPTION);
91662306a36Sopenharmony_ci		} else {
91762306a36Sopenharmony_ci			/*
91862306a36Sopenharmony_ci			 * is NaN; signaling or quiet?
91962306a36Sopenharmony_ci			 */
92062306a36Sopenharmony_ci			if (Dbl_isone_signaling(opnd3p1)) {
92162306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
92262306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
92362306a36Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
92462306a36Sopenharmony_ci				/* make NaN quiet */
92562306a36Sopenharmony_ci				Set_invalidflag();
92662306a36Sopenharmony_ci				Dbl_set_quiet(opnd3p1);
92762306a36Sopenharmony_ci			}
92862306a36Sopenharmony_ci			/*
92962306a36Sopenharmony_ci			 * return quiet NaN
93062306a36Sopenharmony_ci 			 */
93162306a36Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
93262306a36Sopenharmony_ci			return(NOEXCEPTION);
93362306a36Sopenharmony_ci		}
93462306a36Sopenharmony_ci    	}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	/*
93762306a36Sopenharmony_ci	 * Generate multiply mantissa
93862306a36Sopenharmony_ci	 */
93962306a36Sopenharmony_ci	if (Dbl_isnotzero_exponent(opnd1p1)) {
94062306a36Sopenharmony_ci		/* set hidden bit */
94162306a36Sopenharmony_ci		Dbl_clear_signexponent_set_hidden(opnd1p1);
94262306a36Sopenharmony_ci	}
94362306a36Sopenharmony_ci	else {
94462306a36Sopenharmony_ci		/* check for zero */
94562306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
94662306a36Sopenharmony_ci			/*
94762306a36Sopenharmony_ci			 * Perform the add opnd3 with zero here.
94862306a36Sopenharmony_ci			 */
94962306a36Sopenharmony_ci			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
95062306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
95162306a36Sopenharmony_ci					Dbl_or_signs(opnd3p1,resultp1);
95262306a36Sopenharmony_ci				} else {
95362306a36Sopenharmony_ci					Dbl_and_signs(opnd3p1,resultp1);
95462306a36Sopenharmony_ci				}
95562306a36Sopenharmony_ci			}
95662306a36Sopenharmony_ci			/*
95762306a36Sopenharmony_ci			 * Now let's check for trapped underflow case.
95862306a36Sopenharmony_ci			 */
95962306a36Sopenharmony_ci			else if (Dbl_iszero_exponent(opnd3p1) &&
96062306a36Sopenharmony_ci			         Is_underflowtrap_enabled()) {
96162306a36Sopenharmony_ci                    		/* need to normalize results mantissa */
96262306a36Sopenharmony_ci                    		sign_save = Dbl_signextendedsign(opnd3p1);
96362306a36Sopenharmony_ci				result_exponent = 0;
96462306a36Sopenharmony_ci                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
96562306a36Sopenharmony_ci                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
96662306a36Sopenharmony_ci                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
96762306a36Sopenharmony_ci                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
96862306a36Sopenharmony_ci							unfl);
96962306a36Sopenharmony_ci                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
97062306a36Sopenharmony_ci                    		/* inexact = FALSE */
97162306a36Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
97262306a36Sopenharmony_ci			}
97362306a36Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
97462306a36Sopenharmony_ci			return(NOEXCEPTION);
97562306a36Sopenharmony_ci		}
97662306a36Sopenharmony_ci		/* is denormalized, adjust exponent */
97762306a36Sopenharmony_ci		Dbl_clear_signexponent(opnd1p1);
97862306a36Sopenharmony_ci		Dbl_leftshiftby1(opnd1p1,opnd1p2);
97962306a36Sopenharmony_ci		Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
98062306a36Sopenharmony_ci	}
98162306a36Sopenharmony_ci	/* opnd2 needs to have hidden bit set with msb in hidden bit */
98262306a36Sopenharmony_ci	if (Dbl_isnotzero_exponent(opnd2p1)) {
98362306a36Sopenharmony_ci		Dbl_clear_signexponent_set_hidden(opnd2p1);
98462306a36Sopenharmony_ci	}
98562306a36Sopenharmony_ci	else {
98662306a36Sopenharmony_ci		/* check for zero */
98762306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
98862306a36Sopenharmony_ci			/*
98962306a36Sopenharmony_ci			 * Perform the add opnd3 with zero here.
99062306a36Sopenharmony_ci			 */
99162306a36Sopenharmony_ci			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
99262306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
99362306a36Sopenharmony_ci					Dbl_or_signs(opnd3p1,resultp1);
99462306a36Sopenharmony_ci				} else {
99562306a36Sopenharmony_ci					Dbl_and_signs(opnd3p1,resultp1);
99662306a36Sopenharmony_ci				}
99762306a36Sopenharmony_ci			}
99862306a36Sopenharmony_ci			/*
99962306a36Sopenharmony_ci			 * Now let's check for trapped underflow case.
100062306a36Sopenharmony_ci			 */
100162306a36Sopenharmony_ci			else if (Dbl_iszero_exponent(opnd3p1) &&
100262306a36Sopenharmony_ci			    Is_underflowtrap_enabled()) {
100362306a36Sopenharmony_ci                    		/* need to normalize results mantissa */
100462306a36Sopenharmony_ci                    		sign_save = Dbl_signextendedsign(opnd3p1);
100562306a36Sopenharmony_ci				result_exponent = 0;
100662306a36Sopenharmony_ci                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
100762306a36Sopenharmony_ci                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
100862306a36Sopenharmony_ci                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
100962306a36Sopenharmony_ci                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
101062306a36Sopenharmony_ci							unfl);
101162306a36Sopenharmony_ci                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
101262306a36Sopenharmony_ci                    		/* inexact = FALSE */
101362306a36Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
101462306a36Sopenharmony_ci			}
101562306a36Sopenharmony_ci			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
101662306a36Sopenharmony_ci			return(NOEXCEPTION);
101762306a36Sopenharmony_ci		}
101862306a36Sopenharmony_ci		/* is denormalized; want to normalize */
101962306a36Sopenharmony_ci		Dbl_clear_signexponent(opnd2p1);
102062306a36Sopenharmony_ci		Dbl_leftshiftby1(opnd2p1,opnd2p2);
102162306a36Sopenharmony_ci		Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
102262306a36Sopenharmony_ci	}
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	/* Multiply the first two source mantissas together */
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	/*
102762306a36Sopenharmony_ci	 * The intermediate result will be kept in tmpres,
102862306a36Sopenharmony_ci	 * which needs enough room for 106 bits of mantissa,
102962306a36Sopenharmony_ci	 * so lets call it a Double extended.
103062306a36Sopenharmony_ci	 */
103162306a36Sopenharmony_ci	Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	/*
103462306a36Sopenharmony_ci	 * Four bits at a time are inspected in each loop, and a
103562306a36Sopenharmony_ci	 * simple shift and add multiply algorithm is used.
103662306a36Sopenharmony_ci	 */
103762306a36Sopenharmony_ci	for (count = DBL_P-1; count >= 0; count -= 4) {
103862306a36Sopenharmony_ci		Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
103962306a36Sopenharmony_ci		if (Dbit28p2(opnd1p2)) {
104062306a36Sopenharmony_ci	 		/* Fourword_add should be an ADD followed by 3 ADDC's */
104162306a36Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
104262306a36Sopenharmony_ci			 opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
104362306a36Sopenharmony_ci		}
104462306a36Sopenharmony_ci		if (Dbit29p2(opnd1p2)) {
104562306a36Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
104662306a36Sopenharmony_ci			 opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
104762306a36Sopenharmony_ci		}
104862306a36Sopenharmony_ci		if (Dbit30p2(opnd1p2)) {
104962306a36Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
105062306a36Sopenharmony_ci			 opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
105162306a36Sopenharmony_ci		}
105262306a36Sopenharmony_ci		if (Dbit31p2(opnd1p2)) {
105362306a36Sopenharmony_ci			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
105462306a36Sopenharmony_ci			 opnd2p1, opnd2p2, 0, 0);
105562306a36Sopenharmony_ci		}
105662306a36Sopenharmony_ci		Dbl_rightshiftby4(opnd1p1,opnd1p2);
105762306a36Sopenharmony_ci	}
105862306a36Sopenharmony_ci	if (Is_dexthiddenoverflow(tmpresp1)) {
105962306a36Sopenharmony_ci		/* result mantissa >= 2 (mantissa overflow) */
106062306a36Sopenharmony_ci		mpy_exponent++;
106162306a36Sopenharmony_ci		Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
106262306a36Sopenharmony_ci	}
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	/*
106562306a36Sopenharmony_ci	 * Restore the sign of the mpy result which was saved in resultp1.
106662306a36Sopenharmony_ci	 * The exponent will continue to be kept in mpy_exponent.
106762306a36Sopenharmony_ci	 */
106862306a36Sopenharmony_ci	Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	/*
107162306a36Sopenharmony_ci	 * No rounding is required, since the result of the multiply
107262306a36Sopenharmony_ci	 * is exact in the extended format.
107362306a36Sopenharmony_ci	 */
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	/*
107662306a36Sopenharmony_ci	 * Now we are ready to perform the add portion of the operation.
107762306a36Sopenharmony_ci	 *
107862306a36Sopenharmony_ci	 * The exponents need to be kept as integers for now, since the
107962306a36Sopenharmony_ci	 * multiply result might not fit into the exponent field.  We
108062306a36Sopenharmony_ci	 * can't overflow or underflow because of this yet, since the
108162306a36Sopenharmony_ci	 * add could bring the final result back into range.
108262306a36Sopenharmony_ci	 */
108362306a36Sopenharmony_ci	add_exponent = Dbl_exponent(opnd3p1);
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	/*
108662306a36Sopenharmony_ci	 * Check for denormalized or zero add operand.
108762306a36Sopenharmony_ci	 */
108862306a36Sopenharmony_ci	if (add_exponent == 0) {
108962306a36Sopenharmony_ci		/* check for zero */
109062306a36Sopenharmony_ci		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
109162306a36Sopenharmony_ci			/* right is zero */
109262306a36Sopenharmony_ci			/* Left can't be zero and must be result.
109362306a36Sopenharmony_ci			 *
109462306a36Sopenharmony_ci			 * The final result is now in tmpres and mpy_exponent,
109562306a36Sopenharmony_ci			 * and needs to be rounded and squeezed back into
109662306a36Sopenharmony_ci			 * double precision format from double extended.
109762306a36Sopenharmony_ci			 */
109862306a36Sopenharmony_ci			result_exponent = mpy_exponent;
109962306a36Sopenharmony_ci			Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
110062306a36Sopenharmony_ci				resultp1,resultp2,resultp3,resultp4);
110162306a36Sopenharmony_ci			sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
110262306a36Sopenharmony_ci			goto round;
110362306a36Sopenharmony_ci		}
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci		/*
110662306a36Sopenharmony_ci		 * Neither are zeroes.
110762306a36Sopenharmony_ci		 * Adjust exponent and normalize add operand.
110862306a36Sopenharmony_ci		 */
110962306a36Sopenharmony_ci		sign_save = Dbl_signextendedsign(opnd3p1);	/* save sign */
111062306a36Sopenharmony_ci		Dbl_clear_signexponent(opnd3p1);
111162306a36Sopenharmony_ci		Dbl_leftshiftby1(opnd3p1,opnd3p2);
111262306a36Sopenharmony_ci		Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
111362306a36Sopenharmony_ci		Dbl_set_sign(opnd3p1,sign_save);	/* restore sign */
111462306a36Sopenharmony_ci	} else {
111562306a36Sopenharmony_ci		Dbl_clear_exponent_set_hidden(opnd3p1);
111662306a36Sopenharmony_ci	}
111762306a36Sopenharmony_ci	/*
111862306a36Sopenharmony_ci	 * Copy opnd3 to the double extended variable called right.
111962306a36Sopenharmony_ci	 */
112062306a36Sopenharmony_ci	Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	/*
112362306a36Sopenharmony_ci	 * A zero "save" helps discover equal operands (for later),
112462306a36Sopenharmony_ci	 * and is used in swapping operands (if needed).
112562306a36Sopenharmony_ci	 */
112662306a36Sopenharmony_ci	Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	/*
112962306a36Sopenharmony_ci	 * Compare magnitude of operands.
113062306a36Sopenharmony_ci	 */
113162306a36Sopenharmony_ci	Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
113262306a36Sopenharmony_ci	Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
113362306a36Sopenharmony_ci	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
113462306a36Sopenharmony_ci	    Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
113562306a36Sopenharmony_ci		/*
113662306a36Sopenharmony_ci		 * Set the left operand to the larger one by XOR swap.
113762306a36Sopenharmony_ci		 * First finish the first word "save".
113862306a36Sopenharmony_ci		 */
113962306a36Sopenharmony_ci		Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
114062306a36Sopenharmony_ci		Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
114162306a36Sopenharmony_ci		Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
114262306a36Sopenharmony_ci			rightp2,rightp3,rightp4);
114362306a36Sopenharmony_ci		/* also setup exponents used in rest of routine */
114462306a36Sopenharmony_ci		diff_exponent = add_exponent - mpy_exponent;
114562306a36Sopenharmony_ci		result_exponent = add_exponent;
114662306a36Sopenharmony_ci	} else {
114762306a36Sopenharmony_ci		/* also setup exponents used in rest of routine */
114862306a36Sopenharmony_ci		diff_exponent = mpy_exponent - add_exponent;
114962306a36Sopenharmony_ci		result_exponent = mpy_exponent;
115062306a36Sopenharmony_ci	}
115162306a36Sopenharmony_ci	/* Invariant: left is not smaller than right. */
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	/*
115462306a36Sopenharmony_ci	 * Special case alignment of operands that would force alignment
115562306a36Sopenharmony_ci	 * beyond the extent of the extension.  A further optimization
115662306a36Sopenharmony_ci	 * could special case this but only reduces the path length for
115762306a36Sopenharmony_ci	 * this infrequent case.
115862306a36Sopenharmony_ci	 */
115962306a36Sopenharmony_ci	if (diff_exponent > DBLEXT_THRESHOLD) {
116062306a36Sopenharmony_ci		diff_exponent = DBLEXT_THRESHOLD;
116162306a36Sopenharmony_ci	}
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	/* Align right operand by shifting it to the right */
116462306a36Sopenharmony_ci	Dblext_clear_sign(rightp1);
116562306a36Sopenharmony_ci	Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
116662306a36Sopenharmony_ci		/*shifted by*/diff_exponent);
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	/* Treat sum and difference of the operands separately. */
116962306a36Sopenharmony_ci	if ((int)save < 0) {
117062306a36Sopenharmony_ci		/*
117162306a36Sopenharmony_ci		 * Difference of the two operands.  Overflow can occur if the
117262306a36Sopenharmony_ci		 * multiply overflowed.  A borrow can occur out of the hidden
117362306a36Sopenharmony_ci		 * bit and force a post normalization phase.
117462306a36Sopenharmony_ci		 */
117562306a36Sopenharmony_ci		Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
117662306a36Sopenharmony_ci			rightp1,rightp2,rightp3,rightp4,
117762306a36Sopenharmony_ci			resultp1,resultp2,resultp3,resultp4);
117862306a36Sopenharmony_ci		sign_save = Dbl_signextendedsign(resultp1);
117962306a36Sopenharmony_ci		if (Dbl_iszero_hidden(resultp1)) {
118062306a36Sopenharmony_ci			/* Handle normalization */
118162306a36Sopenharmony_ci		/* A straightforward algorithm would now shift the
118262306a36Sopenharmony_ci		 * result and extension left until the hidden bit
118362306a36Sopenharmony_ci		 * becomes one.  Not all of the extension bits need
118462306a36Sopenharmony_ci		 * participate in the shift.  Only the two most
118562306a36Sopenharmony_ci		 * significant bits (round and guard) are needed.
118662306a36Sopenharmony_ci		 * If only a single shift is needed then the guard
118762306a36Sopenharmony_ci		 * bit becomes a significant low order bit and the
118862306a36Sopenharmony_ci		 * extension must participate in the rounding.
118962306a36Sopenharmony_ci		 * If more than a single shift is needed, then all
119062306a36Sopenharmony_ci		 * bits to the right of the guard bit are zeros,
119162306a36Sopenharmony_ci		 * and the guard bit may or may not be zero. */
119262306a36Sopenharmony_ci			Dblext_leftshiftby1(resultp1,resultp2,resultp3,
119362306a36Sopenharmony_ci				resultp4);
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci			/* Need to check for a zero result.  The sign and
119662306a36Sopenharmony_ci			 * exponent fields have already been zeroed.  The more
119762306a36Sopenharmony_ci			 * efficient test of the full object can be used.
119862306a36Sopenharmony_ci			 */
119962306a36Sopenharmony_ci			 if (Dblext_iszero(resultp1,resultp2,resultp3,resultp4)) {
120062306a36Sopenharmony_ci				/* Must have been "x-x" or "x+(-x)". */
120162306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS))
120262306a36Sopenharmony_ci					Dbl_setone_sign(resultp1);
120362306a36Sopenharmony_ci				Dbl_copytoptr(resultp1,resultp2,dstptr);
120462306a36Sopenharmony_ci				return(NOEXCEPTION);
120562306a36Sopenharmony_ci			}
120662306a36Sopenharmony_ci			result_exponent--;
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci			/* Look to see if normalization is finished. */
120962306a36Sopenharmony_ci			if (Dbl_isone_hidden(resultp1)) {
121062306a36Sopenharmony_ci				/* No further normalization is needed */
121162306a36Sopenharmony_ci				goto round;
121262306a36Sopenharmony_ci			}
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci			/* Discover first one bit to determine shift amount.
121562306a36Sopenharmony_ci			 * Use a modified binary search.  We have already
121662306a36Sopenharmony_ci			 * shifted the result one position right and still
121762306a36Sopenharmony_ci			 * not found a one so the remainder of the extension
121862306a36Sopenharmony_ci			 * must be zero and simplifies rounding. */
121962306a36Sopenharmony_ci			/* Scan bytes */
122062306a36Sopenharmony_ci			while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
122162306a36Sopenharmony_ci				Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
122262306a36Sopenharmony_ci				result_exponent -= 8;
122362306a36Sopenharmony_ci			}
122462306a36Sopenharmony_ci			/* Now narrow it down to the nibble */
122562306a36Sopenharmony_ci			if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
122662306a36Sopenharmony_ci				/* The lower nibble contains the
122762306a36Sopenharmony_ci				 * normalizing one */
122862306a36Sopenharmony_ci				Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
122962306a36Sopenharmony_ci				result_exponent -= 4;
123062306a36Sopenharmony_ci			}
123162306a36Sopenharmony_ci			/* Select case where first bit is set (already
123262306a36Sopenharmony_ci			 * normalized) otherwise select the proper shift. */
123362306a36Sopenharmony_ci			jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
123462306a36Sopenharmony_ci			if (jumpsize <= 7) switch(jumpsize) {
123562306a36Sopenharmony_ci			case 1:
123662306a36Sopenharmony_ci				Dblext_leftshiftby3(resultp1,resultp2,resultp3,
123762306a36Sopenharmony_ci					resultp4);
123862306a36Sopenharmony_ci				result_exponent -= 3;
123962306a36Sopenharmony_ci				break;
124062306a36Sopenharmony_ci			case 2:
124162306a36Sopenharmony_ci			case 3:
124262306a36Sopenharmony_ci				Dblext_leftshiftby2(resultp1,resultp2,resultp3,
124362306a36Sopenharmony_ci					resultp4);
124462306a36Sopenharmony_ci				result_exponent -= 2;
124562306a36Sopenharmony_ci				break;
124662306a36Sopenharmony_ci			case 4:
124762306a36Sopenharmony_ci			case 5:
124862306a36Sopenharmony_ci			case 6:
124962306a36Sopenharmony_ci			case 7:
125062306a36Sopenharmony_ci				Dblext_leftshiftby1(resultp1,resultp2,resultp3,
125162306a36Sopenharmony_ci					resultp4);
125262306a36Sopenharmony_ci				result_exponent -= 1;
125362306a36Sopenharmony_ci				break;
125462306a36Sopenharmony_ci			}
125562306a36Sopenharmony_ci		} /* end if (hidden...)... */
125662306a36Sopenharmony_ci	/* Fall through and round */
125762306a36Sopenharmony_ci	} /* end if (save < 0)... */
125862306a36Sopenharmony_ci	else {
125962306a36Sopenharmony_ci		/* Add magnitudes */
126062306a36Sopenharmony_ci		Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
126162306a36Sopenharmony_ci			rightp1,rightp2,rightp3,rightp4,
126262306a36Sopenharmony_ci			/*to*/resultp1,resultp2,resultp3,resultp4);
126362306a36Sopenharmony_ci		sign_save = Dbl_signextendedsign(resultp1);
126462306a36Sopenharmony_ci		if (Dbl_isone_hiddenoverflow(resultp1)) {
126562306a36Sopenharmony_ci	    		/* Prenormalization required. */
126662306a36Sopenharmony_ci	    		Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
126762306a36Sopenharmony_ci				resultp4);
126862306a36Sopenharmony_ci	    		result_exponent++;
126962306a36Sopenharmony_ci		} /* end if hiddenoverflow... */
127062306a36Sopenharmony_ci	} /* end else ...add magnitudes... */
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	/* Round the result.  If the extension and lower two words are
127362306a36Sopenharmony_ci	 * all zeros, then the result is exact.  Otherwise round in the
127462306a36Sopenharmony_ci	 * correct direction.  Underflow is possible. If a postnormalization
127562306a36Sopenharmony_ci	 * is necessary, then the mantissa is all zeros so no shift is needed.
127662306a36Sopenharmony_ci	 */
127762306a36Sopenharmony_ci  round:
127862306a36Sopenharmony_ci	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
127962306a36Sopenharmony_ci		Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
128062306a36Sopenharmony_ci			result_exponent,is_tiny);
128162306a36Sopenharmony_ci	}
128262306a36Sopenharmony_ci	Dbl_set_sign(resultp1,/*using*/sign_save);
128362306a36Sopenharmony_ci	if (Dblext_isnotzero_mantissap3(resultp3) ||
128462306a36Sopenharmony_ci	    Dblext_isnotzero_mantissap4(resultp4)) {
128562306a36Sopenharmony_ci		inexact = TRUE;
128662306a36Sopenharmony_ci		switch(Rounding_mode()) {
128762306a36Sopenharmony_ci		case ROUNDNEAREST: /* The default. */
128862306a36Sopenharmony_ci			if (Dblext_isone_highp3(resultp3)) {
128962306a36Sopenharmony_ci				/* at least 1/2 ulp */
129062306a36Sopenharmony_ci				if (Dblext_isnotzero_low31p3(resultp3) ||
129162306a36Sopenharmony_ci				    Dblext_isnotzero_mantissap4(resultp4) ||
129262306a36Sopenharmony_ci				    Dblext_isone_lowp2(resultp2)) {
129362306a36Sopenharmony_ci					/* either exactly half way and odd or
129462306a36Sopenharmony_ci					 * more than 1/2ulp */
129562306a36Sopenharmony_ci					Dbl_increment(resultp1,resultp2);
129662306a36Sopenharmony_ci				}
129762306a36Sopenharmony_ci			}
129862306a36Sopenharmony_ci	    		break;
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_ci		case ROUNDPLUS:
130162306a36Sopenharmony_ci	    		if (Dbl_iszero_sign(resultp1)) {
130262306a36Sopenharmony_ci				/* Round up positive results */
130362306a36Sopenharmony_ci				Dbl_increment(resultp1,resultp2);
130462306a36Sopenharmony_ci			}
130562306a36Sopenharmony_ci			break;
130662306a36Sopenharmony_ci
130762306a36Sopenharmony_ci		case ROUNDMINUS:
130862306a36Sopenharmony_ci	    		if (Dbl_isone_sign(resultp1)) {
130962306a36Sopenharmony_ci				/* Round down negative results */
131062306a36Sopenharmony_ci				Dbl_increment(resultp1,resultp2);
131162306a36Sopenharmony_ci			}
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ci		case ROUNDZERO:;
131462306a36Sopenharmony_ci			/* truncate is simple */
131562306a36Sopenharmony_ci		} /* end switch... */
131662306a36Sopenharmony_ci		if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
131762306a36Sopenharmony_ci	}
131862306a36Sopenharmony_ci	if (result_exponent >= DBL_INFINITY_EXPONENT) {
131962306a36Sopenharmony_ci		/* Overflow */
132062306a36Sopenharmony_ci		if (Is_overflowtrap_enabled()) {
132162306a36Sopenharmony_ci                        /*
132262306a36Sopenharmony_ci                         * Adjust bias of result
132362306a36Sopenharmony_ci                         */
132462306a36Sopenharmony_ci                        Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
132562306a36Sopenharmony_ci                        Dbl_copytoptr(resultp1,resultp2,dstptr);
132662306a36Sopenharmony_ci                        if (inexact)
132762306a36Sopenharmony_ci                            if (Is_inexacttrap_enabled())
132862306a36Sopenharmony_ci                                return (OPC_2E_OVERFLOWEXCEPTION |
132962306a36Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
133062306a36Sopenharmony_ci                            else Set_inexactflag();
133162306a36Sopenharmony_ci                        return (OPC_2E_OVERFLOWEXCEPTION);
133262306a36Sopenharmony_ci		}
133362306a36Sopenharmony_ci		inexact = TRUE;
133462306a36Sopenharmony_ci		Set_overflowflag();
133562306a36Sopenharmony_ci		Dbl_setoverflow(resultp1,resultp2);
133662306a36Sopenharmony_ci	} else if (result_exponent <= 0) {	/* underflow case */
133762306a36Sopenharmony_ci		if (Is_underflowtrap_enabled()) {
133862306a36Sopenharmony_ci                        /*
133962306a36Sopenharmony_ci                         * Adjust bias of result
134062306a36Sopenharmony_ci                         */
134162306a36Sopenharmony_ci                	Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
134262306a36Sopenharmony_ci			Dbl_copytoptr(resultp1,resultp2,dstptr);
134362306a36Sopenharmony_ci                        if (inexact)
134462306a36Sopenharmony_ci                            if (Is_inexacttrap_enabled())
134562306a36Sopenharmony_ci                                return (OPC_2E_UNDERFLOWEXCEPTION |
134662306a36Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
134762306a36Sopenharmony_ci                            else Set_inexactflag();
134862306a36Sopenharmony_ci	    		return(OPC_2E_UNDERFLOWEXCEPTION);
134962306a36Sopenharmony_ci		}
135062306a36Sopenharmony_ci		else if (inexact && is_tiny) Set_underflowflag();
135162306a36Sopenharmony_ci	}
135262306a36Sopenharmony_ci	else Dbl_set_exponent(resultp1,result_exponent);
135362306a36Sopenharmony_ci	Dbl_copytoptr(resultp1,resultp2,dstptr);
135462306a36Sopenharmony_ci	if (inexact)
135562306a36Sopenharmony_ci		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
135662306a36Sopenharmony_ci		else Set_inexactflag();
135762306a36Sopenharmony_ci    	return(NOEXCEPTION);
135862306a36Sopenharmony_ci}
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci/*
136162306a36Sopenharmony_ci *  Single Floating-point Multiply Fused Add
136262306a36Sopenharmony_ci */
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_cisgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_cisgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
136762306a36Sopenharmony_ciunsigned int *status;
136862306a36Sopenharmony_ci{
136962306a36Sopenharmony_ci	unsigned int opnd1, opnd2, opnd3;
137062306a36Sopenharmony_ci	register unsigned int tmpresp1, tmpresp2;
137162306a36Sopenharmony_ci	unsigned int rightp1, rightp2;
137262306a36Sopenharmony_ci	unsigned int resultp1, resultp2 = 0;
137362306a36Sopenharmony_ci	register int mpy_exponent, add_exponent, count;
137462306a36Sopenharmony_ci	boolean inexact = FALSE, is_tiny = FALSE;
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_ci	unsigned int signlessleft1, signlessright1, save;
137762306a36Sopenharmony_ci	register int result_exponent, diff_exponent;
137862306a36Sopenharmony_ci	int sign_save, jumpsize;
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	Sgl_copyfromptr(src1ptr,opnd1);
138162306a36Sopenharmony_ci	Sgl_copyfromptr(src2ptr,opnd2);
138262306a36Sopenharmony_ci	Sgl_copyfromptr(src3ptr,opnd3);
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_ci	/*
138562306a36Sopenharmony_ci	 * set sign bit of result of multiply
138662306a36Sopenharmony_ci	 */
138762306a36Sopenharmony_ci	if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2))
138862306a36Sopenharmony_ci		Sgl_setnegativezero(resultp1);
138962306a36Sopenharmony_ci	else Sgl_setzero(resultp1);
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci	/*
139262306a36Sopenharmony_ci	 * Generate multiply exponent
139362306a36Sopenharmony_ci	 */
139462306a36Sopenharmony_ci	mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	/*
139762306a36Sopenharmony_ci	 * check first operand for NaN's or infinity
139862306a36Sopenharmony_ci	 */
139962306a36Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd1)) {
140062306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd1)) {
140162306a36Sopenharmony_ci			if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
140262306a36Sopenharmony_ci				if (Sgl_iszero_exponentmantissa(opnd2)) {
140362306a36Sopenharmony_ci					/*
140462306a36Sopenharmony_ci					 * invalid since operands are infinity
140562306a36Sopenharmony_ci					 * and zero
140662306a36Sopenharmony_ci					 */
140762306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
140862306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
140962306a36Sopenharmony_ci					Set_invalidflag();
141062306a36Sopenharmony_ci					Sgl_makequietnan(resultp1);
141162306a36Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
141262306a36Sopenharmony_ci					return(NOEXCEPTION);
141362306a36Sopenharmony_ci				}
141462306a36Sopenharmony_ci				/*
141562306a36Sopenharmony_ci				 * Check third operand for infinity with a
141662306a36Sopenharmony_ci				 *  sign opposite of the multiply result
141762306a36Sopenharmony_ci				 */
141862306a36Sopenharmony_ci				if (Sgl_isinfinity(opnd3) &&
141962306a36Sopenharmony_ci				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
142062306a36Sopenharmony_ci					/*
142162306a36Sopenharmony_ci					 * invalid since attempting a magnitude
142262306a36Sopenharmony_ci					 * subtraction of infinities
142362306a36Sopenharmony_ci					 */
142462306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
142562306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
142662306a36Sopenharmony_ci					Set_invalidflag();
142762306a36Sopenharmony_ci					Sgl_makequietnan(resultp1);
142862306a36Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
142962306a36Sopenharmony_ci					return(NOEXCEPTION);
143062306a36Sopenharmony_ci				}
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci				/*
143362306a36Sopenharmony_ci			 	 * return infinity
143462306a36Sopenharmony_ci			 	 */
143562306a36Sopenharmony_ci				Sgl_setinfinity_exponentmantissa(resultp1);
143662306a36Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
143762306a36Sopenharmony_ci				return(NOEXCEPTION);
143862306a36Sopenharmony_ci			}
143962306a36Sopenharmony_ci		}
144062306a36Sopenharmony_ci		else {
144162306a36Sopenharmony_ci			/*
144262306a36Sopenharmony_ci		 	 * is NaN; signaling or quiet?
144362306a36Sopenharmony_ci		 	 */
144462306a36Sopenharmony_ci			if (Sgl_isone_signaling(opnd1)) {
144562306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
144662306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
144762306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
144862306a36Sopenharmony_ci				/* make NaN quiet */
144962306a36Sopenharmony_ci				Set_invalidflag();
145062306a36Sopenharmony_ci				Sgl_set_quiet(opnd1);
145162306a36Sopenharmony_ci			}
145262306a36Sopenharmony_ci			/*
145362306a36Sopenharmony_ci			 * is second operand a signaling NaN?
145462306a36Sopenharmony_ci			 */
145562306a36Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd2)) {
145662306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
145762306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
145862306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
145962306a36Sopenharmony_ci				/* make NaN quiet */
146062306a36Sopenharmony_ci				Set_invalidflag();
146162306a36Sopenharmony_ci				Sgl_set_quiet(opnd2);
146262306a36Sopenharmony_ci				Sgl_copytoptr(opnd2,dstptr);
146362306a36Sopenharmony_ci				return(NOEXCEPTION);
146462306a36Sopenharmony_ci			}
146562306a36Sopenharmony_ci			/*
146662306a36Sopenharmony_ci			 * is third operand a signaling NaN?
146762306a36Sopenharmony_ci			 */
146862306a36Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd3)) {
146962306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
147062306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
147162306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
147262306a36Sopenharmony_ci				/* make NaN quiet */
147362306a36Sopenharmony_ci				Set_invalidflag();
147462306a36Sopenharmony_ci				Sgl_set_quiet(opnd3);
147562306a36Sopenharmony_ci				Sgl_copytoptr(opnd3,dstptr);
147662306a36Sopenharmony_ci				return(NOEXCEPTION);
147762306a36Sopenharmony_ci			}
147862306a36Sopenharmony_ci			/*
147962306a36Sopenharmony_ci		 	 * return quiet NaN
148062306a36Sopenharmony_ci		 	 */
148162306a36Sopenharmony_ci			Sgl_copytoptr(opnd1,dstptr);
148262306a36Sopenharmony_ci			return(NOEXCEPTION);
148362306a36Sopenharmony_ci		}
148462306a36Sopenharmony_ci	}
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_ci	/*
148762306a36Sopenharmony_ci	 * check second operand for NaN's or infinity
148862306a36Sopenharmony_ci	 */
148962306a36Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd2)) {
149062306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd2)) {
149162306a36Sopenharmony_ci			if (Sgl_isnotnan(opnd3)) {
149262306a36Sopenharmony_ci				if (Sgl_iszero_exponentmantissa(opnd1)) {
149362306a36Sopenharmony_ci					/*
149462306a36Sopenharmony_ci					 * invalid since multiply operands are
149562306a36Sopenharmony_ci					 * zero & infinity
149662306a36Sopenharmony_ci					 */
149762306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
149862306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
149962306a36Sopenharmony_ci					Set_invalidflag();
150062306a36Sopenharmony_ci					Sgl_makequietnan(opnd2);
150162306a36Sopenharmony_ci					Sgl_copytoptr(opnd2,dstptr);
150262306a36Sopenharmony_ci					return(NOEXCEPTION);
150362306a36Sopenharmony_ci				}
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci				/*
150662306a36Sopenharmony_ci				 * Check third operand for infinity with a
150762306a36Sopenharmony_ci				 *  sign opposite of the multiply result
150862306a36Sopenharmony_ci				 */
150962306a36Sopenharmony_ci				if (Sgl_isinfinity(opnd3) &&
151062306a36Sopenharmony_ci				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
151162306a36Sopenharmony_ci					/*
151262306a36Sopenharmony_ci					 * invalid since attempting a magnitude
151362306a36Sopenharmony_ci					 * subtraction of infinities
151462306a36Sopenharmony_ci					 */
151562306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
151662306a36Sopenharmony_ci				       		return(OPC_2E_INVALIDEXCEPTION);
151762306a36Sopenharmony_ci				       	Set_invalidflag();
151862306a36Sopenharmony_ci				       	Sgl_makequietnan(resultp1);
151962306a36Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
152062306a36Sopenharmony_ci					return(NOEXCEPTION);
152162306a36Sopenharmony_ci				}
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci				/*
152462306a36Sopenharmony_ci				 * return infinity
152562306a36Sopenharmony_ci				 */
152662306a36Sopenharmony_ci				Sgl_setinfinity_exponentmantissa(resultp1);
152762306a36Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
152862306a36Sopenharmony_ci				return(NOEXCEPTION);
152962306a36Sopenharmony_ci			}
153062306a36Sopenharmony_ci		}
153162306a36Sopenharmony_ci		else {
153262306a36Sopenharmony_ci			/*
153362306a36Sopenharmony_ci			 * is NaN; signaling or quiet?
153462306a36Sopenharmony_ci			 */
153562306a36Sopenharmony_ci			if (Sgl_isone_signaling(opnd2)) {
153662306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
153762306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
153862306a36Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
153962306a36Sopenharmony_ci				/* make NaN quiet */
154062306a36Sopenharmony_ci				Set_invalidflag();
154162306a36Sopenharmony_ci				Sgl_set_quiet(opnd2);
154262306a36Sopenharmony_ci			}
154362306a36Sopenharmony_ci			/*
154462306a36Sopenharmony_ci			 * is third operand a signaling NaN?
154562306a36Sopenharmony_ci			 */
154662306a36Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd3)) {
154762306a36Sopenharmony_ci			       	/* trap if INVALIDTRAP enabled */
154862306a36Sopenharmony_ci			       	if (Is_invalidtrap_enabled())
154962306a36Sopenharmony_ci				   		return(OPC_2E_INVALIDEXCEPTION);
155062306a36Sopenharmony_ci			       	/* make NaN quiet */
155162306a36Sopenharmony_ci			       	Set_invalidflag();
155262306a36Sopenharmony_ci			       	Sgl_set_quiet(opnd3);
155362306a36Sopenharmony_ci				Sgl_copytoptr(opnd3,dstptr);
155462306a36Sopenharmony_ci		       		return(NOEXCEPTION);
155562306a36Sopenharmony_ci			}
155662306a36Sopenharmony_ci			/*
155762306a36Sopenharmony_ci			 * return quiet NaN
155862306a36Sopenharmony_ci			 */
155962306a36Sopenharmony_ci			Sgl_copytoptr(opnd2,dstptr);
156062306a36Sopenharmony_ci			return(NOEXCEPTION);
156162306a36Sopenharmony_ci		}
156262306a36Sopenharmony_ci	}
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	/*
156562306a36Sopenharmony_ci	 * check third operand for NaN's or infinity
156662306a36Sopenharmony_ci	 */
156762306a36Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd3)) {
156862306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd3)) {
156962306a36Sopenharmony_ci			/* return infinity */
157062306a36Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
157162306a36Sopenharmony_ci			return(NOEXCEPTION);
157262306a36Sopenharmony_ci		} else {
157362306a36Sopenharmony_ci			/*
157462306a36Sopenharmony_ci			 * is NaN; signaling or quiet?
157562306a36Sopenharmony_ci			 */
157662306a36Sopenharmony_ci			if (Sgl_isone_signaling(opnd3)) {
157762306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
157862306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
157962306a36Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
158062306a36Sopenharmony_ci				/* make NaN quiet */
158162306a36Sopenharmony_ci				Set_invalidflag();
158262306a36Sopenharmony_ci				Sgl_set_quiet(opnd3);
158362306a36Sopenharmony_ci			}
158462306a36Sopenharmony_ci			/*
158562306a36Sopenharmony_ci			 * return quiet NaN
158662306a36Sopenharmony_ci 			 */
158762306a36Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
158862306a36Sopenharmony_ci			return(NOEXCEPTION);
158962306a36Sopenharmony_ci		}
159062306a36Sopenharmony_ci    	}
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci	/*
159362306a36Sopenharmony_ci	 * Generate multiply mantissa
159462306a36Sopenharmony_ci	 */
159562306a36Sopenharmony_ci	if (Sgl_isnotzero_exponent(opnd1)) {
159662306a36Sopenharmony_ci		/* set hidden bit */
159762306a36Sopenharmony_ci		Sgl_clear_signexponent_set_hidden(opnd1);
159862306a36Sopenharmony_ci	}
159962306a36Sopenharmony_ci	else {
160062306a36Sopenharmony_ci		/* check for zero */
160162306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd1)) {
160262306a36Sopenharmony_ci			/*
160362306a36Sopenharmony_ci			 * Perform the add opnd3 with zero here.
160462306a36Sopenharmony_ci			 */
160562306a36Sopenharmony_ci			if (Sgl_iszero_exponentmantissa(opnd3)) {
160662306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
160762306a36Sopenharmony_ci					Sgl_or_signs(opnd3,resultp1);
160862306a36Sopenharmony_ci				} else {
160962306a36Sopenharmony_ci					Sgl_and_signs(opnd3,resultp1);
161062306a36Sopenharmony_ci				}
161162306a36Sopenharmony_ci			}
161262306a36Sopenharmony_ci			/*
161362306a36Sopenharmony_ci			 * Now let's check for trapped underflow case.
161462306a36Sopenharmony_ci			 */
161562306a36Sopenharmony_ci			else if (Sgl_iszero_exponent(opnd3) &&
161662306a36Sopenharmony_ci			         Is_underflowtrap_enabled()) {
161762306a36Sopenharmony_ci                    		/* need to normalize results mantissa */
161862306a36Sopenharmony_ci                    		sign_save = Sgl_signextendedsign(opnd3);
161962306a36Sopenharmony_ci				result_exponent = 0;
162062306a36Sopenharmony_ci                    		Sgl_leftshiftby1(opnd3);
162162306a36Sopenharmony_ci                    		Sgl_normalize(opnd3,result_exponent);
162262306a36Sopenharmony_ci                    		Sgl_set_sign(opnd3,/*using*/sign_save);
162362306a36Sopenharmony_ci                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
162462306a36Sopenharmony_ci							unfl);
162562306a36Sopenharmony_ci                    		Sgl_copytoptr(opnd3,dstptr);
162662306a36Sopenharmony_ci                    		/* inexact = FALSE */
162762306a36Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
162862306a36Sopenharmony_ci			}
162962306a36Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
163062306a36Sopenharmony_ci			return(NOEXCEPTION);
163162306a36Sopenharmony_ci		}
163262306a36Sopenharmony_ci		/* is denormalized, adjust exponent */
163362306a36Sopenharmony_ci		Sgl_clear_signexponent(opnd1);
163462306a36Sopenharmony_ci		Sgl_leftshiftby1(opnd1);
163562306a36Sopenharmony_ci		Sgl_normalize(opnd1,mpy_exponent);
163662306a36Sopenharmony_ci	}
163762306a36Sopenharmony_ci	/* opnd2 needs to have hidden bit set with msb in hidden bit */
163862306a36Sopenharmony_ci	if (Sgl_isnotzero_exponent(opnd2)) {
163962306a36Sopenharmony_ci		Sgl_clear_signexponent_set_hidden(opnd2);
164062306a36Sopenharmony_ci	}
164162306a36Sopenharmony_ci	else {
164262306a36Sopenharmony_ci		/* check for zero */
164362306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd2)) {
164462306a36Sopenharmony_ci			/*
164562306a36Sopenharmony_ci			 * Perform the add opnd3 with zero here.
164662306a36Sopenharmony_ci			 */
164762306a36Sopenharmony_ci			if (Sgl_iszero_exponentmantissa(opnd3)) {
164862306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
164962306a36Sopenharmony_ci					Sgl_or_signs(opnd3,resultp1);
165062306a36Sopenharmony_ci				} else {
165162306a36Sopenharmony_ci					Sgl_and_signs(opnd3,resultp1);
165262306a36Sopenharmony_ci				}
165362306a36Sopenharmony_ci			}
165462306a36Sopenharmony_ci			/*
165562306a36Sopenharmony_ci			 * Now let's check for trapped underflow case.
165662306a36Sopenharmony_ci			 */
165762306a36Sopenharmony_ci			else if (Sgl_iszero_exponent(opnd3) &&
165862306a36Sopenharmony_ci			    Is_underflowtrap_enabled()) {
165962306a36Sopenharmony_ci                    		/* need to normalize results mantissa */
166062306a36Sopenharmony_ci                    		sign_save = Sgl_signextendedsign(opnd3);
166162306a36Sopenharmony_ci				result_exponent = 0;
166262306a36Sopenharmony_ci                    		Sgl_leftshiftby1(opnd3);
166362306a36Sopenharmony_ci                    		Sgl_normalize(opnd3,result_exponent);
166462306a36Sopenharmony_ci                    		Sgl_set_sign(opnd3,/*using*/sign_save);
166562306a36Sopenharmony_ci                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
166662306a36Sopenharmony_ci							unfl);
166762306a36Sopenharmony_ci                    		Sgl_copytoptr(opnd3,dstptr);
166862306a36Sopenharmony_ci                    		/* inexact = FALSE */
166962306a36Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
167062306a36Sopenharmony_ci			}
167162306a36Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
167262306a36Sopenharmony_ci			return(NOEXCEPTION);
167362306a36Sopenharmony_ci		}
167462306a36Sopenharmony_ci		/* is denormalized; want to normalize */
167562306a36Sopenharmony_ci		Sgl_clear_signexponent(opnd2);
167662306a36Sopenharmony_ci		Sgl_leftshiftby1(opnd2);
167762306a36Sopenharmony_ci		Sgl_normalize(opnd2,mpy_exponent);
167862306a36Sopenharmony_ci	}
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_ci	/* Multiply the first two source mantissas together */
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	/*
168362306a36Sopenharmony_ci	 * The intermediate result will be kept in tmpres,
168462306a36Sopenharmony_ci	 * which needs enough room for 106 bits of mantissa,
168562306a36Sopenharmony_ci	 * so lets call it a Double extended.
168662306a36Sopenharmony_ci	 */
168762306a36Sopenharmony_ci	Sglext_setzero(tmpresp1,tmpresp2);
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci	/*
169062306a36Sopenharmony_ci	 * Four bits at a time are inspected in each loop, and a
169162306a36Sopenharmony_ci	 * simple shift and add multiply algorithm is used.
169262306a36Sopenharmony_ci	 */
169362306a36Sopenharmony_ci	for (count = SGL_P-1; count >= 0; count -= 4) {
169462306a36Sopenharmony_ci		Sglext_rightshiftby4(tmpresp1,tmpresp2);
169562306a36Sopenharmony_ci		if (Sbit28(opnd1)) {
169662306a36Sopenharmony_ci	 		/* Twoword_add should be an ADD followed by 2 ADDC's */
169762306a36Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
169862306a36Sopenharmony_ci		}
169962306a36Sopenharmony_ci		if (Sbit29(opnd1)) {
170062306a36Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
170162306a36Sopenharmony_ci		}
170262306a36Sopenharmony_ci		if (Sbit30(opnd1)) {
170362306a36Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
170462306a36Sopenharmony_ci		}
170562306a36Sopenharmony_ci		if (Sbit31(opnd1)) {
170662306a36Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
170762306a36Sopenharmony_ci		}
170862306a36Sopenharmony_ci		Sgl_rightshiftby4(opnd1);
170962306a36Sopenharmony_ci	}
171062306a36Sopenharmony_ci	if (Is_sexthiddenoverflow(tmpresp1)) {
171162306a36Sopenharmony_ci		/* result mantissa >= 2 (mantissa overflow) */
171262306a36Sopenharmony_ci		mpy_exponent++;
171362306a36Sopenharmony_ci		Sglext_rightshiftby4(tmpresp1,tmpresp2);
171462306a36Sopenharmony_ci	} else {
171562306a36Sopenharmony_ci		Sglext_rightshiftby3(tmpresp1,tmpresp2);
171662306a36Sopenharmony_ci	}
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci	/*
171962306a36Sopenharmony_ci	 * Restore the sign of the mpy result which was saved in resultp1.
172062306a36Sopenharmony_ci	 * The exponent will continue to be kept in mpy_exponent.
172162306a36Sopenharmony_ci	 */
172262306a36Sopenharmony_ci	Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	/*
172562306a36Sopenharmony_ci	 * No rounding is required, since the result of the multiply
172662306a36Sopenharmony_ci	 * is exact in the extended format.
172762306a36Sopenharmony_ci	 */
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	/*
173062306a36Sopenharmony_ci	 * Now we are ready to perform the add portion of the operation.
173162306a36Sopenharmony_ci	 *
173262306a36Sopenharmony_ci	 * The exponents need to be kept as integers for now, since the
173362306a36Sopenharmony_ci	 * multiply result might not fit into the exponent field.  We
173462306a36Sopenharmony_ci	 * can't overflow or underflow because of this yet, since the
173562306a36Sopenharmony_ci	 * add could bring the final result back into range.
173662306a36Sopenharmony_ci	 */
173762306a36Sopenharmony_ci	add_exponent = Sgl_exponent(opnd3);
173862306a36Sopenharmony_ci
173962306a36Sopenharmony_ci	/*
174062306a36Sopenharmony_ci	 * Check for denormalized or zero add operand.
174162306a36Sopenharmony_ci	 */
174262306a36Sopenharmony_ci	if (add_exponent == 0) {
174362306a36Sopenharmony_ci		/* check for zero */
174462306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd3)) {
174562306a36Sopenharmony_ci			/* right is zero */
174662306a36Sopenharmony_ci			/* Left can't be zero and must be result.
174762306a36Sopenharmony_ci			 *
174862306a36Sopenharmony_ci			 * The final result is now in tmpres and mpy_exponent,
174962306a36Sopenharmony_ci			 * and needs to be rounded and squeezed back into
175062306a36Sopenharmony_ci			 * double precision format from double extended.
175162306a36Sopenharmony_ci			 */
175262306a36Sopenharmony_ci			result_exponent = mpy_exponent;
175362306a36Sopenharmony_ci			Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
175462306a36Sopenharmony_ci			sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
175562306a36Sopenharmony_ci			goto round;
175662306a36Sopenharmony_ci		}
175762306a36Sopenharmony_ci
175862306a36Sopenharmony_ci		/*
175962306a36Sopenharmony_ci		 * Neither are zeroes.
176062306a36Sopenharmony_ci		 * Adjust exponent and normalize add operand.
176162306a36Sopenharmony_ci		 */
176262306a36Sopenharmony_ci		sign_save = Sgl_signextendedsign(opnd3);	/* save sign */
176362306a36Sopenharmony_ci		Sgl_clear_signexponent(opnd3);
176462306a36Sopenharmony_ci		Sgl_leftshiftby1(opnd3);
176562306a36Sopenharmony_ci		Sgl_normalize(opnd3,add_exponent);
176662306a36Sopenharmony_ci		Sgl_set_sign(opnd3,sign_save);		/* restore sign */
176762306a36Sopenharmony_ci	} else {
176862306a36Sopenharmony_ci		Sgl_clear_exponent_set_hidden(opnd3);
176962306a36Sopenharmony_ci	}
177062306a36Sopenharmony_ci	/*
177162306a36Sopenharmony_ci	 * Copy opnd3 to the double extended variable called right.
177262306a36Sopenharmony_ci	 */
177362306a36Sopenharmony_ci	Sgl_copyto_sglext(opnd3,rightp1,rightp2);
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci	/*
177662306a36Sopenharmony_ci	 * A zero "save" helps discover equal operands (for later),
177762306a36Sopenharmony_ci	 * and is used in swapping operands (if needed).
177862306a36Sopenharmony_ci	 */
177962306a36Sopenharmony_ci	Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci	/*
178262306a36Sopenharmony_ci	 * Compare magnitude of operands.
178362306a36Sopenharmony_ci	 */
178462306a36Sopenharmony_ci	Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
178562306a36Sopenharmony_ci	Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
178662306a36Sopenharmony_ci	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
178762306a36Sopenharmony_ci	    Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
178862306a36Sopenharmony_ci		/*
178962306a36Sopenharmony_ci		 * Set the left operand to the larger one by XOR swap.
179062306a36Sopenharmony_ci		 * First finish the first word "save".
179162306a36Sopenharmony_ci		 */
179262306a36Sopenharmony_ci		Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
179362306a36Sopenharmony_ci		Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
179462306a36Sopenharmony_ci		Sglext_swap_lower(tmpresp2,rightp2);
179562306a36Sopenharmony_ci		/* also setup exponents used in rest of routine */
179662306a36Sopenharmony_ci		diff_exponent = add_exponent - mpy_exponent;
179762306a36Sopenharmony_ci		result_exponent = add_exponent;
179862306a36Sopenharmony_ci	} else {
179962306a36Sopenharmony_ci		/* also setup exponents used in rest of routine */
180062306a36Sopenharmony_ci		diff_exponent = mpy_exponent - add_exponent;
180162306a36Sopenharmony_ci		result_exponent = mpy_exponent;
180262306a36Sopenharmony_ci	}
180362306a36Sopenharmony_ci	/* Invariant: left is not smaller than right. */
180462306a36Sopenharmony_ci
180562306a36Sopenharmony_ci	/*
180662306a36Sopenharmony_ci	 * Special case alignment of operands that would force alignment
180762306a36Sopenharmony_ci	 * beyond the extent of the extension.  A further optimization
180862306a36Sopenharmony_ci	 * could special case this but only reduces the path length for
180962306a36Sopenharmony_ci	 * this infrequent case.
181062306a36Sopenharmony_ci	 */
181162306a36Sopenharmony_ci	if (diff_exponent > SGLEXT_THRESHOLD) {
181262306a36Sopenharmony_ci		diff_exponent = SGLEXT_THRESHOLD;
181362306a36Sopenharmony_ci	}
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	/* Align right operand by shifting it to the right */
181662306a36Sopenharmony_ci	Sglext_clear_sign(rightp1);
181762306a36Sopenharmony_ci	Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	/* Treat sum and difference of the operands separately. */
182062306a36Sopenharmony_ci	if ((int)save < 0) {
182162306a36Sopenharmony_ci		/*
182262306a36Sopenharmony_ci		 * Difference of the two operands.  Overflow can occur if the
182362306a36Sopenharmony_ci		 * multiply overflowed.  A borrow can occur out of the hidden
182462306a36Sopenharmony_ci		 * bit and force a post normalization phase.
182562306a36Sopenharmony_ci		 */
182662306a36Sopenharmony_ci		Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
182762306a36Sopenharmony_ci			resultp1,resultp2);
182862306a36Sopenharmony_ci		sign_save = Sgl_signextendedsign(resultp1);
182962306a36Sopenharmony_ci		if (Sgl_iszero_hidden(resultp1)) {
183062306a36Sopenharmony_ci			/* Handle normalization */
183162306a36Sopenharmony_ci		/* A straightforward algorithm would now shift the
183262306a36Sopenharmony_ci		 * result and extension left until the hidden bit
183362306a36Sopenharmony_ci		 * becomes one.  Not all of the extension bits need
183462306a36Sopenharmony_ci		 * participate in the shift.  Only the two most
183562306a36Sopenharmony_ci		 * significant bits (round and guard) are needed.
183662306a36Sopenharmony_ci		 * If only a single shift is needed then the guard
183762306a36Sopenharmony_ci		 * bit becomes a significant low order bit and the
183862306a36Sopenharmony_ci		 * extension must participate in the rounding.
183962306a36Sopenharmony_ci		 * If more than a single shift is needed, then all
184062306a36Sopenharmony_ci		 * bits to the right of the guard bit are zeros,
184162306a36Sopenharmony_ci		 * and the guard bit may or may not be zero. */
184262306a36Sopenharmony_ci			Sglext_leftshiftby1(resultp1,resultp2);
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci			/* Need to check for a zero result.  The sign and
184562306a36Sopenharmony_ci			 * exponent fields have already been zeroed.  The more
184662306a36Sopenharmony_ci			 * efficient test of the full object can be used.
184762306a36Sopenharmony_ci			 */
184862306a36Sopenharmony_ci			 if (Sglext_iszero(resultp1,resultp2)) {
184962306a36Sopenharmony_ci				/* Must have been "x-x" or "x+(-x)". */
185062306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS))
185162306a36Sopenharmony_ci					Sgl_setone_sign(resultp1);
185262306a36Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
185362306a36Sopenharmony_ci				return(NOEXCEPTION);
185462306a36Sopenharmony_ci			}
185562306a36Sopenharmony_ci			result_exponent--;
185662306a36Sopenharmony_ci
185762306a36Sopenharmony_ci			/* Look to see if normalization is finished. */
185862306a36Sopenharmony_ci			if (Sgl_isone_hidden(resultp1)) {
185962306a36Sopenharmony_ci				/* No further normalization is needed */
186062306a36Sopenharmony_ci				goto round;
186162306a36Sopenharmony_ci			}
186262306a36Sopenharmony_ci
186362306a36Sopenharmony_ci			/* Discover first one bit to determine shift amount.
186462306a36Sopenharmony_ci			 * Use a modified binary search.  We have already
186562306a36Sopenharmony_ci			 * shifted the result one position right and still
186662306a36Sopenharmony_ci			 * not found a one so the remainder of the extension
186762306a36Sopenharmony_ci			 * must be zero and simplifies rounding. */
186862306a36Sopenharmony_ci			/* Scan bytes */
186962306a36Sopenharmony_ci			while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
187062306a36Sopenharmony_ci				Sglext_leftshiftby8(resultp1,resultp2);
187162306a36Sopenharmony_ci				result_exponent -= 8;
187262306a36Sopenharmony_ci			}
187362306a36Sopenharmony_ci			/* Now narrow it down to the nibble */
187462306a36Sopenharmony_ci			if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
187562306a36Sopenharmony_ci				/* The lower nibble contains the
187662306a36Sopenharmony_ci				 * normalizing one */
187762306a36Sopenharmony_ci				Sglext_leftshiftby4(resultp1,resultp2);
187862306a36Sopenharmony_ci				result_exponent -= 4;
187962306a36Sopenharmony_ci			}
188062306a36Sopenharmony_ci			/* Select case where first bit is set (already
188162306a36Sopenharmony_ci			 * normalized) otherwise select the proper shift. */
188262306a36Sopenharmony_ci			jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
188362306a36Sopenharmony_ci			if (jumpsize <= 7) switch(jumpsize) {
188462306a36Sopenharmony_ci			case 1:
188562306a36Sopenharmony_ci				Sglext_leftshiftby3(resultp1,resultp2);
188662306a36Sopenharmony_ci				result_exponent -= 3;
188762306a36Sopenharmony_ci				break;
188862306a36Sopenharmony_ci			case 2:
188962306a36Sopenharmony_ci			case 3:
189062306a36Sopenharmony_ci				Sglext_leftshiftby2(resultp1,resultp2);
189162306a36Sopenharmony_ci				result_exponent -= 2;
189262306a36Sopenharmony_ci				break;
189362306a36Sopenharmony_ci			case 4:
189462306a36Sopenharmony_ci			case 5:
189562306a36Sopenharmony_ci			case 6:
189662306a36Sopenharmony_ci			case 7:
189762306a36Sopenharmony_ci				Sglext_leftshiftby1(resultp1,resultp2);
189862306a36Sopenharmony_ci				result_exponent -= 1;
189962306a36Sopenharmony_ci				break;
190062306a36Sopenharmony_ci			}
190162306a36Sopenharmony_ci		} /* end if (hidden...)... */
190262306a36Sopenharmony_ci	/* Fall through and round */
190362306a36Sopenharmony_ci	} /* end if (save < 0)... */
190462306a36Sopenharmony_ci	else {
190562306a36Sopenharmony_ci		/* Add magnitudes */
190662306a36Sopenharmony_ci		Sglext_addition(tmpresp1,tmpresp2,
190762306a36Sopenharmony_ci			rightp1,rightp2, /*to*/resultp1,resultp2);
190862306a36Sopenharmony_ci		sign_save = Sgl_signextendedsign(resultp1);
190962306a36Sopenharmony_ci		if (Sgl_isone_hiddenoverflow(resultp1)) {
191062306a36Sopenharmony_ci	    		/* Prenormalization required. */
191162306a36Sopenharmony_ci	    		Sglext_arithrightshiftby1(resultp1,resultp2);
191262306a36Sopenharmony_ci	    		result_exponent++;
191362306a36Sopenharmony_ci		} /* end if hiddenoverflow... */
191462306a36Sopenharmony_ci	} /* end else ...add magnitudes... */
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci	/* Round the result.  If the extension and lower two words are
191762306a36Sopenharmony_ci	 * all zeros, then the result is exact.  Otherwise round in the
191862306a36Sopenharmony_ci	 * correct direction.  Underflow is possible. If a postnormalization
191962306a36Sopenharmony_ci	 * is necessary, then the mantissa is all zeros so no shift is needed.
192062306a36Sopenharmony_ci	 */
192162306a36Sopenharmony_ci  round:
192262306a36Sopenharmony_ci	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
192362306a36Sopenharmony_ci		Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
192462306a36Sopenharmony_ci	}
192562306a36Sopenharmony_ci	Sgl_set_sign(resultp1,/*using*/sign_save);
192662306a36Sopenharmony_ci	if (Sglext_isnotzero_mantissap2(resultp2)) {
192762306a36Sopenharmony_ci		inexact = TRUE;
192862306a36Sopenharmony_ci		switch(Rounding_mode()) {
192962306a36Sopenharmony_ci		case ROUNDNEAREST: /* The default. */
193062306a36Sopenharmony_ci			if (Sglext_isone_highp2(resultp2)) {
193162306a36Sopenharmony_ci				/* at least 1/2 ulp */
193262306a36Sopenharmony_ci				if (Sglext_isnotzero_low31p2(resultp2) ||
193362306a36Sopenharmony_ci				    Sglext_isone_lowp1(resultp1)) {
193462306a36Sopenharmony_ci					/* either exactly half way and odd or
193562306a36Sopenharmony_ci					 * more than 1/2ulp */
193662306a36Sopenharmony_ci					Sgl_increment(resultp1);
193762306a36Sopenharmony_ci				}
193862306a36Sopenharmony_ci			}
193962306a36Sopenharmony_ci	    		break;
194062306a36Sopenharmony_ci
194162306a36Sopenharmony_ci		case ROUNDPLUS:
194262306a36Sopenharmony_ci	    		if (Sgl_iszero_sign(resultp1)) {
194362306a36Sopenharmony_ci				/* Round up positive results */
194462306a36Sopenharmony_ci				Sgl_increment(resultp1);
194562306a36Sopenharmony_ci			}
194662306a36Sopenharmony_ci			break;
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci		case ROUNDMINUS:
194962306a36Sopenharmony_ci	    		if (Sgl_isone_sign(resultp1)) {
195062306a36Sopenharmony_ci				/* Round down negative results */
195162306a36Sopenharmony_ci				Sgl_increment(resultp1);
195262306a36Sopenharmony_ci			}
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_ci		case ROUNDZERO:;
195562306a36Sopenharmony_ci			/* truncate is simple */
195662306a36Sopenharmony_ci		} /* end switch... */
195762306a36Sopenharmony_ci		if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
195862306a36Sopenharmony_ci	}
195962306a36Sopenharmony_ci	if (result_exponent >= SGL_INFINITY_EXPONENT) {
196062306a36Sopenharmony_ci		/* Overflow */
196162306a36Sopenharmony_ci		if (Is_overflowtrap_enabled()) {
196262306a36Sopenharmony_ci                        /*
196362306a36Sopenharmony_ci                         * Adjust bias of result
196462306a36Sopenharmony_ci                         */
196562306a36Sopenharmony_ci                        Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
196662306a36Sopenharmony_ci                        Sgl_copytoptr(resultp1,dstptr);
196762306a36Sopenharmony_ci                        if (inexact)
196862306a36Sopenharmony_ci                            if (Is_inexacttrap_enabled())
196962306a36Sopenharmony_ci                                return (OPC_2E_OVERFLOWEXCEPTION |
197062306a36Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
197162306a36Sopenharmony_ci                            else Set_inexactflag();
197262306a36Sopenharmony_ci                        return (OPC_2E_OVERFLOWEXCEPTION);
197362306a36Sopenharmony_ci		}
197462306a36Sopenharmony_ci		inexact = TRUE;
197562306a36Sopenharmony_ci		Set_overflowflag();
197662306a36Sopenharmony_ci		Sgl_setoverflow(resultp1);
197762306a36Sopenharmony_ci	} else if (result_exponent <= 0) {	/* underflow case */
197862306a36Sopenharmony_ci		if (Is_underflowtrap_enabled()) {
197962306a36Sopenharmony_ci                        /*
198062306a36Sopenharmony_ci                         * Adjust bias of result
198162306a36Sopenharmony_ci                         */
198262306a36Sopenharmony_ci                	Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
198362306a36Sopenharmony_ci			Sgl_copytoptr(resultp1,dstptr);
198462306a36Sopenharmony_ci                        if (inexact)
198562306a36Sopenharmony_ci                            if (Is_inexacttrap_enabled())
198662306a36Sopenharmony_ci                                return (OPC_2E_UNDERFLOWEXCEPTION |
198762306a36Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
198862306a36Sopenharmony_ci                            else Set_inexactflag();
198962306a36Sopenharmony_ci	    		return(OPC_2E_UNDERFLOWEXCEPTION);
199062306a36Sopenharmony_ci		}
199162306a36Sopenharmony_ci		else if (inexact && is_tiny) Set_underflowflag();
199262306a36Sopenharmony_ci	}
199362306a36Sopenharmony_ci	else Sgl_set_exponent(resultp1,result_exponent);
199462306a36Sopenharmony_ci	Sgl_copytoptr(resultp1,dstptr);
199562306a36Sopenharmony_ci	if (inexact)
199662306a36Sopenharmony_ci		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
199762306a36Sopenharmony_ci		else Set_inexactflag();
199862306a36Sopenharmony_ci    	return(NOEXCEPTION);
199962306a36Sopenharmony_ci}
200062306a36Sopenharmony_ci
200162306a36Sopenharmony_ci/*
200262306a36Sopenharmony_ci *  Single Floating-point Multiply Negate Fused Add
200362306a36Sopenharmony_ci */
200462306a36Sopenharmony_ci
200562306a36Sopenharmony_cisgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
200662306a36Sopenharmony_ci
200762306a36Sopenharmony_cisgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
200862306a36Sopenharmony_ciunsigned int *status;
200962306a36Sopenharmony_ci{
201062306a36Sopenharmony_ci	unsigned int opnd1, opnd2, opnd3;
201162306a36Sopenharmony_ci	register unsigned int tmpresp1, tmpresp2;
201262306a36Sopenharmony_ci	unsigned int rightp1, rightp2;
201362306a36Sopenharmony_ci	unsigned int resultp1, resultp2 = 0;
201462306a36Sopenharmony_ci	register int mpy_exponent, add_exponent, count;
201562306a36Sopenharmony_ci	boolean inexact = FALSE, is_tiny = FALSE;
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	unsigned int signlessleft1, signlessright1, save;
201862306a36Sopenharmony_ci	register int result_exponent, diff_exponent;
201962306a36Sopenharmony_ci	int sign_save, jumpsize;
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	Sgl_copyfromptr(src1ptr,opnd1);
202262306a36Sopenharmony_ci	Sgl_copyfromptr(src2ptr,opnd2);
202362306a36Sopenharmony_ci	Sgl_copyfromptr(src3ptr,opnd3);
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci	/*
202662306a36Sopenharmony_ci	 * set sign bit of result of multiply
202762306a36Sopenharmony_ci	 */
202862306a36Sopenharmony_ci	if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2))
202962306a36Sopenharmony_ci		Sgl_setzero(resultp1);
203062306a36Sopenharmony_ci	else
203162306a36Sopenharmony_ci		Sgl_setnegativezero(resultp1);
203262306a36Sopenharmony_ci
203362306a36Sopenharmony_ci	/*
203462306a36Sopenharmony_ci	 * Generate multiply exponent
203562306a36Sopenharmony_ci	 */
203662306a36Sopenharmony_ci	mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci	/*
203962306a36Sopenharmony_ci	 * check first operand for NaN's or infinity
204062306a36Sopenharmony_ci	 */
204162306a36Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd1)) {
204262306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd1)) {
204362306a36Sopenharmony_ci			if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
204462306a36Sopenharmony_ci				if (Sgl_iszero_exponentmantissa(opnd2)) {
204562306a36Sopenharmony_ci					/*
204662306a36Sopenharmony_ci					 * invalid since operands are infinity
204762306a36Sopenharmony_ci					 * and zero
204862306a36Sopenharmony_ci					 */
204962306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
205062306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
205162306a36Sopenharmony_ci					Set_invalidflag();
205262306a36Sopenharmony_ci					Sgl_makequietnan(resultp1);
205362306a36Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
205462306a36Sopenharmony_ci					return(NOEXCEPTION);
205562306a36Sopenharmony_ci				}
205662306a36Sopenharmony_ci				/*
205762306a36Sopenharmony_ci				 * Check third operand for infinity with a
205862306a36Sopenharmony_ci				 *  sign opposite of the multiply result
205962306a36Sopenharmony_ci				 */
206062306a36Sopenharmony_ci				if (Sgl_isinfinity(opnd3) &&
206162306a36Sopenharmony_ci				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
206262306a36Sopenharmony_ci					/*
206362306a36Sopenharmony_ci					 * invalid since attempting a magnitude
206462306a36Sopenharmony_ci					 * subtraction of infinities
206562306a36Sopenharmony_ci					 */
206662306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
206762306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
206862306a36Sopenharmony_ci					Set_invalidflag();
206962306a36Sopenharmony_ci					Sgl_makequietnan(resultp1);
207062306a36Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
207162306a36Sopenharmony_ci					return(NOEXCEPTION);
207262306a36Sopenharmony_ci				}
207362306a36Sopenharmony_ci
207462306a36Sopenharmony_ci				/*
207562306a36Sopenharmony_ci			 	 * return infinity
207662306a36Sopenharmony_ci			 	 */
207762306a36Sopenharmony_ci				Sgl_setinfinity_exponentmantissa(resultp1);
207862306a36Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
207962306a36Sopenharmony_ci				return(NOEXCEPTION);
208062306a36Sopenharmony_ci			}
208162306a36Sopenharmony_ci		}
208262306a36Sopenharmony_ci		else {
208362306a36Sopenharmony_ci			/*
208462306a36Sopenharmony_ci		 	 * is NaN; signaling or quiet?
208562306a36Sopenharmony_ci		 	 */
208662306a36Sopenharmony_ci			if (Sgl_isone_signaling(opnd1)) {
208762306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
208862306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
208962306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
209062306a36Sopenharmony_ci				/* make NaN quiet */
209162306a36Sopenharmony_ci				Set_invalidflag();
209262306a36Sopenharmony_ci				Sgl_set_quiet(opnd1);
209362306a36Sopenharmony_ci			}
209462306a36Sopenharmony_ci			/*
209562306a36Sopenharmony_ci			 * is second operand a signaling NaN?
209662306a36Sopenharmony_ci			 */
209762306a36Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd2)) {
209862306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
209962306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
210062306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
210162306a36Sopenharmony_ci				/* make NaN quiet */
210262306a36Sopenharmony_ci				Set_invalidflag();
210362306a36Sopenharmony_ci				Sgl_set_quiet(opnd2);
210462306a36Sopenharmony_ci				Sgl_copytoptr(opnd2,dstptr);
210562306a36Sopenharmony_ci				return(NOEXCEPTION);
210662306a36Sopenharmony_ci			}
210762306a36Sopenharmony_ci			/*
210862306a36Sopenharmony_ci			 * is third operand a signaling NaN?
210962306a36Sopenharmony_ci			 */
211062306a36Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd3)) {
211162306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
211262306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
211362306a36Sopenharmony_ci			    		return(OPC_2E_INVALIDEXCEPTION);
211462306a36Sopenharmony_ci				/* make NaN quiet */
211562306a36Sopenharmony_ci				Set_invalidflag();
211662306a36Sopenharmony_ci				Sgl_set_quiet(opnd3);
211762306a36Sopenharmony_ci				Sgl_copytoptr(opnd3,dstptr);
211862306a36Sopenharmony_ci				return(NOEXCEPTION);
211962306a36Sopenharmony_ci			}
212062306a36Sopenharmony_ci			/*
212162306a36Sopenharmony_ci		 	 * return quiet NaN
212262306a36Sopenharmony_ci		 	 */
212362306a36Sopenharmony_ci			Sgl_copytoptr(opnd1,dstptr);
212462306a36Sopenharmony_ci			return(NOEXCEPTION);
212562306a36Sopenharmony_ci		}
212662306a36Sopenharmony_ci	}
212762306a36Sopenharmony_ci
212862306a36Sopenharmony_ci	/*
212962306a36Sopenharmony_ci	 * check second operand for NaN's or infinity
213062306a36Sopenharmony_ci	 */
213162306a36Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd2)) {
213262306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd2)) {
213362306a36Sopenharmony_ci			if (Sgl_isnotnan(opnd3)) {
213462306a36Sopenharmony_ci				if (Sgl_iszero_exponentmantissa(opnd1)) {
213562306a36Sopenharmony_ci					/*
213662306a36Sopenharmony_ci					 * invalid since multiply operands are
213762306a36Sopenharmony_ci					 * zero & infinity
213862306a36Sopenharmony_ci					 */
213962306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
214062306a36Sopenharmony_ci						return(OPC_2E_INVALIDEXCEPTION);
214162306a36Sopenharmony_ci					Set_invalidflag();
214262306a36Sopenharmony_ci					Sgl_makequietnan(opnd2);
214362306a36Sopenharmony_ci					Sgl_copytoptr(opnd2,dstptr);
214462306a36Sopenharmony_ci					return(NOEXCEPTION);
214562306a36Sopenharmony_ci				}
214662306a36Sopenharmony_ci
214762306a36Sopenharmony_ci				/*
214862306a36Sopenharmony_ci				 * Check third operand for infinity with a
214962306a36Sopenharmony_ci				 *  sign opposite of the multiply result
215062306a36Sopenharmony_ci				 */
215162306a36Sopenharmony_ci				if (Sgl_isinfinity(opnd3) &&
215262306a36Sopenharmony_ci				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
215362306a36Sopenharmony_ci					/*
215462306a36Sopenharmony_ci					 * invalid since attempting a magnitude
215562306a36Sopenharmony_ci					 * subtraction of infinities
215662306a36Sopenharmony_ci					 */
215762306a36Sopenharmony_ci					if (Is_invalidtrap_enabled())
215862306a36Sopenharmony_ci				       		return(OPC_2E_INVALIDEXCEPTION);
215962306a36Sopenharmony_ci				       	Set_invalidflag();
216062306a36Sopenharmony_ci				       	Sgl_makequietnan(resultp1);
216162306a36Sopenharmony_ci					Sgl_copytoptr(resultp1,dstptr);
216262306a36Sopenharmony_ci					return(NOEXCEPTION);
216362306a36Sopenharmony_ci				}
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci				/*
216662306a36Sopenharmony_ci				 * return infinity
216762306a36Sopenharmony_ci				 */
216862306a36Sopenharmony_ci				Sgl_setinfinity_exponentmantissa(resultp1);
216962306a36Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
217062306a36Sopenharmony_ci				return(NOEXCEPTION);
217162306a36Sopenharmony_ci			}
217262306a36Sopenharmony_ci		}
217362306a36Sopenharmony_ci		else {
217462306a36Sopenharmony_ci			/*
217562306a36Sopenharmony_ci			 * is NaN; signaling or quiet?
217662306a36Sopenharmony_ci			 */
217762306a36Sopenharmony_ci			if (Sgl_isone_signaling(opnd2)) {
217862306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
217962306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
218062306a36Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
218162306a36Sopenharmony_ci				/* make NaN quiet */
218262306a36Sopenharmony_ci				Set_invalidflag();
218362306a36Sopenharmony_ci				Sgl_set_quiet(opnd2);
218462306a36Sopenharmony_ci			}
218562306a36Sopenharmony_ci			/*
218662306a36Sopenharmony_ci			 * is third operand a signaling NaN?
218762306a36Sopenharmony_ci			 */
218862306a36Sopenharmony_ci			else if (Sgl_is_signalingnan(opnd3)) {
218962306a36Sopenharmony_ci			       	/* trap if INVALIDTRAP enabled */
219062306a36Sopenharmony_ci			       	if (Is_invalidtrap_enabled())
219162306a36Sopenharmony_ci				   		return(OPC_2E_INVALIDEXCEPTION);
219262306a36Sopenharmony_ci			       	/* make NaN quiet */
219362306a36Sopenharmony_ci			       	Set_invalidflag();
219462306a36Sopenharmony_ci			       	Sgl_set_quiet(opnd3);
219562306a36Sopenharmony_ci				Sgl_copytoptr(opnd3,dstptr);
219662306a36Sopenharmony_ci		       		return(NOEXCEPTION);
219762306a36Sopenharmony_ci			}
219862306a36Sopenharmony_ci			/*
219962306a36Sopenharmony_ci			 * return quiet NaN
220062306a36Sopenharmony_ci			 */
220162306a36Sopenharmony_ci			Sgl_copytoptr(opnd2,dstptr);
220262306a36Sopenharmony_ci			return(NOEXCEPTION);
220362306a36Sopenharmony_ci		}
220462306a36Sopenharmony_ci	}
220562306a36Sopenharmony_ci
220662306a36Sopenharmony_ci	/*
220762306a36Sopenharmony_ci	 * check third operand for NaN's or infinity
220862306a36Sopenharmony_ci	 */
220962306a36Sopenharmony_ci	if (Sgl_isinfinity_exponent(opnd3)) {
221062306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd3)) {
221162306a36Sopenharmony_ci			/* return infinity */
221262306a36Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
221362306a36Sopenharmony_ci			return(NOEXCEPTION);
221462306a36Sopenharmony_ci		} else {
221562306a36Sopenharmony_ci			/*
221662306a36Sopenharmony_ci			 * is NaN; signaling or quiet?
221762306a36Sopenharmony_ci			 */
221862306a36Sopenharmony_ci			if (Sgl_isone_signaling(opnd3)) {
221962306a36Sopenharmony_ci				/* trap if INVALIDTRAP enabled */
222062306a36Sopenharmony_ci				if (Is_invalidtrap_enabled())
222162306a36Sopenharmony_ci					return(OPC_2E_INVALIDEXCEPTION);
222262306a36Sopenharmony_ci				/* make NaN quiet */
222362306a36Sopenharmony_ci				Set_invalidflag();
222462306a36Sopenharmony_ci				Sgl_set_quiet(opnd3);
222562306a36Sopenharmony_ci			}
222662306a36Sopenharmony_ci			/*
222762306a36Sopenharmony_ci			 * return quiet NaN
222862306a36Sopenharmony_ci 			 */
222962306a36Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
223062306a36Sopenharmony_ci			return(NOEXCEPTION);
223162306a36Sopenharmony_ci		}
223262306a36Sopenharmony_ci    	}
223362306a36Sopenharmony_ci
223462306a36Sopenharmony_ci	/*
223562306a36Sopenharmony_ci	 * Generate multiply mantissa
223662306a36Sopenharmony_ci	 */
223762306a36Sopenharmony_ci	if (Sgl_isnotzero_exponent(opnd1)) {
223862306a36Sopenharmony_ci		/* set hidden bit */
223962306a36Sopenharmony_ci		Sgl_clear_signexponent_set_hidden(opnd1);
224062306a36Sopenharmony_ci	}
224162306a36Sopenharmony_ci	else {
224262306a36Sopenharmony_ci		/* check for zero */
224362306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd1)) {
224462306a36Sopenharmony_ci			/*
224562306a36Sopenharmony_ci			 * Perform the add opnd3 with zero here.
224662306a36Sopenharmony_ci			 */
224762306a36Sopenharmony_ci			if (Sgl_iszero_exponentmantissa(opnd3)) {
224862306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
224962306a36Sopenharmony_ci					Sgl_or_signs(opnd3,resultp1);
225062306a36Sopenharmony_ci				} else {
225162306a36Sopenharmony_ci					Sgl_and_signs(opnd3,resultp1);
225262306a36Sopenharmony_ci				}
225362306a36Sopenharmony_ci			}
225462306a36Sopenharmony_ci			/*
225562306a36Sopenharmony_ci			 * Now let's check for trapped underflow case.
225662306a36Sopenharmony_ci			 */
225762306a36Sopenharmony_ci			else if (Sgl_iszero_exponent(opnd3) &&
225862306a36Sopenharmony_ci			         Is_underflowtrap_enabled()) {
225962306a36Sopenharmony_ci                    		/* need to normalize results mantissa */
226062306a36Sopenharmony_ci                    		sign_save = Sgl_signextendedsign(opnd3);
226162306a36Sopenharmony_ci				result_exponent = 0;
226262306a36Sopenharmony_ci                    		Sgl_leftshiftby1(opnd3);
226362306a36Sopenharmony_ci                    		Sgl_normalize(opnd3,result_exponent);
226462306a36Sopenharmony_ci                    		Sgl_set_sign(opnd3,/*using*/sign_save);
226562306a36Sopenharmony_ci                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
226662306a36Sopenharmony_ci							unfl);
226762306a36Sopenharmony_ci                    		Sgl_copytoptr(opnd3,dstptr);
226862306a36Sopenharmony_ci                    		/* inexact = FALSE */
226962306a36Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
227062306a36Sopenharmony_ci			}
227162306a36Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
227262306a36Sopenharmony_ci			return(NOEXCEPTION);
227362306a36Sopenharmony_ci		}
227462306a36Sopenharmony_ci		/* is denormalized, adjust exponent */
227562306a36Sopenharmony_ci		Sgl_clear_signexponent(opnd1);
227662306a36Sopenharmony_ci		Sgl_leftshiftby1(opnd1);
227762306a36Sopenharmony_ci		Sgl_normalize(opnd1,mpy_exponent);
227862306a36Sopenharmony_ci	}
227962306a36Sopenharmony_ci	/* opnd2 needs to have hidden bit set with msb in hidden bit */
228062306a36Sopenharmony_ci	if (Sgl_isnotzero_exponent(opnd2)) {
228162306a36Sopenharmony_ci		Sgl_clear_signexponent_set_hidden(opnd2);
228262306a36Sopenharmony_ci	}
228362306a36Sopenharmony_ci	else {
228462306a36Sopenharmony_ci		/* check for zero */
228562306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd2)) {
228662306a36Sopenharmony_ci			/*
228762306a36Sopenharmony_ci			 * Perform the add opnd3 with zero here.
228862306a36Sopenharmony_ci			 */
228962306a36Sopenharmony_ci			if (Sgl_iszero_exponentmantissa(opnd3)) {
229062306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS)) {
229162306a36Sopenharmony_ci					Sgl_or_signs(opnd3,resultp1);
229262306a36Sopenharmony_ci				} else {
229362306a36Sopenharmony_ci					Sgl_and_signs(opnd3,resultp1);
229462306a36Sopenharmony_ci				}
229562306a36Sopenharmony_ci			}
229662306a36Sopenharmony_ci			/*
229762306a36Sopenharmony_ci			 * Now let's check for trapped underflow case.
229862306a36Sopenharmony_ci			 */
229962306a36Sopenharmony_ci			else if (Sgl_iszero_exponent(opnd3) &&
230062306a36Sopenharmony_ci			    Is_underflowtrap_enabled()) {
230162306a36Sopenharmony_ci                    		/* need to normalize results mantissa */
230262306a36Sopenharmony_ci                    		sign_save = Sgl_signextendedsign(opnd3);
230362306a36Sopenharmony_ci				result_exponent = 0;
230462306a36Sopenharmony_ci                    		Sgl_leftshiftby1(opnd3);
230562306a36Sopenharmony_ci                    		Sgl_normalize(opnd3,result_exponent);
230662306a36Sopenharmony_ci                    		Sgl_set_sign(opnd3,/*using*/sign_save);
230762306a36Sopenharmony_ci                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
230862306a36Sopenharmony_ci							unfl);
230962306a36Sopenharmony_ci                    		Sgl_copytoptr(opnd3,dstptr);
231062306a36Sopenharmony_ci                    		/* inexact = FALSE */
231162306a36Sopenharmony_ci                    		return(OPC_2E_UNDERFLOWEXCEPTION);
231262306a36Sopenharmony_ci			}
231362306a36Sopenharmony_ci			Sgl_copytoptr(opnd3,dstptr);
231462306a36Sopenharmony_ci			return(NOEXCEPTION);
231562306a36Sopenharmony_ci		}
231662306a36Sopenharmony_ci		/* is denormalized; want to normalize */
231762306a36Sopenharmony_ci		Sgl_clear_signexponent(opnd2);
231862306a36Sopenharmony_ci		Sgl_leftshiftby1(opnd2);
231962306a36Sopenharmony_ci		Sgl_normalize(opnd2,mpy_exponent);
232062306a36Sopenharmony_ci	}
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_ci	/* Multiply the first two source mantissas together */
232362306a36Sopenharmony_ci
232462306a36Sopenharmony_ci	/*
232562306a36Sopenharmony_ci	 * The intermediate result will be kept in tmpres,
232662306a36Sopenharmony_ci	 * which needs enough room for 106 bits of mantissa,
232762306a36Sopenharmony_ci	 * so lets call it a Double extended.
232862306a36Sopenharmony_ci	 */
232962306a36Sopenharmony_ci	Sglext_setzero(tmpresp1,tmpresp2);
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci	/*
233262306a36Sopenharmony_ci	 * Four bits at a time are inspected in each loop, and a
233362306a36Sopenharmony_ci	 * simple shift and add multiply algorithm is used.
233462306a36Sopenharmony_ci	 */
233562306a36Sopenharmony_ci	for (count = SGL_P-1; count >= 0; count -= 4) {
233662306a36Sopenharmony_ci		Sglext_rightshiftby4(tmpresp1,tmpresp2);
233762306a36Sopenharmony_ci		if (Sbit28(opnd1)) {
233862306a36Sopenharmony_ci	 		/* Twoword_add should be an ADD followed by 2 ADDC's */
233962306a36Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
234062306a36Sopenharmony_ci		}
234162306a36Sopenharmony_ci		if (Sbit29(opnd1)) {
234262306a36Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
234362306a36Sopenharmony_ci		}
234462306a36Sopenharmony_ci		if (Sbit30(opnd1)) {
234562306a36Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
234662306a36Sopenharmony_ci		}
234762306a36Sopenharmony_ci		if (Sbit31(opnd1)) {
234862306a36Sopenharmony_ci			Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
234962306a36Sopenharmony_ci		}
235062306a36Sopenharmony_ci		Sgl_rightshiftby4(opnd1);
235162306a36Sopenharmony_ci	}
235262306a36Sopenharmony_ci	if (Is_sexthiddenoverflow(tmpresp1)) {
235362306a36Sopenharmony_ci		/* result mantissa >= 2 (mantissa overflow) */
235462306a36Sopenharmony_ci		mpy_exponent++;
235562306a36Sopenharmony_ci		Sglext_rightshiftby4(tmpresp1,tmpresp2);
235662306a36Sopenharmony_ci	} else {
235762306a36Sopenharmony_ci		Sglext_rightshiftby3(tmpresp1,tmpresp2);
235862306a36Sopenharmony_ci	}
235962306a36Sopenharmony_ci
236062306a36Sopenharmony_ci	/*
236162306a36Sopenharmony_ci	 * Restore the sign of the mpy result which was saved in resultp1.
236262306a36Sopenharmony_ci	 * The exponent will continue to be kept in mpy_exponent.
236362306a36Sopenharmony_ci	 */
236462306a36Sopenharmony_ci	Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	/*
236762306a36Sopenharmony_ci	 * No rounding is required, since the result of the multiply
236862306a36Sopenharmony_ci	 * is exact in the extended format.
236962306a36Sopenharmony_ci	 */
237062306a36Sopenharmony_ci
237162306a36Sopenharmony_ci	/*
237262306a36Sopenharmony_ci	 * Now we are ready to perform the add portion of the operation.
237362306a36Sopenharmony_ci	 *
237462306a36Sopenharmony_ci	 * The exponents need to be kept as integers for now, since the
237562306a36Sopenharmony_ci	 * multiply result might not fit into the exponent field.  We
237662306a36Sopenharmony_ci	 * can't overflow or underflow because of this yet, since the
237762306a36Sopenharmony_ci	 * add could bring the final result back into range.
237862306a36Sopenharmony_ci	 */
237962306a36Sopenharmony_ci	add_exponent = Sgl_exponent(opnd3);
238062306a36Sopenharmony_ci
238162306a36Sopenharmony_ci	/*
238262306a36Sopenharmony_ci	 * Check for denormalized or zero add operand.
238362306a36Sopenharmony_ci	 */
238462306a36Sopenharmony_ci	if (add_exponent == 0) {
238562306a36Sopenharmony_ci		/* check for zero */
238662306a36Sopenharmony_ci		if (Sgl_iszero_mantissa(opnd3)) {
238762306a36Sopenharmony_ci			/* right is zero */
238862306a36Sopenharmony_ci			/* Left can't be zero and must be result.
238962306a36Sopenharmony_ci			 *
239062306a36Sopenharmony_ci			 * The final result is now in tmpres and mpy_exponent,
239162306a36Sopenharmony_ci			 * and needs to be rounded and squeezed back into
239262306a36Sopenharmony_ci			 * double precision format from double extended.
239362306a36Sopenharmony_ci			 */
239462306a36Sopenharmony_ci			result_exponent = mpy_exponent;
239562306a36Sopenharmony_ci			Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
239662306a36Sopenharmony_ci			sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
239762306a36Sopenharmony_ci			goto round;
239862306a36Sopenharmony_ci		}
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_ci		/*
240162306a36Sopenharmony_ci		 * Neither are zeroes.
240262306a36Sopenharmony_ci		 * Adjust exponent and normalize add operand.
240362306a36Sopenharmony_ci		 */
240462306a36Sopenharmony_ci		sign_save = Sgl_signextendedsign(opnd3);	/* save sign */
240562306a36Sopenharmony_ci		Sgl_clear_signexponent(opnd3);
240662306a36Sopenharmony_ci		Sgl_leftshiftby1(opnd3);
240762306a36Sopenharmony_ci		Sgl_normalize(opnd3,add_exponent);
240862306a36Sopenharmony_ci		Sgl_set_sign(opnd3,sign_save);		/* restore sign */
240962306a36Sopenharmony_ci	} else {
241062306a36Sopenharmony_ci		Sgl_clear_exponent_set_hidden(opnd3);
241162306a36Sopenharmony_ci	}
241262306a36Sopenharmony_ci	/*
241362306a36Sopenharmony_ci	 * Copy opnd3 to the double extended variable called right.
241462306a36Sopenharmony_ci	 */
241562306a36Sopenharmony_ci	Sgl_copyto_sglext(opnd3,rightp1,rightp2);
241662306a36Sopenharmony_ci
241762306a36Sopenharmony_ci	/*
241862306a36Sopenharmony_ci	 * A zero "save" helps discover equal operands (for later),
241962306a36Sopenharmony_ci	 * and is used in swapping operands (if needed).
242062306a36Sopenharmony_ci	 */
242162306a36Sopenharmony_ci	Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);
242262306a36Sopenharmony_ci
242362306a36Sopenharmony_ci	/*
242462306a36Sopenharmony_ci	 * Compare magnitude of operands.
242562306a36Sopenharmony_ci	 */
242662306a36Sopenharmony_ci	Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
242762306a36Sopenharmony_ci	Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
242862306a36Sopenharmony_ci	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
242962306a36Sopenharmony_ci	    Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
243062306a36Sopenharmony_ci		/*
243162306a36Sopenharmony_ci		 * Set the left operand to the larger one by XOR swap.
243262306a36Sopenharmony_ci		 * First finish the first word "save".
243362306a36Sopenharmony_ci		 */
243462306a36Sopenharmony_ci		Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
243562306a36Sopenharmony_ci		Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
243662306a36Sopenharmony_ci		Sglext_swap_lower(tmpresp2,rightp2);
243762306a36Sopenharmony_ci		/* also setup exponents used in rest of routine */
243862306a36Sopenharmony_ci		diff_exponent = add_exponent - mpy_exponent;
243962306a36Sopenharmony_ci		result_exponent = add_exponent;
244062306a36Sopenharmony_ci	} else {
244162306a36Sopenharmony_ci		/* also setup exponents used in rest of routine */
244262306a36Sopenharmony_ci		diff_exponent = mpy_exponent - add_exponent;
244362306a36Sopenharmony_ci		result_exponent = mpy_exponent;
244462306a36Sopenharmony_ci	}
244562306a36Sopenharmony_ci	/* Invariant: left is not smaller than right. */
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci	/*
244862306a36Sopenharmony_ci	 * Special case alignment of operands that would force alignment
244962306a36Sopenharmony_ci	 * beyond the extent of the extension.  A further optimization
245062306a36Sopenharmony_ci	 * could special case this but only reduces the path length for
245162306a36Sopenharmony_ci	 * this infrequent case.
245262306a36Sopenharmony_ci	 */
245362306a36Sopenharmony_ci	if (diff_exponent > SGLEXT_THRESHOLD) {
245462306a36Sopenharmony_ci		diff_exponent = SGLEXT_THRESHOLD;
245562306a36Sopenharmony_ci	}
245662306a36Sopenharmony_ci
245762306a36Sopenharmony_ci	/* Align right operand by shifting it to the right */
245862306a36Sopenharmony_ci	Sglext_clear_sign(rightp1);
245962306a36Sopenharmony_ci	Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
246062306a36Sopenharmony_ci
246162306a36Sopenharmony_ci	/* Treat sum and difference of the operands separately. */
246262306a36Sopenharmony_ci	if ((int)save < 0) {
246362306a36Sopenharmony_ci		/*
246462306a36Sopenharmony_ci		 * Difference of the two operands.  Overflow can occur if the
246562306a36Sopenharmony_ci		 * multiply overflowed.  A borrow can occur out of the hidden
246662306a36Sopenharmony_ci		 * bit and force a post normalization phase.
246762306a36Sopenharmony_ci		 */
246862306a36Sopenharmony_ci		Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
246962306a36Sopenharmony_ci			resultp1,resultp2);
247062306a36Sopenharmony_ci		sign_save = Sgl_signextendedsign(resultp1);
247162306a36Sopenharmony_ci		if (Sgl_iszero_hidden(resultp1)) {
247262306a36Sopenharmony_ci			/* Handle normalization */
247362306a36Sopenharmony_ci		/* A straightforward algorithm would now shift the
247462306a36Sopenharmony_ci		 * result and extension left until the hidden bit
247562306a36Sopenharmony_ci		 * becomes one.  Not all of the extension bits need
247662306a36Sopenharmony_ci		 * participate in the shift.  Only the two most
247762306a36Sopenharmony_ci		 * significant bits (round and guard) are needed.
247862306a36Sopenharmony_ci		 * If only a single shift is needed then the guard
247962306a36Sopenharmony_ci		 * bit becomes a significant low order bit and the
248062306a36Sopenharmony_ci		 * extension must participate in the rounding.
248162306a36Sopenharmony_ci		 * If more than a single shift is needed, then all
248262306a36Sopenharmony_ci		 * bits to the right of the guard bit are zeros,
248362306a36Sopenharmony_ci		 * and the guard bit may or may not be zero. */
248462306a36Sopenharmony_ci			Sglext_leftshiftby1(resultp1,resultp2);
248562306a36Sopenharmony_ci
248662306a36Sopenharmony_ci			/* Need to check for a zero result.  The sign and
248762306a36Sopenharmony_ci			 * exponent fields have already been zeroed.  The more
248862306a36Sopenharmony_ci			 * efficient test of the full object can be used.
248962306a36Sopenharmony_ci			 */
249062306a36Sopenharmony_ci			 if (Sglext_iszero(resultp1,resultp2)) {
249162306a36Sopenharmony_ci				/* Must have been "x-x" or "x+(-x)". */
249262306a36Sopenharmony_ci				if (Is_rounding_mode(ROUNDMINUS))
249362306a36Sopenharmony_ci					Sgl_setone_sign(resultp1);
249462306a36Sopenharmony_ci				Sgl_copytoptr(resultp1,dstptr);
249562306a36Sopenharmony_ci				return(NOEXCEPTION);
249662306a36Sopenharmony_ci			}
249762306a36Sopenharmony_ci			result_exponent--;
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci			/* Look to see if normalization is finished. */
250062306a36Sopenharmony_ci			if (Sgl_isone_hidden(resultp1)) {
250162306a36Sopenharmony_ci				/* No further normalization is needed */
250262306a36Sopenharmony_ci				goto round;
250362306a36Sopenharmony_ci			}
250462306a36Sopenharmony_ci
250562306a36Sopenharmony_ci			/* Discover first one bit to determine shift amount.
250662306a36Sopenharmony_ci			 * Use a modified binary search.  We have already
250762306a36Sopenharmony_ci			 * shifted the result one position right and still
250862306a36Sopenharmony_ci			 * not found a one so the remainder of the extension
250962306a36Sopenharmony_ci			 * must be zero and simplifies rounding. */
251062306a36Sopenharmony_ci			/* Scan bytes */
251162306a36Sopenharmony_ci			while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
251262306a36Sopenharmony_ci				Sglext_leftshiftby8(resultp1,resultp2);
251362306a36Sopenharmony_ci				result_exponent -= 8;
251462306a36Sopenharmony_ci			}
251562306a36Sopenharmony_ci			/* Now narrow it down to the nibble */
251662306a36Sopenharmony_ci			if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
251762306a36Sopenharmony_ci				/* The lower nibble contains the
251862306a36Sopenharmony_ci				 * normalizing one */
251962306a36Sopenharmony_ci				Sglext_leftshiftby4(resultp1,resultp2);
252062306a36Sopenharmony_ci				result_exponent -= 4;
252162306a36Sopenharmony_ci			}
252262306a36Sopenharmony_ci			/* Select case where first bit is set (already
252362306a36Sopenharmony_ci			 * normalized) otherwise select the proper shift. */
252462306a36Sopenharmony_ci			jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
252562306a36Sopenharmony_ci			if (jumpsize <= 7) switch(jumpsize) {
252662306a36Sopenharmony_ci			case 1:
252762306a36Sopenharmony_ci				Sglext_leftshiftby3(resultp1,resultp2);
252862306a36Sopenharmony_ci				result_exponent -= 3;
252962306a36Sopenharmony_ci				break;
253062306a36Sopenharmony_ci			case 2:
253162306a36Sopenharmony_ci			case 3:
253262306a36Sopenharmony_ci				Sglext_leftshiftby2(resultp1,resultp2);
253362306a36Sopenharmony_ci				result_exponent -= 2;
253462306a36Sopenharmony_ci				break;
253562306a36Sopenharmony_ci			case 4:
253662306a36Sopenharmony_ci			case 5:
253762306a36Sopenharmony_ci			case 6:
253862306a36Sopenharmony_ci			case 7:
253962306a36Sopenharmony_ci				Sglext_leftshiftby1(resultp1,resultp2);
254062306a36Sopenharmony_ci				result_exponent -= 1;
254162306a36Sopenharmony_ci				break;
254262306a36Sopenharmony_ci			}
254362306a36Sopenharmony_ci		} /* end if (hidden...)... */
254462306a36Sopenharmony_ci	/* Fall through and round */
254562306a36Sopenharmony_ci	} /* end if (save < 0)... */
254662306a36Sopenharmony_ci	else {
254762306a36Sopenharmony_ci		/* Add magnitudes */
254862306a36Sopenharmony_ci		Sglext_addition(tmpresp1,tmpresp2,
254962306a36Sopenharmony_ci			rightp1,rightp2, /*to*/resultp1,resultp2);
255062306a36Sopenharmony_ci		sign_save = Sgl_signextendedsign(resultp1);
255162306a36Sopenharmony_ci		if (Sgl_isone_hiddenoverflow(resultp1)) {
255262306a36Sopenharmony_ci	    		/* Prenormalization required. */
255362306a36Sopenharmony_ci	    		Sglext_arithrightshiftby1(resultp1,resultp2);
255462306a36Sopenharmony_ci	    		result_exponent++;
255562306a36Sopenharmony_ci		} /* end if hiddenoverflow... */
255662306a36Sopenharmony_ci	} /* end else ...add magnitudes... */
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	/* Round the result.  If the extension and lower two words are
255962306a36Sopenharmony_ci	 * all zeros, then the result is exact.  Otherwise round in the
256062306a36Sopenharmony_ci	 * correct direction.  Underflow is possible. If a postnormalization
256162306a36Sopenharmony_ci	 * is necessary, then the mantissa is all zeros so no shift is needed.
256262306a36Sopenharmony_ci	 */
256362306a36Sopenharmony_ci  round:
256462306a36Sopenharmony_ci	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
256562306a36Sopenharmony_ci		Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
256662306a36Sopenharmony_ci	}
256762306a36Sopenharmony_ci	Sgl_set_sign(resultp1,/*using*/sign_save);
256862306a36Sopenharmony_ci	if (Sglext_isnotzero_mantissap2(resultp2)) {
256962306a36Sopenharmony_ci		inexact = TRUE;
257062306a36Sopenharmony_ci		switch(Rounding_mode()) {
257162306a36Sopenharmony_ci		case ROUNDNEAREST: /* The default. */
257262306a36Sopenharmony_ci			if (Sglext_isone_highp2(resultp2)) {
257362306a36Sopenharmony_ci				/* at least 1/2 ulp */
257462306a36Sopenharmony_ci				if (Sglext_isnotzero_low31p2(resultp2) ||
257562306a36Sopenharmony_ci				    Sglext_isone_lowp1(resultp1)) {
257662306a36Sopenharmony_ci					/* either exactly half way and odd or
257762306a36Sopenharmony_ci					 * more than 1/2ulp */
257862306a36Sopenharmony_ci					Sgl_increment(resultp1);
257962306a36Sopenharmony_ci				}
258062306a36Sopenharmony_ci			}
258162306a36Sopenharmony_ci	    		break;
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_ci		case ROUNDPLUS:
258462306a36Sopenharmony_ci	    		if (Sgl_iszero_sign(resultp1)) {
258562306a36Sopenharmony_ci				/* Round up positive results */
258662306a36Sopenharmony_ci				Sgl_increment(resultp1);
258762306a36Sopenharmony_ci			}
258862306a36Sopenharmony_ci			break;
258962306a36Sopenharmony_ci
259062306a36Sopenharmony_ci		case ROUNDMINUS:
259162306a36Sopenharmony_ci	    		if (Sgl_isone_sign(resultp1)) {
259262306a36Sopenharmony_ci				/* Round down negative results */
259362306a36Sopenharmony_ci				Sgl_increment(resultp1);
259462306a36Sopenharmony_ci			}
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci		case ROUNDZERO:;
259762306a36Sopenharmony_ci			/* truncate is simple */
259862306a36Sopenharmony_ci		} /* end switch... */
259962306a36Sopenharmony_ci		if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
260062306a36Sopenharmony_ci	}
260162306a36Sopenharmony_ci	if (result_exponent >= SGL_INFINITY_EXPONENT) {
260262306a36Sopenharmony_ci		/* Overflow */
260362306a36Sopenharmony_ci		if (Is_overflowtrap_enabled()) {
260462306a36Sopenharmony_ci                        /*
260562306a36Sopenharmony_ci                         * Adjust bias of result
260662306a36Sopenharmony_ci                         */
260762306a36Sopenharmony_ci                        Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
260862306a36Sopenharmony_ci                        Sgl_copytoptr(resultp1,dstptr);
260962306a36Sopenharmony_ci                        if (inexact)
261062306a36Sopenharmony_ci                            if (Is_inexacttrap_enabled())
261162306a36Sopenharmony_ci                                return (OPC_2E_OVERFLOWEXCEPTION |
261262306a36Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
261362306a36Sopenharmony_ci                            else Set_inexactflag();
261462306a36Sopenharmony_ci                        return (OPC_2E_OVERFLOWEXCEPTION);
261562306a36Sopenharmony_ci		}
261662306a36Sopenharmony_ci		inexact = TRUE;
261762306a36Sopenharmony_ci		Set_overflowflag();
261862306a36Sopenharmony_ci		Sgl_setoverflow(resultp1);
261962306a36Sopenharmony_ci	} else if (result_exponent <= 0) {	/* underflow case */
262062306a36Sopenharmony_ci		if (Is_underflowtrap_enabled()) {
262162306a36Sopenharmony_ci                        /*
262262306a36Sopenharmony_ci                         * Adjust bias of result
262362306a36Sopenharmony_ci                         */
262462306a36Sopenharmony_ci                	Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
262562306a36Sopenharmony_ci			Sgl_copytoptr(resultp1,dstptr);
262662306a36Sopenharmony_ci                        if (inexact)
262762306a36Sopenharmony_ci                            if (Is_inexacttrap_enabled())
262862306a36Sopenharmony_ci                                return (OPC_2E_UNDERFLOWEXCEPTION |
262962306a36Sopenharmony_ci					OPC_2E_INEXACTEXCEPTION);
263062306a36Sopenharmony_ci                            else Set_inexactflag();
263162306a36Sopenharmony_ci	    		return(OPC_2E_UNDERFLOWEXCEPTION);
263262306a36Sopenharmony_ci		}
263362306a36Sopenharmony_ci		else if (inexact && is_tiny) Set_underflowflag();
263462306a36Sopenharmony_ci	}
263562306a36Sopenharmony_ci	else Sgl_set_exponent(resultp1,result_exponent);
263662306a36Sopenharmony_ci	Sgl_copytoptr(resultp1,dstptr);
263762306a36Sopenharmony_ci	if (inexact)
263862306a36Sopenharmony_ci		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
263962306a36Sopenharmony_ci		else Set_inexactflag();
264062306a36Sopenharmony_ci    	return(NOEXCEPTION);
264162306a36Sopenharmony_ci}
264262306a36Sopenharmony_ci
2643