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/sfcmp.c		$Revision: 1.1 $
138c2ecf20Sopenharmony_ci *
148c2ecf20Sopenharmony_ci *  Purpose:
158c2ecf20Sopenharmony_ci *	sgl_cmp: compare two values
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci *  External Interfaces:
188c2ecf20Sopenharmony_ci *	sgl_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#include "float.h"
308c2ecf20Sopenharmony_ci#include "sgl_float.h"
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/*
338c2ecf20Sopenharmony_ci * sgl_cmp: compare two values
348c2ecf20Sopenharmony_ci */
358c2ecf20Sopenharmony_ciint
368c2ecf20Sopenharmony_cisgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr,
378c2ecf20Sopenharmony_ci	  unsigned int cond, unsigned int *status)
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci                       /* The predicate to be tested */
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci    {
428c2ecf20Sopenharmony_ci    register unsigned int left, right;
438c2ecf20Sopenharmony_ci    register int xorresult;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci    /* Create local copies of the numbers */
468c2ecf20Sopenharmony_ci    left = *leftptr;
478c2ecf20Sopenharmony_ci    right = *rightptr;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci    /*
508c2ecf20Sopenharmony_ci     * Test for NaN
518c2ecf20Sopenharmony_ci     */
528c2ecf20Sopenharmony_ci    if(    (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
538c2ecf20Sopenharmony_ci        || (Sgl_exponent(right) == SGL_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( (  (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
598c2ecf20Sopenharmony_ci	    && Sgl_isnotzero_mantissa(left)
608c2ecf20Sopenharmony_ci	    && (Exception(cond) || Sgl_isone_signaling(left)))
618c2ecf20Sopenharmony_ci	   ||
628c2ecf20Sopenharmony_ci	    (  (Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
638c2ecf20Sopenharmony_ci	    && Sgl_isnotzero_mantissa(right)
648c2ecf20Sopenharmony_ci	    && (Exception(cond) || Sgl_isone_signaling(right)) ) )
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( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
778c2ecf20Sopenharmony_ci	    && Sgl_isnotzero_mantissa(left))
788c2ecf20Sopenharmony_ci	   ||
798c2ecf20Sopenharmony_ci	    ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
808c2ecf20Sopenharmony_ci	    && Sgl_isnotzero_mantissa(right)) )
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    Sgl_xortointp1(left,right,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( Sgl_iszero_exponentmantissa(left)
968c2ecf20Sopenharmony_ci	  && Sgl_iszero_exponentmantissa(right) )
978c2ecf20Sopenharmony_ci            {
988c2ecf20Sopenharmony_ci	    Set_status_cbit(Equal(cond));
998c2ecf20Sopenharmony_ci	    }
1008c2ecf20Sopenharmony_ci	else if( Sgl_isone_sign(left) )
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( Sgl_all(left) == Sgl_all(right) )
1128c2ecf20Sopenharmony_ci        {
1138c2ecf20Sopenharmony_ci        Set_status_cbit(Equal(cond));
1148c2ecf20Sopenharmony_ci        }
1158c2ecf20Sopenharmony_ci    else if( Sgl_iszero_sign(left) )
1168c2ecf20Sopenharmony_ci        {
1178c2ecf20Sopenharmony_ci        /* Positive compare */
1188c2ecf20Sopenharmony_ci        if( Sgl_all(left) < Sgl_all(right) )
1198c2ecf20Sopenharmony_ci	    {
1208c2ecf20Sopenharmony_ci	    Set_status_cbit(Lessthan(cond));
1218c2ecf20Sopenharmony_ci	    }
1228c2ecf20Sopenharmony_ci	else
1238c2ecf20Sopenharmony_ci	    {
1248c2ecf20Sopenharmony_ci	    Set_status_cbit(Greaterthan(cond));
1258c2ecf20Sopenharmony_ci	    }
1268c2ecf20Sopenharmony_ci	}
1278c2ecf20Sopenharmony_ci    else
1288c2ecf20Sopenharmony_ci        {
1298c2ecf20Sopenharmony_ci        /* Negative compare.  Signed or unsigned compares
1308c2ecf20Sopenharmony_ci         * both work the same.  That distinction is only
1318c2ecf20Sopenharmony_ci         * important when the sign bits differ. */
1328c2ecf20Sopenharmony_ci        if( Sgl_all(left) > Sgl_all(right) )
1338c2ecf20Sopenharmony_ci	    {
1348c2ecf20Sopenharmony_ci	    Set_status_cbit(Lessthan(cond));
1358c2ecf20Sopenharmony_ci	    }
1368c2ecf20Sopenharmony_ci        else
1378c2ecf20Sopenharmony_ci	    {
1388c2ecf20Sopenharmony_ci	    Set_status_cbit(Greaterthan(cond));
1398c2ecf20Sopenharmony_ci	    }
1408c2ecf20Sopenharmony_ci        }
1418c2ecf20Sopenharmony_ci	return(NOEXCEPTION);
1428c2ecf20Sopenharmony_ci    }
143