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 #include "quad.h"
28
29 #ifdef __sparcv9
30 #define _Q_feq _Qp_feq
31 #define _Q_fne _Qp_fne
32 #define _Q_flt _Qp_flt
33 #define _Q_fle _Qp_fle
34 #define _Q_fgt _Qp_fgt
35 #define _Q_fge _Qp_fge
36 #endif
37
38 /*
39 * _Q_feq(x, y) returns nonzero if *x == *y and zero otherwise.
40 * If either *x or *y is a signaling NaN, the invalid operation
41 * exception is raised.
42 */
43 int
_Q_feq(const union longdouble * x,const union longdouble * y)44 _Q_feq(const union longdouble *x, const union longdouble *y)
45 {
46 unsigned int fsr;
47
48 if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
49 if ((QUAD_ISNAN(*x) && !(x->l.msw & 0x8000)) ||
50 (QUAD_ISNAN(*y) && !(y->l.msw & 0x8000))) {
51 /* snan, signal invalid */
52 __quad_getfsrp(&fsr);
53 if (fsr & FSR_NVM) {
54 __quad_fcmpq(x, y, &fsr);
55 return (((fsr >> 10) & 3) == fcc_equal);
56 } else {
57 fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
58 __quad_setfsrp(&fsr);
59 }
60 }
61 return (0);
62 }
63 if (QUAD_ISZERO(*x) && QUAD_ISZERO(*y))
64 return (1);
65 return ((x->l.msw ^ y->l.msw | x->l.frac2 ^ y->l.frac2 |
66 x->l.frac3 ^ y->l.frac3 | x->l.frac4 ^ y->l.frac4) == 0);
67 }
68
69 /*
70 * _Q_fne(x, y) returns nonzero if *x != *y and zero otherwise.
71 * If either *x or *y is a signaling NaN, the invalid operation
72 * exception is raised.
73 */
74 int
_Q_fne(const union longdouble * x,const union longdouble * y)75 _Q_fne(const union longdouble *x, const union longdouble *y)
76 {
77 unsigned int fsr;
78
79 if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
80 if ((QUAD_ISNAN(*x) && !(x->l.msw & 0x8000)) ||
81 (QUAD_ISNAN(*y) && !(y->l.msw & 0x8000))) {
82 /* snan, signal invalid */
83 __quad_getfsrp(&fsr);
84 if (fsr & FSR_NVM) {
85 __quad_fcmpq(x, y, &fsr);
86 return (((fsr >> 10) & 3) != fcc_equal);
87 } else {
88 fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
89 __quad_setfsrp(&fsr);
90 }
91 }
92 return (1); /* x != y is TRUE if x or y is NaN */
93 }
94 if (QUAD_ISZERO(*x) && QUAD_ISZERO(*y))
95 return (0);
96 return ((x->l.msw ^ y->l.msw | x->l.frac2 ^ y->l.frac2 |
97 x->l.frac3 ^ y->l.frac3 | x->l.frac4 ^ y->l.frac4) != 0);
98 }
99
100 /*
101 * _Q_flt(x, y) returns nonzero if *x < *y and zero otherwise. If
102 * either *x or *y is NaN, the invalid operation exception is raised.
103 */
104 int
_Q_flt(const union longdouble * x,const union longdouble * y)105 _Q_flt(const union longdouble *x, const union longdouble *y)
106 {
107 unsigned int xm, ym, fsr;
108
109 if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
110 /* nan, signal invalid */
111 __quad_getfsrp(&fsr);
112 if (fsr & FSR_NVM) {
113 __quad_fcmpeq(x, y, &fsr);
114 return (((fsr >> 10) & 3) == fcc_less);
115 } else {
116 fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
117 __quad_setfsrp(&fsr);
118 }
119 return (0);
120 }
121
122 /* ignore sign of zero */
123 xm = x->l.msw;
124 if (QUAD_ISZERO(*x))
125 xm &= 0x7fffffff;
126 ym = y->l.msw;
127 if (QUAD_ISZERO(*y))
128 ym &= 0x7fffffff;
129
130 if ((xm ^ ym) & 0x80000000) /* x and y have opposite signs */
131 return ((ym & 0x80000000) == 0);
132
133 if (xm & 0x80000000) {
134 return (xm > ym || xm == ym && (x->l.frac2 > y->l.frac2 ||
135 x->l.frac2 == y->l.frac2 && (x->l.frac3 > y->l.frac3 ||
136 x->l.frac3 == y->l.frac3 && x->l.frac4 > y->l.frac4)));
137 }
138 return (xm < ym || xm == ym && (x->l.frac2 < y->l.frac2 ||
139 x->l.frac2 == y->l.frac2 && (x->l.frac3 < y->l.frac3 ||
140 x->l.frac3 == y->l.frac3 && x->l.frac4 < y->l.frac4)));
141 }
142
143 /*
144 * _Q_fle(x, y) returns nonzero if *x <= *y and zero otherwise. If
145 * either *x or *y is NaN, the invalid operation exception is raised.
146 */
147 int
_Q_fle(const union longdouble * x,const union longdouble * y)148 _Q_fle(const union longdouble *x, const union longdouble *y)
149 {
150 unsigned int xm, ym, fsr;
151
152 if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
153 /* nan, signal invalid */
154 __quad_getfsrp(&fsr);
155 if (fsr & FSR_NVM) {
156 __quad_fcmpeq(x, y, &fsr);
157 fsr = (fsr >> 10) & 3;
158 return (fsr == fcc_less || fsr == fcc_equal);
159 } else {
160 fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
161 __quad_setfsrp(&fsr);
162 }
163 return (0);
164 }
165
166 /* ignore sign of zero */
167 xm = x->l.msw;
168 if (QUAD_ISZERO(*x))
169 xm &= 0x7fffffff;
170 ym = y->l.msw;
171 if (QUAD_ISZERO(*y))
172 ym &= 0x7fffffff;
173
174 if ((xm ^ ym) & 0x80000000) /* x and y have opposite signs */
175 return ((ym & 0x80000000) == 0);
176
177 if (xm & 0x80000000) {
178 return (xm > ym || xm == ym && (x->l.frac2 > y->l.frac2 ||
179 x->l.frac2 == y->l.frac2 && (x->l.frac3 > y->l.frac3 ||
180 x->l.frac3 == y->l.frac3 && x->l.frac4 >= y->l.frac4)));
181 }
182 return (xm < ym || xm == ym && (x->l.frac2 < y->l.frac2 ||
183 x->l.frac2 == y->l.frac2 && (x->l.frac3 < y->l.frac3 ||
184 x->l.frac3 == y->l.frac3 && x->l.frac4 <= y->l.frac4)));
185 }
186
187 /*
188 * _Q_fgt(x, y) returns nonzero if *x > *y and zero otherwise. If
189 * either *x or *y is NaN, the invalid operation exception is raised.
190 */
191 int
_Q_fgt(const union longdouble * x,const union longdouble * y)192 _Q_fgt(const union longdouble *x, const union longdouble *y)
193 {
194 unsigned int xm, ym, fsr;
195
196 if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
197 /* nan, signal invalid */
198 __quad_getfsrp(&fsr);
199 if (fsr & FSR_NVM) {
200 __quad_fcmpeq(x, y, &fsr);
201 return (((fsr >> 10) & 3) == fcc_greater);
202 } else {
203 fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
204 __quad_setfsrp(&fsr);
205 }
206 return (0);
207 }
208
209 /* ignore sign of zero */
210 xm = x->l.msw;
211 if (QUAD_ISZERO(*x))
212 xm &= 0x7fffffff;
213 ym = y->l.msw;
214 if (QUAD_ISZERO(*y))
215 ym &= 0x7fffffff;
216
217 if ((xm ^ ym) & 0x80000000) /* x and y have opposite signs */
218 return ((ym & 0x80000000) != 0);
219
220 if (xm & 0x80000000) {
221 return (xm < ym || xm == ym && (x->l.frac2 < y->l.frac2 ||
222 x->l.frac2 == y->l.frac2 && (x->l.frac3 < y->l.frac3 ||
223 x->l.frac3 == y->l.frac3 && x->l.frac4 < y->l.frac4)));
224 }
225 return (xm > ym || xm == ym && (x->l.frac2 > y->l.frac2 ||
226 x->l.frac2 == y->l.frac2 && (x->l.frac3 > y->l.frac3 ||
227 x->l.frac3 == y->l.frac3 && x->l.frac4 > y->l.frac4)));
228 }
229
230 /*
231 * _Q_fge(x, y) returns nonzero if *x >= *y and zero otherwise. If
232 * either *x or *y is NaN, the invalid operation exception is raised.
233 */
234 int
_Q_fge(const union longdouble * x,const union longdouble * y)235 _Q_fge(const union longdouble *x, const union longdouble *y)
236 {
237 unsigned int xm, ym, fsr;
238
239 if (QUAD_ISNAN(*x) || QUAD_ISNAN(*y)) {
240 /* nan, signal invalid */
241 __quad_getfsrp(&fsr);
242 if (fsr & FSR_NVM) {
243 __quad_fcmpeq(x, y, &fsr);
244 fsr = (fsr >> 10) & 3;
245 return (fsr == fcc_greater || fsr == fcc_equal);
246 } else {
247 fsr = (fsr & ~FSR_CEXC) | FSR_NVA | FSR_NVC;
248 __quad_setfsrp(&fsr);
249 }
250 return (0);
251 }
252
253 /* ignore sign of zero */
254 xm = x->l.msw;
255 if (QUAD_ISZERO(*x))
256 xm &= 0x7fffffff;
257 ym = y->l.msw;
258 if (QUAD_ISZERO(*y))
259 ym &= 0x7fffffff;
260
261 if ((xm ^ ym) & 0x80000000) /* x and y have opposite signs */
262 return ((ym & 0x80000000) != 0);
263
264 if (xm & 0x80000000) {
265 return (xm < ym || xm == ym && (x->l.frac2 < y->l.frac2 ||
266 x->l.frac2 == y->l.frac2 && (x->l.frac3 < y->l.frac3 ||
267 x->l.frac3 == y->l.frac3 && x->l.frac4 <= y->l.frac4)));
268 }
269 return (xm > ym || xm == ym && (x->l.frac2 > y->l.frac2 ||
270 x->l.frac2 == y->l.frac2 && (x->l.frac3 > y->l.frac3 ||
271 x->l.frac3 == y->l.frac3 && x->l.frac4 >= y->l.frac4)));
272 }
273