18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Linux/PA-RISC Project (http://www.parisc-linux.org/)
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Floating-point emulation code
68c2ecf20Sopenharmony_ci *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci/*
98c2ecf20Sopenharmony_ci * BEGIN_DESC
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci *  File:
128c2ecf20Sopenharmony_ci *	@(#)	pa/spmath/dfcmp.c		$Revision: 1.1 $
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci *  Purpose:
158c2ecf20Sopenharmony_ci *	dbl_cmp: compare two values
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci *  External Interfaces:
188c2ecf20Sopenharmony_ci *	dbl_fcmp(leftptr, rightptr, cond, status)
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci *  Internal Interfaces:
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci *  Theory:
238c2ecf20Sopenharmony_ci *	<<please update with a overview of the operation of this file>>
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * END_DESC
268c2ecf20Sopenharmony_ci*/
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#include "float.h"
318c2ecf20Sopenharmony_ci#include "dbl_float.h"
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/*
348c2ecf20Sopenharmony_ci * dbl_cmp: compare two values
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_ciint
378c2ecf20Sopenharmony_cidbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr,
388c2ecf20Sopenharmony_ci	  unsigned int cond, unsigned int *status)
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci                       /* The predicate to be tested */
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci    {
438c2ecf20Sopenharmony_ci    register unsigned int leftp1, leftp2, rightp1, rightp2;
448c2ecf20Sopenharmony_ci    register int xorresult;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci    /* Create local copies of the numbers */
478c2ecf20Sopenharmony_ci    Dbl_copyfromptr(leftptr,leftp1,leftp2);
488c2ecf20Sopenharmony_ci    Dbl_copyfromptr(rightptr,rightp1,rightp2);
498c2ecf20Sopenharmony_ci    /*
508c2ecf20Sopenharmony_ci     * Test for NaN
518c2ecf20Sopenharmony_ci     */
528c2ecf20Sopenharmony_ci    if(    (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
538c2ecf20Sopenharmony_ci        || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) )
548c2ecf20Sopenharmony_ci	{
558c2ecf20Sopenharmony_ci	/* Check if a NaN is involved.  Signal an invalid exception when
568c2ecf20Sopenharmony_ci	 * comparing a signaling NaN or when comparing quiet NaNs and the
578c2ecf20Sopenharmony_ci	 * low bit of the condition is set */
588c2ecf20Sopenharmony_ci        if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
598c2ecf20Sopenharmony_ci	    && Dbl_isnotzero_mantissa(leftp1,leftp2)
608c2ecf20Sopenharmony_ci	    && (Exception(cond) || Dbl_isone_signaling(leftp1)))
618c2ecf20Sopenharmony_ci	   ||
628c2ecf20Sopenharmony_ci	    ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
638c2ecf20Sopenharmony_ci	    && Dbl_isnotzero_mantissa(rightp1,rightp2)
648c2ecf20Sopenharmony_ci	    && (Exception(cond) || Dbl_isone_signaling(rightp1))) )
658c2ecf20Sopenharmony_ci	    {
668c2ecf20Sopenharmony_ci	    if( Is_invalidtrap_enabled() ) {
678c2ecf20Sopenharmony_ci	    	Set_status_cbit(Unordered(cond));
688c2ecf20Sopenharmony_ci		return(INVALIDEXCEPTION);
698c2ecf20Sopenharmony_ci	    }
708c2ecf20Sopenharmony_ci	    else Set_invalidflag();
718c2ecf20Sopenharmony_ci	    Set_status_cbit(Unordered(cond));
728c2ecf20Sopenharmony_ci	    return(NOEXCEPTION);
738c2ecf20Sopenharmony_ci	    }
748c2ecf20Sopenharmony_ci	/* All the exceptional conditions are handled, now special case
758c2ecf20Sopenharmony_ci	   NaN compares */
768c2ecf20Sopenharmony_ci        else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
778c2ecf20Sopenharmony_ci	    && Dbl_isnotzero_mantissa(leftp1,leftp2))
788c2ecf20Sopenharmony_ci	   ||
798c2ecf20Sopenharmony_ci	    ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
808c2ecf20Sopenharmony_ci	    && Dbl_isnotzero_mantissa(rightp1,rightp2)) )
818c2ecf20Sopenharmony_ci	    {
828c2ecf20Sopenharmony_ci	    /* NaNs always compare unordered. */
838c2ecf20Sopenharmony_ci	    Set_status_cbit(Unordered(cond));
848c2ecf20Sopenharmony_ci	    return(NOEXCEPTION);
858c2ecf20Sopenharmony_ci	    }
868c2ecf20Sopenharmony_ci	/* infinities will drop down to the normal compare mechanisms */
878c2ecf20Sopenharmony_ci	}
888c2ecf20Sopenharmony_ci    /* First compare for unequal signs => less or greater or
898c2ecf20Sopenharmony_ci     * special equal case */
908c2ecf20Sopenharmony_ci    Dbl_xortointp1(leftp1,rightp1,xorresult);
918c2ecf20Sopenharmony_ci    if( xorresult < 0 )
928c2ecf20Sopenharmony_ci        {
938c2ecf20Sopenharmony_ci        /* left negative => less, left positive => greater.
948c2ecf20Sopenharmony_ci         * equal is possible if both operands are zeros. */
958c2ecf20Sopenharmony_ci        if( Dbl_iszero_exponentmantissa(leftp1,leftp2)
968c2ecf20Sopenharmony_ci	  && Dbl_iszero_exponentmantissa(rightp1,rightp2) )
978c2ecf20Sopenharmony_ci            {
988c2ecf20Sopenharmony_ci	    Set_status_cbit(Equal(cond));
998c2ecf20Sopenharmony_ci	    }
1008c2ecf20Sopenharmony_ci	else if( Dbl_isone_sign(leftp1) )
1018c2ecf20Sopenharmony_ci	    {
1028c2ecf20Sopenharmony_ci	    Set_status_cbit(Lessthan(cond));
1038c2ecf20Sopenharmony_ci	    }
1048c2ecf20Sopenharmony_ci	else
1058c2ecf20Sopenharmony_ci	    {
1068c2ecf20Sopenharmony_ci	    Set_status_cbit(Greaterthan(cond));
1078c2ecf20Sopenharmony_ci	    }
1088c2ecf20Sopenharmony_ci        }
1098c2ecf20Sopenharmony_ci    /* Signs are the same.  Treat negative numbers separately
1108c2ecf20Sopenharmony_ci     * from the positives because of the reversed sense.  */
1118c2ecf20Sopenharmony_ci    else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2))
1128c2ecf20Sopenharmony_ci        {
1138c2ecf20Sopenharmony_ci        Set_status_cbit(Equal(cond));
1148c2ecf20Sopenharmony_ci        }
1158c2ecf20Sopenharmony_ci    else if( Dbl_iszero_sign(leftp1) )
1168c2ecf20Sopenharmony_ci        {
1178c2ecf20Sopenharmony_ci        /* Positive compare */
1188c2ecf20Sopenharmony_ci	if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
1198c2ecf20Sopenharmony_ci	    {
1208c2ecf20Sopenharmony_ci	    Set_status_cbit(Lessthan(cond));
1218c2ecf20Sopenharmony_ci	    }
1228c2ecf20Sopenharmony_ci	else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
1238c2ecf20Sopenharmony_ci	    {
1248c2ecf20Sopenharmony_ci	    Set_status_cbit(Greaterthan(cond));
1258c2ecf20Sopenharmony_ci	    }
1268c2ecf20Sopenharmony_ci	else
1278c2ecf20Sopenharmony_ci	    {
1288c2ecf20Sopenharmony_ci	    /* Equal first parts.  Now we must use unsigned compares to
1298c2ecf20Sopenharmony_ci	     * resolve the two possibilities. */
1308c2ecf20Sopenharmony_ci	    if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) )
1318c2ecf20Sopenharmony_ci		{
1328c2ecf20Sopenharmony_ci		Set_status_cbit(Lessthan(cond));
1338c2ecf20Sopenharmony_ci		}
1348c2ecf20Sopenharmony_ci	    else
1358c2ecf20Sopenharmony_ci		{
1368c2ecf20Sopenharmony_ci		Set_status_cbit(Greaterthan(cond));
1378c2ecf20Sopenharmony_ci		}
1388c2ecf20Sopenharmony_ci	    }
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci    else
1418c2ecf20Sopenharmony_ci        {
1428c2ecf20Sopenharmony_ci        /* Negative compare.  Signed or unsigned compares
1438c2ecf20Sopenharmony_ci         * both work the same.  That distinction is only
1448c2ecf20Sopenharmony_ci         * important when the sign bits differ. */
1458c2ecf20Sopenharmony_ci	if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
1468c2ecf20Sopenharmony_ci	    {
1478c2ecf20Sopenharmony_ci	    Set_status_cbit(Lessthan(cond));
1488c2ecf20Sopenharmony_ci	    }
1498c2ecf20Sopenharmony_ci	else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
1508c2ecf20Sopenharmony_ci	    {
1518c2ecf20Sopenharmony_ci	    Set_status_cbit(Greaterthan(cond));
1528c2ecf20Sopenharmony_ci	    }
1538c2ecf20Sopenharmony_ci	else
1548c2ecf20Sopenharmony_ci	    {
1558c2ecf20Sopenharmony_ci	    /* Equal first parts.  Now we must use unsigned compares to
1568c2ecf20Sopenharmony_ci	     * resolve the two possibilities. */
1578c2ecf20Sopenharmony_ci	    if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) )
1588c2ecf20Sopenharmony_ci		{
1598c2ecf20Sopenharmony_ci		Set_status_cbit(Lessthan(cond));
1608c2ecf20Sopenharmony_ci		}
1618c2ecf20Sopenharmony_ci	    else
1628c2ecf20Sopenharmony_ci		{
1638c2ecf20Sopenharmony_ci		Set_status_cbit(Greaterthan(cond));
1648c2ecf20Sopenharmony_ci		}
1658c2ecf20Sopenharmony_ci	    }
1668c2ecf20Sopenharmony_ci        }
1678c2ecf20Sopenharmony_ci	return(NOEXCEPTION);
1688c2ecf20Sopenharmony_ci    }
169