code:
/*	$OpenBSD: dfsub.c,v 1.7 2002/11/29 09:27:34 deraadt Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)dfsub.c: Revision: 2.8.88.1 Date: 93/12/07 15:05:48 */

#include "float.h"
#include "dbl_float.h"

/*
 * Double_subtract: subtract two double precision values.
 */
int
dbl_fsub(leftptr, rightptr, dstptr, status)
    dbl_floating_point *leftptr, *rightptr, *dstptr;
    unsigned int *status;
{
    register unsigned int signless_upper_left, signless_upper_right, save;
    register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
    register unsigned int resultp1 = 0, resultp2 = 0;

    register int result_exponent, right_exponent, diff_exponent;
    register int sign_save, jumpsize;
    register int inexact = FALSE, underflowtrap;

    /* Create local copies of the numbers */
    Dbl_copyfromptr(leftptr,leftp1,leftp2);
    Dbl_copyfromptr(rightptr,rightp1,rightp2);

    /* A zero "save" helps discover equal operands (for later),  *
     * and is used in swapping operands (if needed).	     */
    Dbl_xortointp1(leftp1,rightp1,/*to*/save);

    /*
     * check first operand for NaN's or infinity
     */
    if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
	{
	if (Dbl_iszero_mantissa(leftp1,leftp2))
	    {
	    if (Dbl_isnotnan(rightp1,rightp2))
		{
		if (Dbl_isinfinity(rightp1,rightp2) && save==0)
		    {
		    /*
		     * invalid since operands are same signed infinity's
		     */
		    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
		    Set_invalidflag();
		    Dbl_makequietnan(resultp1,resultp2);
		    Dbl_copytoptr(resultp1,resultp2,dstptr);
		    return(NOEXCEPTION);
		    }
		/*
		 * return infinity
		 */
		Dbl_copytoptr(leftp1,leftp2,dstptr);
		return(NOEXCEPTION);
		}
	    }
	else
	    {
	    /*
	     * is NaN; signaling or quiet?
	     */
	    if (Dbl_isone_signaling(leftp1))
		{
		/* trap if INVALIDTRAP enabled */
		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
		/* make NaN quiet */
		Set_invalidflag();
		Dbl_set_quiet(leftp1);
		}
	    /*
	     * is second operand a signaling NaN?
	     */
	    else if (Dbl_is_signalingnan(rightp1))
		{
		/* trap if INVALIDTRAP enabled */
		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
		/* make NaN quiet */
		Set_invalidflag();
		Dbl_set_quiet(rightp1);
		Dbl_copytoptr(rightp1,rightp2,dstptr);
		return(NOEXCEPTION);
		}
	    /*
	     * return quiet NaN
	     */
	    Dbl_copytoptr(leftp1,leftp2,dstptr);
	    return(NOEXCEPTION);
	    }
	} /* End left NaN or Infinity processing */
    /*
     * check second operand for NaN's or infinity
     */
    if (Dbl_isinfinity_exponent(rightp1))
	{
	if (Dbl_iszero_mantissa(rightp1,rightp2))
	    {
	    /* return infinity */
	    Dbl_invert_sign(rightp1);
	    Dbl_copytoptr(rightp1,rightp2,dstptr);
	    return(NOEXCEPTION);
	    }
	/*
	 * is NaN; signaling or quiet?
	 */
	if (Dbl_isone_signaling(rightp1))
	    {
	    /* trap if INVALIDTRAP enabled */
	    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
	    /* make NaN quiet */
	    Set_invalidflag();
	    Dbl_set_quiet(rightp1);
	    }
	/*
	 * return quiet NaN
	 */
	Dbl_copytoptr(rightp1,rightp2,dstptr);
	return(NOEXCEPTION);
	} /* End right NaN or Infinity processing */

    /* Invariant: Must be dealing with finite numbers */

    /* Compare operands by removing the sign */
    Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
    Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);

    /* sign difference selects add or sub operation. */
    if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
	{
	/* Set the left operand to the larger one by XOR swap *
	 *  First finish the first word using "save"	  */
	Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
	Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
	Dbl_swap_lower(leftp2,rightp2);
	result_exponent = Dbl_exponent(leftp1);
	Dbl_invert_sign(leftp1);
	}
    /* Invariant:  left is not smaller than right. */

    if((right_exponent = Dbl_exponent(rightp1)) == 0)
	{
	/* Denormalized operands.  First look for zeroes */
	if(Dbl_iszero_mantissa(rightp1,rightp2))
	    {
	    /* right is zero */
	    if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
		{
		/* Both operands are zeros */
		Dbl_invert_sign(rightp1);
		if(Is_rounding_mode(ROUNDMINUS))
		    {
		    Dbl_or_signs(leftp1,/*with*/rightp1);
		    }
		else
		    {
		    Dbl_and_signs(leftp1,/*with*/rightp1);
		    }
		}
	    else
		{
		/* Left is not a zero and must be the result.  Trapped
		 * underflows are signaled if left is denormalized.  Result
		 * is always exact. */
		if( (result_exponent == 0) && Is_underflowtrap_enabled() )
		    {
		    /* need to normalize results mantissa */
		    sign_save = Dbl_signextendedsign(leftp1);
		    Dbl_leftshiftby1(leftp1,leftp2);
		    Dbl_normalize(leftp1,leftp2,result_exponent);
		    Dbl_set_sign(leftp1,/*using*/sign_save);
		    Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
		    Dbl_copytoptr(leftp1,leftp2,dstptr);
		    /* inexact = FALSE */
		    return(UNDERFLOWEXCEPTION);
		    }
		}
	    Dbl_copytoptr(leftp1,leftp2,dstptr);
	    return(NOEXCEPTION);
	    }

	/* Neither are zeroes */
	Dbl_clear_sign(rightp1);	/* Exponent is already cleared */
	if(result_exponent == 0 )
	    {
	    /* Both operands are denormalized.  The result must be exact
	     * and is simply calculated.  A sum could become normalized and a
	     * difference could cancel to a true zero. */
	    if( (/*signed*/int) save >= 0 )
		{
		Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
		 /*into*/resultp1,resultp2);
		if(Dbl_iszero_mantissa(resultp1,resultp2))
		    {
		    if(Is_rounding_mode(ROUNDMINUS))
			{
			Dbl_setone_sign(resultp1);
			}
		    else
			{
			Dbl_setzero_sign(resultp1);
			}
		    Dbl_copytoptr(resultp1,resultp2,dstptr);
		    return(NOEXCEPTION);
		    }
		}
	    else
		{
		Dbl_addition(leftp1,leftp2,rightp1,rightp2,
		 /*into*/resultp1,resultp2);
		if(Dbl_isone_hidden(resultp1))
		    {
		    Dbl_copytoptr(resultp1,resultp2,dstptr);
		    return(NOEXCEPTION);
		    }
		}
	    if(Is_underflowtrap_enabled())
		{
		/* need to normalize result */
		sign_save = Dbl_signextendedsign(resultp1);
		Dbl_leftshiftby1(resultp1,resultp2);
		Dbl_normalize(resultp1,resultp2,result_exponent);
		Dbl_set_sign(resultp1,/*using*/sign_save);
		Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
		Dbl_copytoptr(resultp1,resultp2,dstptr);
		/* inexact = FALSE */
		return(UNDERFLOWEXCEPTION);
		}
	    Dbl_copytoptr(resultp1,resultp2,dstptr);
	    return(NOEXCEPTION);
	    }
	right_exponent = 1;	/* Set exponent to reflect different bias
				 * with denomalized numbers. */
	}
    else
	{
	Dbl_clear_signexponent_set_hidden(rightp1);
	}
    Dbl_clear_exponent_set_hidden(leftp1);
    diff_exponent = result_exponent - right_exponent;

    /*
     * Special case alignment of operands that would force alignment
     * beyond the extent of the extension.  A further optimization
     * could special case this but only reduces the path length for this
     * infrequent case.
     */
    if(diff_exponent > DBL_THRESHOLD)
	{
	diff_exponent = DBL_THRESHOLD;
	}

    /* Align right operand by shifting to right */
    Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
     /*and lower to*/extent);

    /* Treat sum and difference of the operands separately. */
    if( (/*signed*/int) save >= 0 )
	{
	/*
	 * Difference of the two operands.  Their can be no overflow.  A
	 * borrow can occur out of the hidden bit and force a post
	 * normalization phase.
	 */
	Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
	 /*with*/extent,/*into*/resultp1,resultp2);
	if(Dbl_iszero_hidden(resultp1))
	    {
	    /* Handle normalization */
	    /* A straight forward algorithm would now shift the result
	     * and extension left until the hidden bit becomes one.  Not
	     * all of the extension bits need participate in the shift.
	     * Only the two most significant bits (round and guard) are
	     * needed.  If only a single shift is needed then the guard
	     * bit becomes a significant low order bit and the extension
	     * must participate in the rounding.  If more than a single
	     * shift is needed, then all bits to the right of the guard
	     * bit are zeros, and the guard bit may or may not be zero. */
	    sign_save = Dbl_signextendedsign(resultp1);
	    Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);

	    /* Need to check for a zero result.  The sign and exponent
	     * fields have already been zeroed.  The more efficient test
	     * of the full object can be used.
	     */
	    if(Dbl_iszero(resultp1,resultp2))
		/* Must have been "x-x" or "x+(-x)". */
		{
		if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
		Dbl_copytoptr(resultp1,resultp2,dstptr);
		return(NOEXCEPTION);
		}
	    result_exponent--;
	    /* Look to see if normalization is finished. */
	    if(Dbl_isone_hidden(resultp1)) {
		if(result_exponent==0) {
		    /* Denormalized, exponent should be zero.  Left operand *
		     * was normalized, so extent (guard, round) was zero    */
		    goto underflow;
		} else {
			/* No further normalization is needed. */
			Dbl_set_sign(resultp1,/*using*/sign_save);
			Ext_leftshiftby1(extent);
			goto round;
		}
	    }

	    /* Check for denormalized, exponent should be zero.  Left    *
	     * operand was normalized, so extent (guard, round) was zero */
	    if(!(underflowtrap = Is_underflowtrap_enabled()) &&
	       result_exponent==0) goto underflow;

	    /* Shift extension to complete one bit of normalization and
	     * update exponent. */
	    Ext_leftshiftby1(extent);

	    /* Discover first one bit to determine shift amount.  Use a
	     * modified binary search.  We have already shifted the result
	     * one position right and still not found a one so the remainder
	     * of the extension must be zero and simplifies rounding. */
	    /* Scan bytes */
	    while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
		{
		Dbl_leftshiftby8(resultp1,resultp2);
		if((result_exponent -= 8) <= 0  && !underflowtrap)
		    goto underflow;
		}
	    /* Now narrow it down to the nibble */
	    if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
		{
		/* The lower nibble contains the normalizing one */
		Dbl_leftshiftby4(resultp1,resultp2);
		if((result_exponent -= 4) <= 0 && !underflowtrap)
		    goto underflow;
		}
	    /* Select case were first bit is set (already normalized)
	     * otherwise select the proper shift. */
	    if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
		{
		/* Already normalized */
		if(result_exponent <= 0) goto underflow;
		Dbl_set_sign(resultp1,/*using*/sign_save);
		Dbl_set_exponent(resultp1,/*using*/result_exponent);
		Dbl_copytoptr(resultp1,resultp2,dstptr);
		return(NOEXCEPTION);
		}
	    Dbl_sethigh4bits(resultp1,/*using*/sign_save);
	    switch(jumpsize)
		{
		case 1:
		    {
		    Dbl_leftshiftby3(resultp1,resultp2);
		    result_exponent -= 3;
		    break;
		    }
		case 2:
		case 3:
		    {
		    Dbl_leftshiftby2(resultp1,resultp2);
		    result_exponent -= 2;
		    break;
		    }
		case 4:
		case 5:
		case 6:
		case 7:
		    {
		    Dbl_leftshiftby1(resultp1,resultp2);
		    result_exponent -= 1;
		    break;
		    }
		}
	    if(result_exponent > 0)
		{
		Dbl_set_exponent(resultp1,/*using*/result_exponent);
		Dbl_copytoptr(resultp1,resultp2,dstptr);
		return(NOEXCEPTION);		/* Sign bit is already set */
		}
	    /* Fixup potential underflows */
	  underflow:
	    if(Is_underflowtrap_enabled())
		{
		Dbl_set_sign(resultp1,sign_save);
		Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
		Dbl_copytoptr(resultp1,resultp2,dstptr);
		/* inexact = FALSE */
		return(UNDERFLOWEXCEPTION);
		}
	    /*
	     * Since we cannot get an inexact denormalized result,
	     * we can now return.
	     */
	    Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
	    Dbl_clear_signexponent(resultp1);
	    Dbl_set_sign(resultp1,sign_save);
	    Dbl_copytoptr(resultp1,resultp2,dstptr);
	    return(NOEXCEPTION);
	    } /* end if(hidden...)... */
	/* Fall through and round */
	} /* end if(save >= 0)... */
    else
	{
	/* Subtract magnitudes */
	Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
	if(Dbl_isone_hiddenoverflow(resultp1))
	    {
	    /* Prenormalization required. */
	    Dbl_rightshiftby1_withextent(resultp2,extent,extent);
	    Dbl_arithrightshiftby1(resultp1,resultp2);
	    result_exponent++;
	    } /* end if hiddenoverflow... */
	} /* end else ...subtract magnitudes... */

    /* Round the result.  If the extension is all zeros,then the result is
     * exact.  Otherwise round in the correct direction.  No underflow is
     * possible. If a postnormalization is necessary, then the mantissa is
     * all zeros so no shift is needed. */
  round:
    if(Ext_isnotzero(extent))
	{
	inexact = TRUE;
	switch(Rounding_mode())
	    {
	    case ROUNDNEAREST: /* The default. */
	    if(Ext_isone_sign(extent))
		{
		/* at least 1/2 ulp */
		if(Ext_isnotzero_lower(extent)  ||
		  Dbl_isone_lowmantissap2(resultp2))
		    {
		    /* either exactly half way and odd or more than 1/2ulp */
		    Dbl_increment(resultp1,resultp2);
		    }
		}
	    break;

	    case ROUNDPLUS:
	    if(Dbl_iszero_sign(resultp1))
		{
		/* Round up positive results */
		Dbl_increment(resultp1,resultp2);
		}
	    break;

	    case ROUNDMINUS:
	    if(Dbl_isone_sign(resultp1))
		{
		/* Round down negative results */
		Dbl_increment(resultp1,resultp2);
		}

	    case ROUNDZERO:;
	    /* truncate is simple */
	    } /* end switch... */
	if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
	}
    if(result_exponent == DBL_INFINITY_EXPONENT)
	{
	/* Overflow */
	if(Is_overflowtrap_enabled())
	    {
	    Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
	    Dbl_copytoptr(resultp1,resultp2,dstptr);
	    if (inexact) {
		if (Is_inexacttrap_enabled())
		    return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
		else
		    Set_inexactflag();
	    }
	    return(OVERFLOWEXCEPTION);
	    }
	else
	    {
	    inexact = TRUE;
	    Set_overflowflag();
	    Dbl_setoverflow(resultp1,resultp2);
	    }
	}
    else Dbl_set_exponent(resultp1,result_exponent);
    Dbl_copytoptr(resultp1,resultp2,dstptr);
    if(inexact) {
	if(Is_inexacttrap_enabled())
		return(INEXACTEXCEPTION);
	else
		Set_inexactflag();
    }
    return(NOEXCEPTION);
}


code:
/*	$OpenBSD: divsfm.c,v 1.5 2002/05/07 22:19:30 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)divsfm.c: Revision: 1.6.88.1 Date: 93/12/07 15:05:51 */

#include "md.h"

void
divsfm(opnd1,opnd2,result)
	int opnd1, opnd2;
	struct mdsfu_register *result;
{
	register int sign, op1_sign;

	/* check divisor for zero */
	if (opnd2 == 0) {
		overflow = TRUE;
		return;
	}

	/* get sign of result */
	sign = opnd1 ^ opnd2;

	/* get absolute value of operands */
	if (opnd1 < 0) {
		opnd1 = -opnd1;
		op1_sign = TRUE;
	}
	else op1_sign = FALSE;
	if (opnd2 < 0) opnd2 = -opnd2;

	/*
	 * check for overflow
	 *
	 * if abs(opnd1) < 0, then opnd1 = -2**31
	 * and abs(opnd1) >= abs(opnd2) always
	 */
	if (opnd1 >= opnd2 || opnd1 < 0) {
		/* check for opnd2 = -2**31 */
		if (opnd2 < 0 && opnd1 != opnd2) {
			result_hi = 0;		/* remainder = 0 */
			result_lo = opnd1 << 1;
		}
		else {
			overflow = TRUE;
			return;
		}
	}
	else {
		/* do the divide */
		divu(opnd1,0,opnd2,result);

		/* return positive residue */
		if (op1_sign && result_hi) {
			result_hi = opnd2 - result_hi;
			result_lo++;
		}
	}

	/* check for overflow */
	if (result_lo < 0) {
		overflow = TRUE;
		return;
	}
	overflow = FALSE;

	/* return appropriately signed result */
	if (sign<0) result_lo = -result_lo;
	return;
}

license: unknown


code:
/*	$OpenBSD: divsfr.c,v 1.5 2002/05/07 22:19:30 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)divsfr.c: Revision: 1.6.88.1 Date: 93/12/07 15:05:53 */

#include "md.h"

void
divsfr(opnd1,opnd2,result)
	int opnd1, opnd2;
	struct mdsfu_register *result;
{
	int sign, op1_sign;

	/* check divisor for zero */
	if (opnd2 == 0) {
		overflow = TRUE;
		return;
	}

	/* get sign of result */
	sign = opnd1 ^ opnd2;

	/* get absolute value of operands */
	if (opnd1 < 0) {
		opnd1 = -opnd1;
		op1_sign = TRUE;
	}
	else op1_sign = FALSE;
	if (opnd2 < 0) opnd2 = -opnd2;

	/*
	 * check for overflow
	 *
	 * if abs(opnd1) < 0, then opnd1 = -2**31
	 * and abs(opnd1) >= abs(opnd2) always
	 */
	if (opnd1 >= opnd2 || opnd1 < 0) {
		/* check for opnd2 = -2**31 */
		if (opnd2 < 0 && opnd1 != opnd2) {
			result_hi = 0;		/* remainder = 0 */
			result_lo = opnd1 << 1;
		}
		else {
			overflow = TRUE;
			return;
		}
	}
	else {
		/* do the divide */
		divu(opnd1,0,opnd2,result);
	}

	/* check for overflow */
	if (result_lo < 0) {
		overflow = TRUE;
		return;
	}
	overflow = FALSE;

	/* return appropriately signed remainder and result */
	if (op1_sign) result_hi = -result_hi;
	if (sign<0) result_lo = -result_lo;
	return;
}


code:
/*	$OpenBSD: divsim.c,v 1.5 2002/05/07 22:19:30 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)divsim.c: Revision: 1.6.88.1 Date: 93/12/07 15:05:56 */

#include "md.h"

void
divsim(opnd1,opnd2,result)
	int opnd1, opnd2;
	struct mdsfu_register *result;
{
	int sign, op1_sign;

	/* check divisor for zero */
	if (opnd2 == 0) {
		overflow = TRUE;
		return;
	}

	/* get sign of result */
	sign = opnd1 ^ opnd2;

	/* get absolute value of operands */
	if (opnd1 < 0) {
		opnd1 = -opnd1;
		op1_sign = TRUE;
	}
	else op1_sign = FALSE;
	if (opnd2 < 0) opnd2 = -opnd2;

	/* check for opnd2 == -2**31 */
	if (opnd2 < 0) {
		if (opnd1 == opnd2) {
			result_hi = 0;	/* remainder = 0 */
			result_lo = 1;
		}
		else {
			result_hi = opnd1;	/* remainder = opnd1 */
			result_lo = 0;
		}
	}
	else {
		/* do the divide */
		divu(0,opnd1,opnd2,result);

		/*
		 * check for overflow
		 *
		 * at this point, the only way we can get overflow
		 * is with opnd1 = -2**31 and opnd2 = -1
		 */
		if (sign>0 && result_lo<0) {
			overflow = TRUE;
			return;
		}
	}
	overflow = FALSE;

	/* return positive residue */
	if (op1_sign && result_hi) {
		result_hi = opnd2 - result_hi;
		if (++result_lo < 0) {
			overflow = TRUE;
			return;
		}
	}

	/* return appropriately signed result */
	if (sign<0) result_lo = -result_lo;
	return;
}


code:
/*	$OpenBSD: divsir.c,v 1.6 2002/05/07 22:19:30 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)divsir.c: Revision: 1.6.88.1 Date: 93/12/07 15:05:58 */

#include "md.h"

void
divsir(opnd1,opnd2,result)
	int opnd1, opnd2;
	struct mdsfu_register *result;
{
	int sign, op1_sign;

	/* check divisor for zero */
	if (opnd2 == 0) {
		overflow = TRUE;
		return;
	}

	/* get sign of result */
	sign = opnd1 ^ opnd2;

	/* get absolute value of operands */
	if (opnd1 < 0) {
		opnd1 = -opnd1;
		op1_sign = TRUE;
	}
	else op1_sign = FALSE;
	if (opnd2 < 0) opnd2 = -opnd2;

	/* check for opnd2 = -2**31 */
	if (opnd2 + opnd2 == 0) {
		if (opnd1 == opnd2) {
			result_hi = 0;    /* remainder = 0 */
			result_lo = 1;
		}
		else {
			result_hi = opnd1;  /* remainder = opnd1 */
			result_lo = 0;
		}
	}
	else {
		/* do the divide */
		divu(0,opnd1,opnd2,result);

		/*
		 * check for overflow
		 *
		 * at this point, the only way we can get overflow
		 * is with opnd1 = -2**31 and opnd2 = -1
		 */
		if (sign>0 && result_lo<0) {
			overflow = TRUE;
			return;
		}
	}
	overflow = FALSE;

	/* return appropriately signed remainder and result */
	if (op1_sign) result_hi = -result_hi;
	if (sign<0) result_lo = -result_lo;
	return;
}


code:
/*	$OpenBSD: divu.S,v 1.11 2011/04/16 20:52:12 deraadt Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)divu.s: Revision: 1.11.88.1 Date: 93/12/07 15:06:01 */

#include <machine/asm.h>
#include <machine/frame.h>

;************************************************************************
; Implement an integer divide routine for 32-bit operands and 32-bit quotient
; and remainder with operand values of zero (divisor only) treated specially.
;
;****************************************************************************
; Definitions
;****************************************************************************
;
;	General registers
;
gr0	.reg		%r0		; General register zero
rem	.reg		%r3		; remainder and upper part of dividend
quo	.reg		%r4		; quotient and lower part of dividend
dvr	.reg		%r5		; divisor
tp	.reg		%r6		; temp. reg.

;******************************************************************************
	.text
LEAF_ENTRY(divu)
	stws,ma		rem,4(sp)		; save registers on stack
	stws,ma		quo,4(sp)		; save registers on stack
	stws,ma		dvr,4(sp)		; save registers on stack
	stws,ma		tp,4(sp)		; save registers on stack

	addi		0,arg2,dvr		; get divisor
	addi		0,arg1,quo		; get lower dividend
	addi		0,arg0,rem		; get upper dividend

	comib,>,n	0,dvr,hibit		; check for dvr >= 2**31
	addi		-1,gr0,tp		; set V-bit to 1
	ds		0,tp,0
	add		quo,quo,quo		; shift msb bit into carry
	ds		rem,dvr,rem		; 1st divide step, if carry
						;   out, msb of quotient = 0
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 2nd divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 3rd divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 4th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 5th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 6th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 7th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 8th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 9th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 10th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 11th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 12th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 13th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 14th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 15th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 16th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 17th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 18th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 19th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 20th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 21st divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 22nd divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 23rd divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 24th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 25th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 26th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 27th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 28th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 29th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 30th divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 31st divide step
	addc		quo,quo,quo		; shift quo with/into carry
	ds		rem,dvr,rem		; 32nd divide step,
	addc		quo,quo,quo		; shift last quo bit into quo
	addb,>=,n	rem,0,finish		; branch if pos. rem
	add,<		dvr,0,0			; if dvr > 0, add dvr
	add,tr		rem,dvr,rem		;   for correcting rem.
	sub		rem,dvr,rem		; else subtract dvr
;
;	end of divide routine
;
finish	stws		rem,0(arg3)		; save remainder in high part
						;   of result
	stws		quo,4(arg3)		; save quotient in low part
						;   of result
	ldws,mb		-4(sp),tp		; restore registers
	ldws,mb		-4(sp),dvr		; restore registers
	ldws,mb		-4(sp),quo		; restore registers
	bv		0(rp)			; return
	ldws,mb		-4(sp),rem		; restore registers
;
hibit	ldo		32(0),tp		; initialize loop counter
	add		quo,quo,quo		; shift high bit into carry
loop	addc		rem,rem,rem		; shift in high bit of dvdl
	addc,<>		0,0,0			; if bit shifted out of dvdu,
						;   want to do subtract
	comb,<<,n	rem,dvr,nosub		; if upper dividend > dvr,
	sub		rem,dvr,rem		;   subtract and
	add,tr		dvr,dvr,0		;   set carry
nosub	addi		0,0,0			; otherwise clear carry
	addib,>		-1,tp,loop		; inc. counter; finished?
	addc		quo,quo,quo		; shift bit of result into dvdl
	b		finish+4		; finish up
	stws		rem,0(arg3)		; save remainder in high part
						;   of result
EXIT(divu)

	.end


code:
/*	$OpenBSD: divufr.c,v 1.6 2002/05/07 22:19:30 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)divufr.c: Revision: 1.6.88.1 Date: 93/12/07 15:06:03 */

#include "md.h"

void
divufr(opnd1,opnd2,result)
	unsigned int opnd1, opnd2;
	struct mdsfu_register *result;
{
	/* check divisor for zero */
	if (opnd2 == 0) {
		overflow = TRUE;
		return;
	}

	/* check for overflow */
	if (opnd1 >= opnd2) {
		overflow = TRUE;
		return;
	}
	overflow = FALSE;

	/* do the divide */
	divu(opnd1,0,opnd2,result);
}


code:
/*	$OpenBSD: divuir.c,v 1.6 2002/05/07 22:19:30 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)divuir.c: Revision: 1.6.88.1 Date: 93/12/07 15:06:06 */

#include "md.h"

void
divuir(opnd1,opnd2,result)
	unsigned int opnd1, opnd2;
	struct mdsfu_register *result;
{
	/* get source operands, check divisor for zero */
	if (opnd2 == 0) {
		overflow = TRUE;
		return;
	}
	overflow = FALSE;

	/* do the divide */
	divu(0,opnd1,opnd2,result);
}


code:
/*	$OpenBSD: fcnvff.c,v 1.7 2003/04/10 17:27:58 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)fcnvff.c: Revision: 2.8.88.1 Date: 93/12/07 15:06:09 */

#include "float.h"
#include "sgl_float.h"
#include "dbl_float.h"
#include "cnv_float.h"

/*
 *  Single Floating-point to Double Floating-point
 */
/*ARGSUSED*/
int
sgl_to_dbl_fcnvff(srcptr, null, dstptr, status)
	sgl_floating_point *srcptr, *null;
	dbl_floating_point *dstptr;
	unsigned int *status;
{
	register unsigned int src, resultp1, resultp2;
	register int src_exponent;

	src = *srcptr;
	src_exponent = Sgl_exponent(src);
	Dbl_allp1(resultp1) = Sgl_all(src);  /* set sign of result */
	/*
	 * Test for NaN or infinity
	 */
	if (src_exponent == SGL_INFINITY_EXPONENT) {
		/*
		 * determine if NaN or infinity
		 */
		if (Sgl_iszero_mantissa(src)) {
			/*
			 * is infinity; want to return double infinity
			 */
			Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
			Dbl_copytoptr(resultp1,resultp2,dstptr);
			return(NOEXCEPTION);
		}
		else {
			/*
			 * is NaN; signaling or quiet?
			 */
			if (Sgl_isone_signaling(src)) {
				/* trap if INVALIDTRAP enabled */
				if (Is_invalidtrap_enabled())
					return(INVALIDEXCEPTION);
				/* make NaN quiet */
				else {
					Set_invalidflag();
					Sgl_set_quiet(src);
				}
			}
			/*
			 * NaN is quiet, return as double NaN
			 */
			Dbl_setinfinity_exponent(resultp1);
			Sgl_to_dbl_mantissa(src,resultp1,resultp2);
			Dbl_copytoptr(resultp1,resultp2,dstptr);
			return(NOEXCEPTION);
		}
	}
	/*
	 * Test for zero or denormalized
	 */
	if (src_exponent == 0) {
		/*
		 * determine if zero or denormalized
		 */
		if (Sgl_isnotzero_mantissa(src)) {
			/*
			 * is denormalized; want to normalize
			 */
			Sgl_clear_signexponent(src);
			Sgl_leftshiftby1(src);
			Sgl_normalize(src,src_exponent);
			Sgl_to_dbl_exponent(src_exponent,resultp1);
			Sgl_to_dbl_mantissa(src,resultp1,resultp2);
		}
		else {
			Dbl_setzero_exponentmantissa(resultp1,resultp2);
		}
		Dbl_copytoptr(resultp1,resultp2,dstptr);
		return(NOEXCEPTION);
	}
	/*
	 * No special cases, just complete the conversion
	 */
	Sgl_to_dbl_exponent(src_exponent, resultp1);
	Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
	Dbl_copytoptr(resultp1,resultp2,dstptr);
	return(NOEXCEPTION);
}

/*
 *  Double Floating-point to Single Floating-point
 */
/*ARGSUSED*/
int
dbl_to_sgl_fcnvff(srcptr, null, dstptr, status)
	dbl_floating_point *srcptr, *null;
	sgl_floating_point *dstptr;
	unsigned int *status;
{
	register unsigned int srcp1, srcp2, result;
	register int src_exponent, dest_exponent, dest_mantissa;
	register int inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
	register int lsb_odd = FALSE;
	int is_tiny;

	Dbl_copyfromptr(srcptr,srcp1,srcp2);
	src_exponent = Dbl_exponent(srcp1);
	Sgl_all(result) = Dbl_allp1(srcp1);  /* set sign of result */
	/*
	 * Test for NaN or infinity
	 */
	if (src_exponent == DBL_INFINITY_EXPONENT) {
		/*
		 * determine if NaN or infinity
		 */
		if (Dbl_iszero_mantissa(srcp1,srcp2)) {
			/*
			 * is infinity; want to return single infinity
			 */
			Sgl_setinfinity_exponentmantissa(result);
			*dstptr = result;
			return(NOEXCEPTION);
		}
		/*
		 * is NaN; signaling or quiet?
		 */
		if (Dbl_isone_signaling(srcp1)) {
			/* trap if INVALIDTRAP enabled */
			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
			else {
				Set_invalidflag();
				/* make NaN quiet */
				Dbl_set_quiet(srcp1);
			}
		}
		/*
		 * NaN is quiet, return as single NaN
		 */
		Sgl_setinfinity_exponent(result);
		Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
		if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
		*dstptr = result;
		return(NOEXCEPTION);
	}
	/*
	 * Generate result
	 */
	Dbl_to_sgl_exponent(src_exponent,dest_exponent);
	if (dest_exponent > 0) {
		Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit,
		stickybit,lsb_odd);
	}
	else {
		if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
			Sgl_setzero_exponentmantissa(result);
			*dstptr = result;
			return(NOEXCEPTION);
		}
		if (Is_underflowtrap_enabled()) {
			Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
			guardbit,stickybit,lsb_odd);
		}
		else {
			/* compute result, determine inexact info,
			 * and set Underflowflag if appropriate
			 */
			Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
			dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
			is_tiny);
		}
	}
	/*
	 * Now round result if not exact
	 */
	if (inexact) {
		switch (Rounding_mode()) {
			case ROUNDPLUS:
				if (Sgl_iszero_sign(result)) dest_mantissa++;
				break;
			case ROUNDMINUS:
				if (Sgl_isone_sign(result)) dest_mantissa++;
				break;
			case ROUNDNEAREST:
				if (guardbit) {
				   if (stickybit || lsb_odd) dest_mantissa++;
				   }
		}
	}
	Sgl_set_exponentmantissa(result,dest_mantissa);

	/*
	 * check for mantissa overflow after rounding
	 */
	if ((dest_exponent>0 || Is_underflowtrap_enabled()) &&
	    Sgl_isone_hidden(result)) dest_exponent++;

	/*
	 * Test for overflow
	 */
	if (dest_exponent >= SGL_INFINITY_EXPONENT) {
		/* trap if OVERFLOWTRAP enabled */
		if (Is_overflowtrap_enabled()) {
			/*
			 * Check for gross overflow
			 */
			if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP)
				return(UNIMPLEMENTEDEXCEPTION);

			/*
			 * Adjust bias of result
			 */
			Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
			*dstptr = result;
			if (inexact) {
			    if (Is_inexacttrap_enabled())
				return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
			    else
				Set_inexactflag();
			}
			return(OVERFLOWEXCEPTION);
		}
		Set_overflowflag();
		inexact = TRUE;
		/* set result to infinity or largest number */
		Sgl_setoverflow(result);
	}
	/*
	 * Test for underflow
	 */
	else if (dest_exponent <= 0) {
		/* trap if UNDERFLOWTRAP enabled */
		if (Is_underflowtrap_enabled()) {
			/*
			 * Check for gross underflow
			 */
			if (dest_exponent <= -(SGL_WRAP))
				return(UNIMPLEMENTEDEXCEPTION);
			/*
			 * Adjust bias of result
			 */
			Sgl_setwrapped_exponent(result,dest_exponent,unfl);
			*dstptr = result;
			if (inexact) {
			    if (Is_inexacttrap_enabled())
				return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION);
			    else
				Set_inexactflag();
			}
			return(UNDERFLOWEXCEPTION);
		}
		 /*
		  * result is denormalized or signed zero
		  */
	       if (inexact && is_tiny) Set_underflowflag();

	}
	else Sgl_set_exponent(result,dest_exponent);
	*dstptr = result;
	/*
	 * Trap if inexact trap is enabled
	 */
	if (inexact) {
		if (Is_inexacttrap_enabled())
			return(INEXACTEXCEPTION);
		else
			Set_inexactflag();
	}
	return(NOEXCEPTION);
}


code:
/*	$OpenBSD: fcnvfx.c,v 1.8 2010/07/30 18:05:23 kettenis Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)fcnvfx.c: Revision: 2.8.88.2 Date: 93/12/08 13:27:29 */

#include "float.h"
#include "sgl_float.h"
#include "dbl_float.h"
#include "cnv_float.h"

/*
 *  Single Floating-point to Single Fixed-point
 */
/*ARGSUSED*/
int
sgl_to_sgl_fcnvfx(srcptr, null, dstptr, status)
	sgl_floating_point *srcptr, *null;
	int *dstptr;
	unsigned int *status;
{
	register unsigned int src, temp;
	register int src_exponent, result;
	register int inexact = FALSE;

	src = *srcptr;
	src_exponent = Sgl_exponent(src) - SGL_BIAS;

	/*
	 * Test for overflow
	 */
	if (src_exponent > SGL_FX_MAX_EXP) {
		/* check for MININT */
		if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
			if (Sgl_iszero_sign(src)) result = 0x7fffffff;
			else result = 0x80000000;

			if (Is_invalidtrap_enabled()) {
				return(INVALIDEXCEPTION);
			}
			Set_invalidflag();
			*dstptr = result;
			return(NOEXCEPTION);
		}
	}
	/*
	 * Generate result
	 */
	if (src_exponent >= 0) {
		temp = src;
		Sgl_clear_signexponent_set_hidden(temp);
		Int_from_sgl_mantissa(temp,src_exponent);
		if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
		else result = Sgl_all(temp);

		/* check for inexact */
		if (Sgl_isinexact_to_fix(src,src_exponent)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
			     if (Sgl_iszero_sign(src)) result++;
			     break;
			case ROUNDMINUS:
			     if (Sgl_isone_sign(src)) result--;
			     break;
			case ROUNDNEAREST:
			     if (Sgl_isone_roundbit(src,src_exponent)) {
				if (Sgl_isone_stickybit(src,src_exponent)
				|| (Sgl_isone_lowmantissa(temp))) {
				   if (Sgl_iszero_sign(src)) result++;
				   else result--;
				}
			     }
			}
		}
	}
	else {
		result = 0;

		/* check for inexact */
		if (Sgl_isnotzero_exponentmantissa(src)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
			     if (Sgl_iszero_sign(src)) result++;
			     break;
			case ROUNDMINUS:
			     if (Sgl_isone_sign(src)) result--;
			     break;
			case ROUNDNEAREST:
			     if (src_exponent == -1)
				if (Sgl_isnotzero_mantissa(src)) {
				   if (Sgl_iszero_sign(src)) result++;
				   else result--;
				}
			}
		}
	}
	*dstptr = result;
	if (inexact) {
		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
		else Set_inexactflag();
	}
	return(NOEXCEPTION);
}

/*
 *  Single Floating-point to Double Fixed-point
 */
/*ARGSUSED*/
int
sgl_to_dbl_fcnvfx(srcptr, null, dstptr, status)
	sgl_floating_point *srcptr, *null;
	dbl_integer *dstptr;
	unsigned int *status;
{
	register int src_exponent, resultp1;
	register unsigned int src, temp, resultp2;
	register int inexact = FALSE;

	src = *srcptr;
	src_exponent = Sgl_exponent(src) - SGL_BIAS;

	/*
	 * Test for overflow
	 */
	if (src_exponent > DBL_FX_MAX_EXP) {
		/* check for MININT */
		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
			if (Sgl_iszero_sign(src)) {
				resultp1 = 0x7fffffff;
				resultp2 = 0xffffffff;
			}
			else {
				resultp1 = 0x80000000;
				resultp2 = 0;
			}

			if (Is_invalidtrap_enabled()) {
				return(INVALIDEXCEPTION);
			}
			Set_invalidflag();
			Dint_copytoptr(resultp1,resultp2,dstptr);
			return(NOEXCEPTION);
		}
		Dint_set_minint(resultp1,resultp2);
		Dint_copytoptr(resultp1,resultp2,dstptr);
		return(NOEXCEPTION);
	}
	/*
	 * Generate result
	 */
	if (src_exponent >= 0) {
		temp = src;
		Sgl_clear_signexponent_set_hidden(temp);
		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
		if (Sgl_isone_sign(src)) {
			Dint_setone_sign(resultp1,resultp2);
		}

		/* check for inexact */
		if (Sgl_isinexact_to_fix(src,src_exponent)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
			     if (Sgl_iszero_sign(src)) {
				Dint_increment(resultp1,resultp2);
			     }
			     break;
			case ROUNDMINUS:
			     if (Sgl_isone_sign(src)) {
				Dint_decrement(resultp1,resultp2);
			     }
			     break;
			case ROUNDNEAREST:
			     if (Sgl_isone_roundbit(src,src_exponent))
				if (Sgl_isone_stickybit(src,src_exponent) ||
				(Dint_isone_lowp2(resultp2))) {
				   if (Sgl_iszero_sign(src)) {
				      Dint_increment(resultp1,resultp2);
				   }
				   else {
				      Dint_decrement(resultp1,resultp2);
				   }
				}
			}
		}
	}
	else {
		Dint_setzero(resultp1,resultp2);

		/* check for inexact */
		if (Sgl_isnotzero_exponentmantissa(src)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
			     if (Sgl_iszero_sign(src)) {
				Dint_increment(resultp1,resultp2);
			     }
			     break;
			case ROUNDMINUS:
			     if (Sgl_isone_sign(src)) {
				Dint_decrement(resultp1,resultp2);
			     }
			     break;
			case ROUNDNEAREST:
			     if (src_exponent == -1)
				if (Sgl_isnotzero_mantissa(src)) {
				   if (Sgl_iszero_sign(src)) {
				      Dint_increment(resultp1,resultp2);
				   }
				   else {
				      Dint_decrement(resultp1,resultp2);
				   }
				}
			}
		}
	}
	Dint_copytoptr(resultp1,resultp2,dstptr);
	if (inexact) {
		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
		else Set_inexactflag();
	}
	return(NOEXCEPTION);
}

/*
 *  Double Floating-point to Single Fixed-point
 */
/*ARGSUSED*/
int
dbl_to_sgl_fcnvfx(srcptr, null, dstptr, status)
	dbl_floating_point *srcptr, *null;
	int *dstptr;
	unsigned int *status;
{
	register unsigned int srcp1,srcp2, tempp1,tempp2;
	register int src_exponent, result;
	register int inexact = FALSE;

	Dbl_copyfromptr(srcptr,srcp1,srcp2);
	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;

	/*
	 * Test for overflow
	 */
	if (src_exponent > SGL_FX_MAX_EXP) {
		/* check for MININT */
		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
			if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
			else result = 0x80000000;

			if (Is_invalidtrap_enabled()) {
				return(INVALIDEXCEPTION);
			}
			Set_invalidflag();
			*dstptr = result;
			return(NOEXCEPTION);
		}
	}
	/*
	 * Generate result
	 */
	if (src_exponent >= 0) {
		tempp1 = srcp1;
		tempp2 = srcp2;
		Dbl_clear_signexponent_set_hidden(tempp1);
		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
			result = -Dbl_allp1(tempp1);
		else result = Dbl_allp1(tempp1);

		/* check for inexact */
		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
				if (Dbl_iszero_sign(srcp1))
					result++;
				break;
			case ROUNDMINUS:
				if (Dbl_isone_sign(srcp1)) result--;
				break;
			case ROUNDNEAREST:
				if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
				if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
				(Dbl_isone_lowmantissap1(tempp1))) {
					if (Dbl_iszero_sign(srcp1)) result++;
					else result--;
				}
			}
			/* check for overflow */
			if ((Dbl_iszero_sign(srcp1) && result < 0) ||
			    (Dbl_isone_sign(srcp1) && result > 0)) {

				if (Dbl_iszero_sign(srcp1))
					result = 0x7fffffff;
				else
					result = 0x80000000;

			    if (Is_overflowtrap_enabled()) {
			    if (Is_inexacttrap_enabled())
			      return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
			    else Set_inexactflag();
			    return(OVERFLOWEXCEPTION);
			    }
			  Set_overflowflag();
			  *dstptr = result;
			  if (Is_inexacttrap_enabled() )
				return(INEXACTEXCEPTION);
			  else Set_inexactflag();
			  return(NOEXCEPTION);
			}
		}
	}
	else {
		result = 0;

		/* check for inexact */
		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
				if (Dbl_iszero_sign(srcp1)) result++;
					break;
			case ROUNDMINUS:
				if (Dbl_isone_sign(srcp1)) result--;
				break;
			case ROUNDNEAREST:
				if (src_exponent == -1)
				if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
					if (Dbl_iszero_sign(srcp1)) result++;
					else result--;
				}
			}
		}
	}
	*dstptr = result;
	if (inexact) {
		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
		else Set_inexactflag();
	}
	return(NOEXCEPTION);
}

/*
 *  Double Floating-point to Double Fixed-point
 */
/*ARGSUSED*/
int
dbl_to_dbl_fcnvfx(srcptr, null, dstptr, status)
	dbl_floating_point *srcptr, *null;
	dbl_integer *dstptr;
	unsigned int *status;
{
	register int src_exponent, resultp1;
	register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
	register int inexact = FALSE;

	Dbl_copyfromptr(srcptr,srcp1,srcp2);
	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;

	/*
	 * Test for overflow
	 */
	if (src_exponent > DBL_FX_MAX_EXP) {
		/* check for MININT */
		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
		Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
			if (Dbl_iszero_sign(srcp1)) {
				resultp1 = 0x7fffffff;
				resultp2 = 0xffffffff;
			}
			else {
				resultp1 = 0x80000000;
				resultp2 = 0;
			}

			if (Is_invalidtrap_enabled()) {
				return(INVALIDEXCEPTION);
			}
			Set_invalidflag();
			Dint_copytoptr(resultp1,resultp2,dstptr);
			return(NOEXCEPTION);
		}
	}

	/*
	 * Generate result
	 */
	if (src_exponent >= 0) {
		tempp1 = srcp1;
		tempp2 = srcp2;
		Dbl_clear_signexponent_set_hidden(tempp1);
		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
				       resultp1, resultp2);
		if (Dbl_isone_sign(srcp1)) {
			Dint_setone_sign(resultp1,resultp2);
		}

		/* check for inexact */
		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
			     if (Dbl_iszero_sign(srcp1)) {
				Dint_increment(resultp1,resultp2);
			     }
			     break;
			case ROUNDMINUS:
			     if (Dbl_isone_sign(srcp1)) {
				Dint_decrement(resultp1,resultp2);
			     }
			     break;
			case ROUNDNEAREST:
			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
				if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) ||
				(Dint_isone_lowp2(resultp2))) {
				   if (Dbl_iszero_sign(srcp1)) {
				      Dint_increment(resultp1,resultp2);
				   }
				   else {
				      Dint_decrement(resultp1,resultp2);
				   }
				}
			}
		}
	}
	else {
		Dint_setzero(resultp1,resultp2);

		/* check for inexact */
		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
			     if (Dbl_iszero_sign(srcp1)) {
				Dint_increment(resultp1,resultp2);
			     }
			     break;
			case ROUNDMINUS:
			     if (Dbl_isone_sign(srcp1)) {
				Dint_decrement(resultp1,resultp2);
			     }
			     break;
			case ROUNDNEAREST:
			     if (src_exponent == -1)
				if (Dbl_isnotzero_mantissa(srcp1,srcp2)) {
				   if (Dbl_iszero_sign(srcp1)) {
				      Dint_increment(resultp1,resultp2);
				   }
				   else {
				      Dint_decrement(resultp1,resultp2);
				   }
				}
			}
		}
	}
	Dint_copytoptr(resultp1,resultp2,dstptr);
	if (inexact) {
		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
		else Set_inexactflag();
	}
	return(NOEXCEPTION);
}


code:
/*	$OpenBSD: fcnvfxt.c,v 1.8 2010/07/30 18:05:23 kettenis Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)fcnvfxt.c: Revision: 2.8.88.2 Date: 93/12/08 13:27:34 */

#include "float.h"
#include "sgl_float.h"
#include "dbl_float.h"
#include "cnv_float.h"

/*
 *  Convert single floating-point to single fixed-point format
 *  with truncated result
 */
/*ARGSUSED*/
int
sgl_to_sgl_fcnvfxt(srcptr, null, dstptr, status)
	sgl_floating_point *srcptr, *null;
	int *dstptr;
	unsigned int *status;
{
	register unsigned int src, temp;
	register int src_exponent, result;

	src = *srcptr;
	src_exponent = Sgl_exponent(src) - SGL_BIAS;

	/*
	 * Test for overflow
	 */
	if (src_exponent > SGL_FX_MAX_EXP) {
		/* check for MININT */
		if ((src_exponent > SGL_FX_MAX_EXP + 1) ||
		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
			if (Sgl_iszero_sign(src)) result = 0x7fffffff;
			else result = 0x80000000;

			if (Is_invalidtrap_enabled()) {
				return(INVALIDEXCEPTION);
			}
			Set_invalidflag();
			*dstptr = result;
			return(NOEXCEPTION);
		}
	}
	/*
	 * Generate result
	 */
	if (src_exponent >= 0) {
		temp = src;
		Sgl_clear_signexponent_set_hidden(temp);
		Int_from_sgl_mantissa(temp,src_exponent);
		if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
		else result = Sgl_all(temp);
		*dstptr = result;

		/* check for inexact */
		if (Sgl_isinexact_to_fix(src,src_exponent)) {
			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
			else Set_inexactflag();
		}
	}
	else {
		*dstptr = 0;

		/* check for inexact */
		if (Sgl_isnotzero_exponentmantissa(src)) {
			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
			else Set_inexactflag();
		}
	}
	return(NOEXCEPTION);
}

/*
 *  Single Floating-point to Double Fixed-point
 */
/*ARGSUSED*/
int
sgl_to_dbl_fcnvfxt(srcptr, null, dstptr, status)
	sgl_floating_point *srcptr, *null;
	dbl_integer *dstptr;
	unsigned int *status;
{
	register int src_exponent, resultp1;
	register unsigned int src, temp, resultp2;

	src = *srcptr;
	src_exponent = Sgl_exponent(src) - SGL_BIAS;

	/*
	 * Test for overflow
	 */
	if (src_exponent > DBL_FX_MAX_EXP) {
		/* check for MININT */
		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
			if (Sgl_iszero_sign(src)) {
				resultp1 = 0x7fffffff;
				resultp2 = 0xffffffff;
			}
			else {
				resultp1 = 0x80000000;
				resultp2 = 0;
			}

			if (Is_invalidtrap_enabled()) {
				return(INVALIDEXCEPTION);
			}
			Set_invalidflag();
			Dint_copytoptr(resultp1,resultp2,dstptr);
			return(NOEXCEPTION);
		}
		Dint_set_minint(resultp1,resultp2);
		Dint_copytoptr(resultp1,resultp2,dstptr);
		return(NOEXCEPTION);
	}
	/*
	 * Generate result
	 */
	if (src_exponent >= 0) {
		temp = src;
		Sgl_clear_signexponent_set_hidden(temp);
		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
		if (Sgl_isone_sign(src)) {
			Dint_setone_sign(resultp1,resultp2);
		}
		Dint_copytoptr(resultp1,resultp2,dstptr);

		/* check for inexact */
		if (Sgl_isinexact_to_fix(src,src_exponent)) {
			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
			else Set_inexactflag();
		}
	}
	else {
		Dint_setzero(resultp1,resultp2);
		Dint_copytoptr(resultp1,resultp2,dstptr);

		/* check for inexact */
		if (Sgl_isnotzero_exponentmantissa(src)) {
			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
			else Set_inexactflag();
		}
	}
	return(NOEXCEPTION);
}

/*
 *  Double Floating-point to Single Fixed-point
 */
/*ARGSUSED*/
int
dbl_to_sgl_fcnvfxt(srcptr, null, dstptr, status)
	dbl_floating_point *srcptr, *null;
	int *dstptr;
	unsigned int *status;
{
	register unsigned int srcp1, srcp2, tempp1, tempp2;
	register int src_exponent, result;

	Dbl_copyfromptr(srcptr,srcp1,srcp2);
	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;

	/*
	 * Test for overflow
	 */
	if (src_exponent > SGL_FX_MAX_EXP) {
		/* check for MININT */
		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
			if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
			else result = 0x80000000;

			if (Is_invalidtrap_enabled()) {
				return(INVALIDEXCEPTION);
			}
			Set_invalidflag();
			*dstptr = result;
			return(NOEXCEPTION);
		}
	}
	/*
	 * Generate result
	 */
	if (src_exponent >= 0) {
		tempp1 = srcp1;
		tempp2 = srcp2;
		Dbl_clear_signexponent_set_hidden(tempp1);
		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
			result = -Dbl_allp1(tempp1);
		else result = Dbl_allp1(tempp1);
		*dstptr = result;

		/* check for inexact */
		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
			else Set_inexactflag();
		}
	}
	else {
		*dstptr = 0;

		/* check for inexact */
		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
			else Set_inexactflag();
		}
	}
	return(NOEXCEPTION);
}

/*
 *  Double Floating-point to Double Fixed-point
 */
/*ARGSUSED*/
int
dbl_to_dbl_fcnvfxt(srcptr, null, dstptr, status)
	dbl_floating_point *srcptr, *null;
	dbl_integer *dstptr;
	unsigned int *status;
{
	register int src_exponent, resultp1;
	register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;

	Dbl_copyfromptr(srcptr,srcp1,srcp2);
	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;

	/*
	 * Test for overflow
	 */
	if (src_exponent > DBL_FX_MAX_EXP) {
		/* check for MININT */
		if ((src_exponent > DBL_FX_MAX_EXP + 1) ||
		Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
			if (Dbl_iszero_sign(srcp1)) {
				resultp1 = 0x7fffffff;
				resultp2 = 0xffffffff;
			}
			else {
				resultp1 = 0x80000000;
				resultp2 = 0;
			}

			if (Is_invalidtrap_enabled()) {
				return(INVALIDEXCEPTION);
			}
			Set_invalidflag();
			Dint_copytoptr(resultp1,resultp2,dstptr);
			return(NOEXCEPTION);
		}
	}
	/*
	 * Generate result
	 */
	if (src_exponent >= 0) {
		tempp1 = srcp1;
		tempp2 = srcp2;
		Dbl_clear_signexponent_set_hidden(tempp1);
		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
		resultp1,resultp2);
		if (Dbl_isone_sign(srcp1)) {
			Dint_setone_sign(resultp1,resultp2);
		}
		Dint_copytoptr(resultp1,resultp2,dstptr);

		/* check for inexact */
		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
			else Set_inexactflag();
		}
	}
	else {
		Dint_setzero(resultp1,resultp2);
		Dint_copytoptr(resultp1,resultp2,dstptr);

		/* check for inexact */
		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
			else Set_inexactflag();
		}
	}
	return(NOEXCEPTION);
}


code:
/*	$OpenBSD: fcnvxf.c,v 1.7 2003/04/10 17:27:58 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)fcnvxf.c: Revision: 2.7.88.1 Date: 93/12/07 15:06:16 */

#include "float.h"
#include "sgl_float.h"
#include "dbl_float.h"
#include "cnv_float.h"

/*
 *  Convert single fixed-point to single floating-point format
 */
int
sgl_to_sgl_fcnvxf(srcptr, null, dstptr, status)
	int *srcptr, *null;
	sgl_floating_point *dstptr;
	unsigned int *status;
{
	register int src, dst_exponent;
	register unsigned int result = 0;

	src = *srcptr;
	/*
	 * set sign bit of result and get magnitude of source
	 */
	if (src < 0) {
		Sgl_setone_sign(result);
		Int_negate(src);
	}
	else {
		Sgl_setzero_sign(result);
		/* Check for zero */
		if (src == 0) {
			Sgl_setzero(result);
			*dstptr = result;
			return(NOEXCEPTION);
		}
	}
	/*
	 * Generate exponent and normalized mantissa
	 */
	dst_exponent = 16;    /* initialize for normalization */
	/*
	 * Check word for most significant bit set.  Returns
	 * a value in dst_exponent indicating the bit position,
	 * between -1 and 30.
	 */
	Find_ms_one_bit(src,dst_exponent);
	/*  left justify source, with msb at bit position 1  */
	if (dst_exponent >= 0) src <<= dst_exponent;
	else src = 1 << 30;
	Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
	Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);

	/* check for inexact */
	if (Int_isinexact_to_sgl(src)) {
		switch (Rounding_mode()) {
			case ROUNDPLUS:
				if (Sgl_iszero_sign(result))
					Sgl_increment(result);
				break;
			case ROUNDMINUS:
				if (Sgl_isone_sign(result))
					Sgl_increment(result);
				break;
			case ROUNDNEAREST:
				Sgl_roundnearest_from_int(src,result);
		}
		if (Is_inexacttrap_enabled()) {
			*dstptr = result;
			return(INEXACTEXCEPTION);
		}
		else Set_inexactflag();
	}
	*dstptr = result;
	return(NOEXCEPTION);
}

/*
 *  Single Fixed-point to Double Floating-point
 */
int
sgl_to_dbl_fcnvxf(srcptr, null, dstptr, status)
	int *srcptr, *null;
	dbl_floating_point *dstptr;
	unsigned int *status;
{
	register int src, dst_exponent;
	register unsigned int resultp1 = 0, resultp2 = 0;

	src = *srcptr;
	/*
	 * set sign bit of result and get magnitude of source
	 */
	if (src < 0) {
		Dbl_setone_sign(resultp1);
		Int_negate(src);
	}
	else {
		Dbl_setzero_sign(resultp1);
		/* Check for zero */
		if (src == 0) {
			Dbl_setzero(resultp1,resultp2);
			Dbl_copytoptr(resultp1,resultp2,dstptr);
			return(NOEXCEPTION);
		}
	}
	/*
	 * Generate exponent and normalized mantissa
	 */
	dst_exponent = 16;    /* initialize for normalization */
	/*
	 * Check word for most significant bit set.  Returns
	 * a value in dst_exponent indicating the bit position,
	 * between -1 and 30.
	 */
	Find_ms_one_bit(src,dst_exponent);
	/*  left justify source, with msb at bit position 1  */
	if (dst_exponent >= 0) src <<= dst_exponent;
	else src = 1 << 30;
	Dbl_set_mantissap1(resultp1, (src >> (DBL_EXP_LENGTH - 1)));
	Dbl_set_mantissap2(resultp2, (src << (33-DBL_EXP_LENGTH)));
	Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
	Dbl_copytoptr(resultp1,resultp2,dstptr);
	return(NOEXCEPTION);
}

/*
 *  Double Fixed-point to Single Floating-point
 */
int
dbl_to_sgl_fcnvxf(srcptr, null, dstptr, status)
	dbl_integer *srcptr, *null;
	sgl_floating_point *dstptr;
	unsigned int *status;
{
	int dst_exponent, srcp1;
	unsigned int result = 0, srcp2;

	Dint_copyfromptr(srcptr,srcp1,srcp2);
	/*
	 * set sign bit of result and get magnitude of source
	 */
	if (srcp1 < 0) {
		Sgl_setone_sign(result);
		Dint_negate(srcp1,srcp2);
	}
	else {
		Sgl_setzero_sign(result);
		/* Check for zero */
		if (srcp1 == 0 && srcp2 == 0) {
			Sgl_setzero(result);
			*dstptr = result;
			return(NOEXCEPTION);
		}
	}
	/*
	 * Generate exponent and normalized mantissa
	 */
	dst_exponent = 16;    /* initialize for normalization */
	if (srcp1 == 0) {
		/*
		 * Check word for most significant bit set.  Returns
		 * a value in dst_exponent indicating the bit position,
		 * between -1 and 30.
		 */
		Find_ms_one_bit(srcp2,dst_exponent);
		/*  left justify source, with msb at bit position 1  */
		if (dst_exponent >= 0) {
			srcp1 = srcp2 << dst_exponent;
			srcp2 = 0;
		}
		else {
			srcp1 = srcp2 >> 1;
			srcp2 <<= 31;
		}
		/*
		 *  since msb set is in second word, need to
		 *  adjust bit position count
		 */
		dst_exponent += 32;
	}
	else {
		/*
		 * Check word for most significant bit set.  Returns
		 * a value in dst_exponent indicating the bit position,
		 * between -1 and 30.
		 *
		 */
		Find_ms_one_bit(srcp1,dst_exponent);
		/*  left justify source, with msb at bit position 1  */
		if (dst_exponent > 0) {
			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
			 srcp1);
			srcp2 <<= dst_exponent;
		}
		/*
		 * If dst_exponent = 0, we don't need to shift anything.
		 * If dst_exponent = -1, src = - 2**63 so we won't need to
		 * shift srcp2.
		 */
		else srcp1 >>= -(dst_exponent);
	}
	Sgl_set_mantissa(result, (srcp1 >> (SGL_EXP_LENGTH - 1)));
	Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);

	/* check for inexact */
	if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
		switch (Rounding_mode()) {
			case ROUNDPLUS:
				if (Sgl_iszero_sign(result))
					Sgl_increment(result);
				break;
			case ROUNDMINUS:
				if (Sgl_isone_sign(result))
					Sgl_increment(result);
				break;
			case ROUNDNEAREST:
				Sgl_roundnearest_from_dint(srcp1,srcp2,result);
		}
		if (Is_inexacttrap_enabled()) {
			*dstptr = result;
			return(INEXACTEXCEPTION);
		}
		else Set_inexactflag();
	}
	*dstptr = result;
	return(NOEXCEPTION);
}

/*
 *  Double Fixed-point to Double Floating-point
 */
int
dbl_to_dbl_fcnvxf(srcptr, null, dstptr, status)
	dbl_integer *srcptr, *null;
	dbl_floating_point *dstptr;
	unsigned int *status;
{
	register int srcp1, dst_exponent;
	register unsigned int srcp2, resultp1 = 0, resultp2 = 0;

	Dint_copyfromptr(srcptr,srcp1,srcp2);
	/*
	 * set sign bit of result and get magnitude of source
	 */
	if (srcp1 < 0) {
		Dbl_setone_sign(resultp1);
		Dint_negate(srcp1,srcp2);
	}
	else {
		Dbl_setzero_sign(resultp1);
		/* Check for zero */
		if (srcp1 == 0 && srcp2 ==0) {
			Dbl_setzero(resultp1,resultp2);
			Dbl_copytoptr(resultp1,resultp2,dstptr);
			return(NOEXCEPTION);
		}
	}
	/*
	 * Generate exponent and normalized mantissa
	 */
	dst_exponent = 16;    /* initialize for normalization */
	if (srcp1 == 0) {
		/*
		 * Check word for most significant bit set.  Returns
		 * a value in dst_exponent indicating the bit position,
		 * between -1 and 30.
		 */
		Find_ms_one_bit(srcp2,dst_exponent);
		/*  left justify source, with msb at bit position 1  */
		if (dst_exponent >= 0) {
			srcp1 = srcp2 << dst_exponent;
			srcp2 = 0;
		}
		else {
			srcp1 = srcp2 >> 1;
			srcp2 <<= 31;
		}
		/*
		 *  since msb set is in second word, need to
		 *  adjust bit position count
		 */
		dst_exponent += 32;
	}
	else {
		/*
		 * Check word for most significant bit set.  Returns
		 * a value in dst_exponent indicating the bit position,
		 * between -1 and 30.
		 */
		Find_ms_one_bit(srcp1,dst_exponent);
		/*  left justify source, with msb at bit position 1  */
		if (dst_exponent > 0) {
			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
			 srcp1);
			srcp2 <<= dst_exponent;
		}
		/*
		 * If dst_exponent = 0, we don't need to shift anything.
		 * If dst_exponent = -1, src = - 2**63 so we won't need to
		 * shift srcp2.
		 */
		else srcp1 >>= -(dst_exponent);
	}
	Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
	Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
	Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);

	/* check for inexact */
	if (Dint_isinexact_to_dbl(srcp2)) {
		switch (Rounding_mode()) {
			case ROUNDPLUS:
				if (Dbl_iszero_sign(resultp1)) {
					Dbl_increment(resultp1,resultp2);
				}
				break;
			case ROUNDMINUS:
				if (Dbl_isone_sign(resultp1)) {
					Dbl_increment(resultp1,resultp2);
				}
				break;
			case ROUNDNEAREST:
				Dbl_roundnearest_from_dint(srcp2,resultp1,
				resultp2);
		}
		if (Is_inexacttrap_enabled()) {
			Dbl_copytoptr(resultp1,resultp2,dstptr);
			return(INEXACTEXCEPTION);
		}
		else Set_inexactflag();
	}
	Dbl_copytoptr(resultp1,resultp2,dstptr);
	return(NOEXCEPTION);
}


code:
/*	$OpenBSD: float.h,v 1.8 2012/06/25 16:55:13 deraadt Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)float.h: Revision: 2.14.88.2 Date: 93/12/08 13:27:42 */

#include "fpbits.h"
#include "hppa.h"

/*
 * Declare the basic structures for the 3 different
 * floating-point precisions.
 *
 * Single number
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |s|       exp     |               mantissa                      |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 */
#define	Sall(object) (object)
#define	Ssign(object) Bitfield_extract( 0,  1,object)
#define	Ssignedsign(object) Bitfield_signed_extract( 0,  1,object)
#define	Sexponent(object) Bitfield_extract( 1,  8,object)
#define	Smantissa(object) Bitfield_mask( 9, 23,object)
#define	Ssignaling(object) Bitfield_extract( 9,  1,object)
#define	Ssignalingnan(object) Bitfield_extract( 1,  9,object)
#define	Shigh2mantissa(object) Bitfield_extract( 9,  2,object)
#define	Sexponentmantissa(object) Bitfield_mask( 1, 31,object)
#define	Ssignexponent(object) Bitfield_extract( 0,  9,object)
#define	Shidden(object) Bitfield_extract( 8,  1,object)
#define	Shiddenoverflow(object) Bitfield_extract( 7,  1,object)
#define	Shiddenhigh7mantissa(object) Bitfield_extract( 8,  8,object)
#define	Shiddenhigh3mantissa(object) Bitfield_extract( 8,  4,object)
#define	Slow(object) Bitfield_mask( 31,  1,object)
#define	Slow4(object) Bitfield_mask( 28,  4,object)
#define	Slow31(object) Bitfield_mask( 1, 31,object)
#define	Shigh31(object) Bitfield_extract( 0, 31,object)
#define	Ssignedhigh31(object) Bitfield_signed_extract( 0, 31,object)
#define	Shigh4(object) Bitfield_extract( 0,  4,object)
#define	Sbit24(object) Bitfield_extract( 24,  1,object)
#define	Sbit28(object) Bitfield_extract( 28,  1,object)
#define	Sbit29(object) Bitfield_extract( 29,  1,object)
#define	Sbit30(object) Bitfield_extract( 30,  1,object)
#define	Sbit31(object) Bitfield_mask( 31,  1,object)

#define Deposit_ssign(object,value) Bitfield_deposit(value,0,1,object)
#define Deposit_sexponent(object,value) Bitfield_deposit(value,1,8,object)
#define Deposit_smantissa(object,value) Bitfield_deposit(value,9,23,object)
#define Deposit_shigh2mantissa(object,value) Bitfield_deposit(value,9,2,object)
#define Deposit_sexponentmantissa(object,value) \
    Bitfield_deposit(value,1,31,object)
#define Deposit_ssignexponent(object,value) Bitfield_deposit(value,0,9,object)
#define Deposit_slow(object,value) Bitfield_deposit(value,31,1,object)
#define Deposit_shigh4(object,value) Bitfield_deposit(value,0,4,object)

#define	Is_ssign(object) Bitfield_mask( 0,  1,object)
#define	Is_ssignaling(object) Bitfield_mask( 9,  1,object)
#define	Is_shidden(object) Bitfield_mask( 8,  1,object)
#define	Is_shiddenoverflow(object) Bitfield_mask( 7,  1,object)
#define	Is_slow(object) Bitfield_mask( 31,  1,object)
#define	Is_sbit24(object) Bitfield_mask( 24,  1,object)
#define	Is_sbit28(object) Bitfield_mask( 28,  1,object)
#define	Is_sbit29(object) Bitfield_mask( 29,  1,object)
#define	Is_sbit30(object) Bitfield_mask( 30,  1,object)
#define	Is_sbit31(object) Bitfield_mask( 31,  1,object)

/*
 * Double number.
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |s|       exponent      |          mantissa part 1              |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 *
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |                    mantissa part 2                            |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 */
#define Dallp1(object) (object)
#define Dsign(object) Bitfield_extract( 0,  1,object)
#define Dsignedsign(object) Bitfield_signed_extract( 0,  1,object)
#define Dexponent(object) Bitfield_extract( 1,  11,object)
#define Dmantissap1(object) Bitfield_mask( 12, 20,object)
#define Dsignaling(object) Bitfield_extract( 12,  1,object)
#define Dsignalingnan(object) Bitfield_extract( 1,  12,object)
#define Dhigh2mantissa(object) Bitfield_extract( 12,  2,object)
#define Dexponentmantissap1(object) Bitfield_mask( 1, 31,object)
#define Dsignexponent(object) Bitfield_extract( 0, 12,object)
#define Dhidden(object) Bitfield_extract( 11,  1,object)
#define Dhiddenoverflow(object) Bitfield_extract( 10,  1,object)
#define Dhiddenhigh7mantissa(object) Bitfield_extract( 11,  8,object)
#define Dhiddenhigh3mantissa(object) Bitfield_extract( 11,  4,object)
#define Dlowp1(object) Bitfield_mask( 31,  1,object)
#define Dlow31p1(object) Bitfield_mask( 1, 31,object)
#define Dhighp1(object) Bitfield_extract( 0,  1,object)
#define Dhigh4p1(object) Bitfield_extract( 0,  4,object)
#define Dhigh31p1(object) Bitfield_extract( 0, 31,object)
#define Dsignedhigh31p1(object) Bitfield_signed_extract( 0, 31,object)
#define Dbit3p1(object) Bitfield_extract( 3,  1,object)

#define Deposit_dsign(object,value) Bitfield_deposit(value,0,1,object)
#define Deposit_dexponent(object,value) Bitfield_deposit(value,1,11,object)
#define Deposit_dmantissap1(object,value) Bitfield_deposit(value,12,20,object)
#define Deposit_dhigh2mantissa(object,value) Bitfield_deposit(value,12,2,object)
#define Deposit_dexponentmantissap1(object,value) \
    Bitfield_deposit(value,1,31,object)
#define Deposit_dsignexponent(object,value) Bitfield_deposit(value,0,12,object)
#define Deposit_dlowp1(object,value) Bitfield_deposit(value,31,1,object)
#define Deposit_dhigh4p1(object,value) Bitfield_deposit(value,0,4,object)

#define Is_dsign(object) Bitfield_mask( 0,  1,object)
#define Is_dsignaling(object) Bitfield_mask( 12,  1,object)
#define Is_dhidden(object) Bitfield_mask( 11,  1,object)
#define Is_dhiddenoverflow(object) Bitfield_mask( 10,  1,object)
#define Is_dlowp1(object) Bitfield_mask( 31,  1,object)
#define Is_dhighp1(object) Bitfield_mask( 0,  1,object)
#define Is_dbit3p1(object) Bitfield_mask( 3,  1,object)

#define Dallp2(object) (object)
#define Dmantissap2(object) (object)
#define Dlowp2(object) Bitfield_mask( 31,  1,object)
#define Dlow4p2(object) Bitfield_mask( 28,  4,object)
#define Dlow31p2(object) Bitfield_mask( 1, 31,object)
#define Dhighp2(object) Bitfield_extract( 0,  1,object)
#define Dhigh31p2(object) Bitfield_extract( 0, 31,object)
#define Dbit2p2(object) Bitfield_extract( 2,  1,object)
#define Dbit3p2(object) Bitfield_extract( 3,  1,object)
#define Dbit21p2(object) Bitfield_extract( 21,  1,object)
#define Dbit28p2(object) Bitfield_extract( 28,  1,object)
#define Dbit29p2(object) Bitfield_extract( 29,  1,object)
#define Dbit30p2(object) Bitfield_extract( 30,  1,object)
#define Dbit31p2(object) Bitfield_mask( 31,  1,object)

#define Deposit_dlowp2(object,value) Bitfield_deposit(value,31,1,object)

#define Is_dlowp2(object) Bitfield_mask( 31,  1,object)
#define Is_dhighp2(object) Bitfield_mask( 0,  1,object)
#define Is_dbit2p2(object) Bitfield_mask( 2,  1,object)
#define Is_dbit3p2(object) Bitfield_mask( 3,  1,object)
#define Is_dbit21p2(object) Bitfield_mask( 21,  1,object)
#define Is_dbit28p2(object) Bitfield_mask( 28,  1,object)
#define Is_dbit29p2(object) Bitfield_mask( 29,  1,object)
#define Is_dbit30p2(object) Bitfield_mask( 30,  1,object)
#define Is_dbit31p2(object) Bitfield_mask( 31,  1,object)

/*
 * Quad number.
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |s|          exponent           |      mantissa part 1          |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 *
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |                    mantissa part 2                            |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 *
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |                    mantissa part 3                            |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 *
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |                    mantissa part 4                            |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 */
typedef struct
    {
    union
	{
	struct { unsigned qallp1; } u_qallp1;
/* Not needed for now...
	Bitfield_extract( 0,  1,u_qsign,qsign)
	Bitfield_signed_extract( 0,  1,u_qsignedsign,qsignedsign)
	Bitfield_extract( 1, 15,u_qexponent,qexponent)
	Bitfield_extract(16, 16,u_qmantissap1,qmantissap1)
	Bitfield_extract(16,  1,u_qsignaling,qsignaling)
	Bitfield_extract(1,  16,u_qsignalingnan,qsignalingnan)
	Bitfield_extract(16,  2,u_qhigh2mantissa,qhigh2mantissa)
	Bitfield_extract( 1, 31,u_qexponentmantissap1,qexponentmantissap1)
	Bitfield_extract( 0, 16,u_qsignexponent,qsignexponent)
	Bitfield_extract(15,  1,u_qhidden,qhidden)
	Bitfield_extract(14,  1,u_qhiddenoverflow,qhiddenoverflow)
	Bitfield_extract(15,  8,u_qhiddenhigh7mantissa,qhiddenhigh7mantissa)
	Bitfield_extract(15,  4,u_qhiddenhigh3mantissa,qhiddenhigh3mantissa)
	Bitfield_extract(31,  1,u_qlowp1,qlowp1)
	Bitfield_extract( 1, 31,u_qlow31p1,qlow31p1)
	Bitfield_extract( 0,  1,u_qhighp1,qhighp1)
	Bitfield_extract( 0,  4,u_qhigh4p1,qhigh4p1)
	Bitfield_extract( 0, 31,u_qhigh31p1,qhigh31p1)
  */
	} quad_u1;
    union
	{
	struct { unsigned qallp2; } u_qallp2;
  /* Not needed for now...
	Bitfield_extract(31,  1,u_qlowp2,qlowp2)
	Bitfield_extract( 1, 31,u_qlow31p2,qlow31p2)
	Bitfield_extract( 0,  1,u_qhighp2,qhighp2)
	Bitfield_extract( 0, 31,u_qhigh31p2,qhigh31p2)
   */
	} quad_u2;
    union
	{
	struct { unsigned qallp3; } u_qallp3;
  /* Not needed for now...
	Bitfield_extract(31,  1,u_qlowp3,qlowp3)
	Bitfield_extract( 1, 31,u_qlow31p3,qlow31p3)
	Bitfield_extract( 0,  1,u_qhighp3,qhighp3)
	Bitfield_extract( 0, 31,u_qhigh31p3,qhigh31p3)
   */
	} quad_u3;
    union
	{
	struct { unsigned qallp4; } u_qallp4;
    /* Not need for now...
	Bitfield_extract(31,  1,u_qlowp4,qlowp4)
	Bitfield_extract( 1, 31,u_qlow31p4,qlow31p4)
	Bitfield_extract( 0,  1,u_qhighp4,qhighp4)
	Bitfield_extract( 0, 31,u_qhigh31p4,qhigh31p4)
     */
	} quad_u4;
    } quad_floating_point;

/* Extension - An additional structure to hold the guard, round and
 *             sticky bits during computations.
 */
#define Extall(object) (object)
#define Extsign(object) Bitfield_extract( 0,  1,object)
#define Exthigh31(object) Bitfield_extract( 0, 31,object)
#define Extlow31(object) Bitfield_extract( 1, 31,object)
#define Extlow(object) Bitfield_extract( 31,  1,object)

/*
 * Declare the basic structures for the 3 different
 * fixed-point precisions.
 *
 * Single number
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |s|                    integer                                  |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 */
typedef int sgl_integer;

/*
 * Double number.
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |s|                     high integer                            |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 *
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |                       low integer                             |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 */
struct dint {
	int  wd0;
	unsigned int wd1;
};

struct dblwd {
	unsigned int wd0;
	unsigned int wd1;
};

/*
 * Quad number.
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |s|                  integer part1                              |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 *
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |                    integer part 2                             |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 *
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |                    integer part 3                             |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 *
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |                    integer part 4                             |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 */

struct quadwd {
	int  wd0;
	unsigned int wd1;
	unsigned int wd2;
	unsigned int wd3;
};

typedef struct quadwd quad_integer;

/* useful typedefs */
typedef int sgl_floating_point;
typedef struct dblwd dbl_floating_point;
typedef struct dint dbl_integer;

/*
 * Define the different precisions' parameters.
 */
#define SGL_BITLENGTH 32
#define SGL_EMAX 127
#define SGL_BIAS 127
#define SGL_WRAP 192
#define SGL_INFINITY_EXPONENT (SGL_EMAX+SGL_BIAS+1)
#define SGL_THRESHOLD 32
#define SGL_EXP_LENGTH 8
#define SGL_P 24

#define DBL_BITLENGTH 64
#define DBL_EMAX 1023
#define DBL_BIAS 1023
#define DBL_WRAP 1536
#define DBL_INFINITY_EXPONENT (DBL_EMAX+DBL_BIAS+1)
#define DBL_THRESHOLD 64
#define DBL_EXP_LENGTH 11
#define DBL_P 53

#define QUAD_BITLENGTH 128
#define QUAD_EMAX 16383
#define QUAD_BIAS 16383
#define QUAD_WRAP 24576
#define QUAD_INFINITY_EXPONENT (QUAD_EMAX+QUAD_BIAS+1)
#define QUAD_P 113

/* Boolean Values etc. */
#define FALSE 0
#define TRUE (!FALSE)
#define NOT !
#define XOR ^

/* Declare status register equivalent to FPUs architecture.
 *
 *  0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |V|Z|O|U|I|C|  rsv  |  model    | version |RM |rsv|T|r|V|Z|O|U|I|
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 */
#define Cbit(object) Bitfield_extract( 5, 1,object)
#define Tbit(object) Bitfield_extract( 25, 1,object)
#define Roundingmode(object) Bitfield_extract( 21, 2,object)
#define Invalidtrap(object) Bitfield_extract( 27, 1,object)
#define Divisionbyzerotrap(object) Bitfield_extract( 28, 1,object)
#define Overflowtrap(object) Bitfield_extract( 29, 1,object)
#define Underflowtrap(object) Bitfield_extract( 30, 1,object)
#define Inexacttrap(object) Bitfield_extract( 31, 1,object)
#define Invalidflag(object) Bitfield_extract( 0, 1,object)
#define Divisionbyzeroflag(object) Bitfield_extract( 1, 1,object)
#define Overflowflag(object) Bitfield_extract( 2, 1,object)
#define Underflowflag(object) Bitfield_extract( 3, 1,object)
#define Inexactflag(object) Bitfield_extract( 4, 1,object)
#define Allflags(object) Bitfield_extract( 0, 5,object)

/* Definitions relevant to the status register */

/* Rounding Modes */
#define ROUNDNEAREST 0
#define ROUNDZERO    1
#define ROUNDPLUS    2
#define ROUNDMINUS   3

/* Exceptions */
#define NOEXCEPTION		0x0
#define INVALIDEXCEPTION	0x20
#define DIVISIONBYZEROEXCEPTION	0x10
#define OVERFLOWEXCEPTION	0x08
#define UNDERFLOWEXCEPTION	0x04
#define INEXACTEXCEPTION	0x02
#define UNIMPLEMENTEDEXCEPTION	0x01

/* Declare exception registers equivalent to FPUs architecture
 *
 *  0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |excepttype |  r1     | r2/ext  |  operation  |parm |n| t/cond  |
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 */
#define Allexception(object) (object)
#define Exceptiontype(object) Bitfield_extract( 0, 6,object)
#define Instructionfield(object) Bitfield_mask( 6,26,object)
#define Parmfield(object) Bitfield_extract( 23, 3,object)
#define Rabit(object) Bitfield_extract( 24, 1,object)
#define Ibit(object) Bitfield_extract( 25, 1,object)

#define Set_exceptiontype(object,value) Bitfield_deposit(value, 0, 6,object)
#define Set_parmfield(object,value) Bitfield_deposit(value, 23, 3,object)
#define Set_exceptiontype_and_instr_field(exception,instruction,object) \
    object = ((exception) << 26) | (instruction)

/* Declare the condition field
 *
 *  0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 * |                                                     |G|L|E|U|X|
 * +-------+-------+-------+-------+-------+-------+-------+-------+
 */
#define Allexception(object) (object)
#define Greaterthanbit(object) Bitfield_extract( 27, 1,object)
#define Lessthanbit(object) Bitfield_extract( 28, 1,object)
#define Equalbit(object) Bitfield_extract( 29, 1,object)
#define Unorderedbit(object) Bitfield_extract( 30, 1,object)
#define Exceptionbit(object) Bitfield_extract( 31, 1,object)

/* An alias name for the status register */
#define Fpustatus_register (*status)

/**************************************************
 * Status register referencing and manipulation.  *
 **************************************************/

/* Rounding mode */
#define Rounding_mode()  Roundingmode(Fpustatus_register)
#define Is_rounding_mode(rmode) \
    (Roundingmode(Fpustatus_register) == rmode)
#define Set_rounding_mode(value) \
    Bitfield_deposit(value,21,2,Fpustatus_register)

/* Boolean testing of the trap enable bits */
#define Is_invalidtrap_enabled() Invalidtrap(Fpustatus_register)
#define Is_divisionbyzerotrap_enabled() Divisionbyzerotrap(Fpustatus_register)
#define Is_overflowtrap_enabled() Overflowtrap(Fpustatus_register)
#define Is_underflowtrap_enabled() Underflowtrap(Fpustatus_register)
#define Is_inexacttrap_enabled() Inexacttrap(Fpustatus_register)

/* Set the indicated flags in the status register */
#define Set_invalidflag() Bitfield_deposit(1,0,1,Fpustatus_register)
#define Set_divisionbyzeroflag() Bitfield_deposit(1,1,1,Fpustatus_register)
#define Set_overflowflag() Bitfield_deposit(1,2,1,Fpustatus_register)
#define Set_underflowflag() Bitfield_deposit(1,3,1,Fpustatus_register)
#define Set_inexactflag() Bitfield_deposit(1,4,1,Fpustatus_register)

#define Clear_all_flags() Bitfield_deposit(0,0,5,Fpustatus_register)

/* Manipulate the trap and condition code bits (tbit and cbit) */
#define Set_tbit() Bitfield_deposit(1,25,1,Fpustatus_register)
#define Clear_tbit() Bitfield_deposit(0,25,1,Fpustatus_register)
#define Is_tbit_set() Tbit(Fpustatus_register)
#define Is_cbit_set() Cbit(Fpustatus_register)

#ifdef TIMEX
#define Set_status_cbit(value) \
	Bitfield_deposit(Bitfield_extract(10,10,Fpustatus_register),11,10,Fpustatus_register); \
	Bitfield_deposit(Bitfield_extract(5,1,Fpustatus_register),10,1,Fpustatus_register); \
	Bitfield_deposit(value,5,1,Fpustatus_register)
#else
#define Set_status_cbit(value) Bitfield_deposit(value,5,1,Fpustatus_register)
#endif

/*******************************
 * Condition field referencing *
 *******************************/
#define Unordered(cond) Unorderedbit(cond)
#define Equal(cond) Equalbit(cond)
#define Lessthan(cond) Lessthanbit(cond)
#define Greaterthan(cond) Greaterthanbit(cond)
#define Exception(cond) Exceptionbit(cond)

/* Defines for the extension */
#define Ext_isone_sign(extent) (Extsign(extent))
#define Ext_isnotzero(extent) \
    (Extall(extent))
#define Ext_isnotzero_lower(extent) \
    (Extlow31(extent))
#define Ext_leftshiftby1(extent) \
    Extall(extent) <<= 1
#define Ext_negate(extent) \
    (int )Extall(extent) = 0 - (int )Extall(extent)
#define Ext_setone_low(extent) Bitfield_deposit(1,31,1,extent)


code:
/*	$OpenBSD: fpbits.h,v 1.6 2002/09/20 19:26:59 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)fpbits.h: Revision: 1.6.88.1 Date: 93/12/07 15:06:21 */

/*
 *  These macros are designed to be portable to all machines that have
 *  a wordsize greater than or equal to 32 bits that support the portable
 *  C compiler and the standard C preprocessor.  Wordsize (default 32)
 *  and bitfield assignment (default left-to-right,  unlike VAX, PDP-11)
 *  should be predefined using the constants HOSTWDSZ and BITFRL and
 *  the C compiler "-D" flag (e.g., -DHOSTWDSZ=36 -DBITFLR for the DEC-20).
 *  Note that the macro arguments assume that the integer being referenced
 *  is a 32-bit integer (right-justified on the 20) and that bit 0 is the
 *  most significant bit.
 */

#ifndef HOSTWDSZ
#define	HOSTWDSZ	32
#endif

/*###########################  Macros  ######################################*/

/*-------------------------------------------------------------------------
 * NewDeclareBitField_Reference - Declare a structure similar to the simulator
 * function "DeclBitfR" except its use is restricted to occur within a larger
 * enclosing structure or union definition.  This declaration is an unnamed
 * structure with the argument, name, as the member name and the argument,
 * uname, as the element name.
 *----------------------------------------------------------------------- */
#define Bitfield_extract(start, length, object)		\
    ((object) >> (HOSTWDSZ - (start) - (length)) &	\
    ((unsigned)-1 >> (HOSTWDSZ - (length))))

#define Bitfield_signed_extract(start, length, object) \
    ((int)((object) << start) >> (HOSTWDSZ - (length)))

#define Bitfield_mask(start, len, object)		\
    ((object) & (((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len)))

#define Bitfield_deposit(value,start,len,object)  object = \
    ((object) & ~(((unsigned)-1 >> (HOSTWDSZ-(len))) << (HOSTWDSZ-(start)-(len)))) | \
    (((value) & ((unsigned)-1 >> (HOSTWDSZ-(len)))) << (HOSTWDSZ-(start)-(len)))


code:
/*	$OpenBSD: frnd.c,v 1.8 2003/04/10 17:27:58 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)frnd.c: Revision: 2.7.88.1 Date: 93/12/07 15:06:24 */

#include "float.h"
#include "sgl_float.h"
#include "dbl_float.h"
#include "quad_float.h"
#include "cnv_float.h"

/*
 *  Single Floating-point Round to Integer
 */

/*ARGSUSED*/
int
sgl_frnd(srcptr, null, dstptr, status)
	sgl_floating_point *srcptr, *null, *dstptr;
	unsigned int *status;
{
	register unsigned int src, result;
	register int src_exponent;
	register int inexact = FALSE;

	src = *srcptr;
	/*
	 * check source operand for NaN or infinity
	 */
	if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
		/*
		 * is signaling NaN?
		 */
		if (Sgl_isone_signaling(src)) {
			/* trap if INVALIDTRAP enabled */
			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
			/* make NaN quiet */
			Set_invalidflag();
			Sgl_set_quiet(src);
		}
		/*
		 * return quiet NaN or infinity
		 */
		*dstptr = src;
		return(NOEXCEPTION);
	}
	/*
	 * Need to round?
	 */
	if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
		*dstptr = src;
		return(NOEXCEPTION);
	}
	/*
	 * Generate result
	 */
	if (src_exponent >= 0) {
		Sgl_clear_exponent_set_hidden(src);
		result = src;
		Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
		/* check for inexact */
		if (Sgl_isinexact_to_fix(src,src_exponent)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
			     if (Sgl_iszero_sign(src)) Sgl_increment(result);
			     break;
			case ROUNDMINUS:
			     if (Sgl_isone_sign(src)) Sgl_increment(result);
			     break;
			case ROUNDNEAREST:
			     if (Sgl_isone_roundbit(src,src_exponent))
				if (Sgl_isone_stickybit(src,src_exponent)
				|| (Sgl_isone_lowmantissa(result)))
					Sgl_increment(result);
			}
		}
		Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
		if (Sgl_isone_hiddenoverflow(result))
			Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
		else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
	}
	else {
		result = src;		/* set sign */
		Sgl_setzero_exponentmantissa(result);
		/* check for inexact */
		if (Sgl_isnotzero_exponentmantissa(src)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
			     if (Sgl_iszero_sign(src))
				Sgl_set_exponent(result,SGL_BIAS);
			     break;
			case ROUNDMINUS:
			     if (Sgl_isone_sign(src))
				Sgl_set_exponent(result,SGL_BIAS);
			     break;
			case ROUNDNEAREST:
			     if (src_exponent == -1)
				if (Sgl_isnotzero_mantissa(src))
				   Sgl_set_exponent(result,SGL_BIAS);
			}
		}
	}
	*dstptr = result;
	if (inexact) {
		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
		else Set_inexactflag();
	}
	return(NOEXCEPTION);
}

/*
 *  Double Floating-point Round to Integer
 */

/*ARGSUSED*/
int
dbl_frnd(srcptr, null, dstptr, status)
	dbl_floating_point *srcptr, *null, *dstptr;
	unsigned int *status;
{
	register unsigned int srcp1, srcp2, resultp1, resultp2;
	register int src_exponent;
	register int inexact = FALSE;

	Dbl_copyfromptr(srcptr,srcp1,srcp2);
	/*
	 * check source operand for NaN or infinity
	 */
	if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
		/*
		 * is signaling NaN?
		 */
		if (Dbl_isone_signaling(srcp1)) {
			/* trap if INVALIDTRAP enabled */
			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
			/* make NaN quiet */
			Set_invalidflag();
			Dbl_set_quiet(srcp1);
		}
		/*
		 * return quiet NaN or infinity
		 */
		Dbl_copytoptr(srcp1,srcp2,dstptr);
		return(NOEXCEPTION);
	}
	/*
	 * Need to round?
	 */
	if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
		Dbl_copytoptr(srcp1,srcp2,dstptr);
		return(NOEXCEPTION);
	}
	/*
	 * Generate result
	 */
	if (src_exponent >= 0) {
		Dbl_clear_exponent_set_hidden(srcp1);
		resultp1 = srcp1;
		resultp2 = srcp2;
		Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
		/* check for inexact */
		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
			     if (Dbl_iszero_sign(srcp1))
				Dbl_increment(resultp1,resultp2);
			     break;
			case ROUNDMINUS:
			     if (Dbl_isone_sign(srcp1))
				Dbl_increment(resultp1,resultp2);
			     break;
			case ROUNDNEAREST:
			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
			      if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent)
				  || (Dbl_isone_lowmantissap2(resultp2)))
					Dbl_increment(resultp1,resultp2);
			}
		}
		Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
		if (Dbl_isone_hiddenoverflow(resultp1))
			Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
		else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
	}
	else {
		resultp1 = srcp1;  /* set sign */
		Dbl_setzero_exponentmantissa(resultp1,resultp2);
		/* check for inexact */
		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
			inexact = TRUE;
			/*  round result  */
			switch (Rounding_mode()) {
			case ROUNDPLUS:
			     if (Dbl_iszero_sign(srcp1))
				Dbl_set_exponent(resultp1,DBL_BIAS);
			     break;
			case ROUNDMINUS:
			     if (Dbl_isone_sign(srcp1))
				Dbl_set_exponent(resultp1,DBL_BIAS);
			     break;
			case ROUNDNEAREST:
			     if (src_exponent == -1)
				if (Dbl_isnotzero_mantissa(srcp1,srcp2))
				   Dbl_set_exponent(resultp1,DBL_BIAS);
			}
		}
	}
	Dbl_copytoptr(resultp1,resultp2,dstptr);
	if (inexact) {
		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
		else Set_inexactflag();
	}
	return(NOEXCEPTION);
}

/*ARGSUSED*/
int
quad_frnd(srcptr, null, dstptr, status)
	quad_floating_point *srcptr, *null, *dstptr;
	unsigned int *status;
{
	return(UNIMPLEMENTEDEXCEPTION);
}


code:
/*	$OpenBSD: hppa.h,v 1.5 2002/05/07 22:19:30 mickey Exp $	*/
/*
  (c) Copyright 1986 HEWLETT-PACKARD COMPANY
  To anyone who acknowledges that this file is provided "AS IS"
  without any express or implied warranty:
      permission to use, copy, modify, and distribute this file
  for any purpose is hereby granted without fee, provided that
  the above copyright notice and this notice appears in all
  copies, and that the name of Hewlett-Packard Company not be
  used in advertising or publicity pertaining to distribution
  of the software without specific, written prior permission.
  Hewlett-Packard Company makes no representations about the
  suitability of this software for any purpose.
*/
/* @(#)hppa.h: Revision: 2.7.88.1 Date: 93/12/07 15:06:26 */

/* amount is assumed to be a constant between 0 and 32 (non-inclusive) */
#define Shiftdouble(left,right,amount,dest)			\
    /* int left, right, amount, dest; */			\
    dest = ((left) << (32-(amount))) | ((unsigned int)(right) >> (amount))

/* amount must be less than 32 */
#define Variableshiftdouble(left,right,amount,dest)		\
    /* unsigned int left, right;  int amount, dest; */		\
    if (amount == 0) dest = right;				\
    else dest = ((((unsigned) left)&0x7fffffff) << (32-(amount))) |	\
	((unsigned) right >> (amount))

/* amount must be between 0 and 32 (non-inclusive) */
#define Variable_shift_double(left,right,amount,dest)		\
    /* unsigned int left, right;  int amount, dest; */		\
    dest = (left << (32-(amount))) | ((unsigned) right >> (amount))