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