xref: /illumos-gate/usr/src/lib/libc/sparc/fp/_Q_fcc.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1994-1997, by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "quad.h"
30 
31 #ifdef __sparcv9
32 #define	_Q_feq	_Qp_feq
33 #define	_Q_fne	_Qp_fne
34 #define	_Q_flt	_Qp_flt
35 #define	_Q_fle	_Qp_fle
36 #define	_Q_fgt	_Qp_fgt
37 #define	_Q_fge	_Qp_fge
38 #endif
39 
40 /*
41  * _Q_feq(x, y) returns nonzero if *x == *y and zero otherwise.
42  * If either *x or *y is a signaling NaN, the invalid operation
43  * exception is raised.
44  */
45 int
_Q_feq(const union longdouble * x,const union longdouble * y)46 _Q_feq(const union longdouble *x, const union longdouble *y)
47 {
48 	unsigned int	fsr;
49 
50 	if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
51 		if ((QUAD_ISNAN(*x) && !(x->l.msw & 0x8000)) ||
52 		    (QUAD_ISNAN(*y) && !(y->l.msw & 0x8000))) {
53 			/* snan, signal invalid */
54 			__quad_getfsrp(&fsr);
55 			if (fsr & FSR_NVM) {
56 				__quad_fcmpq(x, y, &fsr);
57 				return (((fsr >> 10) & 3) == fcc_equal);
58 			} else {
59 				fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
60 				__quad_setfsrp(&fsr);
61 			}
62 		}
63 		return (0);
64 	}
65 	if (QUAD_ISZERO(*x) && QUAD_ISZERO(*y))
66 		return (1);
67 	return ((x->l.msw ^ y->l.msw | x->l.frac2 ^ y->l.frac2 |
68 	    x->l.frac3 ^ y->l.frac3 | x->l.frac4 ^ y->l.frac4) == 0);
69 }
70 
71 /*
72  * _Q_fne(x, y) returns nonzero if *x != *y and zero otherwise.
73  * If either *x or *y is a signaling NaN, the invalid operation
74  * exception is raised.
75  */
76 int
_Q_fne(const union longdouble * x,const union longdouble * y)77 _Q_fne(const union longdouble *x, const union longdouble *y)
78 {
79 	unsigned int	fsr;
80 
81 	if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
82 		if ((QUAD_ISNAN(*x) && !(x->l.msw & 0x8000)) ||
83 		    (QUAD_ISNAN(*y) && !(y->l.msw & 0x8000))) {
84 			/* snan, signal invalid */
85 			__quad_getfsrp(&fsr);
86 			if (fsr & FSR_NVM) {
87 				__quad_fcmpq(x, y, &fsr);
88 				return (((fsr >> 10) & 3) != fcc_equal);
89 			} else {
90 				fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
91 				__quad_setfsrp(&fsr);
92 			}
93 		}
94 		return (1); /* x != y is TRUE if x or y is NaN */
95 	}
96 	if (QUAD_ISZERO(*x) && QUAD_ISZERO(*y))
97 		return (0);
98 	return ((x->l.msw ^ y->l.msw | x->l.frac2 ^ y->l.frac2 |
99 		x->l.frac3 ^ y->l.frac3 | x->l.frac4 ^ y->l.frac4) != 0);
100 }
101 
102 /*
103  * _Q_flt(x, y) returns nonzero if *x < *y and zero otherwise.  If
104  * either *x or *y is NaN, the invalid operation exception is raised.
105  */
106 int
_Q_flt(const union longdouble * x,const union longdouble * y)107 _Q_flt(const union longdouble *x, const union longdouble *y)
108 {
109 	unsigned int	xm, ym, fsr;
110 
111 	if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
112 		/* nan, signal invalid */
113 		__quad_getfsrp(&fsr);
114 		if (fsr & FSR_NVM) {
115 			__quad_fcmpeq(x, y, &fsr);
116 			return (((fsr >> 10) & 3) == fcc_less);
117 		} else {
118 			fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
119 			__quad_setfsrp(&fsr);
120 		}
121 		return (0);
122 	}
123 
124 	/* ignore sign of zero */
125 	xm = x->l.msw;
126 	if (QUAD_ISZERO(*x))
127 		xm &= 0x7fffffff;
128 	ym = y->l.msw;
129 	if (QUAD_ISZERO(*y))
130 		ym &= 0x7fffffff;
131 
132 	if ((xm ^ ym) & 0x80000000)	/* x and y have opposite signs */
133 		return ((ym & 0x80000000) == 0);
134 
135 	if (xm & 0x80000000) {
136 		return (xm > ym || xm == ym && (x->l.frac2 > y->l.frac2 ||
137 		    x->l.frac2 == y->l.frac2 && (x->l.frac3 > y->l.frac3 ||
138 		    x->l.frac3 == y->l.frac3 && x->l.frac4 > y->l.frac4)));
139 	}
140 	return (xm < ym || xm == ym && (x->l.frac2 < y->l.frac2 ||
141 	    x->l.frac2 == y->l.frac2 && (x->l.frac3 < y->l.frac3 ||
142 	    x->l.frac3 == y->l.frac3 && x->l.frac4 < y->l.frac4)));
143 }
144 
145 /*
146  * _Q_fle(x, y) returns nonzero if *x <= *y and zero otherwise.  If
147  * either *x or *y is NaN, the invalid operation exception is raised.
148  */
149 int
_Q_fle(const union longdouble * x,const union longdouble * y)150 _Q_fle(const union longdouble *x, const union longdouble *y)
151 {
152 	unsigned int	xm, ym, fsr;
153 
154 	if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
155 		/* nan, signal invalid */
156 		__quad_getfsrp(&fsr);
157 		if (fsr & FSR_NVM) {
158 			__quad_fcmpeq(x, y, &fsr);
159 			fsr = (fsr >> 10) & 3;
160 			return (fsr == fcc_less || fsr == fcc_equal);
161 		} else {
162 			fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
163 			__quad_setfsrp(&fsr);
164 		}
165 		return (0);
166 	}
167 
168 	/* ignore sign of zero */
169 	xm = x->l.msw;
170 	if (QUAD_ISZERO(*x))
171 		xm &= 0x7fffffff;
172 	ym = y->l.msw;
173 	if (QUAD_ISZERO(*y))
174 		ym &= 0x7fffffff;
175 
176 	if ((xm ^ ym) & 0x80000000)	/* x and y have opposite signs */
177 		return ((ym & 0x80000000) == 0);
178 
179 	if (xm & 0x80000000) {
180 		return (xm > ym || xm == ym && (x->l.frac2 > y->l.frac2 ||
181 		    x->l.frac2 == y->l.frac2 && (x->l.frac3 > y->l.frac3 ||
182 		    x->l.frac3 == y->l.frac3 && x->l.frac4 >= y->l.frac4)));
183 	}
184 	return (xm < ym || xm == ym && (x->l.frac2 < y->l.frac2 ||
185 	    x->l.frac2 == y->l.frac2 && (x->l.frac3 < y->l.frac3 ||
186 	    x->l.frac3 == y->l.frac3 && x->l.frac4 <= y->l.frac4)));
187 }
188 
189 /*
190  * _Q_fgt(x, y) returns nonzero if *x > *y and zero otherwise.  If
191  * either *x or *y is NaN, the invalid operation exception is raised.
192  */
193 int
_Q_fgt(const union longdouble * x,const union longdouble * y)194 _Q_fgt(const union longdouble *x, const union longdouble *y)
195 {
196 	unsigned int	xm, ym, fsr;
197 
198 	if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
199 		/* nan, signal invalid */
200 		__quad_getfsrp(&fsr);
201 		if (fsr & FSR_NVM) {
202 			__quad_fcmpeq(x, y, &fsr);
203 			return (((fsr >> 10) & 3) == fcc_greater);
204 		} else {
205 			fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
206 			__quad_setfsrp(&fsr);
207 		}
208 		return (0);
209 	}
210 
211 	/* ignore sign of zero */
212 	xm = x->l.msw;
213 	if (QUAD_ISZERO(*x))
214 		xm &= 0x7fffffff;
215 	ym = y->l.msw;
216 	if (QUAD_ISZERO(*y))
217 		ym &= 0x7fffffff;
218 
219 	if ((xm ^ ym) & 0x80000000)	/* x and y have opposite signs */
220 		return ((ym & 0x80000000) != 0);
221 
222 	if (xm & 0x80000000) {
223 		return (xm < ym || xm == ym && (x->l.frac2 < y->l.frac2 ||
224 		    x->l.frac2 == y->l.frac2 && (x->l.frac3 < y->l.frac3 ||
225 		    x->l.frac3 == y->l.frac3 && x->l.frac4 < y->l.frac4)));
226 	}
227 	return (xm > ym || xm == ym && (x->l.frac2 > y->l.frac2 ||
228 	    x->l.frac2 == y->l.frac2 && (x->l.frac3 > y->l.frac3 ||
229 	    x->l.frac3 == y->l.frac3 && x->l.frac4 > y->l.frac4)));
230 }
231 
232 /*
233  * _Q_fge(x, y) returns nonzero if *x >= *y and zero otherwise.  If
234  * either *x or *y is NaN, the invalid operation exception is raised.
235  */
236 int
_Q_fge(const union longdouble * x,const union longdouble * y)237 _Q_fge(const union longdouble *x, const union longdouble *y)
238 {
239 	unsigned int	xm, ym, fsr;
240 
241 	if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
242 		/* nan, signal invalid */
243 		__quad_getfsrp(&fsr);
244 		if (fsr & FSR_NVM) {
245 			__quad_fcmpeq(x, y, &fsr);
246 			fsr = (fsr >> 10) & 3;
247 			return (fsr == fcc_greater || fsr == fcc_equal);
248 		} else {
249 			fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
250 			__quad_setfsrp(&fsr);
251 		}
252 		return (0);
253 	}
254 
255 	/* ignore sign of zero */
256 	xm = x->l.msw;
257 	if (QUAD_ISZERO(*x))
258 		xm &= 0x7fffffff;
259 	ym = y->l.msw;
260 	if (QUAD_ISZERO(*y))
261 		ym &= 0x7fffffff;
262 
263 	if ((xm ^ ym) & 0x80000000)	/* x and y have opposite signs */
264 		return ((ym & 0x80000000) != 0);
265 
266 	if (xm & 0x80000000) {
267 		return (xm < ym || xm == ym && (x->l.frac2 < y->l.frac2 ||
268 		    x->l.frac2 == y->l.frac2 && (x->l.frac3 < y->l.frac3 ||
269 		    x->l.frac3 == y->l.frac3 && x->l.frac4 <= y->l.frac4)));
270 	}
271 	return (xm > ym || xm == ym && (x->l.frac2 > y->l.frac2 ||
272 	    x->l.frac2 == y->l.frac2 && (x->l.frac3 > y->l.frac3 ||
273 	    x->l.frac3 == y->l.frac3 && x->l.frac4 >= y->l.frac4)));
274 }
275