xref: /openbmc/linux/arch/parisc/math-emu/sfcmp.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*660662f8SThomas 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/sfcmp.c		$Revision: 1.1 $
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  *  Purpose:
151da177e4SLinus Torvalds  *	sgl_cmp: compare two values
161da177e4SLinus Torvalds  *
171da177e4SLinus Torvalds  *  External Interfaces:
181da177e4SLinus Torvalds  *	sgl_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 #include "float.h"
301da177e4SLinus Torvalds #include "sgl_float.h"
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds /*
331da177e4SLinus Torvalds  * sgl_cmp: compare two values
341da177e4SLinus Torvalds  */
351da177e4SLinus Torvalds int
sgl_fcmp(sgl_floating_point * leftptr,sgl_floating_point * rightptr,unsigned int cond,unsigned int * status)361da177e4SLinus Torvalds sgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr,
371da177e4SLinus Torvalds 	  unsigned int cond, unsigned int *status)
381da177e4SLinus Torvalds 
391da177e4SLinus Torvalds                        /* The predicate to be tested */
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds     {
421da177e4SLinus Torvalds     register unsigned int left, right;
431da177e4SLinus Torvalds     register int xorresult;
441da177e4SLinus Torvalds 
451da177e4SLinus Torvalds     /* Create local copies of the numbers */
461da177e4SLinus Torvalds     left = *leftptr;
471da177e4SLinus Torvalds     right = *rightptr;
481da177e4SLinus Torvalds 
491da177e4SLinus Torvalds     /*
501da177e4SLinus Torvalds      * Test for NaN
511da177e4SLinus Torvalds      */
521da177e4SLinus Torvalds     if(    (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
531da177e4SLinus Torvalds         || (Sgl_exponent(right) == SGL_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( (  (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
591da177e4SLinus Torvalds 	    && Sgl_isnotzero_mantissa(left)
601da177e4SLinus Torvalds 	    && (Exception(cond) || Sgl_isone_signaling(left)))
611da177e4SLinus Torvalds 	   ||
621da177e4SLinus Torvalds 	    (  (Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
631da177e4SLinus Torvalds 	    && Sgl_isnotzero_mantissa(right)
641da177e4SLinus Torvalds 	    && (Exception(cond) || Sgl_isone_signaling(right)) ) )
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( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
771da177e4SLinus Torvalds 	    && Sgl_isnotzero_mantissa(left))
781da177e4SLinus Torvalds 	   ||
791da177e4SLinus Torvalds 	    ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
801da177e4SLinus Torvalds 	    && Sgl_isnotzero_mantissa(right)) )
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     Sgl_xortointp1(left,right,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( Sgl_iszero_exponentmantissa(left)
961da177e4SLinus Torvalds 	  && Sgl_iszero_exponentmantissa(right) )
971da177e4SLinus Torvalds             {
981da177e4SLinus Torvalds 	    Set_status_cbit(Equal(cond));
991da177e4SLinus Torvalds 	    }
1001da177e4SLinus Torvalds 	else if( Sgl_isone_sign(left) )
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( Sgl_all(left) == Sgl_all(right) )
1121da177e4SLinus Torvalds         {
1131da177e4SLinus Torvalds         Set_status_cbit(Equal(cond));
1141da177e4SLinus Torvalds         }
1151da177e4SLinus Torvalds     else if( Sgl_iszero_sign(left) )
1161da177e4SLinus Torvalds         {
1171da177e4SLinus Torvalds         /* Positive compare */
1181da177e4SLinus Torvalds         if( Sgl_all(left) < Sgl_all(right) )
1191da177e4SLinus Torvalds 	    {
1201da177e4SLinus Torvalds 	    Set_status_cbit(Lessthan(cond));
1211da177e4SLinus Torvalds 	    }
1221da177e4SLinus Torvalds 	else
1231da177e4SLinus Torvalds 	    {
1241da177e4SLinus Torvalds 	    Set_status_cbit(Greaterthan(cond));
1251da177e4SLinus Torvalds 	    }
1261da177e4SLinus Torvalds 	}
1271da177e4SLinus Torvalds     else
1281da177e4SLinus Torvalds         {
1291da177e4SLinus Torvalds         /* Negative compare.  Signed or unsigned compares
1301da177e4SLinus Torvalds          * both work the same.  That distinction is only
1311da177e4SLinus Torvalds          * important when the sign bits differ. */
1321da177e4SLinus Torvalds         if( Sgl_all(left) > Sgl_all(right) )
1331da177e4SLinus Torvalds 	    {
1341da177e4SLinus Torvalds 	    Set_status_cbit(Lessthan(cond));
1351da177e4SLinus Torvalds 	    }
1361da177e4SLinus Torvalds         else
1371da177e4SLinus Torvalds 	    {
1381da177e4SLinus Torvalds 	    Set_status_cbit(Greaterthan(cond));
1391da177e4SLinus Torvalds 	    }
1401da177e4SLinus Torvalds         }
1411da177e4SLinus Torvalds 	return(NOEXCEPTION);
1421da177e4SLinus Torvalds     }
143