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/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