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) 1988-1995, by Sun Microsystems, Inc. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include "base_conversion.h" 29 30 void 31 _fp_rightshift(pu, n) 32 unpacked *pu; 33 int n; 34 35 /* Right shift significand sticky by n bits. */ 36 37 { 38 int i; 39 40 if (n >= (32 * UNPACKED_SIZE)) { /* drastic */ 41 for (i = 0; (pu->significand[i] == 0) && (i < UNPACKED_SIZE); i++); 42 if (i >= UNPACKED_SIZE) { 43 pu->fpclass = fp_zero; 44 return; 45 } else { 46 for (i = 0; i < (UNPACKED_SIZE - 1); i++) 47 pu->significand[i] = 0; 48 pu->significand[UNPACKED_SIZE - 1] = 1; 49 return; 50 } 51 } 52 while (n >= 32) { /* big shift */ 53 if (pu->significand[UNPACKED_SIZE - 1] != 0) 54 pu->significand[UNPACKED_SIZE - 2] |= 1; 55 for (i = UNPACKED_SIZE - 2; i >= 0; i--) 56 pu->significand[i + 1] = pu->significand[i]; 57 pu->significand[0] = 0; 58 n -= 32; 59 } 60 if (n >= 1) { /* small shift */ 61 unsigned long high, low, shiftout = 0; 62 for (i = 0; i < UNPACKED_SIZE; i++) { 63 high = pu->significand[i] >> n; 64 low = pu->significand[i] << (32 - n); 65 pu->significand[i] = shiftout | high; 66 shiftout = low; 67 } 68 if (shiftout != 0) 69 pu->significand[UNPACKED_SIZE - 1] |= 1; 70 } 71 } 72 73 PRIVATE int 74 overflow_to_infinity(sign) 75 int sign; 76 77 /* Returns 1 if overflow should go to infinity, 0 if to max finite. */ 78 79 { 80 int inf; 81 82 switch (_fp_current_direction) { 83 case fp_nearest: 84 inf = 1; 85 break; 86 case fp_tozero: 87 inf = 0; 88 break; 89 case fp_positive: 90 inf = !sign; 91 break; 92 case fp_negative: 93 inf = sign; 94 break; 95 } 96 return (inf); 97 } 98 99 PRIVATE void 100 round(pu, roundword) 101 unpacked *pu; 102 103 /* 104 * Round according to current rounding mode. pu must be shifted to so that 105 * the roundbit is pu->significand[roundword] & 0x80000000 106 */ 107 108 { 109 int increment; /* boolean to indicate round up */ 110 int is; 111 unsigned msw; /* msw before increment */ 112 113 for (is = (roundword + 1); is < UNPACKED_SIZE; is++) 114 if (pu->significand[is] != 0) { /* Condense extra bits into 115 * sticky bottom of 116 * roundword. */ 117 pu->significand[roundword] |= 1; 118 break; 119 } 120 if (pu->significand[roundword] == 0) 121 return; 122 _fp_set_exception(fp_inexact); 123 switch (_fp_current_direction) { 124 case fp_nearest: 125 increment = pu->significand[roundword] >= 0x80000000; 126 break; 127 case fp_tozero: 128 increment = 0; 129 break; 130 case fp_positive: 131 increment = (pu->sign == 0) & (pu->significand[roundword] != 0); 132 break; 133 case fp_negative: 134 increment = (pu->sign != 0) & (pu->significand[roundword] != 0); 135 break; 136 } 137 if (increment) { 138 msw=pu->significand[0]; /* save msw before round */ 139 is = roundword; 140 do { 141 is--; 142 pu->significand[is]++; 143 } 144 while ((pu->significand[is] == 0) && (is > 0)); 145 if (pu->significand[0] < msw) { /* rounding carried out */ 146 pu->exponent++; 147 pu->significand[0] = 0x80000000; 148 } 149 } 150 if ((_fp_current_direction == fp_nearest) && (pu->significand[roundword] == 0x80000000)) { /* ambiguous case */ 151 pu->significand[roundword - 1] &= ~1; /* force round to even */ 152 } 153 } 154 155 void 156 _pack_single(pu, px) 157 unpacked *pu; /* unpacked result */ 158 single *px; /* packed single */ 159 { 160 single_equivalence kluge; 161 162 kluge.f.msw.sign = pu->sign; 163 switch (pu->fpclass) { 164 case fp_zero: 165 kluge.f.msw.exponent = 0; 166 kluge.f.msw.significand = 0; 167 break; 168 case fp_infinity: 169 infinity: 170 kluge.f.msw.exponent = 0xff; 171 kluge.f.msw.significand = 0; 172 break; 173 case fp_quiet: 174 kluge.f.msw.exponent = 0xff; 175 kluge.f.msw.significand = 0x400000 | (0x3fffff & (pu->significand[0] >> 8)); 176 break; 177 case fp_normal: 178 _fp_rightshift(pu, 8); 179 pu->exponent += SINGLE_BIAS; 180 if (pu->exponent <= 0) { 181 kluge.f.msw.exponent = 0; 182 _fp_rightshift(pu, 1 - pu->exponent); 183 round(pu, 1); 184 if (pu->significand[0] == 0x800000) { /* rounded back up to 185 * normal */ 186 kluge.f.msw.exponent = 1; 187 kluge.f.msw.significand = 0; 188 _fp_set_exception(fp_underflow); 189 goto ret; 190 } 191 if (_fp_current_exceptions & (1 << fp_inexact)) 192 _fp_set_exception(fp_underflow); 193 kluge.f.msw.significand = 0x7fffff & pu->significand[0]; 194 goto ret; 195 } 196 round(pu, 1); 197 if (pu->significand[0] == 0x1000000) { /* rounding overflow */ 198 pu->significand[0] = 0x800000; 199 pu->exponent += 1; 200 } 201 if (pu->exponent >= 0xff) { 202 _fp_set_exception(fp_overflow); 203 _fp_set_exception(fp_inexact); 204 if (overflow_to_infinity(pu->sign)) 205 goto infinity; 206 kluge.f.msw.exponent = 0xfe; 207 kluge.f.msw.significand = 0x7fffff; 208 goto ret; 209 } 210 kluge.f.msw.exponent = pu->exponent; 211 kluge.f.msw.significand = 0x7fffff & pu->significand[0]; 212 } 213 ret: 214 *px = kluge.x; 215 } 216 217 void 218 _pack_double(pu, px) 219 unpacked *pu; /* unpacked result */ 220 double *px; /* packed double */ 221 { 222 double_equivalence kluge; 223 224 kluge.f.msw.sign = pu->sign; 225 switch (pu->fpclass) { 226 case fp_zero: 227 kluge.f.msw.exponent = 0; 228 kluge.f.msw.significand = 0; 229 kluge.f.significand2 = 0; 230 break; 231 case fp_infinity: 232 infinity: 233 kluge.f.msw.exponent = 0x7ff; 234 kluge.f.msw.significand = 0; 235 kluge.f.significand2 = 0; 236 break; 237 case fp_quiet: 238 kluge.f.msw.exponent = 0x7ff; 239 _fp_rightshift(pu, 11); 240 kluge.f.msw.significand = 0x80000 | (0x7ffff & pu->significand[0]); 241 kluge.f.significand2 = pu->significand[1]; 242 break; 243 case fp_normal: 244 _fp_rightshift(pu, 11); 245 pu->exponent += DOUBLE_BIAS; 246 if (pu->exponent <= 0) { /* underflow */ 247 kluge.f.msw.exponent = 0; 248 _fp_rightshift(pu, 1 - pu->exponent); 249 round(pu, 2); 250 if (pu->significand[0] == 0x100000) { /* rounded back up to 251 * normal */ 252 kluge.f.msw.exponent = 1; 253 kluge.f.msw.significand = 0; 254 kluge.f.significand2 = 0; 255 _fp_set_exception(fp_underflow); 256 goto ret; 257 } 258 if (_fp_current_exceptions & (1 << fp_inexact)) 259 _fp_set_exception(fp_underflow); 260 kluge.f.msw.exponent = 0; 261 kluge.f.msw.significand = 0xfffff & pu->significand[0]; 262 kluge.f.significand2 = pu->significand[1]; 263 goto ret; 264 } 265 round(pu, 2); 266 if (pu->significand[0] == 0x200000) { /* rounding overflow */ 267 pu->significand[0] = 0x100000; 268 pu->exponent += 1; 269 } 270 if (pu->exponent >= 0x7ff) { /* overflow */ 271 _fp_set_exception(fp_overflow); 272 _fp_set_exception(fp_inexact); 273 if (overflow_to_infinity(pu->sign)) 274 goto infinity; 275 kluge.f.msw.exponent = 0x7fe; 276 kluge.f.msw.significand = 0xfffff; 277 kluge.f.significand2 = 0xffffffff; 278 goto ret; 279 } 280 kluge.f.msw.exponent = pu->exponent; 281 kluge.f.msw.significand = 0xfffff & pu->significand[0]; 282 kluge.f.significand2 = pu->significand[1]; 283 break; 284 } 285 ret: 286 *px = kluge.x; 287 } 288 289 void 290 _pack_extended(pu, px) 291 unpacked *pu; /* unpacked result */ 292 extended *px; /* packed extended */ 293 { 294 extended_equivalence kluge; 295 296 kluge.f.msw.sign = pu->sign; 297 switch (pu->fpclass) { 298 case fp_zero: 299 kluge.f.msw.exponent = 0; 300 kluge.f.significand = 0; 301 kluge.f.significand2 = 0; 302 break; 303 case fp_infinity: 304 infinity: 305 kluge.f.msw.exponent = 0x7fff; 306 kluge.f.significand = 0; 307 kluge.f.significand2 = 0; 308 break; 309 case fp_quiet: 310 kluge.f.msw.exponent = 0x7fff; 311 kluge.f.significand = 0x40000000 | (0x7fffffff & pu->significand[0]); 312 kluge.f.significand2 = pu->significand[1]; 313 break; 314 case fp_normal: 315 switch (_fp_current_precision) { 316 case fp_single: 317 { 318 single s; 319 _pack_single(pu, &s); 320 _unpack_single(pu, &s); 321 break; 322 } 323 case fp_double: 324 { 325 double s; 326 _pack_double(pu, &s); 327 _unpack_double(pu, &s); 328 break; 329 } 330 } 331 pu->exponent += EXTENDED_BIAS; 332 if (pu->exponent <= 0) { /* underflow */ 333 kluge.f.msw.exponent = 0; 334 _fp_rightshift(pu, -pu->exponent); 335 round(pu, 2); 336 if (_fp_current_exceptions & (1 << fp_inexact)) 337 _fp_set_exception(fp_underflow); 338 kluge.f.msw.exponent = 0; 339 kluge.f.significand = pu->significand[0]; 340 kluge.f.significand2 = pu->significand[1]; 341 goto ret; 342 } 343 round(pu, 2); 344 if (pu->exponent >= 0x7fff) { /* overflow */ 345 _fp_set_exception(fp_overflow); 346 _fp_set_exception(fp_inexact); 347 if (overflow_to_infinity(pu->sign)) 348 goto infinity; 349 kluge.f.msw.exponent = 0x7ffe; 350 kluge.f.significand = 0xffffffff; 351 kluge.f.significand2 = 0xffffffff; 352 goto ret; 353 } 354 kluge.f.msw.exponent = pu->exponent; 355 kluge.f.significand = pu->significand[0]; 356 kluge.f.significand2 = pu->significand[1]; 357 break; 358 } 359 ret: 360 (*px)[0] = kluge.x[0]; 361 (*px)[1] = kluge.x[1]; 362 (*px)[2] = kluge.x[2]; 363 } 364 365 void 366 _pack_quadruple(pu, px) 367 unpacked *pu; /* unpacked result */ 368 quadruple *px; /* packed quadruple */ 369 { 370 quadruple_equivalence kluge; 371 int i; 372 373 kluge.f.msw.sign = pu->sign; 374 switch (pu->fpclass) { 375 case fp_zero: 376 kluge.f.msw.exponent = 0; 377 kluge.f.msw.significand = 0; 378 kluge.f.significand2 = 0; 379 kluge.f.significand3 = 0; 380 kluge.f.significand4 = 0; 381 break; 382 case fp_infinity: 383 infinity: 384 kluge.f.msw.exponent = 0x7fff; 385 kluge.f.msw.significand = 0; 386 kluge.f.significand2 = 0; 387 kluge.f.significand3 = 0; 388 kluge.f.significand4 = 0; 389 break; 390 case fp_quiet: 391 kluge.f.msw.exponent = 0x7fff; 392 _fp_rightshift(pu, 15); 393 kluge.f.msw.significand = 0x8000 | (0xffff & pu->significand[0]); 394 kluge.f.significand2 = pu->significand[1]; 395 kluge.f.significand3 = pu->significand[2]; 396 kluge.f.significand4 = pu->significand[3]; 397 break; 398 case fp_normal: 399 _fp_rightshift(pu, 15); 400 pu->exponent += QUAD_BIAS; 401 if (pu->exponent <= 0) { /* underflow */ 402 kluge.f.msw.exponent = 0; 403 _fp_rightshift(pu, 1 - pu->exponent); 404 round(pu, 4); 405 if (pu->significand[0] == 0x10000) { /* rounded back up to 406 * normal */ 407 kluge.f.msw.exponent = 1; 408 kluge.f.msw.significand = 0; 409 kluge.f.significand2 = 0; 410 kluge.f.significand3 = 0; 411 kluge.f.significand4 = 0; 412 _fp_set_exception(fp_underflow); 413 goto ret; 414 } 415 if (_fp_current_exceptions & (1 << fp_inexact)) 416 _fp_set_exception(fp_underflow); 417 kluge.f.msw.exponent = 0; 418 kluge.f.msw.significand = 0xffff & pu->significand[0]; 419 kluge.f.significand2 = pu->significand[1]; 420 kluge.f.significand3 = pu->significand[2]; 421 kluge.f.significand4 = pu->significand[3]; 422 goto ret; 423 } 424 round(pu, 4); 425 if (pu->significand[0] == 0x20000) { /* rounding overflow */ 426 pu->significand[0] = 0x10000; 427 pu->exponent += 1; 428 } 429 if (pu->exponent >= 0x7fff) { /* overflow */ 430 _fp_set_exception(fp_overflow); 431 _fp_set_exception(fp_inexact); 432 if (overflow_to_infinity(pu->sign)) 433 goto infinity; 434 kluge.f.msw.exponent = 0x7ffe; 435 kluge.f.msw.significand = 0xffff; 436 kluge.f.significand2 = 0xffffffff; 437 kluge.f.significand3 = 0xffffffff; 438 kluge.f.significand4 = 0xffffffff; 439 goto ret; 440 } 441 kluge.f.msw.exponent = pu->exponent; 442 kluge.f.msw.significand = pu->significand[0] & 0xffff; 443 kluge.f.significand2 = pu->significand[1]; 444 kluge.f.significand3 = pu->significand[2]; 445 kluge.f.significand4 = pu->significand[3]; 446 break; 447 } 448 ret: 449 #ifdef __STDC__ 450 *px = kluge.x; 451 #else 452 for (i = 0; i < 4; i++) 453 px->u[i] = kluge.x.u[i]; 454 #endif 455 } 456