xref: /linux/arch/parisc/math-emu/dfcmp.c (revision 44f57d78)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Linux/PA-RISC Project (http://www.parisc-linux.org/)
4  *
5  * Floating-point emulation code
6  *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
7  */
8 /*
9  * BEGIN_DESC
10  *
11  *  File:
12  *	@(#)	pa/spmath/dfcmp.c		$Revision: 1.1 $
13  *
14  *  Purpose:
15  *	dbl_cmp: compare two values
16  *
17  *  External Interfaces:
18  *	dbl_fcmp(leftptr, rightptr, cond, status)
19  *
20  *  Internal Interfaces:
21  *
22  *  Theory:
23  *	<<please update with a overview of the operation of this file>>
24  *
25  * END_DESC
26 */
27 
28 
29 
30 #include "float.h"
31 #include "dbl_float.h"
32 
33 /*
34  * dbl_cmp: compare two values
35  */
36 int
37 dbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr,
38 	  unsigned int cond, unsigned int *status)
39 
40                        /* The predicate to be tested */
41 
42     {
43     register unsigned int leftp1, leftp2, rightp1, rightp2;
44     register int xorresult;
45 
46     /* Create local copies of the numbers */
47     Dbl_copyfromptr(leftptr,leftp1,leftp2);
48     Dbl_copyfromptr(rightptr,rightp1,rightp2);
49     /*
50      * Test for NaN
51      */
52     if(    (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
53         || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) )
54 	{
55 	/* Check if a NaN is involved.  Signal an invalid exception when
56 	 * comparing a signaling NaN or when comparing quiet NaNs and the
57 	 * low bit of the condition is set */
58         if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
59 	    && Dbl_isnotzero_mantissa(leftp1,leftp2)
60 	    && (Exception(cond) || Dbl_isone_signaling(leftp1)))
61 	   ||
62 	    ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
63 	    && Dbl_isnotzero_mantissa(rightp1,rightp2)
64 	    && (Exception(cond) || Dbl_isone_signaling(rightp1))) )
65 	    {
66 	    if( Is_invalidtrap_enabled() ) {
67 	    	Set_status_cbit(Unordered(cond));
68 		return(INVALIDEXCEPTION);
69 	    }
70 	    else Set_invalidflag();
71 	    Set_status_cbit(Unordered(cond));
72 	    return(NOEXCEPTION);
73 	    }
74 	/* All the exceptional conditions are handled, now special case
75 	   NaN compares */
76         else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
77 	    && Dbl_isnotzero_mantissa(leftp1,leftp2))
78 	   ||
79 	    ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
80 	    && Dbl_isnotzero_mantissa(rightp1,rightp2)) )
81 	    {
82 	    /* NaNs always compare unordered. */
83 	    Set_status_cbit(Unordered(cond));
84 	    return(NOEXCEPTION);
85 	    }
86 	/* infinities will drop down to the normal compare mechanisms */
87 	}
88     /* First compare for unequal signs => less or greater or
89      * special equal case */
90     Dbl_xortointp1(leftp1,rightp1,xorresult);
91     if( xorresult < 0 )
92         {
93         /* left negative => less, left positive => greater.
94          * equal is possible if both operands are zeros. */
95         if( Dbl_iszero_exponentmantissa(leftp1,leftp2)
96 	  && Dbl_iszero_exponentmantissa(rightp1,rightp2) )
97             {
98 	    Set_status_cbit(Equal(cond));
99 	    }
100 	else if( Dbl_isone_sign(leftp1) )
101 	    {
102 	    Set_status_cbit(Lessthan(cond));
103 	    }
104 	else
105 	    {
106 	    Set_status_cbit(Greaterthan(cond));
107 	    }
108         }
109     /* Signs are the same.  Treat negative numbers separately
110      * from the positives because of the reversed sense.  */
111     else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2))
112         {
113         Set_status_cbit(Equal(cond));
114         }
115     else if( Dbl_iszero_sign(leftp1) )
116         {
117         /* Positive compare */
118 	if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
119 	    {
120 	    Set_status_cbit(Lessthan(cond));
121 	    }
122 	else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
123 	    {
124 	    Set_status_cbit(Greaterthan(cond));
125 	    }
126 	else
127 	    {
128 	    /* Equal first parts.  Now we must use unsigned compares to
129 	     * resolve the two possibilities. */
130 	    if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) )
131 		{
132 		Set_status_cbit(Lessthan(cond));
133 		}
134 	    else
135 		{
136 		Set_status_cbit(Greaterthan(cond));
137 		}
138 	    }
139 	}
140     else
141         {
142         /* Negative compare.  Signed or unsigned compares
143          * both work the same.  That distinction is only
144          * important when the sign bits differ. */
145 	if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
146 	    {
147 	    Set_status_cbit(Lessthan(cond));
148 	    }
149 	else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
150 	    {
151 	    Set_status_cbit(Greaterthan(cond));
152 	    }
153 	else
154 	    {
155 	    /* Equal first parts.  Now we must use unsigned compares to
156 	     * resolve the two possibilities. */
157 	    if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) )
158 		{
159 		Set_status_cbit(Lessthan(cond));
160 		}
161 	    else
162 		{
163 		Set_status_cbit(Greaterthan(cond));
164 		}
165 	    }
166         }
167 	return(NOEXCEPTION);
168     }
169