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 1988 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include "base_conversion.h" 30 31 /* Normalize a number. Does not affect zeros, infs, or NaNs. */ 32 void 33 _fp_normalize(unpacked *pu) 34 { 35 int i; 36 short unsigned nlzwords, nlzbits; 37 long unsigned t; 38 39 if ((*pu).fpclass == fp_normal) { 40 for (nlzwords = 0; (pu->significand[nlzwords] == 0) && (nlzwords < UNPACKED_SIZE); nlzwords++); 41 if (nlzwords >= UNPACKED_SIZE) { 42 (*pu).fpclass = fp_zero; 43 return; 44 } 45 if (nlzwords > 0) { 46 for (i = 0; i < UNPACKED_SIZE - nlzwords; i++) 47 pu->significand[i] = pu->significand[i + nlzwords]; 48 for (; i < UNPACKED_SIZE; i++) 49 pu->significand[i] = 0; 50 pu->exponent -= 32 * nlzwords; 51 } 52 for (; pu->significand[UNPACKED_SIZE - 1 - nlzwords] == 0; nlzwords++); 53 /* nlzwords is now the count of trailing zero words. */ 54 55 nlzbits = 0; 56 t = pu->significand[0]; 57 /* TESTS to determine normalize count. */ 58 59 #define SHIFTMACRO(n) if (t <= (((unsigned long) 0xffffffff) >> n)) { t = t<<n ; nlzbits += n ; } 60 SHIFTMACRO(16); 61 SHIFTMACRO(8); 62 SHIFTMACRO(4); 63 SHIFTMACRO(2); 64 SHIFTMACRO(1); 65 pu->exponent -= nlzbits; 66 if (nlzbits >= 1) { /* small shift */ 67 unsigned long high, low, shiftout = 0; 68 for (i = UNPACKED_SIZE - 1 - nlzwords; i >= 0; i--) { 69 high = pu->significand[i] << nlzbits; 70 low = pu->significand[i] >> (32 - nlzbits); 71 pu->significand[i] = shiftout | high; 72 shiftout = low; 73 } 74 } 75 } 76 } 77 78 /* Set the exception bit in the current exception register. */ 79 void 80 _fp_set_exception(enum fp_exception_type ex) 81 { 82 _fp_current_exceptions |= 1 << (int) ex; 83 } 84 85 enum fp_class_type 86 _class_double(double *x) 87 { 88 double_equivalence kluge; 89 90 kluge.x = *x; 91 if (kluge.f.msw.exponent == 0) { /* 0 or sub */ 92 if ((kluge.f.msw.significand == 0) && (kluge.f.significand2 == 0)) 93 return fp_zero; 94 else 95 return fp_subnormal; 96 } else if (kluge.f.msw.exponent == 0x7ff) { /* inf or nan */ 97 if ((kluge.f.msw.significand == 0) && (kluge.f.significand2 == 0)) 98 return fp_infinity; 99 else if (kluge.f.msw.significand >= 0x40000) 100 return fp_quiet; 101 else 102 return fp_signaling; 103 } else 104 return fp_normal; 105 } 106 107 108 /* Left shift significand by 11 <= n <= 16 bits. Affect all classes. */ 109 void 110 _fp_leftshift(unpacked *pu, unsigned n) 111 { 112 int i; 113 114 unsigned long high, low, shiftout = 0; 115 for (i = UNPACKED_SIZE - 1; i >= 0; i--) { 116 high = pu->significand[i] << n; 117 low = pu->significand[i] >> (32 - n); 118 pu->significand[i] = shiftout | high; 119 shiftout = low; 120 } 121 } 122 123 124 void 125 _unpack_double(unpacked *pu, double *px) 126 { 127 double_equivalence x; 128 int i; 129 130 x.x = *px; 131 (*pu).sign = x.f.msw.sign; 132 pu->significand[1] = x.f.significand2; 133 for (i = 2; i < UNPACKED_SIZE; i++) 134 pu->significand[i] = 0; 135 if (x.f.msw.exponent == 0) { /* zero or sub */ 136 if ((x.f.msw.significand == 0) && (x.f.significand2 == 0)) { /* zero */ 137 pu->fpclass = fp_zero; 138 return; 139 } else { /* subnormal */ 140 pu->fpclass = fp_normal; 141 pu->exponent = 12 - DOUBLE_BIAS; 142 pu->significand[0] = x.f.msw.significand; 143 _fp_normalize(pu); 144 return; 145 } 146 } else if (x.f.msw.exponent == 0x7ff) { /* inf or nan */ 147 if ((x.f.msw.significand == 0) && (x.f.significand2 == 0)) { /* inf */ 148 pu->fpclass = fp_infinity; 149 return; 150 } else { /* nan */ 151 if ((x.f.msw.significand & 0x80000) != 0) { /* quiet */ 152 pu->fpclass = fp_quiet; 153 } else {/* signaling */ 154 pu->fpclass = fp_quiet; 155 _fp_set_exception(fp_invalid); 156 } 157 pu->significand[0] = 0x80000 | x.f.msw.significand; 158 _fp_leftshift(pu, 11); 159 return; 160 } 161 } 162 (*pu).exponent = x.f.msw.exponent - DOUBLE_BIAS; 163 (*pu).fpclass = fp_normal; 164 (*pu).significand[0] = 0x100000 | x.f.msw.significand; 165 _fp_leftshift(pu, 11); 166 } 167 168 enum fp_class_type 169 _class_quadruple(quadruple *x) 170 { 171 quadruple_equivalence kluge; 172 int i; 173 174 for (i = 0; i < 4; i++) 175 #ifdef __STDC__ 176 kluge.x = *x; 177 #else 178 kluge.x.u[i] = x->u[i]; 179 #endif 180 if (kluge.f.msw.exponent == 0) { /* 0 or sub */ 181 if ((kluge.f.msw.significand == 0) && (kluge.f.significand2 == 0) && (kluge.f.significand3 == 0) && (kluge.f.significand4 == 0)) 182 return fp_zero; 183 else 184 return fp_subnormal; 185 } else if (kluge.f.msw.exponent == 0x7fff) { /* inf or nan */ 186 if ((kluge.f.msw.significand == 0) && (kluge.f.significand2 == 0) && (kluge.f.significand3 == 0) && (kluge.f.significand4 == 0)) 187 return fp_infinity; 188 else if ((kluge.f.msw.significand & 0xffff) >= 0x8000) 189 return fp_quiet; 190 else 191 return fp_signaling; 192 } else 193 return fp_normal; 194 } 195 196 void 197 _unpack_quadruple(unpacked *pu, quadruple *px) 198 { 199 quadruple_equivalence x; 200 int i; 201 202 for (i = 0; i < 4; i++) 203 #ifdef __STDC__ 204 x.x = *px; 205 #else 206 x.x.u[i] = px->u[i]; 207 #endif 208 (*pu).sign = x.f.msw.sign; 209 pu->significand[1] = x.f.significand2; 210 pu->significand[2] = x.f.significand3; 211 pu->significand[3] = x.f.significand4; 212 for (i = 4; i < UNPACKED_SIZE; i++) 213 pu->significand[i] = 0; 214 if (x.f.msw.exponent == 0) { /* zero or sub */ 215 if ((x.f.msw.significand | x.f.significand2 | x.f.significand3 | x.f.significand4) == 0) { /* zero */ 216 pu->fpclass = fp_zero; 217 goto ret; 218 } else { /* subnormal */ 219 pu->fpclass = fp_normal; 220 pu->exponent = 16 - QUAD_BIAS; 221 pu->significand[0] = x.f.msw.significand; 222 _fp_normalize(pu); 223 goto ret; 224 } 225 } else if (x.f.msw.exponent == 0x7fff) { /* inf or nan */ 226 if ((x.f.msw.significand | x.f.significand2 | x.f.significand3 | x.f.significand4) == 0) { /* inf */ 227 pu->fpclass = fp_infinity; 228 goto ret; 229 } else { /* nan */ 230 if ((x.f.msw.significand & 0x8000) != 0) { /* quiet */ 231 pu->fpclass = fp_quiet; 232 } else {/* signaling */ 233 pu->fpclass = fp_quiet; 234 _fp_set_exception(fp_invalid); 235 } 236 pu->significand[0] = 0x8000 | x.f.msw.significand; 237 _fp_leftshift(pu, 16); 238 goto ret; 239 } 240 } 241 (*pu).exponent = x.f.msw.exponent - QUAD_BIAS; 242 (*pu).fpclass = fp_normal; 243 (*pu).significand[0] = 0x10000 | x.f.msw.significand; 244 _fp_leftshift(pu, 15); 245 ret: 246 /* 247 * printf("/n _unpack_quadruple ") ; _display_unpacked(pu); 248 */ 249 return; 250 } 251