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