xref: /openbsd-src/sys/arch/hppa/spmath/sfsub.c (revision b466ace6709af8bf2b9ea9631f91ed36f6953dee)
1*b466ace6Sderaadt /*	$OpenBSD: sfsub.c,v 1.6 2002/11/29 09:27:34 deraadt Exp $	*/
2c2feb252Smickey /*
3c2feb252Smickey   (c) Copyright 1986 HEWLETT-PACKARD COMPANY
4c2feb252Smickey   To anyone who acknowledges that this file is provided "AS IS"
5c2feb252Smickey   without any express or implied warranty:
6c2feb252Smickey       permission to use, copy, modify, and distribute this file
7c2feb252Smickey   for any purpose is hereby granted without fee, provided that
8c2feb252Smickey   the above copyright notice and this notice appears in all
9c2feb252Smickey   copies, and that the name of Hewlett-Packard Company not be
10c2feb252Smickey   used in advertising or publicity pertaining to distribution
11c2feb252Smickey   of the software without specific, written prior permission.
12c2feb252Smickey   Hewlett-Packard Company makes no representations about the
13c2feb252Smickey   suitability of this software for any purpose.
14c2feb252Smickey */
15c2feb252Smickey /* @(#)sfsub.c: Revision: 2.7.88.1 Date: 93/12/07 15:07:15 */
16b94afd46Smickey 
17c2feb252Smickey #include "float.h"
18c2feb252Smickey #include "sgl_float.h"
198a472b3eSmickey 
208a472b3eSmickey /*
218a472b3eSmickey  * Single_subtract: subtract two single precision values.
228a472b3eSmickey  */
23b94afd46Smickey int
sgl_fsub(leftptr,rightptr,dstptr,status)248a472b3eSmickey sgl_fsub(leftptr, rightptr, dstptr, status)
258a472b3eSmickey     sgl_floating_point *leftptr, *rightptr, *dstptr;
268a472b3eSmickey     unsigned int *status;
278a472b3eSmickey {
288a472b3eSmickey     register unsigned int left, right, result, extent;
298a472b3eSmickey     register unsigned int signless_upper_left, signless_upper_right, save;
308a472b3eSmickey 
318a472b3eSmickey     register int result_exponent, right_exponent, diff_exponent;
328a472b3eSmickey     register int sign_save, jumpsize;
33628bbdd4Smickey     register int inexact = FALSE, underflowtrap;
348a472b3eSmickey 
358a472b3eSmickey     /* Create local copies of the numbers */
368a472b3eSmickey     left = *leftptr;
378a472b3eSmickey     right = *rightptr;
388a472b3eSmickey 
398a472b3eSmickey     /* A zero "save" helps discover equal operands (for later),	*
408a472b3eSmickey      * and is used in swapping operands (if needed).		*/
418a472b3eSmickey     Sgl_xortointp1(left,right,/*to*/save);
428a472b3eSmickey 
438a472b3eSmickey     /*
448a472b3eSmickey      * check first operand for NaN's or infinity
458a472b3eSmickey      */
468a472b3eSmickey     if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT)
478a472b3eSmickey 	{
488a472b3eSmickey 	if (Sgl_iszero_mantissa(left))
498a472b3eSmickey 	    {
508a472b3eSmickey 	    if (Sgl_isnotnan(right))
518a472b3eSmickey 		{
528a472b3eSmickey 		if (Sgl_isinfinity(right) && save==0)
538a472b3eSmickey 		    {
548a472b3eSmickey 		    /*
558a472b3eSmickey 		     * invalid since operands are same signed infinity's
568a472b3eSmickey 		     */
578a472b3eSmickey 		    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
588a472b3eSmickey 		    Set_invalidflag();
598a472b3eSmickey 		    Sgl_makequietnan(result);
608a472b3eSmickey 		    *dstptr = result;
618a472b3eSmickey 		    return(NOEXCEPTION);
628a472b3eSmickey 		    }
638a472b3eSmickey 		/*
648a472b3eSmickey 		 * return infinity
658a472b3eSmickey 		 */
668a472b3eSmickey 		*dstptr = left;
678a472b3eSmickey 		return(NOEXCEPTION);
688a472b3eSmickey 		}
698a472b3eSmickey 	    }
708a472b3eSmickey 	else
718a472b3eSmickey 	    {
728a472b3eSmickey 	    /*
738a472b3eSmickey 	     * is NaN; signaling or quiet?
748a472b3eSmickey 	     */
758a472b3eSmickey 	    if (Sgl_isone_signaling(left))
768a472b3eSmickey 		{
778a472b3eSmickey 		/* trap if INVALIDTRAP enabled */
788a472b3eSmickey 		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
798a472b3eSmickey 		/* make NaN quiet */
808a472b3eSmickey 		Set_invalidflag();
818a472b3eSmickey 		Sgl_set_quiet(left);
828a472b3eSmickey 		}
838a472b3eSmickey 	    /*
848a472b3eSmickey 	     * is second operand a signaling NaN?
858a472b3eSmickey 	     */
868a472b3eSmickey 	    else if (Sgl_is_signalingnan(right))
878a472b3eSmickey 		{
888a472b3eSmickey 		/* trap if INVALIDTRAP enabled */
898a472b3eSmickey 		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
908a472b3eSmickey 		/* make NaN quiet */
918a472b3eSmickey 		Set_invalidflag();
928a472b3eSmickey 		Sgl_set_quiet(right);
938a472b3eSmickey 		*dstptr = right;
948a472b3eSmickey 		return(NOEXCEPTION);
958a472b3eSmickey 		}
968a472b3eSmickey 	    /*
978a472b3eSmickey 	     * return quiet NaN
988a472b3eSmickey 	     */
998a472b3eSmickey 	    *dstptr = left;
1008a472b3eSmickey 	    return(NOEXCEPTION);
1018a472b3eSmickey 	    }
1028a472b3eSmickey 	} /* End left NaN or Infinity processing */
1038a472b3eSmickey     /*
1048a472b3eSmickey      * check second operand for NaN's or infinity
1058a472b3eSmickey      */
1068a472b3eSmickey     if (Sgl_isinfinity_exponent(right))
1078a472b3eSmickey 	{
1088a472b3eSmickey 	if (Sgl_iszero_mantissa(right))
1098a472b3eSmickey 	    {
1108a472b3eSmickey 	    /* return infinity */
1118a472b3eSmickey 	    Sgl_invert_sign(right);
1128a472b3eSmickey 	    *dstptr = right;
1138a472b3eSmickey 	    return(NOEXCEPTION);
1148a472b3eSmickey 	    }
1158a472b3eSmickey 	/*
1168a472b3eSmickey 	 * is NaN; signaling or quiet?
1178a472b3eSmickey 	 */
1188a472b3eSmickey 	if (Sgl_isone_signaling(right))
1198a472b3eSmickey 	    {
1208a472b3eSmickey 	    /* trap if INVALIDTRAP enabled */
1218a472b3eSmickey 	    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
1228a472b3eSmickey 	    /* make NaN quiet */
1238a472b3eSmickey 	    Set_invalidflag();
1248a472b3eSmickey 	    Sgl_set_quiet(right);
1258a472b3eSmickey 	    }
1268a472b3eSmickey 	/*
1278a472b3eSmickey 	 * return quiet NaN
1288a472b3eSmickey 	 */
1298a472b3eSmickey 	*dstptr = right;
1308a472b3eSmickey 	return(NOEXCEPTION);
1318a472b3eSmickey 	} /* End right NaN or Infinity processing */
1328a472b3eSmickey 
1338a472b3eSmickey     /* Invariant: Must be dealing with finite numbers */
1348a472b3eSmickey 
1358a472b3eSmickey     /* Compare operands by removing the sign */
1368a472b3eSmickey     Sgl_copytoint_exponentmantissa(left,signless_upper_left);
1378a472b3eSmickey     Sgl_copytoint_exponentmantissa(right,signless_upper_right);
1388a472b3eSmickey 
1398a472b3eSmickey     /* sign difference selects sub or add operation. */
1408a472b3eSmickey     if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right))
1418a472b3eSmickey 	{
1428a472b3eSmickey 	/* Set the left operand to the larger one by XOR swap *
1438a472b3eSmickey 	 *  First finish the first word using "save"	  */
1448a472b3eSmickey 	Sgl_xorfromintp1(save,right,/*to*/right);
1458a472b3eSmickey 	Sgl_xorfromintp1(save,left,/*to*/left);
1468a472b3eSmickey 	result_exponent = Sgl_exponent(left);
1478a472b3eSmickey 	Sgl_invert_sign(left);
1488a472b3eSmickey 	}
1498a472b3eSmickey     /* Invariant:  left is not smaller than right. */
1508a472b3eSmickey 
1518a472b3eSmickey     if((right_exponent = Sgl_exponent(right)) == 0)
1528a472b3eSmickey 	{
1538a472b3eSmickey 	/* Denormalized operands.  First look for zeroes */
1548a472b3eSmickey 	if(Sgl_iszero_mantissa(right))
1558a472b3eSmickey 	    {
1568a472b3eSmickey 	    /* right is zero */
1578a472b3eSmickey 	    if(Sgl_iszero_exponentmantissa(left))
1588a472b3eSmickey 		{
1598a472b3eSmickey 		/* Both operands are zeros */
1608a472b3eSmickey 		Sgl_invert_sign(right);
1618a472b3eSmickey 		if(Is_rounding_mode(ROUNDMINUS))
1628a472b3eSmickey 		    {
1638a472b3eSmickey 		    Sgl_or_signs(left,/*with*/right);
1648a472b3eSmickey 		    }
1658a472b3eSmickey 		else
1668a472b3eSmickey 		    {
1678a472b3eSmickey 		    Sgl_and_signs(left,/*with*/right);
1688a472b3eSmickey 		    }
1698a472b3eSmickey 		}
1708a472b3eSmickey 	    else
1718a472b3eSmickey 		{
1728a472b3eSmickey 		/* Left is not a zero and must be the result.  Trapped
1738a472b3eSmickey 		 * underflows are signaled if left is denormalized.  Result
1748a472b3eSmickey 		 * is always exact. */
1758a472b3eSmickey 		if( (result_exponent == 0) && Is_underflowtrap_enabled() )
1768a472b3eSmickey 		    {
1778a472b3eSmickey 		    /* need to normalize results mantissa */
1788a472b3eSmickey 		    sign_save = Sgl_signextendedsign(left);
1798a472b3eSmickey 		    Sgl_leftshiftby1(left);
1808a472b3eSmickey 		    Sgl_normalize(left,result_exponent);
1818a472b3eSmickey 		    Sgl_set_sign(left,/*using*/sign_save);
1828a472b3eSmickey 		    Sgl_setwrapped_exponent(left,result_exponent,unfl);
1838a472b3eSmickey 		    *dstptr = left;
1848a472b3eSmickey 		    /* inexact = FALSE */
1858a472b3eSmickey 		    return(UNDERFLOWEXCEPTION);
1868a472b3eSmickey 		    }
1878a472b3eSmickey 		}
1888a472b3eSmickey 	    *dstptr = left;
1898a472b3eSmickey 	    return(NOEXCEPTION);
1908a472b3eSmickey 	    }
1918a472b3eSmickey 
1928a472b3eSmickey 	/* Neither are zeroes */
1938a472b3eSmickey 	Sgl_clear_sign(right);	/* Exponent is already cleared */
1948a472b3eSmickey 	if(result_exponent == 0 )
1958a472b3eSmickey 	    {
1968a472b3eSmickey 	    /* Both operands are denormalized.  The result must be exact
1978a472b3eSmickey 	     * and is simply calculated.  A sum could become normalized and a
1988a472b3eSmickey 	     * difference could cancel to a true zero. */
1998a472b3eSmickey 	    if( (/*signed*/int) save >= 0 )
2008a472b3eSmickey 		{
2018a472b3eSmickey 		Sgl_subtract(left,/*minus*/right,/*into*/result);
2028a472b3eSmickey 		if(Sgl_iszero_mantissa(result))
2038a472b3eSmickey 		    {
2048a472b3eSmickey 		    if(Is_rounding_mode(ROUNDMINUS))
2058a472b3eSmickey 			{
2068a472b3eSmickey 			Sgl_setone_sign(result);
2078a472b3eSmickey 			}
2088a472b3eSmickey 		    else
2098a472b3eSmickey 			{
2108a472b3eSmickey 			Sgl_setzero_sign(result);
2118a472b3eSmickey 			}
2128a472b3eSmickey 		    *dstptr = result;
2138a472b3eSmickey 		    return(NOEXCEPTION);
2148a472b3eSmickey 		    }
2158a472b3eSmickey 		}
2168a472b3eSmickey 	    else
2178a472b3eSmickey 		{
2188a472b3eSmickey 		Sgl_addition(left,right,/*into*/result);
2198a472b3eSmickey 		if(Sgl_isone_hidden(result))
2208a472b3eSmickey 		    {
2218a472b3eSmickey 		    *dstptr = result;
2228a472b3eSmickey 		    return(NOEXCEPTION);
2238a472b3eSmickey 		    }
2248a472b3eSmickey 		}
2258a472b3eSmickey 	    if(Is_underflowtrap_enabled())
2268a472b3eSmickey 		{
2278a472b3eSmickey 		/* need to normalize result */
2288a472b3eSmickey 		sign_save = Sgl_signextendedsign(result);
2298a472b3eSmickey 		Sgl_leftshiftby1(result);
2308a472b3eSmickey 		Sgl_normalize(result,result_exponent);
2318a472b3eSmickey 		Sgl_set_sign(result,/*using*/sign_save);
2328a472b3eSmickey 		Sgl_setwrapped_exponent(result,result_exponent,unfl);
2338a472b3eSmickey 		*dstptr = result;
2348a472b3eSmickey 		/* inexact = FALSE */
2358a472b3eSmickey 		return(UNDERFLOWEXCEPTION);
2368a472b3eSmickey 		}
2378a472b3eSmickey 	    *dstptr = result;
2388a472b3eSmickey 	    return(NOEXCEPTION);
2398a472b3eSmickey 	    }
2408a472b3eSmickey 	right_exponent = 1;	/* Set exponent to reflect different bias
2418a472b3eSmickey 				 * with denomalized numbers. */
2428a472b3eSmickey 	}
2438a472b3eSmickey     else
2448a472b3eSmickey 	{
2458a472b3eSmickey 	Sgl_clear_signexponent_set_hidden(right);
2468a472b3eSmickey 	}
2478a472b3eSmickey     Sgl_clear_exponent_set_hidden(left);
2488a472b3eSmickey     diff_exponent = result_exponent - right_exponent;
2498a472b3eSmickey 
2508a472b3eSmickey     /*
2518a472b3eSmickey      * Special case alignment of operands that would force alignment
2528a472b3eSmickey      * beyond the extent of the extension.  A further optimization
2538a472b3eSmickey      * could special case this but only reduces the path length for this
2548a472b3eSmickey      * infrequent case.
2558a472b3eSmickey      */
2568a472b3eSmickey     if(diff_exponent > SGL_THRESHOLD)
2578a472b3eSmickey 	{
2588a472b3eSmickey 	diff_exponent = SGL_THRESHOLD;
2598a472b3eSmickey 	}
2608a472b3eSmickey 
2618a472b3eSmickey     /* Align right operand by shifting to right */
2628a472b3eSmickey     Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent,
2638a472b3eSmickey       /*and lower to*/extent);
2648a472b3eSmickey 
2658a472b3eSmickey     /* Treat sum and difference of the operands separately. */
2668a472b3eSmickey     if( (/*signed*/int) save >= 0 )
2678a472b3eSmickey 	{
2688a472b3eSmickey 	/*
2698a472b3eSmickey 	 * Difference of the two operands.  Their can be no overflow.  A
2708a472b3eSmickey 	 * borrow can occur out of the hidden bit and force a post
2718a472b3eSmickey 	 * normalization phase.
2728a472b3eSmickey 	 */
2738a472b3eSmickey 	Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result);
2748a472b3eSmickey 	if(Sgl_iszero_hidden(result))
2758a472b3eSmickey 	    {
2768a472b3eSmickey 	    /* Handle normalization */
277*b466ace6Sderaadt 	    /* A straight forward algorithm would now shift the result
2788a472b3eSmickey 	     * and extension left until the hidden bit becomes one.  Not
2798a472b3eSmickey 	     * all of the extension bits need participate in the shift.
2808a472b3eSmickey 	     * Only the two most significant bits (round and guard) are
2818a472b3eSmickey 	     * needed.  If only a single shift is needed then the guard
2828a472b3eSmickey 	     * bit becomes a significant low order bit and the extension
2838a472b3eSmickey 	     * must participate in the rounding.  If more than a single
2848a472b3eSmickey 	     * shift is needed, then all bits to the right of the guard
2858a472b3eSmickey 	     * bit are zeros, and the guard bit may or may not be zero. */
2868a472b3eSmickey 	    sign_save = Sgl_signextendedsign(result);
2878a472b3eSmickey 	    Sgl_leftshiftby1_withextent(result,extent,result);
2888a472b3eSmickey 
2898a472b3eSmickey 	    /* Need to check for a zero result.  The sign and exponent
2908a472b3eSmickey 	     * fields have already been zeroed.  The more efficient test
2918a472b3eSmickey 	     * of the full object can be used.
2928a472b3eSmickey 	     */
2938a472b3eSmickey 	    if(Sgl_iszero(result))
2948a472b3eSmickey 		/* Must have been "x-x" or "x+(-x)". */
2958a472b3eSmickey 		{
2968a472b3eSmickey 		if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result);
2978a472b3eSmickey 		*dstptr = result;
2988a472b3eSmickey 		return(NOEXCEPTION);
2998a472b3eSmickey 		}
3008a472b3eSmickey 	    result_exponent--;
3018a472b3eSmickey 	    /* Look to see if normalization is finished. */
3028a472b3eSmickey 	    if(Sgl_isone_hidden(result))
3038a472b3eSmickey 		{
3048a472b3eSmickey 		if(result_exponent==0)
3058a472b3eSmickey 		    {
3068a472b3eSmickey 		    /* Denormalized, exponent should be zero.  Left operand *
3078a472b3eSmickey 		     * was normalized, so extent (guard, round) was zero    */
3088a472b3eSmickey 		    goto underflow;
3098a472b3eSmickey 		    }
3108a472b3eSmickey 		else
3118a472b3eSmickey 		    {
3128a472b3eSmickey 		    /* No further normalization is needed. */
3138a472b3eSmickey 		    Sgl_set_sign(result,/*using*/sign_save);
3148a472b3eSmickey 		    Ext_leftshiftby1(extent);
3158a472b3eSmickey 		    goto round;
3168a472b3eSmickey 		    }
3178a472b3eSmickey 		}
3188a472b3eSmickey 
3198a472b3eSmickey 	    /* Check for denormalized, exponent should be zero.  Left    *
3208a472b3eSmickey 	     * operand was normalized, so extent (guard, round) was zero */
3218a472b3eSmickey 	    if(!(underflowtrap = Is_underflowtrap_enabled()) &&
3228a472b3eSmickey 	       result_exponent==0) goto underflow;
3238a472b3eSmickey 
3248a472b3eSmickey 	    /* Shift extension to complete one bit of normalization and
3258a472b3eSmickey 	     * update exponent. */
3268a472b3eSmickey 	    Ext_leftshiftby1(extent);
3278a472b3eSmickey 
3288a472b3eSmickey 	    /* Discover first one bit to determine shift amount.  Use a
3298a472b3eSmickey 	     * modified binary search.  We have already shifted the result
3308a472b3eSmickey 	     * one position right and still not found a one so the remainder
3318a472b3eSmickey 	     * of the extension must be zero and simplifies rounding. */
3328a472b3eSmickey 	    /* Scan bytes */
3338a472b3eSmickey 	    while(Sgl_iszero_hiddenhigh7mantissa(result))
3348a472b3eSmickey 		{
3358a472b3eSmickey 		Sgl_leftshiftby8(result);
3368a472b3eSmickey 		if((result_exponent -= 8) <= 0  && !underflowtrap)
3378a472b3eSmickey 		    goto underflow;
3388a472b3eSmickey 		}
3398a472b3eSmickey 	    /* Now narrow it down to the nibble */
3408a472b3eSmickey 	    if(Sgl_iszero_hiddenhigh3mantissa(result))
3418a472b3eSmickey 		{
3428a472b3eSmickey 		/* The lower nibble contains the normalizing one */
3438a472b3eSmickey 		Sgl_leftshiftby4(result);
3448a472b3eSmickey 		if((result_exponent -= 4) <= 0 && !underflowtrap)
3458a472b3eSmickey 		    goto underflow;
3468a472b3eSmickey 		}
3478a472b3eSmickey 	    /* Select case were first bit is set (already normalized)
3488a472b3eSmickey 	     * otherwise select the proper shift. */
3498a472b3eSmickey 	    if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7)
3508a472b3eSmickey 		{
3518a472b3eSmickey 		/* Already normalized */
3528a472b3eSmickey 		if(result_exponent <= 0) goto underflow;
3538a472b3eSmickey 		Sgl_set_sign(result,/*using*/sign_save);
3548a472b3eSmickey 		Sgl_set_exponent(result,/*using*/result_exponent);
3558a472b3eSmickey 		*dstptr = result;
3568a472b3eSmickey 		return(NOEXCEPTION);
3578a472b3eSmickey 		}
3588a472b3eSmickey 	    Sgl_sethigh4bits(result,/*using*/sign_save);
3598a472b3eSmickey 	    switch(jumpsize)
3608a472b3eSmickey 		{
3618a472b3eSmickey 		case 1:
3628a472b3eSmickey 		    {
3638a472b3eSmickey 		    Sgl_leftshiftby3(result);
3648a472b3eSmickey 		    result_exponent -= 3;
3658a472b3eSmickey 		    break;
3668a472b3eSmickey 		    }
3678a472b3eSmickey 		case 2:
3688a472b3eSmickey 		case 3:
3698a472b3eSmickey 		    {
3708a472b3eSmickey 		    Sgl_leftshiftby2(result);
3718a472b3eSmickey 		    result_exponent -= 2;
3728a472b3eSmickey 		    break;
3738a472b3eSmickey 		    }
3748a472b3eSmickey 		case 4:
3758a472b3eSmickey 		case 5:
3768a472b3eSmickey 		case 6:
3778a472b3eSmickey 		case 7:
3788a472b3eSmickey 		    {
3798a472b3eSmickey 		    Sgl_leftshiftby1(result);
3808a472b3eSmickey 		    result_exponent -= 1;
3818a472b3eSmickey 		    break;
3828a472b3eSmickey 		    }
3838a472b3eSmickey 		}
3848a472b3eSmickey 	    if(result_exponent > 0)
3858a472b3eSmickey 		{
3868a472b3eSmickey 		Sgl_set_exponent(result,/*using*/result_exponent);
3878a472b3eSmickey 		*dstptr = result;	/* Sign bit is already set */
3888a472b3eSmickey 		return(NOEXCEPTION);
3898a472b3eSmickey 		}
3908a472b3eSmickey 	    /* Fixup potential underflows */
3918a472b3eSmickey 	  underflow:
3928a472b3eSmickey 	    if(Is_underflowtrap_enabled())
3938a472b3eSmickey 		{
3948a472b3eSmickey 		Sgl_set_sign(result,sign_save);
3958a472b3eSmickey 		Sgl_setwrapped_exponent(result,result_exponent,unfl);
3968a472b3eSmickey 		*dstptr = result;
3978a472b3eSmickey 		/* inexact = FALSE */
3988a472b3eSmickey 		return(UNDERFLOWEXCEPTION);
3998a472b3eSmickey 		}
4008a472b3eSmickey 	    /*
4018a472b3eSmickey 	     * Since we cannot get an inexact denormalized result,
4028a472b3eSmickey 	     * we can now return.
4038a472b3eSmickey 	     */
4048a472b3eSmickey 	    Sgl_right_align(result,/*by*/(1-result_exponent),extent);
4058a472b3eSmickey 	    Sgl_clear_signexponent(result);
4068a472b3eSmickey 	    Sgl_set_sign(result,sign_save);
4078a472b3eSmickey 	    *dstptr = result;
4088a472b3eSmickey 	    return(NOEXCEPTION);
4098a472b3eSmickey 	    } /* end if(hidden...)... */
4108a472b3eSmickey 	/* Fall through and round */
4118a472b3eSmickey 	} /* end if(save >= 0)... */
4128a472b3eSmickey     else
4138a472b3eSmickey 	{
4148a472b3eSmickey 	/* Add magnitudes */
4158a472b3eSmickey 	Sgl_addition(left,right,/*to*/result);
4168a472b3eSmickey 	if(Sgl_isone_hiddenoverflow(result))
4178a472b3eSmickey 	    {
4188a472b3eSmickey 	    /* Prenormalization required. */
4198a472b3eSmickey 	    Sgl_rightshiftby1_withextent(result,extent,extent);
4208a472b3eSmickey 	    Sgl_arithrightshiftby1(result);
4218a472b3eSmickey 	    result_exponent++;
4228a472b3eSmickey 	    } /* end if hiddenoverflow... */
4238a472b3eSmickey 	} /* end else ...sub magnitudes... */
4248a472b3eSmickey 
4258a472b3eSmickey     /* Round the result.  If the extension is all zeros,then the result is
4268a472b3eSmickey      * exact.  Otherwise round in the correct direction.  No underflow is
4278a472b3eSmickey      * possible. If a postnormalization is necessary, then the mantissa is
4288a472b3eSmickey      * all zeros so no shift is needed. */
4298a472b3eSmickey   round:
4308a472b3eSmickey     if(Ext_isnotzero(extent))
4318a472b3eSmickey 	{
4328a472b3eSmickey 	inexact = TRUE;
4338a472b3eSmickey 	switch(Rounding_mode())
4348a472b3eSmickey 	    {
4358a472b3eSmickey 	    case ROUNDNEAREST: /* The default. */
4368a472b3eSmickey 	    if(Ext_isone_sign(extent))
4378a472b3eSmickey 		{
4388a472b3eSmickey 		/* at least 1/2 ulp */
4398a472b3eSmickey 		if(Ext_isnotzero_lower(extent)  ||
4408a472b3eSmickey 		  Sgl_isone_lowmantissa(result))
4418a472b3eSmickey 		    {
4428a472b3eSmickey 		    /* either exactly half way and odd or more than 1/2ulp */
4438a472b3eSmickey 		    Sgl_increment(result);
4448a472b3eSmickey 		    }
4458a472b3eSmickey 		}
4468a472b3eSmickey 	    break;
4478a472b3eSmickey 
4488a472b3eSmickey 	    case ROUNDPLUS:
4498a472b3eSmickey 	    if(Sgl_iszero_sign(result))
4508a472b3eSmickey 		{
4518a472b3eSmickey 		/* Round up positive results */
4528a472b3eSmickey 		Sgl_increment(result);
4538a472b3eSmickey 		}
4548a472b3eSmickey 	    break;
4558a472b3eSmickey 
4568a472b3eSmickey 	    case ROUNDMINUS:
4578a472b3eSmickey 	    if(Sgl_isone_sign(result))
4588a472b3eSmickey 		{
4598a472b3eSmickey 		/* Round down negative results */
4608a472b3eSmickey 		Sgl_increment(result);
4618a472b3eSmickey 		}
4628a472b3eSmickey 
4638a472b3eSmickey 	    case ROUNDZERO:;
4648a472b3eSmickey 	    /* truncate is simple */
4658a472b3eSmickey 	    } /* end switch... */
4668a472b3eSmickey 	if(Sgl_isone_hiddenoverflow(result)) result_exponent++;
4678a472b3eSmickey 	}
4688a472b3eSmickey     if(result_exponent == SGL_INFINITY_EXPONENT)
4698a472b3eSmickey 	{
4708a472b3eSmickey 	/* Overflow */
4718a472b3eSmickey 	if(Is_overflowtrap_enabled())
4728a472b3eSmickey 	    {
4738a472b3eSmickey 	    Sgl_setwrapped_exponent(result,result_exponent,ovfl);
4748a472b3eSmickey 	    *dstptr = result;
475b94afd46Smickey 	    if (inexact) {
4768a472b3eSmickey 		if (Is_inexacttrap_enabled())
4778a472b3eSmickey 		    return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
4788a472b3eSmickey 		else Set_inexactflag();
479b94afd46Smickey 	    }
4808a472b3eSmickey 	    return(OVERFLOWEXCEPTION);
4818a472b3eSmickey 	    }
4828a472b3eSmickey 	else
4838a472b3eSmickey 	    {
4848a472b3eSmickey 	    Set_overflowflag();
4858a472b3eSmickey 	    inexact = TRUE;
4868a472b3eSmickey 	    Sgl_setoverflow(result);
4878a472b3eSmickey 	    }
4888a472b3eSmickey 	}
4898a472b3eSmickey     else Sgl_set_exponent(result,result_exponent);
4908a472b3eSmickey     *dstptr = result;
491b94afd46Smickey     if(inexact) {
4928a472b3eSmickey 	if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
4938a472b3eSmickey 	else Set_inexactflag();
494b94afd46Smickey     }
4958a472b3eSmickey     return(NOEXCEPTION);
4968a472b3eSmickey }
497