xref: /openbmc/linux/arch/parisc/math-emu/dfcmp.c (revision 660662f8)
1660662f8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Floating-point emulation code
61da177e4SLinus Torvalds  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
71da177e4SLinus Torvalds  */
81da177e4SLinus Torvalds /*
91da177e4SLinus Torvalds  * BEGIN_DESC
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  *  File:
121da177e4SLinus Torvalds  *	@(#)	pa/spmath/dfcmp.c		$Revision: 1.1 $
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  Purpose:
151da177e4SLinus Torvalds  *	dbl_cmp: compare two values
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  *  External Interfaces:
181da177e4SLinus Torvalds  *	dbl_fcmp(leftptr, rightptr, cond, status)
191da177e4SLinus Torvalds  *
201da177e4SLinus Torvalds  *  Internal Interfaces:
211da177e4SLinus Torvalds  *
221da177e4SLinus Torvalds  *  Theory:
231da177e4SLinus Torvalds  *	<<please update with a overview of the operation of this file>>
241da177e4SLinus Torvalds  *
251da177e4SLinus Torvalds  * END_DESC
261da177e4SLinus Torvalds */
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds #include "float.h"
311da177e4SLinus Torvalds #include "dbl_float.h"
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds /*
341da177e4SLinus Torvalds  * dbl_cmp: compare two values
351da177e4SLinus Torvalds  */
361da177e4SLinus Torvalds int
dbl_fcmp(dbl_floating_point * leftptr,dbl_floating_point * rightptr,unsigned int cond,unsigned int * status)371da177e4SLinus Torvalds dbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr,
381da177e4SLinus Torvalds 	  unsigned int cond, unsigned int *status)
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds                        /* The predicate to be tested */
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds     {
431da177e4SLinus Torvalds     register unsigned int leftp1, leftp2, rightp1, rightp2;
441da177e4SLinus Torvalds     register int xorresult;
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds     /* Create local copies of the numbers */
471da177e4SLinus Torvalds     Dbl_copyfromptr(leftptr,leftp1,leftp2);
481da177e4SLinus Torvalds     Dbl_copyfromptr(rightptr,rightp1,rightp2);
491da177e4SLinus Torvalds     /*
501da177e4SLinus Torvalds      * Test for NaN
511da177e4SLinus Torvalds      */
521da177e4SLinus Torvalds     if(    (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
531da177e4SLinus Torvalds         || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) )
541da177e4SLinus Torvalds 	{
551da177e4SLinus Torvalds 	/* Check if a NaN is involved.  Signal an invalid exception when
561da177e4SLinus Torvalds 	 * comparing a signaling NaN or when comparing quiet NaNs and the
571da177e4SLinus Torvalds 	 * low bit of the condition is set */
581da177e4SLinus Torvalds         if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
591da177e4SLinus Torvalds 	    && Dbl_isnotzero_mantissa(leftp1,leftp2)
601da177e4SLinus Torvalds 	    && (Exception(cond) || Dbl_isone_signaling(leftp1)))
611da177e4SLinus Torvalds 	   ||
621da177e4SLinus Torvalds 	    ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
631da177e4SLinus Torvalds 	    && Dbl_isnotzero_mantissa(rightp1,rightp2)
641da177e4SLinus Torvalds 	    && (Exception(cond) || Dbl_isone_signaling(rightp1))) )
651da177e4SLinus Torvalds 	    {
661da177e4SLinus Torvalds 	    if( Is_invalidtrap_enabled() ) {
671da177e4SLinus Torvalds 	    	Set_status_cbit(Unordered(cond));
681da177e4SLinus Torvalds 		return(INVALIDEXCEPTION);
691da177e4SLinus Torvalds 	    }
701da177e4SLinus Torvalds 	    else Set_invalidflag();
711da177e4SLinus Torvalds 	    Set_status_cbit(Unordered(cond));
721da177e4SLinus Torvalds 	    return(NOEXCEPTION);
731da177e4SLinus Torvalds 	    }
741da177e4SLinus Torvalds 	/* All the exceptional conditions are handled, now special case
751da177e4SLinus Torvalds 	   NaN compares */
761da177e4SLinus Torvalds         else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
771da177e4SLinus Torvalds 	    && Dbl_isnotzero_mantissa(leftp1,leftp2))
781da177e4SLinus Torvalds 	   ||
791da177e4SLinus Torvalds 	    ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
801da177e4SLinus Torvalds 	    && Dbl_isnotzero_mantissa(rightp1,rightp2)) )
811da177e4SLinus Torvalds 	    {
821da177e4SLinus Torvalds 	    /* NaNs always compare unordered. */
831da177e4SLinus Torvalds 	    Set_status_cbit(Unordered(cond));
841da177e4SLinus Torvalds 	    return(NOEXCEPTION);
851da177e4SLinus Torvalds 	    }
861da177e4SLinus Torvalds 	/* infinities will drop down to the normal compare mechanisms */
871da177e4SLinus Torvalds 	}
881da177e4SLinus Torvalds     /* First compare for unequal signs => less or greater or
891da177e4SLinus Torvalds      * special equal case */
901da177e4SLinus Torvalds     Dbl_xortointp1(leftp1,rightp1,xorresult);
911da177e4SLinus Torvalds     if( xorresult < 0 )
921da177e4SLinus Torvalds         {
931da177e4SLinus Torvalds         /* left negative => less, left positive => greater.
941da177e4SLinus Torvalds          * equal is possible if both operands are zeros. */
951da177e4SLinus Torvalds         if( Dbl_iszero_exponentmantissa(leftp1,leftp2)
961da177e4SLinus Torvalds 	  && Dbl_iszero_exponentmantissa(rightp1,rightp2) )
971da177e4SLinus Torvalds             {
981da177e4SLinus Torvalds 	    Set_status_cbit(Equal(cond));
991da177e4SLinus Torvalds 	    }
1001da177e4SLinus Torvalds 	else if( Dbl_isone_sign(leftp1) )
1011da177e4SLinus Torvalds 	    {
1021da177e4SLinus Torvalds 	    Set_status_cbit(Lessthan(cond));
1031da177e4SLinus Torvalds 	    }
1041da177e4SLinus Torvalds 	else
1051da177e4SLinus Torvalds 	    {
1061da177e4SLinus Torvalds 	    Set_status_cbit(Greaterthan(cond));
1071da177e4SLinus Torvalds 	    }
1081da177e4SLinus Torvalds         }
1091da177e4SLinus Torvalds     /* Signs are the same.  Treat negative numbers separately
1101da177e4SLinus Torvalds      * from the positives because of the reversed sense.  */
1111da177e4SLinus Torvalds     else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2))
1121da177e4SLinus Torvalds         {
1131da177e4SLinus Torvalds         Set_status_cbit(Equal(cond));
1141da177e4SLinus Torvalds         }
1151da177e4SLinus Torvalds     else if( Dbl_iszero_sign(leftp1) )
1161da177e4SLinus Torvalds         {
1171da177e4SLinus Torvalds         /* Positive compare */
1181da177e4SLinus Torvalds 	if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
1191da177e4SLinus Torvalds 	    {
1201da177e4SLinus Torvalds 	    Set_status_cbit(Lessthan(cond));
1211da177e4SLinus Torvalds 	    }
1221da177e4SLinus Torvalds 	else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
1231da177e4SLinus Torvalds 	    {
1241da177e4SLinus Torvalds 	    Set_status_cbit(Greaterthan(cond));
1251da177e4SLinus Torvalds 	    }
1261da177e4SLinus Torvalds 	else
1271da177e4SLinus Torvalds 	    {
1281da177e4SLinus Torvalds 	    /* Equal first parts.  Now we must use unsigned compares to
1291da177e4SLinus Torvalds 	     * resolve the two possibilities. */
1301da177e4SLinus Torvalds 	    if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) )
1311da177e4SLinus Torvalds 		{
1321da177e4SLinus Torvalds 		Set_status_cbit(Lessthan(cond));
1331da177e4SLinus Torvalds 		}
1341da177e4SLinus Torvalds 	    else
1351da177e4SLinus Torvalds 		{
1361da177e4SLinus Torvalds 		Set_status_cbit(Greaterthan(cond));
1371da177e4SLinus Torvalds 		}
1381da177e4SLinus Torvalds 	    }
1391da177e4SLinus Torvalds 	}
1401da177e4SLinus Torvalds     else
1411da177e4SLinus Torvalds         {
1421da177e4SLinus Torvalds         /* Negative compare.  Signed or unsigned compares
1431da177e4SLinus Torvalds          * both work the same.  That distinction is only
1441da177e4SLinus Torvalds          * important when the sign bits differ. */
1451da177e4SLinus Torvalds 	if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
1461da177e4SLinus Torvalds 	    {
1471da177e4SLinus Torvalds 	    Set_status_cbit(Lessthan(cond));
1481da177e4SLinus Torvalds 	    }
1491da177e4SLinus Torvalds 	else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
1501da177e4SLinus Torvalds 	    {
1511da177e4SLinus Torvalds 	    Set_status_cbit(Greaterthan(cond));
1521da177e4SLinus Torvalds 	    }
1531da177e4SLinus Torvalds 	else
1541da177e4SLinus Torvalds 	    {
1551da177e4SLinus Torvalds 	    /* Equal first parts.  Now we must use unsigned compares to
1561da177e4SLinus Torvalds 	     * resolve the two possibilities. */
1571da177e4SLinus Torvalds 	    if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) )
1581da177e4SLinus Torvalds 		{
1591da177e4SLinus Torvalds 		Set_status_cbit(Lessthan(cond));
1601da177e4SLinus Torvalds 		}
1611da177e4SLinus Torvalds 	    else
1621da177e4SLinus Torvalds 		{
1631da177e4SLinus Torvalds 		Set_status_cbit(Greaterthan(cond));
1641da177e4SLinus Torvalds 		}
1651da177e4SLinus Torvalds 	    }
1661da177e4SLinus Torvalds         }
1671da177e4SLinus Torvalds 	return(NOEXCEPTION);
1681da177e4SLinus Torvalds     }
169