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