162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/)
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Floating-point emulation code
662306a36Sopenharmony_ci *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci * BEGIN_DESC
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci *  File:
1262306a36Sopenharmony_ci *	@(#)	pa/spmath/dfcmp.c		$Revision: 1.1 $
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *  Purpose:
1562306a36Sopenharmony_ci *	dbl_cmp: compare two values
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci *  External Interfaces:
1862306a36Sopenharmony_ci *	dbl_fcmp(leftptr, rightptr, cond, status)
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci *  Internal Interfaces:
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci *  Theory:
2362306a36Sopenharmony_ci *	<<please update with a overview of the operation of this file>>
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * END_DESC
2662306a36Sopenharmony_ci*/
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include "float.h"
3162306a36Sopenharmony_ci#include "dbl_float.h"
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/*
3462306a36Sopenharmony_ci * dbl_cmp: compare two values
3562306a36Sopenharmony_ci */
3662306a36Sopenharmony_ciint
3762306a36Sopenharmony_cidbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr,
3862306a36Sopenharmony_ci	  unsigned int cond, unsigned int *status)
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci                       /* The predicate to be tested */
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci    {
4362306a36Sopenharmony_ci    register unsigned int leftp1, leftp2, rightp1, rightp2;
4462306a36Sopenharmony_ci    register int xorresult;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci    /* Create local copies of the numbers */
4762306a36Sopenharmony_ci    Dbl_copyfromptr(leftptr,leftp1,leftp2);
4862306a36Sopenharmony_ci    Dbl_copyfromptr(rightptr,rightp1,rightp2);
4962306a36Sopenharmony_ci    /*
5062306a36Sopenharmony_ci     * Test for NaN
5162306a36Sopenharmony_ci     */
5262306a36Sopenharmony_ci    if(    (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
5362306a36Sopenharmony_ci        || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) )
5462306a36Sopenharmony_ci	{
5562306a36Sopenharmony_ci	/* Check if a NaN is involved.  Signal an invalid exception when
5662306a36Sopenharmony_ci	 * comparing a signaling NaN or when comparing quiet NaNs and the
5762306a36Sopenharmony_ci	 * low bit of the condition is set */
5862306a36Sopenharmony_ci        if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
5962306a36Sopenharmony_ci	    && Dbl_isnotzero_mantissa(leftp1,leftp2)
6062306a36Sopenharmony_ci	    && (Exception(cond) || Dbl_isone_signaling(leftp1)))
6162306a36Sopenharmony_ci	   ||
6262306a36Sopenharmony_ci	    ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
6362306a36Sopenharmony_ci	    && Dbl_isnotzero_mantissa(rightp1,rightp2)
6462306a36Sopenharmony_ci	    && (Exception(cond) || Dbl_isone_signaling(rightp1))) )
6562306a36Sopenharmony_ci	    {
6662306a36Sopenharmony_ci	    if( Is_invalidtrap_enabled() ) {
6762306a36Sopenharmony_ci	    	Set_status_cbit(Unordered(cond));
6862306a36Sopenharmony_ci		return(INVALIDEXCEPTION);
6962306a36Sopenharmony_ci	    }
7062306a36Sopenharmony_ci	    else Set_invalidflag();
7162306a36Sopenharmony_ci	    Set_status_cbit(Unordered(cond));
7262306a36Sopenharmony_ci	    return(NOEXCEPTION);
7362306a36Sopenharmony_ci	    }
7462306a36Sopenharmony_ci	/* All the exceptional conditions are handled, now special case
7562306a36Sopenharmony_ci	   NaN compares */
7662306a36Sopenharmony_ci        else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
7762306a36Sopenharmony_ci	    && Dbl_isnotzero_mantissa(leftp1,leftp2))
7862306a36Sopenharmony_ci	   ||
7962306a36Sopenharmony_ci	    ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
8062306a36Sopenharmony_ci	    && Dbl_isnotzero_mantissa(rightp1,rightp2)) )
8162306a36Sopenharmony_ci	    {
8262306a36Sopenharmony_ci	    /* NaNs always compare unordered. */
8362306a36Sopenharmony_ci	    Set_status_cbit(Unordered(cond));
8462306a36Sopenharmony_ci	    return(NOEXCEPTION);
8562306a36Sopenharmony_ci	    }
8662306a36Sopenharmony_ci	/* infinities will drop down to the normal compare mechanisms */
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci    /* First compare for unequal signs => less or greater or
8962306a36Sopenharmony_ci     * special equal case */
9062306a36Sopenharmony_ci    Dbl_xortointp1(leftp1,rightp1,xorresult);
9162306a36Sopenharmony_ci    if( xorresult < 0 )
9262306a36Sopenharmony_ci        {
9362306a36Sopenharmony_ci        /* left negative => less, left positive => greater.
9462306a36Sopenharmony_ci         * equal is possible if both operands are zeros. */
9562306a36Sopenharmony_ci        if( Dbl_iszero_exponentmantissa(leftp1,leftp2)
9662306a36Sopenharmony_ci	  && Dbl_iszero_exponentmantissa(rightp1,rightp2) )
9762306a36Sopenharmony_ci            {
9862306a36Sopenharmony_ci	    Set_status_cbit(Equal(cond));
9962306a36Sopenharmony_ci	    }
10062306a36Sopenharmony_ci	else if( Dbl_isone_sign(leftp1) )
10162306a36Sopenharmony_ci	    {
10262306a36Sopenharmony_ci	    Set_status_cbit(Lessthan(cond));
10362306a36Sopenharmony_ci	    }
10462306a36Sopenharmony_ci	else
10562306a36Sopenharmony_ci	    {
10662306a36Sopenharmony_ci	    Set_status_cbit(Greaterthan(cond));
10762306a36Sopenharmony_ci	    }
10862306a36Sopenharmony_ci        }
10962306a36Sopenharmony_ci    /* Signs are the same.  Treat negative numbers separately
11062306a36Sopenharmony_ci     * from the positives because of the reversed sense.  */
11162306a36Sopenharmony_ci    else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2))
11262306a36Sopenharmony_ci        {
11362306a36Sopenharmony_ci        Set_status_cbit(Equal(cond));
11462306a36Sopenharmony_ci        }
11562306a36Sopenharmony_ci    else if( Dbl_iszero_sign(leftp1) )
11662306a36Sopenharmony_ci        {
11762306a36Sopenharmony_ci        /* Positive compare */
11862306a36Sopenharmony_ci	if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
11962306a36Sopenharmony_ci	    {
12062306a36Sopenharmony_ci	    Set_status_cbit(Lessthan(cond));
12162306a36Sopenharmony_ci	    }
12262306a36Sopenharmony_ci	else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
12362306a36Sopenharmony_ci	    {
12462306a36Sopenharmony_ci	    Set_status_cbit(Greaterthan(cond));
12562306a36Sopenharmony_ci	    }
12662306a36Sopenharmony_ci	else
12762306a36Sopenharmony_ci	    {
12862306a36Sopenharmony_ci	    /* Equal first parts.  Now we must use unsigned compares to
12962306a36Sopenharmony_ci	     * resolve the two possibilities. */
13062306a36Sopenharmony_ci	    if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) )
13162306a36Sopenharmony_ci		{
13262306a36Sopenharmony_ci		Set_status_cbit(Lessthan(cond));
13362306a36Sopenharmony_ci		}
13462306a36Sopenharmony_ci	    else
13562306a36Sopenharmony_ci		{
13662306a36Sopenharmony_ci		Set_status_cbit(Greaterthan(cond));
13762306a36Sopenharmony_ci		}
13862306a36Sopenharmony_ci	    }
13962306a36Sopenharmony_ci	}
14062306a36Sopenharmony_ci    else
14162306a36Sopenharmony_ci        {
14262306a36Sopenharmony_ci        /* Negative compare.  Signed or unsigned compares
14362306a36Sopenharmony_ci         * both work the same.  That distinction is only
14462306a36Sopenharmony_ci         * important when the sign bits differ. */
14562306a36Sopenharmony_ci	if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
14662306a36Sopenharmony_ci	    {
14762306a36Sopenharmony_ci	    Set_status_cbit(Lessthan(cond));
14862306a36Sopenharmony_ci	    }
14962306a36Sopenharmony_ci	else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
15062306a36Sopenharmony_ci	    {
15162306a36Sopenharmony_ci	    Set_status_cbit(Greaterthan(cond));
15262306a36Sopenharmony_ci	    }
15362306a36Sopenharmony_ci	else
15462306a36Sopenharmony_ci	    {
15562306a36Sopenharmony_ci	    /* Equal first parts.  Now we must use unsigned compares to
15662306a36Sopenharmony_ci	     * resolve the two possibilities. */
15762306a36Sopenharmony_ci	    if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) )
15862306a36Sopenharmony_ci		{
15962306a36Sopenharmony_ci		Set_status_cbit(Lessthan(cond));
16062306a36Sopenharmony_ci		}
16162306a36Sopenharmony_ci	    else
16262306a36Sopenharmony_ci		{
16362306a36Sopenharmony_ci		Set_status_cbit(Greaterthan(cond));
16462306a36Sopenharmony_ci		}
16562306a36Sopenharmony_ci	    }
16662306a36Sopenharmony_ci        }
16762306a36Sopenharmony_ci	return(NOEXCEPTION);
16862306a36Sopenharmony_ci    }
169