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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include "lint.h" 28 #include "base_conversion.h" 29 30 static void 31 __fp_rightshift(unpacked *pu, int n) 32 33 /* Right shift significand sticky by n bits. */ 34 35 { 36 int i; 37 38 if (n >= (32 * UNPACKED_SIZE)) { /* drastic */ 39 for (i = 0; (pu->significand[i] == 0) && (i < UNPACKED_SIZE); 40 i++); 41 if (i >= UNPACKED_SIZE) { 42 pu->fpclass = fp_zero; 43 return; 44 } else { 45 for (i = 0; i < (UNPACKED_SIZE - 1); i++) 46 pu->significand[i] = 0; 47 pu->significand[UNPACKED_SIZE - 1] = 1; 48 return; 49 } 50 } 51 while (n >= 32) { /* big shift */ 52 if (pu->significand[UNPACKED_SIZE - 1] != 0) 53 pu->significand[UNPACKED_SIZE - 2] |= 1; 54 for (i = UNPACKED_SIZE - 2; i >= 0; i--) 55 pu->significand[i + 1] = pu->significand[i]; 56 pu->significand[0] = 0; 57 n -= 32; 58 } 59 if (n >= 1) { /* small shift */ 60 unsigned int high, low, shiftout = 0; 61 for (i = 0; i < UNPACKED_SIZE; i++) { 62 high = pu->significand[i] >> n; 63 low = pu->significand[i] << (32 - n); 64 pu->significand[i] = shiftout | high; 65 shiftout = low; 66 } 67 if (shiftout != 0) 68 pu->significand[UNPACKED_SIZE - 1] |= 1; 69 } 70 } 71 72 static int 73 overflow_to_infinity(int sign, enum fp_direction_type rd) 74 75 /* Returns 1 if overflow should go to infinity, 0 if to max finite. */ 76 77 { 78 int inf; 79 80 switch (rd) { 81 case fp_nearest: 82 inf = 1; 83 break; 84 case fp_tozero: 85 inf = 0; 86 break; 87 case fp_positive: 88 inf = !sign; 89 break; 90 case fp_negative: 91 inf = sign; 92 break; 93 } 94 return (inf); 95 } 96 97 static void 98 round(unpacked *pu, int roundword, enum fp_direction_type rd, int *ex) 99 /* 100 * Round according to current rounding mode. pu must be shifted to so that 101 * the roundbit is pu->significand[roundword] & 0x80000000 102 */ 103 { 104 int increment; /* boolean to indicate round up */ 105 int is; 106 unsigned msw; /* msw before increment */ 107 108 for (is = (roundword + 1); is < UNPACKED_SIZE; is++) 109 if (pu->significand[is] != 0) { 110 /* Condense extra bits into sticky bottom of roundword. */ 111 pu->significand[roundword] |= 1; 112 break; 113 } 114 if (pu->significand[roundword] == 0) 115 return; 116 *ex |= (1 << fp_inexact); 117 switch (rd) { 118 case fp_nearest: 119 increment = pu->significand[roundword] >= 0x80000000; 120 break; 121 case fp_tozero: 122 increment = 0; 123 break; 124 case fp_positive: 125 increment = (pu->sign == 0) & (pu->significand[roundword] != 0); 126 break; 127 case fp_negative: 128 increment = (pu->sign != 0) & (pu->significand[roundword] != 0); 129 break; 130 } 131 if (increment) { 132 msw = pu->significand[0]; /* save msw before round */ 133 is = roundword; 134 do { 135 is--; 136 pu->significand[is]++; 137 } 138 while ((pu->significand[is] == 0) && (is > 0)); 139 if (pu->significand[0] < msw) { /* rounding carried out */ 140 pu->exponent++; 141 pu->significand[0] = 0x80000000; 142 } 143 } 144 if ((rd == fp_nearest) && 145 (pu->significand[roundword] == 0x80000000)) { 146 /* ambiguous case */ 147 pu->significand[roundword - 1] &= ~1; /* force round to even */ 148 } 149 } 150 151 void 152 __pack_single(unpacked *pu, single *px, enum fp_direction_type rd, 153 fp_exception_field_type *ex) 154 { 155 single_equivalence kluge; 156 int e; 157 158 e = 0; 159 kluge.f.msw.sign = pu->sign; 160 switch (pu->fpclass) { 161 case fp_zero: 162 kluge.f.msw.exponent = 0; 163 kluge.f.msw.significand = 0; 164 break; 165 case fp_infinity: 166 infinity: 167 kluge.f.msw.exponent = 0xff; 168 kluge.f.msw.significand = 0; 169 break; 170 case fp_quiet: 171 kluge.f.msw.exponent = 0xff; 172 kluge.f.msw.significand = 0x400000 | 173 (0x3fffff & (pu->significand[0] >> 8)); 174 break; 175 case fp_normal: 176 __fp_rightshift(pu, 8); 177 pu->exponent += SINGLE_BIAS; 178 if (pu->exponent <= 0) { 179 kluge.f.msw.exponent = 0; 180 __fp_rightshift(pu, 1 - pu->exponent); 181 round(pu, 1, rd, &e); 182 if (pu->significand[0] == 0x800000) { 183 /* rounded back up to normal */ 184 kluge.f.msw.exponent = 1; 185 kluge.f.msw.significand = 0; 186 e |= (1 << fp_underflow); 187 goto ret; 188 } 189 if (e & (1 << fp_inexact)) 190 e |= (1 << fp_underflow); 191 kluge.f.msw.significand = 0x7fffff & pu->significand[0]; 192 goto ret; 193 } 194 round(pu, 1, rd, &e); 195 if (pu->significand[0] == 0x1000000) { /* rounding overflow */ 196 pu->significand[0] = 0x800000; 197 pu->exponent += 1; 198 } 199 if (pu->exponent >= 0xff) { 200 e |= (1 << fp_overflow) | (1 << fp_inexact); 201 if (overflow_to_infinity(pu->sign, rd)) 202 goto infinity; 203 kluge.f.msw.exponent = 0xfe; 204 kluge.f.msw.significand = 0x7fffff; 205 goto ret; 206 } 207 kluge.f.msw.exponent = pu->exponent; 208 kluge.f.msw.significand = 0x7fffff & pu->significand[0]; 209 } 210 ret: 211 *px = kluge.x; 212 *ex = (fp_exception_field_type)e; 213 } 214 215 void 216 __pack_double(unpacked *pu, double *px, enum fp_direction_type rd, 217 fp_exception_field_type *ex) 218 { 219 double_equivalence kluge; 220 int e; 221 222 e = 0; 223 kluge.f.msw.sign = pu->sign; 224 switch (pu->fpclass) { 225 case fp_zero: 226 kluge.f.msw.exponent = 0; 227 kluge.f.msw.significand = 0; 228 kluge.f.significand2 = 0; 229 break; 230 case fp_infinity: 231 infinity: 232 kluge.f.msw.exponent = 0x7ff; 233 kluge.f.msw.significand = 0; 234 kluge.f.significand2 = 0; 235 break; 236 case fp_quiet: 237 kluge.f.msw.exponent = 0x7ff; 238 __fp_rightshift(pu, 11); 239 kluge.f.msw.significand = 0x80000 | 240 (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 __fp_rightshift(pu, 1 - pu->exponent); 248 round(pu, 2, rd, &e); 249 if (pu->significand[0] == 0x100000) { 250 /* rounded back up to normal */ 251 kluge.f.msw.exponent = 1; 252 kluge.f.msw.significand = 0; 253 kluge.f.significand2 = 0; 254 e |= (1 << fp_underflow); 255 goto ret; 256 } 257 if (e & (1 << fp_inexact)) 258 e |= (1 << fp_underflow); 259 kluge.f.msw.exponent = 0; 260 kluge.f.msw.significand = 0xfffff & pu->significand[0]; 261 kluge.f.significand2 = pu->significand[1]; 262 goto ret; 263 } 264 round(pu, 2, rd, &e); 265 if (pu->significand[0] == 0x200000) { /* rounding overflow */ 266 pu->significand[0] = 0x100000; 267 pu->exponent += 1; 268 } 269 if (pu->exponent >= 0x7ff) { /* overflow */ 270 e |= (1 << fp_overflow) | (1 << fp_inexact); 271 if (overflow_to_infinity(pu->sign, rd)) 272 goto infinity; 273 kluge.f.msw.exponent = 0x7fe; 274 kluge.f.msw.significand = 0xfffff; 275 kluge.f.significand2 = 0xffffffff; 276 goto ret; 277 } 278 kluge.f.msw.exponent = pu->exponent; 279 kluge.f.msw.significand = 0xfffff & pu->significand[0]; 280 kluge.f.significand2 = pu->significand[1]; 281 break; 282 } 283 ret: 284 *px = kluge.x; 285 *ex = (fp_exception_field_type)e; 286 } 287 288 void 289 __pack_extended(unpacked *pu, extended *px, enum fp_direction_type rd, 290 fp_exception_field_type *ex) 291 { 292 extended_equivalence kluge; 293 int e; 294 295 e = 0; 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 = 0x80000000; 307 kluge.f.significand2 = 0; 308 break; 309 case fp_quiet: 310 kluge.f.msw.exponent = 0x7fff; 311 kluge.f.significand = 0x40000000 | pu->significand[0]; 312 kluge.f.significand2 = pu->significand[1]; 313 break; 314 case fp_normal: 315 pu->exponent += EXTENDED_BIAS; 316 if (pu->exponent <= 0) { /* underflow */ 317 __fp_rightshift(pu, 1 - pu->exponent); 318 round(pu, 2, rd, &e); 319 if (pu->significand[0] == 0x80000000u) { 320 /* rounded back up to normal */ 321 kluge.f.msw.exponent = 1; 322 kluge.f.significand = 0x80000000u; 323 kluge.f.significand2 = 0; 324 e |= (1 << fp_underflow); 325 goto ret; 326 } 327 if (e & (1 << fp_inexact)) 328 e |= (1 << fp_underflow); 329 kluge.f.msw.exponent = 0; 330 kluge.f.significand = pu->significand[0]; 331 kluge.f.significand2 = pu->significand[1]; 332 goto ret; 333 } 334 round(pu, 2, rd, &e); 335 if (pu->exponent >= 0x7fff) { /* overflow */ 336 e |= (1 << fp_overflow) | (1 << fp_inexact); 337 if (overflow_to_infinity(pu->sign, rd)) 338 goto infinity; 339 kluge.f.msw.exponent = 0x7ffe; 340 kluge.f.significand = 0xffffffff; 341 kluge.f.significand2 = 0xffffffff; 342 goto ret; 343 } 344 kluge.f.msw.exponent = pu->exponent; 345 kluge.f.significand = pu->significand[0]; 346 kluge.f.significand2 = pu->significand[1]; 347 break; 348 } 349 ret: 350 (*px)[0] = kluge.x[0]; 351 (*px)[1] = kluge.x[1]; 352 (*px)[2] = kluge.x[2]; 353 *ex = (fp_exception_field_type)e; 354 } 355 356 void 357 __pack_quadruple(unpacked *pu, quadruple *px, enum fp_direction_type rd, 358 fp_exception_field_type *ex) 359 { 360 quadruple_equivalence kluge; 361 int e; 362 363 e = 0; 364 kluge.f.msw.sign = pu->sign; 365 switch (pu->fpclass) { 366 case fp_zero: 367 kluge.f.msw.exponent = 0; 368 kluge.f.msw.significand = 0; 369 kluge.f.significand2 = 0; 370 kluge.f.significand3 = 0; 371 kluge.f.significand4 = 0; 372 break; 373 case fp_infinity: 374 infinity: 375 kluge.f.msw.exponent = 0x7fff; 376 kluge.f.msw.significand = 0; 377 kluge.f.significand2 = 0; 378 kluge.f.significand3 = 0; 379 kluge.f.significand4 = 0; 380 break; 381 case fp_quiet: 382 kluge.f.msw.exponent = 0x7fff; 383 __fp_rightshift(pu, 15); 384 kluge.f.msw.significand = 0x8000 | 385 (0xffff & pu->significand[0]); 386 kluge.f.significand2 = pu->significand[1]; 387 kluge.f.significand3 = pu->significand[2]; 388 kluge.f.significand4 = pu->significand[3]; 389 break; 390 case fp_normal: 391 __fp_rightshift(pu, 15); 392 pu->exponent += QUAD_BIAS; 393 if (pu->exponent <= 0) { /* underflow */ 394 __fp_rightshift(pu, 1 - pu->exponent); 395 round(pu, 4, rd, &e); 396 if (pu->significand[0] == 0x10000) { 397 /* rounded back up to normal */ 398 kluge.f.msw.exponent = 1; 399 kluge.f.msw.significand = 0; 400 kluge.f.significand2 = 0; 401 kluge.f.significand3 = 0; 402 kluge.f.significand4 = 0; 403 e |= (1 << fp_underflow); 404 goto ret; 405 } 406 if (e & (1 << fp_inexact)) 407 e |= (1 << fp_underflow); 408 kluge.f.msw.exponent = 0; 409 kluge.f.msw.significand = 0xffff & pu->significand[0]; 410 kluge.f.significand2 = pu->significand[1]; 411 kluge.f.significand3 = pu->significand[2]; 412 kluge.f.significand4 = pu->significand[3]; 413 goto ret; 414 } 415 round(pu, 4, rd, &e); 416 if (pu->significand[0] == 0x20000) { /* rounding overflow */ 417 pu->significand[0] = 0x10000; 418 pu->exponent += 1; 419 } 420 if (pu->exponent >= 0x7fff) { /* overflow */ 421 e |= (1 << fp_overflow) | (1 << fp_inexact); 422 if (overflow_to_infinity(pu->sign, rd)) 423 goto infinity; 424 kluge.f.msw.exponent = 0x7ffe; 425 kluge.f.msw.significand = 0xffff; 426 kluge.f.significand2 = 0xffffffff; 427 kluge.f.significand3 = 0xffffffff; 428 kluge.f.significand4 = 0xffffffff; 429 goto ret; 430 } 431 kluge.f.msw.exponent = pu->exponent; 432 kluge.f.msw.significand = pu->significand[0] & 0xffff; 433 kluge.f.significand2 = pu->significand[1]; 434 kluge.f.significand3 = pu->significand[2]; 435 kluge.f.significand4 = pu->significand[3]; 436 break; 437 } 438 ret: 439 *px = kluge.x; 440 *ex = (fp_exception_field_type)e; 441 } 442