11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Linux/PA-RISC Project (http://www.parisc-linux.org/) 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Floating-point emulation code 51da177e4SLinus Torvalds * Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> 61da177e4SLinus Torvalds * 71da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 91da177e4SLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 101da177e4SLinus Torvalds * any later version. 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 131da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 141da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151da177e4SLinus Torvalds * GNU General Public License for more details. 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 181da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 191da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 201da177e4SLinus Torvalds */ 211da177e4SLinus Torvalds /* 221da177e4SLinus Torvalds * BEGIN_DESC 231da177e4SLinus Torvalds * 241da177e4SLinus Torvalds * File: 251da177e4SLinus Torvalds * @(#) pa/spmath/dfcmp.c $Revision: 1.1 $ 261da177e4SLinus Torvalds * 271da177e4SLinus Torvalds * Purpose: 281da177e4SLinus Torvalds * dbl_cmp: compare two values 291da177e4SLinus Torvalds * 301da177e4SLinus Torvalds * External Interfaces: 311da177e4SLinus Torvalds * dbl_fcmp(leftptr, rightptr, cond, status) 321da177e4SLinus Torvalds * 331da177e4SLinus Torvalds * Internal Interfaces: 341da177e4SLinus Torvalds * 351da177e4SLinus Torvalds * Theory: 361da177e4SLinus Torvalds * <<please update with a overview of the operation of this file>> 371da177e4SLinus Torvalds * 381da177e4SLinus Torvalds * END_DESC 391da177e4SLinus Torvalds */ 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds #include "float.h" 441da177e4SLinus Torvalds #include "dbl_float.h" 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds /* 471da177e4SLinus Torvalds * dbl_cmp: compare two values 481da177e4SLinus Torvalds */ 491da177e4SLinus Torvalds int 501da177e4SLinus Torvalds dbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr, 511da177e4SLinus Torvalds unsigned int cond, unsigned int *status) 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds /* The predicate to be tested */ 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds { 561da177e4SLinus Torvalds register unsigned int leftp1, leftp2, rightp1, rightp2; 571da177e4SLinus Torvalds register int xorresult; 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds /* Create local copies of the numbers */ 601da177e4SLinus Torvalds Dbl_copyfromptr(leftptr,leftp1,leftp2); 611da177e4SLinus Torvalds Dbl_copyfromptr(rightptr,rightp1,rightp2); 621da177e4SLinus Torvalds /* 631da177e4SLinus Torvalds * Test for NaN 641da177e4SLinus Torvalds */ 651da177e4SLinus Torvalds if( (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) 661da177e4SLinus Torvalds || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) ) 671da177e4SLinus Torvalds { 681da177e4SLinus Torvalds /* Check if a NaN is involved. Signal an invalid exception when 691da177e4SLinus Torvalds * comparing a signaling NaN or when comparing quiet NaNs and the 701da177e4SLinus Torvalds * low bit of the condition is set */ 711da177e4SLinus Torvalds if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) 721da177e4SLinus Torvalds && Dbl_isnotzero_mantissa(leftp1,leftp2) 731da177e4SLinus Torvalds && (Exception(cond) || Dbl_isone_signaling(leftp1))) 741da177e4SLinus Torvalds || 751da177e4SLinus Torvalds ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) 761da177e4SLinus Torvalds && Dbl_isnotzero_mantissa(rightp1,rightp2) 771da177e4SLinus Torvalds && (Exception(cond) || Dbl_isone_signaling(rightp1))) ) 781da177e4SLinus Torvalds { 791da177e4SLinus Torvalds if( Is_invalidtrap_enabled() ) { 801da177e4SLinus Torvalds Set_status_cbit(Unordered(cond)); 811da177e4SLinus Torvalds return(INVALIDEXCEPTION); 821da177e4SLinus Torvalds } 831da177e4SLinus Torvalds else Set_invalidflag(); 841da177e4SLinus Torvalds Set_status_cbit(Unordered(cond)); 851da177e4SLinus Torvalds return(NOEXCEPTION); 861da177e4SLinus Torvalds } 871da177e4SLinus Torvalds /* All the exceptional conditions are handled, now special case 881da177e4SLinus Torvalds NaN compares */ 891da177e4SLinus Torvalds else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT) 901da177e4SLinus Torvalds && Dbl_isnotzero_mantissa(leftp1,leftp2)) 911da177e4SLinus Torvalds || 921da177e4SLinus Torvalds ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) 931da177e4SLinus Torvalds && Dbl_isnotzero_mantissa(rightp1,rightp2)) ) 941da177e4SLinus Torvalds { 951da177e4SLinus Torvalds /* NaNs always compare unordered. */ 961da177e4SLinus Torvalds Set_status_cbit(Unordered(cond)); 971da177e4SLinus Torvalds return(NOEXCEPTION); 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds /* infinities will drop down to the normal compare mechanisms */ 1001da177e4SLinus Torvalds } 1011da177e4SLinus Torvalds /* First compare for unequal signs => less or greater or 1021da177e4SLinus Torvalds * special equal case */ 1031da177e4SLinus Torvalds Dbl_xortointp1(leftp1,rightp1,xorresult); 1041da177e4SLinus Torvalds if( xorresult < 0 ) 1051da177e4SLinus Torvalds { 1061da177e4SLinus Torvalds /* left negative => less, left positive => greater. 1071da177e4SLinus Torvalds * equal is possible if both operands are zeros. */ 1081da177e4SLinus Torvalds if( Dbl_iszero_exponentmantissa(leftp1,leftp2) 1091da177e4SLinus Torvalds && Dbl_iszero_exponentmantissa(rightp1,rightp2) ) 1101da177e4SLinus Torvalds { 1111da177e4SLinus Torvalds Set_status_cbit(Equal(cond)); 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds else if( Dbl_isone_sign(leftp1) ) 1141da177e4SLinus Torvalds { 1151da177e4SLinus Torvalds Set_status_cbit(Lessthan(cond)); 1161da177e4SLinus Torvalds } 1171da177e4SLinus Torvalds else 1181da177e4SLinus Torvalds { 1191da177e4SLinus Torvalds Set_status_cbit(Greaterthan(cond)); 1201da177e4SLinus Torvalds } 1211da177e4SLinus Torvalds } 1221da177e4SLinus Torvalds /* Signs are the same. Treat negative numbers separately 1231da177e4SLinus Torvalds * from the positives because of the reversed sense. */ 1241da177e4SLinus Torvalds else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2)) 1251da177e4SLinus Torvalds { 1261da177e4SLinus Torvalds Set_status_cbit(Equal(cond)); 1271da177e4SLinus Torvalds } 1281da177e4SLinus Torvalds else if( Dbl_iszero_sign(leftp1) ) 1291da177e4SLinus Torvalds { 1301da177e4SLinus Torvalds /* Positive compare */ 1311da177e4SLinus Torvalds if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) ) 1321da177e4SLinus Torvalds { 1331da177e4SLinus Torvalds Set_status_cbit(Lessthan(cond)); 1341da177e4SLinus Torvalds } 1351da177e4SLinus Torvalds else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) ) 1361da177e4SLinus Torvalds { 1371da177e4SLinus Torvalds Set_status_cbit(Greaterthan(cond)); 1381da177e4SLinus Torvalds } 1391da177e4SLinus Torvalds else 1401da177e4SLinus Torvalds { 1411da177e4SLinus Torvalds /* Equal first parts. Now we must use unsigned compares to 1421da177e4SLinus Torvalds * resolve the two possibilities. */ 1431da177e4SLinus Torvalds if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) ) 1441da177e4SLinus Torvalds { 1451da177e4SLinus Torvalds Set_status_cbit(Lessthan(cond)); 1461da177e4SLinus Torvalds } 1471da177e4SLinus Torvalds else 1481da177e4SLinus Torvalds { 1491da177e4SLinus Torvalds Set_status_cbit(Greaterthan(cond)); 1501da177e4SLinus Torvalds } 1511da177e4SLinus Torvalds } 1521da177e4SLinus Torvalds } 1531da177e4SLinus Torvalds else 1541da177e4SLinus Torvalds { 1551da177e4SLinus Torvalds /* Negative compare. Signed or unsigned compares 1561da177e4SLinus Torvalds * both work the same. That distinction is only 1571da177e4SLinus Torvalds * important when the sign bits differ. */ 1581da177e4SLinus Torvalds if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) ) 1591da177e4SLinus Torvalds { 1601da177e4SLinus Torvalds Set_status_cbit(Lessthan(cond)); 1611da177e4SLinus Torvalds } 1621da177e4SLinus Torvalds else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) ) 1631da177e4SLinus Torvalds { 1641da177e4SLinus Torvalds Set_status_cbit(Greaterthan(cond)); 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds else 1671da177e4SLinus Torvalds { 1681da177e4SLinus Torvalds /* Equal first parts. Now we must use unsigned compares to 1691da177e4SLinus Torvalds * resolve the two possibilities. */ 1701da177e4SLinus Torvalds if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) ) 1711da177e4SLinus Torvalds { 1721da177e4SLinus Torvalds Set_status_cbit(Lessthan(cond)); 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds else 1751da177e4SLinus Torvalds { 1761da177e4SLinus Torvalds Set_status_cbit(Greaterthan(cond)); 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds } 1791da177e4SLinus Torvalds } 1801da177e4SLinus Torvalds return(NOEXCEPTION); 1811da177e4SLinus Torvalds } 182