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/sfcmp.c		$Revision: 1.1 $
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci *  Purpose:
1562306a36Sopenharmony_ci *	sgl_cmp: compare two values
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci *  External Interfaces:
1862306a36Sopenharmony_ci *	sgl_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#include "float.h"
3062306a36Sopenharmony_ci#include "sgl_float.h"
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/*
3362306a36Sopenharmony_ci * sgl_cmp: compare two values
3462306a36Sopenharmony_ci */
3562306a36Sopenharmony_ciint
3662306a36Sopenharmony_cisgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr,
3762306a36Sopenharmony_ci	  unsigned int cond, unsigned int *status)
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci                       /* The predicate to be tested */
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci    {
4262306a36Sopenharmony_ci    register unsigned int left, right;
4362306a36Sopenharmony_ci    register int xorresult;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci    /* Create local copies of the numbers */
4662306a36Sopenharmony_ci    left = *leftptr;
4762306a36Sopenharmony_ci    right = *rightptr;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci    /*
5062306a36Sopenharmony_ci     * Test for NaN
5162306a36Sopenharmony_ci     */
5262306a36Sopenharmony_ci    if(    (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
5362306a36Sopenharmony_ci        || (Sgl_exponent(right) == SGL_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( (  (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
5962306a36Sopenharmony_ci	    && Sgl_isnotzero_mantissa(left)
6062306a36Sopenharmony_ci	    && (Exception(cond) || Sgl_isone_signaling(left)))
6162306a36Sopenharmony_ci	   ||
6262306a36Sopenharmony_ci	    (  (Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
6362306a36Sopenharmony_ci	    && Sgl_isnotzero_mantissa(right)
6462306a36Sopenharmony_ci	    && (Exception(cond) || Sgl_isone_signaling(right)) ) )
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( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
7762306a36Sopenharmony_ci	    && Sgl_isnotzero_mantissa(left))
7862306a36Sopenharmony_ci	   ||
7962306a36Sopenharmony_ci	    ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
8062306a36Sopenharmony_ci	    && Sgl_isnotzero_mantissa(right)) )
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    Sgl_xortointp1(left,right,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( Sgl_iszero_exponentmantissa(left)
9662306a36Sopenharmony_ci	  && Sgl_iszero_exponentmantissa(right) )
9762306a36Sopenharmony_ci            {
9862306a36Sopenharmony_ci	    Set_status_cbit(Equal(cond));
9962306a36Sopenharmony_ci	    }
10062306a36Sopenharmony_ci	else if( Sgl_isone_sign(left) )
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( Sgl_all(left) == Sgl_all(right) )
11262306a36Sopenharmony_ci        {
11362306a36Sopenharmony_ci        Set_status_cbit(Equal(cond));
11462306a36Sopenharmony_ci        }
11562306a36Sopenharmony_ci    else if( Sgl_iszero_sign(left) )
11662306a36Sopenharmony_ci        {
11762306a36Sopenharmony_ci        /* Positive compare */
11862306a36Sopenharmony_ci        if( Sgl_all(left) < Sgl_all(right) )
11962306a36Sopenharmony_ci	    {
12062306a36Sopenharmony_ci	    Set_status_cbit(Lessthan(cond));
12162306a36Sopenharmony_ci	    }
12262306a36Sopenharmony_ci	else
12362306a36Sopenharmony_ci	    {
12462306a36Sopenharmony_ci	    Set_status_cbit(Greaterthan(cond));
12562306a36Sopenharmony_ci	    }
12662306a36Sopenharmony_ci	}
12762306a36Sopenharmony_ci    else
12862306a36Sopenharmony_ci        {
12962306a36Sopenharmony_ci        /* Negative compare.  Signed or unsigned compares
13062306a36Sopenharmony_ci         * both work the same.  That distinction is only
13162306a36Sopenharmony_ci         * important when the sign bits differ. */
13262306a36Sopenharmony_ci        if( Sgl_all(left) > Sgl_all(right) )
13362306a36Sopenharmony_ci	    {
13462306a36Sopenharmony_ci	    Set_status_cbit(Lessthan(cond));
13562306a36Sopenharmony_ci	    }
13662306a36Sopenharmony_ci        else
13762306a36Sopenharmony_ci	    {
13862306a36Sopenharmony_ci	    Set_status_cbit(Greaterthan(cond));
13962306a36Sopenharmony_ci	    }
14062306a36Sopenharmony_ci        }
14162306a36Sopenharmony_ci	return(NOEXCEPTION);
14262306a36Sopenharmony_ci    }
143