1/* Accurate fp support for CGEN-based simulators. 2 Copyright (C) 1999 Cygnus Solutions. 3 4 This implemention assumes: 5 typedef USI SF; 6 typedef UDI DF; 7 8 TODO: 9 - lazy encoding/decoding 10 - checking return code (say by callback) 11 - proper rounding 12*/ 13 14/* This must come before any other includes. */ 15#include "defs.h" 16 17#include "sim-main.h" 18#include "sim-fpu.h" 19 20/* SF mode support */ 21 22static SF 23addsf (CGEN_FPU* fpu, SF x, SF y) 24{ 25 sim_fpu op1; 26 sim_fpu op2; 27 sim_fpu ans; 28 uint32_t res; 29 sim_fpu_status status; 30 31 sim_fpu_32to (&op1, x); 32 sim_fpu_32to (&op2, y); 33 status = sim_fpu_add (&ans, &op1, &op2); 34 if (status != 0) 35 (*fpu->ops->error) (fpu, status); 36 sim_fpu_to32 (&res, &ans); 37 38 return res; 39} 40 41static SF 42subsf (CGEN_FPU* fpu, SF x, SF y) 43{ 44 sim_fpu op1; 45 sim_fpu op2; 46 sim_fpu ans; 47 uint32_t res; 48 sim_fpu_status status; 49 50 sim_fpu_32to (&op1, x); 51 sim_fpu_32to (&op2, y); 52 status = sim_fpu_sub (&ans, &op1, &op2); 53 if (status != 0) 54 (*fpu->ops->error) (fpu, status); 55 sim_fpu_to32 (&res, &ans); 56 57 return res; 58} 59 60static SF 61mulsf (CGEN_FPU* fpu, SF x, SF y) 62{ 63 sim_fpu op1; 64 sim_fpu op2; 65 sim_fpu ans; 66 uint32_t res; 67 sim_fpu_status status; 68 69 sim_fpu_32to (&op1, x); 70 sim_fpu_32to (&op2, y); 71 status = sim_fpu_mul (&ans, &op1, &op2); 72 if (status != 0) 73 (*fpu->ops->error) (fpu, status); 74 sim_fpu_to32 (&res, &ans); 75 76 return res; 77} 78 79static SF 80divsf (CGEN_FPU* fpu, SF x, SF y) 81{ 82 sim_fpu op1; 83 sim_fpu op2; 84 sim_fpu ans; 85 uint32_t res; 86 sim_fpu_status status; 87 88 sim_fpu_32to (&op1, x); 89 sim_fpu_32to (&op2, y); 90 status = sim_fpu_div (&ans, &op1, &op2); 91 if (status != 0) 92 (*fpu->ops->error) (fpu, status); 93 sim_fpu_to32 (&res, &ans); 94 95 return res; 96} 97 98static SF 99remsf (CGEN_FPU* fpu, SF x, SF y) 100{ 101 sim_fpu op1; 102 sim_fpu op2; 103 sim_fpu ans; 104 uint32_t res; 105 sim_fpu_status status; 106 107 sim_fpu_32to (&op1, x); 108 sim_fpu_32to (&op2, y); 109 status = sim_fpu_rem (&ans, &op1, &op2); 110 if (status != 0) 111 (*fpu->ops->error) (fpu, status); 112 sim_fpu_to32 (&res, &ans); 113 114 return res; 115} 116 117static SF 118negsf (CGEN_FPU* fpu, SF x) 119{ 120 sim_fpu op1; 121 sim_fpu ans; 122 uint32_t res; 123 sim_fpu_status status; 124 125 sim_fpu_32to (&op1, x); 126 status = sim_fpu_neg (&ans, &op1); 127 if (status != 0) 128 (*fpu->ops->error) (fpu, status); 129 sim_fpu_to32 (&res, &ans); 130 131 return res; 132} 133 134static SF 135abssf (CGEN_FPU* fpu, SF x) 136{ 137 sim_fpu op1; 138 sim_fpu ans; 139 uint32_t res; 140 sim_fpu_status status; 141 142 sim_fpu_32to (&op1, x); 143 status = sim_fpu_abs (&ans, &op1); 144 if (status != 0) 145 (*fpu->ops->error) (fpu, status); 146 sim_fpu_to32 (&res, &ans); 147 148 return res; 149} 150 151static SF 152sqrtsf (CGEN_FPU* fpu, SF x) 153{ 154 sim_fpu op1; 155 sim_fpu ans; 156 uint32_t res; 157 sim_fpu_status status; 158 159 sim_fpu_32to (&op1, x); 160 status = sim_fpu_sqrt (&ans, &op1); 161 if (status != 0) 162 (*fpu->ops->error) (fpu, status); 163 sim_fpu_to32 (&res, &ans); 164 165 return res; 166} 167 168static SF 169invsf (CGEN_FPU* fpu, SF x) 170{ 171 sim_fpu op1; 172 sim_fpu ans; 173 uint32_t res; 174 sim_fpu_status status; 175 176 sim_fpu_32to (&op1, x); 177 status = sim_fpu_inv (&ans, &op1); 178 if (status != 0) 179 (*fpu->ops->error) (fpu, status); 180 sim_fpu_to32 (&res, &ans); 181 182 return res; 183} 184 185static SF 186minsf (CGEN_FPU* fpu, SF x, SF y) 187{ 188 sim_fpu op1; 189 sim_fpu op2; 190 sim_fpu ans; 191 uint32_t res; 192 sim_fpu_status status; 193 194 sim_fpu_32to (&op1, x); 195 sim_fpu_32to (&op2, y); 196 status = sim_fpu_min (&ans, &op1, &op2); 197 if (status != 0) 198 (*fpu->ops->error) (fpu, status); 199 sim_fpu_to32 (&res, &ans); 200 201 return res; 202} 203 204static SF 205maxsf (CGEN_FPU* fpu, SF x, SF y) 206{ 207 sim_fpu op1; 208 sim_fpu op2; 209 sim_fpu ans; 210 uint32_t res; 211 sim_fpu_status status; 212 213 sim_fpu_32to (&op1, x); 214 sim_fpu_32to (&op2, y); 215 status = sim_fpu_max (&ans, &op1, &op2); 216 if (status != 0) 217 (*fpu->ops->error) (fpu, status); 218 sim_fpu_to32 (&res, &ans); 219 220 return res; 221} 222 223static CGEN_FP_CMP 224cmpsf (CGEN_FPU* fpu, SF x, SF y) 225{ 226 sim_fpu op1; 227 sim_fpu op2; 228 229 sim_fpu_32to (&op1, x); 230 sim_fpu_32to (&op2, y); 231 232 if (sim_fpu_is_nan (&op1) 233 || sim_fpu_is_nan (&op2)) 234 return FP_CMP_NAN; 235 236 if (x < y) 237 return FP_CMP_LT; 238 if (x > y) 239 return FP_CMP_GT; 240 return FP_CMP_EQ; 241} 242 243static int 244eqsf (CGEN_FPU* fpu, SF x, SF y) 245{ 246 sim_fpu op1; 247 sim_fpu op2; 248 249 sim_fpu_32to (&op1, x); 250 sim_fpu_32to (&op2, y); 251 return sim_fpu_is_eq (&op1, &op2); 252} 253 254static int 255nesf (CGEN_FPU* fpu, SF x, SF y) 256{ 257 sim_fpu op1; 258 sim_fpu op2; 259 260 sim_fpu_32to (&op1, x); 261 sim_fpu_32to (&op2, y); 262 return sim_fpu_is_ne (&op1, &op2); 263} 264 265static int 266ltsf (CGEN_FPU* fpu, SF x, SF y) 267{ 268 sim_fpu op1; 269 sim_fpu op2; 270 271 sim_fpu_32to (&op1, x); 272 sim_fpu_32to (&op2, y); 273 return sim_fpu_is_lt (&op1, &op2); 274} 275 276static int 277lesf (CGEN_FPU* fpu, SF x, SF y) 278{ 279 sim_fpu op1; 280 sim_fpu op2; 281 282 sim_fpu_32to (&op1, x); 283 sim_fpu_32to (&op2, y); 284 return sim_fpu_is_le (&op1, &op2); 285} 286 287static int 288gtsf (CGEN_FPU* fpu, SF x, SF y) 289{ 290 sim_fpu op1; 291 sim_fpu op2; 292 293 sim_fpu_32to (&op1, x); 294 sim_fpu_32to (&op2, y); 295 return sim_fpu_is_gt (&op1, &op2); 296} 297 298static int 299gesf (CGEN_FPU* fpu, SF x, SF y) 300{ 301 sim_fpu op1; 302 sim_fpu op2; 303 304 sim_fpu_32to (&op1, x); 305 sim_fpu_32to (&op2, y); 306 return sim_fpu_is_ge (&op1, &op2); 307} 308 309static int 310unorderedsf (CGEN_FPU* fpu, SF x, SF y) 311{ 312 sim_fpu op1; 313 sim_fpu op2; 314 315 sim_fpu_32to (&op1, x); 316 sim_fpu_32to (&op2, y); 317 return sim_fpu_is_nan (&op1) || sim_fpu_is_nan (&op2); 318} 319 320 321static DF 322fextsfdf (CGEN_FPU* fpu, int how UNUSED, SF x) 323{ 324 sim_fpu op1; 325 uint64_t res; 326 327 sim_fpu_32to (&op1, x); 328 sim_fpu_to64 (&res, &op1); 329 330 return res; 331} 332 333static SF 334ftruncdfsf (CGEN_FPU* fpu, int how UNUSED, DF x) 335{ 336 sim_fpu op1; 337 uint32_t res; 338 339 sim_fpu_64to (&op1, x); 340 sim_fpu_to32 (&res, &op1); 341 342 return res; 343} 344 345static SF 346floatsisf (CGEN_FPU* fpu, int how UNUSED, SI x) 347{ 348 sim_fpu ans; 349 uint32_t res; 350 351 sim_fpu_i32to (&ans, x, sim_fpu_round_near); 352 sim_fpu_to32 (&res, &ans); 353 return res; 354} 355 356static DF 357floatsidf (CGEN_FPU* fpu, int how UNUSED, SI x) 358{ 359 sim_fpu ans; 360 uint64_t res; 361 362 sim_fpu_i32to (&ans, x, sim_fpu_round_near); 363 sim_fpu_to64 (&res, &ans); 364 return res; 365} 366 367static DF 368floatdidf (CGEN_FPU* fpu, int how UNUSED, DI x) 369{ 370 sim_fpu ans; 371 uint64_t res; 372 373 sim_fpu_i64to (&ans, x, sim_fpu_round_near); 374 sim_fpu_to64 (&res, &ans); 375 return res; 376} 377 378static SF 379ufloatsisf (CGEN_FPU* fpu, int how UNUSED, USI x) 380{ 381 sim_fpu ans; 382 uint32_t res; 383 384 sim_fpu_u32to (&ans, x, sim_fpu_round_near); 385 sim_fpu_to32 (&res, &ans); 386 return res; 387} 388 389static SI 390fixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x) 391{ 392 sim_fpu op1; 393 int32_t res; 394 395 sim_fpu_32to (&op1, x); 396 sim_fpu_to32i (&res, &op1, sim_fpu_round_near); 397 return res; 398} 399 400static SI 401fixdfsi (CGEN_FPU* fpu, int how UNUSED, DF x) 402{ 403 sim_fpu op1; 404 int32_t res; 405 406 sim_fpu_64to (&op1, x); 407 sim_fpu_to32i (&res, &op1, sim_fpu_round_near); 408 return res; 409} 410 411static DI 412fixdfdi (CGEN_FPU* fpu, int how UNUSED, DF x) 413{ 414 sim_fpu op1; 415 int64_t res; 416 417 sim_fpu_64to (&op1, x); 418 sim_fpu_to64i (&res, &op1, sim_fpu_round_near); 419 return res; 420} 421 422static USI 423ufixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x) 424{ 425 sim_fpu op1; 426 uint32_t res; 427 428 sim_fpu_32to (&op1, x); 429 sim_fpu_to32u (&res, &op1, sim_fpu_round_near); 430 return res; 431} 432 433/* DF mode support */ 434 435static DF 436adddf (CGEN_FPU* fpu, DF x, DF y) 437{ 438 sim_fpu op1; 439 sim_fpu op2; 440 sim_fpu ans; 441 uint64_t res; 442 sim_fpu_status status; 443 444 sim_fpu_64to (&op1, x); 445 sim_fpu_64to (&op2, y); 446 status = sim_fpu_add (&ans, &op1, &op2); 447 if (status != 0) 448 (*fpu->ops->error) (fpu, status); 449 sim_fpu_to64 (&res, &ans); 450 451 return res; 452} 453 454static DF 455subdf (CGEN_FPU* fpu, DF x, DF y) 456{ 457 sim_fpu op1; 458 sim_fpu op2; 459 sim_fpu ans; 460 uint64_t res; 461 sim_fpu_status status; 462 463 sim_fpu_64to (&op1, x); 464 sim_fpu_64to (&op2, y); 465 status = sim_fpu_sub (&ans, &op1, &op2); 466 if (status != 0) 467 (*fpu->ops->error) (fpu, status); 468 sim_fpu_to64 (&res, &ans); 469 470 return res; 471} 472 473static DF 474muldf (CGEN_FPU* fpu, DF x, DF y) 475{ 476 sim_fpu op1; 477 sim_fpu op2; 478 sim_fpu ans; 479 uint64_t res; 480 sim_fpu_status status; 481 482 sim_fpu_64to (&op1, x); 483 sim_fpu_64to (&op2, y); 484 status = sim_fpu_mul (&ans, &op1, &op2); 485 if (status != 0) 486 (*fpu->ops->error) (fpu, status); 487 sim_fpu_to64 (&res, &ans); 488 489 return res; 490} 491 492static DF 493divdf (CGEN_FPU* fpu, DF x, DF y) 494{ 495 sim_fpu op1; 496 sim_fpu op2; 497 sim_fpu ans; 498 uint64_t res; 499 sim_fpu_status status; 500 501 sim_fpu_64to (&op1, x); 502 sim_fpu_64to (&op2, y); 503 status = sim_fpu_div (&ans, &op1, &op2); 504 if (status != 0) 505 (*fpu->ops->error) (fpu, status); 506 sim_fpu_to64 (&res, &ans); 507 508 return res; 509} 510 511static DF 512remdf (CGEN_FPU* fpu, DF x, DF y) 513{ 514 sim_fpu op1; 515 sim_fpu op2; 516 sim_fpu ans; 517 uint64_t res; 518 sim_fpu_status status; 519 520 sim_fpu_64to (&op1, x); 521 sim_fpu_64to (&op2, y); 522 status = sim_fpu_rem (&ans, &op1, &op2); 523 if (status != 0) 524 (*fpu->ops->error) (fpu, status); 525 sim_fpu_to64(&res, &ans); 526 527 return res; 528} 529 530static DF 531negdf (CGEN_FPU* fpu, DF x) 532{ 533 sim_fpu op1; 534 sim_fpu ans; 535 uint64_t res; 536 sim_fpu_status status; 537 538 sim_fpu_64to (&op1, x); 539 status = sim_fpu_neg (&ans, &op1); 540 if (status != 0) 541 (*fpu->ops->error) (fpu, status); 542 sim_fpu_to64 (&res, &ans); 543 544 return res; 545} 546 547static DF 548absdf (CGEN_FPU* fpu, DF x) 549{ 550 sim_fpu op1; 551 sim_fpu ans; 552 uint64_t res; 553 sim_fpu_status status; 554 555 sim_fpu_64to (&op1, x); 556 status = sim_fpu_abs (&ans, &op1); 557 if (status != 0) 558 (*fpu->ops->error) (fpu, status); 559 sim_fpu_to64 (&res, &ans); 560 561 return res; 562} 563 564static DF 565sqrtdf (CGEN_FPU* fpu, DF x) 566{ 567 sim_fpu op1; 568 sim_fpu ans; 569 uint64_t res; 570 sim_fpu_status status; 571 572 sim_fpu_64to (&op1, x); 573 status = sim_fpu_sqrt (&ans, &op1); 574 if (status != 0) 575 (*fpu->ops->error) (fpu, status); 576 sim_fpu_to64 (&res, &ans); 577 578 return res; 579} 580 581static DF 582invdf (CGEN_FPU* fpu, DF x) 583{ 584 sim_fpu op1; 585 sim_fpu ans; 586 uint64_t res; 587 sim_fpu_status status; 588 589 sim_fpu_64to (&op1, x); 590 status = sim_fpu_inv (&ans, &op1); 591 if (status != 0) 592 (*fpu->ops->error) (fpu, status); 593 sim_fpu_to64 (&res, &ans); 594 595 return res; 596} 597 598static DF 599mindf (CGEN_FPU* fpu, DF x, DF y) 600{ 601 sim_fpu op1; 602 sim_fpu op2; 603 sim_fpu ans; 604 uint64_t res; 605 sim_fpu_status status; 606 607 sim_fpu_64to (&op1, x); 608 sim_fpu_64to (&op2, y); 609 status = sim_fpu_min (&ans, &op1, &op2); 610 if (status != 0) 611 (*fpu->ops->error) (fpu, status); 612 sim_fpu_to64 (&res, &ans); 613 614 return res; 615} 616 617static DF 618maxdf (CGEN_FPU* fpu, DF x, DF y) 619{ 620 sim_fpu op1; 621 sim_fpu op2; 622 sim_fpu ans; 623 uint64_t res; 624 sim_fpu_status status; 625 626 sim_fpu_64to (&op1, x); 627 sim_fpu_64to (&op2, y); 628 status = sim_fpu_max (&ans, &op1, &op2); 629 if (status != 0) 630 (*fpu->ops->error) (fpu, status); 631 sim_fpu_to64 (&res, &ans); 632 633 return res; 634} 635 636static CGEN_FP_CMP 637cmpdf (CGEN_FPU* fpu, DF x, DF y) 638{ 639 sim_fpu op1; 640 sim_fpu op2; 641 642 sim_fpu_64to (&op1, x); 643 sim_fpu_64to (&op2, y); 644 645 if (sim_fpu_is_nan (&op1) 646 || sim_fpu_is_nan (&op2)) 647 return FP_CMP_NAN; 648 649 if (x < y) 650 return FP_CMP_LT; 651 if (x > y) 652 return FP_CMP_GT; 653 return FP_CMP_EQ; 654} 655 656static int 657eqdf (CGEN_FPU* fpu, DF x, DF y) 658{ 659 sim_fpu op1; 660 sim_fpu op2; 661 662 sim_fpu_64to (&op1, x); 663 sim_fpu_64to (&op2, y); 664 return sim_fpu_is_eq (&op1, &op2); 665} 666 667static int 668nedf (CGEN_FPU* fpu, DF x, DF y) 669{ 670 sim_fpu op1; 671 sim_fpu op2; 672 673 sim_fpu_64to (&op1, x); 674 sim_fpu_64to (&op2, y); 675 return sim_fpu_is_ne (&op1, &op2); 676} 677 678static int 679ltdf (CGEN_FPU* fpu, DF x, DF y) 680{ 681 sim_fpu op1; 682 sim_fpu op2; 683 684 sim_fpu_64to (&op1, x); 685 sim_fpu_64to (&op2, y); 686 return sim_fpu_is_lt (&op1, &op2); 687} 688 689static int 690ledf (CGEN_FPU* fpu, DF x, DF y) 691{ 692 sim_fpu op1; 693 sim_fpu op2; 694 695 sim_fpu_64to (&op1, x); 696 sim_fpu_64to (&op2, y); 697 return sim_fpu_is_le (&op1, &op2); 698} 699 700static int 701gtdf (CGEN_FPU* fpu, DF x, DF y) 702{ 703 sim_fpu op1; 704 sim_fpu op2; 705 706 sim_fpu_64to (&op1, x); 707 sim_fpu_64to (&op2, y); 708 return sim_fpu_is_gt (&op1, &op2); 709} 710 711static int 712gedf (CGEN_FPU* fpu, DF x, DF y) 713{ 714 sim_fpu op1; 715 sim_fpu op2; 716 717 sim_fpu_64to (&op1, x); 718 sim_fpu_64to (&op2, y); 719 return sim_fpu_is_ge (&op1, &op2); 720} 721 722static int 723unordereddf (CGEN_FPU* fpu, DF x, DF y) 724{ 725 sim_fpu op1; 726 sim_fpu op2; 727 728 sim_fpu_64to (&op1, x); 729 sim_fpu_64to (&op2, y); 730 return sim_fpu_is_nan (&op1) || sim_fpu_is_nan (&op2); 731} 732 733/* Initialize FP_OPS to use accurate library. */ 734 735void 736cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error) 737{ 738 CGEN_FP_OPS* o; 739 740 fpu->owner = cpu; 741 /* ??? small memory leak, not freed by sim_close */ 742 fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS)); 743 744 o = fpu->ops; 745 memset (o, 0, sizeof (*o)); 746 747 o->error = error; 748 749 o->addsf = addsf; 750 o->subsf = subsf; 751 o->mulsf = mulsf; 752 o->divsf = divsf; 753 o->remsf = remsf; 754 o->negsf = negsf; 755 o->abssf = abssf; 756 o->sqrtsf = sqrtsf; 757 o->invsf = invsf; 758 o->minsf = minsf; 759 o->maxsf = maxsf; 760 o->cmpsf = cmpsf; 761 o->eqsf = eqsf; 762 o->nesf = nesf; 763 o->ltsf = ltsf; 764 o->lesf = lesf; 765 o->gtsf = gtsf; 766 o->gesf = gesf; 767 o->unorderedsf = unorderedsf; 768 769 o->adddf = adddf; 770 o->subdf = subdf; 771 o->muldf = muldf; 772 o->divdf = divdf; 773 o->remdf = remdf; 774 o->negdf = negdf; 775 o->absdf = absdf; 776 o->sqrtdf = sqrtdf; 777 o->invdf = invdf; 778 o->mindf = mindf; 779 o->maxdf = maxdf; 780 o->cmpdf = cmpdf; 781 o->eqdf = eqdf; 782 o->nedf = nedf; 783 o->ltdf = ltdf; 784 o->ledf = ledf; 785 o->gtdf = gtdf; 786 o->gedf = gedf; 787 o->unordereddf = unordereddf; 788 o->fextsfdf = fextsfdf; 789 o->ftruncdfsf = ftruncdfsf; 790 o->floatsisf = floatsisf; 791 o->floatsidf = floatsidf; 792 o->floatdidf = floatdidf; 793 o->ufloatsisf = ufloatsisf; 794 o->fixsfsi = fixsfsi; 795 o->fixdfsi = fixdfsi; 796 o->fixdfdi = fixdfdi; 797 o->ufixsfsi = ufixsfsi; 798} 799