1 /*---------------------------------------------------------------------------+ 2 | reg_ld_str.c | 3 | | 4 | All of the functions which transfer data between user memory and FPU_REGs.| 5 | | 6 | Copyright (C) 1992,1993,1994,1996,1997 | 7 | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, Australia | 8 | E-mail billm@suburbia.net | 9 | | 10 | | 11 +---------------------------------------------------------------------------*/ 12 13 /*---------------------------------------------------------------------------+ 14 | Note: | 15 | The file contains code which accesses user memory. | 16 | Emulator static data may change when user memory is accessed, due to | 17 | other processes using the emulator while swapping is in progress. | 18 +---------------------------------------------------------------------------*/ 19 20 #include "fpu_emu.h" 21 22 #include <asm/uaccess.h> 23 24 #include "fpu_system.h" 25 #include "exception.h" 26 #include "reg_constant.h" 27 #include "control_w.h" 28 #include "status_w.h" 29 30 31 #define DOUBLE_Emax 1023 /* largest valid exponent */ 32 #define DOUBLE_Ebias 1023 33 #define DOUBLE_Emin (-1022) /* smallest valid exponent */ 34 35 #define SINGLE_Emax 127 /* largest valid exponent */ 36 #define SINGLE_Ebias 127 37 #define SINGLE_Emin (-126) /* smallest valid exponent */ 38 39 40 static u_char normalize_no_excep(FPU_REG *r, int exp, int sign) 41 { 42 u_char tag; 43 44 setexponent16(r, exp); 45 46 tag = FPU_normalize_nuo(r); 47 stdexp(r); 48 if ( sign ) 49 setnegative(r); 50 51 return tag; 52 } 53 54 55 int FPU_tagof(FPU_REG *ptr) 56 { 57 int exp; 58 59 exp = exponent16(ptr) & 0x7fff; 60 if ( exp == 0 ) 61 { 62 if ( !(ptr->sigh | ptr->sigl) ) 63 { 64 return TAG_Zero; 65 } 66 /* The number is a de-normal or pseudodenormal. */ 67 return TAG_Special; 68 } 69 70 if ( exp == 0x7fff ) 71 { 72 /* Is an Infinity, a NaN, or an unsupported data type. */ 73 return TAG_Special; 74 } 75 76 if ( !(ptr->sigh & 0x80000000) ) 77 { 78 /* Unsupported data type. */ 79 /* Valid numbers have the ms bit set to 1. */ 80 /* Unnormal. */ 81 return TAG_Special; 82 } 83 84 return TAG_Valid; 85 } 86 87 88 /* Get a long double from user memory */ 89 int FPU_load_extended(long double __user *s, int stnr) 90 { 91 FPU_REG *sti_ptr = &st(stnr); 92 93 RE_ENTRANT_CHECK_OFF; 94 FPU_access_ok(VERIFY_READ, s, 10); 95 __copy_from_user(sti_ptr, s, 10); 96 RE_ENTRANT_CHECK_ON; 97 98 return FPU_tagof(sti_ptr); 99 } 100 101 102 /* Get a double from user memory */ 103 int FPU_load_double(double __user *dfloat, FPU_REG *loaded_data) 104 { 105 int exp, tag, negative; 106 unsigned m64, l64; 107 108 RE_ENTRANT_CHECK_OFF; 109 FPU_access_ok(VERIFY_READ, dfloat, 8); 110 FPU_get_user(m64, 1 + (unsigned long __user *) dfloat); 111 FPU_get_user(l64, (unsigned long __user *) dfloat); 112 RE_ENTRANT_CHECK_ON; 113 114 negative = (m64 & 0x80000000) ? SIGN_Negative : SIGN_Positive; 115 exp = ((m64 & 0x7ff00000) >> 20) - DOUBLE_Ebias + EXTENDED_Ebias; 116 m64 &= 0xfffff; 117 if ( exp > DOUBLE_Emax + EXTENDED_Ebias ) 118 { 119 /* Infinity or NaN */ 120 if ((m64 == 0) && (l64 == 0)) 121 { 122 /* +- infinity */ 123 loaded_data->sigh = 0x80000000; 124 loaded_data->sigl = 0x00000000; 125 exp = EXP_Infinity + EXTENDED_Ebias; 126 tag = TAG_Special; 127 } 128 else 129 { 130 /* Must be a signaling or quiet NaN */ 131 exp = EXP_NaN + EXTENDED_Ebias; 132 loaded_data->sigh = (m64 << 11) | 0x80000000; 133 loaded_data->sigh |= l64 >> 21; 134 loaded_data->sigl = l64 << 11; 135 tag = TAG_Special; /* The calling function must look for NaNs */ 136 } 137 } 138 else if ( exp < DOUBLE_Emin + EXTENDED_Ebias ) 139 { 140 /* Zero or de-normal */ 141 if ((m64 == 0) && (l64 == 0)) 142 { 143 /* Zero */ 144 reg_copy(&CONST_Z, loaded_data); 145 exp = 0; 146 tag = TAG_Zero; 147 } 148 else 149 { 150 /* De-normal */ 151 loaded_data->sigh = m64 << 11; 152 loaded_data->sigh |= l64 >> 21; 153 loaded_data->sigl = l64 << 11; 154 155 return normalize_no_excep(loaded_data, DOUBLE_Emin, negative) 156 | (denormal_operand() < 0 ? FPU_Exception : 0); 157 } 158 } 159 else 160 { 161 loaded_data->sigh = (m64 << 11) | 0x80000000; 162 loaded_data->sigh |= l64 >> 21; 163 loaded_data->sigl = l64 << 11; 164 165 tag = TAG_Valid; 166 } 167 168 setexponent16(loaded_data, exp | negative); 169 170 return tag; 171 } 172 173 174 /* Get a float from user memory */ 175 int FPU_load_single(float __user *single, FPU_REG *loaded_data) 176 { 177 unsigned m32; 178 int exp, tag, negative; 179 180 RE_ENTRANT_CHECK_OFF; 181 FPU_access_ok(VERIFY_READ, single, 4); 182 FPU_get_user(m32, (unsigned long __user *) single); 183 RE_ENTRANT_CHECK_ON; 184 185 negative = (m32 & 0x80000000) ? SIGN_Negative : SIGN_Positive; 186 187 if (!(m32 & 0x7fffffff)) 188 { 189 /* Zero */ 190 reg_copy(&CONST_Z, loaded_data); 191 addexponent(loaded_data, negative); 192 return TAG_Zero; 193 } 194 exp = ((m32 & 0x7f800000) >> 23) - SINGLE_Ebias + EXTENDED_Ebias; 195 m32 = (m32 & 0x7fffff) << 8; 196 if ( exp < SINGLE_Emin + EXTENDED_Ebias ) 197 { 198 /* De-normals */ 199 loaded_data->sigh = m32; 200 loaded_data->sigl = 0; 201 202 return normalize_no_excep(loaded_data, SINGLE_Emin, negative) 203 | (denormal_operand() < 0 ? FPU_Exception : 0); 204 } 205 else if ( exp > SINGLE_Emax + EXTENDED_Ebias ) 206 { 207 /* Infinity or NaN */ 208 if ( m32 == 0 ) 209 { 210 /* +- infinity */ 211 loaded_data->sigh = 0x80000000; 212 loaded_data->sigl = 0x00000000; 213 exp = EXP_Infinity + EXTENDED_Ebias; 214 tag = TAG_Special; 215 } 216 else 217 { 218 /* Must be a signaling or quiet NaN */ 219 exp = EXP_NaN + EXTENDED_Ebias; 220 loaded_data->sigh = m32 | 0x80000000; 221 loaded_data->sigl = 0; 222 tag = TAG_Special; /* The calling function must look for NaNs */ 223 } 224 } 225 else 226 { 227 loaded_data->sigh = m32 | 0x80000000; 228 loaded_data->sigl = 0; 229 tag = TAG_Valid; 230 } 231 232 setexponent16(loaded_data, exp | negative); /* Set the sign. */ 233 234 return tag; 235 } 236 237 238 /* Get a long long from user memory */ 239 int FPU_load_int64(long long __user *_s) 240 { 241 long long s; 242 int sign; 243 FPU_REG *st0_ptr = &st(0); 244 245 RE_ENTRANT_CHECK_OFF; 246 FPU_access_ok(VERIFY_READ, _s, 8); 247 if (copy_from_user(&s,_s,8)) 248 FPU_abort; 249 RE_ENTRANT_CHECK_ON; 250 251 if (s == 0) 252 { 253 reg_copy(&CONST_Z, st0_ptr); 254 return TAG_Zero; 255 } 256 257 if (s > 0) 258 sign = SIGN_Positive; 259 else 260 { 261 s = -s; 262 sign = SIGN_Negative; 263 } 264 265 significand(st0_ptr) = s; 266 267 return normalize_no_excep(st0_ptr, 63, sign); 268 } 269 270 271 /* Get a long from user memory */ 272 int FPU_load_int32(long __user *_s, FPU_REG *loaded_data) 273 { 274 long s; 275 int negative; 276 277 RE_ENTRANT_CHECK_OFF; 278 FPU_access_ok(VERIFY_READ, _s, 4); 279 FPU_get_user(s, _s); 280 RE_ENTRANT_CHECK_ON; 281 282 if (s == 0) 283 { reg_copy(&CONST_Z, loaded_data); return TAG_Zero; } 284 285 if (s > 0) 286 negative = SIGN_Positive; 287 else 288 { 289 s = -s; 290 negative = SIGN_Negative; 291 } 292 293 loaded_data->sigh = s; 294 loaded_data->sigl = 0; 295 296 return normalize_no_excep(loaded_data, 31, negative); 297 } 298 299 300 /* Get a short from user memory */ 301 int FPU_load_int16(short __user *_s, FPU_REG *loaded_data) 302 { 303 int s, negative; 304 305 RE_ENTRANT_CHECK_OFF; 306 FPU_access_ok(VERIFY_READ, _s, 2); 307 /* Cast as short to get the sign extended. */ 308 FPU_get_user(s, _s); 309 RE_ENTRANT_CHECK_ON; 310 311 if (s == 0) 312 { reg_copy(&CONST_Z, loaded_data); return TAG_Zero; } 313 314 if (s > 0) 315 negative = SIGN_Positive; 316 else 317 { 318 s = -s; 319 negative = SIGN_Negative; 320 } 321 322 loaded_data->sigh = s << 16; 323 loaded_data->sigl = 0; 324 325 return normalize_no_excep(loaded_data, 15, negative); 326 } 327 328 329 /* Get a packed bcd array from user memory */ 330 int FPU_load_bcd(u_char __user *s) 331 { 332 FPU_REG *st0_ptr = &st(0); 333 int pos; 334 u_char bcd; 335 long long l=0; 336 int sign; 337 338 RE_ENTRANT_CHECK_OFF; 339 FPU_access_ok(VERIFY_READ, s, 10); 340 RE_ENTRANT_CHECK_ON; 341 for ( pos = 8; pos >= 0; pos--) 342 { 343 l *= 10; 344 RE_ENTRANT_CHECK_OFF; 345 FPU_get_user(bcd, s+pos); 346 RE_ENTRANT_CHECK_ON; 347 l += bcd >> 4; 348 l *= 10; 349 l += bcd & 0x0f; 350 } 351 352 RE_ENTRANT_CHECK_OFF; 353 FPU_get_user(sign, s+9); 354 sign = sign & 0x80 ? SIGN_Negative : SIGN_Positive; 355 RE_ENTRANT_CHECK_ON; 356 357 if ( l == 0 ) 358 { 359 reg_copy(&CONST_Z, st0_ptr); 360 addexponent(st0_ptr, sign); /* Set the sign. */ 361 return TAG_Zero; 362 } 363 else 364 { 365 significand(st0_ptr) = l; 366 return normalize_no_excep(st0_ptr, 63, sign); 367 } 368 } 369 370 /*===========================================================================*/ 371 372 /* Put a long double into user memory */ 373 int FPU_store_extended(FPU_REG *st0_ptr, u_char st0_tag, long double __user *d) 374 { 375 /* 376 The only exception raised by an attempt to store to an 377 extended format is the Invalid Stack exception, i.e. 378 attempting to store from an empty register. 379 */ 380 381 if ( st0_tag != TAG_Empty ) 382 { 383 RE_ENTRANT_CHECK_OFF; 384 FPU_access_ok(VERIFY_WRITE, d, 10); 385 386 FPU_put_user(st0_ptr->sigl, (unsigned long __user *) d); 387 FPU_put_user(st0_ptr->sigh, (unsigned long __user *) ((u_char __user *)d + 4)); 388 FPU_put_user(exponent16(st0_ptr), (unsigned short __user *) ((u_char __user *)d + 8)); 389 RE_ENTRANT_CHECK_ON; 390 391 return 1; 392 } 393 394 /* Empty register (stack underflow) */ 395 EXCEPTION(EX_StackUnder); 396 if ( control_word & CW_Invalid ) 397 { 398 /* The masked response */ 399 /* Put out the QNaN indefinite */ 400 RE_ENTRANT_CHECK_OFF; 401 FPU_access_ok(VERIFY_WRITE,d,10); 402 FPU_put_user(0, (unsigned long __user *) d); 403 FPU_put_user(0xc0000000, 1 + (unsigned long __user *) d); 404 FPU_put_user(0xffff, 4 + (short __user *) d); 405 RE_ENTRANT_CHECK_ON; 406 return 1; 407 } 408 else 409 return 0; 410 411 } 412 413 414 /* Put a double into user memory */ 415 int FPU_store_double(FPU_REG *st0_ptr, u_char st0_tag, double __user *dfloat) 416 { 417 unsigned long l[2]; 418 unsigned long increment = 0; /* avoid gcc warnings */ 419 int precision_loss; 420 int exp; 421 FPU_REG tmp; 422 423 if ( st0_tag == TAG_Valid ) 424 { 425 reg_copy(st0_ptr, &tmp); 426 exp = exponent(&tmp); 427 428 if ( exp < DOUBLE_Emin ) /* It may be a denormal */ 429 { 430 addexponent(&tmp, -DOUBLE_Emin + 52); /* largest exp to be 51 */ 431 432 denormal_arg: 433 434 if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) ) 435 { 436 #ifdef PECULIAR_486 437 /* Did it round to a non-denormal ? */ 438 /* This behaviour might be regarded as peculiar, it appears 439 that the 80486 rounds to the dest precision, then 440 converts to decide underflow. */ 441 if ( !((tmp.sigh == 0x00100000) && (tmp.sigl == 0) && 442 (st0_ptr->sigl & 0x000007ff)) ) 443 #endif /* PECULIAR_486 */ 444 { 445 EXCEPTION(EX_Underflow); 446 /* This is a special case: see sec 16.2.5.1 of 447 the 80486 book */ 448 if ( !(control_word & CW_Underflow) ) 449 return 0; 450 } 451 EXCEPTION(precision_loss); 452 if ( !(control_word & CW_Precision) ) 453 return 0; 454 } 455 l[0] = tmp.sigl; 456 l[1] = tmp.sigh; 457 } 458 else 459 { 460 if ( tmp.sigl & 0x000007ff ) 461 { 462 precision_loss = 1; 463 switch (control_word & CW_RC) 464 { 465 case RC_RND: 466 /* Rounding can get a little messy.. */ 467 increment = ((tmp.sigl & 0x7ff) > 0x400) | /* nearest */ 468 ((tmp.sigl & 0xc00) == 0xc00); /* odd -> even */ 469 break; 470 case RC_DOWN: /* towards -infinity */ 471 increment = signpositive(&tmp) ? 0 : tmp.sigl & 0x7ff; 472 break; 473 case RC_UP: /* towards +infinity */ 474 increment = signpositive(&tmp) ? tmp.sigl & 0x7ff : 0; 475 break; 476 case RC_CHOP: 477 increment = 0; 478 break; 479 } 480 481 /* Truncate the mantissa */ 482 tmp.sigl &= 0xfffff800; 483 484 if ( increment ) 485 { 486 if ( tmp.sigl >= 0xfffff800 ) 487 { 488 /* the sigl part overflows */ 489 if ( tmp.sigh == 0xffffffff ) 490 { 491 /* The sigh part overflows */ 492 tmp.sigh = 0x80000000; 493 exp++; 494 if (exp >= EXP_OVER) 495 goto overflow; 496 } 497 else 498 { 499 tmp.sigh ++; 500 } 501 tmp.sigl = 0x00000000; 502 } 503 else 504 { 505 /* We only need to increment sigl */ 506 tmp.sigl += 0x00000800; 507 } 508 } 509 } 510 else 511 precision_loss = 0; 512 513 l[0] = (tmp.sigl >> 11) | (tmp.sigh << 21); 514 l[1] = ((tmp.sigh >> 11) & 0xfffff); 515 516 if ( exp > DOUBLE_Emax ) 517 { 518 overflow: 519 EXCEPTION(EX_Overflow); 520 if ( !(control_word & CW_Overflow) ) 521 return 0; 522 set_precision_flag_up(); 523 if ( !(control_word & CW_Precision) ) 524 return 0; 525 526 /* This is a special case: see sec 16.2.5.1 of the 80486 book */ 527 /* Overflow to infinity */ 528 l[0] = 0x00000000; /* Set to */ 529 l[1] = 0x7ff00000; /* + INF */ 530 } 531 else 532 { 533 if ( precision_loss ) 534 { 535 if ( increment ) 536 set_precision_flag_up(); 537 else 538 set_precision_flag_down(); 539 } 540 /* Add the exponent */ 541 l[1] |= (((exp+DOUBLE_Ebias) & 0x7ff) << 20); 542 } 543 } 544 } 545 else if (st0_tag == TAG_Zero) 546 { 547 /* Number is zero */ 548 l[0] = 0; 549 l[1] = 0; 550 } 551 else if ( st0_tag == TAG_Special ) 552 { 553 st0_tag = FPU_Special(st0_ptr); 554 if ( st0_tag == TW_Denormal ) 555 { 556 /* A denormal will always underflow. */ 557 #ifndef PECULIAR_486 558 /* An 80486 is supposed to be able to generate 559 a denormal exception here, but... */ 560 /* Underflow has priority. */ 561 if ( control_word & CW_Underflow ) 562 denormal_operand(); 563 #endif /* PECULIAR_486 */ 564 reg_copy(st0_ptr, &tmp); 565 goto denormal_arg; 566 } 567 else if (st0_tag == TW_Infinity) 568 { 569 l[0] = 0; 570 l[1] = 0x7ff00000; 571 } 572 else if (st0_tag == TW_NaN) 573 { 574 /* Is it really a NaN ? */ 575 if ( (exponent(st0_ptr) == EXP_OVER) 576 && (st0_ptr->sigh & 0x80000000) ) 577 { 578 /* See if we can get a valid NaN from the FPU_REG */ 579 l[0] = (st0_ptr->sigl >> 11) | (st0_ptr->sigh << 21); 580 l[1] = ((st0_ptr->sigh >> 11) & 0xfffff); 581 if ( !(st0_ptr->sigh & 0x40000000) ) 582 { 583 /* It is a signalling NaN */ 584 EXCEPTION(EX_Invalid); 585 if ( !(control_word & CW_Invalid) ) 586 return 0; 587 l[1] |= (0x40000000 >> 11); 588 } 589 l[1] |= 0x7ff00000; 590 } 591 else 592 { 593 /* It is an unsupported data type */ 594 EXCEPTION(EX_Invalid); 595 if ( !(control_word & CW_Invalid) ) 596 return 0; 597 l[0] = 0; 598 l[1] = 0xfff80000; 599 } 600 } 601 } 602 else if ( st0_tag == TAG_Empty ) 603 { 604 /* Empty register (stack underflow) */ 605 EXCEPTION(EX_StackUnder); 606 if ( control_word & CW_Invalid ) 607 { 608 /* The masked response */ 609 /* Put out the QNaN indefinite */ 610 RE_ENTRANT_CHECK_OFF; 611 FPU_access_ok(VERIFY_WRITE,dfloat,8); 612 FPU_put_user(0, (unsigned long __user *) dfloat); 613 FPU_put_user(0xfff80000, 1 + (unsigned long __user *) dfloat); 614 RE_ENTRANT_CHECK_ON; 615 return 1; 616 } 617 else 618 return 0; 619 } 620 if ( getsign(st0_ptr) ) 621 l[1] |= 0x80000000; 622 623 RE_ENTRANT_CHECK_OFF; 624 FPU_access_ok(VERIFY_WRITE,dfloat,8); 625 FPU_put_user(l[0], (unsigned long __user *)dfloat); 626 FPU_put_user(l[1], 1 + (unsigned long __user *)dfloat); 627 RE_ENTRANT_CHECK_ON; 628 629 return 1; 630 } 631 632 633 /* Put a float into user memory */ 634 int FPU_store_single(FPU_REG *st0_ptr, u_char st0_tag, float __user *single) 635 { 636 long templ = 0; 637 unsigned long increment = 0; /* avoid gcc warnings */ 638 int precision_loss; 639 int exp; 640 FPU_REG tmp; 641 642 if ( st0_tag == TAG_Valid ) 643 { 644 645 reg_copy(st0_ptr, &tmp); 646 exp = exponent(&tmp); 647 648 if ( exp < SINGLE_Emin ) 649 { 650 addexponent(&tmp, -SINGLE_Emin + 23); /* largest exp to be 22 */ 651 652 denormal_arg: 653 654 if ( (precision_loss = FPU_round_to_int(&tmp, st0_tag)) ) 655 { 656 #ifdef PECULIAR_486 657 /* Did it round to a non-denormal ? */ 658 /* This behaviour might be regarded as peculiar, it appears 659 that the 80486 rounds to the dest precision, then 660 converts to decide underflow. */ 661 if ( !((tmp.sigl == 0x00800000) && 662 ((st0_ptr->sigh & 0x000000ff) || st0_ptr->sigl)) ) 663 #endif /* PECULIAR_486 */ 664 { 665 EXCEPTION(EX_Underflow); 666 /* This is a special case: see sec 16.2.5.1 of 667 the 80486 book */ 668 if ( !(control_word & CW_Underflow) ) 669 return 0; 670 } 671 EXCEPTION(precision_loss); 672 if ( !(control_word & CW_Precision) ) 673 return 0; 674 } 675 templ = tmp.sigl; 676 } 677 else 678 { 679 if ( tmp.sigl | (tmp.sigh & 0x000000ff) ) 680 { 681 unsigned long sigh = tmp.sigh; 682 unsigned long sigl = tmp.sigl; 683 684 precision_loss = 1; 685 switch (control_word & CW_RC) 686 { 687 case RC_RND: 688 increment = ((sigh & 0xff) > 0x80) /* more than half */ 689 || (((sigh & 0xff) == 0x80) && sigl) /* more than half */ 690 || ((sigh & 0x180) == 0x180); /* round to even */ 691 break; 692 case RC_DOWN: /* towards -infinity */ 693 increment = signpositive(&tmp) 694 ? 0 : (sigl | (sigh & 0xff)); 695 break; 696 case RC_UP: /* towards +infinity */ 697 increment = signpositive(&tmp) 698 ? (sigl | (sigh & 0xff)) : 0; 699 break; 700 case RC_CHOP: 701 increment = 0; 702 break; 703 } 704 705 /* Truncate part of the mantissa */ 706 tmp.sigl = 0; 707 708 if (increment) 709 { 710 if ( sigh >= 0xffffff00 ) 711 { 712 /* The sigh part overflows */ 713 tmp.sigh = 0x80000000; 714 exp++; 715 if ( exp >= EXP_OVER ) 716 goto overflow; 717 } 718 else 719 { 720 tmp.sigh &= 0xffffff00; 721 tmp.sigh += 0x100; 722 } 723 } 724 else 725 { 726 tmp.sigh &= 0xffffff00; /* Finish the truncation */ 727 } 728 } 729 else 730 precision_loss = 0; 731 732 templ = (tmp.sigh >> 8) & 0x007fffff; 733 734 if ( exp > SINGLE_Emax ) 735 { 736 overflow: 737 EXCEPTION(EX_Overflow); 738 if ( !(control_word & CW_Overflow) ) 739 return 0; 740 set_precision_flag_up(); 741 if ( !(control_word & CW_Precision) ) 742 return 0; 743 744 /* This is a special case: see sec 16.2.5.1 of the 80486 book. */ 745 /* Masked response is overflow to infinity. */ 746 templ = 0x7f800000; 747 } 748 else 749 { 750 if ( precision_loss ) 751 { 752 if ( increment ) 753 set_precision_flag_up(); 754 else 755 set_precision_flag_down(); 756 } 757 /* Add the exponent */ 758 templ |= ((exp+SINGLE_Ebias) & 0xff) << 23; 759 } 760 } 761 } 762 else if (st0_tag == TAG_Zero) 763 { 764 templ = 0; 765 } 766 else if ( st0_tag == TAG_Special ) 767 { 768 st0_tag = FPU_Special(st0_ptr); 769 if (st0_tag == TW_Denormal) 770 { 771 reg_copy(st0_ptr, &tmp); 772 773 /* A denormal will always underflow. */ 774 #ifndef PECULIAR_486 775 /* An 80486 is supposed to be able to generate 776 a denormal exception here, but... */ 777 /* Underflow has priority. */ 778 if ( control_word & CW_Underflow ) 779 denormal_operand(); 780 #endif /* PECULIAR_486 */ 781 goto denormal_arg; 782 } 783 else if (st0_tag == TW_Infinity) 784 { 785 templ = 0x7f800000; 786 } 787 else if (st0_tag == TW_NaN) 788 { 789 /* Is it really a NaN ? */ 790 if ( (exponent(st0_ptr) == EXP_OVER) && (st0_ptr->sigh & 0x80000000) ) 791 { 792 /* See if we can get a valid NaN from the FPU_REG */ 793 templ = st0_ptr->sigh >> 8; 794 if ( !(st0_ptr->sigh & 0x40000000) ) 795 { 796 /* It is a signalling NaN */ 797 EXCEPTION(EX_Invalid); 798 if ( !(control_word & CW_Invalid) ) 799 return 0; 800 templ |= (0x40000000 >> 8); 801 } 802 templ |= 0x7f800000; 803 } 804 else 805 { 806 /* It is an unsupported data type */ 807 EXCEPTION(EX_Invalid); 808 if ( !(control_word & CW_Invalid) ) 809 return 0; 810 templ = 0xffc00000; 811 } 812 } 813 #ifdef PARANOID 814 else 815 { 816 EXCEPTION(EX_INTERNAL|0x164); 817 return 0; 818 } 819 #endif 820 } 821 else if ( st0_tag == TAG_Empty ) 822 { 823 /* Empty register (stack underflow) */ 824 EXCEPTION(EX_StackUnder); 825 if ( control_word & EX_Invalid ) 826 { 827 /* The masked response */ 828 /* Put out the QNaN indefinite */ 829 RE_ENTRANT_CHECK_OFF; 830 FPU_access_ok(VERIFY_WRITE,single,4); 831 FPU_put_user(0xffc00000, (unsigned long __user *) single); 832 RE_ENTRANT_CHECK_ON; 833 return 1; 834 } 835 else 836 return 0; 837 } 838 #ifdef PARANOID 839 else 840 { 841 EXCEPTION(EX_INTERNAL|0x163); 842 return 0; 843 } 844 #endif 845 if ( getsign(st0_ptr) ) 846 templ |= 0x80000000; 847 848 RE_ENTRANT_CHECK_OFF; 849 FPU_access_ok(VERIFY_WRITE,single,4); 850 FPU_put_user(templ,(unsigned long __user *) single); 851 RE_ENTRANT_CHECK_ON; 852 853 return 1; 854 } 855 856 857 /* Put a long long into user memory */ 858 int FPU_store_int64(FPU_REG *st0_ptr, u_char st0_tag, long long __user *d) 859 { 860 FPU_REG t; 861 long long tll; 862 int precision_loss; 863 864 if ( st0_tag == TAG_Empty ) 865 { 866 /* Empty register (stack underflow) */ 867 EXCEPTION(EX_StackUnder); 868 goto invalid_operand; 869 } 870 else if ( st0_tag == TAG_Special ) 871 { 872 st0_tag = FPU_Special(st0_ptr); 873 if ( (st0_tag == TW_Infinity) || 874 (st0_tag == TW_NaN) ) 875 { 876 EXCEPTION(EX_Invalid); 877 goto invalid_operand; 878 } 879 } 880 881 reg_copy(st0_ptr, &t); 882 precision_loss = FPU_round_to_int(&t, st0_tag); 883 ((long *)&tll)[0] = t.sigl; 884 ((long *)&tll)[1] = t.sigh; 885 if ( (precision_loss == 1) || 886 ((t.sigh & 0x80000000) && 887 !((t.sigh == 0x80000000) && (t.sigl == 0) && 888 signnegative(&t))) ) 889 { 890 EXCEPTION(EX_Invalid); 891 /* This is a special case: see sec 16.2.5.1 of the 80486 book */ 892 invalid_operand: 893 if ( control_word & EX_Invalid ) 894 { 895 /* Produce something like QNaN "indefinite" */ 896 tll = 0x8000000000000000LL; 897 } 898 else 899 return 0; 900 } 901 else 902 { 903 if ( precision_loss ) 904 set_precision_flag(precision_loss); 905 if ( signnegative(&t) ) 906 tll = - tll; 907 } 908 909 RE_ENTRANT_CHECK_OFF; 910 FPU_access_ok(VERIFY_WRITE,d,8); 911 if (copy_to_user(d, &tll, 8)) 912 FPU_abort; 913 RE_ENTRANT_CHECK_ON; 914 915 return 1; 916 } 917 918 919 /* Put a long into user memory */ 920 int FPU_store_int32(FPU_REG *st0_ptr, u_char st0_tag, long __user *d) 921 { 922 FPU_REG t; 923 int precision_loss; 924 925 if ( st0_tag == TAG_Empty ) 926 { 927 /* Empty register (stack underflow) */ 928 EXCEPTION(EX_StackUnder); 929 goto invalid_operand; 930 } 931 else if ( st0_tag == TAG_Special ) 932 { 933 st0_tag = FPU_Special(st0_ptr); 934 if ( (st0_tag == TW_Infinity) || 935 (st0_tag == TW_NaN) ) 936 { 937 EXCEPTION(EX_Invalid); 938 goto invalid_operand; 939 } 940 } 941 942 reg_copy(st0_ptr, &t); 943 precision_loss = FPU_round_to_int(&t, st0_tag); 944 if (t.sigh || 945 ((t.sigl & 0x80000000) && 946 !((t.sigl == 0x80000000) && signnegative(&t))) ) 947 { 948 EXCEPTION(EX_Invalid); 949 /* This is a special case: see sec 16.2.5.1 of the 80486 book */ 950 invalid_operand: 951 if ( control_word & EX_Invalid ) 952 { 953 /* Produce something like QNaN "indefinite" */ 954 t.sigl = 0x80000000; 955 } 956 else 957 return 0; 958 } 959 else 960 { 961 if ( precision_loss ) 962 set_precision_flag(precision_loss); 963 if ( signnegative(&t) ) 964 t.sigl = -(long)t.sigl; 965 } 966 967 RE_ENTRANT_CHECK_OFF; 968 FPU_access_ok(VERIFY_WRITE,d,4); 969 FPU_put_user(t.sigl, (unsigned long __user *) d); 970 RE_ENTRANT_CHECK_ON; 971 972 return 1; 973 } 974 975 976 /* Put a short into user memory */ 977 int FPU_store_int16(FPU_REG *st0_ptr, u_char st0_tag, short __user *d) 978 { 979 FPU_REG t; 980 int precision_loss; 981 982 if ( st0_tag == TAG_Empty ) 983 { 984 /* Empty register (stack underflow) */ 985 EXCEPTION(EX_StackUnder); 986 goto invalid_operand; 987 } 988 else if ( st0_tag == TAG_Special ) 989 { 990 st0_tag = FPU_Special(st0_ptr); 991 if ( (st0_tag == TW_Infinity) || 992 (st0_tag == TW_NaN) ) 993 { 994 EXCEPTION(EX_Invalid); 995 goto invalid_operand; 996 } 997 } 998 999 reg_copy(st0_ptr, &t); 1000 precision_loss = FPU_round_to_int(&t, st0_tag); 1001 if (t.sigh || 1002 ((t.sigl & 0xffff8000) && 1003 !((t.sigl == 0x8000) && signnegative(&t))) ) 1004 { 1005 EXCEPTION(EX_Invalid); 1006 /* This is a special case: see sec 16.2.5.1 of the 80486 book */ 1007 invalid_operand: 1008 if ( control_word & EX_Invalid ) 1009 { 1010 /* Produce something like QNaN "indefinite" */ 1011 t.sigl = 0x8000; 1012 } 1013 else 1014 return 0; 1015 } 1016 else 1017 { 1018 if ( precision_loss ) 1019 set_precision_flag(precision_loss); 1020 if ( signnegative(&t) ) 1021 t.sigl = -t.sigl; 1022 } 1023 1024 RE_ENTRANT_CHECK_OFF; 1025 FPU_access_ok(VERIFY_WRITE,d,2); 1026 FPU_put_user((short)t.sigl, d); 1027 RE_ENTRANT_CHECK_ON; 1028 1029 return 1; 1030 } 1031 1032 1033 /* Put a packed bcd array into user memory */ 1034 int FPU_store_bcd(FPU_REG *st0_ptr, u_char st0_tag, u_char __user *d) 1035 { 1036 FPU_REG t; 1037 unsigned long long ll; 1038 u_char b; 1039 int i, precision_loss; 1040 u_char sign = (getsign(st0_ptr) == SIGN_NEG) ? 0x80 : 0; 1041 1042 if ( st0_tag == TAG_Empty ) 1043 { 1044 /* Empty register (stack underflow) */ 1045 EXCEPTION(EX_StackUnder); 1046 goto invalid_operand; 1047 } 1048 else if ( st0_tag == TAG_Special ) 1049 { 1050 st0_tag = FPU_Special(st0_ptr); 1051 if ( (st0_tag == TW_Infinity) || 1052 (st0_tag == TW_NaN) ) 1053 { 1054 EXCEPTION(EX_Invalid); 1055 goto invalid_operand; 1056 } 1057 } 1058 1059 reg_copy(st0_ptr, &t); 1060 precision_loss = FPU_round_to_int(&t, st0_tag); 1061 ll = significand(&t); 1062 1063 /* Check for overflow, by comparing with 999999999999999999 decimal. */ 1064 if ( (t.sigh > 0x0de0b6b3) || 1065 ((t.sigh == 0x0de0b6b3) && (t.sigl > 0xa763ffff)) ) 1066 { 1067 EXCEPTION(EX_Invalid); 1068 /* This is a special case: see sec 16.2.5.1 of the 80486 book */ 1069 invalid_operand: 1070 if ( control_word & CW_Invalid ) 1071 { 1072 /* Produce the QNaN "indefinite" */ 1073 RE_ENTRANT_CHECK_OFF; 1074 FPU_access_ok(VERIFY_WRITE,d,10); 1075 for ( i = 0; i < 7; i++) 1076 FPU_put_user(0, d+i); /* These bytes "undefined" */ 1077 FPU_put_user(0xc0, d+7); /* This byte "undefined" */ 1078 FPU_put_user(0xff, d+8); 1079 FPU_put_user(0xff, d+9); 1080 RE_ENTRANT_CHECK_ON; 1081 return 1; 1082 } 1083 else 1084 return 0; 1085 } 1086 else if ( precision_loss ) 1087 { 1088 /* Precision loss doesn't stop the data transfer */ 1089 set_precision_flag(precision_loss); 1090 } 1091 1092 RE_ENTRANT_CHECK_OFF; 1093 FPU_access_ok(VERIFY_WRITE,d,10); 1094 RE_ENTRANT_CHECK_ON; 1095 for ( i = 0; i < 9; i++) 1096 { 1097 b = FPU_div_small(&ll, 10); 1098 b |= (FPU_div_small(&ll, 10)) << 4; 1099 RE_ENTRANT_CHECK_OFF; 1100 FPU_put_user(b, d+i); 1101 RE_ENTRANT_CHECK_ON; 1102 } 1103 RE_ENTRANT_CHECK_OFF; 1104 FPU_put_user(sign, d+9); 1105 RE_ENTRANT_CHECK_ON; 1106 1107 return 1; 1108 } 1109 1110 /*===========================================================================*/ 1111 1112 /* r gets mangled such that sig is int, sign: 1113 it is NOT normalized */ 1114 /* The return value (in eax) is zero if the result is exact, 1115 if bits are changed due to rounding, truncation, etc, then 1116 a non-zero value is returned */ 1117 /* Overflow is signalled by a non-zero return value (in eax). 1118 In the case of overflow, the returned significand always has the 1119 largest possible value */ 1120 int FPU_round_to_int(FPU_REG *r, u_char tag) 1121 { 1122 u_char very_big; 1123 unsigned eax; 1124 1125 if (tag == TAG_Zero) 1126 { 1127 /* Make sure that zero is returned */ 1128 significand(r) = 0; 1129 return 0; /* o.k. */ 1130 } 1131 1132 if (exponent(r) > 63) 1133 { 1134 r->sigl = r->sigh = ~0; /* The largest representable number */ 1135 return 1; /* overflow */ 1136 } 1137 1138 eax = FPU_shrxs(&r->sigl, 63 - exponent(r)); 1139 very_big = !(~(r->sigh) | ~(r->sigl)); /* test for 0xfff...fff */ 1140 #define half_or_more (eax & 0x80000000) 1141 #define frac_part (eax) 1142 #define more_than_half ((eax & 0x80000001) == 0x80000001) 1143 switch (control_word & CW_RC) 1144 { 1145 case RC_RND: 1146 if ( more_than_half /* nearest */ 1147 || (half_or_more && (r->sigl & 1)) ) /* odd -> even */ 1148 { 1149 if ( very_big ) return 1; /* overflow */ 1150 significand(r) ++; 1151 return PRECISION_LOST_UP; 1152 } 1153 break; 1154 case RC_DOWN: 1155 if (frac_part && getsign(r)) 1156 { 1157 if ( very_big ) return 1; /* overflow */ 1158 significand(r) ++; 1159 return PRECISION_LOST_UP; 1160 } 1161 break; 1162 case RC_UP: 1163 if (frac_part && !getsign(r)) 1164 { 1165 if ( very_big ) return 1; /* overflow */ 1166 significand(r) ++; 1167 return PRECISION_LOST_UP; 1168 } 1169 break; 1170 case RC_CHOP: 1171 break; 1172 } 1173 1174 return eax ? PRECISION_LOST_DOWN : 0; 1175 1176 } 1177 1178 /*===========================================================================*/ 1179 1180 u_char __user *fldenv(fpu_addr_modes addr_modes, u_char __user *s) 1181 { 1182 unsigned short tag_word = 0; 1183 u_char tag; 1184 int i; 1185 1186 if ( (addr_modes.default_mode == VM86) || 1187 ((addr_modes.default_mode == PM16) 1188 ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX)) ) 1189 { 1190 RE_ENTRANT_CHECK_OFF; 1191 FPU_access_ok(VERIFY_READ, s, 0x0e); 1192 FPU_get_user(control_word, (unsigned short __user *) s); 1193 FPU_get_user(partial_status, (unsigned short __user *) (s+2)); 1194 FPU_get_user(tag_word, (unsigned short __user *) (s+4)); 1195 FPU_get_user(instruction_address.offset, (unsigned short __user *) (s+6)); 1196 FPU_get_user(instruction_address.selector, (unsigned short __user *) (s+8)); 1197 FPU_get_user(operand_address.offset, (unsigned short __user *) (s+0x0a)); 1198 FPU_get_user(operand_address.selector, (unsigned short __user *) (s+0x0c)); 1199 RE_ENTRANT_CHECK_ON; 1200 s += 0x0e; 1201 if ( addr_modes.default_mode == VM86 ) 1202 { 1203 instruction_address.offset 1204 += (instruction_address.selector & 0xf000) << 4; 1205 operand_address.offset += (operand_address.selector & 0xf000) << 4; 1206 } 1207 } 1208 else 1209 { 1210 RE_ENTRANT_CHECK_OFF; 1211 FPU_access_ok(VERIFY_READ, s, 0x1c); 1212 FPU_get_user(control_word, (unsigned short __user *) s); 1213 FPU_get_user(partial_status, (unsigned short __user *) (s+4)); 1214 FPU_get_user(tag_word, (unsigned short __user *) (s+8)); 1215 FPU_get_user(instruction_address.offset, (unsigned long __user *) (s+0x0c)); 1216 FPU_get_user(instruction_address.selector, (unsigned short __user *) (s+0x10)); 1217 FPU_get_user(instruction_address.opcode, (unsigned short __user *) (s+0x12)); 1218 FPU_get_user(operand_address.offset, (unsigned long __user *) (s+0x14)); 1219 FPU_get_user(operand_address.selector, (unsigned long __user *) (s+0x18)); 1220 RE_ENTRANT_CHECK_ON; 1221 s += 0x1c; 1222 } 1223 1224 #ifdef PECULIAR_486 1225 control_word &= ~0xe080; 1226 #endif /* PECULIAR_486 */ 1227 1228 top = (partial_status >> SW_Top_Shift) & 7; 1229 1230 if ( partial_status & ~control_word & CW_Exceptions ) 1231 partial_status |= (SW_Summary | SW_Backward); 1232 else 1233 partial_status &= ~(SW_Summary | SW_Backward); 1234 1235 for ( i = 0; i < 8; i++ ) 1236 { 1237 tag = tag_word & 3; 1238 tag_word >>= 2; 1239 1240 if ( tag == TAG_Empty ) 1241 /* New tag is empty. Accept it */ 1242 FPU_settag(i, TAG_Empty); 1243 else if ( FPU_gettag(i) == TAG_Empty ) 1244 { 1245 /* Old tag is empty and new tag is not empty. New tag is determined 1246 by old reg contents */ 1247 if ( exponent(&fpu_register(i)) == - EXTENDED_Ebias ) 1248 { 1249 if ( !(fpu_register(i).sigl | fpu_register(i).sigh) ) 1250 FPU_settag(i, TAG_Zero); 1251 else 1252 FPU_settag(i, TAG_Special); 1253 } 1254 else if ( exponent(&fpu_register(i)) == 0x7fff - EXTENDED_Ebias ) 1255 { 1256 FPU_settag(i, TAG_Special); 1257 } 1258 else if ( fpu_register(i).sigh & 0x80000000 ) 1259 FPU_settag(i, TAG_Valid); 1260 else 1261 FPU_settag(i, TAG_Special); /* An Un-normal */ 1262 } 1263 /* Else old tag is not empty and new tag is not empty. Old tag 1264 remains correct */ 1265 } 1266 1267 return s; 1268 } 1269 1270 1271 void frstor(fpu_addr_modes addr_modes, u_char __user *data_address) 1272 { 1273 int i, regnr; 1274 u_char __user *s = fldenv(addr_modes, data_address); 1275 int offset = (top & 7) * 10, other = 80 - offset; 1276 1277 /* Copy all registers in stack order. */ 1278 RE_ENTRANT_CHECK_OFF; 1279 FPU_access_ok(VERIFY_READ,s,80); 1280 __copy_from_user(register_base+offset, s, other); 1281 if ( offset ) 1282 __copy_from_user(register_base, s+other, offset); 1283 RE_ENTRANT_CHECK_ON; 1284 1285 for ( i = 0; i < 8; i++ ) 1286 { 1287 regnr = (i+top) & 7; 1288 if ( FPU_gettag(regnr) != TAG_Empty ) 1289 /* The loaded data over-rides all other cases. */ 1290 FPU_settag(regnr, FPU_tagof(&st(i))); 1291 } 1292 1293 } 1294 1295 1296 u_char __user *fstenv(fpu_addr_modes addr_modes, u_char __user *d) 1297 { 1298 if ( (addr_modes.default_mode == VM86) || 1299 ((addr_modes.default_mode == PM16) 1300 ^ (addr_modes.override.operand_size == OP_SIZE_PREFIX)) ) 1301 { 1302 RE_ENTRANT_CHECK_OFF; 1303 FPU_access_ok(VERIFY_WRITE,d,14); 1304 #ifdef PECULIAR_486 1305 FPU_put_user(control_word & ~0xe080, (unsigned long __user *) d); 1306 #else 1307 FPU_put_user(control_word, (unsigned short __user *) d); 1308 #endif /* PECULIAR_486 */ 1309 FPU_put_user(status_word(), (unsigned short __user *) (d+2)); 1310 FPU_put_user(fpu_tag_word, (unsigned short __user *) (d+4)); 1311 FPU_put_user(instruction_address.offset, (unsigned short __user *) (d+6)); 1312 FPU_put_user(operand_address.offset, (unsigned short __user *) (d+0x0a)); 1313 if ( addr_modes.default_mode == VM86 ) 1314 { 1315 FPU_put_user((instruction_address.offset & 0xf0000) >> 4, 1316 (unsigned short __user *) (d+8)); 1317 FPU_put_user((operand_address.offset & 0xf0000) >> 4, 1318 (unsigned short __user *) (d+0x0c)); 1319 } 1320 else 1321 { 1322 FPU_put_user(instruction_address.selector, (unsigned short __user *) (d+8)); 1323 FPU_put_user(operand_address.selector, (unsigned short __user *) (d+0x0c)); 1324 } 1325 RE_ENTRANT_CHECK_ON; 1326 d += 0x0e; 1327 } 1328 else 1329 { 1330 RE_ENTRANT_CHECK_OFF; 1331 FPU_access_ok(VERIFY_WRITE, d, 7*4); 1332 #ifdef PECULIAR_486 1333 control_word &= ~0xe080; 1334 /* An 80486 sets nearly all of the reserved bits to 1. */ 1335 control_word |= 0xffff0040; 1336 partial_status = status_word() | 0xffff0000; 1337 fpu_tag_word |= 0xffff0000; 1338 I387.soft.fcs &= ~0xf8000000; 1339 I387.soft.fos |= 0xffff0000; 1340 #endif /* PECULIAR_486 */ 1341 if (__copy_to_user(d, &control_word, 7*4)) 1342 FPU_abort; 1343 RE_ENTRANT_CHECK_ON; 1344 d += 0x1c; 1345 } 1346 1347 control_word |= CW_Exceptions; 1348 partial_status &= ~(SW_Summary | SW_Backward); 1349 1350 return d; 1351 } 1352 1353 1354 void fsave(fpu_addr_modes addr_modes, u_char __user *data_address) 1355 { 1356 u_char __user *d; 1357 int offset = (top & 7) * 10, other = 80 - offset; 1358 1359 d = fstenv(addr_modes, data_address); 1360 1361 RE_ENTRANT_CHECK_OFF; 1362 FPU_access_ok(VERIFY_WRITE,d,80); 1363 1364 /* Copy all registers in stack order. */ 1365 if (__copy_to_user(d, register_base+offset, other)) 1366 FPU_abort; 1367 if ( offset ) 1368 if (__copy_to_user(d+other, register_base, offset)) 1369 FPU_abort; 1370 RE_ENTRANT_CHECK_ON; 1371 1372 finit(); 1373 } 1374 1375 /*===========================================================================*/ 1376