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 22 static SF 23 addsf (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 41 static SF 42 subsf (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 60 static SF 61 mulsf (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 79 static SF 80 divsf (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 98 static SF 99 remsf (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 117 static SF 118 negsf (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 134 static SF 135 abssf (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 151 static SF 152 sqrtsf (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 168 static SF 169 invsf (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 185 static SF 186 minsf (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 204 static SF 205 maxsf (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 223 static CGEN_FP_CMP 224 cmpsf (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 243 static int 244 eqsf (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 254 static int 255 nesf (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 265 static int 266 ltsf (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 276 static int 277 lesf (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 287 static int 288 gtsf (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 298 static int 299 gesf (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 309 static int 310 unorderedsf (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 321 static DF 322 fextsfdf (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 333 static SF 334 ftruncdfsf (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 345 static SF 346 floatsisf (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 356 static DF 357 floatsidf (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 367 static DF 368 floatdidf (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 378 static SF 379 ufloatsisf (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 389 static SI 390 fixsfsi (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 400 static SI 401 fixdfsi (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 411 static DI 412 fixdfdi (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 422 static USI 423 ufixsfsi (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 */ 435 436 static DF 437 adddf (CGEN_FPU* fpu, DF x, DF y) 438 { 439 sim_fpu op1; 440 sim_fpu op2; 441 sim_fpu ans; 442 uint64_t res; 443 sim_fpu_status status; 444 445 sim_fpu_64to (&op1, x); 446 sim_fpu_64to (&op2, y); 447 status = sim_fpu_add (&ans, &op1, &op2); 448 if (status != 0) 449 (*fpu->ops->error) (fpu, status); 450 sim_fpu_to64 (&res, &ans); 451 452 return res; 453 } 454 455 static DF 456 subdf (CGEN_FPU* fpu, DF x, DF y) 457 { 458 sim_fpu op1; 459 sim_fpu op2; 460 sim_fpu ans; 461 uint64_t res; 462 sim_fpu_status status; 463 464 sim_fpu_64to (&op1, x); 465 sim_fpu_64to (&op2, y); 466 status = sim_fpu_sub (&ans, &op1, &op2); 467 if (status != 0) 468 (*fpu->ops->error) (fpu, status); 469 sim_fpu_to64 (&res, &ans); 470 471 return res; 472 } 473 474 static DF 475 muldf (CGEN_FPU* fpu, DF x, DF y) 476 { 477 sim_fpu op1; 478 sim_fpu op2; 479 sim_fpu ans; 480 uint64_t res; 481 sim_fpu_status status; 482 483 sim_fpu_64to (&op1, x); 484 sim_fpu_64to (&op2, y); 485 status = sim_fpu_mul (&ans, &op1, &op2); 486 if (status != 0) 487 (*fpu->ops->error) (fpu, status); 488 sim_fpu_to64 (&res, &ans); 489 490 return res; 491 } 492 493 static DF 494 divdf (CGEN_FPU* fpu, DF x, DF y) 495 { 496 sim_fpu op1; 497 sim_fpu op2; 498 sim_fpu ans; 499 uint64_t res; 500 sim_fpu_status status; 501 502 sim_fpu_64to (&op1, x); 503 sim_fpu_64to (&op2, y); 504 status = sim_fpu_div (&ans, &op1, &op2); 505 if (status != 0) 506 (*fpu->ops->error) (fpu, status); 507 sim_fpu_to64 (&res, &ans); 508 509 return res; 510 } 511 512 static DF 513 remdf (CGEN_FPU* fpu, DF x, DF y) 514 { 515 sim_fpu op1; 516 sim_fpu op2; 517 sim_fpu ans; 518 uint64_t res; 519 sim_fpu_status status; 520 521 sim_fpu_64to (&op1, x); 522 sim_fpu_64to (&op2, y); 523 status = sim_fpu_rem (&ans, &op1, &op2); 524 if (status != 0) 525 (*fpu->ops->error) (fpu, status); 526 sim_fpu_to64(&res, &ans); 527 528 return res; 529 } 530 531 static DF 532 negdf (CGEN_FPU* fpu, DF x) 533 { 534 sim_fpu op1; 535 sim_fpu ans; 536 uint64_t res; 537 sim_fpu_status status; 538 539 sim_fpu_64to (&op1, x); 540 status = sim_fpu_neg (&ans, &op1); 541 if (status != 0) 542 (*fpu->ops->error) (fpu, status); 543 sim_fpu_to64 (&res, &ans); 544 545 return res; 546 } 547 548 static DF 549 absdf (CGEN_FPU* fpu, DF x) 550 { 551 sim_fpu op1; 552 sim_fpu ans; 553 uint64_t res; 554 sim_fpu_status status; 555 556 sim_fpu_64to (&op1, x); 557 status = sim_fpu_abs (&ans, &op1); 558 if (status != 0) 559 (*fpu->ops->error) (fpu, status); 560 sim_fpu_to64 (&res, &ans); 561 562 return res; 563 } 564 565 static DF 566 sqrtdf (CGEN_FPU* fpu, DF x) 567 { 568 sim_fpu op1; 569 sim_fpu ans; 570 uint64_t res; 571 sim_fpu_status status; 572 573 sim_fpu_64to (&op1, x); 574 status = sim_fpu_sqrt (&ans, &op1); 575 if (status != 0) 576 (*fpu->ops->error) (fpu, status); 577 sim_fpu_to64 (&res, &ans); 578 579 return res; 580 } 581 582 static DF 583 invdf (CGEN_FPU* fpu, DF x) 584 { 585 sim_fpu op1; 586 sim_fpu ans; 587 uint64_t res; 588 sim_fpu_status status; 589 590 sim_fpu_64to (&op1, x); 591 status = sim_fpu_inv (&ans, &op1); 592 if (status != 0) 593 (*fpu->ops->error) (fpu, status); 594 sim_fpu_to64 (&res, &ans); 595 596 return res; 597 } 598 599 static DF 600 mindf (CGEN_FPU* fpu, DF x, DF y) 601 { 602 sim_fpu op1; 603 sim_fpu op2; 604 sim_fpu ans; 605 uint64_t res; 606 sim_fpu_status status; 607 608 sim_fpu_64to (&op1, x); 609 sim_fpu_64to (&op2, y); 610 status = sim_fpu_min (&ans, &op1, &op2); 611 if (status != 0) 612 (*fpu->ops->error) (fpu, status); 613 sim_fpu_to64 (&res, &ans); 614 615 return res; 616 } 617 618 static DF 619 maxdf (CGEN_FPU* fpu, DF x, DF y) 620 { 621 sim_fpu op1; 622 sim_fpu op2; 623 sim_fpu ans; 624 uint64_t res; 625 sim_fpu_status status; 626 627 sim_fpu_64to (&op1, x); 628 sim_fpu_64to (&op2, y); 629 status = sim_fpu_max (&ans, &op1, &op2); 630 if (status != 0) 631 (*fpu->ops->error) (fpu, status); 632 sim_fpu_to64 (&res, &ans); 633 634 return res; 635 } 636 637 static CGEN_FP_CMP 638 cmpdf (CGEN_FPU* fpu, DF x, DF y) 639 { 640 sim_fpu op1; 641 sim_fpu op2; 642 643 sim_fpu_64to (&op1, x); 644 sim_fpu_64to (&op2, y); 645 646 if (sim_fpu_is_nan (&op1) 647 || sim_fpu_is_nan (&op2)) 648 return FP_CMP_NAN; 649 650 if (x < y) 651 return FP_CMP_LT; 652 if (x > y) 653 return FP_CMP_GT; 654 return FP_CMP_EQ; 655 } 656 657 static int 658 eqdf (CGEN_FPU* fpu, DF x, DF y) 659 { 660 sim_fpu op1; 661 sim_fpu op2; 662 663 sim_fpu_64to (&op1, x); 664 sim_fpu_64to (&op2, y); 665 return sim_fpu_is_eq (&op1, &op2); 666 } 667 668 static int 669 nedf (CGEN_FPU* fpu, DF x, DF y) 670 { 671 sim_fpu op1; 672 sim_fpu op2; 673 674 sim_fpu_64to (&op1, x); 675 sim_fpu_64to (&op2, y); 676 return sim_fpu_is_ne (&op1, &op2); 677 } 678 679 static int 680 ltdf (CGEN_FPU* fpu, DF x, DF y) 681 { 682 sim_fpu op1; 683 sim_fpu op2; 684 685 sim_fpu_64to (&op1, x); 686 sim_fpu_64to (&op2, y); 687 return sim_fpu_is_lt (&op1, &op2); 688 } 689 690 static int 691 ledf (CGEN_FPU* fpu, DF x, DF y) 692 { 693 sim_fpu op1; 694 sim_fpu op2; 695 696 sim_fpu_64to (&op1, x); 697 sim_fpu_64to (&op2, y); 698 return sim_fpu_is_le (&op1, &op2); 699 } 700 701 static int 702 gtdf (CGEN_FPU* fpu, DF x, DF y) 703 { 704 sim_fpu op1; 705 sim_fpu op2; 706 707 sim_fpu_64to (&op1, x); 708 sim_fpu_64to (&op2, y); 709 return sim_fpu_is_gt (&op1, &op2); 710 } 711 712 static int 713 gedf (CGEN_FPU* fpu, DF x, DF y) 714 { 715 sim_fpu op1; 716 sim_fpu op2; 717 718 sim_fpu_64to (&op1, x); 719 sim_fpu_64to (&op2, y); 720 return sim_fpu_is_ge (&op1, &op2); 721 } 722 723 static int 724 unordereddf (CGEN_FPU* fpu, DF x, DF y) 725 { 726 sim_fpu op1; 727 sim_fpu op2; 728 729 sim_fpu_64to (&op1, x); 730 sim_fpu_64to (&op2, y); 731 return sim_fpu_is_nan (&op1) || sim_fpu_is_nan (&op2); 732 } 733 734 /* Initialize FP_OPS to use accurate library. */ 736 737 void 738 cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error) 739 { 740 CGEN_FP_OPS* o; 741 742 fpu->owner = cpu; 743 /* ??? small memory leak, not freed by sim_close */ 744 fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS)); 745 746 o = fpu->ops; 747 memset (o, 0, sizeof (*o)); 748 749 o->error = error; 750 751 o->addsf = addsf; 752 o->subsf = subsf; 753 o->mulsf = mulsf; 754 o->divsf = divsf; 755 o->remsf = remsf; 756 o->negsf = negsf; 757 o->abssf = abssf; 758 o->sqrtsf = sqrtsf; 759 o->invsf = invsf; 760 o->minsf = minsf; 761 o->maxsf = maxsf; 762 o->cmpsf = cmpsf; 763 o->eqsf = eqsf; 764 o->nesf = nesf; 765 o->ltsf = ltsf; 766 o->lesf = lesf; 767 o->gtsf = gtsf; 768 o->gesf = gesf; 769 o->unorderedsf = unorderedsf; 770 771 o->adddf = adddf; 772 o->subdf = subdf; 773 o->muldf = muldf; 774 o->divdf = divdf; 775 o->remdf = remdf; 776 o->negdf = negdf; 777 o->absdf = absdf; 778 o->sqrtdf = sqrtdf; 779 o->invdf = invdf; 780 o->mindf = mindf; 781 o->maxdf = maxdf; 782 o->cmpdf = cmpdf; 783 o->eqdf = eqdf; 784 o->nedf = nedf; 785 o->ltdf = ltdf; 786 o->ledf = ledf; 787 o->gtdf = gtdf; 788 o->gedf = gedf; 789 o->unordereddf = unordereddf; 790 o->fextsfdf = fextsfdf; 791 o->ftruncdfsf = ftruncdfsf; 792 o->floatsisf = floatsisf; 793 o->floatsidf = floatsidf; 794 o->floatdidf = floatdidf; 795 o->ufloatsisf = ufloatsisf; 796 o->fixsfsi = fixsfsi; 797 o->fixdfsi = fixdfsi; 798 o->fixdfdi = fixdfdi; 799 o->ufixsfsi = ufixsfsi; 800 } 801