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